taler-typescript-core

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

commit 8b22ae29a035bbabab132ba3e0f7078e943525e4
parent d9af4dd3f745d17d171d292d21da8ebf7e44f5f7
Author: Iván Ávalos <avalos@disroot.org>
Date:   Thu, 27 Mar 2025 17:30:08 +0100

WIP: split DB access and token selection logic

Diffstat:
Mpackages/taler-wallet-core/src/tokenSelection.ts | 86+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
1 file changed, 56 insertions(+), 30 deletions(-)

diff --git a/packages/taler-wallet-core/src/tokenSelection.ts b/packages/taler-wallet-core/src/tokenSelection.ts @@ -20,6 +20,7 @@ import { hashTokenIssuePub, j2s, Logger, + MerchantContractInput, MerchantContractInputType, MerchantContractTermsV1, MerchantContractTokenDetails, @@ -176,7 +177,54 @@ export async function selectPayTokensInTx( throw Error(`proposal ${req.proposalId} could not be found`); } - const records: TokenRecord[] = []; + const inputs = req.contractTerms.choices[req.choiceIndex].inputs; + const inputTokens: {[slug: string]: TokenRecord[]} = {}; + for (const input of inputs) { + if (input.type == MerchantContractInputType.Token) { + const slug = input.token_family_slug; + const keys = req.contractTerms.token_families[slug].keys; + + for (const key of keys) { + const keyHash = encodeCrock(hashTokenIssuePub(key)); + const t = await tx.tokens.indexes.byTokenIssuePubHash.getAll(keyHash); + if (inputTokens[slug]) { + inputTokens[slug].push(...t); + } else { + inputTokens[slug] = t; + } + } + } + } + + return selectTokenCandidates( + inputs, + inputTokens, + proposal.merchantBaseUrl, + ); +} + +export async function selectPayTokens( + wex: WalletExecutionContext, + req: SelectPayTokensRequest, +): Promise<SelectPayTokensResult> { + return await wex.db.runReadOnlyTx( + { + storeNames: [ + "tokens", + "purchases", + ] + }, + async (tx) => { + return selectPayTokensInTx(tx, req); + } + ); +} + +export function selectTokenCandidates( + inputs: MerchantContractInput[], + inputTokens: {[slug: string]: TokenRecord[]}, + merchantBaseUrl: string, +): SelectPayTokensResult { const details: PaymentTokenAvailabilityDetails = { tokensRequested: 0, tokensAvailable: 0, @@ -186,29 +234,24 @@ export async function selectPayTokensInTx( }; var insufficient = false; + const records: TokenRecord[] = []; - const inputs = req.contractTerms.choices[req.choiceIndex].inputs; for (const input of inputs) { if (input.type == MerchantContractInputType.Token) { const count = input.count ?? 1; const slug = input.token_family_slug; - const keys = req.contractTerms.token_families[slug].keys; + const tokens = inputTokens[slug]; details.tokensRequested += count; - const tokens: TokenRecord[] = []; - for (const key of keys) { - const keyHash = encodeCrock(hashTokenIssuePub(key)); - const t = await tx.tokens.indexes.byTokenIssuePubHash.getAll(keyHash); - tokens.push(...t); + for (const t of tokens) { + const keyHash = t.tokenIssuePubHash; if (details.perTokenFamily[keyHash] === undefined) { details.perTokenFamily[keyHash] = { requested: count, available: 0, unexpected: 0, untrusted: 0, - }; - } else { - details.perTokenFamily[keyHash].requested += count; + } } } @@ -225,7 +268,7 @@ export async function selectPayTokensInTx( AbsoluteTime.fromProtocolTimestamp(timestampProtocolFromDb(tok.validBefore)), )).filter(tok => { const res = verifyTokenMerchant( - proposal.merchantBaseUrl, + merchantBaseUrl, tok.merchantBaseUrl, tok.extraData, ); @@ -268,22 +311,5 @@ export async function selectPayTokensInTx( type: "success", tokens: records, details: details, - } -} - -export async function selectPayTokens( - wex: WalletExecutionContext, - req: SelectPayTokensRequest, -): Promise<SelectPayTokensResult> { - return await wex.db.runReadOnlyTx( - { - storeNames: [ - "tokens", - "purchases", - ] - }, - async (tx) => { - return selectPayTokensInTx(tx, req); - } - ); + }; }