diff --git a/packages/bridge-controller/src/constants/bridge.ts b/packages/bridge-controller/src/constants/bridge.ts index 049dedc6044..be9f9cbb086 100644 --- a/packages/bridge-controller/src/constants/bridge.ts +++ b/packages/bridge-controller/src/constants/bridge.ts @@ -1,5 +1,5 @@ import { AddressZero } from '@ethersproject/constants'; -import { BtcScope, SolScope } from '@metamask/keyring-api'; +import { BtcScope, SolScope, TrxScope } from '@metamask/keyring-api'; import type { Hex } from '@metamask/utils'; import { CHAIN_IDS } from './chains'; @@ -21,6 +21,7 @@ export const ALLOWED_BRIDGE_CHAIN_IDS = [ CHAIN_IDS.SEI, SolScope.Mainnet, BtcScope.Mainnet, + TrxScope.Mainnet, ] as const; export type AllowedBridgeChainIds = (typeof ALLOWED_BRIDGE_CHAIN_IDS)[number]; diff --git a/packages/bridge-controller/src/constants/tokens.ts b/packages/bridge-controller/src/constants/tokens.ts index 5571a32d415..d413df0a6a0 100644 --- a/packages/bridge-controller/src/constants/tokens.ts +++ b/packages/bridge-controller/src/constants/tokens.ts @@ -1,4 +1,4 @@ -import { BtcScope, SolScope } from '@metamask/keyring-api'; +import { BtcScope, SolScope, TrxScope } from '@metamask/keyring-api'; import type { AllowedBridgeChainIds } from './bridge'; import { CHAIN_IDS } from './chains'; @@ -54,6 +54,7 @@ const CURRENCY_SYMBOLS = { SOL: 'SOL', SEI: 'SEI', BTC: 'BTC', + TRX: 'TRX', } as const; const ETH_SWAPS_TOKEN_OBJECT = { @@ -156,6 +157,14 @@ const SEI_SWAPS_TOKEN_OBJECT = { iconUrl: '', } as const; +const TRX_SWAPS_TOKEN_OBJECT = { + symbol: CURRENCY_SYMBOLS.TRX, + name: 'Tron', + address: DEFAULT_TOKEN_ADDRESS, + decimals: 6, + iconUrl: '', +} as const; + const SWAPS_TESTNET_CHAIN_ID = '0x539'; export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = { @@ -175,6 +184,7 @@ export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = { [SolScope.Mainnet]: SOLANA_SWAPS_TOKEN_OBJECT, [SolScope.Devnet]: SOLANA_SWAPS_TOKEN_OBJECT, [BtcScope.Mainnet]: BTC_SWAPS_TOKEN_OBJECT, + [TrxScope.Mainnet]: TRX_SWAPS_TOKEN_OBJECT, } as const; export type SupportedSwapsNativeCurrencySymbols = @@ -198,4 +208,5 @@ export const SYMBOL_TO_SLIP44_MAP: Record< AVAX: 'slip44:9000', TESTETH: 'slip44:60', SEI: 'slip44:19000118', + TRX: 'slip44:195', }; diff --git a/packages/bridge-controller/src/types.ts b/packages/bridge-controller/src/types.ts index 6284ee1e35c..9153ea48f74 100644 --- a/packages/bridge-controller/src/types.ts +++ b/packages/bridge-controller/src/types.ts @@ -270,6 +270,7 @@ export enum ChainId { LINEA = 59144, SOLANA = 1151111081099710, BTC = 20000000000001, + TRON = 728126428 } export type FeatureFlagsPlatformConfig = Infer; diff --git a/packages/bridge-controller/src/utils/bridge.ts b/packages/bridge-controller/src/utils/bridge.ts index 954f8ba7962..852bbc4f92b 100644 --- a/packages/bridge-controller/src/utils/bridge.ts +++ b/packages/bridge-controller/src/utils/bridge.ts @@ -1,6 +1,6 @@ import { AddressZero } from '@ethersproject/constants'; import { Contract } from '@ethersproject/contracts'; -import { BtcScope, SolScope } from '@metamask/keyring-api'; +import { BtcScope, SolScope, TrxScope } from '@metamask/keyring-api'; import { abiERC20 } from '@metamask/metamask-eth-abis'; import type { CaipAssetType, CaipChainId } from '@metamask/utils'; import { isCaipChainId, isStrictHexString, type Hex } from '@metamask/utils'; @@ -190,9 +190,18 @@ export const isBitcoinChainId = ( return chainId.toString() === ChainId.BTC.toString(); }; +export const isTronChainId = ( + chainId: Hex | number | CaipChainId | string, +) => { + if (isCaipChainId(chainId)) { + return chainId === TrxScope.Mainnet.toString(); + } + return chainId.toString() === ChainId.TRON.toString(); +}; + /** * Checks if a chain ID represents a non-EVM blockchain supported by swaps - * Currently supports Solana and Bitcoin + * Currently supports Solana, Bitcoin and Tron * * @param chainId - The chain ID to check * @returns True if the chain is a supported non-EVM chain, false otherwise @@ -200,7 +209,11 @@ export const isBitcoinChainId = ( export const isNonEvmChainId = ( chainId: GenericQuoteRequest['srcChainId'], ): boolean => { - return isSolanaChainId(chainId) || isBitcoinChainId(chainId); + return ( + isSolanaChainId(chainId) || + isBitcoinChainId(chainId) || + isTronChainId(chainId) + ); }; /** diff --git a/packages/bridge-controller/src/utils/caip-formatters.ts b/packages/bridge-controller/src/utils/caip-formatters.ts index 7491ef70c45..045bbc603cc 100644 --- a/packages/bridge-controller/src/utils/caip-formatters.ts +++ b/packages/bridge-controller/src/utils/caip-formatters.ts @@ -1,7 +1,7 @@ import { getAddress } from '@ethersproject/address'; import { AddressZero } from '@ethersproject/constants'; import { convertHexToDecimal } from '@metamask/controller-utils'; -import { BtcScope, SolScope } from '@metamask/keyring-api'; +import { BtcScope, SolScope, TrxScope } from '@metamask/keyring-api'; import { toEvmCaipChainId } from '@metamask/multichain-network-controller'; import type { CaipAssetType } from '@metamask/utils'; import { @@ -21,6 +21,7 @@ import { isBitcoinChainId, isNativeAddress, isSolanaChainId, + isTronChainId, } from './bridge'; import type { GenericQuoteRequest } from '../types'; import { ChainId } from '../types'; @@ -46,6 +47,9 @@ export const formatChainIdToCaip = ( if (isBitcoinChainId(chainId)) { return BtcScope.Mainnet; } + if (isTronChainId(chainId)) { + return TrxScope.Mainnet; + } return toEvmCaipChainId(numberToHex(Number(chainId))); }; diff --git a/packages/bridge-controller/src/utils/validators.ts b/packages/bridge-controller/src/utils/validators.ts index 5d5507b6225..921587fffba 100644 --- a/packages/bridge-controller/src/utils/validators.ts +++ b/packages/bridge-controller/src/utils/validators.ts @@ -245,11 +245,29 @@ export const BitcoinTradeDataSchema = type({ inputsToSign: nullable(array(type({}))), }); +export const TronTradeDataSchema = type({ + visible: boolean(), + txID: string(), + raw_data: nullable(type({})), + raw_data_hex: string(), + payload: type({ + owner_address: string(), + call_value: number(), + contract_address: string(), + fee_limit: number(), + function_selector: string(), + parameter: string(), + chainType: number(), + }), + energyPenalty: number(), + energyUsed: number(), +}); + export const QuoteResponseSchema = type({ quote: QuoteSchema, estimatedProcessingTimeInSeconds: number(), approval: optional(TxDataSchema), - trade: union([TxDataSchema, BitcoinTradeDataSchema, string()]), + trade: union([TxDataSchema, BitcoinTradeDataSchema, TronTradeDataSchema, string()]), }); export const BitcoinQuoteResponseSchema = type({