diff options
author | Özgür Kesim <oec-taler@kesim.org> | 2023-10-17 12:04:44 +0200 |
---|---|---|
committer | Özgür Kesim <oec-taler@kesim.org> | 2023-10-17 12:04:44 +0200 |
commit | fba664f9a3c35dfeb5bc5ac28f0baea09ff9b8a0 (patch) | |
tree | 6d069afdecade1b13914f4d13020d0331c2f4036 /packages/taler-wallet-core/src | |
parent | def5ecda6fc4015417779af0a829d3f8aad4dd83 (diff) | |
parent | aca3bc9423f15354913d0114cafbd4bd1782d801 (diff) |
Merge branch 'master' into age-withdrawHEADage-withdraw
Diffstat (limited to 'packages/taler-wallet-core/src')
-rw-r--r-- | packages/taler-wallet-core/src/dbless.ts | 25 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/pending.ts | 9 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/reward.ts | 6 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/testing.ts | 74 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/transactions.ts | 11 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/withdraw.ts | 4 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/versions.ts | 15 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet-api-types.ts | 19 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 27 |
9 files changed, 139 insertions, 51 deletions
diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts index 4fc890788..b6b80009f 100644 --- a/packages/taler-wallet-core/src/dbless.ts +++ b/packages/taler-wallet-core/src/dbless.ts @@ -49,6 +49,9 @@ import { Logger, parsePaytoUri, UnblindedSignature, + ExchangeBatchWithdrawRequest, + ExchangeWithdrawBatchResponse, + codecForExchangeWithdrawBatchResponse, } from "@gnu-taler/taler-util"; import { HttpRequestLibrary, @@ -165,25 +168,29 @@ export async function withdrawCoin(args: { value: Amounts.parseOrThrow(denom.value), }); - const reqBody: ExchangeWithdrawRequest = { - denom_pub_hash: planchet.denomPubHash, - reserve_sig: planchet.withdrawSig, - coin_ev: planchet.coinEv, + const reqBody: ExchangeBatchWithdrawRequest = { + planchets: [ + { + denom_pub_hash: planchet.denomPubHash, + reserve_sig: planchet.withdrawSig, + coin_ev: planchet.coinEv, + }, + ], }; const reqUrl = new URL( - `reserves/${planchet.reservePub}/withdraw`, + `reserves/${planchet.reservePub}/batch-withdraw`, exchangeBaseUrl, ).href; - const resp = await http.postJson(reqUrl, reqBody); - const r = await readSuccessResponseJsonOrThrow( + const resp = await http.fetch(reqUrl, { method: "POST", body: reqBody }); + const rBatch = await readSuccessResponseJsonOrThrow( resp, - codecForWithdrawResponse(), + codecForExchangeWithdrawBatchResponse(), ); const ubSig = await cryptoApi.unblindDenominationSignature({ planchet, - evSig: r.ev_sig, + evSig: rBatch.ev_sigs[0].ev_sig, }); return { diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts index 1819aa1b8..7590280bc 100644 --- a/packages/taler-wallet-core/src/operations/pending.ts +++ b/packages/taler-wallet-core/src/operations/pending.ts @@ -101,14 +101,14 @@ async function gatherExchangePending( case ExchangeEntryDbUpdateStatus.Failed: return; } - const opTag = TaskIdentifiers.forExchangeUpdate(exch); - let opr = await tx.operationRetries.get(opTag); + const opUpdateExchangeTag = TaskIdentifiers.forExchangeUpdate(exch); + let opr = await tx.operationRetries.get(opUpdateExchangeTag); const timestampDue = opr?.retryInfo.nextRetry ?? exch.nextRefreshCheckStamp; resp.pendingOperations.push({ type: PendingTaskType.ExchangeUpdate, ...getPendingCommon( ws, - opTag, + opUpdateExchangeTag, AbsoluteTime.fromPreciseTimestamp(timestampPreciseFromDb(timestampDue)), ), givesLifeness: false, @@ -119,11 +119,12 @@ async function gatherExchangePending( // We only schedule a check for auto-refresh if the exchange update // was successful. if (!opr?.lastError) { + const opCheckRefreshTag = TaskIdentifiers.forExchangeCheckRefresh(exch); resp.pendingOperations.push({ type: PendingTaskType.ExchangeCheckRefresh, ...getPendingCommon( ws, - opTag, + opCheckRefreshTag, AbsoluteTime.fromPreciseTimestamp( timestampPreciseFromDb(timestampDue), ), diff --git a/packages/taler-wallet-core/src/operations/reward.ts b/packages/taler-wallet-core/src/operations/reward.ts index 4e16d977d..ed9927bab 100644 --- a/packages/taler-wallet-core/src/operations/reward.ts +++ b/packages/taler-wallet-core/src/operations/reward.ts @@ -23,7 +23,7 @@ import { Amounts, BlindedDenominationSignature, codecForMerchantTipResponseV2, - codecForTipPickupGetResponse, + codecForRewardPickupGetResponse, CoinStatus, DenomKeyType, encodeCrock, @@ -168,11 +168,11 @@ export async function prepareTip( const merchantResp = await ws.http.fetch(tipStatusUrl.href); const tipPickupStatus = await readSuccessResponseJsonOrThrow( merchantResp, - codecForTipPickupGetResponse(), + codecForRewardPickupGetResponse(), ); logger.trace(`status ${j2s(tipPickupStatus)}`); - const amount = Amounts.parseOrThrow(tipPickupStatus.tip_amount); + const amount = Amounts.parseOrThrow(tipPickupStatus.reward_amount); logger.trace("new tip, creating tip record"); await updateExchangeFromUrl(ws, tipPickupStatus.exchange_url); diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts index 607d03470..f5bed13dd 100644 --- a/packages/taler-wallet-core/src/operations/testing.ts +++ b/packages/taler-wallet-core/src/operations/testing.ts @@ -74,6 +74,7 @@ import { import { initiatePeerPushDebit } from "./pay-peer-push-debit.js"; import { OpenedPromise, openPromise } from "../index.js"; import { getTransactionById, getTransactions } from "./transactions.js"; +import { getPendingOperations } from "./pending.js"; const logger = new Logger("operations/testing.ts"); @@ -290,7 +291,7 @@ export async function runIntegrationTest( corebankApiBaseUrl: args.corebankApiBaseUrl, exchangeBaseUrl: args.exchangeBaseUrl, }); - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.info("done withdrawing test balance"); const balance = await getBalances(ws); @@ -305,7 +306,7 @@ export async function runIntegrationTest( await makePayment(ws, myMerchant, args.amountToSpend, "hello world"); // Wait until the refresh is done - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.trace("withdrawing test balance for refund"); const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`); @@ -320,7 +321,7 @@ export async function runIntegrationTest( }); // Wait until the withdraw is done - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); const { orderId: refundOrderId } = await makePayment( ws, @@ -344,7 +345,7 @@ export async function runIntegrationTest( logger.trace("integration test: applied refund"); // Wait until the refund is done - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.trace("integration test: making payment after refund"); @@ -357,12 +358,17 @@ export async function runIntegrationTest( logger.trace("integration test: make payment done"); - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.trace("integration test: all done!"); } -export async function waitUntilDone(ws: InternalWalletState): Promise<void> { +/** + * Wait until all transactions are in a final state. + */ +export async function waitUntilTransactionsFinal( + ws: InternalWalletState, +): Promise<void> { logger.info("waiting until all transactions are in a final state"); ws.ensureTaskLoopRunning(); let p: OpenedPromise<void> | undefined = undefined; @@ -410,6 +416,44 @@ export async function waitUntilDone(ws: InternalWalletState): Promise<void> { logger.info("done waiting until all transactions are in a final state"); } +/** + * Wait until pending work is processed. + */ +export async function waitUntilTasksProcessed( + ws: InternalWalletState, +): Promise<void> { + logger.info("waiting until pending work is processed"); + ws.ensureTaskLoopRunning(); + let p: OpenedPromise<void> | undefined = undefined; + const cancelNotifs = ws.addNotificationListener((notif) => { + if (!p) { + return; + } + if (notif.type === NotificationType.PendingOperationProcessed) { + p.resolve(); + } + }); + while (1) { + p = openPromise(); + const pendingTasksResp = await getPendingOperations(ws); + logger.info(`waiting on pending ops: ${j2s(pendingTasksResp)}`); + let finished = true; + for (const task of pendingTasksResp.pendingOperations) { + if (task.isDue) { + finished = false; + } + logger.info(`continuing waiting for task ${task.id}`); + } + if (finished) { + break; + } + // Wait until task is done + await p.promise; + } + logger.info("done waiting until pending work is processed"); + cancelNotifs(); +} + export async function waitUntilRefreshesDone( ws: InternalWalletState, ): Promise<void> { @@ -463,7 +507,7 @@ export async function waitUntilRefreshesDone( logger.info("done waiting until all refreshes are in a final state"); } -async function waitUntilPendingReady( +async function waitUntilTransactionPendingReady( ws: InternalWalletState, transactionId: string, ): Promise<void> { @@ -560,7 +604,7 @@ export async function runIntegrationTest2( corebankApiBaseUrl: args.corebankApiBaseUrl, exchangeBaseUrl: args.exchangeBaseUrl, }); - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.info("done withdrawing test balance"); const balance = await getBalances(ws); @@ -580,7 +624,7 @@ export async function runIntegrationTest2( ); // Wait until the refresh is done - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.trace("withdrawing test balance for refund"); const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`); @@ -595,7 +639,7 @@ export async function runIntegrationTest2( }); // Wait until the withdraw is done - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); const { orderId: refundOrderId } = await makePayment( ws, @@ -619,7 +663,7 @@ export async function runIntegrationTest2( logger.trace("integration test: applied refund"); // Wait until the refund is done - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.trace("integration test: making payment after refund"); @@ -632,7 +676,7 @@ export async function runIntegrationTest2( logger.trace("integration test: make payment done"); - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); const peerPushInit = await initiatePeerPushDebit(ws, { partialContractTerms: { @@ -647,7 +691,7 @@ export async function runIntegrationTest2( }, }); - await waitUntilPendingReady(ws, peerPushInit.transactionId); + await waitUntilTransactionPendingReady(ws, peerPushInit.transactionId); const peerPushCredit = await preparePeerPushCredit(ws, { talerUri: peerPushInit.talerUri, @@ -670,7 +714,7 @@ export async function runIntegrationTest2( }, }); - await waitUntilPendingReady(ws, peerPullInit.transactionId); + await waitUntilTransactionPendingReady(ws, peerPullInit.transactionId); const peerPullInc = await preparePeerPullDebit(ws, { talerUri: peerPullInit.talerUri, @@ -680,7 +724,7 @@ export async function runIntegrationTest2( peerPullDebitId: peerPullInc.peerPullDebitId, }); - await waitUntilDone(ws); + await waitUntilTransactionsFinal(ws); logger.trace("integration test: all done!"); } diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 72c67b153..bebb3d60b 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -1290,9 +1290,16 @@ export async function getTransactions( const txPending = transactions.filter((x) => isPending(x)); const txNotPending = transactions.filter((x) => !isPending(x)); + let sortSign: number; + if (transactionsRequest?.sort == "descending") { + sortSign = -1; + } else { + sortSign = 1; + } + const txCmp = (h1: Transaction, h2: Transaction) => { // Order transactions by timestamp. Newest transactions come first. - const tsCmp = -AbsoluteTime.cmp( + const tsCmp = AbsoluteTime.cmp( AbsoluteTime.fromPreciseTimestamp(h1.timestamp), AbsoluteTime.fromPreciseTimestamp(h2.timestamp), ); @@ -1300,7 +1307,7 @@ export async function getTransactions( if (tsCmp === 0) { return Math.sign(txOrder[h1.type] - txOrder[h2.type]); } - return tsCmp; + return sortSign * tsCmp; }; txPending.sort(txCmp); diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index eff427bec..245eec4fa 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -33,7 +33,7 @@ import { codecForReserveStatus, codecForTalerConfigResponse, codecForWalletKycUuid, - codecForWithdrawBatchResponse, + codecForExchangeWithdrawBatchResponse, codecForWithdrawOperationStatusResponse, codecForWithdrawResponse, CoinStatus, @@ -944,7 +944,7 @@ async function processPlanchetExchangeBatchRequest( } const r = await readSuccessResponseJsonOrThrow( resp, - codecForWithdrawBatchResponse(), + codecForExchangeWithdrawBatchResponse(), ); return { coinIdxs: requestCoinIdxs, diff --git a/packages/taler-wallet-core/src/versions.ts b/packages/taler-wallet-core/src/versions.ts index e46c7ebe1..8e0e5561b 100644 --- a/packages/taler-wallet-core/src/versions.ts +++ b/packages/taler-wallet-core/src/versions.ts @@ -40,4 +40,17 @@ export const WALLET_BANK_INTEGRATION_PROTOCOL_VERSION = "0:0:0"; * Will be replaced with the value from package.json in a * post-compilation step (inside lib/). */ -export const WALLET_CORE_IMPLEMENTATION_VERSION = "0:0:0"; +export const WALLET_CORE_IMPLEMENTATION_VERSION = "1:0:0"; + +/** + * Libtool rules: + * + * If the library source code has changed at all since the last update, + * then increment revision (‘c:r:a’ becomes ‘c:r+1:a’). + * If any interfaces have been added, removed, or changed since the last + * update, increment current, and set revision to 0. + * If any interfaces have been added since the last public release, then + * increment age. + * If any interfaces have been removed or changed since the last public + * release, then set age to 0. + */
\ No newline at end of file diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index fadc7aa7f..a8de9ac03 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -224,6 +224,7 @@ export enum WalletApiOperation { DeleteStoredBackup = "deleteStoredBackup", RecoverStoredBackup = "recoverStoredBackup", UpdateExchangeEntry = "updateExchangeEntry", + TestingWaitTasksProcessed = "testingWaitTasksProcessed", } // group: Initialization @@ -1007,7 +1008,7 @@ export type TestingSetTimetravelOp = { /** * Wait until all transactions are in a final state. */ -export type TestingWaitTransactionsFinal = { +export type TestingWaitTransactionsFinalOp = { op: WalletApiOperation.TestingWaitTransactionsFinal; request: EmptyObject; response: EmptyObject; @@ -1016,13 +1017,22 @@ export type TestingWaitTransactionsFinal = { /** * Wait until all refresh transactions are in a final state. */ -export type TestingWaitRefreshesFinal = { +export type TestingWaitRefreshesFinalOp = { op: WalletApiOperation.TestingWaitRefreshesFinal; request: EmptyObject; response: EmptyObject; }; /** + * Wait until all tasks have been processed and the wallet is idle. + */ +export type TestingWaitTasksProcessedOp = { + op: WalletApiOperation.TestingWaitTasksProcessed; + request: EmptyObject; + response: EmptyObject; +}; + +/** * Wait until a transaction is in a particular state. */ export type TestingWaitTransactionStateOp = { @@ -1132,8 +1142,9 @@ export type WalletOperations = { [WalletApiOperation.Recycle]: RecycleOp; [WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp; [WalletApiOperation.ValidateIban]: ValidateIbanOp; - [WalletApiOperation.TestingWaitTransactionsFinal]: TestingWaitTransactionsFinal; - [WalletApiOperation.TestingWaitRefreshesFinal]: TestingWaitRefreshesFinal; + [WalletApiOperation.TestingWaitTransactionsFinal]: TestingWaitTransactionsFinalOp; + [WalletApiOperation.TestingWaitRefreshesFinal]: TestingWaitRefreshesFinalOp; + [WalletApiOperation.TestingWaitTasksProcessed]: TestingWaitTasksProcessedOp; [WalletApiOperation.TestingSetTimetravel]: TestingSetTimetravelOp; [WalletApiOperation.TestingWaitTransactionState]: TestingWaitTransactionStateOp; [WalletApiOperation.GetCurrencySpecification]: GetCurrencySpecificationOp; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 571bf07ee..06d9bb9e8 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -252,9 +252,10 @@ import { runIntegrationTest2, testPay, waitTransactionState, - waitUntilDone, + waitUntilTransactionsFinal, waitUntilRefreshesDone, withdrawTestBalance, + waitUntilTasksProcessed, } from "./operations/testing.js"; import { acceptTip, @@ -1427,6 +1428,10 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( await waitTransactionState(ws, req.transactionId, req.txState); return {}; } + case WalletApiOperation.TestingWaitTasksProcessed: { + await waitUntilTasksProcessed(ws); + return {}; + } case WalletApiOperation.GetCurrencySpecification: { // Ignore result, just validate in this mock implementation const req = codecForGetCurrencyInfoRequest().decode(payload); @@ -1436,9 +1441,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( currencySpecification: { decimal_separator: ",", name: "Kudos (Taler Demonstrator)", - fractional_input_digits: 2, - fractional_normal_digits: 2, - fractional_trailing_zero_digits: 2, + num_fractional_input_digits: 2, + num_fractional_normal_digits: 2, + num_fractional_trailing_zero_digits: 2, is_currency_name_leading: true, alt_unit_names: { "0": "ク", @@ -1451,9 +1456,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( currencySpecification: { decimal_separator: ",", name: "Test (Taler Unstable Demonstrator)", - fractional_input_digits: 0, - fractional_normal_digits: 0, - fractional_trailing_zero_digits: 0, + num_fractional_input_digits: 0, + num_fractional_normal_digits: 0, + num_fractional_trailing_zero_digits: 0, is_currency_name_leading: false, alt_unit_names: {}, }, @@ -1464,9 +1469,9 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( currencySpecification: { decimal_separator: ",", name: "Unknown", - fractional_input_digits: 2, - fractional_normal_digits: 2, - fractional_trailing_zero_digits: 2, + num_fractional_input_digits: 2, + num_fractional_normal_digits: 2, + num_fractional_trailing_zero_digits: 2, is_currency_name_leading: true, alt_unit_names: {}, }, @@ -1600,7 +1605,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>( return getVersion(ws); } case WalletApiOperation.TestingWaitTransactionsFinal: - return await waitUntilDone(ws); + return await waitUntilTransactionsFinal(ws); case WalletApiOperation.TestingWaitRefreshesFinal: return await waitUntilRefreshesDone(ws); case WalletApiOperation.TestingSetTimetravel: { |