aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--API_CHANGES.md8
-rw-r--r--packages/taler-util/src/wallet-types.ts15
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts123
3 files changed, 97 insertions, 49 deletions
diff --git a/API_CHANGES.md b/API_CHANGES.md
index 1cfb62637..5ec48a1b7 100644
--- a/API_CHANGES.md
+++ b/API_CHANGES.md
@@ -4,6 +4,8 @@ This files contains all the API changes for the current release:
## wallet-core
- - AcceptManualWithdrawalResult.exchangePaytoUris is deprecated
- - WithdrawalExchangeAccountDetails.transferAmount is now optional (if convertion applies)
- - added WithdrawalExchangeAccountDetails.currencySpecification about the transferAmount currency
+- AcceptManualWithdrawalResult.exchangePaytoUris is deprecated
+- WithdrawalExchangeAccountDetails.transferAmount is now optional (if convertion applies)
+- added WithdrawalExchangeAccountDetails.currencySpecification about the transferAmount currency
+- 2023-12-05 dold: added WithdrawalExchangeAccountDetails.{status,conversionError} to inform the client
+ about errors with a particular conversion account instead of failing the whole withdrawal(-info) request.
diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts
index 8e72a4949..f19a0dd10 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -2783,6 +2783,16 @@ export interface WithdrawalExchangeAccountDetails {
paytoUri: string;
/**
+ * Status that indicates whether the account can be used
+ * by the user to send funds for a withdrawal.
+ *
+ * ok: account should be shown to the user
+ * error: account should not be shown to the user, UIs might render the error (in conversionError),
+ * especially in dev mode.
+ */
+ status: "ok" | "error";
+
+ /**
* Transfer amount. Might be in a different currency than the requested
* amount for withdrawal.
*
@@ -2804,4 +2814,9 @@ export interface WithdrawalExchangeAccountDetails {
* exchange.
*/
creditRestrictions?: AccountRestriction[];
+
+ /**
+ * Error that happened when attempting to request the conversion rate.
+ */
+ conversionError?: TalerErrorDetail;
}
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 63c811e60..b9ba3058f 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -35,6 +35,7 @@ import {
Duration,
ExchangeBatchWithdrawRequest,
ExchangeListItem,
+ ExchangeWireAccount,
ExchangeWithdrawBatchResponse,
ExchangeWithdrawRequest,
ExchangeWithdrawResponse,
@@ -2584,6 +2585,76 @@ export async function acceptWithdrawalFromUri(
};
}
+async function fetchAccount(
+ ws: InternalWalletState,
+ instructedAmount: AmountJson,
+ acct: ExchangeWireAccount,
+ reservePub?: string,
+): Promise<WithdrawalExchangeAccountDetails> {
+ let paytoUri: string;
+ let transferAmount: AmountString | undefined = undefined;
+ let currencySpecification: CurrencySpecification | undefined = undefined;
+ if (acct.conversion_url != null) {
+ const reqUrl = new URL("cashin-rate", acct.conversion_url);
+ reqUrl.searchParams.set(
+ "amount_credit",
+ Amounts.stringify(instructedAmount),
+ );
+ const httpResp = await ws.http.fetch(reqUrl.href);
+ const respOrErr = await readSuccessResponseJsonOrErrorCode(
+ httpResp,
+ codecForCashinConversionResponse(),
+ );
+ if (respOrErr.isError) {
+ return {
+ status: "error",
+ paytoUri: acct.payto_uri,
+ conversionError: respOrErr.talerErrorResponse,
+ };
+ }
+ const resp = respOrErr.response;
+ paytoUri = acct.payto_uri;
+ transferAmount = resp.amount_debit;
+ const configUrl = new URL("config", acct.conversion_url);
+ const configResp = await ws.http.fetch(configUrl.href);
+ const configRespOrError = await readSuccessResponseJsonOrErrorCode(
+ configResp,
+ codecForConversionBankConfig(),
+ );
+ if (configRespOrError.isError) {
+ return {
+ status: "error",
+ paytoUri: acct.payto_uri,
+ conversionError: configRespOrError.talerErrorResponse,
+ };
+ }
+ const configParsed = configRespOrError.response;
+ currencySpecification = configParsed.fiat_currency_specification;
+ } else {
+ paytoUri = acct.payto_uri;
+ transferAmount = Amounts.stringify(instructedAmount);
+ }
+ paytoUri = addPaytoQueryParams(paytoUri, {
+ amount: Amounts.stringify(transferAmount),
+ });
+ if (reservePub != null) {
+ paytoUri = addPaytoQueryParams(paytoUri, {
+ message: `Taler Withdrawal ${reservePub}`,
+ });
+ }
+ const acctInfo: WithdrawalExchangeAccountDetails = {
+ status: "ok",
+ paytoUri,
+ transferAmount,
+ currencySpecification,
+ creditRestrictions: acct.credit_restrictions,
+ };
+ if (transferAmount != null) {
+ acctInfo.transferAmount = transferAmount;
+ }
+ return acctInfo;
+}
+
/**
* Gather information about bank accounts that can be used for
* withdrawals. This includes accounts that are in a different
@@ -2600,52 +2671,12 @@ async function fetchWithdrawalAccountInfo(
const { exchangeDetails, instructedAmount } = req;
const withdrawalAccounts: WithdrawalExchangeAccountDetails[] = [];
for (let acct of exchangeDetails.wireInfo.accounts) {
- let paytoUri: string;
- let transferAmount: AmountString | undefined = undefined;
- let currencySpecification: CurrencySpecification | undefined = undefined;
- if (acct.conversion_url != null) {
- const reqUrl = new URL("cashin-rate", acct.conversion_url);
- reqUrl.searchParams.set(
- "amount_credit",
- Amounts.stringify(instructedAmount),
- );
- const httpResp = await ws.http.fetch(reqUrl.href);
- const resp = await readSuccessResponseJsonOrThrow(
- httpResp,
- codecForCashinConversionResponse(),
- );
- paytoUri = acct.payto_uri;
- transferAmount = resp.amount_debit;
- const configUrl = new URL("config", acct.conversion_url);
- const configResp = await ws.http.fetch(configUrl.href);
- const configParsed = await readSuccessResponseJsonOrThrow(
- configResp,
- codecForConversionBankConfig(),
- );
- currencySpecification = configParsed.fiat_currency_specification;
- if (req.reservePub) {
- }
- } else {
- paytoUri = acct.payto_uri;
- transferAmount = Amounts.stringify(instructedAmount);
- }
- paytoUri = addPaytoQueryParams(paytoUri, {
- amount: Amounts.stringify(transferAmount),
- });
- if (req.reservePub != null) {
- paytoUri = addPaytoQueryParams(paytoUri, {
- message: `Taler Withdrawal ${req.reservePub}`,
- });
- }
- const acctInfo: WithdrawalExchangeAccountDetails = {
- paytoUri,
- transferAmount,
- currencySpecification,
- creditRestrictions: acct.credit_restrictions,
- };
- if (transferAmount != null) {
- acctInfo.transferAmount = transferAmount;
- }
+ const acctInfo = await fetchAccount(
+ ws,
+ req.instructedAmount,
+ acct,
+ req.reservePub,
+ );
withdrawalAccounts.push(acctInfo);
}
return withdrawalAccounts;