diff options
author | Sebastian <sebasjm@gmail.com> | 2022-09-06 17:17:44 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2022-09-06 17:17:50 -0300 |
commit | 1e00724a0dcd0d65e6d786a1d8d7cdffc9fe2a85 (patch) | |
tree | 34eb327ac3370174cec4365ecc375309462d239b /packages/taler-wallet-core | |
parent | 49c9279c1e06a90757b2bd3e75b4887e71345d1d (diff) | |
download | wallet-core-1e00724a0dcd0d65e6d786a1d8d7cdffc9fe2a85.tar.xz |
listExchangesDetailed to getExchangeDetailedInfo & ageRestriction taken from the denoms
Diffstat (limited to 'packages/taler-wallet-core')
5 files changed, 76 insertions, 53 deletions
diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index 9ca1ccb5a..7148999c5 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -82,10 +82,15 @@ export async function prepareTip( logger.trace("new tip, creating tip record"); await updateExchangeFromUrl(ws, tipPickupStatus.exchange_url); + + //FIXME: is this needed? withdrawDetails is not used + // * if the intention is to update the exchange information in the database + // maybe we can use another name. `get` seems like a pure-function const withdrawDetails = await getExchangeWithdrawalInfo( ws, tipPickupStatus.exchange_url, amount, + undefined ); const walletTipId = encodeCrock(getRandomBytes(32)); diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 11f47d8a0..956d565a6 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -161,7 +161,6 @@ export async function getTransactions( info: { expiration: pi.contractTerms.purse_expiration, summary: pi.contractTerms.summary, - completed: Amounts.isZero(amount), }, frozen: false, pending: !pi.purseCreated, @@ -199,7 +198,6 @@ export async function getTransactions( info: { expiration: pi.contractTerms.purse_expiration, summary: pi.contractTerms.summary, - completed: pi.paid }, timestamp: pi.timestampCreated, transactionId: makeEventId( @@ -234,7 +232,6 @@ export async function getTransactions( info: { expiration: wsr.wgInfo.contractTerms.purse_expiration, summary: wsr.wgInfo.contractTerms.summary, - completed: !!wsr.timestampFinish }, talerUri: constructPayPullUri({ exchangeBaseUrl: wsr.exchangeBaseUrl, @@ -259,7 +256,6 @@ export async function getTransactions( info: { expiration: wsr.wgInfo.contractTerms.purse_expiration, summary: wsr.wgInfo.contractTerms.summary, - completed: !!wsr.timestampFinish, }, pending: !wsr.timestampFinish, timestamp: wsr.timestampStart, diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 2b981e117..b80745316 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -192,6 +192,13 @@ export interface ExchangeWithdrawDetails { * Amount that will actually be added to the wallet's balance. */ withdrawalAmountEffective: AmountString; + + /** + * If the exchange supports age-restricted coins it will return + * the array of ages. + * + */ + ageRestrictionOptions?: number[], } /** @@ -242,7 +249,7 @@ export function selectWithdrawalDenominations( for (const d of denoms) { let count = 0; const cost = Amounts.add(d.value, d.feeWithdraw).amount; - for (;;) { + for (; ;) { if (Amounts.cmp(remaining, cost) < 0) { break; } @@ -903,8 +910,7 @@ export async function updateWithdrawalDenoms( denom.verificationStatus === DenominationVerificationStatus.Unverified ) { logger.trace( - `Validating denomination (${current + 1}/${ - denominations.length + `Validating denomination (${current + 1}/${denominations.length }) signature of ${denom.denomPubHash}`, ); let valid = false; @@ -1031,7 +1037,7 @@ async function queryReserve( if ( resp.status === 404 && result.talerErrorResponse.code === - TalerErrorCode.EXCHANGE_RESERVES_STATUS_UNKNOWN + TalerErrorCode.EXCHANGE_RESERVES_STATUS_UNKNOWN ) { ws.notify({ type: NotificationType.ReserveNotYetFound, @@ -1255,10 +1261,13 @@ async function processWithdrawGroupImpl( } } +const AGE_MASK_GROUPS = "8:10:12:14:16:18".split(":").map(n => parseInt(n, 10)) + export async function getExchangeWithdrawalInfo( ws: InternalWalletState, exchangeBaseUrl: string, instructedAmount: AmountJson, + ageRestricted: number | undefined, ): Promise<ExchangeWithdrawDetails> { const { exchange, exchangeDetails } = await ws.exchangeOps.updateExchangeFromUrl(ws, exchangeBaseUrl); @@ -1287,6 +1296,8 @@ export async function getExchangeWithdrawalInfo( exchange, ); + let hasDenomWithAgeRestriction = false + let earliestDepositExpiration: TalerProtocolTimestamp | undefined; for (let i = 0; i < selectedDenoms.selectedDenoms.length; i++) { const ds = selectedDenoms.selectedDenoms[i]; @@ -1310,6 +1321,7 @@ export async function getExchangeWithdrawalInfo( ) { earliestDepositExpiration = expireDeposit; } + hasDenomWithAgeRestriction = hasDenomWithAgeRestriction || denom.denomPub.age_mask > 0 } checkLogicInvariant(!!earliestDepositExpiration); @@ -1337,7 +1349,7 @@ export async function getExchangeWithdrawalInfo( ) { logger.warn( `wallet's support for exchange protocol version ${WALLET_EXCHANGE_PROTOCOL_VERSION} might be outdated ` + - `(exchange has ${exchangeDetails.protocolVersion}), checking for updates`, + `(exchange has ${exchangeDetails.protocolVersion}), checking for updates`, ); } } @@ -1370,6 +1382,9 @@ export async function getExchangeWithdrawalInfo( termsOfServiceAccepted: tosAccepted, withdrawalAmountEffective: Amounts.stringify(selectedDenoms.totalCoinValue), withdrawalAmountRaw: Amounts.stringify(instructedAmount), + // TODO: remove hardcoding, this should be calculated from the denominations info + // force enabled for testing + ageRestrictionOptions: hasDenomWithAgeRestriction ? AGE_MASK_GROUPS : undefined }; return ret; } diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index 14c40a8db..665be80fb 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -46,7 +46,7 @@ import { CreateDepositGroupRequest, CreateDepositGroupResponse, DeleteTransactionRequest, - ExchangesListRespose, + ExchangesListResponse, ForceRefreshRequest, GetExchangeTosRequest, GetExchangeTosResult, @@ -227,7 +227,7 @@ export type WalletOperations = { }; [WalletApiOperation.ListExchanges]: { request: {}; - response: ExchangesListRespose; + response: ExchangesListResponse; }; [WalletApiOperation.AddExchange]: { request: AddExchangeRequest; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index a7a39c5a9..a23bcb12a 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -72,8 +72,8 @@ import { Duration, durationFromSpec, durationMin, - ExchangeFullDetailsListItem, - ExchangesListRespose, + ExchangeFullDetails, + ExchangesListResponse, GetExchangeTosResult, j2s, KnownBankAccounts, @@ -232,8 +232,9 @@ async function getWithdrawalDetailsForAmount( ws: InternalWalletState, exchangeBaseUrl: string, amount: AmountJson, + restrictAge: number | undefined, ): Promise<ManualWithdrawalDetails> { - const wi = await getExchangeWithdrawalInfo(ws, exchangeBaseUrl, amount); + const wi = await getExchangeWithdrawalInfo(ws, exchangeBaseUrl, amount, restrictAge); const paytoUris = wi.exchangeDetails.wireInfo.accounts.map( (x) => x.payto_uri, ); @@ -568,7 +569,7 @@ async function listKnownBankAccounts( async function getExchanges( ws: InternalWalletState, -): Promise<ExchangesListRespose> { +): Promise<ExchangesListResponse> { const exchanges: ExchangeListItem[] = []; await ws.db .mktx((x) => ({ @@ -613,54 +614,56 @@ async function getExchanges( return { exchanges }; } -async function getExchangesDetailled( +async function getExchangeDetailedInfo( ws: InternalWalletState, -): Promise<ExchangesListRespose> { - const exchanges: ExchangeFullDetailsListItem[] = []; - await ws.db + exchangeBaseurl: string, +): Promise<ExchangeFullDetails> { + //TODO: should we use the forceUpdate parameter? + const exchange = await ws.db .mktx((x) => ({ exchanges: x.exchanges, exchangeDetails: x.exchangeDetails, denominations: x.denominations, })) .runReadOnly(async (tx) => { - const exchangeRecords = await tx.exchanges.iter().toArray(); - for (const r of exchangeRecords) { - const dp = r.detailsPointer; - if (!dp) { - continue; - } - const { currency } = dp; - const exchangeDetails = await getExchangeDetails(tx, r.baseUrl); - if (!exchangeDetails) { - continue; - } + const ex = await tx.exchanges.get(exchangeBaseurl) + const dp = ex?.detailsPointer; + if (!dp) { + return; + } + const { currency } = dp; + const exchangeDetails = await getExchangeDetails(tx, ex.baseUrl); + if (!exchangeDetails) { + return; + } - const denominations = await tx.denominations.indexes.byExchangeBaseUrl - .iter(r.baseUrl) - .toArray(); + const denominations = await tx.denominations.indexes.byExchangeBaseUrl + .iter(ex.baseUrl) + .toArray(); - if (!denominations) { - continue; - } + if (!denominations) { + return; + } - exchanges.push({ - exchangeBaseUrl: r.baseUrl, - currency, - tos: { - acceptedVersion: exchangeDetails.termsOfServiceAcceptedEtag, - currentVersion: exchangeDetails.termsOfServiceLastEtag, - contentType: exchangeDetails.termsOfServiceContentType, - content: exchangeDetails.termsOfServiceText, - }, - paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri), - auditors: exchangeDetails.auditors, - wireInfo: exchangeDetails.wireInfo, - denominations: denominations, - }); + return { + exchangeBaseUrl: ex.baseUrl, + currency, + tos: { + acceptedVersion: exchangeDetails.termsOfServiceAcceptedEtag, + currentVersion: exchangeDetails.termsOfServiceLastEtag, + contentType: exchangeDetails.termsOfServiceContentType, + content: exchangeDetails.termsOfServiceText, + }, + paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri), + auditors: exchangeDetails.auditors, + wireInfo: exchangeDetails.wireInfo, + denominations: denominations, } }); - return { exchanges }; + if (!exchange) { + throw Error(`exchange with base url "${exchangeBaseurl}" not found`) + } + return exchange; } async function setCoinSuspended( @@ -834,8 +837,9 @@ async function dispatchRequestInternal( case "listExchanges": { return await getExchanges(ws); } - case "listExchangesDetailled": { - return await getExchangesDetailled(ws); + case "getExchangeDetailedInfo": { + const req = codecForAddExchangeRequest().decode(payload); + return await getExchangeDetailedInfo(ws, req.exchangeBaseUrl); } case "listKnownBankAccounts": { const req = codecForListKnownBankAccounts().decode(payload); @@ -852,6 +856,7 @@ async function dispatchRequestInternal( ws, req.exchangeBaseUrl, req.amount, + req.ageRestricted, ); } case "acceptManualWithdrawal": { @@ -870,6 +875,7 @@ async function dispatchRequestInternal( ws, req.exchangeBaseUrl, Amounts.parseOrThrow(req.amount), + req.restrictAge ); } case "getBalances": { @@ -1067,6 +1073,7 @@ async function dispatchRequestInternal( ws, req.exchange, amount, + undefined ); const wres = await createManualWithdrawal(ws, { amount: amount, |