make db layer more type safe
This commit is contained in:
parent
78ea2ba5b1
commit
89c3c2d58d
@ -34,6 +34,13 @@ declare var cloneInto: any;
|
|||||||
namespace TalerNotify {
|
namespace TalerNotify {
|
||||||
const PROTOCOL_VERSION = 1;
|
const PROTOCOL_VERSION = 1;
|
||||||
|
|
||||||
|
let logVerbose: boolean = false;
|
||||||
|
try {
|
||||||
|
logVerbose = !!localStorage.getItem("taler-log-verbose");
|
||||||
|
} catch (e) {
|
||||||
|
// can't read from local storage
|
||||||
|
}
|
||||||
|
|
||||||
if (!taler) {
|
if (!taler) {
|
||||||
console.error("Taler wallet lib not included, HTTP 402 payments not" +
|
console.error("Taler wallet lib not included, HTTP 402 payments not" +
|
||||||
" supported");
|
" supported");
|
||||||
@ -98,7 +105,7 @@ namespace TalerNotify {
|
|||||||
function init() {
|
function init() {
|
||||||
chrome.runtime.sendMessage({type: "get-tab-cookie"}, (resp) => {
|
chrome.runtime.sendMessage({type: "get-tab-cookie"}, (resp) => {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.log("extension not yet ready");
|
logVerbose && console.log("extension not yet ready");
|
||||||
window.setTimeout(init, 200);
|
window.setTimeout(init, 200);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -107,19 +114,19 @@ namespace TalerNotify {
|
|||||||
let port = chrome.runtime.connect();
|
let port = chrome.runtime.connect();
|
||||||
|
|
||||||
port.onDisconnect.addListener(() => {
|
port.onDisconnect.addListener(() => {
|
||||||
console.log("chrome runtime disconnected, removing handlers");
|
logVerbose && console.log("chrome runtime disconnected, removing handlers");
|
||||||
for (let handler of handlers) {
|
for (let handler of handlers) {
|
||||||
document.removeEventListener(handler.type, handler.listener);
|
document.removeEventListener(handler.type, handler.listener);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (resp && resp.type === "fetch") {
|
if (resp && resp.type === "fetch") {
|
||||||
console.log("it's fetch");
|
logVerbose && console.log("it's fetch");
|
||||||
taler.internalOfferContractFrom(resp.contractUrl);
|
taler.internalOfferContractFrom(resp.contractUrl);
|
||||||
document.documentElement.style.visibility = "hidden";
|
document.documentElement.style.visibility = "hidden";
|
||||||
|
|
||||||
} else if (resp && resp.type === "execute") {
|
} else if (resp && resp.type === "execute") {
|
||||||
console.log("it's execute");
|
logVerbose && console.log("it's execute");
|
||||||
document.documentElement.style.visibility = "hidden";
|
document.documentElement.style.visibility = "hidden";
|
||||||
taler.internalExecutePayment(resp.contractHash,
|
taler.internalExecutePayment(resp.contractHash,
|
||||||
resp.payUrl,
|
resp.payUrl,
|
||||||
@ -128,7 +135,7 @@ namespace TalerNotify {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("loading Taler content script");
|
logVerbose && console.log("loading Taler content script");
|
||||||
init();
|
init();
|
||||||
|
|
||||||
interface HandlerFn {
|
interface HandlerFn {
|
||||||
@ -238,7 +245,7 @@ namespace TalerNotify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (resp.isRepurchase) {
|
if (resp.isRepurchase) {
|
||||||
console.log("doing repurchase");
|
logVerbose && console.log("doing repurchase");
|
||||||
console.assert(resp.existingFulfillmentUrl);
|
console.assert(resp.existingFulfillmentUrl);
|
||||||
console.assert(resp.existingContractHash);
|
console.assert(resp.existingContractHash);
|
||||||
window.location.href = subst(resp.existingFulfillmentUrl,
|
window.location.href = subst(resp.existingFulfillmentUrl,
|
||||||
@ -296,7 +303,7 @@ namespace TalerNotify {
|
|||||||
console.error("H_contract missing in taler-payment-succeeded");
|
console.error("H_contract missing in taler-payment-succeeded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("got taler-payment-succeeded");
|
logVerbose && console.log("got taler-payment-succeeded");
|
||||||
const walletMsg = {
|
const walletMsg = {
|
||||||
type: "payment-succeeded",
|
type: "payment-succeeded",
|
||||||
detail: {
|
detail: {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
import {IExchangeInfo} from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declarations and helpers for
|
* Declarations and helpers for
|
||||||
@ -27,6 +28,7 @@
|
|||||||
const DB_NAME = "taler";
|
const DB_NAME = "taler";
|
||||||
const DB_VERSION = 10;
|
const DB_VERSION = 10;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a promise that resolves
|
* Return a promise that resolves
|
||||||
* to the taler wallet db.
|
* to the taler wallet db.
|
||||||
|
@ -24,6 +24,16 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
|
export class Store<T> {
|
||||||
|
name: string;
|
||||||
|
validator?: (v: T) => T;
|
||||||
|
|
||||||
|
constructor(name: string, validator?: (v: T) => T) {
|
||||||
|
this.name = name;
|
||||||
|
this.validator = validator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stream that can be filtered, reduced or joined
|
* Stream that can be filtered, reduced or joined
|
||||||
* with indices.
|
* with indices.
|
||||||
@ -277,10 +287,10 @@ export class QueryRoot {
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter<T>(storeName: string,
|
iter<T>(store: Store<T>,
|
||||||
{only = <string | undefined>undefined, indexName = <string | undefined>undefined} = {}): QueryStream<T> {
|
{only = <string | undefined>undefined, indexName = <string | undefined>undefined} = {}): QueryStream<T> {
|
||||||
this.stores.add(storeName);
|
this.stores.add(store.name);
|
||||||
return new IterQueryStream(this, storeName, { only, indexName });
|
return new IterQueryStream(this, store.name, { only, indexName });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,11 +298,11 @@ export 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: string, val: any): QueryRoot {
|
put<T>(store: Store<T>, val: T): QueryRoot {
|
||||||
let doPut = (tx: IDBTransaction) => {
|
let doPut = (tx: IDBTransaction) => {
|
||||||
tx.objectStore(storeName).put(val);
|
tx.objectStore(store.name).put(val);
|
||||||
};
|
};
|
||||||
this.addWork(doPut, storeName, true);
|
this.addWork(doPut, store.name, true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,13 +312,13 @@ export 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: string, iterable: any[]): QueryRoot {
|
putAll<T>(store: Store<T>, iterable: T[]): QueryRoot {
|
||||||
const doPutAll = (tx: IDBTransaction) => {
|
const doPutAll = (tx: IDBTransaction) => {
|
||||||
for (let obj of iterable) {
|
for (let obj of iterable) {
|
||||||
tx.objectStore(storeName).put(obj);
|
tx.objectStore(store.name).put(obj);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.addWork(doPutAll, storeName, true);
|
this.addWork(doPutAll, store.name, true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,18 +327,18 @@ export 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: string, val: any): QueryRoot {
|
add<T>(store: Store<T>, val: T): QueryRoot {
|
||||||
const doAdd = (tx: IDBTransaction) => {
|
const doAdd = (tx: IDBTransaction) => {
|
||||||
tx.objectStore(storeName).add(val);
|
tx.objectStore(store.name).add(val);
|
||||||
};
|
};
|
||||||
this.addWork(doAdd, storeName, true);
|
this.addWork(doAdd, store.name, true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get one object from a store by its key.
|
* Get one object from a store by its key.
|
||||||
*/
|
*/
|
||||||
get<T>(storeName: any, key: any): Promise<T|undefined> {
|
get<T>(store: Store<T>, key: any): Promise<T|undefined> {
|
||||||
if (key === void 0) {
|
if (key === void 0) {
|
||||||
throw Error("key must not be undefined");
|
throw Error("key must not be undefined");
|
||||||
}
|
}
|
||||||
@ -336,13 +346,13 @@ export class QueryRoot {
|
|||||||
const {resolve, promise} = openPromise();
|
const {resolve, promise} = openPromise();
|
||||||
|
|
||||||
const doGet = (tx: IDBTransaction) => {
|
const doGet = (tx: IDBTransaction) => {
|
||||||
const req = tx.objectStore(storeName).get(key);
|
const req = tx.objectStore(store.name).get(key);
|
||||||
req.onsuccess = () => {
|
req.onsuccess = () => {
|
||||||
resolve(req.result);
|
resolve(req.result);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addWork(doGet, storeName, false);
|
this.addWork(doGet, store.name, false);
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => this.finish())
|
.then(() => this.finish())
|
||||||
.then(() => promise);
|
.then(() => promise);
|
||||||
|
@ -30,7 +30,7 @@ import {
|
|||||||
WireInfo, RefreshSession, ReserveRecord, CoinPaySig
|
WireInfo, RefreshSession, ReserveRecord, CoinPaySig
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import {HttpResponse, RequestException} from "./http";
|
import {HttpResponse, RequestException} from "./http";
|
||||||
import {QueryRoot} from "./query";
|
import {QueryRoot, Store} from "./query";
|
||||||
import {Checkable} from "./checkable";
|
import {Checkable} from "./checkable";
|
||||||
import {canonicalizeBaseUrl} from "./helpers";
|
import {canonicalizeBaseUrl} from "./helpers";
|
||||||
import {ReserveCreationInfo, Amounts} from "./types";
|
import {ReserveCreationInfo, Amounts} from "./types";
|
||||||
@ -305,6 +305,17 @@ function getWithdrawDenomList(amountAvailable: AmountJson,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace Stores {
|
||||||
|
export let exchanges: Store<IExchangeInfo> = new Store<IExchangeInfo>("exchanges");
|
||||||
|
export let transactions: Store<Transaction> = new Store<Transaction>("transactions");
|
||||||
|
export let reserves: Store<ReserveRecord> = new Store<ReserveRecord>("reserves");
|
||||||
|
export let coins: Store<Coin> = new Store<Coin>("coins");
|
||||||
|
export let refresh: Store<RefreshSession> = new Store<RefreshSession>("refresh");
|
||||||
|
export let history: Store<HistoryRecord> = new Store<HistoryRecord>("history");
|
||||||
|
export let precoins: Store<PreCoin> = new Store<PreCoin>("precoins");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class Wallet {
|
export class Wallet {
|
||||||
private db: IDBDatabase;
|
private db: IDBDatabase;
|
||||||
private http: HttpRequestLibrary;
|
private http: HttpRequestLibrary;
|
||||||
@ -351,7 +362,7 @@ export class Wallet {
|
|||||||
console.log("updating exchanges");
|
console.log("updating exchanges");
|
||||||
|
|
||||||
this.q()
|
this.q()
|
||||||
.iter("exchanges")
|
.iter(Stores.exchanges)
|
||||||
.reduce((exchange: IExchangeInfo) => {
|
.reduce((exchange: IExchangeInfo) => {
|
||||||
this.updateExchangeFromUrl(exchange.baseUrl)
|
this.updateExchangeFromUrl(exchange.baseUrl)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@ -368,28 +379,28 @@ export class Wallet {
|
|||||||
console.log("resuming pending operations from db");
|
console.log("resuming pending operations from db");
|
||||||
|
|
||||||
this.q()
|
this.q()
|
||||||
.iter("reserves")
|
.iter(Stores.reserves)
|
||||||
.reduce((reserve: any) => {
|
.reduce((reserve) => {
|
||||||
console.log("resuming reserve", reserve.reserve_pub);
|
console.log("resuming reserve", reserve.reserve_pub);
|
||||||
this.processReserve(reserve);
|
this.processReserve(reserve);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.q()
|
this.q()
|
||||||
.iter("precoins")
|
.iter(Stores.precoins)
|
||||||
.reduce((preCoin: any) => {
|
.reduce((preCoin) => {
|
||||||
console.log("resuming precoin");
|
console.log("resuming precoin");
|
||||||
this.processPreCoin(preCoin);
|
this.processPreCoin(preCoin);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.q()
|
this.q()
|
||||||
.iter("refresh")
|
.iter(Stores.refresh)
|
||||||
.reduce((r: RefreshSession) => {
|
.reduce((r: RefreshSession) => {
|
||||||
this.continueRefreshSession(r);
|
this.continueRefreshSession(r);
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: optimize via index
|
// FIXME: optimize via index
|
||||||
this.q()
|
this.q()
|
||||||
.iter("coins")
|
.iter(Stores.coins)
|
||||||
.reduce((c: Coin) => {
|
.reduce((c: Coin) => {
|
||||||
if (c.dirty && !c.transactionPending) {
|
if (c.dirty && !c.transactionPending) {
|
||||||
this.refresh(c.coinPub);
|
this.refresh(c.coinPub);
|
||||||
@ -452,7 +463,7 @@ export class Wallet {
|
|||||||
console.log("Checking for merchant's exchange", JSON.stringify(info));
|
console.log("Checking for merchant's exchange", JSON.stringify(info));
|
||||||
return [
|
return [
|
||||||
this.q()
|
this.q()
|
||||||
.iter("exchanges", {indexName: "pubKey", only: info.master_pub})
|
.iter(Stores.exchanges, {indexName: "pubKey", only: info.master_pub})
|
||||||
.indexJoin("coins",
|
.indexJoin("coins",
|
||||||
"exchangeBaseUrl",
|
"exchangeBaseUrl",
|
||||||
(exchange) => exchange.baseUrl)
|
(exchange) => exchange.baseUrl)
|
||||||
@ -536,7 +547,7 @@ export class Wallet {
|
|||||||
merchantSig: offer.merchant_sig,
|
merchantSig: offer.merchant_sig,
|
||||||
};
|
};
|
||||||
|
|
||||||
let historyEntry = {
|
let historyEntry: HistoryRecord = {
|
||||||
type: "pay",
|
type: "pay",
|
||||||
timestamp: (new Date).getTime(),
|
timestamp: (new Date).getTime(),
|
||||||
subjectId: `contract-${offer.H_contract}`,
|
subjectId: `contract-${offer.H_contract}`,
|
||||||
@ -545,13 +556,14 @@ export class Wallet {
|
|||||||
amount: offer.contract.amount,
|
amount: offer.contract.amount,
|
||||||
contractHash: offer.H_contract,
|
contractHash: offer.H_contract,
|
||||||
fulfillmentUrl: offer.contract.fulfillment_url,
|
fulfillmentUrl: offer.contract.fulfillment_url,
|
||||||
}
|
},
|
||||||
|
level: HistoryLevel.User
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.put("transactions", t)
|
.put(Stores.transactions, t)
|
||||||
.put("history", historyEntry)
|
.put(Stores.history, historyEntry)
|
||||||
.putAll("coins", payCoinInfo.map((pci) => pci.updatedCoin))
|
.putAll(Stores.coins, payCoinInfo.map((pci) => pci.updatedCoin))
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
this.notifier.notify();
|
this.notifier.notify();
|
||||||
@ -559,7 +571,7 @@ export class Wallet {
|
|||||||
|
|
||||||
|
|
||||||
async putHistory(historyEntry: HistoryRecord): Promise<void> {
|
async putHistory(historyEntry: HistoryRecord): Promise<void> {
|
||||||
await this.q().put("history", historyEntry).finish();
|
await this.q().put(Stores.history, historyEntry).finish();
|
||||||
this.notifier.notify();
|
this.notifier.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,7 +583,7 @@ export class Wallet {
|
|||||||
async confirmPay(offer: Offer): Promise<any> {
|
async confirmPay(offer: Offer): Promise<any> {
|
||||||
console.log("executing confirmPay");
|
console.log("executing confirmPay");
|
||||||
|
|
||||||
let transaction = await this.q().get("transactions", offer.H_contract);
|
let transaction = await this.q().get(Stores.transactions, offer.H_contract);
|
||||||
|
|
||||||
if (transaction) {
|
if (transaction) {
|
||||||
// Already payed ...
|
// Already payed ...
|
||||||
@ -604,7 +616,7 @@ export class Wallet {
|
|||||||
*/
|
*/
|
||||||
async checkPay(offer: Offer): Promise<any> {
|
async checkPay(offer: Offer): Promise<any> {
|
||||||
// First check if we already payed for it.
|
// First check if we already payed for it.
|
||||||
let transaction = await this.q().get("transactions", offer.H_contract);
|
let transaction = await this.q().get(Stores.transactions, offer.H_contract);
|
||||||
if (transaction) {
|
if (transaction) {
|
||||||
return {isPayed: true};
|
return {isPayed: true};
|
||||||
}
|
}
|
||||||
@ -629,7 +641,7 @@ export class Wallet {
|
|||||||
* with the given hash.
|
* with the given hash.
|
||||||
*/
|
*/
|
||||||
async executePayment(H_contract: string): Promise<any> {
|
async executePayment(H_contract: string): Promise<any> {
|
||||||
let t = await this.q().get<Transaction>("transactions", H_contract);
|
let t = await this.q().get<Transaction>(Stores.transactions, H_contract);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
@ -661,7 +673,7 @@ export class Wallet {
|
|||||||
let n = await this.depleteReserve(reserve, exchange);
|
let n = await this.depleteReserve(reserve, exchange);
|
||||||
|
|
||||||
if (n != 0) {
|
if (n != 0) {
|
||||||
let depleted = {
|
let depleted: HistoryRecord = {
|
||||||
type: "depleted-reserve",
|
type: "depleted-reserve",
|
||||||
subjectId: `reserve-progress-${reserveRecord.reserve_pub}`,
|
subjectId: `reserve-progress-${reserveRecord.reserve_pub}`,
|
||||||
timestamp: (new Date).getTime(),
|
timestamp: (new Date).getTime(),
|
||||||
@ -670,9 +682,10 @@ export class Wallet {
|
|||||||
reservePub: reserveRecord.reserve_pub,
|
reservePub: reserveRecord.reserve_pub,
|
||||||
requestedAmount: reserveRecord.requested_amount,
|
requestedAmount: reserveRecord.requested_amount,
|
||||||
currentAmount: reserveRecord.current_amount,
|
currentAmount: reserveRecord.current_amount,
|
||||||
}
|
},
|
||||||
|
level: HistoryLevel.User
|
||||||
};
|
};
|
||||||
await this.q().put("history", depleted).finish();
|
await this.q().put(Stores.history, depleted).finish();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// random, exponential backoff truncated at 3 minutes
|
// random, exponential backoff truncated at 3 minutes
|
||||||
@ -736,8 +749,8 @@ export class Wallet {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.put("reserves", reserveRecord)
|
.put(Stores.reserves, reserveRecord)
|
||||||
.put("history", historyEntry)
|
.put(Stores.history, historyEntry)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
let r: CreateReserveResponse = {
|
let r: CreateReserveResponse = {
|
||||||
@ -760,14 +773,14 @@ export class Wallet {
|
|||||||
async confirmReserve(req: ConfirmReserveRequest): Promise<void> {
|
async confirmReserve(req: ConfirmReserveRequest): Promise<void> {
|
||||||
const now = (new Date).getTime();
|
const now = (new Date).getTime();
|
||||||
let reserve: ReserveRecord|undefined = await (
|
let reserve: ReserveRecord|undefined = await (
|
||||||
this.q().get<ReserveRecord>("reserves",
|
this.q().get<ReserveRecord>(Stores.reserves,
|
||||||
req.reservePub));
|
req.reservePub));
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
console.error("Unable to confirm reserve, not found in DB");
|
console.error("Unable to confirm reserve, not found in DB");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("reserve confirmed");
|
console.log("reserve confirmed");
|
||||||
const historyEntry = {
|
const historyEntry: HistoryRecord = {
|
||||||
type: "confirm-reserve",
|
type: "confirm-reserve",
|
||||||
timestamp: now,
|
timestamp: now,
|
||||||
subjectId: `reserve-progress-${reserve.reserve_pub}`,
|
subjectId: `reserve-progress-${reserve.reserve_pub}`,
|
||||||
@ -775,12 +788,13 @@ export class Wallet {
|
|||||||
exchangeBaseUrl: reserve.exchange_base_url,
|
exchangeBaseUrl: reserve.exchange_base_url,
|
||||||
reservePub: req.reservePub,
|
reservePub: req.reservePub,
|
||||||
requestedAmount: reserve.requested_amount,
|
requestedAmount: reserve.requested_amount,
|
||||||
}
|
},
|
||||||
|
level: HistoryLevel.User,
|
||||||
};
|
};
|
||||||
reserve.confirmed = true;
|
reserve.confirmed = true;
|
||||||
await this.q()
|
await this.q()
|
||||||
.put("reserves", reserve)
|
.put(Stores.reserves, reserve)
|
||||||
.put("history", historyEntry)
|
.put(Stores.history, historyEntry)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
this.processReserve(reserve);
|
this.processReserve(reserve);
|
||||||
@ -788,7 +802,8 @@ export class Wallet {
|
|||||||
|
|
||||||
|
|
||||||
private async withdrawExecute(pc: PreCoin): Promise<Coin> {
|
private async withdrawExecute(pc: PreCoin): Promise<Coin> {
|
||||||
let reserve = await this.q().get<ReserveRecord>("reserves", pc.reservePub);
|
let reserve = await this.q().get<ReserveRecord>(Stores.reserves,
|
||||||
|
pc.reservePub);
|
||||||
|
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
throw Error("db inconsistent");
|
throw Error("db inconsistent");
|
||||||
@ -837,8 +852,8 @@ export class Wallet {
|
|||||||
};
|
};
|
||||||
await this.q()
|
await this.q()
|
||||||
.delete("precoins", coin.coinPub)
|
.delete("precoins", coin.coinPub)
|
||||||
.add("coins", coin)
|
.add(Stores.coins, coin)
|
||||||
.add("history", historyEntry)
|
.add(Stores.history, historyEntry)
|
||||||
.finish();
|
.finish();
|
||||||
this.notifier.notify();
|
this.notifier.notify();
|
||||||
}
|
}
|
||||||
@ -853,7 +868,7 @@ export class Wallet {
|
|||||||
let preCoin = await this.cryptoApi
|
let preCoin = await this.cryptoApi
|
||||||
.createPreCoin(denom, reserve);
|
.createPreCoin(denom, reserve);
|
||||||
await this.q()
|
await this.q()
|
||||||
.put("precoins", preCoin)
|
.put(Stores.precoins, preCoin)
|
||||||
.finish();
|
.finish();
|
||||||
await this.processPreCoin(preCoin);
|
await this.processPreCoin(preCoin);
|
||||||
}
|
}
|
||||||
@ -881,7 +896,7 @@ export class Wallet {
|
|||||||
private async updateReserve(reservePub: string,
|
private async updateReserve(reservePub: string,
|
||||||
exchange: IExchangeInfo): Promise<ReserveRecord> {
|
exchange: IExchangeInfo): Promise<ReserveRecord> {
|
||||||
let reserve = await this.q()
|
let reserve = await this.q()
|
||||||
.get<ReserveRecord>("reserves", reservePub);
|
.get<ReserveRecord>(Stores.reserves, reservePub);
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
throw Error("reserve not in db");
|
throw Error("reserve not in db");
|
||||||
}
|
}
|
||||||
@ -910,7 +925,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
await this.q()
|
await this.q()
|
||||||
.put("reserves", reserve)
|
.put(Stores.reserves, reserve)
|
||||||
.finish();
|
.finish();
|
||||||
return reserve;
|
return reserve;
|
||||||
}
|
}
|
||||||
@ -982,7 +997,7 @@ export class Wallet {
|
|||||||
private async suspendCoins(exchangeInfo: IExchangeInfo): Promise<void> {
|
private async suspendCoins(exchangeInfo: IExchangeInfo): Promise<void> {
|
||||||
let suspendedCoins = await (
|
let suspendedCoins = await (
|
||||||
this.q()
|
this.q()
|
||||||
.iter("coins",
|
.iter(Stores.coins,
|
||||||
{indexName: "exchangeBaseUrl", only: exchangeInfo.baseUrl})
|
{indexName: "exchangeBaseUrl", only: exchangeInfo.baseUrl})
|
||||||
.reduce((coin: Coin, suspendedCoins: Coin[]) => {
|
.reduce((coin: Coin, suspendedCoins: Coin[]) => {
|
||||||
if (!exchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) {
|
if (!exchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) {
|
||||||
@ -995,7 +1010,7 @@ export class Wallet {
|
|||||||
suspendedCoins.map((c) => {
|
suspendedCoins.map((c) => {
|
||||||
console.log("suspending coin", c);
|
console.log("suspending coin", c);
|
||||||
c.suspended = true;
|
c.suspended = true;
|
||||||
q.put("coins", c);
|
q.put(Stores.coins, c);
|
||||||
});
|
});
|
||||||
await q.finish();
|
await q.finish();
|
||||||
}
|
}
|
||||||
@ -1008,7 +1023,7 @@ export class Wallet {
|
|||||||
throw Error("invalid update time");
|
throw Error("invalid update time");
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = await this.q().get<IExchangeInfo>("exchanges", baseUrl);
|
let r = await this.q().get<IExchangeInfo>(Stores.exchanges, baseUrl);
|
||||||
|
|
||||||
let exchangeInfo: IExchangeInfo;
|
let exchangeInfo: IExchangeInfo;
|
||||||
|
|
||||||
@ -1035,7 +1050,7 @@ export class Wallet {
|
|||||||
await this.suspendCoins(updatedExchangeInfo);
|
await this.suspendCoins(updatedExchangeInfo);
|
||||||
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.put("exchanges", updatedExchangeInfo)
|
.put(Stores.exchanges, updatedExchangeInfo)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
return updatedExchangeInfo;
|
return updatedExchangeInfo;
|
||||||
@ -1120,7 +1135,7 @@ export class Wallet {
|
|||||||
|
|
||||||
let byCurrency = await (
|
let byCurrency = await (
|
||||||
this.q()
|
this.q()
|
||||||
.iter("coins")
|
.iter(Stores.coins)
|
||||||
.reduce(collectBalances, {}));
|
.reduce(collectBalances, {}));
|
||||||
|
|
||||||
return {balances: byCurrency};
|
return {balances: byCurrency};
|
||||||
@ -1131,13 +1146,13 @@ export class Wallet {
|
|||||||
|
|
||||||
// FIXME: this is not running in a transaction.
|
// FIXME: this is not running in a transaction.
|
||||||
|
|
||||||
let coin = await this.q().get<Coin>("coins", oldCoinPub);
|
let coin = await this.q().get<Coin>(Stores.coins, oldCoinPub);
|
||||||
|
|
||||||
if (!coin) {
|
if (!coin) {
|
||||||
throw Error("coin not found");
|
throw Error("coin not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
let exchange = await this.q().get<IExchangeInfo>("exchanges",
|
let exchange = await this.q().get<IExchangeInfo>(Stores.exchanges,
|
||||||
coin.exchangeBaseUrl);
|
coin.exchangeBaseUrl);
|
||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
throw Error("db inconsistent");
|
throw Error("db inconsistent");
|
||||||
@ -1177,8 +1192,8 @@ export class Wallet {
|
|||||||
|
|
||||||
// FIXME: we should check whether the amount still matches!
|
// FIXME: we should check whether the amount still matches!
|
||||||
await this.q()
|
await this.q()
|
||||||
.put("refresh", refreshSession)
|
.put(Stores.refresh, refreshSession)
|
||||||
.put("coins", coin)
|
.put(Stores.coins, coin)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
return refreshSession;
|
return refreshSession;
|
||||||
@ -1187,12 +1202,12 @@ export class Wallet {
|
|||||||
|
|
||||||
async refresh(oldCoinPub: string): Promise<void> {
|
async refresh(oldCoinPub: string): Promise<void> {
|
||||||
let refreshSession: RefreshSession|undefined;
|
let refreshSession: RefreshSession|undefined;
|
||||||
let oldSession = await this.q().get<RefreshSession>("refresh", oldCoinPub);
|
let oldSession = await this.q().get(Stores.refresh, oldCoinPub);
|
||||||
if (oldSession) {
|
if (oldSession) {
|
||||||
refreshSession = oldSession;
|
refreshSession = oldSession;
|
||||||
} else {
|
} else {
|
||||||
refreshSession = await this.q().get<RefreshSession>("refresh",
|
refreshSession = await this.q().get(Stores.refresh,
|
||||||
oldCoinPub);
|
oldCoinPub);
|
||||||
}
|
}
|
||||||
if (!refreshSession) {
|
if (!refreshSession) {
|
||||||
// refreshing not necessary
|
// refreshing not necessary
|
||||||
@ -1208,7 +1223,7 @@ export class Wallet {
|
|||||||
if (typeof refreshSession.norevealIndex !== "number") {
|
if (typeof refreshSession.norevealIndex !== "number") {
|
||||||
let coinPub = refreshSession.meltCoinPub;
|
let coinPub = refreshSession.meltCoinPub;
|
||||||
await this.refreshMelt(refreshSession);
|
await this.refreshMelt(refreshSession);
|
||||||
let r = await this.q().get<RefreshSession>("refresh", coinPub);
|
let r = await this.q().get<RefreshSession>(Stores.refresh, coinPub);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
throw Error("refresh session does not exist anymore");
|
throw Error("refresh session does not exist anymore");
|
||||||
}
|
}
|
||||||
@ -1225,7 +1240,7 @@ export class Wallet {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let coin = await this.q().get<Coin>("coins", refreshSession.meltCoinPub);
|
let coin = await this.q().get<Coin>(Stores.coins, refreshSession.meltCoinPub);
|
||||||
if (!coin) {
|
if (!coin) {
|
||||||
console.error("can't melt coin, it does not exist");
|
console.error("can't melt coin, it does not exist");
|
||||||
return;
|
return;
|
||||||
@ -1271,7 +1286,7 @@ export class Wallet {
|
|||||||
|
|
||||||
refreshSession.norevealIndex = norevealIndex;
|
refreshSession.norevealIndex = norevealIndex;
|
||||||
|
|
||||||
await this.q().put("refresh", refreshSession).finish();
|
await this.q().put(Stores.refresh, refreshSession).finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1307,7 +1322,7 @@ export class Wallet {
|
|||||||
console.log("/refresh/reveal did not contain ev_sigs");
|
console.log("/refresh/reveal did not contain ev_sigs");
|
||||||
}
|
}
|
||||||
|
|
||||||
let exchange = await this.q().get<IExchangeInfo>("exchanges",
|
let exchange = await this.q().get<IExchangeInfo>(Stores.exchanges,
|
||||||
refreshSession.exchangeBaseUrl);
|
refreshSession.exchangeBaseUrl);
|
||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
console.error(`exchange ${refreshSession.exchangeBaseUrl} not found`);
|
console.error(`exchange ${refreshSession.exchangeBaseUrl} not found`);
|
||||||
@ -1343,8 +1358,8 @@ export class Wallet {
|
|||||||
refreshSession.finished = true;
|
refreshSession.finished = true;
|
||||||
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.putAll("coins", coins)
|
.putAll(Stores.coins, coins)
|
||||||
.put("refresh", refreshSession)
|
.put(Stores.refresh, refreshSession)
|
||||||
.finish();
|
.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1360,7 +1375,7 @@ export class Wallet {
|
|||||||
|
|
||||||
let history = await (
|
let history = await (
|
||||||
this.q()
|
this.q()
|
||||||
.iter("history", {indexName: "timestamp"})
|
.iter(Stores.history, {indexName: "timestamp"})
|
||||||
.reduce(collect, []));
|
.reduce(collect, []));
|
||||||
|
|
||||||
return {history};
|
return {history};
|
||||||
@ -1368,28 +1383,28 @@ export class Wallet {
|
|||||||
|
|
||||||
async getExchanges(): Promise<IExchangeInfo[]> {
|
async getExchanges(): Promise<IExchangeInfo[]> {
|
||||||
return this.q()
|
return this.q()
|
||||||
.iter<IExchangeInfo>("exchanges")
|
.iter<IExchangeInfo>(Stores.exchanges)
|
||||||
.flatMap((e) => [e])
|
.flatMap((e) => [e])
|
||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> {
|
async getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> {
|
||||||
return this.q()
|
return this.q()
|
||||||
.iter<ReserveRecord>("reserves")
|
.iter<ReserveRecord>(Stores.reserves)
|
||||||
.filter((r: ReserveRecord) => r.exchange_base_url === exchangeBaseUrl)
|
.filter((r: ReserveRecord) => r.exchange_base_url === exchangeBaseUrl)
|
||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCoins(exchangeBaseUrl: string): Promise<Coin[]> {
|
async getCoins(exchangeBaseUrl: string): Promise<Coin[]> {
|
||||||
return this.q()
|
return this.q()
|
||||||
.iter<Coin>("coins")
|
.iter<Coin>(Stores.coins)
|
||||||
.filter((c: Coin) => c.exchangeBaseUrl === exchangeBaseUrl)
|
.filter((c: Coin) => c.exchangeBaseUrl === exchangeBaseUrl)
|
||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPreCoins(exchangeBaseUrl: string): Promise<PreCoin[]> {
|
async getPreCoins(exchangeBaseUrl: string): Promise<PreCoin[]> {
|
||||||
return this.q()
|
return this.q()
|
||||||
.iter<PreCoin>("precoins")
|
.iter<PreCoin>(Stores.precoins)
|
||||||
.filter((c: PreCoin) => c.exchangeBaseUrl === exchangeBaseUrl)
|
.filter((c: PreCoin) => c.exchangeBaseUrl === exchangeBaseUrl)
|
||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
@ -1431,19 +1446,19 @@ export class Wallet {
|
|||||||
|
|
||||||
async paymentSucceeded(contractHash: string): Promise<any> {
|
async paymentSucceeded(contractHash: string): Promise<any> {
|
||||||
const doPaymentSucceeded = async() => {
|
const doPaymentSucceeded = async() => {
|
||||||
let t = await this.q().get<Transaction>("transactions", contractHash);
|
let t = await this.q().get<Transaction>(Stores.transactions, contractHash);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
console.error("contract not found");
|
console.error("contract not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let pc of t.payReq.coins) {
|
for (let pc of t.payReq.coins) {
|
||||||
let c = await this.q().get<Coin>("coins", pc.coin_pub);
|
let c = await this.q().get<Coin>(Stores.coins, pc.coin_pub);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
console.error("coin not found");
|
console.error("coin not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
c.transactionPending = false;
|
c.transactionPending = false;
|
||||||
await this.q().put("coins", c).finish();
|
await this.q().put(Stores.coins, c).finish();
|
||||||
}
|
}
|
||||||
for (let c of t.payReq.coins) {
|
for (let c of t.payReq.coins) {
|
||||||
this.refresh(c.coin_pub);
|
this.refresh(c.coin_pub);
|
||||||
@ -1452,4 +1467,4 @@ export class Wallet {
|
|||||||
doPaymentSucceeded();
|
doPaymentSucceeded();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user