wallet-core: rename OperationAttempt->TaskRun, do not allow task result values anymore
This commit is contained in:
parent
7523ffa910
commit
d4ee961387
@ -1754,6 +1754,7 @@ export interface CoreApiRequestEnvelope {
|
||||
operation: string;
|
||||
args: unknown;
|
||||
}
|
||||
|
||||
export type CoreApiResponse = CoreApiResponseSuccess | CoreApiResponseError;
|
||||
|
||||
export type CoreApiMessageEnvelope = CoreApiResponse | CoreApiNotification;
|
||||
|
@ -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);
|
||||
|
@ -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})`);
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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(
|
||||
|
@ -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})`);
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -171,6 +171,7 @@ import {
|
||||
import { setWalletDeviceId } from "./operations/backup/state.js";
|
||||
import { getBalanceDetail, getBalances } from "./operations/balance.js";
|
||||
import {
|
||||
TaskRunResult,
|
||||
getExchangeTosStatus,
|
||||
makeExchangeListItem,
|
||||
runTaskWithErrorReporting,
|
||||
@ -287,7 +288,6 @@ import {
|
||||
GetReadWriteAccess,
|
||||
} from "./util/query.js";
|
||||
import {
|
||||
OperationAttemptResult,
|
||||
TaskIdentifiers,
|
||||
} from "./operations/common.js";
|
||||
import { TimerAPI, TimerGroup } from "./util/timer.js";
|
||||
@ -320,7 +320,7 @@ const logger = new Logger("wallet.ts");
|
||||
async function callOperationHandler(
|
||||
ws: InternalWalletState,
|
||||
pending: PendingTaskInfo,
|
||||
): Promise<OperationAttemptResult> {
|
||||
): Promise<TaskRunResult> {
|
||||
switch (pending.type) {
|
||||
case PendingTaskType.ExchangeUpdate:
|
||||
return await updateExchangeFromUrlHandler(ws, pending.exchangeBaseUrl);
|
||||
|
@ -54,6 +54,11 @@ setPRNG(function (x: Uint8Array, n: number) {
|
||||
|
||||
const logger = new Logger("taler-wallet-embedded/index.ts");
|
||||
|
||||
/**
|
||||
* Sends JSON to the host application, i.e. the process that
|
||||
* runs the JavaScript interpreter (quickjs / qtart) to run
|
||||
* the embedded wallet.
|
||||
*/
|
||||
function sendNativeMessage(ev: CoreApiMessageEnvelope): void {
|
||||
const m = JSON.stringify(ev);
|
||||
qjsOs.postMessageToHost(m);
|
||||
@ -183,21 +188,25 @@ export function installNativeWalletListener(): void {
|
||||
const id = msg.id;
|
||||
logger.info(`native listener: got request for ${operation} (${id})`);
|
||||
|
||||
let respMsg: CoreApiResponse;
|
||||
try {
|
||||
respMsg = await handler.handleMessage(operation, id, msg.args ?? {});
|
||||
} catch (e) {
|
||||
respMsg = {
|
||||
type: "error",
|
||||
id,
|
||||
operation,
|
||||
error: getErrorDetailFromException(e),
|
||||
};
|
||||
if (operation === "anastasisReduce") {
|
||||
sendNativeMessage(respMsg);
|
||||
} else {
|
||||
let respMsg: CoreApiResponse;
|
||||
try {
|
||||
respMsg = await handler.handleMessage(operation, id, msg.args ?? {});
|
||||
} catch (e) {
|
||||
respMsg = {
|
||||
type: "error",
|
||||
id,
|
||||
operation,
|
||||
error: getErrorDetailFromException(e),
|
||||
};
|
||||
}
|
||||
logger.info(
|
||||
`native listener: sending back ${respMsg.type} message for operation ${operation} (${id})`,
|
||||
);
|
||||
sendNativeMessage(respMsg);
|
||||
}
|
||||
logger.info(
|
||||
`native listener: sending back ${respMsg.type} message for operation ${operation} (${id})`,
|
||||
);
|
||||
sendNativeMessage(respMsg);
|
||||
};
|
||||
|
||||
qjsOs.setMessageFromHostHandler((m) => onMessage(m));
|
||||
|
Loading…
Reference in New Issue
Block a user