Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions modules/sdk-coin-flrp/src/lib/ImportInCTxBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
UnsignedTx,
Credential,
TransferableInput,
TransferInput,
TransferOutput,
Address,
utils as FlareUtils,
Expand Down Expand Up @@ -186,16 +187,17 @@ export class ImportInCTxBuilder extends AtomicInCTransactionBuilder {
return importedInputs.map((input) => {
const txid = input.utxoID.toString();
const outputidx = input.utxoID.outputIdx.toString();
const transferInput = input.input as TransferInput;
const addressesIndex = transferInput.sigIndicies();

return {
outputID: SECP256K1_Transfer_Output,
amount: input.amount().toString(),
txid: utils.cb58Encode(Buffer.from(txid, 'hex')),
outputidx: outputidx,
threshold: this.transaction._threshold,
addresses: this.transaction._fromAddresses.map((addr) =>
utils.addressToString(this.transaction._network.hrp, this.transaction._network.alias, Buffer.from(addr))
),
threshold: addressesIndex.length || this.transaction._threshold,
addresses: [],
addressesIndex,
};
});
}
Expand Down
9 changes: 5 additions & 4 deletions modules/sdk-coin-flrp/src/lib/ImportInPTxBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,16 @@ export class ImportInPTxBuilder extends AtomicTransactionBuilder {
return importedInputs.map((input) => {
const utxoId = input.utxoID;
const transferInput = input.input as TransferInput;
const addressesIndex = transferInput.sigIndicies();

const utxo: DecodedUtxoObj = {
outputID: SECP256K1_Transfer_Output,
amount: transferInput.amount().toString(),
txid: utils.cb58Encode(Buffer.from(utxoId.txID.toBytes())),
outputidx: utxoId.outputIdx.value().toString(),
threshold: this.transaction._threshold,
addresses: this.transaction._fromAddresses.map((addr) =>
utils.addressToString(this.transaction._network.hrp, this.transaction._network.alias, Buffer.from(addr))
),
threshold: addressesIndex.length || this.transaction._threshold,
addresses: [],
addressesIndex,
};
return utxo;
});
Expand Down
26 changes: 26 additions & 0 deletions modules/sdk-coin-flrp/src/lib/atomicTransactionBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ export abstract class AtomicTransactionBuilder extends TransactionBuilder {
const sender = (this.transaction as Transaction)._fromAddresses;
const hasAddresses = sender && sender.length >= threshold;

// If we have pre-computed addressesIndex (from parsing a transaction), use it directly
// This is the authoritative source for signature ordering from parsed transactions
if (utxo.addressesIndex && utxo.addressesIndex.length >= threshold) {
// Create credentials matching the sigIndicies order from the parsed transaction
const emptySignatures: ReturnType<typeof utils.createNewSig>[] = [];
for (let i = 0; i < threshold; i++) {
emptySignatures.push(utils.createNewSig(''));
}
return new Credential(emptySignatures);
}

if (!hasAddresses || !utxo.addresses || utxo.addresses.length === 0) {
// Fallback: use all zeros if no addresses available
const emptySignatures: ReturnType<typeof utils.createNewSig>[] = [];
Expand Down Expand Up @@ -163,6 +174,21 @@ export abstract class AtomicTransactionBuilder extends TransactionBuilder {
const addressMap = new FlareUtils.AddressMap();
const sender = (this.transaction as Transaction)._fromAddresses;

// If we have pre-computed addressesIndex (from parsing a transaction), use it directly
// addressesIndex from sigIndicies() tells us: addressesIndex[slotIdx] = utxoAddressIdx
// This means slot 'slotIdx' expects signature from UTXO address at index 'utxoAddressIdx'
// Assuming sender[i] corresponds to utxoAddress[i], we map sender[addressesIndex[slotIdx]] to slotIdx
if (utxo.addressesIndex && utxo.addressesIndex.length >= threshold && sender && sender.length >= threshold) {
for (let slotIdx = 0; slotIdx < threshold; slotIdx++) {
const utxoAddrIdx = utxo.addressesIndex[slotIdx];
// Map the sender that corresponds to this UTXO address index to this slot
if (utxoAddrIdx < sender.length) {
addressMap.set(new Address(sender[utxoAddrIdx]), slotIdx);
}
}
return addressMap;
}

// If UTXO has addresses, compute addressesIndex to determine signature order
if (utxo && utxo.addresses && utxo.addresses.length > 0 && sender && sender.length >= threshold) {
const utxoAddresses = utxo.addresses.map((a) => utils.parseAddress(a));
Expand Down
Loading