renaming / dce

This commit is contained in:
Florian Dold 2016-11-15 15:07:17 +01:00
parent a92b7dc0df
commit ded02bf11f
11 changed files with 223 additions and 257 deletions

View File

@ -30,7 +30,7 @@ window.addEventListener("load", () => {
defaultJSExtensions: true, defaultJSExtensions: true,
}); });
System.import("../wxMessaging") System.import("../wxBackend")
.then((wxMessaging: any) => { .then((wxMessaging: any) => {
// Export as global for debugger // Export as global for debugger
(window as any).wxMessaging = wxMessaging; (window as any).wxMessaging = wxMessaging;

View File

@ -21,12 +21,12 @@
*/ */
import {PreCoin, Coin, ReserveRecord, AmountJson} from "./types"; import {PreCoinRecord, CoinRecord, ReserveRecord, AmountJson} from "./types";
import {Denomination} from "./types"; import {Denomination} from "./types";
import {Offer} from "./wallet"; import {OfferRecord} from "./wallet";
import {CoinWithDenom} from "./wallet"; import {CoinWithDenom} from "./wallet";
import {PayCoinInfo} from "./types"; import {PayCoinInfo} from "./types";
import {RefreshSession} from "./types"; import {RefreshSessionRecord} from "./types";
interface WorkerState { interface WorkerState {
@ -214,7 +214,7 @@ export class CryptoApi {
} }
createPreCoin(denom: Denomination, reserve: ReserveRecord): Promise<PreCoin> { createPreCoin(denom: Denomination, reserve: ReserveRecord): Promise<PreCoinRecord> {
return this.doRpc("createPreCoin", 1, denom, reserve); return this.doRpc("createPreCoin", 1, denom, reserve);
} }
@ -227,7 +227,7 @@ export class CryptoApi {
return this.doRpc("isValidDenom", 2, denom, masterPub); return this.doRpc("isValidDenom", 2, denom, masterPub);
} }
signDeposit(offer: Offer, signDeposit(offer: OfferRecord,
cds: CoinWithDenom[]): Promise<PayCoinInfo> { cds: CoinWithDenom[]): Promise<PayCoinInfo> {
return this.doRpc("signDeposit", 3, offer, cds); return this.doRpc("signDeposit", 3, offer, cds);
} }
@ -242,9 +242,9 @@ export class CryptoApi {
createRefreshSession(exchangeBaseUrl: string, createRefreshSession(exchangeBaseUrl: string,
kappa: number, kappa: number,
meltCoin: Coin, meltCoin: CoinRecord,
newCoinDenoms: Denomination[], newCoinDenoms: Denomination[],
meltFee: AmountJson): Promise<RefreshSession> { meltFee: AmountJson): Promise<RefreshSessionRecord> {
return this.doRpc("createRefreshSession", return this.doRpc("createRefreshSession",
4, 4,
exchangeBaseUrl, exchangeBaseUrl,

View File

@ -23,13 +23,13 @@
import * as native from "./emscriptif"; import * as native from "./emscriptif";
import { import {
PreCoin, PayCoinInfo, AmountJson, PreCoinRecord, PayCoinInfo, AmountJson,
RefreshSession, RefreshPreCoin, ReserveRecord RefreshSessionRecord, RefreshPreCoinRecord, ReserveRecord
} from "./types"; } from "./types";
import create = chrome.alarms.create; import create = chrome.alarms.create;
import {Offer} from "./wallet"; import {OfferRecord} from "./wallet";
import {CoinWithDenom} from "./wallet"; import {CoinWithDenom} from "./wallet";
import {CoinPaySig, Coin} from "./types"; import {CoinPaySig, CoinRecord} from "./types";
import {Denomination, Amounts} from "./types"; import {Denomination, Amounts} from "./types";
import {Amount} from "./emscriptif"; import {Amount} from "./emscriptif";
import {HashContext} from "./emscriptif"; import {HashContext} from "./emscriptif";
@ -68,7 +68,7 @@ namespace RpcFunctions {
* reserve. * reserve.
*/ */
export function createPreCoin(denom: Denomination, export function createPreCoin(denom: Denomination,
reserve: ReserveRecord): PreCoin { reserve: ReserveRecord): PreCoinRecord {
let reservePriv = new native.EddsaPrivateKey(); let reservePriv = new native.EddsaPrivateKey();
reservePriv.loadCrock(reserve.reserve_priv); reservePriv.loadCrock(reserve.reserve_priv);
let reservePub = new native.EddsaPublicKey(); let reservePub = new native.EddsaPublicKey();
@ -105,7 +105,7 @@ namespace RpcFunctions {
var sig = native.eddsaSign(withdrawRequest.toPurpose(), reservePriv); var sig = native.eddsaSign(withdrawRequest.toPurpose(), reservePriv);
let preCoin: PreCoin = { let preCoin: PreCoinRecord = {
reservePub: reservePub.toCrock(), reservePub: reservePub.toCrock(),
blindingKey: blindingFactor.toCrock(), blindingKey: blindingFactor.toCrock(),
coinPub: coinPub.toCrock(), coinPub: coinPub.toCrock(),
@ -170,7 +170,7 @@ namespace RpcFunctions {
* Generate updated coins (to store in the database) * Generate updated coins (to store in the database)
* and deposit permissions for each given coin. * and deposit permissions for each given coin.
*/ */
export function signDeposit(offer: Offer, export function signDeposit(offer: OfferRecord,
cds: CoinWithDenom[]): PayCoinInfo { cds: CoinWithDenom[]): PayCoinInfo {
let ret: PayCoinInfo = []; let ret: PayCoinInfo = [];
let amountSpent = native.Amount.getZero(cds[0].coin.currentAmount.currency); let amountSpent = native.Amount.getZero(cds[0].coin.currentAmount.currency);
@ -228,9 +228,9 @@ namespace RpcFunctions {
export function createRefreshSession(exchangeBaseUrl: string, export function createRefreshSession(exchangeBaseUrl: string,
kappa: number, kappa: number,
meltCoin: Coin, meltCoin: CoinRecord,
newCoinDenoms: Denomination[], newCoinDenoms: Denomination[],
meltFee: AmountJson): RefreshSession { meltFee: AmountJson): RefreshSessionRecord {
let valueWithFee = Amounts.getZero(newCoinDenoms[0].value.currency); let valueWithFee = Amounts.getZero(newCoinDenoms[0].value.currency);
@ -248,7 +248,7 @@ namespace RpcFunctions {
let transferPubs: string[] = []; let transferPubs: string[] = [];
let transferPrivs: string[] = []; let transferPrivs: string[] = [];
let preCoinsForGammas: RefreshPreCoin[][] = []; let preCoinsForGammas: RefreshPreCoinRecord[][] = [];
for (let i = 0; i < kappa; i++) { for (let i = 0; i < kappa; i++) {
let t = native.EcdhePrivateKey.create(); let t = native.EcdhePrivateKey.create();
@ -267,7 +267,7 @@ namespace RpcFunctions {
sessionHc.read((new native.Amount(valueWithFee)).toNbo()); sessionHc.read((new native.Amount(valueWithFee)).toNbo());
for (let i = 0; i < kappa; i++) { for (let i = 0; i < kappa; i++) {
let preCoins: RefreshPreCoin[] = []; let preCoins: RefreshPreCoinRecord[] = [];
for (let j = 0; j < newCoinDenoms.length; j++) { for (let j = 0; j < newCoinDenoms.length; j++) {
let transferPriv = native.EcdhePrivateKey.fromCrock(transferPrivs[i]); let transferPriv = native.EcdhePrivateKey.fromCrock(transferPrivs[i]);
@ -287,7 +287,7 @@ namespace RpcFunctions {
if (!ev) { if (!ev) {
throw Error("couldn't blind (malicious exchange key?)"); throw Error("couldn't blind (malicious exchange key?)");
} }
let preCoin: RefreshPreCoin = { let preCoin: RefreshPreCoinRecord = {
blindingKey: blindingFactor.toCrock(), blindingKey: blindingFactor.toCrock(),
coinEv: ev.toCrock(), coinEv: ev.toCrock(),
publicKey: coinPub.toCrock(), publicKey: coinPub.toCrock(),
@ -320,7 +320,7 @@ namespace RpcFunctions {
valueOutput = Amounts.add(valueOutput, denom.value).amount; valueOutput = Amounts.add(valueOutput, denom.value).amount;
} }
let refreshSession: RefreshSession = { let refreshSession: RefreshSessionRecord = {
meltCoinPub: meltCoin.coinPub, meltCoinPub: meltCoin.coinPub,
newDenoms: newCoinDenoms.map((d) => d.denom_pub), newDenoms: newCoinDenoms.map((d) => d.denom_pub),
confirmSig, confirmSig,

117
src/db.ts
View File

@ -1,117 +0,0 @@
/*
This file is part of TALER
(C) 2016 GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
"use strict";
import {IExchangeInfo} from "./types";
/**
* Declarations and helpers for
* things that are stored in the wallet's
* database.
* @module Db
* @author Florian Dold
*/
const DB_NAME = "taler";
const DB_VERSION = 11;
import {Stores} from "./wallet";
import {Store, Index} from "./query";
/**
* Return a promise that resolves
* to the taler wallet db.
*/
export function openTalerDb(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const req = indexedDB.open(DB_NAME, DB_VERSION);
req.onerror = (e) => {
reject(e);
};
req.onsuccess = (e) => {
resolve(req.result);
};
req.onupgradeneeded = (e) => {
const db = req.result;
console.log("DB: upgrade needed: oldVersion = " + e.oldVersion);
switch (e.oldVersion) {
case 0: // DB does not exist yet
for (let n in Stores) {
if ((Stores as any)[n] instanceof Store) {
let si: Store<any> = (Stores as any)[n];
const s = db.createObjectStore(si.name, si.storeParams);
for (let indexName in (si as any)) {
if ((si as any)[indexName] instanceof Index) {
let ii: Index<any,any> = (si as any)[indexName];
s.createIndex(ii.indexName, ii.keyPath);
}
}
}
}
break;
default:
if (e.oldVersion != DB_VERSION) {
window.alert("Incompatible wallet dababase version, please reset" +
" db.");
chrome.browserAction.setBadgeText({text: "err"});
chrome.browserAction.setBadgeBackgroundColor({color: "#F00"});
throw Error("incompatible DB");
}
break;
}
};
});
}
export function exportDb(db: IDBDatabase): Promise<any> {
let dump = {
name: db.name,
version: db.version,
stores: {} as {[s: string]: any},
};
return new Promise((resolve, reject) => {
let tx = db.transaction(Array.from(db.objectStoreNames));
tx.addEventListener("complete", () => {
resolve(dump);
});
for (let i = 0; i < db.objectStoreNames.length; i++) {
let name = db.objectStoreNames[i];
let storeDump = {} as {[s: string]: any};
dump.stores[name] = storeDump;
let store = tx.objectStore(name)
.openCursor()
.addEventListener("success", (e: Event) => {
let cursor = (e.target as any).result;
if (cursor) {
storeDump[cursor.key] = cursor.value;
cursor.continue();
}
});
}
});
}
export function deleteDb() {
indexedDB.deleteDatabase(DB_NAME);
}

View File

@ -24,8 +24,8 @@
"use strict"; "use strict";
import {substituteFulfillmentUrl} from "src/helpers"; import {substituteFulfillmentUrl} from "src/helpers";
import {Contract, AmountJson, IExchangeInfo} from "src/types"; import {Contract, AmountJson, ExchangeRecord} from "src/types";
import {Offer} from "src/wallet"; import {OfferRecord} from "src/wallet";
import {renderContract, prettyAmount} from "src/renderHtml"; import {renderContract, prettyAmount} from "src/renderHtml";
import {getExchanges} from "src/wxApi"; import {getExchanges} from "src/wxApi";
@ -37,7 +37,7 @@ interface DetailState {
interface DetailProps { interface DetailProps {
contract: Contract contract: Contract
collapsed: boolean collapsed: boolean
exchanges: null|IExchangeInfo[]; exchanges: null|ExchangeRecord[];
} }
@ -78,7 +78,7 @@ class Details extends React.Component<DetailProps, DetailState> {
Exchanges in the wallet: Exchanges in the wallet:
<ul> <ul>
{(this.props.exchanges || []).map( {(this.props.exchanges || []).map(
(e: IExchangeInfo) => (e: ExchangeRecord) =>
<li>{`${e.baseUrl}: ${e.masterPublicKey}`}</li>)} <li>{`${e.baseUrl}: ${e.masterPublicKey}`}</li>)}
</ul> </ul>
</div> </div>
@ -92,10 +92,10 @@ interface ContractPromptProps {
} }
interface ContractPromptState { interface ContractPromptState {
offer: Offer|null; offer: OfferRecord|null;
error: string|null; error: string|null;
payDisabled: boolean; payDisabled: boolean;
exchanges: null|IExchangeInfo[]; exchanges: null|ExchangeRecord[];
} }
class ContractPrompt extends React.Component<ContractPromptProps, ContractPromptState> { class ContractPrompt extends React.Component<ContractPromptProps, ContractPromptState> {
@ -125,7 +125,7 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
this.setState({exchanges} as any); this.setState({exchanges} as any);
} }
getOffer(): Promise<Offer> { getOffer(): Promise<OfferRecord> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let msg = { let msg = {
type: 'get-offer', type: 'get-offer',

View File

@ -21,8 +21,8 @@
*/ */
import { IExchangeInfo } from "src/types"; import { ExchangeRecord } from "src/types";
import { ReserveRecord, Coin, PreCoin, Denomination } from "src/types"; import { ReserveRecord, CoinRecord, PreCoinRecord, Denomination } from "src/types";
import { ImplicitStateComponent, StateHolder } from "src/components"; import { ImplicitStateComponent, StateHolder } from "src/components";
import { import {
getReserves, getExchanges, getCoins, getPreCoins, getReserves, getExchanges, getCoins, getPreCoins,
@ -87,11 +87,11 @@ class Toggle extends ImplicitStateComponent<ToggleProps> {
interface CoinViewProps { interface CoinViewProps {
coin: Coin; coin: CoinRecord;
} }
interface RefreshDialogProps { interface RefreshDialogProps {
coin: Coin; coin: CoinRecord;
} }
class RefreshDialog extends ImplicitStateComponent<RefreshDialogProps> { class RefreshDialog extends ImplicitStateComponent<RefreshDialogProps> {
@ -134,7 +134,7 @@ class CoinView extends React.Component<CoinViewProps, void> {
interface PreCoinViewProps { interface PreCoinViewProps {
precoin: PreCoin; precoin: PreCoinRecord;
} }
class PreCoinView extends React.Component<PreCoinViewProps, void> { class PreCoinView extends React.Component<PreCoinViewProps, void> {
@ -155,7 +155,7 @@ interface CoinListProps {
} }
class CoinList extends ImplicitStateComponent<CoinListProps> { class CoinList extends ImplicitStateComponent<CoinListProps> {
coins = this.makeState<Coin[] | null>(null); coins = this.makeState<CoinRecord[] | null>(null);
expanded = this.makeState<boolean>(false); expanded = this.makeState<boolean>(false);
constructor(props: CoinListProps) { constructor(props: CoinListProps) {
@ -194,7 +194,7 @@ interface PreCoinListProps {
} }
class PreCoinList extends ImplicitStateComponent<PreCoinListProps> { class PreCoinList extends ImplicitStateComponent<PreCoinListProps> {
precoins = this.makeState<PreCoin[] | null>(null); precoins = this.makeState<PreCoinRecord[] | null>(null);
expanded = this.makeState<boolean>(false); expanded = this.makeState<boolean>(false);
constructor(props: PreCoinListProps) { constructor(props: PreCoinListProps) {
@ -224,7 +224,7 @@ class PreCoinList extends ImplicitStateComponent<PreCoinListProps> {
} }
interface DenominationListProps { interface DenominationListProps {
exchange: IExchangeInfo; exchange: ExchangeRecord;
} }
interface ExpanderTextProps { interface ExpanderTextProps {
@ -336,7 +336,7 @@ class ReserveList extends ImplicitStateComponent<ReserveListProps> {
} }
interface ExchangeProps { interface ExchangeProps {
exchange: IExchangeInfo; exchange: ExchangeRecord;
} }
class ExchangeView extends React.Component<ExchangeProps, void> { class ExchangeView extends React.Component<ExchangeProps, void> {
@ -358,7 +358,7 @@ class ExchangeView extends React.Component<ExchangeProps, void> {
} }
interface ExchangesListState { interface ExchangesListState {
exchanges?: IExchangeInfo[]; exchanges?: ExchangeRecord[];
} }
class ExchangesList extends React.Component<any, ExchangesListState> { class ExchangesList extends React.Component<any, ExchangesListState> {

View File

@ -132,7 +132,7 @@ export class Denomination {
} }
export interface IExchangeInfo { export interface ExchangeRecord {
baseUrl: string; baseUrl: string;
masterPublicKey: string; masterPublicKey: string;
@ -159,7 +159,7 @@ export interface WireInfo {
} }
export interface ReserveCreationInfo { export interface ReserveCreationInfo {
exchangeInfo: IExchangeInfo; exchangeInfo: ExchangeRecord;
wireInfo: WireInfo; wireInfo: WireInfo;
selectedDenoms: Denomination[]; selectedDenoms: Denomination[];
withdrawFee: AmountJson; withdrawFee: AmountJson;
@ -170,7 +170,7 @@ export interface ReserveCreationInfo {
/** /**
* A coin that isn't yet signed by an exchange. * A coin that isn't yet signed by an exchange.
*/ */
export interface PreCoin { export interface PreCoinRecord {
coinPub: string; coinPub: string;
coinPriv: string; coinPriv: string;
reservePub: string; reservePub: string;
@ -182,7 +182,7 @@ export interface PreCoin {
coinValue: AmountJson; coinValue: AmountJson;
} }
export interface RefreshPreCoin { export interface RefreshPreCoinRecord {
publicKey: string; publicKey: string;
privateKey: string; privateKey: string;
coinEv: string; coinEv: string;
@ -193,7 +193,7 @@ export interface RefreshPreCoin {
/** /**
* Ongoing refresh * Ongoing refresh
*/ */
export interface RefreshSession { export interface RefreshSessionRecord {
/** /**
* Public key that's being melted in this session. * Public key that's being melted in this session.
*/ */
@ -222,7 +222,7 @@ export interface RefreshSession {
newDenoms: string[]; newDenoms: string[];
preCoinsForGammas: RefreshPreCoin[][]; preCoinsForGammas: RefreshPreCoinRecord[][];
/** /**
@ -257,10 +257,10 @@ export interface CoinPaySig {
} }
/** /**
* Coin as stored in the "coins" data store * CoinRecord as stored in the "coins" data store
* of the wallet database. * of the wallet database.
*/ */
export interface Coin { export interface CoinRecord {
/** /**
* Public key of the coin. * Public key of the coin.
*/ */
@ -436,7 +436,7 @@ export class Contract {
} }
export type PayCoinInfo = Array<{ updatedCoin: Coin, sig: CoinPaySig }>; export type PayCoinInfo = Array<{ updatedCoin: CoinRecord, sig: CoinPaySig }>;
export namespace Amounts { export namespace Amounts {

View File

@ -25,17 +25,17 @@ import {
AmountJson, AmountJson,
Amounts, Amounts,
CheckRepurchaseResult, CheckRepurchaseResult,
Coin, CoinRecord,
CoinPaySig, CoinPaySig,
Contract, Contract,
CreateReserveResponse, CreateReserveResponse,
Denomination, Denomination,
ExchangeHandle, ExchangeHandle,
IExchangeInfo, ExchangeRecord,
Notifier, Notifier,
PayCoinInfo, PayCoinInfo,
PreCoin, PreCoinRecord,
RefreshSession, RefreshSessionRecord,
ReserveCreationInfo, ReserveCreationInfo,
ReserveRecord, ReserveRecord,
WalletBalance, WalletBalance,
@ -68,7 +68,7 @@ import {CryptoApi} from "./cryptoApi";
"use strict"; "use strict";
export interface CoinWithDenom { export interface CoinWithDenom {
coin: Coin; coin: CoinRecord;
denom: Denomination; denom: Denomination;
} }
@ -132,7 +132,7 @@ export class ConfirmReserveRequest {
@Checkable.Class @Checkable.Class
export class Offer { export class OfferRecord {
@Checkable.Value(Contract) @Checkable.Value(Contract)
contract: Contract; contract: Contract;
@ -151,7 +151,7 @@ export class Offer {
@Checkable.Optional(Checkable.Number) @Checkable.Optional(Checkable.Number)
id?: number; id?: number;
static checked: (obj: any) => Offer; static checked: (obj: any) => OfferRecord;
} }
export interface HistoryRecord { export interface HistoryRecord {
@ -163,10 +163,6 @@ export interface HistoryRecord {
} }
interface ExchangeCoins {
[exchangeUrl: string]: CoinWithDenom[];
}
interface PayReq { interface PayReq {
amount: AmountJson; amount: AmountJson;
coins: CoinPaySig[]; coins: CoinPaySig[];
@ -185,7 +181,7 @@ interface PayReq {
instance?: string; instance?: string;
} }
interface Transaction { interface TransactionRecord {
contractHash: string; contractHash: string;
contract: Contract; contract: Contract;
payReq: PayReq; payReq: PayReq;
@ -303,20 +299,20 @@ function getWithdrawDenomList(amountAvailable: AmountJson,
export namespace Stores { export namespace Stores {
class ExchangeStore extends Store<IExchangeInfo> { class ExchangeStore extends Store<ExchangeRecord> {
constructor() { constructor() {
super("exchanges", {keyPath: "baseUrl"}); super("exchanges", {keyPath: "baseUrl"});
} }
pubKeyIndex = new Index<string,IExchangeInfo>(this, "pubKey", "masterPublicKey"); pubKeyIndex = new Index<string,ExchangeRecord>(this, "pubKey", "masterPublicKey");
} }
class CoinsStore extends Store<Coin> { class CoinsStore extends Store<CoinRecord> {
constructor() { constructor() {
super("coins", {keyPath: "coinPub"}); super("coins", {keyPath: "coinPub"});
} }
exchangeBaseUrlIndex = new Index<string,Coin>(this, "exchangeBaseUrl", "exchangeBaseUrl"); exchangeBaseUrlIndex = new Index<string,CoinRecord>(this, "exchangeBaseUrl", "exchangeBaseUrl");
} }
class HistoryStore extends Store<HistoryRecord> { class HistoryStore extends Store<HistoryRecord> {
@ -330,7 +326,7 @@ export namespace Stores {
timestampIndex = new Index<number,HistoryRecord>(this, "timestamp", "timestamp"); timestampIndex = new Index<number,HistoryRecord>(this, "timestamp", "timestamp");
} }
class OffersStore extends Store<Offer> { class OffersStore extends Store<OfferRecord> {
constructor() { constructor() {
super("offers", { super("offers", {
keyPath: "id", keyPath: "id",
@ -339,12 +335,12 @@ export namespace Stores {
} }
} }
class TransactionsStore extends Store<Transaction> { class TransactionsStore extends Store<TransactionRecord> {
constructor() { constructor() {
super("transactions", {keyPath: "contractHash"}); super("transactions", {keyPath: "contractHash"});
} }
repurchaseIndex = new Index<[string,string],Transaction>(this, "repurchase", [ repurchaseIndex = new Index<[string,string],TransactionRecord>(this, "repurchase", [
"contract.merchant_pub", "contract.merchant_pub",
"contract.repurchase_correlation_id" "contract.repurchase_correlation_id"
]); ]);
@ -354,10 +350,10 @@ export namespace Stores {
export let transactions: TransactionsStore = new TransactionsStore(); export let transactions: TransactionsStore = new TransactionsStore();
export let reserves: Store<ReserveRecord> = new Store<ReserveRecord>("reserves", {keyPath: "reserve_pub"}); export let reserves: Store<ReserveRecord> = new Store<ReserveRecord>("reserves", {keyPath: "reserve_pub"});
export let coins: CoinsStore = new CoinsStore(); export let coins: CoinsStore = new CoinsStore();
export let refresh: Store<RefreshSession> = new Store<RefreshSession>("refresh", {keyPath: "meltCoinPub"}); export let refresh: Store<RefreshSessionRecord> = new Store<RefreshSessionRecord>("refresh", {keyPath: "meltCoinPub"});
export let history: HistoryStore = new HistoryStore(); export let history: HistoryStore = new HistoryStore();
export let offers: OffersStore = new OffersStore(); export let offers: OffersStore = new OffersStore();
export let precoins: Store<PreCoin> = new Store<PreCoin>("precoins", {keyPath: "coinPub"}); export let precoins: Store<PreCoinRecord> = new Store<PreCoinRecord>("precoins", {keyPath: "coinPub"});
} }
@ -442,14 +438,14 @@ export class Wallet {
this.q() this.q()
.iter(Stores.refresh) .iter(Stores.refresh)
.reduce((r: RefreshSession) => { .reduce((r: RefreshSessionRecord) => {
this.continueRefreshSession(r); this.continueRefreshSession(r);
}); });
// FIXME: optimize via index // FIXME: optimize via index
this.q() this.q()
.iter(Stores.coins) .iter(Stores.coins)
.reduce((c: Coin) => { .reduce((c: CoinRecord) => {
if (c.dirty && !c.transactionPending) { if (c.dirty && !c.transactionPending) {
this.refresh(c.coinPub); this.refresh(c.coinPub);
} }
@ -471,7 +467,7 @@ export class Wallet {
console.error("db inconsistent"); console.error("db inconsistent");
continue; continue;
} }
let coins: Coin[] = await this.q().iterIndex(Stores.coins.exchangeBaseUrlIndex, exchangeHandle.url).toArray(); let coins: CoinRecord[] = await this.q().iterIndex(Stores.coins.exchangeBaseUrlIndex, exchangeHandle.url).toArray();
if (!coins || coins.length == 0) { if (!coins || coins.length == 0) {
continue; continue;
} }
@ -515,7 +511,7 @@ export class Wallet {
* Record all information that is necessary to * Record all information that is necessary to
* pay for a contract in the wallet's database. * pay for a contract in the wallet's database.
*/ */
private async recordConfirmPay(offer: Offer, private async recordConfirmPay(offer: OfferRecord,
payCoinInfo: PayCoinInfo, payCoinInfo: PayCoinInfo,
chosenExchange: string): Promise<void> { chosenExchange: string): Promise<void> {
let payReq: PayReq = { let payReq: PayReq = {
@ -531,7 +527,7 @@ export class Wallet {
transaction_id: offer.contract.transaction_id, transaction_id: offer.contract.transaction_id,
instance: offer.contract.merchant.instance instance: offer.contract.merchant.instance
}; };
let t: Transaction = { let t: TransactionRecord = {
contractHash: offer.H_contract, contractHash: offer.H_contract,
contract: offer.contract, contract: offer.contract,
payReq: payReq, payReq: payReq,
@ -568,7 +564,7 @@ export class Wallet {
} }
async saveOffer(offer: Offer): Promise<number> { async saveOffer(offer: OfferRecord): Promise<number> {
console.log(`saving offer in wallet.ts`); console.log(`saving offer in wallet.ts`);
let id = await this.q().putWithResult(Stores.offers, offer); let id = await this.q().putWithResult(Stores.offers, offer);
this.notifier.notify(); this.notifier.notify();
@ -584,7 +580,7 @@ export class Wallet {
* Add a contract to the wallet and sign coins, * Add a contract to the wallet and sign coins,
* but do not send them yet. * but do not send them yet.
*/ */
async confirmPay(offer: Offer): Promise<any> { async confirmPay(offer: OfferRecord): Promise<any> {
console.log("executing confirmPay"); console.log("executing confirmPay");
let transaction = await this.q().get(Stores.transactions, offer.H_contract); let transaction = await this.q().get(Stores.transactions, offer.H_contract);
@ -618,7 +614,7 @@ export class Wallet {
* Add a contract to the wallet and sign coins, * Add a contract to the wallet and sign coins,
* but do not send them yet. * but do not send them yet.
*/ */
async checkPay(offer: Offer): Promise<any> { async checkPay(offer: OfferRecord): Promise<any> {
// First check if we already payed for it. // First check if we already payed for it.
let transaction = await this.q().get(Stores.transactions, offer.H_contract); let transaction = await this.q().get(Stores.transactions, offer.H_contract);
if (transaction) { if (transaction) {
@ -645,7 +641,7 @@ export class Wallet {
* with the given hash. * with the given hash.
*/ */
async executePayment(H_contract: string): Promise<any> { async executePayment(H_contract: string): Promise<any> {
let t = await this.q().get<Transaction>(Stores.transactions, H_contract); let t = await this.q().get<TransactionRecord>(Stores.transactions, H_contract);
if (!t) { if (!t) {
return { return {
success: false, success: false,
@ -704,7 +700,7 @@ export class Wallet {
} }
private async processPreCoin(preCoin: PreCoin, private async processPreCoin(preCoin: PreCoinRecord,
retryDelayMs = 100): Promise<void> { retryDelayMs = 100): Promise<void> {
let exchange = await this.q().get(Stores.exchanges, let exchange = await this.q().get(Stores.exchanges,
@ -852,7 +848,7 @@ export class Wallet {
} }
private async withdrawExecute(pc: PreCoin): Promise<Coin> { private async withdrawExecute(pc: PreCoinRecord): Promise<CoinRecord> {
let reserve = await this.q().get<ReserveRecord>(Stores.reserves, let reserve = await this.q().get<ReserveRecord>(Stores.reserves,
pc.reservePub); pc.reservePub);
@ -879,7 +875,7 @@ export class Wallet {
let denomSig = await this.cryptoApi.rsaUnblind(r.ev_sig, let denomSig = await this.cryptoApi.rsaUnblind(r.ev_sig,
pc.blindingKey, pc.blindingKey,
pc.denomPub); pc.denomPub);
let coin: Coin = { let coin: CoinRecord = {
coinPub: pc.coinPub, coinPub: pc.coinPub,
coinPriv: pc.coinPriv, coinPriv: pc.coinPriv,
denomPub: pc.denomPub, denomPub: pc.denomPub,
@ -897,7 +893,7 @@ export class Wallet {
* Withdraw coins from a reserve until it is empty. * Withdraw coins from a reserve until it is empty.
*/ */
private async depleteReserve(reserve: ReserveRecord, private async depleteReserve(reserve: ReserveRecord,
exchange: IExchangeInfo): Promise<number> { exchange: ExchangeRecord): Promise<number> {
if (!reserve.current_amount) { if (!reserve.current_amount) {
throw Error("can't withdraw when amount is unknown"); throw Error("can't withdraw when amount is unknown");
} }
@ -947,7 +943,7 @@ export class Wallet {
* by quering the reserve's exchange. * by quering the reserve's exchange.
*/ */
private async updateReserve(reservePub: string, private async updateReserve(reservePub: string,
exchange: IExchangeInfo): Promise<ReserveRecord> { exchange: ExchangeRecord): Promise<ReserveRecord> {
let reserve = await this.q() let reserve = await this.q()
.get<ReserveRecord>(Stores.reserves, reservePub); .get<ReserveRecord>(Stores.reserves, reservePub);
if (!reserve) { if (!reserve) {
@ -1037,7 +1033,7 @@ export class Wallet {
* Optionally link the reserve entry to the new or existing * Optionally link the reserve entry to the new or existing
* exchange entry in then DB. * exchange entry in then DB.
*/ */
async updateExchangeFromUrl(baseUrl: string): Promise<IExchangeInfo> { async updateExchangeFromUrl(baseUrl: string): Promise<ExchangeRecord> {
baseUrl = canonicalizeBaseUrl(baseUrl); baseUrl = canonicalizeBaseUrl(baseUrl);
let reqUrl = URI("keys").absoluteTo(baseUrl); let reqUrl = URI("keys").absoluteTo(baseUrl);
let resp = await this.http.get(reqUrl); let resp = await this.http.get(reqUrl);
@ -1048,11 +1044,11 @@ export class Wallet {
return this.updateExchangeFromJson(baseUrl, exchangeKeysJson); return this.updateExchangeFromJson(baseUrl, exchangeKeysJson);
} }
private async suspendCoins(exchangeInfo: IExchangeInfo): Promise<void> { private async suspendCoins(exchangeInfo: ExchangeRecord): Promise<void> {
let suspendedCoins = await ( let suspendedCoins = await (
this.q() this.q()
.iterIndex(Stores.coins.exchangeBaseUrlIndex, exchangeInfo.baseUrl) .iterIndex(Stores.coins.exchangeBaseUrlIndex, exchangeInfo.baseUrl)
.reduce((coin: Coin, suspendedCoins: Coin[]) => { .reduce((coin: CoinRecord, suspendedCoins: CoinRecord[]) => {
if (!exchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) { if (!exchangeInfo.active_denoms.find((c) => c.denom_pub == coin.denomPub)) {
return Array.prototype.concat(suspendedCoins, [coin]); return Array.prototype.concat(suspendedCoins, [coin]);
} }
@ -1070,15 +1066,15 @@ export class Wallet {
private async updateExchangeFromJson(baseUrl: string, private async updateExchangeFromJson(baseUrl: string,
exchangeKeysJson: KeysJson): Promise<IExchangeInfo> { exchangeKeysJson: KeysJson): Promise<ExchangeRecord> {
const updateTimeSec = getTalerStampSec(exchangeKeysJson.list_issue_date); const updateTimeSec = getTalerStampSec(exchangeKeysJson.list_issue_date);
if (updateTimeSec === null) { if (updateTimeSec === null) {
throw Error("invalid update time"); throw Error("invalid update time");
} }
let r = await this.q().get<IExchangeInfo>(Stores.exchanges, baseUrl); let r = await this.q().get<ExchangeRecord>(Stores.exchanges, baseUrl);
let exchangeInfo: IExchangeInfo; let exchangeInfo: ExchangeRecord;
if (!r) { if (!r) {
exchangeInfo = { exchangeInfo = {
@ -1110,8 +1106,8 @@ export class Wallet {
} }
private async updateExchangeInfo(exchangeInfo: IExchangeInfo, private async updateExchangeInfo(exchangeInfo: ExchangeRecord,
newKeys: KeysJson): Promise<IExchangeInfo> { newKeys: KeysJson): Promise<ExchangeRecord> {
if (exchangeInfo.masterPublicKey != newKeys.master_public_key) { if (exchangeInfo.masterPublicKey != newKeys.master_public_key) {
throw Error("public keys do not match"); throw Error("public keys do not match");
} }
@ -1186,7 +1182,7 @@ export class Wallet {
return entry; return entry;
} }
function collectBalances(c: Coin, balance: WalletBalance) { function collectBalances(c: CoinRecord, balance: WalletBalance) {
if (c.suspended) { if (c.suspended) {
return balance; return balance;
} }
@ -1213,7 +1209,7 @@ export class Wallet {
return balance; return balance;
} }
function collectPendingRefresh(r: RefreshSession, balance: WalletBalance) { function collectPendingRefresh(r: RefreshSessionRecord, balance: WalletBalance) {
if (!r.finished) { if (!r.finished) {
return balance; return balance;
} }
@ -1224,7 +1220,7 @@ export class Wallet {
return balance; return balance;
} }
function collectPayments(t: Transaction, balance: WalletBalance) { function collectPayments(t: TransactionRecord, balance: WalletBalance) {
if (t.finished) { if (t.finished) {
return balance; return balance;
} }
@ -1235,7 +1231,7 @@ export class Wallet {
return balance; return balance;
} }
function collectSmallestWithdraw(e: IExchangeInfo, sw: any) { function collectSmallestWithdraw(e: ExchangeRecord, sw: any) {
let min: AmountJson|undefined; let min: AmountJson|undefined;
for (let d of e.active_denoms) { for (let d of e.active_denoms) {
let v = Amounts.add(d.value, d.fee_withdraw).amount; let v = Amounts.add(d.value, d.fee_withdraw).amount;
@ -1277,8 +1273,8 @@ export class Wallet {
} }
async createRefreshSession(oldCoinPub: string): Promise<RefreshSession|undefined> { async createRefreshSession(oldCoinPub: string): Promise<RefreshSessionRecord|undefined> {
let coin = await this.q().get<Coin>(Stores.coins, oldCoinPub); let coin = await this.q().get<CoinRecord>(Stores.coins, oldCoinPub);
if (!coin) { if (!coin) {
throw Error("coin not found"); throw Error("coin not found");
@ -1312,14 +1308,14 @@ export class Wallet {
} }
let refreshSession: RefreshSession = await ( let refreshSession: RefreshSessionRecord = await (
this.cryptoApi.createRefreshSession(exchange.baseUrl, this.cryptoApi.createRefreshSession(exchange.baseUrl,
3, 3,
coin, coin,
newCoinDenoms, newCoinDenoms,
oldDenom.fee_refresh)); oldDenom.fee_refresh));
function mutateCoin(c: Coin): Coin { function mutateCoin(c: CoinRecord): CoinRecord {
let r = Amounts.sub(c.currentAmount, let r = Amounts.sub(c.currentAmount,
refreshSession.valueWithFee); refreshSession.valueWithFee);
if (r.saturated) { if (r.saturated) {
@ -1340,7 +1336,7 @@ export class Wallet {
async refresh(oldCoinPub: string): Promise<void> { async refresh(oldCoinPub: string): Promise<void> {
let refreshSession: RefreshSession|undefined; let refreshSession: RefreshSessionRecord|undefined;
let oldSession = await this.q().get(Stores.refresh, oldCoinPub); let oldSession = await this.q().get(Stores.refresh, oldCoinPub);
if (oldSession) { if (oldSession) {
refreshSession = oldSession; refreshSession = oldSession;
@ -1354,14 +1350,14 @@ export class Wallet {
this.continueRefreshSession(refreshSession); this.continueRefreshSession(refreshSession);
} }
async continueRefreshSession(refreshSession: RefreshSession) { async continueRefreshSession(refreshSession: RefreshSessionRecord) {
if (refreshSession.finished) { if (refreshSession.finished) {
return; return;
} }
if (typeof refreshSession.norevealIndex !== "number") { if (typeof refreshSession.norevealIndex !== "number") {
let coinPub = refreshSession.meltCoinPub; let coinPub = refreshSession.meltCoinPub;
await this.refreshMelt(refreshSession); await this.refreshMelt(refreshSession);
let r = await this.q().get<RefreshSession>(Stores.refresh, coinPub); let r = await this.q().get<RefreshSessionRecord>(Stores.refresh, coinPub);
if (!r) { if (!r) {
throw Error("refresh session does not exist anymore"); throw Error("refresh session does not exist anymore");
} }
@ -1372,14 +1368,14 @@ export class Wallet {
} }
async refreshMelt(refreshSession: RefreshSession): Promise<void> { async refreshMelt(refreshSession: RefreshSessionRecord): Promise<void> {
if (refreshSession.norevealIndex != undefined) { if (refreshSession.norevealIndex != undefined) {
console.error("won't melt again"); console.error("won't melt again");
return; return;
} }
let coin = await this.q().get<Coin>(Stores.coins, let coin = await this.q().get<CoinRecord>(Stores.coins,
refreshSession.meltCoinPub); refreshSession.meltCoinPub);
if (!coin) { if (!coin) {
console.error("can't melt coin, it does not exist"); console.error("can't melt coin, it does not exist");
return; return;
@ -1429,7 +1425,7 @@ export class Wallet {
} }
async refreshReveal(refreshSession: RefreshSession): Promise<void> { async refreshReveal(refreshSession: RefreshSessionRecord): Promise<void> {
let norevealIndex = refreshSession.norevealIndex; let norevealIndex = refreshSession.norevealIndex;
if (norevealIndex == undefined) { if (norevealIndex == undefined) {
throw Error("can't reveal without melting first"); throw Error("can't reveal without melting first");
@ -1461,14 +1457,14 @@ export class Wallet {
console.log("/refresh/reveal did not contain ev_sigs"); console.log("/refresh/reveal did not contain ev_sigs");
} }
let exchange = await this.q().get<IExchangeInfo>(Stores.exchanges, let exchange = await this.q().get<ExchangeRecord>(Stores.exchanges,
refreshSession.exchangeBaseUrl); refreshSession.exchangeBaseUrl);
if (!exchange) { if (!exchange) {
console.error(`exchange ${refreshSession.exchangeBaseUrl} not found`); console.error(`exchange ${refreshSession.exchangeBaseUrl} not found`);
return; return;
} }
let coins: Coin[] = []; let coins: CoinRecord[] = [];
for (let i = 0; i < respJson.ev_sigs.length; i++) { for (let i = 0; i < respJson.ev_sigs.length; i++) {
let denom = exchange.all_denoms.find((d) => d.denom_pub == refreshSession.newDenoms[i]); let denom = exchange.all_denoms.find((d) => d.denom_pub == refreshSession.newDenoms[i]);
@ -1480,7 +1476,7 @@ export class Wallet {
let denomSig = await this.cryptoApi.rsaUnblind(respJson.ev_sigs[i].ev_sig, let denomSig = await this.cryptoApi.rsaUnblind(respJson.ev_sigs[i].ev_sig,
pc.blindingKey, pc.blindingKey,
denom.denom_pub); denom.denom_pub);
let coin: Coin = { let coin: CoinRecord = {
coinPub: pc.publicKey, coinPub: pc.publicKey,
coinPriv: pc.privateKey, coinPriv: pc.privateKey,
denomPub: denom.denom_pub, denomPub: denom.denom_pub,
@ -1526,9 +1522,9 @@ export class Wallet {
return offer; return offer;
} }
async getExchanges(): Promise<IExchangeInfo[]> { async getExchanges(): Promise<ExchangeRecord[]> {
return this.q() return this.q()
.iter<IExchangeInfo>(Stores.exchanges) .iter<ExchangeRecord>(Stores.exchanges)
.flatMap((e) => [e]) .flatMap((e) => [e])
.toArray(); .toArray();
} }
@ -1540,17 +1536,17 @@ export class Wallet {
.toArray(); .toArray();
} }
async getCoins(exchangeBaseUrl: string): Promise<Coin[]> { async getCoins(exchangeBaseUrl: string): Promise<CoinRecord[]> {
return this.q() return this.q()
.iter<Coin>(Stores.coins) .iter<CoinRecord>(Stores.coins)
.filter((c: Coin) => c.exchangeBaseUrl === exchangeBaseUrl) .filter((c: CoinRecord) => c.exchangeBaseUrl === exchangeBaseUrl)
.toArray(); .toArray();
} }
async getPreCoins(exchangeBaseUrl: string): Promise<PreCoin[]> { async getPreCoins(exchangeBaseUrl: string): Promise<PreCoinRecord[]> {
return this.q() return this.q()
.iter<PreCoin>(Stores.precoins) .iter<PreCoinRecord>(Stores.precoins)
.filter((c: PreCoin) => c.exchangeBaseUrl === exchangeBaseUrl) .filter((c: PreCoinRecord) => c.exchangeBaseUrl === exchangeBaseUrl)
.toArray(); .toArray();
} }
@ -1566,7 +1562,7 @@ export class Wallet {
console.log("no repurchase: no correlation id"); console.log("no repurchase: no correlation id");
return {isRepurchase: false}; return {isRepurchase: false};
} }
let result: Transaction|undefined = await ( let result: TransactionRecord|undefined = await (
this.q() this.q()
.getIndexed(Stores.transactions.repurchaseIndex, .getIndexed(Stores.transactions.repurchaseIndex,
[ [
@ -1589,16 +1585,16 @@ export class Wallet {
async paymentSucceeded(contractHash: string): Promise<any> { async paymentSucceeded(contractHash: string): Promise<any> {
const doPaymentSucceeded = async() => { const doPaymentSucceeded = async() => {
let t = await this.q().get<Transaction>(Stores.transactions, let t = await this.q().get<TransactionRecord>(Stores.transactions,
contractHash); contractHash);
if (!t) { if (!t) {
console.error("contract not found"); console.error("contract not found");
return; return;
} }
t.finished = true; t.finished = true;
let modifiedCoins: Coin[] = []; let modifiedCoins: CoinRecord[] = [];
for (let pc of t.payReq.coins) { for (let pc of t.payReq.coins) {
let c = await this.q().get<Coin>(Stores.coins, pc.coin_pub); let c = await this.q().get<CoinRecord>(Stores.coins, pc.coin_pub);
if (!c) { if (!c) {
console.error("coin not found"); console.error("coin not found");
return; return;

View File

@ -16,10 +16,10 @@
import { import {
AmountJson, AmountJson,
Coin, CoinRecord,
PreCoin, PreCoinRecord,
ReserveCreationInfo, ReserveCreationInfo,
IExchangeInfo, ExchangeRecord,
ReserveRecord ReserveRecord
} from "./types"; } from "./types";
@ -47,14 +47,14 @@ export function getReserveCreationInfo(baseUrl: string,
} }
export async function callBackend(type: string, detail?: any): Promise<any> { export async function callBackend(type: string, detail?: any): Promise<any> {
return new Promise<IExchangeInfo[]>((resolve, reject) => { return new Promise<ExchangeRecord[]>((resolve, reject) => {
chrome.runtime.sendMessage({ type, detail }, (resp) => { chrome.runtime.sendMessage({ type, detail }, (resp) => {
resolve(resp); resolve(resp);
}); });
}); });
} }
export async function getExchanges(): Promise<IExchangeInfo[]> { export async function getExchanges(): Promise<ExchangeRecord[]> {
return await callBackend("get-exchanges"); return await callBackend("get-exchanges");
} }
@ -62,11 +62,11 @@ export async function getReserves(exchangeBaseUrl: string): Promise<ReserveRecor
return await callBackend("get-reserves", { exchangeBaseUrl }); return await callBackend("get-reserves", { exchangeBaseUrl });
} }
export async function getCoins(exchangeBaseUrl: string): Promise<Coin[]> { export async function getCoins(exchangeBaseUrl: string): Promise<CoinRecord[]> {
return await callBackend("get-coins", { exchangeBaseUrl }); return await callBackend("get-coins", { exchangeBaseUrl });
} }
export async function getPreCoins(exchangeBaseUrl: string): Promise<PreCoin[]> { export async function getPreCoins(exchangeBaseUrl: string): Promise<PreCoinRecord[]> {
return await callBackend("get-precoins", { exchangeBaseUrl }); return await callBackend("get-precoins", { exchangeBaseUrl });
} }

View File

@ -17,12 +17,11 @@
import { import {
Wallet, Wallet,
Offer, OfferRecord,
Badge, Badge,
ConfirmReserveRequest, ConfirmReserveRequest,
CreateReserveRequest CreateReserveRequest
} from "./wallet"; } from "./wallet";
import { deleteDb, exportDb, openTalerDb } from "./db";
import { BrowserHttpLib } from "./http"; import { BrowserHttpLib } from "./http";
import { Checkable } from "./checkable"; import { Checkable } from "./checkable";
import { AmountJson } from "./types"; import { AmountJson } from "./types";
@ -34,6 +33,12 @@ import { ChromeBadge } from "./chromeBadge";
"use strict"; "use strict";
const DB_NAME = "taler";
const DB_VERSION = 11;
import {Stores} from "./wallet";
import {Store, Index} from "./query";
/** /**
* Messaging for the WebExtensions wallet. Should contain * Messaging for the WebExtensions wallet. Should contain
* parts that are specific for WebExtensions, but as little business * parts that are specific for WebExtensions, but as little business
@ -97,9 +102,9 @@ function makeHandlers(db: IDBDatabase,
return wallet.confirmReserve(req); return wallet.confirmReserve(req);
}, },
["confirm-pay"]: function (detail, sender) { ["confirm-pay"]: function (detail, sender) {
let offer: Offer; let offer: OfferRecord;
try { try {
offer = Offer.checked(detail.offer); offer = OfferRecord.checked(detail.offer);
} catch (e) { } catch (e) {
if (e instanceof Checkable.SchemaError) { if (e instanceof Checkable.SchemaError) {
console.error("schema error:", e.message); console.error("schema error:", e.message);
@ -116,9 +121,9 @@ function makeHandlers(db: IDBDatabase,
return wallet.confirmPay(offer); return wallet.confirmPay(offer);
}, },
["check-pay"]: function (detail, sender) { ["check-pay"]: function (detail, sender) {
let offer: Offer; let offer: OfferRecord;
try { try {
offer = Offer.checked(detail.offer); offer = OfferRecord.checked(detail.offer);
} catch (e) { } catch (e) {
if (e instanceof Checkable.SchemaError) { if (e instanceof Checkable.SchemaError) {
console.error("schema error:", e.message); console.error("schema error:", e.message);
@ -437,3 +442,86 @@ export function wxMain() {
console.error(e); console.error(e);
}); });
} }
/**
* Return a promise that resolves
* to the taler wallet db.
*/
function openTalerDb(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const req = indexedDB.open(DB_NAME, DB_VERSION);
req.onerror = (e) => {
reject(e);
};
req.onsuccess = (e) => {
resolve(req.result);
};
req.onupgradeneeded = (e) => {
const db = req.result;
console.log("DB: upgrade needed: oldVersion = " + e.oldVersion);
switch (e.oldVersion) {
case 0: // DB does not exist yet
for (let n in Stores) {
if ((Stores as any)[n] instanceof Store) {
let si: Store<any> = (Stores as any)[n];
const s = db.createObjectStore(si.name, si.storeParams);
for (let indexName in (si as any)) {
if ((si as any)[indexName] instanceof Index) {
let ii: Index<any,any> = (si as any)[indexName];
s.createIndex(ii.indexName, ii.keyPath);
}
}
}
}
break;
default:
if (e.oldVersion != DB_VERSION) {
window.alert("Incompatible wallet dababase version, please reset" +
" db.");
chrome.browserAction.setBadgeText({text: "err"});
chrome.browserAction.setBadgeBackgroundColor({color: "#F00"});
throw Error("incompatible DB");
}
break;
}
};
});
}
function exportDb(db: IDBDatabase): Promise<any> {
let dump = {
name: db.name,
version: db.version,
stores: {} as {[s: string]: any},
};
return new Promise((resolve, reject) => {
let tx = db.transaction(Array.from(db.objectStoreNames));
tx.addEventListener("complete", () => {
resolve(dump);
});
for (let i = 0; i < db.objectStoreNames.length; i++) {
let name = db.objectStoreNames[i];
let storeDump = {} as {[s: string]: any};
dump.stores[name] = storeDump;
let store = tx.objectStore(name)
.openCursor()
.addEventListener("success", (e: Event) => {
let cursor = (e.target as any).result;
if (cursor) {
storeDump[cursor.key] = cursor.value;
cursor.continue();
}
});
}
});
}
function deleteDb() {
indexedDB.deleteDatabase(DB_NAME);
}

View File

@ -16,20 +16,19 @@
"src/checkable.ts", "src/checkable.ts",
"decl/lib.es6.d.ts", "decl/lib.es6.d.ts",
"src/chromeBadge.ts", "src/chromeBadge.ts",
"decl/urijs/URIjs.d.ts",
"src/cryptoApi-test.ts", "src/cryptoApi-test.ts",
"decl/urijs/URIjs.d.ts",
"src/components.ts", "src/components.ts",
"decl/systemjs/systemjs.d.ts",
"src/emscriptif-test.ts", "src/emscriptif-test.ts",
"decl/systemjs/systemjs.d.ts",
"src/cryptoApi.ts", "src/cryptoApi.ts",
"decl/react-global.d.ts",
"src/helpers-test.ts", "src/helpers-test.ts",
"decl/react-global.d.ts",
"src/cryptoLib.ts", "src/cryptoLib.ts",
"src/types-test.ts", "src/types-test.ts",
"decl/chrome/chrome.d.ts", "decl/chrome/chrome.d.ts",
"src/cryptoWorker.ts", "src/cryptoWorker.ts",
"src/wallet-test.ts", "src/wallet-test.ts",
"src/db.ts",
"src/emscriptif.ts", "src/emscriptif.ts",
"src/helpers.ts", "src/helpers.ts",
"src/http.ts", "src/http.ts",
@ -39,7 +38,7 @@
"src/types.ts", "src/types.ts",
"src/wallet.ts", "src/wallet.ts",
"src/wxApi.ts", "src/wxApi.ts",
"src/wxMessaging.ts", "src/wxBackend.ts",
"src/renderHtml.tsx", "src/renderHtml.tsx",
"src/background/background.ts", "src/background/background.ts",
"src/content_scripts/notify.ts", "src/content_scripts/notify.ts",