aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src
diff options
context:
space:
mode:
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
commitfba664f9a3c35dfeb5bc5ac28f0baea09ff9b8a0 (patch)
tree6d069afdecade1b13914f4d13020d0331c2f4036 /packages/taler-wallet-core/src
parentdef5ecda6fc4015417779af0a829d3f8aad4dd83 (diff)
parentaca3bc9423f15354913d0114cafbd4bd1782d801 (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.ts25
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts9
-rw-r--r--packages/taler-wallet-core/src/operations/reward.ts6
-rw-r--r--packages/taler-wallet-core/src/operations/testing.ts74
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts11
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts4
-rw-r--r--packages/taler-wallet-core/src/versions.ts15
-rw-r--r--packages/taler-wallet-core/src/wallet-api-types.ts19
-rw-r--r--packages/taler-wallet-core/src/wallet.ts27
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: {