summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-20 00:57:02 +0100
committerFlorian Dold <florian@dold.me>2024-02-20 00:57:02 +0100
commit578bd4b1ed12049800556460359cb55a1e8545a2 (patch)
tree8d7846882b342ceaa1048d5a42120ae973d6ce49
parente10df554c9746971be0ec3f39a9cd98520066380 (diff)
downloadwallet-core-578bd4b1ed12049800556460359cb55a1e8545a2.tar.gz
wallet-core-578bd4b1ed12049800556460359cb55a1e8545a2.tar.bz2
wallet-core-578bd4b1ed12049800556460359cb55a1e8545a2.zip
taler-harness: test for balance during a pending refresh operation
-rw-r--r--packages/taler-harness/src/harness/helpers.ts4
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-refresh.ts70
-rw-r--r--packages/taler-wallet-core/src/deposits.ts20
-rw-r--r--packages/taler-wallet-core/src/refresh.ts14
4 files changed, 98 insertions, 10 deletions
diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts
index 7a91353c8..f567a87ff 100644
--- a/packages/taler-harness/src/harness/helpers.ts
+++ b/packages/taler-harness/src/harness/helpers.ts
@@ -25,7 +25,6 @@
*/
import {
AmountString,
- TalerCorebankApiClient,
ConfirmPayResultType,
Duration,
Logger,
@@ -33,6 +32,7 @@ import {
MerchantContractTerms,
NotificationType,
PreparePayResultType,
+ TalerCorebankApiClient,
TransactionMajorState,
WalletNotification,
} from "@gnu-taler/taler-util";
@@ -678,7 +678,7 @@ export async function makeTestPaymentV2(
);
const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, {
- proposalId: preparePayResult.proposalId,
+ transactionId: preparePayResult.transactionId,
});
t.assertTrue(r2.type === ConfirmPayResultType.Done);
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-refresh.ts b/packages/taler-harness/src/integrationtests/test-wallet-refresh.ts
index 9f8d1503e..b86dfadcf 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-refresh.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-refresh.ts
@@ -17,14 +17,21 @@
/**
* Imports.
*/
-import { Wallet, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState } from "../harness/harness.js";
+import {
+ AmountString,
+ NotificationType,
+ TransactionMajorState,
+ TransactionType,
+ j2s,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { parseTransactionIdentifier } from "../../../taler-wallet-core/src/transactions.js";
+import { GlobalTestState, generateRandomPayto } from "../harness/harness.js";
import {
createSimpleTestkudosEnvironmentV2,
- withdrawViaBankV2,
makeTestPaymentV2,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
-import { TransactionType, j2s } from "@gnu-taler/taler-util";
/**
* Run test for refreshe after a payment.
@@ -77,6 +84,61 @@ export async function runWalletRefreshTest(t: GlobalTestState) {
);
t.assertDeepEqual(refreshTx.type, TransactionType.Refresh);
+
+ // Now we test a pending refresh operation.
+ {
+ await exchange.stop();
+
+ const refreshCreatedCond = walletClient.waitForNotificationCond((x) => {
+ if (
+ x.type === NotificationType.TransactionStateTransition &&
+ parseTransactionIdentifier(x.transactionId)?.tag ===
+ TransactionType.Refresh
+ ) {
+ return true;
+ }
+ return false;
+ });
+
+ const refreshDoneCond = walletClient.waitForNotificationCond((x) => {
+ if (
+ x.type === NotificationType.TransactionStateTransition &&
+ parseTransactionIdentifier(x.transactionId)?.tag ===
+ TransactionType.Refresh &&
+ x.newTxState.major === TransactionMajorState.Done
+ ) {
+ return true;
+ }
+ return false;
+ });
+
+ const depositGroupResult = await walletClient.client.call(
+ WalletApiOperation.CreateDepositGroup,
+ {
+ amount: "TESTKUDOS:10.5" as AmountString,
+ depositPaytoUri: generateRandomPayto("foo"),
+ },
+ );
+
+ await refreshCreatedCond;
+
+ // Here, the refresh operation should be in a pending state.
+
+ const bal1 = await walletClient.call(WalletApiOperation.GetBalances, {});
+
+ await exchange.start();
+
+ await refreshDoneCond;
+
+ const bal2 = await walletClient.call(WalletApiOperation.GetBalances, {});
+
+ // The refresh operation completing should not change the available balance,
+ // as we're accounting pending refreshes towards the available (but not material!) balance.
+ t.assertAmountEquals(
+ bal1.balances[0].available,
+ bal2.balances[0].available,
+ );
+ }
}
runWalletRefreshTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts
index dc3831595..6f247501e 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -95,7 +95,11 @@ import {
generateDepositPermissions,
getTotalPaymentCost,
} from "./pay-merchant.js";
-import { createRefreshGroup, getTotalRefreshCost } from "./refresh.js";
+import {
+ CreateRefreshGroupResult,
+ createRefreshGroup,
+ getTotalRefreshCost,
+} from "./refresh.js";
import {
constructTransactionIdentifier,
notifyTransition,
@@ -532,7 +536,7 @@ async function refundDepositGroup(
const currency = Amounts.currencyOf(depositGroup.totalPayCost);
- await ws.db.runReadWriteTx(
+ const res = await ws.db.runReadWriteTx(
[
"depositGroups",
"refreshGroups",
@@ -553,8 +557,9 @@ async function refundDepositGroup(
coinPub: depositGroup.payCoinSelection.coinPubs[i],
});
}
+ let refreshRes: CreateRefreshGroupResult | undefined = undefined;
if (isDone) {
- const rgid = await createRefreshGroup(
+ refreshRes = await createRefreshGroup(
ws,
tx,
currency,
@@ -565,12 +570,19 @@ async function refundDepositGroup(
depositGroupId: newDg.depositGroupId,
}),
);
- newDg.abortRefreshGroupId = rgid.refreshGroupId;
+ newDg.abortRefreshGroupId = refreshRes.refreshGroupId;
}
await tx.depositGroups.put(newDg);
+ return { refreshRes };
},
);
+ if (res?.refreshRes) {
+ for (const notif of res.refreshRes.notifications) {
+ ws.notify(notif);
+ }
+ }
+
return TaskRunResult.backoff();
}
diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts
index df0ab25f9..09cd75bdd 100644
--- a/packages/taler-wallet-core/src/refresh.ts
+++ b/packages/taler-wallet-core/src/refresh.ts
@@ -54,6 +54,7 @@ import {
TransactionState,
TransactionType,
URL,
+ WalletNotification,
} from "@gnu-taler/taler-util";
import {
readSuccessResponseJsonOrThrow,
@@ -1254,6 +1255,7 @@ async function applyRefresh(
export interface CreateRefreshGroupResult {
refreshGroupId: string;
+ notifications: WalletNotification[];
}
/**
@@ -1310,6 +1312,8 @@ export async function createRefreshGroup(
await tx.refreshGroups.put(refreshGroup);
+ const newTxState = computeRefreshTransactionState(refreshGroup);
+
logger.trace(`created refresh group ${refreshGroupId}`);
const ctx = new RefreshTransactionContext(ws, refreshGroupId);
@@ -1321,6 +1325,16 @@ export async function createRefreshGroup(
return {
refreshGroupId,
+ notifications: [
+ {
+ type: NotificationType.TransactionStateTransition,
+ transactionId: ctx.transactionId,
+ oldTxState: {
+ major: TransactionMajorState.None,
+ },
+ newTxState,
+ },
+ ],
};
}