aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-08-29 23:12:55 +0200
committerFlorian Dold <florian.dold@gmail.com>2019-08-29 23:12:55 +0200
commitdefbf625bdef0f8a666b72b8ce99de5e01af6b91 (patch)
tree1bfe7c1ae0b56721d764893f62aca17271a20dbd /src
parent1390175a9afc53948dd1d6f8a2f88e51c1bf53cc (diff)
url-based pay/withdraw, use react hooks
Diffstat (limited to 'src')
-rw-r--r--src/headless/taler-wallet-cli.ts7
-rw-r--r--src/http.ts50
-rw-r--r--src/i18n.tsx4
-rw-r--r--src/i18n/de.po273
-rw-r--r--src/i18n/en-US.po251
-rw-r--r--src/i18n/fr.po251
-rw-r--r--src/i18n/it.po251
-rw-r--r--src/i18n/strings.ts590
-rw-r--r--src/i18n/sv.po277
-rw-r--r--src/i18n/taler-wallet-webex.pot251
-rw-r--r--src/wallet.ts143
-rw-r--r--src/walletTypes.ts76
-rw-r--r--src/webex/messages.ts68
-rw-r--r--src/webex/pages/confirm-contract.tsx417
-rw-r--r--src/webex/pages/confirm-create-reserve.tsx526
-rw-r--r--src/webex/pages/pay.html (renamed from src/webex/pages/confirm-contract.html)2
-rw-r--r--src/webex/pages/pay.tsx173
-rw-r--r--src/webex/pages/withdraw.html (renamed from src/webex/pages/confirm-create-reserve.html)2
-rw-r--r--src/webex/pages/withdraw.tsx231
-rw-r--r--src/webex/style/wallet.css5
-rw-r--r--src/webex/wxApi.ts23
-rw-r--r--src/webex/wxBackend.ts262
22 files changed, 1782 insertions, 2351 deletions
diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts
index 65b2a0297..659cffe67 100644
--- a/src/headless/taler-wallet-cli.ts
+++ b/src/headless/taler-wallet-cli.ts
@@ -149,7 +149,7 @@ program
const {
reservePub,
confirmTransferUrl,
- } = await wallet.createReserveFromWithdrawUrl(
+ } = await wallet.acceptWithdrawal(
withdrawUrl,
selectedExchange,
);
@@ -191,11 +191,6 @@ program
process.exit(0);
return;
}
- if (result.status === "session-replayed") {
- console.log("already paid! (replayed in different session)");
- process.exit(0);
- return;
- }
if (result.status === "payment-possible") {
console.log("paying ...");
} else {
diff --git a/src/http.ts b/src/http.ts
index f450d8479..8c1f772d8 100644
--- a/src/http.ts
+++ b/src/http.ts
@@ -27,7 +27,6 @@ export interface HttpResponse {
responseJson: object & any;
}
-
/**
* The request library is bundled into an interface to make mocking easy.
*/
@@ -37,15 +36,16 @@ export interface HttpRequestLibrary {
postJson(url: string, body: any): Promise<HttpResponse>;
}
-
/**
* An implementation of the [[HttpRequestLibrary]] using the
* browser's XMLHttpRequest.
*/
export class BrowserHttpLib implements HttpRequestLibrary {
- private req(method: string,
- url: string,
- options?: any): Promise<HttpResponse> {
+ private req(
+ method: string,
+ url: string,
+ options?: any,
+ ): Promise<HttpResponse> {
return new Promise<HttpResponse>((resolve, reject) => {
const myRequest = new XMLHttpRequest();
myRequest.open(method, url);
@@ -54,11 +54,36 @@ export class BrowserHttpLib implements HttpRequestLibrary {
} else {
myRequest.send();
}
- myRequest.addEventListener("readystatechange", (e) => {
+
+ myRequest.onerror = e => {
+ console.error("http request error");
+ reject(Error("could not make XMLHttpRequest"));
+ };
+
+ myRequest.addEventListener("readystatechange", e => {
if (myRequest.readyState === XMLHttpRequest.DONE) {
- const responseJson = JSON.parse(myRequest.responseText);
+ if (myRequest.status === 0) {
+ reject(Error("HTTP Request failed (status code 0, maybe URI scheme is wrong?)"))
+ return;
+ }
+ if (myRequest.status != 200) {
+ reject(
+ Error(
+ `HTTP Response with unexpected status code ${myRequest.status}: ${myRequest.statusText}`,
+ ),
+ );
+ return;
+ }
+ let responseJson;
+ try {
+ responseJson = JSON.parse(myRequest.responseText);
+ } catch (e) {
+ reject(Error("Invalid JSON from HTTP response"));
+ return;
+ }
if (responseJson === null || typeof responseJson !== "object") {
reject(Error("Invalid JSON from HTTP response"));
+ return;
}
const resp = {
responseJson: responseJson,
@@ -70,27 +95,22 @@ export class BrowserHttpLib implements HttpRequestLibrary {
});
}
-
get(url: string) {
return this.req("get", url);
}
-
postJson(url: string, body: any) {
- return this.req("post", url, {req: JSON.stringify(body)});
+ return this.req("post", url, { req: JSON.stringify(body) });
}
-
postForm(url: string, form: any) {
- return this.req("post", url, {req: form});
+ return this.req("post", url, { req: form });
}
}
-
/**
* Exception thrown on request errors.
*/
export class RequestException {
- constructor(public detail: any) {
- }
+ constructor(public detail: any) {}
}
diff --git a/src/i18n.tsx b/src/i18n.tsx
index 29df1c5af..67df6c516 100644
--- a/src/i18n.tsx
+++ b/src/i18n.tsx
@@ -31,6 +31,8 @@ import * as React from "react";
const jed = setupJed();
+let enableTracing = false;
+
/**
* Set up jed library for internationalization,
@@ -94,7 +96,7 @@ function stringifyChildren(children: any): string {
return `%${n++}$s`;
});
const s = ss.join("").replace(/ +/g, " ").trim();
- console.log("translation lookup", JSON.stringify(s));
+ enableTracing && console.log("translation lookup", JSON.stringify(s));
return s;
}
diff --git a/src/i18n/de.po b/src/i18n/de.po
index 6bfda6706..fa55b7e9e 100644
--- a/src/i18n/de.po
+++ b/src/i18n/de.po
@@ -37,28 +37,28 @@ msgstr ""
msgid "time (ms/op)"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
#, c-format
msgid "show more details"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
#, c-format
msgid "Accepted exchanges:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
#, c-format
msgid "Exchanges in the wallet:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
#, 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:221
+#: src/webex/pages/pay.tsx:221
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@@ -66,180 +66,58 @@ msgid ""
"wallet."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
#, fuzzy, c-format
msgid "Confirm payment"
msgstr "Bezahlung bestätigen"
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
#, fuzzy, c-format
msgid "Submitting payment"
msgstr "Bezahlung bestätigen"
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
#, c-format
msgid ""
"You already paid for this, clicking \"Confirm payment\" will not cost money "
"again."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
#, fuzzy, c-format
msgid "Aborting payment ..."
msgstr "Bezahlung bestätigen"
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
#, c-format
msgid "Payment aborted!"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
#, fuzzy, c-format
msgid "Retry Payment"
msgstr "Bezahlung bestätigen"
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
#, fuzzy, c-format
msgid "Abort Payment"
msgstr "Bezahlung bestätigen"
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
#, fuzzy, c-format
msgid "The merchant %1$s offers you to purchase:"
msgstr "Der Händler %1$s möchte einen Vertrag über %2$s mit Ihnen abschließen."
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
#, c-format
msgid "The total price is %1$s (plus %2$s fees)."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
#, c-format
msgid "The total price is %1$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:128
-#, c-format
-msgid "Select"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:145
-#, c-format
-msgid "Error: URL may not be relative"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:160
-#, c-format
-msgid "Invalid exchange URL (%1$s)"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:210
-#, c-format
-msgid "The exchange is trusted by the wallet."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:216
-#, c-format
-msgid "The exchange is audited by a trusted auditor."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:222
-#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:231
-#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:243
-#, c-format
-msgid "Waiting for a response from %1$s %2$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:260
-#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:279
-#, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:290
-#, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:309
-#, c-format
-msgid "Accept fees and withdraw"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:314
-#, c-format
-msgid "Change Exchange Provider"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:335
-#, c-format
-msgid ""
-"Please select an exchange. You can review the details before after your "
-"selection."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
-#, c-format
-msgid "Select %1$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:370
-#, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:459
-#, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:468
-#, c-format
-msgid "Checking URL, please wait ..."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:482
-#, c-format
-msgid "Can't parse amount: %1$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:489
-#, c-format
-msgid "Can't parse wire_types: %1$s"
-msgstr ""
-
-#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
-#, c-format
-msgid "Fatal error: \"%1$s\"."
-msgstr ""
-
#: src/webex/pages/popup.tsx:165
#, c-format
msgid "Balance"
@@ -379,6 +257,127 @@ msgstr "Bezahlung bestätigen"
msgid "Cancel"
msgstr "Saldo"
+#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
+#, c-format
+msgid "Fatal error: \"%1$s\"."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:128
+#, c-format
+msgid "Select"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:145
+#, c-format
+msgid "Error: URL may not be relative"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:160
+#, c-format
+msgid "Invalid exchange URL (%1$s)"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:210
+#, c-format
+msgid "The exchange is trusted by the wallet."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:216
+#, c-format
+msgid "The exchange is audited by a trusted auditor."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:222
+#, c-format
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:231
+#, c-format
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:243
+#, c-format
+msgid "Waiting for a response from %1$s %2$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:260
+#, c-format
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:279
+#, c-format
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:290
+#, c-format
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:309
+#, c-format
+msgid "Accept fees and withdraw"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:314
+#, c-format
+msgid "Change Exchange Provider"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:335
+#, c-format
+msgid ""
+"Please select an exchange. You can review the details before after your "
+"selection."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
+#, c-format
+msgid "Select %1$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:370
+#, c-format
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:459
+#, c-format
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:468
+#, c-format
+msgid "Checking URL, please wait ..."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:482
+#, c-format
+msgid "Can't parse amount: %1$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:489
+#, c-format
+msgid "Can't parse wire_types: %1$s"
+msgstr ""
+
#: src/webex/renderHtml.tsx:225
#, fuzzy, c-format
msgid "Withdrawal fees:"
diff --git a/src/i18n/en-US.po b/src/i18n/en-US.po
index 6d57e0ea2..83f25dd3e 100644
--- a/src/i18n/en-US.po
+++ b/src/i18n/en-US.po
@@ -37,28 +37,28 @@ msgstr ""
msgid "time (ms/op)"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
#, c-format
msgid "show more details"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
#, c-format
msgid "Accepted exchanges:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
#, c-format
msgid "Exchanges in the wallet:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
#, 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:221
+#: src/webex/pages/pay.tsx:221
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
"wallet."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
#, c-format
msgid "Confirm payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
#, c-format
msgid "Submitting payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
#, c-format
msgid ""
"You already paid for this, clicking \"Confirm payment\" will not cost money "
"again."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
#, c-format
msgid "Aborting payment ..."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
#, c-format
msgid "Payment aborted!"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
#, c-format
msgid "Retry Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
#, c-format
msgid "Abort Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
#, c-format
msgid "The merchant %1$s offers you to purchase:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
#, c-format
msgid "The total price is %1$s (plus %2$s fees)."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
#, c-format
msgid "The total price is %1$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
#, c-format
-msgid "Select"
+msgid "Balance"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
#, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
#, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
#, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
#, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
#, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
#, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
#, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
#, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
#, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
#, c-format
-msgid ""
-"Please select an exchange. You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
#, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
#, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
#, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
#, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
#, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
#, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
msgstr ""
-#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
#, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
#, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
#, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
msgstr ""
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
#, c-format
-msgid "Debug"
+msgid "Wire to bank account"
msgstr ""
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
#, c-format
-msgid "help"
+msgid "Confirm"
msgstr ""
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
#, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
msgstr ""
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
#, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
msgstr ""
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
#, c-format
-msgid "%1$s being spent"
+msgid "Select"
msgstr ""
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
#, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
msgstr ""
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
#, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
#, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
#, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
msgstr ""
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
#, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
msgstr ""
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
#, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
msgstr ""
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
#, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
msgstr ""
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
#, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
msgstr ""
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
#, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
#, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
#, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
msgstr ""
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
#, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
msgstr ""
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
#, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange. You can review the details before after your "
+"selection."
msgstr ""
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
#, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
msgstr ""
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
#, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
#, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
msgstr ""
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
#, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
msgstr ""
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
#, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
msgstr ""
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
#, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
msgstr ""
#: src/webex/renderHtml.tsx:225
diff --git a/src/i18n/fr.po b/src/i18n/fr.po
index e7615e41c..1f0dc2a47 100644
--- a/src/i18n/fr.po
+++ b/src/i18n/fr.po
@@ -37,28 +37,28 @@ msgstr ""
msgid "time (ms/op)"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
#, c-format
msgid "show more details"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
#, c-format
msgid "Accepted exchanges:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
#, c-format
msgid "Exchanges in the wallet:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
#, 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:221
+#: src/webex/pages/pay.tsx:221
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
"wallet."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
#, c-format
msgid "Confirm payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
#, c-format
msgid "Submitting payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
#, c-format
msgid ""
"You already paid for this, clicking \"Confirm payment\" will not cost money "
"again."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
#, c-format
msgid "Aborting payment ..."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
#, c-format
msgid "Payment aborted!"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
#, c-format
msgid "Retry Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
#, c-format
msgid "Abort Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
#, c-format
msgid "The merchant %1$s offers you to purchase:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
#, c-format
msgid "The total price is %1$s (plus %2$s fees)."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
#, c-format
msgid "The total price is %1$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
#, c-format
-msgid "Select"
+msgid "Balance"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
#, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
#, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
#, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
#, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
#, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
#, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
#, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
#, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
#, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
#, c-format
-msgid ""
-"Please select an exchange. You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
#, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
#, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
#, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
#, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
#, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
#, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
msgstr ""
-#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
#, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
#, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
#, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
msgstr ""
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
#, c-format
-msgid "Debug"
+msgid "Wire to bank account"
msgstr ""
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
#, c-format
-msgid "help"
+msgid "Confirm"
msgstr ""
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
#, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
msgstr ""
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
#, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
msgstr ""
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
#, c-format
-msgid "%1$s being spent"
+msgid "Select"
msgstr ""
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
#, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
msgstr ""
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
#, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
#, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
#, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
msgstr ""
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
#, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
msgstr ""
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
#, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
msgstr ""
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
#, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
msgstr ""
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
#, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
msgstr ""
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
#, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
#, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
#, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
msgstr ""
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
#, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
msgstr ""
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
#, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange. You can review the details before after your "
+"selection."
msgstr ""
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
#, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
msgstr ""
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
#, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
#, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
msgstr ""
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
#, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
msgstr ""
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
#, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
msgstr ""
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
#, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
msgstr ""
#: src/webex/renderHtml.tsx:225
diff --git a/src/i18n/it.po b/src/i18n/it.po
index e7615e41c..1f0dc2a47 100644
--- a/src/i18n/it.po
+++ b/src/i18n/it.po
@@ -37,28 +37,28 @@ msgstr ""
msgid "time (ms/op)"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
#, c-format
msgid "show more details"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
#, c-format
msgid "Accepted exchanges:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
#, c-format
msgid "Exchanges in the wallet:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
#, 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:221
+#: src/webex/pages/pay.tsx:221
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
"wallet."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
#, c-format
msgid "Confirm payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
#, c-format
msgid "Submitting payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
#, c-format
msgid ""
"You already paid for this, clicking \"Confirm payment\" will not cost money "
"again."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
#, c-format
msgid "Aborting payment ..."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
#, c-format
msgid "Payment aborted!"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
#, c-format
msgid "Retry Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
#, c-format
msgid "Abort Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
#, c-format
msgid "The merchant %1$s offers you to purchase:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
#, c-format
msgid "The total price is %1$s (plus %2$s fees)."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
#, c-format
msgid "The total price is %1$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
#, c-format
-msgid "Select"
+msgid "Balance"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
#, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
#, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
#, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
#, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
#, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
#, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
#, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
#, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
#, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
#, c-format
-msgid ""
-"Please select an exchange. You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
#, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
#, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
#, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
#, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
#, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
#, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
msgstr ""
-#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
#, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
#, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
#, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
msgstr ""
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
#, c-format
-msgid "Debug"
+msgid "Wire to bank account"
msgstr ""
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
#, c-format
-msgid "help"
+msgid "Confirm"
msgstr ""
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
#, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
msgstr ""
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
#, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
msgstr ""
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
#, c-format
-msgid "%1$s being spent"
+msgid "Select"
msgstr ""
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
#, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
msgstr ""
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
#, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
#, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
#, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
msgstr ""
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
#, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
msgstr ""
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
#, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
msgstr ""
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
#, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
msgstr ""
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
#, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
msgstr ""
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
#, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
#, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
#, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
msgstr ""
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
#, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
msgstr ""
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
#, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange. You can review the details before after your "
+"selection."
msgstr ""
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
#, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
msgstr ""
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
#, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
#, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
msgstr ""
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
#, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
msgstr ""
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
#, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
msgstr ""
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
#, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
msgstr ""
#: src/webex/renderHtml.tsx:225
diff --git a/src/i18n/strings.ts b/src/i18n/strings.ts
index 9c2947c6c..066becf16 100644
--- a/src/i18n/strings.ts
+++ b/src/i18n/strings.ts
@@ -92,193 +92,193 @@ strings['de'] = {
null,
""
],
- "Select": [
+ "Balance": [
null,
- ""
+ "Saldo"
],
- "Error: URL may not be relative": [
+ "History": [
null,
- ""
+ "Verlauf"
],
- "Invalid exchange URL (%1$s)": [
+ "Debug": [
null,
- ""
+ "Debug"
],
- "The exchange is trusted by the wallet.": [
+ "help": [
null,
""
],
- "The exchange is audited by a trusted auditor.": [
+ "You have no balance to show. Need some %1$s getting started?": [
null,
- ""
+ "Sie haben kein Digitalgeld. Wollen Sie %1$s? abheben?"
],
- "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
+ "%1$s incoming": [
null,
""
],
- "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
+ "%1$s being spent": [
null,
""
],
- "Waiting for a response from %1$s %2$s": [
+ "Error: could not retrieve balance information.": [
null,
""
],
- "Information about fees will be available when an exchange provider is selected.": [
+ "Payback": [
null,
""
],
- "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
+ "Return Electronic Cash to Bank Account": [
null,
""
],
- "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
+ "Manage Trusted Auditors and Exchanges": [
null,
""
],
- "Accept fees and withdraw": [
+ "Bank requested reserve (%1$s) for %2$s.": [
null,
- ""
+ "Bank bestätig anlegen der Reserve (%1$s) bei %2$s"
],
- "Change Exchange Provider": [
+ "Started to withdraw %1$s from %2$s (%3$s).": [
null,
- ""
+ "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
],
- "Please select an exchange. You can review the details before after your selection.": [
+ "Merchant %1$s offered contract %2$s.": [
null,
- ""
+ "%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
],
- "Select %1$s": [
+ "Withdrew %1$s from %2$s (%3$s).": [
null,
- ""
+ "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
],
- "You are about to withdraw %1$s from your bank account into your wallet.": [
+ "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
null,
- ""
+ "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
],
- "Oops, something went wrong. The wallet responded with error status (%1$s).": [
+ "Merchant %1$s gave a refund over %2$s.": [
null,
- ""
+ "%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
],
- "Checking URL, please wait ...": [
+ "tip": [
null,
""
],
- "Can't parse amount: %1$s": [
+ "Merchant %1$s gave a %2$s of %3$s.": [
null,
- ""
+ "%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
],
- "Can't parse wire_types: %1$s": [
+ "You did not accept the tip yet.": [
null,
""
],
- "Fatal error: \"%1$s\".": [
+ "Unknown event (%1$s)": [
null,
""
],
- "Balance": [
+ "Error: could not retrieve event history": [
null,
- "Saldo"
+ ""
],
- "History": [
+ "Your wallet has no events recorded.": [
null,
- "Verlauf"
+ "Ihre Geldbörse verzeichnet keine Vorkommnisse."
],
- "Debug": [
+ "Wire to bank account": [
null,
- "Debug"
+ ""
],
- "help": [
+ "Confirm": [
null,
- ""
+ "Bezahlung bestätigen"
],
- "You have no balance to show. Need some %1$s getting started?": [
+ "Cancel": [
null,
- "Sie haben kein Digitalgeld. Wollen Sie %1$s? abheben?"
+ "Saldo"
],
- "%1$s incoming": [
+ "Fatal error: \"%1$s\".": [
null,
""
],
- "%1$s being spent": [
+ "Select": [
null,
""
],
- "Error: could not retrieve balance information.": [
+ "Error: URL may not be relative": [
null,
""
],
- "Payback": [
+ "Invalid exchange URL (%1$s)": [
null,
""
],
- "Return Electronic Cash to Bank Account": [
+ "The exchange is trusted by the wallet.": [
null,
""
],
- "Manage Trusted Auditors and Exchanges": [
+ "The exchange is audited by a trusted auditor.": [
null,
""
],
- "Bank requested reserve (%1$s) for %2$s.": [
+ "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
null,
- "Bank bestätig anlegen der Reserve (%1$s) bei %2$s"
+ ""
],
- "Started to withdraw %1$s from %2$s (%3$s).": [
+ "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
null,
- "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
+ ""
],
- "Merchant %1$s offered contract %2$s.": [
+ "Waiting for a response from %1$s %2$s": [
null,
- "%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
+ ""
],
- "Withdrew %1$s from %2$s (%3$s).": [
+ "Information about fees will be available when an exchange provider is selected.": [
null,
- "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
+ ""
],
- "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+ "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
null,
- "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
+ ""
],
- "Merchant %1$s gave a refund over %2$s.": [
+ "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
null,
- "%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
+ ""
],
- "tip": [
+ "Accept fees and withdraw": [
null,
""
],
- "Merchant %1$s gave a %2$s of %3$s.": [
+ "Change Exchange Provider": [
null,
- "%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
+ ""
],
- "You did not accept the tip yet.": [
+ "Please select an exchange. You can review the details before after your selection.": [
null,
""
],
- "Unknown event (%1$s)": [
+ "Select %1$s": [
null,
""
],
- "Error: could not retrieve event history": [
+ "You are about to withdraw %1$s from your bank account into your wallet.": [
null,
""
],
- "Your wallet has no events recorded.": [
+ "Oops, something went wrong. The wallet responded with error status (%1$s).": [
null,
- "Ihre Geldbörse verzeichnet keine Vorkommnisse."
+ ""
],
- "Wire to bank account": [
+ "Checking URL, please wait ...": [
null,
""
],
- "Confirm": [
+ "Can't parse amount: %1$s": [
null,
- "Bezahlung bestätigen"
+ ""
],
- "Cancel": [
+ "Can't parse wire_types: %1$s": [
null,
- "Saldo"
+ ""
],
"Withdrawal fees:": [
null,
@@ -408,191 +408,191 @@ strings['en-US'] = {
null,
""
],
- "Select": [
+ "Balance": [
null,
""
],
- "Error: URL may not be relative": [
+ "History": [
null,
""
],
- "Invalid exchange URL (%1$s)": [
+ "Debug": [
null,
""
],
- "The exchange is trusted by the wallet.": [
+ "help": [
null,
""
],
- "The exchange is audited by a trusted auditor.": [
+ "You have no balance to show. Need some %1$s getting started?": [
null,
""
],
- "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
+ "%1$s incoming": [
null,
""
],
- "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
+ "%1$s being spent": [
null,
""
],
- "Waiting for a response from %1$s %2$s": [
+ "Error: could not retrieve balance information.": [
null,
""
],
- "Information about fees will be available when an exchange provider is selected.": [
+ "Payback": [
null,
""
],
- "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
+ "Return Electronic Cash to Bank Account": [
null,
""
],
- "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
+ "Manage Trusted Auditors and Exchanges": [
null,
""
],
- "Accept fees and withdraw": [
+ "Bank requested reserve (%1$s) for %2$s.": [
null,
""
],
- "Change Exchange Provider": [
+ "Started to withdraw %1$s from %2$s (%3$s).": [
null,
""
],
- "Please select an exchange. You can review the details before after your selection.": [
+ "Merchant %1$s offered contract %2$s.": [
null,
""
],
- "Select %1$s": [
+ "Withdrew %1$s from %2$s (%3$s).": [
null,
""
],
- "You are about to withdraw %1$s from your bank account into your wallet.": [
+ "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
null,
""
],
- "Oops, something went wrong. The wallet responded with error status (%1$s).": [
+ "Merchant %1$s gave a refund over %2$s.": [
null,
""
],
- "Checking URL, please wait ...": [
+ "tip": [
null,
""
],
- "Can't parse amount: %1$s": [
+ "Merchant %1$s gave a %2$s of %3$s.": [
null,
""
],
- "Can't parse wire_types: %1$s": [
+ "You did not accept the tip yet.": [
null,
""
],
- "Fatal error: \"%1$s\".": [
+ "Unknown event (%1$s)": [
null,
""
],
- "Balance": [
+ "Error: could not retrieve event history": [
null,
""
],
- "History": [
+ "Your wallet has no events recorded.": [
null,
""
],
- "Debug": [
+ "Wire to bank account": [
null,
""
],
- "help": [
+ "Confirm": [
null,
""
],
- "You have no balance to show. Need some %1$s getting started?": [
+ "Cancel": [
null,
""
],
- "%1$s incoming": [
+ "Fatal error: \"%1$s\".": [
null,
""
],
- "%1$s being spent": [
+ "Select": [
null,
""
],
- "Error: could not retrieve balance information.": [
+ "Error: URL may not be relative": [
null,
""
],
- "Payback": [
+ "Invalid exchange URL (%1$s)": [
null,
""
],
- "Return Electronic Cash to Bank Account": [
+ "The exchange is trusted by the wallet.": [
null,
""
],
- "Manage Trusted Auditors and Exchanges": [
+ "The exchange is audited by a trusted auditor.": [
null,
""
],
- "Bank requested reserve (%1$s) for %2$s.": [
+ "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
null,
""
],
- "Started to withdraw %1$s from %2$s (%3$s).": [
+ "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
null,
""
],
- "Merchant %1$s offered contract %2$s.": [
+ "Waiting for a response from %1$s %2$s": [
null,
""
],
- "Withdrew %1$s from %2$s (%3$s).": [
+ "Information about fees will be available when an exchange provider is selected.": [
null,
""
],
- "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+ "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
null,
""
],
- "Merchant %1$s gave a refund over %2$s.": [
+ "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
null,
""
],
- "tip": [
+ "Accept fees and withdraw": [
null,
""
],
- "Merchant %1$s gave a %2$s of %3$s.": [
+ "Change Exchange Provider": [
null,
""
],
- "You did not accept the tip yet.": [
+ "Please select an exchange. You can review the details before after your selection.": [
null,
""
],
- "Unknown event (%1$s)": [
+ "Select %1$s": [
null,
""
],
- "Error: could not retrieve event history": [
+ "You are about to withdraw %1$s from your bank account into your wallet.": [
null,
""
],
- "Your wallet has no events recorded.": [
+ "Oops, something went wrong. The wallet responded with error status (%1$s).": [
null,
""
],
- "Wire to bank account": [
+ "Checking URL, please wait ...": [
null,
""
],
- "Confirm": [
+ "Can't parse amount: %1$s": [
null,
""
],
- "Cancel": [
+ "Can't parse wire_types: %1$s": [
null,
""
],
@@ -724,191 +724,191 @@ strings['fr'] = {
null,
""
],
- "Select": [
+ "Balance": [
null,
""
],
- "Error: URL may not be relative": [
+ "History": [
null,
""
],
- "Invalid exchange URL (%1$s)": [
+ "Debug": [
null,
""
],
- "The exchange is trusted by the wallet.": [
+ "help": [
null,
""
],
- "The exchange is audited by a trusted auditor.": [
+ "You have no balance to show. Need some %1$s getting started?": [
null,
""
],
- "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
+ "%1$s incoming": [
null,
""
],
- "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
+ "%1$s being spent": [
null,
""
],
- "Waiting for a response from %1$s %2$s": [
+ "Error: could not retrieve balance information.": [
null,
""
],
- "Information about fees will be available when an exchange provider is selected.": [
+ "Payback": [
null,
""
],
- "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
+ "Return Electronic Cash to Bank Account": [
null,
""
],
- "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
+ "Manage Trusted Auditors and Exchanges": [
null,
""
],
- "Accept fees and withdraw": [
+ "Bank requested reserve (%1$s) for %2$s.": [
null,
""
],
- "Change Exchange Provider": [
+ "Started to withdraw %1$s from %2$s (%3$s).": [
null,
""
],
- "Please select an exchange. You can review the details before after your selection.": [
+ "Merchant %1$s offered contract %2$s.": [
null,
""
],
- "Select %1$s": [
+ "Withdrew %1$s from %2$s (%3$s).": [
null,
""
],
- "You are about to withdraw %1$s from your bank account into your wallet.": [
+ "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
null,
""
],
- "Oops, something went wrong. The wallet responded with error status (%1$s).": [
+ "Merchant %1$s gave a refund over %2$s.": [
null,
""
],
- "Checking URL, please wait ...": [
+ "tip": [
null,
""
],
- "Can't parse amount: %1$s": [
+ "Merchant %1$s gave a %2$s of %3$s.": [
null,
""
],
- "Can't parse wire_types: %1$s": [
+ "You did not accept the tip yet.": [
null,
""
],
- "Fatal error: \"%1$s\".": [
+ "Unknown event (%1$s)": [
null,
""
],
- "Balance": [
+ "Error: could not retrieve event history": [
null,
""
],
- "History": [
+ "Your wallet has no events recorded.": [
null,
""
],
- "Debug": [
+ "Wire to bank account": [
null,
""
],
- "help": [
+ "Confirm": [
null,
""
],
- "You have no balance to show. Need some %1$s getting started?": [
+ "Cancel": [
null,
""
],
- "%1$s incoming": [
+ "Fatal error: \"%1$s\".": [
null,
""
],
- "%1$s being spent": [
+ "Select": [
null,
""
],
- "Error: could not retrieve balance information.": [
+ "Error: URL may not be relative": [
null,
""
],
- "Payback": [
+ "Invalid exchange URL (%1$s)": [
null,
""
],
- "Return Electronic Cash to Bank Account": [
+ "The exchange is trusted by the wallet.": [
null,
""
],
- "Manage Trusted Auditors and Exchanges": [
+ "The exchange is audited by a trusted auditor.": [
null,
""
],
- "Bank requested reserve (%1$s) for %2$s.": [
+ "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
null,
""
],
- "Started to withdraw %1$s from %2$s (%3$s).": [
+ "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
null,
""
],
- "Merchant %1$s offered contract %2$s.": [
+ "Waiting for a response from %1$s %2$s": [
null,
""
],
- "Withdrew %1$s from %2$s (%3$s).": [
+ "Information about fees will be available when an exchange provider is selected.": [
null,
""
],
- "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+ "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
null,
""
],
- "Merchant %1$s gave a refund over %2$s.": [
+ "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
null,
""
],
- "tip": [
+ "Accept fees and withdraw": [
null,
""
],
- "Merchant %1$s gave a %2$s of %3$s.": [
+ "Change Exchange Provider": [
null,
""
],
- "You did not accept the tip yet.": [
+ "Please select an exchange. You can review the details before after your selection.": [
null,
""
],
- "Unknown event (%1$s)": [
+ "Select %1$s": [
null,
""
],
- "Error: could not retrieve event history": [
+ "You are about to withdraw %1$s from your bank account into your wallet.": [
null,
""
],
- "Your wallet has no events recorded.": [
+ "Oops, something went wrong. The wallet responded with error status (%1$s).": [
null,
""
],
- "Wire to bank account": [
+ "Checking URL, please wait ...": [
null,
""
],
- "Confirm": [
+ "Can't parse amount: %1$s": [
null,
""
],
- "Cancel": [
+ "Can't parse wire_types: %1$s": [
null,
""
],
@@ -1040,191 +1040,191 @@ strings['it'] = {
null,
""
],
- "Select": [
+ "Balance": [
null,
""
],
- "Error: URL may not be relative": [
+ "History": [
null,
""
],
- "Invalid exchange URL (%1$s)": [
+ "Debug": [
null,
""
],
- "The exchange is trusted by the wallet.": [
+ "help": [
null,
""
],
- "The exchange is audited by a trusted auditor.": [
+ "You have no balance to show. Need some %1$s getting started?": [
null,
""
],
- "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
+ "%1$s incoming": [
null,
""
],
- "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
+ "%1$s being spent": [
null,
""
],
- "Waiting for a response from %1$s %2$s": [
+ "Error: could not retrieve balance information.": [
null,
""
],
- "Information about fees will be available when an exchange provider is selected.": [
+ "Payback": [
null,
""
],
- "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
+ "Return Electronic Cash to Bank Account": [
null,
""
],
- "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
+ "Manage Trusted Auditors and Exchanges": [
null,
""
],
- "Accept fees and withdraw": [
+ "Bank requested reserve (%1$s) for %2$s.": [
null,
""
],
- "Change Exchange Provider": [
+ "Started to withdraw %1$s from %2$s (%3$s).": [
null,
""
],
- "Please select an exchange. You can review the details before after your selection.": [
+ "Merchant %1$s offered contract %2$s.": [
null,
""
],
- "Select %1$s": [
+ "Withdrew %1$s from %2$s (%3$s).": [
null,
""
],
- "You are about to withdraw %1$s from your bank account into your wallet.": [
+ "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
null,
""
],
- "Oops, something went wrong. The wallet responded with error status (%1$s).": [
+ "Merchant %1$s gave a refund over %2$s.": [
null,
""
],
- "Checking URL, please wait ...": [
+ "tip": [
null,
""
],
- "Can't parse amount: %1$s": [
+ "Merchant %1$s gave a %2$s of %3$s.": [
null,
""
],
- "Can't parse wire_types: %1$s": [
+ "You did not accept the tip yet.": [
null,
""
],
- "Fatal error: \"%1$s\".": [
+ "Unknown event (%1$s)": [
null,
""
],
- "Balance": [
+ "Error: could not retrieve event history": [
null,
""
],
- "History": [
+ "Your wallet has no events recorded.": [
null,
""
],
- "Debug": [
+ "Wire to bank account": [
null,
""
],
- "help": [
+ "Confirm": [
null,
""
],
- "You have no balance to show. Need some %1$s getting started?": [
+ "Cancel": [
null,
""
],
- "%1$s incoming": [
+ "Fatal error: \"%1$s\".": [
null,
""
],
- "%1$s being spent": [
+ "Select": [
null,
""
],
- "Error: could not retrieve balance information.": [
+ "Error: URL may not be relative": [
null,
""
],
- "Payback": [
+ "Invalid exchange URL (%1$s)": [
null,
""
],
- "Return Electronic Cash to Bank Account": [
+ "The exchange is trusted by the wallet.": [
null,
""
],
- "Manage Trusted Auditors and Exchanges": [
+ "The exchange is audited by a trusted auditor.": [
null,
""
],
- "Bank requested reserve (%1$s) for %2$s.": [
+ "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
null,
""
],
- "Started to withdraw %1$s from %2$s (%3$s).": [
+ "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
null,
""
],
- "Merchant %1$s offered contract %2$s.": [
+ "Waiting for a response from %1$s %2$s": [
null,
""
],
- "Withdrew %1$s from %2$s (%3$s).": [
+ "Information about fees will be available when an exchange provider is selected.": [
null,
""
],
- "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+ "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
null,
""
],
- "Merchant %1$s gave a refund over %2$s.": [
+ "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
null,
""
],
- "tip": [
+ "Accept fees and withdraw": [
null,
""
],
- "Merchant %1$s gave a %2$s of %3$s.": [
+ "Change Exchange Provider": [
null,
""
],
- "You did not accept the tip yet.": [
+ "Please select an exchange. You can review the details before after your selection.": [
null,
""
],
- "Unknown event (%1$s)": [
+ "Select %1$s": [
null,
""
],
- "Error: could not retrieve event history": [
+ "You are about to withdraw %1$s from your bank account into your wallet.": [
null,
""
],
- "Your wallet has no events recorded.": [
+ "Oops, something went wrong. The wallet responded with error status (%1$s).": [
null,
""
],
- "Wire to bank account": [
+ "Checking URL, please wait ...": [
null,
""
],
- "Confirm": [
+ "Can't parse amount: %1$s": [
null,
""
],
- "Cancel": [
+ "Can't parse wire_types: %1$s": [
null,
""
],
@@ -1356,193 +1356,193 @@ strings['sv'] = {
null,
"Det totala priset är %1$s."
],
- "Select": [
+ "Balance": [
null,
- "Välj"
+ "Balans"
],
- "Error: URL may not be relative": [
+ "History": [
null,
- ""
+ "Historia"
],
- "Invalid exchange URL (%1$s)": [
+ "Debug": [
null,
""
],
- "The exchange is trusted by the wallet.": [
+ "help": [
null,
- "Tjänsteleverantörer i plånboken:"
+ "hjälp"
],
- "The exchange is audited by a trusted auditor.": [
+ "You have no balance to show. Need some %1$s getting started?": [
null,
- ""
+ "Du har ingen balans att visa. Behöver du\n %1$s att börja?\n"
],
- "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
+ "%1$s incoming": [
null,
- ""
+ "%1$s inkommande"
],
- "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
+ "%1$s being spent": [
null,
""
],
- "Waiting for a response from %1$s %2$s": [
+ "Error: could not retrieve balance information.": [
null,
""
],
- "Information about fees will be available when an exchange provider is selected.": [
+ "Payback": [
null,
- ""
+ "Återbetalning"
],
- "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
+ "Return Electronic Cash to Bank Account": [
null,
- "tjänsteleverantörer plånboken"
+ "Återlämna elektroniska pengar till bank konto"
],
- "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
+ "Manage Trusted Auditors and Exchanges": [
null,
- "tjänsteleverantörer plånboken"
+ ""
],
- "Accept fees and withdraw": [
+ "Bank requested reserve (%1$s) for %2$s.": [
null,
- "Acceptera avgifter och utbetala"
+ ""
],
- "Change Exchange Provider": [
+ "Started to withdraw %1$s from %2$s (%3$s).": [
null,
- "Ändra tjänsteleverantörer"
+ ""
],
- "Please select an exchange. You can review the details before after your selection.": [
+ "Merchant %1$s offered contract %2$s.": [
null,
- ""
+ "Säljaren %1$s erbjöd kontrakt %2$s.\n"
],
- "Select %1$s": [
+ "Withdrew %1$s from %2$s (%3$s).": [
null,
- "Välj %1$s"
+ ""
],
- "You are about to withdraw %1$s from your bank account into your wallet.": [
+ "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
null,
- "Du är på väg att ta ut\n %1$s från ditt bankkonto till din plånbok.\n"
+ ""
],
- "Oops, something went wrong. The wallet responded with error status (%1$s).": [
+ "Merchant %1$s gave a refund over %2$s.": [
null,
- "plånboken"
+ "Säljaren %1$sgav en återbetalning på %2$s.\n"
],
- "Checking URL, please wait ...": [
+ "tip": [
null,
""
],
- "Can't parse amount: %1$s": [
+ "Merchant %1$s gave a %2$s of %3$s.": [
null,
- ""
+ "Säljaren %1$sgav en återbetalning på %2$s.\n"
],
- "Can't parse wire_types: %1$s": [
+ "You did not accept the tip yet.": [
null,
""
],
- "Fatal error: \"%1$s\".": [
+ "Unknown event (%1$s)": [
null,
""
],
- "Balance": [
+ "Error: could not retrieve event history": [
null,
- "Balans"
+ ""
],
- "History": [
+ "Your wallet has no events recorded.": [
null,
- "Historia"
+ "plånboken"
],
- "Debug": [
+ "Wire to bank account": [
null,
- ""
+ "Övervisa till bank konto"
],
- "help": [
+ "Confirm": [
null,
- "hjälp"
+ "Bekräfta"
],
- "You have no balance to show. Need some %1$s getting started?": [
+ "Cancel": [
null,
- "Du har ingen balans att visa. Behöver du\n %1$s att börja?\n"
+ "Avbryt"
],
- "%1$s incoming": [
+ "Fatal error: \"%1$s\".": [
null,
- "%1$s inkommande"
+ ""
],
- "%1$s being spent": [
+ "Select": [
null,
- ""
+ "Välj"
],
- "Error: could not retrieve balance information.": [
+ "Error: URL may not be relative": [
null,
""
],
- "Payback": [
+ "Invalid exchange URL (%1$s)": [
null,
- "Återbetalning"
+ ""
],
- "Return Electronic Cash to Bank Account": [
+ "The exchange is trusted by the wallet.": [
null,
- "Återlämna elektroniska pengar till bank konto"
+ "Tjänsteleverantörer i plånboken:"
],
- "Manage Trusted Auditors and Exchanges": [
+ "The exchange is audited by a trusted auditor.": [
null,
""
],
- "Bank requested reserve (%1$s) for %2$s.": [
+ "Warning: The exchange is neither directly trusted nor audited by a trusted auditor. If you withdraw from this exchange, it will be trusted in the future.": [
null,
""
],
- "Started to withdraw %1$s from %2$s (%3$s).": [
+ "Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
null,
""
],
- "Merchant %1$s offered contract %2$s.": [
+ "Waiting for a response from %1$s %2$s": [
null,
- "Säljaren %1$s erbjöd kontrakt %2$s.\n"
+ ""
],
- "Withdrew %1$s from %2$s (%3$s).": [
+ "Information about fees will be available when an exchange provider is selected.": [
null,
""
],
- "Paid %1$s to merchant %2$s. %3$s (%4$s)": [
+ "Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
null,
- ""
+ "tjänsteleverantörer plånboken"
],
- "Merchant %1$s gave a refund over %2$s.": [
+ "The chosen exchange (protocol version %1$s might be outdated.%2$s The exchange has a lower, incompatible protocol version than your wallet (protocol version %3$s).": [
null,
- "Säljaren %1$sgav en återbetalning på %2$s.\n"
+ "tjänsteleverantörer plånboken"
],
- "tip": [
+ "Accept fees and withdraw": [
null,
- ""
+ "Acceptera avgifter och utbetala"
],
- "Merchant %1$s gave a %2$s of %3$s.": [
+ "Change Exchange Provider": [
null,
- "Säljaren %1$sgav en återbetalning på %2$s.\n"
+ "Ändra tjänsteleverantörer"
],
- "You did not accept the tip yet.": [
+ "Please select an exchange. You can review the details before after your selection.": [
null,
""
],
- "Unknown event (%1$s)": [
+ "Select %1$s": [
null,
- ""
+ "Välj %1$s"
],
- "Error: could not retrieve event history": [
+ "You are about to withdraw %1$s from your bank account into your wallet.": [
null,
- ""
+ "Du är på väg att ta ut\n %1$s från ditt bankkonto till din plånbok.\n"
],
- "Your wallet has no events recorded.": [
+ "Oops, something went wrong. The wallet responded with error status (%1$s).": [
null,
"plånboken"
],
- "Wire to bank account": [
+ "Checking URL, please wait ...": [
null,
- "Övervisa till bank konto"
+ ""
],
- "Confirm": [
+ "Can't parse amount: %1$s": [
null,
- "Bekräfta"
+ ""
],
- "Cancel": [
+ "Can't parse wire_types: %1$s": [
null,
- "Avbryt"
+ ""
],
"Withdrawal fees:": [
null,
diff --git a/src/i18n/sv.po b/src/i18n/sv.po
index 1b99a13a0..7e3ec5165 100644
--- a/src/i18n/sv.po
+++ b/src/i18n/sv.po
@@ -37,28 +37,28 @@ msgstr ""
msgid "time (ms/op)"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
#, fuzzy, c-format
msgid "show more details"
msgstr "visa mer"
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
#, c-format
msgid "Accepted exchanges:"
msgstr "Accepterade tjänsteleverantörer:"
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
#, c-format
msgid "Exchanges in the wallet:"
msgstr "Tjänsteleverantörer i plånboken:"
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
#, c-format
msgid "You have insufficient funds of the requested currency in your wallet."
msgstr "plånboken"
#. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:221
+#: src/webex/pages/pay.tsx:221
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@@ -66,17 +66,17 @@ msgid ""
"wallet."
msgstr "plånboken"
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
#, c-format
msgid "Confirm payment"
msgstr "Godkän betalning"
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
#, c-format
msgid "Submitting payment"
msgstr "Bekräftar betalning"
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
#, c-format
msgid ""
"You already paid for this, clicking \"Confirm payment\" will not cost money "
@@ -85,165 +85,41 @@ msgstr ""
"Du har redan betalat för det här, om du trycker \"Godkän betalning\" "
"debiteras du inte igen"
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
#, fuzzy, c-format
msgid "Aborting payment ..."
msgstr "Bekräftar betalning"
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
#, c-format
msgid "Payment aborted!"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
#, c-format
msgid "Retry Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
#, fuzzy, c-format
msgid "Abort Payment"
msgstr "Godkän betalning"
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
#, fuzzy, c-format
msgid "The merchant %1$s offers you to purchase:"
msgstr "Säljaren %1$s erbjuder följande:"
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
#, fuzzy, c-format
msgid "The total price is %1$s (plus %2$s fees)."
msgstr "Det totala priset är %1$s (plus %2$s avgifter).\n"
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
#, fuzzy, c-format
msgid "The total price is %1$s."
msgstr "Det totala priset är %1$s."
-#: src/webex/pages/confirm-create-reserve.tsx:128
-#, c-format
-msgid "Select"
-msgstr "Välj"
-
-#: src/webex/pages/confirm-create-reserve.tsx:145
-#, c-format
-msgid "Error: URL may not be relative"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:160
-#, c-format
-msgid "Invalid exchange URL (%1$s)"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:210
-#, fuzzy, c-format
-msgid "The exchange is trusted by the wallet."
-msgstr "Tjänsteleverantörer i plånboken:"
-
-#: src/webex/pages/confirm-create-reserve.tsx:216
-#, c-format
-msgid "The exchange is audited by a trusted auditor."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:222
-#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:231
-#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:243
-#, c-format
-msgid "Waiting for a response from %1$s %2$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:260
-#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:279
-#, fuzzy, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
-msgstr "tjänsteleverantörer plånboken"
-
-#: src/webex/pages/confirm-create-reserve.tsx:290
-#, fuzzy, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
-msgstr "tjänsteleverantörer plånboken"
-
-#: src/webex/pages/confirm-create-reserve.tsx:309
-#, c-format
-msgid "Accept fees and withdraw"
-msgstr "Acceptera avgifter och utbetala"
-
-#: src/webex/pages/confirm-create-reserve.tsx:314
-#, c-format
-msgid "Change Exchange Provider"
-msgstr "Ändra tjänsteleverantörer"
-
-#: src/webex/pages/confirm-create-reserve.tsx:335
-#, c-format
-msgid ""
-"Please select an exchange. You can review the details before after your "
-"selection."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
-#, fuzzy, c-format
-msgid "Select %1$s"
-msgstr "Välj %1$s"
-
-#: src/webex/pages/confirm-create-reserve.tsx:370
-#, fuzzy, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
-msgstr ""
-"Du är på väg att ta ut\n"
-" %1$s från ditt bankkonto till din plånbok.\n"
-
-#: src/webex/pages/confirm-create-reserve.tsx:459
-#, fuzzy, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
-msgstr "plånboken"
-
-#: src/webex/pages/confirm-create-reserve.tsx:468
-#, c-format
-msgid "Checking URL, please wait ..."
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:482
-#, c-format
-msgid "Can't parse amount: %1$s"
-msgstr ""
-
-#: src/webex/pages/confirm-create-reserve.tsx:489
-#, c-format
-msgid "Can't parse wire_types: %1$s"
-msgstr ""
-
-#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
-#, c-format
-msgid "Fatal error: \"%1$s\"."
-msgstr ""
-
#: src/webex/pages/popup.tsx:165
#, c-format
msgid "Balance"
@@ -376,6 +252,129 @@ msgstr "Bekräfta"
msgid "Cancel"
msgstr "Avbryt"
+#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
+#, c-format
+msgid "Fatal error: \"%1$s\"."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:128
+#, c-format
+msgid "Select"
+msgstr "Välj"
+
+#: src/webex/pages/withdraw.tsx:145
+#, c-format
+msgid "Error: URL may not be relative"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:160
+#, c-format
+msgid "Invalid exchange URL (%1$s)"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:210
+#, fuzzy, c-format
+msgid "The exchange is trusted by the wallet."
+msgstr "Tjänsteleverantörer i plånboken:"
+
+#: src/webex/pages/withdraw.tsx:216
+#, c-format
+msgid "The exchange is audited by a trusted auditor."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:222
+#, c-format
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:231
+#, c-format
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:243
+#, c-format
+msgid "Waiting for a response from %1$s %2$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:260
+#, c-format
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:279
+#, fuzzy, c-format
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
+msgstr "tjänsteleverantörer plånboken"
+
+#: src/webex/pages/withdraw.tsx:290
+#, fuzzy, c-format
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
+msgstr "tjänsteleverantörer plånboken"
+
+#: src/webex/pages/withdraw.tsx:309
+#, c-format
+msgid "Accept fees and withdraw"
+msgstr "Acceptera avgifter och utbetala"
+
+#: src/webex/pages/withdraw.tsx:314
+#, c-format
+msgid "Change Exchange Provider"
+msgstr "Ändra tjänsteleverantörer"
+
+#: src/webex/pages/withdraw.tsx:335
+#, c-format
+msgid ""
+"Please select an exchange. You can review the details before after your "
+"selection."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
+#, fuzzy, c-format
+msgid "Select %1$s"
+msgstr "Välj %1$s"
+
+#: src/webex/pages/withdraw.tsx:370
+#, fuzzy, c-format
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgstr ""
+"Du är på väg att ta ut\n"
+" %1$s från ditt bankkonto till din plånbok.\n"
+
+#: src/webex/pages/withdraw.tsx:459
+#, fuzzy, c-format
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgstr "plånboken"
+
+#: src/webex/pages/withdraw.tsx:468
+#, c-format
+msgid "Checking URL, please wait ..."
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:482
+#, c-format
+msgid "Can't parse amount: %1$s"
+msgstr ""
+
+#: src/webex/pages/withdraw.tsx:489
+#, c-format
+msgid "Can't parse wire_types: %1$s"
+msgstr ""
+
#: src/webex/renderHtml.tsx:225
#, c-format
msgid "Withdrawal fees:"
diff --git a/src/i18n/taler-wallet-webex.pot b/src/i18n/taler-wallet-webex.pot
index e7615e41c..1f0dc2a47 100644
--- a/src/i18n/taler-wallet-webex.pot
+++ b/src/i18n/taler-wallet-webex.pot
@@ -37,28 +37,28 @@ msgstr ""
msgid "time (ms/op)"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:78
+#: src/webex/pages/pay.tsx:78
#, c-format
msgid "show more details"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:92
+#: src/webex/pages/pay.tsx:92
#, c-format
msgid "Accepted exchanges:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:97
+#: src/webex/pages/pay.tsx:97
#, c-format
msgid "Exchanges in the wallet:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:219
+#: src/webex/pages/pay.tsx:219
#, 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:221
+#: src/webex/pages/pay.tsx:221
#, c-format
msgid ""
"You do not have any funds from an exchange that is accepted by this "
@@ -66,308 +66,307 @@ msgid ""
"wallet."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:322
+#: src/webex/pages/pay.tsx:322
#, c-format
msgid "Confirm payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:332
+#: src/webex/pages/pay.tsx:332
#, c-format
msgid "Submitting payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:343
+#: src/webex/pages/pay.tsx:343
#, c-format
msgid ""
"You already paid for this, clicking \"Confirm payment\" will not cost money "
"again."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:357
+#: src/webex/pages/pay.tsx:357
#, c-format
msgid "Aborting payment ..."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:359
+#: src/webex/pages/pay.tsx:359
#, c-format
msgid "Payment aborted!"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:362
+#: src/webex/pages/pay.tsx:362
#, c-format
msgid "Retry Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:365
+#: src/webex/pages/pay.tsx:365
#, c-format
msgid "Abort Payment"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:374
+#: src/webex/pages/pay.tsx:374
#, c-format
msgid "The merchant %1$s offers you to purchase:"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:383
+#: src/webex/pages/pay.tsx:383
#, c-format
msgid "The total price is %1$s (plus %2$s fees)."
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:387
+#: src/webex/pages/pay.tsx:387
#, c-format
msgid "The total price is %1$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:128
+#: src/webex/pages/popup.tsx:165
#, c-format
-msgid "Select"
+msgid "Balance"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:145
+#: src/webex/pages/popup.tsx:168
#, c-format
-msgid "Error: URL may not be relative"
+msgid "History"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:160
+#: src/webex/pages/popup.tsx:171
#, c-format
-msgid "Invalid exchange URL (%1$s)"
+msgid "Debug"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:210
+#: src/webex/pages/popup.tsx:251
#, c-format
-msgid "The exchange is trusted by the wallet."
+msgid "help"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:216
+#: src/webex/pages/popup.tsx:256
#, c-format
-msgid "The exchange is audited by a trusted auditor."
+msgid "You have no balance to show. Need some %1$s getting started?"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:222
+#: src/webex/pages/popup.tsx:273
#, c-format
-msgid ""
-"Warning: The exchange is neither directly trusted nor audited by a trusted "
-"auditor. If you withdraw from this exchange, it will be trusted in the "
-"future."
+msgid "%1$s incoming"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:231
+#: src/webex/pages/popup.tsx:286
#, c-format
-msgid ""
-"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
+msgid "%1$s being spent"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:243
+#: src/webex/pages/popup.tsx:313
#, c-format
-msgid "Waiting for a response from %1$s %2$s"
+msgid "Error: could not retrieve balance information."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:260
+#: src/webex/pages/popup.tsx:340
#, c-format
-msgid ""
-"Information about fees will be available when an exchange provider is "
-"selected."
+msgid "Payback"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:279
+#: src/webex/pages/popup.tsx:341
#, c-format
-msgid ""
-"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
-"a higher, incompatible protocol version (%3$s)."
+msgid "Return Electronic Cash to Bank Account"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:290
+#: src/webex/pages/popup.tsx:342
#, c-format
-msgid ""
-"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
-"exchange has a lower, incompatible protocol version than your wallet "
-"(protocol version %3$s)."
+msgid "Manage Trusted Auditors and Exchanges"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:309
+#: src/webex/pages/popup.tsx:354
#, c-format
-msgid "Accept fees and withdraw"
+msgid "Bank requested reserve (%1$s) for %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:314
+#: src/webex/pages/popup.tsx:364
#, c-format
-msgid "Change Exchange Provider"
+msgid "Started to withdraw %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:335
+#: src/webex/pages/popup.tsx:373
#, c-format
-msgid ""
-"Please select an exchange. You can review the details before after your "
-"selection."
+msgid "Merchant %1$s offered contract %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:341
-#: src/webex/pages/confirm-create-reserve.tsx:353
+#: src/webex/pages/popup.tsx:384
#, c-format
-msgid "Select %1$s"
+msgid "Withdrew %1$s from %2$s (%3$s)."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:370
+#: src/webex/pages/popup.tsx:394
#, c-format
-msgid "You are about to withdraw %1$s from your bank account into your wallet."
+msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:459
+#: src/webex/pages/popup.tsx:404
#, c-format
-msgid ""
-"Oops, something went wrong. The wallet responded with error status (%1$s)."
+msgid "Merchant %1$s gave a refund over %2$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:468
+#: src/webex/pages/popup.tsx:414
#, c-format
-msgid "Checking URL, please wait ..."
+msgid "tip"
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:482
+#: src/webex/pages/popup.tsx:418
#, c-format
-msgid "Can't parse amount: %1$s"
+msgid "Merchant %1$s gave a %2$s of %3$s."
msgstr ""
-#: src/webex/pages/confirm-create-reserve.tsx:489
+#: src/webex/pages/popup.tsx:422
#, c-format
-msgid "Can't parse wire_types: %1$s"
+msgid "You did not accept the tip yet."
msgstr ""
-#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
-#. TODO:generic error reporting function or component.
-#: src/webex/pages/confirm-create-reserve.tsx:519 src/webex/pages/tip.tsx:180
+#: src/webex/pages/popup.tsx:427
#, c-format
-msgid "Fatal error: \"%1$s\"."
+msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:165
+#: src/webex/pages/popup.tsx:470
#, c-format
-msgid "Balance"
+msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:168
+#: src/webex/pages/popup.tsx:495
#, c-format
-msgid "History"
+msgid "Your wallet has no events recorded."
msgstr ""
-#: src/webex/pages/popup.tsx:171
+#: src/webex/pages/return-coins.tsx:105
#, c-format
-msgid "Debug"
+msgid "Wire to bank account"
msgstr ""
-#: src/webex/pages/popup.tsx:251
+#: src/webex/pages/return-coins.tsx:173
#, c-format
-msgid "help"
+msgid "Confirm"
msgstr ""
-#: src/webex/pages/popup.tsx:256
+#: src/webex/pages/return-coins.tsx:176
#, c-format
-msgid "You have no balance to show. Need some %1$s getting started?"
+msgid "Cancel"
msgstr ""
-#: src/webex/pages/popup.tsx:273
+#. #-#-#-#-# - (PACKAGE VERSION) #-#-#-#-#
+#. TODO:generic error reporting function or component.
+#: src/webex/pages/tip.tsx:180 src/webex/pages/withdraw.tsx:519
#, c-format
-msgid "%1$s incoming"
+msgid "Fatal error: \"%1$s\"."
msgstr ""
-#: src/webex/pages/popup.tsx:286
+#: src/webex/pages/withdraw.tsx:128
#, c-format
-msgid "%1$s being spent"
+msgid "Select"
msgstr ""
-#: src/webex/pages/popup.tsx:313
+#: src/webex/pages/withdraw.tsx:145
#, c-format
-msgid "Error: could not retrieve balance information."
+msgid "Error: URL may not be relative"
msgstr ""
-#: src/webex/pages/popup.tsx:340
+#: src/webex/pages/withdraw.tsx:160
#, c-format
-msgid "Payback"
+msgid "Invalid exchange URL (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:341
+#: src/webex/pages/withdraw.tsx:210
#, c-format
-msgid "Return Electronic Cash to Bank Account"
+msgid "The exchange is trusted by the wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:342
+#: src/webex/pages/withdraw.tsx:216
#, c-format
-msgid "Manage Trusted Auditors and Exchanges"
+msgid "The exchange is audited by a trusted auditor."
msgstr ""
-#: src/webex/pages/popup.tsx:354
+#: src/webex/pages/withdraw.tsx:222
#, c-format
-msgid "Bank requested reserve (%1$s) for %2$s."
+msgid ""
+"Warning: The exchange is neither directly trusted nor audited by a trusted "
+"auditor. If you withdraw from this exchange, it will be trusted in the "
+"future."
msgstr ""
-#: src/webex/pages/popup.tsx:364
+#: src/webex/pages/withdraw.tsx:231
#, c-format
-msgid "Started to withdraw %1$s from %2$s (%3$s)."
+msgid ""
+"Using exchange provider %1$s. The exchange provider will charge %2$s in fees."
msgstr ""
-#: src/webex/pages/popup.tsx:373
+#: src/webex/pages/withdraw.tsx:243
#, c-format
-msgid "Merchant %1$s offered contract %2$s."
+msgid "Waiting for a response from %1$s %2$s"
msgstr ""
-#: src/webex/pages/popup.tsx:384
+#: src/webex/pages/withdraw.tsx:260
#, c-format
-msgid "Withdrew %1$s from %2$s (%3$s)."
+msgid ""
+"Information about fees will be available when an exchange provider is "
+"selected."
msgstr ""
-#: src/webex/pages/popup.tsx:394
+#: src/webex/pages/withdraw.tsx:279
#, c-format
-msgid "Paid %1$s to merchant %2$s. %3$s (%4$s)"
+msgid ""
+"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has "
+"a higher, incompatible protocol version (%3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:404
+#: src/webex/pages/withdraw.tsx:290
#, c-format
-msgid "Merchant %1$s gave a refund over %2$s."
+msgid ""
+"The chosen exchange (protocol version %1$s might be outdated.%2$s The "
+"exchange has a lower, incompatible protocol version than your wallet "
+"(protocol version %3$s)."
msgstr ""
-#: src/webex/pages/popup.tsx:414
+#: src/webex/pages/withdraw.tsx:309
#, c-format
-msgid "tip"
+msgid "Accept fees and withdraw"
msgstr ""
-#: src/webex/pages/popup.tsx:418
+#: src/webex/pages/withdraw.tsx:314
#, c-format
-msgid "Merchant %1$s gave a %2$s of %3$s."
+msgid "Change Exchange Provider"
msgstr ""
-#: src/webex/pages/popup.tsx:422
+#: src/webex/pages/withdraw.tsx:335
#, c-format
-msgid "You did not accept the tip yet."
+msgid ""
+"Please select an exchange. You can review the details before after your "
+"selection."
msgstr ""
-#: src/webex/pages/popup.tsx:427
+#: src/webex/pages/withdraw.tsx:341 src/webex/pages/withdraw.tsx:353
#, c-format
-msgid "Unknown event (%1$s)"
+msgid "Select %1$s"
msgstr ""
-#: src/webex/pages/popup.tsx:470
+#: src/webex/pages/withdraw.tsx:370
#, c-format
-msgid "Error: could not retrieve event history"
+msgid "You are about to withdraw %1$s from your bank account into your wallet."
msgstr ""
-#: src/webex/pages/popup.tsx:495
+#: src/webex/pages/withdraw.tsx:459
#, c-format
-msgid "Your wallet has no events recorded."
+msgid ""
+"Oops, something went wrong. The wallet responded with error status (%1$s)."
msgstr ""
-#: src/webex/pages/return-coins.tsx:105
+#: src/webex/pages/withdraw.tsx:468
#, c-format
-msgid "Wire to bank account"
+msgid "Checking URL, please wait ..."
msgstr ""
-#: src/webex/pages/return-coins.tsx:173
+#: src/webex/pages/withdraw.tsx:482
#, c-format
-msgid "Confirm"
+msgid "Can't parse amount: %1$s"
msgstr ""
-#: src/webex/pages/return-coins.tsx:176
+#: src/webex/pages/withdraw.tsx:489
#, c-format
-msgid "Cancel"
+msgid "Can't parse wire_types: %1$s"
msgstr ""
#: src/webex/renderHtml.tsx:225
diff --git a/src/wallet.ts b/src/wallet.ts
index b6a9361c1..e476c94f6 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -105,6 +105,8 @@ import {
WalletBalanceEntry,
PreparePayResult,
DownloadedWithdrawInfo,
+ WithdrawDetails,
+ AcceptWithdrawalResponse,
} from "./walletTypes";
import { openPromise } from "./promiseUtils";
import { parsePayUri, parseWithdrawUri } from "./taleruri";
@@ -717,6 +719,12 @@ export class Wallet {
return t;
}
+ getNextUrl(contractTerms: ContractTerms): string {
+ const fu = new URI(contractTerms.fulfillment_url);
+ fu.addSearch("order_id", contractTerms.order_id);
+ return fu.href();
+ }
+
async preparePay(url: string): Promise<PreparePayResult> {
const uriResult = parsePayUri(url);
@@ -760,17 +768,20 @@ export class Wallet {
uriResult.sessionId,
);
return {
- status: "session-replayed",
+ status: "paid",
contractTerms: existingPayment.contractTerms,
+ nextUrl: this.getNextUrl(existingPayment.contractTerms),
};
}
}
if (checkResult.status === "paid") {
+ const nextUrl = this.getNextUrl(proposal.contractTerms);
return {
status: "paid",
contractTerms: proposal.contractTerms,
proposalId: proposal.id!,
+ nextUrl,
};
}
if (checkResult.status === "insufficient-balance") {
@@ -912,14 +923,6 @@ export class Wallet {
modifiedCoins.push(c);
}
- const fu = new URI(purchase.contractTerms.fulfillment_url);
- fu.addSearch("order_id", purchase.contractTerms.order_id);
- if (merchantResp.session_sig) {
- purchase.lastSessionSig = merchantResp.session_sig;
- purchase.lastSessionId = sessionId;
- fu.addSearch("session_sig", merchantResp.session_sig);
- }
-
await this.q()
.putAll(Stores.coins, modifiedCoins)
.put(Stores.purchases, purchase)
@@ -928,7 +931,7 @@ export class Wallet {
this.refresh(c.coin_pub);
}
- const nextUrl = fu.href();
+ const nextUrl = this.getNextUrl(purchase.contractTerms);
this.cachedNextUrl[purchase.contractTerms.fulfillment_url] = {
nextUrl,
lastSessionId: sessionId,
@@ -1150,6 +1153,54 @@ export class Wallet {
return t;
}
+ private async sendReserveInfoToBank(reservePub: string) {
+ const reserve = await this.q().get<ReserveRecord>(
+ Stores.reserves,
+ reservePub,
+ );
+ if (!reserve) {
+ throw Error("reserve not in db");
+ }
+
+ const bankStatusUrl = reserve.bankWithdrawStatusUrl;
+ if (!bankStatusUrl) {
+ throw Error("reserve not confirmed yet, and no status URL available.");
+ }
+
+ const now = new Date().getTime();
+ let status;
+ try {
+ const statusResp = await this.http.get(bankStatusUrl);
+ status = WithdrawOperationStatusResponse.checked(statusResp.responseJson);
+ } catch (e) {
+ console.log("bank error response", e);
+ throw e;
+ }
+
+ if (status.transfer_done) {
+ await this.q().mutate(Stores.reserves, reservePub, r => {
+ r.timestamp_confirmed = now;
+ return r;
+ });
+ } else if (reserve.timestamp_reserve_info_posted === 0) {
+ try {
+ if (!status.selection_done) {
+ const bankResp = await this.http.postJson(bankStatusUrl, {
+ reserve_pub: reservePub,
+ selected_exchange: reserve.exchangeWire,
+ });
+ }
+ } catch (e) {
+ console.log("bank error response", e);
+ throw e;
+ }
+ await this.q().mutate(Stores.reserves, reservePub, r => {
+ r.timestamp_reserve_info_posted = now;
+ return r;
+ });
+ }
+ }
+
/**
* First fetch information requred to withdraw from the reserve,
* then deplete the reserve, withdrawing coins until it is empty.
@@ -1192,41 +1243,10 @@ export class Wallet {
);
}
maxTimeout = 2000;
- const now = new Date().getTime();
- let status;
- try {
- const statusResp = await this.http.get(bankStatusUrl);
- status = WithdrawOperationStatusResponse.checked(
- statusResp.responseJson,
- );
- } catch (e) {
- console.log("bank error response", e);
- throw e;
- }
-
- if (status.transfer_done) {
- await this.q().mutate(Stores.reserves, reservePub, r => {
- r.timestamp_confirmed = now;
- return r;
- });
- } else if (reserve.timestamp_reserve_info_posted === 0) {
- try {
- if (!status.selection_done) {
- const bankResp = await this.http.postJson(bankStatusUrl, {
- reserve_pub: reservePub,
- selected_exchange: reserve.exchangeWire,
- });
- }
- } catch (e) {
- console.log("bank error response", e);
- throw e;
- }
- await this.q().mutate(Stores.reserves, reservePub, r => {
- r.timestamp_reserve_info_posted = now;
- return r;
- });
- throw Error("waiting for reserve to be confirmed");
- }
+ /* This path is only taken if the wallet crashed after a withdraw was accepted,
+ * and before the information could be sent to the bank. */
+ await this.sendReserveInfoToBank(reservePub);
+ throw Error("waiting for reserve to be confirmed");
}
const updatedReserve = await this.updateReserve(reservePub);
@@ -1836,6 +1856,24 @@ export class Wallet {
return { isTrusted, isAudited };
}
+ async getWithdrawDetails(
+ talerPayUri: string,
+ maybeSelectedExchange?: string,
+ ): Promise<WithdrawDetails> {
+ const info = await this.downloadWithdrawInfo(talerPayUri);
+ let rci: ReserveCreationInfo | undefined = undefined;
+ if (maybeSelectedExchange) {
+ rci = await this.getReserveCreationInfo(
+ maybeSelectedExchange,
+ info.amount,
+ );
+ }
+ return {
+ withdrawInfo: info,
+ reserveCreationInfo: rci,
+ };
+ }
+
async getReserveCreationInfo(
baseUrl: string,
amount: AmountJson,
@@ -3515,16 +3553,6 @@ export class Wallet {
}
/**
- * Synchronously get the paid URL for a resource from the plain fulfillment
- * URL. Returns undefined if the fulfillment URL is not a resource that was
- * payed for, or if it is not cached anymore. Use the asynchronous
- * queryPaymentByFulfillmentUrl to avoid false negatives.
- */
- getNextUrlFromResourceUrl(resourceUrl: string): NextUrlResult | undefined {
- return this.cachedNextUrl[resourceUrl];
- }
-
- /**
* Remove unreferenced / expired data from the wallet's database
* based on the current system time.
*/
@@ -3557,10 +3585,10 @@ export class Wallet {
};
}
- async createReserveFromWithdrawUrl(
+ async acceptWithdrawal(
talerWithdrawUri: string,
selectedExchange: string,
- ): Promise<{ reservePub: string; confirmTransferUrl?: string }> {
+ ): Promise<AcceptWithdrawalResponse> {
const withdrawInfo = await this.downloadWithdrawInfo(talerWithdrawUri);
const exchangeWire = await this.getExchangePaytoUri(
selectedExchange,
@@ -3573,6 +3601,7 @@ export class Wallet {
senderWire: withdrawInfo.senderWire,
exchangeWire: exchangeWire,
});
+ await this.sendReserveInfoToBank(reserve.reservePub);
return {
reservePub: reserve.reservePub,
confirmTransferUrl: withdrawInfo.confirmTransferUrl,
diff --git a/src/walletTypes.ts b/src/walletTypes.ts
index abe9f2712..c657ac02a 100644
--- a/src/walletTypes.ts
+++ b/src/walletTypes.ts
@@ -37,12 +37,7 @@ import {
ExchangeWireFeesRecord,
TipRecord,
} from "./dbTypes";
-import {
- CoinPaySig,
- ContractTerms,
- PayReq,
-} from "./talerTypes";
-
+import { CoinPaySig, ContractTerms, PayReq } from "./talerTypes";
/**
* Response for the create reserve request to the wallet.
@@ -69,7 +64,6 @@ export class CreateReserveResponse {
static checked: (obj: any) => CreateReserveResponse;
}
-
/**
* Information about what will happen when creating a reserve.
*
@@ -138,7 +132,7 @@ export interface ReserveCreationInfo {
*
* Older exchanges don't return version information.
*/
- versionMatch: LibtoolVersion.VersionMatchResult|undefined;
+ versionMatch: LibtoolVersion.VersionMatchResult | undefined;
/**
* Libtool-style version string for the exchange or "unknown"
@@ -152,6 +146,10 @@ export interface ReserveCreationInfo {
walletVersion: string;
}
+export interface WithdrawDetails {
+ withdrawInfo: DownloadedWithdrawInfo;
+ reserveCreationInfo: ReserveCreationInfo | undefined;
+}
/**
* Mapping from currency/exchange to detailed balance
@@ -169,7 +167,6 @@ export interface WalletBalance {
byCurrency: { [currency: string]: WalletBalanceEntry };
}
-
/**
* Detailed wallet balance for a particular currency.
*/
@@ -192,7 +189,6 @@ export interface WalletBalanceEntry {
paybackAmount: AmountJson;
}
-
/**
* Coins used for a payment, with signatures authorizing the payment and the
* coins with remaining value updated to accomodate for a payment.
@@ -203,7 +199,6 @@ export interface PayCoinInfo {
sigs: CoinPaySig[];
}
-
/**
* Listener for notifications from the wallet.
*/
@@ -214,15 +209,17 @@ export interface Notifier {
notify(): void;
}
-
/**
* For terseness.
*/
-export function mkAmount(value: number, fraction: number, currency: string): AmountJson {
- return {value, fraction, currency};
+export function mkAmount(
+ value: number,
+ fraction: number,
+ currency: string,
+): AmountJson {
+ return { value, fraction, currency };
}
-
/**
* Possible results for checkPay.
*/
@@ -231,7 +228,6 @@ export interface CheckPayResult {
coinSelection?: CoinSelectionResult;
}
-
/**
* Result for confirmPay
*/
@@ -239,7 +235,6 @@ export interface ConfirmPayResult {
nextUrl: string;
}
-
/**
* Activity history record.
*/
@@ -266,7 +261,6 @@ export interface HistoryRecord {
detail: any;
}
-
/**
* Query payment response when the payment was found.
*/
@@ -274,7 +268,6 @@ export interface QueryPaymentNotFound {
found: false;
}
-
/**
* Query payment response when the payment wasn't found.
*/
@@ -288,7 +281,6 @@ export interface QueryPaymentFound {
proposalId: number;
}
-
/**
* Information about all sender wire details known to the wallet,
* as well as exchanges that accept these wire types.
@@ -306,7 +298,6 @@ export interface SenderWireInfos {
senderWires: string[];
}
-
/**
* Request to mark a reserve as confirmed.
*/
@@ -351,7 +342,6 @@ export class CreateReserveRequest {
static checked: (obj: any) => CreateReserveRequest;
}
-
/**
* Request to mark a reserve as confirmed.
*/
@@ -371,7 +361,6 @@ export class ConfirmReserveRequest {
static checked: (obj: any) => ConfirmReserveRequest;
}
-
/**
* Wire coins to the user's own bank account.
*/
@@ -403,7 +392,6 @@ export class ReturnCoinsRequest {
static checked: (obj: any) => ReturnCoinsRequest;
}
-
/**
* Result of selecting coins, contains the exchange, and selected
* coins with their denomination.
@@ -418,7 +406,6 @@ export interface CoinSelectionResult {
totalAmount: AmountJson;
}
-
/**
* Named tuple of coin and denomination.
*/
@@ -446,7 +433,6 @@ export interface TipStatus {
tipRecord?: TipRecord;
}
-
/**
* Badge that shows activity for the wallet.
*/
@@ -477,7 +463,6 @@ export interface BenchmarkResult {
repetitions: number;
}
-
/**
* Cached next URL for a particular session id.
*/
@@ -486,14 +471,38 @@ export interface NextUrlResult {
lastSessionId: string | undefined;
}
-export interface PreparePayResult {
- status: "paid" | "session-replayed" | "insufficient-balance" | "payment-possible" | "error";
+export type PreparePayResult =
+ | PreparePayResultError
+ | PreparePayResultInsufficientBalance
+ | PreparePayResultPaid
+ | PreparePayResultPaymentPossible;
+
+export interface PreparePayResultPaymentPossible {
+ status: "payment-possible";
+ proposalId?: number;
contractTerms?: ContractTerms;
- error?: string;
+ totalFees?: AmountJson;
+}
+
+export interface PreparePayResultInsufficientBalance {
+ status: "insufficient-balance";
proposalId?: number;
+ contractTerms?: ContractTerms;
totalFees?: AmountJson;
}
+export interface PreparePayResultError {
+ status: "error";
+ error: string;
+}
+
+export interface PreparePayResultPaid {
+ status: "paid";
+ proposalId?: number;
+ contractTerms?: ContractTerms;
+ nextUrl: string;
+}
+
export interface DownloadedWithdrawInfo {
selectionDone: boolean;
transferDone: boolean;
@@ -503,4 +512,9 @@ export interface DownloadedWithdrawInfo {
confirmTransferUrl?: string;
wireTypes: string[];
extractedStatusUrl: string;
-} \ No newline at end of file
+}
+
+export interface AcceptWithdrawalResponse {
+ reservePub: string;
+ confirmTransferUrl?: string;
+}
diff --git a/src/webex/messages.ts b/src/webex/messages.ts
index 8bb9cafe5..ca0e1c7e1 100644
--- a/src/webex/messages.ts
+++ b/src/webex/messages.ts
@@ -32,12 +32,12 @@ import { UpgradeResponse } from "./wxApi";
* Message type information.
*/
export interface MessageMap {
- "balances": {
- request: { };
+ balances: {
+ request: {};
response: walletTypes.WalletBalance;
};
"dump-db": {
- request: { };
+ request: {};
response: any;
};
"import-db": {
@@ -46,18 +46,18 @@ export interface MessageMap {
};
response: void;
};
- "ping": {
- request: { };
+ ping: {
+ request: {};
response: void;
};
"reset-db": {
- request: { };
+ request: {};
response: void;
};
"create-reserve": {
request: {
amount: AmountJson;
- exchange: string
+ exchange: string;
};
response: void;
};
@@ -70,11 +70,11 @@ export interface MessageMap {
response: walletTypes.ConfirmPayResult;
};
"check-pay": {
- request: { proposalId: number; };
+ request: { proposalId: number };
response: walletTypes.CheckPayResult;
};
"query-payment": {
- request: { };
+ request: {};
response: dbTypes.PurchaseRecord;
};
"exchange-info": {
@@ -90,11 +90,11 @@ export interface MessageMap {
response: string;
};
"reserve-creation-info": {
- request: { baseUrl: string, amount: AmountJson };
+ request: { baseUrl: string; amount: AmountJson };
response: walletTypes.ReserveCreationInfo;
};
"get-history": {
- request: { };
+ request: {};
response: walletTypes.HistoryRecord[];
};
"get-proposal": {
@@ -110,7 +110,7 @@ export interface MessageMap {
response: any;
};
"get-currencies": {
- request: { };
+ request: {};
response: dbTypes.CurrencyRecord[];
};
"update-currency": {
@@ -118,7 +118,7 @@ export interface MessageMap {
response: void;
};
"get-exchanges": {
- request: { };
+ request: {};
response: dbTypes.ExchangeRecord[];
};
"get-reserves": {
@@ -126,7 +126,7 @@ export interface MessageMap {
response: dbTypes.ReserveRecord[];
};
"get-payback-reserves": {
- request: { };
+ request: {};
response: dbTypes.ReserveRecord[];
};
"withdraw-payback-reserve": {
@@ -146,15 +146,15 @@ export interface MessageMap {
response: void;
};
"check-upgrade": {
- request: { };
+ request: {};
response: UpgradeResponse;
};
"get-sender-wire-infos": {
- request: { };
+ request: {};
response: walletTypes.SenderWireInfos;
};
"return-coins": {
- request: { };
+ request: {};
response: void;
};
"log-and-display-error": {
@@ -182,7 +182,7 @@ export interface MessageMap {
response: walletTypes.TipStatus;
};
"clear-notification": {
- request: { };
+ request: {};
response: void;
};
"taler-pay": {
@@ -194,23 +194,36 @@ export interface MessageMap {
response: number;
};
"submit-pay": {
- request: { contractTermsHash: string, sessionId: string | undefined };
+ request: { contractTermsHash: string; sessionId: string | undefined };
response: walletTypes.ConfirmPayResult;
};
"accept-refund": {
- request: { refundUrl: string }
+ request: { refundUrl: string };
response: string;
};
"abort-failed-payment": {
- request: { contractTermsHash: string }
+ request: { contractTermsHash: string };
response: void;
};
"benchmark-crypto": {
- request: { repetitions: number }
+ request: { repetitions: number };
response: walletTypes.BenchmarkResult;
};
+ "get-withdraw-details": {
+ request: { talerWithdrawUri: string; maybeSelectedExchange: string | undefined };
+ response: walletTypes.WithdrawDetails;
+ };
+ "accept-withdrawal": {
+ request: { talerWithdrawUri: string; selectedExchange: string };
+ response: walletTypes.AcceptWithdrawalResponse;
+ };
+ "prepare-pay": {
+ request: { talerPayUri: string };
+ response: walletTypes.PreparePayResult;
+ };
}
+
/**
* String literal types for messages.
*/
@@ -219,14 +232,19 @@ export type MessageType = keyof MessageMap;
/**
* Make a request whose details match the request type.
*/
-export function makeRequest<T extends MessageType>(type: T, details: MessageMap[T]["request"]) {
+export function makeRequest<T extends MessageType>(
+ type: T,
+ details: MessageMap[T]["request"],
+) {
return { type, details };
}
/**
* Make a response that matches the request type.
*/
-export function makeResponse<T extends MessageType>(type: T, response: MessageMap[T]["response"]) {
+export function makeResponse<T extends MessageType>(
+ type: T,
+ response: MessageMap[T]["response"],
+) {
return response;
}
-
diff --git a/src/webex/pages/confirm-contract.tsx b/src/webex/pages/confirm-contract.tsx
deleted file mode 100644
index d24613794..000000000
--- a/src/webex/pages/confirm-contract.tsx
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Page shown to the user to confirm entering
- * a contract.
- */
-
-
-/**
- * Imports.
- */
-import * as i18n from "../../i18n";
-
-import { runOnceWhenReady } from "./common";
-
-import {
- ExchangeRecord,
- ProposalDownloadRecord,
-} from "../../dbTypes";
-import { ContractTerms } from "../../talerTypes";
-import {
- CheckPayResult,
-} from "../../walletTypes";
-
-import { renderAmount } from "../renderHtml";
-import * as wxApi from "../wxApi";
-
-import * as React from "react";
-import * as ReactDOM from "react-dom";
-import URI = require("urijs");
-import { WalletApiError } from "../wxApi";
-
-import * as Amounts from "../../amounts";
-
-
-interface DetailState {
- collapsed: boolean;
-}
-
-interface DetailProps {
- contractTerms: ContractTerms;
- collapsed: boolean;
- exchanges: ExchangeRecord[] | undefined;
-}
-
-
-class Details extends React.Component<DetailProps, DetailState> {
- constructor(props: DetailProps) {
- super(props);
- console.log("new Details component created");
- this.state = {
- collapsed: props.collapsed,
- };
-
- console.log("initial state:", this.state);
- }
-
- render() {
- if (this.state.collapsed) {
- return (
- <div>
- <button className="linky"
- onClick={() => { this.setState({collapsed: false} as any); }}>
- <i18n.Translate wrap="span">
- show more details
- </i18n.Translate>
- </button>
- </div>
- );
- } else {
- return (
- <div>
- <button className="linky"
- onClick={() => this.setState({collapsed: true} as any)}>
- i18n.str`show fewer details`
- </button>
- <div>
- {i18n.str`Accepted exchanges:`}
- <ul>
- {this.props.contractTerms.exchanges.map(
- (e) => <li>{`${e.url}: ${e.master_pub}`}</li>)}
- </ul>
- {i18n.str`Exchanges in the wallet:`}
- <ul>
- {(this.props.exchanges || []).map(
- (e: ExchangeRecord) =>
- <li>{`${e.baseUrl}: ${e.masterPublicKey}`}</li>)}
- </ul>
- </div>
- </div>);
- }
- }
-}
-
-interface ContractPromptProps {
- proposalId?: number;
- contractUrl?: string;
- sessionId?: string;
- resourceUrl?: string;
-}
-
-interface ContractPromptState {
- proposalId: number | undefined;
- proposal: ProposalDownloadRecord | undefined;
- checkPayError: string | undefined;
- confirmPayError: object | undefined;
- payDisabled: boolean;
- alreadyPaid: boolean;
- exchanges: ExchangeRecord[] | undefined;
- /**
- * Don't request updates to proposal state while
- * this is set to true, to avoid UI flickering
- * when pressing pay.
- */
- holdCheck: boolean;
- payStatus?: CheckPayResult;
- replaying: boolean;
- payInProgress: boolean;
- payAttempt: number;
- working: boolean;
- abortDone: boolean;
- abortStarted: boolean;
-}
-
-class ContractPrompt extends React.Component<ContractPromptProps, ContractPromptState> {
- constructor(props: ContractPromptProps) {
- super(props);
- this.state = {
- abortDone: false,
- abortStarted: false,
- alreadyPaid: false,
- checkPayError: undefined,
- confirmPayError: undefined,
- exchanges: undefined,
- holdCheck: false,
- payAttempt: 0,
- payDisabled: true,
- payInProgress: false,
- proposal: undefined,
- proposalId: props.proposalId,
- replaying: false,
- working: false,
- };
- }
-
- componentWillMount() {
- this.update();
- }
-
- componentWillUnmount() {
- // FIXME: abort running ops
- }
-
- async update() {
- if (this.props.resourceUrl) {
- const p = await wxApi.queryPaymentByFulfillmentUrl(this.props.resourceUrl);
- console.log("query for resource url", this.props.resourceUrl, "result", p);
- if (p && p.finished) {
- if (p.lastSessionSig === undefined || p.lastSessionSig === this.props.sessionId) {
- const nextUrl = new URI(p.contractTerms.fulfillment_url);
- nextUrl.addSearch("order_id", p.contractTerms.order_id);
- if (p.lastSessionSig) {
- nextUrl.addSearch("session_sig", p.lastSessionSig);
- }
- location.replace(nextUrl.href());
- return;
- } else {
- // We're in a new session
- this.setState({ replaying: true });
- // FIXME: This could also go wrong. However the payment
- // was already successful once, so we can just retry and not refund it.
- const payResult = await wxApi.submitPay(p.contractTermsHash, this.props.sessionId);
- console.log("payResult", payResult);
- location.replace(payResult.nextUrl);
- return;
- }
- }
- }
- let proposalId = this.props.proposalId;
- if (proposalId === undefined) {
- if (this.props.contractUrl === undefined) {
- // Nothing we can do ...
- return;
- }
- proposalId = await wxApi.downloadProposal(this.props.contractUrl);
- }
- const proposal = await wxApi.getProposal(proposalId);
- this.setState({ proposal, proposalId });
- this.checkPayment();
- const exchanges = await wxApi.getExchanges();
- this.setState({ exchanges });
- }
-
- async checkPayment() {
- window.setTimeout(() => this.checkPayment(), 500);
- if (this.state.holdCheck) {
- return;
- }
- const proposalId = this.state.proposalId;
- if (proposalId === undefined) {
- return;
- }
- const payStatus = await wxApi.checkPay(proposalId);
- if (payStatus.status === "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.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({ checkPayError: msgInsufficient });
- } else {
- this.setState({ checkPayError: msgNoMatch });
- }
- } else {
- this.setState({ checkPayError: msgInsufficient });
- }
- this.setState({ payDisabled: true });
- } else if (payStatus.status === "paid") {
- this.setState({ alreadyPaid: true, payDisabled: false, checkPayError: undefined, payStatus });
- } else {
- this.setState({ payDisabled: false, checkPayError: undefined, payStatus });
- }
- }
-
- async doPayment() {
- const proposal = this.state.proposal;
- this.setState({ holdCheck: true, payAttempt: this.state.payAttempt + 1});
- if (!proposal) {
- return;
- }
- const proposalId = proposal.id;
- if (proposalId === undefined) {
- console.error("proposal has no id");
- return;
- }
- console.log("confirmPay with", proposalId, "and", this.props.sessionId);
- let payResult;
- this.setState({ working: true });
- try {
- payResult = await wxApi.confirmPay(proposalId, this.props.sessionId);
- } catch (e) {
- if (!(e instanceof WalletApiError)) {
- throw e;
- }
- this.setState({ confirmPayError: e.detail });
- return;
- }
- console.log("payResult", payResult);
- document.location.replace(payResult.nextUrl);
- this.setState({ holdCheck: true });
- }
-
-
- async abortPayment() {
- const proposal = this.state.proposal;
- this.setState({ holdCheck: true, abortStarted: true });
- if (!proposal) {
- return;
- }
- wxApi.abortFailedPayment(proposal.contractTermsHash);
- this.setState({ abortDone: true });
- }
-
-
- render() {
- if (this.props.contractUrl === undefined && this.props.proposalId === undefined) {
- return <span>Error: either contractUrl or proposalId must be given</span>;
- }
- if (this.state.replaying) {
- return <span>Re-submitting existing payment</span>;
- }
- if (this.state.proposalId === undefined) {
- return <span>Downloading contract terms</span>;
- }
- if (!this.state.proposal) {
- return <span>...</span>;
- }
- const c = this.state.proposal.contractTerms;
- let merchantName;
- if (c.merchant && c.merchant.name) {
- merchantName = <strong>{c.merchant.name}</strong>;
- } else {
- merchantName = <strong>(pub: {c.merchant_pub})</strong>;
- }
- const amount = <strong>{renderAmount(Amounts.parseOrThrow(c.amount))}</strong>;
- console.log("payStatus", this.state.payStatus);
-
- let products = null;
- if (c.products.length) {
- products = (
- <div>
- <span>The following items are included:</span>
- <ul>
- {c.products.map(
- (p: any, i: number) => (<li key={i}>{p.description}: {renderAmount(p.price)}</li>))
- }
- </ul>
- </div>
- );
- }
-
- const ConfirmButton = () => (
- <button className="pure-button button-success"
- disabled={this.state.payDisabled}
- onClick={() => this.doPayment()}>
- {i18n.str`Confirm payment`}
- </button>
- );
-
- const WorkingButton = () => (
- <div>
- <button className="pure-button button-success"
- disabled={this.state.payDisabled}
- onClick={() => this.doPayment()}>
- <span><object className="svg-icon svg-baseline" data="/img/spinner-bars.svg" /> </span>
- {i18n.str`Submitting payment`}
- </button>
- </div>
- );
-
- const ConfirmPayDialog = () => (
- <div>
- {this.state.working ? WorkingButton() : ConfirmButton()}
- <div>
- {(this.state.alreadyPaid
- ? <p className="okaybox">
- {i18n.str`You already paid for this, clicking "Confirm payment" will not cost money again.`}
- </p>
- : <p />)}
- {(this.state.checkPayError ? <p className="errorbox">{this.state.checkPayError}</p> : <p />)}
- </div>
- <Details exchanges={this.state.exchanges} contractTerms={c} collapsed={!this.state.checkPayError}/>
- </div>
- );
-
- const PayErrorDialog = () => (
- <div>
- <p>There was an error paying (attempt #{this.state.payAttempt}):</p>
- <pre>{JSON.stringify(this.state.confirmPayError)}</pre>
- { this.state.abortStarted
- ? <span>{i18n.str`Aborting payment ...`}</span>
- : this.state.abortDone
- ? <span>{i18n.str`Payment aborted!`}</span>
- : <>
- <button className="pure-button" onClick={() => this.doPayment()}>
- {i18n.str`Retry Payment`}
- </button>
- <button className="pure-button" onClick={() => this.abortPayment()}>
- {i18n.str`Abort Payment`}
- </button>
- </>
- }
- </div>
- );
-
- return (
- <div>
- <i18n.Translate wrap="p">
- The merchant{" "}<span>{merchantName}</span> offers you to purchase:
- </i18n.Translate>
- <div style={{"textAlign": "center"}}>
- <strong>{c.summary}</strong>
- </div>
- <strong></strong>
- {products}
- {(this.state.payStatus && this.state.payStatus.coinSelection)
- ? <i18n.Translate wrap="p">
- The total price is <span>{amount} </span>
- (plus <span>{renderAmount(this.state.payStatus.coinSelection.totalFees)}</span> fees).
- </i18n.Translate>
- :
- <i18n.Translate wrap="p">The total price is <span>{amount}</span>.</i18n.Translate>
- }
- { this.state.confirmPayError
- ? PayErrorDialog()
- : ConfirmPayDialog()
- }
- </div>
- );
- }
-}
-
-
-runOnceWhenReady(() => {
- const url = new URI(document.location.href);
- const query: any = URI.parseQuery(url.query());
-
- let proposalId;
- try {
- proposalId = JSON.parse(query.proposalId);
- } catch {
- // ignore error
- }
- const sessionId = query.sessionId;
- const contractUrl = query.contractUrl;
- const resourceUrl = query.resourceUrl;
-
- ReactDOM.render(
- <ContractPrompt {...{ proposalId, contractUrl, sessionId, resourceUrl }}/>,
- document.getElementById("contract")!);
-});
diff --git a/src/webex/pages/confirm-create-reserve.tsx b/src/webex/pages/confirm-create-reserve.tsx
deleted file mode 100644
index 2d4f41dfe..000000000
--- a/src/webex/pages/confirm-create-reserve.tsx
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- This file is part of TALER
- (C) 2015-2016 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-
-/**
- * Page shown to the user to confirm creation
- * of a reserve, usually requested by the bank.
- *
- * @author Florian Dold
- */
-
-import { canonicalizeBaseUrl } from "../../helpers";
-import * as i18n from "../../i18n";
-
-import { AmountJson } from "../../amounts";
-import * as Amounts from "../../amounts";
-
-import {
- CurrencyRecord,
-} from "../../dbTypes";
-import {
- CreateReserveResponse,
- ReserveCreationInfo,
-} from "../../walletTypes";
-
-import { ImplicitStateComponent, StateHolder } from "../components";
-import {
- WalletApiError,
- createReserve,
- getCurrency,
- getExchangeInfo,
- getReserveCreationInfo,
-} from "../wxApi";
-
-import {
- WithdrawDetailView,
- renderAmount,
-} from "../renderHtml";
-
-import * as React from "react";
-import * as ReactDOM from "react-dom";
-import URI = require("urijs");
-
-
-function delay<T>(delayMs: number, value: T): Promise<T> {
- return new Promise<T>((resolve, reject) => {
- setTimeout(() => resolve(value), delayMs);
- });
-}
-
-class EventTrigger {
- private triggerResolve: any;
- private triggerPromise: Promise<boolean>;
-
- constructor() {
- this.reset();
- }
-
- private reset() {
- this.triggerPromise = new Promise<boolean>((resolve, reject) => {
- this.triggerResolve = resolve;
- });
- }
-
- trigger() {
- this.triggerResolve(false);
- this.reset();
- }
-
- async wait(delayMs: number): Promise<boolean> {
- return await Promise.race([this.triggerPromise, delay(delayMs, true)]);
- }
-}
-
-
-interface ExchangeSelectionProps {
- suggestedExchangeUrl: string;
- amount: AmountJson;
- callback_url: string;
- wt_types: string[];
- currencyRecord: CurrencyRecord|null;
- sender_wire: string | undefined;
-}
-
-interface ManualSelectionProps {
- onSelect(url: string): void;
- initialUrl: string;
-}
-
-class ManualSelection extends ImplicitStateComponent<ManualSelectionProps> {
- private url: StateHolder<string> = this.makeState("");
- private errorMessage: StateHolder<string|null> = this.makeState(null);
- private isOkay: StateHolder<boolean> = this.makeState(false);
- private updateEvent = new EventTrigger();
- constructor(p: ManualSelectionProps) {
- super(p);
- this.url(p.initialUrl);
- this.update();
- }
- render() {
- return (
- <div className="pure-g pure-form pure-form-stacked">
- <div className="pure-u-1">
- <label>URL</label>
- <input className="url" type="text" spellCheck={false}
- value={this.url()}
- key="exchange-url-input"
- onInput={(e) => this.onUrlChanged((e.target as HTMLInputElement).value)}
- onChange={(e) => this.onUrlChanged((e.target as HTMLInputElement).value)} />
- </div>
- <div className="pure-u-1">
- <button className="pure-button button-success"
- disabled={!this.isOkay()}
- onClick={() => this.props.onSelect(this.url())}>
- {i18n.str`Select`}
- </button>
- <span> </span>
- {this.errorMessage()}
- </div>
- </div>
- );
- }
-
- async update() {
- this.errorMessage(null);
- this.isOkay(false);
- if (!this.url()) {
- return;
- }
- const parsedUrl = new URI(this.url()!);
- if (parsedUrl.is("relative")) {
- this.errorMessage(i18n.str`Error: URL may not be relative`);
- this.isOkay(false);
- return;
- }
- try {
- const url = canonicalizeBaseUrl(this.url()!);
- await getExchangeInfo(url);
- console.log("getExchangeInfo returned");
- this.isOkay(true);
- } catch (e) {
- if (!(e instanceof WalletApiError)) {
- // maybe it's something more serious, don't handle here!
- throw e;
- }
- console.log(`got error "${e.message} "with detail`, e.detail);
- this.errorMessage(i18n.str`Invalid exchange URL (${e.message})`);
- }
- }
-
- async onUrlChanged(s: string) {
- this.url(s);
- this.errorMessage(null);
- this.isOkay(false);
- this.updateEvent.trigger();
- const waited = await this.updateEvent.wait(200);
- if (waited) {
- // Run the actual update if nobody else preempted us.
- this.update();
- }
- }
-}
-
-
-class ExchangeSelection extends ImplicitStateComponent<ExchangeSelectionProps> {
- private statusString: StateHolder<string|null> = this.makeState(null);
- private reserveCreationInfo: StateHolder<ReserveCreationInfo|null> = this.makeState(
- null);
- private url: StateHolder<string|null> = this.makeState(null);
-
- private selectingExchange: StateHolder<boolean> = this.makeState(false);
-
- constructor(props: ExchangeSelectionProps) {
- super(props);
- const prefilledExchangesUrls = [];
- if (props.currencyRecord) {
- const exchanges = props.currencyRecord.exchanges.map((x) => x.baseUrl);
- prefilledExchangesUrls.push(...exchanges);
- }
- if (props.suggestedExchangeUrl) {
- prefilledExchangesUrls.push(props.suggestedExchangeUrl);
- }
- if (prefilledExchangesUrls.length !== 0) {
- this.url(prefilledExchangesUrls[0]);
- this.forceReserveUpdate();
- } else {
- this.selectingExchange(true);
- }
- }
-
- renderFeeStatus() {
- const rci = this.reserveCreationInfo();
- if (rci) {
- const totalCost = Amounts.add(rci.overhead, rci.withdrawFee).amount;
- let trustMessage;
- if (rci.isTrusted) {
- trustMessage = (
- <i18n.Translate wrap="p">
- The exchange is trusted by the wallet.
- </i18n.Translate>
- );
- } else if (rci.isAudited) {
- trustMessage = (
- <i18n.Translate wrap="p">
- The exchange is audited by a trusted auditor.
- </i18n.Translate>
- );
- } else {
- trustMessage = (
- <i18n.Translate wrap="p">
- Warning: The exchange is neither directly trusted nor audited by a trusted auditor.
- If you withdraw from this exchange, it will be trusted in the future.
- </i18n.Translate>
- );
- }
- return (
- <div>
- <i18n.Translate wrap="p">
- Using exchange provider <strong>{this.url()}</strong>.
- The exchange provider will charge
- {" "}<span>{renderAmount(totalCost)}</span>{" "}
- in fees.
- </i18n.Translate>
- {trustMessage}
- </div>
- );
- }
- if (this.url() && !this.statusString()) {
- const shortName = new URI(this.url()!).host();
- return (
- <i18n.Translate wrap="p">
- Waiting for a response from
- <span> </span>
- <em>{shortName}</em>
- </i18n.Translate>
- );
- }
- if (this.statusString()) {
- return (
- <p>
- <strong style={{color: "red"}}>{this.statusString()}</strong>
- </p>
- );
- }
- return (
- <p>
- {i18n.str`Information about fees will be available when an exchange provider is selected.`}
- </p>
- );
- }
-
- renderUpdateStatus() {
- const rci = this.reserveCreationInfo();
- if (!rci) {
- return null;
- }
- if (!rci.versionMatch) {
- return null;
- }
- if (rci.versionMatch.compatible) {
- return null;
- }
- if (rci.versionMatch.currentCmp === -1) {
- return (
- <p className="errorbox">
- <i18n.Translate wrap="span">
- Your wallet (protocol version <span>{rci.walletVersion}</span>) might be outdated.<span> </span>
- The exchange has a higher, incompatible
- protocol version (<span>{rci.exchangeVersion}</span>).
- </i18n.Translate>
- </p>
- );
- }
- if (rci.versionMatch.currentCmp === 1) {
- return (
- <p className="errorbox">
- <i18n.Translate wrap="span">
- The chosen exchange (protocol version <span>{rci.exchangeVersion}</span> might be outdated.<span> </span>
- The exchange has a lower, incompatible
- protocol version than your wallet (protocol version <span>{rci.walletVersion}</span>).
- </i18n.Translate>
- </p>
- );
- }
- throw Error("not reached");
- }
-
- renderConfirm() {
- return (
- <div>
- {this.renderFeeStatus()}
- <p>
- <button className="pure-button button-success"
- disabled={this.reserveCreationInfo() === null}
- onClick={() => this.confirmReserve()}>
- {i18n.str`Accept fees and withdraw`}
- </button>
- { " " }
- <button className="pure-button button-secondary"
- onClick={() => this.selectingExchange(true)}>
- {i18n.str`Change Exchange Provider`}
- </button>
- </p>
- {this.renderUpdateStatus()}
- <WithdrawDetailView rci={this.reserveCreationInfo()} />
- </div>
- );
- }
-
- select(url: string) {
- this.reserveCreationInfo(null);
- this.url(url);
- this.selectingExchange(false);
- this.forceReserveUpdate();
- }
-
- renderSelect() {
- const exchanges = (this.props.currencyRecord && this.props.currencyRecord.exchanges) || [];
- console.log(exchanges);
- return (
- <div>
- {i18n.str`Please select an exchange. You can review the details before after your selection.`}
-
- {this.props.suggestedExchangeUrl && (
- <div>
- <h2>Bank Suggestion</h2>
- <button className="pure-button button-success" onClick={() => this.select(this.props.suggestedExchangeUrl)}>
- <i18n.Translate wrap="span">
- Select <strong>{this.props.suggestedExchangeUrl}</strong>
- </i18n.Translate>
- </button>
- </div>
- )}
-
- {exchanges.length > 0 && (
- <div>
- <h2>Known Exchanges</h2>
- {exchanges.map((e) => (
- <button key={e.baseUrl} className="pure-button button-success" onClick={() => this.select(e.baseUrl)}>
- <i18n.Translate>
- Select <strong>{e.baseUrl}</strong>
- </i18n.Translate>
- </button>
- ))}
- </div>
- )}
-
- <h2>i18n.str`Manual Selection`</h2>
- <ManualSelection initialUrl={this.url() || ""} onSelect={(url: string) => this.select(url)} />
- </div>
- );
- }
-
- render(): JSX.Element {
- return (
- <div>
- <i18n.Translate wrap="p">
- You are about to withdraw
- {" "}<strong>{renderAmount(this.props.amount)}</strong>{" "}
- from your bank account into your wallet.
- </i18n.Translate>
- {this.selectingExchange() ? this.renderSelect() : this.renderConfirm()}
- </div>
- );
- }
-
-
- confirmReserve() {
- this.confirmReserveImpl(this.reserveCreationInfo()!,
- this.url()!,
- this.props.amount,
- this.props.callback_url,
- this.props.sender_wire);
- }
-
- /**
- * Do an update of the reserve creation info, without any debouncing.
- */
- async forceReserveUpdate() {
- this.reserveCreationInfo(null);
- try {
- const url = canonicalizeBaseUrl(this.url()!);
- const r = await getReserveCreationInfo(url,
- this.props.amount);
- console.log("get exchange info resolved");
- this.reserveCreationInfo(r);
- console.dir(r);
- } catch (e) {
- console.log("get exchange info rejected", e);
- this.statusString(`Error: ${e.message}`);
- // Re-try every 5 seconds as long as there is a problem
- setTimeout(() => this.statusString() ? this.forceReserveUpdate() : undefined, 5000);
- }
- }
-
- async confirmReserveImpl(rci: ReserveCreationInfo,
- exchange: string,
- amount: AmountJson,
- callback_url: string,
- sender_wire: string | undefined) {
- const rawResp = await createReserve({
- amount,
- exchange: canonicalizeBaseUrl(exchange),
- senderWire: sender_wire,
- });
- if (!rawResp) {
- throw Error("empty response");
- }
- // FIXME: filter out types that bank/exchange don't have in common
- const exchangeWireAccounts = [];
-
- for (let acct of rci.exchangeWireAccounts) {
- const payto = new URI(acct);
- if (payto.scheme() != "payto") {
- console.warn("unknown wire account URI scheme", acct);
- continue;
- }
- if (this.props.wt_types.includes(payto.authority())) {
- exchangeWireAccounts.push(acct);
- }
- }
-
- const chosenAcct = exchangeWireAccounts[0];
-
- if (!chosenAcct) {
- throw Error("no exchange account matches the bank's supported types");
- }
-
- if (!rawResp.error) {
- const resp = CreateReserveResponse.checked(rawResp);
- const q: {[name: string]: string|number} = {
- amount_currency: amount.currency,
- amount_fraction: amount.fraction,
- amount_value: amount.value,
- exchange: resp.exchange,
- exchange_wire_details: chosenAcct,
- reserve_pub: resp.reservePub,
- };
- const url = new URI(callback_url).addQuery(q);
- if (!url.is("absolute")) {
- throw Error("callback url is not absolute");
- }
- console.log("going to", url.href());
- document.location.href = url.href();
- } else {
- this.statusString(
- i18n.str`Oops, something went wrong. The wallet responded with error status (${rawResp.error}).`);
- }
- }
-
- renderStatus(): any {
- if (this.statusString()) {
- return <p><strong style={{color: "red"}}>{this.statusString()}</strong></p>;
- } else if (!this.reserveCreationInfo()) {
- return <p>{i18n.str`Checking URL, please wait ...`}</p>;
- }
- return "";
- }
-}
-
-async function main() {
- try {
- const url = new URI(document.location.href);
- const query: any = URI.parseQuery(url.query());
- let amount;
- try {
- amount = AmountJson.checked(JSON.parse(query.amount));
- } catch (e) {
- throw Error(i18n.str`Can't parse amount: ${e.message}`);
- }
- const callback_url = query.callback_url;
- let wt_types;
- try {
- wt_types = JSON.parse(query.wt_types);
- } catch (e) {
- throw Error(i18n.str`Can't parse wire_types: ${e.message}`);
- }
-
- let sender_wire;
- if (query.sender_wire) {
- let senderWireUri = new URI(query.sender_wire);
- if (senderWireUri.scheme() != "payto") {
- throw Error("sender wire info must be a payto URI");
- }
- sender_wire = query.sender_wire;
- }
-
- const suggestedExchangeUrl = query.suggested_exchange_url;
- const currencyRecord = await getCurrency(amount.currency);
-
- const args = {
- amount,
- callback_url,
- currencyRecord,
- sender_wire,
- suggestedExchangeUrl,
- wt_types,
- };
-
- ReactDOM.render(<ExchangeSelection {...args} />, document.getElementById(
- "exchange-selection")!);
-
- } catch (e) {
- // TODO: provide more context information, maybe factor it out into a
- // TODO:generic error reporting function or component.
- document.body.innerText = i18n.str`Fatal error: "${e.message}".`;
- console.error("got error", e);
- }
-}
-
-document.addEventListener("DOMContentLoaded", () => {
- main();
-});
diff --git a/src/webex/pages/confirm-contract.html b/src/webex/pages/pay.html
index 5a949159a..d3bf992ad 100644
--- a/src/webex/pages/confirm-contract.html
+++ b/src/webex/pages/pay.html
@@ -11,7 +11,7 @@
<link rel="icon" href="/img/icon.png">
<script src="/dist/page-common-bundle.js"></script>
- <script src="/dist/confirm-contract-bundle.js"></script>
+ <script src="/dist/pay-bundle.js"></script>
<style>
button.accept {
diff --git a/src/webex/pages/pay.tsx b/src/webex/pages/pay.tsx
new file mode 100644
index 000000000..d929426c4
--- /dev/null
+++ b/src/webex/pages/pay.tsx
@@ -0,0 +1,173 @@
+/*
+ This file is part of TALER
+ (C) 2015 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page shown to the user to confirm entering
+ * a contract.
+ */
+
+/**
+ * Imports.
+ */
+import * as i18n from "../../i18n";
+
+import { runOnceWhenReady } from "./common";
+
+import { ExchangeRecord, ProposalDownloadRecord } from "../../dbTypes";
+import { ContractTerms } from "../../talerTypes";
+import { CheckPayResult, PreparePayResult } from "../../walletTypes";
+
+import { renderAmount } from "../renderHtml";
+import * as wxApi from "../wxApi";
+
+import React, { useState, useEffect } from "react";
+import * as ReactDOM from "react-dom";
+import URI = require("urijs");
+import { WalletApiError } from "../wxApi";
+
+import * as Amounts from "../../amounts";
+
+function TalerPayDialog({ talerPayUri }: { talerPayUri: string }) {
+ const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>();
+ const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
+ const [numTries, setNumTries] = useState(0);
+ let totalFees: Amounts.AmountJson | undefined = undefined;
+
+ useEffect(() => {
+ const doFetch = async () => {
+ const p = await wxApi.preparePay(talerPayUri);
+ setPayStatus(p);
+ };
+ doFetch();
+ });
+
+ if (!payStatus) {
+ return <span>Loading payment information ...</span>;
+ }
+
+ if (payStatus.status === "error") {
+ return <span>Error: {payStatus.error}</span>;
+ }
+
+ if (payStatus.status === "payment-possible") {
+ totalFees = payStatus.totalFees;
+ }
+
+ if (payStatus.status === "paid" && numTries === 0) {
+ return (
+ <span>
+ You have already paid for this article. Click{" "}
+ <a href={payStatus.nextUrl}>here</a> to view it again.
+ </span>
+ );
+ }
+
+ const contractTerms = payStatus.contractTerms;
+
+ if (!contractTerms) {
+ return (
+ <span>
+ Error: did not get contract terms from merchant or wallet backend.
+ </span>
+ );
+ }
+
+ let merchantName: React.ReactElement;
+ if (contractTerms.merchant && contractTerms.merchant.name) {
+ merchantName = <strong>{contractTerms.merchant.name}</strong>;
+ } else {
+ merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
+ }
+
+ const amount = (
+ <strong>{renderAmount(Amounts.parseOrThrow(contractTerms.amount))}</strong>
+ );
+
+ const doPayment = async () => {
+ setNumTries(numTries + 1);
+ try {
+ const res = await wxApi.confirmPay(payStatus!.proposalId!, undefined);
+ document.location.href = res.nextUrl;
+ } catch (e) {
+ console.error(e);
+ setPayErrMsg(e.message);
+ }
+ };
+
+ return (
+ <div>
+ <p>
+ <i18n.Translate wrap="p">
+ The merchant <span>{merchantName}</span> offers you to purchase:
+ </i18n.Translate>
+ <div style={{ textAlign: "center" }}>
+ <strong>{contractTerms.summary}</strong>
+ </div>
+ {totalFees ? (
+ <i18n.Translate wrap="p">
+ The total price is <span>{amount} </span>
+ (plus <span>{renderAmount(totalFees)}</span> fees).
+ </i18n.Translate>
+ ) : (
+ <i18n.Translate wrap="p">
+ The total price is <span>{amount}</span>.
+ </i18n.Translate>
+ )}
+ </p>
+
+ {payErrMsg ? (
+ <div>
+ <p>Payment failed: {payErrMsg}</p>
+ <button
+ className="pure-button button-success"
+ onClick={() => doPayment()}
+ >
+ {i18n.str`Retry`}
+ </button>
+ </div>
+ ) : (
+ <div>
+ <button
+ className="pure-button button-success"
+ onClick={() => doPayment()}
+ >
+ {i18n.str`Confirm payment`}
+ </button>
+ </div>
+ )}
+ </div>
+ );
+}
+
+runOnceWhenReady(() => {
+ try {
+ const url = new URI(document.location.href);
+ const query: any = URI.parseQuery(url.query());
+
+ let talerPayUri = query.talerPayUri;
+
+ ReactDOM.render(
+ <TalerPayDialog talerPayUri={talerPayUri} />,
+ document.getElementById("contract")!,
+ );
+ } catch (e) {
+ ReactDOM.render(
+ <span>Fatal error: {e.message}</span>,
+ document.getElementById("contract")!,
+ );
+ console.error(e);
+ }
+});
diff --git a/src/webex/pages/confirm-create-reserve.html b/src/webex/pages/withdraw.html
index 17daf4dde..8b1e59b1d 100644
--- a/src/webex/pages/confirm-create-reserve.html
+++ b/src/webex/pages/withdraw.html
@@ -10,7 +10,7 @@
<link rel="stylesheet" type="text/css" href="../style/wallet.css">
<script src="/dist/page-common-bundle.js"></script>
- <script src="/dist/confirm-create-reserve-bundle.js"></script>
+ <script src="/dist/withdraw-bundle.js"></script>
</head>
diff --git a/src/webex/pages/withdraw.tsx b/src/webex/pages/withdraw.tsx
new file mode 100644
index 000000000..66617373b
--- /dev/null
+++ b/src/webex/pages/withdraw.tsx
@@ -0,0 +1,231 @@
+/*
+ This file is part of TALER
+ (C) 2015-2016 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page shown to the user to confirm creation
+ * of a reserve, usually requested by the bank.
+ *
+ * @author Florian Dold
+ */
+
+import { canonicalizeBaseUrl } from "../../helpers";
+import * as i18n from "../../i18n";
+
+import { AmountJson } from "../../amounts";
+import * as Amounts from "../../amounts";
+
+import { CurrencyRecord } from "../../dbTypes";
+import {
+ CreateReserveResponse,
+ ReserveCreationInfo,
+ WithdrawDetails,
+} from "../../walletTypes";
+
+import { ImplicitStateComponent, StateHolder } from "../components";
+
+import { WithdrawDetailView, renderAmount } from "../renderHtml";
+
+import React, { useState, useEffect } from "react";
+import * as ReactDOM from "react-dom";
+import URI = require("urijs");
+import { getWithdrawDetails, acceptWithdrawal } from "../wxApi";
+
+function NewExchangeSelection(props: { talerWithdrawUri: string }) {
+ const [details, setDetails] = useState<WithdrawDetails | undefined>();
+ const [selectedExchange, setSelectedExchange] = useState<
+ string | undefined
+ >();
+ const talerWithdrawUri = props.talerWithdrawUri;
+ const [cancelled, setCancelled] = useState(false);
+ const [selecting, setSelecting] = useState(false);
+ const [customUrl, setCustomUrl] = useState<string>("");
+ const [errMsg, setErrMsg] = useState<string | undefined>("");
+
+ useEffect(() => {
+ const fetchData = async () => {
+ console.log("getting from", talerWithdrawUri);
+ let d: WithdrawDetails | undefined = undefined;
+ try {
+ d = await getWithdrawDetails(talerWithdrawUri, selectedExchange);
+ } catch (e) {
+ console.error("error getting withdraw details", e);
+ setErrMsg(e.message);
+ return;
+ }
+ console.log("got withdrawDetails", d);
+ if (!selectedExchange && d.withdrawInfo.suggestedExchange) {
+ console.log("setting selected exchange");
+ setSelectedExchange(d.withdrawInfo.suggestedExchange);
+ }
+ setDetails(d);
+ };
+ fetchData();
+ }, [selectedExchange, errMsg, selecting]);
+
+ if (errMsg) {
+ return (
+ <div>
+ <i18n.Translate wrap="p">
+ Could not get details for withdraw operation:
+ </i18n.Translate>
+ <p style={{ color: "red" }}>{errMsg}</p>
+ <p>
+ <span
+ role="button"
+ tabIndex={0}
+ style={{ textDecoration: "underline", cursor: "pointer" }}
+ onClick={() => {
+ setSelecting(true);
+ setErrMsg(undefined);
+ setSelectedExchange(undefined);
+ setDetails(undefined);
+ }}
+ >
+ {i18n.str`Chose different exchange provider`}
+ </span>
+ </p>
+ </div>
+ );
+ }
+
+ if (!details) {
+ return <span>Loading...</span>;
+ }
+
+ if (cancelled) {
+ return <span>Withdraw operation has been cancelled.</span>;
+ }
+
+ if (selecting) {
+ const bankSuggestion = details && details.withdrawInfo.suggestedExchange;
+ return (
+ <div>
+ {i18n.str`Please select an exchange. You can review the details before after your selection.`}
+ {bankSuggestion && (
+ <div>
+ <h2>Bank Suggestion</h2>
+ <button
+ className="pure-button button-success"
+ onClick={() => {
+ setDetails(undefined);
+ setSelectedExchange(bankSuggestion);
+ setSelecting(false);
+ }}
+ >
+ <i18n.Translate wrap="span">
+ Select <strong>{bankSuggestion}</strong>
+ </i18n.Translate>
+ </button>
+ </div>
+ )}
+ <h2>Custom Selection</h2>
+ <p>
+ <input
+ type="text"
+ onChange={e => setCustomUrl(e.target.value)}
+ value={customUrl}
+ />
+ </p>
+ <button
+ className="pure-button button-success"
+ onClick={() => {
+ setDetails(undefined);
+ setSelectedExchange(customUrl);
+ setSelecting(false);
+ }}
+ >
+ <i18n.Translate wrap="span">Select custom exchange</i18n.Translate>
+ </button>
+ </div>
+ );
+ }
+
+ const accept = async () => {
+ console.log("accepting exchange", selectedExchange);
+ const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange!);
+ console.log("accept withdrawal response", res);
+ if (res.confirmTransferUrl) {
+ document.location.href = res.confirmTransferUrl;
+ }
+ };
+
+ return (
+ <div>
+ <i18n.Translate wrap="p">
+ You are about to withdraw{" "}
+ <strong>{renderAmount(details.withdrawInfo.amount)}</strong> from your
+ bank account into your wallet.
+ </i18n.Translate>
+ <div>
+ <button
+ className="pure-button button-success"
+ disabled={!selectedExchange}
+ onClick={() => accept()}
+ >
+ {i18n.str`Accept fees and withdraw`}
+ </button>
+ <p>
+ <span
+ role="button"
+ tabIndex={0}
+ style={{ textDecoration: "underline", cursor: "pointer" }}
+ onClick={() => setSelecting(true)}
+ >
+ {i18n.str`Chose different exchange provider`}
+ </span>
+ <br />
+ <span
+ role="button"
+ tabIndex={0}
+ style={{ textDecoration: "underline", cursor: "pointer" }}
+ onClick={() => setCancelled(true)}
+ >
+ {i18n.str`Cancel withdraw operation`}
+ </span>
+ </p>
+
+ {details.reserveCreationInfo ? (
+ <WithdrawDetailView rci={details.reserveCreationInfo} />
+ ) : null}
+ </div>
+ </div>
+ );
+}
+
+async function main() {
+ try {
+ const url = new URI(document.location.href);
+ const query: any = URI.parseQuery(url.query());
+ let talerWithdrawUri = query.talerWithdrawUri;
+ if (!talerWithdrawUri) {
+ throw Error("withdraw URI required");
+ }
+
+ ReactDOM.render(
+ <NewExchangeSelection talerWithdrawUri={talerWithdrawUri} />,
+ document.getElementById("exchange-selection")!,
+ );
+ } catch (e) {
+ // TODO: provide more context information, maybe factor it out into a
+ // TODO:generic error reporting function or component.
+ document.body.innerText = i18n.str`Fatal error: "${e.message}".`;
+ console.error("got error", e);
+ }
+}
+
+document.addEventListener("DOMContentLoaded", () => {
+ main();
+});
diff --git a/src/webex/style/wallet.css b/src/webex/style/wallet.css
index dde17e890..b4bfd6f6d 100644
--- a/src/webex/style/wallet.css
+++ b/src/webex/style/wallet.css
@@ -137,6 +137,11 @@ button.linky {
cursor:pointer;
}
+.blacklink a:link, .blacklink a:visited, .blacklink a:hover, .blacklink a:active {
+ color: #000;
+}
+
+
table, th, td {
border: 1px solid black;
}
diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts
index 4f7500368..feabc7819 100644
--- a/src/webex/wxApi.ts
+++ b/src/webex/wxApi.ts
@@ -79,6 +79,8 @@ export interface UpgradeResponse {
export class WalletApiError extends Error {
constructor(message: string, public detail: any) {
super(message);
+ // restore prototype chain
+ Object.setPrototypeOf(this, new.target.prototype);
}
}
@@ -401,3 +403,24 @@ export function abortFailedPayment(contractTermsHash: string) {
export function benchmarkCrypto(repetitions: number): Promise<BenchmarkResult> {
return callBackend("benchmark-crypto", { repetitions });
}
+
+/**
+ * Get details about a withdraw operation.
+ */
+export function getWithdrawDetails(talerWithdrawUri: string, maybeSelectedExchange: string | undefined) {
+ return callBackend("get-withdraw-details", { talerWithdrawUri, maybeSelectedExchange });
+}
+
+/**
+ * Get details about a pay operation.
+ */
+export function preparePay(talerPayUri: string) {
+ return callBackend("prepare-pay", { talerPayUri });
+}
+
+/**
+ * Get details about a withdraw operation.
+ */
+export function acceptWithdrawal(talerWithdrawUri: string, selectedExchange: string) {
+ return callBackend("accept-withdrawal", { talerWithdrawUri, selectedExchange });
+} \ No newline at end of file
diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts
index 594418ebf..d31ea388d 100644
--- a/src/webex/wxBackend.ts
+++ b/src/webex/wxBackend.ts
@@ -339,6 +339,20 @@ function handleMessage(
}
return needsWallet().benchmarkCrypto(detail.repetitions);
}
+ case "get-withdraw-details": {
+ return needsWallet().getWithdrawDetails(
+ detail.talerWithdrawUri,
+ detail.maybeSelectedExchange,
+ );
+ }
+ case "accept-withdrawal": {
+ return needsWallet().acceptWithdrawal(
+ detail.talerWithdrawUri,
+ detail.selectedExchange,
+ );
+ }
+ case "prepare-pay":
+ return needsWallet().preparePay(detail.talerPayUri);
default:
// Exhaustiveness check.
// See https://www.typescriptlang.org/docs/handbook/advanced-types.html
@@ -523,190 +537,6 @@ function makeSyncWalletRedirect(
return { redirectUrl: outerUrl.href() };
}
-/**
- * Handle a HTTP response that has the "402 Payment Required" status.
- * In this callback we don't have access to the body, and must communicate via
- * shared state with the content script that will later be run later
- * in this tab.
- */
-function handleHttpPayment(
- headerList: chrome.webRequest.HttpHeader[],
- url: string,
- tabId: number,
-): any {
- if (!currentWallet) {
- console.log("can't handle payment, no wallet");
- return;
- }
-
- const headers: { [s: string]: string } = {};
- for (const kv of headerList) {
- if (kv.value) {
- headers[kv.name.toLowerCase()] = kv.value;
- }
- }
-
- const decodeIfDefined = (url?: string) =>
- url ? decodeURIComponent(url) : undefined;
-
- const fields = {
- contract_url: decodeIfDefined(headers["taler-contract-url"]),
- offer_url: decodeIfDefined(headers["taler-offer-url"]),
- refund_url: decodeIfDefined(headers["taler-refund-url"]),
- resource_url: decodeIfDefined(headers["taler-resource-url"]),
- session_id: decodeIfDefined(headers["taler-session-id"]),
- tip: decodeIfDefined(headers["taler-tip"]),
- };
-
- const talerHeaderFound =
- Object.keys(fields).filter((x: any) => (fields as any)[x]).length !== 0;
-
- if (!talerHeaderFound) {
- // looks like it's not a taler request, it might be
- // for a different payment system (or the shop is buggy)
- console.log("ignoring non-taler 402 response");
- return;
- }
-
- console.log("got pay detail", fields);
-
- // Synchronous fast path for existing payment
- if (fields.resource_url) {
- const result = currentWallet.getNextUrlFromResourceUrl(fields.resource_url);
- if (
- result &&
- (fields.session_id === undefined ||
- fields.session_id === result.lastSessionId)
- ) {
- return { redirectUrl: result.nextUrl };
- }
- }
- // Synchronous fast path for new contract
- if (fields.contract_url) {
- return makeSyncWalletRedirect("confirm-contract.html", tabId, url, {
- contractUrl: fields.contract_url,
- resourceUrl: fields.resource_url,
- sessionId: fields.session_id,
- });
- }
-
- // Synchronous fast path for tip
- if (fields.tip) {
- return makeSyncWalletRedirect("tip.html", tabId, url, {
- tip_token: fields.tip,
- });
- }
-
- // Synchronous fast path for refund
- if (fields.refund_url) {
- console.log("processing refund");
- return makeSyncWalletRedirect("refund.html", tabId, url, {
- refundUrl: fields.refund_url,
- });
- }
-
- // We need to do some asynchronous operation, we can't directly redirect
- talerPay(fields, url, tabId).then(nextUrl => {
- if (nextUrl) {
- // We use chrome.tabs.executeScript instead of chrome.tabs.update
- // because the latter is buggy when it does not execute in the same
- // (micro-?)task as the header callback.
- chrome.tabs.executeScript({
- code: `document.location.href = decodeURIComponent("${encodeURI(
- nextUrl,
- )}");`,
- runAt: "document_start",
- });
- }
- });
-
- return;
-}
-
-function handleBankRequest(
- wallet: Wallet,
- headerList: chrome.webRequest.HttpHeader[],
- url: string,
- tabId: number,
-): any {
- const headers: { [s: string]: string } = {};
- for (const kv of headerList) {
- if (kv.value) {
- headers[kv.name.toLowerCase()] = kv.value;
- }
- }
-
- const operation = headers["taler-operation"];
-
- if (!operation) {
- // Not a taler related request.
- return;
- }
-
- if (operation === "confirm-reserve") {
- const reservePub = headers["taler-reserve-pub"];
- if (reservePub !== undefined) {
- console.log(`confirming reserve ${reservePub} via 201`);
- wallet.confirmReserve({ reservePub });
- } else {
- console.warn(
- "got 'Taler-Operation: confirm-reserve' without 'Taler-Reserve-Pub'",
- );
- }
- return;
- }
-
- if (operation === "create-reserve") {
- const amount = headers["taler-amount"];
- if (!amount) {
- console.log("202 not understood (Taler-Amount missing)");
- return;
- }
- const callbackUrl = headers["taler-callback-url"];
- if (!callbackUrl) {
- console.log("202 not understood (Taler-Callback-Url missing)");
- return;
- }
- try {
- JSON.parse(amount);
- } catch (e) {
- const errUri = new URI(
- chrome.extension.getURL("/src/webex/pages/error.html"),
- );
- const p = {
- message: `Can't parse amount ("${amount}"): ${e.message}`,
- };
- const errRedirectUrl = errUri.query(p).href();
- // FIXME: use direct redirect when https://bugzilla.mozilla.org/show_bug.cgi?id=707624 is fixed
- chrome.tabs.update(tabId, { url: errRedirectUrl });
- return;
- }
- const wtTypes = headers["taler-wt-types"];
- if (!wtTypes) {
- console.log("202 not understood (Taler-Wt-Types missing)");
- return;
- }
- const params = {
- amount,
- bank_url: url,
- callback_url: new URI(callbackUrl).absoluteTo(url),
- sender_wire: headers["taler-sender-wire"],
- suggested_exchange_url: headers["taler-suggested-exchange"],
- wt_types: wtTypes,
- };
- const uri = new URI(
- chrome.extension.getURL("/src/webex/pages/confirm-create-reserve.html"),
- );
- const redirectUrl = uri.query(params).href();
- console.log("redirecting to", redirectUrl);
- // FIXME: use direct redirect when https://bugzilla.mozilla.org/show_bug.cgi?id=707624 is fixed
- chrome.tabs.update(tabId, { url: redirectUrl });
- return;
- }
-
- console.log("Ignoring unknown (X-)Taler-Operation:", operation);
-}
-
// Rate limit cache for executePayment operations, to break redirect loops
let rateLimitCache: { [n: number]: number } = {};
@@ -931,19 +761,59 @@ export async function wxMain() {
}
if (details.statusCode === 402) {
console.log(`got 402 from ${details.url}`);
- return handleHttpPayment(
- details.responseHeaders || [],
- details.url,
- details.tabId,
- );
- } else if (details.statusCode === 202) {
- return handleBankRequest(
- wallet!,
- details.responseHeaders || [],
- details.url,
- details.tabId,
- );
+ for (let header of details.responseHeaders || []) {
+ if (header.name.toLowerCase() === "taler") {
+ const talerUri = header.value || "";
+ if (!talerUri.startsWith("taler://")) {
+ console.warn(
+ "Response with HTTP 402 has Taler header, but header value is not a taler:// URI.",
+ );
+ break;
+ }
+ if (talerUri.startsWith("taler://withdraw/")) {
+ return makeSyncWalletRedirect(
+ "withdraw.html",
+ details.tabId,
+ details.url,
+ {
+ talerWithdrawUri: talerUri,
+ },
+ );
+ } else if (talerUri.startsWith("taler://pay/")) {
+ return makeSyncWalletRedirect(
+ "pay.html",
+ details.tabId,
+ details.url,
+ {
+ talerPayUri: talerUri,
+ },
+ );
+ } else if (talerUri.startsWith("taler://tip/")) {
+ return makeSyncWalletRedirect(
+ "tip.html",
+ details.tabId,
+ details.url,
+ {
+ talerTipUri: talerUri,
+ },
+ );
+ } else if (talerUri.startsWith("taler://refund/")) {
+ return makeSyncWalletRedirect(
+ "refund.html",
+ details.tabId,
+ details.url,
+ {
+ talerRefundUri: talerUri,
+ },
+ );
+ } else {
+ console.warn("Unknown action in taler:// URI, ignoring.");
+ }
+ break;
+ }
+ }
}
+ return {};
},
{ urls: ["<all_urls>"] },
["responseHeaders", "blocking"],