Skip to content
Draft
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
2 changes: 1 addition & 1 deletion oxlint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -2238,7 +2238,7 @@
"count": 2
},
"typescript/no-unsafe-assignment": {
"count": 5
"count": 9
},
"typescript/no-unsafe-return": {
"count": 2
Expand Down
1 change: 1 addition & 0 deletions packages/bridge-status-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Pass the swap/bridge `sourceAssetId` and `destAssetId` to Tron, Solana, and Bitcoin Snap `signAndSendTransaction` requests. ([#10775](https://github.com/MetaMask/core/pull/10775))
- Bump `@metamask/profile-sync-controller` from `^34.0.0` to `^34.0.3` ([#10752](https://github.com/MetaMask/core/pull/10752), [#10756](https://github.com/MetaMask/core/pull/10756), [#10761](https://github.com/MetaMask/core/pull/10761))
- Bump `@metamask/snaps-controllers` from `^19.0.0` to `^19.0.1` ([#10719](https://github.com/MetaMask/core/pull/10719))
- Bump `@metamask/transaction-controller` from `^72.1.0` to `^72.2.0` ([#10772](https://github.com/MetaMask/core/pull/10772))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5012,6 +5012,10 @@ exports[`BridgeStatusController submitTx: Solana bridge should handle snap contr
"method": "signAndSendTransaction",
"params": {
"accountId": "solana-account-1",
"options": {
"destAssetId": "eip155:1/slip44:60",
"sourceAssetId": "eip155:1399811149/slip44:501",
},
"scope": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHDXLY8oVRIwA8ZdRSGjM5RIZJW8Wv+Twyw3NqU4Hov+OHoHp/dmeDvstKbICW3ezeGR69t3/PTAvdXgZVdJFJXaxkoKXUTWfEAyQyCCG9nwVoDsd10OFdnM9ldSi+9SLqHpqWVDV+zzkmftkF//DpbXxqeH8obNXHFR7pUlxG9uNVOn64oNsFdeUvD139j1M51iRmUY839Y25ET4jDRscT081oGb+rLnywLjLSrIQx6MkqNBhCFbxqY1YmoGZVORW/QMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAAjJclj04kifG7PRApFI4NgwtaE5na/xCEBI572Nvp+FkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpBHnVW/IxwG7udMVuzmgVB/2xst6j9I5RArHNola8E4+0P/on9df2SnTAmx8pWHneSwmrNt/J3VFLMhqns4zl6JmXkZ+niuxMhAGrmKBaBo94uMv2Sl+Xh3i+VOO0m5BdNZ1ElenbwQylHQY+VW1ydG1MaUEeNpG+EVgswzPMwPoLBgAFAsBcFQAGAAkDQA0DAAAAAAAHBgABAhMICQAHBgADABYICQEBCAIAAwwCAAAAUEYVOwAAAAAJAQMBEQoUCQADBAETCgsKFw0ODxARAwQACRQj5RfLl3rjrSoBAAAAQ2QAAVBGFTsAAAAAyYZnBwAAAABkAAAJAwMAAAEJDAkAAAIBBBMVCQjGASBMKQwnooTbKNxdBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUHTKomh4KXvNgA0ovYKS5F8GIOBgAAAAAAAAAAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAEIF7RFOAwAAAAAAAAAAAAAAaAIAAAAAAAC4CwAAAAAAAOAA2mcAAAAAAAAAAAAAAAAAAAAApapuIXG0FuHSfsU8qME9s/kaic0AAwGCsZdSuxV5eCm+Ria4LEQPgTg4bg65gNrTAefEzpAfPQgCABIMAgAAAAAAAAAAAAAACAIABQwCAAAAsIOFAAAAAAADWk6DVOZO8lMFQg2r0dgfltD6tRL/B1hH3u00UzZdgqkAAxEqIPdq2eRt/F6mHNmFe7iwZpdrtGmHNJMFlK7c6Bc6k6kjBezr6u/tAgvu3OGsJSwSElmcOHZ21imqH/rhJ2KgqDJdBPFH4SYIM1kBAAA=",
},
Expand Down Expand Up @@ -5111,6 +5115,10 @@ exports[`BridgeStatusController submitTx: Solana bridge should successfully subm
"method": "signAndSendTransaction",
"params": {
"accountId": "solana-account-1",
"options": {
"destAssetId": "eip155:1/slip44:60",
"sourceAssetId": "eip155:1399811149/slip44:501",
},
"scope": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHDXLY8oVRIwA8ZdRSGjM5RIZJW8Wv+Twyw3NqU4Hov+OHoHp/dmeDvstKbICW3ezeGR69t3/PTAvdXgZVdJFJXaxkoKXUTWfEAyQyCCG9nwVoDsd10OFdnM9ldSi+9SLqHpqWVDV+zzkmftkF//DpbXxqeH8obNXHFR7pUlxG9uNVOn64oNsFdeUvD139j1M51iRmUY839Y25ET4jDRscT081oGb+rLnywLjLSrIQx6MkqNBhCFbxqY1YmoGZVORW/QMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAAjJclj04kifG7PRApFI4NgwtaE5na/xCEBI572Nvp+FkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpBHnVW/IxwG7udMVuzmgVB/2xst6j9I5RArHNola8E4+0P/on9df2SnTAmx8pWHneSwmrNt/J3VFLMhqns4zl6JmXkZ+niuxMhAGrmKBaBo94uMv2Sl+Xh3i+VOO0m5BdNZ1ElenbwQylHQY+VW1ydG1MaUEeNpG+EVgswzPMwPoLBgAFAsBcFQAGAAkDQA0DAAAAAAAHBgABAhMICQAHBgADABYICQEBCAIAAwwCAAAAUEYVOwAAAAAJAQMBEQoUCQADBAETCgsKFw0ODxARAwQACRQj5RfLl3rjrSoBAAAAQ2QAAVBGFTsAAAAAyYZnBwAAAABkAAAJAwMAAAEJDAkAAAIBBBMVCQjGASBMKQwnooTbKNxdBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUHTKomh4KXvNgA0ovYKS5F8GIOBgAAAAAAAAAAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAEIF7RFOAwAAAAAAAAAAAAAAaAIAAAAAAAC4CwAAAAAAAOAA2mcAAAAAAAAAAAAAAAAAAAAApapuIXG0FuHSfsU8qME9s/kaic0AAwGCsZdSuxV5eCm+Ria4LEQPgTg4bg65gNrTAefEzpAfPQgCABIMAgAAAAAAAAAAAAAACAIABQwCAAAAsIOFAAAAAAADWk6DVOZO8lMFQg2r0dgfltD6tRL/B1hH3u00UzZdgqkAAxEqIPdq2eRt/F6mHNmFe7iwZpdrtGmHNJMFlK7c6Bc6k6kjBezr6u/tAgvu3OGsJSwSElmcOHZ21imqH/rhJ2KgqDJdBPFH4SYIM1kBAAA=",
},
Expand Down Expand Up @@ -5370,7 +5378,7 @@ exports[`BridgeStatusController submitTx: Solana swap should handle snap control
"source_hash_present": false,
"stx_enabled": false,
"swap_type": "single_chain",
"token_address_destination": "eip155:1399811149/slip44:501",
"token_address_destination": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"token_address_source": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
"token_security_type_destination": null,
"token_symbol_destination": "USDC",
Expand All @@ -5391,6 +5399,10 @@ exports[`BridgeStatusController submitTx: Solana swap should handle snap control
"method": "signAndSendTransaction",
"params": {
"accountId": "solana-account-1",
"options": {
"destAssetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"sourceAssetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
},
"scope": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHDXLY8oVRIwA8ZdRSGjM5RIZJW8Wv+Twyw3NqU4Hov+OHoHp/dmeDvstKbICW3ezeGR69t3/PTAvdXgZVdJFJXaxkoKXUTWfEAyQyCCG9nwVoDsd10OFdnM9ldSi+9SLqHpqWVDV+zzkmftkF//DpbXxqeH8obNXHFR7pUlxG9uNVOn64oNsFdeUvD139j1M51iRmUY839Y25ET4jDRscT081oGb+rLnywLjLSrIQx6MkqNBhCFbxqY1YmoGZVORW/QMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAAjJclj04kifG7PRApFI4NgwtaE5na/xCEBI572Nvp+FkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpBHnVW/IxwG7udMVuzmgVB/2xst6j9I5RArHNola8E4+0P/on9df2SnTAmx8pWHneSwmrNt/J3VFLMhqns4zl6JmXkZ+niuxMhAGrmKBaBo94uMv2Sl+Xh3i+VOO0m5BdNZ1ElenbwQylHQY+VW1ydG1MaUEeNpG+EVgswzPMwPoLBgAFAsBcFQAGAAkDQA0DAAAAAAAHBgABAhMICQAHBgADABYICQEBCAIAAwwCAAAAUEYVOwAAAAAJAQMBEQoUCQADBAETCgsKFw0ODxARAwQACRQj5RfLl3rjrSoBAAAAQ2QAAVBGFTsAAAAAyYZnBwAAAABkAAAJAwMAAAEJDAkAAAIBBBMVCQjGASBMKQwnooTbKNxdBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUHTKomh4KXvNgA0ovYKS5F8GIOBgAAAAAAAAAAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAEIF7RFOAwAAAAAAAAAAAAAAaAIAAAAAAAC4CwAAAAAAAOAA2mcAAAAAAAAAAAAAAAAAAAAApapuIXG0FuHSfsU8qME9s/kaic0AAwGCsZdSuxV5eCm+Ria4LEQPgTg4bg65gNrTAefEzpAfPQgCABIMAgAAAAAAAAAAAAAACAIABQwCAAAAsIOFAAAAAAADWk6DVOZO8lMFQg2r0dgfltD6tRL/B1hH3u00UzZdgqkAAxEqIPdq2eRt/F6mHNmFe7iwZpdrtGmHNJMFlK7c6Bc6k6kjBezr6u/tAgvu3OGsJSwSElmcOHZ21imqH/rhJ2KgqDJdBPFH4SYIM1kBAAA=",
},
Expand Down Expand Up @@ -5423,7 +5435,7 @@ exports[`BridgeStatusController submitTx: Solana swap should handle snap control
"source_hash_present": false,
"stx_enabled": false,
"swap_type": "single_chain",
"token_address_destination": "eip155:1399811149/slip44:501",
"token_address_destination": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"token_address_source": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
"token_security_type_destination": null,
"token_symbol_destination": "USDC",
Expand Down Expand Up @@ -5469,7 +5481,7 @@ exports[`BridgeStatusController submitTx: Solana swap should successfully submit
"source_hash_present": false,
"stx_enabled": false,
"swap_type": "single_chain",
"token_address_destination": "eip155:1399811149/slip44:501",
"token_address_destination": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"token_address_source": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
"token_security_type_destination": null,
"token_symbol_destination": "USDC",
Expand All @@ -5490,6 +5502,10 @@ exports[`BridgeStatusController submitTx: Solana swap should successfully submit
"method": "signAndSendTransaction",
"params": {
"accountId": "solana-account-1",
"options": {
"destAssetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"sourceAssetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
},
"scope": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHDXLY8oVRIwA8ZdRSGjM5RIZJW8Wv+Twyw3NqU4Hov+OHoHp/dmeDvstKbICW3ezeGR69t3/PTAvdXgZVdJFJXaxkoKXUTWfEAyQyCCG9nwVoDsd10OFdnM9ldSi+9SLqHpqWVDV+zzkmftkF//DpbXxqeH8obNXHFR7pUlxG9uNVOn64oNsFdeUvD139j1M51iRmUY839Y25ET4jDRscT081oGb+rLnywLjLSrIQx6MkqNBhCFbxqY1YmoGZVORW/QMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAAjJclj04kifG7PRApFI4NgwtaE5na/xCEBI572Nvp+FkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpBHnVW/IxwG7udMVuzmgVB/2xst6j9I5RArHNola8E4+0P/on9df2SnTAmx8pWHneSwmrNt/J3VFLMhqns4zl6JmXkZ+niuxMhAGrmKBaBo94uMv2Sl+Xh3i+VOO0m5BdNZ1ElenbwQylHQY+VW1ydG1MaUEeNpG+EVgswzPMwPoLBgAFAsBcFQAGAAkDQA0DAAAAAAAHBgABAhMICQAHBgADABYICQEBCAIAAwwCAAAAUEYVOwAAAAAJAQMBEQoUCQADBAETCgsKFw0ODxARAwQACRQj5RfLl3rjrSoBAAAAQ2QAAVBGFTsAAAAAyYZnBwAAAABkAAAJAwMAAAEJDAkAAAIBBBMVCQjGASBMKQwnooTbKNxdBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUHTKomh4KXvNgA0ovYKS5F8GIOBgAAAAAAAAAAAAAAAAAQgAAAAAAAAAAAAAAAAAAAAAAAEIF7RFOAwAAAAAAAAAAAAAAaAIAAAAAAAC4CwAAAAAAAOAA2mcAAAAAAAAAAAAAAAAAAAAApapuIXG0FuHSfsU8qME9s/kaic0AAwGCsZdSuxV5eCm+Ria4LEQPgTg4bg65gNrTAefEzpAfPQgCABIMAgAAAAAAAAAAAAAACAIABQwCAAAAsIOFAAAAAAADWk6DVOZO8lMFQg2r0dgfltD6tRL/B1hH3u00UzZdgqkAAxEqIPdq2eRt/F6mHNmFe7iwZpdrtGmHNJMFlK7c6Bc6k6kjBezr6u/tAgvu3OGsJSwSElmcOHZ21imqH/rhJ2KgqDJdBPFH4SYIM1kBAAA=",
},
Expand Down Expand Up @@ -5534,7 +5550,7 @@ exports[`BridgeStatusController submitTx: Solana swap should successfully submit
"source_transaction": "COMPLETE",
"stx_enabled": false,
"swap_type": "single_chain",
"token_address_destination": "eip155:1399811149/slip44:501",
"token_address_destination": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"token_address_source": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
"token_security_type_destination": null,
"token_symbol_destination": "USDC",
Expand Down Expand Up @@ -5604,7 +5620,7 @@ exports[`BridgeStatusController submitTx: Solana swap should successfully submit
"bridges": [],
"destAsset": {
"address": "0x...",
"assetId": "eip155:1399811149/slip44:501",
"assetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"chainId": 1151111081099710,
"decimals": 18,
"name": "USDC",
Expand Down Expand Up @@ -5723,7 +5739,7 @@ exports[`BridgeStatusController submitTx: Solana swap should throw error when sn
"source_hash_present": false,
"stx_enabled": false,
"swap_type": "single_chain",
"token_address_destination": "eip155:1399811149/slip44:501",
"token_address_destination": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"token_address_source": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
"token_security_type_destination": null,
"token_symbol_destination": "USDC",
Expand Down Expand Up @@ -5758,7 +5774,7 @@ exports[`BridgeStatusController submitTx: Solana swap should throw error when sn
"source_hash_present": false,
"stx_enabled": false,
"swap_type": "single_chain",
"token_address_destination": "eip155:1399811149/slip44:501",
"token_address_destination": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"token_address_source": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
"token_security_type_destination": null,
"token_symbol_destination": "USDC",
Expand Down Expand Up @@ -5951,6 +5967,8 @@ exports[`BridgeStatusController submitTx: Tron swap with approval should success
"params": {
"accountId": "tron-account-1",
"options": {
"destAssetId": "tron:728126428/slip44:195",
"sourceAssetId": "tron:728126428/slip44:195",
"type": undefined,
"visible": undefined,
},
Expand Down Expand Up @@ -6174,6 +6192,8 @@ exports[`BridgeStatusController submitTx: Tron swap with approval should success
"params": {
"accountId": "tron-account-1",
"options": {
"destAssetId": "tron:728126428/slip44:195",
"sourceAssetId": "tron:728126428/slip44:195",
"type": undefined,
"visible": undefined,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2632,7 +2632,7 @@ describe('BridgeStatusController', () => {
symbol: 'USDC',
name: 'USDC',
decimals: 18,
assetId: 'eip155:1399811149/slip44:501',
assetId: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`,
},
bridgeId: 'test-bridge',
bridges: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const handleTronApproval = async (
quoteResponse.approval,
quoteResponse,
args.selectedAccount,
true,
);
return txMeta.id;
}
Expand Down
37 changes: 37 additions & 0 deletions packages/bridge-status-controller/src/utils/snaps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,43 @@ describe('Snaps Utils', () => {
}
`);
});

it('omits the swap asset ids for an approval transaction', async () => {
const snapId = 'test-snap-id';
const transaction = 'base64-encoded-approval';
const accountId = 'test-account-id';

const mockCall = jest.fn((...args: unknown[]) => {
const [action] = args;
if (action === 'SnapController:handleRequest') {
return Promise.resolve({ transactionId: 'approval-tx-id' });
}
});
const messenger = {
call: (...args: unknown[]) => mockCall(...args),
} as unknown as BridgeStatusControllerMessenger;

await handleNonEvmTx(
messenger,
transaction,
{
quote: {
srcChainId: ChainId.SOLANA,
srcAsset: { symbol: 'SOL', assetId: 'solana:src/slip44:501' },
destAsset: { symbol: 'USDC', assetId: 'solana:dest/token:usdc' },
},
sentAmount: { amount: '1000000000' },
} as never,
{ id: accountId, metadata: { snap: { id: snapId } } } as never,
true,
);

const [, request] = mockCall.mock.calls[0] as [
string,
{ request: { params: { options?: unknown } } },
];
expect(request.request.params.options).toBeUndefined();
});
});

describe('createClientTransactionRequest', () => {
Expand Down
30 changes: 22 additions & 8 deletions packages/bridge-status-controller/src/utils/snaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import {
extractTradeData,
formatChainIdToCaip,
formatChainIdToHex,
isBitcoinChainId,
isCrossChain,
isStellarTrade,
isSolanaChainId,
isStellarChainId,
isTronTrade,
} from '@metamask/bridge-controller';
import { SnapController } from '@metamask/snaps-controllers';
Expand Down Expand Up @@ -91,10 +93,11 @@ export const getClientRequest = (

let options: Record<string, unknown> | undefined;

// Only Stellar trades expect asset IDs in the request options. Passing them
// for other non-EVM chains (e.g. Bitcoin) breaks strict snap request
// validation and prevents the transaction from being broadcast.
if (isStellarTrade(trade)) {
if (
isStellarChainId(srcChainId) ||
isSolanaChainId(srcChainId) ||
isBitcoinChainId(srcChainId)
Comment on lines +96 to +99

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why srcChainId instead of trade

Two reasons: consistency, and the trade shape does not always tell you the chain.

1. The trade shape is a lossy proxy for the chain

The strategy layer establishes that trade shape maps 1:1 to chain, but note the Stellar case in strategy/index.ts:

case ChainId.STELLAR:
  return txs.every((tx) => typeof tx === 'string' || isStellarTrade(tx));

A Stellar trade is either a string or an { xdr / xdrBase64 } object. So isStellarTrade(trade) is false for a string-shaped Stellar trade, and that string is indistinguishable from a Solana trade by shape alone. The chain id is the only reliable signal for Stellar-vs-Solana strings, which is exactly why the original Solana check used isSolanaChainId(srcChainId) (there is no isSolanaTrade).

2. Consistency: one condition, one kind of check

Before, the condition mixed two kinds of check:

isStellarTrade(trade) ||        // trade-shape guard
isSolanaChainId(srcChainId) ||  // chain guard
isBitcoinTrade(trade)           // trade-shape guard

getClientRequest already has srcChainId in scope (it derives scope from it on the first line), so using chain guards for all three makes the condition uniform:

isStellarChainId(srcChainId) ||
isSolanaChainId(srcChainId) ||
isBitcoinChainId(srcChainId)

3. It is also slightly more accurate

isStellarChainId accepts both pubnet and testnet (XlmScope.Pubnet / XlmScope.Testnet), whereas isStellarTrade only reflects the payload shape.

Behavior equivalence

Chain Before After Same?
Stellar (object xdr) isStellarTrade -> true isStellarChainId -> true Yes
Stellar (string xdr) isStellarTrade -> false isStellarChainId -> true After is more correct
Solana isSolanaChainId -> true isSolanaChainId -> true Yes
Bitcoin isBitcoinTrade -> true isBitcoinChainId -> true Yes
Tron not in this condition not in this condition Yes (separate branch)
EVM all false all false Yes

The only behavioral difference is the string-shaped Stellar case, where the new version is correct and the old one would have silently omitted the asset ids.

) {
if (sourceAssetId !== undefined || destAssetId !== undefined) {
options = {
...(sourceAssetId !== undefined && {
Expand All @@ -108,10 +111,15 @@ export const getClientRequest = (
}

if (isTronTrade(trade)) {
// Tron trades need the visible flag and contract type to be included in the request options
options = {
visible: trade.visible,
type: trade.raw_data?.contract?.[0]?.type,
...(sourceAssetId !== undefined && {
sourceAssetId,
}),
...(destAssetId !== undefined && {
destAssetId,
}),
Comment thread
Battambang marked this conversation as resolved.
Comment thread
Copilot marked this conversation as resolved.
Comment on lines +117 to +122

@Battambang Battambang Oct 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • First, the Tron snap is bumped before/at the same time than this bridge-status-controller will be bumped so there will be no regression with retro-compatibility.
  • Second, the new arguments are optional on the Tron snap side so it would still be compatible with previous versions.

MetaMask/internal-snaps#434: feat(tron): classify swap, bridge, and send transactions in analytics

The new options are optional, so existing callers keep validating; the Snap is backward compatible with clients that do not send asset ids yet.

};
}

Expand Down Expand Up @@ -254,27 +262,33 @@ export const handleNonEvmTxResponse = (
* @param trade - The trade data (can be approval or main trade)
* @param quoteResponse - The quote response containing metadata
* @param selectedAccount - The account to submit the transaction for
* @param isApproval - Whether the trade is the approval transaction rather than the main trade
* @returns The transaction meta
*/
export const handleNonEvmTx = async (
messenger: BridgeStatusControllerMessenger,
trade: Trade,
quoteResponse: QuoteResponseV1<Trade, Trade> & QuoteMetadata,
selectedAccount: AccountsControllerState['internalAccounts']['accounts'][string],
isApproval = false,
): Promise<TransactionMeta> => {
if (!selectedAccount.metadata?.snap?.id) {
throw new Error(
'Failed to submit cross-chain swap transaction: undefined snap id',
);
}

// The quote's asset ids describe the swap/bridge transaction, not the token
// approval that precedes it. Passing them for the approval would make the snap
// classify the approval as a swap or a bridge, so they are only attached to
// the main trade.
const request = getClientRequest(
trade,
quoteResponse.quote.srcChainId,
selectedAccount.id,
selectedAccount.metadata?.snap?.id,
quoteResponse.quote.srcAsset.assetId,
quoteResponse.quote.destAsset.assetId,
isApproval ? undefined : quoteResponse.quote.srcAsset.assetId,
isApproval ? undefined : quoteResponse.quote.destAsset.assetId,
);
const requestResponse = (await messenger.call(
'SnapController:handleRequest',
Expand Down
Loading
Loading