moved wireInfo and denomInfo into taler-util so it can be used from the ui

This commit is contained in:
Sebastian 2022-08-18 16:01:47 -03:00
parent 23bb82f00c
commit d1980c39fc
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
8 changed files with 209 additions and 71 deletions

View File

@ -44,14 +44,17 @@ import {
codecForAny, codecForAny,
buildCodecForUnion, buildCodecForUnion,
codecForNumber, codecForNumber,
codecForMap,
} from "./codec.js"; } from "./codec.js";
import { import {
AmountString, AmountString,
AuditorDenomSig,
codecForContractTerms, codecForContractTerms,
CoinEnvelope, CoinEnvelope,
ContractTerms, ContractTerms,
DenominationPubKey, DenominationPubKey,
DenomKeyType, DenomKeyType,
ExchangeAuditor,
UnblindedSignature, UnblindedSignature,
} from "./talerTypes.js"; } from "./talerTypes.js";
import { OrderShortInfo, codecForOrderShortInfo } from "./transactionsTypes.js"; import { OrderShortInfo, codecForOrderShortInfo } from "./transactionsTypes.js";
@ -580,13 +583,164 @@ export interface ExchangeTos {
contentType?: string; contentType?: string;
content?: 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<ExchangeAccount> =>
buildCodecForObject<ExchangeAccount>()
.property("payto_uri", codecForString())
.property("master_sig", codecForString())
.build("codecForExchangeAccount");
const codecForWireFee = (): Codec<WireFee> =>
buildCodecForObject<WireFee>()
.property("sig", codecForString())
.property("wireFee", codecForAmountJson())
.property("wadFee", codecForAmountJson())
.property("closingFee", codecForAmountJson())
.property("startStamp", codecForTimestamp)
.property("endStamp", codecForTimestamp)
.build("codecForWireFee");
const codecForWireInfo = (): Codec<WireInfo> =>
buildCodecForObject<WireInfo>()
.property("feesForType", codecForMap(codecForList(codecForWireFee())))
.property("accounts", codecForList(codecForExchangeAccount()))
.build("codecForWireInfo");
const codecForDenominationInfo = (): Codec<DenominationInfo> =>
buildCodecForObject<DenominationInfo>()
.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 { export interface ExchangeListItem {
exchangeBaseUrl: string; exchangeBaseUrl: string;
currency: string; currency: string;
paytoUris: string[]; paytoUris: string[];
tos: ExchangeTos; tos: ExchangeTos;
auditors: ExchangeAuditor[];
wireInfo: WireInfo;
denominations: DenominationInfo[];
} }
const codecForAuditorDenomSig = (): Codec<AuditorDenomSig> =>
buildCodecForObject<AuditorDenomSig>()
.property("denom_pub_h", codecForString())
.property("auditor_sig", codecForString())
.build("AuditorDenomSig");
const codecForExchangeAuditor = (): Codec<ExchangeAuditor> =>
buildCodecForObject<ExchangeAuditor>()
.property("auditor_pub", codecForString())
.property("auditor_url", codecForString())
.property("denomination_keys", codecForList(codecForAuditorDenomSig()))
.build("codecForExchangeAuditor");
const codecForExchangeTos = (): Codec<ExchangeTos> => const codecForExchangeTos = (): Codec<ExchangeTos> =>
buildCodecForObject<ExchangeTos>() buildCodecForObject<ExchangeTos>()
.property("acceptedVersion", codecOptional(codecForString())) .property("acceptedVersion", codecOptional(codecForString()))
@ -601,6 +755,9 @@ export const codecForExchangeListItem = (): Codec<ExchangeListItem> =>
.property("exchangeBaseUrl", codecForString()) .property("exchangeBaseUrl", codecForString())
.property("paytoUris", codecForList(codecForString())) .property("paytoUris", codecForList(codecForString()))
.property("tos", codecForExchangeTos()) .property("tos", codecForExchangeTos())
.property("auditors", codecForList(codecForExchangeAuditor()))
.property("wireInfo", codecForWireInfo())
.property("denominations", codecForList(codecForDenominationInfo()))
.build("ExchangeListItem"); .build("ExchangeListItem");
export const codecForExchangesListResponse = (): Codec<ExchangesListRespose> => export const codecForExchangesListResponse = (): Codec<ExchangesListRespose> =>

View File

@ -76,11 +76,12 @@ import {
TalerProtocolTimestamp, TalerProtocolTimestamp,
TalerSignaturePurpose, TalerSignaturePurpose,
UnblindedSignature, UnblindedSignature,
WireFee,
WithdrawalPlanchet, WithdrawalPlanchet,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import bigint from "big-integer"; import bigint from "big-integer";
// FIXME: Crypto should not use DB Types! // FIXME: Crypto should not use DB Types!
import { DenominationRecord, WireFee } from "../db.js"; import { DenominationRecord } from "../db.js";
import { import {
CreateRecoupRefreshReqRequest, CreateRecoupRefreshReqRequest,
CreateRecoupReqRequest, CreateRecoupReqRequest,
@ -1045,10 +1046,10 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
}; };
if (depositInfo.requiredMinimumAge != null) { if (depositInfo.requiredMinimumAge != null) {
s.minimum_age_sig = minimumAgeSig; s.minimum_age_sig = minimumAgeSig;
s.age_commitment = depositInfo.ageCommitmentProof?.commitment.publicKeys; s.age_commitment = depositInfo.ageCommitmentProof?.commitment.publicKeys;
} else if (depositInfo.ageCommitmentProof) { } else if (depositInfo.ageCommitmentProof) {
(s as any).h_age_commitment = hAgeCommitment; (s as any).h_age_commitment = hAgeCommitment;
} }
return s; return s;

View File

@ -44,6 +44,7 @@ import {
PayCoinSelection, PayCoinSelection,
PeerContractTerms, PeerContractTerms,
Location, Location,
WireInfo,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { RetryInfo } from "./util/retries.js"; import { RetryInfo } from "./util/retries.js";
import { Event, IDBDatabase } from "@gnu-taler/idb-bridge"; import { Event, IDBDatabase } from "@gnu-taler/idb-bridge";
@ -392,11 +393,6 @@ export interface ExchangeDetailsRecord {
wireInfo: WireInfo; wireInfo: WireInfo;
} }
export interface WireInfo {
feesForType: { [wireMethod: string]: WireFee[] };
accounts: ExchangeBankAccount[];
}
export interface ExchangeDetailsPointer { export interface ExchangeDetailsPointer {
masterPublicKey: string; masterPublicKey: string;
@ -926,41 +922,6 @@ export interface RefreshSessionRecord {
norevealIndex?: number; 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 { export enum RefundState {
Failed = "failed", Failed = "failed",
@ -1225,9 +1186,9 @@ export const WALLET_BACKUP_STATE_KEY = "walletBackupState";
*/ */
export type ConfigRecord = export type ConfigRecord =
| { | {
key: typeof WALLET_BACKUP_STATE_KEY; key: typeof WALLET_BACKUP_STATE_KEY;
value: WalletBackupConfState; value: WalletBackupConfState;
} }
| { key: "currencyDefaultsApplied"; value: boolean }; | { key: "currencyDefaultsApplied"; value: boolean };
export interface WalletBackupConfState { export interface WalletBackupConfState {
@ -1444,17 +1405,17 @@ export enum BackupProviderStateTag {
export type BackupProviderState = export type BackupProviderState =
| { | {
tag: BackupProviderStateTag.Provisional; tag: BackupProviderStateTag.Provisional;
} }
| { | {
tag: BackupProviderStateTag.Ready; tag: BackupProviderStateTag.Ready;
nextBackupTimestamp: TalerProtocolTimestamp; nextBackupTimestamp: TalerProtocolTimestamp;
} }
| { | {
tag: BackupProviderStateTag.Retrying; tag: BackupProviderStateTag.Retrying;
retryInfo: RetryInfo; retryInfo: RetryInfo;
lastError?: TalerErrorDetail; lastError?: TalerErrorDetail;
}; };
export interface BackupProviderTerms { export interface BackupProviderTerms {
supportedProtocolVersion: string; supportedProtocolVersion: string;

View File

@ -31,6 +31,7 @@ import {
RefreshReason, RefreshReason,
TalerProtocolTimestamp, TalerProtocolTimestamp,
WalletBackupContentV1, WalletBackupContentV1,
WireInfo,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { import {
AbortStatus, AbortStatus,
@ -50,7 +51,6 @@ import {
WalletContractData, WalletContractData,
WalletRefundItem, WalletRefundItem,
WalletStoresV1, WalletStoresV1,
WireInfo,
} from "../../db.js"; } from "../../db.js";
import { InternalWalletState } from "../../internal-wallet-state.js"; import { InternalWalletState } from "../../internal-wallet-state.js";
import { import {
@ -341,7 +341,7 @@ export async function importBackup(
} }
const denomPubHash = const denomPubHash =
cryptoComp.rsaDenomPubToHash[ cryptoComp.rsaDenomPubToHash[
backupDenomination.denom_pub.rsa_public_key backupDenomination.denom_pub.rsa_public_key
]; ];
checkLogicInvariant(!!denomPubHash); checkLogicInvariant(!!denomPubHash);
const existingDenom = await tx.denominations.get([ 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) { // for (const backupReserve of backupExchangeDetails.reserves) {
// const reservePub = // const reservePub =
@ -560,7 +560,7 @@ export async function importBackup(
const amount = Amounts.parseOrThrow(parsedContractTerms.amount); const amount = Amounts.parseOrThrow(parsedContractTerms.amount);
const contractTermsHash = const contractTermsHash =
cryptoComp.proposalIdToContractTermsHash[ cryptoComp.proposalIdToContractTermsHash[
backupProposal.proposal_id backupProposal.proposal_id
]; ];
let maxWireFee: AmountJson; let maxWireFee: AmountJson;
if (parsedContractTerms.max_wire_fee) { if (parsedContractTerms.max_wire_fee) {
@ -706,7 +706,7 @@ export async function importBackup(
const amount = Amounts.parseOrThrow(parsedContractTerms.amount); const amount = Amounts.parseOrThrow(parsedContractTerms.amount);
const contractTermsHash = const contractTermsHash =
cryptoComp.proposalIdToContractTermsHash[ cryptoComp.proposalIdToContractTermsHash[
backupPurchase.proposal_id backupPurchase.proposal_id
]; ];
let maxWireFee: AmountJson; let maxWireFee: AmountJson;
if (parsedContractTerms.max_wire_fee) { if (parsedContractTerms.max_wire_fee) {

View File

@ -44,7 +44,7 @@ import {
TrackDepositGroupResponse, TrackDepositGroupResponse,
URL, URL,
} from "@gnu-taler/taler-util"; } 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 { InternalWalletState } from "../internal-wallet-state.js";
import { selectPayCoins } from "../util/coinSelection.js"; import { selectPayCoins } from "../util/coinSelection.js";
import { readSuccessResponseJsonOrThrow } from "../util/http.js"; import { readSuccessResponseJsonOrThrow } from "../util/http.js";

View File

@ -44,6 +44,9 @@ import {
TalerProtocolDuration, TalerProtocolDuration,
TalerProtocolTimestamp, TalerProtocolTimestamp,
URL, URL,
WireFee,
WireFeeMap,
WireInfo,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { import {
DenominationRecord, DenominationRecord,
@ -51,8 +54,6 @@ import {
ExchangeDetailsRecord, ExchangeDetailsRecord,
ExchangeRecord, ExchangeRecord,
WalletStoresV1, WalletStoresV1,
WireFee,
WireInfo,
} from "../db.js"; } from "../db.js";
import { TalerError } from "../errors.js"; import { TalerError } from "../errors.js";
import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js"; import { InternalWalletState, TrustInfo } from "../internal-wallet-state.js";
@ -276,7 +277,7 @@ async function validateWireInfo(
throw Error("exchange acct signature invalid"); throw Error("exchange acct signature invalid");
} }
} }
const feesForType: { [wireMethod: string]: WireFee[] } = {}; const feesForType: WireFeeMap = {};
for (const wireMethod of Object.keys(wireInfo.fees)) { for (const wireMethod of Object.keys(wireInfo.fees)) {
const feeList: WireFee[] = []; const feeList: WireFee[] = [];
for (const x of wireInfo.fees[wireMethod]) { for (const x of wireInfo.fees[wireMethod]) {

View File

@ -241,7 +241,7 @@ export function selectWithdrawalDenominations(
for (const d of denoms) { for (const d of denoms) {
let count = 0; let count = 0;
const cost = Amounts.add(d.value, d.feeWithdraw).amount; const cost = Amounts.add(d.value, d.feeWithdraw).amount;
for (;;) { for (; ;) {
if (Amounts.cmp(remaining, cost) < 0) { if (Amounts.cmp(remaining, cost) < 0) {
break; break;
} }
@ -898,8 +898,7 @@ export async function updateWithdrawalDenoms(
denom.verificationStatus === DenominationVerificationStatus.Unverified denom.verificationStatus === DenominationVerificationStatus.Unverified
) { ) {
logger.trace( logger.trace(
`Validating denomination (${current + 1}/${ `Validating denomination (${current + 1}/${denominations.length
denominations.length
}) signature of ${denom.denomPubHash}`, }) signature of ${denom.denomPubHash}`,
); );
let valid = false; let valid = false;
@ -1026,7 +1025,7 @@ async function queryReserve(
if ( if (
resp.status === 404 && resp.status === 404 &&
result.talerErrorResponse.code === result.talerErrorResponse.code ===
TalerErrorCode.EXCHANGE_RESERVES_STATUS_UNKNOWN TalerErrorCode.EXCHANGE_RESERVES_STATUS_UNKNOWN
) { ) {
ws.notify({ ws.notify({
type: NotificationType.ReserveNotYetFound, type: NotificationType.ReserveNotYetFound,
@ -1316,7 +1315,7 @@ export async function getExchangeWithdrawalInfo(
) { ) {
logger.warn( logger.warn(
`wallet's support for exchange protocol version ${WALLET_EXCHANGE_PROTOCOL_VERSION} might be outdated ` + `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) => ({ .mktx((x) => ({
exchanges: x.exchanges, exchanges: x.exchanges,
exchangeDetails: x.exchangeDetails, exchangeDetails: x.exchangeDetails,
denominations: x.denominations,
})) }))
.runReadOnly(async (tx) => { .runReadOnly(async (tx) => {
const exchangeRecords = await tx.exchanges.iter().toArray(); const exchangeRecords = await tx.exchanges.iter().toArray();
for (const r of exchangeRecords) { for (const r of exchangeRecords) {
const details = await ws.exchangeOps.getExchangeDetails(tx, r.baseUrl); 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({ exchanges.push({
exchangeBaseUrl: details.exchangeBaseUrl, exchangeBaseUrl: details.exchangeBaseUrl,
currency: details.currency, currency: details.currency,
@ -1411,6 +1415,9 @@ export async function getWithdrawalDetailsForUri(
content: details.termsOfServiceText, content: details.termsOfServiceText,
}, },
paytoUris: details.wireInfo.accounts.map((x) => x.payto_uri), paytoUris: details.wireInfo.accounts.map((x) => x.payto_uri),
auditors: details.auditors,
wireInfo: details.wireInfo,
denominations: denominations
}); });
} }
} }

View File

@ -553,6 +553,7 @@ async function getExchanges(
.mktx((x) => ({ .mktx((x) => ({
exchanges: x.exchanges, exchanges: x.exchanges,
exchangeDetails: x.exchangeDetails, exchangeDetails: x.exchangeDetails,
denominations: x.denominations,
})) }))
.runReadOnly(async (tx) => { .runReadOnly(async (tx) => {
const exchangeRecords = await tx.exchanges.iter().toArray(); const exchangeRecords = await tx.exchanges.iter().toArray();
@ -567,6 +568,13 @@ async function getExchanges(
continue; continue;
} }
const denominations = await tx.denominations.indexes
.byExchangeBaseUrl.iter(r.baseUrl).toArray();
if (!denominations) {
continue;
}
exchanges.push({ exchanges.push({
exchangeBaseUrl: r.baseUrl, exchangeBaseUrl: r.baseUrl,
currency, currency,
@ -577,6 +585,9 @@ async function getExchanges(
content: exchangeDetails.termsOfServiceText, content: exchangeDetails.termsOfServiceText,
}, },
paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri), paytoUris: exchangeDetails.wireInfo.accounts.map((x) => x.payto_uri),
auditors: exchangeDetails.auditors,
wireInfo: exchangeDetails.wireInfo,
denominations: denominations,
}); });
} }
}); });