@@ -110,12 +110,10 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
110110 this . transaction . _rawSignedBytes = rawBytes ;
111111 }
112112
113- // Create proper UnsignedTx wrapper with credentials
114- const sortedAddresses = [ ...this . transaction . _fromAddresses ] . sort ( ( a , b ) => Buffer . compare ( a , b ) ) ;
115-
116113 // When credentials were extracted, use them directly to preserve existing signatures
117114 // Otherwise, create empty credentials with dynamic ordering based on addressesIndex
118115 // Match avaxp behavior: order depends on UTXO address positions
116+ // Use centralized method for credential creation
119117 const txCredentials =
120118 credentials . length > 0
121119 ? credentials
@@ -126,39 +124,11 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
126124 // Get UTXO for this input to determine addressesIndex
127125 const utxo = this . transaction . _utxos [ inputIdx ] ;
128126
129- // either user (0) or recovery (2)
130- const firstIndex = this . recoverSigner ? 2 : 0 ;
131- const bitgoIndex = 1 ;
132-
133- // If UTXO has addresses, compute dynamic ordering
134- if ( utxo && utxo . addresses && utxo . addresses . length > 0 ) {
135- const utxoAddresses = utxo . addresses . map ( ( a ) => utils . parseAddress ( a ) ) ;
136- const addressesIndex = this . transaction . _fromAddresses . map ( ( a ) =>
137- utxoAddresses . findIndex ( ( u ) => Buffer . compare ( Buffer . from ( u ) , Buffer . from ( a ) ) === 0 )
138- ) ;
139-
140- // Dynamic ordering based on addressesIndex
141- let sigSlots : ReturnType < typeof utils . createNewSig > [ ] ;
142- if ( addressesIndex [ bitgoIndex ] < addressesIndex [ firstIndex ] ) {
143- // Bitgo comes first: [zeros, userAddress]
144- sigSlots = [
145- utils . createNewSig ( '' ) ,
146- utils . createEmptySigWithAddress (
147- Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' )
148- ) ,
149- ] ;
150- } else {
151- // User comes first: [userAddress, zeros]
152- sigSlots = [
153- utils . createEmptySigWithAddress (
154- Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' )
155- ) ,
156- utils . createNewSig ( '' ) ,
157- ] ;
158- }
159- 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 ) ;
160130 } else {
161- // Fallback: use all zeros if no UTXO addresses available
131+ // Fallback: use all zeros if threshold differs (shouldn't happen normally)
162132 const sigSlots : ReturnType < typeof utils . createNewSig > [ ] = [ ] ;
163133 for ( let i = 0 ; i < inputThreshold ; i ++ ) {
164134 sigSlots . push ( utils . createNewSig ( '' ) ) ;
@@ -167,15 +137,13 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
167137 }
168138 } ) ;
169139
170- // Create address maps for signing - one per input/credential
171- // Each address map contains all addresses mapped to their indices
172- const addressMaps = txCredentials . map ( ( ) => {
173- const addressMap = new FlareUtils . AddressMap ( ) ;
174- sortedAddresses . forEach ( ( addr , i ) => {
175- addressMap . set ( new Address ( addr ) , i ) ;
176- } ) ;
177- return addressMap ;
178- } ) ;
140+ // Create AddressMaps based on signature slot order (matching credential order), not sorted addresses
141+ // This matches the approach used in credentials: addressesIndex determines signature order
142+ // AddressMaps should map addresses to signature slots in the same order as credentials
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+ ) ;
179147
180148 // Always create a new UnsignedTx with properly structured credentials
181149 const unsignedTx = new UnsignedTx ( exportTx , [ ] , new FlareUtils . AddressMaps ( addressMaps ) , txCredentials ) ;
@@ -227,15 +195,13 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
227195 this . exportedOutputs ( ) // exportedOutputs
228196 ) ;
229197
230- // Create address maps for signing - one per input/credential
231- const sortedAddresses = [ ...this . transaction . _fromAddresses ] . sort ( ( a , b ) => Buffer . compare ( a , b ) ) ;
232- const addressMaps = credentials . map ( ( ) => {
233- const addressMap = new FlareUtils . AddressMap ( ) ;
234- sortedAddresses . forEach ( ( addr , i ) => {
235- addressMap . set ( new Address ( addr ) , i ) ;
236- } ) ;
237- return addressMap ;
238- } ) ;
198+ // Create AddressMaps based on signature slot order (matching credential order), not sorted addresses
199+ // This matches the approach used in credentials: addressesIndex determines signature order
200+ // AddressMaps should map addresses to signature slots in the same order as credentials
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+ ) ;
239205
240206 // Create unsigned transaction
241207 const unsignedTx = new UnsignedTx (
@@ -316,39 +282,15 @@ export class ExportInPTxBuilder extends AtomicTransactionBuilder {
316282
317283 // Create credential with empty signatures for slot identification
318284 // Match avaxp behavior: dynamic ordering based on addressesIndex from UTXO
319- const hasAddresses =
320- this . transaction . _fromAddresses && this . transaction . _fromAddresses . length >= this . transaction . _threshold ;
321-
322- if ( ! hasAddresses ) {
323- // If addresses not available, use all zeros
324- const emptySignatures = sigIndices . map ( ( ) => utils . createNewSig ( '' ) ) ;
325- 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 ) ) ;
326291 } else {
327- // Compute addressesIndex: position of each _fromAddresses in UTXO's address list
328- const utxoAddresses = utxo . addresses . map ( ( a ) => utils . parseAddress ( a ) ) ;
329- const addressesIndex = this . transaction . _fromAddresses . map ( ( a ) =>
330- utxoAddresses . findIndex ( ( u ) => Buffer . compare ( Buffer . from ( u ) , Buffer . from ( a ) ) === 0 )
331- ) ;
332-
333- // either user (0) or recovery (2)
334- const firstIndex = this . recoverSigner ? 2 : 0 ;
335- const bitgoIndex = 1 ;
336-
337- // Dynamic ordering based on addressesIndex
338- let emptySignatures : ReturnType < typeof utils . createNewSig > [ ] ;
339- if ( addressesIndex [ bitgoIndex ] < addressesIndex [ firstIndex ] ) {
340- // Bitgo comes first in signature order: [zeros, userAddress]
341- emptySignatures = [
342- utils . createNewSig ( '' ) ,
343- utils . createEmptySigWithAddress ( Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' ) ) ,
344- ] ;
345- } else {
346- // User comes first in signature order: [userAddress, zeros]
347- emptySignatures = [
348- utils . createEmptySigWithAddress ( Buffer . from ( this . transaction . _fromAddresses [ firstIndex ] ) . toString ( 'hex' ) ) ,
349- utils . createNewSig ( '' ) ,
350- ] ;
351- }
292+ // Fallback: use all zeros if threshold differs (shouldn't happen normally)
293+ const emptySignatures = sigIndices . map ( ( ) => utils . createNewSig ( '' ) ) ;
352294 credentials . push ( new Credential ( emptySignatures ) ) ;
353295 }
354296 }
0 commit comments