@@ -42,6 +42,7 @@ import {
4242} from './utils.js' ;
4343import NetworkProvider from './network/NetworkProvider.js' ;
4444import SignatureTemplate from './SignatureTemplate.js' ;
45+ import { P2PKH_INPUT_SIZE } from './constants.js' ;
4546
4647const bip68 = await import ( 'bip68' ) ;
4748
@@ -398,7 +399,7 @@ export class Transaction {
398399 ) ;
399400
400401 // Add one extra byte per input to over-estimate tx-in count
401- const inputSize = getInputSize ( placeholderScript ) + 1 ;
402+ const contractInputSize = getInputSize ( placeholderScript ) + 1 ;
402403
403404 // Note that we use the addPrecision function to add "decimal points" to BigInt numbers
404405
@@ -410,7 +411,14 @@ export class Transaction {
410411 let satsAvailable = 0n ;
411412 if ( this . inputs . length > 0 ) {
412413 // If inputs are already defined, the user provided the UTXOs and we perform no further UTXO selection
413- if ( ! this . hardcodedFee ) fee += addPrecision ( this . inputs . length * inputSize * this . feePerByte ) ;
414+ if ( ! this . hardcodedFee ) {
415+ const totalInputSize = this . inputs . reduce (
416+ ( acc , input ) => acc + ( isSignableUtxo ( input ) ? P2PKH_INPUT_SIZE : contractInputSize ) ,
417+ 0 ,
418+ ) ;
419+ fee += addPrecision ( totalInputSize * this . feePerByte ) ;
420+ }
421+
414422 satsAvailable = addPrecision ( this . inputs . reduce ( ( acc , input ) => acc + input . satoshis , 0n ) ) ;
415423 } else {
416424 // If inputs are not defined yet, we retrieve the contract's UTXOs and perform selection
@@ -424,14 +432,14 @@ export class Transaction {
424432 for ( const utxo of automaticTokenInputs ) {
425433 this . inputs . push ( utxo ) ;
426434 satsAvailable += addPrecision ( utxo . satoshis ) ;
427- if ( ! this . hardcodedFee ) fee += addPrecision ( inputSize * this . feePerByte ) ;
435+ if ( ! this . hardcodedFee ) fee += addPrecision ( contractInputSize * this . feePerByte ) ;
428436 }
429437
430438 for ( const utxo of bchUtxos ) {
431439 if ( satsAvailable > amount + fee ) break ;
432440 this . inputs . push ( utxo ) ;
433441 satsAvailable += addPrecision ( utxo . satoshis ) ;
434- if ( ! this . hardcodedFee ) fee += addPrecision ( inputSize * this . feePerByte ) ;
442+ if ( ! this . hardcodedFee ) fee += addPrecision ( contractInputSize * this . feePerByte ) ;
435443 }
436444 }
437445
@@ -480,12 +488,9 @@ const calculateTotalTokenAmount = (outputs: Array<Output | Utxo>, tokenCategory:
480488
481489const selectTokenUtxos = ( utxos : Utxo [ ] , amountNeeded : bigint , tokenCategory : string ) : Utxo [ ] => {
482490 const genesisUtxo = getTokenGenesisUtxo ( utxos , tokenCategory ) ;
491+ if ( genesisUtxo ) return [ genesisUtxo ] ;
483492
484- if ( genesisUtxo ) {
485- return [ genesisUtxo ] ;
486- }
487-
488- const tokenUtxos = utxos . filter ( ( utxo ) => utxo . token ?. category === tokenCategory ) ;
493+ const tokenUtxos = utxos . filter ( ( utxo ) => utxo . token ?. category === tokenCategory && utxo . token ?. amount > 0n ) ;
489494
490495 // We sort the UTXOs mainly so there is consistent behaviour between network providers
491496 // even if they report UTXOs in a different order
@@ -496,9 +501,9 @@ const selectTokenUtxos = (utxos: Utxo[], amountNeeded: bigint, tokenCategory: st
496501
497502 // Add token UTXOs until we have enough to cover the amount needed (no fee calculation because it's a token)
498503 for ( const utxo of tokenUtxos ) {
504+ if ( amountAvailable >= amountNeeded ) break ;
499505 selectedUtxos . push ( utxo ) ;
500506 amountAvailable += utxo . token ! . amount ;
501- if ( amountAvailable >= amountNeeded ) break ;
502507 }
503508
504509 if ( amountAvailable < amountNeeded ) {
0 commit comments