diff options
Diffstat (limited to 'packages/taler-wallet-core/src/deposits.ts')
-rw-r--r-- | packages/taler-wallet-core/src/deposits.ts | 135 |
1 files changed, 84 insertions, 51 deletions
diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts index 2004c12cb..36ebf3974 100644 --- a/packages/taler-wallet-core/src/deposits.ts +++ b/packages/taler-wallet-core/src/deposits.ts @@ -72,7 +72,7 @@ import { stringToBytes, } from "@gnu-taler/taler-util"; import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; -import { selectPayCoins } from "./coinSelection.js"; +import { selectPayCoins, selectPayCoinsInTx } from "./coinSelection.js"; import { PendingTaskType, TaskIdStr, @@ -518,12 +518,13 @@ async function refundDepositGroup( const res = await wex.db.runReadWriteTx( { storeNames: [ + "coinAvailability", + "coinHistory", + "coins", + "denominations", "depositGroups", "refreshGroups", "refreshSessions", - "coins", - "denominations", - "coinAvailability", ], }, async (tx) => { @@ -668,12 +669,20 @@ async function processDepositGroupPendingKyc( `kyc-check/${kycInfo.requirementRow}/${kycInfo.paytoHash}/${userType}`, kycInfo.exchangeBaseUrl, ); - url.searchParams.set("timeout_ms", "10000"); - logger.info(`kyc url ${url.href}`); - const kycStatusRes = await wex.http.fetch(url.href, { - method: "GET", - cancellationToken: wex.cancellationToken, - }); + + const kycStatusRes = await wex.ws.runLongpollQueueing( + wex, + url.hostname, + async (timeoutMs) => { + url.searchParams.set("timeout_ms", `${timeoutMs}`); + logger.info(`kyc url ${url.href}`); + return await wex.http.fetch(url.href, { + method: "GET", + cancellationToken: wex.cancellationToken, + }); + }, + ); + if ( kycStatusRes.status === HttpStatusCode.Ok || //FIXME: NoContent is not expected https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge @@ -979,43 +988,17 @@ async function processDepositGroupPendingDeposit( if (!depositGroup.payCoinSelection) { logger.info("missing coin selection for deposit group, selecting now"); - // FIXME: Consider doing the coin selection inside the txn - const payCoinSel = await selectPayCoins(wex, { - restrictExchanges: { - auditors: [], - exchanges: contractData.allowedExchanges, - }, - restrictWireMethod: contractData.wireMethod, - contractTermsAmount: Amounts.parseOrThrow(contractData.amount), - depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee), - prevPayCoins: [], - }); - - switch (payCoinSel.type) { - case "success": - logger.info("coin selection success"); - break; - case "failure": - logger.info("coin selection failure"); - throw TalerError.fromDetail( - TalerErrorCode.WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE, - { - insufficientBalanceDetails: payCoinSel.insufficientBalanceDetails, - }, - ); - case "prospective": - logger.info("coin selection prospective"); - throw Error("insufficient balance (waiting on pending refresh)"); - default: - assertUnreachable(payCoinSel); - } const transitionDone = await wex.db.runReadWriteTx( { storeNames: [ + "contractTerms", + "exchanges", + "exchangeDetails", "depositGroups", "coins", "coinAvailability", + "coinHistory", "refreshGroups", "refreshSessions", "denominations", @@ -1029,6 +1012,45 @@ async function processDepositGroupPendingDeposit( if (dg.statusPerCoin) { return false; } + + const contractTermsRec = tx.contractTerms.get( + depositGroup.contractTermsHash, + ); + if (!contractTermsRec) { + throw Error("contract terms for deposit not found in database"); + } + + const payCoinSel = await selectPayCoinsInTx(wex, tx, { + restrictExchanges: { + auditors: [], + exchanges: contractData.allowedExchanges, + }, + restrictWireMethod: contractData.wireMethod, + contractTermsAmount: Amounts.parseOrThrow(contractData.amount), + depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee), + prevPayCoins: [], + }); + + switch (payCoinSel.type) { + case "success": + logger.info("coin selection success"); + break; + case "failure": + logger.info("coin selection failure"); + throw TalerError.fromDetail( + TalerErrorCode.WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE, + { + insufficientBalanceDetails: + payCoinSel.insufficientBalanceDetails, + }, + ); + case "prospective": + logger.info("coin selection prospective"); + throw Error("insufficient balance (waiting on pending refresh)"); + default: + assertUnreachable(payCoinSel); + } + dg.payCoinSelection = { coinContributions: payCoinSel.coinSel.coins.map( (x) => x.contribution, @@ -1041,7 +1063,7 @@ async function processDepositGroupPendingDeposit( ); await tx.depositGroups.put(dg); await spendCoins(wex, tx, { - allocationId: transactionId, + transactionId, coinPubs: dg.payCoinSelection.coinPubs, contributions: dg.payCoinSelection.coinContributions.map((x) => Amounts.parseOrThrow(x), @@ -1168,6 +1190,10 @@ export async function processDepositGroup( wex: WalletExecutionContext, depositGroupId: string, ): Promise<TaskRunResult> { + if (!wex.ws.networkAvailable) { + return TaskRunResult.networkRequired(); + } + const depositGroup = await wex.db.runReadOnlyTx( { storeNames: ["depositGroups"] }, async (tx) => { @@ -1264,11 +1290,17 @@ async function trackDeposit( wireHash, }); url.searchParams.set("merchant_sig", sigResp.sig); - url.searchParams.set("timeout_ms", "30000"); - const httpResp = await wex.http.fetch(url.href, { - method: "GET", - cancellationToken: wex.cancellationToken, - }); + const httpResp = await wex.ws.runLongpollQueueing( + wex, + url.hostname, + async (timeoutMs) => { + url.searchParams.set("timeout_ms", `${timeoutMs}`); + return await wex.http.fetch(url.href, { + method: "GET", + cancellationToken: wex.cancellationToken, + }); + }, + ); logger.trace(`deposits response status: ${httpResp.status}`); switch (httpResp.status) { case HttpStatusCode.Accepted: { @@ -1606,20 +1638,21 @@ export async function createDepositGroup( const newTxState = await wex.db.runReadWriteTx( { storeNames: [ - "depositGroups", + "coinAvailability", + "coinHistory", "coins", - "recoupGroups", + "contractTerms", "denominations", + "depositGroups", + "recoupGroups", "refreshGroups", "refreshSessions", - "coinAvailability", - "contractTerms", ], }, async (tx) => { if (depositGroup.payCoinSelection) { await spendCoins(wex, tx, { - allocationId: transactionId, + transactionId, coinPubs: depositGroup.payCoinSelection.coinPubs, contributions: depositGroup.payCoinSelection.coinContributions.map( (x) => Amounts.parseOrThrow(x), |