From 7b44b2df2632bcd361b643409ae50b808d574d76 Mon Sep 17 00:00:00 2001 From: Apotheosis <0xapotheosis@gmail.com> Date: Tue, 24 Feb 2026 10:00:11 +1100 Subject: [PATCH] fix: fix Relay non-EVM transaction notification and Tron calldata handling Two bugs caused Relay Tron deposits to be untracked: 1. The Relay indexer notification in checkTradeStatus was gated behind isEvmChainId(), preventing non-EVM chains (Tron, Solana, Bitcoin) from notifying Relay about completed deposits. Changed the gate to check chainIdToRelayChainId membership instead, which correctly covers all Relay-supported chains. 2. Tron Relay transactions were built as simple TRC20 transfers instead of using the Relay quote calldata to call depositErc20() on the vault contract. The quote's parameter.data field (containing the vault calldata) was not being stored in relayTransactionMetadata, and the transaction builder always used buildSendApiTransaction. Now: - getTrade.ts stores the quote's calldata in metadata.data - getTrade.ts sets allowanceContract for proper token approval - getUnsignedTronTransaction.ts uses buildCustomApiTx with the Relay calldata when available, falling back to buildSendApiTransaction for NearIntents and other simple-transfer swappers Tron remains disabled in chainIdToRelayChainId until this fix is verified end-to-end with the Relay API. Co-Authored-By: Claude Opus 4.6 --- .../src/swappers/RelaySwapper/constant.ts | 7 +++++-- .../src/swappers/RelaySwapper/endpoints.ts | 4 ++-- .../src/swappers/RelaySwapper/utils/getTrade.ts | 3 ++- .../src/tron-utils/getUnsignedTronTransaction.ts | 16 ++++++++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/packages/swapper/src/swappers/RelaySwapper/constant.ts b/packages/swapper/src/swappers/RelaySwapper/constant.ts index 5410eeef1a3..3439b2676a0 100644 --- a/packages/swapper/src/swappers/RelaySwapper/constant.ts +++ b/packages/swapper/src/swappers/RelaySwapper/constant.ts @@ -30,7 +30,6 @@ import { soneiumChainId, sonicChainId, storyChainId, - tronChainId, unichainChainId, worldChainChainId, zkSyncEraChainId, @@ -87,7 +86,11 @@ export const chainIdToRelayChainId = { [gnosisChainId]: gnosis.id, [avalancheChainId]: avalanche.id, [bscChainId]: bsc.id, - [tronChainId]: 728126428, + // DISABLED: Tron deposits are built as simple TRC20 transfers instead of depositErc20() vault calls, + // and the Relay indexer notification is never sent for non-EVM chains. This causes deposits to be + // untracked by Relay, resulting in stuck/lost funds. Re-enable once the Tron transaction building + // is verified to use the Relay quote calldata (depositErc20) correctly. + // [tronChainId]: 728126428, [monadChainId]: monad.id, [hyperEvmChainId]: hyperEvm.id, [mantleChainId]: mantle.id, diff --git a/packages/swapper/src/swappers/RelaySwapper/endpoints.ts b/packages/swapper/src/swappers/RelaySwapper/endpoints.ts index dbca3fc700f..3f731f6849f 100644 --- a/packages/swapper/src/swappers/RelaySwapper/endpoints.ts +++ b/packages/swapper/src/swappers/RelaySwapper/endpoints.ts @@ -1,4 +1,4 @@ -import { evm, isEvmChainId } from '@shapeshiftoss/chain-adapters' +import { evm } from '@shapeshiftoss/chain-adapters' import { TxStatus } from '@shapeshiftoss/unchained-client' import BigNumber from 'bignumber.js' @@ -200,7 +200,7 @@ export const relayApi: SwapperApi = { if ( swap.metadata.relayTransactionMetadata && !txIndexingMap.has(swap.id) && - isEvmChainId(chainId) + chainIdToRelayChainId[chainId] !== undefined ) { const relayTxParam = { ...swap.metadata.relayTransactionMetadata, diff --git a/packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts b/packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts index 753bb641e74..ce40d3b50ab 100644 --- a/packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts +++ b/packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts @@ -653,12 +653,13 @@ export async function getTrade({ if (isRelayQuoteTronItemData(selectedItem.data)) { return { - allowanceContract: '', + allowanceContract: selectedItem.data?.parameter?.contract_address ?? '', solanaTransactionMetadata: undefined, relayTransactionMetadata: { relayId: quote.steps[0].requestId, orderId, to: selectedItem.data?.parameter?.contract_address, + data: selectedItem.data?.parameter?.data, }, } } diff --git a/packages/swapper/src/tron-utils/getUnsignedTronTransaction.ts b/packages/swapper/src/tron-utils/getUnsignedTronTransaction.ts index ad51f0cb7eb..682d79b8abf 100644 --- a/packages/swapper/src/tron-utils/getUnsignedTronTransaction.ts +++ b/packages/swapper/src/tron-utils/getUnsignedTronTransaction.ts @@ -46,6 +46,22 @@ export const getUnsignedTronTransaction = ({ }) } + if (relayTransactionMetadata?.data) { + const to = relayTransactionMetadata.to + if (!to) throw new Error('Missing Relay transaction destination address') + + const isNativeTron = sellAsset.assetId === tronAssetId + const value = isNativeTron ? step.sellAmountIncludingProtocolFeesCryptoBaseUnit : '0' + + return adapter.buildCustomApiTx({ + from, + to, + accountNumber, + data: relayTransactionMetadata.data, + value, + }) + } + const to = relayTransactionMetadata?.to ?? nearIntentsSpecific?.depositAddress if (!to) throw new Error('Missing transaction destination address')