@@ -113,6 +113,7 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
113113 // When credentials were extracted, use them directly to preserve existing signatures
114114 // Otherwise, create empty credentials with dynamic ordering based on addressesIndex
115115 // Match avaxp behavior: order depends on UTXO address positions
116+ // Use centralized method for credential creation
116117 const txCredentials =
117118 credentials . length > 0
118119 ? credentials
@@ -123,39 +124,11 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
123124 // Get UTXO for this input to determine addressesIndex
124125 const utxo = this . transaction . _utxos [ inputIdx ] ;
125126
126- // either user (0) or recovery (2)
127- const firstIndex = this . recoverSigner ? 2 : 0 ;
128- const bitgoIndex = 1 ;
129-
130- // If UTXO has addresses, compute dynamic ordering
131- if ( utxo && utxo . addresses && utxo . addresses . length > 0 ) {
132- const utxoAddresses = utxo . addresses . map ( ( a ) => utils . parseAddress ( a ) ) ;
133- const addressesIndex = this . transaction . _fromAddresses . map ( ( a ) =>
134- utxoAddresses . findIndex ( ( u ) => Buffer . compare ( Buffer . from ( u ) , Buffer . from ( a ) ) === 0 )
135- ) ;
136-
137- // Dynamic ordering based on addressesIndex
138- let sigSlots : ReturnType < typeof utils . createNewSig > [ ] ;
139- if ( addressesIndex [ bitgoIndex ] < addressesIndex [ firstIndex ] ) {
140- // Bitgo comes first: [zeros, userAddress]
141- sigSlots = [
142- utils . createNewSig ( '' ) ,
143- utils . createEmptySigWithAddress (
144- Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' )
145- ) ,
146- ] ;
147- } else {
148- // User comes first: [userAddress, zeros]
149- sigSlots = [
150- utils . createEmptySigWithAddress (
151- Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' )
152- ) ,
153- utils . createNewSig ( '' ) ,
154- ] ;
155- }
156- return new Credential ( sigSlots ) ;
127+ // Use centralized method, but handle case where inputThreshold might differ
128+ if ( inputThreshold === this . transaction . _threshold ) {
129+ return this . createCredentialForUtxo ( utxo , this . transaction . _threshold ) ;
157130 } else {
158- // Fallback: use all zeros if no UTXO addresses available
131+ // Fallback: use all zeros if threshold differs (shouldn't happen normally)
159132 const sigSlots : ReturnType < typeof utils . createNewSig > [ ] = [ ] ;
160133 for ( let i = 0 ; i < inputThreshold ; i ++ ) {
161134 sigSlots . push ( utils . createNewSig ( '' ) ) ;
@@ -167,39 +140,10 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
167140 // Create AddressMaps based on signature slot order (matching credential order), not sorted addresses
168141 // This matches the approach used in credentials: addressesIndex determines signature order
169142 // AddressMaps should map addresses to signature slots in the same order as credentials
170- const addressMaps = txCredentials . map ( ( credential , credIdx ) => {
171- const addressMap = new FlareUtils . AddressMap ( ) ;
172- const utxo = this . transaction . _utxos [ credIdx ] ;
173-
174- // If UTXO has addresses, compute addressesIndex to determine signature order
175- if ( utxo && utxo . addresses && utxo . addresses . length > 0 ) {
176- const utxoAddresses = utxo . addresses . map ( ( a ) => utils . parseAddress ( a ) ) ;
177- const addressesIndex = this . transaction . _fromAddresses . map ( ( a ) =>
178- utxoAddresses . findIndex ( ( u ) => Buffer . compare ( Buffer . from ( u ) , Buffer . from ( a ) ) === 0 )
179- ) ;
180-
181- const firstIndex = this . recoverSigner ? 2 : 0 ;
182- const bitgoIndex = 1 ;
183-
184- // Determine signature slot order based on addressesIndex (same logic as credentials)
185- if ( addressesIndex [ bitgoIndex ] < addressesIndex [ firstIndex ] ) {
186- // Bitgo comes first: slot 0 = bitgo, slot 1 = firstIndex
187- addressMap . set ( new Address ( this . transaction . _fromAddresses [ bitgoIndex ] ) , 0 ) ;
188- addressMap . set ( new Address ( this . transaction . _fromAddresses [ firstIndex ] ) , 1 ) ;
189- } else {
190- // User/recovery comes first: slot 0 = firstIndex, slot 1 = bitgo
191- addressMap . set ( new Address ( this . transaction . _fromAddresses [ firstIndex ] ) , 0 ) ;
192- addressMap . set ( new Address ( this . transaction . _fromAddresses [ bitgoIndex ] ) , 1 ) ;
193- }
194- } else {
195- // Fallback: map addresses sequentially if no UTXO addresses available
196- this . transaction . _fromAddresses . slice ( 0 , this . transaction . _threshold ) . forEach ( ( addr , i ) => {
197- addressMap . set ( new Address ( addr ) , i ) ;
198- } ) ;
199- }
200-
201- return addressMap ;
202- } ) ;
143+ // Use centralized method for AddressMap creation
144+ const addressMaps = txCredentials . map ( ( credential , credIdx ) =>
145+ this . createAddressMapForUtxo ( this . transaction . _utxos [ credIdx ] , this . transaction . _threshold )
146+ ) ;
203147
204148 // Always create a new UnsignedTx with properly structured credentials
205149 const unsignedTx = new UnsignedTx ( exportTx , [ ] , new FlareUtils . AddressMaps ( addressMaps ) , txCredentials ) ;
@@ -254,39 +198,10 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
254198 // Create AddressMaps based on signature slot order (matching credential order), not sorted addresses
255199 // This matches the approach used in credentials: addressesIndex determines signature order
256200 // AddressMaps should map addresses to signature slots in the same order as credentials
257- const addressMaps = credentials . map ( ( credential , credIdx ) => {
258- const addressMap = new FlareUtils . AddressMap ( ) ;
259- const utxo = this . transaction . _utxos [ credIdx ] ;
260-
261- // If UTXO has addresses, compute addressesIndex to determine signature order
262- if ( utxo && utxo . addresses && utxo . addresses . length > 0 ) {
263- const utxoAddresses = utxo . addresses . map ( ( a ) => utils . parseAddress ( a ) ) ;
264- const addressesIndex = this . transaction . _fromAddresses . map ( ( a ) =>
265- utxoAddresses . findIndex ( ( u ) => Buffer . compare ( Buffer . from ( u ) , Buffer . from ( a ) ) === 0 )
266- ) ;
267-
268- const firstIndex = this . recoverSigner ? 2 : 0 ;
269- const bitgoIndex = 1 ;
270-
271- // Determine signature slot order based on addressesIndex (same logic as credentials)
272- if ( addressesIndex [ bitgoIndex ] < addressesIndex [ firstIndex ] ) {
273- // Bitgo comes first: slot 0 = bitgo, slot 1 = firstIndex
274- addressMap . set ( new Address ( this . transaction . _fromAddresses [ bitgoIndex ] ) , 0 ) ;
275- addressMap . set ( new Address ( this . transaction . _fromAddresses [ firstIndex ] ) , 1 ) ;
276- } else {
277- // User/recovery comes first: slot 0 = firstIndex, slot 1 = bitgo
278- addressMap . set ( new Address ( this . transaction . _fromAddresses [ firstIndex ] ) , 0 ) ;
279- addressMap . set ( new Address ( this . transaction . _fromAddresses [ bitgoIndex ] ) , 1 ) ;
280- }
281- } else {
282- // Fallback: map addresses sequentially if no UTXO addresses available
283- this . transaction . _fromAddresses . slice ( 0 , this . transaction . _threshold ) . forEach ( ( addr , i ) => {
284- addressMap . set ( new Address ( addr ) , i ) ;
285- } ) ;
286- }
287-
288- return addressMap ;
289- } ) ;
201+ // Use centralized method for AddressMap creation
202+ const addressMaps = credentials . map ( ( credential , credIdx ) =>
203+ this . createAddressMapForUtxo ( this . transaction . _utxos [ credIdx ] , this . transaction . _threshold )
204+ ) ;
290205
291206 // Create unsigned transaction
292207 const unsignedTx = new UnsignedTx (
@@ -367,39 +282,15 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
367282
368283 // Create credential with empty signatures for slot identification
369284 // Match avaxp behavior: dynamic ordering based on addressesIndex from UTXO
370- const hasAddresses =
371- this . transaction . _fromAddresses && this . transaction . _fromAddresses . length >= this . transaction . _threshold ;
372-
373- if ( ! hasAddresses ) {
374- // If addresses not available, use all zeros
375- const emptySignatures = sigIndices . map ( ( ) => utils . createNewSig ( '' ) ) ;
376- credentials . push ( new Credential ( emptySignatures ) ) ;
285+ // Use centralized method for credential creation
286+ // Note: Use utxoThreshold if it differs from transaction threshold (should be rare)
287+ const thresholdToUse =
288+ utxoThreshold === this . transaction . _threshold ? this . transaction . _threshold : utxoThreshold ;
289+ if ( thresholdToUse === this . transaction . _threshold ) {
290+ credentials . push ( this . createCredentialForUtxo ( utxo , thresholdToUse ) ) ;
377291 } else {
378- // Compute addressesIndex: position of each _fromAddresses in UTXO's address list
379- const utxoAddresses = utxo . addresses . map ( ( a ) => utils . parseAddress ( a ) ) ;
380- const addressesIndex = this . transaction . _fromAddresses . map ( ( a ) =>
381- utxoAddresses . findIndex ( ( u ) => Buffer . compare ( Buffer . from ( u ) , Buffer . from ( a ) ) === 0 )
382- ) ;
383-
384- // either user (0) or recovery (2)
385- const firstIndex = this . recoverSigner ? 2 : 0 ;
386- const bitgoIndex = 1 ;
387-
388- // Dynamic ordering based on addressesIndex
389- let emptySignatures : ReturnType < typeof utils . createNewSig > [ ] ;
390- if ( addressesIndex [ bitgoIndex ] < addressesIndex [ firstIndex ] ) {
391- // Bitgo comes first in signature order: [zeros, userAddress]
392- emptySignatures = [
393- utils . createNewSig ( '' ) ,
394- utils . createEmptySigWithAddress ( Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' ) ) ,
395- ] ;
396- } else {
397- // User comes first in signature order: [userAddress, zeros]
398- emptySignatures = [
399- utils . createEmptySigWithAddress ( Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' ) ) ,
400- utils . createNewSig ( '' ) ,
401- ] ;
402- }
292+ // Fallback: use all zeros if threshold differs (shouldn't happen normally)
293+ const emptySignatures = sigIndices . map ( ( ) => utils . createNewSig ( '' ) ) ;
403294 credentials . push ( new Credential ( emptySignatures ) ) ;
404295 }
405296 }
0 commit comments