Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,35 @@ describe('BitcoinFeeService', () => {
});
});

// --- getSendFeeRate() Tests --- //

describe('getSendFeeRate()', () => {
const feeConfig = { allowUnconfirmedUtxos: true, cpfpFeeMultiplier: 2.0, defaultFeeMultiplier: 1.5 };

beforeEach(() => {
Object.defineProperty(service, 'feeConfig', { get: () => feeConfig });
});

it('should round fee rate to 3 decimal places (Bitcoin Core send RPC limit)', async () => {
// estimatesmartfee returning 1.935 sat/vB multiplied by cpfpFeeMultiplier=2.0
// produces 3.8699999999999997 in JS due to floating-point arithmetic; Bitcoin Core
// rejects fee_rate with more than 3 decimal places via "Invalid amount".
mockClient.estimateSmartFee.mockResolvedValueOnce(1.935);

const result = await service.getSendFeeRate();

expect(result).toBe(3.87);
});

it('should preserve integer fee rates without artifacts', async () => {
mockClient.estimateSmartFee.mockResolvedValueOnce(10);

const result = await service.getSendFeeRate();

expect(result).toBe(20); // 10 * cpfpFeeMultiplier (2.0)
});
});

// --- getTxFeeRate() Tests --- //

describe('getTxFeeRate()', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DfxLogger } from 'src/shared/services/dfx-logger';
import { AsyncCache, CacheItemResetPeriod } from 'src/shared/utils/async-cache';
import { Util } from 'src/shared/utils/util';
import { NodeClient } from '../node/node-client';

export type TxFeeRateStatus = 'unconfirmed' | 'confirmed' | 'not_found' | 'error';
Expand Down Expand Up @@ -89,6 +90,8 @@ export abstract class BitcoinBasedFeeService {
const { allowUnconfirmedUtxos, cpfpFeeMultiplier, defaultFeeMultiplier } = this.feeConfig;
const multiplier = allowUnconfirmedUtxos ? cpfpFeeMultiplier : defaultFeeMultiplier;

return baseRate * multiplier;
// Bitcoin Core's send RPC parses fee_rate with decimals=3; un-rounded floating-point
// products (e.g. 1.935 * 2 = 3.8699999999999997) are rejected with "Invalid amount".
return Util.round(baseRate * multiplier, 3);
}
}
Loading