taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit ef8dc39aabddc6fa50c43ac2fec3ac1ba17ac3f5
parent 6900c5ad7fc2b9328fd3547a50aeca32d1e378ee
Author: Florian Dold <dold@taler.net>
Date:   Thu, 16 Jul 2026 00:17:26 +0200

wallet-core: use DAL for tokens and P2P

Diffstat:
Mpackages/taler-wallet-core/src/coinSelection.ts | 5++++-
Mpackages/taler-wallet-core/src/common.ts | 10+++++++---
Mpackages/taler-wallet-core/src/db-common.ts | 373+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-wallet-core/src/dbtx.ts | 453++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mpackages/taler-wallet-core/src/deposits.ts | 14+++++++++-----
Mpackages/taler-wallet-core/src/exchanges.ts | 8++++----
Mpackages/taler-wallet-core/src/pay-merchant.ts | 22+++++++++++-----------
Mpackages/taler-wallet-core/src/pay-peer-pull-credit.ts | 52++++++++++++++++++++++++++++------------------------
Mpackages/taler-wallet-core/src/pay-peer-pull-debit.ts | 65++++++++++++++++++++++++++++++++---------------------------------
Mpackages/taler-wallet-core/src/pay-peer-push-credit.ts | 67+++++++++++++++++++++++++++++++++++--------------------------------
Mpackages/taler-wallet-core/src/pay-peer-push-debit.ts | 52+++++++++++++++++++++++++++-------------------------
Mpackages/taler-wallet-core/src/recoup.ts | 16++++++++++------
Mpackages/taler-wallet-core/src/refresh.ts | 11++++++-----
Mpackages/taler-wallet-core/src/tokenFamilies.ts | 24++++++++++++------------
Mpackages/taler-wallet-core/src/tokenSelection.ts | 26+++++++++++++-------------
Mpackages/taler-wallet-core/src/transactions.ts | 8+++++---
Mpackages/taler-wallet-core/src/withdraw.ts | 16++++++++++------
17 files changed, 1037 insertions(+), 185 deletions(-)

diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts @@ -61,7 +61,10 @@ import { PaymentBalanceDetails, } from "./balance.js"; import { getAutoRefreshExecuteThreshold } from "./common.js"; -import { DenominationRecord, WalletIndexedDbTransaction } from "./db-indexeddb.js"; +import { + DenominationRecord, + WalletIndexedDbTransaction, +} from "./db-indexeddb.js"; import { checkExchangeInScopeTx, ExchangeDetails, diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts @@ -81,7 +81,11 @@ import { import { ReadyExchangeSummary } from "./exchanges.js"; import { createRefreshGroup } from "./refresh.js"; import { BalanceEffect, applyNotifyTransition } from "./transactions.js"; -import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + getDenomInfo, +} from "./wallet.js"; const logger = new Logger("operations/common.ts"); @@ -884,7 +888,7 @@ export interface TransactionContext { */ userDeleteTransaction(): Promise<void>; lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, args?: LookupFullTransactionOpts, ): Promise<Transaction | undefined>; } @@ -1119,7 +1123,7 @@ export interface RecordHandle<T> { */ export async function getGenericRecordHandle<T>( ctx: TransactionContext, - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, getRec: () => Promise<T | undefined>, storeRec: (r: T) => Promise<void>, deleteRec: () => Promise<void>, diff --git a/packages/taler-wallet-core/src/db-common.ts b/packages/taler-wallet-core/src/db-common.ts @@ -16,8 +16,16 @@ import { AbsoluteTime, + AmountString, TalerPreciseTimestamp, TalerProtocolTimestamp, + MerchantContractTokenKind, + TokenIssuePublicKey, + UnblindedDenominationSignature, + TokenUseSig, + MerchantContractTokenDetails, + ScopeInfo, + TalerErrorDetail, } from "@gnu-taler/taler-util"; declare const symDbProtocolTimestamp: unique symbol; @@ -709,3 +717,368 @@ export enum DonationReceiptStatus { */ Pending = 0x0100_0000, } + +export interface DbPeerPushPaymentCoinSelection { + contributions: AmountString[]; + coinPubs: string[]; +} + +export interface PeerPullPaymentCoinSelection { + contributions: AmountString[]; + coinPubs: string[]; + totalCost: AmountString | undefined; +} + +/** + * Record for a push P2P payment that this wallet initiated. + */ +export interface WalletPeerPushDebit { + /** + * What exchange are funds coming from? + */ + exchangeBaseUrl: string; + + /** + * Restricted scope for this transaction. + * + * Relevant for coin reselection. + */ + restrictScope?: ScopeInfo; + + /** + * Instructed amount. + */ + amount: AmountString; + + /** + * Effective amount. + * + * (Called totalCost for historical reasons.) + */ + totalCost: AmountString; + + coinSel?: DbPeerPushPaymentCoinSelection; + + contractTermsHash: string; + + /** + * Purse public key. Used as the primary key to look + * up this record. + */ + pursePub: string; + + /** + * Purse private key. + */ + pursePriv: string; + + /** + * Public key of the merge capability of the purse. + */ + mergePub: string; + + /** + * Private key of the merge capability of the purse. + */ + mergePriv: string; + + contractPriv: string; + contractPub: string; + + /** + * 24 byte nonce. + */ + contractEncNonce: string; + + purseExpiration: DbProtocolTimestamp; + + timestampCreated: DbPreciseTimestamp; + + abortRefreshGroupId?: string; + + abortReason?: TalerErrorDetail; + failReason?: TalerErrorDetail; + + /** + * Status of the peer push payment initiation. + */ + status: PeerPushDebitStatus; +} + +/** + * Record for a pull P2P payment that this wallet initiated. + */ +export interface WalletPeerPullCredit { + /** + * What exchange are we using for the payment request? + */ + exchangeBaseUrl: string; + + /** + * Amount requested. + * FIXME: What type of instructed amount is i? + */ + amount: AmountString; + + estimatedAmountEffective: AmountString; + + /** + * Purse public key. Used as the primary key to look + * up this record. + */ + pursePub: string; + + /** + * Purse private key. + */ + pursePriv: string; + + /** + * Hash of the contract terms. Also + * used to look up the contract terms in the DB. + */ + contractTermsHash: string; + + mergePub: string; + mergePriv: string; + + contractPub: string; + contractPriv: string; + + contractEncNonce: string; + + mergeTimestamp: DbPreciseTimestamp; + + mergeReserveRowId: number; + + /** + * Status of the peer pull payment initiation. + */ + status: PeerPullPaymentCreditStatus; + + kycPaytoHash?: string; + + kycAccessToken?: string; + + kycLastCheckStatus?: number; + kycLastCheckCode?: number; + kycLastRuleGen?: number; + kycLastAmlReview?: boolean; + kycLastDeny?: DbPreciseTimestamp; + + abortReason?: TalerErrorDetail; + failReason?: TalerErrorDetail; + + withdrawalGroupId: string | undefined; +} + +/** + * Record for a push P2P payment that this wallet was offered. + */ +export interface WalletPeerPushCredit { + peerPushCreditId: string; + + exchangeBaseUrl: string; + + pursePub: string; + + mergePriv: string; + + contractPriv: string; + + timestamp: DbPreciseTimestamp; + + estimatedAmountEffective: AmountString; + + /** + * Hash of the contract terms. Also + * used to look up the contract terms in the DB. + */ + contractTermsHash: string; + + /** + * Status of the peer push payment incoming initiation. + */ + status: PeerPushCreditStatus; + + abortReason?: TalerErrorDetail; + failReason?: TalerErrorDetail; + + /** + * Associated withdrawal group. + */ + withdrawalGroupId: string | undefined; + + /** + * Currency of the peer push payment credit transaction. + * + * Mandatory in current schema version, optional for compatibility + * with older (ver_minor<4) DB versions. + */ + currency: string | undefined; + + kycPaytoHash?: string; + + kycAccessToken?: string; + + kycLastCheckStatus?: number; + kycLastCheckCode?: number; + kycLastRuleGen?: number; + kycLastAmlReview?: boolean; + kycLastDeny?: DbPreciseTimestamp; +} + +/** + * AKA PeerPullDebit. Record for a pull P2P payment that this wallet was offered. + */ +export interface WalletPeerPullDebit { + peerPullDebitId: string; + + pursePub: string; + + exchangeBaseUrl: string; + + amount: AmountString; + + contractTermsHash: string; + + timestampCreated: DbPreciseTimestamp; + + /** + * Contract priv that we got from the other party. + */ + contractPriv: string; + + /** + * Status of the peer push payment incoming initiation. + */ + status: PeerPullDebitRecordStatus; + + /** + * Estimated total cost when the record was created. + */ + totalCostEstimated: AmountString; + + abortRefreshGroupId?: string; + + abortReason?: TalerErrorDetail; + failReason?: TalerErrorDetail; + + coinSel?: PeerPullPaymentCoinSelection; +} + +/** + * Token record. + */ +export interface WalletToken { + /** + * Identifier for the token family consisting of + * unreserved characters according to RFC 3986. + */ + slug: string; + + /** + * Human-readable name for the token family. + */ + name: string; + + /** + * Human-readable description for the token family. + */ + description: string; + + /** + * Optional map from IETF BCP 47 language tags to localized descriptions. + */ + descriptionI18n: any | undefined; + + /** + * Additional meta data, such as the trusted_domains + * or expected_domains. Depends on the kind. + */ + extraData: MerchantContractTokenDetails; + + /** + * Token issue public key used by merchant to verify tokens. + */ + tokenIssuePub: TokenIssuePublicKey; + + /** + * Source purchase of the token. + */ + purchaseId: string; + + /** + * Transaction where token is being used. + */ + transactionId?: string; + + /** + * Index of token in choices array. + */ + choiceIndex?: number; + + /** + * Index of token in outputs array. + */ + outputIndex?: number; + + /** + * For token outputs with a count>1, this stores + * the index of this token within the same output + * index. + * + * If missing, assumed to be 0. + */ + repeatIndex?: number; + + /** + * URL of the merchant issuing the token. + */ + merchantBaseUrl: string; + + /** + * Kind of the token. + */ + kind: MerchantContractTokenKind; + + /** + * Hash of token issue public key. + */ + tokenIssuePubHash: string; + + /** + * Hash of TokenFamilyInfo object. + */ + tokenFamilyHash?: string; + + /** + * Start time of the token family's validity period. + */ + validAfter: DbProtocolTimestamp; + + /** + * End time of the token family's validity period. + */ + validBefore: DbProtocolTimestamp; + + /** + * Unblinded token issue signature made by the merchant. + */ + tokenIssueSig: UnblindedDenominationSignature; + + /** + * Token use public key used to confirm usage of tokens. + */ + tokenUsePub: string; + + /** + * Token use private key used to verify usage of tokens. + */ + tokenUsePriv: string; + + /** + * Signature on token use request. + */ + tokenUseSig?: TokenUseSig; +} diff --git a/packages/taler-wallet-core/src/dbtx.ts b/packages/taler-wallet-core/src/dbtx.ts @@ -22,8 +22,22 @@ import { ScopeInfo, stringifyScopeInfo, } from "@gnu-taler/taler-util"; -import { ConfigRecord } from "./db-common.js"; -import { PurchaseRecord, WalletIndexedDbTransaction } from "./db-indexeddb.js"; +import { + ConfigRecord, + WalletPeerPullCredit, + WalletPeerPushDebit, + WalletPeerPushCredit, + WalletPeerPullDebit, + WalletToken, +} from "./db-common.js"; +import { + PeerPullCreditRecord, + PeerPushDebitRecord, + PeerPushCreditRecord, + PeerPullPaymentIncomingRecord, + PurchaseRecord, + WalletIndexedDbTransaction, +} from "./db-indexeddb.js"; export interface GetCurrencyInfoDbResult { /** @@ -87,6 +101,103 @@ export interface WalletDbTransaction { upsertMailboxConfiguration(mailboxConf: MailboxConfiguration): Promise<void>; getPurchase(proposalId: string): Promise<PurchaseRecord | undefined>; + + /** + * List all stored wallet tokens. + */ + listTokens(): Promise<WalletToken[]>; + + /** + * Delete a wallet token by its token use public key. + */ + deleteToken(tokenUsePub: string): Promise<void>; + + /** + * Get all tokens matching a specific token issue public key hash. + */ + getTokensByIssuePubHash(tokenIssuePubHash: string): Promise<WalletToken[]>; + + /** + * Get an incoming peer pull payment (credit) record by purse public key. + */ + getPeerPullCredit( + pursePub: string, + ): Promise<WalletPeerPullCredit | undefined>; + + /** + * Create or update an incoming peer pull payment (credit) record. + */ + upsertPeerPullCredit(rec: WalletPeerPullCredit): Promise<void>; + + /** + * Delete an incoming peer pull payment (credit) record. + */ + deletePeerPullCredit(pursePub: string): Promise<void>; + + /** + * Get an outgoing peer push payment (debit) record by purse public key. + */ + getPeerPushDebit(pursePub: string): Promise<WalletPeerPushDebit | undefined>; + + /** + * Create or update an outgoing peer push payment (debit) record. + */ + upsertPeerPushDebit(rec: WalletPeerPushDebit): Promise<void>; + + /** + * Delete an outgoing peer push payment (debit) record. + */ + deletePeerPushDebit(pursePub: string): Promise<void>; + + /** + * Get an incoming peer push payment (credit) record by peer push credit ID. + */ + getPeerPushCredit( + peerPushCreditId: string, + ): Promise<WalletPeerPushCredit | undefined>; + + /** + * Create or update an incoming peer push payment (credit) record. + */ + upsertPeerPushCredit(rec: WalletPeerPushCredit): Promise<void>; + + /** + * Delete an incoming peer push payment (credit) record. + */ + deletePeerPushCredit(peerPushCreditId: string): Promise<void>; + + /** + * Get an incoming peer push payment (credit) record by exchange URL and contract private key. + */ + getPeerPushCreditByExchangeAndContractPriv( + exchangeBaseUrl: string, + contractPriv: string, + ): Promise<WalletPeerPushCredit | undefined>; + + /** + * Get an incoming peer pull payment (debit) record by peer pull debit ID. + */ + getPeerPullDebit( + peerPullDebitId: string, + ): Promise<WalletPeerPullDebit | undefined>; + + /** + * Create or update an incoming peer pull payment (debit) record. + */ + upsertPeerPullDebit(rec: WalletPeerPullDebit): Promise<void>; + + /** + * Delete an incoming peer pull payment (debit) record. + */ + deletePeerPullDebit(peerPullDebitId: string): Promise<void>; + + /** + * Get an incoming peer pull payment (debit) record by exchange URL and contract private key. + */ + getPeerPullDebitByExchangeAndContractPriv( + exchangeBaseUrl: string, + contractPriv: string, + ): Promise<WalletPeerPullDebit | undefined>; } export class IdbWalletTransaction implements WalletDbTransaction { @@ -212,4 +323,342 @@ export class IdbWalletTransaction implements WalletDbTransaction { const tx = this.tx; return await tx.purchases.get(proposalId); } + + async listTokens(): Promise<WalletToken[]> { + const tx = this.tx; + const records = await tx.tokens.getAll(); + return records.map((r) => ({ + slug: r.slug, + name: r.name, + description: r.description, + descriptionI18n: r.descriptionI18n, + extraData: r.extraData, + tokenIssuePub: r.tokenIssuePub, + purchaseId: r.purchaseId, + transactionId: r.transactionId, + choiceIndex: r.choiceIndex, + outputIndex: r.outputIndex, + repeatIndex: r.repeatIndex, + merchantBaseUrl: r.merchantBaseUrl, + kind: r.kind, + tokenIssuePubHash: r.tokenIssuePubHash, + tokenFamilyHash: r.tokenFamilyHash, + validAfter: r.validAfter, + validBefore: r.validBefore, + tokenIssueSig: r.tokenIssueSig, + tokenUsePub: r.tokenUsePub, + tokenUsePriv: r.tokenUsePriv, + tokenUseSig: r.tokenUseSig, + })); + } + + async deleteToken(tokenUsePub: string): Promise<void> { + const tx = this.tx; + await tx.tokens.delete(tokenUsePub); + } + + async getTokensByIssuePubHash( + tokenIssuePubHash: string, + ): Promise<WalletToken[]> { + const tx = this.tx; + const records = + await tx.tokens.indexes.byTokenIssuePubHash.getAll(tokenIssuePubHash); + return records.map((r) => ({ + slug: r.slug, + name: r.name, + description: r.description, + descriptionI18n: r.descriptionI18n, + extraData: r.extraData, + tokenIssuePub: r.tokenIssuePub, + purchaseId: r.purchaseId, + transactionId: r.transactionId, + choiceIndex: r.choiceIndex, + outputIndex: r.outputIndex, + repeatIndex: r.repeatIndex, + merchantBaseUrl: r.merchantBaseUrl, + kind: r.kind, + tokenIssuePubHash: r.tokenIssuePubHash, + tokenFamilyHash: r.tokenFamilyHash, + validAfter: r.validAfter, + validBefore: r.validBefore, + tokenIssueSig: r.tokenIssueSig, + tokenUsePub: r.tokenUsePub, + tokenUsePriv: r.tokenUsePriv, + tokenUseSig: r.tokenUseSig, + })); + } + + async getPeerPullCredit( + pursePub: string, + ): Promise<WalletPeerPullCredit | undefined> { + const tx = this.tx; + const r = await tx.peerPullCredit.get(pursePub); + if (!r) { + return undefined; + } + return { + exchangeBaseUrl: r.exchangeBaseUrl, + amount: r.amount, + estimatedAmountEffective: r.estimatedAmountEffective, + pursePub: r.pursePub, + pursePriv: r.pursePriv, + contractTermsHash: r.contractTermsHash, + mergePub: r.mergePub, + mergePriv: r.mergePriv, + contractPub: r.contractPub, + contractPriv: r.contractPriv, + contractEncNonce: r.contractEncNonce, + mergeTimestamp: r.mergeTimestamp, + mergeReserveRowId: r.mergeReserveRowId, + status: r.status, + kycPaytoHash: r.kycPaytoHash, + kycAccessToken: r.kycAccessToken, + kycLastCheckStatus: r.kycLastCheckStatus, + kycLastCheckCode: r.kycLastCheckCode, + kycLastRuleGen: r.kycLastRuleGen, + kycLastAmlReview: r.kycLastAmlReview, + kycLastDeny: r.kycLastDeny, + abortReason: r.abortReason, + failReason: r.failReason, + withdrawalGroupId: r.withdrawalGroupId, + }; + } + + async upsertPeerPullCredit(rec: WalletPeerPullCredit): Promise<void> { + const tx = this.tx; + await tx.peerPullCredit.put({ + exchangeBaseUrl: rec.exchangeBaseUrl, + amount: rec.amount, + estimatedAmountEffective: rec.estimatedAmountEffective, + pursePub: rec.pursePub, + pursePriv: rec.pursePriv, + contractTermsHash: rec.contractTermsHash, + mergePub: rec.mergePub, + mergePriv: rec.mergePriv, + contractPub: rec.contractPub, + contractPriv: rec.contractPriv, + contractEncNonce: rec.contractEncNonce, + mergeTimestamp: rec.mergeTimestamp, + mergeReserveRowId: rec.mergeReserveRowId, + status: rec.status, + kycPaytoHash: rec.kycPaytoHash, + kycAccessToken: rec.kycAccessToken, + kycLastCheckStatus: rec.kycLastCheckStatus, + kycLastCheckCode: rec.kycLastCheckCode, + kycLastRuleGen: rec.kycLastRuleGen, + kycLastAmlReview: rec.kycLastAmlReview, + kycLastDeny: rec.kycLastDeny, + abortReason: rec.abortReason, + failReason: rec.failReason, + withdrawalGroupId: rec.withdrawalGroupId, + }); + } + + async deletePeerPullCredit(pursePub: string): Promise<void> { + const tx = this.tx; + await tx.peerPullCredit.delete(pursePub); + } + + async getPeerPushDebit( + pursePub: string, + ): Promise<WalletPeerPushDebit | undefined> { + const tx = this.tx; + const r = await tx.peerPushDebit.get(pursePub); + if (!r) { + return undefined; + } + return { + exchangeBaseUrl: r.exchangeBaseUrl, + restrictScope: r.restrictScope, + amount: r.amount, + totalCost: r.totalCost, + coinSel: r.coinSel, + contractTermsHash: r.contractTermsHash, + pursePub: r.pursePub, + pursePriv: r.pursePriv, + mergePub: r.mergePub, + mergePriv: r.mergePriv, + contractPriv: r.contractPriv, + contractPub: r.contractPub, + contractEncNonce: r.contractEncNonce, + purseExpiration: r.purseExpiration, + timestampCreated: r.timestampCreated, + abortRefreshGroupId: r.abortRefreshGroupId, + abortReason: r.abortReason, + failReason: r.failReason, + status: r.status, + }; + } + + async upsertPeerPushDebit(rec: WalletPeerPushDebit): Promise<void> { + const tx = this.tx; + await tx.peerPushDebit.put({ + exchangeBaseUrl: rec.exchangeBaseUrl, + restrictScope: rec.restrictScope, + amount: rec.amount, + totalCost: rec.totalCost, + coinSel: rec.coinSel, + contractTermsHash: rec.contractTermsHash, + pursePub: rec.pursePub, + pursePriv: rec.pursePriv, + mergePub: rec.mergePub, + mergePriv: rec.mergePriv, + contractPriv: rec.contractPriv, + contractPub: rec.contractPub, + contractEncNonce: rec.contractEncNonce, + purseExpiration: rec.purseExpiration, + timestampCreated: rec.timestampCreated, + abortRefreshGroupId: rec.abortRefreshGroupId, + abortReason: rec.abortReason, + failReason: rec.failReason, + status: rec.status, + }); + } + + async deletePeerPushDebit(pursePub: string): Promise<void> { + const tx = this.tx; + await tx.peerPushDebit.delete(pursePub); + } + + async getPeerPushCredit( + peerPushCreditId: string, + ): Promise<WalletPeerPushCredit | undefined> { + const tx = this.tx; + const r = await tx.peerPushCredit.get(peerPushCreditId); + if (!r) { + return undefined; + } + return { + peerPushCreditId: r.peerPushCreditId, + exchangeBaseUrl: r.exchangeBaseUrl, + pursePub: r.pursePub, + mergePriv: r.mergePriv, + contractPriv: r.contractPriv, + timestamp: r.timestamp, + estimatedAmountEffective: r.estimatedAmountEffective, + contractTermsHash: r.contractTermsHash, + status: r.status, + abortReason: r.abortReason, + failReason: r.failReason, + withdrawalGroupId: r.withdrawalGroupId, + currency: r.currency, + kycPaytoHash: r.kycPaytoHash, + kycAccessToken: r.kycAccessToken, + kycLastCheckStatus: r.kycLastCheckStatus, + kycLastCheckCode: r.kycLastCheckCode, + kycLastRuleGen: r.kycLastRuleGen, + kycLastAmlReview: r.kycLastAmlReview, + kycLastDeny: r.kycLastDeny, + }; + } + + async upsertPeerPushCredit(rec: WalletPeerPushCredit): Promise<void> { + const tx = this.tx; + await tx.peerPushCredit.put({ + peerPushCreditId: rec.peerPushCreditId, + exchangeBaseUrl: rec.exchangeBaseUrl, + pursePub: rec.pursePub, + mergePriv: rec.mergePriv, + contractPriv: rec.contractPriv, + timestamp: rec.timestamp, + estimatedAmountEffective: rec.estimatedAmountEffective, + contractTermsHash: rec.contractTermsHash, + status: rec.status, + abortReason: rec.abortReason, + failReason: rec.failReason, + withdrawalGroupId: rec.withdrawalGroupId, + currency: rec.currency, + kycPaytoHash: rec.kycPaytoHash, + kycAccessToken: rec.kycAccessToken, + kycLastCheckStatus: rec.kycLastCheckStatus, + kycLastCheckCode: rec.kycLastCheckCode, + kycLastRuleGen: rec.kycLastRuleGen, + kycLastAmlReview: rec.kycLastAmlReview, + kycLastDeny: rec.kycLastDeny, + }); + } + + async deletePeerPushCredit(peerPushCreditId: string): Promise<void> { + const tx = this.tx; + await tx.peerPushCredit.delete(peerPushCreditId); + } + + async getPeerPushCreditByExchangeAndContractPriv( + exchangeBaseUrl: string, + contractPriv: string, + ): Promise<WalletPeerPushCredit | undefined> { + const tx = this.tx; + const r = await tx.peerPushCredit.indexes.byExchangeAndContractPriv.get([ + exchangeBaseUrl, + contractPriv, + ]); + if (!r) { + return undefined; + } + return this.getPeerPushCredit(r.peerPushCreditId); + } + + async getPeerPullDebit( + peerPullDebitId: string, + ): Promise<WalletPeerPullDebit | undefined> { + const tx = this.tx; + const r = await tx.peerPullDebit.get(peerPullDebitId); + if (!r) { + return undefined; + } + return { + peerPullDebitId: r.peerPullDebitId, + pursePub: r.pursePub, + exchangeBaseUrl: r.exchangeBaseUrl, + amount: r.amount, + contractTermsHash: r.contractTermsHash, + timestampCreated: r.timestampCreated, + contractPriv: r.contractPriv, + status: r.status, + totalCostEstimated: r.totalCostEstimated, + abortRefreshGroupId: r.abortRefreshGroupId, + abortReason: r.abortReason, + failReason: r.failReason, + coinSel: r.coinSel, + }; + } + + async upsertPeerPullDebit(rec: WalletPeerPullDebit): Promise<void> { + const tx = this.tx; + await tx.peerPullDebit.put({ + peerPullDebitId: rec.peerPullDebitId, + pursePub: rec.pursePub, + exchangeBaseUrl: rec.exchangeBaseUrl, + amount: rec.amount, + contractTermsHash: rec.contractTermsHash, + timestampCreated: rec.timestampCreated, + contractPriv: rec.contractPriv, + status: rec.status, + totalCostEstimated: rec.totalCostEstimated, + abortRefreshGroupId: rec.abortRefreshGroupId, + abortReason: rec.abortReason, + failReason: rec.failReason, + coinSel: rec.coinSel, + }); + } + + async deletePeerPullDebit(peerPullDebitId: string): Promise<void> { + const tx = this.tx; + await tx.peerPullDebit.delete(peerPullDebitId); + } + + async getPeerPullDebitByExchangeAndContractPriv( + exchangeBaseUrl: string, + contractPriv: string, + ): Promise<WalletPeerPullDebit | undefined> { + const tx = this.tx; + const r = await tx.peerPullDebit.indexes.byExchangeAndContractPriv.get([ + exchangeBaseUrl, + contractPriv, + ]); + if (!r) { + return undefined; + } + return this.getPeerPullDebit(r.peerPullDebitId); + } } diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts @@ -160,7 +160,11 @@ import { isUnsuccessfulTransaction, parseTransactionIdentifier, } from "./transactions.js"; -import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + getDenomInfo, +} from "./wallet.js"; import { augmentPaytoUrisForKycTransfer } from "./withdraw.js"; /** @@ -193,7 +197,7 @@ export class DepositTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { const dg = await tx.depositGroups.get(this.depositGroupId); if (!dg) { @@ -330,7 +334,7 @@ export class DepositTransactionContext implements TransactionContext { /** * Update the metadata of the transaction in the database. */ - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const depositRec = await tx.depositGroups.get(this.depositGroupId); if (!depositRec) { await tx.transactionsMeta.delete(this.transactionId); @@ -346,7 +350,7 @@ export class DepositTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise< [DepositGroupRecord | undefined, RecordHandle<DepositGroupRecord>] > { @@ -370,7 +374,7 @@ export class DepositTransactionContext implements TransactionContext { }); } - async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> { + async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -2325,7 +2325,7 @@ export async function processTaskExchangeAutoRefresh( async function handleDenomLoss( wex: WalletExecutionContext, - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, currency: string, exchangeBaseUrl: string, ): Promise<void> { @@ -2530,7 +2530,7 @@ export class DenomLossTransactionContext implements TransactionContext { return undefined; } - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const denomLossRec = await tx.denomLossEvents.get(this.denomLossEventId); if (!denomLossRec) { await tx.transactionsMeta.delete(this.transactionId); @@ -2590,7 +2590,7 @@ export class DenomLossTransactionContext implements TransactionContext { } async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { const rec = await tx.denomLossEvents.get(this.denomLossEventId); if (!rec) { @@ -3138,7 +3138,7 @@ async function internalGetExchangeResources( */ async function purgeExchange( wex: WalletExecutionContext, - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, exchangeRec: ExchangeEntryRecord, purgeTransactions?: boolean, ): Promise<void> { diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -228,7 +228,7 @@ export class PayMerchantTransactionContext implements TransactionContext { * * Must be called each time the DB record for the transaction is updated. */ - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const purchaseRec = await tx.purchases.get(this.proposalId); if (!purchaseRec) { await tx.transactionsMeta.delete(this.transactionId); @@ -250,7 +250,7 @@ export class PayMerchantTransactionContext implements TransactionContext { } async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, req?: LookupFullTransactionOpts, ): Promise<Transaction | undefined> { const proposalId = this.proposalId; @@ -417,7 +417,7 @@ export class PayMerchantTransactionContext implements TransactionContext { } async deleteTransactionInTx( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, opts: { keepRelated?: boolean } = {}, ): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); @@ -566,7 +566,7 @@ export class PayMerchantTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<[PurchaseRecord | undefined, RecordHandle<PurchaseRecord>]> { return getGenericRecordHandle<PurchaseRecord>( this, @@ -655,7 +655,7 @@ export class RefundTransactionContext implements TransactionContext { * * Must be called each time the DB record for the transaction is updated. */ - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const refundRec = await tx.refundGroups.get(this.refundGroupId); if (!refundRec) { await tx.transactionsMeta.delete(this.transactionId); @@ -676,7 +676,7 @@ export class RefundTransactionContext implements TransactionContext { } async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { const refundRecord = await tx.refundGroups.get(this.refundGroupId); if (!refundRecord) { @@ -749,7 +749,7 @@ export class RefundTransactionContext implements TransactionContext { } async deleteTransactionInTx( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<{ notifs: WalletNotification[] }> { const notifs: WalletNotification[] = []; const refundRecord = await tx.refundGroups.get(this.refundGroupId); @@ -1694,7 +1694,7 @@ async function reselectCoinsTx( if (contractData.contractTerms.version !== MerchantContractVersion.V1) throw Error("assertion failed"); - const res = await selectPayTokensInTx(tx, { + const res = await selectPayTokensInTx((tx as LegacyWalletTxHandle).wtx, { proposalId: p.proposalId, choiceIndex: p.choiceIndex, contractTerms: contractData.contractTerms, @@ -1717,7 +1717,7 @@ async function reselectCoinsTx( } await tx.purchases.put(p); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx as LegacyWalletTxHandle); if (p.payInfo.payCoinSelection) { await spendCoins(ctx.wex, tx, { @@ -2507,7 +2507,7 @@ export async function getChoicesForPayment( case MerchantContractVersion.V1: for (let i = 0; i < contractTerms.choices.length; i++) { tokenSels.push( - await selectPayTokensInTx(tx, { + await selectPayTokensInTx(tx.wtx, { proposalId, choiceIndex: i, contractTerms: contractTerms, @@ -2826,7 +2826,7 @@ export async function confirmPay( let selectTokensResult: SelectPayTokensResult | undefined; if (contractTerms.version === MerchantContractVersion.V1) { - selectTokensResult = await selectPayTokensInTx(tx, { + selectTokensResult = await selectPayTokensInTx(tx.wtx, { proposalId, choiceIndex: choiceIndex!, contractTerms, diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts @@ -69,10 +69,10 @@ import { WithdrawalGroupStatus, timestampPreciseFromDb, timestampPreciseToDb, + WalletPeerPullCredit, } from "./db-common.js"; import { OperationRetryRecord, - PeerPullCreditRecord, WalletIndexedDbTransaction, WithdrawalGroupRecord, WithdrawalRecordType, @@ -96,7 +96,11 @@ import { constructTransactionIdentifier, isUnsuccessfulTransaction, } from "./transactions.js"; -import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + walletExchangeClient, +} from "./wallet.js"; import { WithdrawTransactionContext, getExchangeWithdrawalInfo, @@ -124,8 +128,8 @@ export class PeerPullCreditTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { - const rec = await tx.peerPullCredit.get(this.pursePub); + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { + const rec = await tx.wtx.getPeerPullCredit(this.pursePub); if (rec == null) { await tx.transactionsMeta.delete(this.transactionId); } else { @@ -139,7 +143,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } } - async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> { + async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -162,9 +166,9 @@ export class PeerPullCreditTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { - const pullCredit = await tx.peerPullCredit.get(this.pursePub); + const pullCredit = await tx.wtx.getPeerPullCredit(this.pursePub); if (!pullCredit) { return undefined; } @@ -288,18 +292,18 @@ export class PeerPullCreditTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise< - [PeerPullCreditRecord | undefined, RecordHandle<PeerPullCreditRecord>] + [WalletPeerPullCredit | undefined, RecordHandle<WalletPeerPullCredit>] > { - return getGenericRecordHandle<PeerPullCreditRecord>( + return getGenericRecordHandle<WalletPeerPullCredit>( this, - tx as any, - async () => tx.peerPullCredit.get(this.pursePub), + tx, + async () => tx.wtx.getPeerPullCredit(this.pursePub), async (r) => { - await tx.peerPullCredit.put(r); + await tx.wtx.upsertPeerPullCredit(r); }, - async () => tx.peerPullCredit.delete(this.pursePub), + async () => tx.wtx.deletePeerPullCredit(this.pursePub), (r) => computePeerPullCreditTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -505,7 +509,7 @@ export class PeerPullCreditTransactionContext implements TransactionContext { async function processPendingReady( wex: WalletExecutionContext, - pullIni: PeerPullCreditRecord, + pullIni: WalletPeerPullCredit, ): Promise<TaskRunResult> { const ctx = new PeerPullCreditTransactionContext(wex, pullIni.pursePub); const exchangeClient = walletExchangeClient(pullIni.exchangeBaseUrl, wex); @@ -587,7 +591,7 @@ async function processPendingReady( async function processPendingMergeKycRequired( wex: WalletExecutionContext, - pullIni: PeerPullCreditRecord, + pullIni: WalletPeerPullCredit, ): Promise<TaskRunResult> { const ctx = new PeerPullCreditTransactionContext(wex, pullIni.pursePub); const { exchangeBaseUrl, kycPaytoHash } = pullIni; @@ -653,7 +657,7 @@ async function processPendingMergeKycRequired( async function processPeerPullCreditAbortingDeletePurse( wex: WalletExecutionContext, - peerPullIni: PeerPullCreditRecord, + peerPullIni: WalletPeerPullCredit, ): Promise<TaskRunResult> { const { pursePub, pursePriv } = peerPullIni; const ctx = new PeerPullCreditTransactionContext(wex, peerPullIni.pursePub); @@ -693,7 +697,7 @@ async function processPeerPullCreditAbortingDeletePurse( async function processPeerPullCreditWithdrawing( wex: WalletExecutionContext, - pullIni: PeerPullCreditRecord, + pullIni: WalletPeerPullCredit, ): Promise<TaskRunResult> { if (!pullIni.withdrawalGroupId) { throw Error("invalid db state (withdrawing, but no withdrawal group ID"); @@ -751,7 +755,7 @@ async function processPeerPullCreditWithdrawing( async function processPeerPullCreditCreatePurse( wex: WalletExecutionContext, - pullIni: PeerPullCreditRecord, + pullIni: WalletPeerPullCredit, ): Promise<TaskRunResult> { const ctx = new PeerPullCreditTransactionContext(wex, pullIni.pursePub); @@ -903,7 +907,7 @@ export async function processPeerPullCredit( } const pullIni = await wex.runLegacyWalletDbTx(async (tx) => - tx.peerPullCredit.get(pursePub), + tx.wtx.getPeerPullCredit(pursePub), ); if (!pullIni) { throw Error("peer pull payment initiation not found in database"); @@ -950,7 +954,7 @@ export async function processPeerPullCredit( async function processPeerPullCreditBalanceKyc( ctx: PeerPullCreditTransactionContext, - peerInc: PeerPullCreditRecord, + peerInc: WalletPeerPullCredit, ): Promise<TaskRunResult> { const exchangeBaseUrl = peerInc.exchangeBaseUrl; const amount = peerInc.estimatedAmountEffective; @@ -1031,7 +1035,7 @@ async function processPeerPullCreditBalanceKyc( async function handlePeerPullCreditKycRequired( wex: WalletExecutionContext, - peerIni: PeerPullCreditRecord, + peerIni: WalletPeerPullCredit, kycPaytoHash: string, ): Promise<TaskRunResult> { const ctx = new PeerPullCreditTransactionContext(wex, peerIni.pursePub); @@ -1249,7 +1253,7 @@ export async function initiatePeerPullPayment( } export function computePeerPullCreditTransactionState( - pullCreditRecord: PeerPullCreditRecord, + pullCreditRecord: WalletPeerPullCredit, ): TransactionState { switch (pullCreditRecord.status) { case PeerPullPaymentCreditStatus.PendingCreatePurse: @@ -1361,7 +1365,7 @@ export function computePeerPullCreditTransactionState( } export function computePeerPullCreditTransactionActions( - pullCreditRecord: PeerPullCreditRecord, + pullCreditRecord: WalletPeerPullCredit, ): TransactionAction[] { switch (pullCreditRecord.status) { case PeerPullPaymentCreditStatus.PendingCreatePurse: diff --git a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts @@ -79,11 +79,9 @@ import { RefreshOperationStatus, timestampPreciseFromDb, timestampPreciseToDb, + WalletPeerPullDebit, } from "./db-common.js"; -import { - PeerPullPaymentIncomingRecord, - WalletIndexedDbTransaction, -} from "./db-indexeddb.js"; +import { WalletIndexedDbTransaction } from "./db-indexeddb.js"; import { getExchangeScopeInfo, getScopeForAllExchanges } from "./exchanges.js"; import { getTotalPeerPaymentCost, @@ -96,7 +94,11 @@ import { isUnsuccessfulTransaction, parseTransactionIdentifier, } from "./transactions.js"; -import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + walletExchangeClient, +} from "./wallet.js"; const logger = new Logger("pay-peer-pull-debit.ts"); @@ -121,8 +123,8 @@ export class PeerPullDebitTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { - const rec = await tx.peerPullDebit.get(this.peerPullDebitId); + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { + const rec = await tx.wtx.getPeerPullDebit(this.peerPullDebitId); if (rec == null) { await tx.transactionsMeta.delete(this.transactionId); } else { @@ -143,9 +145,9 @@ export class PeerPullDebitTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { - const pi = await tx.peerPullDebit.get(this.peerPullDebitId); + const pi = await tx.wtx.getPeerPullDebit(this.peerPullDebitId); if (!pi) { return undefined; } @@ -181,21 +183,18 @@ export class PeerPullDebitTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise< - [ - PeerPullPaymentIncomingRecord | undefined, - RecordHandle<PeerPullPaymentIncomingRecord>, - ] + [WalletPeerPullDebit | undefined, RecordHandle<WalletPeerPullDebit>] > { - return getGenericRecordHandle<PeerPullPaymentIncomingRecord>( + return getGenericRecordHandle<WalletPeerPullDebit>( this, - tx as any, - async () => tx.peerPullDebit.get(this.peerPullDebitId), + tx, + async () => tx.wtx.getPeerPullDebit(this.peerPullDebitId), async (r) => { - await tx.peerPullDebit.put(r); + await tx.wtx.upsertPeerPullDebit(r); }, - async () => tx.peerPullDebit.delete(this.peerPullDebitId), + async () => tx.wtx.deletePeerPullDebit(this.peerPullDebitId), (r) => computePeerPullDebitTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -224,7 +223,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { }); } - async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> { + async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -360,7 +359,7 @@ export class PeerPullDebitTransactionContext implements TransactionContext { async function handlePurseCreationConflict( ctx: PeerPullDebitTransactionContext, - peerPullInc: PeerPullPaymentIncomingRecord, + peerPullInc: WalletPeerPullDebit, conflict: PurseConflict, ): Promise<TaskRunResult> { if (conflict.code !== TalerErrorCode.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS) { @@ -444,7 +443,7 @@ async function handlePurseCreationConflict( async function processPeerPullDebitDialogProposed( wex: WalletExecutionContext, - pullIni: PeerPullPaymentIncomingRecord, + pullIni: WalletPeerPullDebit, ): Promise<TaskRunResult> { const ctx = new PeerPullDebitTransactionContext(wex, pullIni.peerPullDebitId); const exchangeClient = walletExchangeClient(pullIni.exchangeBaseUrl, wex); @@ -501,7 +500,7 @@ async function processPeerPullDebitDialogProposed( async function processPeerPullDebitPendingDeposit( wex: WalletExecutionContext, - peerPullInc: PeerPullPaymentIncomingRecord, + peerPullInc: WalletPeerPullDebit, ): Promise<TaskRunResult> { const ctx = new PeerPullDebitTransactionContext( wex, @@ -648,7 +647,7 @@ async function processPeerPullDebitPendingDeposit( async function processPeerPullDebitAbortingRefresh( wex: WalletExecutionContext, - peerPullInc: PeerPullPaymentIncomingRecord, + peerPullInc: WalletPeerPullDebit, ): Promise<TaskRunResult> { const peerPullDebitId = peerPullInc.peerPullDebitId; const abortRefreshGroupId = peerPullInc.abortRefreshGroupId; @@ -693,7 +692,7 @@ export async function processPeerPullDebit( } const peerPullInc = await wex.runLegacyWalletDbTx(async (tx) => - tx.peerPullDebit.get(peerPullDebitId), + tx.wtx.getPeerPullDebit(peerPullDebitId), ); if (!peerPullInc) { throw Error("peer pull debit not found"); @@ -728,7 +727,7 @@ export async function confirmPeerPullDebit( } const peerPullInc = await wex.runLegacyWalletDbTx(async (tx) => - tx.peerPullDebit.get(parsed.peerPullDebitId), + tx.wtx.getPeerPullDebit(parsed.peerPullDebitId), ); if (peerPullInc == null) { @@ -841,15 +840,15 @@ export async function preparePeerPullDebit( } const existing = await wex.runLegacyWalletDbTx(async (tx) => { - let peerPullDebitRecord: PeerPullPaymentIncomingRecord | undefined; + let peerPullDebitRecord: WalletPeerPullDebit | undefined; if (uri) { peerPullDebitRecord = - await tx.peerPullDebit.indexes.byExchangeAndContractPriv.get([ + await tx.wtx.getPeerPullDebitByExchangeAndContractPriv( uri.exchangeBaseUrl, uri.contractPriv, - ]); + ); } else if (parsedTxId) { - peerPullDebitRecord = await tx.peerPullDebit.get(parsedTxId); + peerPullDebitRecord = await tx.wtx.getPeerPullDebit(parsedTxId); } if (!peerPullDebitRecord) { return; @@ -1002,7 +1001,7 @@ export async function preparePeerPullDebit( if (rec) { throw Error("peer-pull-debit record already exists"); } - const newRec: PeerPullPaymentIncomingRecord = { + const newRec: WalletPeerPullDebit = { peerPullDebitId, contractPriv: contractPriv, exchangeBaseUrl: exchangeBaseUrl, @@ -1035,7 +1034,7 @@ export async function preparePeerPullDebit( } export function computePeerPullDebitTransactionState( - pullDebitRecord: PeerPullPaymentIncomingRecord, + pullDebitRecord: WalletPeerPullDebit, ): TransactionState { switch (pullDebitRecord.status) { case PeerPullDebitRecordStatus.DialogProposed: @@ -1085,7 +1084,7 @@ export function computePeerPullDebitTransactionState( } export function computePeerPullDebitTransactionActions( - pullDebitRecord: PeerPullPaymentIncomingRecord, + pullDebitRecord: WalletPeerPullDebit, ): TransactionAction[] { switch (pullDebitRecord.status) { case PeerPullDebitRecordStatus.DialogProposed: diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/pay-peer-push-credit.ts @@ -71,10 +71,10 @@ import { WithdrawalGroupStatus, timestampPreciseFromDb, timestampPreciseToDb, + WalletPeerPushCredit, } from "./db-common.js"; import { OperationRetryRecord, - PeerPushCreditRecord, WalletIndexedDbTransaction, WithdrawalGroupRecord, WithdrawalRecordType, @@ -100,7 +100,11 @@ import { isUnsuccessfulTransaction, parseTransactionIdentifier, } from "./transactions.js"; -import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + walletExchangeClient, +} from "./wallet.js"; import { PerformCreateWithdrawalGroupResult, WithdrawTransactionContext, @@ -130,8 +134,8 @@ export class PeerPushCreditTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { - const rec = await tx.peerPushCredit.get(this.peerPushCreditId); + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { + const rec = await tx.wtx.getPeerPushCredit(this.peerPushCreditId); if (rec == null) { await tx.transactionsMeta.delete(this.transactionId); } else { @@ -152,9 +156,9 @@ export class PeerPushCreditTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { - const pushInc = await tx.peerPushCredit.get(this.peerPushCreditId); + const pushInc = await tx.wtx.getPeerPushCredit(this.peerPushCreditId); if (!pushInc) { return undefined; } @@ -261,18 +265,18 @@ export class PeerPushCreditTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise< - [PeerPushCreditRecord | undefined, RecordHandle<PeerPushCreditRecord>] + [WalletPeerPushCredit | undefined, RecordHandle<WalletPeerPushCredit>] > { - return getGenericRecordHandle<PeerPushCreditRecord>( + return getGenericRecordHandle<WalletPeerPushCredit>( this, - tx as any, - async () => tx.peerPushCredit.get(this.peerPushCreditId), + tx, + async () => tx.wtx.getPeerPushCredit(this.peerPushCreditId), async (r) => { - await tx.peerPushCredit.put(r); + await tx.wtx.upsertPeerPushCredit(r); }, - async () => tx.peerPushCredit.delete(this.peerPushCreditId), + async () => tx.wtx.deletePeerPushCredit(this.peerPushCreditId), (r) => computePeerPushCreditTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -285,7 +289,7 @@ export class PeerPushCreditTransactionContext implements TransactionContext { ); } - async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> { + async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -498,15 +502,14 @@ export async function preparePeerPushCredit( } const existing = await wex.runLegacyWalletDbTx(async (tx) => { - let existingPushInc: PeerPushCreditRecord | undefined; + let existingPushInc: WalletPeerPushCredit | undefined; if (uri) { - existingPushInc = - await tx.peerPushCredit.indexes.byExchangeAndContractPriv.get([ - uri.exchangeBaseUrl, - uri.contractPriv, - ]); + existingPushInc = await tx.wtx.getPeerPushCreditByExchangeAndContractPriv( + uri.exchangeBaseUrl, + uri.contractPriv, + ); } else if (parsedTxId) { - existingPushInc = await tx.peerPushCredit.get(parsedTxId); + existingPushInc = await tx.wtx.getPeerPushCredit(parsedTxId); } if (!existingPushInc) { return; @@ -639,7 +642,7 @@ export async function preparePeerPushCredit( if (rec) { throw Error("record already exists"); } - const newRec: PeerPushCreditRecord = { + const newRec: WalletPeerPushCredit = { peerPushCreditId, contractPriv: contractPriv, exchangeBaseUrl: exchangeBaseUrl, @@ -676,7 +679,7 @@ export async function preparePeerPushCredit( async function processPeerPushDebitMergeKyc( wex: WalletExecutionContext, - peerInc: PeerPushCreditRecord, + peerInc: WalletPeerPushCredit, contractTerms: PeerContractTerms, ): Promise<TaskRunResult> { const ctx = new PeerPushCreditTransactionContext( @@ -745,7 +748,7 @@ async function processPeerPushDebitMergeKyc( async function transitionPeerPushCreditKycRequired( wex: WalletExecutionContext, - peerInc: PeerPushCreditRecord, + peerInc: WalletPeerPushCredit, kycPending: LegitimizationNeededResponse, ): Promise<TaskRunResult> { const ctx = new PeerPushCreditTransactionContext( @@ -768,7 +771,7 @@ async function transitionPeerPushCreditKycRequired( async function processPendingMerge( wex: WalletExecutionContext, - peerInc: PeerPushCreditRecord, + peerInc: WalletPeerPushCredit, contractTerms: PeerContractTerms, ): Promise<TaskRunResult> { const { peerPushCreditId } = peerInc; @@ -953,7 +956,7 @@ async function processPendingMerge( async function processPendingWithdrawing( wex: WalletExecutionContext, - peerInc: PeerPushCreditRecord, + peerInc: WalletPeerPushCredit, ): Promise<TaskRunResult> { if (!peerInc.withdrawalGroupId) { throw Error("invalid db state (withdrawing, but no withdrawal group ID"); @@ -1023,7 +1026,7 @@ async function processPendingWithdrawing( async function processPeerPushDebitDialogProposed( wex: WalletExecutionContext, - pullIni: PeerPushCreditRecord, + pullIni: WalletPeerPushCredit, ): Promise<TaskRunResult> { const ctx = new PeerPushCreditTransactionContext( wex, @@ -1097,7 +1100,7 @@ export async function processPeerPushCredit( const { peerInc, contractTerms } = await wex.runLegacyWalletDbTx( async (tx) => { - const rec = await tx.peerPushCredit.get(peerPushCreditId); + const rec = await tx.wtx.getPeerPushCredit(peerPushCreditId); let contractTerms = null; if (rec != null) { const contract = await tx.contractTerms.get(rec.contractTermsHash); @@ -1149,7 +1152,7 @@ export async function processPeerPushCredit( async function processPeerPushCreditBalanceKyc( ctx: PeerPushCreditTransactionContext, - peerInc: PeerPushCreditRecord, + peerInc: WalletPeerPushCredit, ): Promise<TaskRunResult> { const exchangeBaseUrl = peerInc.exchangeBaseUrl; const amount = peerInc.estimatedAmountEffective; @@ -1247,7 +1250,7 @@ export async function confirmPeerPushCredit( logger.trace(`confirming peer-push-credit ${ctx.peerPushCreditId}`); const res = await wex.runLegacyWalletDbTx(async (tx) => { - const rec = await tx.peerPushCredit.get(ctx.peerPushCreditId); + const rec = await tx.wtx.getPeerPushCredit(ctx.peerPushCreditId); if (!rec) { return; } @@ -1298,7 +1301,7 @@ export async function confirmPeerPushCredit( } export function computePeerPushCreditTransactionState( - pushCreditRecord: PeerPushCreditRecord, + pushCreditRecord: WalletPeerPushCredit, ): TransactionState { switch (pushCreditRecord.status) { case PeerPushCreditStatus.DialogProposed: @@ -1396,7 +1399,7 @@ export function computePeerPushCreditTransactionState( } export function computePeerPushCreditTransactionActions( - pushCreditRecord: PeerPushCreditRecord, + pushCreditRecord: WalletPeerPushCredit, ): TransactionAction[] { switch (pushCreditRecord.status) { case PeerPushCreditStatus.DialogProposed: diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/pay-peer-push-debit.ts @@ -80,11 +80,9 @@ import { timestampPreciseToDb, timestampProtocolFromDb, timestampProtocolToDb, + WalletPeerPushDebit, } from "./db-common.js"; -import { - PeerPushDebitRecord, - WalletIndexedDbTransaction, -} from "./db-indexeddb.js"; +import { WalletIndexedDbTransaction } from "./db-indexeddb.js"; import { fetchFreshExchange, getExchangeDetailsInTx, @@ -102,7 +100,11 @@ import { constructTransactionIdentifier, isUnsuccessfulTransaction, } from "./transactions.js"; -import { WalletExecutionContext, walletExchangeClient } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + walletExchangeClient, +} from "./wallet.js"; import { updateWithdrawalDenomsForCurrency } from "./withdraw.js"; const logger = new Logger("pay-peer-push-debit.ts"); @@ -125,8 +127,8 @@ export class PeerPushDebitTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { - const rec = await tx.peerPushDebit.get(this.pursePub); + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { + const rec = await tx.wtx.getPeerPushDebit(this.pursePub); logger.info(`updating peer-push-debit meta for ${j2s(rec)}`); if (rec == null) { await tx.transactionsMeta.delete(this.transactionId); @@ -148,9 +150,9 @@ export class PeerPushDebitTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { - const pushDebitRec = await tx.peerPushDebit.get(this.pursePub); + const pushDebitRec = await tx.wtx.getPeerPushDebit(this.pursePub); if (pushDebitRec == null) { return undefined; } @@ -204,18 +206,18 @@ export class PeerPushDebitTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise< - [PeerPushDebitRecord | undefined, RecordHandle<PeerPushDebitRecord>] + [WalletPeerPushDebit | undefined, RecordHandle<WalletPeerPushDebit>] > { - return getGenericRecordHandle<PeerPushDebitRecord>( + return getGenericRecordHandle<WalletPeerPushDebit>( this, - tx as any, - async () => tx.peerPushDebit.get(this.pursePub), + tx, + async () => tx.wtx.getPeerPushDebit(this.pursePub), async (r) => { - await tx.peerPushDebit.put(r); + await tx.wtx.upsertPeerPushDebit(r); }, - async () => tx.peerPushDebit.delete(this.pursePub), + async () => tx.wtx.deletePeerPushDebit(this.pursePub), (r) => computePeerPushDebitTransactionState(r), (r) => r.status, () => this.updateTransactionMeta(tx), @@ -228,7 +230,7 @@ export class PeerPushDebitTransactionContext implements TransactionContext { }); } - async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> { + async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -523,7 +525,7 @@ async function internalCheckPeerPushDebit( async function handlePurseCreationConflict( wex: WalletExecutionContext, - peerPushInitiation: PeerPushDebitRecord, + peerPushInitiation: WalletPeerPushDebit, conflict: PurseConflict, ): Promise<TaskRunResult> { const pursePub = peerPushInitiation.pursePub; @@ -604,7 +606,7 @@ async function handlePurseCreationConflict( async function processPeerPushDebitCreateReserve( wex: WalletExecutionContext, - peerPushInitiation: PeerPushDebitRecord, + peerPushInitiation: WalletPeerPushDebit, ): Promise<TaskRunResult> { const { pursePub, purseExpiration, contractTermsHash, exchangeBaseUrl } = peerPushInitiation; @@ -856,7 +858,7 @@ async function processPeerPushDebitCreateReserve( async function processPeerPushDebitAbortingDeletePurse( wex: WalletExecutionContext, - peerPushInitiation: PeerPushDebitRecord, + peerPushInitiation: WalletPeerPushDebit, ): Promise<TaskRunResult> { const { pursePub, pursePriv, exchangeBaseUrl } = peerPushInitiation; const ctx = new PeerPushDebitTransactionContext(wex, pursePub); @@ -933,7 +935,7 @@ async function processPeerPushDebitAbortingDeletePurse( */ async function processPeerPushDebitReady( wex: WalletExecutionContext, - peerPushInitiation: PeerPushDebitRecord, + peerPushInitiation: WalletPeerPushDebit, ): Promise<TaskRunResult> { logger.trace("processing peer-push-debit pending(ready)"); const pursePub = peerPushInitiation.pursePub; @@ -1019,7 +1021,7 @@ export async function processPeerPushDebit( } const peerPushInitiation = await wex.runLegacyWalletDbTx(async (tx) => { - return tx.peerPushDebit.get(pursePub); + return tx.wtx.getPeerPushDebit(pursePub); }); if (!peerPushInitiation) { return TaskRunResult.finished(); @@ -1152,7 +1154,7 @@ export async function initiatePeerPushDebit( const hContractTerms = ContractTermsUtil.hashContractTerms(contractTerms); const totalAmount = await getTotalPeerPaymentCostInTx(wex, tx, coins); - const ppi: PeerPushDebitRecord = { + const ppi: WalletPeerPushDebit = { amount: Amounts.stringify(instructedAmount), restrictScope: req.restrictScope, contractPriv: contractKeyPair.priv, @@ -1213,7 +1215,7 @@ export async function initiatePeerPushDebit( } export function computePeerPushDebitTransactionActions( - ppiRecord: PeerPushDebitRecord, + ppiRecord: WalletPeerPushDebit, ): TransactionAction[] { switch (ppiRecord.status) { case PeerPushDebitStatus.PendingCreatePurse: @@ -1252,7 +1254,7 @@ export function computePeerPushDebitTransactionActions( } export function computePeerPushDebitTransactionState( - ppiRecord: PeerPushDebitRecord, + ppiRecord: WalletPeerPushDebit, ): TransactionState { switch (ppiRecord.status) { case PeerPushDebitStatus.PendingCreatePurse: diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts @@ -67,7 +67,11 @@ import { } from "./db-indexeddb.js"; import { createRefreshGroup } from "./refresh.js"; import { constructTransactionIdentifier } from "./transactions.js"; -import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + getDenomInfo, +} from "./wallet.js"; import { internalCreateWithdrawalGroup } from "./withdraw.js"; const logger = new Logger("operations/recoup.ts"); @@ -91,7 +95,7 @@ export async function putGroupAsFinished( } recoupGroup.recoupFinishedPerCoin[coinIdx] = true; await tx.recoupGroups.put(recoupGroup); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx as LegacyWalletTxHandle); } async function recoupRewardCoin( @@ -420,7 +424,7 @@ export class RecoupTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const recoupRec = await tx.recoupGroups.get(this.recoupGroupId); if (!recoupRec) { await tx.transactionsMeta.delete(this.transactionId); @@ -474,7 +478,7 @@ export class RecoupTransactionContext implements TransactionContext { } async deleteTransactionInTx( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<{ notifs: WalletNotification[] }> { const notifs: WalletNotification[] = []; const rec = await tx.recoupGroups.get(this.recoupGroupId); @@ -487,7 +491,7 @@ export class RecoupTransactionContext implements TransactionContext { } lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { throw new Error("Method not implemented."); } @@ -524,7 +528,7 @@ export async function createRecoupGroup( } await tx.recoupGroups.put(recoupGroup); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx as LegacyWalletTxHandle); wex.taskScheduler.startShepherdTask(ctx.taskId); diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts @@ -120,6 +120,7 @@ import { import { EXCHANGE_COINS_LOCK, getDenomInfo, + LegacyWalletTxHandle, WalletExecutionContext, } from "./wallet.js"; import { @@ -150,7 +151,7 @@ export class RefreshTransactionContext implements TransactionContext { }); } - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const rgRec = await tx.refreshGroups.get(this.refreshGroupId); if (!rgRec) { await tx.transactionsMeta.delete(this.transactionId); @@ -172,7 +173,7 @@ export class RefreshTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { const refreshGroupRecord = await tx.refreshGroups.get(this.refreshGroupId); if (!refreshGroupRecord) { @@ -220,7 +221,7 @@ export class RefreshTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise< [RefreshGroupRecord | undefined, RecordHandle<RefreshGroupRecord>] > { @@ -244,7 +245,7 @@ export class RefreshTransactionContext implements TransactionContext { }); } - async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> { + async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { const [rg, h] = await this.getRecordHandle(tx); if (!rg) { logger.warn( @@ -1681,7 +1682,7 @@ export async function createRefreshGroup( const ctx = new RefreshTransactionContext(wex, refreshGroupId); await tx.refreshGroups.put(refreshGroup); - await ctx.updateTransactionMeta(tx); + await ctx.updateTransactionMeta(tx as LegacyWalletTxHandle); const newTxState = computeRefreshTransactionState(refreshGroup); diff --git a/packages/taler-wallet-core/src/tokenFamilies.ts b/packages/taler-wallet-core/src/tokenFamilies.ts @@ -29,7 +29,7 @@ import { MerchantInfo, SubscriptionListDetail, } from "@gnu-taler/taler-util"; -import { TokenRecord } from "./db-indexeddb.js"; +import { WalletToken } from "./db-common.js"; import { WalletExecutionContext } from "./index.js"; import { expectProposalDownloadInTx } from "./pay-merchant.js"; import { isTokenInUse, isTokenValid } from "./tokenSelection.js"; @@ -40,7 +40,7 @@ export type MerchantInfos = { [purchaseId: string]: MerchantInfo }; // FIXME: unit test for discount grouping function groupDiscounts( - tokens: TokenRecord[], + tokens: WalletToken[], merchantInfos: MerchantInfos, ): DiscountListDetail[] { const groupedIdx: number[] = []; @@ -86,7 +86,7 @@ function groupDiscounts( // FIXME: unit test for subscription grouping function groupSubscriptions( - tokens: TokenRecord[], + tokens: WalletToken[], merchantInfos: MerchantInfos, ): SubscriptionListDetail[] { const groupedIdx: number[] = []; @@ -130,13 +130,13 @@ function groupSubscriptions( async function getMerchantInfos( wex: WalletExecutionContext, - tokens: TokenRecord[], + tokens: WalletToken[], ): Promise<MerchantInfos> { const merchantInfos: MerchantInfos = {}; await wex.runLegacyWalletDbTx(async (tx) => { for (const t of tokens) { if (t.purchaseId in merchantInfos) continue; - const purchase = await tx.purchases.get(t.purchaseId); + const purchase = await tx.wtx.getPurchase(t.purchaseId); if (!purchase) continue; const download = await expectProposalDownloadInTx(wex, tx, purchase); const contractData = download.contractTerms; @@ -151,8 +151,8 @@ export async function listDiscounts( tokenIssuePubHash?: string, merchantBaseUrl?: string, ): Promise<ListDiscountsResponse> { - const tokens: TokenRecord[] = await wex.runLegacyWalletDbTx(async (tx) => { - return (await tx.tokens.getAll()) + const tokens: WalletToken[] = await wex.runLegacyWalletDbTx(async (tx) => { + return (await tx.wtx.listTokens()) .filter((t) => isTokenValid(t)) .filter((t) => t.kind === MerchantContractTokenKind.Discount) .filter( @@ -175,8 +175,8 @@ export async function listSubscriptions( tokenIssuePubHash?: string, merchantBaseUrl?: string, ): Promise<ListSubscriptionsResponse> { - const tokens: TokenRecord[] = await wex.runLegacyWalletDbTx(async (tx) => { - return (await tx.tokens.getAll()) + const tokens: WalletToken[] = await wex.runLegacyWalletDbTx(async (tx) => { + return (await tx.wtx.listTokens()) .filter((t) => isTokenValid(t)) .filter((t) => t.kind === MerchantContractTokenKind.Subscription) .filter( @@ -202,7 +202,7 @@ export async function deleteDiscount( tokenFamilyHash: string, ): Promise<EmptyObject> { await wex.runLegacyWalletDbTx(async (tx) => { - const tokens = (await tx.tokens.getAll()) + const tokens = (await tx.wtx.listTokens()) .filter((t) => t.kind === MerchantContractTokenKind.Discount) .filter((t) => t.tokenFamilyHash === tokenFamilyHash); @@ -225,7 +225,7 @@ export async function deleteDiscount( `deleting token in ${token.tokenIssuePubHash} token family`, ); } - await tx.tokens.delete(token.tokenUsePub); + await tx.wtx.deleteToken(token.tokenUsePub); } }); @@ -237,7 +237,7 @@ export async function deleteSubscription( tokenFamilyHash: string, ): Promise<EmptyObject> { await wex.runLegacyWalletDbTx(async (tx) => { - const tokens = (await tx.tokens.getAll()) + const tokens = (await tx.wtx.listTokens()) .filter((t) => t.kind === MerchantContractTokenKind.Subscription) .filter((t) => t.tokenFamilyHash === tokenFamilyHash) .sort((a, b) => a.validBefore - b.validBefore); diff --git a/packages/taler-wallet-core/src/tokenSelection.ts b/packages/taler-wallet-core/src/tokenSelection.ts @@ -28,8 +28,8 @@ import { TalerProtocolTimestamp, TokenAvailabilityHint, } from "@gnu-taler/taler-util"; -import { timestampProtocolFromDb } from "./db-common.js"; -import { TokenRecord, WalletIndexedDbTransaction } from "./db-indexeddb.js"; +import { timestampProtocolFromDb, WalletToken } from "./db-common.js"; +import { WalletDbTransaction } from "./dbtx.js"; import { WalletExecutionContext } from "./index.js"; const logger = new Logger("tokenSelection.ts"); @@ -52,7 +52,7 @@ export type SelectPayTokensResult = } | { type: "success"; - tokens: TokenRecord[]; + tokens: WalletToken[]; details: PaymentTokenAvailabilityDetails; }; @@ -156,14 +156,14 @@ export function verifyTokenMerchant( } export async function selectPayTokensInTx( - tx: WalletIndexedDbTransaction, + tx: WalletDbTransaction, req: SelectPayTokensRequest, ): Promise<SelectPayTokensResult> { if (logger.shouldLogTrace()) { logger.trace(`selecting tokens for ${j2s(req)}`); } - const proposal = await tx.purchases.get(req.proposalId); + const proposal = await tx.getPurchase(req.proposalId); if (!proposal) { throw Error(`proposal ${req.proposalId} could not be found`); } @@ -171,7 +171,7 @@ export async function selectPayTokensInTx( var tokensRequested = 0; const inputTokens: { [slug: string]: { - records: TokenRecord[]; + records: WalletToken[]; requested: number; }; } = {}; @@ -193,7 +193,7 @@ export async function selectPayTokensInTx( const keyHash = encodeCrock(hashTokenIssuePub(key)); if (!tokenIssuePubs.includes(keyHash)) { tokenIssuePubs.push(keyHash); - const t = await tx.tokens.indexes.byTokenIssuePubHash.getAll(keyHash); + const t = await tx.getTokensByIssuePubHash(keyHash); inputTokens[slug].records.push(...t); } } @@ -217,14 +217,14 @@ export async function selectPayTokens( req: SelectPayTokensRequest, ): Promise<SelectPayTokensResult> { return await wex.runLegacyWalletDbTx(async (tx) => { - return selectPayTokensInTx(tx, req); + return selectPayTokensInTx(tx.wtx, req); }); } export function selectTokenCandidates( inputTokens: { [slug: string]: { - records: TokenRecord[]; + records: WalletToken[]; requested: number; }; }, @@ -240,7 +240,7 @@ export function selectTokenCandidates( }; var insufficient = false; - const tokens: TokenRecord[] = []; + const tokens: WalletToken[] = []; for (const slug in inputTokens) { const { records, requested } = inputTokens[slug]; @@ -324,11 +324,11 @@ export function selectTokenCandidates( }; } -export function isTokenInUse(tok: TokenRecord): boolean { +export function isTokenInUse(tok: WalletToken): boolean { return tok.transactionId !== undefined; } -export function isTokenValid(tok: TokenRecord): boolean { +export function isTokenValid(tok: WalletToken): boolean { return AbsoluteTime.isBetween( AbsoluteTime.now(), AbsoluteTime.fromProtocolTimestamp(timestampProtocolFromDb(tok.validAfter)), @@ -339,7 +339,7 @@ export function isTokenValid(tok: TokenRecord): boolean { } export function isTokenValidBetween( - tok: TokenRecord, + tok: WalletToken, start: TalerProtocolTimestamp, end: TalerProtocolTimestamp, ): boolean { diff --git a/packages/taler-wallet-core/src/transactions.ts b/packages/taler-wallet-core/src/transactions.ts @@ -73,7 +73,7 @@ import { PeerPullDebitTransactionContext } from "./pay-peer-pull-debit.js"; import { PeerPushCreditTransactionContext } from "./pay-peer-push-credit.js"; import { PeerPushDebitTransactionContext } from "./pay-peer-push-debit.js"; import { RefreshTransactionContext } from "./refresh.js"; -import type { WalletExecutionContext } from "./wallet.js"; +import type { LegacyWalletTxHandle, WalletExecutionContext } from "./wallet.js"; import { WithdrawTransactionContext } from "./withdraw.js"; const logger = new Logger("taler-wallet-core:transactions.ts"); @@ -266,7 +266,9 @@ async function addFiltered( } if (checkFilterIncludes(req, mtx)) { const ctx = await getContextForTransaction(wex, mtx.transactionId); - const txDetails = await ctx.lookupFullTransaction(tx); + const txDetails = await ctx.lookupFullTransaction( + tx as LegacyWalletTxHandle, + ); // FIXME: This means that in some cases we can return fewer transactions // than requested. if (!txDetails) { @@ -566,7 +568,7 @@ export async function getTransactions( */ export async function rematerializeTransactions( wex: WalletExecutionContext, - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<void> { logger.trace("re-materializing transactions"); diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts @@ -184,7 +184,11 @@ import { parseTransactionIdentifier, } from "./transactions.js"; import { WALLET_EXCHANGE_PROTOCOL_VERSION } from "./versions.js"; -import { WalletExecutionContext, getDenomInfo } from "./wallet.js"; +import { + LegacyWalletTxHandle, + WalletExecutionContext, + getDenomInfo, +} from "./wallet.js"; import { WithdrawalGroupStatus, timestampPreciseFromDb, @@ -365,7 +369,7 @@ export class WithdrawTransactionContext implements TransactionContext { * transaction item (e.g. if it was deleted). */ async lookupFullTransaction( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise<Transaction | undefined> { const withdrawalGroupRecord = await tx.withdrawalGroups.get( this.withdrawalGroupId, @@ -437,7 +441,7 @@ export class WithdrawTransactionContext implements TransactionContext { /** * Update the metadata of the transaction in the database. */ - async updateTransactionMeta(tx: WalletIndexedDbTransaction): Promise<void> { + async updateTransactionMeta(tx: LegacyWalletTxHandle): Promise<void> { const ctx = this; const wgRecord = await tx.withdrawalGroups.get(ctx.withdrawalGroupId); if (!wgRecord) { @@ -482,7 +486,7 @@ export class WithdrawTransactionContext implements TransactionContext { } async getRecordHandle( - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, ): Promise< [WithdrawalGroupRecord | undefined, RecordHandle<WithdrawalGroupRecord>] > { @@ -506,7 +510,7 @@ export class WithdrawTransactionContext implements TransactionContext { }); } - async deleteTransactionInTx(tx: WalletIndexedDbTransaction): Promise<void> { + async deleteTransactionInTx(tx: LegacyWalletTxHandle): Promise<void> { const [rec, h] = await this.getRecordHandle(tx); if (!rec) { return; @@ -3597,7 +3601,7 @@ export interface PerformCreateWithdrawalGroupResult { export async function internalPerformCreateWithdrawalGroup( wex: WalletExecutionContext, - tx: WalletIndexedDbTransaction, + tx: LegacyWalletTxHandle, prep: PrepareCreateWithdrawalGroupResult, ): Promise<PerformCreateWithdrawalGroupResult> { const { withdrawalGroup } = prep;