derive history from db instead of storing it
This commit is contained in:
parent
23633cf1be
commit
03782f8aea
@ -183,7 +183,7 @@ export namespace Checkable {
|
|||||||
if (innerProp.optional) {
|
if (innerProp.optional) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
throw new SchemaError(`Property ${innerProp.propertyKey} missing on ${path}`);
|
throw new SchemaError(`Property ${innerProp.propertyKey} missing on ${path} of ${type.name||"??"}`);
|
||||||
}
|
}
|
||||||
if (!remainingPropNames.delete(innerProp.propertyKey)) {
|
if (!remainingPropNames.delete(innerProp.propertyKey)) {
|
||||||
throw new SchemaError("assertion failed");
|
throw new SchemaError("assertion failed");
|
||||||
@ -195,8 +195,7 @@ export namespace Checkable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!prop.extraAllowed && remainingPropNames.size !== 0) {
|
if (!prop.extraAllowed && remainingPropNames.size !== 0) {
|
||||||
throw new SchemaError("superfluous properties " + JSON.stringify(Array.from(
|
throw new SchemaError(`superfluous properties ${JSON.stringify(Array.from(remainingPropNames.values()))} of ${type.name||"??"}`);
|
||||||
remainingPropNames.values())));
|
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -81,16 +81,16 @@ test("precoin creation", async (t) => {
|
|||||||
const crypto = new CryptoApi();
|
const crypto = new CryptoApi();
|
||||||
const {priv, pub} = await crypto.createEddsaKeypair();
|
const {priv, pub} = await crypto.createEddsaKeypair();
|
||||||
const r: ReserveRecord = {
|
const r: ReserveRecord = {
|
||||||
confirmed: false,
|
|
||||||
created: 0,
|
created: 0,
|
||||||
current_amount: null,
|
current_amount: null,
|
||||||
exchange_base_url: "https://example.com/exchange",
|
exchange_base_url: "https://example.com/exchange",
|
||||||
hasPayback: false,
|
hasPayback: false,
|
||||||
last_query: null,
|
|
||||||
precoin_amount: {currency: "PUDOS", value: 0, fraction: 0},
|
precoin_amount: {currency: "PUDOS", value: 0, fraction: 0},
|
||||||
requested_amount: {currency: "PUDOS", value: 0, fraction: 0},
|
requested_amount: {currency: "PUDOS", value: 0, fraction: 0},
|
||||||
reserve_priv: priv,
|
reserve_priv: priv,
|
||||||
reserve_pub: pub,
|
reserve_pub: pub,
|
||||||
|
timestamp_confirmed: 0,
|
||||||
|
timestamp_depleted: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const precoin = await crypto.createPreCoin(denomValid1, r);
|
const precoin = await crypto.createPreCoin(denomValid1, r);
|
||||||
|
@ -198,105 +198,105 @@ msgstr ""
|
|||||||
msgid "Fatal error: \"%1$s\"."
|
msgid "Fatal error: \"%1$s\"."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:161
|
#: src/webex/pages/popup.tsx:160
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Balance"
|
msgid "Balance"
|
||||||
msgstr "Saldo"
|
msgstr "Saldo"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:164
|
#: src/webex/pages/popup.tsx:163
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "History"
|
msgid "History"
|
||||||
msgstr "Verlauf"
|
msgstr "Verlauf"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:167
|
#: src/webex/pages/popup.tsx:166
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr "Debug"
|
msgstr "Debug"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:247
|
#: src/webex/pages/popup.tsx:246
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "help"
|
msgid "help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:252
|
#: src/webex/pages/popup.tsx:251
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You have no balance to show. Need some\n"
|
"You have no balance to show. Need some\n"
|
||||||
" %1$s getting started?\n"
|
" %1$s getting started?\n"
|
||||||
msgstr "Sie haben kein Digitalgeld. Wollen Sie %1$s? abheben?"
|
msgstr "Sie haben kein Digitalgeld. Wollen Sie %1$s? abheben?"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:269
|
#: src/webex/pages/popup.tsx:268
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s incoming\n"
|
msgid "%1$s incoming\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:282
|
#: src/webex/pages/popup.tsx:281
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s being spent\n"
|
msgid "%1$s being spent\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:308
|
#: src/webex/pages/popup.tsx:307
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve balance information."
|
msgid "Error: could not retrieve balance information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:335
|
#: src/webex/pages/popup.tsx:334
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Payback"
|
msgid "Payback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:336
|
#: src/webex/pages/popup.tsx:335
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Return Electronic Cash to Bank Account"
|
msgid "Return Electronic Cash to Bank Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:337
|
#: src/webex/pages/popup.tsx:336
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Manage Trusted Auditors and Exchanges"
|
msgid "Manage Trusted Auditors and Exchanges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:349
|
#: src/webex/pages/popup.tsx:348
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Bank requested reserve (%1$s) for\n"
|
"Bank requested reserve (%1$s) for\n"
|
||||||
" %2$s.\n"
|
" %2$s.\n"
|
||||||
msgstr "Bank bestätig anlegen der Reserve (%1$s) bei %2$s"
|
msgstr "Bank bestätig anlegen der Reserve (%1$s) bei %2$s"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:360
|
#: src/webex/pages/popup.tsx:359
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Started to withdraw\n"
|
"Started to withdraw\n"
|
||||||
" %1$s from%2$s(%3$s).\n"
|
" %1$s from%2$s(%3$s).\n"
|
||||||
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
|
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:370
|
#: src/webex/pages/popup.tsx:369
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Merchant%1$soffered contract%2$s;\n"
|
msgid "Merchant%1$soffered contract%2$s;\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:380
|
#: src/webex/pages/popup.tsx:379
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
||||||
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
|
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:390
|
#: src/webex/pages/popup.tsx:389
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Paid%1$sto merchant%2$s.\n"
|
"Paid%1$sto merchant%2$s.\n"
|
||||||
" (%3$s)\n"
|
" (%3$s)\n"
|
||||||
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
|
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:399
|
#: src/webex/pages/popup.tsx:398
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown event (%1$s)"
|
msgid "Unknown event (%1$s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:442
|
#: src/webex/pages/popup.tsx:441
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve event history"
|
msgid "Error: could not retrieve event history"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:476
|
#: src/webex/pages/popup.tsx:466
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Your wallet has no events recorded."
|
msgid "Your wallet has no events recorded."
|
||||||
msgstr "Ihre Geldbörse verzeichnet keine Vorkommnisse."
|
msgstr "Ihre Geldbörse verzeichnet keine Vorkommnisse."
|
||||||
|
@ -198,105 +198,105 @@ msgstr ""
|
|||||||
msgid "Fatal error: \"%1$s\"."
|
msgid "Fatal error: \"%1$s\"."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:161
|
#: src/webex/pages/popup.tsx:160
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Balance"
|
msgid "Balance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:164
|
#: src/webex/pages/popup.tsx:163
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "History"
|
msgid "History"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:167
|
#: src/webex/pages/popup.tsx:166
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:247
|
#: src/webex/pages/popup.tsx:246
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "help"
|
msgid "help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:252
|
#: src/webex/pages/popup.tsx:251
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You have no balance to show. Need some\n"
|
"You have no balance to show. Need some\n"
|
||||||
" %1$s getting started?\n"
|
" %1$s getting started?\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:269
|
#: src/webex/pages/popup.tsx:268
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s incoming\n"
|
msgid "%1$s incoming\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:282
|
#: src/webex/pages/popup.tsx:281
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s being spent\n"
|
msgid "%1$s being spent\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:308
|
#: src/webex/pages/popup.tsx:307
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve balance information."
|
msgid "Error: could not retrieve balance information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:335
|
#: src/webex/pages/popup.tsx:334
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Payback"
|
msgid "Payback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:336
|
#: src/webex/pages/popup.tsx:335
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Return Electronic Cash to Bank Account"
|
msgid "Return Electronic Cash to Bank Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:337
|
#: src/webex/pages/popup.tsx:336
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Manage Trusted Auditors and Exchanges"
|
msgid "Manage Trusted Auditors and Exchanges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:349
|
#: src/webex/pages/popup.tsx:348
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Bank requested reserve (%1$s) for\n"
|
"Bank requested reserve (%1$s) for\n"
|
||||||
" %2$s.\n"
|
" %2$s.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:360
|
#: src/webex/pages/popup.tsx:359
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Started to withdraw\n"
|
"Started to withdraw\n"
|
||||||
" %1$s from%2$s(%3$s).\n"
|
" %1$s from%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:370
|
#: src/webex/pages/popup.tsx:369
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Merchant%1$soffered contract%2$s;\n"
|
msgid "Merchant%1$soffered contract%2$s;\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:380
|
#: src/webex/pages/popup.tsx:379
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:390
|
#: src/webex/pages/popup.tsx:389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Paid%1$sto merchant%2$s.\n"
|
"Paid%1$sto merchant%2$s.\n"
|
||||||
" (%3$s)\n"
|
" (%3$s)\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:399
|
#: src/webex/pages/popup.tsx:398
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown event (%1$s)"
|
msgid "Unknown event (%1$s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:442
|
#: src/webex/pages/popup.tsx:441
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve event history"
|
msgid "Error: could not retrieve event history"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:476
|
#: src/webex/pages/popup.tsx:466
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Your wallet has no events recorded."
|
msgid "Your wallet has no events recorded."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -198,105 +198,105 @@ msgstr ""
|
|||||||
msgid "Fatal error: \"%1$s\"."
|
msgid "Fatal error: \"%1$s\"."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:161
|
#: src/webex/pages/popup.tsx:160
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Balance"
|
msgid "Balance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:164
|
#: src/webex/pages/popup.tsx:163
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "History"
|
msgid "History"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:167
|
#: src/webex/pages/popup.tsx:166
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:247
|
#: src/webex/pages/popup.tsx:246
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "help"
|
msgid "help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:252
|
#: src/webex/pages/popup.tsx:251
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You have no balance to show. Need some\n"
|
"You have no balance to show. Need some\n"
|
||||||
" %1$s getting started?\n"
|
" %1$s getting started?\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:269
|
#: src/webex/pages/popup.tsx:268
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s incoming\n"
|
msgid "%1$s incoming\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:282
|
#: src/webex/pages/popup.tsx:281
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s being spent\n"
|
msgid "%1$s being spent\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:308
|
#: src/webex/pages/popup.tsx:307
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve balance information."
|
msgid "Error: could not retrieve balance information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:335
|
#: src/webex/pages/popup.tsx:334
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Payback"
|
msgid "Payback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:336
|
#: src/webex/pages/popup.tsx:335
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Return Electronic Cash to Bank Account"
|
msgid "Return Electronic Cash to Bank Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:337
|
#: src/webex/pages/popup.tsx:336
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Manage Trusted Auditors and Exchanges"
|
msgid "Manage Trusted Auditors and Exchanges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:349
|
#: src/webex/pages/popup.tsx:348
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Bank requested reserve (%1$s) for\n"
|
"Bank requested reserve (%1$s) for\n"
|
||||||
" %2$s.\n"
|
" %2$s.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:360
|
#: src/webex/pages/popup.tsx:359
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Started to withdraw\n"
|
"Started to withdraw\n"
|
||||||
" %1$s from%2$s(%3$s).\n"
|
" %1$s from%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:370
|
#: src/webex/pages/popup.tsx:369
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Merchant%1$soffered contract%2$s;\n"
|
msgid "Merchant%1$soffered contract%2$s;\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:380
|
#: src/webex/pages/popup.tsx:379
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:390
|
#: src/webex/pages/popup.tsx:389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Paid%1$sto merchant%2$s.\n"
|
"Paid%1$sto merchant%2$s.\n"
|
||||||
" (%3$s)\n"
|
" (%3$s)\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:399
|
#: src/webex/pages/popup.tsx:398
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown event (%1$s)"
|
msgid "Unknown event (%1$s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:442
|
#: src/webex/pages/popup.tsx:441
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve event history"
|
msgid "Error: could not retrieve event history"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:476
|
#: src/webex/pages/popup.tsx:466
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Your wallet has no events recorded."
|
msgid "Your wallet has no events recorded."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -198,105 +198,105 @@ msgstr ""
|
|||||||
msgid "Fatal error: \"%1$s\"."
|
msgid "Fatal error: \"%1$s\"."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:161
|
#: src/webex/pages/popup.tsx:160
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Balance"
|
msgid "Balance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:164
|
#: src/webex/pages/popup.tsx:163
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "History"
|
msgid "History"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:167
|
#: src/webex/pages/popup.tsx:166
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:247
|
#: src/webex/pages/popup.tsx:246
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "help"
|
msgid "help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:252
|
#: src/webex/pages/popup.tsx:251
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You have no balance to show. Need some\n"
|
"You have no balance to show. Need some\n"
|
||||||
" %1$s getting started?\n"
|
" %1$s getting started?\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:269
|
#: src/webex/pages/popup.tsx:268
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s incoming\n"
|
msgid "%1$s incoming\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:282
|
#: src/webex/pages/popup.tsx:281
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s being spent\n"
|
msgid "%1$s being spent\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:308
|
#: src/webex/pages/popup.tsx:307
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve balance information."
|
msgid "Error: could not retrieve balance information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:335
|
#: src/webex/pages/popup.tsx:334
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Payback"
|
msgid "Payback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:336
|
#: src/webex/pages/popup.tsx:335
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Return Electronic Cash to Bank Account"
|
msgid "Return Electronic Cash to Bank Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:337
|
#: src/webex/pages/popup.tsx:336
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Manage Trusted Auditors and Exchanges"
|
msgid "Manage Trusted Auditors and Exchanges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:349
|
#: src/webex/pages/popup.tsx:348
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Bank requested reserve (%1$s) for\n"
|
"Bank requested reserve (%1$s) for\n"
|
||||||
" %2$s.\n"
|
" %2$s.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:360
|
#: src/webex/pages/popup.tsx:359
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Started to withdraw\n"
|
"Started to withdraw\n"
|
||||||
" %1$s from%2$s(%3$s).\n"
|
" %1$s from%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:370
|
#: src/webex/pages/popup.tsx:369
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Merchant%1$soffered contract%2$s;\n"
|
msgid "Merchant%1$soffered contract%2$s;\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:380
|
#: src/webex/pages/popup.tsx:379
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:390
|
#: src/webex/pages/popup.tsx:389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Paid%1$sto merchant%2$s.\n"
|
"Paid%1$sto merchant%2$s.\n"
|
||||||
" (%3$s)\n"
|
" (%3$s)\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:399
|
#: src/webex/pages/popup.tsx:398
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown event (%1$s)"
|
msgid "Unknown event (%1$s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:442
|
#: src/webex/pages/popup.tsx:441
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve event history"
|
msgid "Error: could not retrieve event history"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:476
|
#: src/webex/pages/popup.tsx:466
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Your wallet has no events recorded."
|
msgid "Your wallet has no events recorded."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -198,105 +198,105 @@ msgstr ""
|
|||||||
msgid "Fatal error: \"%1$s\"."
|
msgid "Fatal error: \"%1$s\"."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:161
|
#: src/webex/pages/popup.tsx:160
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Balance"
|
msgid "Balance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:164
|
#: src/webex/pages/popup.tsx:163
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "History"
|
msgid "History"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:167
|
#: src/webex/pages/popup.tsx:166
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Debug"
|
msgid "Debug"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:247
|
#: src/webex/pages/popup.tsx:246
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "help"
|
msgid "help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:252
|
#: src/webex/pages/popup.tsx:251
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You have no balance to show. Need some\n"
|
"You have no balance to show. Need some\n"
|
||||||
" %1$s getting started?\n"
|
" %1$s getting started?\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:269
|
#: src/webex/pages/popup.tsx:268
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s incoming\n"
|
msgid "%1$s incoming\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:282
|
#: src/webex/pages/popup.tsx:281
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%1$s being spent\n"
|
msgid "%1$s being spent\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:308
|
#: src/webex/pages/popup.tsx:307
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve balance information."
|
msgid "Error: could not retrieve balance information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:335
|
#: src/webex/pages/popup.tsx:334
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Payback"
|
msgid "Payback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:336
|
#: src/webex/pages/popup.tsx:335
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Return Electronic Cash to Bank Account"
|
msgid "Return Electronic Cash to Bank Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:337
|
#: src/webex/pages/popup.tsx:336
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Manage Trusted Auditors and Exchanges"
|
msgid "Manage Trusted Auditors and Exchanges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:349
|
#: src/webex/pages/popup.tsx:348
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Bank requested reserve (%1$s) for\n"
|
"Bank requested reserve (%1$s) for\n"
|
||||||
" %2$s.\n"
|
" %2$s.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:360
|
#: src/webex/pages/popup.tsx:359
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Started to withdraw\n"
|
"Started to withdraw\n"
|
||||||
" %1$s from%2$s(%3$s).\n"
|
" %1$s from%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:370
|
#: src/webex/pages/popup.tsx:369
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Merchant%1$soffered contract%2$s;\n"
|
msgid "Merchant%1$soffered contract%2$s;\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:380
|
#: src/webex/pages/popup.tsx:379
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:390
|
#: src/webex/pages/popup.tsx:389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Paid%1$sto merchant%2$s.\n"
|
"Paid%1$sto merchant%2$s.\n"
|
||||||
" (%3$s)\n"
|
" (%3$s)\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:399
|
#: src/webex/pages/popup.tsx:398
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unknown event (%1$s)"
|
msgid "Unknown event (%1$s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:442
|
#: src/webex/pages/popup.tsx:441
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error: could not retrieve event history"
|
msgid "Error: could not retrieve event history"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/webex/pages/popup.tsx:476
|
#: src/webex/pages/popup.tsx:466
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Your wallet has no events recorded."
|
msgid "Your wallet has no events recorded."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
58
src/types.ts
58
src/types.ts
@ -84,43 +84,53 @@ export interface ReserveRecord {
|
|||||||
* The reserve public key.
|
* The reserve public key.
|
||||||
*/
|
*/
|
||||||
reserve_pub: string;
|
reserve_pub: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The reserve private key.
|
* The reserve private key.
|
||||||
*/
|
*/
|
||||||
reserve_priv: string;
|
reserve_priv: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The exchange base URL.
|
* The exchange base URL.
|
||||||
*/
|
*/
|
||||||
exchange_base_url: string;
|
exchange_base_url: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time when the reserve was created.
|
* Time when the reserve was created.
|
||||||
*/
|
*/
|
||||||
created: number;
|
created: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time when the reserve was last queried,
|
* Time when the reserve was depleted.
|
||||||
* or 'null' if it was never queried.
|
* Set to 0 if not depleted yet.
|
||||||
*/
|
*/
|
||||||
last_query: number | null;
|
timestamp_depleted: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time when the reserve was confirmed.
|
||||||
|
*
|
||||||
|
* Set to 0 if not confirmed yet.
|
||||||
|
*/
|
||||||
|
timestamp_confirmed: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current amount left in the reserve
|
* Current amount left in the reserve
|
||||||
*/
|
*/
|
||||||
current_amount: AmountJson | null;
|
current_amount: AmountJson | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amount requested when the reserve was created.
|
* Amount requested when the reserve was created.
|
||||||
* When a reserve is re-used (rare!) the current_amount can
|
* When a reserve is re-used (rare!) the current_amount can
|
||||||
* be higher than the requested_amount
|
* be higher than the requested_amount
|
||||||
*/
|
*/
|
||||||
requested_amount: AmountJson;
|
requested_amount: AmountJson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What's the current amount that sits
|
* What's the current amount that sits
|
||||||
* in precoins?
|
* in precoins?
|
||||||
*/
|
*/
|
||||||
precoin_amount: AmountJson;
|
precoin_amount: AmountJson;
|
||||||
/**
|
|
||||||
* The bank conformed that the reserve will eventually
|
|
||||||
* be filled with money.
|
|
||||||
*/
|
|
||||||
confirmed: boolean;
|
|
||||||
/**
|
/**
|
||||||
* We got some payback to this reserve. We'll cease to automatically
|
* We got some payback to this reserve. We'll cease to automatically
|
||||||
* withdraw money from it.
|
* withdraw money from it.
|
||||||
@ -1188,6 +1198,9 @@ export class ProposalRecord {
|
|||||||
@Checkable.Optional(Checkable.Number)
|
@Checkable.Optional(Checkable.Number)
|
||||||
id?: number;
|
id?: number;
|
||||||
|
|
||||||
|
@Checkable.Number
|
||||||
|
timestamp: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that a value matches the schema of this class and convert it into a
|
* Verify that a value matches the schema of this class and convert it into a
|
||||||
* member.
|
* member.
|
||||||
@ -1482,18 +1495,6 @@ export interface CheckPayResult {
|
|||||||
export type ConfirmPayResult = "paid" | "insufficient-balance";
|
export type ConfirmPayResult = "paid" | "insufficient-balance";
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Level of detail at which a history
|
|
||||||
* entry should be shown.
|
|
||||||
*/
|
|
||||||
export enum HistoryLevel {
|
|
||||||
Trace = 1,
|
|
||||||
Developer = 2,
|
|
||||||
Expert = 3,
|
|
||||||
User = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Activity history record.
|
* Activity history record.
|
||||||
*/
|
*/
|
||||||
@ -1518,11 +1519,6 @@ export interface HistoryRecord {
|
|||||||
* Details used when rendering the history record.
|
* Details used when rendering the history record.
|
||||||
*/
|
*/
|
||||||
detail: any;
|
detail: any;
|
||||||
|
|
||||||
/**
|
|
||||||
* Level of detail of the history entry.
|
|
||||||
*/
|
|
||||||
level: HistoryLevel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1701,6 +1697,18 @@ export interface PurchaseRecord {
|
|||||||
|
|
||||||
refundsPending: { [refundSig: string]: RefundPermission };
|
refundsPending: { [refundSig: string]: RefundPermission };
|
||||||
refundsDone: { [refundSig: string]: RefundPermission };
|
refundsDone: { [refundSig: string]: RefundPermission };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was the purchase made?
|
||||||
|
* Refers to the time that the user accepted.
|
||||||
|
*/
|
||||||
|
timestamp: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was the last refund made?
|
||||||
|
* Set to 0 if no refund was made on the purchase.
|
||||||
|
*/
|
||||||
|
timestamp_refund: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
266
src/wallet.ts
266
src/wallet.ts
@ -66,7 +66,6 @@ import {
|
|||||||
ExchangeHandle,
|
ExchangeHandle,
|
||||||
ExchangeRecord,
|
ExchangeRecord,
|
||||||
ExchangeWireFeesRecord,
|
ExchangeWireFeesRecord,
|
||||||
HistoryLevel,
|
|
||||||
HistoryRecord,
|
HistoryRecord,
|
||||||
Notifier,
|
Notifier,
|
||||||
PayCoinInfo,
|
PayCoinInfo,
|
||||||
@ -321,7 +320,7 @@ export const WALLET_PROTOCOL_VERSION = "0:0:0";
|
|||||||
* In the future we might consider adding migration functions for
|
* In the future we might consider adding migration functions for
|
||||||
* each version increment.
|
* each version increment.
|
||||||
*/
|
*/
|
||||||
export const WALLET_DB_VERSION = 19;
|
export const WALLET_DB_VERSION = 20;
|
||||||
|
|
||||||
const builtinCurrencies: CurrencyRecord[] = [
|
const builtinCurrencies: CurrencyRecord[] = [
|
||||||
{
|
{
|
||||||
@ -518,17 +517,6 @@ export namespace Stores {
|
|||||||
denomPubIndex = new Index<string, CoinRecord>(this, "denomPub", "denomPub");
|
denomPubIndex = new Index<string, CoinRecord>(this, "denomPub", "denomPub");
|
||||||
}
|
}
|
||||||
|
|
||||||
class HistoryStore extends Store<HistoryRecord> {
|
|
||||||
constructor() {
|
|
||||||
super("history", {
|
|
||||||
autoIncrement: true,
|
|
||||||
keyPath: "id",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
timestampIndex = new Index<number, HistoryRecord>(this, "timestamp", "timestamp");
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProposalsStore extends Store<ProposalRecord> {
|
class ProposalsStore extends Store<ProposalRecord> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("proposals", {
|
super("proposals", {
|
||||||
@ -536,6 +524,7 @@ export namespace Stores {
|
|||||||
keyPath: "id",
|
keyPath: "id",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
timestampIndex = new Index<string, ProposalRecord>(this, "timestamp", "timestamp");
|
||||||
}
|
}
|
||||||
|
|
||||||
class PurchasesStore extends Store<PurchaseRecord> {
|
class PurchasesStore extends Store<PurchaseRecord> {
|
||||||
@ -545,6 +534,7 @@ export namespace Stores {
|
|||||||
|
|
||||||
fulfillmentUrlIndex = new Index<string, PurchaseRecord>(this, "fulfillment_url", "contractTerms.fulfillment_url");
|
fulfillmentUrlIndex = new Index<string, PurchaseRecord>(this, "fulfillment_url", "contractTerms.fulfillment_url");
|
||||||
orderIdIndex = new Index<string, PurchaseRecord>(this, "order_id", "contractTerms.order_id");
|
orderIdIndex = new Index<string, PurchaseRecord>(this, "order_id", "contractTerms.order_id");
|
||||||
|
timestampIndex = new Index<string, PurchaseRecord>(this, "timestamp", "timestamp");
|
||||||
}
|
}
|
||||||
|
|
||||||
class DenominationsStore extends Store<DenominationRecord> {
|
class DenominationsStore extends Store<DenominationRecord> {
|
||||||
@ -577,6 +567,15 @@ export namespace Stores {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ReservesStore extends Store<ReserveRecord> {
|
||||||
|
constructor() {
|
||||||
|
super("reserves", {keyPath: "reserve_pub"});
|
||||||
|
}
|
||||||
|
timestampCreatedIndex = new Index<string, ReserveRecord>(this, "timestampCreated", "created");
|
||||||
|
timestampConfirmedIndex = new Index<string, ReserveRecord>(this, "timestampConfirmed", "timestamp_confirmed");
|
||||||
|
timestampDepletedIndex = new Index<string, ReserveRecord>(this, "timestampDepleted", "timestamp_depleted");
|
||||||
|
}
|
||||||
|
|
||||||
export const coins = new CoinsStore();
|
export const coins = new CoinsStore();
|
||||||
export const coinsReturns = new Store<CoinsReturnRecord>("coinsReturns", {keyPath: "contractTermsHash"});
|
export const coinsReturns = new Store<CoinsReturnRecord>("coinsReturns", {keyPath: "contractTermsHash"});
|
||||||
export const config = new ConfigStore();
|
export const config = new ConfigStore();
|
||||||
@ -584,12 +583,11 @@ export namespace Stores {
|
|||||||
export const denominations = new DenominationsStore();
|
export const denominations = new DenominationsStore();
|
||||||
export const exchangeWireFees = new ExchangeWireFeesStore();
|
export const exchangeWireFees = new ExchangeWireFeesStore();
|
||||||
export const exchanges = new ExchangeStore();
|
export const exchanges = new ExchangeStore();
|
||||||
export const history = new HistoryStore();
|
|
||||||
export const nonces = new NonceStore();
|
export const nonces = new NonceStore();
|
||||||
export const precoins = new Store<PreCoinRecord>("precoins", {keyPath: "coinPub"});
|
export const precoins = new Store<PreCoinRecord>("precoins", {keyPath: "coinPub"});
|
||||||
export const proposals = new ProposalsStore();
|
export const proposals = new ProposalsStore();
|
||||||
export const refresh = new Store<RefreshSessionRecord>("refresh", {keyPath: "id", autoIncrement: true});
|
export const refresh = new Store<RefreshSessionRecord>("refresh", {keyPath: "id", autoIncrement: true});
|
||||||
export const reserves = new Store<ReserveRecord>("reserves", {keyPath: "reserve_pub"});
|
export const reserves = new ReservesStore();
|
||||||
export const purchases = new PurchasesStore();
|
export const purchases = new PurchasesStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,24 +950,12 @@ export class Wallet {
|
|||||||
payReq,
|
payReq,
|
||||||
refundsDone: {},
|
refundsDone: {},
|
||||||
refundsPending: {},
|
refundsPending: {},
|
||||||
};
|
|
||||||
|
|
||||||
const historyEntry: HistoryRecord = {
|
|
||||||
detail: {
|
|
||||||
amount: proposal.contractTerms.amount,
|
|
||||||
contractTermsHash: proposal.contractTermsHash,
|
|
||||||
fulfillmentUrl: proposal.contractTerms.fulfillment_url,
|
|
||||||
merchantName: proposal.contractTerms.merchant.name,
|
|
||||||
},
|
|
||||||
level: HistoryLevel.User,
|
|
||||||
subjectId: `contract-${proposal.contractTermsHash}`,
|
|
||||||
timestamp: (new Date()).getTime(),
|
timestamp: (new Date()).getTime(),
|
||||||
type: "pay",
|
timestamp_refund: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.put(Stores.purchases, t)
|
.put(Stores.purchases, t)
|
||||||
.put(Stores.history, historyEntry)
|
|
||||||
.putAll(Stores.coins, payCoinInfo.map((pci) => pci.updatedCoin))
|
.putAll(Stores.coins, payCoinInfo.map((pci) => pci.updatedCoin))
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
@ -977,12 +963,6 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async putHistory(historyEntry: HistoryRecord): Promise<void> {
|
|
||||||
await this.q().put(Stores.history, historyEntry).finish();
|
|
||||||
this.notifier.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a proposal in the database and return an id for it to
|
* Save a proposal in the database and return an id for it to
|
||||||
* retrieve it later.
|
* retrieve it later.
|
||||||
@ -1115,23 +1095,7 @@ export class Wallet {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const reserve = await this.updateReserve(reserveRecord.reserve_pub);
|
const reserve = await this.updateReserve(reserveRecord.reserve_pub);
|
||||||
const n = await this.depleteReserve(reserve);
|
await this.depleteReserve(reserve);
|
||||||
|
|
||||||
if (n !== 0) {
|
|
||||||
const depleted: HistoryRecord = {
|
|
||||||
detail: {
|
|
||||||
currentAmount: reserveRecord.current_amount,
|
|
||||||
exchangeBaseUrl: reserveRecord.exchange_base_url,
|
|
||||||
requestedAmount: reserveRecord.requested_amount,
|
|
||||||
reservePub: reserveRecord.reserve_pub,
|
|
||||||
},
|
|
||||||
level: HistoryLevel.User,
|
|
||||||
subjectId: `reserve-progress-${reserveRecord.reserve_pub}`,
|
|
||||||
timestamp: (new Date()).getTime(),
|
|
||||||
type: "depleted-reserve",
|
|
||||||
};
|
|
||||||
await this.q().put(Stores.history, depleted).finish();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// random, exponential backoff truncated at 3 minutes
|
// random, exponential backoff truncated at 3 minutes
|
||||||
const nextDelay = Math.min(2 * retryDelayMs + retryDelayMs * Math.random(), 3000 * 60);
|
const nextDelay = Math.min(2 * retryDelayMs + retryDelayMs * Math.random(), 3000 * 60);
|
||||||
@ -1143,8 +1107,12 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a planchet, withdraw a coin from the exchange.
|
||||||
|
*/
|
||||||
private async processPreCoin(preCoin: PreCoinRecord,
|
private async processPreCoin(preCoin: PreCoinRecord,
|
||||||
retryDelayMs = 200): Promise<void> {
|
retryDelayMs = 200): Promise<void> {
|
||||||
|
// Throttle concurrent executions of this function, so we don't withdraw too many coins at once.
|
||||||
if (this.processPreCoinConcurrent >= 4 || this.processPreCoinThrottle[preCoin.exchangeBaseUrl]) {
|
if (this.processPreCoinConcurrent >= 4 || this.processPreCoinThrottle[preCoin.exchangeBaseUrl]) {
|
||||||
console.log("delaying processPreCoin");
|
console.log("delaying processPreCoin");
|
||||||
this.timerGroup.after(retryDelayMs, () => this.processPreCoin(preCoin, Math.min(retryDelayMs * 2, 5 * 60 * 1000)));
|
this.timerGroup.after(retryDelayMs, () => this.processPreCoin(preCoin, Math.min(retryDelayMs * 2, 5 * 60 * 1000)));
|
||||||
@ -1156,7 +1124,7 @@ export class Wallet {
|
|||||||
const exchange = await this.q().get(Stores.exchanges,
|
const exchange = await this.q().get(Stores.exchanges,
|
||||||
preCoin.exchangeBaseUrl);
|
preCoin.exchangeBaseUrl);
|
||||||
if (!exchange) {
|
if (!exchange) {
|
||||||
console.error("db inconsistend: exchange for precoin not found");
|
console.error("db inconsistent: exchange for precoin not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const denom = await this.q().get(Stores.denominations,
|
const denom = await this.q().get(Stores.denominations,
|
||||||
@ -1182,20 +1150,10 @@ export class Wallet {
|
|||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
const historyEntry: HistoryRecord = {
|
|
||||||
detail: {
|
|
||||||
coinPub: coin.coinPub,
|
|
||||||
},
|
|
||||||
level: HistoryLevel.Expert,
|
|
||||||
timestamp: (new Date()).getTime(),
|
|
||||||
type: "withdraw",
|
|
||||||
};
|
|
||||||
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.mutate(Stores.reserves, preCoin.reservePub, mutateReserve)
|
.mutate(Stores.reserves, preCoin.reservePub, mutateReserve)
|
||||||
.delete("precoins", coin.coinPub)
|
.delete("precoins", coin.coinPub)
|
||||||
.add(Stores.coins, coin)
|
.add(Stores.coins, coin)
|
||||||
.add(Stores.history, historyEntry)
|
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
this.notifier.notify();
|
this.notifier.notify();
|
||||||
@ -1228,28 +1186,17 @@ export class Wallet {
|
|||||||
const canonExchange = canonicalizeBaseUrl(req.exchange);
|
const canonExchange = canonicalizeBaseUrl(req.exchange);
|
||||||
|
|
||||||
const reserveRecord: ReserveRecord = {
|
const reserveRecord: ReserveRecord = {
|
||||||
confirmed: false,
|
|
||||||
created: now,
|
created: now,
|
||||||
current_amount: null,
|
current_amount: null,
|
||||||
exchange_base_url: canonExchange,
|
exchange_base_url: canonExchange,
|
||||||
hasPayback: false,
|
hasPayback: false,
|
||||||
last_query: null,
|
|
||||||
precoin_amount: Amounts.getZero(req.amount.currency),
|
precoin_amount: Amounts.getZero(req.amount.currency),
|
||||||
requested_amount: req.amount,
|
requested_amount: req.amount,
|
||||||
reserve_priv: keypair.priv,
|
reserve_priv: keypair.priv,
|
||||||
reserve_pub: keypair.pub,
|
reserve_pub: keypair.pub,
|
||||||
senderWire: req.senderWire,
|
senderWire: req.senderWire,
|
||||||
};
|
timestamp_confirmed: 0,
|
||||||
|
timestamp_depleted: 0,
|
||||||
const historyEntry = {
|
|
||||||
detail: {
|
|
||||||
requestedAmount: req.amount,
|
|
||||||
reservePub: reserveRecord.reserve_pub,
|
|
||||||
},
|
|
||||||
level: HistoryLevel.Expert,
|
|
||||||
subjectId: `reserve-progress-${reserveRecord.reserve_pub}`,
|
|
||||||
timestamp: now,
|
|
||||||
type: "create-reserve",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const exchangeInfo = await this.updateExchangeFromUrl(req.exchange);
|
const exchangeInfo = await this.updateExchangeFromUrl(req.exchange);
|
||||||
@ -1271,7 +1218,6 @@ export class Wallet {
|
|||||||
await this.q()
|
await this.q()
|
||||||
.put(Stores.currencies, currencyRecord)
|
.put(Stores.currencies, currencyRecord)
|
||||||
.put(Stores.reserves, reserveRecord)
|
.put(Stores.reserves, reserveRecord)
|
||||||
.put(Stores.history, historyEntry)
|
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
const r: CreateReserveResponse = {
|
const r: CreateReserveResponse = {
|
||||||
@ -1301,21 +1247,9 @@ export class Wallet {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("reserve confirmed");
|
console.log("reserve confirmed");
|
||||||
const historyEntry: HistoryRecord = {
|
reserve.timestamp_confirmed = now;
|
||||||
detail: {
|
|
||||||
exchangeBaseUrl: reserve.exchange_base_url,
|
|
||||||
requestedAmount: reserve.requested_amount,
|
|
||||||
reservePub: req.reservePub,
|
|
||||||
},
|
|
||||||
level: HistoryLevel.User,
|
|
||||||
subjectId: `reserve-progress-${reserve.reserve_pub}`,
|
|
||||||
timestamp: now,
|
|
||||||
type: "confirm-reserve",
|
|
||||||
};
|
|
||||||
reserve.confirmed = true;
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.put(Stores.reserves, reserve)
|
.put(Stores.reserves, reserve)
|
||||||
.put(Stores.history, historyEntry)
|
|
||||||
.finish();
|
.finish();
|
||||||
this.notifier.notify();
|
this.notifier.notify();
|
||||||
|
|
||||||
@ -1366,8 +1300,11 @@ export class Wallet {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Withdraw coins from a reserve until it is empty.
|
* Withdraw coins from a reserve until it is empty.
|
||||||
|
*
|
||||||
|
* When finished, marks the reserve as depleted by setting
|
||||||
|
* the depleted timestamp.
|
||||||
*/
|
*/
|
||||||
private async depleteReserve(reserve: ReserveRecord): Promise<number> {
|
private async depleteReserve(reserve: ReserveRecord): Promise<void> {
|
||||||
console.log("depleting reserve");
|
console.log("depleting reserve");
|
||||||
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");
|
||||||
@ -1377,6 +1314,7 @@ export class Wallet {
|
|||||||
throw Error("can't withdraw when amount is unknown");
|
throw Error("can't withdraw when amount is unknown");
|
||||||
}
|
}
|
||||||
const denomsForWithdraw = await this.getVerifiedWithdrawDenomList(reserve.exchange_base_url, withdrawAmount);
|
const denomsForWithdraw = await this.getVerifiedWithdrawDenomList(reserve.exchange_base_url, withdrawAmount);
|
||||||
|
const smallestAmount = await this.getVerifiedSmallestWithdrawAmount(reserve.exchange_base_url);
|
||||||
|
|
||||||
console.log(`withdrawing ${denomsForWithdraw.length} coins`);
|
console.log(`withdrawing ${denomsForWithdraw.length} coins`);
|
||||||
|
|
||||||
@ -1398,6 +1336,11 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
r.current_amount = result.amount;
|
r.current_amount = result.amount;
|
||||||
|
|
||||||
|
// Reserve is depleted if the amount left is too small to withdraw
|
||||||
|
if (Amounts.cmp(r.current_amount, smallestAmount) < 0) {
|
||||||
|
r.timestamp_depleted = (new Date()).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`after creating precoin: current ${amountToPretty(r.current_amount)}, precoin: ${amountToPretty(
|
console.log(`after creating precoin: current ${amountToPretty(r.current_amount)}, precoin: ${amountToPretty(
|
||||||
r.precoin_amount)})}`);
|
r.precoin_amount)})}`);
|
||||||
|
|
||||||
@ -1413,7 +1356,6 @@ export class Wallet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(ps);
|
await Promise.all(ps);
|
||||||
return ps.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1437,24 +1379,9 @@ export class Wallet {
|
|||||||
if (!reserveInfo) {
|
if (!reserveInfo) {
|
||||||
throw Error();
|
throw Error();
|
||||||
}
|
}
|
||||||
const oldAmount = reserve.current_amount;
|
|
||||||
const newAmount = reserveInfo.balance;
|
|
||||||
reserve.current_amount = reserveInfo.balance;
|
reserve.current_amount = reserveInfo.balance;
|
||||||
const historyEntry = {
|
|
||||||
detail: {
|
|
||||||
newAmount,
|
|
||||||
oldAmount,
|
|
||||||
requestedAmount: reserve.requested_amount,
|
|
||||||
reservePub,
|
|
||||||
},
|
|
||||||
level: HistoryLevel.Developer,
|
|
||||||
subjectId: `reserve-progress-${reserve.reserve_pub}`,
|
|
||||||
timestamp: (new Date()).getTime(),
|
|
||||||
type: "reserve-update",
|
|
||||||
};
|
|
||||||
await this.q()
|
await this.q()
|
||||||
.put(Stores.reserves, reserve)
|
.put(Stores.reserves, reserve)
|
||||||
.put(Stores.history, historyEntry)
|
|
||||||
.finish();
|
.finish();
|
||||||
this.notifier.notify();
|
this.notifier.notify();
|
||||||
return reserve;
|
return reserve;
|
||||||
@ -1489,6 +1416,52 @@ export class Wallet {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the smallest withdrawable amount possible, based on verified denominations.
|
||||||
|
*
|
||||||
|
* Writes to the DB in order to record the result from verifying
|
||||||
|
* denominations.
|
||||||
|
*/
|
||||||
|
async getVerifiedSmallestWithdrawAmount(exchangeBaseUrl: string): Promise<AmountJson> {
|
||||||
|
const exchange = await this.q().get(Stores.exchanges, exchangeBaseUrl);
|
||||||
|
if (!exchange) {
|
||||||
|
throw Error(`exchange ${exchangeBaseUrl} not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const possibleDenoms = await (
|
||||||
|
this.q().iterIndex(Stores.denominations.exchangeBaseUrlIndex,
|
||||||
|
exchange.baseUrl)
|
||||||
|
.filter((d) => d.status === DenominationStatus.Unverified || d.status === DenominationStatus.VerifiedGood)
|
||||||
|
.toArray()
|
||||||
|
);
|
||||||
|
possibleDenoms.sort((d1, d2) => {
|
||||||
|
let a1 = Amounts.add(d1.feeWithdraw, d1.value).amount;
|
||||||
|
let a2 = Amounts.add(d2.feeWithdraw, d2.value).amount;
|
||||||
|
return Amounts.cmp(a1, a2);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let denom of possibleDenoms) {
|
||||||
|
if (denom.status === DenominationStatus.VerifiedGood) {
|
||||||
|
return Amounts.add(denom.feeWithdraw, denom.value).amount;
|
||||||
|
}
|
||||||
|
console.log(`verifying denom ${denom.denomPub.substr(0, 15)}`);
|
||||||
|
const valid = await this.cryptoApi.isValidDenom(denom,
|
||||||
|
exchange.masterPublicKey);
|
||||||
|
if (!valid) {
|
||||||
|
denom.status = DenominationStatus.VerifiedBad;
|
||||||
|
} else {
|
||||||
|
denom.status = DenominationStatus.VerifiedGood;
|
||||||
|
}
|
||||||
|
await this.q().put(Stores.denominations, denom).finish();
|
||||||
|
if (valid) {
|
||||||
|
return Amounts.add(denom.feeWithdraw, denom.value).amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Amounts.getZero(exchange.currency);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of denominations to withdraw from the given exchange for the
|
* Get a list of denominations to withdraw from the given exchange for the
|
||||||
* given amount, making sure that all denominations' signatures are verified.
|
* given amount, making sure that all denominations' signatures are verified.
|
||||||
@ -1895,7 +1868,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function collectPendingWithdraw(r: ReserveRecord, balance: WalletBalance) {
|
function collectPendingWithdraw(r: ReserveRecord, balance: WalletBalance) {
|
||||||
if (!r.confirmed) {
|
if (!r.timestamp_confirmed) {
|
||||||
return balance;
|
return balance;
|
||||||
}
|
}
|
||||||
let amount = r.current_amount;
|
let amount = r.current_amount;
|
||||||
@ -2253,16 +2226,79 @@ export class Wallet {
|
|||||||
* Retrive the full event history for this wallet.
|
* Retrive the full event history for this wallet.
|
||||||
*/
|
*/
|
||||||
async getHistory(): Promise<{history: HistoryRecord[]}> {
|
async getHistory(): Promise<{history: HistoryRecord[]}> {
|
||||||
function collect(x: any, acc: any) {
|
const history: HistoryRecord[] = [];
|
||||||
acc.push(x);
|
|
||||||
return acc;
|
// FIXME: do pagination instead of generating the full history
|
||||||
|
|
||||||
|
const proposals = await this.q().iter<ProposalRecord>(Stores.proposals).toArray();
|
||||||
|
for (let p of proposals) {
|
||||||
|
history.push({
|
||||||
|
type: "offer-contract",
|
||||||
|
timestamp: p.timestamp,
|
||||||
|
detail: {
|
||||||
|
contractTermsHash: p.contractTermsHash,
|
||||||
|
merchantName: p.contractTerms.merchant.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const history = await (
|
const purchases = await this.q().iter<PurchaseRecord>(Stores.purchases).toArray();
|
||||||
this.q()
|
for (let p of purchases) {
|
||||||
.iterIndex(Stores.history.timestampIndex)
|
history.push({
|
||||||
.reduce(collect, []));
|
type: "pay",
|
||||||
|
timestamp: p.timestamp,
|
||||||
|
detail: {
|
||||||
|
amount: p.contractTerms.amount,
|
||||||
|
contractTermsHash: p.contractTermsHash,
|
||||||
|
fulfillmentUrl: p.contractTerms.fulfillment_url,
|
||||||
|
merchantName: p.contractTerms.merchant.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (p.timestamp_refund) {
|
||||||
|
const amountsPending = Object.keys(p.refundsPending).map((x) => p.refundsPending[x].refund_amount);
|
||||||
|
const amountsDone = Object.keys(p.refundsDone).map((x) => p.refundsDone[x].refund_amount);
|
||||||
|
const amounts: AmountJson[] = amountsPending.concat(amountsDone);
|
||||||
|
const amount = Amounts.add(Amounts.getZero(p.contractTerms.amount.currency), ...amounts).amount;
|
||||||
|
|
||||||
|
history.push({
|
||||||
|
type: "refund",
|
||||||
|
timestamp: p.timestamp_refund,
|
||||||
|
detail: {
|
||||||
|
refundAmount: amount,
|
||||||
|
contractTermsHash: p.contractTermsHash,
|
||||||
|
fulfillmentUrl: p.contractTerms.fulfillment_url,
|
||||||
|
merchantName: p.contractTerms.merchant.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reserves: ReserveRecord[] = await this.q().iter<ReserveRecord>(Stores.reserves).toArray();
|
||||||
|
for (let r of reserves) {
|
||||||
|
history.push({
|
||||||
|
type: "create-reserve",
|
||||||
|
timestamp: r.created,
|
||||||
|
detail: {
|
||||||
|
exchangeBaseUrl: r.exchange_base_url,
|
||||||
|
requestedAmount: r.requested_amount,
|
||||||
|
reservePub: r.reserve_pub,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (r.timestamp_depleted) {
|
||||||
|
history.push({
|
||||||
|
type: "depleted-reserve",
|
||||||
|
timestamp: r.timestamp_depleted,
|
||||||
|
detail: {
|
||||||
|
exchangeBaseUrl: r.exchange_base_url,
|
||||||
|
requestedAmount: r.requested_amount,
|
||||||
|
reservePub: r.reserve_pub,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
history.sort((h1, h2) => Math.sign(h1.timestamp - h2.timestamp));
|
||||||
|
|
||||||
return {history};
|
return {history};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2656,6 +2692,8 @@ export class Wallet {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.timestamp_refund = (new Date()).getTime();
|
||||||
|
|
||||||
for (const perm of refundPermissions) {
|
for (const perm of refundPermissions) {
|
||||||
if (!t.refundsPending[perm.merchant_sig] && !t.refundsDone[perm.merchant_sig]) {
|
if (!t.refundsPending[perm.merchant_sig] && !t.refundsDone[perm.merchant_sig]) {
|
||||||
t.refundsPending[perm.merchant_sig] = perm;
|
t.refundsPending[perm.merchant_sig] = perm;
|
||||||
|
@ -92,10 +92,6 @@ export interface MessageMap {
|
|||||||
request: { contract: object };
|
request: { contract: object };
|
||||||
response: string;
|
response: string;
|
||||||
};
|
};
|
||||||
"put-history-entry": {
|
|
||||||
request: { historyEntry: types.HistoryRecord };
|
|
||||||
response: void;
|
|
||||||
};
|
|
||||||
"save-proposal": {
|
"save-proposal": {
|
||||||
request: { proposal: types.ProposalRecord };
|
request: { proposal: types.ProposalRecord };
|
||||||
response: void;
|
response: void;
|
||||||
|
@ -210,6 +210,7 @@ async function downloadContract(url: string, nonce: string): Promise<any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function processProposal(proposal: any) {
|
async function processProposal(proposal: any) {
|
||||||
|
|
||||||
if (!proposal.data) {
|
if (!proposal.data) {
|
||||||
console.error("field proposal.data field missing");
|
console.error("field proposal.data field missing");
|
||||||
return;
|
return;
|
||||||
@ -235,17 +236,12 @@ async function processProposal(proposal: any) {
|
|||||||
// bad contract / name not included
|
// bad contract / name not included
|
||||||
}
|
}
|
||||||
|
|
||||||
const historyEntry = {
|
let proposalId = await wxApi.saveProposal({
|
||||||
detail: {
|
|
||||||
contractHash,
|
|
||||||
merchantName,
|
|
||||||
},
|
|
||||||
subjectId: `contract-${contractHash}`,
|
|
||||||
timestamp: (new Date()).getTime(),
|
timestamp: (new Date()).getTime(),
|
||||||
type: "offer-contract",
|
contractTerms: proposal.data,
|
||||||
};
|
contractTermsHash: proposal.hash,
|
||||||
await wxApi.putHistory(historyEntry);
|
merchantSig: proposal.sig,
|
||||||
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 = {
|
const params = {
|
||||||
|
@ -29,7 +29,6 @@ import * as i18n from "../../i18n";
|
|||||||
import {
|
import {
|
||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
HistoryLevel,
|
|
||||||
HistoryRecord,
|
HistoryRecord,
|
||||||
WalletBalance,
|
WalletBalance,
|
||||||
WalletBalanceEntry,
|
WalletBalanceEntry,
|
||||||
@ -354,8 +353,7 @@ function formatHistoryItem(historyItem: HistoryRecord) {
|
|||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
);
|
);
|
||||||
case "confirm-reserve": {
|
case "confirm-reserve": {
|
||||||
// FIXME: eventually remove compat fix
|
const exchange = (new URI(d.exchangeBaseUrl)).host();
|
||||||
const exchange = d.exchangeBaseUrl ? (new URI(d.exchangeBaseUrl)).host() : "??";
|
|
||||||
const pub = abbrev(d.reservePub);
|
const pub = abbrev(d.reservePub);
|
||||||
return (
|
return (
|
||||||
<i18n.Translate wrap="p">
|
<i18n.Translate wrap="p">
|
||||||
@ -369,7 +367,7 @@ function formatHistoryItem(historyItem: HistoryRecord) {
|
|||||||
const link = chrome.extension.getURL("view-contract.html");
|
const link = chrome.extension.getURL("view-contract.html");
|
||||||
return (
|
return (
|
||||||
<i18n.Translate wrap="p">
|
<i18n.Translate wrap="p">
|
||||||
Merchant <em>{abbrev(d.merchantName, 15)}</em> offered contract <a href={link}>{abbrev(d.contractHash)}</a>;
|
Merchant <em>{abbrev(d.merchantName, 15)}</em> offered contract <a href={link}>{abbrev(d.contractTermsHash)}</a>;
|
||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -395,6 +393,14 @@ function formatHistoryItem(historyItem: HistoryRecord) {
|
|||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
case "refund": {
|
||||||
|
const merchantElem = <em>{abbrev(d.merchantName, 15)}</em>;
|
||||||
|
return (
|
||||||
|
<i18n.Translate wrap="p">
|
||||||
|
Merchant <span>{merchantElem}</span> gave a refund over <span>{renderAmount(d.refundAmount)}</span>.
|
||||||
|
</i18n.Translate>
|
||||||
|
);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return (<p>{i18n.str`Unknown event (${historyItem.type})`}</p>);
|
return (<p>{i18n.str`Unknown event (${historyItem.type})`}</p>);
|
||||||
}
|
}
|
||||||
@ -447,17 +453,8 @@ class WalletHistory extends React.Component<any, any> {
|
|||||||
return <span />;
|
return <span />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subjectMemo: {[s: string]: boolean} = {};
|
|
||||||
const listing: any[] = [];
|
const listing: any[] = [];
|
||||||
for (const record of history.reverse()) {
|
for (const record of history.reverse()) {
|
||||||
if (record.subjectId && subjectMemo[record.subjectId]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (record.level !== undefined && record.level < HistoryLevel.User) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
subjectMemo[record.subjectId as string] = true;
|
|
||||||
|
|
||||||
const item = (
|
const item = (
|
||||||
<div className="historyItem">
|
<div className="historyItem">
|
||||||
<div className="historyDate">
|
<div className="historyDate">
|
||||||
|
@ -63,10 +63,12 @@ const RefundDetail = ({purchase, fullRefundFees}: {purchase: types.PurchaseRecor
|
|||||||
amountDone = types.Amounts.add(amountDone, purchase.refundsDone[k].refund_amount).amount;
|
amountDone = types.Amounts.add(amountDone, purchase.refundsDone[k].refund_amount).amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasPending = amountPending.fraction !== 0 || amountPending.value !== 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Refund fully received: <AmountDisplay amount={amountDone} /> (refund fees: <AmountDisplay amount={fullRefundFees} />)</p>
|
{hasPending ? <p>Refund pending: <AmountDisplay amount={amountPending} /></p> : null}
|
||||||
<p>Refund incoming: <AmountDisplay amount={amountPending} /></p>
|
<p>Refund received: <AmountDisplay amount={amountDone} /> (refund fees: <AmountDisplay amount={fullRefundFees} />)</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -61,7 +61,7 @@ class ReserveView extends React.Component<ReserveViewProps, {}> {
|
|||||||
<li>Created: {(new Date(r.created * 1000).toString())}</li>
|
<li>Created: {(new Date(r.created * 1000).toString())}</li>
|
||||||
<li>Current: {r.current_amount ? renderAmount(r.current_amount!) : "null"}</li>
|
<li>Current: {r.current_amount ? renderAmount(r.current_amount!) : "null"}</li>
|
||||||
<li>Requested: {renderAmount(r.requested_amount)}</li>
|
<li>Requested: {renderAmount(r.requested_amount)}</li>
|
||||||
<li>Confirmed: {r.confirmed}</li>
|
<li>Confirmed: {r.timestamp_confirmed}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -226,7 +226,7 @@ export function hashContract(contract: object): Promise<string> {
|
|||||||
* the proposal is stored under.
|
* the proposal is stored under.
|
||||||
*/
|
*/
|
||||||
export function saveProposal(proposal: any): Promise<number> {
|
export function saveProposal(proposal: any): Promise<number> {
|
||||||
return callBackend("save-proposal", proposal);
|
return callBackend("save-proposal", { proposal });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,13 +243,6 @@ export function queryPayment(url: string): Promise<QueryPaymentResult> {
|
|||||||
return callBackend("query-payment", { url });
|
return callBackend("query-payment", { url });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new history item.
|
|
||||||
*/
|
|
||||||
export function putHistory(historyEntry: any): Promise<void> {
|
|
||||||
return callBackend("put-history-entry", { historyEntry });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark a payment as succeeded.
|
* Mark a payment as succeeded.
|
||||||
*/
|
*/
|
||||||
|
@ -177,19 +177,9 @@ function handleMessage(sender: MessageSender,
|
|||||||
return hash;
|
return hash;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case "put-history-entry": {
|
|
||||||
if (!detail.historyEntry) {
|
|
||||||
return Promise.resolve({ error: "historyEntry missing" });
|
|
||||||
}
|
|
||||||
return needsWallet().putHistory(detail.historyEntry);
|
|
||||||
}
|
|
||||||
case "save-proposal": {
|
case "save-proposal": {
|
||||||
console.log("handling save-proposal", detail);
|
console.log("handling save-proposal", detail);
|
||||||
const checkedRecord = ProposalRecord.checked({
|
const checkedRecord = ProposalRecord.checked(detail.proposal);
|
||||||
contractTerms: detail.data,
|
|
||||||
contractTermsHash: detail.hash,
|
|
||||||
merchantSig: detail.sig,
|
|
||||||
});
|
|
||||||
return needsWallet().saveProposal(checkedRecord);
|
return needsWallet().saveProposal(checkedRecord);
|
||||||
}
|
}
|
||||||
case "reserve-creation-info": {
|
case "reserve-creation-info": {
|
||||||
|
@ -63,12 +63,14 @@
|
|||||||
"src/webex/pages/logs.tsx",
|
"src/webex/pages/logs.tsx",
|
||||||
"src/webex/pages/payback.tsx",
|
"src/webex/pages/payback.tsx",
|
||||||
"src/webex/pages/popup.tsx",
|
"src/webex/pages/popup.tsx",
|
||||||
|
"src/webex/pages/refund.tsx",
|
||||||
"src/webex/pages/reset-required.tsx",
|
"src/webex/pages/reset-required.tsx",
|
||||||
"src/webex/pages/return-coins.tsx",
|
"src/webex/pages/return-coins.tsx",
|
||||||
"src/webex/pages/show-db.ts",
|
"src/webex/pages/show-db.ts",
|
||||||
"src/webex/pages/tree.tsx",
|
"src/webex/pages/tree.tsx",
|
||||||
"src/webex/renderHtml.tsx",
|
"src/webex/renderHtml.tsx",
|
||||||
"src/webex/wxApi.ts",
|
"src/webex/wxApi.ts",
|
||||||
"src/webex/wxBackend.ts"
|
"src/webex/wxBackend.ts",
|
||||||
|
"src/wire.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user