aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations/deposits.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/operations/deposits.ts')
-rw-r--r--packages/taler-wallet-core/src/operations/deposits.ts93
1 files changed, 92 insertions, 1 deletions
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts
index 22283b7a8..c6cd4732c 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -53,12 +53,15 @@ import {
TrackDepositGroupRequest,
TrackDepositGroupResponse,
TrackTransaction,
+ TrackTransactionWired,
TransactionType,
URL,
+ WireFee,
} from "@gnu-taler/taler-util";
import {
DenominationRecord,
DepositGroupRecord,
+ ExchangeDetailsRecord,
OperationStatus,
TransactionStatus,
} from "../db.js";
@@ -157,7 +160,6 @@ export async function processDepositGroup(
const perm = depositPermissions[i];
let updatedDeposit: boolean | undefined = undefined;
- let updatedTxStatus: TransactionStatus | undefined = undefined;
if (!depositGroup.depositedPerCoin[i]) {
const requestBody: ExchangeDepositRequest = {
@@ -186,6 +188,17 @@ export async function processDepositGroup(
updatedDeposit = true;
}
+ let updatedTxStatus: TransactionStatus | undefined = undefined;
+ type ValueOf<T> = T[keyof T];
+
+ let newWiredTransaction:
+ | {
+ id: string;
+ value: ValueOf<NonNullable<DepositGroupRecord["trackingState"]>>;
+ }
+ | undefined;
+
+ let signature: string | undefined;
if (depositGroup.transactionPerCoin[i] !== TransactionStatus.Wired) {
const track = await trackDepositPermission(ws, depositGroup, perm);
@@ -207,6 +220,32 @@ export async function processDepositGroup(
}
} else if (track.type === "wired") {
updatedTxStatus = TransactionStatus.Wired;
+
+ const payto = parsePaytoUri(depositGroup.wire.payto_uri);
+ if (!payto) {
+ throw Error(`unparsable payto: ${depositGroup.wire.payto_uri}`);
+ }
+
+ const fee = await getExchangeWireFee(
+ ws,
+ payto.targetType,
+ perm.exchange_url,
+ track.execution_time,
+ );
+ const raw = Amounts.parseOrThrow(track.coin_contribution);
+ const wireFee = Amounts.parseOrThrow(fee.wireFee);
+ const effective = Amounts.sub(raw, wireFee).amount;
+
+ newWiredTransaction = {
+ value: {
+ amountRaw: Amounts.stringify(raw),
+ amountEffective: Amounts.stringify(effective),
+ exchangePub: track.exchange_pub,
+ timestampExecuted: track.execution_time,
+ wireTransferId: track.wtid,
+ },
+ id: track.exchange_sig,
+ };
} else {
updatedTxStatus = TransactionStatus.Unknown;
}
@@ -226,6 +265,14 @@ export async function processDepositGroup(
if (updatedTxStatus !== undefined) {
dg.transactionPerCoin[i] = updatedTxStatus;
}
+ if (newWiredTransaction) {
+ if (!dg.trackingState) {
+ dg.trackingState = {};
+ }
+
+ dg.trackingState[newWiredTransaction.id] =
+ newWiredTransaction.value;
+ }
await tx.depositGroups.put(dg);
});
}
@@ -257,6 +304,50 @@ export async function processDepositGroup(
return OperationAttemptResult.finishedEmpty();
}
+async function getExchangeWireFee(
+ ws: InternalWalletState,
+ wireType: string,
+ baseUrl: string,
+ time: TalerProtocolTimestamp,
+): Promise<WireFee> {
+ const exchangeDetails = await ws.db
+ .mktx((x) => [x.exchanges, x.exchangeDetails])
+ .runReadOnly(async (tx) => {
+ const ex = await tx.exchanges.get(baseUrl);
+ if (!ex || !ex.detailsPointer) return undefined;
+ return await tx.exchangeDetails.indexes.byPointer.get([
+ baseUrl,
+ ex.detailsPointer.currency,
+ ex.detailsPointer.masterPublicKey,
+ ]);
+ });
+
+ if (!exchangeDetails) {
+ throw Error(`exchange missing: ${baseUrl}`);
+ }
+
+ const fees = exchangeDetails.wireInfo.feesForType[wireType];
+ if (!fees || fees.length === 0) {
+ throw Error(
+ `exchange ${baseUrl} doesn't have fees for wire type ${wireType}`,
+ );
+ }
+ const fee = fees.find((x) => {
+ return AbsoluteTime.isBetween(
+ AbsoluteTime.fromTimestamp(time),
+ AbsoluteTime.fromTimestamp(x.startStamp),
+ AbsoluteTime.fromTimestamp(x.endStamp),
+ );
+ });
+ if (!fee) {
+ throw Error(
+ `exchange ${exchangeDetails.exchangeBaseUrl} doesn't have fees for wire type ${wireType} at ${time.t_s}`,
+ );
+ }
+
+ return fee;
+}
+
export async function trackDepositGroup(
ws: InternalWalletState,
req: TrackDepositGroupRequest,