Skip to content

Commit 99d219e

Browse files
authored
Merge pull request #7922 from BitGo/WIN-8657
feat(sdk-coin-flrp): enhance transaction builders with addressesIndex handling
2 parents 0d57abd + 46512e9 commit 99d219e

5 files changed

Lines changed: 188 additions & 443 deletions

File tree

modules/sdk-coin-flrp/src/lib/ImportInCTxBuilder.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
UnsignedTx,
77
Credential,
88
TransferableInput,
9+
TransferInput,
910
TransferOutput,
1011
Address,
1112
utils as FlareUtils,
@@ -186,16 +187,17 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
186187
return importedInputs.map((input) => {
187188
const txid = input.utxoID.toString();
188189
const outputidx = input.utxoID.outputIdx.toString();
190+
const transferInput = input.input as TransferInput;
191+
const addressesIndex = transferInput.sigIndicies();
189192

190193
return {
191194
outputID: SECP256K1_Transfer_Output,
192195
amount: input.amount().toString(),
193196
txid: utils.cb58Encode(Buffer.from(txid, 'hex')),
194197
outputidx: outputidx,
195-
threshold: this.transaction._threshold,
196-
addresses: this.transaction._fromAddresses.map((addr) =>
197-
utils.addressToString(this.transaction._network.hrp, this.transaction._network.alias, Buffer.from(addr))
198-
),
198+
threshold: addressesIndex.length || this.transaction._threshold,
199+
addresses: [],
200+
addressesIndex,
199201
};
200202
});
201203
}

modules/sdk-coin-flrp/src/lib/ImportInPTxBuilder.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,16 @@ export class ImportInPTxBuilder extends AtomicTransactionBuilder {
198198
return importedInputs.map((input) => {
199199
const utxoId = input.utxoID;
200200
const transferInput = input.input as TransferInput;
201+
const addressesIndex = transferInput.sigIndicies();
202+
201203
const utxo: DecodedUtxoObj = {
202204
outputID: SECP256K1_Transfer_Output,
203205
amount: transferInput.amount().toString(),
204206
txid: utils.cb58Encode(Buffer.from(utxoId.txID.toBytes())),
205207
outputidx: utxoId.outputIdx.value().toString(),
206-
threshold: this.transaction._threshold,
207-
addresses: this.transaction._fromAddresses.map((addr) =>
208-
utils.addressToString(this.transaction._network.hrp, this.transaction._network.alias, Buffer.from(addr))
209-
),
208+
threshold: addressesIndex.length || this.transaction._threshold,
209+
addresses: [],
210+
addressesIndex,
210211
};
211212
return utxo;
212213
});

modules/sdk-coin-flrp/src/lib/atomicTransactionBuilder.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,17 @@ export abstract class AtomicTransactionBuilder extends TransactionBuilder {
113113
const sender = (this.transaction as Transaction)._fromAddresses;
114114
const hasAddresses = sender && sender.length >= threshold;
115115

116+
// If we have pre-computed addressesIndex (from parsing a transaction), use it directly
117+
// This is the authoritative source for signature ordering from parsed transactions
118+
if (utxo.addressesIndex && utxo.addressesIndex.length >= threshold) {
119+
// Create credentials matching the sigIndicies order from the parsed transaction
120+
const emptySignatures: ReturnType<typeof utils.createNewSig>[] = [];
121+
for (let i = 0; i < threshold; i++) {
122+
emptySignatures.push(utils.createNewSig(''));
123+
}
124+
return new Credential(emptySignatures);
125+
}
126+
116127
if (!hasAddresses || !utxo.addresses || utxo.addresses.length === 0) {
117128
// Fallback: use all zeros if no addresses available
118129
const emptySignatures: ReturnType<typeof utils.createNewSig>[] = [];
@@ -163,6 +174,21 @@ export abstract class AtomicTransactionBuilder extends TransactionBuilder {
163174
const addressMap = new FlareUtils.AddressMap();
164175
const sender = (this.transaction as Transaction)._fromAddresses;
165176

177+
// If we have pre-computed addressesIndex (from parsing a transaction), use it directly
178+
// addressesIndex from sigIndicies() tells us: addressesIndex[slotIdx] = utxoAddressIdx
179+
// This means slot 'slotIdx' expects signature from UTXO address at index 'utxoAddressIdx'
180+
// Assuming sender[i] corresponds to utxoAddress[i], we map sender[addressesIndex[slotIdx]] to slotIdx
181+
if (utxo.addressesIndex && utxo.addressesIndex.length >= threshold && sender && sender.length >= threshold) {
182+
for (let slotIdx = 0; slotIdx < threshold; slotIdx++) {
183+
const utxoAddrIdx = utxo.addressesIndex[slotIdx];
184+
// Map the sender that corresponds to this UTXO address index to this slot
185+
if (utxoAddrIdx < sender.length) {
186+
addressMap.set(new Address(sender[utxoAddrIdx]), slotIdx);
187+
}
188+
}
189+
return addressMap;
190+
}
191+
166192
// If UTXO has addresses, compute addressesIndex to determine signature order
167193
if (utxo && utxo.addresses && utxo.addresses.length > 0 && sender && sender.length >= threshold) {
168194
const utxoAddresses = utxo.addresses.map((a) => utils.parseAddress(a));

0 commit comments

Comments
 (0)