summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-02-20 02:19:41 +0100
committerFlorian Dold <florian@dold.me>2024-02-20 02:19:41 +0100
commitdf6f50028339c033982b94662e8ab465383095b3 (patch)
treef2963e5bee0dbe9552b0978ab59f7d384be5f64a /packages
parent578bd4b1ed12049800556460359cb55a1e8545a2 (diff)
downloadwallet-core-df6f50028339c033982b94662e8ab465383095b3.tar.gz
wallet-core-df6f50028339c033982b94662e8ab465383095b3.tar.bz2
wallet-core-df6f50028339c033982b94662e8ab465383095b3.zip
wallet-core: count deposits towards pendingOutgoing
Diffstat (limited to 'packages')
-rw-r--r--packages/taler-harness/src/integrationtests/test-deposit.ts10
-rw-r--r--packages/taler-wallet-core/src/balance.ts30
-rw-r--r--packages/taler-wallet-core/src/db.ts3
-rw-r--r--packages/taler-wallet-core/src/deposits.ts46
-rw-r--r--packages/taler-wallet-core/src/withdraw.ts16
5 files changed, 93 insertions, 12 deletions
diff --git a/packages/taler-harness/src/integrationtests/test-deposit.ts b/packages/taler-harness/src/integrationtests/test-deposit.ts
index 4339e75db..fa5750d0c 100644
--- a/packages/taler-harness/src/integrationtests/test-deposit.ts
+++ b/packages/taler-harness/src/integrationtests/test-deposit.ts
@@ -22,6 +22,7 @@ import {
NotificationType,
TransactionMajorState,
TransactionMinorState,
+ j2s,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState, generateRandomPayto } from "../harness/harness.js";
@@ -29,7 +30,6 @@ import {
createSimpleTestkudosEnvironmentV2,
withdrawViaBankV2,
} from "../harness/helpers.js";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
/**
* Run test for basic, bank-integrated withdrawal and payment.
@@ -84,6 +84,10 @@ export async function runDepositTest(t: GlobalTestState) {
t.assertDeepEqual(depositGroupResult.transactionId, depositTxId);
+ const balDuring = await walletClient.call(WalletApiOperation.GetBalances, {});
+ console.log(`balances during deposit: ${j2s(balDuring)}`);
+ t.assertAmountEquals(balDuring.balances[0].pendingOutgoing, "TESTKUDOS:10");
+
await depositTrack;
await exchange.runAggregatorOnceWithTimetravel({
@@ -103,6 +107,10 @@ export async function runDepositTest(t: GlobalTestState) {
// The raw amount is what ends up on the bank account, which includes
// deposit and wire fees.
t.assertDeepEqual(transactions.transactions[1].amountRaw, "TESTKUDOS:9.79");
+
+ const balAfter = await walletClient.call(WalletApiOperation.GetBalances, {});
+ console.log(`balances after deposit: ${j2s(balAfter)}`);
+ t.assertAmountEquals(balAfter.balances[0].pendingOutgoing, "TESTKUDOS:0");
}
runDepositTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-core/src/balance.ts b/packages/taler-wallet-core/src/balance.ts
index e63ea6641..94a500384 100644
--- a/packages/taler-wallet-core/src/balance.ts
+++ b/packages/taler-wallet-core/src/balance.ts
@@ -196,6 +196,15 @@ class BalancesStore {
b.pendingIncoming = Amounts.add(b.pendingIncoming, amount).amount;
}
+ async addPendingOutgoing(
+ currency: string,
+ exchangeBaseUrl: string,
+ amount: AmountLike,
+ ): Promise<void> {
+ const b = await this.initBalance(currency, exchangeBaseUrl);
+ b.pendingOutgoing = Amounts.add(b.pendingOutgoing, amount).amount;
+ }
+
async setFlagIncomingAml(
currency: string,
exchangeBaseUrl: string,
@@ -388,6 +397,27 @@ export async function getBalancesInsideTransaction(
case DepositOperationStatus.PendingKyc:
await balanceStore.setFlagOutgoingKyc(currency, e);
}
+
+ switch (dgRecord.operationStatus) {
+ case DepositOperationStatus.SuspendedKyc:
+ case DepositOperationStatus.PendingKyc:
+ case DepositOperationStatus.PendingTrack:
+ case DepositOperationStatus.SuspendedAborting:
+ case DepositOperationStatus.SuspendedDeposit:
+ case DepositOperationStatus.SuspendedTrack:
+ case DepositOperationStatus.PendingDeposit: {
+ const perExchange = dgRecord.infoPerExchange;
+ if (perExchange) {
+ for (const [e, v] of Object.entries(perExchange)) {
+ await balanceStore.addPendingOutgoing(
+ currency,
+ e,
+ v.amountEffective,
+ );
+ }
+ }
+ }
+ }
}
});
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 33f962339..672c1d9aa 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -30,7 +30,6 @@ import {
import {
AbsoluteTime,
AgeCommitmentProof,
- AmountJson,
AmountString,
Amounts,
AttentionInfo,
@@ -1724,7 +1723,7 @@ export interface DepositInfoPerExchange {
* Expected effective amount that will be deposited
* from coins of this exchange.
*/
- amountEffective: AmountJson;
+ amountEffective: AmountString;
}
/**
diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts
index 6f247501e..b327632d3 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -81,6 +81,7 @@ import {
import {
DepositElementStatus,
DepositGroupRecord,
+ DepositInfoPerExchange,
DepositOperationStatus,
DepositTrackingInfo,
KycPendingInfo,
@@ -226,6 +227,10 @@ export class DepositTransactionContext implements TransactionContext {
ws.taskScheduler.stopShepherdTask(retryTag);
notifyTransition(ws, transactionId, transitionInfo);
ws.taskScheduler.startShepherdTask(retryTag);
+ ws.notify({
+ type: NotificationType.BalanceChange,
+ hintTransactionId: transactionId,
+ });
}
async resumeTransaction(): Promise<void> {
@@ -300,6 +305,10 @@ export class DepositTransactionContext implements TransactionContext {
);
ws.taskScheduler.stopShepherdTask(retryTag);
notifyTransition(ws, transactionId, transitionInfo);
+ ws.notify({
+ type: NotificationType.BalanceChange,
+ hintTransactionId: transactionId,
+ });
}
}
@@ -458,6 +467,10 @@ async function waitForRefreshOnDepositGroup(
);
notifyTransition(ws, transactionId, transitionInfo);
+ ws.notify({
+ type: NotificationType.BalanceChange,
+ hintTransactionId: transactionId,
+ });
return TaskRunResult.backoff();
}
@@ -610,10 +623,6 @@ async function processDepositGroupPendingKyc(
tag: TransactionType.Deposit,
depositGroupId,
});
- const retryTag = constructTaskIdentifier({
- tag: PendingTaskType.Deposit,
- depositGroupId,
- });
const kycInfo = depositGroup.kycInfo;
const userType = "individual";
@@ -873,6 +882,10 @@ async function processDepositGroupPendingTrack(
});
notifyTransition(ws, transactionId, transitionInfo);
if (allWired) {
+ ws.notify({
+ type: NotificationType.BalanceChange,
+ hintTransactionId: transactionId,
+ });
return TaskRunResult.finished();
} else {
// FIXME: Use long-polling.
@@ -1365,6 +1378,30 @@ export async function createDepositGroup(
depositGroupId = encodeCrock(getRandomBytes(32));
}
+ const infoPerExchange: Record<string, DepositInfoPerExchange> = {};
+
+ await ws.db.runReadOnlyTx(["coins"], async (tx) => {
+ for (let i = 0; i < payCoinSel.coinSel.coinPubs.length; i++) {
+ const coin = await tx.coins.get(payCoinSel.coinSel.coinPubs[i]);
+ if (!coin) {
+ logger.error("coin not found anymore");
+ continue;
+ }
+ let depPerExchange = infoPerExchange[coin.exchangeBaseUrl];
+ if (!depPerExchange) {
+ infoPerExchange[coin.exchangeBaseUrl] = depPerExchange = {
+ amountEffective: Amounts.stringify(
+ Amounts.zeroOfAmount(totalDepositCost),
+ ),
+ };
+ }
+ const contrib = payCoinSel.coinSel.coinContributions[i];
+ depPerExchange.amountEffective = Amounts.stringify(
+ Amounts.add(depPerExchange.amountEffective, contrib).amount,
+ );
+ }
+ });
+
const counterpartyEffectiveDepositAmount =
await getCounterpartyEffectiveDepositAmount(
ws,
@@ -1402,6 +1439,7 @@ export async function createDepositGroup(
salt: wireSalt,
},
operationStatus: DepositOperationStatus.PendingDeposit,
+ infoPerExchange,
};
const ctx = new DepositTransactionContext(ws, depositGroupId);
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
index 3f4b3ef70..b34ad521d 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -1685,7 +1685,11 @@ export async function processWithdrawalGroup(
case WithdrawalGroupStatus.PendingQueryingStatus:
return processQueryReserve(ws, withdrawalGroupId, cancellationToken);
case WithdrawalGroupStatus.PendingWaitConfirmBank:
- return await processReserveBankStatus(ws, withdrawalGroupId);
+ return await processReserveBankStatus(
+ ws,
+ withdrawalGroupId,
+ cancellationToken,
+ );
case WithdrawalGroupStatus.PendingAml:
// FIXME: Handle this case, withdrawal doesn't support AML yet.
return TaskRunResult.backoff();
@@ -2233,6 +2237,7 @@ async function processBankRegisterReserve(
async function processReserveBankStatus(
ws: InternalWalletState,
withdrawalGroupId: string,
+ cancellationToken: CancellationToken,
): Promise<TaskRunResult> {
const withdrawalGroup = await getWithdrawalGroupRecordTx(ws.db, {
withdrawalGroupId,
@@ -2258,15 +2263,16 @@ async function processReserveBankStatus(
if (!uriResult) {
throw Error(`can't parse withdrawal URL ${bankInfo.talerWithdrawUri}`);
}
- const url = new URL(
+ const bankStatusUrl = new URL(
`withdrawal-operation/${uriResult.withdrawalOperationId}`,
uriResult.bankIntegrationApiBaseUrl,
);
- url.searchParams.set("long_poll_ms", "30000");
+ bankStatusUrl.searchParams.set("long_poll_ms", "30000");
- logger.info(`long-polling for withdrawal operation at ${url.href}`);
- const statusResp = await ws.http.fetch(url.href, {
+ logger.info(`long-polling for withdrawal operation at ${bankStatusUrl.href}`);
+ const statusResp = await ws.http.fetch(bankStatusUrl.href, {
timeout: getReserveRequestTimeout(withdrawalGroup),
+ cancellationToken,
});
logger.info(
`long-polling for withdrawal operation returned status ${statusResp.status}`,