aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-12-04 21:33:11 +0100
committerFlorian Dold <florian@dold.me>2023-12-04 21:33:14 +0100
commitc93d53d6473934f1d6082a25e2fe26b90c55bb91 (patch)
tree661d75d05218a1307b9e4bcf7dbabd1f2f91b5af
parent8a3e6f25ef975e1a3177f73630f866a7b9b214fb (diff)
downloadwallet-core-c93d53d6473934f1d6082a25e2fe26b90c55bb91.tar.xz
wallet-core: work around a libeufin-bank bug
We now ignore the result of POSTing to the bank integration API, since the implementation is outdated and doesn't match the API spec and wallet-core type validators.
-rw-r--r--packages/taler-util/src/codec.ts19
-rw-r--r--packages/taler-util/src/http-client/types.ts102
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts22
3 files changed, 85 insertions, 58 deletions
diff --git a/packages/taler-util/src/codec.ts b/packages/taler-util/src/codec.ts
index 670111b75..701fc8835 100644
--- a/packages/taler-util/src/codec.ts
+++ b/packages/taler-util/src/codec.ts
@@ -14,12 +14,17 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import { j2s } from "./helpers.js";
+import { Logger } from "./logging.js";
+
/**
* Type-safe codecs for converting from/to JSON.
*/
/* eslint-disable @typescript-eslint/ban-types */
+const logger = new Logger("codec.ts");
+
/**
* Error thrown when decoding fails.
*/
@@ -334,21 +339,22 @@ export function codecForStringURL(shouldEndWithSlash?: boolean): Codec<string> {
}
if (shouldEndWithSlash && !x.endsWith("/")) {
throw new DecodingError(
- `expected URL string that ends with slash at ${renderContext(c)} but got ${x}`,
+ `expected URL string that ends with slash at ${renderContext(
+ c,
+ )} but got ${x}`,
);
}
try {
- const url = new URL(x)
+ const url = new URL(x);
return x;
- } catch(e) {
+ } catch (e) {
if (e instanceof Error) {
- throw new DecodingError(e.message)
+ throw new DecodingError(e.message);
} else {
throw new DecodingError(
`expected an URL string at ${renderContext(c)} but got "${x}"`,
);
}
-
}
},
};
@@ -465,6 +471,9 @@ export function codecForEither<T extends Array<Codec<unknown>>>(
continue;
}
}
+ if (logger.shouldLogTrace()) {
+ logger.trace(`offending value: ${j2s(x)}`);
+ }
throw new DecodingError(
`No alternative matched at at ${renderContext(c)}`,
);
diff --git a/packages/taler-util/src/http-client/types.ts b/packages/taler-util/src/http-client/types.ts
index e25bd6ebd..436a06874 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -358,16 +358,22 @@ export const codecForChallengeContactData =
export const codecForWithdrawalPublicInfo =
(): Codec<TalerCorebankApi.WithdrawalPublicInfo> =>
buildCodecForObject<TalerCorebankApi.WithdrawalPublicInfo>()
- .property("username", codecForString(),)
- .property("amount", codecForAmountString(),)
- .property("selected_exchange_account", codecOptional(codecForPaytoString()))
+ .property("username", codecForString())
+ .property("amount", codecForAmountString())
+ .property(
+ "selected_exchange_account",
+ codecOptional(codecForPaytoString()),
+ )
.property("selected_reserve_pub", codecOptional(codecForString()))
- .property("status", codecForEither(
- codecForConstString("pending"),
- codecForConstString("selected"),
- codecForConstString("aborted"),
- codecForConstString("confirmed"),
- ),)
+ .property(
+ "status",
+ codecForEither(
+ codecForConstString("pending"),
+ codecForConstString("selected"),
+ codecForConstString("aborted"),
+ codecForConstString("confirmed"),
+ ),
+ )
.build("TalerCorebankApi.WithdrawalPublicInfo");
export const codecForBankAccountTransactionsResponse =
@@ -397,7 +403,6 @@ export const codecForBankAccountTransactionInfo =
.property("date", codecForTimestamp)
.build("TalerCorebankApi.BankAccountTransactionInfo");
-
export const codecForCreateTransactionResponse =
(): Codec<TalerCorebankApi.CreateTransactionResponse> =>
buildCodecForObject<TalerCorebankApi.CreateTransactionResponse>()
@@ -410,7 +415,6 @@ export const codecForRegisterAccountResponse =
.property("internal_payto_uri", codecForPaytoString())
.build("TalerCorebankApi.RegisterAccountResponse");
-
export const codecForBankAccountCreateWithdrawalResponse =
(): Codec<TalerCorebankApi.BankAccountCreateWithdrawalResponse> =>
buildCodecForObject<TalerCorebankApi.BankAccountCreateWithdrawalResponse>()
@@ -559,12 +563,15 @@ export const codecForBankVersion =
export const codecForBankWithdrawalOperationStatus =
(): Codec<TalerBankIntegrationApi.BankWithdrawalOperationStatus> =>
buildCodecForObject<TalerBankIntegrationApi.BankWithdrawalOperationStatus>()
- .property("status", codecForEither(
- codecForConstString("pending"),
- codecForConstString("selected"),
- codecForConstString("aborted"),
- codecForConstString("confirmed")
- ))
+ .property(
+ "status",
+ codecForEither(
+ codecForConstString("pending"),
+ codecForConstString("selected"),
+ codecForConstString("aborted"),
+ codecForConstString("confirmed"),
+ ),
+ )
.property("amount", codecForAmountString())
.property("sender_wire", codecOptional(codecForPaytoString()))
.property("suggested_exchange", codecOptional(codecForString()))
@@ -577,11 +584,15 @@ export const codecForBankWithdrawalOperationStatus =
export const codecForBankWithdrawalOperationPostResponse =
(): Codec<TalerBankIntegrationApi.BankWithdrawalOperationPostResponse> =>
buildCodecForObject<TalerBankIntegrationApi.BankWithdrawalOperationPostResponse>()
- .property("status", codecForEither(
- codecForConstString("selected"),
- codecForConstString("aborted"),
- codecForConstString("confirmed")
- ))
+ .property(
+ "status",
+ codecForEither(
+ codecForConstString("pending"),
+ codecForConstString("selected"),
+ codecForConstString("aborted"),
+ codecForConstString("confirmed"),
+ ),
+ )
.property("confirm_transfer_url", codecOptional(codecForURL()))
.build("TalerBankIntegrationApi.BankWithdrawalOperationPostResponse");
@@ -789,20 +800,26 @@ export const codecForConversionInfo =
.property("cashin_fee", codecForAmountString())
.property("cashin_min_amount", codecForAmountString())
.property("cashin_ratio", codecForDecimalNumber())
- .property("cashin_rounding_mode", codecForEither(
- codecForConstString("zero"),
- codecForConstString("up"),
- codecForConstString("nearest")
- ))
+ .property(
+ "cashin_rounding_mode",
+ codecForEither(
+ codecForConstString("zero"),
+ codecForConstString("up"),
+ codecForConstString("nearest"),
+ ),
+ )
.property("cashin_tiny_amount", codecForAmountString())
.property("cashout_fee", codecForAmountString())
.property("cashout_min_amount", codecForAmountString())
.property("cashout_ratio", codecForDecimalNumber())
- .property("cashout_rounding_mode", codecForEither(
- codecForConstString("zero"),
- codecForConstString("up"),
- codecForConstString("nearest")
- ))
+ .property(
+ "cashout_rounding_mode",
+ codecForEither(
+ codecForConstString("zero"),
+ codecForConstString("up"),
+ codecForConstString("nearest"),
+ ),
+ )
.property("cashout_tiny_amount", codecForAmountString())
.build("ConversionBankConfig.ConversionInfo");
@@ -820,7 +837,7 @@ export const codecForConversionBankConfig =
.property("fiat_currency_specification", codecForCurrencySpecificiation())
.property("conversion_rate", codecOptional(codecForConversionInfo()))
- .build("ConversionBankConfig.IntegrationConfig")
+ .build("ConversionBankConfig.IntegrationConfig");
// export const codecFor =
// (): Codec<TalerWireGatewayApi.PublicAccountsResponse> =>
@@ -861,17 +878,20 @@ interface CSCoinEnvelope {
// a 256-bit nonce, converted to Crockford Base32.
type DenominationBlindingKeyP = string;
-const codecForURL = codecForString
-const codecForLibtoolVersion = codecForString
-const codecForCurrencyName = codecForString
-const codecForDecimalNumber = codecForString
+const codecForURL = codecForString;
+const codecForLibtoolVersion = codecForString;
+const codecForCurrencyName = codecForString;
+const codecForDecimalNumber = codecForString;
enum TanChannel {
SMS = "sms",
EMAIL = "email",
}
-export type WithdrawalOperationStatus = "pending" | "selected" | "aborted" | "confirmed"
-
+export type WithdrawalOperationStatus =
+ | "pending"
+ | "selected"
+ | "aborted"
+ | "confirmed";
export namespace TalerWireGatewayApi {
export interface TransferResponse {
@@ -1125,7 +1145,7 @@ export namespace TalerBankConversionApi {
// Extra conversion rate information.
// Only present if server opts in to report the static conversion rate.
- conversion_rate?: ConversionInfo
+ conversion_rate?: ConversionInfo;
}
export interface CashinConversionResponse {
@@ -1205,7 +1225,6 @@ export namespace TalerBankIntegrationApi {
// confirmed: the transfer has been confirmed and registered by the bank
status: WithdrawalOperationStatus;
-
// Amount that will be withdrawn with this operation
// (raw amount without fee considerations).
amount: AmountString;
@@ -1338,7 +1357,6 @@ export namespace TalerCorebankApi {
selected_exchange_account?: PaytoString;
}
-
export interface BankAccountTransactionsResponse {
transactions: BankAccountTransactionInfo[];
}
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 4a1fdbfae..63c811e60 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -60,6 +60,7 @@ import {
WithdrawalExchangeAccountDetails,
addPaytoQueryParams,
canonicalizeBaseUrl,
+ codecForAny,
codecForBankWithdrawalOperationPostResponse,
codecForCashinConversionResponse,
codecForConversionBankConfig,
@@ -868,10 +869,10 @@ async function handleKycRequired(
amlStatus === AmlStatus.normal || amlStatus === undefined
? WithdrawalGroupStatus.PendingKyc
: amlStatus === AmlStatus.pending
- ? WithdrawalGroupStatus.PendingAml
- : amlStatus === AmlStatus.fronzen
- ? WithdrawalGroupStatus.SuspendedAml
- : assertUnreachable(amlStatus);
+ ? WithdrawalGroupStatus.PendingAml
+ : amlStatus === AmlStatus.fronzen
+ ? WithdrawalGroupStatus.SuspendedAml
+ : assertUnreachable(amlStatus);
notificationKycUrl = kycUrl;
@@ -1207,7 +1208,8 @@ export async function updateWithdrawalDenoms(
denom.verificationStatus === DenominationVerificationStatus.Unverified
) {
logger.trace(
- `Validating denomination (${current + 1}/${denominations.length
+ `Validating denomination (${current + 1}/${
+ denominations.length
}) signature of ${denom.denomPubHash}`,
);
let valid = false;
@@ -1853,7 +1855,7 @@ export async function getExchangeWithdrawalInfo(
) {
logger.warn(
`wallet's support for exchange protocol version ${WALLET_EXCHANGE_PROTOCOL_VERSION} might be outdated ` +
- `(exchange has ${exchangeDetails.protocolVersionRange}), checking for updates`,
+ `(exchange has ${exchangeDetails.protocolVersionRange}), checking for updates`,
);
}
}
@@ -2097,10 +2099,8 @@ async function registerReserveWithBank(
body: reqBody,
timeout: getReserveRequestTimeout(withdrawalGroup),
});
- await readSuccessResponseJsonOrThrow(
- httpResp,
- codecForBankWithdrawalOperationPostResponse(),
- );
+ // FIXME: libeufin-bank currently doesn't return a response in the right format, so we don't validate at all.
+ await readSuccessResponseJsonOrThrow(httpResp, codecForAny());
const transitionInfo = await ws.db
.mktx((x) => [x.withdrawalGroups])
.runReadWrite(async (tx) => {
@@ -2622,7 +2622,7 @@ async function fetchWithdrawalAccountInfo(
configResp,
codecForConversionBankConfig(),
);
- currencySpecification = configParsed.fiat_currency_specification
+ currencySpecification = configParsed.fiat_currency_specification;
if (req.reservePub) {
}
} else {