compute full fees for refresh and spending
This commit is contained in:
parent
24e021fef3
commit
008926b184
@ -26,6 +26,7 @@
|
||||
import {
|
||||
AmountJson,
|
||||
CoinRecord,
|
||||
CoinWithDenom,
|
||||
ContractTerms,
|
||||
DenominationRecord,
|
||||
PayCoinInfo,
|
||||
@ -36,10 +37,6 @@ import {
|
||||
WireFee,
|
||||
} from "../types";
|
||||
|
||||
import {
|
||||
CoinWithDenom,
|
||||
} from "../wallet";
|
||||
|
||||
import * as timer from "../timer";
|
||||
|
||||
import { startWorker } from "./startWorker";
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
CoinPaySig,
|
||||
CoinRecord,
|
||||
CoinStatus,
|
||||
CoinWithDenom,
|
||||
ContractTerms,
|
||||
DenominationRecord,
|
||||
PayCoinInfo,
|
||||
@ -41,9 +42,6 @@ import {
|
||||
import {
|
||||
canonicalJson,
|
||||
} from "../helpers";
|
||||
import {
|
||||
CoinWithDenom,
|
||||
} from "../wallet";
|
||||
|
||||
import {
|
||||
Amount,
|
||||
|
@ -27,28 +27,28 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:69
|
||||
#: src/webex/pages/confirm-contract.tsx:70
|
||||
#, c-format
|
||||
msgid "show more details\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:83
|
||||
#: src/webex/pages/confirm-contract.tsx:84
|
||||
#, c-format
|
||||
msgid "Accepted exchanges:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:88
|
||||
#: src/webex/pages/confirm-contract.tsx:89
|
||||
#, c-format
|
||||
msgid "Exchanges in the wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:154
|
||||
#: src/webex/pages/confirm-contract.tsx:156
|
||||
#, 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:156
|
||||
#: src/webex/pages/confirm-contract.tsx:158
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You do not have any funds from an exchange that is accepted by this "
|
||||
@ -56,67 +56,77 @@ msgid ""
|
||||
"wallet."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:213
|
||||
#: src/webex/pages/confirm-contract.tsx:214
|
||||
#, c-format
|
||||
msgid "The merchant%1$s offers you to purchase:\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:232
|
||||
#, fuzzy, c-format
|
||||
msgid "Confirm payment"
|
||||
msgstr "Bezahlung bestätigen"
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:179
|
||||
#, fuzzy, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
msgstr "Abheben bei %1$s"
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:214
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:180
|
||||
#, c-format
|
||||
msgid "Rounding loss:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:215
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:181
|
||||
#, c-format
|
||||
msgid "Earliest expiration (for deposit): %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:220
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:186
|
||||
#, c-format
|
||||
msgid "# Coins"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:221
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:187
|
||||
#, c-format
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:222
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:188
|
||||
#, fuzzy, c-format
|
||||
msgid "Withdraw Fee"
|
||||
msgstr "Abheben bei %1$s"
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:223
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:189
|
||||
#, c-format
|
||||
msgid "Refresh Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:224
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:190
|
||||
#, c-format
|
||||
msgid "Deposit Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:278
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:244
|
||||
#, c-format
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:294
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:260
|
||||
#, c-format
|
||||
msgid "Error: URL may not be relative"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:362
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:328
|
||||
#, c-format
|
||||
msgid "The exchange is trusted by the wallet.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:368
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:334
|
||||
#, c-format
|
||||
msgid "The exchange is audited by a trusted auditor.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:374
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:340
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: The exchange is neither directly trusted nor audited by a trusted "
|
||||
@ -124,7 +134,7 @@ msgid ""
|
||||
"If you withdraw from this exchange, it will be trusted in the future.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:383
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:349
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Using exchange provider%1$s.\n"
|
||||
@ -132,63 +142,58 @@ msgid ""
|
||||
" %2$s in fees.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:397
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:363
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Waiting for a response from\n"
|
||||
" %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:408
|
||||
#, c-format
|
||||
msgid "A problem occured, see below. %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:414
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:380
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Information about fees will be available when an exchange provider is "
|
||||
"selected."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:457
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:423
|
||||
#, c-format
|
||||
msgid "Accept fees and withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:462
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:428
|
||||
#, c-format
|
||||
msgid "Change Exchange Provider"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:519
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:485
|
||||
#, 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:607
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:570
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s)."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:616
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:579
|
||||
#, c-format
|
||||
msgid "Checking URL, please wait ..."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:630
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:593
|
||||
#, c-format
|
||||
msgid "Can't parse amount: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:637
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:600
|
||||
#, c-format
|
||||
msgid "Can't parse wire_types: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#. TODO:generic error reporting function or component.
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:663
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:626
|
||||
#, c-format
|
||||
msgid "Fatal error: \"%1$s\"."
|
||||
msgstr ""
|
||||
@ -311,19 +316,6 @@ msgstr "Bezahlung bestätigen"
|
||||
msgid "Cancel"
|
||||
msgstr "Saldo"
|
||||
|
||||
#: src/webex/renderHtml.tsx:51
|
||||
#, fuzzy, c-format
|
||||
msgid "The merchant%1$swants to enter a contract over%2$s with you.\n"
|
||||
msgstr ""
|
||||
"%1$s\n"
|
||||
" möchte einen Vertrag über %2$s\n"
|
||||
" mit Ihnen abschließen."
|
||||
|
||||
#: src/webex/renderHtml.tsx:56
|
||||
#, fuzzy, c-format
|
||||
msgid "You are about to purchase:"
|
||||
msgstr "Sie sind dabei, Folgendes zu kaufen:"
|
||||
|
||||
#: src/wire.ts:38
|
||||
#, c-format
|
||||
msgid "Invalid Wire"
|
||||
@ -344,6 +336,17 @@ msgstr ""
|
||||
msgid "Unknown Wire Detail"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "The merchant%1$swants to enter a contract over%2$s with you.\n"
|
||||
#~ msgstr ""
|
||||
#~ "%1$s\n"
|
||||
#~ " möchte einen Vertrag über %2$s\n"
|
||||
#~ " mit Ihnen abschließen."
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "You are about to purchase:"
|
||||
#~ msgstr "Sie sind dabei, Folgendes zu kaufen:"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Withdrawal fees: %1$s"
|
||||
#~ msgstr "Abheben bei %1$s"
|
||||
|
@ -27,28 +27,28 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:69
|
||||
#: src/webex/pages/confirm-contract.tsx:70
|
||||
#, c-format
|
||||
msgid "show more details\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:83
|
||||
#: src/webex/pages/confirm-contract.tsx:84
|
||||
#, c-format
|
||||
msgid "Accepted exchanges:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:88
|
||||
#: src/webex/pages/confirm-contract.tsx:89
|
||||
#, c-format
|
||||
msgid "Exchanges in the wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:154
|
||||
#: src/webex/pages/confirm-contract.tsx:156
|
||||
#, 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:156
|
||||
#: src/webex/pages/confirm-contract.tsx:158
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You do not have any funds from an exchange that is accepted by this "
|
||||
@ -56,67 +56,77 @@ msgid ""
|
||||
"wallet."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:213
|
||||
#: src/webex/pages/confirm-contract.tsx:214
|
||||
#, c-format
|
||||
msgid "The merchant%1$s offers you to purchase:\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:232
|
||||
#, c-format
|
||||
msgid "Confirm payment"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:179
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:214
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:180
|
||||
#, c-format
|
||||
msgid "Rounding loss:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:215
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:181
|
||||
#, c-format
|
||||
msgid "Earliest expiration (for deposit): %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:220
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:186
|
||||
#, c-format
|
||||
msgid "# Coins"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:221
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:187
|
||||
#, c-format
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:222
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:188
|
||||
#, c-format
|
||||
msgid "Withdraw Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:223
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:189
|
||||
#, c-format
|
||||
msgid "Refresh Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:224
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:190
|
||||
#, c-format
|
||||
msgid "Deposit Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:278
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:244
|
||||
#, c-format
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:294
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:260
|
||||
#, c-format
|
||||
msgid "Error: URL may not be relative"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:362
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:328
|
||||
#, c-format
|
||||
msgid "The exchange is trusted by the wallet.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:368
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:334
|
||||
#, c-format
|
||||
msgid "The exchange is audited by a trusted auditor.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:374
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:340
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: The exchange is neither directly trusted nor audited by a trusted "
|
||||
@ -124,7 +134,7 @@ msgid ""
|
||||
"If you withdraw from this exchange, it will be trusted in the future.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:383
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:349
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Using exchange provider%1$s.\n"
|
||||
@ -132,63 +142,58 @@ msgid ""
|
||||
" %2$s in fees.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:397
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:363
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Waiting for a response from\n"
|
||||
" %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:408
|
||||
#, c-format
|
||||
msgid "A problem occured, see below. %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:414
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:380
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Information about fees will be available when an exchange provider is "
|
||||
"selected."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:457
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:423
|
||||
#, c-format
|
||||
msgid "Accept fees and withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:462
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:428
|
||||
#, c-format
|
||||
msgid "Change Exchange Provider"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:519
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:485
|
||||
#, 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:607
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:570
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s)."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:616
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:579
|
||||
#, c-format
|
||||
msgid "Checking URL, please wait ..."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:630
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:593
|
||||
#, c-format
|
||||
msgid "Can't parse amount: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:637
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:600
|
||||
#, c-format
|
||||
msgid "Can't parse wire_types: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#. TODO:generic error reporting function or component.
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:663
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:626
|
||||
#, c-format
|
||||
msgid "Fatal error: \"%1$s\"."
|
||||
msgstr ""
|
||||
@ -311,16 +316,6 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:51
|
||||
#, c-format
|
||||
msgid "The merchant%1$swants to enter a contract over%2$s with you.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:56
|
||||
#, c-format
|
||||
msgid "You are about to purchase:"
|
||||
msgstr ""
|
||||
|
||||
#: src/wire.ts:38
|
||||
#, c-format
|
||||
msgid "Invalid Wire"
|
||||
|
@ -27,28 +27,28 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:69
|
||||
#: src/webex/pages/confirm-contract.tsx:70
|
||||
#, c-format
|
||||
msgid "show more details\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:83
|
||||
#: src/webex/pages/confirm-contract.tsx:84
|
||||
#, c-format
|
||||
msgid "Accepted exchanges:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:88
|
||||
#: src/webex/pages/confirm-contract.tsx:89
|
||||
#, c-format
|
||||
msgid "Exchanges in the wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:154
|
||||
#: src/webex/pages/confirm-contract.tsx:156
|
||||
#, 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:156
|
||||
#: src/webex/pages/confirm-contract.tsx:158
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You do not have any funds from an exchange that is accepted by this "
|
||||
@ -56,67 +56,77 @@ msgid ""
|
||||
"wallet."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:213
|
||||
#: src/webex/pages/confirm-contract.tsx:214
|
||||
#, c-format
|
||||
msgid "The merchant%1$s offers you to purchase:\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:232
|
||||
#, c-format
|
||||
msgid "Confirm payment"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:179
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:214
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:180
|
||||
#, c-format
|
||||
msgid "Rounding loss:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:215
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:181
|
||||
#, c-format
|
||||
msgid "Earliest expiration (for deposit): %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:220
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:186
|
||||
#, c-format
|
||||
msgid "# Coins"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:221
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:187
|
||||
#, c-format
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:222
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:188
|
||||
#, c-format
|
||||
msgid "Withdraw Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:223
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:189
|
||||
#, c-format
|
||||
msgid "Refresh Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:224
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:190
|
||||
#, c-format
|
||||
msgid "Deposit Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:278
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:244
|
||||
#, c-format
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:294
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:260
|
||||
#, c-format
|
||||
msgid "Error: URL may not be relative"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:362
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:328
|
||||
#, c-format
|
||||
msgid "The exchange is trusted by the wallet.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:368
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:334
|
||||
#, c-format
|
||||
msgid "The exchange is audited by a trusted auditor.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:374
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:340
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: The exchange is neither directly trusted nor audited by a trusted "
|
||||
@ -124,7 +134,7 @@ msgid ""
|
||||
"If you withdraw from this exchange, it will be trusted in the future.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:383
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:349
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Using exchange provider%1$s.\n"
|
||||
@ -132,63 +142,58 @@ msgid ""
|
||||
" %2$s in fees.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:397
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:363
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Waiting for a response from\n"
|
||||
" %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:408
|
||||
#, c-format
|
||||
msgid "A problem occured, see below. %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:414
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:380
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Information about fees will be available when an exchange provider is "
|
||||
"selected."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:457
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:423
|
||||
#, c-format
|
||||
msgid "Accept fees and withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:462
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:428
|
||||
#, c-format
|
||||
msgid "Change Exchange Provider"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:519
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:485
|
||||
#, 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:607
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:570
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s)."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:616
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:579
|
||||
#, c-format
|
||||
msgid "Checking URL, please wait ..."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:630
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:593
|
||||
#, c-format
|
||||
msgid "Can't parse amount: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:637
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:600
|
||||
#, c-format
|
||||
msgid "Can't parse wire_types: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#. TODO:generic error reporting function or component.
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:663
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:626
|
||||
#, c-format
|
||||
msgid "Fatal error: \"%1$s\"."
|
||||
msgstr ""
|
||||
@ -311,16 +316,6 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:51
|
||||
#, c-format
|
||||
msgid "The merchant%1$swants to enter a contract over%2$s with you.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:56
|
||||
#, c-format
|
||||
msgid "You are about to purchase:"
|
||||
msgstr ""
|
||||
|
||||
#: src/wire.ts:38
|
||||
#, c-format
|
||||
msgid "Invalid Wire"
|
||||
|
@ -27,28 +27,28 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:69
|
||||
#: src/webex/pages/confirm-contract.tsx:70
|
||||
#, c-format
|
||||
msgid "show more details\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:83
|
||||
#: src/webex/pages/confirm-contract.tsx:84
|
||||
#, c-format
|
||||
msgid "Accepted exchanges:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:88
|
||||
#: src/webex/pages/confirm-contract.tsx:89
|
||||
#, c-format
|
||||
msgid "Exchanges in the wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:154
|
||||
#: src/webex/pages/confirm-contract.tsx:156
|
||||
#, 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:156
|
||||
#: src/webex/pages/confirm-contract.tsx:158
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You do not have any funds from an exchange that is accepted by this "
|
||||
@ -56,67 +56,77 @@ msgid ""
|
||||
"wallet."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:213
|
||||
#: src/webex/pages/confirm-contract.tsx:214
|
||||
#, c-format
|
||||
msgid "The merchant%1$s offers you to purchase:\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:232
|
||||
#, c-format
|
||||
msgid "Confirm payment"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:179
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:214
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:180
|
||||
#, c-format
|
||||
msgid "Rounding loss:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:215
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:181
|
||||
#, c-format
|
||||
msgid "Earliest expiration (for deposit): %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:220
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:186
|
||||
#, c-format
|
||||
msgid "# Coins"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:221
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:187
|
||||
#, c-format
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:222
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:188
|
||||
#, c-format
|
||||
msgid "Withdraw Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:223
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:189
|
||||
#, c-format
|
||||
msgid "Refresh Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:224
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:190
|
||||
#, c-format
|
||||
msgid "Deposit Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:278
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:244
|
||||
#, c-format
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:294
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:260
|
||||
#, c-format
|
||||
msgid "Error: URL may not be relative"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:362
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:328
|
||||
#, c-format
|
||||
msgid "The exchange is trusted by the wallet.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:368
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:334
|
||||
#, c-format
|
||||
msgid "The exchange is audited by a trusted auditor.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:374
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:340
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: The exchange is neither directly trusted nor audited by a trusted "
|
||||
@ -124,7 +134,7 @@ msgid ""
|
||||
"If you withdraw from this exchange, it will be trusted in the future.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:383
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:349
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Using exchange provider%1$s.\n"
|
||||
@ -132,63 +142,58 @@ msgid ""
|
||||
" %2$s in fees.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:397
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:363
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Waiting for a response from\n"
|
||||
" %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:408
|
||||
#, c-format
|
||||
msgid "A problem occured, see below. %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:414
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:380
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Information about fees will be available when an exchange provider is "
|
||||
"selected."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:457
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:423
|
||||
#, c-format
|
||||
msgid "Accept fees and withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:462
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:428
|
||||
#, c-format
|
||||
msgid "Change Exchange Provider"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:519
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:485
|
||||
#, 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:607
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:570
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s)."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:616
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:579
|
||||
#, c-format
|
||||
msgid "Checking URL, please wait ..."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:630
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:593
|
||||
#, c-format
|
||||
msgid "Can't parse amount: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:637
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:600
|
||||
#, c-format
|
||||
msgid "Can't parse wire_types: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#. TODO:generic error reporting function or component.
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:663
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:626
|
||||
#, c-format
|
||||
msgid "Fatal error: \"%1$s\"."
|
||||
msgstr ""
|
||||
@ -311,16 +316,6 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:51
|
||||
#, c-format
|
||||
msgid "The merchant%1$swants to enter a contract over%2$s with you.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:56
|
||||
#, c-format
|
||||
msgid "You are about to purchase:"
|
||||
msgstr ""
|
||||
|
||||
#: src/wire.ts:38
|
||||
#, c-format
|
||||
msgid "Invalid Wire"
|
||||
|
@ -39,6 +39,12 @@ strings['de'] = {
|
||||
"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.": [
|
||||
""
|
||||
],
|
||||
"The merchant%1$s offers you to purchase:\n": [
|
||||
""
|
||||
],
|
||||
"Confirm payment": [
|
||||
"Bezahlung bestätigen"
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
"Abheben bei %1$s"
|
||||
],
|
||||
@ -84,9 +90,6 @@ strings['de'] = {
|
||||
"Waiting for a response from\n %1$s": [
|
||||
""
|
||||
],
|
||||
"A problem occured, see below. %1$s": [
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
""
|
||||
],
|
||||
@ -180,12 +183,6 @@ strings['de'] = {
|
||||
"Cancel": [
|
||||
"Saldo"
|
||||
],
|
||||
"The merchant%1$swants to enter a contract over%2$s with you.\n": [
|
||||
"%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
|
||||
],
|
||||
"You are about to purchase:": [
|
||||
"Sie sind dabei, Folgendes zu kaufen:"
|
||||
],
|
||||
"Invalid Wire": [
|
||||
""
|
||||
],
|
||||
@ -225,6 +222,12 @@ strings['en-US'] = {
|
||||
"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.": [
|
||||
""
|
||||
],
|
||||
"The merchant%1$s offers you to purchase:\n": [
|
||||
""
|
||||
],
|
||||
"Confirm payment": [
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
""
|
||||
],
|
||||
@ -270,9 +273,6 @@ strings['en-US'] = {
|
||||
"Waiting for a response from\n %1$s": [
|
||||
""
|
||||
],
|
||||
"A problem occured, see below. %1$s": [
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
""
|
||||
],
|
||||
@ -366,12 +366,6 @@ strings['en-US'] = {
|
||||
"Cancel": [
|
||||
""
|
||||
],
|
||||
"The merchant%1$swants to enter a contract over%2$s with you.\n": [
|
||||
""
|
||||
],
|
||||
"You are about to purchase:": [
|
||||
""
|
||||
],
|
||||
"Invalid Wire": [
|
||||
""
|
||||
],
|
||||
@ -411,6 +405,12 @@ strings['fr'] = {
|
||||
"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.": [
|
||||
""
|
||||
],
|
||||
"The merchant%1$s offers you to purchase:\n": [
|
||||
""
|
||||
],
|
||||
"Confirm payment": [
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
""
|
||||
],
|
||||
@ -456,9 +456,6 @@ strings['fr'] = {
|
||||
"Waiting for a response from\n %1$s": [
|
||||
""
|
||||
],
|
||||
"A problem occured, see below. %1$s": [
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
""
|
||||
],
|
||||
@ -552,12 +549,6 @@ strings['fr'] = {
|
||||
"Cancel": [
|
||||
""
|
||||
],
|
||||
"The merchant%1$swants to enter a contract over%2$s with you.\n": [
|
||||
""
|
||||
],
|
||||
"You are about to purchase:": [
|
||||
""
|
||||
],
|
||||
"Invalid Wire": [
|
||||
""
|
||||
],
|
||||
@ -597,6 +588,12 @@ strings['it'] = {
|
||||
"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.": [
|
||||
""
|
||||
],
|
||||
"The merchant%1$s offers you to purchase:\n": [
|
||||
""
|
||||
],
|
||||
"Confirm payment": [
|
||||
""
|
||||
],
|
||||
"Withdrawal fees:": [
|
||||
""
|
||||
],
|
||||
@ -642,9 +639,6 @@ strings['it'] = {
|
||||
"Waiting for a response from\n %1$s": [
|
||||
""
|
||||
],
|
||||
"A problem occured, see below. %1$s": [
|
||||
""
|
||||
],
|
||||
"Information about fees will be available when an exchange provider is selected.": [
|
||||
""
|
||||
],
|
||||
@ -738,12 +732,6 @@ strings['it'] = {
|
||||
"Cancel": [
|
||||
""
|
||||
],
|
||||
"The merchant%1$swants to enter a contract over%2$s with you.\n": [
|
||||
""
|
||||
],
|
||||
"You are about to purchase:": [
|
||||
""
|
||||
],
|
||||
"Invalid Wire": [
|
||||
""
|
||||
],
|
||||
|
@ -27,28 +27,28 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:69
|
||||
#: src/webex/pages/confirm-contract.tsx:70
|
||||
#, c-format
|
||||
msgid "show more details\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:83
|
||||
#: src/webex/pages/confirm-contract.tsx:84
|
||||
#, c-format
|
||||
msgid "Accepted exchanges:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:88
|
||||
#: src/webex/pages/confirm-contract.tsx:89
|
||||
#, c-format
|
||||
msgid "Exchanges in the wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:154
|
||||
#: src/webex/pages/confirm-contract.tsx:156
|
||||
#, 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:156
|
||||
#: src/webex/pages/confirm-contract.tsx:158
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You do not have any funds from an exchange that is accepted by this "
|
||||
@ -56,67 +56,77 @@ msgid ""
|
||||
"wallet."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:213
|
||||
#: src/webex/pages/confirm-contract.tsx:214
|
||||
#, c-format
|
||||
msgid "The merchant%1$s offers you to purchase:\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-contract.tsx:232
|
||||
#, c-format
|
||||
msgid "Confirm payment"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:179
|
||||
#, c-format
|
||||
msgid "Withdrawal fees:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:214
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:180
|
||||
#, c-format
|
||||
msgid "Rounding loss:"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:215
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:181
|
||||
#, c-format
|
||||
msgid "Earliest expiration (for deposit): %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:220
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:186
|
||||
#, c-format
|
||||
msgid "# Coins"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:221
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:187
|
||||
#, c-format
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:222
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:188
|
||||
#, c-format
|
||||
msgid "Withdraw Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:223
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:189
|
||||
#, c-format
|
||||
msgid "Refresh Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:224
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:190
|
||||
#, c-format
|
||||
msgid "Deposit Fee"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:278
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:244
|
||||
#, c-format
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:294
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:260
|
||||
#, c-format
|
||||
msgid "Error: URL may not be relative"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:362
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:328
|
||||
#, c-format
|
||||
msgid "The exchange is trusted by the wallet.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:368
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:334
|
||||
#, c-format
|
||||
msgid "The exchange is audited by a trusted auditor.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:374
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:340
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Warning: The exchange is neither directly trusted nor audited by a trusted "
|
||||
@ -124,7 +134,7 @@ msgid ""
|
||||
"If you withdraw from this exchange, it will be trusted in the future.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:383
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:349
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Using exchange provider%1$s.\n"
|
||||
@ -132,63 +142,58 @@ msgid ""
|
||||
" %2$s in fees.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:397
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:363
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Waiting for a response from\n"
|
||||
" %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:408
|
||||
#, c-format
|
||||
msgid "A problem occured, see below. %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:414
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:380
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Information about fees will be available when an exchange provider is "
|
||||
"selected."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:457
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:423
|
||||
#, c-format
|
||||
msgid "Accept fees and withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:462
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:428
|
||||
#, c-format
|
||||
msgid "Change Exchange Provider"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:519
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:485
|
||||
#, 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:607
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:570
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Oops, something went wrong. The wallet responded with error status (%1$s)."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:616
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:579
|
||||
#, c-format
|
||||
msgid "Checking URL, please wait ..."
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:630
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:593
|
||||
#, c-format
|
||||
msgid "Can't parse amount: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:637
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:600
|
||||
#, c-format
|
||||
msgid "Can't parse wire_types: %1$s"
|
||||
msgstr ""
|
||||
|
||||
#. TODO:generic error reporting function or component.
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:663
|
||||
#: src/webex/pages/confirm-create-reserve.tsx:626
|
||||
#, c-format
|
||||
msgid "Fatal error: \"%1$s\"."
|
||||
msgstr ""
|
||||
@ -311,16 +316,6 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:51
|
||||
#, c-format
|
||||
msgid "The merchant%1$swants to enter a contract over%2$s with you.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/webex/renderHtml.tsx:56
|
||||
#, c-format
|
||||
msgid "You are about to purchase:"
|
||||
msgstr ""
|
||||
|
||||
#: src/wire.ts:38
|
||||
#, c-format
|
||||
msgid "Invalid Wire"
|
||||
|
36
src/types.ts
36
src/types.ts
@ -822,6 +822,10 @@ export enum CoinStatus {
|
||||
* Coin fully paid back.
|
||||
*/
|
||||
PaybackDone,
|
||||
/**
|
||||
* Coin was dirty but can't be refreshed.
|
||||
*/
|
||||
Useless,
|
||||
}
|
||||
|
||||
|
||||
@ -1467,7 +1471,10 @@ export function mkAmount(value: number, fraction: number, currency: string): Amo
|
||||
/**
|
||||
* Possible results for checkPay.
|
||||
*/
|
||||
export type CheckPayResult = "paid" | "payment-possible" | "insufficient-balance";
|
||||
export interface CheckPayResult {
|
||||
status: "paid" | "payment-possible" | "insufficient-balance";
|
||||
coinSelection?: CoinSelectionResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible results for confirmPay.
|
||||
@ -1695,3 +1702,30 @@ export interface PurchaseRecord {
|
||||
refundsPending: { [refundSig: string]: RefundPermission };
|
||||
refundsDone: { [refundSig: string]: RefundPermission };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Result of selecting coins, contains the exchange, and selected
|
||||
* coins with their denomination.
|
||||
*/
|
||||
export interface CoinSelectionResult {
|
||||
exchangeUrl: string;
|
||||
cds: CoinWithDenom[];
|
||||
totalFees: AmountJson;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Named tuple of coin and denomination.
|
||||
*/
|
||||
export interface CoinWithDenom {
|
||||
/**
|
||||
* A coin. Must have the same denomination public key as the associated
|
||||
* denomination.
|
||||
*/
|
||||
coin: CoinRecord;
|
||||
/**
|
||||
* An associated denomination.
|
||||
*/
|
||||
denom: DenominationRecord;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ function a(x: string): types.AmountJson {
|
||||
}
|
||||
|
||||
|
||||
function fakeCwd(current: string, value: string, feeDeposit: string): wallet.CoinWithDenom {
|
||||
function fakeCwd(current: string, value: string, feeDeposit: string): types.CoinWithDenom {
|
||||
return {
|
||||
coin: {
|
||||
blindingKey: "(mock)",
|
||||
@ -64,89 +64,89 @@ function fakeCwd(current: string, value: string, feeDeposit: string): wallet.Coi
|
||||
|
||||
|
||||
test("coin selection 1", (t) => {
|
||||
const cds: wallet.CoinWithDenom[] = [
|
||||
const cds: types.CoinWithDenom[] = [
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.1"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.0"),
|
||||
];
|
||||
|
||||
const res = wallet.selectPayCoins(cds, a("EUR:2.0"), a("EUR:0.1"));
|
||||
const res = wallet.selectPayCoins([], cds, a("EUR:2.0"), a("EUR:0.1"));
|
||||
if (!res) {
|
||||
t.fail();
|
||||
return;
|
||||
}
|
||||
t.true(res.length === 2);
|
||||
t.true(res.cds.length === 2);
|
||||
t.pass();
|
||||
});
|
||||
|
||||
|
||||
test("coin selection 2", (t) => {
|
||||
const cds: wallet.CoinWithDenom[] = [
|
||||
const cds: types.CoinWithDenom[] = [
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.0"),
|
||||
// Merchant covers the fee, this one shouldn't be used
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.0"),
|
||||
];
|
||||
const res = wallet.selectPayCoins(cds, a("EUR:2.0"), a("EUR:0.5"));
|
||||
const res = wallet.selectPayCoins([], cds, a("EUR:2.0"), a("EUR:0.5"));
|
||||
if (!res) {
|
||||
t.fail();
|
||||
return;
|
||||
}
|
||||
t.true(res.length === 2);
|
||||
t.true(res.cds.length === 2);
|
||||
t.pass();
|
||||
});
|
||||
|
||||
|
||||
test("coin selection 3", (t) => {
|
||||
const cds: wallet.CoinWithDenom[] = [
|
||||
const cds: types.CoinWithDenom[] = [
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
// this coin should be selected instead of previous one with fee
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.0"),
|
||||
];
|
||||
const res = wallet.selectPayCoins(cds, a("EUR:2.0"), a("EUR:0.5"));
|
||||
const res = wallet.selectPayCoins([], cds, a("EUR:2.0"), a("EUR:0.5"));
|
||||
if (!res) {
|
||||
t.fail();
|
||||
return;
|
||||
}
|
||||
t.true(res.length === 2);
|
||||
t.true(res.cds.length === 2);
|
||||
t.pass();
|
||||
});
|
||||
|
||||
|
||||
test("coin selection 4", (t) => {
|
||||
const cds: wallet.CoinWithDenom[] = [
|
||||
const cds: types.CoinWithDenom[] = [
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
];
|
||||
const res = wallet.selectPayCoins(cds, a("EUR:2.0"), a("EUR:0.2"));
|
||||
const res = wallet.selectPayCoins([], cds, a("EUR:2.0"), a("EUR:0.2"));
|
||||
if (!res) {
|
||||
t.fail();
|
||||
return;
|
||||
}
|
||||
t.true(res.length === 3);
|
||||
t.true(res.cds.length === 3);
|
||||
t.pass();
|
||||
});
|
||||
|
||||
|
||||
test("coin selection 5", (t) => {
|
||||
const cds: wallet.CoinWithDenom[] = [
|
||||
const cds: types.CoinWithDenom[] = [
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
];
|
||||
const res = wallet.selectPayCoins(cds, a("EUR:4.0"), a("EUR:0.2"));
|
||||
const res = wallet.selectPayCoins([], cds, a("EUR:4.0"), a("EUR:0.2"));
|
||||
t.true(!res);
|
||||
t.pass();
|
||||
});
|
||||
|
||||
|
||||
test("coin selection 6", (t) => {
|
||||
const cds: wallet.CoinWithDenom[] = [
|
||||
const cds: types.CoinWithDenom[] = [
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
fakeCwd("EUR:1.0", "EUR:1.0", "EUR:0.5"),
|
||||
];
|
||||
const res = wallet.selectPayCoins(cds, a("EUR:2.0"), a("EUR:0.2"));
|
||||
const res = wallet.selectPayCoins([], cds, a("EUR:2.0"), a("EUR:0.2"));
|
||||
t.true(!res);
|
||||
t.pass();
|
||||
});
|
||||
|
186
src/wallet.ts
186
src/wallet.ts
@ -51,7 +51,9 @@ import {
|
||||
CheckPayResult,
|
||||
CoinPaySig,
|
||||
CoinRecord,
|
||||
CoinSelectionResult,
|
||||
CoinStatus,
|
||||
CoinWithDenom,
|
||||
ConfirmPayResult,
|
||||
ConfirmReserveRequest,
|
||||
ContractTerms,
|
||||
@ -72,8 +74,10 @@ import {
|
||||
PaybackConfirmation,
|
||||
PreCoinRecord,
|
||||
ProposalRecord,
|
||||
PurchaseRecord,
|
||||
QueryPaymentResult,
|
||||
RefreshSessionRecord,
|
||||
RefundPermission,
|
||||
ReserveCreationInfo,
|
||||
ReserveRecord,
|
||||
ReturnCoinsRequest,
|
||||
@ -82,27 +86,10 @@ import {
|
||||
WalletBalanceEntry,
|
||||
WireFee,
|
||||
WireInfo,
|
||||
RefundPermission,
|
||||
PurchaseRecord,
|
||||
} from "./types";
|
||||
import URI = require("urijs");
|
||||
|
||||
|
||||
/**
|
||||
* Named tuple of coin and denomination.
|
||||
*/
|
||||
export interface CoinWithDenom {
|
||||
/**
|
||||
* A coin. Must have the same denomination public key as the associated
|
||||
* denomination.
|
||||
*/
|
||||
coin: CoinRecord;
|
||||
/**
|
||||
* An associated denomination.
|
||||
*/
|
||||
denom: DenominationRecord;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Element of the payback list that the
|
||||
@ -370,30 +357,62 @@ function isWithdrawableDenom(d: DenominationRecord) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function strcmp(s1: string, s2: string): number {
|
||||
if (s1 < s2) {
|
||||
return -1;
|
||||
}
|
||||
if (s1 > s2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
interface SelectPayCoinsResult {
|
||||
cds: CoinWithDenom[];
|
||||
totalFees: AmountJson;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Result of selecting coins, contains the exchange, and selected
|
||||
* coins with their denomination.
|
||||
* Get the amount that we lose when refreshing a coin of the given denomination
|
||||
* with a certain amount left.
|
||||
*
|
||||
* If the amount left is zero, then the refresh cost
|
||||
* is also considered to be zero. If a refresh isn't possible (e.g. due to lack of
|
||||
* the right denominations), then the cost is the full amount left.
|
||||
*
|
||||
* Considers refresh fees, withdrawal fees after refresh and amounts too small
|
||||
* to refresh.
|
||||
*/
|
||||
export type CoinSelectionResult = {exchangeUrl: string, cds: CoinWithDenom[]}|undefined;
|
||||
export function getTotalRefreshCost(denoms: DenominationRecord[], refreshedDenom: DenominationRecord, amountLeft: AmountJson): AmountJson {
|
||||
const withdrawAmount = Amounts.sub(amountLeft, refreshedDenom.feeRefresh).amount;
|
||||
const withdrawDenoms = getWithdrawDenomList(withdrawAmount, denoms);
|
||||
const resultingAmount = Amounts.add(Amounts.getZero(withdrawAmount.currency), ...withdrawDenoms.map((d) => d.value)).amount;
|
||||
const totalCost = Amounts.sub(amountLeft, resultingAmount).amount;
|
||||
console.log("total refresh cost for", amountToPretty(amountLeft), "is", amountToPretty(totalCost));
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select coins for a payment under the merchant's constraints.
|
||||
*
|
||||
* @param denoms all available denoms, used to compute refresh fees
|
||||
*/
|
||||
export function selectPayCoins(cds: CoinWithDenom[], paymentAmount: AmountJson,
|
||||
depositFeeLimit: AmountJson): CoinWithDenom[]|undefined {
|
||||
export function selectPayCoins(denoms: DenominationRecord[], cds: CoinWithDenom[], paymentAmount: AmountJson,
|
||||
depositFeeLimit: AmountJson): SelectPayCoinsResult|undefined {
|
||||
if (cds.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
// Sort by ascending deposit fee
|
||||
cds.sort((o1, o2) => Amounts.cmp(o1.denom.feeDeposit,
|
||||
o2.denom.feeDeposit));
|
||||
// Sort by ascending deposit fee and denomPub if deposit fee is the same
|
||||
// (to guarantee deterministic results)
|
||||
cds.sort((o1, o2) => Amounts.cmp(o1.denom.feeDeposit, o2.denom.feeDeposit) || strcmp(o1.denom.denomPub, o2.denom.denomPub));
|
||||
const currency = cds[0].denom.value.currency;
|
||||
const cdsResult: CoinWithDenom[] = [];
|
||||
let accFee: AmountJson = Amounts.getZero(currency);
|
||||
let accDepositFee: AmountJson = Amounts.getZero(currency);
|
||||
let accAmount: AmountJson = Amounts.getZero(currency);
|
||||
let isBelowFee = false;
|
||||
let coversAmount = false;
|
||||
let coversAmountWithFee = false;
|
||||
for (const {coin, denom} of cds) {
|
||||
if (coin.suspended) {
|
||||
continue;
|
||||
@ -405,18 +424,30 @@ export function selectPayCoins(cds: CoinWithDenom[], paymentAmount: AmountJson,
|
||||
continue;
|
||||
}
|
||||
cdsResult.push({coin, denom});
|
||||
accFee = Amounts.add(denom.feeDeposit, accFee).amount;
|
||||
accDepositFee = Amounts.add(denom.feeDeposit, accDepositFee).amount;
|
||||
let leftAmount = Amounts.sub(coin.currentAmount, Amounts.sub(paymentAmount, accAmount).amount).amount;
|
||||
accAmount = Amounts.add(coin.currentAmount, accAmount).amount;
|
||||
coversAmount = Amounts.cmp(accAmount, paymentAmount) >= 0;
|
||||
coversAmountWithFee = Amounts.cmp(accAmount,
|
||||
const coversAmount = Amounts.cmp(accAmount, paymentAmount) >= 0;
|
||||
const coversAmountWithFee = Amounts.cmp(accAmount,
|
||||
Amounts.add(paymentAmount,
|
||||
denom.feeDeposit).amount) >= 0;
|
||||
isBelowFee = Amounts.cmp(accFee, depositFeeLimit) <= 0;
|
||||
const isBelowFee = Amounts.cmp(accDepositFee, depositFeeLimit) <= 0;
|
||||
|
||||
console.log("coin selection", { coversAmount, isBelowFee, accFee, accAmount, paymentAmount });
|
||||
console.log("coin selection", { coversAmount, isBelowFee, accDepositFee, accAmount, paymentAmount });
|
||||
|
||||
if ((coversAmount && isBelowFee) || coversAmountWithFee) {
|
||||
return cdsResult;
|
||||
let depositFeeToCover = Amounts.sub(accDepositFee, depositFeeLimit).amount;
|
||||
leftAmount = Amounts.sub(leftAmount, depositFeeToCover).amount;
|
||||
console.log("deposit fee to cover", amountToPretty(depositFeeToCover));
|
||||
|
||||
let totalFees: AmountJson = Amounts.getZero(currency);
|
||||
if (coversAmountWithFee && !isBelowFee) {
|
||||
// these are the fees the customer has to pay
|
||||
// because the merchant doesn't cover them
|
||||
totalFees = Amounts.sub(depositFeeLimit, accDepositFee).amount;
|
||||
}
|
||||
totalFees = Amounts.add(totalFees, getTotalRefreshCost(denoms, denom, leftAmount)).amount;
|
||||
return { cds: cdsResult, totalFees };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@ -729,6 +760,8 @@ export class Wallet {
|
||||
return [];
|
||||
}
|
||||
|
||||
const denoms = await this.q().iterIndex(Stores.denominations.exchangeBaseUrlIndex, exchange.baseUrl).toArray();
|
||||
|
||||
// Denomination of the first coin, we assume that all other
|
||||
// coins have the same currency
|
||||
const firstDenom = await this.q().get(Stores.denominations,
|
||||
@ -763,7 +796,11 @@ export class Wallet {
|
||||
|
||||
console.log("coin return: selecting from possible coins", { cds, amount } );
|
||||
|
||||
return selectPayCoins(cds, amount, amount);
|
||||
const res = selectPayCoins(denoms, cds, amount, amount);
|
||||
if (res) {
|
||||
return res.cds;
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
@ -771,7 +808,7 @@ export class Wallet {
|
||||
* Get exchanges and associated coins that are still spendable,
|
||||
* but only if the sum the coins' remaining value exceeds the payment amount.
|
||||
*/
|
||||
private async getCoinsForPayment(args: CoinsForPaymentArgs): Promise<CoinSelectionResult> {
|
||||
private async getCoinsForPayment(args: CoinsForPaymentArgs): Promise<CoinSelectionResult|undefined> {
|
||||
const {
|
||||
allowedAuditors,
|
||||
allowedExchanges,
|
||||
@ -821,6 +858,7 @@ export class Wallet {
|
||||
.iterIndex(Stores.coins.exchangeBaseUrlIndex,
|
||||
exchange.baseUrl)
|
||||
.toArray();
|
||||
const denoms = await this.q().iterIndex(Stores.denominations.exchangeBaseUrlIndex, exchange.baseUrl).toArray();
|
||||
if (!coins || coins.length === 0) {
|
||||
continue;
|
||||
}
|
||||
@ -862,6 +900,7 @@ export class Wallet {
|
||||
continue;
|
||||
}
|
||||
|
||||
let totalFees = Amounts.getZero(currency);
|
||||
let wireFee: AmountJson|undefined;
|
||||
for (const fee of (fees.feesForType[wireMethod] || [])) {
|
||||
if (fee.startStamp >= wireFeeTime && fee.endStamp <= wireFeeTime) {
|
||||
@ -873,15 +912,18 @@ export class Wallet {
|
||||
if (wireFee) {
|
||||
const amortizedWireFee = Amounts.divide(wireFee, wireFeeAmortization);
|
||||
if (Amounts.cmp(wireFeeLimit, amortizedWireFee) < 0) {
|
||||
totalFees = Amounts.add(amortizedWireFee, totalFees).amount;
|
||||
remainingAmount = Amounts.add(amortizedWireFee, remainingAmount).amount;
|
||||
}
|
||||
}
|
||||
|
||||
const res = selectPayCoins(cds, remainingAmount, depositFeeLimit);
|
||||
const res = selectPayCoins(denoms, cds, remainingAmount, depositFeeLimit);
|
||||
if (res) {
|
||||
totalFees = Amounts.add(totalFees, res.totalFees).amount;
|
||||
return {
|
||||
cds: res,
|
||||
cds: res.cds,
|
||||
exchangeUrl: exchange.baseUrl,
|
||||
totalFees,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1014,7 +1056,7 @@ export class Wallet {
|
||||
// First check if we already payed for it.
|
||||
const purchase = await this.q().get(Stores.purchases, proposal.contractTermsHash);
|
||||
if (purchase) {
|
||||
return "paid";
|
||||
return { status: "paid" };
|
||||
}
|
||||
|
||||
// If not already payed, check if we could pay for it.
|
||||
@ -1031,9 +1073,9 @@ export class Wallet {
|
||||
|
||||
if (!res) {
|
||||
console.log("not confirming payment, insufficient coins");
|
||||
return "insufficient-balance";
|
||||
return { status: "insufficient-balance" };
|
||||
}
|
||||
return "payment-possible";
|
||||
return { status: "payment-possible", coinSelection: res };
|
||||
}
|
||||
|
||||
|
||||
@ -1653,6 +1695,7 @@ export class Wallet {
|
||||
console.log("suspending coin", c);
|
||||
c.suspended = true;
|
||||
q.put(Stores.coins, c);
|
||||
this.notifier.notify();
|
||||
});
|
||||
await q.finish();
|
||||
}
|
||||
@ -1840,11 +1883,14 @@ export class Wallet {
|
||||
if (c.suspended) {
|
||||
return balance;
|
||||
}
|
||||
if (!(c.status === CoinStatus.Fresh)) {
|
||||
if (c.status === CoinStatus.Fresh) {
|
||||
addTo(balance, "available", c.currentAmount, c.exchangeBaseUrl);
|
||||
return balance;
|
||||
}
|
||||
if (c.status === CoinStatus.Dirty) {
|
||||
addTo(balance, "pendingIncoming", c.currentAmount, c.exchangeBaseUrl);
|
||||
return balance;
|
||||
}
|
||||
console.log("collecting balance");
|
||||
addTo(balance, "available", c.currentAmount, c.exchangeBaseUrl);
|
||||
return balance;
|
||||
}
|
||||
|
||||
@ -1978,6 +2024,9 @@ export class Wallet {
|
||||
|
||||
if (newCoinDenoms.length === 0) {
|
||||
console.log(`not refreshing, available amount ${amountToPretty(availableAmount)} too small`);
|
||||
coin.status = CoinStatus.Useless;
|
||||
await this.q().put(Stores.coins, coin);
|
||||
this.notifier.notify();
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -2007,6 +2056,7 @@ export class Wallet {
|
||||
query.put(Stores.refresh, refreshSession, "refreshKey")
|
||||
.mutate(Stores.coins, coin.coinPub, mutateCoin);
|
||||
await query.finish();
|
||||
this.notifier.notify();
|
||||
|
||||
const key = query.key("refreshKey");
|
||||
if (!key || typeof key !== "number") {
|
||||
@ -2026,7 +2076,15 @@ export class Wallet {
|
||||
console.log("got old session for", oldCoinPub, session);
|
||||
this.continueRefreshSession(session);
|
||||
}
|
||||
let refreshSession = await this.createRefreshSession(oldCoinPub);
|
||||
const coin = await this.q().get(Stores.coins, oldCoinPub);
|
||||
if (!coin) {
|
||||
console.warn("can't refresh, coin not in database");
|
||||
return;
|
||||
}
|
||||
if (coin.status === CoinStatus.Useless || coin.status === CoinStatus.Fresh) {
|
||||
return;
|
||||
}
|
||||
const refreshSession = await this.createRefreshSession(oldCoinPub);
|
||||
if (!refreshSession) {
|
||||
// refreshing not necessary
|
||||
console.log("not refreshing", oldCoinPub);
|
||||
@ -2106,6 +2164,7 @@ export class Wallet {
|
||||
refreshSession.norevealIndex = norevealIndex;
|
||||
|
||||
await this.q().put(Stores.refresh, refreshSession).finish();
|
||||
this.notifier.notify();
|
||||
}
|
||||
|
||||
|
||||
@ -2186,6 +2245,7 @@ export class Wallet {
|
||||
.putAll(Stores.coins, coins)
|
||||
.put(Stores.refresh, refreshSession)
|
||||
.finish();
|
||||
this.notifier.notify();
|
||||
}
|
||||
|
||||
|
||||
@ -2344,6 +2404,7 @@ export class Wallet {
|
||||
// from the reserve for the payback request.
|
||||
reserve.hasPayback = true;
|
||||
await this.q().put(Stores.coins, coin).put(Stores.reserves, reserve);
|
||||
this.notifier.notify();
|
||||
|
||||
const paybackRequest = await this.cryptoApi.createPaybackRequest(coin);
|
||||
const reqUrl = new URI("payback").absoluteTo(coin.exchangeBaseUrl);
|
||||
@ -2361,6 +2422,7 @@ export class Wallet {
|
||||
}
|
||||
coin.status = CoinStatus.PaybackDone;
|
||||
await this.q().put(Stores.coins, coin);
|
||||
this.notifier.notify();
|
||||
await this.updateReserve(reservePub!);
|
||||
}
|
||||
|
||||
@ -2502,6 +2564,7 @@ export class Wallet {
|
||||
.put(Stores.coinsReturns, coinsReturnRecord)
|
||||
.putAll(Stores.coins, payCoinInfo.map((pci) => pci.updatedCoin))
|
||||
.finish();
|
||||
this.notifier.notify();
|
||||
|
||||
this.depositReturnedCoins(coinsReturnRecord);
|
||||
}
|
||||
@ -2558,6 +2621,7 @@ export class Wallet {
|
||||
}
|
||||
}
|
||||
await this.q().put(Stores.coinsReturns, currentCrr);
|
||||
this.notifier.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2666,4 +2730,34 @@ export class Wallet {
|
||||
async getPurchase(contractTermsHash: string): Promise<PurchaseRecord|undefined> {
|
||||
return this.q().get(Stores.purchases, contractTermsHash);
|
||||
}
|
||||
|
||||
async getFullRefundFees(refundPermissions: RefundPermission[]): Promise<AmountJson> {
|
||||
if (refundPermissions.length === 0) {
|
||||
throw Error("no refunds given");
|
||||
}
|
||||
const coin0 = await this.q().get(Stores.coins, refundPermissions[0].coin_pub)
|
||||
if (!coin0) {
|
||||
throw Error("coin not found");
|
||||
}
|
||||
let feeAcc = Amounts.getZero(refundPermissions[0].refund_amount.currency);
|
||||
|
||||
const denoms = await this.q().iterIndex(Stores.denominations.exchangeBaseUrlIndex, coin0.exchangeBaseUrl).toArray();
|
||||
for (const rp of refundPermissions) {
|
||||
const coin = await this.q().get(Stores.coins, rp.coin_pub);
|
||||
if (!coin) {
|
||||
throw Error("coin not found");
|
||||
}
|
||||
const denom = await this.q().get(Stores.denominations, [coin0.exchangeBaseUrl, coin.denomPub]);
|
||||
if (!denom) {
|
||||
throw Error(`denom not found (${coin.denomPub})`);
|
||||
}
|
||||
// FIXME: this assumes that the refund already happened.
|
||||
// When it hasn't, the refresh cost is inaccurate. To fix this,
|
||||
// we need introduce a flag to tell if a coin was refunded or
|
||||
// refreshed normally (and what about incremental refunds?)
|
||||
const refreshCost = getTotalRefreshCost(denoms, denom, Amounts.sub(rp.refund_amount, rp.refund_fee).amount);
|
||||
feeAcc = Amounts.add(feeAcc, refreshCost, rp.refund_fee).amount;
|
||||
}
|
||||
return feeAcc;
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +191,11 @@ export interface MessageMap {
|
||||
"get-purchase": {
|
||||
request: any;
|
||||
response: void;
|
||||
}
|
||||
};
|
||||
"get-full-refund-fees": {
|
||||
request: { refundPermissions: types.RefundPermission[] };
|
||||
response: void;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Taler Wallet: Confirm Reserve Creation</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../style/pure.css">
|
||||
<link rel="stylesheet" type="text/css" href="../style/wallet.css">
|
||||
|
||||
<link rel="icon" href="/img/icon.png">
|
||||
|
@ -25,12 +25,13 @@
|
||||
*/
|
||||
import * as i18n from "../../i18n";
|
||||
import {
|
||||
CheckPayResult,
|
||||
ContractTerms,
|
||||
ExchangeRecord,
|
||||
ProposalRecord,
|
||||
} from "../../types";
|
||||
|
||||
import { renderContractTerms } from "../renderHtml";
|
||||
import { renderAmount } from "../renderHtml";
|
||||
import * as wxApi from "../wxApi";
|
||||
|
||||
import * as React from "react";
|
||||
@ -113,6 +114,7 @@ interface ContractPromptState {
|
||||
* when pressing pay.
|
||||
*/
|
||||
holdCheck: boolean;
|
||||
payStatus?: CheckPayResult;
|
||||
}
|
||||
|
||||
class ContractPrompt extends React.Component<ContractPromptProps, ContractPromptState> {
|
||||
@ -150,7 +152,7 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
||||
return;
|
||||
}
|
||||
const payStatus = await wxApi.checkPay(this.props.proposalId);
|
||||
if (payStatus === "insufficient-balance") {
|
||||
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.`;
|
||||
@ -166,10 +168,10 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
||||
this.setState({error: msgInsufficient});
|
||||
}
|
||||
this.setState({payDisabled: true});
|
||||
} else if (payStatus === "paid") {
|
||||
this.setState({alreadyPaid: true, payDisabled: false, error: null});
|
||||
} else if (payStatus.status === "paid") {
|
||||
this.setState({alreadyPaid: true, payDisabled: false, error: null, payStatus});
|
||||
} else {
|
||||
this.setState({payDisabled: false, error: null});
|
||||
this.setState({payDisabled: false, error: null, payStatus});
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,7 +191,7 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
||||
document.location.href = proposal.contractTerms.fulfillment_url;
|
||||
break;
|
||||
}
|
||||
this.setState({holdCheck: false});
|
||||
this.setState({holdCheck: true});
|
||||
}
|
||||
|
||||
|
||||
@ -198,15 +200,36 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
||||
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(c.amount)}</strong>;
|
||||
console.log("payStatus", this.state.payStatus);
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
{renderContractTerms(c)}
|
||||
<i18n.Translate wrap="p">
|
||||
The merchant <span>{merchantName}</span> {" "}
|
||||
offers you to purchase:
|
||||
</i18n.Translate>
|
||||
<ul>
|
||||
{c.products.map(
|
||||
(p: any, i: number) => (<li key={i}>{p.description}: {renderAmount(p.price)}</li>))
|
||||
}
|
||||
</ul>
|
||||
{(this.state.payStatus && this.state.payStatus.coinSelection) ?
|
||||
<p>The total price is <span>{amount}</span> (plus <span>{renderAmount(this.state.payStatus.coinSelection.totalFees)}</span> fees).</p>
|
||||
:
|
||||
<p>The total price is <span>{amount}</span>.</p>
|
||||
}
|
||||
</div>
|
||||
<button onClick={() => this.doPayment()}
|
||||
<button className="pure-button button-success"
|
||||
disabled={this.state.payDisabled}
|
||||
className="accept">
|
||||
Confirm payment
|
||||
onClick={() => this.doPayment()}>
|
||||
{i18n.str`Confirm payment`}
|
||||
</button>
|
||||
<div>
|
||||
{(this.state.alreadyPaid ? <p className="okaybox">You already paid for this, clicking "Confirm payment" will not cost money again.</p> : <p />)}
|
||||
|
@ -37,11 +37,12 @@ interface RefundStatusViewProps {
|
||||
|
||||
interface RefundStatusViewState {
|
||||
purchase?: types.PurchaseRecord;
|
||||
refundFees?: types.AmountJson;
|
||||
gotResult: boolean;
|
||||
}
|
||||
|
||||
|
||||
const RefundDetail = ({purchase}: {purchase: types.PurchaseRecord}) => {
|
||||
const RefundDetail = ({purchase, fullRefundFees}: {purchase: types.PurchaseRecord, fullRefundFees: types.AmountJson}) => {
|
||||
const pendingKeys = Object.keys(purchase.refundsPending);
|
||||
const doneKeys = Object.keys(purchase.refundsDone);
|
||||
if (pendingKeys.length == 0 && doneKeys.length == 0) {
|
||||
@ -54,22 +55,18 @@ const RefundDetail = ({purchase}: {purchase: types.PurchaseRecord}) => {
|
||||
}
|
||||
|
||||
let amountPending = types.Amounts.getZero(currency);
|
||||
let feesPending = types.Amounts.getZero(currency)
|
||||
for (let k of pendingKeys) {
|
||||
amountPending = types.Amounts.add(amountPending, purchase.refundsPending[k].refund_amount).amount;
|
||||
feesPending = types.Amounts.add(feesPending, purchase.refundsPending[k].refund_fee).amount;
|
||||
}
|
||||
let amountDone = types.Amounts.getZero(currency);
|
||||
let feesDone = types.Amounts.getZero(currency);
|
||||
for (let k of doneKeys) {
|
||||
amountDone = types.Amounts.add(amountDone, purchase.refundsDone[k].refund_amount).amount;
|
||||
feesDone = types.Amounts.add(feesDone, purchase.refundsDone[k].refund_fee).amount;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Refund fully received: <AmountDisplay amount={amountDone} /> (refund fees: <AmountDisplay amount={feesDone} />)</p>
|
||||
<p>Refund incoming: <AmountDisplay amount={amountPending} /> (refund fees: <AmountDisplay amount={feesPending} />)</p>
|
||||
<p>Refund fully received: <AmountDisplay amount={amountDone} /> (refund fees: <AmountDisplay amount={fullRefundFees} />)</p>
|
||||
<p>Refund incoming: <AmountDisplay amount={amountPending} /></p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -108,7 +105,7 @@ class RefundStatusView extends React.Component<RefundStatusViewProps, RefundStat
|
||||
<h1>Refund Status</h1>
|
||||
<p>Status of purchase <strong>{summary}</strong> from merchant <strong>{merchantName}</strong> (order id {purchase.contractTerms.order_id}).</p>
|
||||
<p>Total amount: <AmountDisplay amount={purchase.contractTerms.amount} /></p>
|
||||
{purchase.finished ? <RefundDetail purchase={purchase} /> : <p>Purchase not completed.</p>}
|
||||
{purchase.finished ? <RefundDetail purchase={purchase} fullRefundFees={this.state.refundFees!} /> : <p>Purchase not completed.</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -116,7 +113,9 @@ class RefundStatusView extends React.Component<RefundStatusViewProps, RefundStat
|
||||
async update() {
|
||||
const purchase = await wxApi.getPurchase(this.props.contractTermsHash);
|
||||
console.log("got purchase", purchase);
|
||||
this.setState({ purchase, gotResult: true });
|
||||
const refundsDone = Object.keys(purchase.refundsDone).map((x) => purchase.refundsDone[x]);
|
||||
const refundFees = await wxApi.getFullRefundFees( {refundPermissions: refundsDone });
|
||||
this.setState({ purchase, gotResult: true, refundFees });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,45 +24,13 @@
|
||||
/**
|
||||
* Imports.
|
||||
*/
|
||||
import { amountToPretty } from "../helpers";
|
||||
import * as i18n from "../i18n";
|
||||
import {
|
||||
AmountJson,
|
||||
Amounts,
|
||||
ContractTerms,
|
||||
} from "../types";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
/**
|
||||
* Render contract terms for the end user to view.
|
||||
*/
|
||||
export function renderContractTerms(contractTerms: ContractTerms): JSX.Element {
|
||||
let merchantName;
|
||||
if (contractTerms.merchant && contractTerms.merchant.name) {
|
||||
merchantName = <strong>{contractTerms.merchant.name}</strong>;
|
||||
} else {
|
||||
merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
|
||||
}
|
||||
const amount = <strong>{amountToPretty(contractTerms.amount)}</strong>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<i18n.Translate wrap="p">
|
||||
The merchant <span>{merchantName}</span>
|
||||
wants to enter a contract over <span>{amount}</span>{" "}
|
||||
with you.
|
||||
</i18n.Translate>
|
||||
<p>{i18n.str`You are about to purchase:`}</p>
|
||||
<ul>
|
||||
{contractTerms.products.map(
|
||||
(p: any, i: number) => (<li key={i}>{`${p.description}: ${amountToPretty(p.price)}`}</li>))
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render amount as HTML, which non-breaking space between
|
||||
|
@ -33,6 +33,7 @@ import {
|
||||
PreCoinRecord,
|
||||
PurchaseRecord,
|
||||
QueryPaymentResult,
|
||||
RefundPermission,
|
||||
ReserveCreationInfo,
|
||||
ReserveRecord,
|
||||
SenderWireInfos,
|
||||
@ -345,3 +346,7 @@ export function acceptRefund(refundData: any): Promise<number> {
|
||||
export function getPurchase(contractTermsHash: string): Promise<PurchaseRecord> {
|
||||
return callBackend("get-purchase", { contractTermsHash });
|
||||
}
|
||||
|
||||
export function getFullRefundFees(args: { refundPermissions: RefundPermission[] }): Promise<AmountJson> {
|
||||
return callBackend("get-full-refund-fees", { refundPermissions: args.refundPermissions });
|
||||
}
|
||||
|
@ -323,6 +323,8 @@ function handleMessage(sender: MessageSender,
|
||||
throw Error("contractTermsHash missing");
|
||||
}
|
||||
return needsWallet().getPurchase(contractTermsHash);
|
||||
case "get-full-refund-fees":
|
||||
return needsWallet().getFullRefundFees(detail.refundPermissions);
|
||||
default:
|
||||
// Exhaustiveness check.
|
||||
// See https://www.typescriptlang.org/docs/handbook/advanced-types.html
|
||||
|
Loading…
Reference in New Issue
Block a user