diff --git a/modules/sdk-coin-flrp/src/lib/ImportInCTxBuilder.ts b/modules/sdk-coin-flrp/src/lib/ImportInCTxBuilder.ts index 800ebd4758..368ed47117 100644 --- a/modules/sdk-coin-flrp/src/lib/ImportInCTxBuilder.ts +++ b/modules/sdk-coin-flrp/src/lib/ImportInCTxBuilder.ts @@ -126,8 +126,6 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder { protected buildFlareTransaction(): void { // if tx has credentials or was already recovered from raw, tx shouldn't change if (this.transaction.hasCredentials) return; - // If fee is already calculated (from initBuilder), the transaction is already built - if (this.transaction._fee.fee) return; if (this.transaction._to.length !== 1) { throw new Error('to is required'); } diff --git a/modules/sdk-coin-flrp/src/lib/atomicTransactionBuilder.ts b/modules/sdk-coin-flrp/src/lib/atomicTransactionBuilder.ts index 8f69a14058..3e0d9ef25a 100644 --- a/modules/sdk-coin-flrp/src/lib/atomicTransactionBuilder.ts +++ b/modules/sdk-coin-flrp/src/lib/atomicTransactionBuilder.ts @@ -20,6 +20,7 @@ export abstract class AtomicTransactionBuilder extends TransactionBuilder { constructor(_coinConfig: Readonly) { super(_coinConfig); this.transaction = new Transaction(_coinConfig); + this.transaction._fee.fee = this.fixedFee; } /** diff --git a/modules/sdk-coin-flrp/test/unit/lib/exportInPTxBuilder.ts b/modules/sdk-coin-flrp/test/unit/lib/exportInPTxBuilder.ts index f1156b0f86..3d85d64f72 100644 --- a/modules/sdk-coin-flrp/test/unit/lib/exportInPTxBuilder.ts +++ b/modules/sdk-coin-flrp/test/unit/lib/exportInPTxBuilder.ts @@ -5,12 +5,54 @@ import { EXPORT_IN_P_TWO_UTXOS as twoUtxoTestData, EXPORT_IN_P_NO_CHANGE as noChangeTestData, } from '../../resources/transactionData/exportInP'; -import { TransactionBuilderFactory, DecodedUtxoObj } from '../../../src/lib'; -import { coins } from '@bitgo/statics'; +import { TransactionBuilderFactory, DecodedUtxoObj, Transaction } from '../../../src/lib'; +import { coins, FlareNetwork } from '@bitgo/statics'; import signFlowTest from './signFlowTestSuit'; describe('Flrp Export In P Tx Builder', () => { - const factory = new TransactionBuilderFactory(coins.get('tflrp')); + const coinConfig = coins.get('tflrp'); + const factory = new TransactionBuilderFactory(coinConfig); + + describe('default fee', () => { + const FIXED_FEE = (coinConfig.network as FlareNetwork).txFee; + + it('should set fixedFee (1000000) by default in constructor', () => { + const txBuilder = factory.getExportInPBuilder(); + // The fixedFee should be set from network.txFee = '1000000' + const transaction = (txBuilder as any).transaction; + transaction._fee.fee.should.equal(FIXED_FEE); + }); + + it('should use default fixedFee when fee is not explicitly set', async () => { + // Create a UTXO with enough balance to cover amount + default fee + const amount = '500000000'; // 0.5 FLR + const utxoAmount = (BigInt(amount) + BigInt(FIXED_FEE)).toString(); // amount + fixedFee + + const txBuilder = factory + .getExportInPBuilder() + .threshold(testData.threshold) + .locktime(testData.locktime) + .fromPubKey(testData.pAddresses) + .amount(amount) + .externalChainId(testData.sourceChainId) + // NOTE: .fee() is NOT called - should use default fixedFee + .utxos([ + { + outputID: 0, + amount: utxoAmount, + txid: '21hcD64N9QzdayPjhKLsBQBa8FyXcsJGNStBZ3vCRdCCEsLru2', + outputidx: '0', + addresses: testData.outputs[0].addresses, + threshold: testData.threshold, + }, + ]); + + const tx = (await txBuilder.build()) as Transaction; + + // Verify the fee in the built transaction equals the fixedFee + tx.fee.fee.should.equal(FIXED_FEE); + }); + }); describe('validate txBuilder fields', () => { const txBuilder = factory.getExportInPBuilder(); diff --git a/modules/sdk-coin-flrp/test/unit/lib/importInPTxBuilder.ts b/modules/sdk-coin-flrp/test/unit/lib/importInPTxBuilder.ts index 23400364d0..0d5410666c 100644 --- a/modules/sdk-coin-flrp/test/unit/lib/importInPTxBuilder.ts +++ b/modules/sdk-coin-flrp/test/unit/lib/importInPTxBuilder.ts @@ -1,12 +1,53 @@ import assert from 'assert'; import 'should'; import { IMPORT_IN_P as testData } from '../../resources/transactionData/importInP'; -import { TransactionBuilderFactory, DecodedUtxoObj } from '../../../src/lib'; -import { coins } from '@bitgo/statics'; +import { TransactionBuilderFactory, DecodedUtxoObj, Transaction } from '../../../src/lib'; +import { coins, FlareNetwork } from '@bitgo/statics'; import signFlowTest from './signFlowTestSuit'; describe('Flrp Import In P Tx Builder', () => { - const factory = new TransactionBuilderFactory(coins.get('tflrp')); + const coinConfig = coins.get('tflrp'); + const factory = new TransactionBuilderFactory(coinConfig); + + describe('default fee', () => { + const FIXED_FEE = (coinConfig.network as FlareNetwork).txFee; + + it('should set fixedFee (1000000) by default in constructor', () => { + const txBuilder = factory.getImportInPBuilder(); + // The fixedFee should be set from network.txFee = '1000000' + const transaction = (txBuilder as any).transaction; + transaction._fee.fee.should.equal(FIXED_FEE); + }); + + it('should use default fixedFee when fee is not explicitly set', async () => { + // Create a UTXO with enough balance to cover the default fee + const utxoAmount = '50000000'; // 0.05 FLR - enough to cover fee and have output + + const txBuilder = factory + .getImportInPBuilder() + .threshold(testData.threshold) + .locktime(testData.locktime) + .fromPubKey(testData.pAddresses) + .externalChainId(testData.sourceChainId) + // NOTE: .fee() is NOT called - should use default fixedFee + .utxos([ + { + outputID: 0, + amount: utxoAmount, + txid: testData.outputs[0].txid, + outputidx: '0', + addresses: testData.outputs[0].addresses, + threshold: testData.threshold, + }, + ]); + + const tx = (await txBuilder.build()) as Transaction; + + // Verify the fee in the built transaction equals the fixedFee + tx.fee.fee.should.equal(FIXED_FEE); + }); + }); + describe('validate txBuilder fields', () => { const txBuilder = factory.getImportInPBuilder();