refactor DB access
This commit is contained in:
parent
24650b1781
commit
f3329ecf06
117
src/db.ts
117
src/db.ts
@ -1,118 +1,27 @@
|
|||||||
import { Stores, WALLET_DB_VERSION } from "./types/dbTypes";
|
import { Stores, WALLET_DB_VERSION } from "./types/dbTypes";
|
||||||
import { Store, Index } from "./util/query";
|
import { openDatabase, Database } from "./util/query";
|
||||||
|
|
||||||
const DB_NAME = "taler";
|
const TALER_DB_NAME = "taler";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a promise that resolves
|
* Return a promise that resolves
|
||||||
* to the taler wallet db.
|
* to the taler wallet db.
|
||||||
*/
|
*/
|
||||||
export function openDatabase(
|
export function openTalerDatabase(
|
||||||
idbFactory: IDBFactory,
|
idbFactory: IDBFactory,
|
||||||
onVersionChange: () => void,
|
onVersionChange: () => void,
|
||||||
onUpgradeUnsupported: (oldVersion: number, newVersion: number) => void,
|
onUpgradeUnsupported: (oldVersion: number, newVersion: number) => void,
|
||||||
): Promise<IDBDatabase> {
|
): Promise<IDBDatabase> {
|
||||||
return new Promise<IDBDatabase>((resolve, reject) => {
|
return openDatabase(
|
||||||
const req = idbFactory.open(DB_NAME, WALLET_DB_VERSION);
|
idbFactory,
|
||||||
req.onerror = e => {
|
TALER_DB_NAME,
|
||||||
console.log("taler database error", e);
|
WALLET_DB_VERSION,
|
||||||
reject(new Error("database error"));
|
Stores,
|
||||||
};
|
onVersionChange,
|
||||||
req.onsuccess = e => {
|
onUpgradeUnsupported,
|
||||||
req.result.onversionchange = (evt: IDBVersionChangeEvent) => {
|
);
|
||||||
console.log(
|
|
||||||
`handling live db version change from ${evt.oldVersion} to ${evt.newVersion}`,
|
|
||||||
);
|
|
||||||
req.result.close();
|
|
||||||
onVersionChange();
|
|
||||||
};
|
|
||||||
resolve(req.result);
|
|
||||||
};
|
|
||||||
req.onupgradeneeded = e => {
|
|
||||||
const db = req.result;
|
|
||||||
console.log(
|
|
||||||
`DB: upgrade needed: oldVersion=${e.oldVersion}, newVersion=${e.newVersion}`,
|
|
||||||
);
|
|
||||||
switch (e.oldVersion) {
|
|
||||||
case 0: // DB does not exist yet
|
|
||||||
for (const n in Stores) {
|
|
||||||
if ((Stores as any)[n] instanceof Store) {
|
|
||||||
const si: Store<any> = (Stores as any)[n];
|
|
||||||
const s = db.createObjectStore(si.name, si.storeParams);
|
|
||||||
for (const indexName in si as any) {
|
|
||||||
if ((si as any)[indexName] instanceof Index) {
|
|
||||||
const ii: Index<any, any> = (si as any)[indexName];
|
|
||||||
s.createIndex(ii.indexName, ii.keyPath, ii.options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (e.oldVersion !== WALLET_DB_VERSION) {
|
|
||||||
onUpgradeUnsupported(e.oldVersion, WALLET_DB_VERSION);
|
|
||||||
throw Error("incompatible DB");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function exportDatabase(db: IDBDatabase): Promise<any> {
|
export function deleteTalerDatabase(idbFactory: IDBFactory) {
|
||||||
const dump = {
|
Database.deleteDatabase(idbFactory, TALER_DB_NAME);
|
||||||
name: db.name,
|
|
||||||
stores: {} as { [s: string]: any },
|
|
||||||
version: db.version,
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const tx = db.transaction(Array.from(db.objectStoreNames));
|
|
||||||
tx.addEventListener("complete", () => {
|
|
||||||
resolve(dump);
|
|
||||||
});
|
|
||||||
// tslint:disable-next-line:prefer-for-of
|
|
||||||
for (let i = 0; i < db.objectStoreNames.length; i++) {
|
|
||||||
const name = db.objectStoreNames[i];
|
|
||||||
const storeDump = {} as { [s: string]: any };
|
|
||||||
dump.stores[name] = storeDump;
|
|
||||||
tx.objectStore(name)
|
|
||||||
.openCursor()
|
|
||||||
.addEventListener("success", (e: Event) => {
|
|
||||||
const cursor = (e.target as any).result;
|
|
||||||
if (cursor) {
|
|
||||||
storeDump[cursor.key] = cursor.value;
|
|
||||||
cursor.continue();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function importDatabase(db: IDBDatabase, dump: any): Promise<void> {
|
|
||||||
console.log("importing db", dump);
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
|
|
||||||
if (dump.stores) {
|
|
||||||
for (const storeName in dump.stores) {
|
|
||||||
const objects = [];
|
|
||||||
const dumpStore = dump.stores[storeName];
|
|
||||||
for (const key in dumpStore) {
|
|
||||||
objects.push(dumpStore[key]);
|
|
||||||
}
|
|
||||||
console.log(`importing ${objects.length} records into ${storeName}`);
|
|
||||||
const store = tx.objectStore(storeName);
|
|
||||||
for (const obj of objects) {
|
|
||||||
store.put(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tx.addEventListener("complete", () => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteDatabase(idbFactory: IDBFactory) {
|
|
||||||
idbFactory.deleteDatabase(DB_NAME);
|
|
||||||
}
|
}
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
import { Wallet } from "../wallet";
|
import { Wallet } from "../wallet";
|
||||||
import { MemoryBackend, BridgeIDBFactory, shimIndexedDB } from "idb-bridge";
|
import { MemoryBackend, BridgeIDBFactory, shimIndexedDB } from "idb-bridge";
|
||||||
import { openDatabase } from "../db";
|
import { openTalerDatabase } from "../db";
|
||||||
import Axios, { AxiosPromise, AxiosResponse } from "axios";
|
import Axios, { AxiosPromise, AxiosResponse } from "axios";
|
||||||
import {
|
import {
|
||||||
HttpRequestLibrary,
|
HttpRequestLibrary,
|
||||||
@ -39,6 +39,7 @@ import { NodeThreadCryptoWorkerFactory } from "../crypto/workers/nodeThreadWorke
|
|||||||
import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorker";
|
import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorker";
|
||||||
import { RequestThrottler } from "../util/RequestThrottler";
|
import { RequestThrottler } from "../util/RequestThrottler";
|
||||||
import { WalletNotification, NotificationType } from "../types/notifications";
|
import { WalletNotification, NotificationType } from "../types/notifications";
|
||||||
|
import { Database } from "../util/query";
|
||||||
|
|
||||||
const logger = new Logger("helpers.ts");
|
const logger = new Logger("helpers.ts");
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ export async function getDefaultNodeWallet(
|
|||||||
|
|
||||||
shimIndexedDB(myBridgeIdbFactory);
|
shimIndexedDB(myBridgeIdbFactory);
|
||||||
|
|
||||||
const myDb = await openDatabase(
|
const myDb = await openTalerDatabase(
|
||||||
myIdbFactory,
|
myIdbFactory,
|
||||||
myVersionChange,
|
myVersionChange,
|
||||||
myUnsupportedUpgrade,
|
myUnsupportedUpgrade,
|
||||||
@ -202,7 +203,9 @@ export async function getDefaultNodeWallet(
|
|||||||
|
|
||||||
const worker = new NodeThreadCryptoWorkerFactory();
|
const worker = new NodeThreadCryptoWorkerFactory();
|
||||||
|
|
||||||
const w = new Wallet(myDb, myHttpLib, worker);
|
const dbWrap = new Database(myDb);
|
||||||
|
|
||||||
|
const w = new Wallet(dbWrap, myHttpLib, worker);
|
||||||
if (args.notifyHandler) {
|
if (args.notifyHandler) {
|
||||||
w.addNotificationListener(args.notifyHandler);
|
w.addNotificationListener(args.notifyHandler);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { WalletBalance, WalletBalanceEntry } from "../types/walletTypes";
|
import { WalletBalance, WalletBalanceEntry } from "../types/walletTypes";
|
||||||
import { runWithReadTransaction } from "../util/query";
|
import { Database } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { Stores, TipRecord, CoinStatus } from "../types/dbTypes";
|
import { Stores, TipRecord, CoinStatus } from "../types/dbTypes";
|
||||||
import * as Amounts from "../util/amounts";
|
import * as Amounts from "../util/amounts";
|
||||||
@ -73,8 +73,7 @@ export async function getBalances(
|
|||||||
byExchange: {},
|
byExchange: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
await runWithReadTransaction(
|
await ws.db.runWithReadTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.coins, Stores.refresh, Stores.reserves, Stores.purchases, Stores.withdrawalSession],
|
[Stores.coins, Stores.refresh, Stores.reserves, Stores.purchases, Stores.withdrawalSession],
|
||||||
async tx => {
|
async tx => {
|
||||||
await tx.iter(Stores.coins).forEach(c => {
|
await tx.iter(Stores.coins).forEach(c => {
|
||||||
|
@ -32,10 +32,7 @@ import {
|
|||||||
extractTalerStampOrThrow,
|
extractTalerStampOrThrow,
|
||||||
} from "../util/helpers";
|
} from "../util/helpers";
|
||||||
import {
|
import {
|
||||||
oneShotGet,
|
Database
|
||||||
oneShotPut,
|
|
||||||
runWithWriteTransaction,
|
|
||||||
oneShotMutate,
|
|
||||||
} from "../util/query";
|
} from "../util/query";
|
||||||
import * as Amounts from "../util/amounts";
|
import * as Amounts from "../util/amounts";
|
||||||
import { parsePaytoUri } from "../util/payto";
|
import { parsePaytoUri } from "../util/payto";
|
||||||
@ -81,7 +78,7 @@ async function setExchangeError(
|
|||||||
exchange.lastError = err;
|
exchange.lastError = err;
|
||||||
return exchange;
|
return exchange;
|
||||||
};
|
};
|
||||||
await oneShotMutate(ws.db, Stores.exchanges, baseUrl, mut);
|
await ws.db.mutate( Stores.exchanges, baseUrl, mut);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,8 +91,7 @@ async function updateExchangeWithKeys(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const existingExchangeRecord = await oneShotGet(
|
const existingExchangeRecord = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.exchanges,
|
Stores.exchanges,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
);
|
);
|
||||||
@ -180,8 +176,7 @@ async function updateExchangeWithKeys(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.exchanges, Stores.denominations],
|
[Stores.exchanges, Stores.denominations],
|
||||||
async tx => {
|
async tx => {
|
||||||
const r = await tx.get(Stores.exchanges, baseUrl);
|
const r = await tx.get(Stores.exchanges, baseUrl);
|
||||||
@ -222,7 +217,7 @@ async function updateExchangeWithTermsOfService(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
) {
|
) {
|
||||||
const exchange = await oneShotGet(ws.db, Stores.exchanges, exchangeBaseUrl);
|
const exchange = await ws.db.get(Stores.exchanges, exchangeBaseUrl);
|
||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -243,7 +238,7 @@ async function updateExchangeWithTermsOfService(
|
|||||||
const tosText = await resp.text();
|
const tosText = await resp.text();
|
||||||
const tosEtag = resp.headers.get("etag") || undefined;
|
const tosEtag = resp.headers.get("etag") || undefined;
|
||||||
|
|
||||||
await runWithWriteTransaction(ws.db, [Stores.exchanges], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.exchanges], async tx => {
|
||||||
const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
|
const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return;
|
return;
|
||||||
@ -263,7 +258,7 @@ export async function acceptExchangeTermsOfService(
|
|||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
etag: string | undefined,
|
etag: string | undefined,
|
||||||
) {
|
) {
|
||||||
await runWithWriteTransaction(ws.db, [Stores.exchanges], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.exchanges], async tx => {
|
||||||
const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
|
const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return;
|
return;
|
||||||
@ -283,7 +278,7 @@ async function updateExchangeWithWireInfo(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
) {
|
) {
|
||||||
const exchange = await oneShotGet(ws.db, Stores.exchanges, exchangeBaseUrl);
|
const exchange = await ws.db.get(Stores.exchanges, exchangeBaseUrl);
|
||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -349,7 +344,7 @@ async function updateExchangeWithWireInfo(
|
|||||||
feesForType[wireMethod] = feeList;
|
feesForType[wireMethod] = feeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
await runWithWriteTransaction(ws.db, [Stores.exchanges], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.exchanges], async tx => {
|
||||||
const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
|
const r = await tx.get(Stores.exchanges, exchangeBaseUrl);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return;
|
return;
|
||||||
@ -392,7 +387,7 @@ async function updateExchangeFromUrlImpl(
|
|||||||
const now = getTimestampNow();
|
const now = getTimestampNow();
|
||||||
baseUrl = canonicalizeBaseUrl(baseUrl);
|
baseUrl = canonicalizeBaseUrl(baseUrl);
|
||||||
|
|
||||||
const r = await oneShotGet(ws.db, Stores.exchanges, baseUrl);
|
const r = await ws.db.get(Stores.exchanges, baseUrl);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
const newExchangeRecord: ExchangeRecord = {
|
const newExchangeRecord: ExchangeRecord = {
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
@ -407,9 +402,9 @@ async function updateExchangeFromUrlImpl(
|
|||||||
termsOfServiceLastEtag: undefined,
|
termsOfServiceLastEtag: undefined,
|
||||||
termsOfServiceText: undefined,
|
termsOfServiceText: undefined,
|
||||||
};
|
};
|
||||||
await oneShotPut(ws.db, Stores.exchanges, newExchangeRecord);
|
await ws.db.put(Stores.exchanges, newExchangeRecord);
|
||||||
} else {
|
} else {
|
||||||
await runWithWriteTransaction(ws.db, [Stores.exchanges], async t => {
|
await ws.db.runWithWriteTransaction([Stores.exchanges], async t => {
|
||||||
const rec = await t.get(Stores.exchanges, baseUrl);
|
const rec = await t.get(Stores.exchanges, baseUrl);
|
||||||
if (!rec) {
|
if (!rec) {
|
||||||
return;
|
return;
|
||||||
@ -431,7 +426,7 @@ async function updateExchangeFromUrlImpl(
|
|||||||
await updateExchangeWithWireInfo(ws, baseUrl);
|
await updateExchangeWithWireInfo(ws, baseUrl);
|
||||||
await updateExchangeWithTermsOfService(ws, baseUrl);
|
await updateExchangeWithTermsOfService(ws, baseUrl);
|
||||||
|
|
||||||
const updatedExchange = await oneShotGet(ws.db, Stores.exchanges, baseUrl);
|
const updatedExchange = await ws.db.get(Stores.exchanges, baseUrl);
|
||||||
|
|
||||||
if (!updatedExchange) {
|
if (!updatedExchange) {
|
||||||
// This should practically never happen
|
// This should practically never happen
|
||||||
@ -453,8 +448,7 @@ export async function getExchangeTrust(
|
|||||||
if (!exchangeDetails) {
|
if (!exchangeDetails) {
|
||||||
throw Error(`exchange ${exchangeInfo.baseUrl} details not available`);
|
throw Error(`exchange ${exchangeInfo.baseUrl} details not available`);
|
||||||
}
|
}
|
||||||
const currencyRecord = await oneShotGet(
|
const currencyRecord = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.currencies,
|
Stores.currencies,
|
||||||
exchangeDetails.currency,
|
exchangeDetails.currency,
|
||||||
);
|
);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { oneShotIter, runWithReadTransaction } from "../util/query";
|
import { Database } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { Stores, TipRecord } from "../types/dbTypes";
|
import { Stores, TipRecord } from "../types/dbTypes";
|
||||||
import * as Amounts from "../util/amounts";
|
import * as Amounts from "../util/amounts";
|
||||||
@ -38,8 +38,7 @@ export async function getHistory(
|
|||||||
// This works as timestamps are guaranteed to be monotonically
|
// This works as timestamps are guaranteed to be monotonically
|
||||||
// increasing even
|
// increasing even
|
||||||
|
|
||||||
await runWithReadTransaction(
|
await ws.db.runWithReadTransaction(
|
||||||
ws.db,
|
|
||||||
[
|
[
|
||||||
Stores.currencies,
|
Stores.currencies,
|
||||||
Stores.coins,
|
Stores.coins,
|
||||||
|
@ -36,13 +36,7 @@ import {
|
|||||||
OperationError,
|
OperationError,
|
||||||
} from "../types/walletTypes";
|
} from "../types/walletTypes";
|
||||||
import {
|
import {
|
||||||
oneShotIter,
|
Database
|
||||||
oneShotIterIndex,
|
|
||||||
oneShotGet,
|
|
||||||
runWithWriteTransaction,
|
|
||||||
oneShotPut,
|
|
||||||
oneShotGetIndexed,
|
|
||||||
oneShotMutate,
|
|
||||||
} from "../util/query";
|
} from "../util/query";
|
||||||
import {
|
import {
|
||||||
Stores,
|
Stores,
|
||||||
@ -202,7 +196,7 @@ async function getCoinsForPayment(
|
|||||||
|
|
||||||
let remainingAmount = paymentAmount;
|
let remainingAmount = paymentAmount;
|
||||||
|
|
||||||
const exchanges = await oneShotIter(ws.db, Stores.exchanges).toArray();
|
const exchanges = await ws.db.iter(Stores.exchanges).toArray();
|
||||||
|
|
||||||
for (const exchange of exchanges) {
|
for (const exchange of exchanges) {
|
||||||
let isOkay: boolean = false;
|
let isOkay: boolean = false;
|
||||||
@ -242,14 +236,12 @@ async function getCoinsForPayment(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const coins = await oneShotIterIndex(
|
const coins = await ws.db.iterIndex(
|
||||||
ws.db,
|
|
||||||
Stores.coins.exchangeBaseUrlIndex,
|
Stores.coins.exchangeBaseUrlIndex,
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
).toArray();
|
).toArray();
|
||||||
|
|
||||||
const denoms = await oneShotIterIndex(
|
const denoms = await ws.db.iterIndex(
|
||||||
ws.db,
|
|
||||||
Stores.denominations.exchangeBaseUrlIndex,
|
Stores.denominations.exchangeBaseUrlIndex,
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
).toArray();
|
).toArray();
|
||||||
@ -260,7 +252,7 @@ async function getCoinsForPayment(
|
|||||||
|
|
||||||
// Denomination of the first coin, we assume that all other
|
// Denomination of the first coin, we assume that all other
|
||||||
// coins have the same currency
|
// coins have the same currency
|
||||||
const firstDenom = await oneShotGet(ws.db, Stores.denominations, [
|
const firstDenom = await ws.db.get(Stores.denominations, [
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
coins[0].denomPub,
|
coins[0].denomPub,
|
||||||
]);
|
]);
|
||||||
@ -270,7 +262,7 @@ async function getCoinsForPayment(
|
|||||||
const currency = firstDenom.value.currency;
|
const currency = firstDenom.value.currency;
|
||||||
const cds: CoinWithDenom[] = [];
|
const cds: CoinWithDenom[] = [];
|
||||||
for (const coin of coins) {
|
for (const coin of coins) {
|
||||||
const denom = await oneShotGet(ws.db, Stores.denominations, [
|
const denom = await ws.db.get(Stores.denominations, [
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
coin.denomPub,
|
coin.denomPub,
|
||||||
]);
|
]);
|
||||||
@ -377,8 +369,7 @@ async function recordConfirmPay(
|
|||||||
paymentSubmitPending: true,
|
paymentSubmitPending: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.coins, Stores.purchases, Stores.proposals],
|
[Stores.coins, Stores.purchases, Stores.proposals],
|
||||||
async tx => {
|
async tx => {
|
||||||
const p = await tx.get(Stores.proposals, proposal.proposalId);
|
const p = await tx.get(Stores.proposals, proposal.proposalId);
|
||||||
@ -417,7 +408,7 @@ export async function abortFailedPayment(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const purchase = await oneShotGet(ws.db, Stores.purchases, proposalId);
|
const purchase = await ws.db.get(Stores.purchases, proposalId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
throw Error("Purchase not found, unable to abort with refund");
|
throw Error("Purchase not found, unable to abort with refund");
|
||||||
}
|
}
|
||||||
@ -434,7 +425,7 @@ export async function abortFailedPayment(
|
|||||||
// From now on, we can't retry payment anymore,
|
// From now on, we can't retry payment anymore,
|
||||||
// so mark this in the DB in case the /pay abort
|
// so mark this in the DB in case the /pay abort
|
||||||
// does not complete on the first try.
|
// does not complete on the first try.
|
||||||
await oneShotPut(ws.db, Stores.purchases, purchase);
|
await ws.db.put(Stores.purchases, purchase);
|
||||||
|
|
||||||
let resp;
|
let resp;
|
||||||
|
|
||||||
@ -457,7 +448,7 @@ export async function abortFailedPayment(
|
|||||||
const refundResponse = MerchantRefundResponse.checked(await resp.json());
|
const refundResponse = MerchantRefundResponse.checked(await resp.json());
|
||||||
await acceptRefundResponse(ws, purchase.proposalId, refundResponse);
|
await acceptRefundResponse(ws, purchase.proposalId, refundResponse);
|
||||||
|
|
||||||
await runWithWriteTransaction(ws.db, [Stores.purchases], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.purchases], async tx => {
|
||||||
const p = await tx.get(Stores.purchases, proposalId);
|
const p = await tx.get(Stores.purchases, proposalId);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
return;
|
return;
|
||||||
@ -472,7 +463,7 @@ async function incrementProposalRetry(
|
|||||||
proposalId: string,
|
proposalId: string,
|
||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await runWithWriteTransaction(ws.db, [Stores.proposals], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.proposals], async tx => {
|
||||||
const pr = await tx.get(Stores.proposals, proposalId);
|
const pr = await tx.get(Stores.proposals, proposalId);
|
||||||
if (!pr) {
|
if (!pr) {
|
||||||
return;
|
return;
|
||||||
@ -494,7 +485,7 @@ async function incrementPurchasePayRetry(
|
|||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log("incrementing purchase pay retry with error", err);
|
console.log("incrementing purchase pay retry with error", err);
|
||||||
await runWithWriteTransaction(ws.db, [Stores.purchases], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.purchases], async tx => {
|
||||||
const pr = await tx.get(Stores.purchases, proposalId);
|
const pr = await tx.get(Stores.purchases, proposalId);
|
||||||
if (!pr) {
|
if (!pr) {
|
||||||
return;
|
return;
|
||||||
@ -516,7 +507,7 @@ async function incrementPurchaseQueryRefundRetry(
|
|||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log("incrementing purchase refund query retry with error", err);
|
console.log("incrementing purchase refund query retry with error", err);
|
||||||
await runWithWriteTransaction(ws.db, [Stores.purchases], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.purchases], async tx => {
|
||||||
const pr = await tx.get(Stores.purchases, proposalId);
|
const pr = await tx.get(Stores.purchases, proposalId);
|
||||||
if (!pr) {
|
if (!pr) {
|
||||||
return;
|
return;
|
||||||
@ -538,7 +529,7 @@ async function incrementPurchaseApplyRefundRetry(
|
|||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log("incrementing purchase refund apply retry with error", err);
|
console.log("incrementing purchase refund apply retry with error", err);
|
||||||
await runWithWriteTransaction(ws.db, [Stores.purchases], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.purchases], async tx => {
|
||||||
const pr = await tx.get(Stores.purchases, proposalId);
|
const pr = await tx.get(Stores.purchases, proposalId);
|
||||||
if (!pr) {
|
if (!pr) {
|
||||||
return;
|
return;
|
||||||
@ -571,7 +562,7 @@ async function resetDownloadProposalRetry(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
) {
|
) {
|
||||||
await oneShotMutate(ws.db, Stores.proposals, proposalId, x => {
|
await ws.db.mutate(Stores.proposals, proposalId, x => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
@ -587,7 +578,7 @@ async function processDownloadProposalImpl(
|
|||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetDownloadProposalRetry(ws, proposalId);
|
await resetDownloadProposalRetry(ws, proposalId);
|
||||||
}
|
}
|
||||||
const proposal = await oneShotGet(ws.db, Stores.proposals, proposalId);
|
const proposal = await ws.db.get(Stores.proposals, proposalId);
|
||||||
if (!proposal) {
|
if (!proposal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -621,8 +612,7 @@ async function processDownloadProposalImpl(
|
|||||||
|
|
||||||
const fulfillmentUrl = proposalResp.contract_terms.fulfillment_url;
|
const fulfillmentUrl = proposalResp.contract_terms.fulfillment_url;
|
||||||
|
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.proposals, Stores.purchases],
|
[Stores.proposals, Stores.purchases],
|
||||||
async tx => {
|
async tx => {
|
||||||
const p = await tx.get(Stores.proposals, proposalId);
|
const p = await tx.get(Stores.proposals, proposalId);
|
||||||
@ -677,8 +667,7 @@ async function startDownloadProposal(
|
|||||||
orderId: string,
|
orderId: string,
|
||||||
sessionId: string | undefined,
|
sessionId: string | undefined,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const oldProposal = await oneShotGetIndexed(
|
const oldProposal = await ws.db.getIndexed(
|
||||||
ws.db,
|
|
||||||
Stores.proposals.urlAndOrderIdIndex,
|
Stores.proposals.urlAndOrderIdIndex,
|
||||||
[merchantBaseUrl, orderId],
|
[merchantBaseUrl, orderId],
|
||||||
);
|
);
|
||||||
@ -705,7 +694,7 @@ async function startDownloadProposal(
|
|||||||
downloadSessionId: sessionId,
|
downloadSessionId: sessionId,
|
||||||
};
|
};
|
||||||
|
|
||||||
await runWithWriteTransaction(ws.db, [Stores.proposals], async (tx) => {
|
await ws.db.runWithWriteTransaction([Stores.proposals], async (tx) => {
|
||||||
const existingRecord = await tx.getIndexed(Stores.proposals.urlAndOrderIdIndex, [
|
const existingRecord = await tx.getIndexed(Stores.proposals.urlAndOrderIdIndex, [
|
||||||
merchantBaseUrl,
|
merchantBaseUrl,
|
||||||
orderId,
|
orderId,
|
||||||
@ -725,7 +714,7 @@ export async function submitPay(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
): Promise<ConfirmPayResult> {
|
): Promise<ConfirmPayResult> {
|
||||||
const purchase = await oneShotGet(ws.db, Stores.purchases, proposalId);
|
const purchase = await ws.db.get(Stores.purchases, proposalId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
throw Error("Purchase not found: " + proposalId);
|
throw Error("Purchase not found: " + proposalId);
|
||||||
}
|
}
|
||||||
@ -788,7 +777,7 @@ export async function submitPay(
|
|||||||
|
|
||||||
const modifiedCoins: CoinRecord[] = [];
|
const modifiedCoins: CoinRecord[] = [];
|
||||||
for (const pc of purchase.payReq.coins) {
|
for (const pc of purchase.payReq.coins) {
|
||||||
const c = await oneShotGet(ws.db, Stores.coins, pc.coin_pub);
|
const c = await ws.db.get(Stores.coins, pc.coin_pub);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
console.error("coin not found");
|
console.error("coin not found");
|
||||||
throw Error("coin used in payment not found");
|
throw Error("coin used in payment not found");
|
||||||
@ -797,8 +786,7 @@ export async function submitPay(
|
|||||||
modifiedCoins.push(c);
|
modifiedCoins.push(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.coins, Stores.purchases],
|
[Stores.coins, Stores.purchases],
|
||||||
async tx => {
|
async tx => {
|
||||||
for (let c of modifiedCoins) {
|
for (let c of modifiedCoins) {
|
||||||
@ -849,7 +837,7 @@ export async function preparePay(
|
|||||||
uriResult.sessionId,
|
uriResult.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
let proposal = await oneShotGet(ws.db, Stores.proposals, proposalId);
|
let proposal = await ws.db.get(Stores.proposals, proposalId);
|
||||||
if (!proposal) {
|
if (!proposal) {
|
||||||
throw Error(`could not get proposal ${proposalId}`);
|
throw Error(`could not get proposal ${proposalId}`);
|
||||||
}
|
}
|
||||||
@ -859,7 +847,7 @@ export async function preparePay(
|
|||||||
throw Error("invalid proposal state");
|
throw Error("invalid proposal state");
|
||||||
}
|
}
|
||||||
console.log("using existing purchase for same product");
|
console.log("using existing purchase for same product");
|
||||||
proposal = await oneShotGet(ws.db, Stores.proposals, existingProposalId);
|
proposal = await ws.db.get(Stores.proposals, existingProposalId);
|
||||||
if (!proposal) {
|
if (!proposal) {
|
||||||
throw Error("existing proposal is in wrong state");
|
throw Error("existing proposal is in wrong state");
|
||||||
}
|
}
|
||||||
@ -878,7 +866,7 @@ export async function preparePay(
|
|||||||
proposalId = proposal.proposalId;
|
proposalId = proposal.proposalId;
|
||||||
|
|
||||||
// First check if we already payed for it.
|
// First check if we already payed for it.
|
||||||
const purchase = await oneShotGet(ws.db, Stores.purchases, proposalId);
|
const purchase = await ws.db.get(Stores.purchases, proposalId);
|
||||||
|
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
const paymentAmount = Amounts.parseOrThrow(contractTerms.amount);
|
const paymentAmount = Amounts.parseOrThrow(contractTerms.amount);
|
||||||
@ -966,7 +954,7 @@ async function getSpeculativePayData(
|
|||||||
const coinKeys = sp.payCoinInfo.updatedCoins.map(x => x.coinPub);
|
const coinKeys = sp.payCoinInfo.updatedCoins.map(x => x.coinPub);
|
||||||
const coins: CoinRecord[] = [];
|
const coins: CoinRecord[] = [];
|
||||||
for (let coinKey of coinKeys) {
|
for (let coinKey of coinKeys) {
|
||||||
const cc = await oneShotGet(ws.db, Stores.coins, coinKey);
|
const cc = await ws.db.get(Stores.coins, coinKey);
|
||||||
if (cc) {
|
if (cc) {
|
||||||
coins.push(cc);
|
coins.push(cc);
|
||||||
}
|
}
|
||||||
@ -997,7 +985,7 @@ export async function confirmPay(
|
|||||||
logger.trace(
|
logger.trace(
|
||||||
`executing confirmPay with proposalId ${proposalId} and sessionIdOverride ${sessionIdOverride}`,
|
`executing confirmPay with proposalId ${proposalId} and sessionIdOverride ${sessionIdOverride}`,
|
||||||
);
|
);
|
||||||
const proposal = await oneShotGet(ws.db, Stores.proposals, proposalId);
|
const proposal = await ws.db.get(Stores.proposals, proposalId);
|
||||||
|
|
||||||
if (!proposal) {
|
if (!proposal) {
|
||||||
throw Error(`proposal with id ${proposalId} not found`);
|
throw Error(`proposal with id ${proposalId} not found`);
|
||||||
@ -1008,7 +996,7 @@ export async function confirmPay(
|
|||||||
throw Error("proposal is in invalid state");
|
throw Error("proposal is in invalid state");
|
||||||
}
|
}
|
||||||
|
|
||||||
let purchase = await oneShotGet(ws.db, Stores.purchases, d.contractTermsHash);
|
let purchase = await ws.db.get(Stores.purchases, d.contractTermsHash);
|
||||||
|
|
||||||
if (purchase) {
|
if (purchase) {
|
||||||
if (
|
if (
|
||||||
@ -1016,7 +1004,7 @@ export async function confirmPay(
|
|||||||
sessionIdOverride != purchase.lastSessionId
|
sessionIdOverride != purchase.lastSessionId
|
||||||
) {
|
) {
|
||||||
logger.trace(`changing session ID to ${sessionIdOverride}`);
|
logger.trace(`changing session ID to ${sessionIdOverride}`);
|
||||||
await oneShotMutate(ws.db, Stores.purchases, purchase.proposalId, x => {
|
await ws.db.mutate(Stores.purchases, purchase.proposalId, x => {
|
||||||
x.lastSessionId = sessionIdOverride;
|
x.lastSessionId = sessionIdOverride;
|
||||||
x.paymentSubmitPending = true;
|
x.paymentSubmitPending = true;
|
||||||
return x;
|
return x;
|
||||||
@ -1092,8 +1080,7 @@ export async function getFullRefundFees(
|
|||||||
if (refundPermissions.length === 0) {
|
if (refundPermissions.length === 0) {
|
||||||
throw Error("no refunds given");
|
throw Error("no refunds given");
|
||||||
}
|
}
|
||||||
const coin0 = await oneShotGet(
|
const coin0 = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.coins,
|
Stores.coins,
|
||||||
refundPermissions[0].coin_pub,
|
refundPermissions[0].coin_pub,
|
||||||
);
|
);
|
||||||
@ -1104,18 +1091,17 @@ export async function getFullRefundFees(
|
|||||||
Amounts.parseOrThrow(refundPermissions[0].refund_amount).currency,
|
Amounts.parseOrThrow(refundPermissions[0].refund_amount).currency,
|
||||||
);
|
);
|
||||||
|
|
||||||
const denoms = await oneShotIterIndex(
|
const denoms = await ws.db.iterIndex(
|
||||||
ws.db,
|
|
||||||
Stores.denominations.exchangeBaseUrlIndex,
|
Stores.denominations.exchangeBaseUrlIndex,
|
||||||
coin0.exchangeBaseUrl,
|
coin0.exchangeBaseUrl,
|
||||||
).toArray();
|
).toArray();
|
||||||
|
|
||||||
for (const rp of refundPermissions) {
|
for (const rp of refundPermissions) {
|
||||||
const coin = await oneShotGet(ws.db, Stores.coins, rp.coin_pub);
|
const coin = await ws.db.get(Stores.coins, rp.coin_pub);
|
||||||
if (!coin) {
|
if (!coin) {
|
||||||
throw Error("coin not found");
|
throw Error("coin not found");
|
||||||
}
|
}
|
||||||
const denom = await oneShotGet(ws.db, Stores.denominations, [
|
const denom = await ws.db.get(Stores.denominations, [
|
||||||
coin0.exchangeBaseUrl,
|
coin0.exchangeBaseUrl,
|
||||||
coin.denomPub,
|
coin.denomPub,
|
||||||
]);
|
]);
|
||||||
@ -1147,7 +1133,7 @@ async function acceptRefundResponse(
|
|||||||
|
|
||||||
let numNewRefunds = 0;
|
let numNewRefunds = 0;
|
||||||
|
|
||||||
await runWithWriteTransaction(ws.db, [Stores.purchases], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.purchases], async tx => {
|
||||||
const p = await tx.get(Stores.purchases, proposalId);
|
const p = await tx.get(Stores.purchases, proposalId);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
console.error("purchase not found, not adding refunds");
|
console.error("purchase not found, not adding refunds");
|
||||||
@ -1215,8 +1201,7 @@ async function startRefundQuery(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const success = await runWithWriteTransaction(
|
const success = await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.purchases],
|
[Stores.purchases],
|
||||||
async tx => {
|
async tx => {
|
||||||
const p = await tx.get(Stores.purchases, proposalId);
|
const p = await tx.get(Stores.purchases, proposalId);
|
||||||
@ -1259,8 +1244,7 @@ export async function applyRefund(
|
|||||||
throw Error("invalid refund URI");
|
throw Error("invalid refund URI");
|
||||||
}
|
}
|
||||||
|
|
||||||
const purchase = await oneShotGetIndexed(
|
const purchase = await ws.db.getIndexed(
|
||||||
ws.db,
|
|
||||||
Stores.purchases.orderIdIndex,
|
Stores.purchases.orderIdIndex,
|
||||||
[parseResult.merchantBaseUrl, parseResult.orderId],
|
[parseResult.merchantBaseUrl, parseResult.orderId],
|
||||||
);
|
);
|
||||||
@ -1292,7 +1276,7 @@ async function resetPurchasePayRetry(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
) {
|
) {
|
||||||
await oneShotMutate(ws.db, Stores.purchases, proposalId, x => {
|
await ws.db.mutate(Stores.purchases, proposalId, x => {
|
||||||
if (x.payRetryInfo.active) {
|
if (x.payRetryInfo.active) {
|
||||||
x.payRetryInfo = initRetryInfo();
|
x.payRetryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
@ -1308,7 +1292,7 @@ async function processPurchasePayImpl(
|
|||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetPurchasePayRetry(ws, proposalId);
|
await resetPurchasePayRetry(ws, proposalId);
|
||||||
}
|
}
|
||||||
const purchase = await oneShotGet(ws.db, Stores.purchases, proposalId);
|
const purchase = await ws.db.get(Stores.purchases, proposalId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1336,7 +1320,7 @@ async function resetPurchaseQueryRefundRetry(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
) {
|
) {
|
||||||
await oneShotMutate(ws.db, Stores.purchases, proposalId, x => {
|
await ws.db.mutate(Stores.purchases, proposalId, x => {
|
||||||
if (x.refundStatusRetryInfo.active) {
|
if (x.refundStatusRetryInfo.active) {
|
||||||
x.refundStatusRetryInfo = initRetryInfo();
|
x.refundStatusRetryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
@ -1352,7 +1336,7 @@ async function processPurchaseQueryRefundImpl(
|
|||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetPurchaseQueryRefundRetry(ws, proposalId);
|
await resetPurchaseQueryRefundRetry(ws, proposalId);
|
||||||
}
|
}
|
||||||
const purchase = await oneShotGet(ws.db, Stores.purchases, proposalId);
|
const purchase = await ws.db.get(Stores.purchases, proposalId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1398,7 +1382,7 @@ async function resetPurchaseApplyRefundRetry(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
) {
|
) {
|
||||||
await oneShotMutate(ws.db, Stores.purchases, proposalId, x => {
|
await ws.db.mutate(Stores.purchases, proposalId, x => {
|
||||||
if (x.refundApplyRetryInfo.active) {
|
if (x.refundApplyRetryInfo.active) {
|
||||||
x.refundApplyRetryInfo = initRetryInfo();
|
x.refundApplyRetryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
@ -1414,7 +1398,7 @@ async function processPurchaseApplyRefundImpl(
|
|||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetPurchaseApplyRefundRetry(ws, proposalId);
|
await resetPurchaseApplyRefundRetry(ws, proposalId);
|
||||||
}
|
}
|
||||||
const purchase = await oneShotGet(ws.db, Stores.purchases, proposalId);
|
const purchase = await ws.db.get(Stores.purchases, proposalId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
console.error("not submitting refunds, payment not found:");
|
console.error("not submitting refunds, payment not found:");
|
||||||
return;
|
return;
|
||||||
@ -1448,8 +1432,7 @@ async function processPurchaseApplyRefundImpl(
|
|||||||
|
|
||||||
let allRefundsProcessed = false;
|
let allRefundsProcessed = false;
|
||||||
|
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.purchases, Stores.coins],
|
[Stores.purchases, Stores.coins],
|
||||||
async tx => {
|
async tx => {
|
||||||
const p = await tx.get(Stores.purchases, proposalId);
|
const p = await tx.get(Stores.purchases, proposalId);
|
||||||
|
@ -18,10 +18,7 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
oneShotIter,
|
Database
|
||||||
runWithWriteTransaction,
|
|
||||||
oneShotGet,
|
|
||||||
oneShotPut,
|
|
||||||
} from "../util/query";
|
} from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { Stores, TipRecord, CoinStatus } from "../types/dbTypes";
|
import { Stores, TipRecord, CoinStatus } from "../types/dbTypes";
|
||||||
@ -37,7 +34,7 @@ export async function payback(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
coinPub: string,
|
coinPub: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
let coin = await oneShotGet(ws.db, Stores.coins, coinPub);
|
let coin = await ws.db.get(Stores.coins, coinPub);
|
||||||
if (!coin) {
|
if (!coin) {
|
||||||
throw Error(`Coin ${coinPub} not found, can't request payback`);
|
throw Error(`Coin ${coinPub} not found, can't request payback`);
|
||||||
}
|
}
|
||||||
@ -45,7 +42,7 @@ export async function payback(
|
|||||||
if (!reservePub) {
|
if (!reservePub) {
|
||||||
throw Error(`Can't request payback for a refreshed coin`);
|
throw Error(`Can't request payback for a refreshed coin`);
|
||||||
}
|
}
|
||||||
const reserve = await oneShotGet(ws.db, Stores.reserves, reservePub);
|
const reserve = await ws.db.get(Stores.reserves, reservePub);
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
throw Error(`Reserve of coin ${coinPub} not found`);
|
throw Error(`Reserve of coin ${coinPub} not found`);
|
||||||
}
|
}
|
||||||
@ -58,8 +55,7 @@ export async function payback(
|
|||||||
// technically we might update reserve status before we get the response
|
// technically we might update reserve status before we get the response
|
||||||
// from the reserve for the payback request.
|
// from the reserve for the payback request.
|
||||||
reserve.hasPayback = true;
|
reserve.hasPayback = true;
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.coins, Stores.reserves],
|
[Stores.coins, Stores.reserves],
|
||||||
async tx => {
|
async tx => {
|
||||||
await tx.put(Stores.coins, coin!!);
|
await tx.put(Stores.coins, coin!!);
|
||||||
@ -80,12 +76,12 @@ export async function payback(
|
|||||||
if (paybackConfirmation.reserve_pub !== coin.reservePub) {
|
if (paybackConfirmation.reserve_pub !== coin.reservePub) {
|
||||||
throw Error(`Coin's reserve doesn't match reserve on payback`);
|
throw Error(`Coin's reserve doesn't match reserve on payback`);
|
||||||
}
|
}
|
||||||
coin = await oneShotGet(ws.db, Stores.coins, coinPub);
|
coin = await ws.db.get(Stores.coins, coinPub);
|
||||||
if (!coin) {
|
if (!coin) {
|
||||||
throw Error(`Coin ${coinPub} not found, can't confirm payback`);
|
throw Error(`Coin ${coinPub} not found, can't confirm payback`);
|
||||||
}
|
}
|
||||||
coin.status = CoinStatus.Dormant;
|
coin.status = CoinStatus.Dormant;
|
||||||
await oneShotPut(ws.db, Stores.coins, coin);
|
await ws.db.put(Stores.coins, coin);
|
||||||
ws.notify({
|
ws.notify({
|
||||||
type: NotificationType.PaybackFinished,
|
type: NotificationType.PaybackFinished,
|
||||||
});
|
});
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
Timestamp,
|
Timestamp,
|
||||||
Duration,
|
Duration,
|
||||||
} from "../types/walletTypes";
|
} from "../types/walletTypes";
|
||||||
import { runWithReadTransaction, TransactionHandle } from "../util/query";
|
import { Database, TransactionHandle } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import {
|
import {
|
||||||
Stores,
|
Stores,
|
||||||
@ -425,8 +425,7 @@ export async function getPendingOperations(
|
|||||||
pendingOperations: [],
|
pendingOperations: [],
|
||||||
};
|
};
|
||||||
const now = getTimestampNow();
|
const now = getTimestampNow();
|
||||||
await runWithReadTransaction(
|
await ws.db.runWithReadTransaction(
|
||||||
ws.db,
|
|
||||||
[
|
[
|
||||||
Stores.exchanges,
|
Stores.exchanges,
|
||||||
Stores.reserves,
|
Stores.reserves,
|
||||||
|
@ -27,21 +27,12 @@ import {
|
|||||||
updateRetryInfoTimeout,
|
updateRetryInfoTimeout,
|
||||||
} from "../types/dbTypes";
|
} from "../types/dbTypes";
|
||||||
import { amountToPretty } from "../util/helpers";
|
import { amountToPretty } from "../util/helpers";
|
||||||
import {
|
import { Database } from "../util/query";
|
||||||
oneShotGet,
|
|
||||||
oneShotMutate,
|
|
||||||
runWithWriteTransaction,
|
|
||||||
TransactionAbort,
|
|
||||||
oneShotIterIndex,
|
|
||||||
} from "../util/query";
|
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import { getWithdrawDenomList } from "./withdraw";
|
import { getWithdrawDenomList } from "./withdraw";
|
||||||
import { updateExchangeFromUrl } from "./exchanges";
|
import { updateExchangeFromUrl } from "./exchanges";
|
||||||
import {
|
import { getTimestampNow, OperationError } from "../types/walletTypes";
|
||||||
getTimestampNow,
|
|
||||||
OperationError,
|
|
||||||
} from "../types/walletTypes";
|
|
||||||
import { guardOperationException } from "./errors";
|
import { guardOperationException } from "./errors";
|
||||||
import { NotificationType } from "../types/notifications";
|
import { NotificationType } from "../types/notifications";
|
||||||
|
|
||||||
@ -84,11 +75,7 @@ async function refreshMelt(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
refreshSessionId: string,
|
refreshSessionId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const refreshSession = await oneShotGet(
|
const refreshSession = await ws.db.get(Stores.refresh, refreshSessionId);
|
||||||
ws.db,
|
|
||||||
Stores.refresh,
|
|
||||||
refreshSessionId,
|
|
||||||
);
|
|
||||||
if (!refreshSession) {
|
if (!refreshSession) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -96,11 +83,7 @@ async function refreshMelt(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const coin = await oneShotGet(
|
const coin = await ws.db.get(Stores.coins, refreshSession.meltCoinPub);
|
||||||
ws.db,
|
|
||||||
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");
|
||||||
@ -139,7 +122,7 @@ async function refreshMelt(
|
|||||||
|
|
||||||
refreshSession.norevealIndex = norevealIndex;
|
refreshSession.norevealIndex = norevealIndex;
|
||||||
|
|
||||||
await oneShotMutate(ws.db, Stores.refresh, refreshSessionId, rs => {
|
await ws.db.mutate(Stores.refresh, refreshSessionId, rs => {
|
||||||
if (rs.norevealIndex !== undefined) {
|
if (rs.norevealIndex !== undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -159,11 +142,7 @@ async function refreshReveal(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
refreshSessionId: string,
|
refreshSessionId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const refreshSession = await oneShotGet(
|
const refreshSession = await ws.db.get(Stores.refresh, refreshSessionId);
|
||||||
ws.db,
|
|
||||||
Stores.refresh,
|
|
||||||
refreshSessionId,
|
|
||||||
);
|
|
||||||
if (!refreshSession) {
|
if (!refreshSession) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -179,8 +158,7 @@ async function refreshReveal(
|
|||||||
throw Error("refresh index error");
|
throw Error("refresh index error");
|
||||||
}
|
}
|
||||||
|
|
||||||
const meltCoinRecord = await oneShotGet(
|
const meltCoinRecord = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.coins,
|
Stores.coins,
|
||||||
refreshSession.meltCoinPub,
|
refreshSession.meltCoinPub,
|
||||||
);
|
);
|
||||||
@ -241,7 +219,7 @@ async function refreshReveal(
|
|||||||
const coins: CoinRecord[] = [];
|
const coins: CoinRecord[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < respJson.ev_sigs.length; i++) {
|
for (let i = 0; i < respJson.ev_sigs.length; i++) {
|
||||||
const denom = await oneShotGet(ws.db, Stores.denominations, [
|
const denom = await ws.db.get(Stores.denominations, [
|
||||||
refreshSession.exchangeBaseUrl,
|
refreshSession.exchangeBaseUrl,
|
||||||
refreshSession.newDenoms[i],
|
refreshSession.newDenoms[i],
|
||||||
]);
|
]);
|
||||||
@ -274,8 +252,7 @@ async function refreshReveal(
|
|||||||
coins.push(coin);
|
coins.push(coin);
|
||||||
}
|
}
|
||||||
|
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.coins, Stores.refresh],
|
[Stores.coins, Stores.refresh],
|
||||||
async tx => {
|
async tx => {
|
||||||
const rs = await tx.get(Stores.refresh, refreshSessionId);
|
const rs = await tx.get(Stores.refresh, refreshSessionId);
|
||||||
@ -306,7 +283,7 @@ async function incrementRefreshRetry(
|
|||||||
refreshSessionId: string,
|
refreshSessionId: string,
|
||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await runWithWriteTransaction(ws.db, [Stores.refresh], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.refresh], async tx => {
|
||||||
const r = await tx.get(Stores.refresh, refreshSessionId);
|
const r = await tx.get(Stores.refresh, refreshSessionId);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return;
|
return;
|
||||||
@ -341,7 +318,7 @@ async function resetRefreshSessionRetry(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
refreshSessionId: string,
|
refreshSessionId: string,
|
||||||
) {
|
) {
|
||||||
await oneShotMutate(ws.db, Stores.refresh, refreshSessionId, (x) => {
|
await ws.db.mutate(Stores.refresh, refreshSessionId, x => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
@ -357,11 +334,7 @@ async function processRefreshSessionImpl(
|
|||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetRefreshSessionRetry(ws, refreshSessionId);
|
await resetRefreshSessionRetry(ws, refreshSessionId);
|
||||||
}
|
}
|
||||||
const refreshSession = await oneShotGet(
|
const refreshSession = await ws.db.get(Stores.refresh, refreshSessionId);
|
||||||
ws.db,
|
|
||||||
Stores.refresh,
|
|
||||||
refreshSessionId,
|
|
||||||
);
|
|
||||||
if (!refreshSession) {
|
if (!refreshSession) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -380,7 +353,7 @@ export async function refresh(
|
|||||||
oldCoinPub: string,
|
oldCoinPub: string,
|
||||||
force: boolean = false,
|
force: boolean = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const coin = await oneShotGet(ws.db, Stores.coins, oldCoinPub);
|
const coin = await ws.db.get(Stores.coins, oldCoinPub);
|
||||||
if (!coin) {
|
if (!coin) {
|
||||||
console.warn("can't refresh, coin not in database");
|
console.warn("can't refresh, coin not in database");
|
||||||
return;
|
return;
|
||||||
@ -402,7 +375,7 @@ export async function refresh(
|
|||||||
throw Error("db inconsistent: exchange of coin not found");
|
throw Error("db inconsistent: exchange of coin not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldDenom = await oneShotGet(ws.db, Stores.denominations, [
|
const oldDenom = await ws.db.get(Stores.denominations, [
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
coin.denomPub,
|
coin.denomPub,
|
||||||
]);
|
]);
|
||||||
@ -411,11 +384,9 @@ export async function refresh(
|
|||||||
throw Error("db inconsistent: denomination for coin not found");
|
throw Error("db inconsistent: denomination for coin not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
const availableDenoms: DenominationRecord[] = await oneShotIterIndex(
|
const availableDenoms: DenominationRecord[] = await ws.db
|
||||||
ws.db,
|
.iterIndex(Stores.denominations.exchangeBaseUrlIndex, exchange.baseUrl)
|
||||||
Stores.denominations.exchangeBaseUrlIndex,
|
.toArray();
|
||||||
exchange.baseUrl,
|
|
||||||
).toArray();
|
|
||||||
|
|
||||||
const availableAmount = Amounts.sub(coin.currentAmount, oldDenom.feeRefresh)
|
const availableAmount = Amounts.sub(coin.currentAmount, oldDenom.feeRefresh)
|
||||||
.amount;
|
.amount;
|
||||||
@ -428,7 +399,7 @@ export async function refresh(
|
|||||||
availableAmount,
|
availableAmount,
|
||||||
)} too small`,
|
)} too small`,
|
||||||
);
|
);
|
||||||
await oneShotMutate(ws.db, Stores.coins, oldCoinPub, x => {
|
await ws.db.mutate(Stores.coins, oldCoinPub, x => {
|
||||||
if (x.status != coin.status) {
|
if (x.status != coin.status) {
|
||||||
// Concurrent modification?
|
// Concurrent modification?
|
||||||
return;
|
return;
|
||||||
@ -450,8 +421,7 @@ export async function refresh(
|
|||||||
|
|
||||||
// Store refresh session and subtract refreshed amount from
|
// Store refresh session and subtract refreshed amount from
|
||||||
// coin in the same transaction.
|
// coin in the same transaction.
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.refresh, Stores.coins],
|
[Stores.refresh, Stores.coins],
|
||||||
async tx => {
|
async tx => {
|
||||||
const c = await tx.get(Stores.coins, coin.coinPub);
|
const c = await tx.get(Stores.coins, coin.coinPub);
|
||||||
|
@ -33,10 +33,7 @@ import {
|
|||||||
updateRetryInfoTimeout,
|
updateRetryInfoTimeout,
|
||||||
} from "../types/dbTypes";
|
} from "../types/dbTypes";
|
||||||
import {
|
import {
|
||||||
oneShotMutate,
|
Database,
|
||||||
oneShotPut,
|
|
||||||
oneShotGet,
|
|
||||||
runWithWriteTransaction,
|
|
||||||
TransactionAbort,
|
TransactionAbort,
|
||||||
} from "../util/query";
|
} from "../util/query";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
@ -104,7 +101,7 @@ export async function createReserve(
|
|||||||
const rec = {
|
const rec = {
|
||||||
paytoUri: senderWire,
|
paytoUri: senderWire,
|
||||||
};
|
};
|
||||||
await oneShotPut(ws.db, Stores.senderWires, rec);
|
await ws.db.put(Stores.senderWires, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
const exchangeInfo = await updateExchangeFromUrl(ws, req.exchange);
|
const exchangeInfo = await updateExchangeFromUrl(ws, req.exchange);
|
||||||
@ -114,8 +111,7 @@ export async function createReserve(
|
|||||||
throw Error("exchange not updated");
|
throw Error("exchange not updated");
|
||||||
}
|
}
|
||||||
const { isAudited, isTrusted } = await getExchangeTrust(ws, exchangeInfo);
|
const { isAudited, isTrusted } = await getExchangeTrust(ws, exchangeInfo);
|
||||||
let currencyRecord = await oneShotGet(
|
let currencyRecord = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.currencies,
|
Stores.currencies,
|
||||||
exchangeDetails.currency,
|
exchangeDetails.currency,
|
||||||
);
|
);
|
||||||
@ -137,8 +133,7 @@ export async function createReserve(
|
|||||||
|
|
||||||
const cr: CurrencyRecord = currencyRecord;
|
const cr: CurrencyRecord = currencyRecord;
|
||||||
|
|
||||||
const resp = await runWithWriteTransaction(
|
const resp = await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.currencies, Stores.reserves, Stores.bankWithdrawUris],
|
[Stores.currencies, Stores.reserves, Stores.bankWithdrawUris],
|
||||||
async tx => {
|
async tx => {
|
||||||
// Check if we have already created a reserve for that bankWithdrawStatusUrl
|
// Check if we have already created a reserve for that bankWithdrawStatusUrl
|
||||||
@ -212,7 +207,7 @@ async function registerReserveWithBank(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
reservePub: string,
|
reservePub: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
let reserve = await oneShotGet(ws.db, Stores.reserves, reservePub);
|
let reserve = await ws.db.get(Stores.reserves, reservePub);
|
||||||
switch (reserve?.reserveStatus) {
|
switch (reserve?.reserveStatus) {
|
||||||
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
||||||
case ReserveRecordStatus.REGISTERING_BANK:
|
case ReserveRecordStatus.REGISTERING_BANK:
|
||||||
@ -233,7 +228,7 @@ async function registerReserveWithBank(
|
|||||||
selected_exchange: reserve.exchangeWire,
|
selected_exchange: reserve.exchangeWire,
|
||||||
});
|
});
|
||||||
console.log("got response", bankResp);
|
console.log("got response", bankResp);
|
||||||
await oneShotMutate(ws.db, Stores.reserves, reservePub, r => {
|
await ws.db.mutate(Stores.reserves, reservePub, r => {
|
||||||
switch (r.reserveStatus) {
|
switch (r.reserveStatus) {
|
||||||
case ReserveRecordStatus.REGISTERING_BANK:
|
case ReserveRecordStatus.REGISTERING_BANK:
|
||||||
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
||||||
@ -266,7 +261,7 @@ async function processReserveBankStatusImpl(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
reservePub: string,
|
reservePub: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
let reserve = await oneShotGet(ws.db, Stores.reserves, reservePub);
|
let reserve = await ws.db.get(Stores.reserves, reservePub);
|
||||||
switch (reserve?.reserveStatus) {
|
switch (reserve?.reserveStatus) {
|
||||||
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
||||||
case ReserveRecordStatus.REGISTERING_BANK:
|
case ReserveRecordStatus.REGISTERING_BANK:
|
||||||
@ -303,7 +298,7 @@ async function processReserveBankStatusImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status.transfer_done) {
|
if (status.transfer_done) {
|
||||||
await oneShotMutate(ws.db, Stores.reserves, reservePub, r => {
|
await ws.db.mutate(Stores.reserves, reservePub, r => {
|
||||||
switch (r.reserveStatus) {
|
switch (r.reserveStatus) {
|
||||||
case ReserveRecordStatus.REGISTERING_BANK:
|
case ReserveRecordStatus.REGISTERING_BANK:
|
||||||
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
||||||
@ -319,7 +314,7 @@ async function processReserveBankStatusImpl(
|
|||||||
});
|
});
|
||||||
await processReserveImpl(ws, reservePub, true);
|
await processReserveImpl(ws, reservePub, true);
|
||||||
} else {
|
} else {
|
||||||
await oneShotMutate(ws.db, Stores.reserves, reservePub, r => {
|
await ws.db.mutate(Stores.reserves, reservePub, r => {
|
||||||
switch (r.reserveStatus) {
|
switch (r.reserveStatus) {
|
||||||
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
case ReserveRecordStatus.WAIT_CONFIRM_BANK:
|
||||||
break;
|
break;
|
||||||
@ -339,7 +334,7 @@ async function incrementReserveRetry(
|
|||||||
reservePub: string,
|
reservePub: string,
|
||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await runWithWriteTransaction(ws.db, [Stores.reserves], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.reserves], async tx => {
|
||||||
const r = await tx.get(Stores.reserves, reservePub);
|
const r = await tx.get(Stores.reserves, reservePub);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return;
|
return;
|
||||||
@ -363,7 +358,7 @@ async function updateReserve(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
reservePub: string,
|
reservePub: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reserve = await oneShotGet(ws.db, Stores.reserves, reservePub);
|
const reserve = await ws.db.get(Stores.reserves, reservePub);
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
throw Error("reserve not in db");
|
throw Error("reserve not in db");
|
||||||
}
|
}
|
||||||
@ -400,7 +395,7 @@ async function updateReserve(
|
|||||||
}
|
}
|
||||||
const reserveInfo = ReserveStatus.checked(await resp.json());
|
const reserveInfo = ReserveStatus.checked(await resp.json());
|
||||||
const balance = Amounts.parseOrThrow(reserveInfo.balance);
|
const balance = Amounts.parseOrThrow(reserveInfo.balance);
|
||||||
await oneShotMutate(ws.db, Stores.reserves, reserve.reservePub, r => {
|
await ws.db.mutate(Stores.reserves, reserve.reservePub, r => {
|
||||||
if (r.reserveStatus !== ReserveRecordStatus.QUERYING_STATUS) {
|
if (r.reserveStatus !== ReserveRecordStatus.QUERYING_STATUS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -442,7 +437,7 @@ async function processReserveImpl(
|
|||||||
reservePub: string,
|
reservePub: string,
|
||||||
forceNow: boolean = false,
|
forceNow: boolean = false,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reserve = await oneShotGet(ws.db, Stores.reserves, reservePub);
|
const reserve = await ws.db.get(Stores.reserves, reservePub);
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
console.log("not processing reserve: reserve does not exist");
|
console.log("not processing reserve: reserve does not exist");
|
||||||
return;
|
return;
|
||||||
@ -488,7 +483,7 @@ export async function confirmReserve(
|
|||||||
req: ConfirmReserveRequest,
|
req: ConfirmReserveRequest,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const now = getTimestampNow();
|
const now = getTimestampNow();
|
||||||
await oneShotMutate(ws.db, Stores.reserves, req.reservePub, reserve => {
|
await ws.db.mutate(Stores.reserves, req.reservePub, reserve => {
|
||||||
if (reserve.reserveStatus !== ReserveRecordStatus.UNCONFIRMED) {
|
if (reserve.reserveStatus !== ReserveRecordStatus.UNCONFIRMED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -515,7 +510,7 @@ async function depleteReserve(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
reservePub: string,
|
reservePub: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const reserve = await oneShotGet(ws.db, Stores.reserves, reservePub);
|
const reserve = await ws.db.get(Stores.reserves, reservePub);
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -600,8 +595,7 @@ async function depleteReserve(
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
const success = await runWithWriteTransaction(
|
const success = await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.withdrawalSession, Stores.reserves],
|
[Stores.withdrawalSession, Stores.reserves],
|
||||||
async tx => {
|
async tx => {
|
||||||
const myReserve = await tx.get(Stores.reserves, reservePub);
|
const myReserve = await tx.get(Stores.reserves, reservePub);
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
ReturnCoinsRequest,
|
ReturnCoinsRequest,
|
||||||
CoinWithDenom,
|
CoinWithDenom,
|
||||||
} from "../types/walletTypes";
|
} from "../types/walletTypes";
|
||||||
import { runWithWriteTransaction, oneShotGet, oneShotIterIndex, oneShotPut } from "../util/query";
|
import { Database } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { Stores, TipRecord, CoinStatus, CoinsReturnRecord, CoinRecord } from "../types/dbTypes";
|
import { Stores, TipRecord, CoinStatus, CoinsReturnRecord, CoinRecord } from "../types/dbTypes";
|
||||||
import * as Amounts from "../util/amounts";
|
import * as Amounts from "../util/amounts";
|
||||||
@ -38,8 +38,7 @@ async function getCoinsForReturn(
|
|||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
amount: AmountJson,
|
amount: AmountJson,
|
||||||
): Promise<CoinWithDenom[] | undefined> {
|
): Promise<CoinWithDenom[] | undefined> {
|
||||||
const exchange = await oneShotGet(
|
const exchange = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.exchanges,
|
Stores.exchanges,
|
||||||
exchangeBaseUrl,
|
exchangeBaseUrl,
|
||||||
);
|
);
|
||||||
@ -47,8 +46,7 @@ async function getCoinsForReturn(
|
|||||||
throw Error(`Exchange ${exchangeBaseUrl} not known to the wallet`);
|
throw Error(`Exchange ${exchangeBaseUrl} not known to the wallet`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const coins: CoinRecord[] = await oneShotIterIndex(
|
const coins: CoinRecord[] = await ws.db.iterIndex(
|
||||||
ws.db,
|
|
||||||
Stores.coins.exchangeBaseUrlIndex,
|
Stores.coins.exchangeBaseUrlIndex,
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
).toArray();
|
).toArray();
|
||||||
@ -57,15 +55,14 @@ async function getCoinsForReturn(
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const denoms = await oneShotIterIndex(
|
const denoms = await ws.db.iterIndex(
|
||||||
ws.db,
|
|
||||||
Stores.denominations.exchangeBaseUrlIndex,
|
Stores.denominations.exchangeBaseUrlIndex,
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
).toArray();
|
).toArray();
|
||||||
|
|
||||||
// Denomination of the first coin, we assume that all other
|
// Denomination of the first coin, we assume that all other
|
||||||
// coins have the same currency
|
// coins have the same currency
|
||||||
const firstDenom = await oneShotGet(ws.db, Stores.denominations, [
|
const firstDenom = await ws.db.get(Stores.denominations, [
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
coins[0].denomPub,
|
coins[0].denomPub,
|
||||||
]);
|
]);
|
||||||
@ -76,7 +73,7 @@ async function getCoinsForReturn(
|
|||||||
|
|
||||||
const cds: CoinWithDenom[] = [];
|
const cds: CoinWithDenom[] = [];
|
||||||
for (const coin of coins) {
|
for (const coin of coins) {
|
||||||
const denom = await oneShotGet(ws.db, Stores.denominations, [
|
const denom = await ws.db.get(Stores.denominations, [
|
||||||
exchange.baseUrl,
|
exchange.baseUrl,
|
||||||
coin.denomPub,
|
coin.denomPub,
|
||||||
]);
|
]);
|
||||||
@ -121,7 +118,7 @@ export async function returnCoins(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const stampSecNow = Math.floor(new Date().getTime() / 1000);
|
const stampSecNow = Math.floor(new Date().getTime() / 1000);
|
||||||
const exchange = await oneShotGet(ws.db, Stores.exchanges, req.exchange);
|
const exchange = await ws.db.get(Stores.exchanges, req.exchange);
|
||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
console.error(`Exchange ${req.exchange} not known to the wallet`);
|
console.error(`Exchange ${req.exchange} not known to the wallet`);
|
||||||
return;
|
return;
|
||||||
@ -190,8 +187,7 @@ export async function returnCoins(
|
|||||||
wire: req.senderWire,
|
wire: req.senderWire,
|
||||||
};
|
};
|
||||||
|
|
||||||
await runWithWriteTransaction(
|
await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.coinsReturns, Stores.coins],
|
[Stores.coinsReturns, Stores.coins],
|
||||||
async tx => {
|
async tx => {
|
||||||
await tx.put(Stores.coinsReturns, coinsReturnRecord);
|
await tx.put(Stores.coinsReturns, coinsReturnRecord);
|
||||||
@ -248,8 +244,7 @@ async function depositReturnedCoins(
|
|||||||
// FIXME: verify signature
|
// FIXME: verify signature
|
||||||
|
|
||||||
// For every successful deposit, we replace the old record with an updated one
|
// For every successful deposit, we replace the old record with an updated one
|
||||||
const currentCrr = await oneShotGet(
|
const currentCrr = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.coinsReturns,
|
Stores.coinsReturns,
|
||||||
coinsReturnRecord.contractTermsHash,
|
coinsReturnRecord.contractTermsHash,
|
||||||
);
|
);
|
||||||
@ -262,6 +257,6 @@ async function depositReturnedCoins(
|
|||||||
nc.depositedSig = respJson.sig;
|
nc.depositedSig = respJson.sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await oneShotPut(ws.db, Stores.coinsReturns, currentCrr);
|
await ws.db.put(Stores.coinsReturns, currentCrr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import { AsyncOpMemoMap, AsyncOpMemoSingle } from "../util/asyncMemo";
|
|||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import { PendingOperationsResponse } from "../types/pending";
|
import { PendingOperationsResponse } from "../types/pending";
|
||||||
import { WalletNotification } from "../types/notifications";
|
import { WalletNotification } from "../types/notifications";
|
||||||
|
import { Database } from "../util/query";
|
||||||
|
|
||||||
type NotificationListener = (n: WalletNotification) => void;
|
type NotificationListener = (n: WalletNotification) => void;
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ export class InternalWalletState {
|
|||||||
listeners: NotificationListener[] = [];
|
listeners: NotificationListener[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public db: IDBDatabase,
|
public db: Database,
|
||||||
public http: HttpRequestLibrary,
|
public http: HttpRequestLibrary,
|
||||||
cryptoWorkerFactory: CryptoWorkerFactory,
|
cryptoWorkerFactory: CryptoWorkerFactory,
|
||||||
) {
|
) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import { oneShotGet, oneShotPut, oneShotMutate, runWithWriteTransaction } from "../util/query";
|
import { Database } from "../util/query";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { parseTipUri } from "../util/taleruri";
|
import { parseTipUri } from "../util/taleruri";
|
||||||
import { TipStatus, getTimestampNow, OperationError } from "../types/walletTypes";
|
import { TipStatus, getTimestampNow, OperationError } from "../types/walletTypes";
|
||||||
@ -53,7 +53,7 @@ export async function getTipStatus(
|
|||||||
|
|
||||||
let amount = Amounts.parseOrThrow(tipPickupStatus.amount);
|
let amount = Amounts.parseOrThrow(tipPickupStatus.amount);
|
||||||
|
|
||||||
let tipRecord = await oneShotGet(ws.db, Stores.tips, [
|
let tipRecord = await ws.db.get(Stores.tips, [
|
||||||
res.merchantTipId,
|
res.merchantTipId,
|
||||||
res.merchantOrigin,
|
res.merchantOrigin,
|
||||||
]);
|
]);
|
||||||
@ -87,7 +87,7 @@ export async function getTipStatus(
|
|||||||
retryInfo: initRetryInfo(),
|
retryInfo: initRetryInfo(),
|
||||||
lastError: undefined,
|
lastError: undefined,
|
||||||
};
|
};
|
||||||
await oneShotPut(ws.db, Stores.tips, tipRecord);
|
await ws.db.put(Stores.tips, tipRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tipStatus: TipStatus = {
|
const tipStatus: TipStatus = {
|
||||||
@ -112,7 +112,7 @@ async function incrementTipRetry(
|
|||||||
refreshSessionId: string,
|
refreshSessionId: string,
|
||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await runWithWriteTransaction(ws.db, [Stores.tips], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.tips], async tx => {
|
||||||
const t = await tx.get(Stores.tips, refreshSessionId);
|
const t = await tx.get(Stores.tips, refreshSessionId);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
return;
|
return;
|
||||||
@ -141,7 +141,7 @@ async function resetTipRetry(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
tipId: string,
|
tipId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await oneShotMutate(ws.db, Stores.tips, tipId, (x) => {
|
await ws.db.mutate(Stores.tips, tipId, (x) => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ async function processTipImpl(
|
|||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetTipRetry(ws, tipId);
|
await resetTipRetry(ws, tipId);
|
||||||
}
|
}
|
||||||
let tipRecord = await oneShotGet(ws.db, Stores.tips, tipId);
|
let tipRecord = await ws.db.get(Stores.tips, tipId);
|
||||||
if (!tipRecord) {
|
if (!tipRecord) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ async function processTipImpl(
|
|||||||
denomsForWithdraw.map(d => ws.cryptoApi.createTipPlanchet(d)),
|
denomsForWithdraw.map(d => ws.cryptoApi.createTipPlanchet(d)),
|
||||||
);
|
);
|
||||||
|
|
||||||
await oneShotMutate(ws.db, Stores.tips, tipId, r => {
|
await ws.db.mutate(Stores.tips, tipId, r => {
|
||||||
if (!r.planchets) {
|
if (!r.planchets) {
|
||||||
r.planchets = planchets;
|
r.planchets = planchets;
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ async function processTipImpl(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tipRecord = await oneShotGet(ws.db, Stores.tips, tipId);
|
tipRecord = await ws.db.get(Stores.tips, tipId);
|
||||||
if (!tipRecord) {
|
if (!tipRecord) {
|
||||||
throw Error("tip not in database");
|
throw Error("tip not in database");
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ async function processTipImpl(
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await runWithWriteTransaction(ws.db, [Stores.tips, Stores.withdrawalSession], async (tx) => {
|
await ws.db.runWithWriteTransaction([Stores.tips, Stores.withdrawalSession], async (tx) => {
|
||||||
const tr = await tx.get(Stores.tips, tipId);
|
const tr = await tx.get(Stores.tips, tipId);
|
||||||
if (!tr) {
|
if (!tr) {
|
||||||
return;
|
return;
|
||||||
@ -291,14 +291,14 @@ export async function acceptTip(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
tipId: string,
|
tipId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const tipRecord = await oneShotGet(ws.db, Stores.tips, tipId);
|
const tipRecord = await ws.db.get(Stores.tips, tipId);
|
||||||
if (!tipRecord) {
|
if (!tipRecord) {
|
||||||
console.log("tip not found");
|
console.log("tip not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tipRecord.accepted = true;
|
tipRecord.accepted = true;
|
||||||
await oneShotPut(ws.db, Stores.tips, tipRecord);
|
await ws.db.put(Stores.tips, tipRecord);
|
||||||
|
|
||||||
await processTip(ws, tipId);
|
await processTip(ws, tipId);
|
||||||
return;
|
return;
|
||||||
|
@ -39,12 +39,7 @@ import { InternalWalletState } from "./state";
|
|||||||
import { parseWithdrawUri } from "../util/taleruri";
|
import { parseWithdrawUri } from "../util/taleruri";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import {
|
import {
|
||||||
oneShotGet,
|
Database
|
||||||
oneShotPut,
|
|
||||||
oneShotIterIndex,
|
|
||||||
oneShotGetIndexed,
|
|
||||||
runWithWriteTransaction,
|
|
||||||
oneShotMutate,
|
|
||||||
} from "../util/query";
|
} from "../util/query";
|
||||||
import {
|
import {
|
||||||
updateExchangeFromUrl,
|
updateExchangeFromUrl,
|
||||||
@ -167,8 +162,7 @@ async function getPossibleDenoms(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
): Promise<DenominationRecord[]> {
|
): Promise<DenominationRecord[]> {
|
||||||
return await oneShotIterIndex(
|
return await ws.db.iterIndex(
|
||||||
ws.db,
|
|
||||||
Stores.denominations.exchangeBaseUrlIndex,
|
Stores.denominations.exchangeBaseUrlIndex,
|
||||||
exchangeBaseUrl,
|
exchangeBaseUrl,
|
||||||
).filter(d => {
|
).filter(d => {
|
||||||
@ -187,8 +181,7 @@ async function processPlanchet(
|
|||||||
withdrawalSessionId: string,
|
withdrawalSessionId: string,
|
||||||
coinIdx: number,
|
coinIdx: number,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const withdrawalSession = await oneShotGet(
|
const withdrawalSession = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.withdrawalSession,
|
Stores.withdrawalSession,
|
||||||
withdrawalSessionId,
|
withdrawalSessionId,
|
||||||
);
|
);
|
||||||
@ -205,8 +198,7 @@ async function processPlanchet(
|
|||||||
console.log("processPlanchet: planchet not found");
|
console.log("processPlanchet: planchet not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const exchange = await oneShotGet(
|
const exchange = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.exchanges,
|
Stores.exchanges,
|
||||||
withdrawalSession.exchangeBaseUrl,
|
withdrawalSession.exchangeBaseUrl,
|
||||||
);
|
);
|
||||||
@ -215,7 +207,7 @@ async function processPlanchet(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const denom = await oneShotGet(ws.db, Stores.denominations, [
|
const denom = await ws.db.get(Stores.denominations, [
|
||||||
withdrawalSession.exchangeBaseUrl,
|
withdrawalSession.exchangeBaseUrl,
|
||||||
planchet.denomPub,
|
planchet.denomPub,
|
||||||
]);
|
]);
|
||||||
@ -268,8 +260,7 @@ async function processPlanchet(
|
|||||||
let withdrawSessionFinished = false;
|
let withdrawSessionFinished = false;
|
||||||
let reserveDepleted = false;
|
let reserveDepleted = false;
|
||||||
|
|
||||||
const success = await runWithWriteTransaction(
|
const success = await ws.db.runWithWriteTransaction(
|
||||||
ws.db,
|
|
||||||
[Stores.coins, Stores.withdrawalSession, Stores.reserves],
|
[Stores.coins, Stores.withdrawalSession, Stores.reserves],
|
||||||
async tx => {
|
async tx => {
|
||||||
const ws = await tx.get(Stores.withdrawalSession, withdrawalSessionId);
|
const ws = await tx.get(Stores.withdrawalSession, withdrawalSessionId);
|
||||||
@ -346,7 +337,7 @@ export async function getVerifiedWithdrawDenomList(
|
|||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
amount: AmountJson,
|
amount: AmountJson,
|
||||||
): Promise<DenominationRecord[]> {
|
): Promise<DenominationRecord[]> {
|
||||||
const exchange = await oneShotGet(ws.db, Stores.exchanges, exchangeBaseUrl);
|
const exchange = await ws.db.get(Stores.exchanges, exchangeBaseUrl);
|
||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
console.log("exchange not found");
|
console.log("exchange not found");
|
||||||
throw Error(`exchange ${exchangeBaseUrl} not found`);
|
throw Error(`exchange ${exchangeBaseUrl} not found`);
|
||||||
@ -391,7 +382,7 @@ export async function getVerifiedWithdrawDenomList(
|
|||||||
denom.status = DenominationStatus.VerifiedGood;
|
denom.status = DenominationStatus.VerifiedGood;
|
||||||
nextPossibleDenoms.push(denom);
|
nextPossibleDenoms.push(denom);
|
||||||
}
|
}
|
||||||
await oneShotPut(ws.db, Stores.denominations, denom);
|
await ws.db.put(Stores.denominations, denom);
|
||||||
} else {
|
} else {
|
||||||
nextPossibleDenoms.push(denom);
|
nextPossibleDenoms.push(denom);
|
||||||
}
|
}
|
||||||
@ -408,8 +399,7 @@ async function makePlanchet(
|
|||||||
withdrawalSessionId: string,
|
withdrawalSessionId: string,
|
||||||
coinIndex: number,
|
coinIndex: number,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const withdrawalSession = await oneShotGet(
|
const withdrawalSession = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.withdrawalSession,
|
Stores.withdrawalSession,
|
||||||
withdrawalSessionId,
|
withdrawalSessionId,
|
||||||
);
|
);
|
||||||
@ -420,11 +410,11 @@ async function makePlanchet(
|
|||||||
if (src.type !== "reserve") {
|
if (src.type !== "reserve") {
|
||||||
throw Error("invalid state");
|
throw Error("invalid state");
|
||||||
}
|
}
|
||||||
const reserve = await oneShotGet(ws.db, Stores.reserves, src.reservePub);
|
const reserve = await ws.db.get(Stores.reserves, src.reservePub);
|
||||||
if (!reserve) {
|
if (!reserve) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const denom = await oneShotGet(ws.db, Stores.denominations, [
|
const denom = await ws.db.get(Stores.denominations, [
|
||||||
withdrawalSession.exchangeBaseUrl,
|
withdrawalSession.exchangeBaseUrl,
|
||||||
withdrawalSession.denoms[coinIndex],
|
withdrawalSession.denoms[coinIndex],
|
||||||
]);
|
]);
|
||||||
@ -450,7 +440,7 @@ async function makePlanchet(
|
|||||||
reservePub: r.reservePub,
|
reservePub: r.reservePub,
|
||||||
withdrawSig: r.withdrawSig,
|
withdrawSig: r.withdrawSig,
|
||||||
};
|
};
|
||||||
await runWithWriteTransaction(ws.db, [Stores.withdrawalSession], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.withdrawalSession], async tx => {
|
||||||
const myWs = await tx.get(Stores.withdrawalSession, withdrawalSessionId);
|
const myWs = await tx.get(Stores.withdrawalSession, withdrawalSessionId);
|
||||||
if (!myWs) {
|
if (!myWs) {
|
||||||
return;
|
return;
|
||||||
@ -469,8 +459,7 @@ async function processWithdrawCoin(
|
|||||||
coinIndex: number,
|
coinIndex: number,
|
||||||
) {
|
) {
|
||||||
logger.trace("starting withdraw for coin", coinIndex);
|
logger.trace("starting withdraw for coin", coinIndex);
|
||||||
const withdrawalSession = await oneShotGet(
|
const withdrawalSession = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.withdrawalSession,
|
Stores.withdrawalSession,
|
||||||
withdrawalSessionId,
|
withdrawalSessionId,
|
||||||
);
|
);
|
||||||
@ -479,8 +468,7 @@ async function processWithdrawCoin(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const coin = await oneShotGetIndexed(
|
const coin = await ws.db.getIndexed(
|
||||||
ws.db,
|
|
||||||
Stores.coins.byWithdrawalWithIdx,
|
Stores.coins.byWithdrawalWithIdx,
|
||||||
[withdrawalSessionId, coinIndex],
|
[withdrawalSessionId, coinIndex],
|
||||||
);
|
);
|
||||||
@ -505,7 +493,7 @@ async function incrementWithdrawalRetry(
|
|||||||
withdrawalSessionId: string,
|
withdrawalSessionId: string,
|
||||||
err: OperationError | undefined,
|
err: OperationError | undefined,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await runWithWriteTransaction(ws.db, [Stores.withdrawalSession], async tx => {
|
await ws.db.runWithWriteTransaction([Stores.withdrawalSession], async tx => {
|
||||||
const wsr = await tx.get(Stores.withdrawalSession, withdrawalSessionId);
|
const wsr = await tx.get(Stores.withdrawalSession, withdrawalSessionId);
|
||||||
if (!wsr) {
|
if (!wsr) {
|
||||||
return;
|
return;
|
||||||
@ -538,7 +526,7 @@ async function resetWithdrawSessionRetry(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
withdrawalSessionId: string,
|
withdrawalSessionId: string,
|
||||||
) {
|
) {
|
||||||
await oneShotMutate(ws.db, Stores.withdrawalSession, withdrawalSessionId, (x) => {
|
await ws.db.mutate(Stores.withdrawalSession, withdrawalSessionId, (x) => {
|
||||||
if (x.retryInfo.active) {
|
if (x.retryInfo.active) {
|
||||||
x.retryInfo = initRetryInfo();
|
x.retryInfo = initRetryInfo();
|
||||||
}
|
}
|
||||||
@ -555,8 +543,7 @@ async function processWithdrawSessionImpl(
|
|||||||
if (forceNow) {
|
if (forceNow) {
|
||||||
await resetWithdrawSessionRetry(ws, withdrawalSessionId);
|
await resetWithdrawSessionRetry(ws, withdrawalSessionId);
|
||||||
}
|
}
|
||||||
const withdrawalSession = await oneShotGet(
|
const withdrawalSession = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.withdrawalSession,
|
Stores.withdrawalSession,
|
||||||
withdrawalSessionId,
|
withdrawalSessionId,
|
||||||
);
|
);
|
||||||
@ -615,15 +602,13 @@ export async function getExchangeWithdrawalInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const possibleDenoms = await oneShotIterIndex(
|
const possibleDenoms = await ws.db.iterIndex(
|
||||||
ws.db,
|
|
||||||
Stores.denominations.exchangeBaseUrlIndex,
|
Stores.denominations.exchangeBaseUrlIndex,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
).filter(d => d.isOffered);
|
).filter(d => d.isOffered);
|
||||||
|
|
||||||
const trustedAuditorPubs = [];
|
const trustedAuditorPubs = [];
|
||||||
const currencyRecord = await oneShotGet(
|
const currencyRecord = await ws.db.get(
|
||||||
ws.db,
|
|
||||||
Stores.currencies,
|
Stores.currencies,
|
||||||
amount.currency,
|
amount.currency,
|
||||||
);
|
);
|
||||||
|
@ -25,22 +25,6 @@
|
|||||||
*/
|
*/
|
||||||
import { openPromise } from "./promiseUtils";
|
import { openPromise } from "./promiseUtils";
|
||||||
|
|
||||||
/**
|
|
||||||
* Result of an inner join.
|
|
||||||
*/
|
|
||||||
export interface JoinResult<L, R> {
|
|
||||||
left: L;
|
|
||||||
right: R;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Result of a left outer join.
|
|
||||||
*/
|
|
||||||
export interface JoinLeftResult<L, R> {
|
|
||||||
left: L;
|
|
||||||
right?: R;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition of an object store.
|
* Definition of an object store.
|
||||||
*/
|
*/
|
||||||
@ -95,46 +79,6 @@ function transactionToPromise(tx: IDBTransaction): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function oneShotGet<T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
store: Store<T>,
|
|
||||||
key: any,
|
|
||||||
): Promise<T | undefined> {
|
|
||||||
const tx = db.transaction([store.name], "readonly");
|
|
||||||
const req = tx.objectStore(store.name).get(key);
|
|
||||||
const v = await requestToPromise(req);
|
|
||||||
await transactionToPromise(tx);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function oneShotGetIndexed<S extends IDBValidKey, T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
index: Index<S, T>,
|
|
||||||
key: any,
|
|
||||||
): Promise<T | undefined> {
|
|
||||||
const tx = db.transaction([index.storeName], "readonly");
|
|
||||||
const req = tx
|
|
||||||
.objectStore(index.storeName)
|
|
||||||
.index(index.indexName)
|
|
||||||
.get(key);
|
|
||||||
const v = await requestToPromise(req);
|
|
||||||
await transactionToPromise(tx);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function oneShotPut<T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
store: Store<T>,
|
|
||||||
value: T,
|
|
||||||
key?: any,
|
|
||||||
): Promise<any> {
|
|
||||||
const tx = db.transaction([store.name], "readwrite");
|
|
||||||
const req = tx.objectStore(store.name).put(value, key);
|
|
||||||
const v = await requestToPromise(req);
|
|
||||||
await transactionToPromise(tx);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyMutation<T>(
|
function applyMutation<T>(
|
||||||
req: IDBRequest,
|
req: IDBRequest,
|
||||||
f: (x: T) => T | undefined,
|
f: (x: T) => T | undefined,
|
||||||
@ -166,18 +110,6 @@ function applyMutation<T>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function oneShotMutate<T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
store: Store<T>,
|
|
||||||
key: any,
|
|
||||||
f: (x: T) => T | undefined,
|
|
||||||
): Promise<void> {
|
|
||||||
const tx = db.transaction([store.name], "readwrite");
|
|
||||||
const req = tx.objectStore(store.name).openCursor(key);
|
|
||||||
await applyMutation(req, f);
|
|
||||||
await transactionToPromise(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
type CursorResult<T> = CursorEmptyResult<T> | CursorValueResult<T>;
|
type CursorResult<T> = CursorEmptyResult<T> | CursorValueResult<T>;
|
||||||
|
|
||||||
interface CursorEmptyResult<T> {
|
interface CursorEmptyResult<T> {
|
||||||
@ -294,28 +226,6 @@ class ResultStream<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function oneShotIter<T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
store: Store<T>,
|
|
||||||
): ResultStream<T> {
|
|
||||||
const tx = db.transaction([store.name], "readonly");
|
|
||||||
const req = tx.objectStore(store.name).openCursor();
|
|
||||||
return new ResultStream<T>(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function oneShotIterIndex<S extends IDBValidKey, T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
index: Index<S, T>,
|
|
||||||
query?: any,
|
|
||||||
): ResultStream<T> {
|
|
||||||
const tx = db.transaction([index.storeName], "readonly");
|
|
||||||
const req = tx
|
|
||||||
.objectStore(index.storeName)
|
|
||||||
.index(index.indexName)
|
|
||||||
.openCursor(query);
|
|
||||||
return new ResultStream<T>(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TransactionHandle {
|
export class TransactionHandle {
|
||||||
constructor(private tx: IDBTransaction) {}
|
constructor(private tx: IDBTransaction) {}
|
||||||
|
|
||||||
@ -361,22 +271,6 @@ export class TransactionHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runWithReadTransaction<T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
stores: Store<any>[],
|
|
||||||
f: (t: TransactionHandle) => Promise<T>,
|
|
||||||
): Promise<T> {
|
|
||||||
return runWithTransaction<T>(db, stores, f, "readonly");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function runWithWriteTransaction<T>(
|
|
||||||
db: IDBDatabase,
|
|
||||||
stores: Store<any>[],
|
|
||||||
f: (t: TransactionHandle) => Promise<T>,
|
|
||||||
): Promise<T> {
|
|
||||||
return runWithTransaction<T>(db, stores, f, "readwrite");
|
|
||||||
}
|
|
||||||
|
|
||||||
function runWithTransaction<T>(
|
function runWithTransaction<T>(
|
||||||
db: IDBDatabase,
|
db: IDBDatabase,
|
||||||
stores: Store<any>[],
|
stores: Store<any>[],
|
||||||
@ -470,7 +364,203 @@ export class Index<S extends IDBValidKey, T> {
|
|||||||
protected _dummyKey: S | undefined;
|
protected _dummyKey: S | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a promise that resolves
|
||||||
|
* to the taler wallet db.
|
||||||
|
*/
|
||||||
|
export function openDatabase(
|
||||||
|
idbFactory: IDBFactory,
|
||||||
|
databaseName: string,
|
||||||
|
databaseVersion: number,
|
||||||
|
schema: any,
|
||||||
|
onVersionChange: () => void,
|
||||||
|
onUpgradeUnsupported: (oldVersion: number, newVersion: number) => void,
|
||||||
|
): Promise<IDBDatabase> {
|
||||||
|
return new Promise<IDBDatabase>((resolve, reject) => {
|
||||||
|
const req = idbFactory.open(databaseName, databaseVersion);
|
||||||
|
req.onerror = e => {
|
||||||
|
console.log("taler database error", e);
|
||||||
|
reject(new Error("database error"));
|
||||||
|
};
|
||||||
|
req.onsuccess = e => {
|
||||||
|
req.result.onversionchange = (evt: IDBVersionChangeEvent) => {
|
||||||
|
console.log(
|
||||||
|
`handling live db version change from ${evt.oldVersion} to ${evt.newVersion}`,
|
||||||
|
);
|
||||||
|
req.result.close();
|
||||||
|
onVersionChange();
|
||||||
|
};
|
||||||
|
resolve(req.result);
|
||||||
|
};
|
||||||
|
req.onupgradeneeded = e => {
|
||||||
|
const db = req.result;
|
||||||
|
console.log(
|
||||||
|
`DB: upgrade needed: oldVersion=${e.oldVersion}, newVersion=${e.newVersion}`,
|
||||||
|
);
|
||||||
|
switch (e.oldVersion) {
|
||||||
|
case 0: // DB does not exist yet
|
||||||
|
for (const n in schema) {
|
||||||
|
if (schema[n] instanceof Store) {
|
||||||
|
const si: Store<any> = schema[n];
|
||||||
|
const s = db.createObjectStore(si.name, si.storeParams);
|
||||||
|
for (const indexName in si as any) {
|
||||||
|
if ((si as any)[indexName] instanceof Index) {
|
||||||
|
const ii: Index<any, any> = (si as any)[indexName];
|
||||||
|
s.createIndex(ii.indexName, ii.keyPath, ii.options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (e.oldVersion !== databaseVersion) {
|
||||||
|
onUpgradeUnsupported(e.oldVersion, databaseVersion);
|
||||||
|
throw Error("incompatible DB");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception that should be thrown by client code to abort a transaction.
|
* Exception that should be thrown by client code to abort a transaction.
|
||||||
*/
|
*/
|
||||||
export const TransactionAbort = Symbol("transaction_abort");
|
export const TransactionAbort = Symbol("transaction_abort");
|
||||||
|
|
||||||
|
export class Database {
|
||||||
|
constructor(private db: IDBDatabase) {}
|
||||||
|
|
||||||
|
static deleteDatabase(idbFactory: IDBFactory, dbName: string) {
|
||||||
|
idbFactory.deleteDatabase(dbName);
|
||||||
|
}
|
||||||
|
|
||||||
|
async exportDatabase(): Promise<any> {
|
||||||
|
const db = this.db;
|
||||||
|
const dump = {
|
||||||
|
name: db.name,
|
||||||
|
stores: {} as { [s: string]: any },
|
||||||
|
version: db.version,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const tx = db.transaction(Array.from(db.objectStoreNames));
|
||||||
|
tx.addEventListener("complete", () => {
|
||||||
|
resolve(dump);
|
||||||
|
});
|
||||||
|
// tslint:disable-next-line:prefer-for-of
|
||||||
|
for (let i = 0; i < db.objectStoreNames.length; i++) {
|
||||||
|
const name = db.objectStoreNames[i];
|
||||||
|
const storeDump = {} as { [s: string]: any };
|
||||||
|
dump.stores[name] = storeDump;
|
||||||
|
tx.objectStore(name)
|
||||||
|
.openCursor()
|
||||||
|
.addEventListener("success", (e: Event) => {
|
||||||
|
const cursor = (e.target as any).result;
|
||||||
|
if (cursor) {
|
||||||
|
storeDump[cursor.key] = cursor.value;
|
||||||
|
cursor.continue();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
importDatabase(dump: any): Promise<void> {
|
||||||
|
const db = this.db;
|
||||||
|
console.log("importing db", dump);
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
|
||||||
|
if (dump.stores) {
|
||||||
|
for (const storeName in dump.stores) {
|
||||||
|
const objects = [];
|
||||||
|
const dumpStore = dump.stores[storeName];
|
||||||
|
for (const key in dumpStore) {
|
||||||
|
objects.push(dumpStore[key]);
|
||||||
|
}
|
||||||
|
console.log(`importing ${objects.length} records into ${storeName}`);
|
||||||
|
const store = tx.objectStore(storeName);
|
||||||
|
for (const obj of objects) {
|
||||||
|
store.put(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tx.addEventListener("complete", () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async get<T>(store: Store<T>, key: any): Promise<T | undefined> {
|
||||||
|
const tx = this.db.transaction([store.name], "readonly");
|
||||||
|
const req = tx.objectStore(store.name).get(key);
|
||||||
|
const v = await requestToPromise(req);
|
||||||
|
await transactionToPromise(tx);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getIndexed<S extends IDBValidKey, T>(
|
||||||
|
index: Index<S, T>,
|
||||||
|
key: any,
|
||||||
|
): Promise<T | undefined> {
|
||||||
|
const tx = this.db.transaction([index.storeName], "readonly");
|
||||||
|
const req = tx
|
||||||
|
.objectStore(index.storeName)
|
||||||
|
.index(index.indexName)
|
||||||
|
.get(key);
|
||||||
|
const v = await requestToPromise(req);
|
||||||
|
await transactionToPromise(tx);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
async put<T>(store: Store<T>, value: T, key?: any): Promise<any> {
|
||||||
|
const tx = this.db.transaction([store.name], "readwrite");
|
||||||
|
const req = tx.objectStore(store.name).put(value, key);
|
||||||
|
const v = await requestToPromise(req);
|
||||||
|
await transactionToPromise(tx);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
async mutate<T>(
|
||||||
|
store: Store<T>,
|
||||||
|
key: any,
|
||||||
|
f: (x: T) => T | undefined,
|
||||||
|
): Promise<void> {
|
||||||
|
const tx = this.db.transaction([store.name], "readwrite");
|
||||||
|
const req = tx.objectStore(store.name).openCursor(key);
|
||||||
|
await applyMutation(req, f);
|
||||||
|
await transactionToPromise(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
iter<T>(store: Store<T>): ResultStream<T> {
|
||||||
|
const tx = this.db.transaction([store.name], "readonly");
|
||||||
|
const req = tx.objectStore(store.name).openCursor();
|
||||||
|
return new ResultStream<T>(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterIndex<S extends IDBValidKey, T>(
|
||||||
|
index: Index<S, T>,
|
||||||
|
query?: any,
|
||||||
|
): ResultStream<T> {
|
||||||
|
const tx = this.db.transaction([index.storeName], "readonly");
|
||||||
|
const req = tx
|
||||||
|
.objectStore(index.storeName)
|
||||||
|
.index(index.indexName)
|
||||||
|
.openCursor(query);
|
||||||
|
return new ResultStream<T>(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
async runWithReadTransaction<T>(
|
||||||
|
stores: Store<any>[],
|
||||||
|
f: (t: TransactionHandle) => Promise<T>,
|
||||||
|
): Promise<T> {
|
||||||
|
return runWithTransaction<T>(this.db, stores, f, "readonly");
|
||||||
|
}
|
||||||
|
|
||||||
|
async runWithWriteTransaction<T>(
|
||||||
|
stores: Store<any>[],
|
||||||
|
f: (t: TransactionHandle) => Promise<T>,
|
||||||
|
): Promise<T> {
|
||||||
|
return runWithTransaction<T>(this.db, stores, f, "readwrite");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,11 +25,7 @@
|
|||||||
import { CryptoWorkerFactory } from "./crypto/workers/cryptoApi";
|
import { CryptoWorkerFactory } from "./crypto/workers/cryptoApi";
|
||||||
import { HttpRequestLibrary } from "./util/http";
|
import { HttpRequestLibrary } from "./util/http";
|
||||||
import {
|
import {
|
||||||
oneShotPut,
|
Database
|
||||||
oneShotGet,
|
|
||||||
runWithWriteTransaction,
|
|
||||||
oneShotIter,
|
|
||||||
oneShotIterIndex,
|
|
||||||
} from "./util/query";
|
} from "./util/query";
|
||||||
|
|
||||||
import { AmountJson } from "./util/amounts";
|
import { AmountJson } from "./util/amounts";
|
||||||
@ -148,12 +144,12 @@ export class Wallet {
|
|||||||
private stopped: boolean = false;
|
private stopped: boolean = false;
|
||||||
private memoRunRetryLoop = new AsyncOpMemoSingle<void>();
|
private memoRunRetryLoop = new AsyncOpMemoSingle<void>();
|
||||||
|
|
||||||
get db(): IDBDatabase {
|
get db(): Database {
|
||||||
return this.ws.db;
|
return this.ws.db;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
db: IDBDatabase,
|
db: Database,
|
||||||
http: HttpRequestLibrary,
|
http: HttpRequestLibrary,
|
||||||
cryptoWorkerFactory: CryptoWorkerFactory,
|
cryptoWorkerFactory: CryptoWorkerFactory,
|
||||||
) {
|
) {
|
||||||
@ -345,8 +341,7 @@ export class Wallet {
|
|||||||
* already been applied.
|
* already been applied.
|
||||||
*/
|
*/
|
||||||
async fillDefaults() {
|
async fillDefaults() {
|
||||||
await runWithWriteTransaction(
|
await this.db.runWithWriteTransaction(
|
||||||
this.db,
|
|
||||||
[Stores.config, Stores.currencies],
|
[Stores.config, Stores.currencies],
|
||||||
async tx => {
|
async tx => {
|
||||||
let applied = false;
|
let applied = false;
|
||||||
@ -381,7 +376,7 @@ export class Wallet {
|
|||||||
*/
|
*/
|
||||||
async refreshDirtyCoins(): Promise<{ numRefreshed: number }> {
|
async refreshDirtyCoins(): Promise<{ numRefreshed: number }> {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
const coins = await oneShotIter(this.db, Stores.coins).toArray();
|
const coins = await this.db.iter(Stores.coins).toArray();
|
||||||
for (let coin of coins) {
|
for (let coin of coins) {
|
||||||
if (coin.status == CoinStatus.Dirty) {
|
if (coin.status == CoinStatus.Dirty) {
|
||||||
try {
|
try {
|
||||||
@ -512,7 +507,7 @@ export class Wallet {
|
|||||||
async findExchange(
|
async findExchange(
|
||||||
exchangeBaseUrl: string,
|
exchangeBaseUrl: string,
|
||||||
): Promise<ExchangeRecord | undefined> {
|
): Promise<ExchangeRecord | undefined> {
|
||||||
return await oneShotGet(this.db, Stores.exchanges, exchangeBaseUrl);
|
return await this.db.get(Stores.exchanges, exchangeBaseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -540,8 +535,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getDenoms(exchangeUrl: string): Promise<DenominationRecord[]> {
|
async getDenoms(exchangeUrl: string): Promise<DenominationRecord[]> {
|
||||||
const denoms = await oneShotIterIndex(
|
const denoms = await this.db.iterIndex(
|
||||||
this.db,
|
|
||||||
Stores.denominations.exchangeBaseUrlIndex,
|
Stores.denominations.exchangeBaseUrlIndex,
|
||||||
exchangeUrl,
|
exchangeUrl,
|
||||||
).toArray();
|
).toArray();
|
||||||
@ -549,37 +543,37 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getProposal(proposalId: string): Promise<ProposalRecord | undefined> {
|
async getProposal(proposalId: string): Promise<ProposalRecord | undefined> {
|
||||||
const proposal = await oneShotGet(this.db, Stores.proposals, proposalId);
|
const proposal = await this.db.get(Stores.proposals, proposalId);
|
||||||
return proposal;
|
return proposal;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getExchanges(): Promise<ExchangeRecord[]> {
|
async getExchanges(): Promise<ExchangeRecord[]> {
|
||||||
return await oneShotIter(this.db, Stores.exchanges).toArray();
|
return await this.db.iter(Stores.exchanges).toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCurrencies(): Promise<CurrencyRecord[]> {
|
async getCurrencies(): Promise<CurrencyRecord[]> {
|
||||||
return await oneShotIter(this.db, Stores.currencies).toArray();
|
return await this.db.iter(Stores.currencies).toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateCurrency(currencyRecord: CurrencyRecord): Promise<void> {
|
async updateCurrency(currencyRecord: CurrencyRecord): Promise<void> {
|
||||||
logger.trace("updating currency to", currencyRecord);
|
logger.trace("updating currency to", currencyRecord);
|
||||||
await oneShotPut(this.db, Stores.currencies, currencyRecord);
|
await this.db.put(Stores.currencies, currencyRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> {
|
async getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> {
|
||||||
return await oneShotIter(this.db, Stores.reserves).filter(
|
return await this.db.iter(Stores.reserves).filter(
|
||||||
r => r.exchangeBaseUrl === exchangeBaseUrl,
|
r => r.exchangeBaseUrl === exchangeBaseUrl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCoinsForExchange(exchangeBaseUrl: string): Promise<CoinRecord[]> {
|
async getCoinsForExchange(exchangeBaseUrl: string): Promise<CoinRecord[]> {
|
||||||
return await oneShotIter(this.db, Stores.coins).filter(
|
return await this.db.iter(Stores.coins).filter(
|
||||||
c => c.exchangeBaseUrl === exchangeBaseUrl,
|
c => c.exchangeBaseUrl === exchangeBaseUrl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCoins(): Promise<CoinRecord[]> {
|
async getCoins(): Promise<CoinRecord[]> {
|
||||||
return await oneShotIter(this.db, Stores.coins).toArray();
|
return await this.db.iter(Stores.coins).toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
async payback(coinPub: string): Promise<void> {
|
async payback(coinPub: string): Promise<void> {
|
||||||
@ -587,7 +581,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getPaybackReserves(): Promise<ReserveRecord[]> {
|
async getPaybackReserves(): Promise<ReserveRecord[]> {
|
||||||
return await oneShotIter(this.db, Stores.reserves).filter(
|
return await this.db.iter(Stores.reserves).filter(
|
||||||
r => r.hasPayback,
|
r => r.hasPayback,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -604,7 +598,7 @@ export class Wallet {
|
|||||||
async getSenderWireInfos(): Promise<SenderWireInfos> {
|
async getSenderWireInfos(): Promise<SenderWireInfos> {
|
||||||
const m: { [url: string]: Set<string> } = {};
|
const m: { [url: string]: Set<string> } = {};
|
||||||
|
|
||||||
await oneShotIter(this.db, Stores.exchanges).forEach(x => {
|
await this.db.iter(Stores.exchanges).forEach(x => {
|
||||||
const wi = x.wireInfo;
|
const wi = x.wireInfo;
|
||||||
if (!wi) {
|
if (!wi) {
|
||||||
return;
|
return;
|
||||||
@ -619,7 +613,7 @@ export class Wallet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const senderWiresSet: Set<string> = new Set();
|
const senderWiresSet: Set<string> = new Set();
|
||||||
await oneShotIter(this.db, Stores.senderWires).forEach(x => {
|
await this.db.iter(Stores.senderWires).forEach(x => {
|
||||||
senderWiresSet.add(x.paytoUri);
|
senderWiresSet.add(x.paytoUri);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -649,7 +643,7 @@ export class Wallet {
|
|||||||
async getPurchase(
|
async getPurchase(
|
||||||
contractTermsHash: string,
|
contractTermsHash: string,
|
||||||
): Promise<PurchaseRecord | undefined> {
|
): Promise<PurchaseRecord | undefined> {
|
||||||
return oneShotGet(this.db, Stores.purchases, contractTermsHash);
|
return this.db.get(Stores.purchases, contractTermsHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFullRefundFees(
|
async getFullRefundFees(
|
||||||
@ -683,7 +677,7 @@ export class Wallet {
|
|||||||
* confirmation from the bank.).
|
* confirmation from the bank.).
|
||||||
*/
|
*/
|
||||||
public async handleNotifyReserve() {
|
public async handleNotifyReserve() {
|
||||||
const reserves = await oneShotIter(this.db, Stores.reserves).toArray();
|
const reserves = await this.db.iter(Stores.reserves).toArray();
|
||||||
for (const r of reserves) {
|
for (const r of reserves) {
|
||||||
if (r.reserveStatus === ReserveRecordStatus.WAIT_CONFIRM_BANK) {
|
if (r.reserveStatus === ReserveRecordStatus.WAIT_CONFIRM_BANK) {
|
||||||
try {
|
try {
|
||||||
@ -718,7 +712,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getPurchaseDetails(hc: string): Promise<PurchaseDetails> {
|
async getPurchaseDetails(hc: string): Promise<PurchaseDetails> {
|
||||||
const purchase = await oneShotGet(this.db, Stores.purchases, hc);
|
const purchase = await this.db.get(Stores.purchases, hc);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
throw Error("unknown purchase");
|
throw Error("unknown purchase");
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { BrowserCryptoWorkerFactory } from "../crypto/workers/cryptoApi";
|
import { BrowserCryptoWorkerFactory } from "../crypto/workers/cryptoApi";
|
||||||
import { deleteDatabase, exportDatabase, importDatabase, openDatabase } from "../db";
|
import { deleteTalerDatabase, openTalerDatabase } from "../db";
|
||||||
import { WALLET_DB_VERSION } from "../types/dbTypes";
|
import { WALLET_DB_VERSION } from "../types/dbTypes";
|
||||||
import { ConfirmReserveRequest, CreateReserveRequest, ReturnCoinsRequest, WalletDiagnostics } from "../types/walletTypes";
|
import { ConfirmReserveRequest, CreateReserveRequest, ReturnCoinsRequest, WalletDiagnostics } from "../types/walletTypes";
|
||||||
import { AmountJson } from "../util/amounts";
|
import { AmountJson } from "../util/amounts";
|
||||||
@ -37,6 +37,7 @@ import { isFirefox } from "./compat";
|
|||||||
import { MessageType } from "./messages";
|
import { MessageType } from "./messages";
|
||||||
import * as wxApi from "./wxApi";
|
import * as wxApi from "./wxApi";
|
||||||
import MessageSender = chrome.runtime.MessageSender;
|
import MessageSender = chrome.runtime.MessageSender;
|
||||||
|
import { Database } from "../util/query";
|
||||||
|
|
||||||
const NeedsWallet = Symbol("NeedsWallet");
|
const NeedsWallet = Symbol("NeedsWallet");
|
||||||
|
|
||||||
@ -67,25 +68,17 @@ async function handleMessage(
|
|||||||
}
|
}
|
||||||
case "dump-db": {
|
case "dump-db": {
|
||||||
const db = needsWallet().db;
|
const db = needsWallet().db;
|
||||||
return exportDatabase(db);
|
return db.exportDatabase()
|
||||||
}
|
}
|
||||||
case "import-db": {
|
case "import-db": {
|
||||||
const db = needsWallet().db;
|
const db = needsWallet().db;
|
||||||
return importDatabase(db, detail.dump);
|
return db.importDatabase(detail.dump);
|
||||||
}
|
}
|
||||||
case "ping": {
|
case "ping": {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
case "reset-db": {
|
case "reset-db": {
|
||||||
if (currentWallet) {
|
deleteTalerDatabase(indexedDB);
|
||||||
const db = currentWallet.db;
|
|
||||||
const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
|
|
||||||
// tslint:disable-next-line:prefer-for-of
|
|
||||||
for (let i = 0; i < db.objectStoreNames.length; i++) {
|
|
||||||
tx.objectStore(db.objectStoreNames[i]).clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deleteDatabase(indexedDB);
|
|
||||||
setBadgeText({ text: "" });
|
setBadgeText({ text: "" });
|
||||||
console.log("reset done");
|
console.log("reset done");
|
||||||
if (!currentWallet) {
|
if (!currentWallet) {
|
||||||
@ -417,7 +410,7 @@ async function reinitWallet() {
|
|||||||
setBadgeText({ text: "" });
|
setBadgeText({ text: "" });
|
||||||
const badge = new ChromeBadge();
|
const badge = new ChromeBadge();
|
||||||
try {
|
try {
|
||||||
currentDatabase = await openDatabase(
|
currentDatabase = await openTalerDatabase(
|
||||||
indexedDB,
|
indexedDB,
|
||||||
reinitWallet,
|
reinitWallet,
|
||||||
handleUpgradeUnsupported,
|
handleUpgradeUnsupported,
|
||||||
@ -430,7 +423,7 @@ async function reinitWallet() {
|
|||||||
const http = new BrowserHttpLib();
|
const http = new BrowserHttpLib();
|
||||||
console.log("setting wallet");
|
console.log("setting wallet");
|
||||||
const wallet = new Wallet(
|
const wallet = new Wallet(
|
||||||
currentDatabase,
|
new Database(currentDatabase),
|
||||||
http,
|
http,
|
||||||
new BrowserCryptoWorkerFactory(),
|
new BrowserCryptoWorkerFactory(),
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user