query transaction status for deposit
This commit is contained in:
parent
e034f1045c
commit
fc38d0da95
@ -850,6 +850,13 @@ export enum RefreshOperationStatus {
|
|||||||
FinishedWithError = 51 /* DORMANT_START + 1 */,
|
FinishedWithError = 51 /* DORMANT_START + 1 */,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TransactionStatus {
|
||||||
|
Unknown = 10,
|
||||||
|
Accepted = 20,
|
||||||
|
KycRequired = 30,
|
||||||
|
Wired = 40,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional information about the reason of a refresh.
|
* Additional information about the reason of a refresh.
|
||||||
*/
|
*/
|
||||||
@ -1652,6 +1659,8 @@ export interface DepositGroupRecord {
|
|||||||
timestampFinished: TalerProtocolTimestamp | undefined;
|
timestampFinished: TalerProtocolTimestamp | undefined;
|
||||||
|
|
||||||
operationStatus: OperationStatus;
|
operationStatus: OperationStatus;
|
||||||
|
|
||||||
|
transactionPerCoin: TransactionStatus[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2416,6 +2425,20 @@ export const walletDbFixups: FixupDescription[] = [
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "DepositGroupRecord_transactionPerCoin",
|
||||||
|
async fn(tx): Promise<void> {
|
||||||
|
await tx.depositGroups.iter().forEachAsync(async (dg) => {
|
||||||
|
if (dg.transactionPerCoin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dg.transactionPerCoin = dg.depositedPerCoin.map(
|
||||||
|
(c) => TransactionStatus.Unknown,
|
||||||
|
);
|
||||||
|
await tx.depositGroups.put(dg);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const logger = new Logger("db.ts");
|
const logger = new Logger("db.ts");
|
||||||
|
@ -24,7 +24,9 @@ import {
|
|||||||
CancellationToken,
|
CancellationToken,
|
||||||
canonicalJson,
|
canonicalJson,
|
||||||
codecForDepositSuccess,
|
codecForDepositSuccess,
|
||||||
MerchantContractTerms,
|
codecForTackTransactionAccepted,
|
||||||
|
codecForTackTransactionWired,
|
||||||
|
CoinDepositPermission,
|
||||||
CreateDepositGroupRequest,
|
CreateDepositGroupRequest,
|
||||||
CreateDepositGroupResponse,
|
CreateDepositGroupResponse,
|
||||||
DepositGroupFees,
|
DepositGroupFees,
|
||||||
@ -34,23 +36,27 @@ import {
|
|||||||
GetFeeForDepositRequest,
|
GetFeeForDepositRequest,
|
||||||
getRandomBytes,
|
getRandomBytes,
|
||||||
hashWire,
|
hashWire,
|
||||||
|
HttpStatusCode,
|
||||||
Logger,
|
Logger,
|
||||||
|
MerchantContractTerms,
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
PayCoinSelection,
|
PayCoinSelection,
|
||||||
PrepareDepositRequest,
|
PrepareDepositRequest,
|
||||||
PrepareDepositResponse,
|
PrepareDepositResponse,
|
||||||
RefreshReason,
|
RefreshReason,
|
||||||
|
TalerErrorCode,
|
||||||
TalerProtocolTimestamp,
|
TalerProtocolTimestamp,
|
||||||
TrackDepositGroupRequest,
|
TrackDepositGroupRequest,
|
||||||
TrackDepositGroupResponse,
|
TrackDepositGroupResponse,
|
||||||
|
TrackTransaction,
|
||||||
TransactionType,
|
TransactionType,
|
||||||
URL,
|
URL,
|
||||||
TalerErrorCode,
|
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
DepositGroupRecord,
|
DepositGroupRecord,
|
||||||
OperationStatus,
|
OperationStatus,
|
||||||
|
TransactionStatus,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { TalerError } from "../errors.js";
|
import { TalerError } from "../errors.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
@ -111,10 +117,12 @@ export async function processDepositGroup(
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (let i = 0; i < depositPermissions.length; i++) {
|
for (let i = 0; i < depositPermissions.length; i++) {
|
||||||
if (depositGroup.depositedPerCoin[i]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const perm = depositPermissions[i];
|
const perm = depositPermissions[i];
|
||||||
|
|
||||||
|
let updatedDeposit: boolean | undefined = undefined;
|
||||||
|
let updatedTxStatus: TransactionStatus | undefined = undefined;
|
||||||
|
|
||||||
|
if (!depositGroup.depositedPerCoin[i]) {
|
||||||
const requestBody: ExchangeDepositRequest = {
|
const requestBody: ExchangeDepositRequest = {
|
||||||
contribution: Amounts.stringify(perm.contribution),
|
contribution: Amounts.stringify(perm.contribution),
|
||||||
merchant_payto_uri: depositGroup.wire.payto_uri,
|
merchant_payto_uri: depositGroup.wire.payto_uri,
|
||||||
@ -138,6 +146,15 @@ export async function processDepositGroup(
|
|||||||
cancellationToken: options.cancellationToken,
|
cancellationToken: options.cancellationToken,
|
||||||
});
|
});
|
||||||
await readSuccessResponseJsonOrThrow(httpResp, codecForDepositSuccess());
|
await readSuccessResponseJsonOrThrow(httpResp, codecForDepositSuccess());
|
||||||
|
updatedDeposit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depositGroup.transactionPerCoin[i] !== TransactionStatus.Wired) {
|
||||||
|
const track = await trackDepositPermission(ws, depositGroup, perm);
|
||||||
|
updatedTxStatus = txStatusFromTrack(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedTxStatus !== undefined || updatedDeposit !== undefined) {
|
||||||
await ws.db
|
await ws.db
|
||||||
.mktx((x) => [x.depositGroups])
|
.mktx((x) => [x.depositGroups])
|
||||||
.runReadWrite(async (tx) => {
|
.runReadWrite(async (tx) => {
|
||||||
@ -145,10 +162,16 @@ export async function processDepositGroup(
|
|||||||
if (!dg) {
|
if (!dg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dg.depositedPerCoin[i] = true;
|
if (updatedDeposit !== undefined) {
|
||||||
|
dg.depositedPerCoin[i] = updatedDeposit;
|
||||||
|
}
|
||||||
|
if (updatedTxStatus !== undefined) {
|
||||||
|
dg.transactionPerCoin[i] = updatedTxStatus;
|
||||||
|
}
|
||||||
await tx.depositGroups.put(dg);
|
await tx.depositGroups.put(dg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await ws.db
|
await ws.db
|
||||||
.mktx((x) => [x.depositGroups])
|
.mktx((x) => [x.depositGroups])
|
||||||
@ -157,13 +180,17 @@ export async function processDepositGroup(
|
|||||||
if (!dg) {
|
if (!dg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let allDeposited = true;
|
let allDepositedAndWired = true;
|
||||||
for (const d of depositGroup.depositedPerCoin) {
|
for (let i = 0; i < depositGroup.depositedPerCoin.length; i++) {
|
||||||
if (!d) {
|
if (
|
||||||
allDeposited = false;
|
!depositGroup.depositedPerCoin[i] ||
|
||||||
|
depositGroup.transactionPerCoin[i] !== TransactionStatus.Wired
|
||||||
|
) {
|
||||||
|
allDepositedAndWired = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allDeposited) {
|
if (allDepositedAndWired) {
|
||||||
dg.timestampFinished = TalerProtocolTimestamp.now();
|
dg.timestampFinished = TalerProtocolTimestamp.now();
|
||||||
dg.operationStatus = OperationStatus.Finished;
|
dg.operationStatus = OperationStatus.Finished;
|
||||||
await tx.depositGroups.put(dg);
|
await tx.depositGroups.put(dg);
|
||||||
@ -172,14 +199,24 @@ export async function processDepositGroup(
|
|||||||
return OperationAttemptResult.finishedEmpty();
|
return OperationAttemptResult.finishedEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function txStatusFromTrack(t: TrackTransaction): TransactionStatus {
|
||||||
|
if (t.type === "accepted") {
|
||||||
|
if (!t.kyc_ok && t.requirement_row !== undefined) {
|
||||||
|
return TransactionStatus.KycRequired;
|
||||||
|
}
|
||||||
|
return TransactionStatus.Accepted;
|
||||||
|
}
|
||||||
|
if (t.type === "wired") {
|
||||||
|
return TransactionStatus.Wired;
|
||||||
|
}
|
||||||
|
return TransactionStatus.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
export async function trackDepositGroup(
|
export async function trackDepositGroup(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
req: TrackDepositGroupRequest,
|
req: TrackDepositGroupRequest,
|
||||||
): Promise<TrackDepositGroupResponse> {
|
): Promise<TrackDepositGroupResponse> {
|
||||||
const responses: {
|
const responses: TrackTransaction[] = [];
|
||||||
status: number;
|
|
||||||
body: any;
|
|
||||||
}[] = [];
|
|
||||||
const depositGroup = await ws.db
|
const depositGroup = await ws.db
|
||||||
.mktx((x) => [x.depositGroups])
|
.mktx((x) => [x.depositGroups])
|
||||||
.runReadOnly(async (tx) => {
|
.runReadOnly(async (tx) => {
|
||||||
@ -200,9 +237,21 @@ export async function trackDepositGroup(
|
|||||||
contractData,
|
contractData,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for (const dp of depositPermissions) {
|
||||||
|
const track = await trackDepositPermission(ws, depositGroup, dp);
|
||||||
|
responses.push(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { responses };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function trackDepositPermission(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
depositGroup: DepositGroupRecord,
|
||||||
|
dp: CoinDepositPermission,
|
||||||
|
): Promise<TrackTransaction> {
|
||||||
const wireHash = depositGroup.contractTermsRaw.h_wire;
|
const wireHash = depositGroup.contractTermsRaw.h_wire;
|
||||||
|
|
||||||
for (const dp of depositPermissions) {
|
|
||||||
const url = new URL(
|
const url = new URL(
|
||||||
`deposits/${wireHash}/${depositGroup.merchantPub}/${depositGroup.contractTermsHash}/${dp.coin_pub}`,
|
`deposits/${wireHash}/${depositGroup.merchantPub}/${depositGroup.contractTermsHash}/${dp.coin_pub}`,
|
||||||
dp.exchange_url,
|
dp.exchange_url,
|
||||||
@ -216,15 +265,27 @@ export async function trackDepositGroup(
|
|||||||
});
|
});
|
||||||
url.searchParams.set("merchant_sig", sigResp.sig);
|
url.searchParams.set("merchant_sig", sigResp.sig);
|
||||||
const httpResp = await ws.http.get(url.href);
|
const httpResp = await ws.http.get(url.href);
|
||||||
const body = await httpResp.json();
|
switch (httpResp.status) {
|
||||||
responses.push({
|
case HttpStatusCode.Accepted: {
|
||||||
body,
|
const accepted = await readSuccessResponseJsonOrThrow(
|
||||||
status: httpResp.status,
|
httpResp,
|
||||||
});
|
codecForTackTransactionAccepted(),
|
||||||
|
);
|
||||||
|
return { type: "accepted", ...accepted };
|
||||||
|
}
|
||||||
|
case HttpStatusCode.Ok: {
|
||||||
|
const wired = await readSuccessResponseJsonOrThrow(
|
||||||
|
httpResp,
|
||||||
|
codecForTackTransactionWired(),
|
||||||
|
);
|
||||||
|
return { type: "wired", ...wired };
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw Error(
|
||||||
|
`unexpected response from track-transaction (${httpResp.status})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
|
||||||
responses,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFeeForDeposit(
|
export async function getFeeForDeposit(
|
||||||
@ -491,6 +552,9 @@ export async function createDepositGroup(
|
|||||||
noncePub: noncePair.pub,
|
noncePub: noncePair.pub,
|
||||||
timestampCreated: AbsoluteTime.toTimestamp(now),
|
timestampCreated: AbsoluteTime.toTimestamp(now),
|
||||||
timestampFinished: undefined,
|
timestampFinished: undefined,
|
||||||
|
transactionPerCoin: payCoinSel.coinSel.coinPubs.map(
|
||||||
|
() => TransactionStatus.Unknown,
|
||||||
|
),
|
||||||
payCoinSelection: payCoinSel.coinSel,
|
payCoinSelection: payCoinSel.coinSel,
|
||||||
payCoinSelectionUid: encodeCrock(getRandomBytes(32)),
|
payCoinSelectionUid: encodeCrock(getRandomBytes(32)),
|
||||||
depositedPerCoin: payCoinSel.coinSel.coinPubs.map(() => false),
|
depositedPerCoin: payCoinSel.coinSel.coinPubs.map(() => false),
|
||||||
|
@ -53,6 +53,7 @@ import {
|
|||||||
WalletContractData,
|
WalletContractData,
|
||||||
PeerPushPaymentInitiationStatus,
|
PeerPushPaymentInitiationStatus,
|
||||||
PeerPullPaymentIncomingStatus,
|
PeerPullPaymentIncomingStatus,
|
||||||
|
TransactionStatus,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||||
import { assertUnreachable } from "../util/assertUnreachable.js";
|
import { assertUnreachable } from "../util/assertUnreachable.js";
|
||||||
@ -552,6 +553,13 @@ function buildTransactionForDeposit(
|
|||||||
TransactionType.Deposit,
|
TransactionType.Deposit,
|
||||||
dg.depositGroupId,
|
dg.depositGroupId,
|
||||||
),
|
),
|
||||||
|
wireTransferProgress:
|
||||||
|
(100 *
|
||||||
|
dg.transactionPerCoin.reduce(
|
||||||
|
(prev, cur) => prev + (cur === TransactionStatus.Wired ? 1 : 0),
|
||||||
|
0,
|
||||||
|
)) /
|
||||||
|
dg.transactionPerCoin.length,
|
||||||
depositGroupId: dg.depositGroupId,
|
depositGroupId: dg.depositGroupId,
|
||||||
...(ort?.lastError ? { error: ort.lastError } : {}),
|
...(ort?.lastError ? { error: ort.lastError } : {}),
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user