summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-06-30 16:14:58 +0200
committerFlorian Dold <florian@dold.me>2023-06-30 16:14:58 +0200
commitd4ee96138774e8bc469f172bbb6276af89d6f240 (patch)
treeeda5bc6833306727f711cc5aedd5f307fa8b1f67 /packages/taler-wallet-core/src/operations
parent7523ffa9105f71a6a4c201d3ee46dbfccc929cea (diff)
downloadwallet-core-d4ee96138774e8bc469f172bbb6276af89d6f240.tar.gz
wallet-core-d4ee96138774e8bc469f172bbb6276af89d6f240.tar.bz2
wallet-core-d4ee96138774e8bc469f172bbb6276af89d6f240.zip
wallet-core: rename OperationAttempt->TaskRun, do not allow task result values anymore
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
-rw-r--r--packages/taler-wallet-core/src/operations/backup/index.ts44
-rw-r--r--packages/taler-wallet-core/src/operations/common.ts86
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts38
-rw-r--r--packages/taler-wallet-core/src/operations/exchanges.ts60
-rw-r--r--packages/taler-wallet-core/src/operations/pay-merchant.ts79
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts56
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts30
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts38
-rw-r--r--packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts39
-rw-r--r--packages/taler-wallet-core/src/operations/recoup.ts14
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts32
-rw-r--r--packages/taler-wallet-core/src/operations/testing.ts14
-rw-r--r--packages/taler-wallet-core/src/operations/tip.ts25
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts51
14 files changed, 258 insertions, 348 deletions
diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts
index 364e876ec..236ef1e0f 100644
--- a/packages/taler-wallet-core/src/operations/backup/index.ts
+++ b/packages/taler-wallet-core/src/operations/backup/index.ts
@@ -94,8 +94,8 @@ import {
} from "../../util/invariants.js";
import { addAttentionRequest, removeAttentionRequest } from "../attention.js";
import {
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
TaskIdentifiers,
} from "../common.js";
import { checkPaymentByProposalId, preparePayForUri } from "../pay-merchant.js";
@@ -250,7 +250,7 @@ function getNextBackupTimestamp(): TalerPreciseTimestamp {
async function runBackupCycleForProvider(
ws: InternalWalletState,
args: BackupForProviderArgs,
-): Promise<OperationAttemptResult<unknown, { talerUri?: string }>> {
+): Promise<TaskRunResult> {
const provider = await ws.db
.mktx((x) => [x.backupProviders])
.runReadOnly(async (tx) => {
@@ -259,10 +259,7 @@ async function runBackupCycleForProvider(
if (!provider) {
logger.warn("provider disappeared");
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
const backupJson = await exportBackup(ws);
@@ -333,10 +330,7 @@ async function runBackupCycleForProvider(
type: AttentionType.BackupUnpaid,
});
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
if (resp.status === HttpStatusCode.PaymentRequired) {
@@ -378,10 +372,7 @@ async function runBackupCycleForProvider(
});
return {
- type: OperationAttemptResultType.Pending,
- result: {
- talerUri,
- },
+ type: TaskRunResultType.Pending,
};
}
const result = res;
@@ -415,10 +406,7 @@ async function runBackupCycleForProvider(
);
return {
- type: OperationAttemptResultType.Pending,
- result: {
- talerUri,
- },
+ type: TaskRunResultType.Pending,
};
}
@@ -445,8 +433,7 @@ async function runBackupCycleForProvider(
});
return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
+ type: TaskRunResultType.Finished,
};
}
@@ -487,7 +474,7 @@ async function runBackupCycleForProvider(
const err = await readTalerErrorResponse(resp);
logger.error(`got error response from backup provider: ${j2s(err)}`);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: err,
};
}
@@ -495,7 +482,7 @@ async function runBackupCycleForProvider(
export async function processBackupForProvider(
ws: InternalWalletState,
backupProviderBaseUrl: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const provider = await ws.db
.mktx((x) => [x.backupProviders])
.runReadOnly(async (tx) => {
@@ -720,23 +707,24 @@ async function runFirstBackupCycleForProvider(
): Promise<AddBackupProviderResponse> {
const resp = await runBackupCycleForProvider(ws, args);
switch (resp.type) {
- case OperationAttemptResultType.Error:
+ case TaskRunResultType.Error:
throw TalerError.fromDetail(
TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
resp.errorDetail as any, //FIXME create an error for backup problems
);
- case OperationAttemptResultType.Finished:
+ case TaskRunResultType.Finished:
return {
status: "ok",
};
- case OperationAttemptResultType.Longpoll:
+ case TaskRunResultType.Longpoll:
throw Error(
"unexpected runFirstBackupCycleForProvider result (longpoll)",
);
- case OperationAttemptResultType.Pending:
+ case TaskRunResultType.Pending:
return {
status: "payment-required",
- talerUri: resp.result.talerUri,
+ talerUri: "FIXME",
+ //talerUri: resp.result.talerUri,
};
default:
assertUnreachable(resp);
diff --git a/packages/taler-wallet-core/src/operations/common.ts b/packages/taler-wallet-core/src/operations/common.ts
index 620054cae..cc16a4704 100644
--- a/packages/taler-wallet-core/src/operations/common.ts
+++ b/packages/taler-wallet-core/src/operations/common.ts
@@ -433,25 +433,25 @@ async function storePendingTaskFinished(
});
}
-export async function runTaskWithErrorReporting<T1, T2>(
+export async function runTaskWithErrorReporting(
ws: InternalWalletState,
opId: TaskId,
- f: () => Promise<OperationAttemptResult<T1, T2>>,
-): Promise<OperationAttemptResult<T1, T2>> {
+ f: () => Promise<TaskRunResult>,
+): Promise<TaskRunResult> {
let maybeError: TalerErrorDetail | undefined;
try {
const resp = await f();
switch (resp.type) {
- case OperationAttemptResultType.Error:
+ case TaskRunResultType.Error:
await storePendingTaskError(ws, opId, resp.errorDetail);
return resp;
- case OperationAttemptResultType.Finished:
+ case TaskRunResultType.Finished:
await storePendingTaskFinished(ws, opId);
return resp;
- case OperationAttemptResultType.Pending:
+ case TaskRunResultType.Pending:
await storePendingTaskPending(ws, opId);
return resp;
- case OperationAttemptResultType.Longpoll:
+ case TaskRunResultType.Longpoll:
return resp;
}
} catch (e) {
@@ -459,7 +459,7 @@ export async function runTaskWithErrorReporting<T1, T2>(
if (ws.stopped) {
logger.warn("crypto API stopped during shutdown, ignoring error");
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
{},
@@ -474,7 +474,7 @@ export async function runTaskWithErrorReporting<T1, T2>(
maybeError = e.errorDetail;
await storePendingTaskError(ws, opId, maybeError!);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: e.errorDetail,
};
} else if (e instanceof Error) {
@@ -492,7 +492,7 @@ export async function runTaskWithErrorReporting<T1, T2>(
);
await storePendingTaskError(ws, opId, maybeError);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: maybeError,
};
} else {
@@ -504,7 +504,7 @@ export async function runTaskWithErrorReporting<T1, T2>(
);
await storePendingTaskError(ws, opId, maybeError);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: maybeError,
};
}
@@ -654,59 +654,55 @@ export interface TransactionManager {
abort(): Promise<void>;
suspend(): Promise<void>;
resume(): Promise<void>;
- process(): Promise<OperationAttemptResult>;
+ process(): Promise<TaskRunResult>;
}
-export enum OperationAttemptResultType {
+export enum TaskRunResultType {
Finished = "finished",
Pending = "pending",
Error = "error",
Longpoll = "longpoll",
}
-export type OperationAttemptResult<TSuccess = unknown, TPending = unknown> =
- | OperationAttemptFinishedResult<TSuccess>
- | OperationAttemptErrorResult
- | OperationAttemptLongpollResult
- | OperationAttemptPendingResult<TPending>;
+export type TaskRunResult =
+ | TaskRunFinishedResult
+ | TaskRunErrorResult
+ | TaskRunLongpollResult
+ | TaskRunPendingResult;
-export namespace OperationAttemptResult {
- export function finishedEmpty(): OperationAttemptResult<unknown, unknown> {
+export namespace TaskRunResult {
+ export function finished(): TaskRunResult {
return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
+ type: TaskRunResultType.Finished,
};
}
- export function pendingEmpty(): OperationAttemptResult<unknown, unknown> {
+ export function pending(): TaskRunResult {
return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
+ type: TaskRunResultType.Pending,
};
}
- export function longpoll(): OperationAttemptResult<unknown, unknown> {
+ export function longpoll(): TaskRunResult {
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
}
-export interface OperationAttemptFinishedResult<T> {
- type: OperationAttemptResultType.Finished;
- result: T;
+export interface TaskRunFinishedResult {
+ type: TaskRunResultType.Finished;
}
-export interface OperationAttemptPendingResult<T> {
- type: OperationAttemptResultType.Pending;
- result: T;
+export interface TaskRunPendingResult {
+ type: TaskRunResultType.Pending;
}
-export interface OperationAttemptErrorResult {
- type: OperationAttemptResultType.Error;
+export interface TaskRunErrorResult {
+ type: TaskRunResultType.Error;
errorDetail: TalerErrorDetail;
}
-export interface OperationAttemptLongpollResult {
- type: OperationAttemptResultType.Longpoll;
+export interface TaskRunLongpollResult {
+ type: TaskRunResultType.Longpoll;
}
export interface RetryInfo {
@@ -942,19 +938,3 @@ export namespace TaskIdentifiers {
return `${PendingTaskType.PeerPushCredit}:${ppi.peerPushPaymentIncomingId}` as TaskId;
}
}
-
-/**
- * Run an operation handler, expect a success result and extract the success value.
- */
-export async function unwrapOperationHandlerResultOrThrow<T>(
- res: OperationAttemptResult<T>,
-): Promise<T> {
- switch (res.type) {
- case OperationAttemptResultType.Finished:
- return res.result;
- case OperationAttemptResultType.Error:
- throw TalerError.fromUncheckedDetail(res.errorDetail);
- default:
- throw Error(`unexpected operation result (${res.type})`);
- }
-}
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index 236fa6b59..a8ec859cf 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -81,7 +81,7 @@ import { InternalWalletState } from "../internal-wallet-state.js";
import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
import {
constructTaskIdentifier,
- OperationAttemptResult,
+ TaskRunResult,
runLongpollAsync,
spendCoins,
TombstoneTag,
@@ -462,7 +462,7 @@ async function checkDepositKycStatus(
async function waitForRefreshOnDepositGroup(
ws: InternalWalletState,
depositGroup: DepositGroupRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const abortRefreshGroupId = depositGroup.abortRefreshGroupId;
checkLogicInvariant(!!abortRefreshGroupId);
const transactionId = constructTransactionIdentifier({
@@ -503,13 +503,13 @@ async function waitForRefreshOnDepositGroup(
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
async function refundDepositGroup(
ws: InternalWalletState,
depositGroup: DepositGroupRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const newTxPerCoin = [...depositGroup.transactionPerCoin];
logger.info(`status per coin: ${j2s(depositGroup.transactionPerCoin)}`);
for (let i = 0; i < depositGroup.transactionPerCoin.length; i++) {
@@ -614,13 +614,13 @@ async function refundDepositGroup(
await tx.depositGroups.put(newDg);
});
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
async function processDepositGroupAborting(
ws: InternalWalletState,
depositGroup: DepositGroupRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.info("processing deposit tx in 'aborting'");
const abortRefreshGroupId = depositGroup.abortRefreshGroupId;
if (!abortRefreshGroupId) {
@@ -634,7 +634,7 @@ async function processDepositGroupAborting(
async function processDepositGroupPendingKyc(
ws: InternalWalletState,
depositGroup: DepositGroupRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { depositGroupId } = depositGroup;
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Deposit,
@@ -696,7 +696,7 @@ async function processDepositGroupPendingKyc(
);
}
});
- return OperationAttemptResult.longpoll();
+ return TaskRunResult.longpoll();
}
/**
@@ -709,7 +709,7 @@ async function transitionToKycRequired(
depositGroup: DepositGroupRecord,
kycInfo: KycPendingInfo,
exchangeUrl: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { depositGroupId } = depositGroup;
const userType = "individual";
@@ -728,7 +728,7 @@ async function transitionToKycRequired(
});
if (kycStatusReq.status === HttpStatusCode.Ok) {
logger.warn("kyc requested, but already fulfilled");
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
} else if (kycStatusReq.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusReq.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
@@ -754,7 +754,7 @@ async function transitionToKycRequired(
return { oldTxState, newTxState };
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
} else {
throw Error(`unexpected response from kyc-check (${kycStatusReq.status})`);
}
@@ -764,7 +764,7 @@ async function processDepositGroupPendingTrack(
ws: InternalWalletState,
depositGroup: DepositGroupRecord,
cancellationToken?: CancellationToken,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { depositGroupId } = depositGroup;
for (let i = 0; i < depositGroup.depositedPerCoin.length; i++) {
const coinPub = depositGroup.payCoinSelection.coinPubs[i];
@@ -905,10 +905,10 @@ async function processDepositGroupPendingTrack(
});
notifyTransition(ws, transactionId, transitionInfo);
if (allWired) {
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
} else {
// FIXME: Use long-polling.
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
}
@@ -916,7 +916,7 @@ async function processDepositGroupPendingDeposit(
ws: InternalWalletState,
depositGroup: DepositGroupRecord,
cancellationToken?: CancellationToken,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.info("processing deposit group in pending(deposit)");
const depositGroupId = depositGroup.depositGroupId;
const contractData = extractContractData(
@@ -1000,7 +1000,7 @@ async function processDepositGroupPendingDeposit(
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
/**
@@ -1012,7 +1012,7 @@ export async function processDepositGroup(
options: {
cancellationToken?: CancellationToken;
} = {},
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const depositGroup = await ws.db
.mktx((x) => [x.depositGroups])
.runReadOnly(async (tx) => {
@@ -1020,7 +1020,7 @@ export async function processDepositGroup(
});
if (!depositGroup) {
logger.warn(`deposit group ${depositGroupId} not found`);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
switch (depositGroup.operationStatus) {
@@ -1042,7 +1042,7 @@ export async function processDepositGroup(
return processDepositGroupAborting(ws, depositGroup);
}
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
async function getExchangeWireFee(
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts
index 56ef672dc..c0373704a 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -76,11 +76,10 @@ import {
} from "../util/query.js";
import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "../versions.js";
import {
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResultType,
runTaskWithErrorReporting,
TaskIdentifiers,
- unwrapOperationHandlerResultOrThrow,
+ TaskRunResult,
} from "./common.js";
const logger = new Logger("exchanges.ts");
@@ -559,13 +558,34 @@ export async function updateExchangeFromUrl(
exchangeDetails: ExchangeDetailsRecord;
}> {
const canonUrl = canonicalizeBaseUrl(baseUrl);
- return unwrapOperationHandlerResultOrThrow(
- await runTaskWithErrorReporting(
- ws,
- TaskIdentifiers.forExchangeUpdateFromUrl(canonUrl),
- () => updateExchangeFromUrlHandler(ws, canonUrl, options),
- ),
+ const res = await runTaskWithErrorReporting(
+ ws,
+ TaskIdentifiers.forExchangeUpdateFromUrl(canonUrl),
+ () => updateExchangeFromUrlHandler(ws, canonUrl, options),
);
+ switch (res.type) {
+ case TaskRunResultType.Finished: {
+ const now = AbsoluteTime.now();
+ const { exchange, exchangeDetails } = await ws.db
+ .mktx((x) => [x.exchanges, x.exchangeDetails])
+ .runReadWrite(async (tx) => {
+ let exchange = await tx.exchanges.get(canonUrl);
+ const exchangeDetails = await getExchangeDetails(tx, baseUrl);
+ return { exchange, exchangeDetails };
+ });
+ if (!exchange) {
+ throw Error("exchange not found");
+ }
+ if (!exchangeDetails) {
+ throw Error("exchange details not found");
+ }
+ return { exchange, exchangeDetails };
+ }
+ case TaskRunResultType.Error:
+ throw TalerError.fromUncheckedDetail(res.errorDetail);
+ default:
+ throw Error(`unexpected operation result (${res.type})`);
+ }
}
/**
@@ -581,12 +601,7 @@ export async function updateExchangeFromUrlHandler(
forceNow?: boolean;
cancellationToken?: CancellationToken;
} = {},
-): Promise<
- OperationAttemptResult<{
- exchange: ExchangeRecord;
- exchangeDetails: ExchangeDetailsRecord;
- }>
-> {
+): Promise<TaskRunResult> {
const forceNow = options.forceNow ?? false;
logger.trace(
`updating exchange info for ${exchangeBaseUrl}, forced: ${forceNow}`,
@@ -620,10 +635,7 @@ export async function updateExchangeFromUrlHandler(
}
}
- return {
- type: OperationAttemptResultType.Finished,
- result: { exchange, exchangeDetails },
- };
+ return TaskRunResult.finished();
}
logger.info("updating exchange /keys info");
@@ -679,7 +691,7 @@ export async function updateExchangeFromUrlHandler(
},
);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail,
};
}
@@ -911,13 +923,7 @@ export async function updateExchangeFromUrlHandler(
});
}
- return {
- type: OperationAttemptResultType.Finished,
- result: {
- exchange: updated.exchange,
- exchangeDetails: updated.exchangeDetails,
- },
- };
+ return TaskRunResult.finished();
}
/**
diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts b/packages/taler-wallet-core/src/operations/pay-merchant.ts
index f2df08247..c74fcedcf 100644
--- a/packages/taler-wallet-core/src/operations/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts
@@ -112,8 +112,8 @@ import { checkDbInvariant } from "../util/invariants.js";
import { GetReadOnlyAccess } from "../util/query.js";
import {
constructTaskIdentifier,
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
RetryInfo,
TaskIdentifiers,
} from "./common.js";
@@ -325,7 +325,7 @@ export function extractContractData(
async function processDownloadProposal(
ws: InternalWalletState,
proposalId: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const proposal = await ws.db
.mktx((x) => [x.purchases])
.runReadOnly(async (tx) => {
@@ -333,17 +333,11 @@ async function processDownloadProposal(
});
if (!proposal) {
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
if (proposal.purchaseStatus != PurchaseStatus.PendingDownloadingProposal) {
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
const transactionId = constructTransactionIdentifier({
@@ -560,10 +554,7 @@ async function processDownloadProposal(
notifyTransition(ws, transactionId, transitionInfo);
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
/**
@@ -1065,7 +1056,7 @@ export async function checkPaymentByProposalId(
notifyTransition(ws, transactionId, transitionInfo);
// FIXME: What about error handling?! This doesn't properly store errors in the DB.
const r = await processPurchasePay(ws, proposalId, { forceNow: true });
- if (r.type !== OperationAttemptResultType.Finished) {
+ if (r.type !== TaskRunResultType.Finished) {
// FIXME: This does not surface the original error
throw Error("submitting pay failed");
}
@@ -1253,7 +1244,7 @@ export async function runPayForConfirmPay(
});
logger.trace(`processPurchasePay response type ${res.type}`);
switch (res.type) {
- case OperationAttemptResultType.Finished: {
+ case TaskRunResultType.Finished: {
const purchase = await ws.db
.mktx((x) => [x.purchases])
.runReadOnly(async (tx) => {
@@ -1272,7 +1263,7 @@ export async function runPayForConfirmPay(
}),
};
}
- case OperationAttemptResultType.Error: {
+ case TaskRunResultType.Error: {
// We hide transient errors from the caller.
const opRetry = await ws.db
.mktx((x) => [x.operationRetries])
@@ -1286,7 +1277,7 @@ export async function runPayForConfirmPay(
}),
};
}
- case OperationAttemptResultType.Pending:
+ case TaskRunResultType.Pending:
logger.trace("reporting pending as confirmPay response");
return {
type: ConfirmPayResultType.Pending,
@@ -1296,7 +1287,7 @@ export async function runPayForConfirmPay(
}),
lastError: undefined,
};
- case OperationAttemptResultType.Longpoll:
+ case TaskRunResultType.Longpoll:
throw Error("unexpected processPurchasePay result (longpoll)");
default:
assertUnreachable(res);
@@ -1456,7 +1447,7 @@ export async function confirmPay(
export async function processPurchase(
ws: InternalWalletState,
proposalId: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const purchase = await ws.db
.mktx((x) => [x.purchases])
.runReadOnly(async (tx) => {
@@ -1464,7 +1455,7 @@ export async function processPurchase(
});
if (!purchase) {
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: {
// FIXME: allocate more specific error code
code: TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
@@ -1504,10 +1495,7 @@ export async function processPurchase(
case PurchaseStatus.SuspendedQueryingAutoRefund:
case PurchaseStatus.SuspendedQueryingRefund:
case PurchaseStatus.FailedAbort:
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
default:
assertUnreachable(purchase.purchaseStatus);
// throw Error(`unexpected purchase status (${purchase.purchaseStatus})`);
@@ -1518,7 +1506,7 @@ export async function processPurchasePay(
ws: InternalWalletState,
proposalId: string,
options: unknown = {},
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const purchase = await ws.db
.mktx((x) => [x.purchases])
.runReadOnly(async (tx) => {
@@ -1526,7 +1514,7 @@ export async function processPurchasePay(
});
if (!purchase) {
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: {
// FIXME: allocate more specific error code
code: TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
@@ -1541,7 +1529,7 @@ export async function processPurchasePay(
case PurchaseStatus.PendingPayingReplay:
break;
default:
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
logger.trace(`processing purchase pay ${proposalId}`);
@@ -1589,7 +1577,7 @@ export async function processPurchasePay(
if (resp.status >= 500 && resp.status <= 599) {
const errDetails = await readUnexpectedResponseDetails(resp);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_PAY_MERCHANT_SERVER_ERROR,
{
@@ -1613,10 +1601,7 @@ export async function processPurchasePay(
// FIXME: Should we really consider this to be pending?
- return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
- };
+ return TaskRunResult.pending();
}
}
@@ -1677,7 +1662,7 @@ export async function processPurchasePay(
await unblockBackup(ws, proposalId);
}
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
export async function refuseProposal(
@@ -2114,7 +2099,7 @@ export function computePayMerchantTransactionActions(
async function processPurchaseAutoRefund(
ws: InternalWalletState,
purchase: PurchaseRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
logger.trace(`processing auto-refund for proposal ${proposalId}`);
@@ -2130,7 +2115,7 @@ async function processPurchaseAutoRefund(
// FIXME: Put this logic into runLongpollAsync?
if (ws.activeLongpoll[taskId]) {
- return OperationAttemptResult.longpoll();
+ return TaskRunResult.longpoll();
}
const download = await expectProposalDownload(ws, purchase);
@@ -2215,13 +2200,13 @@ async function processPurchaseAutoRefund(
}
});
- return OperationAttemptResult.longpoll();
+ return TaskRunResult.longpoll();
}
async function processPurchaseAbortingRefund(
ws: InternalWalletState,
purchase: PurchaseRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
const download = await expectProposalDownload(ws, purchase);
logger.trace(`processing aborting-refund for proposal ${proposalId}`);
@@ -2296,7 +2281,7 @@ async function processPurchaseAbortingRefund(
async function processPurchaseQueryRefund(
ws: InternalWalletState,
purchase: PurchaseRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
logger.trace(`processing query-refund for proposal ${proposalId}`);
@@ -2341,7 +2326,7 @@ async function processPurchaseQueryRefund(
return { oldTxState, newTxState };
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
} else {
const refundAwaiting = Amounts.sub(
Amounts.parseOrThrow(orderStatus.refund_amount),
@@ -2367,14 +2352,14 @@ async function processPurchaseQueryRefund(
return { oldTxState, newTxState };
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
}
async function processPurchaseAcceptRefund(
ws: InternalWalletState,
purchase: PurchaseRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const proposalId = purchase.proposalId;
const download = await expectProposalDownload(ws, purchase);
@@ -2472,7 +2457,7 @@ async function storeRefunds(
purchase: PurchaseRecord,
refunds: MerchantCoinRefundStatus[],
reason: RefundReason,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.info(`storing refunds: ${j2s(refunds)}`);
const transactionId = constructTransactionIdentifier({
@@ -2699,16 +2684,16 @@ async function storeRefunds(
});
if (!result) {
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
notifyTransition(ws, transactionId, result.transitionInfo);
if (result.numPendingItemsTotal > 0) {
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
export function computeRefundTransactionState(
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 88bdcb90e..4c00ed592 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
@@ -66,8 +66,8 @@ import { assertUnreachable } from "../util/assertUnreachable.js";
import { checkDbInvariant } from "../util/invariants.js";
import {
LongpollResult,
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
constructTaskIdentifier,
runLongpollAsync,
} from "./common.js";
@@ -184,7 +184,7 @@ async function longpollKycStatus(
exchangeUrl: string,
kycInfo: KycPendingInfo,
userType: KycUserType,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPullCredit,
pursePub,
@@ -242,14 +242,14 @@ async function longpollKycStatus(
}
});
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
async function processPeerPullCreditAbortingDeletePurse(
ws: InternalWalletState,
peerPullIni: PeerPullPaymentInitiationRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { pursePub, pursePriv } = peerPullIni;
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushDebit,
@@ -296,13 +296,13 @@ async function processPeerPullCreditAbortingDeletePurse(
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
async function handlePeerPullCreditWithdrawing(
ws: InternalWalletState,
pullIni: PeerPullPaymentInitiationRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
if (!pullIni.withdrawalGroupId) {
throw Error("invalid db state (withdrawing, but no withdrawal group ID");
}
@@ -346,17 +346,17 @@ async function handlePeerPullCreditWithdrawing(
});
notifyTransition(ws, transactionId, transitionInfo);
if (finished) {
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
} else {
// FIXME: Return indicator that we depend on the other operation!
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
}
async function handlePeerPullCreditCreatePurse(
ws: InternalWalletState,
pullIni: PeerPullPaymentInitiationRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const purseFee = Amounts.stringify(Amounts.zeroOfAmount(pullIni.amount));
const pursePub = pullIni.pursePub;
const mergeReserve = await ws.db
@@ -447,16 +447,13 @@ async function handlePeerPullCreditCreatePurse(
await tx.peerPullPaymentInitiations.put(pi2);
});
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
export async function processPeerPullCredit(
ws: InternalWalletState,
pursePub: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const pullIni = await ws.db
.mktx((x) => [x.peerPullPaymentInitiations])
.runReadOnly(async (tx) => {
@@ -475,7 +472,7 @@ export async function processPeerPullCredit(
if (ws.activeLongpoll[retryTag]) {
logger.info("peer-pull-credit already in long-polling, returning!");
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
@@ -483,10 +480,7 @@ export async function processPeerPullCredit(
switch (pullIni.status) {
case PeerPullPaymentInitiationStatus.Done: {
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
case PeerPullPaymentInitiationStatus.PendingReady:
runLongpollAsync(ws, retryTag, async (cancellationToken) =>
@@ -496,7 +490,7 @@ export async function processPeerPullCredit(
"returning early from processPeerPullCredit for long-polling in background",
);
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
case PeerPullPaymentInitiationStatus.PendingMergeKycRequired: {
if (!pullIni.kycInfo) {
@@ -528,14 +522,14 @@ export async function processPeerPullCredit(
assertUnreachable(pullIni.status);
}
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
async function processPeerPullCreditKycRequired(
ws: InternalWalletState,
peerIni: PeerPullPaymentInitiationRecord,
kycPending: WalletKycUuid,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPullCredit,
pursePub: peerIni.pursePub,
@@ -560,10 +554,7 @@ async function processPeerPullCreditKycRequired(
kycStatusRes.status === HttpStatusCode.NoContent
) {
logger.warn("kyc requested, but already fulfilled");
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusRes.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
@@ -574,7 +565,7 @@ async function processPeerPullCreditKycRequired(
if (!peerInc) {
return {
transitionInfo: undefined,
- result: OperationAttemptResult.finishedEmpty(),
+ result: TaskRunResult.finished(),
};
}
const oldTxState = computePeerPullCreditTransactionState(peerInc);
@@ -589,8 +580,8 @@ async function processPeerPullCreditKycRequired(
await tx.peerPullPaymentInitiations.put(peerInc);
// We'll remove this eventually! New clients should rely on the
// kycUrl field of the transaction, not the error code.
- const res: OperationAttemptResult = {
- type: OperationAttemptResultType.Error,
+ const res: TaskRunResult = {
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED,
{
@@ -604,10 +595,7 @@ async function processPeerPullCreditKycRequired(
};
});
notifyTransition(ws, transactionId, transitionInfo);
- return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
- };
+ return TaskRunResult.pending();
} else {
throw Error(`unexpected response from kyc-check (${kycStatusRes.status})`);
}
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts
index 9d8fabfb2..1aa332439 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts
@@ -62,8 +62,8 @@ import {
import { assertUnreachable } from "../util/assertUnreachable.js";
import { checkLogicInvariant } from "../util/invariants.js";
import {
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
TaskIdentifiers,
constructTaskIdentifier,
runTaskWithErrorReporting,
@@ -89,12 +89,12 @@ async function handlePurseCreationConflict(
ws: InternalWalletState,
peerPullInc: PeerPullPaymentIncomingRecord,
resp: HttpResponse,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const pursePub = peerPullInc.pursePub;
const errResp = await readTalerErrorResponse(resp);
if (errResp.code !== TalerErrorCode.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS) {
await failPeerPullDebitTransaction(ws, pursePub);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
// FIXME: Properly parse!
@@ -167,13 +167,13 @@ async function handlePurseCreationConflict(
}
await tx.peerPullPaymentIncoming.put(myPpi);
});
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
async function processPeerPullDebitPendingDeposit(
ws: InternalWalletState,
peerPullInc: PeerPullPaymentIncomingRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const peerPullPaymentIncomingId = peerPullInc.peerPullPaymentIncomingId;
const pursePub = peerPullInc.pursePub;
@@ -299,21 +299,18 @@ async function processPeerPullDebitPendingDeposit(
default: {
const errResp = await readTalerErrorResponse(httpResp);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: errResp,
};
}
}
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
async function processPeerPullDebitAbortingRefresh(
ws: InternalWalletState,
peerPullInc: PeerPullPaymentIncomingRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const peerPullPaymentIncomingId = peerPullInc.peerPullPaymentIncomingId;
const abortRefreshGroupId = peerPullInc.abortRefreshGroupId;
checkLogicInvariant(!!abortRefreshGroupId);
@@ -357,13 +354,13 @@ async function processPeerPullDebitAbortingRefresh(
});
notifyTransition(ws, transactionId, transitionInfo);
// FIXME: Shouldn't this be finished in some cases?!
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
export async function processPeerPullDebit(
ws: InternalWalletState,
peerPullPaymentIncomingId: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const peerPullInc = await ws.db
.mktx((x) => [x.peerPullPaymentIncoming])
.runReadOnly(async (tx) => {
@@ -379,10 +376,7 @@ export async function processPeerPullDebit(
case PeerPullDebitRecordStatus.AbortingRefresh:
return await processPeerPullDebitAbortingRefresh(ws, peerPullInc);
}
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
export async function confirmPeerPullDebit(
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
index 3e5750af7..e76b934fa 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
@@ -62,8 +62,8 @@ import {
import { assertUnreachable } from "../util/assertUnreachable.js";
import { checkDbInvariant } from "../util/invariants.js";
import {
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
constructTaskIdentifier,
runLongpollAsync,
} from "./common.js";
@@ -233,7 +233,7 @@ async function longpollKycStatus(
exchangeUrl: string,
kycInfo: KycPendingInfo,
userType: KycUserType,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
peerPushPaymentIncomingId,
@@ -293,7 +293,7 @@ async function longpollKycStatus(
}
});
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
@@ -301,7 +301,7 @@ async function processPeerPushCreditKycRequired(
ws: InternalWalletState,
peerInc: PeerPushPaymentIncomingRecord,
kycPending: WalletKycUuid,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
peerPushPaymentIncomingId: peerInc.peerPushPaymentIncomingId,
@@ -326,10 +326,7 @@ async function processPeerPushCreditKycRequired(
kycStatusRes.status === HttpStatusCode.NoContent
) {
logger.warn("kyc requested, but already fulfilled");
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
} else if (kycStatusRes.status === HttpStatusCode.Accepted) {
const kycStatus = await kycStatusRes.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
@@ -342,7 +339,7 @@ async function processPeerPushCreditKycRequired(
if (!peerInc) {
return {
transitionInfo: undefined,
- result: OperationAttemptResult.finishedEmpty(),
+ result: TaskRunResult.finished(),
};
}
const oldTxState = computePeerPushCreditTransactionState(peerInc);
@@ -356,8 +353,8 @@ async function processPeerPushCreditKycRequired(
await tx.peerPushPaymentIncoming.put(peerInc);
// We'll remove this eventually! New clients should rely on the
// kycUrl field of the transaction, not the error code.
- const res: OperationAttemptResult = {
- type: OperationAttemptResultType.Error,
+ const res: TaskRunResult = {
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED,
{
@@ -381,7 +378,7 @@ async function handlePendingMerge(
ws: InternalWalletState,
peerInc: PeerPushPaymentIncomingRecord,
contractTerms: PeerContractTerms,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { peerPushPaymentIncomingId } = peerInc;
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushCredit,
@@ -506,16 +503,13 @@ async function handlePendingMerge(
);
notifyTransition(ws, transactionId, txRes?.peerPushCreditTransition);
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
async function handlePendingWithdrawing(
ws: InternalWalletState,
peerInc: PeerPushPaymentIncomingRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
if (!peerInc.withdrawalGroupId) {
throw Error("invalid db state (withdrawing, but no withdrawal group ID");
}
@@ -561,17 +555,17 @@ async function handlePendingWithdrawing(
});
notifyTransition(ws, transactionId, transitionInfo);
if (finished) {
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
} else {
// FIXME: Return indicator that we depend on the other operation!
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
}
export async function processPeerPushCredit(
ws: InternalWalletState,
peerPushPaymentIncomingId: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
let peerInc: PeerPushPaymentIncomingRecord | undefined;
let contractTerms: PeerContractTerms | undefined;
await ws.db
@@ -617,7 +611,7 @@ export async function processPeerPushCredit(
return handlePendingWithdrawing(ws, peerInc);
default:
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
}
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
index 9ae94fff8..c853bc0ef 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts
@@ -61,8 +61,8 @@ import { PendingTaskType } from "../pending-types.js";
import { assertUnreachable } from "../util/assertUnreachable.js";
import { checkLogicInvariant } from "../util/invariants.js";
import {
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
constructTaskIdentifier,
runLongpollAsync,
spendCoins,
@@ -110,12 +110,12 @@ async function handlePurseCreationConflict(
ws: InternalWalletState,
peerPushInitiation: PeerPushPaymentInitiationRecord,
resp: HttpResponse,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const pursePub = peerPushInitiation.pursePub;
const errResp = await readTalerErrorResponse(resp);
if (errResp.code !== TalerErrorCode.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS) {
await failPeerPushDebitTransaction(ws, pursePub);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
// FIXME: Properly parse!
@@ -176,13 +176,13 @@ async function handlePurseCreationConflict(
}
await tx.peerPushPaymentInitiations.put(myPpi);
});
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
async function processPeerPushDebitCreateReserve(
ws: InternalWalletState,
peerPushInitiation: PeerPushPaymentInitiationRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.info("processing peer-push-debit pending(create-reserve)");
const pursePub = peerPushInitiation.pursePub;
const purseExpiration = peerPushInitiation.purseExpiration;
@@ -264,7 +264,7 @@ async function processPeerPushDebitCreateReserve(
case HttpStatusCode.Forbidden: {
// FIXME: Store this error!
await failPeerPushDebitTransaction(ws, pursePub);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
case HttpStatusCode.Conflict: {
// Handle double-spending
@@ -273,7 +273,7 @@ async function processPeerPushDebitCreateReserve(
default: {
const errResp = await readTalerErrorResponse(httpResp);
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: errResp,
};
}
@@ -289,13 +289,13 @@ async function processPeerPushDebitCreateReserve(
stTo: PeerPushPaymentInitiationStatus.PendingReady,
});
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
async function processPeerPushDebitAbortingDeletePurse(
ws: InternalWalletState,
peerPushInitiation: PeerPushPaymentInitiationRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { pursePub, pursePriv } = peerPushInitiation;
const transactionId = constructTransactionIdentifier({
tag: TransactionType.PeerPushDebit,
@@ -364,7 +364,7 @@ async function processPeerPushDebitAbortingDeletePurse(
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
interface SimpleTransition {
@@ -406,7 +406,7 @@ async function transitionPeerPushDebitTransaction(
async function processPeerPushDebitAbortingRefresh(
ws: InternalWalletState,
peerPushInitiation: PeerPushPaymentInitiationRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const pursePub = peerPushInitiation.pursePub;
const abortRefreshGroupId = peerPushInitiation.abortRefreshGroupId;
checkLogicInvariant(!!abortRefreshGroupId);
@@ -448,7 +448,7 @@ async function processPeerPushDebitAbortingRefresh(
});
notifyTransition(ws, transactionId, transitionInfo);
// FIXME: Shouldn't this be finished in some cases?!
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
}
/**
@@ -457,7 +457,7 @@ async function processPeerPushDebitAbortingRefresh(
async function processPeerPushDebitReady(
ws: InternalWalletState,
peerPushInitiation: PeerPushPaymentInitiationRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.info("processing peer-push-debit pending(ready)");
const pursePub = peerPushInitiation.pursePub;
const retryTag = constructTaskIdentifier({
@@ -520,14 +520,14 @@ async function processPeerPushDebitReady(
"returning early from peer-push-debit for long-polling in background",
);
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
export async function processPeerPushDebit(
ws: InternalWalletState,
pursePub: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const peerPushInitiation = await ws.db
.mktx((x) => [x.peerPushPaymentInitiations])
.runReadOnly(async (tx) => {
@@ -546,7 +546,7 @@ export async function processPeerPushDebit(
if (ws.activeLongpoll[retryTag]) {
logger.info("peer-push-debit task already in long-polling, returning!");
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
@@ -567,10 +567,7 @@ export async function processPeerPushDebit(
}
}
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
/**
diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts
index 056aa83b8..c8c766d1b 100644
--- a/packages/taler-wallet-core/src/operations/recoup.ts
+++ b/packages/taler-wallet-core/src/operations/recoup.ts
@@ -55,7 +55,7 @@ import { checkDbInvariant } from "../util/invariants.js";
import { GetReadWriteAccess } from "../util/query.js";
import { createRefreshGroup, processRefreshGroup } from "./refresh.js";
import { internalCreateWithdrawalGroup } from "./withdraw.js";
-import { OperationAttemptResult } from "./common.js";
+import { TaskRunResult } from "./common.js";
const logger = new Logger("operations/recoup.ts");
@@ -289,18 +289,18 @@ async function recoupRefreshCoin(
export async function processRecoupGroup(
ws: InternalWalletState,
recoupGroupId: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
let recoupGroup = await ws.db
.mktx((x) => [x.recoupGroups])
.runReadOnly(async (tx) => {
return tx.recoupGroups.get(recoupGroupId);
});
if (!recoupGroup) {
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
if (recoupGroup.timestampFinished) {
logger.trace("recoup group finished");
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
const ps = recoupGroup.coinPubs.map(async (x, i) => {
try {
@@ -318,12 +318,12 @@ export async function processRecoupGroup(
return tx.recoupGroups.get(recoupGroupId);
});
if (!recoupGroup) {
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
for (const b of recoupGroup.recoupFinishedPerCoin) {
if (!b) {
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
}
@@ -408,7 +408,7 @@ export async function processRecoupGroup(
}
await tx.recoupGroups.put(rg2);
});
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
export async function createRecoupGroup(
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts
index c1a16badf..caa5f9c9f 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -89,8 +89,8 @@ import {
constructTaskIdentifier,
makeCoinAvailable,
makeCoinsVisible,
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
} from "./common.js";
import { updateExchangeFromUrl } from "./exchanges.js";
import {
@@ -770,23 +770,17 @@ export async function processRefreshGroup(
ws: InternalWalletState,
refreshGroupId: string,
options: Record<string, never> = {},
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.info(`processing refresh group ${refreshGroupId}`);
const refreshGroup = await ws.db
.mktx((x) => [x.refreshGroups])
.runReadOnly(async (tx) => tx.refreshGroups.get(refreshGroupId));
if (!refreshGroup) {
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished()
}
if (refreshGroup.timestampFinished) {
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
// Process refresh sessions of the group in parallel.
logger.trace("processing refresh sessions for old coins");
@@ -823,14 +817,11 @@ export async function processRefreshGroup(
logger.warn(`exception: ${e}`);
}
if (inShutdown) {
- return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
- };
+ return TaskRunResult.pending();
}
if (errors.length > 0) {
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_REFRESH_GROUP_INCOMPLETE,
{
@@ -841,10 +832,7 @@ export async function processRefreshGroup(
};
}
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.pending();
}
async function processRefreshSession(
@@ -1122,7 +1110,7 @@ function getAutoRefreshExecuteThreshold(d: DenominationRecord): AbsoluteTime {
export async function autoRefresh(
ws: InternalWalletState,
exchangeBaseUrl: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.info(`doing auto-refresh check for '${exchangeBaseUrl}'`);
// We must make sure that the exchange is up-to-date so that
@@ -1204,7 +1192,7 @@ export async function autoRefresh(
AbsoluteTime.toPreciseTimestamp(minCheckThreshold);
await tx.exchanges.put(exchange);
});
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
export function computeRefreshTransactionState(
diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts
index ece71439c..77e218cd7 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -24,6 +24,7 @@ import {
Duration,
IntegrationTestV2Args,
Logger,
+ NotificationType,
stringToBytes,
TestPayResult,
WithdrawTestBalanceRequest,
@@ -64,6 +65,7 @@ import {
confirmPeerPushCredit,
} from "./pay-peer-push-credit.js";
import { initiatePeerPushDebit } from "./pay-peer-push-debit.js";
+import { OpenedPromise, openPromise } from "../index.js";
const logger = new Logger("operations/testing.ts");
@@ -445,6 +447,18 @@ export async function runIntegrationTest(
logger.trace("integration test: all done!");
}
+async function waitUntilDone(ws: InternalWalletState): Promise<void> {
+ let p: OpenedPromise<void> | undefined = undefined;
+ ws.addNotificationListener((notif) => {
+ if (!p) {
+ return;
+ }
+ if (notif.type === NotificationType.TransactionStateTransition) {
+ p.resolve();
+ }
+ });
+}
+
export async function runIntegrationTest2(
ws: InternalWalletState,
args: IntegrationTestV2Args,
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts
index 18ef03c51..e56fb1e8d 100644
--- a/packages/taler-wallet-core/src/operations/tip.ts
+++ b/packages/taler-wallet-core/src/operations/tip.ts
@@ -62,8 +62,8 @@ import {
constructTaskIdentifier,
makeCoinAvailable,
makeCoinsVisible,
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
} from "./common.js";
import { updateExchangeFromUrl } from "./exchanges.js";
import {
@@ -241,17 +241,14 @@ export async function prepareTip(
export async function processTip(
ws: InternalWalletState,
walletTipId: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const tipRecord = await ws.db
.mktx((x) => [x.tips])
.runReadOnly(async (tx) => {
return tx.tips.get(walletTipId);
});
if (!tipRecord) {
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
switch (tipRecord.status) {
@@ -259,10 +256,7 @@ export async function processTip(
case TipRecordStatus.DialogAccept:
case TipRecordStatus.Done:
case TipRecordStatus.SuspendidPickup:
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
const transactionId = constructTransactionIdentifier({
@@ -324,7 +318,7 @@ export async function processTip(
logger.trace(`got transient tip error`);
// FIXME: wrap in another error code that indicates a transient error
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
getHttpResponseErrorDetails(merchantResp),
@@ -376,7 +370,7 @@ export async function processTip(
if (!isValid) {
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_TIPPING_COIN_SIGNATURE_INVALID,
{},
@@ -430,10 +424,7 @@ export async function processTip(
notifyTransition(ws, transactionId, transitionInfo);
ws.notify({ type: NotificationType.BalanceChange });
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
export async function acceptTip(
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 1362ca278..f972d3cb1 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -90,8 +90,8 @@ import {
} from "@gnu-taler/taler-util";
import { InternalWalletState } from "../internal-wallet-state.js";
import {
- OperationAttemptResult,
- OperationAttemptResultType,
+ TaskRunResult,
+ TaskRunResultType,
TaskIdentifiers,
constructTaskIdentifier,
makeCoinAvailable,
@@ -1326,7 +1326,7 @@ export interface WithdrawalGroupContext {
async function processWithdrawalGroupAbortingBank(
ws: InternalWalletState,
withdrawalGroup: WithdrawalGroupRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { withdrawalGroupId } = withdrawalGroup;
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
@@ -1363,10 +1363,7 @@ async function processWithdrawalGroupAbortingBank(
};
});
notifyTransition(ws, transactionId, transitionInfo);
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
/**
@@ -1413,7 +1410,7 @@ async function transitionKycSatisfied(
async function processWithdrawalGroupPendingKyc(
ws: InternalWalletState,
withdrawalGroup: WithdrawalGroupRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const userType = "individual";
const kycInfo = withdrawalGroup.kycPending;
if (!kycInfo) {
@@ -1456,13 +1453,13 @@ async function processWithdrawalGroupPendingKyc(
);
}
});
- return OperationAttemptResult.longpoll();
+ return TaskRunResult.longpoll();
}
async function processWithdrawalGroupPendingReady(
ws: InternalWalletState,
withdrawalGroup: WithdrawalGroupRecord,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
const { withdrawalGroupId } = withdrawalGroup;
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
@@ -1494,7 +1491,7 @@ async function processWithdrawalGroupPendingReady(
};
});
notifyTransition(ws, transactionId, transitionInfo);
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
}
const numTotalCoins = withdrawalGroup.denomsSel.selectedDenoms
@@ -1608,7 +1605,7 @@ async function processWithdrawalGroupPendingReady(
if (numPlanchetErrors > 0) {
return {
- type: OperationAttemptResultType.Error,
+ type: TaskRunResultType.Error,
errorDetail: makeErrorDetail(
TalerErrorCode.WALLET_WITHDRAWAL_GROUP_INCOMPLETE,
{
@@ -1619,16 +1616,13 @@ async function processWithdrawalGroupPendingReady(
};
}
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
}
export async function processWithdrawalGroup(
ws: InternalWalletState,
withdrawalGroupId: string,
-): Promise<OperationAttemptResult> {
+): Promise<TaskRunResult> {
logger.trace("processing withdrawal group", withdrawalGroupId);
const withdrawalGroup = await ws.db
.mktx((x) => [x.withdrawalGroups])
@@ -1646,7 +1640,7 @@ export async function processWithdrawalGroup(
if (ws.activeLongpoll[retryTag]) {
logger.info("withdrawal group already in long-polling, returning!");
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
@@ -1663,7 +1657,7 @@ export async function processWithdrawalGroup(
"returning early from withdrawal for long-polling in background",
);
return {
- type: OperationAttemptResultType.Longpoll,
+ type: TaskRunResultType.Longpoll,
};
}
case WithdrawalGroupStatus.PendingWaitConfirmBank: {
@@ -1671,15 +1665,9 @@ export async function processWithdrawalGroup(
switch (res.status) {
case BankStatusResultCode.Aborted:
case BankStatusResultCode.Done:
- return {
- type: OperationAttemptResultType.Finished,
- result: undefined,
- };
+ return TaskRunResult.finished();
case BankStatusResultCode.Waiting: {
- return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
- };
+ return TaskRunResult.pending();
}
}
break;
@@ -1687,14 +1675,11 @@ export async function processWithdrawalGroup(
case WithdrawalGroupStatus.Finished:
case WithdrawalGroupStatus.FailedBankAborted: {
// FIXME
- return {
- type: OperationAttemptResultType.Pending,
- result: undefined,
- };
+ return TaskRunResult.pending();
}
case WithdrawalGroupStatus.PendingAml:
// FIXME: Handle this case, withdrawal doesn't support AML yet.
- return OperationAttemptResult.pendingEmpty();
+ return TaskRunResult.pending();
case WithdrawalGroupStatus.PendingKyc:
return processWithdrawalGroupPendingKyc(ws, withdrawalGroup);
case WithdrawalGroupStatus.PendingReady:
@@ -1713,7 +1698,7 @@ export async function processWithdrawalGroup(
case WithdrawalGroupStatus.SuspendedRegisteringBank:
case WithdrawalGroupStatus.SuspendedWaitConfirmBank:
// Nothing to do.
- return OperationAttemptResult.finishedEmpty();
+ return TaskRunResult.finished();
default:
assertUnreachable(withdrawalGroup.status);
}