wallet-core: DB FIXMEs (amount format)
This commit is contained in:
parent
6c3ef31d9a
commit
d50294f76e
@ -306,7 +306,7 @@ async function getProviderInfo(
|
||||
status: "error",
|
||||
code: TalerErrorCode.ANASTASIS_REDUCER_PROVIDER_CONFIG_FAILED,
|
||||
hint: "provider did not have provider salt",
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
status: "ok",
|
||||
@ -663,12 +663,12 @@ async function uploadSecret(
|
||||
let policyExpiration: TalerProtocolTimestamp = { t_s: 0 };
|
||||
try {
|
||||
policyVersion = Number(resp.headers.get("Anastasis-Version") ?? "0");
|
||||
} catch (e) { }
|
||||
} catch (e) {}
|
||||
try {
|
||||
policyExpiration = {
|
||||
t_s: Number(resp.headers.get("Anastasis-Policy-Expiration") ?? "0"),
|
||||
};
|
||||
} catch (e) { }
|
||||
} catch (e) {}
|
||||
successDetails[prov.provider_url] = {
|
||||
policy_version: policyVersion,
|
||||
policy_expiration: policyExpiration,
|
||||
@ -1469,7 +1469,7 @@ async function updateUploadFees(
|
||||
const addFee = (x: AmountLike) => {
|
||||
x = Amounts.jsonifyAmount(x);
|
||||
feePerCurrency[x.currency] = Amounts.add(
|
||||
feePerCurrency[x.currency] ?? Amounts.getZero(x.currency),
|
||||
feePerCurrency[x.currency] ?? Amounts.zeroOfAmount(x),
|
||||
x,
|
||||
).amount;
|
||||
};
|
||||
|
@ -103,10 +103,24 @@ export class Amounts {
|
||||
throw Error("not instantiable");
|
||||
}
|
||||
|
||||
static currencyOf(amount: AmountLike) {
|
||||
const amt = Amounts.parseOrThrow(amount);
|
||||
return amt.currency;
|
||||
}
|
||||
|
||||
static zeroOfAmount(amount: AmountLike): AmountJson {
|
||||
const amt = Amounts.parseOrThrow(amount);
|
||||
return {
|
||||
currency: amt.currency,
|
||||
fraction: 0,
|
||||
value: 0,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an amount that represents zero units of a currency.
|
||||
*/
|
||||
static getZero(currency: string): AmountJson {
|
||||
static zeroOfCurrency(currency: string): AmountJson {
|
||||
return {
|
||||
currency,
|
||||
fraction: 0,
|
||||
@ -132,7 +146,7 @@ export class Amounts {
|
||||
static sumOrZero(currency: string, amounts: AmountLike[]): Result {
|
||||
if (amounts.length <= 0) {
|
||||
return {
|
||||
amount: Amounts.getZero(currency),
|
||||
amount: Amounts.zeroOfCurrency(currency),
|
||||
saturated: false,
|
||||
};
|
||||
}
|
||||
@ -147,9 +161,11 @@ export class Amounts {
|
||||
*
|
||||
* Throws when currencies don't match.
|
||||
*/
|
||||
static add(first: AmountJson, ...rest: AmountJson[]): Result {
|
||||
const currency = first.currency;
|
||||
let value = first.value + Math.floor(first.fraction / amountFractionalBase);
|
||||
static add(first: AmountLike, ...rest: AmountLike[]): Result {
|
||||
const firstJ = Amounts.jsonifyAmount(first);
|
||||
const currency = firstJ.currency;
|
||||
let value =
|
||||
firstJ.value + Math.floor(firstJ.fraction / amountFractionalBase);
|
||||
if (value > amountMaxValue) {
|
||||
return {
|
||||
amount: {
|
||||
@ -160,17 +176,18 @@ export class Amounts {
|
||||
saturated: true,
|
||||
};
|
||||
}
|
||||
let fraction = first.fraction % amountFractionalBase;
|
||||
let fraction = firstJ.fraction % amountFractionalBase;
|
||||
for (const x of rest) {
|
||||
if (x.currency.toUpperCase() !== currency.toUpperCase()) {
|
||||
throw Error(`Mismatched currency: ${x.currency} and ${currency}`);
|
||||
const xJ = Amounts.jsonifyAmount(x);
|
||||
if (xJ.currency.toUpperCase() !== currency.toUpperCase()) {
|
||||
throw Error(`Mismatched currency: ${xJ.currency} and ${currency}`);
|
||||
}
|
||||
|
||||
value =
|
||||
value +
|
||||
x.value +
|
||||
Math.floor((fraction + x.fraction) / amountFractionalBase);
|
||||
fraction = Math.floor((fraction + x.fraction) % amountFractionalBase);
|
||||
xJ.value +
|
||||
Math.floor((fraction + xJ.fraction) / amountFractionalBase);
|
||||
fraction = Math.floor((fraction + xJ.fraction) % amountFractionalBase);
|
||||
if (value > amountMaxValue) {
|
||||
return {
|
||||
amount: {
|
||||
@ -322,12 +339,27 @@ export class Amounts {
|
||||
* Parse amount in standard string form (like 'EUR:20.5'),
|
||||
* throw if the input is not a valid amount.
|
||||
*/
|
||||
static parseOrThrow(s: string): AmountJson {
|
||||
static parseOrThrow(s: AmountLike): AmountJson {
|
||||
if (typeof s === "object") {
|
||||
if (typeof s.currency !== "string") {
|
||||
throw Error("invalid amount object");
|
||||
}
|
||||
if (typeof s.value !== "number") {
|
||||
throw Error("invalid amount object");
|
||||
}
|
||||
if (typeof s.fraction !== "number") {
|
||||
throw Error("invalid amount object");
|
||||
}
|
||||
return { currency: s.currency, value: s.value, fraction: s.fraction };
|
||||
} else if (typeof s === "string") {
|
||||
const res = Amounts.parse(s);
|
||||
if (!res) {
|
||||
throw Error(`Can't parse amount: "${s}"`);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
throw Error("invalid amount (illegal type)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -371,10 +403,13 @@ export class Amounts {
|
||||
throw Error("amount can only be multiplied by a positive integer");
|
||||
}
|
||||
if (n == 0) {
|
||||
return { amount: Amounts.getZero(a.currency), saturated: false };
|
||||
return {
|
||||
amount: Amounts.zeroOfCurrency(a.currency),
|
||||
saturated: false,
|
||||
};
|
||||
}
|
||||
let x = a;
|
||||
let acc = Amounts.getZero(a.currency);
|
||||
let acc = Amounts.zeroOfCurrency(a.currency);
|
||||
while (n > 1) {
|
||||
if (n % 2 == 0) {
|
||||
n = n / 2;
|
||||
@ -427,9 +462,10 @@ export class Amounts {
|
||||
return x1.currency.toUpperCase() === x2.currency.toUpperCase();
|
||||
}
|
||||
|
||||
static stringifyValue(a: AmountJson, minFractional = 0): string {
|
||||
const av = a.value + Math.floor(a.fraction / amountFractionalBase);
|
||||
const af = a.fraction % amountFractionalBase;
|
||||
static stringifyValue(a: AmountLike, minFractional = 0): string {
|
||||
const aJ = Amounts.jsonifyAmount(a);
|
||||
const av = aJ.value + Math.floor(aJ.fraction / amountFractionalBase);
|
||||
const af = aJ.fraction % amountFractionalBase;
|
||||
let s = av.toString();
|
||||
|
||||
if (af) {
|
||||
|
@ -644,7 +644,7 @@ export enum RefreshReason {
|
||||
*/
|
||||
export interface CoinRefreshRequest {
|
||||
readonly coinPub: string;
|
||||
readonly amount: AmountJson;
|
||||
readonly amount: AmountString;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -719,12 +719,12 @@ export interface WireFee {
|
||||
/**
|
||||
* Fee for wire transfers.
|
||||
*/
|
||||
wireFee: AmountJson;
|
||||
wireFee: AmountString;
|
||||
|
||||
/**
|
||||
* Fees to close and refund a reserve.
|
||||
*/
|
||||
closingFee: AmountJson;
|
||||
closingFee: AmountString;
|
||||
|
||||
/**
|
||||
* Start date of the fee.
|
||||
@ -761,9 +761,9 @@ export interface ExchangeGlobalFees {
|
||||
startDate: TalerProtocolTimestamp;
|
||||
endDate: TalerProtocolTimestamp;
|
||||
|
||||
historyFee: AmountJson;
|
||||
accountFee: AmountJson;
|
||||
purseFee: AmountJson;
|
||||
historyFee: AmountString;
|
||||
accountFee: AmountString;
|
||||
purseFee: AmountString;
|
||||
|
||||
historyTimeout: TalerProtocolDuration;
|
||||
purseTimeout: TalerProtocolDuration;
|
||||
@ -782,8 +782,8 @@ const codecForExchangeAccount = (): Codec<ExchangeAccount> =>
|
||||
const codecForWireFee = (): Codec<WireFee> =>
|
||||
buildCodecForObject<WireFee>()
|
||||
.property("sig", codecForString())
|
||||
.property("wireFee", codecForAmountJson())
|
||||
.property("closingFee", codecForAmountJson())
|
||||
.property("wireFee", codecForAmountString())
|
||||
.property("closingFee", codecForAmountString())
|
||||
.property("startStamp", codecForTimestamp)
|
||||
.property("endStamp", codecForTimestamp)
|
||||
.build("codecForWireFee");
|
||||
@ -798,7 +798,7 @@ export interface DenominationInfo {
|
||||
/**
|
||||
* Value of one coin of the denomination.
|
||||
*/
|
||||
value: AmountJson;
|
||||
value: AmountString;
|
||||
|
||||
/**
|
||||
* Hash of the denomination public key.
|
||||
@ -811,22 +811,22 @@ export interface DenominationInfo {
|
||||
/**
|
||||
* Fee for withdrawing.
|
||||
*/
|
||||
feeWithdraw: AmountJson;
|
||||
feeWithdraw: AmountString;
|
||||
|
||||
/**
|
||||
* Fee for depositing.
|
||||
*/
|
||||
feeDeposit: AmountJson;
|
||||
feeDeposit: AmountString;
|
||||
|
||||
/**
|
||||
* Fee for refreshing.
|
||||
*/
|
||||
feeRefresh: AmountJson;
|
||||
feeRefresh: AmountString;
|
||||
|
||||
/**
|
||||
* Fee for refunding.
|
||||
*/
|
||||
feeRefund: AmountJson;
|
||||
feeRefund: AmountString;
|
||||
|
||||
/**
|
||||
* Validity start date of the denomination.
|
||||
@ -858,21 +858,21 @@ export interface FeeDescription {
|
||||
group: string;
|
||||
from: AbsoluteTime;
|
||||
until: AbsoluteTime;
|
||||
fee?: AmountJson;
|
||||
fee?: AmountString;
|
||||
}
|
||||
|
||||
export interface FeeDescriptionPair {
|
||||
group: string;
|
||||
from: AbsoluteTime;
|
||||
until: AbsoluteTime;
|
||||
left?: AmountJson;
|
||||
right?: AmountJson;
|
||||
left?: AmountString;
|
||||
right?: AmountString;
|
||||
}
|
||||
|
||||
export interface TimePoint<T> {
|
||||
id: string;
|
||||
group: string;
|
||||
fee: AmountJson;
|
||||
fee: AmountString;
|
||||
type: "start" | "end";
|
||||
moment: AbsoluteTime;
|
||||
denom: T;
|
||||
@ -955,8 +955,8 @@ export const codecForFeeDescriptionPair = (): Codec<FeeDescriptionPair> =>
|
||||
.property("group", codecForString())
|
||||
.property("from", codecForAbsoluteTime)
|
||||
.property("until", codecForAbsoluteTime)
|
||||
.property("left", codecOptional(codecForAmountJson()))
|
||||
.property("right", codecOptional(codecForAmountJson()))
|
||||
.property("left", codecOptional(codecForAmountString()))
|
||||
.property("right", codecOptional(codecForAmountString()))
|
||||
.build("FeeDescriptionPair");
|
||||
|
||||
export const codecForFeeDescription = (): Codec<FeeDescription> =>
|
||||
@ -964,7 +964,7 @@ export const codecForFeeDescription = (): Codec<FeeDescription> =>
|
||||
.property("group", codecForString())
|
||||
.property("from", codecForAbsoluteTime)
|
||||
.property("until", codecForAbsoluteTime)
|
||||
.property("fee", codecOptional(codecForAmountJson()))
|
||||
.property("fee", codecOptional(codecForAmountString()))
|
||||
.build("FeeDescription");
|
||||
|
||||
export const codecForFeesByOperations = (): Codec<
|
||||
@ -1056,8 +1056,8 @@ export interface ManualWithdrawalDetails {
|
||||
* Selected denominations withn some extra info.
|
||||
*/
|
||||
export interface DenomSelectionState {
|
||||
totalCoinValue: AmountJson;
|
||||
totalWithdrawCost: AmountJson;
|
||||
totalCoinValue: AmountString;
|
||||
totalWithdrawCost: AmountString;
|
||||
selectedDenoms: {
|
||||
denomPubHash: string;
|
||||
count: number;
|
||||
@ -1786,7 +1786,7 @@ export interface PayCoinSelection {
|
||||
/**
|
||||
* Amount requested by the merchant.
|
||||
*/
|
||||
paymentAmount: AmountJson;
|
||||
paymentAmount: AmountString;
|
||||
|
||||
/**
|
||||
* Public keys of the coins that were selected.
|
||||
@ -1796,17 +1796,17 @@ export interface PayCoinSelection {
|
||||
/**
|
||||
* Amount that each coin contributes.
|
||||
*/
|
||||
coinContributions: AmountJson[];
|
||||
coinContributions: AmountString[];
|
||||
|
||||
/**
|
||||
* How much of the wire fees is the customer paying?
|
||||
*/
|
||||
customerWireFees: AmountJson;
|
||||
customerWireFees: AmountString;
|
||||
|
||||
/**
|
||||
* How much of the deposit fees is the customer paying?
|
||||
*/
|
||||
customerDepositFees: AmountJson;
|
||||
customerDepositFees: AmountString;
|
||||
}
|
||||
|
||||
export interface InitiatePeerPushPaymentRequest {
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
AgeCommitmentProof,
|
||||
AgeRestriction,
|
||||
AmountJson,
|
||||
AmountLike,
|
||||
Amounts,
|
||||
AmountString,
|
||||
BlindedDenominationSignature,
|
||||
@ -1155,8 +1156,8 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
|
||||
sessionSecretSeed: refreshSessionSecretSeed,
|
||||
} = req;
|
||||
|
||||
const currency = newCoinDenoms[0].value.currency;
|
||||
let valueWithFee = Amounts.getZero(currency);
|
||||
const currency = Amounts.currencyOf(newCoinDenoms[0].value);
|
||||
let valueWithFee = Amounts.zeroOfCurrency(currency);
|
||||
|
||||
for (const ncd of newCoinDenoms) {
|
||||
const t = Amounts.add(ncd.value, ncd.feeWithdraw).amount;
|
||||
@ -1627,21 +1628,22 @@ export const nativeCryptoR: TalerCryptoInterfaceR = {
|
||||
},
|
||||
};
|
||||
|
||||
function amountToBuffer(amount: AmountJson): Uint8Array {
|
||||
function amountToBuffer(amount: AmountLike): Uint8Array {
|
||||
const amountJ = Amounts.jsonifyAmount(amount);
|
||||
const buffer = new ArrayBuffer(8 + 4 + 12);
|
||||
const dvbuf = new DataView(buffer);
|
||||
const u8buf = new Uint8Array(buffer);
|
||||
const curr = stringToBytes(amount.currency);
|
||||
const curr = stringToBytes(amountJ.currency);
|
||||
if (typeof dvbuf.setBigUint64 !== "undefined") {
|
||||
dvbuf.setBigUint64(0, BigInt(amount.value));
|
||||
dvbuf.setBigUint64(0, BigInt(amountJ.value));
|
||||
} else {
|
||||
const arr = bigint(amount.value).toArray(2 ** 8).value;
|
||||
const arr = bigint(amountJ.value).toArray(2 ** 8).value;
|
||||
let offset = 8 - arr.length;
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
dvbuf.setUint8(offset++, arr[i]);
|
||||
}
|
||||
}
|
||||
dvbuf.setUint32(8, amount.fraction);
|
||||
dvbuf.setUint32(8, amountJ.fraction);
|
||||
u8buf.set(curr, 8 + 4);
|
||||
|
||||
return u8buf;
|
||||
|
@ -44,8 +44,8 @@ import {
|
||||
|
||||
export interface RefreshNewDenomInfo {
|
||||
count: number;
|
||||
value: AmountJson;
|
||||
feeWithdraw: AmountJson;
|
||||
value: AmountString;
|
||||
feeWithdraw: AmountString;
|
||||
denomPub: DenominationPubKey;
|
||||
denomPubHash: string;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ import {
|
||||
UnblindedSignature,
|
||||
WireInfo,
|
||||
HashCodeString,
|
||||
Amounts,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import {
|
||||
describeContents,
|
||||
@ -276,22 +277,22 @@ export interface DenomFees {
|
||||
/**
|
||||
* Fee for withdrawing.
|
||||
*/
|
||||
feeWithdraw: AmountJson;
|
||||
feeWithdraw: AmountString;
|
||||
|
||||
/**
|
||||
* Fee for depositing.
|
||||
*/
|
||||
feeDeposit: AmountJson;
|
||||
feeDeposit: AmountString;
|
||||
|
||||
/**
|
||||
* Fee for refreshing.
|
||||
*/
|
||||
feeRefresh: AmountJson;
|
||||
feeRefresh: AmountString;
|
||||
|
||||
/**
|
||||
* Fee for refunding.
|
||||
*/
|
||||
feeRefund: AmountJson;
|
||||
feeRefund: AmountString;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -393,15 +394,15 @@ export namespace DenominationRecord {
|
||||
return {
|
||||
denomPub: d.denomPub,
|
||||
denomPubHash: d.denomPubHash,
|
||||
feeDeposit: d.fees.feeDeposit,
|
||||
feeRefresh: d.fees.feeRefresh,
|
||||
feeRefund: d.fees.feeRefund,
|
||||
feeWithdraw: d.fees.feeWithdraw,
|
||||
feeDeposit: Amounts.stringify(d.fees.feeDeposit),
|
||||
feeRefresh: Amounts.stringify(d.fees.feeRefresh),
|
||||
feeRefund: Amounts.stringify(d.fees.feeRefund),
|
||||
feeWithdraw: Amounts.stringify(d.fees.feeWithdraw),
|
||||
stampExpireDeposit: d.stampExpireDeposit,
|
||||
stampExpireLegal: d.stampExpireLegal,
|
||||
stampExpireWithdraw: d.stampExpireWithdraw,
|
||||
stampStart: d.stampStart,
|
||||
value: DenominationRecord.getValue(d),
|
||||
value: Amounts.stringify(DenominationRecord.getValue(d)),
|
||||
exchangeBaseUrl: d.exchangeBaseUrl,
|
||||
};
|
||||
}
|
||||
@ -527,7 +528,7 @@ export interface ExchangeRecord {
|
||||
* currency.
|
||||
*
|
||||
* We could use a rowID here, but having the currency in the
|
||||
* details pointer lets us do fewer DB queries sometimes.
|
||||
* details pointer lets us do fewer DB queries
|
||||
*/
|
||||
detailsPointer: ExchangeDetailsPointer | undefined;
|
||||
|
||||
@ -752,12 +753,12 @@ export interface TipRecord {
|
||||
/**
|
||||
* The tipped amount.
|
||||
*/
|
||||
tipAmountRaw: AmountJson;
|
||||
tipAmountRaw: AmountString;
|
||||
|
||||
/**
|
||||
* Effect on the balance (including fees etc).
|
||||
*/
|
||||
tipAmountEffective: AmountJson;
|
||||
tipAmountEffective: AmountString;
|
||||
|
||||
/**
|
||||
* Timestamp, the tip can't be picked up anymore after this deadline.
|
||||
@ -854,9 +855,9 @@ export interface RefreshGroupRecord {
|
||||
// object store for faster updates?
|
||||
refreshSessionPerCoin: (RefreshSessionRecord | undefined)[];
|
||||
|
||||
inputPerCoin: AmountJson[];
|
||||
inputPerCoin: AmountString[];
|
||||
|
||||
estimatedOutputPerCoin: AmountJson[];
|
||||
estimatedOutputPerCoin: AmountString[];
|
||||
|
||||
/**
|
||||
* Flag for each coin whether refreshing finished.
|
||||
@ -888,7 +889,7 @@ export interface RefreshSessionRecord {
|
||||
* Sum of the value of denominations we want
|
||||
* to withdraw in this session, without fees.
|
||||
*/
|
||||
amountRefreshOutput: AmountJson;
|
||||
amountRefreshOutput: AmountString;
|
||||
|
||||
/**
|
||||
* Hashed denominations of the newly requested coins.
|
||||
@ -927,9 +928,9 @@ export interface WalletRefundItemCommon {
|
||||
*/
|
||||
obtainedTime: TalerProtocolTimestamp;
|
||||
|
||||
refundAmount: AmountJson;
|
||||
refundAmount: AmountString;
|
||||
|
||||
refundFee: AmountJson;
|
||||
refundFee: AmountString;
|
||||
|
||||
/**
|
||||
* Upper bound on the refresh cost incurred by
|
||||
@ -938,7 +939,7 @@ export interface WalletRefundItemCommon {
|
||||
* Might be lower in practice when two refunds on the same
|
||||
* coin are refreshed in the same refresh operation.
|
||||
*/
|
||||
totalRefreshCostBound: AmountJson;
|
||||
totalRefreshCostBound: AmountString;
|
||||
|
||||
coinPub: string;
|
||||
|
||||
@ -1003,12 +1004,12 @@ export interface WalletContractData {
|
||||
merchantSig: string;
|
||||
merchantPub: string;
|
||||
merchant: MerchantInfo;
|
||||
amount: AmountJson;
|
||||
amount: AmountString;
|
||||
orderId: string;
|
||||
merchantBaseUrl: string;
|
||||
summary: string;
|
||||
autoRefund: TalerProtocolDuration | undefined;
|
||||
maxWireFee: AmountJson;
|
||||
maxWireFee: AmountString;
|
||||
wireFeeAmortization: number;
|
||||
payDeadline: TalerProtocolTimestamp;
|
||||
refundDeadline: TalerProtocolTimestamp;
|
||||
@ -1017,7 +1018,7 @@ export interface WalletContractData {
|
||||
timestamp: TalerProtocolTimestamp;
|
||||
wireMethod: string;
|
||||
wireInfoHash: string;
|
||||
maxDepositFee: AmountJson;
|
||||
maxDepositFee: AmountString;
|
||||
minimumAge?: number;
|
||||
deliveryDate: TalerProtocolTimestamp | undefined;
|
||||
deliveryLocation: Location | undefined;
|
||||
@ -1099,7 +1100,7 @@ export interface ProposalDownloadInfo {
|
||||
|
||||
export interface PurchasePayInfo {
|
||||
payCoinSelection: PayCoinSelection;
|
||||
totalPayCost: AmountJson;
|
||||
totalPayCost: AmountString;
|
||||
payCoinSelectionUid: string;
|
||||
}
|
||||
|
||||
@ -1216,7 +1217,7 @@ export interface PurchaseRecord {
|
||||
* How much merchant has refund to be taken but the wallet
|
||||
* did not picked up yet
|
||||
*/
|
||||
refundAmountAwaiting: AmountJson | undefined;
|
||||
refundAmountAwaiting: AmountString | undefined;
|
||||
}
|
||||
|
||||
export enum ConfigRecordKey {
|
||||
@ -1379,7 +1380,7 @@ export interface WithdrawalGroupRecord {
|
||||
/**
|
||||
* Amount that was sent by the user to fund the reserve.
|
||||
*/
|
||||
instructedAmount: AmountJson;
|
||||
instructedAmount: AmountString;
|
||||
|
||||
/**
|
||||
* Amount that was observed when querying the reserve that
|
||||
@ -1387,7 +1388,7 @@ export interface WithdrawalGroupRecord {
|
||||
*
|
||||
* Useful for diagnostics.
|
||||
*/
|
||||
reserveBalanceAmount?: AmountJson;
|
||||
reserveBalanceAmount?: AmountString;
|
||||
|
||||
/**
|
||||
* Amount including fees (i.e. the amount subtracted from the
|
||||
@ -1396,7 +1397,7 @@ export interface WithdrawalGroupRecord {
|
||||
* (Initial amount confirmed by the user, might differ with denomSel
|
||||
* on reselection.)
|
||||
*/
|
||||
rawWithdrawalAmount: AmountJson;
|
||||
rawWithdrawalAmount: AmountString;
|
||||
|
||||
/**
|
||||
* Amount that will be added to the balance when the withdrawal succeeds.
|
||||
@ -1404,7 +1405,7 @@ export interface WithdrawalGroupRecord {
|
||||
* (Initial amount confirmed by the user, might differ with denomSel
|
||||
* on reselection.)
|
||||
*/
|
||||
effectiveWithdrawalAmount: AmountJson;
|
||||
effectiveWithdrawalAmount: AmountString;
|
||||
|
||||
/**
|
||||
* Denominations selected for withdrawal.
|
||||
@ -1587,9 +1588,9 @@ export interface DepositGroupRecord {
|
||||
|
||||
payCoinSelectionUid: string;
|
||||
|
||||
totalPayCost: AmountJson;
|
||||
totalPayCost: AmountString;
|
||||
|
||||
effectiveDepositAmount: AmountJson;
|
||||
effectiveDepositAmount: AmountString;
|
||||
|
||||
depositedPerCoin: boolean[];
|
||||
|
||||
|
@ -160,7 +160,7 @@ export async function withdrawCoin(args: {
|
||||
const planchet = await cryptoApi.createPlanchet({
|
||||
coinIndex: 0,
|
||||
denomPub: denom.denomPub,
|
||||
feeWithdraw: denom.fees.feeWithdraw,
|
||||
feeWithdraw: Amounts.parseOrThrow(denom.fees.feeWithdraw),
|
||||
reservePriv: reserveKeyPair.reservePriv,
|
||||
reservePub: reserveKeyPair.reservePub,
|
||||
secretSeed: encodeCrock(getRandomBytes(32)),
|
||||
@ -294,11 +294,11 @@ export async function refreshCoin(req: {
|
||||
denomPub: x.denomPub,
|
||||
denomPubHash: x.denomPubHash,
|
||||
feeWithdraw: x.fees.feeWithdraw,
|
||||
value: {
|
||||
value: Amounts.stringify({
|
||||
currency: x.currency,
|
||||
fraction: x.amountFrac,
|
||||
value: x.amountVal,
|
||||
},
|
||||
}),
|
||||
})),
|
||||
meltCoinMaxAge: oldCoin.maxAge,
|
||||
});
|
||||
|
@ -104,10 +104,8 @@ async function recoverPayCoinSelection(
|
||||
|
||||
const coveredExchanges: Set<string> = new Set();
|
||||
|
||||
let totalWireFee: AmountJson = Amounts.getZero(contractData.amount.currency);
|
||||
let totalDepositFees: AmountJson = Amounts.getZero(
|
||||
contractData.amount.currency,
|
||||
);
|
||||
let totalWireFee: AmountJson = Amounts.zeroOfAmount(contractData.amount);
|
||||
let totalDepositFees: AmountJson = Amounts.zeroOfAmount(contractData.amount);
|
||||
|
||||
for (const coinPub of coinPubs) {
|
||||
const coinRecord = await tx.coins.get(coinPub);
|
||||
@ -136,7 +134,7 @@ async function recoverPayCoinSelection(
|
||||
fee.startStamp <= contractData.timestamp &&
|
||||
fee.endStamp >= contractData.timestamp
|
||||
) {
|
||||
wireFee = fee.wireFee;
|
||||
wireFee = Amounts.parseOrThrow(fee.wireFee);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -156,7 +154,7 @@ async function recoverPayCoinSelection(
|
||||
if (Amounts.cmp(contractData.maxWireFee, amortizedWireFee) < 0) {
|
||||
customerWireFee = amortizedWireFee;
|
||||
} else {
|
||||
customerWireFee = Amounts.getZero(contractData.amount.currency);
|
||||
customerWireFee = Amounts.zeroOfAmount(contractData.amount);
|
||||
}
|
||||
|
||||
const customerDepositFees = Amounts.sub(
|
||||
@ -166,10 +164,10 @@ async function recoverPayCoinSelection(
|
||||
|
||||
return {
|
||||
coinPubs,
|
||||
coinContributions,
|
||||
paymentAmount: contractData.amount,
|
||||
customerWireFees: customerWireFee,
|
||||
customerDepositFees,
|
||||
coinContributions: coinContributions.map((x) => Amounts.stringify(x)),
|
||||
paymentAmount: Amounts.stringify(contractData.amount),
|
||||
customerWireFees: Amounts.stringify(customerWireFee),
|
||||
customerDepositFees: Amounts.stringify(customerDepositFees),
|
||||
};
|
||||
}
|
||||
|
||||
@ -183,8 +181,8 @@ async function getDenomSelStateFromBackup(
|
||||
denomPubHash: string;
|
||||
count: number;
|
||||
}[] = [];
|
||||
let totalCoinValue = Amounts.getZero(currency);
|
||||
let totalWithdrawCost = Amounts.getZero(currency);
|
||||
let totalCoinValue = Amounts.zeroOfCurrency(currency);
|
||||
let totalWithdrawCost = Amounts.zeroOfCurrency(currency);
|
||||
for (const s of sel) {
|
||||
const d = await tx.denominations.get([exchangeBaseUrl, s.denom_pub_hash]);
|
||||
checkBackupInvariant(!!d);
|
||||
@ -200,8 +198,8 @@ async function getDenomSelStateFromBackup(
|
||||
}
|
||||
return {
|
||||
selectedDenoms,
|
||||
totalCoinValue,
|
||||
totalWithdrawCost,
|
||||
totalCoinValue: Amounts.stringify(totalCoinValue),
|
||||
totalWithdrawCost: Amounts.stringify(totalCoinValue),
|
||||
};
|
||||
}
|
||||
|
||||
@ -380,11 +378,11 @@ export async function importBackup(
|
||||
for (const fee of backupExchangeDetails.wire_fees) {
|
||||
const w = (wireInfo.feesForType[fee.wire_type] ??= []);
|
||||
w.push({
|
||||
closingFee: Amounts.parseOrThrow(fee.closing_fee),
|
||||
closingFee: Amounts.stringify(fee.closing_fee),
|
||||
endStamp: fee.end_stamp,
|
||||
sig: fee.sig,
|
||||
startStamp: fee.start_stamp,
|
||||
wireFee: Amounts.parseOrThrow(fee.wire_fee),
|
||||
wireFee: Amounts.stringify(fee.wire_fee),
|
||||
});
|
||||
}
|
||||
let tosAccepted = undefined;
|
||||
@ -412,9 +410,9 @@ export async function importBackup(
|
||||
tosCurrentEtag: backupExchangeDetails.tos_accepted_etag || "",
|
||||
tosAccepted,
|
||||
globalFees: backupExchangeDetails.global_fees.map((x) => ({
|
||||
accountFee: Amounts.parseOrThrow(x.accountFee),
|
||||
historyFee: Amounts.parseOrThrow(x.historyFee),
|
||||
purseFee: Amounts.parseOrThrow(x.purseFee),
|
||||
accountFee: Amounts.stringify(x.accountFee),
|
||||
historyFee: Amounts.stringify(x.historyFee),
|
||||
purseFee: Amounts.stringify(x.purseFee),
|
||||
endDate: x.endDate,
|
||||
historyTimeout: x.historyTimeout,
|
||||
signature: x.signature,
|
||||
@ -447,16 +445,10 @@ export async function importBackup(
|
||||
exchangeBaseUrl: backupExchangeDetails.base_url,
|
||||
exchangeMasterPub: backupExchangeDetails.master_public_key,
|
||||
fees: {
|
||||
feeDeposit: Amounts.parseOrThrow(
|
||||
backupDenomination.fee_deposit,
|
||||
),
|
||||
feeRefresh: Amounts.parseOrThrow(
|
||||
backupDenomination.fee_refresh,
|
||||
),
|
||||
feeRefund: Amounts.parseOrThrow(backupDenomination.fee_refund),
|
||||
feeWithdraw: Amounts.parseOrThrow(
|
||||
backupDenomination.fee_withdraw,
|
||||
),
|
||||
feeDeposit: Amounts.stringify(backupDenomination.fee_deposit),
|
||||
feeRefresh: Amounts.stringify(backupDenomination.fee_refresh),
|
||||
feeRefund: Amounts.stringify(backupDenomination.fee_refund),
|
||||
feeWithdraw: Amounts.stringify(backupDenomination.fee_withdraw),
|
||||
},
|
||||
isOffered: backupDenomination.is_offered,
|
||||
isRevoked: backupDenomination.is_revoked,
|
||||
@ -542,7 +534,7 @@ export async function importBackup(
|
||||
await tx.withdrawalGroups.put({
|
||||
withdrawalGroupId: backupWg.withdrawal_group_id,
|
||||
exchangeBaseUrl: backupWg.exchange_base_url,
|
||||
instructedAmount,
|
||||
instructedAmount: Amounts.stringify(instructedAmount),
|
||||
secretSeed: backupWg.secret_seed,
|
||||
denomsSel: await getDenomSelStateFromBackup(
|
||||
tx,
|
||||
@ -551,10 +543,10 @@ export async function importBackup(
|
||||
backupWg.selected_denoms,
|
||||
),
|
||||
denomSelUid: backupWg.selected_denoms_uid,
|
||||
rawWithdrawalAmount: Amounts.parseOrThrow(
|
||||
rawWithdrawalAmount: Amounts.stringify(
|
||||
backupWg.raw_withdrawal_amount,
|
||||
),
|
||||
effectiveWithdrawalAmount: Amounts.parseOrThrow(
|
||||
effectiveWithdrawalAmount: Amounts.stringify(
|
||||
backupWg.effective_withdrawal_amount,
|
||||
),
|
||||
reservePriv: backupWg.reserve_priv,
|
||||
@ -618,10 +610,10 @@ export async function importBackup(
|
||||
coinPub: backupRefund.coin_pub,
|
||||
executionTime: backupRefund.execution_time,
|
||||
obtainedTime: backupRefund.obtained_time,
|
||||
refundAmount: Amounts.parseOrThrow(backupRefund.refund_amount),
|
||||
refundFee: denom.fees.feeRefund,
|
||||
refundAmount: Amounts.stringify(backupRefund.refund_amount),
|
||||
refundFee: Amounts.stringify(denom.fees.feeRefund),
|
||||
rtransactionId: backupRefund.rtransaction_id,
|
||||
totalRefreshCostBound: Amounts.parseOrThrow(
|
||||
totalRefreshCostBound: Amounts.stringify(
|
||||
backupRefund.total_refresh_cost_bound,
|
||||
),
|
||||
};
|
||||
@ -658,7 +650,7 @@ export async function importBackup(
|
||||
if (parsedContractTerms.max_wire_fee) {
|
||||
maxWireFee = Amounts.parseOrThrow(parsedContractTerms.max_wire_fee);
|
||||
} else {
|
||||
maxWireFee = Amounts.getZero(amount.currency);
|
||||
maxWireFee = Amounts.zeroOfCurrency(amount.currency);
|
||||
}
|
||||
const download: ProposalDownloadInfo = {
|
||||
contractTermsHash,
|
||||
@ -682,7 +674,7 @@ export async function importBackup(
|
||||
backupPurchase.pay_info,
|
||||
),
|
||||
payCoinSelectionUid: backupPurchase.pay_info.pay_coins_uid,
|
||||
totalPayCost: Amounts.parseOrThrow(
|
||||
totalPayCost: Amounts.stringify(
|
||||
backupPurchase.pay_info.total_pay_cost,
|
||||
),
|
||||
};
|
||||
@ -776,7 +768,7 @@ export async function importBackup(
|
||||
count: x.count,
|
||||
denomPubHash: x.denom_pub_hash,
|
||||
})),
|
||||
amountRefreshOutput: denomSel.totalCoinValue,
|
||||
amountRefreshOutput: Amounts.stringify(denomSel.totalCoinValue),
|
||||
});
|
||||
} else {
|
||||
refreshSessionPerCoin.push(undefined);
|
||||
@ -797,11 +789,11 @@ export async function importBackup(
|
||||
operationStatus: backupRefreshGroup.timestamp_finish
|
||||
? RefreshOperationStatus.Finished
|
||||
: RefreshOperationStatus.Pending,
|
||||
inputPerCoin: backupRefreshGroup.old_coins.map((x) =>
|
||||
Amounts.parseOrThrow(x.input_amount),
|
||||
inputPerCoin: backupRefreshGroup.old_coins.map(
|
||||
(x) => x.input_amount,
|
||||
),
|
||||
estimatedOutputPerCoin: backupRefreshGroup.old_coins.map((x) =>
|
||||
Amounts.parseOrThrow(x.estimated_output_amount),
|
||||
estimatedOutputPerCoin: backupRefreshGroup.old_coins.map(
|
||||
(x) => x.estimated_output_amount,
|
||||
),
|
||||
refreshSessionPerCoin,
|
||||
});
|
||||
@ -834,8 +826,8 @@ export async function importBackup(
|
||||
merchantTipId: backupTip.merchant_tip_id,
|
||||
pickedUpTimestamp: backupTip.timestamp_finished,
|
||||
secretSeed: backupTip.secret_seed,
|
||||
tipAmountEffective: denomsSel.totalCoinValue,
|
||||
tipAmountRaw,
|
||||
tipAmountEffective: Amounts.stringify(denomsSel.totalCoinValue),
|
||||
tipAmountRaw: Amounts.stringify(tipAmountRaw),
|
||||
tipExpiration: backupTip.timestamp_expiration,
|
||||
walletTipId: backupTip.wallet_tip_id,
|
||||
denomSelUid: backupTip.selected_denoms_uid,
|
||||
|
@ -57,9 +57,9 @@ export async function getBalancesInsideTransaction(
|
||||
const b = balanceStore[currency];
|
||||
if (!b) {
|
||||
balanceStore[currency] = {
|
||||
available: Amounts.getZero(currency),
|
||||
pendingIncoming: Amounts.getZero(currency),
|
||||
pendingOutgoing: Amounts.getZero(currency),
|
||||
available: Amounts.zeroOfCurrency(currency),
|
||||
pendingIncoming: Amounts.zeroOfCurrency(currency),
|
||||
pendingOutgoing: Amounts.zeroOfCurrency(currency),
|
||||
};
|
||||
}
|
||||
return balanceStore[currency];
|
||||
@ -85,7 +85,10 @@ export async function getBalancesInsideTransaction(
|
||||
for (let i = 0; i < r.oldCoinPubs.length; i++) {
|
||||
const session = r.refreshSessionPerCoin[i];
|
||||
if (session) {
|
||||
const b = initBalance(session.amountRefreshOutput.currency);
|
||||
const currency = Amounts.parseOrThrow(
|
||||
session.amountRefreshOutput,
|
||||
).currency;
|
||||
const b = initBalance(currency);
|
||||
// We are always assuming the refresh will succeed, thus we
|
||||
// report the output as available balance.
|
||||
b.available = Amounts.add(
|
||||
@ -93,7 +96,8 @@ export async function getBalancesInsideTransaction(
|
||||
session.amountRefreshOutput,
|
||||
).amount;
|
||||
} else {
|
||||
const b = initBalance(r.inputPerCoin[i].currency);
|
||||
const currency = Amounts.parseOrThrow(r.inputPerCoin[i]).currency;
|
||||
const b = initBalance(currency);
|
||||
b.available = Amounts.add(
|
||||
b.available,
|
||||
r.estimatedOutputPerCoin[i],
|
||||
@ -106,7 +110,7 @@ export async function getBalancesInsideTransaction(
|
||||
if (wds.timestampFinish) {
|
||||
return;
|
||||
}
|
||||
const b = initBalance(wds.denomsSel.totalWithdrawCost.currency);
|
||||
const b = initBalance(Amounts.currencyOf(wds.denomsSel.totalWithdrawCost));
|
||||
b.pendingIncoming = Amounts.add(
|
||||
b.pendingIncoming,
|
||||
wds.denomsSel.totalCoinValue,
|
||||
|
@ -160,7 +160,7 @@ export async function spendCoins(
|
||||
throw Error("not enough remaining balance on coin for payment");
|
||||
}
|
||||
refreshCoinPubs.push({
|
||||
amount: remaining.amount,
|
||||
amount: Amounts.stringify(remaining.amount),
|
||||
coinPub: coin.coinPub,
|
||||
});
|
||||
checkDbInvariant(!!coinAvailability);
|
||||
|
@ -348,10 +348,10 @@ export async function prepareDepositGroup(
|
||||
auditors: contractData.allowedAuditors,
|
||||
exchanges: contractData.allowedExchanges,
|
||||
wireMethod: contractData.wireMethod,
|
||||
contractTermsAmount: contractData.amount,
|
||||
depositFeeLimit: contractData.maxDepositFee,
|
||||
contractTermsAmount: Amounts.parseOrThrow(contractData.amount),
|
||||
depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee),
|
||||
wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
|
||||
wireFeeLimit: contractData.maxWireFee,
|
||||
wireFeeLimit: Amounts.parseOrThrow(contractData.maxWireFee),
|
||||
prevPayCoins: [],
|
||||
});
|
||||
|
||||
@ -445,10 +445,10 @@ export async function createDepositGroup(
|
||||
auditors: contractData.allowedAuditors,
|
||||
exchanges: contractData.allowedExchanges,
|
||||
wireMethod: contractData.wireMethod,
|
||||
contractTermsAmount: contractData.amount,
|
||||
depositFeeLimit: contractData.maxDepositFee,
|
||||
contractTermsAmount: Amounts.parseOrThrow(contractData.amount),
|
||||
depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee),
|
||||
wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
|
||||
wireFeeLimit: contractData.maxWireFee,
|
||||
wireFeeLimit: Amounts.parseOrThrow(contractData.maxWireFee),
|
||||
prevPayCoins: [],
|
||||
});
|
||||
|
||||
@ -479,8 +479,8 @@ export async function createDepositGroup(
|
||||
depositedPerCoin: payCoinSel.coinPubs.map(() => false),
|
||||
merchantPriv: merchantPair.priv,
|
||||
merchantPub: merchantPair.pub,
|
||||
totalPayCost: totalDepositCost,
|
||||
effectiveDepositAmount,
|
||||
totalPayCost: Amounts.stringify(totalDepositCost),
|
||||
effectiveDepositAmount: Amounts.stringify(effectiveDepositAmount),
|
||||
wire: {
|
||||
payto_uri: req.depositPaytoUri,
|
||||
salt: wireSalt,
|
||||
@ -501,7 +501,9 @@ export async function createDepositGroup(
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `txn:deposit:${depositGroup.depositGroupId}`,
|
||||
coinPubs: payCoinSel.coinPubs,
|
||||
contributions: payCoinSel.coinContributions,
|
||||
contributions: payCoinSel.coinContributions.map((x) =>
|
||||
Amounts.parseOrThrow(x),
|
||||
),
|
||||
refreshReason: RefreshReason.PayDeposit,
|
||||
});
|
||||
await tx.depositGroups.put(depositGroup);
|
||||
@ -543,8 +545,8 @@ export async function getEffectiveDepositAmount(
|
||||
if (!denom) {
|
||||
throw Error("can't find denomination to calculate deposit amount");
|
||||
}
|
||||
amt.push(pcs.coinContributions[i]);
|
||||
fees.push(denom.feeDeposit);
|
||||
amt.push(Amounts.parseOrThrow(pcs.coinContributions[i]));
|
||||
fees.push(Amounts.parseOrThrow(denom.feeDeposit));
|
||||
exchangeSet.add(coin.exchangeBaseUrl);
|
||||
}
|
||||
|
||||
@ -565,7 +567,7 @@ export async function getEffectiveDepositAmount(
|
||||
);
|
||||
})?.wireFee;
|
||||
if (fee) {
|
||||
fees.push(fee);
|
||||
fees.push(Amounts.parseOrThrow(fee));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -604,7 +606,7 @@ export async function getTotalFeesForDepositAmount(
|
||||
if (!denom) {
|
||||
throw Error("can't find denomination to calculate deposit amount");
|
||||
}
|
||||
coinFee.push(denom.feeDeposit);
|
||||
coinFee.push(Amounts.parseOrThrow(denom.feeDeposit));
|
||||
exchangeSet.add(coin.exchangeBaseUrl);
|
||||
|
||||
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl
|
||||
@ -638,7 +640,7 @@ export async function getTotalFeesForDepositAmount(
|
||||
},
|
||||
)?.wireFee;
|
||||
if (fee) {
|
||||
wireFee.push(fee);
|
||||
wireFee.push(Amounts.parseOrThrow(fee));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -98,10 +98,10 @@ function denominationRecordFromKeys(
|
||||
exchangeBaseUrl,
|
||||
exchangeMasterPub,
|
||||
fees: {
|
||||
feeDeposit: Amounts.parseOrThrow(denomIn.fee_deposit),
|
||||
feeRefresh: Amounts.parseOrThrow(denomIn.fee_refresh),
|
||||
feeRefund: Amounts.parseOrThrow(denomIn.fee_refund),
|
||||
feeWithdraw: Amounts.parseOrThrow(denomIn.fee_withdraw),
|
||||
feeDeposit: Amounts.stringify(denomIn.fee_deposit),
|
||||
feeRefresh: Amounts.stringify(denomIn.fee_refresh),
|
||||
feeRefund: Amounts.stringify(denomIn.fee_refund),
|
||||
feeWithdraw: Amounts.stringify(denomIn.fee_withdraw),
|
||||
},
|
||||
isOffered: true,
|
||||
isRevoked: false,
|
||||
@ -267,11 +267,11 @@ async function validateWireInfo(
|
||||
const startStamp = x.start_date;
|
||||
const endStamp = x.end_date;
|
||||
const fee: WireFee = {
|
||||
closingFee: Amounts.parseOrThrow(x.closing_fee),
|
||||
closingFee: Amounts.stringify(x.closing_fee),
|
||||
endStamp,
|
||||
sig: x.sig,
|
||||
startStamp,
|
||||
wireFee: Amounts.parseOrThrow(x.wire_fee),
|
||||
wireFee: Amounts.stringify(x.wire_fee),
|
||||
};
|
||||
let isValid = false;
|
||||
if (ws.insecureTrustExchange) {
|
||||
@ -321,9 +321,9 @@ async function validateGlobalFees(
|
||||
throw Error("exchange global fees signature invalid: " + gf.master_sig);
|
||||
}
|
||||
egf.push({
|
||||
accountFee: Amounts.parseOrThrow(gf.account_fee),
|
||||
historyFee: Amounts.parseOrThrow(gf.history_fee),
|
||||
purseFee: Amounts.parseOrThrow(gf.purse_fee),
|
||||
accountFee: Amounts.stringify(gf.account_fee),
|
||||
historyFee: Amounts.stringify(gf.history_fee),
|
||||
purseFee: Amounts.stringify(gf.purse_fee),
|
||||
startDate: gf.start_date,
|
||||
endDate: gf.end_date,
|
||||
signature: gf.master_sig,
|
||||
|
@ -182,10 +182,10 @@ export async function getTotalPaymentCost(
|
||||
DenominationRecord.toDenomInfo(denom),
|
||||
amountLeft,
|
||||
);
|
||||
costs.push(pcs.coinContributions[i]);
|
||||
costs.push(Amounts.parseOrThrow(pcs.coinContributions[i]));
|
||||
costs.push(refreshCost);
|
||||
}
|
||||
const zero = Amounts.getZero(pcs.paymentAmount.currency);
|
||||
const zero = Amounts.zeroOfAmount(pcs.paymentAmount);
|
||||
return Amounts.sum([zero, ...costs]).amount;
|
||||
});
|
||||
}
|
||||
@ -307,10 +307,10 @@ export function extractContractData(
|
||||
if (parsedContractTerms.max_wire_fee) {
|
||||
maxWireFee = Amounts.parseOrThrow(parsedContractTerms.max_wire_fee);
|
||||
} else {
|
||||
maxWireFee = Amounts.getZero(amount.currency);
|
||||
maxWireFee = Amounts.zeroOfCurrency(amount.currency);
|
||||
}
|
||||
return {
|
||||
amount,
|
||||
amount: Amounts.stringify(amount),
|
||||
contractTermsHash: contractTermsHash,
|
||||
fulfillmentUrl: parsedContractTerms.fulfillment_url ?? "",
|
||||
merchantBaseUrl: parsedContractTerms.merchant_base_url,
|
||||
@ -319,7 +319,7 @@ export function extractContractData(
|
||||
orderId: parsedContractTerms.order_id,
|
||||
summary: parsedContractTerms.summary,
|
||||
autoRefund: parsedContractTerms.auto_refund,
|
||||
maxWireFee,
|
||||
maxWireFee: Amounts.stringify(maxWireFee),
|
||||
payDeadline: parsedContractTerms.pay_deadline,
|
||||
refundDeadline: parsedContractTerms.refund_deadline,
|
||||
wireFeeAmortization: parsedContractTerms.wire_fee_amortization || 1,
|
||||
@ -334,7 +334,7 @@ export function extractContractData(
|
||||
timestamp: parsedContractTerms.timestamp,
|
||||
wireMethod: parsedContractTerms.wire_method,
|
||||
wireInfoHash: parsedContractTerms.h_wire,
|
||||
maxDepositFee: Amounts.parseOrThrow(parsedContractTerms.max_fee),
|
||||
maxDepositFee: Amounts.stringify(parsedContractTerms.max_fee),
|
||||
merchant: parsedContractTerms.merchant,
|
||||
products: parsedContractTerms.products,
|
||||
summaryI18n: parsedContractTerms.summary_i18n,
|
||||
@ -539,7 +539,7 @@ export async function processDownloadProposal(
|
||||
p.download = {
|
||||
contractTermsHash,
|
||||
contractTermsMerchantSig: contractData.merchantSig,
|
||||
currency: contractData.amount.currency,
|
||||
currency: Amounts.currencyOf(contractData.amount),
|
||||
fulfillmentUrl: contractData.fulfillmentUrl,
|
||||
};
|
||||
await tx.contractTerms.put({
|
||||
@ -825,9 +825,9 @@ async function handleInsufficientFunds(
|
||||
}
|
||||
prevPayCoins.push({
|
||||
coinPub,
|
||||
contribution: contrib,
|
||||
contribution: Amounts.parseOrThrow(contrib),
|
||||
exchangeBaseUrl: coin.exchangeBaseUrl,
|
||||
feeDeposit: denom.fees.feeDeposit,
|
||||
feeDeposit: Amounts.parseOrThrow(denom.fees.feeDeposit),
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -836,10 +836,10 @@ async function handleInsufficientFunds(
|
||||
auditors: contractData.allowedAuditors,
|
||||
exchanges: contractData.allowedExchanges,
|
||||
wireMethod: contractData.wireMethod,
|
||||
contractTermsAmount: contractData.amount,
|
||||
depositFeeLimit: contractData.maxDepositFee,
|
||||
contractTermsAmount: Amounts.parseOrThrow(contractData.amount),
|
||||
depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee),
|
||||
wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
|
||||
wireFeeLimit: contractData.maxWireFee,
|
||||
wireFeeLimit: Amounts.parseOrThrow(contractData.maxWireFee),
|
||||
prevPayCoins,
|
||||
requiredMinimumAge: contractData.minimumAge,
|
||||
});
|
||||
@ -875,7 +875,9 @@ async function handleInsufficientFunds(
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `txn:proposal:${p.proposalId}`,
|
||||
coinPubs: payInfo.payCoinSelection.coinPubs,
|
||||
contributions: payInfo.payCoinSelection.coinContributions,
|
||||
contributions: payInfo.payCoinSelection.coinContributions.map((x) =>
|
||||
Amounts.parseOrThrow(x),
|
||||
),
|
||||
refreshReason: RefreshReason.PayMerchant,
|
||||
});
|
||||
});
|
||||
@ -1068,7 +1070,7 @@ export function selectGreedy(
|
||||
wireFeesPerExchange,
|
||||
wireFeeAmortization,
|
||||
aci.exchangeBaseUrl,
|
||||
aci.feeDeposit,
|
||||
Amounts.parseOrThrow(aci.feeDeposit),
|
||||
);
|
||||
|
||||
let coinSpend = Amounts.max(
|
||||
@ -1190,8 +1192,8 @@ export async function selectPayCoinsNew(
|
||||
amountPayRemaining: contractTermsAmount,
|
||||
amountWireFeeLimitRemaining: wireFeeLimit,
|
||||
amountDepositFeeLimitRemaining: depositFeeLimit,
|
||||
customerDepositFees: Amounts.getZero(currency),
|
||||
customerWireFees: Amounts.getZero(currency),
|
||||
customerDepositFees: Amounts.zeroOfCurrency(currency),
|
||||
customerWireFees: Amounts.zeroOfCurrency(currency),
|
||||
wireFeeCoveredForExchange: new Set(),
|
||||
};
|
||||
|
||||
@ -1269,11 +1271,11 @@ export async function selectPayCoinsNew(
|
||||
});
|
||||
|
||||
return {
|
||||
paymentAmount: contractTermsAmount,
|
||||
coinContributions,
|
||||
paymentAmount: Amounts.stringify(contractTermsAmount),
|
||||
coinContributions: coinContributions.map((x) => Amounts.stringify(x)),
|
||||
coinPubs,
|
||||
customerDepositFees: tally.customerDepositFees,
|
||||
customerWireFees: tally.customerWireFees,
|
||||
customerDepositFees: Amounts.stringify(tally.customerDepositFees),
|
||||
customerWireFees: Amounts.stringify(tally.customerWireFees),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1326,10 +1328,10 @@ export async function checkPaymentByProposalId(
|
||||
const res = await selectPayCoinsNew(ws, {
|
||||
auditors: contractData.allowedAuditors,
|
||||
exchanges: contractData.allowedExchanges,
|
||||
contractTermsAmount: contractData.amount,
|
||||
depositFeeLimit: contractData.maxDepositFee,
|
||||
contractTermsAmount: Amounts.parseOrThrow(contractData.amount),
|
||||
depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee),
|
||||
wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
|
||||
wireFeeLimit: contractData.maxWireFee,
|
||||
wireFeeLimit: Amounts.parseOrThrow(contractData.maxWireFee),
|
||||
prevPayCoins: [],
|
||||
requiredMinimumAge: contractData.minimumAge,
|
||||
wireMethod: contractData.wireMethod,
|
||||
@ -1531,10 +1533,10 @@ export async function generateDepositPermissions(
|
||||
denomKeyType: denom.denomPub.cipher,
|
||||
denomSig: coin.denomSig,
|
||||
exchangeBaseUrl: coin.exchangeBaseUrl,
|
||||
feeDeposit: denom.fees.feeDeposit,
|
||||
feeDeposit: Amounts.parseOrThrow(denom.fees.feeDeposit),
|
||||
merchantPub: contractData.merchantPub,
|
||||
refundDeadline: contractData.refundDeadline,
|
||||
spendAmount: payCoinSel.coinContributions[i],
|
||||
spendAmount: Amounts.parseOrThrow(payCoinSel.coinContributions[i]),
|
||||
timestamp: contractData.timestamp,
|
||||
wireInfoHash,
|
||||
ageCommitmentProof: coin.ageCommitmentProof,
|
||||
@ -1684,10 +1686,10 @@ export async function confirmPay(
|
||||
auditors: contractData.allowedAuditors,
|
||||
exchanges: contractData.allowedExchanges,
|
||||
wireMethod: contractData.wireMethod,
|
||||
contractTermsAmount: contractData.amount,
|
||||
depositFeeLimit: contractData.maxDepositFee,
|
||||
contractTermsAmount: Amounts.parseOrThrow(contractData.amount),
|
||||
depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee),
|
||||
wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
|
||||
wireFeeLimit: contractData.maxWireFee,
|
||||
wireFeeLimit: Amounts.parseOrThrow(contractData.maxWireFee),
|
||||
prevPayCoins: [],
|
||||
requiredMinimumAge: contractData.minimumAge,
|
||||
forcedSelection: forcedCoinSel,
|
||||
@ -1742,7 +1744,7 @@ export async function confirmPay(
|
||||
p.payInfo = {
|
||||
payCoinSelection: coinSelection,
|
||||
payCoinSelectionUid: encodeCrock(getRandomBytes(16)),
|
||||
totalPayCost: payCostInfo,
|
||||
totalPayCost: Amounts.stringify(payCostInfo),
|
||||
};
|
||||
p.lastSessionId = sessionId;
|
||||
p.timestampAccept = TalerProtocolTimestamp.now();
|
||||
@ -1751,7 +1753,9 @@ export async function confirmPay(
|
||||
await spendCoins(ws, tx, {
|
||||
allocationId: `txn:proposal:${p.proposalId}`,
|
||||
coinPubs: coinSelection.coinPubs,
|
||||
contributions: coinSelection.coinContributions,
|
||||
contributions: coinSelection.coinContributions.map((x) =>
|
||||
Amounts.parseOrThrow(x),
|
||||
),
|
||||
refreshReason: RefreshReason.PayMerchant,
|
||||
});
|
||||
break;
|
||||
@ -2131,15 +2135,18 @@ async function applySuccessfulRefund(
|
||||
amountLeft,
|
||||
);
|
||||
|
||||
refreshCoinsMap[coin.coinPub] = { coinPub: coin.coinPub, amount: amountLeft };
|
||||
refreshCoinsMap[coin.coinPub] = {
|
||||
coinPub: coin.coinPub,
|
||||
amount: Amounts.stringify(amountLeft),
|
||||
};
|
||||
|
||||
p.refunds[refundKey] = {
|
||||
type: RefundState.Applied,
|
||||
obtainedTime: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
|
||||
executionTime: r.execution_time,
|
||||
refundAmount: Amounts.parseOrThrow(r.refund_amount),
|
||||
refundFee: denom.fees.feeRefund,
|
||||
totalRefreshCostBound,
|
||||
refundAmount: Amounts.stringify(r.refund_amount),
|
||||
refundFee: Amounts.stringify(denom.fees.feeRefund),
|
||||
totalRefreshCostBound: Amounts.stringify(totalRefreshCostBound),
|
||||
coinPub: r.coin_pub,
|
||||
rtransactionId: r.rtransaction_id,
|
||||
};
|
||||
@ -2189,9 +2196,9 @@ async function storePendingRefund(
|
||||
type: RefundState.Pending,
|
||||
obtainedTime: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
|
||||
executionTime: r.execution_time,
|
||||
refundAmount: Amounts.parseOrThrow(r.refund_amount),
|
||||
refundFee: denom.fees.feeRefund,
|
||||
totalRefreshCostBound,
|
||||
refundAmount: Amounts.stringify(r.refund_amount),
|
||||
refundFee: Amounts.stringify(denom.fees.feeRefund),
|
||||
totalRefreshCostBound: Amounts.stringify(totalRefreshCostBound),
|
||||
coinPub: r.coin_pub,
|
||||
rtransactionId: r.rtransaction_id,
|
||||
};
|
||||
@ -2241,9 +2248,9 @@ async function storeFailedRefund(
|
||||
type: RefundState.Failed,
|
||||
obtainedTime: TalerProtocolTimestamp.now(),
|
||||
executionTime: r.execution_time,
|
||||
refundAmount: Amounts.parseOrThrow(r.refund_amount),
|
||||
refundFee: denom.fees.feeRefund,
|
||||
totalRefreshCostBound,
|
||||
refundAmount: Amounts.stringify(r.refund_amount),
|
||||
refundFee: Amounts.stringify(denom.fees.feeRefund),
|
||||
totalRefreshCostBound: Amounts.stringify(totalRefreshCostBound),
|
||||
coinPub: r.coin_pub,
|
||||
rtransactionId: r.rtransaction_id,
|
||||
};
|
||||
@ -2274,13 +2281,13 @@ async function storeFailedRefund(
|
||||
let contrib: AmountJson | undefined;
|
||||
for (let i = 0; i < payCoinSelection.coinPubs.length; i++) {
|
||||
if (payCoinSelection.coinPubs[i] === r.coin_pub) {
|
||||
contrib = payCoinSelection.coinContributions[i];
|
||||
contrib = Amounts.parseOrThrow(payCoinSelection.coinContributions[i]);
|
||||
}
|
||||
}
|
||||
// FIXME: Is this case tested?!
|
||||
refreshCoinsMap[coin.coinPub] = {
|
||||
coinPub: coin.coinPub,
|
||||
amount: amountLeft,
|
||||
amount: Amounts.stringify(amountLeft),
|
||||
};
|
||||
await tx.coins.put(coin);
|
||||
}
|
||||
@ -2417,10 +2424,8 @@ async function calculateRefundSummary(
|
||||
p: PurchaseRecord,
|
||||
): Promise<RefundSummary> {
|
||||
const download = await expectProposalDownload(ws, p);
|
||||
let amountRefundGranted = Amounts.getZero(
|
||||
download.contractData.amount.currency,
|
||||
);
|
||||
let amountRefundGone = Amounts.getZero(download.contractData.amount.currency);
|
||||
let amountRefundGranted = Amounts.zeroOfAmount(download.contractData.amount);
|
||||
let amountRefundGone = Amounts.zeroOfAmount(download.contractData.amount);
|
||||
|
||||
let pendingAtExchange = false;
|
||||
|
||||
@ -2454,7 +2459,7 @@ async function calculateRefundSummary(
|
||||
}
|
||||
});
|
||||
return {
|
||||
amountEffectivePaid: payInfo.totalPayCost,
|
||||
amountEffectivePaid: Amounts.parseOrThrow(payInfo.totalPayCost),
|
||||
amountRefundGone,
|
||||
amountRefundGranted,
|
||||
pendingAtExchange,
|
||||
@ -2598,7 +2603,7 @@ async function queryAndSaveAwaitingRefund(
|
||||
);
|
||||
if (!orderStatus.refunded) {
|
||||
// Wait for retry ...
|
||||
return Amounts.getZero(download.contractData.amount.currency);
|
||||
return Amounts.zeroOfAmount(download.contractData.amount);
|
||||
}
|
||||
|
||||
const refundAwaiting = Amounts.sub(
|
||||
@ -2618,7 +2623,7 @@ async function queryAndSaveAwaitingRefund(
|
||||
logger.warn("purchase does not exist anymore");
|
||||
return;
|
||||
}
|
||||
p.refundAmountAwaiting = refundAwaiting;
|
||||
p.refundAmountAwaiting = Amounts.stringify(refundAwaiting);
|
||||
await tx.purchases.put(p);
|
||||
});
|
||||
}
|
||||
|
@ -158,8 +158,8 @@ export async function selectPeerCoins(
|
||||
}
|
||||
coinInfos.push({
|
||||
coinPub: coin.coinPub,
|
||||
feeDeposit: denom.feeDeposit,
|
||||
value: denom.value,
|
||||
feeDeposit: Amounts.parseOrThrow(denom.feeDeposit),
|
||||
value: Amounts.parseOrThrow(denom.value),
|
||||
denomPubHash: denom.denomPubHash,
|
||||
coinPriv: coin.coinPriv,
|
||||
denomSig: coin.denomSig,
|
||||
@ -175,8 +175,8 @@ export async function selectPeerCoins(
|
||||
-Amounts.cmp(o1.value, o2.value) ||
|
||||
strcmp(o1.denomPubHash, o2.denomPubHash),
|
||||
);
|
||||
let amountAcc = Amounts.getZero(instructedAmount.currency);
|
||||
let depositFeesAcc = Amounts.getZero(instructedAmount.currency);
|
||||
let amountAcc = Amounts.zeroOfCurrency(instructedAmount.currency);
|
||||
let depositFeesAcc = Amounts.zeroOfCurrency(instructedAmount.currency);
|
||||
const resCoins: {
|
||||
coinPub: string;
|
||||
coinPriv: string;
|
||||
@ -553,7 +553,7 @@ export async function acceptPeerPushPayment(
|
||||
mergeTimestamp: mergeTimestamp,
|
||||
purseAmount: Amounts.stringify(amount),
|
||||
purseExpiration: contractTerms.purse_expiration,
|
||||
purseFee: Amounts.stringify(Amounts.getZero(amount.currency)),
|
||||
purseFee: Amounts.stringify(Amounts.zeroOfCurrency(amount.currency)),
|
||||
pursePub: peerInc.pursePub,
|
||||
reservePayto,
|
||||
reservePriv: mergeReserveInfo.reservePriv,
|
||||
@ -796,7 +796,7 @@ export async function initiatePeerPullPayment(
|
||||
const hContractTerms = ContractTermsUtil.hashContractTerms(contractTerms);
|
||||
|
||||
const purseFee = Amounts.stringify(
|
||||
Amounts.getZero(Amounts.parseOrThrow(req.amount).currency),
|
||||
Amounts.zeroOfCurrency(Amounts.parseOrThrow(req.amount).currency),
|
||||
);
|
||||
|
||||
const sigRes = await ws.cryptoApi.signReservePurseCreate({
|
||||
|
@ -291,7 +291,7 @@ async function recoupRefreshCoin(
|
||||
).amount;
|
||||
recoupGroup.scheduleRefreshCoins.push({
|
||||
coinPub: oldCoin.coinPub,
|
||||
amount: residualAmount,
|
||||
amount: Amounts.stringify(residualAmount),
|
||||
});
|
||||
}
|
||||
await tx.coins.put(revokedCoin);
|
||||
|
@ -110,7 +110,7 @@ export function getTotalRefreshCost(
|
||||
const denomMap = Object.fromEntries(denoms.map((x) => [x.denomPubHash, x]));
|
||||
const withdrawDenoms = selectWithdrawalDenominations(withdrawAmount, denoms);
|
||||
const resultingAmount = Amounts.add(
|
||||
Amounts.getZero(withdrawAmount.currency),
|
||||
Amounts.zeroOfCurrency(withdrawAmount.currency),
|
||||
...withdrawDenoms.selectedDenoms.map(
|
||||
(d) =>
|
||||
Amounts.mult(
|
||||
@ -273,7 +273,7 @@ async function refreshCreateSession(
|
||||
count: x.count,
|
||||
denomPubHash: x.denomPubHash,
|
||||
})),
|
||||
amountRefreshOutput: newCoinDenoms.totalCoinValue,
|
||||
amountRefreshOutput: Amounts.stringify(newCoinDenoms.totalCoinValue),
|
||||
};
|
||||
await tx.refreshGroups.put(rg);
|
||||
});
|
||||
@ -340,7 +340,7 @@ async function refreshMelt(
|
||||
denomPub: newDenom.denomPub,
|
||||
denomPubHash: newDenom.denomPubHash,
|
||||
feeWithdraw: newDenom.feeWithdraw,
|
||||
value: newDenom.value,
|
||||
value: Amounts.stringify(newDenom.value),
|
||||
});
|
||||
}
|
||||
return { newCoinDenoms, oldCoin, oldDenom, refreshGroup, refreshSession };
|
||||
@ -368,7 +368,7 @@ async function refreshMelt(
|
||||
meltCoinDenomPubHash: oldCoin.denomPubHash,
|
||||
meltCoinPriv: oldCoin.coinPriv,
|
||||
meltCoinPub: oldCoin.coinPub,
|
||||
feeRefresh: oldDenom.feeRefresh,
|
||||
feeRefresh: Amounts.parseOrThrow(oldDenom.feeRefresh),
|
||||
meltCoinMaxAge: oldCoin.maxAge,
|
||||
meltCoinAgeCommitmentProof: oldCoin.ageCommitmentProof,
|
||||
newCoinDenoms,
|
||||
@ -584,7 +584,7 @@ async function refreshReveal(
|
||||
denomPub: newDenom.denomPub,
|
||||
denomPubHash: newDenom.denomPubHash,
|
||||
feeWithdraw: newDenom.feeWithdraw,
|
||||
value: newDenom.value,
|
||||
value: Amounts.stringify(newDenom.value),
|
||||
});
|
||||
}
|
||||
return {
|
||||
@ -626,7 +626,7 @@ async function refreshReveal(
|
||||
meltCoinDenomPubHash: oldCoin.denomPubHash,
|
||||
meltCoinPriv: oldCoin.coinPriv,
|
||||
meltCoinPub: oldCoin.coinPub,
|
||||
feeRefresh: oldDenom.feeRefresh,
|
||||
feeRefresh: Amounts.parseOrThrow(oldDenom.feeRefresh),
|
||||
newCoinDenoms,
|
||||
meltCoinMaxAge: oldCoin.maxAge,
|
||||
meltCoinAgeCommitmentProof: oldCoin.ageCommitmentProof,
|
||||
@ -922,10 +922,14 @@ export async function createRefreshGroup(
|
||||
assertUnreachable(coin.status);
|
||||
}
|
||||
const refreshAmount = ocp.amount;
|
||||
inputPerCoin.push(refreshAmount);
|
||||
inputPerCoin.push(Amounts.parseOrThrow(refreshAmount));
|
||||
await tx.coins.put(coin);
|
||||
const denoms = await getDenoms(coin.exchangeBaseUrl);
|
||||
const cost = getTotalRefreshCost(denoms, denom, refreshAmount);
|
||||
const cost = getTotalRefreshCost(
|
||||
denoms,
|
||||
denom,
|
||||
Amounts.parseOrThrow(refreshAmount),
|
||||
);
|
||||
const output = Amounts.sub(refreshAmount, cost).amount;
|
||||
estimatedOutputPerCoin.push(output);
|
||||
}
|
||||
@ -934,13 +938,15 @@ export async function createRefreshGroup(
|
||||
operationStatus: RefreshOperationStatus.Pending,
|
||||
timestampFinished: undefined,
|
||||
statusPerCoin: oldCoinPubs.map(() => RefreshCoinStatus.Pending),
|
||||
lastErrorPerCoin: {},
|
||||
oldCoinPubs: oldCoinPubs.map((x) => x.coinPub),
|
||||
lastErrorPerCoin: {},
|
||||
reason,
|
||||
refreshGroupId,
|
||||
refreshSessionPerCoin: oldCoinPubs.map(() => undefined),
|
||||
inputPerCoin,
|
||||
estimatedOutputPerCoin,
|
||||
inputPerCoin: inputPerCoin.map((x) => Amounts.stringify(x)),
|
||||
estimatedOutputPerCoin: estimatedOutputPerCoin.map((x) =>
|
||||
Amounts.stringify(x),
|
||||
),
|
||||
timestampCreated: TalerProtocolTimestamp.now(),
|
||||
};
|
||||
|
||||
@ -1037,11 +1043,11 @@ export async function autoRefresh(
|
||||
if (AbsoluteTime.isExpired(executeThreshold)) {
|
||||
refreshCoins.push({
|
||||
coinPub: coin.coinPub,
|
||||
amount: {
|
||||
amount: Amounts.stringify({
|
||||
value: denom.amountVal,
|
||||
fraction: denom.amountFrac,
|
||||
currency: denom.currency,
|
||||
},
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
const checkThreshold = getAutoRefreshCheckThreshold(denom);
|
||||
|
@ -127,13 +127,13 @@ export async function prepareTip(
|
||||
const newTipRecord: TipRecord = {
|
||||
walletTipId: walletTipId,
|
||||
acceptedTimestamp: undefined,
|
||||
tipAmountRaw: amount,
|
||||
tipAmountRaw: Amounts.stringify(amount),
|
||||
tipExpiration: tipPickupStatus.expiration,
|
||||
exchangeBaseUrl: tipPickupStatus.exchange_url,
|
||||
merchantBaseUrl: res.merchantBaseUrl,
|
||||
createdTimestamp: TalerProtocolTimestamp.now(),
|
||||
merchantTipId: res.merchantTipId,
|
||||
tipAmountEffective: selectedDenoms.totalCoinValue,
|
||||
tipAmountEffective: Amounts.stringify(selectedDenoms.totalCoinValue),
|
||||
denomsSel: selectedDenoms,
|
||||
pickedUpTimestamp: undefined,
|
||||
secretSeed,
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
Logger,
|
||||
OrderShortInfo,
|
||||
PaymentStatus,
|
||||
PeerContractTerms,
|
||||
RefundInfoShort,
|
||||
TalerProtocolTimestamp,
|
||||
Transaction,
|
||||
@ -49,6 +50,8 @@ import {
|
||||
WithdrawalGroupRecord,
|
||||
WithdrawalRecordType,
|
||||
WalletContractData,
|
||||
PeerPushPaymentInitiationStatus,
|
||||
PeerPullPaymentIncomingStatus,
|
||||
} from "../db.js";
|
||||
import { InternalWalletState } from "../internal-wallet-state.js";
|
||||
import { assertUnreachable } from "../util/assertUnreachable.js";
|
||||
@ -222,7 +225,7 @@ export async function getTransactionById(
|
||||
const contractData = download.contractData;
|
||||
const refunds = mergeRefundByExecutionTime(
|
||||
cleanRefunds,
|
||||
Amounts.getZero(contractData.amount.currency),
|
||||
Amounts.zeroOfAmount(contractData.amount),
|
||||
);
|
||||
|
||||
const payOpId = RetryTags.forPay(purchase);
|
||||
@ -296,7 +299,7 @@ export async function getTransactionById(
|
||||
const contractData = download.contractData;
|
||||
const refunds = mergeRefundByExecutionTime(
|
||||
[theRefund],
|
||||
Amounts.getZero(contractData.amount.currency),
|
||||
Amounts.zeroOfAmount(contractData.amount),
|
||||
);
|
||||
|
||||
return buildTransactionForRefund(
|
||||
@ -320,11 +323,13 @@ export async function getTransactionById(
|
||||
} else if (type === TransactionType.PeerPushDebit) {
|
||||
const pursePub = rest[0];
|
||||
return await ws.db
|
||||
.mktx((x) => [x.peerPushPaymentInitiations])
|
||||
.mktx((x) => [x.peerPushPaymentInitiations, x.contractTerms])
|
||||
.runReadWrite(async (tx) => {
|
||||
const debit = await tx.peerPushPaymentInitiations.get(pursePub);
|
||||
if (!debit) throw Error("not found");
|
||||
return buildTransactionForPushPaymentDebit(debit);
|
||||
const ct = await tx.contractTerms.get(debit.contractTermsHash);
|
||||
checkDbInvariant(!!ct);
|
||||
return buildTransactionForPushPaymentDebit(debit, ct.contractTermsRaw);
|
||||
});
|
||||
} else {
|
||||
const unknownTxType: never = type;
|
||||
@ -334,6 +339,7 @@ export async function getTransactionById(
|
||||
|
||||
function buildTransactionForPushPaymentDebit(
|
||||
pi: PeerPushPaymentInitiationRecord,
|
||||
contractTerms: PeerContractTerms,
|
||||
ort?: OperationRetryRecord,
|
||||
): Transaction {
|
||||
return {
|
||||
@ -342,11 +348,11 @@ function buildTransactionForPushPaymentDebit(
|
||||
amountRaw: pi.amount,
|
||||
exchangeBaseUrl: pi.exchangeBaseUrl,
|
||||
info: {
|
||||
expiration: pi.contractTerms.purse_expiration,
|
||||
summary: pi.contractTerms.summary,
|
||||
expiration: contractTerms.purse_expiration,
|
||||
summary: contractTerms.summary,
|
||||
},
|
||||
frozen: false,
|
||||
pending: !pi.purseCreated,
|
||||
pending: pi.status != PeerPushPaymentInitiationStatus.PurseCreated,
|
||||
timestamp: pi.timestampCreated,
|
||||
talerUri: constructPayPushUri({
|
||||
exchangeBaseUrl: pi.exchangeBaseUrl,
|
||||
@ -586,7 +592,7 @@ function mergeRefundByExecutionTime(
|
||||
prev.set(key, {
|
||||
executionTime: refund.executionTime,
|
||||
amountAppliedEffective: effective,
|
||||
amountAppliedRaw: raw,
|
||||
amountAppliedRaw: Amounts.parseOrThrow(raw),
|
||||
firstTimestamp: refund.obtainedTime,
|
||||
});
|
||||
} else {
|
||||
@ -659,7 +665,7 @@ async function buildTransactionForPurchase(
|
||||
refundsInfo: MergedRefundInfo[],
|
||||
ort?: OperationRetryRecord,
|
||||
): Promise<Transaction> {
|
||||
const zero = Amounts.getZero(contractData.amount.currency);
|
||||
const zero = Amounts.zeroOfAmount(contractData.amount);
|
||||
|
||||
const info: OrderShortInfo = {
|
||||
merchant: contractData.merchant,
|
||||
@ -769,7 +775,11 @@ export async function getTransactions(
|
||||
if (shouldSkipSearch(transactionsRequest, [])) {
|
||||
return;
|
||||
}
|
||||
transactions.push(buildTransactionForPushPaymentDebit(pi));
|
||||
const ct = await tx.contractTerms.get(pi.contractTermsHash);
|
||||
checkDbInvariant(!!ct);
|
||||
transactions.push(
|
||||
buildTransactionForPushPaymentDebit(pi, ct.contractTermsRaw),
|
||||
);
|
||||
});
|
||||
|
||||
tx.peerPullPaymentIncoming.iter().forEachAsync(async (pi) => {
|
||||
@ -780,7 +790,10 @@ export async function getTransactions(
|
||||
if (shouldSkipSearch(transactionsRequest, [])) {
|
||||
return;
|
||||
}
|
||||
if (!pi.accepted) {
|
||||
if (
|
||||
pi.status !== PeerPullPaymentIncomingStatus.Accepted &&
|
||||
pi.status !== PeerPullPaymentIncomingStatus.Paid
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -791,7 +804,7 @@ export async function getTransactions(
|
||||
if (
|
||||
shouldSkipCurrency(
|
||||
transactionsRequest,
|
||||
wsr.rawWithdrawalAmount.currency,
|
||||
Amounts.currencyOf(wsr.rawWithdrawalAmount),
|
||||
)
|
||||
) {
|
||||
return;
|
||||
@ -899,7 +912,7 @@ export async function getTransactions(
|
||||
|
||||
const refunds = mergeRefundByExecutionTime(
|
||||
cleanRefunds,
|
||||
Amounts.getZero(download.currency),
|
||||
Amounts.zeroOfCurrency(download.currency),
|
||||
);
|
||||
|
||||
refunds.forEach(async (refundInfo) => {
|
||||
@ -929,7 +942,7 @@ export async function getTransactions(
|
||||
if (
|
||||
shouldSkipCurrency(
|
||||
transactionsRequest,
|
||||
tipRecord.tipAmountRaw.currency,
|
||||
Amounts.parseOrThrow(tipRecord.tipAmountRaw).currency,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
|
@ -39,26 +39,26 @@ test("withdrawal selection bug repro", (t) => {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net/",
|
||||
exchangeMasterPub: "",
|
||||
fees: {
|
||||
feeDeposit: {
|
||||
feeDeposit: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefresh: {
|
||||
}),
|
||||
feeRefresh: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefund: {
|
||||
}),
|
||||
feeRefund: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeWithdraw: {
|
||||
}),
|
||||
feeWithdraw: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
isOffered: true,
|
||||
isRevoked: false,
|
||||
@ -95,26 +95,26 @@ test("withdrawal selection bug repro", (t) => {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net/",
|
||||
exchangeMasterPub: "",
|
||||
fees: {
|
||||
feeDeposit: {
|
||||
feeDeposit: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefresh: {
|
||||
}),
|
||||
feeRefresh: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefund: {
|
||||
}),
|
||||
feeRefund: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeWithdraw: {
|
||||
}),
|
||||
feeWithdraw: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
isOffered: true,
|
||||
isRevoked: false,
|
||||
@ -150,26 +150,26 @@ test("withdrawal selection bug repro", (t) => {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net/",
|
||||
exchangeMasterPub: "",
|
||||
fees: {
|
||||
feeDeposit: {
|
||||
feeDeposit: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefresh: {
|
||||
}),
|
||||
feeRefresh: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefund: {
|
||||
}),
|
||||
feeRefund: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeWithdraw: {
|
||||
}),
|
||||
feeWithdraw: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
isOffered: true,
|
||||
isRevoked: false,
|
||||
@ -206,26 +206,26 @@ test("withdrawal selection bug repro", (t) => {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net/",
|
||||
exchangeMasterPub: "",
|
||||
fees: {
|
||||
feeDeposit: {
|
||||
feeDeposit: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefresh: {
|
||||
}),
|
||||
feeRefresh: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefund: {
|
||||
}),
|
||||
feeRefund: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeWithdraw: {
|
||||
}),
|
||||
feeWithdraw: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
isOffered: true,
|
||||
isRevoked: false,
|
||||
@ -261,26 +261,26 @@ test("withdrawal selection bug repro", (t) => {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net/",
|
||||
exchangeMasterPub: "",
|
||||
fees: {
|
||||
feeDeposit: {
|
||||
feeDeposit: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefresh: {
|
||||
}),
|
||||
feeRefresh: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefund: {
|
||||
}),
|
||||
feeRefund: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeWithdraw: {
|
||||
}),
|
||||
feeWithdraw: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
isOffered: true,
|
||||
isRevoked: false,
|
||||
@ -316,26 +316,26 @@ test("withdrawal selection bug repro", (t) => {
|
||||
exchangeBaseUrl: "https://exchange.demo.taler.net/",
|
||||
exchangeMasterPub: "",
|
||||
fees: {
|
||||
feeDeposit: {
|
||||
feeDeposit: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefresh: {
|
||||
}),
|
||||
feeRefresh: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeRefund: {
|
||||
}),
|
||||
feeRefund: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
feeWithdraw: {
|
||||
}),
|
||||
feeWithdraw: Amounts.stringify({
|
||||
currency: "KUDOS",
|
||||
fraction: 1000000,
|
||||
value: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
isOffered: true,
|
||||
isRevoked: false,
|
||||
|
@ -167,8 +167,8 @@ export function selectWithdrawalDenominations(
|
||||
denomPubHash: string;
|
||||
}[] = [];
|
||||
|
||||
let totalCoinValue = Amounts.getZero(amountAvailable.currency);
|
||||
let totalWithdrawCost = Amounts.getZero(amountAvailable.currency);
|
||||
let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||
let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||
|
||||
denoms = denoms.filter(isWithdrawableDenom);
|
||||
denoms.sort((d1, d2) =>
|
||||
@ -223,8 +223,8 @@ export function selectWithdrawalDenominations(
|
||||
|
||||
return {
|
||||
selectedDenoms,
|
||||
totalCoinValue,
|
||||
totalWithdrawCost,
|
||||
totalCoinValue: Amounts.stringify(totalCoinValue),
|
||||
totalWithdrawCost: Amounts.stringify(totalCoinValue),
|
||||
};
|
||||
}
|
||||
|
||||
@ -238,8 +238,8 @@ export function selectForcedWithdrawalDenominations(
|
||||
denomPubHash: string;
|
||||
}[] = [];
|
||||
|
||||
let totalCoinValue = Amounts.getZero(amountAvailable.currency);
|
||||
let totalWithdrawCost = Amounts.getZero(amountAvailable.currency);
|
||||
let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||
let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
|
||||
|
||||
denoms = denoms.filter(isWithdrawableDenom);
|
||||
denoms.sort((d1, d2) =>
|
||||
@ -279,8 +279,8 @@ export function selectForcedWithdrawalDenominations(
|
||||
|
||||
return {
|
||||
selectedDenoms,
|
||||
totalCoinValue,
|
||||
totalWithdrawCost,
|
||||
totalCoinValue: Amounts.stringify(totalCoinValue),
|
||||
totalWithdrawCost: Amounts.stringify(totalWithdrawCost),
|
||||
};
|
||||
}
|
||||
|
||||
@ -416,10 +416,10 @@ async function processPlanchetGenerate(
|
||||
checkDbInvariant(!!denom);
|
||||
const r = await ws.cryptoApi.createPlanchet({
|
||||
denomPub: denom.denomPub,
|
||||
feeWithdraw: denom.feeWithdraw,
|
||||
feeWithdraw: Amounts.parseOrThrow(denom.feeWithdraw),
|
||||
reservePriv: withdrawalGroup.reservePriv,
|
||||
reservePub: withdrawalGroup.reservePub,
|
||||
value: denom.value,
|
||||
value: Amounts.parseOrThrow(denom.value),
|
||||
coinIndex: coinIdx,
|
||||
secretSeed: withdrawalGroup.secretSeed,
|
||||
restrictAge: withdrawalGroup.restrictAge,
|
||||
@ -950,7 +950,7 @@ async function queryReserve(
|
||||
return;
|
||||
}
|
||||
wg.status = WithdrawalGroupStatus.Ready;
|
||||
wg.reserveBalanceAmount = Amounts.parse(result.response.balance);
|
||||
wg.reserveBalanceAmount = Amounts.stringify(result.response.balance);
|
||||
await tx.withdrawalGroups.put(wg);
|
||||
});
|
||||
|
||||
@ -1427,7 +1427,7 @@ export async function getFundingPaytoUrisTx(
|
||||
export function augmentPaytoUrisForWithdrawal(
|
||||
plainPaytoUris: string[],
|
||||
reservePub: string,
|
||||
instructedAmount: AmountJson,
|
||||
instructedAmount: AmountLike,
|
||||
): string[] {
|
||||
return plainPaytoUris.map((x) =>
|
||||
addPaytoQueryParams(x, {
|
||||
@ -1732,7 +1732,7 @@ export async function internalCreateWithdrawalGroup(
|
||||
denomSelUid,
|
||||
denomsSel: initialDenomSel,
|
||||
exchangeBaseUrl: canonExchange,
|
||||
instructedAmount: amount,
|
||||
instructedAmount: Amounts.stringify(amount),
|
||||
timestampStart: now,
|
||||
rawWithdrawalAmount: initialDenomSel.totalWithdrawCost,
|
||||
effectiveWithdrawalAmount: initialDenomSel.totalCoinValue,
|
||||
|
@ -139,7 +139,7 @@ export function tallyFees(
|
||||
|
||||
if (!tally.wireFeeCoveredForExchange.has(exchangeBaseUrl)) {
|
||||
const wf =
|
||||
wireFeesPerExchange[exchangeBaseUrl] ?? Amounts.getZero(currency);
|
||||
wireFeesPerExchange[exchangeBaseUrl] ?? Amounts.zeroOfCurrency(currency);
|
||||
const wfForgiven = Amounts.min(amountWireFeeLimitRemaining, wf);
|
||||
amountWireFeeLimitRemaining = Amounts.sub(
|
||||
amountWireFeeLimitRemaining,
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
FeeDescriptionPair,
|
||||
Amounts,
|
||||
DenominationInfo,
|
||||
AmountString,
|
||||
} from "@gnu-taler/taler-util";
|
||||
// import { expect } from "chai";
|
||||
import {
|
||||
@ -37,8 +38,8 @@ import test, { ExecutionContext } from "ava";
|
||||
/**
|
||||
* Create some constants to be used as reference in the tests
|
||||
*/
|
||||
const VALUES = Array.from({ length: 10 }).map((undef, t) =>
|
||||
Amounts.parseOrThrow(`USD:${t}`),
|
||||
const VALUES: AmountString[] = Array.from({ length: 10 }).map(
|
||||
(undef, t) => `USD:${t}`,
|
||||
);
|
||||
const TIMESTAMPS = Array.from({ length: 20 }).map((undef, t_s) => ({ t_s }));
|
||||
const ABS_TIME = TIMESTAMPS.map((m) => AbsoluteTime.fromTimestamp(m));
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
AbsoluteTime,
|
||||
AmountJson,
|
||||
Amounts,
|
||||
AmountString,
|
||||
DenominationInfo,
|
||||
FeeDescription,
|
||||
FeeDescriptionPair,
|
||||
@ -51,7 +52,7 @@ export function selectBestForOverlappingDenominations<
|
||||
return minDeposit;
|
||||
}
|
||||
|
||||
export function selectMinimumFee<T extends { fee: AmountJson }>(
|
||||
export function selectMinimumFee<T extends { fee: AmountString }>(
|
||||
list: T[],
|
||||
): T | undefined {
|
||||
let minFee: T | undefined = undefined;
|
||||
@ -285,7 +286,7 @@ export function createTimeline<Type extends object>(
|
||||
idProp: PropsWithReturnType<Type, string>,
|
||||
periodStartProp: PropsWithReturnType<Type, TalerProtocolTimestamp>,
|
||||
periodEndProp: PropsWithReturnType<Type, TalerProtocolTimestamp>,
|
||||
feeProp: PropsWithReturnType<Type, AmountJson>,
|
||||
feeProp: PropsWithReturnType<Type, AmountString>,
|
||||
groupProp: PropsWithReturnType<Type, string> | undefined,
|
||||
selectBestForOverlapping: (l: Type[]) => Type | undefined,
|
||||
): FeeDescription[] {
|
||||
@ -312,7 +313,7 @@ export function createTimeline<Type extends object>(
|
||||
}
|
||||
ps.push({
|
||||
type: "start",
|
||||
fee,
|
||||
fee: Amounts.stringify(fee),
|
||||
group,
|
||||
id,
|
||||
moment: AbsoluteTime.fromTimestamp(stampStart),
|
||||
@ -320,7 +321,7 @@ export function createTimeline<Type extends object>(
|
||||
});
|
||||
ps.push({
|
||||
type: "end",
|
||||
fee,
|
||||
fee: Amounts.stringify(fee),
|
||||
group,
|
||||
id,
|
||||
moment: AbsoluteTime.fromTimestamp(stampEnd),
|
||||
@ -416,7 +417,7 @@ export function createTimeline<Type extends object>(
|
||||
group: cursor.group,
|
||||
from: cursor.moment,
|
||||
until: AbsoluteTime.never(), //not yet known
|
||||
fee: currentFee,
|
||||
fee: Amounts.stringify(currentFee),
|
||||
});
|
||||
} else {
|
||||
prev.until = cursor.moment;
|
||||
|
@ -771,7 +771,7 @@ async function getExchangeDetailedInfo(
|
||||
const feesByGroup = [
|
||||
...infoForType.map((w) => ({
|
||||
...w,
|
||||
fee: w.closingFee,
|
||||
fee: Amounts.stringify(w.closingFee),
|
||||
group: "closing",
|
||||
})),
|
||||
...infoForType.map((w) => ({ ...w, fee: w.wireFee, group: "wire" })),
|
||||
|
@ -33,11 +33,7 @@ export default {
|
||||
};
|
||||
|
||||
const cd: WalletContractData = {
|
||||
amount: {
|
||||
currency: "ARS",
|
||||
fraction: 0,
|
||||
value: 2,
|
||||
},
|
||||
amount: "ARS:2",
|
||||
contractTermsHash:
|
||||
"92X0KSJPZ8XS2XECCGFWTCGW8XMFCXTT2S6WHZDP6H9Y3TSKMTHY94WXEWDERTNN5XWCYGW4VN5CF2D4846HXTW7P06J4CZMHCWKC9G",
|
||||
fulfillmentUrl: "",
|
||||
@ -47,11 +43,7 @@ const cd: WalletContractData = {
|
||||
"0YA1WETV15R6K8QKS79QA3QMT16010F42Q49VSKYQ71HVQKAG0A4ZJCA4YTKHE9EA5SP156TJSKZEJJJ87305N6PS80PC48RNKYZE08",
|
||||
orderId: "2022.220-0281XKKB8W7YE",
|
||||
summary: "w",
|
||||
maxWireFee: {
|
||||
currency: "ARS",
|
||||
fraction: 0,
|
||||
value: 1,
|
||||
},
|
||||
maxWireFee: "ARS:1",
|
||||
payDeadline: {
|
||||
t_s: 1660002673,
|
||||
},
|
||||
@ -77,11 +69,7 @@ const cd: WalletContractData = {
|
||||
wireMethod: "x-taler-bank",
|
||||
wireInfoHash:
|
||||
"QDT28374ZHYJ59WQFZ3TW1D5WKJVDYHQT86VHED3TNMB15ANJSKXDYPPNX01348KDYCX6T4WXA5A8FJJ8YWNEB1JW726C1JPKHM89DR",
|
||||
maxDepositFee: {
|
||||
currency: "ARS",
|
||||
fraction: 0,
|
||||
value: 1,
|
||||
},
|
||||
maxDepositFee: "ARS:1",
|
||||
merchant: {
|
||||
name: "Default",
|
||||
address: {
|
||||
|
@ -99,7 +99,7 @@ export function useComponentState(
|
||||
const balance =
|
||||
bs.length > 0
|
||||
? Amounts.parseOrThrow(bs[0].available)
|
||||
: Amounts.getZero(currency);
|
||||
: Amounts.zeroOfCurrency(currency);
|
||||
|
||||
if (Amounts.isZero(balance)) {
|
||||
return {
|
||||
@ -157,12 +157,12 @@ export function useComponentState(
|
||||
const totalFee =
|
||||
fee !== undefined
|
||||
? Amounts.sum([fee.wire, fee.coin, fee.refresh]).amount
|
||||
: Amounts.getZero(currency);
|
||||
: Amounts.zeroOfCurrency(currency);
|
||||
|
||||
const totalToDeposit =
|
||||
parsedAmount && fee !== undefined
|
||||
? Amounts.sub(parsedAmount, totalFee).amount
|
||||
: Amounts.getZero(currency);
|
||||
: Amounts.zeroOfCurrency(currency);
|
||||
|
||||
const isDirty = amount !== initialValue;
|
||||
const amountError = !isDirty
|
||||
|
@ -76,7 +76,7 @@ export const WithNoAccountForIBAN = createExample(ReadyView, {
|
||||
return;
|
||||
},
|
||||
},
|
||||
totalFee: Amounts.getZero("USD"),
|
||||
totalFee: Amounts.zeroOfCurrency("USD"),
|
||||
totalToDeposit: Amounts.parseOrThrow("USD:10"),
|
||||
// onCalculateFee: alwaysReturnFeeToOne,
|
||||
});
|
||||
@ -111,7 +111,7 @@ export const WithIBANAccountTypeSelected = createExample(ReadyView, {
|
||||
return;
|
||||
},
|
||||
},
|
||||
totalFee: Amounts.getZero("USD"),
|
||||
totalFee: Amounts.zeroOfCurrency("USD"),
|
||||
totalToDeposit: Amounts.parseOrThrow("USD:10"),
|
||||
// onCalculateFee: alwaysReturnFeeToOne,
|
||||
});
|
||||
@ -146,7 +146,7 @@ export const NewBitcoinAccountTypeSelected = createExample(ReadyView, {
|
||||
return;
|
||||
},
|
||||
},
|
||||
totalFee: Amounts.getZero("USD"),
|
||||
totalFee: Amounts.zeroOfCurrency("USD"),
|
||||
totalToDeposit: Amounts.parseOrThrow("USD:10"),
|
||||
// onCalculateFee: alwaysReturnFeeToOne,
|
||||
});
|
||||
|
@ -1132,7 +1132,7 @@ export function PurchaseDetails({
|
||||
const partialFee = Amounts.sub(price.effective, price.raw).amount;
|
||||
|
||||
const refundFee = !refund
|
||||
? Amounts.getZero(price.effective.currency)
|
||||
? Amounts.zeroOfCurrency(price.effective.currency)
|
||||
: Amounts.sub(refund.raw, refund.effective).amount;
|
||||
|
||||
const fee = Amounts.sum([partialFee, refundFee]).amount;
|
||||
|
Loading…
Reference in New Issue
Block a user