summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts523
1 files changed, 271 insertions, 252 deletions
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
index a90eceed7..e655eba4b 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
@@ -69,6 +69,8 @@ import {
LongpollResult,
TaskRunResult,
TaskRunResultType,
+ TombstoneTag,
+ TransactionContext,
constructTaskIdentifier,
runLongpollAsync,
} from "./common.js";
@@ -88,6 +90,275 @@ import {
const logger = new Logger("pay-peer-pull-credit.ts");
+export class PeerPullCreditTransactionContext implements TransactionContext {
+ private transactionId: string;
+ private retryTag: string;
+
+ constructor(
+ public ws: InternalWalletState,
+ public pursePub: string,
+ ) {
+ this.retryTag = constructTaskIdentifier({
+ tag: PendingTaskType.PeerPullCredit,
+ pursePub,
+ });
+ this.transactionId = constructTransactionIdentifier({
+ tag: TransactionType.PeerPullCredit,
+ pursePub,
+ });
+ }
+
+ async deleteTransaction(): Promise<void> {
+ const { ws, pursePub } = this;
+ await ws.db
+ .mktx((x) => [x.withdrawalGroups, x.peerPullCredit, x.tombstones])
+ .runReadWrite(async (tx) => {
+ const pullIni = await tx.peerPullCredit.get(pursePub);
+ if (!pullIni) {
+ return;
+ }
+ if (pullIni.withdrawalGroupId) {
+ const withdrawalGroupId = pullIni.withdrawalGroupId;
+ const withdrawalGroupRecord =
+ await tx.withdrawalGroups.get(withdrawalGroupId);
+ if (withdrawalGroupRecord) {
+ await tx.withdrawalGroups.delete(withdrawalGroupId);
+ await tx.tombstones.put({
+ id: TombstoneTag.DeleteWithdrawalGroup + ":" + withdrawalGroupId,
+ });
+ }
+ }
+ await tx.peerPullCredit.delete(pursePub);
+ await tx.tombstones.put({
+ id: TombstoneTag.DeletePeerPullCredit + ":" + pursePub,
+ });
+ });
+
+ return;
+ }
+
+ async suspendTransaction(): Promise<void> {
+ const { ws, pursePub, retryTag, transactionId } = this;
+ stopLongpolling(ws, retryTag);
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.peerPullCredit])
+ .runReadWrite(async (tx) => {
+ const pullCreditRec = await tx.peerPullCredit.get(pursePub);
+ if (!pullCreditRec) {
+ logger.warn(`peer pull credit ${pursePub} not found`);
+ return;
+ }
+ let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
+ switch (pullCreditRec.status) {
+ case PeerPullPaymentCreditStatus.PendingCreatePurse:
+ newStatus = PeerPullPaymentCreditStatus.SuspendedCreatePurse;
+ break;
+ case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
+ newStatus = PeerPullPaymentCreditStatus.SuspendedMergeKycRequired;
+ break;
+ case PeerPullPaymentCreditStatus.PendingWithdrawing:
+ newStatus = PeerPullPaymentCreditStatus.SuspendedWithdrawing;
+ break;
+ case PeerPullPaymentCreditStatus.PendingReady:
+ newStatus = PeerPullPaymentCreditStatus.SuspendedReady;
+ break;
+ case PeerPullPaymentCreditStatus.AbortingDeletePurse:
+ newStatus =
+ PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse;
+ break;
+ case PeerPullPaymentCreditStatus.Done:
+ case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
+ case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
+ case PeerPullPaymentCreditStatus.SuspendedReady:
+ case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
+ case PeerPullPaymentCreditStatus.Aborted:
+ case PeerPullPaymentCreditStatus.Failed:
+ case PeerPullPaymentCreditStatus.Expired:
+ case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
+ break;
+ default:
+ assertUnreachable(pullCreditRec.status);
+ }
+ if (newStatus != null) {
+ const oldTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ pullCreditRec.status = newStatus;
+ const newTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ await tx.peerPullCredit.put(pullCreditRec);
+ return {
+ oldTxState,
+ newTxState,
+ };
+ }
+ return undefined;
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+ }
+
+ async failTransaction(): Promise<void> {
+ const { ws, pursePub, retryTag, transactionId } = this;
+ stopLongpolling(ws, retryTag);
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.peerPullCredit])
+ .runReadWrite(async (tx) => {
+ const pullCreditRec = await tx.peerPullCredit.get(pursePub);
+ if (!pullCreditRec) {
+ logger.warn(`peer pull credit ${pursePub} not found`);
+ return;
+ }
+ let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
+ switch (pullCreditRec.status) {
+ case PeerPullPaymentCreditStatus.PendingCreatePurse:
+ case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
+ case PeerPullPaymentCreditStatus.PendingWithdrawing:
+ case PeerPullPaymentCreditStatus.PendingReady:
+ case PeerPullPaymentCreditStatus.Done:
+ case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
+ case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
+ case PeerPullPaymentCreditStatus.SuspendedReady:
+ case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
+ case PeerPullPaymentCreditStatus.Aborted:
+ case PeerPullPaymentCreditStatus.Failed:
+ case PeerPullPaymentCreditStatus.Expired:
+ break;
+ case PeerPullPaymentCreditStatus.AbortingDeletePurse:
+ case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
+ newStatus = PeerPullPaymentCreditStatus.Failed;
+ break;
+ default:
+ assertUnreachable(pullCreditRec.status);
+ }
+ if (newStatus != null) {
+ const oldTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ pullCreditRec.status = newStatus;
+ const newTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ await tx.peerPullCredit.put(pullCreditRec);
+ return {
+ oldTxState,
+ newTxState,
+ };
+ }
+ return undefined;
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+ }
+
+ async resumeTransaction(): Promise<void> {
+ const { ws, pursePub, retryTag, transactionId } = this;
+ stopLongpolling(ws, retryTag);
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.peerPullCredit])
+ .runReadWrite(async (tx) => {
+ const pullCreditRec = await tx.peerPullCredit.get(pursePub);
+ if (!pullCreditRec) {
+ logger.warn(`peer pull credit ${pursePub} not found`);
+ return;
+ }
+ let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
+ switch (pullCreditRec.status) {
+ case PeerPullPaymentCreditStatus.PendingCreatePurse:
+ case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
+ case PeerPullPaymentCreditStatus.PendingWithdrawing:
+ case PeerPullPaymentCreditStatus.PendingReady:
+ case PeerPullPaymentCreditStatus.AbortingDeletePurse:
+ case PeerPullPaymentCreditStatus.Done:
+ case PeerPullPaymentCreditStatus.Failed:
+ case PeerPullPaymentCreditStatus.Expired:
+ case PeerPullPaymentCreditStatus.Aborted:
+ break;
+ case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
+ newStatus = PeerPullPaymentCreditStatus.PendingCreatePurse;
+ break;
+ case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
+ newStatus = PeerPullPaymentCreditStatus.PendingMergeKycRequired;
+ break;
+ case PeerPullPaymentCreditStatus.SuspendedReady:
+ newStatus = PeerPullPaymentCreditStatus.PendingReady;
+ break;
+ case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
+ newStatus = PeerPullPaymentCreditStatus.PendingWithdrawing;
+ break;
+ case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
+ newStatus = PeerPullPaymentCreditStatus.AbortingDeletePurse;
+ break;
+ default:
+ assertUnreachable(pullCreditRec.status);
+ }
+ if (newStatus != null) {
+ const oldTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ pullCreditRec.status = newStatus;
+ const newTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ await tx.peerPullCredit.put(pullCreditRec);
+ return {
+ oldTxState,
+ newTxState,
+ };
+ }
+ return undefined;
+ });
+ ws.workAvailable.trigger();
+ notifyTransition(ws, transactionId, transitionInfo);
+ }
+
+ async abortTransaction(): Promise<void> {
+ const { ws, pursePub, retryTag, transactionId } = this;
+ stopLongpolling(ws, retryTag);
+ const transitionInfo = await ws.db
+ .mktx((x) => [x.peerPullCredit])
+ .runReadWrite(async (tx) => {
+ const pullCreditRec = await tx.peerPullCredit.get(pursePub);
+ if (!pullCreditRec) {
+ logger.warn(`peer pull credit ${pursePub} not found`);
+ return;
+ }
+ let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
+ switch (pullCreditRec.status) {
+ case PeerPullPaymentCreditStatus.PendingCreatePurse:
+ case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
+ newStatus = PeerPullPaymentCreditStatus.AbortingDeletePurse;
+ break;
+ case PeerPullPaymentCreditStatus.PendingWithdrawing:
+ throw Error("can't abort anymore");
+ case PeerPullPaymentCreditStatus.PendingReady:
+ newStatus = PeerPullPaymentCreditStatus.AbortingDeletePurse;
+ break;
+ case PeerPullPaymentCreditStatus.Done:
+ case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
+ case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
+ case PeerPullPaymentCreditStatus.SuspendedReady:
+ case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
+ case PeerPullPaymentCreditStatus.Aborted:
+ case PeerPullPaymentCreditStatus.AbortingDeletePurse:
+ case PeerPullPaymentCreditStatus.Failed:
+ case PeerPullPaymentCreditStatus.Expired:
+ case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
+ break;
+ default:
+ assertUnreachable(pullCreditRec.status);
+ }
+ if (newStatus != null) {
+ const oldTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ pullCreditRec.status = newStatus;
+ const newTxState =
+ computePeerPullCreditTransactionState(pullCreditRec);
+ await tx.peerPullCredit.put(pullCreditRec);
+ return {
+ oldTxState,
+ newTxState,
+ };
+ }
+ return undefined;
+ });
+ notifyTransition(ws, transactionId, transitionInfo);
+ }
+}
+
async function queryPurseForPeerPullCredit(
ws: InternalWalletState,
pullIni: PeerPullCreditRecord,
@@ -849,258 +1120,6 @@ export async function initiatePeerPullPayment(
};
}
-export async function suspendPeerPullCreditTransaction(
- ws: InternalWalletState,
- pursePub: string,
-) {
- const taskId = constructTaskIdentifier({
- tag: PendingTaskType.PeerPullCredit,
- pursePub,
- });
- const transactionId = constructTransactionIdentifier({
- tag: TransactionType.PeerPullCredit,
- pursePub,
- });
- stopLongpolling(ws, taskId);
- const transitionInfo = await ws.db
- .mktx((x) => [x.peerPullCredit])
- .runReadWrite(async (tx) => {
- const pullCreditRec = await tx.peerPullCredit.get(pursePub);
- if (!pullCreditRec) {
- logger.warn(`peer pull credit ${pursePub} not found`);
- return;
- }
- let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
- switch (pullCreditRec.status) {
- case PeerPullPaymentCreditStatus.PendingCreatePurse:
- newStatus = PeerPullPaymentCreditStatus.SuspendedCreatePurse;
- break;
- case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
- newStatus = PeerPullPaymentCreditStatus.SuspendedMergeKycRequired;
- break;
- case PeerPullPaymentCreditStatus.PendingWithdrawing:
- newStatus = PeerPullPaymentCreditStatus.SuspendedWithdrawing;
- break;
- case PeerPullPaymentCreditStatus.PendingReady:
- newStatus = PeerPullPaymentCreditStatus.SuspendedReady;
- break;
- case PeerPullPaymentCreditStatus.AbortingDeletePurse:
- newStatus = PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse;
- break;
- case PeerPullPaymentCreditStatus.Done:
- case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
- case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
- case PeerPullPaymentCreditStatus.SuspendedReady:
- case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
- case PeerPullPaymentCreditStatus.Aborted:
- case PeerPullPaymentCreditStatus.Failed:
- case PeerPullPaymentCreditStatus.Expired:
- case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
- break;
- default:
- assertUnreachable(pullCreditRec.status);
- }
- if (newStatus != null) {
- const oldTxState = computePeerPullCreditTransactionState(pullCreditRec);
- pullCreditRec.status = newStatus;
- const newTxState = computePeerPullCreditTransactionState(pullCreditRec);
- await tx.peerPullCredit.put(pullCreditRec);
- return {
- oldTxState,
- newTxState,
- };
- }
- return undefined;
- });
- notifyTransition(ws, transactionId, transitionInfo);
-}
-
-export async function abortPeerPullCreditTransaction(
- ws: InternalWalletState,
- pursePub: string,
-) {
- const taskId = constructTaskIdentifier({
- tag: PendingTaskType.PeerPullCredit,
- pursePub,
- });
- const transactionId = constructTransactionIdentifier({
- tag: TransactionType.PeerPullCredit,
- pursePub,
- });
- stopLongpolling(ws, taskId);
- const transitionInfo = await ws.db
- .mktx((x) => [x.peerPullCredit])
- .runReadWrite(async (tx) => {
- const pullCreditRec = await tx.peerPullCredit.get(pursePub);
- if (!pullCreditRec) {
- logger.warn(`peer pull credit ${pursePub} not found`);
- return;
- }
- let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
- switch (pullCreditRec.status) {
- case PeerPullPaymentCreditStatus.PendingCreatePurse:
- case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
- newStatus = PeerPullPaymentCreditStatus.AbortingDeletePurse;
- break;
- case PeerPullPaymentCreditStatus.PendingWithdrawing:
- throw Error("can't abort anymore");
- case PeerPullPaymentCreditStatus.PendingReady:
- newStatus = PeerPullPaymentCreditStatus.AbortingDeletePurse;
- break;
- case PeerPullPaymentCreditStatus.Done:
- case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
- case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
- case PeerPullPaymentCreditStatus.SuspendedReady:
- case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
- case PeerPullPaymentCreditStatus.Aborted:
- case PeerPullPaymentCreditStatus.AbortingDeletePurse:
- case PeerPullPaymentCreditStatus.Failed:
- case PeerPullPaymentCreditStatus.Expired:
- case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
- break;
- default:
- assertUnreachable(pullCreditRec.status);
- }
- if (newStatus != null) {
- const oldTxState = computePeerPullCreditTransactionState(pullCreditRec);
- pullCreditRec.status = newStatus;
- const newTxState = computePeerPullCreditTransactionState(pullCreditRec);
- await tx.peerPullCredit.put(pullCreditRec);
- return {
- oldTxState,
- newTxState,
- };
- }
- return undefined;
- });
- notifyTransition(ws, transactionId, transitionInfo);
-}
-
-export async function failPeerPullCreditTransaction(
- ws: InternalWalletState,
- pursePub: string,
-) {
- const taskId = constructTaskIdentifier({
- tag: PendingTaskType.PeerPullCredit,
- pursePub,
- });
- const transactionId = constructTransactionIdentifier({
- tag: TransactionType.PeerPullCredit,
- pursePub,
- });
- stopLongpolling(ws, taskId);
- const transitionInfo = await ws.db
- .mktx((x) => [x.peerPullCredit])
- .runReadWrite(async (tx) => {
- const pullCreditRec = await tx.peerPullCredit.get(pursePub);
- if (!pullCreditRec) {
- logger.warn(`peer pull credit ${pursePub} not found`);
- return;
- }
- let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
- switch (pullCreditRec.status) {
- case PeerPullPaymentCreditStatus.PendingCreatePurse:
- case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
- case PeerPullPaymentCreditStatus.PendingWithdrawing:
- case PeerPullPaymentCreditStatus.PendingReady:
- case PeerPullPaymentCreditStatus.Done:
- case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
- case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
- case PeerPullPaymentCreditStatus.SuspendedReady:
- case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
- case PeerPullPaymentCreditStatus.Aborted:
- case PeerPullPaymentCreditStatus.Failed:
- case PeerPullPaymentCreditStatus.Expired:
- break;
- case PeerPullPaymentCreditStatus.AbortingDeletePurse:
- case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
- newStatus = PeerPullPaymentCreditStatus.Failed;
- break;
- default:
- assertUnreachable(pullCreditRec.status);
- }
- if (newStatus != null) {
- const oldTxState = computePeerPullCreditTransactionState(pullCreditRec);
- pullCreditRec.status = newStatus;
- const newTxState = computePeerPullCreditTransactionState(pullCreditRec);
- await tx.peerPullCredit.put(pullCreditRec);
- return {
- oldTxState,
- newTxState,
- };
- }
- return undefined;
- });
- notifyTransition(ws, transactionId, transitionInfo);
-}
-
-export async function resumePeerPullCreditTransaction(
- ws: InternalWalletState,
- pursePub: string,
-) {
- const taskId = constructTaskIdentifier({
- tag: PendingTaskType.PeerPullCredit,
- pursePub,
- });
- const transactionId = constructTransactionIdentifier({
- tag: TransactionType.PeerPullCredit,
- pursePub,
- });
- stopLongpolling(ws, taskId);
- const transitionInfo = await ws.db
- .mktx((x) => [x.peerPullCredit])
- .runReadWrite(async (tx) => {
- const pullCreditRec = await tx.peerPullCredit.get(pursePub);
- if (!pullCreditRec) {
- logger.warn(`peer pull credit ${pursePub} not found`);
- return;
- }
- let newStatus: PeerPullPaymentCreditStatus | undefined = undefined;
- switch (pullCreditRec.status) {
- case PeerPullPaymentCreditStatus.PendingCreatePurse:
- case PeerPullPaymentCreditStatus.PendingMergeKycRequired:
- case PeerPullPaymentCreditStatus.PendingWithdrawing:
- case PeerPullPaymentCreditStatus.PendingReady:
- case PeerPullPaymentCreditStatus.AbortingDeletePurse:
- case PeerPullPaymentCreditStatus.Done:
- case PeerPullPaymentCreditStatus.Failed:
- case PeerPullPaymentCreditStatus.Expired:
- case PeerPullPaymentCreditStatus.Aborted:
- break;
- case PeerPullPaymentCreditStatus.SuspendedCreatePurse:
- newStatus = PeerPullPaymentCreditStatus.PendingCreatePurse;
- break;
- case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired:
- newStatus = PeerPullPaymentCreditStatus.PendingMergeKycRequired;
- break;
- case PeerPullPaymentCreditStatus.SuspendedReady:
- newStatus = PeerPullPaymentCreditStatus.PendingReady;
- break;
- case PeerPullPaymentCreditStatus.SuspendedWithdrawing:
- newStatus = PeerPullPaymentCreditStatus.PendingWithdrawing;
- break;
- case PeerPullPaymentCreditStatus.SuspendedAbortingDeletePurse:
- newStatus = PeerPullPaymentCreditStatus.AbortingDeletePurse;
- break;
- default:
- assertUnreachable(pullCreditRec.status);
- }
- if (newStatus != null) {
- const oldTxState = computePeerPullCreditTransactionState(pullCreditRec);
- pullCreditRec.status = newStatus;
- const newTxState = computePeerPullCreditTransactionState(pullCreditRec);
- await tx.peerPullCredit.put(pullCreditRec);
- return {
- oldTxState,
- newTxState,
- };
- }
- return undefined;
- });
- ws.workAvailable.trigger();
- notifyTransition(ws, transactionId, transitionInfo);
-}
-
export function computePeerPullCreditTransactionState(
pullCreditRecord: PeerPullCreditRecord,
): TransactionState {