diff options
-rw-r--r-- | packages/taler-util/src/transactionsTypes.ts | 22 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/db.ts | 41 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/peer-to-peer.ts | 9 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/transactions.ts | 26 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/operations/withdraw.ts | 74 |
5 files changed, 131 insertions, 41 deletions
diff --git a/packages/taler-util/src/transactionsTypes.ts b/packages/taler-util/src/transactionsTypes.ts index c4bd3d464..79c62cbc8 100644 --- a/packages/taler-util/src/transactionsTypes.ts +++ b/packages/taler-util/src/transactionsTypes.ts @@ -187,6 +187,9 @@ export interface TransactionWithdrawal extends TransactionCommon { withdrawalDetails: WithdrawalDetails; } +/** + * Credit because we were paid for a P2P invoice we created. + */ export interface TransactionPeerPullCredit extends TransactionCommon { type: TransactionType.PeerPullCredit; @@ -204,8 +207,16 @@ export interface TransactionPeerPullCredit extends TransactionCommon { * Amount that actually was (or will be) added to the wallet's balance. */ amountEffective: AmountString; + + /** + * URI to send to the other party. + */ + talerUri: string; } +/** + * Debit because we paid someone's invoice. + */ export interface TransactionPeerPullDebit extends TransactionCommon { type: TransactionType.PeerPullDebit; @@ -219,6 +230,9 @@ export interface TransactionPeerPullDebit extends TransactionCommon { amountEffective: AmountString; } +/** + * We sent money via a P2P payment. + */ export interface TransactionPeerPushDebit extends TransactionCommon { type: TransactionType.PeerPushDebit; @@ -236,8 +250,16 @@ export interface TransactionPeerPushDebit extends TransactionCommon { * Amount that actually was (or will be) added to the wallet's balance. */ amountEffective: AmountString; + + /** + * URI to accept the payment. + */ + talerUri: string; } +/** + * We received money via a P2P payment. + */ export interface TransactionPeerPushCredit extends TransactionCommon { type: TransactionType.PeerPushCredit; diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index e6b4854db..40f4ea2b5 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -1226,6 +1226,39 @@ export const enum WithdrawalRecordType { PeerPushCredit = "peer-push-credit", } +export interface WgInfoBankIntegrated { + withdrawalType: WithdrawalRecordType.BankIntegrated; + /** + * Extra state for when this is a withdrawal involving + * a Taler-integrated bank. + */ + bankInfo: ReserveBankInfo; +} + +export interface WgInfoBankManual { + withdrawalType: WithdrawalRecordType.BankManual; +} + +export interface WgInfoBankPeerPull { + withdrawalType: WithdrawalRecordType.PeerPullCredit; + + /** + * Needed to quickly construct the taler:// URI for the counterparty + * without a join. + */ + contractPriv: string; +} + +export interface WgInfoBankPeerPush { + withdrawalType: WithdrawalRecordType.PeerPushCredit; +} + +export type WgInfo = + | WgInfoBankIntegrated + | WgInfoBankManual + | WgInfoBankPeerPull + | WgInfoBankPeerPush; + /** * Group of withdrawal operations that need to be executed. * (Either for a normal withdrawal or from a tip.) @@ -1239,7 +1272,7 @@ export interface WithdrawalGroupRecord { */ withdrawalGroupId: string; - withdrawalType: WithdrawalRecordType; + wgInfo: WgInfo; /** * Secret seed used to derive planchets. @@ -1302,12 +1335,6 @@ export interface WithdrawalGroupRecord { restrictAge?: number; /** - * Extra state for when this is a withdrawal involving - * a Taler-integrated bank. - */ - bankInfo?: ReserveBankInfo; - - /** * Amount including fees (i.e. the amount subtracted from the * reserve to withdraw all coins in this withdrawal session). */ diff --git a/packages/taler-wallet-core/src/operations/peer-to-peer.ts b/packages/taler-wallet-core/src/operations/peer-to-peer.ts index d6d71720c..19306845a 100644 --- a/packages/taler-wallet-core/src/operations/peer-to-peer.ts +++ b/packages/taler-wallet-core/src/operations/peer-to-peer.ts @@ -534,7 +534,9 @@ export async function acceptPeerPushPayment( await internalCreateWithdrawalGroup(ws, { amount, - withdrawalType: WithdrawalRecordType.PeerPushCredit, + wgInfo: { + withdrawalType: WithdrawalRecordType.PeerPushCredit, + }, exchangeBaseUrl: peerInc.exchangeBaseUrl, reserveStatus: ReserveRecordStatus.QueryingStatus, reserveKeyPair: { @@ -804,7 +806,10 @@ export async function initiatePeerRequestForPay( await internalCreateWithdrawalGroup(ws, { amount: Amounts.parseOrThrow(req.amount), - withdrawalType: WithdrawalRecordType.PeerPullCredit, + wgInfo: { + withdrawalType: WithdrawalRecordType.PeerPullCredit, + contractPriv: econtractResp.contractPriv, + }, exchangeBaseUrl: req.exchangeBaseUrl, reserveStatus: ReserveRecordStatus.QueryingStatus, reserveKeyPair: { diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 62df996c3..8eff945c5 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -21,6 +21,8 @@ import { AbsoluteTime, AmountJson, Amounts, + constructPayPullUri, + constructPayPushUri, Logger, OrderShortInfo, PaymentStatus, @@ -156,6 +158,10 @@ export async function getTransactions( frozen: false, pending: !pi.purseCreated, timestamp: pi.timestampCreated, + talerUri: constructPayPushUri({ + exchangeBaseUrl: pi.exchangeBaseUrl, + contractPriv: pi.contractPriv, + }), transactionId: makeEventId( TransactionType.PeerPushDebit, pi.pursePub, @@ -203,7 +209,7 @@ export async function getTransactions( return; } let withdrawalDetails: WithdrawalDetails; - if (wsr.withdrawalType === WithdrawalRecordType.PeerPullCredit) { + if (wsr.wgInfo.withdrawalType === WithdrawalRecordType.PeerPullCredit) { transactions.push({ type: TransactionType.PeerPullCredit, amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue), @@ -211,6 +217,10 @@ export async function getTransactions( exchangeBaseUrl: wsr.exchangeBaseUrl, pending: !wsr.timestampFinish, timestamp: wsr.timestampStart, + talerUri: constructPayPullUri({ + exchangeBaseUrl: wsr.exchangeBaseUrl, + contractPriv: wsr.wgInfo.contractPriv, + }), transactionId: makeEventId( TransactionType.PeerPullCredit, wsr.withdrawalGroupId, @@ -219,7 +229,9 @@ export async function getTransactions( ...(wsr.lastError ? { error: wsr.lastError } : {}), }); return; - } else if (wsr.withdrawalType === WithdrawalRecordType.PeerPushCredit) { + } else if ( + wsr.wgInfo.withdrawalType === WithdrawalRecordType.PeerPushCredit + ) { transactions.push({ type: TransactionType.PeerPushCredit, amountEffective: Amounts.stringify(wsr.denomsSel.totalCoinValue), @@ -235,12 +247,16 @@ export async function getTransactions( ...(wsr.lastError ? { error: wsr.lastError } : {}), }); return; - } else if (wsr.bankInfo) { + } else if ( + wsr.wgInfo.withdrawalType === WithdrawalRecordType.BankIntegrated + ) { withdrawalDetails = { type: WithdrawalType.TalerBankIntegrationApi, - confirmed: wsr.bankInfo.timestampBankConfirmed ? true : false, + confirmed: wsr.wgInfo.bankInfo.timestampBankConfirmed + ? true + : false, reservePub: wsr.reservePub, - bankConfirmationUrl: wsr.bankInfo.confirmUrl, + bankConfirmationUrl: wsr.wgInfo.bankInfo.confirmUrl, }; } else { const exchangeDetails = await getExchangeDetails( diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 4e350670d..a0a4b4bbd 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -73,6 +73,7 @@ import { ReserveBankInfo, ReserveRecordStatus, WalletStoresV1, + WgInfo, WithdrawalGroupRecord, WithdrawalRecordType, } from "../db.js"; @@ -1531,7 +1532,12 @@ async function registerReserveWithBank( default: return; } - const bankInfo = withdrawalGroup.bankInfo; + if ( + withdrawalGroup.wgInfo.withdrawalType != WithdrawalRecordType.BankIntegrated + ) { + throw Error(); + } + const bankInfo = withdrawalGroup.wgInfo.bankInfo; if (!bankInfo) { return; } @@ -1566,10 +1572,10 @@ async function registerReserveWithBank( default: return; } - if (!r.bankInfo) { + if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) { throw Error("invariant failed"); } - r.bankInfo.timestampReserveInfoPosted = AbsoluteTime.toTimestamp( + r.wgInfo.bankInfo.timestampReserveInfoPosted = AbsoluteTime.toTimestamp( AbsoluteTime.now(), ); r.reserveStatus = ReserveRecordStatus.WaitConfirmBank; @@ -1595,12 +1601,18 @@ async function processReserveBankStatus( default: return; } - if (!withdrawalGroup.bankInfo) { + + if ( + withdrawalGroup.wgInfo.withdrawalType != WithdrawalRecordType.BankIntegrated + ) { + throw Error(); + } + const bankInfo = withdrawalGroup.wgInfo.bankInfo; + if (!bankInfo) { return; } - const bankStatusUrl = getBankStatusUrl( - withdrawalGroup.bankInfo.talerWithdrawUri, - ); + + const bankStatusUrl = getBankStatusUrl(bankInfo.talerWithdrawUri); const statusResp = await ws.http.get(bankStatusUrl, { timeout: getReserveRequestTimeout(withdrawalGroup), @@ -1628,11 +1640,11 @@ async function processReserveBankStatus( default: return; } - if (!r.bankInfo) { + if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) { throw Error("invariant failed"); } const now = AbsoluteTime.toTimestamp(AbsoluteTime.now()); - r.bankInfo.timestampBankConfirmed = now; + r.wgInfo.bankInfo.timestampBankConfirmed = now; r.reserveStatus = ReserveRecordStatus.BankAborted; r.operationStatus = OperationStatus.Finished; r.retryInfo = RetryInfo.reset(); @@ -1670,21 +1682,19 @@ async function processReserveBankStatus( default: return; } + if (r.wgInfo.withdrawalType !== WithdrawalRecordType.BankIntegrated) { + throw Error("invariant failed"); + } if (status.transfer_done) { logger.info("withdrawal: transfer confirmed by bank."); const now = AbsoluteTime.toTimestamp(AbsoluteTime.now()); - if (!r.bankInfo) { - throw Error("invariant failed"); - } - r.bankInfo.timestampBankConfirmed = now; + r.wgInfo.bankInfo.timestampBankConfirmed = now; r.reserveStatus = ReserveRecordStatus.QueryingStatus; r.operationStatus = OperationStatus.Pending; r.retryInfo = RetryInfo.reset(); } else { logger.info("withdrawal: transfer not yet confirmed by bank"); - if (r.bankInfo) { - r.bankInfo.confirmUrl = status.confirm_transfer_url; - } + r.wgInfo.bankInfo.confirmUrl = status.confirm_transfer_url; r.retryInfo = RetryInfo.increment(r.retryInfo); } await tx.withdrawalGroups.put(r); @@ -1701,7 +1711,7 @@ export async function internalCreateWithdrawalGroup( forcedDenomSel?: ForcedDenomSel; reserveKeyPair?: EddsaKeypair; restrictAge?: number; - withdrawalType: WithdrawalRecordType; + wgInfo: WgInfo; }, ): Promise<WithdrawalGroupRecord> { const reserveKeyPair = @@ -1743,11 +1753,10 @@ export async function internalCreateWithdrawalGroup( reserveStatus: args.reserveStatus, retryInfo: RetryInfo.reset(), withdrawalGroupId, - bankInfo: args.bankInfo, restrictAge: args.restrictAge, senderWire: undefined, timestampFinish: undefined, - withdrawalType: args.withdrawalType, + wgInfo: args.wgInfo, }; const exchangeInfo = await updateExchangeFromUrl(ws, canonExchange); @@ -1802,9 +1811,16 @@ export async function acceptWithdrawalFromUri( }); if (existingWithdrawalGroup) { + let url: string | undefined; + if ( + existingWithdrawalGroup.wgInfo.withdrawalType === + WithdrawalRecordType.BankIntegrated + ) { + url = existingWithdrawalGroup.wgInfo.bankInfo.confirmUrl; + } return { reservePub: existingWithdrawalGroup.reservePub, - confirmTransferUrl: existingWithdrawalGroup.bankInfo?.confirmUrl, + confirmTransferUrl: url, }; } @@ -1822,14 +1838,16 @@ export async function acceptWithdrawalFromUri( const withdrawalGroup = await internalCreateWithdrawalGroup(ws, { amount: withdrawInfo.amount, exchangeBaseUrl: req.selectedExchange, - withdrawalType: WithdrawalRecordType.BankIntegrated, + wgInfo: { + withdrawalType: WithdrawalRecordType.BankIntegrated, + bankInfo: { + exchangePaytoUri, + talerWithdrawUri: req.talerWithdrawUri, + confirmUrl: withdrawInfo.confirmTransferUrl, + }, + }, forcedDenomSel: req.forcedDenomSel, reserveStatus: ReserveRecordStatus.RegisteringBank, - bankInfo: { - exchangePaytoUri, - talerWithdrawUri: req.talerWithdrawUri, - confirmUrl: withdrawInfo.confirmTransferUrl, - }, }); const withdrawalGroupId = withdrawalGroup.withdrawalGroupId; @@ -1881,7 +1899,9 @@ export async function createManualWithdrawal( ): Promise<AcceptManualWithdrawalResult> { const withdrawalGroup = await internalCreateWithdrawalGroup(ws, { amount: Amounts.jsonifyAmount(req.amount), - withdrawalType: WithdrawalRecordType.BankManual, + wgInfo: { + withdrawalType: WithdrawalRecordType.BankManual, + }, exchangeBaseUrl: req.exchangeBaseUrl, bankInfo: undefined, forcedDenomSel: req.forcedDenomSel, |