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
17 changes: 16 additions & 1 deletion modules/sdk-coin-iota/src/iota.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
MPCType,
PopulatedIntent,
PrebuildTransactionWithIntentOptions,
TransactionRecipient,
verifyEddsaTssWalletAddress,
} from '@bitgo/sdk-core';
import { BaseCoin as StaticsBaseCoin, CoinFamily, coins } from '@bitgo/statics';
Expand Down Expand Up @@ -121,7 +122,21 @@ export class Iota extends BaseCoin {
throw new Error('Tx not a transfer transaction');
}
const txData = transaction.toJson() as TransferTxData;
if (!txData.recipients || !_.isEqual(txParams.recipients, txData.recipients)) {

if (!txData.recipients) {
throw new Error('Tx recipients does not match with expected txParams recipients');
}

const normalizeRecipient = (recipient: TransactionRecipient) =>
_.pick(recipient, ['address', 'amount', 'tokenName']);
const txDataRecipients = txData.recipients.map(normalizeRecipient);
const txParamsRecipients = txParams.recipients.map(normalizeRecipient);

const allRecipientsMatch = txParamsRecipients.every((expectedRecipient) =>
txDataRecipients.some((actualRecipient) => _.isEqual(expectedRecipient, actualRecipient))
);

if (!allRecipientsMatch) {
throw new Error('Tx recipients does not match with expected txParams recipients');
}
}
Expand Down
41 changes: 39 additions & 2 deletions modules/sdk-coin-iota/test/unit/iota.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,34 @@ describe('IOTA:', function () {
);
});

it('should verify transaction with recipients containing extra fields', async function () {
// The verification should only compare address, amount, and tokenName
// Extra fields should be ignored
const txBuilder = factory.getTransferBuilder();
txBuilder.sender(testData.sender.address);
txBuilder.recipients(testData.recipients);
txBuilder.paymentObjects(testData.paymentObjects);
txBuilder.gasData(testData.gasData);

const tx = (await txBuilder.build()) as TransferTransaction;
const txHex = Buffer.from(await tx.toBroadcastFormat(), 'base64').toString('hex');

// Add extra fields to recipients that should be ignored during comparison
const recipientsWithExtraFields = testData.recipients.map((r) => ({
...r,
extraField: 'should be ignored',
anotherField: 123,
}));

should.equal(
await basecoin.verifyTransaction({
txPrebuild: { txHex: txHex },
txParams: { recipients: recipientsWithExtraFields },
}),
true
);
});

it('should detect mismatched recipients', async function () {
const txBuilder = factory.getTransferBuilder();
txBuilder.sender(testData.sender.address);
Expand All @@ -210,11 +238,20 @@ describe('IOTA:', function () {

const tx = (await txBuilder.build()) as TransferTransaction;
const txHex = Buffer.from(await tx.toBroadcastFormat(), 'base64').toString('hex');
assert.rejects(

// Create mismatched recipients with different addresses/amounts
const mismatchedRecipients = [
{
address: testData.addresses.validAddresses[2], // Different address
amount: '9999', // Different amount
},
];

await assert.rejects(
async () =>
await basecoin.verifyTransaction({
txPrebuild: { txHex: txHex },
txParams: { recipients: testData.recipients },
txParams: { recipients: mismatchedRecipients },
}),
/Tx recipients does not match with expected txParams recipients/
);
Expand Down