@ledgerhq/coin-canton
Version:
54 lines (42 loc) • 1.8 kB
text/typescript
import type { CryptoCurrency } from "@ledgerhq/ledger-wallet-framework/types";
import coinConfig from "../../config";
const magnitude: bigint = 10n ** 38n;
type FeeTier = {
limit: bigint | null; // `null` means no upper limit
rateNumerator: bigint; // e.g., 1 for 1%
rateDenominator: bigint; // e.g., 100 for 1%
};
const cantonCoinTiers: FeeTier[] = [
// 100n because of rateDenominator for percentages
{ limit: 100n * 100n * magnitude, rateNumerator: 1n, rateDenominator: 100n }, // 1.0%
{ limit: 1000n * 100n * magnitude, rateNumerator: 1n, rateDenominator: 1000n }, // 0.1%
{ limit: 1_000_000n * 100n * magnitude, rateNumerator: 1n, rateDenominator: 10_000n }, // 0.01%
{ limit: null, rateNumerator: 1n, rateDenominator: 100_000n }, // 0.001%
];
const feeValue = (currency: CryptoCurrency) => coinConfig.getCoinConfig(currency.id).fee;
export async function estimateFees(currency: CryptoCurrency, amount: bigint): Promise<bigint> {
const forcedValue = feeValue(currency);
if (forcedValue !== undefined) {
return Promise.resolve(BigInt(forcedValue) * magnitude);
} else {
return Promise.resolve(
// Add 1 CC as base fee
1n * magnitude + BigInt(calculateFeeWithTiers(amount, cantonCoinTiers)),
);
}
}
function calculateFeeWithTiers(value: bigint, tiers: FeeTier[]): bigint {
let remaining = value;
let lastLimit = 0n;
let fee = 0n;
for (const tier of tiers) {
if (remaining <= 0n) break;
const currentLimit = tier.limit ?? BigInt(2 ** 62); // highest bigint value
const tierCap = currentLimit - lastLimit;
const applicable = remaining < tierCap ? remaining : tierCap;
fee += (applicable * tier.rateNumerator) / tier.rateDenominator;
remaining -= applicable;
lastLimit = currentLimit;
}
return fee;
}