summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/tip.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/tip.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/tip.ts108
1 files changed, 106 insertions, 2 deletions
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts
index 524970faa..70b595c2f 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -48,6 +48,7 @@ import {
CoinSourceType,
DenominationRecord,
TipRecord,
+ TipRecordStatus,
} from "../db.js";
import { makeErrorDetail } from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
@@ -57,6 +58,7 @@ import {
} from "@gnu-taler/taler-util/http";
import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js";
import {
+ constructTaskIdentifier,
OperationAttemptResult,
OperationAttemptResultType,
} from "../util/retries.js";
@@ -68,7 +70,13 @@ import {
updateWithdrawalDenoms,
} from "./withdraw.js";
import { selectWithdrawalDenominations } from "../util/coinSelection.js";
-import { constructTransactionIdentifier } from "./transactions.js";
+import {
+ constructTransactionIdentifier,
+ notifyTransition,
+ stopLongpolling,
+} from "./transactions.js";
+import { PendingTaskType } from "../pending-types.js";
+import { assertUnreachable } from "../util/assertUnreachable.js";
const logger = new Logger("operations/tip.ts");
@@ -156,6 +164,7 @@ export async function prepareTip(
const newTipRecord: TipRecord = {
walletTipId: walletTipId,
acceptedTimestamp: undefined,
+ status: TipRecordStatus.PendingPickup,
tipAmountRaw: Amounts.stringify(amount),
tipExpiration: tipPickupStatus.expiration,
exchangeBaseUrl: tipPickupStatus.exchange_url,
@@ -180,7 +189,7 @@ export async function prepareTip(
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Tip,
walletTipId: tipRecord.walletTipId,
- })
+ });
const tipStatus: PrepareTipResult = {
accepted: !!tipRecord && !!tipRecord.acceptedTimestamp,
@@ -410,3 +419,98 @@ export async function acceptTip(
next_url: found?.next_url,
};
}
+
+export async function suspendTipTransaction(
+ ws: InternalWalletState,
+ walletTipId: string,
+): Promise<void> {
+ const taskId = constructTaskIdentifier({
+ tag: PendingTaskType.TipPickup,
+ walletTipId,
+ });
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.Tip,
+ walletTipId,
+ });
+ stopLongpolling(ws, taskId);
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.tips])
+ .runReadWrite(async (tx) => {
+ const tipRec = await tx.tips.get(walletTipId);
+ if (!tipRec) {
+ logger.warn(`transaction tip ${walletTipId} not found`);
+ return;
+ }
+ let newStatus: TipRecordStatus | undefined = undefined;
+ switch (tipRec.status) {
+ case TipRecordStatus.Done:
+ case TipRecordStatus.SuspendidPickup:
+ break;
+ case TipRecordStatus.PendingPickup:
+ newStatus = TipRecordStatus.SuspendidPickup;
+ break;
+ default:
+ assertUnreachable(tipRec.status);
+ }
+ if (newStatus != null) {
+ const oldTxState = computeTipTransactionStatus(tipRec);
+ tipRec.status = newStatus;
+ const newTxState = computeTipTransactionStatus(tipRec);
+ await tx.tips.put(tipRec);
+ return {
+ oldTxState,
+ newTxState,
+ };
+ }
+ return undefined;
+ });
+ ws.workAvailable.trigger();
+ notifyTransition(ws, transactionId, transitionInfo);
+}
+
+export async function resumeTipTransaction(
+ ws: InternalWalletState,
+ walletTipId: string,
+): Promise<void> {
+ const taskId = constructTaskIdentifier({
+ tag: PendingTaskType.TipPickup,
+ walletTipId,
+ });
+ const transactionId = constructTransactionIdentifier({
+ tag: TransactionType.Tip,
+ walletTipId,
+ });
+ stopLongpolling(ws, taskId);
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.tips])
+ .runReadWrite(async (tx) => {
+ const tipRec = await tx.tips.get(walletTipId);
+ if (!tipRec) {
+ logger.warn(`transaction tip ${walletTipId} not found`);
+ return;
+ }
+ let newStatus: TipRecordStatus | undefined = undefined;
+ switch (tipRec.status) {
+ case TipRecordStatus.Done:
+ case TipRecordStatus.SuspendidPickup:
+ newStatus = TipRecordStatus.PendingPickup;
+ break;
+ case TipRecordStatus.PendingPickup:
+ break;
+ default:
+ assertUnreachable(tipRec.status);
+ }
+ if (newStatus != null) {
+ const oldTxState = computeTipTransactionStatus(tipRec);
+ tipRec.status = newStatus;
+ const newTxState = computeTipTransactionStatus(tipRec);
+ await tx.tips.put(tipRec);
+ return {
+ oldTxState,
+ newTxState,
+ };
+ }
+ return undefined;
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+}