From cf49af2bb9fcc2ceae15a7b90045cc79914dc453 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 3 Aug 2023 21:44:43 +0200 Subject: [PATCH 01/26] harness: allow overriding the test timeout via env variable --- .../src/integrationtests/testrunner.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts index e35264d13..67572f0f7 100644 --- a/packages/taler-harness/src/integrationtests/testrunner.ts +++ b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -338,8 +338,17 @@ export async function runTests(spec: TestRunSpec) { currentChild.stdout?.pipe(harnessLogStream); currentChild.stderr?.pipe(harnessLogStream); - const defaultTimeout = 60000; - const testTimeoutMs = testCase.timeoutMs ?? defaultTimeout; + // Default timeout when the test doesn't override it. + let defaultTimeout = 60000; + const overrideDefaultTimeout = process.env.TALER_TEST_TIMEOUT; + if (overrideDefaultTimeout) { + defaultTimeout = Number.parseInt(overrideDefaultTimeout, 10) * 1000; + } + + // Set the timeout to at least be the default timeout. + const testTimeoutMs = testCase.timeoutMs + ? Math.max(testCase.timeoutMs, defaultTimeout) + : defaultTimeout; if (spec.noTimeout) { console.log(`running ${testName}, no timeout`); From c12a366d4937a5ede3dfe8cef3111e12fc39f23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zg=C3=BCr=20Kesim?= Date: Thu, 3 Aug 2023 21:44:53 +0200 Subject: [PATCH 02/26] adjustment of age-commitment and -proof generation age-withdraw requires that the public keys in the age groups that are too large for the commitment are derived from a published public key. --- packages/taler-util/src/taler-crypto.ts | 30 +++++++++++++++---- .../src/crypto/cryptoImplementation.ts | 3 +- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/taler-util/src/taler-crypto.ts b/packages/taler-util/src/taler-crypto.ts index 408b7e7c2..d52edc1e5 100644 --- a/packages/taler-util/src/taler-crypto.ts +++ b/packages/taler-util/src/taler-crypto.ts @@ -1280,6 +1280,9 @@ export namespace AgeRestriction { }; } + const PublishedAgeRestrictionBaseKey: Edx25519PublicKey = decodeCrock( + "CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG"); + export async function restrictionCommitSeeded( ageMask: number, age: number, @@ -1292,19 +1295,32 @@ export namespace AgeRestriction { const pubs: Edx25519PublicKey[] = []; const privs: Edx25519PrivateKey[] = []; - for (let i = 0; i < numPubs; i++) { + for (let i = 0; i < numPrivs; i++) { const privSeed = await kdfKw({ outputLength: 32, ikm: seed, - info: stringToBytes("age-restriction-commit"), + info: stringToBytes("age-commitment"), salt: bufferForUint32(i), }); + const priv = await Edx25519.keyCreateFromSeed(privSeed); const pub = await Edx25519.getPublic(priv); pubs.push(pub); - if (i < numPrivs) { - privs.push(priv); - } + privs.push(priv); + } + + for (let i = numPrivs; i < numPubs; i++) { + const deriveSeed = await kdfKw({ + outputLength: 32, + ikm: seed, + info: stringToBytes("age-factor"), + salt: bufferForUint32(i), + }); + const pub = await Edx25519.publicKeyDerive( + PublishedAgeRestrictionBaseKey, + deriveSeed, + ); + pubs.push(pub); } return { @@ -1604,7 +1620,9 @@ export function amountToBuffer(amount: AmountLike): Uint8Array { return u8buf; } -export function timestampRoundedToBuffer(ts: TalerProtocolTimestamp): Uint8Array { +export function timestampRoundedToBuffer( + ts: TalerProtocolTimestamp, +): Uint8Array { const b = new ArrayBuffer(8); const v = new DataView(b); // The buffer we sign over represents the timestamp in microseconds. diff --git a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts index 16d96eaa9..01d2677dc 100644 --- a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts @@ -720,9 +720,10 @@ export const nativeCryptoR: TalerCryptoInterfaceR = { if (denomPub.age_mask) { const age = req.restrictAge || AgeRestriction.AGE_UNRESTRICTED; logger.info(`creating age-restricted planchet (age ${age})`); - maybeAcp = await AgeRestriction.restrictionCommit( + maybeAcp = await AgeRestriction.restrictionCommitSeeded( denomPub.age_mask, age, + stringToBytes(req.secretSeed) ); maybeAgeCommitmentHash = AgeRestriction.hashCommitment( maybeAcp.commitment, From 6f4548c89259d366b74c4f16ecf4bc57cf35437c Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 4 Aug 2023 09:09:00 -0300 Subject: [PATCH 03/26] fix signature for aml decision --- packages/aml-backoffice-ui/src/account.ts | 9 ++++++--- packages/aml-backoffice-ui/src/hooks/useCases.ts | 1 - packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/aml-backoffice-ui/src/account.ts b/packages/aml-backoffice-ui/src/account.ts index 2225bf2ff..615d843c4 100644 --- a/packages/aml-backoffice-ui/src/account.ts +++ b/packages/aml-backoffice-ui/src/account.ts @@ -61,17 +61,20 @@ export function buildQuerySignature(key: SigningKey): string { return encodeCrock(eddsaSign(sigBlob, key)); } + export function buildDecisionSignature( key: SigningKey, decision: AmlExchangeBackend.AmlDecision, ): string { + const zero = new Uint8Array(new ArrayBuffer(64)) const sigBlob = buildSigPS(TalerSignaturePurpose.TALER_SIGNATURE_AML_DECISION) - .put(hash(stringToBytes(decision.justification))) - // .put(timestampRoundedToBuffer(decision.decision_time)) + //TODO: new need the null terminator, also in the exchange + .put(hash(stringToBytes(decision.justification)))//check null + .put(timestampRoundedToBuffer(decision.decision_time)) .put(amountToBuffer(decision.new_threshold)) .put(decodeCrock(decision.h_payto)) - // .put(hash(stringToBytes(decision.kyc_requirements))) + .put(zero) //kyc_requirement .put(bufferForUint32(decision.new_state)) .build(); diff --git a/packages/aml-backoffice-ui/src/hooks/useCases.ts b/packages/aml-backoffice-ui/src/hooks/useCases.ts index c5a0fc489..c07bd5f18 100644 --- a/packages/aml-backoffice-ui/src/hooks/useCases.ts +++ b/packages/aml-backoffice-ui/src/hooks/useCases.ts @@ -85,7 +85,6 @@ export function useCases( const records = !afterData ? [] : ((afterData ?? lastAfter).data ?? { records: [] }).records; - console.log("afterdata", afterData, lastAfter, records) if (loadingAfter) return { loading: true, data: { records } }; if (afterData) { return { ok: true, data: { records }, ...pagination }; diff --git a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx index 13e78b169..429cfb9ca 100644 --- a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx +++ b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx @@ -38,7 +38,7 @@ export function NewFormEntry({ fullName: "loggedIn_user_fullname", when: AbsoluteTime.now(), state: AmlExchangeBackend.AmlState.pending, - threshold: Amounts.parseOrThrow("ARS:1000"), + threshold: Amounts.parseOrThrow("KUDOS:1000"), }; const api = useAmlCasesAPI() From acf110dd780c7b8a76171072e7c52d4928d41811 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 4 Aug 2023 10:10:30 -0300 Subject: [PATCH 04/26] added new continue after wire transfer confirmed --- .../demobank-ui/src/components/Loading.tsx | 8 +- packages/demobank-ui/src/pages/HomePage.tsx | 15 +-- packages/demobank-ui/src/pages/Routing.tsx | 2 +- .../pages/WithdrawalConfirmationQuestion.tsx | 3 - .../src/pages/WithdrawalQRCode.tsx | 95 ++++++++++++++----- packages/demobank-ui/src/scss/bank.scss | 38 +++++++- packages/demobank-ui/src/utils.ts | 6 +- 7 files changed, 122 insertions(+), 45 deletions(-) diff --git a/packages/demobank-ui/src/components/Loading.tsx b/packages/demobank-ui/src/components/Loading.tsx index 7cbdad681..b567e9056 100644 --- a/packages/demobank-ui/src/components/Loading.tsx +++ b/packages/demobank-ui/src/components/Loading.tsx @@ -21,9 +21,11 @@ export function Loading(): VNode {
@@ -33,7 +35,7 @@ export function Loading(): VNode { export function Spinner(): VNode { return ( -
+
diff --git a/packages/demobank-ui/src/pages/HomePage.tsx b/packages/demobank-ui/src/pages/HomePage.tsx index 20fcef39a..93a9bdfae 100644 --- a/packages/demobank-ui/src/pages/HomePage.tsx +++ b/packages/demobank-ui/src/pages/HomePage.tsx @@ -84,11 +84,11 @@ export function HomePage({ export function WithdrawalOperationPage({ operationId, onLoadNotOk, - onAbort, + onContinue, }: { operationId: string; onLoadNotOk: () => void; - onAbort: () => void; + onContinue: () => void; }): VNode { //FIXME: libeufin sandbox should return show to create the integration api endpoint //or return withdrawal uri from response @@ -99,12 +99,6 @@ export function WithdrawalOperationPage({ const parsedUri = parseWithdrawUri(uri); const { i18n } = useTranslationContext(); - const [settings, updateSettings] = useSettings(); - function clearCurrentWithdrawal(): void { - updateSettings("currentWithdrawalOperationId", undefined); - onAbort(); - } - if (!parsedUri) { notifyError({ title: i18n.str`The Withdrawal URI is not valid: "${uri}"`, @@ -115,10 +109,7 @@ export function WithdrawalOperationPage({ return ( { - notifyInfo(i18n.str`Withdrawal confirmed!`); - }} - onAborted={clearCurrentWithdrawal} + onContinue={onContinue} onLoadNotOk={onLoadNotOk} /> ); diff --git a/packages/demobank-ui/src/pages/Routing.tsx b/packages/demobank-ui/src/pages/Routing.tsx index 64f9b1208..f176c73db 100644 --- a/packages/demobank-ui/src/pages/Routing.tsx +++ b/packages/demobank-ui/src/pages/Routing.tsx @@ -40,7 +40,7 @@ export function Routing(): VNode { component={({ wopid }: { wopid: string }) => ( { + onContinue={() => { route("/account"); }} onLoadNotOk={() => { diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx index da245b75d..cdb612155 100644 --- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx @@ -33,7 +33,6 @@ import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js"; const logger = new Logger("WithdrawalConfirmationQuestion"); interface Props { - onConfirmed: () => void; onAborted: () => void; withdrawUri: WithdrawUriResult; } @@ -42,7 +41,6 @@ interface Props { * Not providing a back button, only abort. */ export function WithdrawalConfirmationQuestion({ - onConfirmed, onAborted, withdrawUri, }: Props): VNode { @@ -119,7 +117,6 @@ export function WithdrawalConfirmationQuestion({ await confirmWithdrawal( withdrawUri.withdrawalOperationId, ); - onConfirmed(); } catch (error) { if (error instanceof RequestError) { notifyError( diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx index 9f9c9925e..80fdac3c8 100644 --- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx @@ -24,6 +24,7 @@ import { Fragment, VNode, h } from "preact"; import { Loading } from "../components/Loading.js"; import { useWithdrawalDetails } from "../hooks/access.js"; import { notifyInfo } from "../hooks/notification.js"; +import { useSettings } from "../hooks/settings.js"; import { handleNotOkResult } from "./HomePage.js"; import { QrCodeSection } from "./QrCodeSection.js"; import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js"; @@ -32,8 +33,7 @@ const logger = new Logger("WithdrawalQRCode"); interface Props { withdrawUri: WithdrawUriResult; - onAborted: () => void; - onConfirmed: () => void; + onContinue: () => void; onLoadNotOk: () => void; } /** @@ -43,10 +43,14 @@ interface Props { */ export function WithdrawalQRCode({ withdrawUri, - onConfirmed, - onAborted, + onContinue, onLoadNotOk, }: Props): VNode { + const [settings, updateSettings] = useSettings(); + function clearCurrentWithdrawal(): void { + updateSettings("currentWithdrawalOperationId", undefined); + onContinue(); + } const { i18n } = useTranslationContext(); const result = useWithdrawalDetails(withdrawUri.withdrawalOperationId); if (!result.ok) { @@ -64,13 +68,64 @@ export function WithdrawalQRCode({ } const { data } = result; - logger.trace("withdrawal status", data); - if (data.aborted || data.confirmation_done) { - // signal that this withdrawal is aborted - // will redirect to account info - notifyInfo(i18n.str`Operation completed`); - onAborted(); - return ; + if (data.aborted) { + return
+

{i18n.str`Operation aborted`}

+
+

+ + The wire transfer to the GNU Taler Exchange bank's account was aborted, your balance + was not affected. + +

+

+ + You can close this page now or continue to the account page. + +

+ { + e.preventDefault(); + clearCurrentWithdrawal() + onContinue() + }}> + {i18n.str`Continue`} + + +
+
+ } + + if (data.confirmation_done) { + return
+

{i18n.str`Operation completed`}

+ +
+

+ + The wire transfer to the GNU Taler Exchange bank's account is completed, now the + exchange will send the requested amount into your GNU Taler wallet. + +

+

+ + You can close this page now or continue to the account page. + +

+ +
+
} if (!data.selection_done) { @@ -79,25 +134,21 @@ export function WithdrawalQRCode({ withdrawUri={withdrawUri} onAborted={() => { notifyInfo(i18n.str`Operation canceled`); - onAborted(); - }} + clearCurrentWithdrawal() + onContinue() + }} /> ); } - // Wallet POSTed the withdrawal details! Ask the - // user to authorize the operation (here CAPTCHA). return ( { - notifyInfo(i18n.str`Operation confirmed`); - onConfirmed(); - }} onAborted={() => { notifyInfo(i18n.str`Operation canceled`); - onAborted(); - }} + clearCurrentWithdrawal() + onContinue() + }} /> ); -} +} \ No newline at end of file diff --git a/packages/demobank-ui/src/scss/bank.scss b/packages/demobank-ui/src/scss/bank.scss index 0089b9734..f8de0a984 100644 --- a/packages/demobank-ui/src/scss/bank.scss +++ b/packages/demobank-ui/src/scss/bank.scss @@ -314,4 +314,40 @@ h1.nav { [name=wire-transfer-form] > input { margin-bottom: 1em; -} \ No newline at end of file +} + +.lds-ring { + display: inline-block; + position: relative; + width: 80px; + height: 80px; +} +.lds-ring div { + box-sizing: border-box; + display: block; + position: absolute; + width: 64px; + height: 64px; + margin: 8px; + border: 8px solid black; + border-radius: 50%; + animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; + border-color: black transparent transparent transparent; +} +.lds-ring div:nth-child(1) { + animation-delay: -0.45s; +} +.lds-ring div:nth-child(2) { + animation-delay: -0.3s; +} +.lds-ring div:nth-child(3) { + animation-delay: -0.15s; +} +@keyframes lds-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/packages/demobank-ui/src/utils.ts b/packages/demobank-ui/src/utils.ts index e60ba7f3b..4ce0f140e 100644 --- a/packages/demobank-ui/src/utils.ts +++ b/packages/demobank-ui/src/utils.ts @@ -134,7 +134,7 @@ export function buildRequestErrorMessage( specialCases.onClientError && specialCases.onClientError(cause.status); result = { title: title ? title : i18n.str`The server didn't accept the request`, - description: cause.payload.error.description, + description: cause?.payload?.error?.description, debug: JSON.stringify(cause), }; break; @@ -146,7 +146,7 @@ export function buildRequestErrorMessage( title: title ? title : i18n.str`The server had problems processing the request`, - description: cause.payload.error.description, + description: cause?.payload?.error?.description, debug: JSON.stringify(cause), }; break; @@ -154,7 +154,7 @@ export function buildRequestErrorMessage( case ErrorType.UNREADABLE: { result = { title: i18n.str`Unexpected error`, - description: `Response from ${cause.info?.url} is unreadable, status: ${cause.status}`, + description: `Response from ${cause?.info?.url} is unreadable, status: ${cause?.status}`, debug: JSON.stringify(cause), }; break; From 951d1b66fa0ba0dbe7cc4f81a0de4d64b35f8fad Mon Sep 17 00:00:00 2001 From: L Date: Thu, 3 Aug 2023 22:56:36 +0200 Subject: [PATCH 05/26] Added translation using Weblate (Dutch) --- .../taler-wallet-webextension/src/i18n/nl.po | 1950 +++++++++++++++++ 1 file changed, 1950 insertions(+) create mode 100644 packages/taler-wallet-webextension/src/i18n/nl.po diff --git a/packages/taler-wallet-webextension/src/i18n/nl.po b/packages/taler-wallet-webextension/src/i18n/nl.po new file mode 100644 index 000000000..26f543b52 --- /dev/null +++ b/packages/taler-wallet-webextension/src/i18n/nl.po @@ -0,0 +1,1950 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-11-23 00:00+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/NavigationBar.tsx:139 +#, c-format +msgid "Balance" +msgstr "" + +#: src/NavigationBar.tsx:142 +#, c-format +msgid "Backup" +msgstr "" + +#: src/NavigationBar.tsx:147 +#, c-format +msgid "QR Reader and Taler URI" +msgstr "" + +#: src/NavigationBar.tsx:154 +#, c-format +msgid "Settings" +msgstr "" + +#: src/NavigationBar.tsx:184 +#, c-format +msgid "Dev" +msgstr "" + +#: src/mui/Typography.tsx:122 +#, c-format +msgid "%1$s" +msgstr "" + +#: src/components/PendingTransactions.tsx:74 +#, c-format +msgid "PENDING OPERATIONS" +msgstr "" + +#: src/components/Loading.tsx:36 +#, c-format +msgid "Loading" +msgstr "" + +#: src/wallet/BackupPage.tsx:123 +#, c-format +msgid "Could not load backup providers" +msgstr "" + +#: src/wallet/BackupPage.tsx:202 +#, c-format +msgid "No backup providers configured" +msgstr "" + +#: src/wallet/BackupPage.tsx:205 +#, c-format +msgid "Add provider" +msgstr "" + +#: src/wallet/BackupPage.tsx:219 +#, c-format +msgid "Sync all backups" +msgstr "" + +#: src/wallet/BackupPage.tsx:221 +#, c-format +msgid "Sync now" +msgstr "" + +#: src/wallet/BackupPage.tsx:264 +#, c-format +msgid "Last synced" +msgstr "" + +#: src/wallet/BackupPage.tsx:269 +#, c-format +msgid "Not synced" +msgstr "" + +#: src/wallet/BackupPage.tsx:289 +#, c-format +msgid "Expires in" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:60 +#, c-format +msgid "There was an error loading the provider detail for " %1$s"" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:108 +#, c-format +msgid "There is not known provider with url "%1$s"." +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:115 +#, c-format +msgid "See providers" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:143 +#, c-format +msgid "Last backup" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:148 +#, c-format +msgid "Back up" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:154 +#, c-format +msgid "Provider fee" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:157 +#, c-format +msgid "per year" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:163 +#, c-format +msgid "Extend" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:169 +#, c-format +msgid "" +"terms has changed, extending the service will imply accepting the new terms of " +"service" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:179 +#, c-format +msgid "old" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:183 +#, c-format +msgid "new" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:190 +#, c-format +msgid "fee" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:198 +#, c-format +msgid "storage" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:215 +#, c-format +msgid "Remove provider" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:228 +#, c-format +msgid "This provider has reported an error" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:242 +#, c-format +msgid "There is conflict with another backup from %1$s" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:253 +#, c-format +msgid "Backup is not readable" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:261 +#, c-format +msgid "Unknown backup problem: %1$s" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:283 +#, c-format +msgid "service paid" +msgstr "" + +#: src/wallet/ProviderDetailPage.tsx:290 +#, c-format +msgid "Backup valid until" +msgstr "" + +#: src/wallet/AddNewActionView.tsx:57 +#, c-format +msgid "Cancel" +msgstr "" + +#: src/wallet/AddNewActionView.tsx:68 +#, c-format +msgid "Open reserve page" +msgstr "" + +#: src/wallet/AddNewActionView.tsx:70 +#, c-format +msgid "Open pay page" +msgstr "" + +#: src/wallet/AddNewActionView.tsx:72 +#, c-format +msgid "Open refund page" +msgstr "" + +#: src/wallet/AddNewActionView.tsx:74 +#, c-format +msgid "Open tip page" +msgstr "" + +#: src/wallet/AddNewActionView.tsx:76 +#, c-format +msgid "Open withdraw page" +msgstr "" + +#: src/popup/NoBalanceHelp.tsx:43 +#, c-format +msgid "Get digital cash" +msgstr "" + +#: src/popup/BalancePage.tsx:138 +#, c-format +msgid "Could not load balance page" +msgstr "" + +#: src/popup/BalancePage.tsx:175 +#, c-format +msgid "Add" +msgstr "" + +#: src/popup/BalancePage.tsx:179 +#, c-format +msgid "Send %1$s" +msgstr "" + +#: src/popup/TalerActionFound.tsx:44 +#, c-format +msgid "Taler Action" +msgstr "" + +#: src/popup/TalerActionFound.tsx:49 +#, c-format +msgid "This page has pay action." +msgstr "" + +#: src/popup/TalerActionFound.tsx:63 +#, c-format +msgid "This page has a withdrawal action." +msgstr "" + +#: src/popup/TalerActionFound.tsx:79 +#, c-format +msgid "This page has a tip action." +msgstr "" + +#: src/popup/TalerActionFound.tsx:93 +#, c-format +msgid "This page has a notify reserve action." +msgstr "" + +#: src/popup/TalerActionFound.tsx:102 +#, c-format +msgid "Notify" +msgstr "" + +#: src/popup/TalerActionFound.tsx:109 +#, c-format +msgid "This page has a refund action." +msgstr "" + +#: src/popup/TalerActionFound.tsx:123 +#, c-format +msgid "This page has a malformed taler uri." +msgstr "" + +#: src/popup/TalerActionFound.tsx:134 +#, c-format +msgid "Dismiss" +msgstr "" + +#: src/popup/Application.tsx:177 +#, c-format +msgid "this popup is being closed and you are being redirected to %1$s" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:158 +#, c-format +msgid "Could not load purchase proposal details" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:183 +#, c-format +msgid "Order Id" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:189 +#, c-format +msgid "Summary" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:195 +#, c-format +msgid "Amount" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:203 +#, c-format +msgid "Merchant name" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:209 +#, c-format +msgid "Merchant jurisdiction" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:215 +#, c-format +msgid "Merchant address" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:221 +#, c-format +msgid "Merchant logo" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:234 +#, c-format +msgid "Merchant website" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:240 +#, c-format +msgid "Merchant email" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:246 +#, c-format +msgid "Merchant public key" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:256 +#, c-format +msgid "Delivery date" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:271 +#, c-format +msgid "Delivery location" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:277 +#, c-format +msgid "Products" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:289 +#, c-format +msgid "Created at" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:304 +#, c-format +msgid "Refund deadline" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:319 +#, c-format +msgid "Auto refund" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:339 +#, c-format +msgid "Pay deadline" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:354 +#, c-format +msgid "Fulfillment URL" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:360 +#, c-format +msgid "Fulfillment message" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:370 +#, c-format +msgid "Max deposit fee" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:378 +#, c-format +msgid "Max fee" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:386 +#, c-format +msgid "Minimum age" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:398 +#, c-format +msgid "Wire fee amortization" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:404 +#, c-format +msgid "Auditors" +msgstr "" + +#: src/components/ShowFullContractTermPopup.tsx:419 +#, c-format +msgid "Exchanges" +msgstr "" + +#: src/components/Part.tsx:148 +#, c-format +msgid "Bank account" +msgstr "" + +#: src/components/Part.tsx:160 +#, c-format +msgid "Bitcoin address" +msgstr "" + +#: src/components/Part.tsx:163 +#, c-format +msgid "IBAN" +msgstr "" + +#: src/cta/Deposit/views.tsx:38 +#, c-format +msgid "Could not load deposit status" +msgstr "" + +#: src/cta/Deposit/views.tsx:52 +#, c-format +msgid "Digital cash deposit" +msgstr "" + +#: src/cta/Deposit/views.tsx:58 +#, c-format +msgid "Cost" +msgstr "" + +#: src/cta/Deposit/views.tsx:66 +#, c-format +msgid "Fee" +msgstr "" + +#: src/cta/Deposit/views.tsx:73 +#, c-format +msgid "To be received" +msgstr "" + +#: src/cta/Deposit/views.tsx:84 +#, c-format +msgid "Send   %1$s" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:63 +#, c-format +msgid "Bitcoin transfer details" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:66 +#, c-format +msgid "" +"The exchange need a transaction with 3 output, one output is the exchange " +"account and the other two are segwit fake address for metadata with an minimum " +"amount." +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:74 +#, c-format +msgid "" +"In bitcoincore wallet use 'Add Recipient' button to add two additional " +"recipient and copy addresses and amounts" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:98 +#, c-format +msgid "Make sure the amount show %1$s BTC, else you have to change the base unit to BTC" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:110 +#, c-format +msgid "Account" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:116 +#, c-format +msgid "Bank host" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:139 +#, c-format +msgid "Bank transfer details" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:148 +#, c-format +msgid "Subject" +msgstr "" + +#: src/components/BankDetailsByPaytoType.tsx:154 +#, c-format +msgid "Receiver name" +msgstr "" + +#: src/wallet/Transaction.tsx:98 +#, c-format +msgid "Could not load the transaction information" +msgstr "" + +#: src/wallet/Transaction.tsx:191 +#, c-format +msgid "There was an error trying to complete the transaction" +msgstr "" + +#: src/wallet/Transaction.tsx:200 +#, c-format +msgid "This transaction is not completed" +msgstr "" + +#: src/wallet/Transaction.tsx:209 +#, c-format +msgid "Send" +msgstr "" + +#: src/wallet/Transaction.tsx:216 +#, c-format +msgid "Retry" +msgstr "" + +#: src/wallet/Transaction.tsx:224 +#, c-format +msgid "Forget" +msgstr "" + +#: src/wallet/Transaction.tsx:241 +#, c-format +msgid "Caution!" +msgstr "" + +#: src/wallet/Transaction.tsx:244 +#, c-format +msgid "" +"If you have already wired money to the exchange you will loose the chance to get " +"the coins form it." +msgstr "" + +#: src/wallet/Transaction.tsx:259 +#, c-format +msgid "Confirm" +msgstr "" + +#: src/wallet/Transaction.tsx:267 +#, c-format +msgid "Withdrawal" +msgstr "" + +#: src/wallet/Transaction.tsx:286 +#, c-format +msgid "" +"Make sure to use the correct subject, otherwise the money will not arrive in " +"this wallet." +msgstr "" + +#: src/wallet/Transaction.tsx:298 +#, c-format +msgid "" +"The bank did not yet confirmed the wire transfer. Go to the %1$s %2$s and check " +"there is no pending step." +msgstr "" + +#: src/wallet/Transaction.tsx:316 +#, c-format +msgid "Bank has confirmed the wire transfer. Waiting for the exchange to send the coins" +msgstr "" + +#: src/wallet/Transaction.tsx:325 +#, c-format +msgid "Details" +msgstr "" + +#: src/wallet/Transaction.tsx:360 +#, c-format +msgid "Payment" +msgstr "" + +#: src/wallet/Transaction.tsx:378 +#, c-format +msgid "Refunds" +msgstr "" + +#: src/wallet/Transaction.tsx:385 +#, c-format +msgid "%1$s %2$s on %3$s" +msgstr "" + +#: src/wallet/Transaction.tsx:415 +#, c-format +msgid "Merchant created a refund for this order but was not automatically picked up." +msgstr "" + +#: src/wallet/Transaction.tsx:420 +#, c-format +msgid "Offer" +msgstr "" + +#: src/wallet/Transaction.tsx:431 +#, c-format +msgid "Accept" +msgstr "" + +#: src/wallet/Transaction.tsx:438 +#, c-format +msgid "Merchant" +msgstr "" + +#: src/wallet/Transaction.tsx:443 +#, c-format +msgid "Invoice ID" +msgstr "" + +#: src/wallet/Transaction.tsx:470 +#, c-format +msgid "Deposit" +msgstr "" + +#: src/wallet/Transaction.tsx:496 +#, c-format +msgid "Refresh" +msgstr "" + +#: src/wallet/Transaction.tsx:517 +#, c-format +msgid "Tip" +msgstr "" + +#: src/wallet/Transaction.tsx:542 +#, c-format +msgid "Refund" +msgstr "" + +#: src/wallet/Transaction.tsx:555 +#, c-format +msgid "Original order ID" +msgstr "" + +#: src/wallet/Transaction.tsx:568 +#, c-format +msgid "Purchase summary" +msgstr "" + +#: src/wallet/Transaction.tsx:593 +#, c-format +msgid "copy" +msgstr "" + +#: src/wallet/Transaction.tsx:596 +#, c-format +msgid "hide qr" +msgstr "" + +#: src/wallet/Transaction.tsx:608 +#, c-format +msgid "show qr" +msgstr "" + +#: src/wallet/Transaction.tsx:620 +#, c-format +msgid "Credit" +msgstr "" + +#: src/wallet/Transaction.tsx:624 +#, c-format +msgid "Invoice" +msgstr "" + +#: src/wallet/Transaction.tsx:635 +#, c-format +msgid "Exchange" +msgstr "" + +#: src/wallet/Transaction.tsx:641 +#, c-format +msgid "URI" +msgstr "" + +#: src/wallet/Transaction.tsx:667 +#, c-format +msgid "Debit" +msgstr "" + +#: src/wallet/Transaction.tsx:710 +#, c-format +msgid "Transfer" +msgstr "" + +#: src/wallet/Transaction.tsx:844 +#, c-format +msgid "Country" +msgstr "" + +#: src/wallet/Transaction.tsx:852 +#, c-format +msgid "Address lines" +msgstr "" + +#: src/wallet/Transaction.tsx:860 +#, c-format +msgid "Building number" +msgstr "" + +#: src/wallet/Transaction.tsx:868 +#, c-format +msgid "Building name" +msgstr "" + +#: src/wallet/Transaction.tsx:876 +#, c-format +msgid "Street" +msgstr "" + +#: src/wallet/Transaction.tsx:884 +#, c-format +msgid "Post code" +msgstr "" + +#: src/wallet/Transaction.tsx:892 +#, c-format +msgid "Town location" +msgstr "" + +#: src/wallet/Transaction.tsx:900 +#, c-format +msgid "Town" +msgstr "" + +#: src/wallet/Transaction.tsx:908 +#, c-format +msgid "District" +msgstr "" + +#: src/wallet/Transaction.tsx:916 +#, c-format +msgid "Country subdivision" +msgstr "" + +#: src/wallet/Transaction.tsx:935 +#, c-format +msgid "Date" +msgstr "" + +#: src/wallet/Transaction.tsx:990 +#, c-format +msgid "Transaction fees" +msgstr "" + +#: src/wallet/Transaction.tsx:1004 +#, c-format +msgid "Total" +msgstr "" + +#: src/wallet/Transaction.tsx:1074 +#, c-format +msgid "Withdraw" +msgstr "" + +#: src/wallet/Transaction.tsx:1146 +#, c-format +msgid "Price" +msgstr "" + +#: src/wallet/Transaction.tsx:1156 +#, c-format +msgid "Refunded" +msgstr "" + +#: src/wallet/Transaction.tsx:1220 +#, c-format +msgid "Delivery" +msgstr "" + +#: src/wallet/Transaction.tsx:1335 +#, c-format +msgid "Total transfer" +msgstr "" + +#: src/cta/Payment/views.tsx:57 +#, c-format +msgid "Could not load pay status" +msgstr "" + +#: src/cta/Payment/views.tsx:87 +#, c-format +msgid "Digital cash payment" +msgstr "" + +#: src/cta/Payment/views.tsx:119 +#, c-format +msgid "Purchase" +msgstr "" + +#: src/cta/Payment/views.tsx:149 +#, c-format +msgid "Receipt" +msgstr "" + +#: src/cta/Payment/views.tsx:156 +#, c-format +msgid "Valid until" +msgstr "" + +#: src/cta/Payment/views.tsx:191 +#, c-format +msgid "List of products" +msgstr "" + +#: src/cta/Payment/views.tsx:242 +#, c-format +msgid "free" +msgstr "" + +#: src/cta/Payment/views.tsx:263 +#, c-format +msgid "Already paid, you are going to be redirected to %1$s" +msgstr "" + +#: src/cta/Payment/views.tsx:274 +#, c-format +msgid "Already paid" +msgstr "" + +#: src/cta/Payment/views.tsx:280 +#, c-format +msgid "Already claimed" +msgstr "" + +#: src/cta/Payment/views.tsx:296 +#, c-format +msgid "Pay with a mobile phone" +msgstr "" + +#: src/cta/Payment/views.tsx:298 +#, c-format +msgid "Hide QR" +msgstr "" + +#: src/cta/Payment/views.tsx:305 +#, c-format +msgid "Scan the QR code or   %1$s" +msgstr "" + +#: src/cta/Payment/views.tsx:346 +#, c-format +msgid "Pay   %1$s" +msgstr "" + +#: src/cta/Payment/views.tsx:360 +#, c-format +msgid "You have no balance for this currency. Withdraw digital cash first." +msgstr "" + +#: src/cta/Payment/views.tsx:364 +#, c-format +msgid "" +"Could not find enough coins to pay. Even if you have enough %1$s some " +"restriction may apply." +msgstr "" + +#: src/cta/Payment/views.tsx:366 +#, c-format +msgid "Your current balance is not enough." +msgstr "" + +#: src/cta/Payment/views.tsx:395 +#, c-format +msgid "Merchant message" +msgstr "" + +#: src/cta/Refund/views.tsx:34 +#, c-format +msgid "Could not load refund status" +msgstr "" + +#: src/cta/Refund/views.tsx:48 +#, c-format +msgid "Digital cash refund" +msgstr "" + +#: src/cta/Refund/views.tsx:52 +#, c-format +msgid "You've ignored the tip." +msgstr "" + +#: src/cta/Refund/views.tsx:70 +#, c-format +msgid "The refund is in progress." +msgstr "" + +#: src/cta/Refund/views.tsx:76 +#, c-format +msgid "Total to refund" +msgstr "" + +#: src/cta/Refund/views.tsx:106 +#, c-format +msgid "The merchant "%1$s" is offering you a refund." +msgstr "" + +#: src/cta/Refund/views.tsx:115 +#, c-format +msgid "Order amount" +msgstr "" + +#: src/cta/Refund/views.tsx:122 +#, c-format +msgid "Already refunded" +msgstr "" + +#: src/cta/Refund/views.tsx:129 +#, c-format +msgid "Refund offered" +msgstr "" + +#: src/cta/Refund/views.tsx:145 +#, c-format +msgid "Accept   %1$s" +msgstr "" + +#: src/cta/Tip/views.tsx:32 +#, c-format +msgid "Could not load tip status" +msgstr "" + +#: src/cta/Tip/views.tsx:45 +#, c-format +msgid "Digital cash tip" +msgstr "" + +#: src/cta/Tip/views.tsx:66 +#, c-format +msgid "The merchant is offering you a tip" +msgstr "" + +#: src/cta/Tip/views.tsx:74 +#, c-format +msgid "Merchant URL" +msgstr "" + +#: src/cta/Tip/views.tsx:90 +#, c-format +msgid "Receive   %1$s" +msgstr "" + +#: src/cta/Tip/views.tsx:114 +#, c-format +msgid "Tip from %1$s accepted. Check your transactions list for more details." +msgstr "" + +#: src/components/SelectList.tsx:66 +#, c-format +msgid "Select one option" +msgstr "" + +#: src/components/TermsOfService/views.tsx:39 +#, c-format +msgid "Could not load" +msgstr "" + +#: src/components/TermsOfService/views.tsx:73 +#, c-format +msgid "Show terms of service" +msgstr "" + +#: src/components/TermsOfService/views.tsx:81 +#, c-format +msgid "I accept the exchange terms of service" +msgstr "" + +#: src/components/TermsOfService/views.tsx:107 +#, c-format +msgid "Exchange doesn't have terms of service" +msgstr "" + +#: src/components/TermsOfService/views.tsx:135 +#, c-format +msgid "Review exchange terms of service" +msgstr "" + +#: src/components/TermsOfService/views.tsx:146 +#, c-format +msgid "Review new version of terms of service" +msgstr "" + +#: src/components/TermsOfService/views.tsx:170 +#, c-format +msgid "The exchange reply with a empty terms of service" +msgstr "" + +#: src/components/TermsOfService/views.tsx:193 +#, c-format +msgid "Download Terms of Service" +msgstr "" + +#: src/components/TermsOfService/views.tsx:204 +#, c-format +msgid "Hide terms of service" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:117 +#, c-format +msgid "Could not load exchange fees" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:131 +#, c-format +msgid "Close" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:160 +#, c-format +msgid "could not find any exchange" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:166 +#, c-format +msgid "could not find any exchange for the currency %1$s" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:186 +#, c-format +msgid "Service fee description" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:201 +#, c-format +msgid "Select %1$s exchange" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:215 +#, c-format +msgid "Reset" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:218 +#, c-format +msgid "Use this exchange" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:230 +#, c-format +msgid "Doesn't have auditors" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:241 +#, c-format +msgid "currency" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:249 +#, c-format +msgid "Operations" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:252 +#, c-format +msgid "Deposits" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:259 +#, c-format +msgid "Denomination" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:265 +#, c-format +msgid "Until" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:274 +#, c-format +msgid "Withdrawals" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:423 +#, c-format +msgid "Currency" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:433 +#, c-format +msgid "Coin operations" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:436 +#, c-format +msgid "" +"Every operation in this section may be different by denomination value and is " +"valid for a period of time. The exchange will charge the indicated amount every " +"time a coin is used in such operation." +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:545 +#, c-format +msgid "Transfer operations" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:548 +#, c-format +msgid "" +"Every operation in this section may be different by transfer type and is valid " +"for a period of time. The exchange will charge the indicated amount every time a " +"transfer is made." +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:563 +#, c-format +msgid "Operation" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:583 +#, c-format +msgid "Wallet operations" +msgstr "" + +#: src/wallet/ExchangeSelection/views.tsx:597 +#, c-format +msgid "Feature" +msgstr "" + +#: src/cta/Withdraw/views.tsx:47 +#, c-format +msgid "Could not get the info from the URI" +msgstr "" + +#: src/cta/Withdraw/views.tsx:60 +#, c-format +msgid "Could not get info of withdrawal" +msgstr "" + +#: src/cta/Withdraw/views.tsx:74 +#, c-format +msgid "Digital cash withdrawal" +msgstr "" + +#: src/cta/Withdraw/views.tsx:79 +#, c-format +msgid "Could not finish the withdrawal operation" +msgstr "" + +#: src/cta/Withdraw/views.tsx:127 +#, c-format +msgid "Age restriction" +msgstr "" + +#: src/cta/Withdraw/views.tsx:145 +#, c-format +msgid "Withdraw   %1$s" +msgstr "" + +#: src/cta/Withdraw/views.tsx:179 +#, c-format +msgid "Withdraw to a mobile phone" +msgstr "" + +#: src/cta/InvoiceCreate/views.tsx:65 +#, c-format +msgid "Digital invoice" +msgstr "" + +#: src/cta/InvoiceCreate/views.tsx:69 +#, c-format +msgid "Could not finish the invoice creation" +msgstr "" + +#: src/cta/InvoiceCreate/views.tsx:130 +#, c-format +msgid "Create" +msgstr "" + +#: src/cta/InvoicePay/views.tsx:63 +#, c-format +msgid "Could not finish the payment operation" +msgstr "" + +#: src/cta/TransferCreate/views.tsx:55 +#, c-format +msgid "Digital cash transfer" +msgstr "" + +#: src/cta/TransferCreate/views.tsx:59 +#, c-format +msgid "Could not finish the transfer creation" +msgstr "" + +#: src/cta/TransferPickup/views.tsx:57 +#, c-format +msgid "Could not finish the pickup operation" +msgstr "" + +#: src/wallet/CreateManualWithdraw.tsx:149 +#, c-format +msgid "Manual Withdrawal for %1$s" +msgstr "" + +#: src/wallet/CreateManualWithdraw.tsx:154 +#, c-format +msgid "" +"Choose a exchange from where the coins will be withdrawn. The exchange will send " +"the coins to this wallet after receiving a wire transfer with the correct " +"subject." +msgstr "" + +#: src/wallet/CreateManualWithdraw.tsx:162 +#, c-format +msgid "No exchange found for %1$s" +msgstr "" + +#: src/wallet/CreateManualWithdraw.tsx:170 +#, c-format +msgid "Add Exchange" +msgstr "" + +#: src/wallet/CreateManualWithdraw.tsx:192 +#, c-format +msgid "No exchange configured" +msgstr "" + +#: src/wallet/CreateManualWithdraw.tsx:210 +#, c-format +msgid "Can't create the reserve" +msgstr "" + +#: src/wallet/CreateManualWithdraw.tsx:277 +#, c-format +msgid "Start withdrawal" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:38 +#, c-format +msgid "Could not load deposit balance" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:51 +#, c-format +msgid "A currency or an amount should be indicated" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:67 +#, c-format +msgid "There is no enough balance to make a deposit for currency %1$s" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:117 +#, c-format +msgid "Send %1$s to your account" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:121 +#, c-format +msgid "There is no account to make a deposit for currency %1$s" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:127 +#, c-format +msgid "Add account" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:151 +#, c-format +msgid "Select account" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:163 +#, c-format +msgid "Add another account" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:191 +#, c-format +msgid "Deposit fee" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:205 +#, c-format +msgid "Total deposit" +msgstr "" + +#: src/wallet/DepositPage/views.tsx:233 +#, c-format +msgid "Deposit %1$s %2$s" +msgstr "" + +#: src/wallet/AddAccount/views.tsx:56 +#, c-format +msgid "Add bank account for %1$s" +msgstr "" + +#: src/wallet/AddAccount/views.tsx:59 +#, c-format +msgid "Enter the URL of an exchange you trust." +msgstr "" + +#: src/wallet/AddAccount/views.tsx:66 +#, c-format +msgid "Unable add this account" +msgstr "" + +#: src/wallet/AddAccount/views.tsx:73 +#, c-format +msgid "Select account type" +msgstr "" + +#: src/wallet/ExchangeAddConfirm.tsx:42 +#, c-format +msgid "Review terms of service" +msgstr "" + +#: src/wallet/ExchangeAddConfirm.tsx:45 +#, c-format +msgid "Exchange URL" +msgstr "" + +#: src/wallet/ExchangeAddConfirm.tsx:70 +#, c-format +msgid "Add exchange" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:112 +#, c-format +msgid "Add new exchange" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:116 +#, c-format +msgid "Add exchange for %1$s" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:128 +#, c-format +msgid "An exchange has been found! Review the information and click next" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:135 +#, c-format +msgid "This exchange doesn't match the expected currency %1$s" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:143 +#, c-format +msgid "Unable to verify this exchange" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:151 +#, c-format +msgid "Unable to add this exchange" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:167 +#, c-format +msgid "loading" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:174 +#, c-format +msgid "Version" +msgstr "" + +#: src/wallet/ExchangeSetUrl.tsx:206 +#, c-format +msgid "Next" +msgstr "" + +#: src/components/TransactionItem.tsx:201 +#, c-format +msgid "Waiting for confirmation" +msgstr "" + +#: src/components/TransactionItem.tsx:266 +#, c-format +msgid "PENDING" +msgstr "" + +#: src/wallet/History.tsx:75 +#, c-format +msgid "Could not load the list of transactions" +msgstr "" + +#: src/wallet/History.tsx:233 +#, c-format +msgid "Your transaction history is empty for this currency." +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:127 +#, c-format +msgid "Add backup provider" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:131 +#, c-format +msgid "Could not get provider information" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:140 +#, c-format +msgid "Backup providers may charge for their service" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:147 +#, c-format +msgid "URL" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:158 +#, c-format +msgid "Name" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:212 +#, c-format +msgid "Provider URL" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:218 +#, c-format +msgid "Please review and accept this provider's terms of service" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:223 +#, c-format +msgid "Pricing" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:226 +#, c-format +msgid "free of charge" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:228 +#, c-format +msgid "%1$s per year of service" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:235 +#, c-format +msgid "Storage" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:238 +#, c-format +msgid "%1$s megabytes of storage per year of service" +msgstr "" + +#: src/wallet/ProviderAddPage.tsx:244 +#, c-format +msgid "Accept terms of service" +msgstr "" + +#: src/wallet/ReserveCreated.tsx:44 +#, c-format +msgid "Could not parse the payto URI" +msgstr "" + +#: src/wallet/ReserveCreated.tsx:45 +#, c-format +msgid "Please check the uri" +msgstr "" + +#: src/wallet/ReserveCreated.tsx:75 +#, c-format +msgid "Exchange is ready for withdrawal" +msgstr "" + +#: src/wallet/ReserveCreated.tsx:78 +#, c-format +msgid "To complete the process you need to wire%1$s %2$s to the exchange bank account" +msgstr "" + +#: src/wallet/ReserveCreated.tsx:87 +#, c-format +msgid "" +"Alternative, you can also scan this QR code or open %1$s if you have a banking " +"app installed that supports RFC 8905" +msgstr "" + +#: src/wallet/ReserveCreated.tsx:98 +#, c-format +msgid "Cancel withdrawal" +msgstr "" + +#: src/wallet/Settings.tsx:115 +#, c-format +msgid "Could not toggle auto-open" +msgstr "" + +#: src/wallet/Settings.tsx:121 +#, c-format +msgid "Could not toggle clipboard" +msgstr "" + +#: src/wallet/Settings.tsx:126 +#, c-format +msgid "Navigator" +msgstr "" + +#: src/wallet/Settings.tsx:129 +#, c-format +msgid "Automatically open wallet based on page content" +msgstr "" + +#: src/wallet/Settings.tsx:135 +#, c-format +msgid "" +"Enabling this option below will make using the wallet faster, but requires more " +"permissions from your browser." +msgstr "" + +#: src/wallet/Settings.tsx:145 +#, c-format +msgid "Automatically check clipboard for Taler URI" +msgstr "" + +#: src/wallet/Settings.tsx:162 +#, c-format +msgid "Trust" +msgstr "" + +#: src/wallet/Settings.tsx:166 +#, c-format +msgid "No exchange yet" +msgstr "" + +#: src/wallet/Settings.tsx:180 +#, c-format +msgid "Term of Service" +msgstr "" + +#: src/wallet/Settings.tsx:191 +#, c-format +msgid "ok" +msgstr "" + +#: src/wallet/Settings.tsx:197 +#, c-format +msgid "changed" +msgstr "" + +#: src/wallet/Settings.tsx:204 +#, c-format +msgid "not accepted" +msgstr "" + +#: src/wallet/Settings.tsx:210 +#, c-format +msgid "unknown (exchange status should be updated)" +msgstr "" + +#: src/wallet/Settings.tsx:236 +#, c-format +msgid "Add an exchange" +msgstr "" + +#: src/wallet/Settings.tsx:241 +#, c-format +msgid "Troubleshooting" +msgstr "" + +#: src/wallet/Settings.tsx:244 +#, c-format +msgid "Developer mode" +msgstr "" + +#: src/wallet/Settings.tsx:246 +#, c-format +msgid "More options and information useful for debugging" +msgstr "" + +#: src/wallet/Settings.tsx:257 +#, c-format +msgid "Display" +msgstr "" + +#: src/wallet/Settings.tsx:261 +#, c-format +msgid "Current Language" +msgstr "" + +#: src/wallet/Settings.tsx:274 +#, c-format +msgid "Wallet Core" +msgstr "" + +#: src/wallet/Settings.tsx:284 +#, c-format +msgid "Web Extension" +msgstr "" + +#: src/wallet/Settings.tsx:295 +#, c-format +msgid "Exchange compatibility" +msgstr "" + +#: src/wallet/Settings.tsx:299 +#, c-format +msgid "Merchant compatibility" +msgstr "" + +#: src/wallet/Settings.tsx:303 +#, c-format +msgid "Bank compatibility" +msgstr "" + +#: src/wallet/Welcome.tsx:59 +#, c-format +msgid "Browser Extension Installed!" +msgstr "" + +#: src/wallet/Welcome.tsx:63 +#, c-format +msgid "You can open the GNU Taler Wallet using the combination %1$s ." +msgstr "" + +#: src/wallet/Welcome.tsx:72 +#, c-format +msgid "" +"Also pinning the GNU Taler Wallet to your Chrome browser allows you to quick " +"access without keyboard:" +msgstr "" + +#: src/wallet/Welcome.tsx:79 +#, c-format +msgid "Click the puzzle icon" +msgstr "" + +#: src/wallet/Welcome.tsx:82 +#, c-format +msgid "Search for GNU Taler Wallet" +msgstr "" + +#: src/wallet/Welcome.tsx:85 +#, c-format +msgid "Click the pin icon" +msgstr "" + +#: src/wallet/Welcome.tsx:91 +#, c-format +msgid "Permissions" +msgstr "" + +#: src/wallet/Welcome.tsx:100 +#, c-format +msgid "" +"(Enabling this option below will make using the wallet faster, but requires more " +"permissions from your browser.)" +msgstr "" + +#: src/wallet/Welcome.tsx:110 +#, c-format +msgid "Next Steps" +msgstr "" + +#: src/wallet/Welcome.tsx:113 +#, c-format +msgid "Try the demo" +msgstr "" + +#: src/wallet/Welcome.tsx:116 +#, c-format +msgid "Learn how to top up your wallet balance" +msgstr "" + +#: src/components/Diagnostics.tsx:31 +#, c-format +msgid "Diagnostics timed out. Could not talk to the wallet backend." +msgstr "" + +#: src/components/Diagnostics.tsx:52 +#, c-format +msgid "Problems detected:" +msgstr "" + +#: src/components/Diagnostics.tsx:61 +#, c-format +msgid "" +"Please check in your %1$s settings that you have IndexedDB enabled (check the " +"preference name %2$s)." +msgstr "" + +#: src/components/Diagnostics.tsx:70 +#, c-format +msgid "" +"Your wallet database is outdated. Currently automatic migration is not " +"supported. Please go %1$s to reset the wallet database." +msgstr "" + +#: src/components/Diagnostics.tsx:83 +#, c-format +msgid "Running diagnostics" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:163 +#, c-format +msgid "Debug tools" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:170 +#, c-format +msgid "" +"Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL " +"YOUR COINS?" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:176 +#, c-format +msgid "reset" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:183 +#, c-format +msgid "TESTING: This may delete all your coin, proceed with caution" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:189 +#, c-format +msgid "run gc" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:197 +#, c-format +msgid "import database" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:219 +#, c-format +msgid "export database" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:225 +#, c-format +msgid "Database exported at %1$s %2$s to download" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:248 +#, c-format +msgid "Coins" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:282 +#, c-format +msgid "Pending operations" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:328 +#, c-format +msgid "usable coins" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:337 +#, c-format +msgid "id" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:340 +#, c-format +msgid "denom" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:343 +#, c-format +msgid "value" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:346 +#, c-format +msgid "status" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:349 +#, c-format +msgid "from refresh?" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:352 +#, c-format +msgid "age key count" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:369 +#, c-format +msgid "spent coins" +msgstr "" + +#: src/wallet/DeveloperPage.tsx:373 +#, c-format +msgid "click to show" +msgstr "" + +#: src/wallet/QrReader.tsx:108 +#, c-format +msgid "Scan a QR code or enter taler:// URI below" +msgstr "" + +#: src/wallet/QrReader.tsx:122 +#, c-format +msgid "Open" +msgstr "" + +#: src/wallet/QrReader.tsx:128 +#, c-format +msgid "URI is not valid. Taler URI should start with `taler://`" +msgstr "" + +#: src/wallet/QrReader.tsx:133 +#, c-format +msgid "Try another" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:183 +#, c-format +msgid "Could not load list of exchange" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:209 +#, c-format +msgid "Choose a currency to proceed or add another exchange" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:217 +#, c-format +msgid "Known currencies" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:318 +#, c-format +msgid "Specify the amount and the origin" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:336 +#, c-format +msgid "Change currency" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:344 +#, c-format +msgid "Use previous origins:" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:364 +#, c-format +msgid "Or specify the origin of the money" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:372 +#, c-format +msgid "Specify the origin of the money" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:380 +#, c-format +msgid "From my bank account" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:395 +#, c-format +msgid "From another wallet" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:449 +#, c-format +msgid "currency not provided" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:459 +#, c-format +msgid "Specify the amount and the destination" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:483 +#, c-format +msgid "Use previous destinations:" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:503 +#, c-format +msgid "Or specify the destination of the money" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:511 +#, c-format +msgid "Specify the destination of the money" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:521 +#, c-format +msgid "To my bank account" +msgstr "" + +#: src/wallet/DestinationSelection.tsx:534 +#, c-format +msgid "To another wallet" +msgstr "" + +#: src/cta/Recovery/views.tsx:30 +#, c-format +msgid "Could not load backup recovery information" +msgstr "" + +#: src/cta/Recovery/views.tsx:47 +#, c-format +msgid "Digital wallet recovery" +msgstr "" + +#: src/cta/Recovery/views.tsx:52 +#, c-format +msgid "Import backup, show info" +msgstr "" + +#: src/wallet/Application.tsx:189 +#, c-format +msgid "All done, your transaction is in progress" +msgstr "" + +#: src/components/EditableText.tsx:45 +#, c-format +msgid "Edit" +msgstr "" + +#: src/wallet/ManualWithdrawPage.tsx:102 +#, c-format +msgid "Could not load the list of known exchanges" +msgstr "" From 308a4282cbdde7376d88ca76e3eca967a1f02c46 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sat, 5 Aug 2023 23:19:55 +0200 Subject: [PATCH 06/26] wallet-core: mock implementation of GetCurrencyInfo --- .../integrationtests/test-age-restrictions-peer.ts | 4 ++-- packages/taler-util/src/wallet-types.ts | 14 ++++++++++++++ packages/taler-wallet-core/src/db.ts | 5 ++++- packages/taler-wallet-core/src/wallet-api-types.ts | 10 ++++++++++ packages/taler-wallet-core/src/wallet.ts | 9 +++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts b/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts index d15858322..45a4391cb 100644 --- a/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts +++ b/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts @@ -26,7 +26,7 @@ import { } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; -import { GlobalTestState, WalletCli } from "../harness/harness.js"; +import { GlobalTestState } from "../harness/harness.js"; import { createSimpleTestkudosEnvironmentV2, createWalletDaemonWithClient, @@ -106,7 +106,7 @@ export async function runAgeRestrictionsPeerTest(t: GlobalTestState) { ); await wallet2.call(WalletApiOperation.ConfirmPeerPushCredit, { - peerPushPaymentIncomingId: checkResp.peerPushPaymentIncomingId, + transactionId: checkResp.transactionId, }); const peerPullCreditDoneCond = wallet2.waitForNotificationCond( diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 38e5787ba..922b20862 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -379,6 +379,20 @@ export interface Balance { requiresUserInput: boolean; } +export interface GetCurrencyInfoRequest { + currency: string; + scope: ScopeInfo; +} + +export interface GetCurrencyInfoResponse { + decimalSeparator: string; + numFractionalDigits: number; + /** + * Is the currency name leading or trailing? + */ + isCurrencyNameLeading: boolean; +} + export interface InitRequest { skipDefaults?: boolean; } diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 3d2878d93..c7d0b0bda 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -711,7 +711,10 @@ export interface RewardCoinSource { coinIndex: number; } -export type CoinSource = WithdrawCoinSource | RefreshCoinSource | RewardCoinSource; +export type CoinSource = + | WithdrawCoinSource + | RefreshCoinSource + | RewardCoinSource; /** * CoinRecord as stored in the "coins" data store diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index eaa99a6c3..0c9755a3a 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -114,6 +114,8 @@ import { WithdrawUriInfoResponse, SharePaymentRequest, SharePaymentResult, + GetCurrencyInfoRequest, + GetCurrencyInfoResponse, } from "@gnu-taler/taler-util"; import { AuditorTrustRecord, WalletContractData } from "./db.js"; import { @@ -210,6 +212,7 @@ export enum WalletApiOperation { ApplyDevExperiment = "applyDevExperiment", ValidateIban = "validateIban", TestingWaitTransactionsFinal = "testingWaitTransactionsFinal", + GetCurrencyInfo = "getCurrencyInfo", } // group: Initialization @@ -601,6 +604,12 @@ export type ListCurrenciesOp = { response: WalletCurrencyInfo; }; +export type GetCurrencyInfoOp = { + op: WalletApiOperation.GetCurrencyInfo; + request: GetCurrencyInfoRequest; + response: GetCurrencyInfoResponse; +}; + // group: Deposits /** @@ -1072,6 +1081,7 @@ export type WalletOperations = { [WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp; [WalletApiOperation.ValidateIban]: ValidateIbanOp; [WalletApiOperation.TestingWaitTransactionsFinal]: TestingWaitTransactionsFinal; + [WalletApiOperation.GetCurrencyInfo]: GetCurrencyInfoOp; }; export type WalletCoreRequestType< diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index aab414e94..81ea26260 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -118,6 +118,7 @@ import { sampleWalletCoreTransactions, validateIban, codecForSharePaymentRequest, + GetCurrencyInfoResponse, } from "@gnu-taler/taler-util"; import { HttpRequestLibrary, @@ -1395,6 +1396,14 @@ async function dispatchRequestInternal( const resp = await getBackupRecovery(ws); return resp; } + case WalletApiOperation.GetCurrencyInfo: { + const resp: GetCurrencyInfoResponse = { + decimalSeparator: ",", + isCurrencyNameLeading: false, + numFractionalDigits: 2, + }; + return resp; + } case WalletApiOperation.ImportBackupRecovery: { const req = codecForAny().decode(payload); await loadBackupRecovery(ws, req); From 6286699f26f486a9406827ef7359f62896a2dada Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sat, 5 Aug 2023 23:34:25 +0200 Subject: [PATCH 07/26] -validation --- packages/taler-util/src/wallet-types.ts | 52 +++++++++++++++++-- .../taler-wallet-core/src/wallet-api-types.ts | 8 +-- packages/taler-wallet-core/src/wallet.ts | 6 ++- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 922b20862..42d54752a 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -379,11 +379,44 @@ export interface Balance { requiresUserInput: boolean; } +export const codecForScopeInfoGlobal = (): Codec => + buildCodecForObject() + .property("currency", codecForString()) + .property("type", codecForConstString(ScopeType.Global)) + .build("ScopeInfoGlobal"); + +export const codecForScopeInfoExchange = (): Codec => + buildCodecForObject() + .property("currency", codecForString()) + .property("type", codecForConstString(ScopeType.Exchange)) + .property("url", codecForString()) + .build("ScopeInfoExchange"); + +export const codecForScopeInfoAuditor = (): Codec => + buildCodecForObject() + .property("currency", codecForString()) + .property("type", codecForConstString(ScopeType.Auditor)) + .property("url", codecForString()) + .build("ScopeInfoAuditor"); + +export const codecForScopeInfo = (): Codec => + buildCodecForUnion() + .discriminateOn("type") + .alternative(ScopeType.Global, codecForScopeInfoGlobal()) + .alternative(ScopeType.Exchange, codecForScopeInfoExchange()) + .alternative(ScopeType.Auditor, codecForScopeInfoAuditor()) + .build("ScopeInfo"); + export interface GetCurrencyInfoRequest { - currency: string; scope: ScopeInfo; } +export const codecForGetCurrencyInfoRequest = + (): Codec => + buildCodecForObject() + .property("scope", codecForScopeInfo()) + .build("GetCurrencyInfoRequest"); + export interface GetCurrencyInfoResponse { decimalSeparator: string; numFractionalDigits: number; @@ -407,10 +440,19 @@ export enum ScopeType { Auditor = "auditor", } -export type ScopeInfo = - | { type: ScopeType.Global; currency: string } - | { type: ScopeType.Exchange; currency: string; url: string } - | { type: ScopeType.Auditor; currency: string; url: string }; +export type ScopeInfoGlobal = { type: ScopeType.Global; currency: string }; +export type ScopeInfoExchange = { + type: ScopeType.Exchange; + currency: string; + url: string; +}; +export type ScopeInfoAuditor = { + type: ScopeType.Auditor; + currency: string; + url: string; +}; + +export type ScopeInfo = ScopeInfoGlobal | ScopeInfoExchange | ScopeInfoAuditor; export interface BalancesResponse { balances: Balance[]; diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index 0c9755a3a..36c4809af 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -212,7 +212,7 @@ export enum WalletApiOperation { ApplyDevExperiment = "applyDevExperiment", ValidateIban = "validateIban", TestingWaitTransactionsFinal = "testingWaitTransactionsFinal", - GetCurrencyInfo = "getCurrencyInfo", + GetScopedCurrencyInfo = "getScopedCurrencyInfo", } // group: Initialization @@ -604,8 +604,8 @@ export type ListCurrenciesOp = { response: WalletCurrencyInfo; }; -export type GetCurrencyInfoOp = { - op: WalletApiOperation.GetCurrencyInfo; +export type GetScopedCurrencyInfoOp = { + op: WalletApiOperation.GetScopedCurrencyInfo; request: GetCurrencyInfoRequest; response: GetCurrencyInfoResponse; }; @@ -1081,7 +1081,7 @@ export type WalletOperations = { [WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp; [WalletApiOperation.ValidateIban]: ValidateIbanOp; [WalletApiOperation.TestingWaitTransactionsFinal]: TestingWaitTransactionsFinal; - [WalletApiOperation.GetCurrencyInfo]: GetCurrencyInfoOp; + [WalletApiOperation.GetScopedCurrencyInfo]: GetScopedCurrencyInfoOp; }; export type WalletCoreRequestType< diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 81ea26260..dfa41d60e 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -119,6 +119,7 @@ import { validateIban, codecForSharePaymentRequest, GetCurrencyInfoResponse, + codecForGetCurrencyInfoRequest, } from "@gnu-taler/taler-util"; import { HttpRequestLibrary, @@ -1396,7 +1397,10 @@ async function dispatchRequestInternal( const resp = await getBackupRecovery(ws); return resp; } - case WalletApiOperation.GetCurrencyInfo: { + case WalletApiOperation.GetScopedCurrencyInfo: { + logger.info(`payload: ${j2s(payload)}`); + // Ignore result, just validate in this mock implementation + codecForGetCurrencyInfoRequest().decode(payload); const resp: GetCurrencyInfoResponse = { decimalSeparator: ",", isCurrencyNameLeading: false, From 0547df9538657c36d733ff9617704e7c115adefa Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sat, 5 Aug 2023 23:36:32 +0200 Subject: [PATCH 08/26] -remove logging --- packages/taler-wallet-core/src/wallet.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index dfa41d60e..78fb8789e 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -1398,7 +1398,6 @@ async function dispatchRequestInternal( return resp; } case WalletApiOperation.GetScopedCurrencyInfo: { - logger.info(`payload: ${j2s(payload)}`); // Ignore result, just validate in this mock implementation codecForGetCurrencyInfoRequest().decode(payload); const resp: GetCurrencyInfoResponse = { From 44aeaba7b4d21e518928ca545b114e2a8e8c2a24 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sat, 5 Aug 2023 23:56:07 +0200 Subject: [PATCH 09/26] wallet-core: introduce tiny digits --- packages/taler-util/src/wallet-types.ts | 1 + packages/taler-wallet-core/src/wallet.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 42d54752a..3179cd6f3 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -420,6 +420,7 @@ export const codecForGetCurrencyInfoRequest = export interface GetCurrencyInfoResponse { decimalSeparator: string; numFractionalDigits: number; + numTinyDigits: number; /** * Is the currency name leading or trailing? */ diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 78fb8789e..796a96f14 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -1404,6 +1404,7 @@ async function dispatchRequestInternal( decimalSeparator: ",", isCurrencyNameLeading: false, numFractionalDigits: 2, + numTinyDigits: 1, }; return resp; } From 37d0f9438e6e6507c46d56324e38a5f0c391ab45 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 4 Aug 2023 13:32:08 -0300 Subject: [PATCH 10/26] accesstoken in memory and better login when switching between accounts --- .../src/components/exception/login.tsx | 97 +++++++++++++++++-- .../src/components/menu/index.tsx | 7 +- .../merchant-backoffice-ui/src/hooks/index.ts | 25 ++--- .../src/paths/notfound/index.tsx | 1 - 4 files changed, 111 insertions(+), 19 deletions(-) diff --git a/packages/merchant-backoffice-ui/src/components/exception/login.tsx b/packages/merchant-backoffice-ui/src/components/exception/login.tsx index 42c5e89d0..984b6fe06 100644 --- a/packages/merchant-backoffice-ui/src/components/exception/login.tsx +++ b/packages/merchant-backoffice-ui/src/components/exception/login.tsx @@ -20,7 +20,7 @@ */ import { useTranslationContext } from "@gnu-taler/web-util/browser"; -import { h, VNode } from "preact"; +import { ComponentChildren, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useBackendContext } from "../../context/backend.js"; import { useInstanceContext } from "../../context/instance.js"; @@ -40,7 +40,7 @@ function getTokenValuePart(t: string): string { } function normalizeToken(r: string): string { - return `secret-token:${encodeURIComponent(r)}`; + return `secret-token:${r}`; } function cleanUp(s: string): string { @@ -53,7 +53,7 @@ function cleanUp(s: string): string { export function LoginModal({ onConfirm, withMessage }: Props): VNode { const { url: backendUrl, token: baseToken } = useBackendContext(); - const { admin, token: instanceToken } = useInstanceContext(); + const { admin, token: instanceToken, id } = useInstanceContext(); const testLogin = useCredentialsChecker(); const currentToken = getTokenValuePart( (!admin ? baseToken : instanceToken) ?? "", @@ -63,6 +63,78 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode { const [url, setURL] = useState(cleanUp(backendUrl)); const { i18n } = useTranslationContext(); + if (admin && id !== "default") { + //admin trying to access another instance + return (
+
+ +
+
) + } + return (
@@ -137,8 +209,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode { borderTop: 0, }} > - +
); } + +function AsyncButton({onClick, children}:{onClick: () => Promise, children: ComponentChildren}):VNode { + const [running, setRunning] = useState(false) + return +} diff --git a/packages/merchant-backoffice-ui/src/components/menu/index.tsx b/packages/merchant-backoffice-ui/src/components/menu/index.tsx index 56573b8ca..2beaf6956 100644 --- a/packages/merchant-backoffice-ui/src/components/menu/index.tsx +++ b/packages/merchant-backoffice-ui/src/components/menu/index.tsx @@ -130,7 +130,12 @@ export function Menu({ )} {mimic && ( -