refactor code to be clearer/prettier
This commit is contained in:
parent
4f934925e0
commit
ffe6dee6aa
@ -14,12 +14,12 @@
|
|||||||
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Handlebars.registerHelper('prettyAmount', function (amount) {
|
Handlebars.registerHelper("prettyAmount", function (amount) {
|
||||||
let v = amount.value + amount.fraction / 1e6;
|
let v = amount.value + amount.fraction / 1e6;
|
||||||
return v.toFixed(2) + " " + amount.currency;
|
return `${v.toFixed(2)} ${amount.currency}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
Handlebars.registerHelper('prettyAmountNoCurrency', function (amount) {
|
Handlebars.registerHelper("prettyAmountNoCurrency", function (amount) {
|
||||||
let v = amount.value + amount.fraction / 1e6;
|
let v = amount.value + amount.fraction / 1e6;
|
||||||
return v.toFixed(2);
|
return v.toFixed(2);
|
||||||
});
|
});
|
||||||
|
16
extension/lib/emscripten/emsc.d.ts
vendored
16
extension/lib/emscripten/emsc.d.ts
vendored
@ -19,23 +19,31 @@ export interface EmscFunGen {
|
|||||||
ret: string,
|
ret: string,
|
||||||
args: string[]): ((...x: (number|string)[]) => any);
|
args: string[]): ((...x: (number|string)[]) => any);
|
||||||
(name: string,
|
(name: string,
|
||||||
ret: 'number',
|
ret: "number",
|
||||||
args: string[]): ((...x: (number|string)[]) => number);
|
args: string[]): ((...x: (number|string)[]) => number);
|
||||||
(name: string,
|
(name: string,
|
||||||
ret: 'void',
|
ret: "void",
|
||||||
args: string[]): ((...x: (number|string)[]) => void);
|
args: string[]): ((...x: (number|string)[]) => void);
|
||||||
(name: string,
|
(name: string,
|
||||||
ret: 'string',
|
ret: "string",
|
||||||
args: string[]): ((...x: (number|string)[]) => string);
|
args: string[]): ((...x: (number|string)[]) => string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export declare namespace Module {
|
export declare namespace Module {
|
||||||
var cwrap: EmscFunGen;
|
var cwrap: EmscFunGen;
|
||||||
|
|
||||||
function _free(ptr: number);
|
function _free(ptr: number);
|
||||||
|
|
||||||
function _malloc(n: number): number;
|
function _malloc(n: number): number;
|
||||||
|
|
||||||
function Pointer_stringify(p: number, len?: number): string;
|
function Pointer_stringify(p: number, len?: number): string;
|
||||||
|
|
||||||
function getValue(ptr: number, type: string, noSafe?: boolean): number;
|
function getValue(ptr: number, type: string, noSafe?: boolean): number;
|
||||||
|
|
||||||
function setValue(ptr: number, value: number, type: string, noSafe?: boolean);
|
function setValue(ptr: number, value: number, type: string, noSafe?: boolean);
|
||||||
function writeStringToMemory(s: string, buffer: number, dontAddNull?: boolean);
|
|
||||||
|
function writeStringToMemory(s: string,
|
||||||
|
buffer: number,
|
||||||
|
dontAddNull?: boolean);
|
||||||
}
|
}
|
@ -1,3 +1,24 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
(C) 2016 GNUnet e.V.
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement the "React" namespace so that we can use TSX literals.
|
||||||
|
* Just returns plain DOM elements, no fancy virtual DOM.
|
||||||
|
*/
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let React = {
|
let React = {
|
||||||
@ -7,7 +28,7 @@ let React = {
|
|||||||
e.setAttribute(k, props[k]);
|
e.setAttribute(k, props[k]);
|
||||||
}
|
}
|
||||||
for (let child of children) {
|
for (let child of children) {
|
||||||
if ("string" === typeof child || "number" == typeof child) {
|
if ("string" === typeof child || "number" === typeof child) {
|
||||||
child = document.createTextNode(child);
|
child = document.createTextNode(child);
|
||||||
}
|
}
|
||||||
e.appendChild(child);
|
e.appendChild(child);
|
||||||
|
@ -36,7 +36,8 @@ const GNUNET_SYSERR = -1;
|
|||||||
|
|
||||||
let Module = EmscWrapper.Module;
|
let Module = EmscWrapper.Module;
|
||||||
|
|
||||||
let getEmsc: EmscWrapper.EmscFunGen = (...args) => Module.cwrap.apply(null, args);
|
let getEmsc: EmscWrapper.EmscFunGen = (...args) => Module.cwrap.apply(null,
|
||||||
|
args);
|
||||||
|
|
||||||
var emsc = {
|
var emsc = {
|
||||||
free: (ptr) => Module._free(ptr),
|
free: (ptr) => Module._free(ptr),
|
||||||
@ -447,8 +448,8 @@ abstract class PackedArenaObject extends ArenaObject {
|
|||||||
bytes.push("0".concat(b.toString(16)).slice(-2));
|
bytes.push("0".concat(b.toString(16)).slice(-2));
|
||||||
}
|
}
|
||||||
let lines = [];
|
let lines = [];
|
||||||
for (let i = 0; i < bytes.length; i+=8) {
|
for (let i = 0; i < bytes.length; i += 8) {
|
||||||
lines.push(bytes.slice(i, i+8).join(","));
|
lines.push(bytes.slice(i, i + 8).join(","));
|
||||||
}
|
}
|
||||||
return lines.join("\n");
|
return lines.join("\n");
|
||||||
}
|
}
|
||||||
@ -459,6 +460,7 @@ export class AmountNbo extends PackedArenaObject {
|
|||||||
size() {
|
size() {
|
||||||
return 24;
|
return 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJson(): any {
|
toJson(): any {
|
||||||
let a = new DefaultArena();
|
let a = new DefaultArena();
|
||||||
let am = new Amount(null, a);
|
let am = new Amount(null, a);
|
||||||
@ -526,6 +528,7 @@ export class EddsaPublicKey extends PackedArenaObject {
|
|||||||
size() {
|
size() {
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromCrock: (s: string) => EddsaPublicKey;
|
static fromCrock: (s: string) => EddsaPublicKey;
|
||||||
}
|
}
|
||||||
mixinStatic(EddsaPublicKey, fromCrock);
|
mixinStatic(EddsaPublicKey, fromCrock);
|
||||||
@ -543,7 +546,8 @@ function makeFromCrock(decodeFn: (p: number, s: number) => number) {
|
|||||||
return fromCrock;
|
return fromCrock;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeToCrock(encodeFn: (po: number, ps: number) => number): () => string {
|
function makeToCrock(encodeFn: (po: number,
|
||||||
|
ps: number) => number): () => string {
|
||||||
function toCrock() {
|
function toCrock() {
|
||||||
let ptr = emscAlloc.malloc(PTR_SIZE);
|
let ptr = emscAlloc.malloc(PTR_SIZE);
|
||||||
let size = emscAlloc.rsa_blinding_key_encode(this.nativePtr, ptr);
|
let size = emscAlloc.rsa_blinding_key_encode(this.nativePtr, ptr);
|
||||||
@ -553,6 +557,7 @@ function makeToCrock(encodeFn: (po: number, ps: number) => number): () => string
|
|||||||
res.destroy();
|
res.destroy();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return toCrock;
|
return toCrock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,7 +704,7 @@ abstract class SignatureStruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
toJson() {
|
toJson() {
|
||||||
let res: any = {};
|
let res: any = {};
|
||||||
for (let f of this.fieldTypes()) {
|
for (let f of this.fieldTypes()) {
|
||||||
let name = f[0];
|
let name = f[0];
|
||||||
@ -857,6 +862,7 @@ function makeEncode(encodeFn) {
|
|||||||
emsc.free(ptr);
|
emsc.free(ptr);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return encode;
|
return encode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -886,7 +892,7 @@ export class EddsaSignature extends PackedArenaObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class RsaSignature extends ArenaObject implements Encodeable{
|
export class RsaSignature extends ArenaObject implements Encodeable {
|
||||||
static fromCrock: (s: string, a?: Arena) => RsaSignature;
|
static fromCrock: (s: string, a?: Arena) => RsaSignature;
|
||||||
|
|
||||||
encode: (arena?: Arena) => ByteArray;
|
encode: (arena?: Arena) => ByteArray;
|
||||||
@ -901,9 +907,9 @@ mixin(RsaSignature, makeEncode(emscAlloc.rsa_signature_encode));
|
|||||||
|
|
||||||
|
|
||||||
export function rsaBlind(hashCode: HashCode,
|
export function rsaBlind(hashCode: HashCode,
|
||||||
blindingKey: RsaBlindingKey,
|
blindingKey: RsaBlindingKey,
|
||||||
pkey: RsaPublicKey,
|
pkey: RsaPublicKey,
|
||||||
arena?: Arena): ByteArray {
|
arena?: Arena): ByteArray {
|
||||||
let ptr = emscAlloc.malloc(PTR_SIZE);
|
let ptr = emscAlloc.malloc(PTR_SIZE);
|
||||||
let s = emscAlloc.rsa_blind(hashCode.nativePtr,
|
let s = emscAlloc.rsa_blind(hashCode.nativePtr,
|
||||||
blindingKey.nativePtr,
|
blindingKey.nativePtr,
|
||||||
@ -914,8 +920,8 @@ export function rsaBlind(hashCode: HashCode,
|
|||||||
|
|
||||||
|
|
||||||
export function eddsaSign(purpose: EccSignaturePurpose,
|
export function eddsaSign(purpose: EccSignaturePurpose,
|
||||||
priv: EddsaPrivateKey,
|
priv: EddsaPrivateKey,
|
||||||
a?: Arena): EddsaSignature {
|
a?: Arena): EddsaSignature {
|
||||||
let sig = new EddsaSignature(a);
|
let sig = new EddsaSignature(a);
|
||||||
sig.alloc();
|
sig.alloc();
|
||||||
let res = emsc.eddsa_sign(priv.nativePtr, purpose.nativePtr, sig.nativePtr);
|
let res = emsc.eddsa_sign(priv.nativePtr, purpose.nativePtr, sig.nativePtr);
|
||||||
@ -927,9 +933,9 @@ export function eddsaSign(purpose: EccSignaturePurpose,
|
|||||||
|
|
||||||
|
|
||||||
export function rsaUnblind(sig: RsaSignature,
|
export function rsaUnblind(sig: RsaSignature,
|
||||||
bk: RsaBlindingKey,
|
bk: RsaBlindingKey,
|
||||||
pk: RsaPublicKey,
|
pk: RsaPublicKey,
|
||||||
a?: Arena): RsaSignature {
|
a?: Arena): RsaSignature {
|
||||||
let x = new RsaSignature(a);
|
let x = new RsaSignature(a);
|
||||||
x.nativePtr = emscAlloc.rsa_unblind(sig.nativePtr,
|
x.nativePtr = emscAlloc.rsa_unblind(sig.nativePtr,
|
||||||
bk.nativePtr,
|
bk.nativePtr,
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export interface HttpResponse {
|
export interface HttpResponse {
|
||||||
status: number;
|
status: number;
|
||||||
responseText: string;
|
responseText: string;
|
||||||
@ -32,8 +31,8 @@ export interface HttpResponse {
|
|||||||
|
|
||||||
export class BrowserHttpLib {
|
export class BrowserHttpLib {
|
||||||
req(method: string,
|
req(method: string,
|
||||||
url: string|uri.URI,
|
url: string|uri.URI,
|
||||||
options?: any): Promise<HttpResponse> {
|
options?: any): Promise<HttpResponse> {
|
||||||
let urlString: string;
|
let urlString: string;
|
||||||
if (url instanceof URI) {
|
if (url instanceof URI) {
|
||||||
urlString = url.href();
|
urlString = url.href();
|
||||||
|
@ -30,9 +30,39 @@ export function Query(db) {
|
|||||||
return new QueryRoot(db);
|
return new QueryRoot(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream that can be filtered, reduced or joined
|
||||||
|
* with indices.
|
||||||
|
*/
|
||||||
|
export interface QueryStream<T> {
|
||||||
|
indexJoin<S>(storeName: string,
|
||||||
|
indexName: string,
|
||||||
|
keyFn: (obj: any) => any): QueryStream<[T,S]>;
|
||||||
|
filter(f: (any) => boolean): QueryStream<T>;
|
||||||
|
reduce<S>(f: (S, T) => S, acc?: S): Promise<S>;
|
||||||
|
}
|
||||||
|
|
||||||
abstract class QueryStreamBase {
|
|
||||||
abstract subscribe(f: (isDone: boolean, value: any) => void);
|
/**
|
||||||
|
* Get an unresolved promise together with its extracted resolve / reject
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* @returns {{resolve: any, reject: any, promise: Promise<T>}}
|
||||||
|
*/
|
||||||
|
function openPromise<T>() {
|
||||||
|
let resolve, reject;
|
||||||
|
const promise = new Promise<T>((res, rej) => {
|
||||||
|
resolve = res;
|
||||||
|
reject = rej;
|
||||||
|
});
|
||||||
|
return {resolve, reject, promise};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
abstract class QueryStreamBase<T> implements QueryStream<T> {
|
||||||
|
abstract subscribe(f: (isDone: boolean,
|
||||||
|
value: any,
|
||||||
|
tx: IDBTransaction) => void);
|
||||||
|
|
||||||
root: QueryRoot;
|
root: QueryRoot;
|
||||||
|
|
||||||
@ -40,14 +70,14 @@ abstract class QueryStreamBase {
|
|||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
indexJoin(storeName: string, indexName: string, key: any): QueryStreamBase {
|
indexJoin<S>(storeName: string,
|
||||||
// join on the source relation's key, which may be
|
indexName: string,
|
||||||
// a path or a transformer function
|
key: any): QueryStream<[T,S]> {
|
||||||
this.root.stores.add(storeName);
|
this.root.addWork(null, storeName, false);
|
||||||
return new QueryStreamIndexJoin(this, storeName, indexName, key);
|
return new QueryStreamIndexJoin(this, storeName, indexName, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter(f: (any) => boolean): QueryStreamBase {
|
filter(f: (any) => boolean): QueryStream<T> {
|
||||||
return new QueryStreamFilter(this, f);
|
return new QueryStreamFilter(this, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,37 +95,39 @@ abstract class QueryStreamBase {
|
|||||||
acc = f(value, acc);
|
acc = f(value, acc);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.resolve().then(() => this.root.finish().then(() => p));
|
return Promise.resolve()
|
||||||
|
.then(() => this.root.finish())
|
||||||
|
.then(() => p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class QueryStreamFilter extends QueryStreamBase {
|
class QueryStreamFilter<T> extends QueryStreamBase<T> {
|
||||||
s: QueryStreamBase;
|
s: QueryStreamBase<T>;
|
||||||
filterFn;
|
filterFn;
|
||||||
|
|
||||||
constructor(s: QueryStreamBase, filterFn) {
|
constructor(s: QueryStreamBase<T>, filterFn) {
|
||||||
super(s.root);
|
super(s.root);
|
||||||
this.s = s;
|
this.s = s;
|
||||||
this.filterFn = filterFn;
|
this.filterFn = filterFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(f) {
|
subscribe(f) {
|
||||||
this.s.subscribe((isDone, value) => {
|
this.s.subscribe((isDone, value, tx) => {
|
||||||
if (isDone) {
|
if (isDone) {
|
||||||
f(true, undefined);
|
f(true, undefined, tx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.filterFn(value)) {
|
if (this.filterFn(value)) {
|
||||||
f(false, value)
|
f(false, value, tx)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class QueryStreamIndexJoin extends QueryStreamBase {
|
class QueryStreamIndexJoin<T> extends QueryStreamBase<T> {
|
||||||
s: QueryStreamBase;
|
s: QueryStreamBase<T>;
|
||||||
storeName;
|
storeName;
|
||||||
key;
|
key;
|
||||||
indexName;
|
indexName;
|
||||||
@ -109,48 +141,45 @@ class QueryStreamIndexJoin extends QueryStreamBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
subscribe(f) {
|
subscribe(f) {
|
||||||
this.s.subscribe((isDone, value) => {
|
this.s.subscribe((isDone, value, tx) => {
|
||||||
if (isDone) {
|
if (isDone) {
|
||||||
f(true, undefined);
|
f(true, undefined, tx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let s = this.root.tx.objectStore(this.storeName).index(this.indexName);
|
let s = tx.objectStore(this.storeName).index(this.indexName);
|
||||||
let req = s.openCursor(IDBKeyRange.only(this.key(value)));
|
let req = s.openCursor(IDBKeyRange.only(this.key(value)));
|
||||||
req.onsuccess = () => {
|
req.onsuccess = () => {
|
||||||
let cursor = req.result;
|
let cursor = req.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
f(false, [value, cursor.value]);
|
f(false, [value, cursor.value], tx);
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
} else {
|
} else {
|
||||||
f(true, undefined);
|
f(true, undefined, tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class IterQueryStream extends QueryStreamBase {
|
class IterQueryStream<T> extends QueryStreamBase<T> {
|
||||||
private qr: QueryRoot;
|
|
||||||
private storeName;
|
private storeName;
|
||||||
private options;
|
private options;
|
||||||
|
|
||||||
constructor(qr, storeName, options?) {
|
constructor(qr, storeName, options?) {
|
||||||
super(qr);
|
super(qr);
|
||||||
this.qr = qr;
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.storeName = storeName;
|
this.storeName = storeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(f) {
|
subscribe(f) {
|
||||||
function doIt() {
|
let doIt = (tx) => {
|
||||||
let s;
|
let s;
|
||||||
if (this.options && this.options.indexName) {
|
if (this.options && this.options.indexName) {
|
||||||
s = this.qr.tx.objectStore(this.storeName)
|
s = tx.objectStore(this.storeName)
|
||||||
.index(this.options.indexName);
|
.index(this.options.indexName);
|
||||||
} else {
|
} else {
|
||||||
s = this.qr.tx.objectStore(this.storeName);
|
s = tx.objectStore(this.storeName);
|
||||||
}
|
}
|
||||||
let kr = undefined;
|
let kr = undefined;
|
||||||
if (this.options && ("only" in this.options)) {
|
if (this.options && ("only" in this.options)) {
|
||||||
@ -160,124 +189,158 @@ class IterQueryStream extends QueryStreamBase {
|
|||||||
req.onsuccess = (e) => {
|
req.onsuccess = (e) => {
|
||||||
let cursor: IDBCursorWithValue = req.result;
|
let cursor: IDBCursorWithValue = req.result;
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
f(false, cursor.value);
|
f(false, cursor.value, tx);
|
||||||
cursor.continue();
|
cursor.continue();
|
||||||
} else {
|
} else {
|
||||||
f(true, undefined);
|
f(true, undefined, tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
this.qr.work.push(doIt.bind(this));
|
this.root.addWork(doIt, null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class QueryRoot {
|
class QueryRoot {
|
||||||
work = [];
|
private work = [];
|
||||||
db: IDBDatabase;
|
private db: IDBDatabase;
|
||||||
tx: IDBTransaction;
|
private stores = new Set();
|
||||||
stores = new Set();
|
private kickoffPromise;
|
||||||
kickoffPromise;
|
|
||||||
|
/**
|
||||||
|
* Some operations is a write operation,
|
||||||
|
* and we need to do a "readwrite" transaction/
|
||||||
|
*/
|
||||||
|
private hasWrite;
|
||||||
|
|
||||||
constructor(db) {
|
constructor(db) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter(storeName): QueryStreamBase {
|
iter<T>(storeName): QueryStream<T> {
|
||||||
this.stores.add(storeName);
|
this.stores.add(storeName);
|
||||||
return new IterQueryStream(this, storeName);
|
return new IterQueryStream(this, storeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterOnly(storeName, key): QueryStreamBase {
|
iterOnly<T>(storeName, key): QueryStream<T> {
|
||||||
this.stores.add(storeName);
|
this.stores.add(storeName);
|
||||||
return new IterQueryStream(this, storeName, {only: key});
|
return new IterQueryStream(this, storeName, {only: key});
|
||||||
}
|
}
|
||||||
|
|
||||||
iterIndex(storeName, indexName, key) {
|
|
||||||
|
iterIndex<T>(storeName, indexName, key) {
|
||||||
this.stores.add(storeName);
|
this.stores.add(storeName);
|
||||||
return new IterQueryStream(this, storeName, {indexName: indexName});
|
return new IterQueryStream(this, storeName, {indexName: indexName});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put an object into the given object store.
|
||||||
|
* Overrides if an existing object with the same key exists
|
||||||
|
* in the store.
|
||||||
|
*/
|
||||||
put(storeName, val): QueryRoot {
|
put(storeName, val): QueryRoot {
|
||||||
this.stores.add(storeName);
|
let doPut = (tx: IDBTransaction) => {
|
||||||
function doPut() {
|
tx.objectStore(storeName).put(val);
|
||||||
this.tx.objectStore(storeName).put(val);
|
};
|
||||||
}
|
this.addWork(doPut, storeName, true);
|
||||||
|
|
||||||
this.work.push(doPut.bind(this));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all object from an iterable to the given object store.
|
||||||
|
* Fails if the object's key is already present
|
||||||
|
* in the object store.
|
||||||
|
*/
|
||||||
putAll(storeName, iterable): QueryRoot {
|
putAll(storeName, iterable): QueryRoot {
|
||||||
this.stores.add(storeName);
|
const doPutAll = (tx: IDBTransaction) => {
|
||||||
function doPutAll() {
|
for (const obj of iterable) {
|
||||||
for (let obj of iterable) {
|
tx.objectStore(storeName).put(obj);
|
||||||
this.tx.objectStore(storeName).put(obj);
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
this.addWork(doPutAll, storeName, true);
|
||||||
this.work.push(doPutAll.bind(this));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an object to the given object store.
|
||||||
|
* Fails if the object's key is already present
|
||||||
|
* in the object store.
|
||||||
|
*/
|
||||||
add(storeName, val): QueryRoot {
|
add(storeName, val): QueryRoot {
|
||||||
this.stores.add(storeName);
|
const doAdd = (tx: IDBTransaction) => {
|
||||||
function doAdd() {
|
tx.objectStore(storeName).add(val);
|
||||||
this.tx.objectStore(storeName).add(val);
|
};
|
||||||
}
|
this.addWork(doAdd, storeName, true);
|
||||||
|
|
||||||
this.work.push(doAdd.bind(this));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get one object from a store by its key.
|
||||||
|
*/
|
||||||
get(storeName, key): Promise<any> {
|
get(storeName, key): Promise<any> {
|
||||||
this.stores.add(storeName);
|
const {resolve, promise} = openPromise();
|
||||||
let leakedResolve;
|
|
||||||
let p = new Promise((resolve, reject) => {
|
|
||||||
leakedResolve = resolve;
|
|
||||||
});
|
|
||||||
if (!leakedResolve) {
|
|
||||||
// According to ES6 spec (paragraph 25.4.3.1), this can't happen.
|
|
||||||
throw Error("assertion failed");
|
|
||||||
}
|
|
||||||
function doGet() {
|
|
||||||
let req = this.tx.objectStore(storeName).get(key);
|
|
||||||
req.onsuccess = (r) => {
|
|
||||||
leakedResolve(req.result);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.work.push(doGet.bind(this));
|
const doGet = (tx) => {
|
||||||
return Promise.resolve().then(() => {
|
const req = tx.objectStore(storeName).get(key);
|
||||||
return this.finish().then(() => p);
|
req.onsuccess = (r) => {
|
||||||
});
|
resolve(req.result);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addWork(doGet, storeName, false);
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(() => this.finish())
|
||||||
|
.then(() => promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the query, and start the query in the first place if necessary.
|
||||||
|
*/
|
||||||
finish(): Promise<void> {
|
finish(): Promise<void> {
|
||||||
if (this.kickoffPromise) {
|
if (this.kickoffPromise) {
|
||||||
return this.kickoffPromise;
|
return this.kickoffPromise;
|
||||||
}
|
}
|
||||||
this.kickoffPromise = new Promise((resolve, reject) => {
|
this.kickoffPromise = new Promise((resolve, reject) => {
|
||||||
|
const mode = this.hasWrite ? "readwrite" : "readonly";
|
||||||
this.tx = this.db.transaction(Array.from(this.stores), "readwrite");
|
const tx = this.db.transaction(Array.from(this.stores), mode);
|
||||||
this.tx.oncomplete = () => {
|
tx.oncomplete = () => {
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
for (let w of this.work) {
|
for (let w of this.work) {
|
||||||
w();
|
w(tx);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return this.kickoffPromise;
|
return this.kickoffPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an object by from the given object store.
|
||||||
|
*/
|
||||||
delete(storeName: string, key): QueryRoot {
|
delete(storeName: string, key): QueryRoot {
|
||||||
this.stores.add(storeName);
|
const doDelete = (tx) => {
|
||||||
function doDelete() {
|
tx.objectStore(storeName).delete(key);
|
||||||
this.tx.objectStore(storeName).delete(key);
|
};
|
||||||
}
|
this.addWork(doDelete, storeName, true);
|
||||||
|
|
||||||
this.work.push(doDelete.bind(this));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Low-level function to add a task to the internal work queue.
|
||||||
|
*/
|
||||||
|
addWork(workFn: (IDBTransaction) => void,
|
||||||
|
storeName: string,
|
||||||
|
isWrite: boolean) {
|
||||||
|
if (storeName) {
|
||||||
|
this.stores.add(storeName);
|
||||||
|
}
|
||||||
|
if (isWrite) {
|
||||||
|
this.hasWrite = true;
|
||||||
|
}
|
||||||
|
if (workFn) {
|
||||||
|
this.work.push(workFn);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,10 +0,0 @@
|
|||||||
/**
|
|
||||||
* This file should be used as a WebWorker.
|
|
||||||
* Background pages in the WebExtensions model do
|
|
||||||
* not allow to schedule callbacks that should be called
|
|
||||||
* after a timeout. We can emulate this with WebWorkers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
onmessage = function(e) {
|
|
||||||
self.setInterval(() => postMessage(true, "timerThread"), e.data.interval);
|
|
||||||
};
|
|
@ -462,8 +462,10 @@ export class Wallet {
|
|||||||
.then((mint) =>
|
.then((mint) =>
|
||||||
this.updateReserve(reservePub, mint)
|
this.updateReserve(reservePub, mint)
|
||||||
.then((reserve) => this.depleteReserve(reserve,
|
.then((reserve) => this.depleteReserve(reserve,
|
||||||
mint))
|
mint)))
|
||||||
);
|
.catch((e) => {
|
||||||
|
console.error("Failed to deplete reserve", e.stack);
|
||||||
|
});
|
||||||
return resp;
|
return resp;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -137,7 +137,6 @@ System.register(["./wallet", "./db", "./http"], function(exports_1) {
|
|||||||
};
|
};
|
||||||
return ChromeBadge;
|
return ChromeBadge;
|
||||||
}());
|
}());
|
||||||
wxMain();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -132,4 +132,4 @@ export function wxMain() {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -19,7 +19,6 @@
|
|||||||
"lib/wallet/types.ts",
|
"lib/wallet/types.ts",
|
||||||
"lib/commonHelpers.ts",
|
"lib/commonHelpers.ts",
|
||||||
"lib/polyfill-react.ts",
|
"lib/polyfill-react.ts",
|
||||||
"lib/wallet/timerThread.ts",
|
|
||||||
"content_scripts/notify.ts",
|
"content_scripts/notify.ts",
|
||||||
"background/main.ts",
|
"background/main.ts",
|
||||||
"popup/balance-overview.tsx",
|
"popup/balance-overview.tsx",
|
||||||
|
Loading…
Reference in New Issue
Block a user