aboutsummaryrefslogtreecommitdiff
path: root/src/operations
diff options
context:
space:
mode:
Diffstat (limited to 'src/operations')
-rw-r--r--src/operations/reserves.ts31
-rw-r--r--src/operations/transactions.ts110
-rw-r--r--src/operations/withdraw.ts4
3 files changed, 98 insertions, 47 deletions
diff --git a/src/operations/reserves.ts b/src/operations/reserves.ts
index 2761dfaf9..ff20ce9ba 100644
--- a/src/operations/reserves.ts
+++ b/src/operations/reserves.ts
@@ -53,7 +53,6 @@ import {
processWithdrawGroup,
getBankWithdrawalInfo,
denomSelectionInfoToState,
- getWithdrawDenomList,
} from "./withdraw";
import {
guardOperationException,
@@ -106,22 +105,25 @@ export async function createReserve(
let bankInfo: ReserveBankInfo | undefined;
if (req.bankWithdrawStatusUrl) {
- const denomSelInfo = await selectWithdrawalDenoms(
- ws,
- canonExchange,
- req.amount,
- );
- const denomSel = denomSelectionInfoToState(denomSelInfo);
bankInfo = {
statusUrl: req.bankWithdrawStatusUrl,
- amount: req.amount,
- bankWithdrawalGroupId: encodeCrock(getRandomBytes(32)),
- withdrawalStarted: false,
- denomSel,
};
}
+ const initialWithdrawalGroupId = encodeCrock(getRandomBytes(32));
+
+ const denomSelInfo = await selectWithdrawalDenoms(
+ ws,
+ canonExchange,
+ req.amount,
+ );
+ const initialDenomSel = denomSelectionInfoToState(denomSelInfo);
+
const reserveRecord: ReserveRecord = {
+ instructedAmount: req.amount,
+ initialWithdrawalGroupId,
+ initialDenomSel,
+ initialWithdrawalStarted: false,
timestampCreated: now,
exchangeBaseUrl: canonExchange,
reservePriv: keypair.priv,
@@ -750,10 +752,9 @@ async function depleteReserve(
let withdrawalGroupId: string;
- const bankInfo = newReserve.bankInfo;
- if (bankInfo && !bankInfo.withdrawalStarted) {
- withdrawalGroupId = bankInfo.bankWithdrawalGroupId;
- bankInfo.withdrawalStarted = true;
+ if (!newReserve.initialWithdrawalStarted) {
+ withdrawalGroupId = newReserve.initialWithdrawalGroupId;
+ newReserve.initialWithdrawalStarted = true;
} else {
withdrawalGroupId = encodeCrock(randomBytes(32));
}
diff --git a/src/operations/transactions.ts b/src/operations/transactions.ts
index 9a3d48bb3..f2845cb18 100644
--- a/src/operations/transactions.ts
+++ b/src/operations/transactions.ts
@@ -32,7 +32,10 @@ import {
Transaction,
TransactionType,
PaymentStatus,
+ WithdrawalType,
+ WithdrawalDetails,
} from "../types/transactions";
+import { WithdrawalDetailsResponse } from "../types/walletTypes";
/**
* Create an event ID from the type and the primary key for the event.
@@ -156,6 +159,7 @@ export async function getTransactions(
Stores.reserveUpdatedEvents,
Stores.recoupGroups,
],
+ // Report withdrawals that are currently in progress.
async (tx) => {
tx.iter(Stores.withdrawalGroups).forEachAsync(async (wsr) => {
if (
@@ -171,34 +175,62 @@ export async function getTransactions(
return;
}
- let amountRaw: AmountJson | undefined = undefined;
-
- if (wsr.source.type === WithdrawalSourceType.Reserve) {
- const r = await tx.get(Stores.reserves, wsr.source.reservePub);
- if (r?.bankInfo?.amount) {
- amountRaw = r.bankInfo.amount;
+ switch (wsr.source.type) {
+ case WithdrawalSourceType.Reserve: {
+ const r = await tx.get(Stores.reserves, wsr.source.reservePub);
+ if (!r) {
+ break;
+ }
+ let amountRaw: AmountJson | undefined = undefined;
+ if (wsr.withdrawalGroupId === r.initialWithdrawalGroupId) {
+ amountRaw = r.instructedAmount;
+ } else {
+ amountRaw = wsr.denomsSel.totalWithdrawCost;
+ }
+ let withdrawalDetails: WithdrawalDetails;
+ if (r.bankInfo) {
+ withdrawalDetails = {
+ type: WithdrawalType.TalerBankIntegrationApi,
+ confirmed: true,
+ bankConfirmationUrl: r.bankInfo.confirmUrl,
+ };
+ } else {
+ const exchange = await tx.get(Stores.exchanges, r.exchangeBaseUrl);
+ if (!exchange) {
+ // FIXME: report somehow
+ break;
+ }
+ withdrawalDetails = {
+ type: WithdrawalType.ManualTransfer,
+ reservePublicKey: r.reservePub,
+ exchangePaytoUris: exchange.wireInfo?.accounts.map((x) => x.payto_uri) ?? [],
+ };
+ }
+ transactions.push({
+ type: TransactionType.Withdrawal,
+ amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue),
+ amountRaw: Amounts.stringify(amountRaw),
+ withdrawalDetails,
+ exchangeBaseUrl: wsr.exchangeBaseUrl,
+ pending: !wsr.timestampFinish,
+ timestamp: wsr.timestampStart,
+ transactionId: makeEventId(
+ TransactionType.Withdrawal,
+ wsr.withdrawalGroupId,
+ ),
+ });
}
+ break;
+ default:
+ // Tips are reported via their own event
+ break;
}
- if (!amountRaw) {
- amountRaw = wsr.denomsSel.totalWithdrawCost;
- }
-
- transactions.push({
- type: TransactionType.Withdrawal,
- amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue),
- amountRaw: Amounts.stringify(amountRaw),
- confirmed: true,
- exchangeBaseUrl: wsr.exchangeBaseUrl,
- pending: !wsr.timestampFinish,
- timestamp: wsr.timestampStart,
- transactionId: makeEventId(
- TransactionType.Withdrawal,
- wsr.withdrawalGroupId,
- ),
- });
});
- tx.iter(Stores.reserves).forEach((r) => {
+ // Report pending withdrawals based on reserves that
+ // were created, but where the actual withdrawal group has
+ // not started yet.
+ tx.iter(Stores.reserves).forEachAsync(async (r) => {
if (shouldSkipCurrency(transactionsRequest, r.currency)) {
return;
}
@@ -213,23 +245,41 @@ export async function getTransactions(
default:
return;
}
- if (!r.bankInfo) {
+ if (r.initialWithdrawalStarted) {
return;
}
+ let withdrawalDetails: WithdrawalDetails;
+ if (r.bankInfo) {
+ withdrawalDetails = {
+ type: WithdrawalType.TalerBankIntegrationApi,
+ confirmed: false,
+ bankConfirmationUrl: r.bankInfo.confirmUrl,
+ }
+ } else {
+ const exchange = await tx.get(Stores.exchanges, r.exchangeBaseUrl);
+ if (!exchange) {
+ // FIXME: report somehow
+ return;
+ }
+ withdrawalDetails = {
+ type: WithdrawalType.ManualTransfer,
+ reservePublicKey: r.reservePub,
+ exchangePaytoUris: exchange.wireInfo?.accounts.map((x) => x.payto_uri) ?? [],
+ };
+ }
transactions.push({
type: TransactionType.Withdrawal,
- confirmed: false,
- amountRaw: Amounts.stringify(r.bankInfo.amount),
+ amountRaw: Amounts.stringify(r.instructedAmount),
amountEffective: Amounts.stringify(
- r.bankInfo.denomSel.totalCoinValue,
+ r.initialDenomSel.totalCoinValue,
),
exchangeBaseUrl: r.exchangeBaseUrl,
pending: true,
timestamp: r.timestampCreated,
- bankConfirmationUrl: r.bankInfo.confirmUrl,
+ withdrawalDetails: withdrawalDetails,
transactionId: makeEventId(
TransactionType.Withdrawal,
- r.bankInfo.bankWithdrawalGroupId,
+ r.initialWithdrawalGroupId,
),
});
});
diff --git a/src/operations/withdraw.ts b/src/operations/withdraw.ts
index 284743415..fd850f140 100644
--- a/src/operations/withdraw.ts
+++ b/src/operations/withdraw.ts
@@ -32,7 +32,7 @@ import {
import {
BankWithdrawDetails,
ExchangeWithdrawDetails,
- WithdrawDetails,
+ WithdrawalDetailsResponse,
OperationError,
} from "../types/walletTypes";
import {
@@ -708,7 +708,7 @@ export async function getWithdrawDetailsForUri(
ws: InternalWalletState,
talerWithdrawUri: string,
maybeSelectedExchange?: string,
-): Promise<WithdrawDetails> {
+): Promise<WithdrawalDetailsResponse> {
const info = await getBankWithdrawalInfo(ws, talerWithdrawUri);
let rci: ExchangeWithdrawDetails | undefined = undefined;
if (maybeSelectedExchange) {