commit 25578cf199015938c49972be5bb4374dc9d5f1b6
parent f661cc9d5313f607776a9af634aae43722e94e7b
Author: Florian Dold <florian@dold.me>
Date: Wed, 1 Jul 2026 19:47:33 +0200
fix prepared transfer API signature, fix test assertions
Diffstat:
6 files changed, 48 insertions(+), 38 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-kyc-form-bad-measure.ts b/packages/taler-harness/src/integrationtests/test-kyc-form-bad-measure.ts
@@ -144,8 +144,9 @@ export async function runKycFormBadMeasureTest(t: GlobalTestState) {
);
console.log("resp status", uploadResp.status);
+ console.log(`resp body: ${j2s(uploadResp.json())}`);
- t.assertDeepEqual(uploadResp.status, 500);
+ t.assertDeepEqual(uploadResp.status, 409);
}
runKycFormBadMeasureTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-shorten.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-shorten.ts
@@ -70,8 +70,7 @@ export async function runWithdrawalShortenTest(t: GlobalTestState) {
bank.corebankApiBaseUrl,
).href;
- const prepBaseUrl =
- bank.corebankApiBaseUrl + "/taler-prepared-transfer/";
+ const prepBaseUrl = bank.corebankApiBaseUrl + "/taler-prepared-transfer/";
const exchangeBankAccount: HarnessExchangeBankAccount = {
wireGatewayApiBaseUrl,
@@ -115,13 +114,10 @@ export async function runWithdrawalShortenTest(t: GlobalTestState) {
console.log(j2s(keys.accounts));
- const { walletClient, walletService } = await createWalletDaemonWithClient(
- t,
- {
- name: "wallet",
- persistent: true,
- },
- );
+ const { walletClient } = await createWalletDaemonWithClient(t, {
+ name: "wallet",
+ persistent: true,
+ });
await walletClient.call(WalletApiOperation.AddExchange, {
exchangeBaseUrl: exchange.baseUrl,
diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts
@@ -51,10 +51,7 @@ import {
assertUnreachable,
checkDbInvariant,
checkLogicInvariant,
- decodeCrock,
durationMul,
- eddsaSign,
- encodeCrock,
getQrCodesForPayto,
j2s,
succeedOrThrow,
@@ -1159,13 +1156,21 @@ export interface TransferOptionsRawResult {
transferExpiry: TalerProtocolTimestamp;
}
-export async function getTransferOptionsRaw(
+/**
+ * Get transfer options for withdrawals or
+ * KYC auth transfers.
+ *
+ * If necessary, register the target key with
+ * the prepared transfer service.
+ */
+export async function prepareTransferOptionsRaw(
wex: WalletExecutionContext,
req: {
acct: ExchangeWireAccount;
reservePub: string;
reservePriv: string;
transferAmount: AmountString;
+ isKyc: boolean;
},
): Promise<TransferOptionsRawResult> {
const { acct, reservePub, reservePriv, transferAmount } = req;
@@ -1194,14 +1199,22 @@ export async function getTransferOptionsRaw(
acct.prepared_transfer_url,
{ httpClient: wex.http },
);
- const mySig = eddsaSign(decodeCrock(reservePub), decodeCrock(reservePriv));
+ const mySig = await wex.cryptoApi.signPreparedTransferRegister({
+ account_pub: reservePub,
+ alg: "EdDSA",
+ authorization_priv: reservePriv,
+ credit_account: acct.payto_uri,
+ credit_amount: transferAmount,
+ recurrent: false,
+ type: req.isKyc ? "kyc" : "reserve",
+ });
const resp = succeedOrThrow(
await prepClient.register({
credit_account: acct.payto_uri,
account_pub: reservePub,
alg: "EdDSA",
authorization_pub: reservePub,
- authorization_sig: encodeCrock(mySig),
+ authorization_sig: mySig.sig,
credit_amount: transferAmount,
recurrent: false,
type: "reserve",
diff --git a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts
@@ -2357,46 +2357,44 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
tci: TalerCryptoInterfaceR,
req: SignPreparedTransferRegisterRequest,
): Promise<SignPreparedTransferRegisterResponse> {
-
- let b = buildSigPS(
- TalerSignaturePurpose.WALLET_PREPARED_TRANSFER_REGISTER
- )
- .put(hashTruncate32(stringToBytes(req.credit_account + "\0")))
- .put(bufferFromAmount(req.credit_amount));
+ let b = buildSigPS(TalerSignaturePurpose.WALLET_PREPARED_TRANSFER_REGISTER)
+ .put(hashTruncate32(stringToBytes(req.credit_account + "\0")))
+ .put(bufferFromAmount(req.credit_amount));
if (req.type == "reserve") {
- b = b.put(bufferForUint32(1));
+ b.put(bufferForUint32(1));
} else {
- b = b.put(bufferForUint32(2));
+ b.put(bufferForUint32(2));
}
if (req.recurrent) {
- b = b.put(bufferForUint16(2));
+ b.put(bufferForUint16(2));
} else {
- b = b.put(bufferForUint16(1));
+ b.put(bufferForUint16(1));
}
- b = b.put(bufferForUint16(1)).put(decodeCrock(req.account_pub));
+ b.put(bufferForUint16(1));
+ b.put(decodeCrock(req.account_pub));
return await tci.eddsaSign(tci, {
msg: encodeCrock(b.build()),
priv: req.authorization_priv,
- })
+ });
},
async signPreparedTransferUnregister(
tci: TalerCryptoInterfaceR,
req: SignPreparedTransferUnregisterRequest,
): Promise<SignPreparedTransferUnregisterResponse> {
-
const b = buildSigPS(
- TalerSignaturePurpose.WALLET_PREPARED_TRANSFER_UNREGISTER
+ TalerSignaturePurpose.WALLET_PREPARED_TRANSFER_UNREGISTER,
)
- .put(timestampRoundedToBuffer(req.timestamp)).build();
+ .put(timestampRoundedToBuffer(req.timestamp))
+ .build();
return await tci.eddsaSign(tci, {
msg: encodeCrock(b),
priv: req.authorization_priv,
- })
- }
-}
+ });
+ },
+};
export interface EddsaSignRequest {
msg: string;
diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts
@@ -103,7 +103,7 @@ import {
constructTaskIdentifier,
genericWaitForState,
getGenericRecordHandle,
- getTransferOptionsRaw,
+ prepareTransferOptionsRaw,
runWithClientCancellation,
spendCoins,
} from "./common.js";
@@ -1059,11 +1059,12 @@ async function getAuthTransferDetails(
const exch = await fetchFreshExchange(wex, exchangeBaseUrl);
for (const acct of exch.wireInfo.accounts) {
- const optRes = await getTransferOptionsRaw(wex, {
+ const optRes = await prepareTransferOptionsRaw(wex, {
acct,
reservePriv: depositGroup.merchantPriv,
reservePub: depositGroup.merchantPub,
transferAmount: exch.tinyAmount,
+ isKyc: true,
});
options.push(...optRes.transferOptions);
if (!transferExpiry) {
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
@@ -128,9 +128,9 @@ import {
genericWaitForState,
genericWaitForStateVal,
getGenericRecordHandle,
- getTransferOptionsRaw,
makeCoinAvailable,
makeCoinsVisible,
+ prepareTransferOptionsRaw,
requireExchangeTosAcceptedOrThrow,
runWithClientCancellation,
} from "./common.js";
@@ -4227,11 +4227,12 @@ async function fetchAccount(
let options: TransferOption[] = [];
let transferExpiry: TalerProtocolTimestamp | undefined = undefined;
if (reservePub != null && reservePriv != null) {
- const optRes = await getTransferOptionsRaw(wex, {
+ const optRes = await prepareTransferOptionsRaw(wex, {
acct,
reservePriv,
reservePub,
transferAmount,
+ isKyc: false,
});
options = augmentTransferOptions(optRes.transferOptions);
transferExpiry = optRes.transferExpiry;