taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 686a65234b050d4f2806c7474cad39880664f3b4
parent 0e733d30458b6e2ffed015f1add906ddda586a79
Author: Florian Dold <florian@dold.me>
Date:   Wed,  7 May 2025 00:58:40 +0200

harness: use new withdrawal protocol in dbless withdrawal

Diffstat:
Mpackages/taler-util/src/http-client/exchange-client.ts | 32+++++++++++++++++++++++++++++++-
Mpackages/taler-wallet-core/src/dbless.ts | 41+++++++++++++++++++++--------------------
2 files changed, 52 insertions(+), 21 deletions(-)

diff --git a/packages/taler-util/src/http-client/exchange-client.ts b/packages/taler-util/src/http-client/exchange-client.ts @@ -63,6 +63,8 @@ import { ExchangeReservePurseRequest, ExchangeTransferList, ExchangeVersionResponse, + ExchangeWithdrawRequest, + ExchangeWithdrawResponse, KycAttributes, KycProcessClientInformation, KycProcessStartInformation, @@ -85,6 +87,7 @@ import { codecForExchangeMergeSuccessResponse, codecForExchangePurseStatus, codecForExchangeTransferList, + codecForExchangeWithdrawResponse, codecForKycProcessClientInformation, codecForKycProcessStartInformation, codecForLegitimizationNeededResponse, @@ -139,7 +142,7 @@ export class TalerExchangeHttpClient2 { preventCompression?: boolean; cancelationToken?: CancellationToken; longPollQueue?: LongpollQueue; - }, + } = {}, ) { this.httpLib = params.httpClient ?? createPlatformHttpLib(); this.cacheEvictor = params.cacheEvictor ?? nullEvictor; @@ -1115,4 +1118,31 @@ export class TalerExchangeHttpClient2 { return opUnknownHttpFailure(resp); } } + + /** + * Request: POST /withdraw + * + * https://docs.taler.net/core/api-exchange.html#withdrawal + */ + async withdraw(args: { + body: ExchangeWithdrawRequest; + }): Promise< + | OperationOk<ExchangeWithdrawResponse> + | OperationFail<HttpStatusCode.Forbidden> + > { + const url = new URL(`withdraw`, this.baseUrl); + const resp = await this.fetch(url, { + method: "POST", + body: args.body, + }); + // FIXME: Some documented cases are missing. + switch (resp.status) { + case HttpStatusCode.Ok: + return opSuccessFromHttp(resp, codecForExchangeWithdrawResponse()); + case HttpStatusCode.Forbidden: + return opKnownHttpFailure(resp.status, resp); + default: + return opUnknownHttpFailure(resp); + } + } } diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts @@ -35,22 +35,22 @@ import { EddsaPrivateKeyString, EddsaPublicKeyString, ExchangeBatchDepositRequest, - ExchangeLegacyBatchWithdrawRequest, ExchangeMeltRequest, ExchangeProtocolVersion, Logger, TalerCorebankApiClient, + TalerExchangeHttpClient2, UnblindedDenominationSignature, codecForAny, codecForBankWithdrawalOperationPostResponse, codecForBatchDepositSuccess, codecForExchangeMeltResponse, codecForExchangeRevealResponse, - codecForExchangeLegacyWithdrawBatchResponse, encodeCrock, getRandomBytes, hashWire, parsePaytoUri, + succeedOrThrow, } from "@gnu-taler/taler-util"; import { HttpRequestLibrary, @@ -149,30 +149,31 @@ export async function withdrawCoin(args: { secretSeed: encodeCrock(getRandomBytes(32)), value: Amounts.parseOrThrow(denom.value), }); + const exchangeClient = new TalerExchangeHttpClient2(exchangeBaseUrl); - const reqBody: ExchangeLegacyBatchWithdrawRequest = { - planchets: [ - { - denom_pub_hash: planchet.denomPubHash, - reserve_sig: planchet.withdrawSig, - coin_ev: planchet.coinEv, + const sigResp = await cryptoApi.signWithdrawal({ + amount: Amounts.stringify(denom.value), + fee: Amounts.stringify(denom.fees.feeWithdraw), + coinEvs: [planchet.coinEv], + denomsPubHashes: [planchet.denomPubHash], + reservePriv: reserveKeyPair.reservePriv, + }); + + const rBatch = succeedOrThrow( + await exchangeClient.withdraw({ + body: { + cipher: "ED25519", + coin_evs: [planchet.coinEv], + denoms_h: [planchet.denomPubHash], + reserve_pub: planchet.reservePub, + reserve_sig: sigResp.sig, }, - ], - }; - const reqUrl = new URL( - `reserves/${planchet.reservePub}/batch-withdraw`, - exchangeBaseUrl, - ).href; - - const resp = await http.fetch(reqUrl, { method: "POST", body: reqBody }); - const rBatch = await readSuccessResponseJsonOrThrow( - resp, - codecForExchangeLegacyWithdrawBatchResponse(), + }), ); const ubSig = await cryptoApi.unblindDenominationSignature({ planchet, - evSig: rBatch.ev_sigs[0].ev_sig, + evSig: rBatch.ev_sigs[0], }); return {