From d1980c39fc2cf5054cfa9d3a03d685d75c2662d9 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 18 Aug 2022 16:01:47 -0300 Subject: moved wireInfo and denomInfo into taler-util so it can be used from the ui --- packages/taler-util/src/walletTypes.ts | 157 +++++++++++++++++++++ .../src/crypto/cryptoImplementation.ts | 9 +- packages/taler-wallet-core/src/db.ts | 65 ++------- .../src/operations/backup/import.ts | 10 +- .../taler-wallet-core/src/operations/deposits.ts | 2 +- .../taler-wallet-core/src/operations/exchanges.ts | 7 +- .../taler-wallet-core/src/operations/withdraw.ts | 19 ++- packages/taler-wallet-core/src/wallet.ts | 11 ++ 8 files changed, 209 insertions(+), 71 deletions(-) diff --git a/packages/taler-util/src/walletTypes.ts b/packages/taler-util/src/walletTypes.ts index eac9cf7db..7b482c60e 100644 --- a/packages/taler-util/src/walletTypes.ts +++ b/packages/taler-util/src/walletTypes.ts @@ -44,14 +44,17 @@ import { codecForAny, buildCodecForUnion, codecForNumber, + codecForMap, } from "./codec.js"; import { AmountString, + AuditorDenomSig, codecForContractTerms, CoinEnvelope, ContractTerms, DenominationPubKey, DenomKeyType, + ExchangeAuditor, UnblindedSignature, } from "./talerTypes.js"; import { OrderShortInfo, codecForOrderShortInfo } from "./transactionsTypes.js"; @@ -580,13 +583,164 @@ export interface ExchangeTos { contentType?: string; content?: string; } + +/** + * Wire fee for one wire method + */ +export interface WireFee { + /** + * Fee for wire transfers. + */ + wireFee: AmountJson; + + /** + * Fees to close and refund a reserve. + */ + closingFee: AmountJson; + + /** + * Fees for inter-exchange transfers from P2P payments. + */ + wadFee: AmountJson; + + /** + * Start date of the fee. + */ + startStamp: TalerProtocolTimestamp; + + /** + * End date of the fee. + */ + endStamp: TalerProtocolTimestamp; + + /** + * Signature made by the exchange master key. + */ + sig: string; +} + +/** + * Information about one of the exchange's bank accounts. + */ +export interface ExchangeAccount { + payto_uri: string; + master_sig: string; +} + +export type WireFeeMap = { [wireMethod: string]: WireFee[] } +export interface WireInfo { + feesForType: WireFeeMap; + accounts: ExchangeAccount[]; +} + +const codecForExchangeAccount = (): Codec => + buildCodecForObject() + .property("payto_uri", codecForString()) + .property("master_sig", codecForString()) + .build("codecForExchangeAccount"); + + +const codecForWireFee = (): Codec => + buildCodecForObject() + .property("sig", codecForString()) + .property("wireFee", codecForAmountJson()) + .property("wadFee", codecForAmountJson()) + .property("closingFee", codecForAmountJson()) + .property("startStamp", codecForTimestamp) + .property("endStamp", codecForTimestamp) + .build("codecForWireFee"); + +const codecForWireInfo = (): Codec => + buildCodecForObject() + .property("feesForType", codecForMap(codecForList(codecForWireFee()))) + .property("accounts", codecForList(codecForExchangeAccount())) + .build("codecForWireInfo"); + +const codecForDenominationInfo = (): Codec => + buildCodecForObject() + .property("denomPubHash", (codecForString())) + .property("value", (codecForAmountJson())) + .property("feeWithdraw", (codecForAmountJson())) + .property("feeDeposit", (codecForAmountJson())) + .property("feeRefresh", (codecForAmountJson())) + .property("feeRefund", (codecForAmountJson())) + .property("stampStart", (codecForTimestamp)) + .property("stampExpireWithdraw", (codecForTimestamp)) + .property("stampExpireLegal", (codecForTimestamp)) + .property("stampExpireDeposit", (codecForTimestamp)) + .build("codecForDenominationInfo"); + + +export interface DenominationInfo { + value: AmountJson; + denomPubHash: string; + /** + * Fee for withdrawing. + */ + feeWithdraw: AmountJson; + + /** + * Fee for depositing. + */ + feeDeposit: AmountJson; + + /** + * Fee for refreshing. + */ + feeRefresh: AmountJson; + + /** + * Fee for refunding. + */ + feeRefund: AmountJson; + + /** + * Validity start date of the denomination. + */ + stampStart: TalerProtocolTimestamp; + + /** + * Date after which the currency can't be withdrawn anymore. + */ + stampExpireWithdraw: TalerProtocolTimestamp; + + /** + * Date after the denomination officially doesn't exist anymore. + */ + stampExpireLegal: TalerProtocolTimestamp; + + /** + * Data after which coins of this denomination can't be deposited anymore. + */ + stampExpireDeposit: TalerProtocolTimestamp; + +} + export interface ExchangeListItem { exchangeBaseUrl: string; currency: string; paytoUris: string[]; tos: ExchangeTos; + auditors: ExchangeAuditor[]; + wireInfo: WireInfo; + denominations: DenominationInfo[]; } + +const codecForAuditorDenomSig = (): Codec => + buildCodecForObject() + .property("denom_pub_h", codecForString()) + .property("auditor_sig", codecForString()) + .build("AuditorDenomSig"); + +const codecForExchangeAuditor = (): Codec => + buildCodecForObject() + .property("auditor_pub", codecForString()) + .property("auditor_url", codecForString()) + .property("denomination_keys", codecForList(codecForAuditorDenomSig())) + .build("codecForExchangeAuditor"); + + const codecForExchangeTos = (): Codec => buildCodecForObject() .property("acceptedVersion", codecOptional(codecForString())) @@ -601,6 +755,9 @@ export const codecForExchangeListItem = (): Codec => .property("exchangeBaseUrl", codecForString()) .property("paytoUris", codecForList(codecForString())) .property("tos", codecForExchangeTos()) + .property("auditors", codecForList(codecForExchangeAuditor())) + .property("wireInfo", codecForWireInfo()) + .property("denominations", codecForList(codecForDenominationInfo())) .build("ExchangeListItem"); export const codecForExchangesListResponse = (): Codec => diff --git a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts index edb9cdccb..099bf09fe 100644 --- a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts @@ -76,11 +76,12 @@ import { TalerProtocolTimestamp, TalerSignaturePurpose, UnblindedSignature, + WireFee, WithdrawalPlanchet, } from "@gnu-taler/taler-util"; import bigint from "big-integer"; // FIXME: Crypto should not use DB Types! -import { DenominationRecord, WireFee } from "../db.js"; +import { DenominationRecord } from "../db.js"; import { CreateRecoupRefreshReqRequest, CreateRecoupReqRequest, @@ -1045,10 +1046,10 @@ export const nativeCryptoR: TalerCryptoInterfaceR = { }; if (depositInfo.requiredMinimumAge != null) { - s.minimum_age_sig = minimumAgeSig; - s.age_commitment = depositInfo.ageCommitmentProof?.commitment.publicKeys; + s.minimum_age_sig = minimumAgeSig; + s.age_commitment = depositInfo.ageCommitmentProof?.commitment.publicKeys; } else if (depositInfo.ageCommitmentProof) { - (s as any).h_age_commitment = hAgeCommitment; + (s as any).h_age_commitment = hAgeCommitment; } return s; diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 8f558abd3..a34a09f75 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -44,6 +44,7 @@ import { PayCoinSelection, PeerContractTerms, Location, + WireInfo, } from "@gnu-taler/taler-util"; import { RetryInfo } from "./util/retries.js"; import { Event, IDBDatabase } from "@gnu-taler/idb-bridge"; @@ -392,11 +393,6 @@ export interface ExchangeDetailsRecord { wireInfo: WireInfo; } -export interface WireInfo { - feesForType: { [wireMethod: string]: WireFee[] }; - - accounts: ExchangeBankAccount[]; -} export interface ExchangeDetailsPointer { masterPublicKey: string; @@ -926,41 +922,6 @@ export interface RefreshSessionRecord { norevealIndex?: number; } -/** - * Wire fee for one wire method as stored in the - * wallet's database. - */ -export interface WireFee { - /** - * Fee for wire transfers. - */ - wireFee: AmountJson; - - /** - * Fees to close and refund a reserve. - */ - closingFee: AmountJson; - - /** - * Fees for inter-exchange transfers from P2P payments. - */ - wadFee: AmountJson; - - /** - * Start date of the fee. - */ - startStamp: TalerProtocolTimestamp; - - /** - * End date of the fee. - */ - endStamp: TalerProtocolTimestamp; - - /** - * Signature made by the exchange master key. - */ - sig: string; -} export enum RefundState { Failed = "failed", @@ -1225,9 +1186,9 @@ export const WALLET_BACKUP_STATE_KEY = "walletBackupState"; */ export type ConfigRecord = | { - key: typeof WALLET_BACKUP_STATE_KEY; - value: WalletBackupConfState; - } + key: typeof WALLET_BACKUP_STATE_KEY; + value: WalletBackupConfState; + } | { key: "currencyDefaultsApplied"; value: boolean }; export interface WalletBackupConfState { @@ -1444,17 +1405,17 @@ export enum BackupProviderStateTag { export type BackupProviderState = | { - tag: BackupProviderStateTag.Provisional; - } + tag: BackupProviderStateTag.Provisional; + } | { - tag: BackupProviderStateTag.Ready; - nextBackupTimestamp: TalerProtocolTimestamp; - } + tag: BackupProviderStateTag.Ready; + nextBackupTimestamp: TalerProtocolTimestamp; + } | { - tag: BackupProviderStateTag.Retrying; - retryInfo: RetryInfo; - lastError?: TalerErrorDetail; - }; + tag: BackupProviderStateTag.Retrying; + retryInfo: RetryInfo; + lastError?: TalerErrorDetail; + }; export interface BackupProviderTerms { supportedProtocolVersion: string; diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index f26c42770..57d7449e0 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -31,6 +31,7 @@ import { RefreshReason, TalerProtocolTimestamp, WalletBackupContentV1, + WireInfo, } from "@gnu-taler/taler-util"; import { AbortStatus, @@ -50,7 +51,6 @@ import { WalletContractData, WalletRefundItem, WalletStoresV1, - WireInfo, } from "../../db.js"; import { InternalWalletState } from "../../internal-wallet-state.js"; import { @@ -341,7 +341,7 @@ export async function importBackup( } const denomPubHash = cryptoComp.rsaDenomPubToHash[ - backupDenomination.denom_pub.rsa_public_key + backupDenomination.denom_pub.rsa_public_key ]; checkLogicInvariant(!!denomPubHash); const existingDenom = await tx.denominations.get([ @@ -427,7 +427,7 @@ export async function importBackup( } - // FIXME: import reserves with new schema + // FIXME: import reserves with new schema // for (const backupReserve of backupExchangeDetails.reserves) { // const reservePub = @@ -560,7 +560,7 @@ export async function importBackup( const amount = Amounts.parseOrThrow(parsedContractTerms.amount); const contractTermsHash = cryptoComp.proposalIdToContractTermsHash[ - backupProposal.proposal_id + backupProposal.proposal_id ]; let maxWireFee: AmountJson; if (parsedContractTerms.max_wire_fee) { @@ -706,7 +706,7 @@ export async function importBackup( const amount = Amounts.parseOrThrow(parsedContractTerms.amount); const contractTermsHash = cryptoComp.proposalIdToContractTermsHash[ - backupPurchase.proposal_id + backupPurchase.proposal_id ]; let maxWireFee: AmountJson; if (parsedContractTerms.max_wire_fee) { diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts index a016cb8e5..734bc4c2b 100644 --- a/packages/taler-wallet-core/src/operations/deposits.ts +++ b/packages/taler-wallet-core/src/operations/deposits.ts @@ -44,7 +44,7 @@ import { TrackDepositGroupResponse, URL, } from "@gnu-taler/taler-util"; -import { DepositGroupRecord, OperationStatus, WireFee } from "../db.js"; +import { DepositGroupRecord, OperationStatus } from "../db.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { selectPayCoins } from "../util/coinSelection.js"; import { readSuccessResponseJsonOrThrow } from "../util/http.js"; diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index 007dad685..6f8da5aee 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -44,6 +44,9 @@ import { TalerProtocolDuration, TalerProtocolTimestamp, URL, + WireFee, + WireFeeMap, + WireInfo, } from "@gnu-taler/taler-util"; import { DenominationRecord, @@ -51,8 +54,6 @@ import { ExchangeDetailsRecord, ExchangeRecord, WalletStoresV1, - WireFee, - WireInfo, } from "../db.js"; import { TalerError } from "../errors.js"; import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js"; @@ -276,7 +277,7 @@ async function validateWireInfo( throw Error("exchange acct signature invalid"); } } - const feesForType: { [wireMethod: string]: WireFee[] } = {}; + const feesForType: WireFeeMap = {}; for (const wireMethod of Object.keys(wireInfo.fees)) { const feeList: WireFee[] = []; for (const x of wireInfo.fees[wireMethod]) { diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 484b9b962..721a043d7 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -241,7 +241,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; } @@ -898,8 +898,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; @@ -1026,7 +1025,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, @@ -1316,7 +1315,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`, ); } } @@ -1395,12 +1394,17 @@ export async function getWithdrawalDetailsForUri( .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 details = await ws.exchangeOps.getExchangeDetails(tx, r.baseUrl); - if (details) { + const denominations = await tx.denominations.indexes + .byExchangeBaseUrl.iter(r.baseUrl).toArray(); + if (details && denominations) { + + exchanges.push({ exchangeBaseUrl: details.exchangeBaseUrl, currency: details.currency, @@ -1411,6 +1415,9 @@ export async function getWithdrawalDetailsForUri( content: details.termsOfServiceText, }, paytoUris: details.wireInfo.accounts.map((x) => x.payto_uri), + auditors: details.auditors, + wireInfo: details.wireInfo, + denominations: denominations }); } } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 1b6b56691..593d2e0ff 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -553,6 +553,7 @@ async function getExchanges( .mktx((x) => ({ exchanges: x.exchanges, exchangeDetails: x.exchangeDetails, + denominations: x.denominations, })) .runReadOnly(async (tx) => { const exchangeRecords = await tx.exchanges.iter().toArray(); @@ -567,6 +568,13 @@ async function getExchanges( continue; } + const denominations = await tx.denominations.indexes + .byExchangeBaseUrl.iter(r.baseUrl).toArray(); + + if (!denominations) { + continue; + } + exchanges.push({ exchangeBaseUrl: r.baseUrl, currency, @@ -577,6 +585,9 @@ async function getExchanges( content: exchangeDetails.termsOfServiceText, }, paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri), + auditors: exchangeDetails.auditors, + wireInfo: exchangeDetails.wireInfo, + denominations: denominations, }); } }); -- cgit v1.2.3