stricter type checking
This commit is contained in:
parent
17581b946d
commit
e3cc9c59bc
@ -35,7 +35,7 @@ namespace TalerNotify {
|
|||||||
* Wallet-internal version of offerContractFrom, used for 402 payments.
|
* Wallet-internal version of offerContractFrom, used for 402 payments.
|
||||||
*/
|
*/
|
||||||
function internalOfferContractFrom(url: string) {
|
function internalOfferContractFrom(url: string) {
|
||||||
function handle_contract(contract_wrapper) {
|
function handle_contract(contract_wrapper: any) {
|
||||||
var cEvent = new CustomEvent("taler-confirm-contract", {
|
var cEvent = new CustomEvent("taler-confirm-contract", {
|
||||||
detail: {
|
detail: {
|
||||||
contract_wrapper: contract_wrapper,
|
contract_wrapper: contract_wrapper,
|
||||||
@ -88,7 +88,7 @@ namespace TalerNotify {
|
|||||||
* Try to notify the wallet first, before we show a potentially
|
* Try to notify the wallet first, before we show a potentially
|
||||||
* synchronous error message (such as an alert) or leave the page.
|
* synchronous error message (such as an alert) or leave the page.
|
||||||
*/
|
*/
|
||||||
function handleFailedPayment(status) {
|
function handleFailedPayment(status: any) {
|
||||||
const msg = {
|
const msg = {
|
||||||
type: "payment-failed",
|
type: "payment-failed",
|
||||||
detail: {},
|
detail: {},
|
||||||
@ -99,19 +99,22 @@ namespace TalerNotify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleResponse(evt) {
|
function handleResponse(evt: CustomEvent) {
|
||||||
console.log("handling taler-notify-payment");
|
console.log("handling taler-notify-payment");
|
||||||
// Payment timeout in ms.
|
// Payment timeout in ms.
|
||||||
let timeout_ms = 1000;
|
let timeout_ms = 1000;
|
||||||
// Current request.
|
// Current request.
|
||||||
let r;
|
let r: XMLHttpRequest | null = null;
|
||||||
let timeoutHandle = null;
|
let timeoutHandle: number|null = null;
|
||||||
function sendPay() {
|
function sendPay() {
|
||||||
r = new XMLHttpRequest();
|
r = new XMLHttpRequest();
|
||||||
r.open("post", payUrl);
|
r.open("post", payUrl);
|
||||||
r.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
r.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||||
r.send(JSON.stringify(evt.detail.payment));
|
r.send(JSON.stringify(evt.detail.payment));
|
||||||
r.onload = function() {
|
r.onload = function() {
|
||||||
|
if (!r) {
|
||||||
|
throw Error("invariant");
|
||||||
|
}
|
||||||
switch (r.status) {
|
switch (r.status) {
|
||||||
case 200:
|
case 200:
|
||||||
window.location.href = subst(evt.detail.contract.fulfillment_url,
|
window.location.href = subst(evt.detail.contract.fulfillment_url,
|
||||||
@ -152,13 +155,17 @@ namespace TalerNotify {
|
|||||||
document.dispatchEvent(eve);
|
document.dispatchEvent(eve);
|
||||||
}
|
}
|
||||||
|
|
||||||
function subst(url: string, H_contract) {
|
function subst(url: string, H_contract: string) {
|
||||||
url = url.replace("${H_contract}", H_contract);
|
url = url.replace("${H_contract}", H_contract);
|
||||||
url = url.replace("${$}", "$");
|
url = url.replace("${$}", "$");
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlers = [];
|
interface Handler {
|
||||||
|
type: string;
|
||||||
|
listener: (e: CustomEvent) => void;
|
||||||
|
}
|
||||||
|
const handlers: Handler[] = [];
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
chrome.runtime.sendMessage({type: "ping"}, (resp) => {
|
chrome.runtime.sendMessage({type: "ping"}, (resp) => {
|
||||||
@ -197,9 +204,7 @@ namespace TalerNotify {
|
|||||||
init();
|
init();
|
||||||
|
|
||||||
function registerHandlers() {
|
function registerHandlers() {
|
||||||
const $ = (x) => document.getElementById(x);
|
function addHandler(type: string, listener: (e: CustomEvent) => void) {
|
||||||
|
|
||||||
function addHandler(type, listener) {
|
|
||||||
document.addEventListener(type, listener);
|
document.addEventListener(type, listener);
|
||||||
handlers.push({type, listener});
|
handlers.push({type, listener});
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,8 @@ const tsBaseArgs = {
|
|||||||
noLib: true,
|
noLib: true,
|
||||||
noImplicitReturns: true,
|
noImplicitReturns: true,
|
||||||
noFallthroughCasesInSwitch: true,
|
noFallthroughCasesInSwitch: true,
|
||||||
|
strictNullChecks: true,
|
||||||
|
noImplicitAny: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function subst(url: string, H_contract) {
|
function subst(url: string, H_contract: string) {
|
||||||
url = url.replace("${H_contract}", H_contract);
|
url = url.replace("${H_contract}", H_contract);
|
||||||
url = url.replace("${$}", "$");
|
url = url.replace("${$}", "$");
|
||||||
return url;
|
return url;
|
||||||
@ -138,7 +138,7 @@ export function fetchPayment(H_contract: any, offering_url: any) {
|
|||||||
* Offer a contract to the wallet after
|
* Offer a contract to the wallet after
|
||||||
* downloading it from the given URL.
|
* downloading it from the given URL.
|
||||||
*/
|
*/
|
||||||
function offerContractFrom(url) {
|
function offerContractFrom(url: string) {
|
||||||
var contract_request = new XMLHttpRequest();
|
var contract_request = new XMLHttpRequest();
|
||||||
console.log("downloading contract from '" + url + "'");
|
console.log("downloading contract from '" + url + "'");
|
||||||
contract_request.open("GET", url, true);
|
contract_request.open("GET", url, true);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
export function Query(db) {
|
export function Query(db: IDBDatabase) {
|
||||||
return new QueryRoot(db);
|
return new QueryRoot(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,24 +36,27 @@ export interface QueryStream<T> {
|
|||||||
indexJoin<S>(storeName: string,
|
indexJoin<S>(storeName: string,
|
||||||
indexName: string,
|
indexName: string,
|
||||||
keyFn: (obj: any) => any): QueryStream<[T,S]>;
|
keyFn: (obj: any) => any): QueryStream<[T,S]>;
|
||||||
filter(f: (any) => boolean): QueryStream<T>;
|
filter(f: (x: any) => boolean): QueryStream<T>;
|
||||||
reduce<S>(f: (v: T, acc: S) => S, start?: S): Promise<S>;
|
reduce<S>(f: (v: T, acc: S) => S, start?: S): Promise<S>;
|
||||||
flatMap(f: (T) => T[]): QueryStream<T>;
|
flatMap(f: (x: T) => T[]): QueryStream<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an unresolved promise together with its extracted resolve / reject
|
* Get an unresolved promise together with its extracted resolve / reject
|
||||||
* function.
|
* function.
|
||||||
*
|
|
||||||
* @returns {{resolve: any, reject: any, promise: Promise<T>}}
|
|
||||||
*/
|
*/
|
||||||
function openPromise<T>() {
|
function openPromise<T>() {
|
||||||
let resolve, reject;
|
let resolve: ((value?: T | PromiseLike<T>) => void) | null = null;
|
||||||
|
let reject: ((reason?: any) => void) | null = null;
|
||||||
const promise = new Promise<T>((res, rej) => {
|
const promise = new Promise<T>((res, rej) => {
|
||||||
resolve = res;
|
resolve = res;
|
||||||
reject = rej;
|
reject = rej;
|
||||||
});
|
});
|
||||||
|
if (!(resolve && reject)) {
|
||||||
|
// Never happens, unless JS implementation is broken
|
||||||
|
throw Error();
|
||||||
|
}
|
||||||
return {resolve, reject, promise};
|
return {resolve, reject, promise};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +64,7 @@ function openPromise<T>() {
|
|||||||
abstract class QueryStreamBase<T> implements QueryStream<T> {
|
abstract class QueryStreamBase<T> implements QueryStream<T> {
|
||||||
abstract subscribe(f: (isDone: boolean,
|
abstract subscribe(f: (isDone: boolean,
|
||||||
value: any,
|
value: any,
|
||||||
tx: IDBTransaction) => void);
|
tx: IDBTransaction) => void): void;
|
||||||
|
|
||||||
root: QueryRoot;
|
root: QueryRoot;
|
||||||
|
|
||||||
@ -69,30 +72,28 @@ abstract class QueryStreamBase<T> implements QueryStream<T> {
|
|||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
flatMap(f: (T) => T[]): QueryStream<T> {
|
flatMap(f: (x: T) => T[]): QueryStream<T> {
|
||||||
return new QueryStreamFlatMap(this, f);
|
return new QueryStreamFlatMap(this, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
indexJoin<S>(storeName: string,
|
indexJoin<S>(storeName: string,
|
||||||
indexName: string,
|
indexName: string,
|
||||||
key: any): QueryStream<[T,S]> {
|
key: any): QueryStream<[T,S]> {
|
||||||
this.root.addWork(null, storeName, false);
|
this.root.addStoreAccess(storeName, false);
|
||||||
return new QueryStreamIndexJoin(this, storeName, indexName, key);
|
return new QueryStreamIndexJoin(this, storeName, indexName, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter(f: (any) => boolean): QueryStream<T> {
|
filter(f: (x: any) => boolean): QueryStream<T> {
|
||||||
return new QueryStreamFilter(this, f);
|
return new QueryStreamFilter(this, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
reduce(f, acc?): Promise<any> {
|
reduce<A>(f: (x: any, acc?: A) => A, init?: A): Promise<any> {
|
||||||
let leakedResolve;
|
let {resolve, promise} = openPromise();
|
||||||
let p = new Promise((resolve, reject) => {
|
let acc = init;
|
||||||
leakedResolve = resolve;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.subscribe((isDone, value) => {
|
this.subscribe((isDone, value) => {
|
||||||
if (isDone) {
|
if (isDone) {
|
||||||
leakedResolve(acc);
|
resolve(acc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
acc = f(value, acc);
|
acc = f(value, acc);
|
||||||
@ -100,22 +101,28 @@ abstract class QueryStreamBase<T> implements QueryStream<T> {
|
|||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => this.root.finish())
|
.then(() => this.root.finish())
|
||||||
.then(() => p);
|
.then(() => promise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FilterFn = (e: any) => boolean;
|
||||||
|
type SubscribeFn = (done: boolean, value: any, tx: IDBTransaction) => void;
|
||||||
|
|
||||||
|
interface FlatMapFn<T> {
|
||||||
|
(v: T): T[];
|
||||||
|
}
|
||||||
|
|
||||||
class QueryStreamFilter<T> extends QueryStreamBase<T> {
|
class QueryStreamFilter<T> extends QueryStreamBase<T> {
|
||||||
s: QueryStreamBase<T>;
|
s: QueryStreamBase<T>;
|
||||||
filterFn;
|
filterFn: FilterFn;
|
||||||
|
|
||||||
constructor(s: QueryStreamBase<T>, filterFn) {
|
constructor(s: QueryStreamBase<T>, filterFn: FilterFn) {
|
||||||
super(s.root);
|
super(s.root);
|
||||||
this.s = s;
|
this.s = s;
|
||||||
this.filterFn = filterFn;
|
this.filterFn = filterFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(f) {
|
subscribe(f: SubscribeFn) {
|
||||||
this.s.subscribe((isDone, value, tx) => {
|
this.s.subscribe((isDone, value, tx) => {
|
||||||
if (isDone) {
|
if (isDone) {
|
||||||
f(true, undefined, tx);
|
f(true, undefined, tx);
|
||||||
@ -131,15 +138,15 @@ class QueryStreamFilter<T> extends QueryStreamBase<T> {
|
|||||||
|
|
||||||
class QueryStreamFlatMap<T> extends QueryStreamBase<T> {
|
class QueryStreamFlatMap<T> extends QueryStreamBase<T> {
|
||||||
s: QueryStreamBase<T>;
|
s: QueryStreamBase<T>;
|
||||||
flatMapFn;
|
flatMapFn: (v: T) => T[];
|
||||||
|
|
||||||
constructor(s: QueryStreamBase<T>, flatMapFn) {
|
constructor(s: QueryStreamBase<T>, flatMapFn: (v: T) => T[]) {
|
||||||
super(s.root);
|
super(s.root);
|
||||||
this.s = s;
|
this.s = s;
|
||||||
this.flatMap = flatMapFn;
|
this.flatMapFn = flatMapFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(f) {
|
subscribe(f: SubscribeFn) {
|
||||||
this.s.subscribe((isDone, value, tx) => {
|
this.s.subscribe((isDone, value, tx) => {
|
||||||
if (isDone) {
|
if (isDone) {
|
||||||
f(true, undefined, tx);
|
f(true, undefined, tx);
|
||||||
@ -154,13 +161,13 @@ class QueryStreamFlatMap<T> extends QueryStreamBase<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class QueryStreamIndexJoin<T> extends QueryStreamBase<T> {
|
class QueryStreamIndexJoin<T,S> extends QueryStreamBase<[T, S]> {
|
||||||
s: QueryStreamBase<T>;
|
s: QueryStreamBase<T>;
|
||||||
storeName;
|
storeName: string;
|
||||||
key;
|
key: any;
|
||||||
indexName;
|
indexName: string;
|
||||||
|
|
||||||
constructor(s, storeName: string, indexName: string, key: any) {
|
constructor(s: QueryStreamBase<T>, storeName: string, indexName: string, key: any) {
|
||||||
super(s.root);
|
super(s.root);
|
||||||
this.s = s;
|
this.s = s;
|
||||||
this.storeName = storeName;
|
this.storeName = storeName;
|
||||||
@ -168,7 +175,7 @@ class QueryStreamIndexJoin<T> extends QueryStreamBase<T> {
|
|||||||
this.indexName = indexName;
|
this.indexName = indexName;
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(f) {
|
subscribe(f: SubscribeFn) {
|
||||||
this.s.subscribe((isDone, value, tx) => {
|
this.s.subscribe((isDone, value, tx) => {
|
||||||
if (isDone) {
|
if (isDone) {
|
||||||
f(true, undefined, tx);
|
f(true, undefined, tx);
|
||||||
@ -192,31 +199,31 @@ class QueryStreamIndexJoin<T> extends QueryStreamBase<T> {
|
|||||||
|
|
||||||
|
|
||||||
class IterQueryStream<T> extends QueryStreamBase<T> {
|
class IterQueryStream<T> extends QueryStreamBase<T> {
|
||||||
private storeName;
|
private storeName: string;
|
||||||
private options;
|
private options: any;
|
||||||
private subscribers;
|
private subscribers: SubscribeFn[];
|
||||||
|
|
||||||
constructor(qr, storeName, options) {
|
constructor(qr: QueryRoot, storeName: string, options: any) {
|
||||||
super(qr);
|
super(qr);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.storeName = storeName;
|
this.storeName = storeName;
|
||||||
this.subscribers = [];
|
this.subscribers = [];
|
||||||
|
|
||||||
let doIt = (tx) => {
|
let doIt = (tx: IDBTransaction) => {
|
||||||
const {indexName = void 0, only = void 0} = this.options;
|
const {indexName = void 0, only = void 0} = this.options;
|
||||||
let s;
|
let s: any;
|
||||||
if (indexName !== void 0) {
|
if (indexName !== void 0) {
|
||||||
s = tx.objectStore(this.storeName)
|
s = tx.objectStore(this.storeName)
|
||||||
.index(this.options.indexName);
|
.index(this.options.indexName);
|
||||||
} else {
|
} else {
|
||||||
s = tx.objectStore(this.storeName);
|
s = tx.objectStore(this.storeName);
|
||||||
}
|
}
|
||||||
let kr = undefined;
|
let kr: IDBKeyRange|undefined = undefined;
|
||||||
if (only !== void 0) {
|
if (only !== undefined) {
|
||||||
kr = IDBKeyRange.only(this.options.only);
|
kr = IDBKeyRange.only(this.options.only);
|
||||||
}
|
}
|
||||||
let req = s.openCursor(kr);
|
let req = s.openCursor(kr);
|
||||||
req.onsuccess = (e) => {
|
req.onsuccess = () => {
|
||||||
let cursor: IDBCursorWithValue = req.result;
|
let cursor: IDBCursorWithValue = req.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
for (let f of this.subscribers) {
|
for (let f of this.subscribers) {
|
||||||
@ -231,32 +238,33 @@ class IterQueryStream<T> extends QueryStreamBase<T> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.root.addWork(doIt, null, false);
|
this.root.addWork(doIt);
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(f) {
|
subscribe(f: SubscribeFn) {
|
||||||
this.subscribers.push(f);
|
this.subscribers.push(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class QueryRoot {
|
class QueryRoot {
|
||||||
private work = [];
|
private work: ((t: IDBTransaction) => void)[] = [];
|
||||||
private db: IDBDatabase;
|
private db: IDBDatabase;
|
||||||
private stores = new Set();
|
private stores = new Set();
|
||||||
private kickoffPromise;
|
private kickoffPromise: Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some operations is a write operation,
|
* Some operations is a write operation,
|
||||||
* and we need to do a "readwrite" transaction/
|
* and we need to do a "readwrite" transaction/
|
||||||
*/
|
*/
|
||||||
private hasWrite;
|
private hasWrite: boolean;
|
||||||
|
|
||||||
constructor(db) {
|
constructor(db: IDBDatabase) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter<T>(storeName, {only = void 0, indexName = void 0} = {}): QueryStream<T> {
|
iter<T>(storeName: string,
|
||||||
|
{only = <string|undefined>undefined, indexName = <string|undefined>undefined} = {}): QueryStream<T> {
|
||||||
this.stores.add(storeName);
|
this.stores.add(storeName);
|
||||||
return new IterQueryStream(this, storeName, {only, indexName});
|
return new IterQueryStream(this, storeName, {only, indexName});
|
||||||
}
|
}
|
||||||
@ -266,7 +274,7 @@ class QueryRoot {
|
|||||||
* Overrides if an existing object with the same key exists
|
* Overrides if an existing object with the same key exists
|
||||||
* in the store.
|
* in the store.
|
||||||
*/
|
*/
|
||||||
put(storeName, val): QueryRoot {
|
put(storeName: string, val: any): QueryRoot {
|
||||||
let doPut = (tx: IDBTransaction) => {
|
let doPut = (tx: IDBTransaction) => {
|
||||||
tx.objectStore(storeName).put(val);
|
tx.objectStore(storeName).put(val);
|
||||||
};
|
};
|
||||||
@ -280,7 +288,7 @@ class QueryRoot {
|
|||||||
* Fails if the object's key is already present
|
* Fails if the object's key is already present
|
||||||
* in the object store.
|
* in the object store.
|
||||||
*/
|
*/
|
||||||
putAll(storeName, iterable): QueryRoot {
|
putAll(storeName: string, iterable: any[]): QueryRoot {
|
||||||
const doPutAll = (tx: IDBTransaction) => {
|
const doPutAll = (tx: IDBTransaction) => {
|
||||||
for (const obj of iterable) {
|
for (const obj of iterable) {
|
||||||
tx.objectStore(storeName).put(obj);
|
tx.objectStore(storeName).put(obj);
|
||||||
@ -295,7 +303,7 @@ class QueryRoot {
|
|||||||
* Fails if the object's key is already present
|
* Fails if the object's key is already present
|
||||||
* in the object store.
|
* in the object store.
|
||||||
*/
|
*/
|
||||||
add(storeName, val): QueryRoot {
|
add(storeName: string, val: any): QueryRoot {
|
||||||
const doAdd = (tx: IDBTransaction) => {
|
const doAdd = (tx: IDBTransaction) => {
|
||||||
tx.objectStore(storeName).add(val);
|
tx.objectStore(storeName).add(val);
|
||||||
};
|
};
|
||||||
@ -306,16 +314,16 @@ class QueryRoot {
|
|||||||
/**
|
/**
|
||||||
* Get one object from a store by its key.
|
* Get one object from a store by its key.
|
||||||
*/
|
*/
|
||||||
get(storeName, key): Promise<any> {
|
get(storeName: any, key: any): Promise<any> {
|
||||||
if (key === void 0) {
|
if (key === void 0) {
|
||||||
throw Error("key must not be undefined");
|
throw Error("key must not be undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
const {resolve, promise} = openPromise();
|
const {resolve, promise} = openPromise();
|
||||||
|
|
||||||
const doGet = (tx) => {
|
const doGet = (tx: IDBTransaction) => {
|
||||||
const req = tx.objectStore(storeName).get(key);
|
const req = tx.objectStore(storeName).get(key);
|
||||||
req.onsuccess = (r) => {
|
req.onsuccess = () => {
|
||||||
resolve(req.result);
|
resolve(req.result);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -329,16 +337,16 @@ class QueryRoot {
|
|||||||
/**
|
/**
|
||||||
* Get one object from a store by its key.
|
* Get one object from a store by its key.
|
||||||
*/
|
*/
|
||||||
getIndexed(storeName, indexName, key): Promise<any> {
|
getIndexed(storeName: string, indexName: string, key: any): Promise<any> {
|
||||||
if (key === void 0) {
|
if (key === void 0) {
|
||||||
throw Error("key must not be undefined");
|
throw Error("key must not be undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
const {resolve, promise} = openPromise();
|
const {resolve, promise} = openPromise();
|
||||||
|
|
||||||
const doGetIndexed = (tx) => {
|
const doGetIndexed = (tx: IDBTransaction) => {
|
||||||
const req = tx.objectStore(storeName).index(indexName).get(key);
|
const req = tx.objectStore(storeName).index(indexName).get(key);
|
||||||
req.onsuccess = (r) => {
|
req.onsuccess = () => {
|
||||||
resolve(req.result);
|
resolve(req.result);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -356,7 +364,7 @@ class QueryRoot {
|
|||||||
if (this.kickoffPromise) {
|
if (this.kickoffPromise) {
|
||||||
return this.kickoffPromise;
|
return this.kickoffPromise;
|
||||||
}
|
}
|
||||||
this.kickoffPromise = new Promise((resolve, reject) => {
|
this.kickoffPromise = new Promise<void>((resolve, reject) => {
|
||||||
if (this.work.length == 0) {
|
if (this.work.length == 0) {
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
@ -376,8 +384,8 @@ class QueryRoot {
|
|||||||
/**
|
/**
|
||||||
* Delete an object by from the given object store.
|
* Delete an object by from the given object store.
|
||||||
*/
|
*/
|
||||||
delete(storeName: string, key): QueryRoot {
|
delete(storeName: string, key: any): QueryRoot {
|
||||||
const doDelete = (tx) => {
|
const doDelete = (tx: IDBTransaction) => {
|
||||||
tx.objectStore(storeName).delete(key);
|
tx.objectStore(storeName).delete(key);
|
||||||
};
|
};
|
||||||
this.addWork(doDelete, storeName, true);
|
this.addWork(doDelete, storeName, true);
|
||||||
@ -387,17 +395,21 @@ class QueryRoot {
|
|||||||
/**
|
/**
|
||||||
* Low-level function to add a task to the internal work queue.
|
* Low-level function to add a task to the internal work queue.
|
||||||
*/
|
*/
|
||||||
addWork(workFn: (IDBTransaction) => void,
|
addWork(workFn: (t: IDBTransaction) => void,
|
||||||
storeName: string,
|
storeName?: string,
|
||||||
isWrite: boolean) {
|
isWrite?: boolean) {
|
||||||
|
this.work.push(workFn);
|
||||||
|
if (storeName) {
|
||||||
|
this.addStoreAccess(storeName, isWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addStoreAccess(storeName: string, isWrite?: boolean) {
|
||||||
if (storeName) {
|
if (storeName) {
|
||||||
this.stores.add(storeName);
|
this.stores.add(storeName);
|
||||||
}
|
}
|
||||||
if (isWrite) {
|
if (isWrite) {
|
||||||
this.hasWrite = true;
|
this.hasWrite = true;
|
||||||
}
|
}
|
||||||
if (workFn) {
|
|
||||||
this.work.push(workFn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -154,12 +154,12 @@ interface Transaction {
|
|||||||
export interface Badge {
|
export interface Badge {
|
||||||
setText(s: string): void;
|
setText(s: string): void;
|
||||||
setColor(c: string): void;
|
setColor(c: string): void;
|
||||||
startBusy();
|
startBusy(): void;
|
||||||
stopBusy();
|
stopBusy(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function deepEquals(x, y) {
|
function deepEquals(x: any, y: any): boolean {
|
||||||
if (x === y) {
|
if (x === y) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ function flatMap<T, U>(xs: T[], f: (x: T) => U[]): U[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getTalerStampSec(stamp: string): number {
|
function getTalerStampSec(stamp: string): number|null {
|
||||||
const m = stamp.match(/\/?Date\(([0-9]*)\)\/?/);
|
const m = stamp.match(/\/?Date\(([0-9]*)\)\/?/);
|
||||||
if (!m) {
|
if (!m) {
|
||||||
return null;
|
return null;
|
||||||
@ -188,7 +188,7 @@ function getTalerStampSec(stamp: string): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function setTimeout(f, t) {
|
function setTimeout(f: any, t: number) {
|
||||||
return chrome.extension.getBackgroundPage().setTimeout(f, t);
|
return chrome.extension.getBackgroundPage().setTimeout(f, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,13 +211,13 @@ interface HttpRequestLibrary {
|
|||||||
|
|
||||||
get(url: string|uri.URI): Promise<HttpResponse>;
|
get(url: string|uri.URI): Promise<HttpResponse>;
|
||||||
|
|
||||||
postJson(url: string|uri.URI, body): Promise<HttpResponse>;
|
postJson(url: string|uri.URI, body: any): Promise<HttpResponse>;
|
||||||
|
|
||||||
postForm(url: string|uri.URI, form): Promise<HttpResponse>;
|
postForm(url: string|uri.URI, form: any): Promise<HttpResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function copy(o) {
|
function copy(o: any) {
|
||||||
return JSON.parse(JSON.stringify(o));
|
return JSON.parse(JSON.stringify(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ interface KeyUpdateInfo {
|
|||||||
function getWithdrawDenomList(amountAvailable: AmountJson,
|
function getWithdrawDenomList(amountAvailable: AmountJson,
|
||||||
denoms: Denomination[]): Denomination[] {
|
denoms: Denomination[]): Denomination[] {
|
||||||
let remaining = Amounts.copy(amountAvailable);
|
let remaining = Amounts.copy(amountAvailable);
|
||||||
let ds: Denomination[] = [];
|
const ds: Denomination[] = [];
|
||||||
|
|
||||||
console.log("available denoms");
|
console.log("available denoms");
|
||||||
console.log(denoms);
|
console.log(denoms);
|
||||||
@ -362,7 +362,7 @@ export class Wallet {
|
|||||||
|
|
||||||
let x: number;
|
let x: number;
|
||||||
|
|
||||||
function storeExchangeCoin(mc, url) {
|
function storeExchangeCoin(mc: any, url: string) {
|
||||||
let exchange: IExchangeInfo = mc[0];
|
let exchange: IExchangeInfo = mc[0];
|
||||||
console.log("got coin for exchange", url);
|
console.log("got coin for exchange", url);
|
||||||
let coin: Coin = mc[1];
|
let coin: Coin = mc[1];
|
||||||
@ -471,7 +471,7 @@ export class Wallet {
|
|||||||
private recordConfirmPay(offer: Offer,
|
private recordConfirmPay(offer: Offer,
|
||||||
payCoinInfo: PayCoinInfo,
|
payCoinInfo: PayCoinInfo,
|
||||||
chosenExchange: string): Promise<void> {
|
chosenExchange: string): Promise<void> {
|
||||||
let payReq = {};
|
let payReq: any = {};
|
||||||
payReq["amount"] = offer.contract.amount;
|
payReq["amount"] = offer.contract.amount;
|
||||||
payReq["coins"] = payCoinInfo.map((x) => x.sig);
|
payReq["coins"] = payCoinInfo.map((x) => x.sig);
|
||||||
payReq["H_contract"] = offer.H_contract;
|
payReq["H_contract"] = offer.H_contract;
|
||||||
@ -588,7 +588,7 @@ export class Wallet {
|
|||||||
* Retrieve all necessary information for looking up the contract
|
* Retrieve all necessary information for looking up the contract
|
||||||
* with the given hash.
|
* with the given hash.
|
||||||
*/
|
*/
|
||||||
executePayment(H_contract): Promise<any> {
|
executePayment(H_contract: string): Promise<any> {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
return Query(this.db)
|
return Query(this.db)
|
||||||
.get("transactions", H_contract)
|
.get("transactions", H_contract)
|
||||||
@ -614,7 +614,7 @@ export class Wallet {
|
|||||||
* First fetch information requred to withdraw from the reserve,
|
* First fetch information requred to withdraw from the reserve,
|
||||||
* then deplete the reserve, withdrawing coins until it is empty.
|
* then deplete the reserve, withdrawing coins until it is empty.
|
||||||
*/
|
*/
|
||||||
private processReserve(reserveRecord): void {
|
private processReserve(reserveRecord: any): void {
|
||||||
let retryDelayMs = 100;
|
let retryDelayMs = 100;
|
||||||
const opId = "reserve-" + reserveRecord.reserve_pub;
|
const opId = "reserve-" + reserveRecord.reserve_pub;
|
||||||
this.startOperation(opId);
|
this.startOperation(opId);
|
||||||
@ -644,7 +644,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private processPreCoin(preCoin, retryDelayMs = 100): void {
|
private processPreCoin(preCoin: any, retryDelayMs = 100): void {
|
||||||
this.withdrawExecute(preCoin)
|
this.withdrawExecute(preCoin)
|
||||||
.then((c) => this.storeCoin(c))
|
.then((c) => this.storeCoin(c))
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@ -810,7 +810,7 @@ export class Wallet {
|
|||||||
/**
|
/**
|
||||||
* Withdraw coins from a reserve until it is empty.
|
* Withdraw coins from a reserve until it is empty.
|
||||||
*/
|
*/
|
||||||
private depleteReserve(reserve, exchange: IExchangeInfo): Promise<void> {
|
private depleteReserve(reserve: any, exchange: IExchangeInfo): Promise<void> {
|
||||||
let denomsAvailable: Denomination[] = copy(exchange.active_denoms);
|
let denomsAvailable: Denomination[] = copy(exchange.active_denoms);
|
||||||
let denomsForWithdraw = getWithdrawDenomList(reserve.current_amount,
|
let denomsForWithdraw = getWithdrawDenomList(reserve.current_amount,
|
||||||
denomsAvailable);
|
denomsAvailable);
|
||||||
@ -919,7 +919,7 @@ export class Wallet {
|
|||||||
* Optionally link the reserve entry to the new or existing
|
* Optionally link the reserve entry to the new or existing
|
||||||
* exchange entry in then DB.
|
* exchange entry in then DB.
|
||||||
*/
|
*/
|
||||||
updateExchangeFromUrl(baseUrl): Promise<IExchangeInfo> {
|
updateExchangeFromUrl(baseUrl: string): Promise<IExchangeInfo> {
|
||||||
baseUrl = canonicalizeBaseUrl(baseUrl);
|
baseUrl = canonicalizeBaseUrl(baseUrl);
|
||||||
let reqUrl = URI("keys").absoluteTo(baseUrl);
|
let reqUrl = URI("keys").absoluteTo(baseUrl);
|
||||||
return this.http.get(reqUrl).then((resp) => {
|
return this.http.get(reqUrl).then((resp) => {
|
||||||
@ -934,8 +934,8 @@ export class Wallet {
|
|||||||
|
|
||||||
private updateExchangeFromJson(baseUrl: string,
|
private updateExchangeFromJson(baseUrl: string,
|
||||||
exchangeKeysJson: KeysJson): Promise<IExchangeInfo> {
|
exchangeKeysJson: KeysJson): Promise<IExchangeInfo> {
|
||||||
let updateTimeSec = getTalerStampSec(exchangeKeysJson.list_issue_date);
|
const updateTimeSec = getTalerStampSec(exchangeKeysJson.list_issue_date);
|
||||||
if (!updateTimeSec) {
|
if (updateTimeSec === null) {
|
||||||
throw Error("invalid update time");
|
throw Error("invalid update time");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,9 +973,9 @@ export class Wallet {
|
|||||||
{indexName: "exchangeBaseUrl", only: baseUrl})
|
{indexName: "exchangeBaseUrl", only: baseUrl})
|
||||||
.reduce((coin: Coin, suspendedCoins: Coin[]) => {
|
.reduce((coin: Coin, suspendedCoins: Coin[]) => {
|
||||||
if (!updatedExchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) {
|
if (!updatedExchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) {
|
||||||
return [].concat(suspendedCoins, [coin]);
|
return Array.prototype.concat(suspendedCoins, [coin]);
|
||||||
}
|
}
|
||||||
return [].concat(suspendedCoins);
|
return Array.prototype.concat(suspendedCoins);
|
||||||
}, [])
|
}, [])
|
||||||
.then((suspendedCoins: Coin[]) => {
|
.then((suspendedCoins: Coin[]) => {
|
||||||
let q = Query(this.db);
|
let q = Query(this.db);
|
||||||
@ -1006,8 +1006,8 @@ export class Wallet {
|
|||||||
let found = false;
|
let found = false;
|
||||||
for (let oldDenom of exchangeInfo.all_denoms) {
|
for (let oldDenom of exchangeInfo.all_denoms) {
|
||||||
if (oldDenom.denom_pub === newDenom.denom_pub) {
|
if (oldDenom.denom_pub === newDenom.denom_pub) {
|
||||||
let a = Object.assign({}, oldDenom);
|
let a: any = Object.assign({}, oldDenom);
|
||||||
let b = Object.assign({}, newDenom);
|
let b: any = Object.assign({}, newDenom);
|
||||||
// pub hash is only there for convenience in the wallet
|
// pub hash is only there for convenience in the wallet
|
||||||
delete a["pub_hash"];
|
delete a["pub_hash"];
|
||||||
delete b["pub_hash"];
|
delete b["pub_hash"];
|
||||||
@ -1055,7 +1055,7 @@ export class Wallet {
|
|||||||
* that is currenctly available for spending in the wallet.
|
* that is currenctly available for spending in the wallet.
|
||||||
*/
|
*/
|
||||||
getBalances(): Promise<any> {
|
getBalances(): Promise<any> {
|
||||||
function collectBalances(c: Coin, byCurrency) {
|
function collectBalances(c: Coin, byCurrency: any) {
|
||||||
if (c.suspended) {
|
if (c.suspended) {
|
||||||
return byCurrency;
|
return byCurrency;
|
||||||
}
|
}
|
||||||
@ -1081,7 +1081,7 @@ export class Wallet {
|
|||||||
* Retrive the full event history for this wallet.
|
* Retrive the full event history for this wallet.
|
||||||
*/
|
*/
|
||||||
getHistory(): Promise<any> {
|
getHistory(): Promise<any> {
|
||||||
function collect(x, acc) {
|
function collect(x: any, acc: any) {
|
||||||
acc.push(x);
|
acc.push(x);
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
@ -1106,7 +1106,7 @@ export class Wallet {
|
|||||||
[contract.merchant_pub, contract.repurchase_correlation_id])
|
[contract.merchant_pub, contract.repurchase_correlation_id])
|
||||||
.then((result: Transaction) => {
|
.then((result: Transaction) => {
|
||||||
console.log("db result", result);
|
console.log("db result", result);
|
||||||
let isRepurchase;
|
let isRepurchase: boolean;
|
||||||
if (result) {
|
if (result) {
|
||||||
console.assert(result.contract.repurchase_correlation_id == contract.repurchase_correlation_id);
|
console.assert(result.contract.repurchase_correlation_id == contract.repurchase_correlation_id);
|
||||||
return {
|
return {
|
||||||
|
@ -54,8 +54,12 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
return exportDb(db);
|
return exportDb(db);
|
||||||
},
|
},
|
||||||
["ping"]: function(detail, sender) {
|
["ping"]: function(detail, sender) {
|
||||||
let info = paymentRequestCookies[sender.tab.id];
|
if (!sender || !sender.tab || !sender.tab.id) {
|
||||||
delete paymentRequestCookies[sender.tab.id];
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
let id: number = sender.tab.id;
|
||||||
|
let info: any = <any>paymentRequestCookies[id];
|
||||||
|
delete paymentRequestCookies[id];
|
||||||
return Promise.resolve(info);
|
return Promise.resolve(info);
|
||||||
},
|
},
|
||||||
["reset"]: function(detail, sender) {
|
["reset"]: function(detail, sender) {
|
||||||
@ -89,7 +93,7 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
return wallet.confirmReserve(req);
|
return wallet.confirmReserve(req);
|
||||||
},
|
},
|
||||||
["confirm-pay"]: function(detail, sender) {
|
["confirm-pay"]: function(detail, sender) {
|
||||||
let offer;
|
let offer: Offer;
|
||||||
try {
|
try {
|
||||||
offer = Offer.checked(detail.offer);
|
offer = Offer.checked(detail.offer);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -108,7 +112,7 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
return wallet.confirmPay(offer);
|
return wallet.confirmPay(offer);
|
||||||
},
|
},
|
||||||
["check-pay"]: function(detail, sender) {
|
["check-pay"]: function(detail, sender) {
|
||||||
let offer;
|
let offer: Offer;
|
||||||
try {
|
try {
|
||||||
offer = Offer.checked(detail.offer);
|
offer = Offer.checked(detail.offer);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -181,14 +185,14 @@ class ChromeBadge implements Badge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function dispatch(handlers, req, sender, sendResponse) {
|
function dispatch(handlers: any, req: any, sender: any, sendResponse: any) {
|
||||||
if (req.type in handlers) {
|
if (req.type in handlers) {
|
||||||
Promise
|
Promise
|
||||||
.resolve()
|
.resolve()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const p = handlers[req.type](req.detail, sender);
|
const p = handlers[req.type](req.detail, sender);
|
||||||
|
|
||||||
return p.then((r) => {
|
return p.then((r: any) => {
|
||||||
sendResponse(r);
|
sendResponse(r);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -242,13 +246,15 @@ class ChromeNotifier implements Notifier {
|
|||||||
/**
|
/**
|
||||||
* Mapping from tab ID to payment information (if any).
|
* Mapping from tab ID to payment information (if any).
|
||||||
*/
|
*/
|
||||||
let paymentRequestCookies = {};
|
let paymentRequestCookies: {[n: number]: any} = {};
|
||||||
|
|
||||||
function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[],
|
function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[],
|
||||||
url: string, tabId: number): any {
|
url: string, tabId: number): any {
|
||||||
const headers = {};
|
const headers: {[s: string]: string} = {};
|
||||||
for (let kv of headerList) {
|
for (let kv of headerList) {
|
||||||
headers[kv.name.toLowerCase()] = kv.value;
|
if (kv.value) {
|
||||||
|
headers[kv.name.toLowerCase()] = kv.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const contractUrl = headers["x-taler-contract-url"];
|
const contractUrl = headers["x-taler-contract-url"];
|
||||||
@ -288,7 +294,7 @@ export function wxMain() {
|
|||||||
|
|
||||||
chrome.tabs.query({}, function(tabs) {
|
chrome.tabs.query({}, function(tabs) {
|
||||||
for (let tab of tabs) {
|
for (let tab of tabs) {
|
||||||
if (!tab.url) {
|
if (!tab.url || !tab.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let uri = URI(tab.url);
|
let uri = URI(tab.url);
|
||||||
@ -338,7 +344,7 @@ export function wxMain() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`got 402 from ${details.url}`);
|
console.log(`got 402 from ${details.url}`);
|
||||||
return handleHttpPayment(details.responseHeaders,
|
return handleHttpPayment(details.responseHeaders || [],
|
||||||
details.url,
|
details.url,
|
||||||
details.tabId);
|
details.tabId);
|
||||||
}, {urls: ["<all_urls>"]}, ["responseHeaders", "blocking"]);
|
}, {urls: ["<all_urls>"]}, ["responseHeaders", "blocking"]);
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"noLib": true,
|
"noLib": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noImplicitAny": true
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib/i18n.ts",
|
"lib/i18n.ts",
|
||||||
|
Loading…
Reference in New Issue
Block a user