diff --git a/advanced/dapps/react-dapp-v2/public/assets/tron.png b/advanced/dapps/react-dapp-v2/public/assets/tron.png new file mode 100644 index 000000000..7d37d203a Binary files /dev/null and b/advanced/dapps/react-dapp-v2/public/assets/tron.png differ diff --git a/advanced/dapps/react-dapp-v2/src/chains/tron.ts b/advanced/dapps/react-dapp-v2/src/chains/tron.ts index 2519e40e0..e5e762bb3 100644 --- a/advanced/dapps/react-dapp-v2/src/chains/tron.ts +++ b/advanced/dapps/react-dapp-v2/src/chains/tron.ts @@ -20,12 +20,12 @@ export const TronChainData: ChainsMap = { export const TronMetadata: NamespaceMetadata = { // Tron Mainnet "0x2b6653dc": { - logo: "https://tronscan.io/static/media/TRON.4a760cebd163969b2ee874abf2415e9a.svg", + logo: "/assets/tron.png", rgb: "183, 62, 49", }, // Tron TestNet "0xcd8690dc": { - logo: "https://tronscan.io/static/media/TRON.4a760cebd163969b2ee874abf2415e9a.svg", + logo: "assets/tron.png", rgb: "183, 62, 49", }, }; diff --git a/advanced/dapps/react-dapp-v2/src/components/Asset.tsx b/advanced/dapps/react-dapp-v2/src/components/Asset.tsx index 1bf917338..ae56df7f7 100644 --- a/advanced/dapps/react-dapp-v2/src/components/Asset.tsx +++ b/advanced/dapps/react-dapp-v2/src/components/Asset.tsx @@ -14,6 +14,7 @@ const btcLogo = getChainMetadata( "bip122:000000000933ea01ad0ee984209779ba" ).logo; const suiLogo = getChainMetadata("sui:mainnet").logo; +const tronLogo = getChainMetadata("tron:0x2b6653dc").logo; const SAsset = styled.div` width: 100%; padding: 20px; @@ -55,6 +56,8 @@ function getAssetIcon(asset: AssetData): JSX.Element { return ; case "sui": return ; + case "trx": + return ; default: return ; } diff --git a/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx b/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx index a4293272a..f0a9b29be 100644 --- a/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx +++ b/advanced/dapps/react-dapp-v2/src/contexts/JsonRpcContext.tsx @@ -1643,7 +1643,7 @@ export function JsonRpcContextProvider({ const tronWeb = getTronWeb(chainId); if (!tronWeb) { - throw new Error("Tron web not found for chainId: " + chainId); + throw new Error("TronWeb not found for chainId: " + chainId); } // Take USDT as an example: @@ -1653,7 +1653,7 @@ export function JsonRpcContextProvider({ const testContract = isTestnet ? "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf" : "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"; - const testTransaction = + const { transaction } = await tronWeb.transactionBuilder.triggerSmartContract( testContract, "approve(address,uint256)", @@ -1665,17 +1665,26 @@ export function JsonRpcContextProvider({ address ); - const result = await client!.request<{ signature: any }>({ + const sessionProperties = session!.sessionProperties; + const isV1Method = sessionProperties?.tron_method_version === "v1"; + + const result = await client!.request<{ + signature: any; + result?: { signature: any }; + }>({ chainId, topic: session!.topic, request: { method: DEFAULT_TRON_METHODS.TRON_SIGN_TRANSACTION, - params: { - address, - transaction: { - ...testTransaction, - }, - }, + params: isV1Method + ? { + address, + transaction, + } + : { + address, + transaction: { transaction }, + }, }, }); console.log("tron sign transaction result", result); @@ -1684,7 +1693,7 @@ export function JsonRpcContextProvider({ method: DEFAULT_TRON_METHODS.TRON_SIGN_TRANSACTION, address, valid: true, - result: result.signature, + result: result.result?.signature ?? result.signature, }; } ), @@ -1697,7 +1706,7 @@ export function JsonRpcContextProvider({ const tronWeb = getTronWeb(chainId); if (!tronWeb) { - throw new Error("Tron web not found for chainId: " + chainId); + throw new Error("TronWeb not found for chainId: " + chainId); } const result = await client!.request<{ signature: string }>({ @@ -1711,14 +1720,17 @@ export function JsonRpcContextProvider({ }, }, }); - const valid = await tronWeb.trx.verifyMessage( - result.signature, - message + const valid = await tronWeb.trx.verifyMessageV2( + message, + result.signature ); + + console.log("tron sign message valid", { valid, address }); + console.log("tron sign message result", result); return { method: DEFAULT_TRON_METHODS.TRON_SIGN_MESSAGE, address, - valid: valid, + valid: valid === address, result: result.signature, }; } diff --git a/advanced/dapps/react-dapp-v2/src/helpers/api.ts b/advanced/dapps/react-dapp-v2/src/helpers/api.ts index f64f51446..b7891782a 100644 --- a/advanced/dapps/react-dapp-v2/src/helpers/api.ts +++ b/advanced/dapps/react-dapp-v2/src/helpers/api.ts @@ -5,6 +5,7 @@ import { AssetData } from "./types"; import { PactCommand } from "@kadena/client"; import { apiGetBip122AccountBalance } from "./bip122"; import { getSuiClient } from "./sui"; +import { TronWeb } from "tronweb"; export type RpcProvidersByChainId = Record< number, @@ -165,6 +166,10 @@ export async function apiGetAccountBalance( return apiGetSuiAccountBalance(address, chainId); } + if (namespace === "tron") { + return apiGetTronAccountBalance(address, networkId); + } + if (namespace !== "eip155") { return { balance: "", symbol: "", name: "" }; } @@ -186,6 +191,49 @@ export async function apiGetAccountBalance( return { balance, ...token }; } +export const apiGetTronAccountBalance = async ( + address: string, + networkId: string +): Promise => { + try { + let fullHost: string; + + switch (networkId) { + case "0x2b6653dc": + fullHost = "https://api.trongrid.io"; + break; + case "0x94a9059e": + fullHost = "https://api.shasta.trongrid.io"; + break; + case "0xcd8690dc": + fullHost = "https://nile.trongrid.io"; + break; + default: + fullHost = "https://api.trongrid.io"; + } + + const tronWeb = new TronWeb({ + fullHost: fullHost, + }); + const balance = await tronWeb.trx.getBalance(address); + + const balanceInTrx = tronWeb.fromSun(balance); + + return { + balance: balanceInTrx.toString(), + symbol: "TRX", + name: "TRX", + }; + } catch (error) { + console.error("Failed to fetch TRON balance:", error); + return { + balance: "0", + symbol: "TRX", + name: "TRON", + }; + } +}; + export const apiGetSuiAccountBalance = async ( address: string, chainId: string diff --git a/advanced/dapps/react-dapp-v2/src/helpers/tron.ts b/advanced/dapps/react-dapp-v2/src/helpers/tron.ts index 5ac85b033..acb2e460c 100644 --- a/advanced/dapps/react-dapp-v2/src/helpers/tron.ts +++ b/advanced/dapps/react-dapp-v2/src/helpers/tron.ts @@ -7,15 +7,16 @@ export const getTronWeb = (network: string) => { tronWebTestnet = new TronWeb({ fullHost: "https://nile.trongrid.io/", }); - return tronWebTestnet; } + return tronWebTestnet; } if (network === "tron:0x2b6653dc") { if (!tronWebMainnet) { tronWebMainnet = new TronWeb({ fullHost: "https://api.trongrid.io/", }); - return tronWebMainnet; } + return tronWebMainnet; } + return undefined; }; diff --git a/advanced/wallets/react-wallet-v2/public/chain-logos/tron.png b/advanced/wallets/react-wallet-v2/public/chain-logos/tron.png new file mode 100644 index 000000000..7d37d203a Binary files /dev/null and b/advanced/wallets/react-wallet-v2/public/chain-logos/tron.png differ diff --git a/advanced/wallets/react-wallet-v2/src/data/TronData.ts b/advanced/wallets/react-wallet-v2/src/data/TronData.ts index 41e4d4e28..2fb08543b 100644 --- a/advanced/wallets/react-wallet-v2/src/data/TronData.ts +++ b/advanced/wallets/react-wallet-v2/src/data/TronData.ts @@ -23,7 +23,7 @@ export const TRON_MAINNET_CHAINS: TRONChains = { 'tron:0x2b6653dc': { chainId: '0x2b6653dc', name: 'Tron', - logo: 'https://tronscan.io/static/media/TRON.4a760cebd163969b2ee874abf2415e9a.svg', + logo: 'chain-logos/tron.png', rgb: '183, 62, 49', fullNode: 'https://api.trongrid.io', namespace: 'tron' @@ -34,7 +34,7 @@ export const TRON_TEST_CHAINS: TRONChains = { 'tron:0xcd8690dc': { chainId: '0xcd8690dc', name: 'Tron Testnet', - logo: 'https://tronscan.io/static/media/TRON.4a760cebd163969b2ee874abf2415e9a.svg', + logo: 'chain-logos/tron.png', rgb: '183, 62, 49', fullNode: 'https://nile.trongrid.io/', namespace: 'tron' diff --git a/advanced/wallets/react-wallet-v2/src/lib/TronLib.ts b/advanced/wallets/react-wallet-v2/src/lib/TronLib.ts index 792b4a302..2e2b2d8d5 100644 --- a/advanced/wallets/react-wallet-v2/src/lib/TronLib.ts +++ b/advanced/wallets/react-wallet-v2/src/lib/TronLib.ts @@ -50,7 +50,8 @@ export default class TronLib { } public async signTransaction(transaction: any) { - const signedtxn = await this.tronWeb.trx.sign(transaction.transaction) + // The transaction parameter is expected to be unwrapped already. + const signedtxn = await this.tronWeb.trx.sign(transaction) return signedtxn } } diff --git a/advanced/wallets/react-wallet-v2/src/utils/TronRequestHandlerUtil.ts b/advanced/wallets/react-wallet-v2/src/utils/TronRequestHandlerUtil.ts index b4421da4b..aea1c8d5d 100644 --- a/advanced/wallets/react-wallet-v2/src/utils/TronRequestHandlerUtil.ts +++ b/advanced/wallets/react-wallet-v2/src/utils/TronRequestHandlerUtil.ts @@ -30,7 +30,11 @@ export async function approveTronRequest( return formatJsonRpcResult(id, res) case TRON_SIGNING_METHODS.TRON_SIGN_TRANSACTION: - const signedTransaction = await wallet.signTransaction(request.params.transaction) + // Compatible with both new and old structures + // New structure : request.params.transaction = transaction + // Old structure: request.params.transaction = { transaction: transaction } + const transaction = request.params.transaction?.transaction || request.params.transaction + const signedTransaction = await wallet.signTransaction(transaction) return formatJsonRpcResult(id, signedTransaction) diff --git a/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx b/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx index 15749fd17..8d76b04d2 100644 --- a/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx +++ b/advanced/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx @@ -404,6 +404,12 @@ export default function SessionProposalModal() { let sessionProperties = { capabilities: JSON.stringify(capabilities) } as any + + // Add TRON-specific properties if TRON namespace exists + if (namespaces.tron) { + sessionProperties['tron_method_version'] = 'v1' + } + if (namespaces.bip122) { const bip122Chain = namespaces.bip122.chains?.[0]! sessionProperties.bip122_getAccountAddresses = JSON.stringify({