url-based pay/withdraw, use react hooks
This commit is contained in:
parent
1390175a9a
commit
defbf625bd
@ -104,6 +104,7 @@ const tsBaseArgs = {
|
||||
allowJs: true,
|
||||
checkJs: true,
|
||||
incremental: true,
|
||||
esModuleInterop: true,
|
||||
};
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.4.0",
|
||||
"@types/react-dom": "^16.0.0",
|
||||
"ava": "^1.4.1",
|
||||
"ava": "^2.3.0",
|
||||
"awesome-typescript-loader": "^5.2.1",
|
||||
"glob": "^7.1.1",
|
||||
"gulp": "^4.0.0",
|
||||
@ -44,10 +44,10 @@
|
||||
"uglify-js": "^3.0.27",
|
||||
"vinyl": "^2.2.0",
|
||||
"vinyl-fs": "^3.0.3",
|
||||
"webpack": "^4.29.6",
|
||||
"webpack": "^4.39.3",
|
||||
"webpack-bundle-analyzer": "^3.0.2",
|
||||
"webpack-cli": "^3.1.0",
|
||||
"webpack-merge": "^4.1.0"
|
||||
"webpack-merge": "^4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/chrome": "^0.0.88",
|
||||
|
@ -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 {
|
||||
|
50
src/http.ts
50
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) {}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
273
src/i18n/de.po
273
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:"
|
||||
|
@ -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
|
||||
#, 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
|
||||
#, 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"
|
||||
@ -370,6 +248,127 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. #-#-#-#-# - (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
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
|
273
src/i18n/fr.po
273
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,180 +66,58 @@ 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
|
||||
#, 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"
|
||||
@ -370,6 +248,127 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. #-#-#-#-# - (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
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
|
273
src/i18n/it.po
273
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,180 +66,58 @@ 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
|
||||
#, 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"
|
||||
@ -370,6 +248,127 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. #-#-#-#-# - (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
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
|
@ -92,90 +92,6 @@ strings['de'] = {
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Balance": [
|
||||
null,
|
||||
"Saldo"
|
||||
@ -280,6 +196,90 @@ strings['de'] = {
|
||||
null,
|
||||
"Saldo"
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
null,
|
||||
"Abheben bei"
|
||||
@ -408,90 +408,6 @@ strings['en-US'] = {
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Balance": [
|
||||
null,
|
||||
""
|
||||
@ -596,6 +512,90 @@ strings['en-US'] = {
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
null,
|
||||
""
|
||||
@ -724,90 +724,6 @@ strings['fr'] = {
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Balance": [
|
||||
null,
|
||||
""
|
||||
@ -912,6 +828,90 @@ strings['fr'] = {
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
null,
|
||||
""
|
||||
@ -1040,90 +1040,6 @@ strings['it'] = {
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Balance": [
|
||||
null,
|
||||
""
|
||||
@ -1228,6 +1144,90 @@ strings['it'] = {
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Your wallet (protocol version %1$s) might be outdated.%2$s The exchange has a higher, incompatible protocol version (%3$s).": [
|
||||
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).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"You are about to withdraw %1$s from your bank account into your wallet.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
null,
|
||||
""
|
||||
@ -1356,90 +1356,6 @@ strings['sv'] = {
|
||||
null,
|
||||
"Det totala priset är %1$s."
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
"Välj"
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
"Tjänsteleverantörer i plånboken:"
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"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"
|
||||
],
|
||||
"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,
|
||||
"tjänsteleverantörer plånboken"
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
"Acceptera avgifter och utbetala"
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
"Ändra tjänsteleverantörer"
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
"Välj %1$s"
|
||||
],
|
||||
"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"
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
"plånboken"
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Balance": [
|
||||
null,
|
||||
"Balans"
|
||||
@ -1544,6 +1460,90 @@ strings['sv'] = {
|
||||
null,
|
||||
"Avbryt"
|
||||
],
|
||||
"Fatal error: \"%1$s\".": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select": [
|
||||
null,
|
||||
"Välj"
|
||||
],
|
||||
"Error: URL may not be relative": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Invalid exchange URL (%1$s)": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"The exchange is trusted by the wallet.": [
|
||||
null,
|
||||
"Tjänsteleverantörer i plånboken:"
|
||||
],
|
||||
"The exchange is audited by a trusted auditor.": [
|
||||
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.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Using exchange provider %1$s. The exchange provider will charge %2$s in fees.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Waiting for a response from %1$s %2$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"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"
|
||||
],
|
||||
"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,
|
||||
"tjänsteleverantörer plånboken"
|
||||
],
|
||||
"Accept fees and withdraw": [
|
||||
null,
|
||||
"Acceptera avgifter och utbetala"
|
||||
],
|
||||
"Change Exchange Provider": [
|
||||
null,
|
||||
"Ändra tjänsteleverantörer"
|
||||
],
|
||||
"Please select an exchange. You can review the details before after your selection.": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Select %1$s": [
|
||||
null,
|
||||
"Välj %1$s"
|
||||
],
|
||||
"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"
|
||||
],
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s).": [
|
||||
null,
|
||||
"plånboken"
|
||||
],
|
||||
"Checking URL, please wait ...": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse amount: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Can't parse wire_types: %1$s": [
|
||||
null,
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
null,
|
||||
"Utbetalnings avgifter:"
|
||||
|
277
src/i18n/sv.po
277
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:"
|
||||
|
@ -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
|
||||
#, 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
|
||||
#, 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"
|
||||
@ -370,6 +248,127 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. #-#-#-#-# - (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
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
|
143
src/wallet.ts
143
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,
|
||||
@ -3514,16 +3552,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,
|
||||
|
@ -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";
|
||||
contractTerms?: ContractTerms;
|
||||
error?: string;
|
||||
export type PreparePayResult =
|
||||
| PreparePayResultError
|
||||
| PreparePayResultInsufficientBalance
|
||||
| PreparePayResultPaid
|
||||
| PreparePayResultPaymentPossible;
|
||||
|
||||
export interface PreparePayResultPaymentPossible {
|
||||
status: "payment-possible";
|
||||
proposalId?: number;
|
||||
contractTerms?: ContractTerms;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
export interface AcceptWithdrawalResponse {
|
||||
reservePub: string;
|
||||
confirmTransferUrl?: string;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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")!);
|
||||
});
|
@ -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();
|
||||
});
|
@ -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 {
|
173
src/webex/pages/pay.tsx
Normal file
173
src/webex/pages/pay.tsx
Normal file
@ -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);
|
||||
}
|
||||
});
|
@ -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>
|
||||
|
231
src/webex/pages/withdraw.tsx
Normal file
231
src/webex/pages/withdraw.tsx
Normal file
@ -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();
|
||||
});
|
@ -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;
|
||||
}
|
||||
|
@ -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 });
|
||||
}
|
@ -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"],
|
||||
|
@ -19,7 +19,8 @@
|
||||
"noImplicitAny": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"incremental": true
|
||||
"incremental": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"files": [
|
||||
"src/amounts.ts",
|
||||
@ -72,10 +73,9 @@
|
||||
"src/webex/pages/auditors.tsx",
|
||||
"src/webex/pages/benchmark.tsx",
|
||||
"src/webex/pages/common.ts",
|
||||
"src/webex/pages/confirm-contract.tsx",
|
||||
"src/webex/pages/confirm-create-reserve.tsx",
|
||||
"src/webex/pages/error.tsx",
|
||||
"src/webex/pages/logs.tsx",
|
||||
"src/webex/pages/pay.tsx",
|
||||
"src/webex/pages/payback.tsx",
|
||||
"src/webex/pages/popup.tsx",
|
||||
"src/webex/pages/redirect.js",
|
||||
@ -85,6 +85,7 @@
|
||||
"src/webex/pages/show-db.ts",
|
||||
"src/webex/pages/tip.tsx",
|
||||
"src/webex/pages/tree.tsx",
|
||||
"src/webex/pages/withdraw.tsx",
|
||||
"src/webex/renderHtml.tsx",
|
||||
"src/webex/wxApi.ts",
|
||||
"src/webex/wxBackend.ts",
|
||||
|
@ -77,8 +77,8 @@ module.exports = function (env) {
|
||||
"add-auditor": "./src/webex/pages/add-auditor.tsx",
|
||||
"auditors": "./src/webex/pages/auditors.tsx",
|
||||
"benchmark": "./src/webex/pages/benchmark.tsx",
|
||||
"confirm-contract": "./src/webex/pages/confirm-contract.tsx",
|
||||
"confirm-create-reserve": "./src/webex/pages/confirm-create-reserve.tsx",
|
||||
"pay": "./src/webex/pages/pay.tsx",
|
||||
"withdraw": "./src/webex/pages/withdraw.tsx",
|
||||
"error": "./src/webex/pages/error.tsx",
|
||||
"logs": "./src/webex/pages/logs.tsx",
|
||||
"payback": "./src/webex/pages/payback.tsx",
|
||||
|
Loading…
Reference in New Issue
Block a user