fix messaging, small issues and safer types

This commit is contained in:
Florian Dold 2017-05-31 16:04:14 +02:00
parent 7e5ddf3a45
commit 613a14c14f
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
15 changed files with 311 additions and 361 deletions

View File

@ -27,7 +27,7 @@ import {
AmountJson,
CoinRecord,
DenominationRecord,
OfferRecord,
ProposalRecord,
PayCoinInfo,
PaybackRequest,
PreCoinRecord,
@ -277,9 +277,9 @@ export class CryptoApi {
return this.doRpc<PayCoinInfo>("isValidPaymentSignature", 1, sig, contractHash, merchantPub);
}
signDeposit(offer: OfferRecord,
signDeposit(proposal: ProposalRecord,
cds: CoinWithDenom[]): Promise<PayCoinInfo> {
return this.doRpc<PayCoinInfo>("signDeposit", 3, offer, cds);
return this.doRpc<PayCoinInfo>("signDeposit", 3, proposal, cds);
}
createEddsaKeypair(): Promise<{priv: string, pub: string}> {

View File

@ -29,7 +29,7 @@ import {
CoinRecord,
CoinStatus,
DenominationRecord,
OfferRecord,
ProposalRecord,
PayCoinInfo,
PaybackRequest,
PreCoinRecord,
@ -227,7 +227,7 @@ namespace RpcFunctions {
* Generate updated coins (to store in the database)
* and deposit permissions for each given coin.
*/
export function signDeposit(offer: OfferRecord,
export function signDeposit(proposal: ProposalRecord,
cds: CoinWithDenom[]): PayCoinInfo {
const ret: PayCoinInfo = [];
@ -235,8 +235,8 @@ namespace RpcFunctions {
const feeList: AmountJson[] = cds.map((x) => x.denom.feeDeposit);
let fees = Amounts.add(Amounts.getZero(feeList[0].currency), ...feeList).amount;
// okay if saturates
fees = Amounts.sub(fees, offer.contract.max_fee).amount;
const total = Amounts.add(fees, offer.contract.amount).amount;
fees = Amounts.sub(fees, proposal.contractTerms.max_fee).amount;
const total = Amounts.add(fees, proposal.contractTerms.amount).amount;
const amountSpent = native.Amount.getZero(cds[0].coin.currentAmount.currency);
const amountRemaining = new native.Amount(total);
@ -273,11 +273,11 @@ namespace RpcFunctions {
amount_with_fee: coinSpend.toNbo(),
coin_pub: native.EddsaPublicKey.fromCrock(cd.coin.coinPub),
deposit_fee: new native.Amount(cd.denom.feeDeposit).toNbo(),
h_contract: native.HashCode.fromCrock(offer.H_contract),
h_wire: native.HashCode.fromCrock(offer.contract.H_wire),
merchant: native.EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
refund_deadline: native.AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
timestamp: native.AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
h_contract: native.HashCode.fromCrock(proposal.contractTermsHash),
h_wire: native.HashCode.fromCrock(proposal.contractTerms.H_wire),
merchant: native.EddsaPublicKey.fromCrock(proposal.contractTerms.merchant_pub),
refund_deadline: native.AbsoluteTimeNbo.fromTalerString(proposal.contractTerms.refund_deadline),
timestamp: native.AbsoluteTimeNbo.fromTalerString(proposal.contractTerms.timestamp),
});
const coinSig = native.eddsaSign(d.toPurpose(),

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:"
msgstr ""
#: src/webex/pages/confirm-contract.tsx:146
#: src/webex/pages/confirm-contract.tsx:141
#, c-format
msgid "You have insufficient funds of the requested currency in your wallet."
msgstr ""
#. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:148
#: src/webex/pages/confirm-contract.tsx:143
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@ -193,90 +193,90 @@ msgstr ""
msgid "Fatal error: \"%1$s\"."
msgstr ""
#: src/webex/pages/popup.tsx:163
#: src/webex/pages/popup.tsx:161
#, c-format
msgid "Balance"
msgstr "Saldo"
#: src/webex/pages/popup.tsx:166
#: src/webex/pages/popup.tsx:164
#, c-format
msgid "History"
msgstr "Verlauf"
#: src/webex/pages/popup.tsx:169
#: src/webex/pages/popup.tsx:167
#, c-format
msgid "Debug"
msgstr "Debug"
#: src/webex/pages/popup.tsx:245
#: src/webex/pages/popup.tsx:243
#, c-format
msgid "help"
msgstr ""
#: src/webex/pages/popup.tsx:250
#: src/webex/pages/popup.tsx:248
#, fuzzy, c-format
msgid ""
"You have no balance to show. Need some\n"
" %1$s getting started?\n"
msgstr "Sie haben kein Digitalgeld. Wollen Sie %1$s? abheben?"
#: src/webex/pages/popup.tsx:267
#: src/webex/pages/popup.tsx:265
#, c-format
msgid "%1$s incoming\n"
msgstr ""
#: src/webex/pages/popup.tsx:280
#: src/webex/pages/popup.tsx:278
#, c-format
msgid "%1$s being spent\n"
msgstr ""
#: src/webex/pages/popup.tsx:306
#: src/webex/pages/popup.tsx:304
#, c-format
msgid "Error: could not retrieve balance information."
msgstr ""
#: src/webex/pages/popup.tsx:345
#: src/webex/pages/popup.tsx:343
#, fuzzy, c-format
msgid ""
"Bank requested reserve (%1$s) for\n"
" %2$s.\n"
msgstr "Bank bestätig anlegen der Reserve (%1$s) bei %2$s"
#: src/webex/pages/popup.tsx:356
#: src/webex/pages/popup.tsx:354
#, fuzzy, c-format
msgid ""
"Started to withdraw\n"
" %1$s from%2$s(%3$s).\n"
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
#: src/webex/pages/popup.tsx:366
#: src/webex/pages/popup.tsx:364
#, c-format
msgid "Merchant%1$soffered contract%2$s;\n"
msgstr ""
#: src/webex/pages/popup.tsx:376
#: src/webex/pages/popup.tsx:374
#, fuzzy, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
#: src/webex/pages/popup.tsx:386
#: src/webex/pages/popup.tsx:384
#, fuzzy, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
#: src/webex/pages/popup.tsx:395
#: src/webex/pages/popup.tsx:393
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
#: src/webex/pages/popup.tsx:438
#: src/webex/pages/popup.tsx:436
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
#: src/webex/pages/popup.tsx:472
#: src/webex/pages/popup.tsx:470
#, c-format
msgid "Your wallet has no events recorded."
msgstr "Ihre Geldbörse verzeichnet keine Vorkommnisse."

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:"
msgstr ""
#: src/webex/pages/confirm-contract.tsx:146
#: src/webex/pages/confirm-contract.tsx:141
#, c-format
msgid "You have insufficient funds of the requested currency in your wallet."
msgstr ""
#. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:148
#: src/webex/pages/confirm-contract.tsx:143
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@ -193,90 +193,90 @@ msgstr ""
msgid "Fatal error: \"%1$s\"."
msgstr ""
#: src/webex/pages/popup.tsx:163
#: src/webex/pages/popup.tsx:161
#, c-format
msgid "Balance"
msgstr ""
#: src/webex/pages/popup.tsx:166
#: src/webex/pages/popup.tsx:164
#, c-format
msgid "History"
msgstr ""
#: src/webex/pages/popup.tsx:169
#: src/webex/pages/popup.tsx:167
#, c-format
msgid "Debug"
msgstr ""
#: src/webex/pages/popup.tsx:245
#: src/webex/pages/popup.tsx:243
#, c-format
msgid "help"
msgstr ""
#: src/webex/pages/popup.tsx:250
#: src/webex/pages/popup.tsx:248
#, c-format
msgid ""
"You have no balance to show. Need some\n"
" %1$s getting started?\n"
msgstr ""
#: src/webex/pages/popup.tsx:267
#: src/webex/pages/popup.tsx:265
#, c-format
msgid "%1$s incoming\n"
msgstr ""
#: src/webex/pages/popup.tsx:280
#: src/webex/pages/popup.tsx:278
#, c-format
msgid "%1$s being spent\n"
msgstr ""
#: src/webex/pages/popup.tsx:306
#: src/webex/pages/popup.tsx:304
#, c-format
msgid "Error: could not retrieve balance information."
msgstr ""
#: src/webex/pages/popup.tsx:345
#: src/webex/pages/popup.tsx:343
#, c-format
msgid ""
"Bank requested reserve (%1$s) for\n"
" %2$s.\n"
msgstr ""
#: src/webex/pages/popup.tsx:356
#: src/webex/pages/popup.tsx:354
#, c-format
msgid ""
"Started to withdraw\n"
" %1$s from%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:366
#: src/webex/pages/popup.tsx:364
#, c-format
msgid "Merchant%1$soffered contract%2$s;\n"
msgstr ""
#: src/webex/pages/popup.tsx:376
#: src/webex/pages/popup.tsx:374
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:386
#: src/webex/pages/popup.tsx:384
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
#: src/webex/pages/popup.tsx:395
#: src/webex/pages/popup.tsx:393
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
#: src/webex/pages/popup.tsx:438
#: src/webex/pages/popup.tsx:436
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
#: src/webex/pages/popup.tsx:472
#: src/webex/pages/popup.tsx:470
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:"
msgstr ""
#: src/webex/pages/confirm-contract.tsx:146
#: src/webex/pages/confirm-contract.tsx:141
#, c-format
msgid "You have insufficient funds of the requested currency in your wallet."
msgstr ""
#. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:148
#: src/webex/pages/confirm-contract.tsx:143
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@ -193,90 +193,90 @@ msgstr ""
msgid "Fatal error: \"%1$s\"."
msgstr ""
#: src/webex/pages/popup.tsx:163
#: src/webex/pages/popup.tsx:161
#, c-format
msgid "Balance"
msgstr ""
#: src/webex/pages/popup.tsx:166
#: src/webex/pages/popup.tsx:164
#, c-format
msgid "History"
msgstr ""
#: src/webex/pages/popup.tsx:169
#: src/webex/pages/popup.tsx:167
#, c-format
msgid "Debug"
msgstr ""
#: src/webex/pages/popup.tsx:245
#: src/webex/pages/popup.tsx:243
#, c-format
msgid "help"
msgstr ""
#: src/webex/pages/popup.tsx:250
#: src/webex/pages/popup.tsx:248
#, c-format
msgid ""
"You have no balance to show. Need some\n"
" %1$s getting started?\n"
msgstr ""
#: src/webex/pages/popup.tsx:267
#: src/webex/pages/popup.tsx:265
#, c-format
msgid "%1$s incoming\n"
msgstr ""
#: src/webex/pages/popup.tsx:280
#: src/webex/pages/popup.tsx:278
#, c-format
msgid "%1$s being spent\n"
msgstr ""
#: src/webex/pages/popup.tsx:306
#: src/webex/pages/popup.tsx:304
#, c-format
msgid "Error: could not retrieve balance information."
msgstr ""
#: src/webex/pages/popup.tsx:345
#: src/webex/pages/popup.tsx:343
#, c-format
msgid ""
"Bank requested reserve (%1$s) for\n"
" %2$s.\n"
msgstr ""
#: src/webex/pages/popup.tsx:356
#: src/webex/pages/popup.tsx:354
#, c-format
msgid ""
"Started to withdraw\n"
" %1$s from%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:366
#: src/webex/pages/popup.tsx:364
#, c-format
msgid "Merchant%1$soffered contract%2$s;\n"
msgstr ""
#: src/webex/pages/popup.tsx:376
#: src/webex/pages/popup.tsx:374
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:386
#: src/webex/pages/popup.tsx:384
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
#: src/webex/pages/popup.tsx:395
#: src/webex/pages/popup.tsx:393
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
#: src/webex/pages/popup.tsx:438
#: src/webex/pages/popup.tsx:436
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
#: src/webex/pages/popup.tsx:472
#: src/webex/pages/popup.tsx:470
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:"
msgstr ""
#: src/webex/pages/confirm-contract.tsx:146
#: src/webex/pages/confirm-contract.tsx:141
#, c-format
msgid "You have insufficient funds of the requested currency in your wallet."
msgstr ""
#. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:148
#: src/webex/pages/confirm-contract.tsx:143
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@ -193,90 +193,90 @@ msgstr ""
msgid "Fatal error: \"%1$s\"."
msgstr ""
#: src/webex/pages/popup.tsx:163
#: src/webex/pages/popup.tsx:161
#, c-format
msgid "Balance"
msgstr ""
#: src/webex/pages/popup.tsx:166
#: src/webex/pages/popup.tsx:164
#, c-format
msgid "History"
msgstr ""
#: src/webex/pages/popup.tsx:169
#: src/webex/pages/popup.tsx:167
#, c-format
msgid "Debug"
msgstr ""
#: src/webex/pages/popup.tsx:245
#: src/webex/pages/popup.tsx:243
#, c-format
msgid "help"
msgstr ""
#: src/webex/pages/popup.tsx:250
#: src/webex/pages/popup.tsx:248
#, c-format
msgid ""
"You have no balance to show. Need some\n"
" %1$s getting started?\n"
msgstr ""
#: src/webex/pages/popup.tsx:267
#: src/webex/pages/popup.tsx:265
#, c-format
msgid "%1$s incoming\n"
msgstr ""
#: src/webex/pages/popup.tsx:280
#: src/webex/pages/popup.tsx:278
#, c-format
msgid "%1$s being spent\n"
msgstr ""
#: src/webex/pages/popup.tsx:306
#: src/webex/pages/popup.tsx:304
#, c-format
msgid "Error: could not retrieve balance information."
msgstr ""
#: src/webex/pages/popup.tsx:345
#: src/webex/pages/popup.tsx:343
#, c-format
msgid ""
"Bank requested reserve (%1$s) for\n"
" %2$s.\n"
msgstr ""
#: src/webex/pages/popup.tsx:356
#: src/webex/pages/popup.tsx:354
#, c-format
msgid ""
"Started to withdraw\n"
" %1$s from%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:366
#: src/webex/pages/popup.tsx:364
#, c-format
msgid "Merchant%1$soffered contract%2$s;\n"
msgstr ""
#: src/webex/pages/popup.tsx:376
#: src/webex/pages/popup.tsx:374
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:386
#: src/webex/pages/popup.tsx:384
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
#: src/webex/pages/popup.tsx:395
#: src/webex/pages/popup.tsx:393
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
#: src/webex/pages/popup.tsx:438
#: src/webex/pages/popup.tsx:436
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
#: src/webex/pages/popup.tsx:472
#: src/webex/pages/popup.tsx:470
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:"
msgstr ""
#: src/webex/pages/confirm-contract.tsx:146
#: src/webex/pages/confirm-contract.tsx:141
#, c-format
msgid "You have insufficient funds of the requested currency in your wallet."
msgstr ""
#. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:148
#: src/webex/pages/confirm-contract.tsx:143
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@ -193,90 +193,90 @@ msgstr ""
msgid "Fatal error: \"%1$s\"."
msgstr ""
#: src/webex/pages/popup.tsx:163
#: src/webex/pages/popup.tsx:161
#, c-format
msgid "Balance"
msgstr ""
#: src/webex/pages/popup.tsx:166
#: src/webex/pages/popup.tsx:164
#, c-format
msgid "History"
msgstr ""
#: src/webex/pages/popup.tsx:169
#: src/webex/pages/popup.tsx:167
#, c-format
msgid "Debug"
msgstr ""
#: src/webex/pages/popup.tsx:245
#: src/webex/pages/popup.tsx:243
#, c-format
msgid "help"
msgstr ""
#: src/webex/pages/popup.tsx:250
#: src/webex/pages/popup.tsx:248
#, c-format
msgid ""
"You have no balance to show. Need some\n"
" %1$s getting started?\n"
msgstr ""
#: src/webex/pages/popup.tsx:267
#: src/webex/pages/popup.tsx:265
#, c-format
msgid "%1$s incoming\n"
msgstr ""
#: src/webex/pages/popup.tsx:280
#: src/webex/pages/popup.tsx:278
#, c-format
msgid "%1$s being spent\n"
msgstr ""
#: src/webex/pages/popup.tsx:306
#: src/webex/pages/popup.tsx:304
#, c-format
msgid "Error: could not retrieve balance information."
msgstr ""
#: src/webex/pages/popup.tsx:345
#: src/webex/pages/popup.tsx:343
#, c-format
msgid ""
"Bank requested reserve (%1$s) for\n"
" %2$s.\n"
msgstr ""
#: src/webex/pages/popup.tsx:356
#: src/webex/pages/popup.tsx:354
#, c-format
msgid ""
"Started to withdraw\n"
" %1$s from%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:366
#: src/webex/pages/popup.tsx:364
#, c-format
msgid "Merchant%1$soffered contract%2$s;\n"
msgstr ""
#: src/webex/pages/popup.tsx:376
#: src/webex/pages/popup.tsx:374
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
#: src/webex/pages/popup.tsx:386
#: src/webex/pages/popup.tsx:384
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
#: src/webex/pages/popup.tsx:395
#: src/webex/pages/popup.tsx:393
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
#: src/webex/pages/popup.tsx:438
#: src/webex/pages/popup.tsx:436
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
#: src/webex/pages/popup.tsx:472
#: src/webex/pages/popup.tsx:470
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""

View File

@ -1047,33 +1047,27 @@ export class Contract {
/**
* Offer record, stored in the wallet's database.
* Proposal record, stored in the wallet's database.
*/
@Checkable.Class()
export class OfferRecord {
export class ProposalRecord {
/**
* The contract that was offered by the merchant.
*/
@Checkable.Value(Contract)
contract: Contract;
contractTerms: Contract;
/**
* Signature by the merchant over the contract details.
*/
@Checkable.String
merchant_sig: string;
merchantSig: string;
/**
* Hash of the contract terms.
*/
@Checkable.String
H_contract: string;
/**
* Time when the offer was made.
*/
@Checkable.Number
offer_time: number;
contractTermsHash: string;
/**
* Serial ID when the offer is stored in the wallet DB.
@ -1085,7 +1079,7 @@ export class OfferRecord {
* Verify that a value matches the schema of this class and convert it into a
* member.
*/
static checked: (obj: any) => OfferRecord;
static checked: (obj: any) => ProposalRecord;
}

View File

@ -63,7 +63,7 @@ import {
HistoryLevel,
HistoryRecord,
Notifier,
OfferRecord,
ProposalRecord,
PayCoinInfo,
PaybackConfirmation,
PreCoinRecord,
@ -507,9 +507,9 @@ export namespace Stores {
timestampIndex = new Index<number, HistoryRecord>(this, "timestamp", "timestamp");
}
class OffersStore extends Store<OfferRecord> {
class ProposalsStore extends Store<ProposalRecord> {
constructor() {
super("offers", {
super("proposals", {
autoIncrement: true,
keyPath: "id",
});
@ -555,19 +555,19 @@ export namespace Stores {
}
}
export const exchanges = new ExchangeStore();
export const exchangeWireFees = new ExchangeWireFeesStore();
export const nonces = new NonceStore();
export const transactions = new TransactionsStore();
export const reserves = new Store<ReserveRecord>("reserves", {keyPath: "reserve_pub"});
export const coins = new CoinsStore();
export const refresh = new Store<RefreshSessionRecord>("refresh", {keyPath: "meltCoinPub"});
export const history = new HistoryStore();
export const offers = new OffersStore();
export const precoins = new Store<PreCoinRecord>("precoins", {keyPath: "coinPub"});
export const denominations = new DenominationsStore();
export const currencies = new CurrenciesStore();
export const config = new ConfigStore();
export const currencies = new CurrenciesStore();
export const denominations = new DenominationsStore();
export const exchangeWireFees = new ExchangeWireFeesStore();
export const exchanges = new ExchangeStore();
export const history = new HistoryStore();
export const nonces = new NonceStore();
export const precoins = new Store<PreCoinRecord>("precoins", {keyPath: "coinPub"});
export const proposals = new ProposalsStore();
export const refresh = new Store<RefreshSessionRecord>("refresh", {keyPath: "meltCoinPub"});
export const reserves = new Store<ReserveRecord>("reserves", {keyPath: "reserve_pub"});
export const transactions = new TransactionsStore();
}
/* tslint:enable:completed-docs */
@ -834,32 +834,32 @@ export class Wallet {
* Record all information that is necessary to
* pay for a contract in the wallet's database.
*/
private async recordConfirmPay(offer: OfferRecord,
private async recordConfirmPay(proposal: ProposalRecord,
payCoinInfo: PayCoinInfo,
chosenExchange: string): Promise<void> {
const payReq: PayReq = {
coins: payCoinInfo.map((x) => x.sig),
exchange: chosenExchange,
merchant_pub: offer.contract.merchant_pub,
order_id: offer.contract.order_id,
merchant_pub: proposal.contractTerms.merchant_pub,
order_id: proposal.contractTerms.order_id,
};
const t: TransactionRecord = {
contract: offer.contract,
contractHash: offer.H_contract,
contract: proposal.contractTerms,
contractHash: proposal.contractTermsHash,
finished: false,
merchantSig: offer.merchant_sig,
merchantSig: proposal.merchantSig,
payReq,
};
const historyEntry: HistoryRecord = {
detail: {
amount: offer.contract.amount,
contractHash: offer.H_contract,
fulfillmentUrl: offer.contract.fulfillment_url,
merchantName: offer.contract.merchant.name,
amount: proposal.contractTerms.amount,
contractHash: proposal.contractTermsHash,
fulfillmentUrl: proposal.contractTerms.fulfillment_url,
merchantName: proposal.contractTerms.merchant.name,
},
level: HistoryLevel.User,
subjectId: `contract-${offer.H_contract}`,
subjectId: `contract-${proposal.contractTermsHash}`,
timestamp: (new Date()).getTime(),
type: "pay",
};
@ -880,11 +880,13 @@ export class Wallet {
}
async saveOffer(offer: OfferRecord): Promise<number> {
console.log(`saving offer in wallet.ts`);
const id = await this.q().putWithResult(Stores.offers, offer);
/**
* Save a proposal in the database and return an id for it to
* retrieve it later.
*/
async saveProposal(proposal: ProposalRecord): Promise<number> {
const id = await this.q().putWithResult(Stores.proposals, proposal);
this.notifier.notify();
console.log(`saved offer with id ${id}`);
if (typeof id !== "number") {
throw Error("db schema wrong");
}
@ -896,10 +898,15 @@ export class Wallet {
* Add a contract to the wallet and sign coins,
* but do not send them yet.
*/
async confirmPay(offer: OfferRecord): Promise<ConfirmPayResult> {
async confirmPay(proposalId: number): Promise<ConfirmPayResult> {
console.log("executing confirmPay");
const proposal = await this.q().get(Stores.proposals, proposalId);
const transaction = await this.q().get(Stores.transactions, offer.H_contract);
if (!proposal) {
throw Error(`proposal with id ${proposalId} not found`);
}
const transaction = await this.q().get(Stores.transactions, proposal.contractTermsHash);
if (transaction) {
// Already payed ...
@ -907,17 +914,17 @@ export class Wallet {
}
const res = await this.getCoinsForPayment({
allowedAuditors: offer.contract.auditors,
allowedExchanges: offer.contract.exchanges,
depositFeeLimit: offer.contract.max_fee,
paymentAmount: offer.contract.amount,
wireFeeAmortization: offer.contract.wire_fee_amortization || 1,
wireFeeLimit: offer.contract.max_wire_fee || Amounts.getZero(offer.contract.amount.currency),
wireFeeTime: getTalerStampSec(offer.contract.timestamp) || 0,
wireMethod: offer.contract.wire_method,
allowedAuditors: proposal.contractTerms.auditors,
allowedExchanges: proposal.contractTerms.exchanges,
depositFeeLimit: proposal.contractTerms.max_fee,
paymentAmount: proposal.contractTerms.amount,
wireFeeAmortization: proposal.contractTerms.wire_fee_amortization || 1,
wireFeeLimit: proposal.contractTerms.max_wire_fee || Amounts.getZero(proposal.contractTerms.amount.currency),
wireFeeTime: getTalerStampSec(proposal.contractTerms.timestamp) || 0,
wireMethod: proposal.contractTerms.wire_method,
});
console.log("max_fee", offer.contract.max_fee);
console.log("max_fee", proposal.contractTerms.max_fee);
console.log("coin selection result", res);
if (!res) {
@ -926,8 +933,8 @@ export class Wallet {
}
const {exchangeUrl, cds} = res;
const ds = await this.cryptoApi.signDeposit(offer, cds);
await this.recordConfirmPay(offer, ds, exchangeUrl);
const ds = await this.cryptoApi.signDeposit(proposal, cds);
await this.recordConfirmPay(proposal, ds, exchangeUrl);
return "paid";
}
@ -936,23 +943,29 @@ export class Wallet {
* Check if payment for an offer is possible, or if the offer has already
* been payed for.
*/
async checkPay(offer: OfferRecord): Promise<CheckPayResult> {
async checkPay(proposalId: number): Promise<CheckPayResult> {
const proposal = await this.q().get(Stores.proposals, proposalId);
if (!proposal) {
throw Error(`proposal with id ${proposalId} not found`);
}
// First check if we already payed for it.
const transaction = await this.q().get(Stores.transactions, offer.H_contract);
const transaction = await this.q().get(Stores.transactions, proposal.contractTermsHash);
if (transaction) {
return "insufficient-balance";
}
// If not already payed, check if we could pay for it.
const res = await this.getCoinsForPayment({
allowedAuditors: offer.contract.auditors,
allowedExchanges: offer.contract.exchanges,
depositFeeLimit: offer.contract.max_fee,
paymentAmount: offer.contract.amount,
wireFeeAmortization: offer.contract.wire_fee_amortization || 1,
wireFeeLimit: offer.contract.max_wire_fee || Amounts.getZero(offer.contract.amount.currency),
wireFeeTime: getTalerStampSec(offer.contract.timestamp) || 0,
wireMethod: offer.contract.wire_method,
allowedAuditors: proposal.contractTerms.auditors,
allowedExchanges: proposal.contractTerms.exchanges,
depositFeeLimit: proposal.contractTerms.max_fee,
paymentAmount: proposal.contractTerms.amount,
wireFeeAmortization: proposal.contractTerms.wire_fee_amortization || 1,
wireFeeLimit: proposal.contractTerms.max_wire_fee || Amounts.getZero(proposal.contractTerms.amount.currency),
wireFeeTime: getTalerStampSec(proposal.contractTerms.timestamp) || 0,
wireMethod: proposal.contractTerms.wire_method,
});
if (!res) {
@ -2110,9 +2123,9 @@ export class Wallet {
return denoms;
}
async getOffer(offerId: number): Promise<any> {
const offer = await this.q() .get(Stores.offers, offerId);
return offer;
async getProposal(proposalId: number): Promise<ProposalRecord|undefined> {
const proposal = await this.q().get(Stores.proposals, proposalId);
return proposal;
}
async getExchanges(): Promise<ExchangeRecord[]> {

View File

@ -69,11 +69,11 @@ export interface MessageMap {
response: string;
};
"confirm-pay": {
request: { offer: types.OfferRecord; };
request: { proposalId: number; };
response: types.ConfirmPayResult;
};
"check-pay": {
request: { offer: types.OfferRecord; };
request: { proposalId: number; };
response: types.CheckPayResult;
};
"query-payment": {
@ -96,21 +96,29 @@ export interface MessageMap {
request: { historyEntry: types.HistoryRecord };
response: void;
};
"safe-offer": {
request: { offer: types.OfferRecord };
"save-proposal": {
request: { proposal: types.ProposalRecord };
response: void;
};
"reserve-creation-info": {
request: { baseUrl: string };
request: { baseUrl: string, amount: types.AmountJson };
response: types.ReserveCreationInfo;
}
"get-history": {
request: { };
response: types.HistoryRecord[];
};
"get-offer": {
request: { offerId: number };
response: types.OfferRecord | undefined;
"get-proposal": {
request: { proposalId: number };
response: types.ProposalRecord | undefined;
};
"get-coins": {
request: { exchangeBaseUrl: string };
response: any;
};
"refresh-coin": {
request: { coinPub: string };
response: any;
};
"get-currencies": {
request: { };
@ -120,6 +128,10 @@ export interface MessageMap {
request: { currencyRecord: types.CurrencyRecord };
response: void;
};
"get-exchanges": {
request: { };
response: types.ExchangeRecord[];
};
"get-reserves": {
request: { exchangeBaseUrl: string };
response: types.ReserveRecord[];

View File

@ -280,7 +280,8 @@ async function processProposal(proposal: any) {
const contractHash = await wxApi.hashContract(proposal.data);
if (contractHash !== proposal.hash) {
console.error("merchant-supplied contract hash is wrong");
console.error(`merchant-supplied contract hash is wrong (us: ${contractHash}, merchant: ${proposal.hash})`);
console.dir(proposal.data);
return;
}
@ -301,12 +302,11 @@ async function processProposal(proposal: any) {
type: "offer-contract",
};
await wxApi.putHistory(historyEntry);
const offerId = await wxApi.saveOffer(proposal);
let proposalId = await wxApi.saveProposal(proposal);
const uri = new URI(chrome.extension.getURL(
"/src/webex/pages/confirm-contract.html"));
const uri = new URI(chrome.extension.getURL("/src/webex/pages/confirm-contract.html"));
const params = {
offerId: offerId.toString(),
proposalId: proposalId.toString(),
};
const target = uri.query(params).href();
document.location.replace(target);

View File

@ -5,7 +5,7 @@
<meta charset="UTF-8">
<title>Taler Wallet: Confirm Reserve Creation</title>
<link rel="stylesheet" type="text/css" href="/src/style/wallet.css">
<link rel="stylesheet" type="text/css" href="../style/wallet.css">
<link rel="icon" href="/img/icon.png">

View File

@ -27,7 +27,7 @@ import * as i18n from "../../i18n";
import {
Contract,
ExchangeRecord,
OfferRecord,
ProposalRecord,
} from "../../types";
import { renderContract } from "../renderHtml";
@ -98,11 +98,11 @@ class Details extends React.Component<DetailProps, DetailState> {
}
interface ContractPromptProps {
offerId: number;
proposalId: number;
}
interface ContractPromptState {
offer: OfferRecord|null;
proposal: ProposalRecord|null;
error: string|null;
payDisabled: boolean;
exchanges: null|ExchangeRecord[];
@ -114,7 +114,7 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
this.state = {
error: null,
exchanges: null,
offer: null,
proposal: null,
payDisabled: true,
};
}
@ -128,26 +128,21 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
}
async update() {
const offer = await wxApi.getOffer(this.props.offerId);
this.setState({offer} as any);
const proposal = await wxApi.getProposal(this.props.proposalId);
this.setState({proposal} as any);
this.checkPayment();
const exchanges = await wxApi.getExchanges();
this.setState({exchanges} as any);
}
async checkPayment() {
const offer = this.state.offer;
if (!offer) {
return;
}
const payStatus = await wxApi.checkPay(offer);
const payStatus = await wxApi.checkPay(this.props.proposalId);
if (payStatus === "insufficient-balance") {
const msgInsufficient = i18n.str`You have insufficient funds of the requested currency in your wallet.`;
// tslint:disable-next-line:max-line-length
const msgNoMatch = i18n.str`You do not have any funds from an exchange that is accepted by this merchant. None of the exchanges accepted by the merchant is known to your wallet.`;
if (this.state.exchanges && this.state.offer) {
const acceptedExchangePubs = this.state.offer.contract.exchanges.map((e) => e.master_pub);
if (this.state.exchanges && this.state.proposal) {
const acceptedExchangePubs = this.state.proposal.contractTerms.exchanges.map((e) => e.master_pub);
const ex = this.state.exchanges.find((e) => acceptedExchangePubs.indexOf(e.masterPublicKey) >= 0);
if (ex) {
this.setState({error: msgInsufficient});
@ -165,28 +160,28 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
}
async doPayment() {
const offer = this.state.offer;
if (!offer) {
const proposal = this.state.proposal;
if (!proposal) {
return;
}
const payStatus = await wxApi.confirmPay(offer);
const payStatus = await wxApi.confirmPay(this.props.proposalId);
switch (payStatus) {
case "insufficient-balance":
this.checkPayment();
return;
case "paid":
console.log("contract", offer.contract);
document.location.href = offer.contract.fulfillment_url;
console.log("contract", proposal.contractTerms);
document.location.href = proposal.contractTerms.fulfillment_url;
break;
}
}
render() {
if (!this.state.offer) {
if (!this.state.proposal) {
return <span>...</span>;
}
const c = this.state.offer.contract;
const c = this.state.proposal.contractTerms;
return (
<div>
<div>
@ -210,8 +205,8 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
document.addEventListener("DOMContentLoaded", () => {
const url = new URI(document.location.href);
const query: any = URI.parseQuery(url.query());
const offerId = JSON.parse(query.offerId);
const proposalId = JSON.parse(query.proposalId);
ReactDOM.render(<ContractPrompt offerId={offerId}/>, document.getElementById(
ReactDOM.render(<ContractPrompt proposalId={proposalId}/>, document.getElementById(
"contract")!);
});

View File

@ -30,15 +30,16 @@ import {
CurrencyRecord,
DenominationRecord,
ExchangeRecord,
OfferRecord,
PreCoinRecord,
ReserveCreationInfo,
ReserveRecord,
} from "../types";
import { MessageType, MessageMap } from "./messages";
async function callBackend(type: string, detail?: any): Promise<any> {
async function callBackend<T extends MessageType>(type: T, detail: MessageMap[T]["request"]): Promise<any> {
return new Promise<any>((resolve, reject) => {
chrome.runtime.sendMessage({ type, detail }, (resp) => {
if (resp && resp.error) {
@ -65,7 +66,7 @@ export function getReserveCreationInfo(baseUrl: string,
* Get all exchanges the wallet knows about.
*/
export function getExchanges(): Promise<ExchangeRecord[]> {
return callBackend("get-exchanges");
return callBackend("get-exchanges", { });
}
@ -73,7 +74,7 @@ export function getExchanges(): Promise<ExchangeRecord[]> {
* Get all currencies the exchange knows about.
*/
export function getCurrencies(): Promise<CurrencyRecord[]> {
return callBackend("get-currencies");
return callBackend("get-currencies", { });
}
@ -114,7 +115,7 @@ export function getReserves(exchangeBaseUrl: string): Promise<ReserveRecord[]> {
* Get all reserves for which a payback is available.
*/
export function getPaybackReserves(): Promise<ReserveRecord[]> {
return callBackend("get-payback-reserves");
return callBackend("get-payback-reserves", { });
}
@ -166,41 +167,40 @@ export function payback(coinPub: string): Promise<void> {
}
/**
* Get an offer stored in the wallet by its offer id.
* Note that the numeric offer id is not to be confused with
* the string order_id from the contract terms.
* Get a proposal stored in the wallet by its proposal id.
*/
export function getOffer(offerId: number) {
return callBackend("get-offer", { offerId });
export function getProposal(proposalId: number) {
return callBackend("get-proposal", { proposalId });
}
/**
* Check if payment is possible or already done.
*/
export function checkPay(offer: OfferRecord): Promise<CheckPayResult> {
return callBackend("check-pay", { offer });
export function checkPay(proposalId: number): Promise<CheckPayResult> {
return callBackend("check-pay", { proposalId });
}
/**
* Pay for an offer.
* Pay for a proposal.
*/
export function confirmPay(offer: OfferRecord): Promise<ConfirmPayResult> {
return callBackend("confirm-pay", { offer });
export function confirmPay(proposalId: number): Promise<ConfirmPayResult> {
return callBackend("confirm-pay", { proposalId });
}
/**
* Hash a contract. Throws if its not a valid contract.
*/
export function hashContract(contract: object): Promise<string> {
return callBackend("confirm-pay", { contract });
return callBackend("hash-contract", { contract });
}
/**
* Save an offer in the wallet. Returns the offer id that
* the offer is stored under.
* Save a proposal in the wallet. Returns the proposal id that
* the proposal is stored under.
*/
export function saveOffer(offer: object): Promise<number> {
return callBackend("save-offer", { offer });
export function saveProposal(proposal: any): Promise<number> {
return callBackend("save-proposal", proposal);
}
/**
@ -243,7 +243,7 @@ export function paymentFailed(contractTermsHash: string): Promise<void> {
* cookie was set.
*/
export function getTabCookie(contractTermsHash: string, merchantSig: string): Promise<any> {
return callBackend("get-tab-cookie");
return callBackend("get-tab-cookie", { });
}
/**
@ -251,5 +251,5 @@ export function getTabCookie(contractTermsHash: string, merchantSig: string): Pr
* database and return the public key.
*/
export function generateNonce(): Promise<string> {
return callBackend("generate-nonce");
return callBackend("generate-nonce", { });
}

View File

@ -24,7 +24,6 @@
/**
* Imports.
*/
import { Checkable } from "../checkable";
import { BrowserHttpLib } from "../http";
import * as logging from "../logging";
import {
@ -34,7 +33,7 @@ import {
import {
AmountJson,
Notifier,
OfferRecord,
ProposalRecord,
} from "../types";
import {
ConfirmReserveRequest,
@ -44,6 +43,7 @@ import {
} from "../wallet";
import { ChromeBadge } from "./chromeBadge";
import { MessageType } from "./messages";
import URI = require("urijs");
import Port = chrome.runtime.Port;
@ -60,21 +60,23 @@ const DB_NAME = "taler";
*/
const DB_VERSION = 17;
type Handler = (detail: any, sender: MessageSender) => Promise<any>;
function makeHandlers(db: IDBDatabase,
wallet: Wallet): { [msg: string]: Handler } {
return {
["balances"]: (detail, sender) => {
function handleMessage(db: IDBDatabase,
wallet: Wallet,
sender: MessageSender,
type: MessageType, detail: any): any {
function assertNotFound(t: never): never {
console.error(`Request type ${t as string} unknown`);
console.error(`Request detail was ${detail}`);
return { error: "request unknown", requestType: type } as never;
}
switch (type) {
case "balances":
return wallet.getBalances();
},
["dump-db"]: (detail, sender) => {
case "dump-db":
return exportDb(db);
},
["import-db"]: (detail, sender) => {
case "import-db":
return importDb(db, detail.dump);
},
["get-tab-cookie"]: (detail, sender) => {
case "get-tab-cookie":
if (!sender || !sender.tab || !sender.tab.id) {
return Promise.resolve();
}
@ -82,11 +84,9 @@ function makeHandlers(db: IDBDatabase,
const info: any = paymentRequestCookies[id] as any;
delete paymentRequestCookies[id];
return Promise.resolve(info);
},
["ping"]: (detail, sender) => {
case "ping":
return Promise.resolve();
},
["reset"]: (detail, sender) => {
case "reset":
if (db) {
const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
// tslint:disable-next-line:prefer-for-of
@ -95,69 +95,36 @@ function makeHandlers(db: IDBDatabase,
}
}
deleteDb();
chrome.browserAction.setBadgeText({ text: "" });
console.log("reset done");
// Response is synchronous
return Promise.resolve({});
},
["create-reserve"]: (detail, sender) => {
case "create-reserve": {
const d = {
amount: detail.amount,
exchange: detail.exchange,
};
const req = CreateReserveRequest.checked(d);
return wallet.createReserve(req);
},
["confirm-reserve"]: (detail, sender) => {
// TODO: make it a checkable
}
case "confirm-reserve":
const d = {
reservePub: detail.reservePub,
};
const req = ConfirmReserveRequest.checked(d);
return wallet.confirmReserve(req);
},
["generate-nonce"]: (detail, sender) => {
case "generate-nonce":
return wallet.generateNonce();
},
["confirm-pay"]: (detail, sender) => {
let offer: OfferRecord;
try {
offer = OfferRecord.checked(detail.offer);
} catch (e) {
if (e instanceof Checkable.SchemaError) {
console.error("schema error:", e.message);
return Promise.resolve({
detail,
error: "invalid contract",
hint: e.message,
});
} else {
throw e;
}
case "confirm-pay":
if (typeof detail.proposalId !== "number") {
throw Error("proposalId must be number");
}
return wallet.confirmPay(offer);
},
["check-pay"]: (detail, sender) => {
let offer: OfferRecord;
try {
offer = OfferRecord.checked(detail.offer);
} catch (e) {
if (e instanceof Checkable.SchemaError) {
console.error("schema error:", e.message);
return Promise.resolve({
detail,
error: "invalid contract",
hint: e.message,
});
} else {
throw e;
}
return wallet.confirmPay(detail.proposalId);
case "check-pay":
if (typeof detail.proposalId !== "number") {
throw Error("proposalId must be number");
}
return wallet.checkPay(offer);
},
["query-payment"]: (detail: any, sender: MessageSender) => {
return wallet.checkPay(detail.proposalId);
case "query-payment":
if (sender.tab && sender.tab.id) {
rateLimitCache[sender.tab.id]++;
if (rateLimitCache[sender.tab.id] > 10) {
@ -171,120 +138,98 @@ function makeHandlers(db: IDBDatabase,
}
}
return wallet.queryPayment(detail.url);
},
["exchange-info"]: (detail) => {
case "exchange-info":
if (!detail.baseUrl) {
return Promise.resolve({ error: "bad url" });
}
return wallet.updateExchangeFromUrl(detail.baseUrl);
},
["currency-info"]: (detail) => {
case "currency-info":
if (!detail.name) {
return Promise.resolve({ error: "name missing" });
}
return wallet.getCurrencyRecord(detail.name);
},
["hash-contract"]: (detail) => {
case "hash-contract":
if (!detail.contract) {
return Promise.resolve({ error: "contract missing" });
}
return wallet.hashContract(detail.contract).then((hash) => {
return { hash };
return hash;
});
},
["put-history-entry"]: (detail: any) => {
case "put-history-entry":
if (!detail.historyEntry) {
return Promise.resolve({ error: "historyEntry missing" });
}
return wallet.putHistory(detail.historyEntry);
},
["save-offer"]: (detail: any) => {
const offer = detail.offer;
if (!offer) {
return Promise.resolve({ error: "offer missing" });
}
console.log("handling safe-offer", detail);
// FIXME: fully migrate to new terminology
const checkedOffer = OfferRecord.checked(offer);
return wallet.saveOffer(checkedOffer);
},
["reserve-creation-info"]: (detail, sender) => {
case "save-proposal":
console.log("handling save-proposal", detail);
const checkedRecord = ProposalRecord.checked({
contractTerms: detail.data,
contractTermsHash: detail.hash,
merchantSig: detail.sig,
});
return wallet.saveProposal(checkedRecord);
case "reserve-creation-info":
if (!detail.baseUrl || typeof detail.baseUrl !== "string") {
return Promise.resolve({ error: "bad url" });
}
const amount = AmountJson.checked(detail.amount);
return wallet.getReserveCreationInfo(detail.baseUrl, amount);
},
["get-history"]: (detail, sender) => {
case "get-history":
// TODO: limit history length
return wallet.getHistory();
},
["get-offer"]: (detail, sender) => {
return wallet.getOffer(detail.offerId);
},
["get-exchanges"]: (detail, sender) => {
case "get-proposal":
return wallet.getProposal(detail.proposalId);
case "get-exchanges":
return wallet.getExchanges();
},
["get-currencies"]: (detail, sender) => {
case "get-currencies":
return wallet.getCurrencies();
},
["update-currency"]: (detail, sender) => {
case "update-currency":
return wallet.updateCurrency(detail.currencyRecord);
},
["get-reserves"]: (detail, sender) => {
case "get-reserves":
if (typeof detail.exchangeBaseUrl !== "string") {
return Promise.reject(Error("exchangeBaseUrl missing"));
}
return wallet.getReserves(detail.exchangeBaseUrl);
},
["get-payback-reserves"]: (detail, sender) => {
case "get-payback-reserves":
return wallet.getPaybackReserves();
},
["withdraw-payback-reserve"]: (detail, sender) => {
case "withdraw-payback-reserve":
if (typeof detail.reservePub !== "string") {
return Promise.reject(Error("reservePub missing"));
}
return wallet.withdrawPaybackReserve(detail.reservePub);
},
["get-coins"]: (detail, sender) => {
case "get-coins":
if (typeof detail.exchangeBaseUrl !== "string") {
return Promise.reject(Error("exchangBaseUrl missing"));
}
return wallet.getCoins(detail.exchangeBaseUrl);
},
["get-precoins"]: (detail, sender) => {
case "get-precoins":
if (typeof detail.exchangeBaseUrl !== "string") {
return Promise.reject(Error("exchangBaseUrl missing"));
}
return wallet.getPreCoins(detail.exchangeBaseUrl);
},
["get-denoms"]: (detail, sender) => {
case "get-denoms":
if (typeof detail.exchangeBaseUrl !== "string") {
return Promise.reject(Error("exchangBaseUrl missing"));
}
return wallet.getDenoms(detail.exchangeBaseUrl);
},
["refresh-coin"]: (detail, sender) => {
case "refresh-coin":
if (typeof detail.coinPub !== "string") {
return Promise.reject(Error("coinPub missing"));
}
return wallet.refresh(detail.coinPub);
},
["payback-coin"]: (detail, sender) => {
case "payback-coin":
if (typeof detail.coinPub !== "string") {
return Promise.reject(Error("coinPub missing"));
}
return wallet.payback(detail.coinPub);
},
["payment-failed"]: (detail, sender) => {
case "payment-failed":
// For now we just update exchanges (maybe the exchange did something
// wrong and the keys were messed up).
// FIXME: in the future we should look at what actually went wrong.
console.error("payment reported as failed");
wallet.updateExchanges();
return Promise.resolve();
},
["payment-succeeded"]: (detail, sender) => {
case "payment-succeeded":
const contractTermsHash = detail.contractTermsHash;
const merchantSig = detail.merchantSig;
if (!contractTermsHash) {
@ -294,24 +239,16 @@ function makeHandlers(db: IDBDatabase,
return Promise.reject(Error("merchantSig missing"));
}
return wallet.paymentSucceeded(contractTermsHash, merchantSig);
},
};
default:
// Exhaustiveness check.
// See https://www.typescriptlang.org/docs/handbook/advanced-types.html
return assertNotFound(type);
}
}
async function dispatch(handlers: any, req: any, sender: any, sendResponse: any): Promise<void> {
if (!(req.type in handlers)) {
console.error(`Request type ${req.type} unknown`);
console.error(`Request was ${req}`);
try {
sendResponse({ error: "request unknown", requestType: req.type });
} catch (e) {
// might fail if tab disconnected
}
}
async function dispatch(db: IDBDatabase, wallet: Wallet, req: any, sender: any, sendResponse: any): Promise<void> {
try {
const p = handlers[req.type](req.detail, sender);
const p = handleMessage(db, wallet, sender, req.type, req.detail);
const r = await p;
try {
sendResponse(r);
@ -587,9 +524,8 @@ export async function wxMain() {
// Handlers for messages coming directly from the content
// script on the page
const handlers = makeHandlers(db, wallet!);
chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
dispatch(handlers, req, sender, sendResponse);
dispatch(db, wallet, req, sender, sendResponse);
return true;
});