[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-typescript-core] branch master updated: fix test, simplify
From: |
gnunet |
Subject: |
[taler-typescript-core] branch master updated: fix test, simplify |
Date: |
Thu, 16 Jan 2025 15:39:24 +0100 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository taler-typescript-core.
The following commit(s) were added to refs/heads/master by this push:
new 87d3eb80c fix test, simplify
87d3eb80c is described below
commit 87d3eb80c6ddb1b24740e073705d515d12f3e9f4
Author: Florian Dold <florian@dold.me>
AuthorDate: Thu Jan 16 15:39:19 2025 +0100
fix test, simplify
---
.../src/integrationtests/test-bank-wop.ts | 32 +++++-
.../integrationtests/test-withdrawal-conflict.ts | 38 ++++---
packages/taler-util/src/codec.ts | 3 +
.../taler-util/src/http-client/bank-integration.ts | 3 +-
packages/taler-util/src/types-taler-common.ts | 1 +
packages/taler-util/src/types-taler-corebank.ts | 3 +
.../src/types-taler-wallet-transactions.ts | 2 +
packages/taler-util/src/types-taler-wallet.ts | 13 ++-
packages/taler-wallet-core/src/testing.ts | 23 ++--
packages/taler-wallet-core/src/withdraw.ts | 126 +++++++++++++--------
10 files changed, 161 insertions(+), 83 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-bank-wop.ts
b/packages/taler-harness/src/integrationtests/test-bank-wop.ts
index a07ed9920..d857884c7 100644
--- a/packages/taler-harness/src/integrationtests/test-bank-wop.ts
+++ b/packages/taler-harness/src/integrationtests/test-bank-wop.ts
@@ -18,6 +18,8 @@
* Imports.
*/
import {
+ createEddsaKeyPair,
+ encodeCrock,
j2s,
narrowOpSuccessOrThrow,
TalerBankIntegrationHttpClient,
@@ -35,7 +37,8 @@ import { GlobalTestState } from "../harness/harness.js";
export async function runBankWopTest(t: GlobalTestState) {
// Set up test environment
- const { bank } = await createSimpleTestkudosEnvironmentV3(t);
+ const { bank, exchange, exchangeBankAccount } =
+ await createSimpleTestkudosEnvironmentV3(t);
const bankClientNg = new TalerCoreBankHttpClient(bank.corebankApiBaseUrl);
@@ -48,15 +51,34 @@ export async function runBankWopTest(t: GlobalTestState) {
narrowOpSuccessOrThrow("", withdrawalRes);
const biClient = new TalerBankIntegrationHttpClient(
- `${bank.corebankApiBaseUrl}/taler-integration/`,
+ `${bank.corebankApiBaseUrl}taler-integration/`,
);
- const wopStatus = await biClient.getWithdrawalOperationById(
- withdrawalRes.body.withdrawal_id,
- );
+ const wopid = withdrawalRes.body.withdrawal_id;
+
+ const wopStatus = await biClient.getWithdrawalOperationById(wopid);
narrowOpSuccessOrThrow("", wopStatus);
console.log(`${j2s(wopStatus)}`);
+
+ const keyPair = createEddsaKeyPair();
+
+ const postRes = await biClient.completeWithdrawalOperationById(wopid, {
+ selected_exchange: exchangeBankAccount.accountPaytoUri,
+ reserve_pub: encodeCrock(keyPair.eddsaPub),
+ });
+ narrowOpSuccessOrThrow("", postRes);
+
+ const confirmResp = await bankClientNg.confirmWithdrawalById(
+ bankUser,
+ {},
+ wopid,
+ );
+ narrowOpSuccessOrThrow("", confirmResp);
+
+ const wopStatus2 = await biClient.getWithdrawalOperationById(wopid);
+ narrowOpSuccessOrThrow("", wopStatus2);
+ console.log(`status after: ${j2s(wopStatus2.body)}`);
}
runBankWopTest.suites = ["wallet"];
diff --git
a/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts
b/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts
index 576890801..757cf6e6d 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts
@@ -22,6 +22,7 @@ import {
TransactionIdStr,
TransactionMajorState,
TransactionMinorState,
+ TransactionStatePattern,
j2s,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
@@ -131,30 +132,31 @@ export async function runWithdrawalConflictTest(t:
GlobalTestState) {
// One wallet will succeed, another one will have an aborted transaction.
// Order is non-determinstic.
+ // The "aborted(bank)" state is only present because the
taler-exchange-fakebank
+ // returns 404 when one wallet completes the withdrawal, which is a
+ // bug.
+ const expectedFinalStates = [
+ {
+ major: TransactionMajorState.Done,
+ },
+ {
+ major: TransactionMajorState.Aborted,
+ minor: "*",
+ },
+ {
+ major: TransactionMajorState.Failed,
+ minor: "*",
+ },
+ ] satisfies TransactionStatePattern[];
+
await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
transactionId: wMainPrepareResp.transactionId as TransactionIdStr,
- txState: [
- {
- major: TransactionMajorState.Done,
- },
- {
- major: TransactionMajorState.Aborted,
- minor: TransactionMinorState.CompletedByOtherWallet,
- },
- ],
+ txState: expectedFinalStates,
});
await w2.walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
transactionId: w2PrepareResp.transactionId as TransactionIdStr,
- txState: [
- {
- major: TransactionMajorState.Done,
- },
- {
- major: TransactionMajorState.Aborted,
- minor: TransactionMinorState.CompletedByOtherWallet,
- },
- ],
+ txState: expectedFinalStates,
});
}
diff --git a/packages/taler-util/src/codec.ts b/packages/taler-util/src/codec.ts
index 4c02fb1d7..cbbfff23c 100644
--- a/packages/taler-util/src/codec.ts
+++ b/packages/taler-util/src/codec.ts
@@ -114,6 +114,9 @@ class ObjectCodecBuilder<OutputType, PartialOutputType> {
return this as any;
}
+ /**
+ * Do not log warnings if the object has extra properties.
+ */
allowExtra(): ObjectCodecBuilder<OutputType, PartialOutputType> {
this._allowExtra = true;
return this;
diff --git a/packages/taler-util/src/http-client/bank-integration.ts
b/packages/taler-util/src/http-client/bank-integration.ts
index 17c5337c2..e25c88962 100644
--- a/packages/taler-util/src/http-client/bank-integration.ts
+++ b/packages/taler-util/src/http-client/bank-integration.ts
@@ -127,8 +127,9 @@ export class TalerBankIntegrationHttpClient {
}
/**
- *
https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid
+ * FIXME: This is a misnomer!
*
+ *
https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid
*/
async completeWithdrawalOperationById(
woid: string,
diff --git a/packages/taler-util/src/types-taler-common.ts
b/packages/taler-util/src/types-taler-common.ts
index ee7be5176..38fd51954 100644
--- a/packages/taler-util/src/types-taler-common.ts
+++ b/packages/taler-util/src/types-taler-common.ts
@@ -232,6 +232,7 @@ export const codecForTalerCommonConfigResponse =
.allowExtra()
.property("name", codecForString())
.property("version", codecForString())
+ .allowExtra()
.build("TalerCommonConfigResponse");
export enum ExchangeProtocolVersion {
diff --git a/packages/taler-util/src/types-taler-corebank.ts
b/packages/taler-util/src/types-taler-corebank.ts
index b9722c1f7..bf94112e3 100644
--- a/packages/taler-util/src/types-taler-corebank.ts
+++ b/packages/taler-util/src/types-taler-corebank.ts
@@ -61,6 +61,8 @@ export interface IntegrationConfig {
// Name of the API.
name: "taler-bank-integration";
+
+ implementation?: string;
}
export interface TalerCorebankConfigResponse {
@@ -673,6 +675,7 @@ export const codecForIntegrationBankConfig = ():
Codec<IntegrationConfig> =>
.property("version", codecForString())
.property("currency", codecForString())
.property("currency_specification", codecForCurrencySpecificiation())
+ .property("implementation", codecOptional(codecForString()))
.build("TalerCorebankApi.IntegrationConfig");
export const codecForCoreBankConfig = (): Codec<TalerCorebankConfigResponse> =>
diff --git a/packages/taler-util/src/types-taler-wallet-transactions.ts
b/packages/taler-util/src/types-taler-wallet-transactions.ts
index fc7f12fd2..996a3190e 100644
--- a/packages/taler-util/src/types-taler-wallet-transactions.ts
+++ b/packages/taler-util/src/types-taler-wallet-transactions.ts
@@ -161,6 +161,8 @@ export interface TransactionState {
minor?: TransactionMinorState;
}
+export type TransactionStateWildcard = "*";
+
export enum TransactionMajorState {
// No state, only used when reporting transitions into the initial state
None = "none",
diff --git a/packages/taler-util/src/types-taler-wallet.ts
b/packages/taler-util/src/types-taler-wallet.ts
index 5291f304f..760c619e7 100644
--- a/packages/taler-util/src/types-taler-wallet.ts
+++ b/packages/taler-util/src/types-taler-wallet.ts
@@ -89,7 +89,11 @@ import {
codecForMerchantContractTerms,
} from "./types-taler-merchant.js";
import { BackupRecovery } from "./types-taler-sync.js";
-import { TransactionState } from "./types-taler-wallet-transactions.js";
+import {
+ TransactionMajorState,
+ TransactionMinorState,
+ TransactionStateWildcard,
+} from "./types-taler-wallet-transactions.js";
/**
* Identifier for a transaction in the wallet.
@@ -3288,9 +3292,14 @@ export interface TestingWaitExchangeStateRequest {
walletKycStatus?: ExchangeWalletKycStatus;
}
+export interface TransactionStatePattern {
+ major: TransactionMajorState | TransactionStateWildcard;
+ minor?: TransactionMinorState | TransactionStateWildcard;
+}
+
export interface TestingWaitTransactionRequest {
transactionId: TransactionIdStr;
- txState: TransactionState | TransactionState[];
+ txState: TransactionStatePattern | TransactionStatePattern[];
}
export interface TestingGetReserveHistoryRequest {
diff --git a/packages/taler-wallet-core/src/testing.ts
b/packages/taler-wallet-core/src/testing.ts
index 5917c28e5..eeb439715 100644
--- a/packages/taler-wallet-core/src/testing.ts
+++ b/packages/taler-wallet-core/src/testing.ts
@@ -48,6 +48,7 @@ import {
TransactionMajorState,
TransactionMinorState,
TransactionState,
+ TransactionStatePattern,
TransactionType,
URL,
WithdrawTestBalanceRequest,
@@ -596,13 +597,23 @@ async function waitUntilTransactionPendingReady(
});
}
+function matchState(
+ st: TransactionState,
+ pat: TransactionStatePattern,
+): boolean {
+ return (
+ (pat.major === "*" || st.major === pat.major) &&
+ (pat.minor === "*" || st.minor === pat.minor)
+ );
+}
+
/**
* Wait until a transaction is in a particular state.
*/
export async function waitTransactionState(
wex: WalletExecutionContext,
transactionId: string,
- txState: TransactionState | TransactionState[],
+ txState: TransactionStatePattern | TransactionStatePattern[],
): Promise<void> {
logger.info(
`starting waiting for ${transactionId} to be in ${JSON.stringify(
@@ -616,19 +627,13 @@ export async function waitTransactionState(
});
if (Array.isArray(txState)) {
for (const myState of txState) {
- if (
- tx.txState.major === myState.major &&
- tx.txState.minor === myState.minor
- ) {
+ if (matchState(tx.txState, myState)) {
return true;
}
}
return false;
} else {
- return (
- tx.txState.major === txState.major &&
- tx.txState.minor === txState.minor
- );
+ return matchState(tx.txState, txState);
}
},
filterNotification(notif) {
diff --git a/packages/taler-wallet-core/src/withdraw.ts
b/packages/taler-wallet-core/src/withdraw.ts
index d469fa4b1..fd3bd476a 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -763,7 +763,7 @@ export function computeWithdrawalTransactionStatus(
switch (wgRecord.status) {
case WithdrawalGroupStatus.FailedBankAborted:
return {
- major: TransactionMajorState.Aborted,
+ major: TransactionMajorState.Failed,
};
case WithdrawalGroupStatus.Done:
return {
@@ -1057,6 +1057,35 @@ async function processWithdrawalGroupBalanceKyc(
}
}
+/**
+ * Perform a simple transition of a withdrawal transaction
+ * from one state to another.
+ *
+ * If the transaction is in a different state, do not do anything.
+ */
+async function transitionSimple(
+ ctx: WithdrawTransactionContext,
+ from: WithdrawalGroupStatus,
+ to: WithdrawalGroupStatus,
+): Promise<void> {
+ await ctx.transition({}, async (rec) => {
+ switch (rec?.status) {
+ case from: {
+ rec.status = to;
+ return TransitionResult.transition(rec);
+ }
+ }
+ return TransitionResult.stay();
+ });
+}
+
+/**
+ * Handle state "dialog(proposed)" for a withdrawal transaction.
+ *
+ * In this state, we wait for the user to confirm
+ * and also monitor the state of the bank's withdrawal
+ * operation.
+ */
async function processWithdrawalGroupDialogProposed(
ctx: WithdrawTransactionContext,
withdrawalGroup: WithdrawalGroupRecord,
@@ -1098,26 +1127,30 @@ async function processWithdrawalGroupDialogProposed(
},
);
- // If the bank claims that the withdrawal operation is already
- // pending, but we're still in DialogProposed, some other wallet
- // must've completed the withdrawal, we're giving up.
-
switch (resp.status) {
+ case HttpStatusCode.NotFound: {
+ // FIXME: Further inspect the error body
+ await transitionSimple(
+ ctx,
+ WithdrawalGroupStatus.DialogProposed,
+ WithdrawalGroupStatus.AbortedBank,
+ );
+ break;
+ }
case HttpStatusCode.Ok: {
+ // If the bank claims that the withdrawal operation is already
+ // pending, but we're still in DialogProposed, some other wallet
+ // must've completed the withdrawal, we're giving up.
const body = await readSuccessResponseJsonOrThrow(
resp,
codecForBankWithdrawalOperationStatus(),
);
if (body.status !== "pending") {
- await ctx.transition({}, async (rec) => {
- switch (rec?.status) {
- case WithdrawalGroupStatus.DialogProposed: {
- rec.status = WithdrawalGroupStatus.AbortedOtherWallet;
- return TransitionResult.transition(rec);
- }
- }
- return TransitionResult.stay();
- });
+ await transitionSimple(
+ ctx,
+ WithdrawalGroupStatus.DialogProposed,
+ WithdrawalGroupStatus.AbortedOtherWallet,
+ );
}
break;
}
@@ -2830,16 +2863,21 @@ async function registerReserveWithBank(
});
switch (httpResp.status) {
+ case HttpStatusCode.NotFound: {
+ // FIXME: Inspect particular status code
+ await transitionSimple(
+ ctx,
+ WithdrawalGroupStatus.PendingRegisteringBank,
+ WithdrawalGroupStatus.FailedBankAborted,
+ );
+ return TaskRunResult.progress();
+ }
case HttpStatusCode.Conflict:
- await ctx.transition({}, async (rec) => {
- switch (rec?.status) {
- case WithdrawalGroupStatus.PendingRegisteringBank: {
- rec.status = WithdrawalGroupStatus.FailedBankAborted;
- return TransitionResult.transition(rec);
- }
- }
- return TransitionResult.stay();
- });
+ await transitionSimple(
+ ctx,
+ WithdrawalGroupStatus.PendingRegisteringBank,
+ WithdrawalGroupStatus.FailedBankAborted,
+ );
return TaskRunResult.progress();
}
@@ -2935,32 +2973,24 @@ async function processBankRegisterReserve(
cancellationToken: wex.cancellationToken,
});
- if (statusResp.status >= 400 && statusResp.status >= 499) {
- let newSt: WithdrawalGroupStatus | undefined;
- // FIXME: Consider looking at the exact status code
- switch (statusResp.status) {
- case HttpStatusCode.NotFound:
- newSt = WithdrawalGroupStatus.FailedAbortingBank;
- break;
- case HttpStatusCode.Conflict:
- newSt = WithdrawalGroupStatus.AbortedOtherWallet;
- break;
- default:
- break;
- }
- if (newSt != null) {
- // FIXME: Consider looking at the exact status code
- await ctx.transition({}, async (rec) => {
- switch (rec?.status) {
- case WithdrawalGroupStatus.PendingRegisteringBank: {
- rec.status = WithdrawalGroupStatus.FailedBankAborted;
- return TransitionResult.transition(rec);
- }
- }
- return TransitionResult.stay();
- });
+ // FIXME: Consider looking at the exact taler error code
+ switch (statusResp.status) {
+ case HttpStatusCode.NotFound:
+ await transitionSimple(
+ ctx,
+ WithdrawalGroupStatus.PendingRegisteringBank,
+ WithdrawalGroupStatus.FailedBankAborted,
+ );
return TaskRunResult.progress();
- }
+ case HttpStatusCode.Conflict:
+ await transitionSimple(
+ ctx,
+ WithdrawalGroupStatus.PendingRegisteringBank,
+ WithdrawalGroupStatus.AbortedOtherWallet,
+ );
+ return TaskRunResult.progress();
+ default:
+ break;
}
const status = await readSuccessResponseJsonOrThrow(
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-typescript-core] branch master updated: fix test, simplify,
gnunet <=