finish implementation of abort / cancelAborting on all tx types
This commit is contained in:
parent
d1dade4426
commit
000359a5e7
@ -116,6 +116,7 @@ export enum TransactionMinorState {
|
|||||||
WithdrawCoins = "withdraw-coins",
|
WithdrawCoins = "withdraw-coins",
|
||||||
ExchangeWaitReserve = "exchange-wait-reserve",
|
ExchangeWaitReserve = "exchange-wait-reserve",
|
||||||
AbortingBank = "aborting-bank",
|
AbortingBank = "aborting-bank",
|
||||||
|
Aborting = "aborting",
|
||||||
Refused = "refused",
|
Refused = "refused",
|
||||||
Withdraw = "withdraw",
|
Withdraw = "withdraw",
|
||||||
MerchantOrderProposed = "merchant-order-proposed",
|
MerchantOrderProposed = "merchant-order-proposed",
|
||||||
|
@ -879,6 +879,7 @@ export enum TipRecordStatus {
|
|||||||
SuspendidPickup = 21,
|
SuspendidPickup = 21,
|
||||||
|
|
||||||
Done = 50,
|
Done = 50,
|
||||||
|
Aborted = 51,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RefreshCoinStatus {
|
export enum RefreshCoinStatus {
|
||||||
@ -899,9 +900,10 @@ export enum OperationStatus {
|
|||||||
|
|
||||||
export enum RefreshOperationStatus {
|
export enum RefreshOperationStatus {
|
||||||
Pending = 10 /* ACTIVE_START */,
|
Pending = 10 /* ACTIVE_START */,
|
||||||
|
Suspended = 20 /* DORMANT_START + 2 */,
|
||||||
|
|
||||||
Finished = 50 /* DORMANT_START */,
|
Finished = 50 /* DORMANT_START */,
|
||||||
FinishedWithError = 51 /* DORMANT_START + 1 */,
|
Failed = 51 /* DORMANT_START + 1 */,
|
||||||
Suspended = 52 /* DORMANT_START + 2 */,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DepositGroupOperationStatus {
|
export enum DepositGroupOperationStatus {
|
||||||
@ -1155,6 +1157,8 @@ export enum PurchaseStatus {
|
|||||||
* Payment was successful.
|
* Payment was successful.
|
||||||
*/
|
*/
|
||||||
Done = 54,
|
Done = 54,
|
||||||
|
|
||||||
|
FailedAbort = 55,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1778,6 +1782,7 @@ export enum PeerPushPaymentInitiationStatus {
|
|||||||
|
|
||||||
Done = 50 /* DORMANT_START */,
|
Done = 50 /* DORMANT_START */,
|
||||||
Aborted = 51,
|
Aborted = 51,
|
||||||
|
Failed = 52,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PeerPushPaymentCoinSelection {
|
export interface PeerPushPaymentCoinSelection {
|
||||||
@ -1850,13 +1855,17 @@ export enum PeerPullPaymentInitiationStatus {
|
|||||||
PendingReady = 11 /* ACTIVE_START + 1 */,
|
PendingReady = 11 /* ACTIVE_START + 1 */,
|
||||||
PendingMergeKycRequired = 12 /* ACTIVE_START + 2 */,
|
PendingMergeKycRequired = 12 /* ACTIVE_START + 2 */,
|
||||||
PendingWithdrawing = 13,
|
PendingWithdrawing = 13,
|
||||||
|
AbortingDeletePurse = 14,
|
||||||
|
|
||||||
SuspendedCreatePurse = 30,
|
SuspendedCreatePurse = 30,
|
||||||
SuspendedReady = 31,
|
SuspendedReady = 31,
|
||||||
SuspendedMergeKycRequired = 32,
|
SuspendedMergeKycRequired = 32,
|
||||||
SuspendedWithdrawing = 33,
|
SuspendedWithdrawing = 33,
|
||||||
|
SuspendedAbortingDeletePurse = 34,
|
||||||
|
|
||||||
DonePurseDeposited = 50 /* DORMANT_START */,
|
DonePurseDeposited = 50 /* DORMANT_START */,
|
||||||
|
Failed = 51,
|
||||||
|
Aborted = 52,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PeerPullPaymentInitiationRecord {
|
export interface PeerPullPaymentInitiationRecord {
|
||||||
@ -1927,6 +1936,8 @@ export enum PeerPushPaymentIncomingStatus {
|
|||||||
DialogProposed = 30 /* USER_ATTENTION_START */,
|
DialogProposed = 30 /* USER_ATTENTION_START */,
|
||||||
|
|
||||||
Done = 50 /* DORMANT_START */,
|
Done = 50 /* DORMANT_START */,
|
||||||
|
Aborted = 51,
|
||||||
|
Failed = 52,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1978,12 +1989,16 @@ export interface PeerPushPaymentIncomingRecord {
|
|||||||
|
|
||||||
export enum PeerPullDebitRecordStatus {
|
export enum PeerPullDebitRecordStatus {
|
||||||
PendingDeposit = 10 /* ACTIVE_START */,
|
PendingDeposit = 10 /* ACTIVE_START */,
|
||||||
|
AbortingRefresh = 11,
|
||||||
|
|
||||||
SuspendedDeposit = 11,
|
SuspendedDeposit = 20,
|
||||||
|
SuspendedAbortingRefresh = 21,
|
||||||
|
|
||||||
DialogProposed = 30 /* USER_ATTENTION_START */,
|
DialogProposed = 30 /* USER_ATTENTION_START */,
|
||||||
|
|
||||||
DonePaid = 50 /* DORMANT_START */,
|
DonePaid = 50 /* DORMANT_START */,
|
||||||
|
Aborted = 51,
|
||||||
|
Failed = 52,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PeerPullPaymentCoinSelection {
|
export interface PeerPullPaymentCoinSelection {
|
||||||
|
@ -447,7 +447,7 @@ async function waitForRefreshOnDepositGroup(
|
|||||||
newOpState = DepositOperationStatus.Aborted;
|
newOpState = DepositOperationStatus.Aborted;
|
||||||
} else if (
|
} else if (
|
||||||
refreshGroup.operationStatus ===
|
refreshGroup.operationStatus ===
|
||||||
RefreshOperationStatus.FinishedWithError
|
RefreshOperationStatus.Failed
|
||||||
) {
|
) {
|
||||||
newOpState = DepositOperationStatus.Aborted;
|
newOpState = DepositOperationStatus.Aborted;
|
||||||
}
|
}
|
||||||
|
@ -1508,6 +1508,7 @@ export async function processPurchase(
|
|||||||
case PurchaseStatus.SuspendedPendingAcceptRefund:
|
case PurchaseStatus.SuspendedPendingAcceptRefund:
|
||||||
case PurchaseStatus.SuspendedQueryingAutoRefund:
|
case PurchaseStatus.SuspendedQueryingAutoRefund:
|
||||||
case PurchaseStatus.SuspendedQueryingRefund:
|
case PurchaseStatus.SuspendedQueryingRefund:
|
||||||
|
case PurchaseStatus.FailedAbort:
|
||||||
return {
|
return {
|
||||||
type: OperationAttemptResultType.Finished,
|
type: OperationAttemptResultType.Finished,
|
||||||
result: undefined,
|
result: undefined,
|
||||||
@ -1790,10 +1791,55 @@ export async function abortPayMerchant(
|
|||||||
ws.workAvailable.trigger();
|
ws.workAvailable.trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function cancelAbortingPaymentTransaction(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
proposalId: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const transactionId = constructTransactionIdentifier({
|
||||||
|
tag: TransactionType.Payment,
|
||||||
|
proposalId,
|
||||||
|
});
|
||||||
|
const opId = constructTaskIdentifier({
|
||||||
|
tag: PendingTaskType.Purchase,
|
||||||
|
proposalId,
|
||||||
|
});
|
||||||
|
const transitionInfo = await ws.db
|
||||||
|
.mktx((x) => [
|
||||||
|
x.purchases,
|
||||||
|
x.refreshGroups,
|
||||||
|
x.denominations,
|
||||||
|
x.coinAvailability,
|
||||||
|
x.coins,
|
||||||
|
x.operationRetries,
|
||||||
|
])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const purchase = await tx.purchases.get(proposalId);
|
||||||
|
if (!purchase) {
|
||||||
|
throw Error("purchase not found");
|
||||||
|
}
|
||||||
|
const oldTxState = computePayMerchantTransactionState(purchase);
|
||||||
|
let newState: PurchaseStatus | undefined = undefined;
|
||||||
|
switch (purchase.purchaseStatus) {
|
||||||
|
case PurchaseStatus.AbortingWithRefund:
|
||||||
|
newState = PurchaseStatus.FailedAbort;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (newState) {
|
||||||
|
purchase.purchaseStatus = newState;
|
||||||
|
await tx.purchases.put(purchase);
|
||||||
|
}
|
||||||
|
const newTxState = computePayMerchantTransactionState(purchase);
|
||||||
|
return { oldTxState, newTxState };
|
||||||
|
});
|
||||||
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
|
ws.workAvailable.trigger();
|
||||||
|
}
|
||||||
|
|
||||||
const transitionSuspend: { [x in PurchaseStatus]?: {
|
const transitionSuspend: {
|
||||||
next: PurchaseStatus | undefined,
|
[x in PurchaseStatus]?: {
|
||||||
} } = {
|
next: PurchaseStatus | undefined;
|
||||||
|
};
|
||||||
|
} = {
|
||||||
[PurchaseStatus.PendingDownloadingProposal]: {
|
[PurchaseStatus.PendingDownloadingProposal]: {
|
||||||
next: PurchaseStatus.SuspendedDownloadingProposal,
|
next: PurchaseStatus.SuspendedDownloadingProposal,
|
||||||
},
|
},
|
||||||
@ -1808,12 +1854,14 @@ const transitionSuspend: { [x in PurchaseStatus]?: {
|
|||||||
},
|
},
|
||||||
[PurchaseStatus.PendingQueryingAutoRefund]: {
|
[PurchaseStatus.PendingQueryingAutoRefund]: {
|
||||||
next: PurchaseStatus.SuspendedQueryingAutoRefund,
|
next: PurchaseStatus.SuspendedQueryingAutoRefund,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
const transitionResume: { [x in PurchaseStatus]?: {
|
const transitionResume: {
|
||||||
next: PurchaseStatus | undefined,
|
[x in PurchaseStatus]?: {
|
||||||
} } = {
|
next: PurchaseStatus | undefined;
|
||||||
|
};
|
||||||
|
} = {
|
||||||
[PurchaseStatus.SuspendedDownloadingProposal]: {
|
[PurchaseStatus.SuspendedDownloadingProposal]: {
|
||||||
next: PurchaseStatus.PendingDownloadingProposal,
|
next: PurchaseStatus.PendingDownloadingProposal,
|
||||||
},
|
},
|
||||||
@ -1828,9 +1876,8 @@ const transitionResume: { [x in PurchaseStatus]?: {
|
|||||||
},
|
},
|
||||||
[PurchaseStatus.SuspendedQueryingAutoRefund]: {
|
[PurchaseStatus.SuspendedQueryingAutoRefund]: {
|
||||||
next: PurchaseStatus.PendingQueryingAutoRefund,
|
next: PurchaseStatus.PendingQueryingAutoRefund,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export async function suspendPayMerchant(
|
export async function suspendPayMerchant(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
@ -1846,9 +1893,7 @@ export async function suspendPayMerchant(
|
|||||||
});
|
});
|
||||||
stopLongpolling(ws, opId);
|
stopLongpolling(ws, opId);
|
||||||
const transitionInfo = await ws.db
|
const transitionInfo = await ws.db
|
||||||
.mktx((x) => [
|
.mktx((x) => [x.purchases])
|
||||||
x.purchases,
|
|
||||||
])
|
|
||||||
.runReadWrite(async (tx) => {
|
.runReadWrite(async (tx) => {
|
||||||
const purchase = await tx.purchases.get(proposalId);
|
const purchase = await tx.purchases.get(proposalId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
@ -1867,7 +1912,6 @@ export async function suspendPayMerchant(
|
|||||||
ws.workAvailable.trigger();
|
ws.workAvailable.trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function resumePayMerchant(
|
export async function resumePayMerchant(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
proposalId: string,
|
proposalId: string,
|
||||||
@ -1882,9 +1926,7 @@ export async function resumePayMerchant(
|
|||||||
});
|
});
|
||||||
stopLongpolling(ws, opId);
|
stopLongpolling(ws, opId);
|
||||||
const transitionInfo = await ws.db
|
const transitionInfo = await ws.db
|
||||||
.mktx((x) => [
|
.mktx((x) => [x.purchases])
|
||||||
x.purchases,
|
|
||||||
])
|
|
||||||
.runReadWrite(async (tx) => {
|
.runReadWrite(async (tx) => {
|
||||||
const purchase = await tx.purchases.get(proposalId);
|
const purchase = await tx.purchases.get(proposalId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
@ -2010,6 +2052,11 @@ export function computePayMerchantTransactionState(
|
|||||||
major: TransactionMajorState.Failed,
|
major: TransactionMajorState.Failed,
|
||||||
minor: TransactionMinorState.ClaimProposal,
|
minor: TransactionMinorState.ClaimProposal,
|
||||||
};
|
};
|
||||||
|
case PurchaseStatus.FailedAbort:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Failed,
|
||||||
|
minor: TransactionMinorState.AbortingBank,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2005,6 +2005,10 @@ export function computePeerPushDebitTransactionState(
|
|||||||
return {
|
return {
|
||||||
major: TransactionMajorState.Done,
|
major: TransactionMajorState.Done,
|
||||||
};
|
};
|
||||||
|
case PeerPushPaymentInitiationStatus.Failed:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Failed,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2048,6 +2052,8 @@ export async function abortPeerPushDebitTransaction(
|
|||||||
case PeerPushPaymentInitiationStatus.Aborted:
|
case PeerPushPaymentInitiationStatus.Aborted:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
|
case PeerPushPaymentInitiationStatus.Failed:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(pushDebitRec.status);
|
assertUnreachable(pushDebitRec.status);
|
||||||
}
|
}
|
||||||
@ -2104,6 +2110,7 @@ export async function cancelAbortingPeerPushDebitTransaction(
|
|||||||
case PeerPushPaymentInitiationStatus.PendingCreatePurse:
|
case PeerPushPaymentInitiationStatus.PendingCreatePurse:
|
||||||
case PeerPushPaymentInitiationStatus.Done:
|
case PeerPushPaymentInitiationStatus.Done:
|
||||||
case PeerPushPaymentInitiationStatus.Aborted:
|
case PeerPushPaymentInitiationStatus.Aborted:
|
||||||
|
case PeerPushPaymentInitiationStatus.Failed:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2166,6 +2173,7 @@ export async function suspendPeerPushDebitTransaction(
|
|||||||
case PeerPushPaymentInitiationStatus.SuspendedCreatePurse:
|
case PeerPushPaymentInitiationStatus.SuspendedCreatePurse:
|
||||||
case PeerPushPaymentInitiationStatus.Done:
|
case PeerPushPaymentInitiationStatus.Done:
|
||||||
case PeerPushPaymentInitiationStatus.Aborted:
|
case PeerPushPaymentInitiationStatus.Aborted:
|
||||||
|
case PeerPushPaymentInitiationStatus.Failed:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2220,6 +2228,138 @@ export async function suspendPeerPullDebitTransaction(
|
|||||||
break;
|
break;
|
||||||
case PeerPullDebitRecordStatus.SuspendedDeposit:
|
case PeerPullDebitRecordStatus.SuspendedDeposit:
|
||||||
break;
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Aborted:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.AbortingRefresh:
|
||||||
|
newStatus = PeerPullDebitRecordStatus.SuspendedAbortingRefresh;
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Failed:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.SuspendedAbortingRefresh:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assertUnreachable(pullDebitRec.status);
|
||||||
|
}
|
||||||
|
if (newStatus != null) {
|
||||||
|
const oldTxState = computePeerPullDebitTransactionState(pullDebitRec);
|
||||||
|
pullDebitRec.status = newStatus;
|
||||||
|
const newTxState = computePeerPullDebitTransactionState(pullDebitRec);
|
||||||
|
await tx.peerPullPaymentIncoming.put(pullDebitRec);
|
||||||
|
return {
|
||||||
|
oldTxState,
|
||||||
|
newTxState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function abortPeerPullDebitTransaction(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
peerPullPaymentIncomingId: string,
|
||||||
|
) {
|
||||||
|
const taskId = constructTaskIdentifier({
|
||||||
|
tag: PendingTaskType.PeerPullDebit,
|
||||||
|
peerPullPaymentIncomingId,
|
||||||
|
});
|
||||||
|
const transactionId = constructTransactionIdentifier({
|
||||||
|
tag: TransactionType.PeerPullDebit,
|
||||||
|
peerPullPaymentIncomingId,
|
||||||
|
});
|
||||||
|
stopLongpolling(ws, taskId);
|
||||||
|
const transitionInfo = await ws.db
|
||||||
|
.mktx((x) => [x.peerPullPaymentIncoming])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const pullDebitRec = await tx.peerPullPaymentIncoming.get(
|
||||||
|
peerPullPaymentIncomingId,
|
||||||
|
);
|
||||||
|
if (!pullDebitRec) {
|
||||||
|
logger.warn(`peer pull debit ${peerPullPaymentIncomingId} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let newStatus: PeerPullDebitRecordStatus | undefined = undefined;
|
||||||
|
switch (pullDebitRec.status) {
|
||||||
|
case PeerPullDebitRecordStatus.DialogProposed:
|
||||||
|
newStatus = PeerPullDebitRecordStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.DonePaid:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.PendingDeposit:
|
||||||
|
newStatus = PeerPullDebitRecordStatus.AbortingRefresh;
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.SuspendedDeposit:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Aborted:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.AbortingRefresh:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Failed:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.SuspendedAbortingRefresh:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assertUnreachable(pullDebitRec.status);
|
||||||
|
}
|
||||||
|
if (newStatus != null) {
|
||||||
|
const oldTxState = computePeerPullDebitTransactionState(pullDebitRec);
|
||||||
|
pullDebitRec.status = newStatus;
|
||||||
|
const newTxState = computePeerPullDebitTransactionState(pullDebitRec);
|
||||||
|
await tx.peerPullPaymentIncoming.put(pullDebitRec);
|
||||||
|
return {
|
||||||
|
oldTxState,
|
||||||
|
newTxState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function cancelAbortingPeerPullDebitTransaction(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
peerPullPaymentIncomingId: string,
|
||||||
|
) {
|
||||||
|
const taskId = constructTaskIdentifier({
|
||||||
|
tag: PendingTaskType.PeerPullDebit,
|
||||||
|
peerPullPaymentIncomingId,
|
||||||
|
});
|
||||||
|
const transactionId = constructTransactionIdentifier({
|
||||||
|
tag: TransactionType.PeerPullDebit,
|
||||||
|
peerPullPaymentIncomingId,
|
||||||
|
});
|
||||||
|
stopLongpolling(ws, taskId);
|
||||||
|
const transitionInfo = await ws.db
|
||||||
|
.mktx((x) => [x.peerPullPaymentIncoming])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const pullDebitRec = await tx.peerPullPaymentIncoming.get(
|
||||||
|
peerPullPaymentIncomingId,
|
||||||
|
);
|
||||||
|
if (!pullDebitRec) {
|
||||||
|
logger.warn(`peer pull debit ${peerPullPaymentIncomingId} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let newStatus: PeerPullDebitRecordStatus | undefined = undefined;
|
||||||
|
switch (pullDebitRec.status) {
|
||||||
|
case PeerPullDebitRecordStatus.DialogProposed:
|
||||||
|
newStatus = PeerPullDebitRecordStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.DonePaid:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.PendingDeposit:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.SuspendedDeposit:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Aborted:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Failed:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.SuspendedAbortingRefresh:
|
||||||
|
case PeerPullDebitRecordStatus.AbortingRefresh:
|
||||||
|
// FIXME: abort underlying refresh!
|
||||||
|
newStatus = PeerPullDebitRecordStatus.Failed;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(pullDebitRec.status);
|
assertUnreachable(pullDebitRec.status);
|
||||||
}
|
}
|
||||||
@ -2270,6 +2410,15 @@ export async function resumePeerPullDebitTransaction(
|
|||||||
case PeerPullDebitRecordStatus.SuspendedDeposit:
|
case PeerPullDebitRecordStatus.SuspendedDeposit:
|
||||||
newStatus = PeerPullDebitRecordStatus.PendingDeposit;
|
newStatus = PeerPullDebitRecordStatus.PendingDeposit;
|
||||||
break;
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Aborted:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.AbortingRefresh:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.Failed:
|
||||||
|
break;
|
||||||
|
case PeerPullDebitRecordStatus.SuspendedAbortingRefresh:
|
||||||
|
newStatus = PeerPullDebitRecordStatus.AbortingRefresh;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(pullDebitRec.status);
|
assertUnreachable(pullDebitRec.status);
|
||||||
}
|
}
|
||||||
@ -2330,6 +2479,10 @@ export async function suspendPeerPushCreditTransaction(
|
|||||||
// FIXME: Suspend internal withdrawal transaction!
|
// FIXME: Suspend internal withdrawal transaction!
|
||||||
newStatus = PeerPushPaymentIncomingStatus.SuspendedWithdrawing;
|
newStatus = PeerPushPaymentIncomingStatus.SuspendedWithdrawing;
|
||||||
break;
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.Aborted:
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.Failed:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(pushCreditRec.status);
|
assertUnreachable(pushCreditRec.status);
|
||||||
}
|
}
|
||||||
@ -2348,6 +2501,81 @@ export async function suspendPeerPushCreditTransaction(
|
|||||||
notifyTransition(ws, transactionId, transitionInfo);
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function abortPeerPushCreditTransaction(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
peerPushPaymentIncomingId: string,
|
||||||
|
) {
|
||||||
|
const taskId = constructTaskIdentifier({
|
||||||
|
tag: PendingTaskType.PeerPushCredit,
|
||||||
|
peerPushPaymentIncomingId,
|
||||||
|
});
|
||||||
|
const transactionId = constructTransactionIdentifier({
|
||||||
|
tag: TransactionType.PeerPushCredit,
|
||||||
|
peerPushPaymentIncomingId,
|
||||||
|
});
|
||||||
|
stopLongpolling(ws, taskId);
|
||||||
|
const transitionInfo = await ws.db
|
||||||
|
.mktx((x) => [x.peerPushPaymentIncoming])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const pushCreditRec = await tx.peerPushPaymentIncoming.get(
|
||||||
|
peerPushPaymentIncomingId,
|
||||||
|
);
|
||||||
|
if (!pushCreditRec) {
|
||||||
|
logger.warn(`peer push credit ${peerPushPaymentIncomingId} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let newStatus: PeerPushPaymentIncomingStatus | undefined = undefined;
|
||||||
|
switch (pushCreditRec.status) {
|
||||||
|
case PeerPushPaymentIncomingStatus.DialogProposed:
|
||||||
|
newStatus = PeerPushPaymentIncomingStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.Done:
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.SuspendedMerge:
|
||||||
|
case PeerPushPaymentIncomingStatus.SuspendedMergeKycRequired:
|
||||||
|
case PeerPushPaymentIncomingStatus.SuspendedWithdrawing:
|
||||||
|
newStatus = PeerPushPaymentIncomingStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.PendingMergeKycRequired:
|
||||||
|
newStatus = PeerPushPaymentIncomingStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.PendingMerge:
|
||||||
|
newStatus = PeerPushPaymentIncomingStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.PendingWithdrawing:
|
||||||
|
newStatus = PeerPushPaymentIncomingStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.Aborted:
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.Failed:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assertUnreachable(pushCreditRec.status);
|
||||||
|
}
|
||||||
|
if (newStatus != null) {
|
||||||
|
const oldTxState = computePeerPushCreditTransactionState(pushCreditRec);
|
||||||
|
pushCreditRec.status = newStatus;
|
||||||
|
const newTxState = computePeerPushCreditTransactionState(pushCreditRec);
|
||||||
|
await tx.peerPushPaymentIncoming.put(pushCreditRec);
|
||||||
|
return {
|
||||||
|
oldTxState,
|
||||||
|
newTxState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cancelAbortingPeerPushCreditTransaction(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
peerPushPaymentIncomingId: string,
|
||||||
|
) {
|
||||||
|
// We don't have any "aborting" states!
|
||||||
|
throw Error("can't run cancel-aborting on peer-push-credit transaction");
|
||||||
|
}
|
||||||
|
|
||||||
export async function resumePeerPushCreditTransaction(
|
export async function resumePeerPushCreditTransaction(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
peerPushPaymentIncomingId: string,
|
peerPushPaymentIncomingId: string,
|
||||||
@ -2388,6 +2616,10 @@ export async function resumePeerPushCreditTransaction(
|
|||||||
// FIXME: resume underlying "internal-withdrawal" transaction.
|
// FIXME: resume underlying "internal-withdrawal" transaction.
|
||||||
newStatus = PeerPushPaymentIncomingStatus.PendingWithdrawing;
|
newStatus = PeerPushPaymentIncomingStatus.PendingWithdrawing;
|
||||||
break;
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.Aborted:
|
||||||
|
break;
|
||||||
|
case PeerPushPaymentIncomingStatus.Failed:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(pushCreditRec.status);
|
assertUnreachable(pushCreditRec.status);
|
||||||
}
|
}
|
||||||
@ -2442,11 +2674,135 @@ export async function suspendPeerPullCreditTransaction(
|
|||||||
case PeerPullPaymentInitiationStatus.PendingReady:
|
case PeerPullPaymentInitiationStatus.PendingReady:
|
||||||
newStatus = PeerPullPaymentInitiationStatus.SuspendedReady;
|
newStatus = PeerPullPaymentInitiationStatus.SuspendedReady;
|
||||||
break;
|
break;
|
||||||
|
case PeerPullPaymentInitiationStatus.AbortingDeletePurse:
|
||||||
|
newStatus =
|
||||||
|
PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse;
|
||||||
|
break;
|
||||||
case PeerPullPaymentInitiationStatus.DonePurseDeposited:
|
case PeerPullPaymentInitiationStatus.DonePurseDeposited:
|
||||||
case PeerPullPaymentInitiationStatus.SuspendedCreatePurse:
|
case PeerPullPaymentInitiationStatus.SuspendedCreatePurse:
|
||||||
case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired:
|
case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired:
|
||||||
case PeerPullPaymentInitiationStatus.SuspendedReady:
|
case PeerPullPaymentInitiationStatus.SuspendedReady:
|
||||||
case PeerPullPaymentInitiationStatus.SuspendedWithdrawing:
|
case PeerPullPaymentInitiationStatus.SuspendedWithdrawing:
|
||||||
|
case PeerPullPaymentInitiationStatus.Aborted:
|
||||||
|
case PeerPullPaymentInitiationStatus.Failed:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assertUnreachable(pullCreditRec.status);
|
||||||
|
}
|
||||||
|
if (newStatus != null) {
|
||||||
|
const oldTxState = computePeerPullCreditTransactionState(pullCreditRec);
|
||||||
|
pullCreditRec.status = newStatus;
|
||||||
|
const newTxState = computePeerPullCreditTransactionState(pullCreditRec);
|
||||||
|
await tx.peerPullPaymentInitiations.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.peerPullPaymentInitiations])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const pullCreditRec = await tx.peerPullPaymentInitiations.get(pursePub);
|
||||||
|
if (!pullCreditRec) {
|
||||||
|
logger.warn(`peer pull credit ${pursePub} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let newStatus: PeerPullPaymentInitiationStatus | undefined = undefined;
|
||||||
|
switch (pullCreditRec.status) {
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingCreatePurse:
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingMergeKycRequired:
|
||||||
|
newStatus = PeerPullPaymentInitiationStatus.AbortingDeletePurse;
|
||||||
|
break;
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingWithdrawing:
|
||||||
|
throw Error("can't abort anymore");
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingReady:
|
||||||
|
newStatus = PeerPullPaymentInitiationStatus.AbortingDeletePurse;
|
||||||
|
break;
|
||||||
|
case PeerPullPaymentInitiationStatus.DonePurseDeposited:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedCreatePurse:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedReady:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedWithdrawing:
|
||||||
|
case PeerPullPaymentInitiationStatus.Aborted:
|
||||||
|
case PeerPullPaymentInitiationStatus.AbortingDeletePurse:
|
||||||
|
case PeerPullPaymentInitiationStatus.Failed:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assertUnreachable(pullCreditRec.status);
|
||||||
|
}
|
||||||
|
if (newStatus != null) {
|
||||||
|
const oldTxState = computePeerPullCreditTransactionState(pullCreditRec);
|
||||||
|
pullCreditRec.status = newStatus;
|
||||||
|
const newTxState = computePeerPullCreditTransactionState(pullCreditRec);
|
||||||
|
await tx.peerPullPaymentInitiations.put(pullCreditRec);
|
||||||
|
return {
|
||||||
|
oldTxState,
|
||||||
|
newTxState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cancelAbortingPeerPullCreditTransaction(
|
||||||
|
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.peerPullPaymentInitiations])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const pullCreditRec = await tx.peerPullPaymentInitiations.get(pursePub);
|
||||||
|
if (!pullCreditRec) {
|
||||||
|
logger.warn(`peer pull credit ${pursePub} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let newStatus: PeerPullPaymentInitiationStatus | undefined = undefined;
|
||||||
|
switch (pullCreditRec.status) {
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingCreatePurse:
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingMergeKycRequired:
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingWithdrawing:
|
||||||
|
case PeerPullPaymentInitiationStatus.PendingReady:
|
||||||
|
case PeerPullPaymentInitiationStatus.DonePurseDeposited:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedCreatePurse:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedMergeKycRequired:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedReady:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedWithdrawing:
|
||||||
|
case PeerPullPaymentInitiationStatus.Aborted:
|
||||||
|
case PeerPullPaymentInitiationStatus.Failed:
|
||||||
|
break;
|
||||||
|
case PeerPullPaymentInitiationStatus.AbortingDeletePurse:
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse:
|
||||||
|
newStatus = PeerPullPaymentInitiationStatus.Failed;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(pullCreditRec.status);
|
assertUnreachable(pullCreditRec.status);
|
||||||
@ -2493,7 +2849,11 @@ export async function resumePeerPullCreditTransaction(
|
|||||||
case PeerPullPaymentInitiationStatus.PendingMergeKycRequired:
|
case PeerPullPaymentInitiationStatus.PendingMergeKycRequired:
|
||||||
case PeerPullPaymentInitiationStatus.PendingWithdrawing:
|
case PeerPullPaymentInitiationStatus.PendingWithdrawing:
|
||||||
case PeerPullPaymentInitiationStatus.PendingReady:
|
case PeerPullPaymentInitiationStatus.PendingReady:
|
||||||
|
case PeerPullPaymentInitiationStatus.AbortingDeletePurse:
|
||||||
case PeerPullPaymentInitiationStatus.DonePurseDeposited:
|
case PeerPullPaymentInitiationStatus.DonePurseDeposited:
|
||||||
|
case PeerPullPaymentInitiationStatus.Failed:
|
||||||
|
case PeerPullPaymentInitiationStatus.Aborted:
|
||||||
|
break;
|
||||||
case PeerPullPaymentInitiationStatus.SuspendedCreatePurse:
|
case PeerPullPaymentInitiationStatus.SuspendedCreatePurse:
|
||||||
newStatus = PeerPullPaymentInitiationStatus.PendingCreatePurse;
|
newStatus = PeerPullPaymentInitiationStatus.PendingCreatePurse;
|
||||||
break;
|
break;
|
||||||
@ -2506,6 +2866,9 @@ export async function resumePeerPullCreditTransaction(
|
|||||||
case PeerPullPaymentInitiationStatus.SuspendedWithdrawing:
|
case PeerPullPaymentInitiationStatus.SuspendedWithdrawing:
|
||||||
newStatus = PeerPullPaymentInitiationStatus.PendingWithdrawing;
|
newStatus = PeerPullPaymentInitiationStatus.PendingWithdrawing;
|
||||||
break;
|
break;
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse:
|
||||||
|
newStatus = PeerPullPaymentInitiationStatus.AbortingDeletePurse;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(pullCreditRec.status);
|
assertUnreachable(pullCreditRec.status);
|
||||||
}
|
}
|
||||||
@ -2566,6 +2929,7 @@ export async function resumePeerPushDebitTransaction(
|
|||||||
case PeerPushPaymentInitiationStatus.PendingReady:
|
case PeerPushPaymentInitiationStatus.PendingReady:
|
||||||
case PeerPushPaymentInitiationStatus.Done:
|
case PeerPushPaymentInitiationStatus.Done:
|
||||||
case PeerPushPaymentInitiationStatus.Aborted:
|
case PeerPushPaymentInitiationStatus.Aborted:
|
||||||
|
case PeerPushPaymentInitiationStatus.Failed:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2630,6 +2994,16 @@ export function computePeerPushCreditTransactionState(
|
|||||||
major: TransactionMajorState.Suspended,
|
major: TransactionMajorState.Suspended,
|
||||||
minor: TransactionMinorState.Withdraw,
|
minor: TransactionMinorState.Withdraw,
|
||||||
};
|
};
|
||||||
|
case PeerPushPaymentIncomingStatus.Aborted:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Aborted
|
||||||
|
};
|
||||||
|
case PeerPushPaymentIncomingStatus.Failed:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Failed,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assertUnreachable(pushCreditRecord.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2681,6 +3055,24 @@ export function computePeerPullCreditTransactionState(
|
|||||||
major: TransactionMajorState.Suspended,
|
major: TransactionMajorState.Suspended,
|
||||||
minor: TransactionMinorState.MergeKycRequired,
|
minor: TransactionMinorState.MergeKycRequired,
|
||||||
};
|
};
|
||||||
|
case PeerPullPaymentInitiationStatus.Aborted:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Aborted,
|
||||||
|
};
|
||||||
|
case PeerPullPaymentInitiationStatus.AbortingDeletePurse:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Aborting,
|
||||||
|
minor: TransactionMinorState.DeletePurse,
|
||||||
|
};
|
||||||
|
case PeerPullPaymentInitiationStatus.Failed:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Failed,
|
||||||
|
};
|
||||||
|
case PeerPullPaymentInitiationStatus.SuspendedAbortingDeletePurse:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Aborting,
|
||||||
|
minor: TransactionMinorState.DeletePurse,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2707,5 +3099,23 @@ export function computePeerPullDebitTransactionState(
|
|||||||
major: TransactionMajorState.Suspended,
|
major: TransactionMajorState.Suspended,
|
||||||
minor: TransactionMinorState.Deposit,
|
minor: TransactionMinorState.Deposit,
|
||||||
};
|
};
|
||||||
|
case PeerPullDebitRecordStatus.Aborted:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Aborted,
|
||||||
|
};
|
||||||
|
case PeerPullDebitRecordStatus.AbortingRefresh:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Aborting,
|
||||||
|
minor: TransactionMinorState.Refresh,
|
||||||
|
};
|
||||||
|
case PeerPullDebitRecordStatus.Failed:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Failed,
|
||||||
|
};
|
||||||
|
case PeerPullDebitRecordStatus.SuspendedAbortingRefresh:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.SuspendedAborting,
|
||||||
|
minor: TransactionMinorState.Refresh,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ import {
|
|||||||
PendingTaskType,
|
PendingTaskType,
|
||||||
WalletConfig,
|
WalletConfig,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import { constructTransactionIdentifier } from "./transactions.js";
|
import { constructTransactionIdentifier, notifyTransition } from "./transactions.js";
|
||||||
|
|
||||||
const logger = new Logger("refresh.ts");
|
const logger = new Logger("refresh.ts");
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ function updateGroupStatus(rg: RefreshGroupRecord): void {
|
|||||||
if (allDone) {
|
if (allDone) {
|
||||||
if (anyFrozen) {
|
if (anyFrozen) {
|
||||||
rg.timestampFinished = TalerPreciseTimestamp.now();
|
rg.timestampFinished = TalerPreciseTimestamp.now();
|
||||||
rg.operationStatus = RefreshOperationStatus.FinishedWithError;
|
rg.operationStatus = RefreshOperationStatus.Failed;
|
||||||
} else {
|
} else {
|
||||||
rg.timestampFinished = TalerPreciseTimestamp.now();
|
rg.timestampFinished = TalerPreciseTimestamp.now();
|
||||||
rg.operationStatus = RefreshOperationStatus.Finished;
|
rg.operationStatus = RefreshOperationStatus.Finished;
|
||||||
@ -1189,7 +1189,7 @@ export function computeRefreshTransactionState(
|
|||||||
return {
|
return {
|
||||||
major: TransactionMajorState.Done,
|
major: TransactionMajorState.Done,
|
||||||
};
|
};
|
||||||
case RefreshOperationStatus.FinishedWithError:
|
case RefreshOperationStatus.Failed:
|
||||||
return {
|
return {
|
||||||
major: TransactionMajorState.Failed,
|
major: TransactionMajorState.Failed,
|
||||||
};
|
};
|
||||||
@ -1261,7 +1261,7 @@ export async function resumeRefreshGroup(
|
|||||||
tag: TransactionType.Refresh,
|
tag: TransactionType.Refresh,
|
||||||
refreshGroupId,
|
refreshGroupId,
|
||||||
});
|
});
|
||||||
let res = await ws.db
|
const transitionInfo = await ws.db
|
||||||
.mktx((x) => [x.refreshGroups])
|
.mktx((x) => [x.refreshGroups])
|
||||||
.runReadWrite(async (tx) => {
|
.runReadWrite(async (tx) => {
|
||||||
const dg = await tx.refreshGroups.get(refreshGroupId);
|
const dg = await tx.refreshGroups.get(refreshGroupId);
|
||||||
@ -1289,19 +1289,57 @@ export async function resumeRefreshGroup(
|
|||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
ws.workAvailable.trigger();
|
ws.workAvailable.trigger();
|
||||||
if (res) {
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
ws.notify({
|
}
|
||||||
type: NotificationType.TransactionStateTransition,
|
|
||||||
transactionId,
|
export async function cancelAbortingRefreshGroup(
|
||||||
oldTxState: res.oldTxState,
|
ws: InternalWalletState,
|
||||||
newTxState: res.newTxState,
|
refreshGroupId: string,
|
||||||
});
|
): Promise<void> {
|
||||||
}
|
throw Error("action cancel-aborting not allowed on refreshes");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function abortRefreshGroup(
|
export async function abortRefreshGroup(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
refreshGroupId: string,
|
refreshGroupId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
throw Error("can't abort refresh groups.");
|
const transactionId = constructTransactionIdentifier({
|
||||||
|
tag: TransactionType.Refresh,
|
||||||
|
refreshGroupId,
|
||||||
|
});
|
||||||
|
const transitionInfo = await ws.db
|
||||||
|
.mktx((x) => [x.refreshGroups])
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
const dg = await tx.refreshGroups.get(refreshGroupId);
|
||||||
|
if (!dg) {
|
||||||
|
logger.warn(
|
||||||
|
`can't resume refresh group, refreshGroupId=${refreshGroupId} not found`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const oldState = computeRefreshTransactionState(dg);
|
||||||
|
let newStatus: RefreshOperationStatus | undefined;
|
||||||
|
switch (dg.operationStatus) {
|
||||||
|
case RefreshOperationStatus.Finished:
|
||||||
|
break;;
|
||||||
|
case RefreshOperationStatus.Pending:
|
||||||
|
case RefreshOperationStatus.Suspended:
|
||||||
|
newStatus = RefreshOperationStatus.Failed;
|
||||||
|
break;
|
||||||
|
case RefreshOperationStatus.Failed:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assertUnreachable(dg.operationStatus);
|
||||||
|
}
|
||||||
|
if (newStatus) {
|
||||||
|
dg.operationStatus = newStatus;
|
||||||
|
await tx.refreshGroups.put(dg);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
oldTxState: oldState,
|
||||||
|
newTxState: computeRefreshTransactionState(dg),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
ws.workAvailable.trigger();
|
||||||
|
notifyTransition(ws, transactionId, transitionInfo);
|
||||||
}
|
}
|
||||||
|
@ -87,21 +87,28 @@ const logger = new Logger("operations/tip.ts");
|
|||||||
export function computeTipTransactionStatus(
|
export function computeTipTransactionStatus(
|
||||||
tipRecord: TipRecord,
|
tipRecord: TipRecord,
|
||||||
): TransactionState {
|
): TransactionState {
|
||||||
if (tipRecord.pickedUpTimestamp) {
|
switch (tipRecord.status) {
|
||||||
return {
|
case TipRecordStatus.Done:
|
||||||
major: TransactionMajorState.Done,
|
return {
|
||||||
};
|
major: TransactionMajorState.Done,
|
||||||
|
};
|
||||||
|
case TipRecordStatus.Aborted:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Aborted,
|
||||||
|
};
|
||||||
|
case TipRecordStatus.PendingPickup:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Pending,
|
||||||
|
minor: TransactionMinorState.Pickup,
|
||||||
|
};
|
||||||
|
case TipRecordStatus.SuspendidPickup:
|
||||||
|
return {
|
||||||
|
major: TransactionMajorState.Pending,
|
||||||
|
minor: TransactionMinorState.User,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
assertUnreachable(tipRecord.status);
|
||||||
}
|
}
|
||||||
if (tipRecord.acceptedTimestamp) {
|
|
||||||
return {
|
|
||||||
major: TransactionMajorState.Pending,
|
|
||||||
minor: TransactionMinorState.Pickup,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
major: TransactionMajorState.Pending,
|
|
||||||
minor: TransactionMinorState.User,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function prepareTip(
|
export async function prepareTip(
|
||||||
@ -445,6 +452,7 @@ export async function suspendTipTransaction(
|
|||||||
switch (tipRec.status) {
|
switch (tipRec.status) {
|
||||||
case TipRecordStatus.Done:
|
case TipRecordStatus.Done:
|
||||||
case TipRecordStatus.SuspendidPickup:
|
case TipRecordStatus.SuspendidPickup:
|
||||||
|
case TipRecordStatus.Aborted:
|
||||||
break;
|
break;
|
||||||
case TipRecordStatus.PendingPickup:
|
case TipRecordStatus.PendingPickup:
|
||||||
newStatus = TipRecordStatus.SuspendidPickup;
|
newStatus = TipRecordStatus.SuspendidPickup;
|
||||||
@ -492,11 +500,72 @@ export async function resumeTipTransaction(
|
|||||||
let newStatus: TipRecordStatus | undefined = undefined;
|
let newStatus: TipRecordStatus | undefined = undefined;
|
||||||
switch (tipRec.status) {
|
switch (tipRec.status) {
|
||||||
case TipRecordStatus.Done:
|
case TipRecordStatus.Done:
|
||||||
|
break;
|
||||||
case TipRecordStatus.SuspendidPickup:
|
case TipRecordStatus.SuspendidPickup:
|
||||||
newStatus = TipRecordStatus.PendingPickup;
|
newStatus = TipRecordStatus.PendingPickup;
|
||||||
break;
|
break;
|
||||||
case TipRecordStatus.PendingPickup:
|
case TipRecordStatus.PendingPickup:
|
||||||
break;
|
break;
|
||||||
|
case TipRecordStatus.Aborted:
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cancelAbortingTipTransaction(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
walletTipId: string,
|
||||||
|
): Promise<void> {
|
||||||
|
// We don't have an "aborting" state, so this should never happen!
|
||||||
|
throw Error("can't run cance-aborting on tip transaction");
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function abortTipTransaction(
|
||||||
|
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:
|
||||||
|
break;
|
||||||
|
case TipRecordStatus.SuspendidPickup:
|
||||||
|
newStatus = TipRecordStatus.Aborted;
|
||||||
|
break;
|
||||||
|
case TipRecordStatus.PendingPickup:
|
||||||
|
break;
|
||||||
|
case TipRecordStatus.Aborted:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assertUnreachable(tipRec.status);
|
assertUnreachable(tipRec.status);
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ import {
|
|||||||
import { getExchangeDetails } from "./exchanges.js";
|
import { getExchangeDetails } from "./exchanges.js";
|
||||||
import {
|
import {
|
||||||
abortPayMerchant,
|
abortPayMerchant,
|
||||||
|
cancelAbortingPaymentTransaction,
|
||||||
computePayMerchantTransactionState,
|
computePayMerchantTransactionState,
|
||||||
computeRefundTransactionState,
|
computeRefundTransactionState,
|
||||||
expectProposalDownload,
|
expectProposalDownload,
|
||||||
@ -90,6 +91,14 @@ import {
|
|||||||
suspendPayMerchant,
|
suspendPayMerchant,
|
||||||
} from "./pay-merchant.js";
|
} from "./pay-merchant.js";
|
||||||
import {
|
import {
|
||||||
|
abortPeerPullCreditTransaction,
|
||||||
|
abortPeerPullDebitTransaction,
|
||||||
|
abortPeerPushCreditTransaction,
|
||||||
|
abortPeerPushDebitTransaction,
|
||||||
|
cancelAbortingPeerPullCreditTransaction,
|
||||||
|
cancelAbortingPeerPullDebitTransaction,
|
||||||
|
cancelAbortingPeerPushCreditTransaction,
|
||||||
|
cancelAbortingPeerPushDebitTransaction,
|
||||||
computePeerPullCreditTransactionState,
|
computePeerPullCreditTransactionState,
|
||||||
computePeerPullDebitTransactionState,
|
computePeerPullDebitTransactionState,
|
||||||
computePeerPushCreditTransactionState,
|
computePeerPushCreditTransactionState,
|
||||||
@ -104,11 +113,15 @@ import {
|
|||||||
suspendPeerPushDebitTransaction,
|
suspendPeerPushDebitTransaction,
|
||||||
} from "./pay-peer.js";
|
} from "./pay-peer.js";
|
||||||
import {
|
import {
|
||||||
|
abortRefreshGroup,
|
||||||
|
cancelAbortingRefreshGroup,
|
||||||
computeRefreshTransactionState,
|
computeRefreshTransactionState,
|
||||||
resumeRefreshGroup,
|
resumeRefreshGroup,
|
||||||
suspendRefreshGroup,
|
suspendRefreshGroup,
|
||||||
} from "./refresh.js";
|
} from "./refresh.js";
|
||||||
import {
|
import {
|
||||||
|
abortTipTransaction,
|
||||||
|
cancelAbortingTipTransaction,
|
||||||
computeTipTransactionStatus,
|
computeTipTransactionStatus,
|
||||||
resumeTipTransaction,
|
resumeTipTransaction,
|
||||||
suspendTipTransaction,
|
suspendTipTransaction,
|
||||||
@ -1492,11 +1505,35 @@ export async function cancelAbortingTransaction(
|
|||||||
case TransactionType.Deposit:
|
case TransactionType.Deposit:
|
||||||
await cancelAbortingDepositGroup(ws, tx.depositGroupId);
|
await cancelAbortingDepositGroup(ws, tx.depositGroupId);
|
||||||
return;
|
return;
|
||||||
|
case TransactionType.InternalWithdrawal:
|
||||||
case TransactionType.Withdrawal:
|
case TransactionType.Withdrawal:
|
||||||
await cancelAbortingWithdrawalTransaction(ws, tx.withdrawalGroupId);
|
await cancelAbortingWithdrawalTransaction(ws, tx.withdrawalGroupId);
|
||||||
return;
|
return;
|
||||||
|
case TransactionType.Payment:
|
||||||
|
await cancelAbortingPaymentTransaction(ws, tx.proposalId);
|
||||||
|
return;
|
||||||
|
case TransactionType.Refund:
|
||||||
|
throw Error("can't do cancel-aborting on refund transaction");
|
||||||
|
case TransactionType.Tip:
|
||||||
|
await cancelAbortingTipTransaction(ws, tx.walletTipId);
|
||||||
|
return;
|
||||||
|
case TransactionType.Refresh:
|
||||||
|
await cancelAbortingRefreshGroup(ws, tx.refreshGroupId);
|
||||||
|
return;
|
||||||
|
case TransactionType.PeerPullCredit:
|
||||||
|
await cancelAbortingPeerPullCreditTransaction(ws, tx.pursePub);
|
||||||
|
return;
|
||||||
|
case TransactionType.PeerPullDebit:
|
||||||
|
await cancelAbortingPeerPullDebitTransaction(ws, tx.peerPullPaymentIncomingId);
|
||||||
|
return;
|
||||||
|
case TransactionType.PeerPushCredit:
|
||||||
|
await cancelAbortingPeerPushCreditTransaction(ws, tx.peerPushPaymentIncomingId);
|
||||||
|
return;
|
||||||
|
case TransactionType.PeerPushDebit:
|
||||||
|
await cancelAbortingPeerPushDebitTransaction(ws, tx.pursePub);
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
logger.warn(`unable to suspend transaction of type '${tx.tag}'`);
|
assertUnreachable(tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1774,18 +1811,36 @@ export async function abortTransaction(
|
|||||||
await abortPayMerchant(ws, txId.proposalId);
|
await abortPayMerchant(ws, txId.proposalId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TransactionType.Withdrawal: {
|
case TransactionType.Withdrawal:
|
||||||
|
case TransactionType.InternalWithdrawal: {
|
||||||
await abortWithdrawalTransaction(ws, txId.withdrawalGroupId);
|
await abortWithdrawalTransaction(ws, txId.withdrawalGroupId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TransactionType.Deposit:
|
case TransactionType.Deposit:
|
||||||
await abortDepositGroup(ws, txId.depositGroupId);
|
await abortDepositGroup(ws, txId.depositGroupId);
|
||||||
break;
|
break;
|
||||||
|
case TransactionType.Tip:
|
||||||
|
await abortTipTransaction(ws, txId.walletTipId);
|
||||||
|
break;
|
||||||
|
case TransactionType.Refund:
|
||||||
|
throw Error("can't abort refund transactions");
|
||||||
|
case TransactionType.Refresh:
|
||||||
|
await abortRefreshGroup(ws, txId.refreshGroupId);
|
||||||
|
break;
|
||||||
|
case TransactionType.PeerPullCredit:
|
||||||
|
await abortPeerPullCreditTransaction(ws, txId.pursePub);
|
||||||
|
break;
|
||||||
|
case TransactionType.PeerPullDebit:
|
||||||
|
await abortPeerPullDebitTransaction(ws, txId.peerPullPaymentIncomingId);
|
||||||
|
break;
|
||||||
|
case TransactionType.PeerPushCredit:
|
||||||
|
await abortPeerPushCreditTransaction(ws, txId.peerPushPaymentIncomingId);
|
||||||
|
break;
|
||||||
|
case TransactionType.PeerPushDebit:
|
||||||
|
await abortPeerPushDebitTransaction(ws, txId.pursePub);
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
const unknownTxType: any = txId.tag;
|
assertUnreachable(txId);
|
||||||
throw Error(
|
|
||||||
`can't abort a '${unknownTxType}' transaction: not yet implemented`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user