@swapkit/toolboxes 4.0.0-beta.37 → 4.0.0-beta.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import{d as k,e as D}from"../../chunk-s47y8512.js";import{AssetValue as I,Chain as X,NetworkDerivationPath as u,SKConfig as w,SwapKitError as Y,derivationPathToString as b,updateDerivationPath as p,warnOnce as K}from"@swapkit/helpers";import{P as g,match as fy}from"ts-pattern";var P=[{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"success",type:"bool"}],type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],type:"function"},{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],type:"function"}];import{TronWeb as m}from"tronweb";async function l(){return(R)=>{return m.isAddress(R)}}async function Ty({phrase:R,derivationPath:U,index:x}){let T=U||b(p(u[X.Tron],{index:x||0})),{HDKey:L}=await import("@scure/bip32"),{mnemonicToSeedSync:N}=await import("@scure/bip39"),G=N(R),$=L.fromMasterSeed(G).derive(T);if(!$.privateKey)throw new Y("toolbox_tron_no_signer");return Buffer.from($.privateKey).toString("hex")}async function _y({phrase:R,derivationPath:U}){let{HDKey:x}=await import("@scure/bip32"),{mnemonicToSeedSync:T}=await import("@scure/bip39"),L=T(R),G=x.fromMasterSeed(L).derive(U);if(!G.privateKey)throw new Y("toolbox_tron_no_signer");let Z=Buffer.from(G.privateKey).toString("hex"),$=new m({fullHost:w.get("rpcUrls")[X.Tron],privateKey:Z}),E=$.address.fromPrivateKey(Z);return{getAddress:()=>Promise.resolve(typeof E==="string"?E:""),signTransaction:async(S)=>{return await $.trx.sign(S,Z)}}}var qy=async(R={})=>{let U=w.get("rpcUrls")[X.Tron],x=void 0,T=new m({fullHost:U,headers:void 0}),L="index"in R?R.index||0:0,N=b("derivationPath"in R&&R.derivationPath?R.derivationPath:p(u[X.Tron],{index:L})),G=await fy(R).with({phrase:g.string},async({phrase:f})=>_y({phrase:f,derivationPath:N})).with({signer:g.any},({signer:f})=>Promise.resolve(f)).otherwise(()=>Promise.resolve(void 0)),Z=async()=>{if(!G)throw new Y("toolbox_tron_no_signer");return await G.getAddress()},$=()=>{return 1e8},E=268,S=13000,h=345,c=async()=>{try{let f=await T.trx.getChainParameters(),y={};for(let q of f)y[q.key]=q.value;return{energyFee:y.getEnergyFee||420,bandwidthFee:y.getTransactionFee||1000,createAccountFee:y.getCreateAccountFee||1e5}}catch{return{energyFee:420,bandwidthFee:1000,createAccountFee:1e5}}},o=async(f)=>{try{let y=await T.trx.getAccount(f);return y&&Object.keys(y).length>0}catch{return!1}},n=async(f)=>{try{let y=await T.trx.getAccountResources(f);return{bandwidth:{free:y.freeNetLimit-y.freeNetUsed,total:y.NetLimit||0,used:y.NetUsed||0},energy:{total:y.EnergyLimit||0,used:y.EnergyUsed||0}}}catch{return{bandwidth:{free:600,total:0,used:0},energy:{total:0,used:0}}}},d=async(f,y=!0)=>{let{getBalance:q}=await import("../../chunk-6f98phv2.js");try{let z=await q(X.Tron)(f,y);if(z.length>0)return z;let _=await T.trx.getBalance(f);return[I.from({chain:X.Tron,value:_,fromBaseDecimal:6})]}catch(z){K(!0,`Failed to get Tron balance for ${f}: ${z instanceof Error?z.message:z}`);try{let _=await T.trx.getBalance(f);return[I.from({chain:X.Tron,value:_,fromBaseDecimal:6})]}catch(_){return K(!0,`Failed to get native TRX balance for ${f}: ${_ instanceof Error?_.message:_}`),[]}}},t=async({recipient:f,assetValue:y,memo:q})=>{if(!G)throw new Y("toolbox_tron_no_signer");let z=await Z();if(y.isGasAsset){let O=await T.transactionBuilder.sendTrx(f,y.getBaseValue("number"),z);if(q){let C=await T.transactionBuilder.addUpdateData(O,q,"utf8"),A=await G.signTransaction(C),{txid:F}=await T.trx.sendRawTransaction(A);return F}let H=await G.signTransaction(O),{txid:B}=await T.trx.sendRawTransaction(H);return B}let j=y.address;if(!j)throw new Y("toolbox_tron_invalid_token_identifier",{identifier:y.toString()});let M=$(),J=T.contract(P,j);if(!J.methods?.transfer)throw new Y("toolbox_tron_token_transfer_failed");let Q=await J.methods.transfer(f,y.getBaseValue("string")).send({from:z,feeLimit:M,callValue:0});if(!Q)throw new Y("toolbox_tron_token_transfer_failed");return Q},i=async({assetValue:f,recipient:y,sender:q})=>{let z=f.isGasAsset;try{let _=q?q:G?await Z():void 0;if(!_)return z?I.from({chain:X.Tron,value:0.1,fromBaseDecimal:0}):I.from({chain:X.Tron,value:15,fromBaseDecimal:0});let j=await c(),J=await o(y)?0:j.createAccountFee,Q=await n(_);if(z){let V=Q.bandwidth.free+(Q.bandwidth.total-Q.bandwidth.used),v=0;if(268>V)v=(268-V)*j.bandwidthFee;let yy=J+v;return I.from({chain:X.Tron,value:yy,fromBaseDecimal:6})}let O=345,H=13000,B=Q.bandwidth.free+(Q.bandwidth.total-Q.bandwidth.used),C=Q.energy.total-Q.energy.used,A=0;if(O>B)A=(O-B)*j.bandwidthFee;let F=0;if(H>C)F=(H-C)*j.energyFee;let e=J+A+F;return I.from({chain:X.Tron,value:e,fromBaseDecimal:6})}catch(_){throw K(!0,`Failed to calculate exact fee, using conservative estimate: ${_ instanceof Error?_.message:_}`),new Y("toolbox_tron_fee_estimation_failed",{error:_})}},s=async(f)=>{let{recipient:y,assetValue:q,memo:z,sender:_}=f;if(q.isGasAsset){let J=await T.transactionBuilder.sendTrx(y,q.getBaseValue("number"),_);if(z)return T.transactionBuilder.addUpdateData(J,z,"utf8");return J}let M=q.address;if(!M)throw new Y("toolbox_tron_invalid_token_identifier",{identifier:q.toString()});try{let Q=[{type:"address",value:y},{type:"uint256",value:q.getBaseValue("string")}],O={feeLimit:$(),callValue:0};return(await T.transactionBuilder.triggerSmartContract(M,"transfer(address,uint256)",O,Q,_)).transaction}catch(J){throw new Y("toolbox_tron_transaction_creation_failed",{message:"Failed to create TRC20 transaction. This might be due to TronWeb 6.0.3 bug. Use the transfer method directly instead.",originalError:J instanceof Error?J.message:String(J)})}},a=async(f)=>{if(!G)throw new Y("toolbox_tron_no_signer");return await G.signTransaction(f)},r=async(f)=>{let{txid:y}=await T.trx.sendRawTransaction(f);return y};return{tronWeb:T,getAddress:Z,validateAddress:await l(),getBalance:d,transfer:t,estimateTransactionFee:i,createTransaction:s,signTransaction:a,broadcastTransaction:r}};export{P as trc20ABI,Ty as getTronPrivateKeyFromMnemonic,l as getTronAddressValidator,qy as createTronToolbox};
1
+ import{d as N,e as m}from"../../chunk-s47y8512.js";import{AssetValue as H,Chain as U,NetworkDerivationPath as b,SKConfig as l,SwapKitError as O,derivationPathToString as h,updateDerivationPath as o,warnOnce as V}from"@swapkit/helpers";import{P as u,match as Q2}from"ts-pattern";var T=[{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"success",type:"bool"}],type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],type:"function"},{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],type:"function"}];import{SwapKitError as q2}from"@swapkit/helpers";import{TronWeb as z2}from"tronweb";var J2="https://api.trongrid.io";async function p(Z){try{let j=await fetch(`${J2}/v1/accounts/${Z}`);if(!j.ok)throw new Error(`TronGrid API error: ${j.status} ${j.statusText}`);let M=await j.json();if(!(M.success&&M.data)||M.data.length===0)throw new Error("Invalid response from TronGrid API");let z;try{z=z2.address.toHex(Z).toLowerCase()}catch{z=Z.toLowerCase()}let I=M.data.find((B)=>{return B.address.toLowerCase()===z});if(!I)return;return{balance:I.balance,trc20:I.trc20||[]}}catch(j){throw new q2("toolbox_tron_trongrid_api_error",{message:j instanceof Error?j.message:"Unknown error",address:Z})}}import{TronWeb as g}from"tronweb";var Z2=268,$2=13000,X2=345,A="TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";async function c(){return(Z)=>{return g.isAddress(Z)}}async function Y2({phrase:Z,derivationPath:j,index:M}){let z=j||h(o(b[U.Tron],{index:M||0})),{HDKey:I}=await import("@scure/bip32"),{mnemonicToSeedSync:B}=await import("@scure/bip39"),G=B(Z),_=I.fromMasterSeed(G).derive(z);if(!_.privateKey)throw new O("toolbox_tron_no_signer");return Buffer.from(_.privateKey).toString("hex")}async function j2({phrase:Z,derivationPath:j}){let{HDKey:M}=await import("@scure/bip32"),{mnemonicToSeedSync:z}=await import("@scure/bip39"),I=z(Z),G=M.fromMasterSeed(I).derive(j);if(!G.privateKey)throw new O("toolbox_tron_no_signer");let k=Buffer.from(G.privateKey).toString("hex"),_=new g({fullHost:l.get("rpcUrls")[U.Tron],privateKey:k}),C=_.address.fromPrivateKey(k);return{getAddress:()=>Promise.resolve(typeof C==="string"?C:""),signTransaction:async(v)=>{return await _.trx.sign(v,k)}}}var G2=async(Z={})=>{let j=l.get("rpcUrls")[U.Tron],M=void 0,z=new g({fullHost:j,headers:void 0}),I="index"in Z?Z.index||0:0,B=h("derivationPath"in Z&&Z.derivationPath?Z.derivationPath:o(b[U.Tron],{index:I})),G=await Q2(Z).with({phrase:u.string},async({phrase:f})=>j2({phrase:f,derivationPath:B})).with({signer:u.any},({signer:f})=>Promise.resolve(f)).otherwise(()=>Promise.resolve(void 0)),k=async()=>{if(!G)throw new O("toolbox_tron_no_signer");return await G.getAddress()},_=()=>{return 1e8},C=async()=>{try{let f=await z.trx.getChainParameters(),y={};for(let q of f)y[q.key]=q.value;return{energyFee:y.getEnergyFee||420,bandwidthFee:y.getTransactionFee||1000,createAccountFee:y.getCreateAccountFee||1e5}}catch{return{energyFee:420,bandwidthFee:1000,createAccountFee:1e5}}},v=async(f)=>{try{let y=await z.trx.getAccount(f);return y&&Object.keys(y).length>0}catch{return!1}},W=async(f)=>{try{let y=await z.trx.getAccountResources(f);return{bandwidth:{free:y.freeNetLimit-y.freeNetUsed,total:y.NetLimit||0,used:y.NetUsed||0},energy:{total:y.EnergyLimit||0,used:y.EnergyUsed||0}}}catch{return{bandwidth:{free:600,total:0,used:0},energy:{total:0,used:0}}}},i=async(f,y)=>{try{let q=z.contract(T,y);if(!q.methods?.balanceOf)return 0n;let Q=(await q.methods.balanceOf(f).call())[0];return BigInt(Q||0)}catch(q){return console.warn(`balanceOf() failed for ${y}:`,q),0n}},n=async(f,y)=>{try{z.setAddress(y);let q=z.contract(T,f),[Q,J]=await Promise.all([q.symbol().call().catch(()=>"UNKNOWN"),q.decimals().call().catch(()=>"18")]);return{symbol:Q??"UNKNOWN",decimals:Number(J??18)}}catch(q){return V(!0,`Failed to get token balance for ${f}: ${q instanceof Error?q.message:q}`),null}},d=async(f,y=!0)=>{let q=[H.from({chain:U.Tron})];try{let Q=await p(f);if(Q){let J=[];J.push(H.from({chain:U.Tron,value:Q.balance,fromBaseDecimal:6}));for(let Y of Q.trc20){let[L,X]=Object.entries(Y)[0]||[];if(!(L&&X))continue;let $=await n(L,f);if(!$)continue;J.push(H.from({asset:`TRX.${$.symbol}-${L}`,value:BigInt(X||0),fromBaseDecimal:$.decimals}))}return J}return q}catch(Q){V(!0,`Tron API getBalance failed: ${Q instanceof Error?Q.message:Q}`);let J=[],Y=await z.trx.getBalance(f);if(Y&&Number(Y)>0)J.push(H.from({chain:U.Tron,value:Y,fromBaseDecimal:6}));let L=await i(f,A);if(L)J.push(H.from({asset:`TRX.USDT-${A}`,value:L,fromBaseDecimal:6}));return J}},t=async({recipient:f,assetValue:y,memo:q})=>{if(!G)throw new O("toolbox_tron_no_signer");let Q=await k();if(y.isGasAsset){let x=await z.transactionBuilder.sendTrx(f,y.getBaseValue("number"),Q);if(q){let P=await z.transactionBuilder.addUpdateData(x,q,"utf8"),R=await G.signTransaction(P),{txid:E}=await z.trx.sendRawTransaction(R);return E}let F=await G.signTransaction(x),{txid:D}=await z.trx.sendRawTransaction(F);return D}let Y=y.address;if(!Y)throw new O("toolbox_tron_invalid_token_identifier",{identifier:y.toString()});let L=_(),X=z.contract(T,Y);if(!X.methods?.transfer)throw new O("toolbox_tron_token_transfer_failed");let $=await X.methods.transfer(f,y.getBaseValue("string")).send({from:Q,feeLimit:L,callValue:0});if(!$)throw new O("toolbox_tron_token_transfer_failed");return $},s=async({assetValue:f,recipient:y,sender:q})=>{let Q=f.isGasAsset;try{let J=q?q:G?await k():void 0;if(!J)return Q?H.from({chain:U.Tron,value:0.1,fromBaseDecimal:0}):H.from({chain:U.Tron,value:15,fromBaseDecimal:0});let Y=await C(),X=await v(y)?0:Y.createAccountFee,$=await W(J);if(Q){let K=Z2,S=$.bandwidth.free+($.bandwidth.total-$.bandwidth.used),w=0;if(K>S)w=(K-S)*Y.bandwidthFee;let f2=X+w;return H.from({chain:U.Tron,value:f2,fromBaseDecimal:6})}let x=X2,F=$2,D=$.bandwidth.free+($.bandwidth.total-$.bandwidth.used),P=$.energy.total-$.energy.used,R=0;if(x>D)R=(x-D)*Y.bandwidthFee;let E=0;if(F>P)E=(F-P)*Y.energyFee;let y2=X+R+E;return H.from({chain:U.Tron,value:y2,fromBaseDecimal:6})}catch(J){throw V(!0,`Failed to calculate exact fee, using conservative estimate: ${J instanceof Error?J.message:J}`),new O("toolbox_tron_fee_estimation_failed",{error:J})}},r=async(f)=>{let{recipient:y,assetValue:q,memo:Q,sender:J}=f;if(q.isGasAsset){let X=await z.transactionBuilder.sendTrx(y,q.getBaseValue("number"),J);if(Q)return z.transactionBuilder.addUpdateData(X,Q,"utf8");return X}let L=q.address;if(!L)throw new O("toolbox_tron_invalid_token_identifier",{identifier:q.toString()});try{let $=[{type:"address",value:y},{type:"uint256",value:q.getBaseValue("string")}],x={feeLimit:_(),callValue:0};return(await z.transactionBuilder.triggerSmartContract(L,"transfer(address,uint256)",x,$,J)).transaction}catch(X){throw new O("toolbox_tron_transaction_creation_failed",{message:"Failed to create TRC20 transaction. This might be due to TronWeb 6.0.3 bug. Use the transfer method directly instead.",originalError:X instanceof Error?X.message:String(X)})}},a=async(f)=>{if(!G)throw new O("toolbox_tron_no_signer");return await G.signTransaction(f)},e=async(f)=>{let{txid:y}=await z.trx.sendRawTransaction(f);return y};return{tronWeb:z,getAddress:k,validateAddress:await c(),getBalance:d,transfer:t,estimateTransactionFee:s,createTransaction:r,signTransaction:a,broadcastTransaction:e}};export{T as trc20ABI,Y2 as getTronPrivateKeyFromMnemonic,c as getTronAddressValidator,G2 as createTronToolbox};
2
2
 
3
- //# debugId=EED46AFEC48D42F464756E2164756E21
3
+ //# debugId=59C8476FFA1F925764756E2164756E21
4
4
  //# sourceMappingURL=index.js.map
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/tron/toolbox.ts", "../src/tron/helpers/trc20.abi.ts"],
3
+ "sources": ["../src/tron/toolbox.ts", "../src/tron/helpers/trc20.abi.ts", "../src/tron/helpers/trongrid.ts"],
4
4
  "sourcesContent": [
5
- "import {\n AssetValue,\n Chain,\n NetworkDerivationPath,\n SKConfig,\n SwapKitError,\n derivationPathToString,\n updateDerivationPath,\n warnOnce,\n} from \"@swapkit/helpers\";\nimport { P, match } from \"ts-pattern\";\n\nimport { trc20ABI } from \"./helpers/trc20.abi.js\";\nimport type {\n TronCreateTransactionParams,\n TronSignedTransaction,\n TronSigner,\n TronToolboxOptions,\n TronTransaction,\n TronTransferParams,\n} from \"./types.js\";\n\nimport { TronWeb } from \"tronweb\";\n\nexport async function getTronAddressValidator() {\n return (address: string) => {\n return TronWeb.isAddress(address);\n };\n}\n\nexport async function getTronPrivateKeyFromMnemonic({\n phrase,\n derivationPath: customPath,\n index,\n}: {\n phrase: string;\n derivationPath?: string;\n index?: number;\n}) {\n const derivationPathToUse =\n customPath ||\n derivationPathToString(\n updateDerivationPath(NetworkDerivationPath[Chain.Tron], {\n index: index || 0,\n }),\n );\n\n const { HDKey } = await import(\"@scure/bip32\");\n const { mnemonicToSeedSync } = await import(\"@scure/bip39\");\n\n const seed = mnemonicToSeedSync(phrase);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(derivationPathToUse);\n\n if (!derived.privateKey) {\n throw new SwapKitError(\"toolbox_tron_no_signer\");\n }\n\n return Buffer.from(derived.privateKey).toString(\"hex\");\n}\n\nasync function createKeysForPath({\n phrase,\n derivationPath,\n}: {\n phrase: string;\n derivationPath: string;\n}) {\n const { HDKey } = await import(\"@scure/bip32\");\n const { mnemonicToSeedSync } = await import(\"@scure/bip39\");\n\n const seed = mnemonicToSeedSync(phrase);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(derivationPath);\n\n if (!derived.privateKey) {\n throw new SwapKitError(\"toolbox_tron_no_signer\");\n }\n\n // Convert private key to hex string for TronWeb\n const privateKeyHex = Buffer.from(derived.privateKey).toString(\"hex\");\n\n // Create TronWeb instance with the derived private key\n const tronWebWithKey = new TronWeb({\n fullHost: SKConfig.get(\"rpcUrls\")[Chain.Tron],\n privateKey: privateKeyHex,\n });\n\n const address = tronWebWithKey.address.fromPrivateKey(privateKeyHex);\n\n return {\n getAddress: () => Promise.resolve(typeof address === \"string\" ? address : \"\"),\n signTransaction: async (transaction: TronTransaction) => {\n const signedTx = await tronWebWithKey.trx.sign(transaction, privateKeyHex);\n return signedTx;\n },\n };\n}\n\nexport const createTronToolbox = async (options: TronToolboxOptions = {}) => {\n // Always get configuration from SKConfig\n const rpcUrl = SKConfig.get(\"rpcUrls\")[Chain.Tron];\n // Note: TRON API key support can be added to SKConfig apiKeys when needed\n const headers = undefined; // No API key needed for basic TronGrid access\n\n const tronWeb = new TronWeb({\n fullHost: rpcUrl,\n headers,\n });\n\n // Handle derivation path and index\n const index = \"index\" in options ? options.index || 0 : 0;\n const derivationPath = derivationPathToString(\n \"derivationPath\" in options && options.derivationPath\n ? options.derivationPath\n : updateDerivationPath(NetworkDerivationPath[Chain.Tron], { index }),\n );\n\n // Create signer based on options using pattern matching\n const signer: TronSigner | undefined = await match(options)\n .with({ phrase: P.string }, async ({ phrase }) => createKeysForPath({ phrase, derivationPath }))\n .with({ signer: P.any }, ({ signer }) => Promise.resolve(signer as TronSigner))\n .otherwise(() => Promise.resolve(undefined));\n\n const getAddress = async () => {\n if (!signer) throw new SwapKitError(\"toolbox_tron_no_signer\");\n return await signer.getAddress();\n };\n\n const calculateFeeLimit = () => {\n return 100_000_000; // 100 TRX in SUN\n };\n\n // Constants for TRON resource calculation\n const TRX_TRANSFER_BANDWIDTH = 268; // Bandwidth consumed by a TRX transfer\n const TRC20_TRANSFER_ENERGY = 13000; // Average energy consumed by TRC20 transfer\n const TRC20_TRANSFER_BANDWIDTH = 345; // Bandwidth consumed by TRC20 transfer\n\n /**\n * Get current chain parameters including resource prices\n */\n const getChainParameters = async () => {\n try {\n const parameters = await tronWeb.trx.getChainParameters();\n const paramMap: Record<string, number> = {};\n\n for (const param of parameters) {\n paramMap[param.key] = param.value;\n }\n\n return {\n energyFee: paramMap.getEnergyFee || 420, // SUN per energy unit\n bandwidthFee: paramMap.getTransactionFee || 1000, // SUN per bandwidth unit\n createAccountFee: paramMap.getCreateAccountFee || 100000, // 0.1 TRX in SUN\n };\n } catch {\n // Return default values if unable to fetch\n return {\n energyFee: 420,\n bandwidthFee: 1000,\n createAccountFee: 100000,\n };\n }\n };\n\n /**\n * Check if an address exists on the blockchain\n */\n const accountExists = async (address: string) => {\n try {\n const account = await tronWeb.trx.getAccount(address);\n return account && Object.keys(account).length > 0;\n } catch {\n return false;\n }\n };\n\n /**\n * Get account resources (bandwidth and energy)\n */\n const getAccountResources = async (address: string) => {\n try {\n const resources = await tronWeb.trx.getAccountResources(address);\n\n return {\n bandwidth: {\n free: resources.freeNetLimit - resources.freeNetUsed,\n total: resources.NetLimit || 0,\n used: resources.NetUsed || 0,\n },\n energy: {\n total: resources.EnergyLimit || 0,\n used: resources.EnergyUsed || 0,\n },\n };\n } catch {\n // Return default structure if unable to fetch\n return {\n bandwidth: { free: 600, total: 0, used: 0 }, // 600 free bandwidth daily\n energy: { total: 0, used: 0 },\n };\n }\n };\n\n const getBalance = async (address: string, scamFilter = true) => {\n const { getBalance: getBalanceFromApi } = await import(\"../utils.js\");\n\n try {\n // Use SwapKit API for comprehensive balance fetching (includes TRX + TRC20 tokens)\n const apiBalances = await getBalanceFromApi(Chain.Tron)(address, scamFilter);\n\n // If API returns balances, use those\n if (apiBalances.length > 0) {\n return apiBalances;\n }\n\n // Fallback to on-chain TRX balance if API fails or returns empty\n const trxBalanceInSun = await tronWeb.trx.getBalance(address);\n return [\n AssetValue.from({\n chain: Chain.Tron,\n value: trxBalanceInSun,\n fromBaseDecimal: 6, // TRX has 6 decimals\n }),\n ];\n } catch (error) {\n warnOnce(\n true,\n `Failed to get Tron balance for ${address}: ${error instanceof Error ? error.message : error}`,\n );\n\n // Final fallback: try to get just the native TRX balance\n try {\n const trxBalanceInSun = await tronWeb.trx.getBalance(address);\n return [\n AssetValue.from({\n chain: Chain.Tron,\n value: trxBalanceInSun,\n fromBaseDecimal: 6,\n }),\n ];\n } catch (fallbackError) {\n warnOnce(\n true,\n `Failed to get native TRX balance for ${address}: ${fallbackError instanceof Error ? fallbackError.message : fallbackError}`,\n );\n return [];\n }\n }\n };\n\n const transfer = async ({ recipient, assetValue, memo }: TronTransferParams) => {\n if (!signer) throw new SwapKitError(\"toolbox_tron_no_signer\");\n\n const from = await getAddress();\n const isNative = assetValue.isGasAsset;\n\n if (isNative) {\n // Native TRX Transfer (amount in SUN - base units)\n const transaction = await tronWeb.transactionBuilder.sendTrx(\n recipient,\n assetValue.getBaseValue(\"number\"),\n from,\n );\n\n // Add memo if provided\n if (memo) {\n const transactionWithMemo = await tronWeb.transactionBuilder.addUpdateData(\n transaction,\n memo,\n \"utf8\",\n );\n const signedTx = await signer.signTransaction(transactionWithMemo);\n const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);\n return txid;\n }\n\n const signedTx = await signer.signTransaction(transaction);\n const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);\n return txid;\n }\n\n // TRC20 Token Transfer\n const contractAddress = assetValue.address;\n if (!contractAddress) {\n throw new SwapKitError(\"toolbox_tron_invalid_token_identifier\", {\n identifier: assetValue.toString(),\n });\n }\n\n const feeLimit = calculateFeeLimit();\n const contract = tronWeb.contract(trc20ABI, contractAddress);\n\n if (!contract.methods?.transfer) {\n throw new SwapKitError(\"toolbox_tron_token_transfer_failed\");\n }\n\n const txid = await contract.methods\n .transfer(recipient, assetValue.getBaseValue(\"string\"))\n .send({\n from,\n feeLimit,\n callValue: 0,\n });\n\n if (!txid) {\n throw new SwapKitError(\"toolbox_tron_token_transfer_failed\");\n }\n\n return txid;\n };\n\n const estimateTransactionFee = async ({\n assetValue,\n recipient,\n sender,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>\n }: TronTransferParams & { sender?: string }) => {\n const isNative = assetValue.isGasAsset;\n\n try {\n // Get sender address\n const senderAddress = sender ? sender : signer ? await getAddress() : undefined;\n if (!senderAddress) {\n // If no signer, return conservative estimate\n return isNative\n ? AssetValue.from({ chain: Chain.Tron, value: 0.1, fromBaseDecimal: 0 })\n : AssetValue.from({ chain: Chain.Tron, value: 15, fromBaseDecimal: 0 });\n }\n\n // Get chain parameters for current resource prices\n const chainParams = await getChainParameters();\n\n // Check if recipient account exists (new accounts require activation fee)\n const recipientExists = await accountExists(recipient);\n const activationFee = recipientExists ? 0 : chainParams.createAccountFee;\n\n // Get account resources\n const resources = await getAccountResources(senderAddress);\n\n if (isNative) {\n // Calculate bandwidth needed for TRX transfer\n const bandwidthNeeded = TRX_TRANSFER_BANDWIDTH;\n const availableBandwidth =\n resources.bandwidth.free + (resources.bandwidth.total - resources.bandwidth.used);\n\n let bandwidthFee = 0;\n if (bandwidthNeeded > availableBandwidth) {\n // Need to burn TRX for bandwidth\n const bandwidthToBuy = bandwidthNeeded - availableBandwidth;\n bandwidthFee = bandwidthToBuy * chainParams.bandwidthFee;\n }\n\n // Total fee in SUN\n const totalFeeSun = activationFee + bandwidthFee;\n\n return AssetValue.from({\n chain: Chain.Tron,\n value: totalFeeSun,\n fromBaseDecimal: 6, // SUN to TRX\n });\n }\n\n // TRC20 Transfer - needs both bandwidth and energy\n const bandwidthNeeded = TRC20_TRANSFER_BANDWIDTH;\n const energyNeeded = TRC20_TRANSFER_ENERGY;\n\n const availableBandwidth =\n resources.bandwidth.free + (resources.bandwidth.total - resources.bandwidth.used);\n const availableEnergy = resources.energy.total - resources.energy.used;\n\n let bandwidthFee = 0;\n if (bandwidthNeeded > availableBandwidth) {\n const bandwidthToBuy = bandwidthNeeded - availableBandwidth;\n bandwidthFee = bandwidthToBuy * chainParams.bandwidthFee;\n }\n\n let energyFee = 0;\n if (energyNeeded > availableEnergy) {\n const energyToBuy = energyNeeded - availableEnergy;\n energyFee = energyToBuy * chainParams.energyFee;\n }\n\n // Total fee in SUN\n const totalFeeSun = activationFee + bandwidthFee + energyFee;\n\n return AssetValue.from({\n chain: Chain.Tron,\n value: totalFeeSun,\n fromBaseDecimal: 6, // SUN to TRX\n });\n } catch (error) {\n // Fallback to conservative estimates if calculation fails\n warnOnce(\n true,\n `Failed to calculate exact fee, using conservative estimate: ${error instanceof Error ? error.message : error}`,\n );\n\n throw new SwapKitError(\"toolbox_tron_fee_estimation_failed\", { error });\n }\n };\n\n const createTransaction = async (params: TronCreateTransactionParams) => {\n const { recipient, assetValue, memo, sender } = params;\n const isNative = assetValue.isGasAsset;\n\n if (isNative) {\n const transaction = await tronWeb.transactionBuilder.sendTrx(\n recipient,\n assetValue.getBaseValue(\"number\"),\n sender,\n );\n\n if (memo) {\n return tronWeb.transactionBuilder.addUpdateData(transaction, memo, \"utf8\");\n }\n\n return transaction;\n }\n\n // For TRC20, we would need to build the transaction manually\n // This is a simplified version - in practice, you'd build the contract call transaction\n const contractAddress = assetValue.address;\n if (!contractAddress) {\n throw new SwapKitError(\"toolbox_tron_invalid_token_identifier\", {\n identifier: assetValue.toString(),\n });\n }\n\n // Build TRC20 transfer transaction\n // First, try using triggerSmartContract (might work despite the known bug)\n try {\n const functionSelector = \"transfer(address,uint256)\";\n const parameter = [\n { type: \"address\", value: recipient },\n { type: \"uint256\", value: assetValue.getBaseValue(\"string\") },\n ];\n\n const options = {\n feeLimit: calculateFeeLimit(),\n callValue: 0,\n };\n\n const result = await tronWeb.transactionBuilder.triggerSmartContract(\n contractAddress,\n functionSelector,\n options,\n parameter,\n sender,\n );\n\n return result.transaction;\n } catch (error) {\n // If both methods fail, throw a descriptive error\n throw new SwapKitError(\"toolbox_tron_transaction_creation_failed\", {\n message:\n \"Failed to create TRC20 transaction. This might be due to TronWeb 6.0.3 bug. Use the transfer method directly instead.\",\n originalError: error instanceof Error ? error.message : String(error),\n });\n }\n };\n\n const signTransaction = async (transaction: TronTransaction) => {\n if (!signer) throw new SwapKitError(\"toolbox_tron_no_signer\");\n return await signer.signTransaction(transaction);\n };\n\n const broadcastTransaction = async (signedTx: TronSignedTransaction) => {\n const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);\n return txid;\n };\n\n return {\n tronWeb,\n getAddress,\n validateAddress: await getTronAddressValidator(),\n getBalance,\n transfer,\n estimateTransactionFee,\n createTransaction,\n signTransaction,\n broadcastTransaction,\n };\n};\n",
6
- "export const trc20ABI = [\n {\n constant: true,\n inputs: [{ name: \"_owner\", type: \"address\" }],\n name: \"balanceOf\",\n outputs: [{ name: \"balance\", type: \"uint256\" }],\n type: \"function\",\n },\n {\n constant: false,\n inputs: [\n { name: \"_to\", type: \"address\" },\n { name: \"_value\", type: \"uint256\" },\n ],\n name: \"transfer\",\n outputs: [{ name: \"success\", type: \"bool\" }],\n type: \"function\",\n },\n {\n constant: true,\n inputs: [],\n name: \"decimals\",\n outputs: [{ name: \"\", type: \"uint8\" }],\n type: \"function\",\n },\n {\n constant: true,\n inputs: [],\n name: \"symbol\",\n outputs: [{ name: \"\", type: \"string\" }],\n type: \"function\",\n },\n {\n constant: true,\n inputs: [],\n name: \"name\",\n outputs: [{ name: \"\", type: \"string\" }],\n type: \"function\",\n },\n] as const;\n"
5
+ "import {\n AssetValue,\n Chain,\n NetworkDerivationPath,\n SKConfig,\n SwapKitError,\n derivationPathToString,\n updateDerivationPath,\n warnOnce,\n} from \"@swapkit/helpers\";\nimport { P, match } from \"ts-pattern\";\n\nimport { trc20ABI } from \"./helpers/trc20.abi.js\";\nimport { fetchAccountFromTronGrid } from \"./helpers/trongrid.js\";\nimport type {\n TronCreateTransactionParams,\n TronSignedTransaction,\n TronSigner,\n TronToolboxOptions,\n TronTransaction,\n TronTransferParams,\n} from \"./types.js\";\n\nimport { TronWeb } from \"tronweb\";\n\n// Constants for TRON resource calculation\nconst TRX_TRANSFER_BANDWIDTH = 268; // Bandwidth consumed by a TRX transfer\nconst TRC20_TRANSFER_ENERGY = 13000; // Average energy consumed by TRC20 transfer\nconst TRC20_TRANSFER_BANDWIDTH = 345; // Bandwidth consumed by TRC20 transfer\n\n// Known TRON tokens\nconst TRON_USDT_CONTRACT = \"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t\";\n\nexport async function getTronAddressValidator() {\n return (address: string) => {\n return TronWeb.isAddress(address);\n };\n}\n\nexport async function getTronPrivateKeyFromMnemonic({\n phrase,\n derivationPath: customPath,\n index,\n}: {\n phrase: string;\n derivationPath?: string;\n index?: number;\n}) {\n const derivationPathToUse =\n customPath ||\n derivationPathToString(\n updateDerivationPath(NetworkDerivationPath[Chain.Tron], {\n index: index || 0,\n }),\n );\n\n const { HDKey } = await import(\"@scure/bip32\");\n const { mnemonicToSeedSync } = await import(\"@scure/bip39\");\n\n const seed = mnemonicToSeedSync(phrase);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(derivationPathToUse);\n\n if (!derived.privateKey) {\n throw new SwapKitError(\"toolbox_tron_no_signer\");\n }\n\n return Buffer.from(derived.privateKey).toString(\"hex\");\n}\n\nasync function createKeysForPath({\n phrase,\n derivationPath,\n}: {\n phrase: string;\n derivationPath: string;\n}) {\n const { HDKey } = await import(\"@scure/bip32\");\n const { mnemonicToSeedSync } = await import(\"@scure/bip39\");\n\n const seed = mnemonicToSeedSync(phrase);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(derivationPath);\n\n if (!derived.privateKey) {\n throw new SwapKitError(\"toolbox_tron_no_signer\");\n }\n\n // Convert private key to hex string for TronWeb\n const privateKeyHex = Buffer.from(derived.privateKey).toString(\"hex\");\n\n // Create TronWeb instance with the derived private key\n const tronWebWithKey = new TronWeb({\n fullHost: SKConfig.get(\"rpcUrls\")[Chain.Tron],\n privateKey: privateKeyHex,\n });\n\n const address = tronWebWithKey.address.fromPrivateKey(privateKeyHex);\n\n return {\n getAddress: () => Promise.resolve(typeof address === \"string\" ? address : \"\"),\n signTransaction: async (transaction: TronTransaction) => {\n const signedTx = await tronWebWithKey.trx.sign(transaction, privateKeyHex);\n return signedTx;\n },\n };\n}\n\nexport const createTronToolbox = async (options: TronToolboxOptions = {}) => {\n // Always get configuration from SKConfig\n const rpcUrl = SKConfig.get(\"rpcUrls\")[Chain.Tron];\n // Note: TRON API key support can be added to SKConfig apiKeys when needed\n const headers = undefined; // No API key needed for basic TronGrid access\n\n const tronWeb = new TronWeb({\n fullHost: rpcUrl,\n headers,\n });\n\n // Handle derivation path and index\n const index = \"index\" in options ? options.index || 0 : 0;\n const derivationPath = derivationPathToString(\n \"derivationPath\" in options && options.derivationPath\n ? options.derivationPath\n : updateDerivationPath(NetworkDerivationPath[Chain.Tron], { index }),\n );\n\n // Create signer based on options using pattern matching\n const signer: TronSigner | undefined = await match(options)\n .with({ phrase: P.string }, async ({ phrase }) => createKeysForPath({ phrase, derivationPath }))\n .with({ signer: P.any }, ({ signer }) => Promise.resolve(signer as TronSigner))\n .otherwise(() => Promise.resolve(undefined));\n\n const getAddress = async () => {\n if (!signer) throw new SwapKitError(\"toolbox_tron_no_signer\");\n return await signer.getAddress();\n };\n\n const calculateFeeLimit = () => {\n return 100_000_000; // 100 TRX in SUN\n };\n\n /**\n * Get current chain parameters including resource prices\n */\n const getChainParameters = async () => {\n try {\n const parameters = await tronWeb.trx.getChainParameters();\n const paramMap: Record<string, number> = {};\n\n for (const param of parameters) {\n paramMap[param.key] = param.value;\n }\n\n return {\n energyFee: paramMap.getEnergyFee || 420, // SUN per energy unit\n bandwidthFee: paramMap.getTransactionFee || 1000, // SUN per bandwidth unit\n createAccountFee: paramMap.getCreateAccountFee || 100000, // 0.1 TRX in SUN\n };\n } catch {\n // Return default values if unable to fetch\n return {\n energyFee: 420,\n bandwidthFee: 1000,\n createAccountFee: 100000,\n };\n }\n };\n\n /**\n * Check if an address exists on the blockchain\n */\n const accountExists = async (address: string) => {\n try {\n const account = await tronWeb.trx.getAccount(address);\n return account && Object.keys(account).length > 0;\n } catch {\n return false;\n }\n };\n\n /**\n * Get account resources (bandwidth and energy)\n */\n const getAccountResources = async (address: string) => {\n try {\n const resources = await tronWeb.trx.getAccountResources(address);\n\n return {\n bandwidth: {\n free: resources.freeNetLimit - resources.freeNetUsed,\n total: resources.NetLimit || 0,\n used: resources.NetUsed || 0,\n },\n energy: {\n total: resources.EnergyLimit || 0,\n used: resources.EnergyUsed || 0,\n },\n };\n } catch {\n // Return default structure if unable to fetch\n return {\n bandwidth: { free: 600, total: 0, used: 0 }, // 600 free bandwidth daily\n energy: { total: 0, used: 0 },\n };\n }\n };\n\n /**\n * Get token balance and info directly from contract\n */\n const fetchTokenBalance = async (address: string, contractAddress: string) => {\n try {\n const contract = tronWeb.contract(trc20ABI, contractAddress);\n\n if (!contract.methods?.balanceOf) {\n return 0n;\n }\n\n const balance = (await contract.methods.balanceOf(address).call())[0] as string;\n\n return BigInt(balance || 0); // Convert to BigInt for consistency\n } catch (err) {\n console.warn(`balanceOf() failed for ${contractAddress}:`, err);\n return 0n;\n }\n };\n\n /**\n * Get token balance and info directly from contract\n */\n const fetchTokenMetadata = async (contractAddress: string, address: string) => {\n try {\n tronWeb.setAddress(address); // Set address for contract calls\n const contract = tronWeb.contract(trc20ABI, contractAddress);\n\n const [symbolRaw, decimalsRaw] = await Promise.all([\n contract\n .symbol()\n .call()\n .catch(() => \"UNKNOWN\"),\n contract\n .decimals()\n .call()\n .catch(() => \"18\"),\n ]);\n\n return {\n symbol: symbolRaw ?? \"UNKNOWN\",\n decimals: Number(decimalsRaw ?? 18),\n };\n } catch (error) {\n warnOnce(\n true,\n `Failed to get token balance for ${contractAddress}: ${error instanceof Error ? error.message : error}`,\n );\n return null;\n }\n };\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>\n const getBalance = async (address: string, _scamFilter = true) => {\n const fallbackBalance = [\n AssetValue.from({\n chain: Chain.Tron,\n }),\n ];\n // Try primary source (TronGrid)\n try {\n const accountData = await fetchAccountFromTronGrid(address);\n if (accountData) {\n const balances: AssetValue[] = [];\n\n // Add TRX balance\n balances.push(\n AssetValue.from({\n chain: Chain.Tron,\n value: accountData.balance,\n fromBaseDecimal: 6,\n }),\n );\n\n // Add TRC20 balances\n\n for (const token of accountData.trc20) {\n const [contractAddress, balance] = Object.entries(token)[0] || [];\n\n if (!(contractAddress && balance)) continue;\n\n const tokenMetaData = await fetchTokenMetadata(contractAddress, address);\n\n if (!tokenMetaData) continue;\n\n balances.push(\n AssetValue.from({\n asset: `TRX.${tokenMetaData.symbol}-${contractAddress}`,\n value: BigInt(balance || 0),\n fromBaseDecimal: tokenMetaData.decimals,\n }),\n );\n }\n\n return balances;\n }\n return fallbackBalance;\n } catch (error) {\n warnOnce(\n true,\n `Tron API getBalance failed: ${error instanceof Error ? error.message : error}`,\n );\n\n // Fallback: get TRX and USDT directly\n const balances: AssetValue[] = [];\n\n const trxBalanceInSun = await tronWeb.trx.getBalance(address);\n if (trxBalanceInSun && Number(trxBalanceInSun) > 0) {\n balances.push(\n AssetValue.from({\n chain: Chain.Tron,\n value: trxBalanceInSun,\n fromBaseDecimal: 6,\n }),\n );\n }\n\n const usdtBalance = await fetchTokenBalance(address, TRON_USDT_CONTRACT);\n if (usdtBalance) {\n balances.push(\n AssetValue.from({\n asset: `TRX.USDT-${TRON_USDT_CONTRACT}`,\n value: usdtBalance,\n fromBaseDecimal: 6,\n }),\n );\n }\n\n return balances;\n }\n };\n\n const transfer = async ({ recipient, assetValue, memo }: TronTransferParams) => {\n if (!signer) throw new SwapKitError(\"toolbox_tron_no_signer\");\n\n const from = await getAddress();\n const isNative = assetValue.isGasAsset;\n\n if (isNative) {\n // Native TRX Transfer (amount in SUN - base units)\n const transaction = await tronWeb.transactionBuilder.sendTrx(\n recipient,\n assetValue.getBaseValue(\"number\"),\n from,\n );\n\n // Add memo if provided\n if (memo) {\n const transactionWithMemo = await tronWeb.transactionBuilder.addUpdateData(\n transaction,\n memo,\n \"utf8\",\n );\n const signedTx = await signer.signTransaction(transactionWithMemo);\n const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);\n return txid;\n }\n\n const signedTx = await signer.signTransaction(transaction);\n const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);\n return txid;\n }\n\n // TRC20 Token Transfer\n const contractAddress = assetValue.address;\n if (!contractAddress) {\n throw new SwapKitError(\"toolbox_tron_invalid_token_identifier\", {\n identifier: assetValue.toString(),\n });\n }\n\n const feeLimit = calculateFeeLimit();\n const contract = tronWeb.contract(trc20ABI, contractAddress);\n\n if (!contract.methods?.transfer) {\n throw new SwapKitError(\"toolbox_tron_token_transfer_failed\");\n }\n\n const txid = await contract.methods\n .transfer(recipient, assetValue.getBaseValue(\"string\"))\n .send({\n from,\n feeLimit,\n callValue: 0,\n });\n\n if (!txid) {\n throw new SwapKitError(\"toolbox_tron_token_transfer_failed\");\n }\n\n return txid;\n };\n\n const estimateTransactionFee = async ({\n assetValue,\n recipient,\n sender,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>\n }: TronTransferParams & { sender?: string }) => {\n const isNative = assetValue.isGasAsset;\n\n try {\n // Get sender address\n const senderAddress = sender ? sender : signer ? await getAddress() : undefined;\n if (!senderAddress) {\n // If no signer, return conservative estimate\n return isNative\n ? AssetValue.from({ chain: Chain.Tron, value: 0.1, fromBaseDecimal: 0 })\n : AssetValue.from({ chain: Chain.Tron, value: 15, fromBaseDecimal: 0 });\n }\n\n // Get chain parameters for current resource prices\n const chainParams = await getChainParameters();\n\n // Check if recipient account exists (new accounts require activation fee)\n const recipientExists = await accountExists(recipient);\n const activationFee = recipientExists ? 0 : chainParams.createAccountFee;\n\n // Get account resources\n const resources = await getAccountResources(senderAddress);\n\n if (isNative) {\n // Calculate bandwidth needed for TRX transfer\n const bandwidthNeeded = TRX_TRANSFER_BANDWIDTH;\n const availableBandwidth =\n resources.bandwidth.free + (resources.bandwidth.total - resources.bandwidth.used);\n\n let bandwidthFee = 0;\n if (bandwidthNeeded > availableBandwidth) {\n // Need to burn TRX for bandwidth\n const bandwidthToBuy = bandwidthNeeded - availableBandwidth;\n bandwidthFee = bandwidthToBuy * chainParams.bandwidthFee;\n }\n\n // Total fee in SUN\n const totalFeeSun = activationFee + bandwidthFee;\n\n return AssetValue.from({\n chain: Chain.Tron,\n value: totalFeeSun,\n fromBaseDecimal: 6, // SUN to TRX\n });\n }\n\n // TRC20 Transfer - needs both bandwidth and energy\n const bandwidthNeeded = TRC20_TRANSFER_BANDWIDTH;\n const energyNeeded = TRC20_TRANSFER_ENERGY;\n\n const availableBandwidth =\n resources.bandwidth.free + (resources.bandwidth.total - resources.bandwidth.used);\n const availableEnergy = resources.energy.total - resources.energy.used;\n\n let bandwidthFee = 0;\n if (bandwidthNeeded > availableBandwidth) {\n const bandwidthToBuy = bandwidthNeeded - availableBandwidth;\n bandwidthFee = bandwidthToBuy * chainParams.bandwidthFee;\n }\n\n let energyFee = 0;\n if (energyNeeded > availableEnergy) {\n const energyToBuy = energyNeeded - availableEnergy;\n energyFee = energyToBuy * chainParams.energyFee;\n }\n\n // Total fee in SUN\n const totalFeeSun = activationFee + bandwidthFee + energyFee;\n\n return AssetValue.from({\n chain: Chain.Tron,\n value: totalFeeSun,\n fromBaseDecimal: 6, // SUN to TRX\n });\n } catch (error) {\n // Fallback to conservative estimates if calculation fails\n warnOnce(\n true,\n `Failed to calculate exact fee, using conservative estimate: ${error instanceof Error ? error.message : error}`,\n );\n\n throw new SwapKitError(\"toolbox_tron_fee_estimation_failed\", { error });\n }\n };\n\n const createTransaction = async (params: TronCreateTransactionParams) => {\n const { recipient, assetValue, memo, sender } = params;\n const isNative = assetValue.isGasAsset;\n\n if (isNative) {\n const transaction = await tronWeb.transactionBuilder.sendTrx(\n recipient,\n assetValue.getBaseValue(\"number\"),\n sender,\n );\n\n if (memo) {\n return tronWeb.transactionBuilder.addUpdateData(transaction, memo, \"utf8\");\n }\n\n return transaction;\n }\n\n // For TRC20, we would need to build the transaction manually\n // This is a simplified version - in practice, you'd build the contract call transaction\n const contractAddress = assetValue.address;\n if (!contractAddress) {\n throw new SwapKitError(\"toolbox_tron_invalid_token_identifier\", {\n identifier: assetValue.toString(),\n });\n }\n\n // Build TRC20 transfer transaction\n // First, try using triggerSmartContract (might work despite the known bug)\n try {\n const functionSelector = \"transfer(address,uint256)\";\n const parameter = [\n { type: \"address\", value: recipient },\n { type: \"uint256\", value: assetValue.getBaseValue(\"string\") },\n ];\n\n const options = {\n feeLimit: calculateFeeLimit(),\n callValue: 0,\n };\n\n const result = await tronWeb.transactionBuilder.triggerSmartContract(\n contractAddress,\n functionSelector,\n options,\n parameter,\n sender,\n );\n\n return result.transaction;\n } catch (error) {\n // If both methods fail, throw a descriptive error\n throw new SwapKitError(\"toolbox_tron_transaction_creation_failed\", {\n message:\n \"Failed to create TRC20 transaction. This might be due to TronWeb 6.0.3 bug. Use the transfer method directly instead.\",\n originalError: error instanceof Error ? error.message : String(error),\n });\n }\n };\n\n const signTransaction = async (transaction: TronTransaction) => {\n if (!signer) throw new SwapKitError(\"toolbox_tron_no_signer\");\n return await signer.signTransaction(transaction);\n };\n\n const broadcastTransaction = async (signedTx: TronSignedTransaction) => {\n const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);\n return txid;\n };\n\n return {\n tronWeb,\n getAddress,\n validateAddress: await getTronAddressValidator(),\n getBalance,\n transfer,\n estimateTransactionFee,\n createTransaction,\n signTransaction,\n broadcastTransaction,\n };\n};\n",
6
+ "export const trc20ABI = [\n {\n constant: true,\n inputs: [{ name: \"_owner\", type: \"address\" }],\n name: \"balanceOf\",\n outputs: [{ name: \"balance\", type: \"uint256\" }],\n type: \"function\",\n },\n {\n constant: false,\n inputs: [\n { name: \"_to\", type: \"address\" },\n { name: \"_value\", type: \"uint256\" },\n ],\n name: \"transfer\",\n outputs: [{ name: \"success\", type: \"bool\" }],\n type: \"function\",\n },\n {\n constant: true,\n inputs: [],\n name: \"decimals\",\n outputs: [{ name: \"\", type: \"uint8\" }],\n type: \"function\",\n },\n {\n constant: true,\n inputs: [],\n name: \"symbol\",\n outputs: [{ name: \"\", type: \"string\" }],\n type: \"function\",\n },\n {\n constant: true,\n inputs: [],\n name: \"name\",\n outputs: [{ name: \"\", type: \"string\" }],\n type: \"function\",\n },\n] as const;\n",
7
+ "import { SwapKitError } from \"@swapkit/helpers\";\nimport { TronWeb } from \"tronweb\";\nimport type { TronGridAccountResponse } from \"../types.js\";\n\nconst TRONGRID_API_BASE = \"https://api.trongrid.io\";\n\n/**\n * Fetch account information including TRC20 balances from TronGrid API\n */\nexport async function fetchAccountFromTronGrid(address: string) {\n try {\n const response = await fetch(`${TRONGRID_API_BASE}/v1/accounts/${address}`);\n\n if (!response.ok) {\n throw new Error(`TronGrid API error: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as TronGridAccountResponse;\n\n if (!(data.success && data.data) || data.data.length === 0) {\n throw new Error(\"Invalid response from TronGrid API\");\n }\n\n // Convert search address to hex format for comparison\n let searchAddressHex: string;\n try {\n // If address is base58, convert to hex\n searchAddressHex = TronWeb.address.toHex(address).toLowerCase();\n } catch {\n // If conversion fails, assume it's already hex\n searchAddressHex = address.toLowerCase();\n }\n\n // Find the account that matches the requested address\n const account = data.data.find((acc) => {\n return acc.address.toLowerCase() === searchAddressHex;\n });\n\n if (!account) {\n return;\n }\n\n // Return simplified object with balance and trc20 array\n return {\n balance: account.balance,\n trc20: account.trc20 || [],\n };\n } catch (error) {\n throw new SwapKitError(\"toolbox_tron_trongrid_api_error\", {\n message: error instanceof Error ? error.message : \"Unknown error\",\n address,\n });\n }\n}\n"
7
8
  ],
8
- "mappings": "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",
9
- "debugId": "EED46AFEC48D42F464756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "59C8476FFA1F925764756E2164756E21",
10
11
  "names": []
11
12
  }
@@ -1,4 +1,4 @@
1
- import{a as DX,b as AX}from"../../chunk-6f98phv2.js";import"../../chunk-s47y8512.js";import{Chain as E,SwapKitError as aZ}from"@swapkit/helpers";import{Transaction as xZ,TransactionBuilder as gZ,address as mZ}from"@psf/bitcoincashjs-lib";import{Chain as lZ,FeeOption as hZ,NetworkDerivationPath as cZ,SwapKitError as K,derivationPathToString as uZ,updateDerivationPath as pZ}from"@swapkit/helpers";import{Psbt as oZ}from"bitcoinjs-lib";import{Chain as Y,RequestClient as l,SKConfig as h,SwapKitError as N,warnOnce as UX}from"@swapkit/helpers";import{networks as xX}from"bitcoinjs-lib";import S from"coininfo";async function gX({chain:X,txHash:Z}){let G=h.get("rpcUrls")[X],J=JSON.stringify({jsonrpc:"2.0",method:"sendrawtransaction",params:[Z],id:DX()}),Q=await l.post(G,{headers:{"Content-Type":"application/json"},body:J});if(Q.error)throw new N("toolbox_utxo_broadcast_failed",{error:Q.error?.message});if(Q.result.includes('"code":-26'))throw new N("toolbox_utxo_invalid_transaction",{error:"Transaction amount was too low"});return Q.result}function a(X){return`https://api.blockchair.com/${mX(X)}`}function BX(X){switch(X){case Y.Bitcoin:return 5;case Y.Dogecoin:return 1e4;case Y.Litecoin:return 1;case Y.Zcash:return 1;default:return 2}}function mX(X){switch(X){case Y.BitcoinCash:return"bitcoin-cash";case Y.Litecoin:return"litecoin";case Y.Dash:return"dash";case Y.Dogecoin:return"dogecoin";case Y.Zcash:return"zcash";case Y.Polkadot:return"polkadot";default:return"bitcoin"}}async function lX(X){try{let{feePerKb:Z}=await l.get(`https://app.bitgo.com/api/v2/${X.toLowerCase()}/tx/fee`),G=Z/1000;return Math.max(G,BX(X))}catch(Z){return BX(X)}}async function s(X,Z){try{let G=await l.get(X);if(!G||G.context.code!==200)throw new N("toolbox_utxo_api_error",{error:`Failed to query ${X}`});return G.data}catch(G){if(!Z)throw G;let J=await l.get(`${X}${Z?`&key=${Z}`:""}`);if(!J||J.context.code!==200)throw new N("toolbox_utxo_api_error",{error:`Failed to query ${X}`});return J.data}}async function zX({address:X,chain:Z,apiKey:G}){if(!X)throw new N("toolbox_utxo_invalid_params",{error:"Address is required"});try{return(await s(`${a(Z)}/dashboards/address/${X}?transaction_details=true`,G))[X]}catch(J){return{utxo:[],address:{balance:0,transaction_count:0}}}}async function hX({address:X,chain:Z,apiKey:G}){return(await zX({address:X,chain:Z,apiKey:G}))?.address.balance||0}async function MX({chain:X,apiKey:Z,txHash:G}){if(!G)throw new N("toolbox_utxo_invalid_params",{error:"TxHash is required"});try{return(await s(`${a(X)}/raw/transaction/${G}`,Z))?.[G]?.raw_transaction||""}catch(J){return console.error("Failed to fetch raw transaction:",J),""}}async function cX({chain:X,address:Z,apiKey:G,offset:J=0,limit:Q=100}){return(await s(`${a(X)}/outputs?q=is_spent(false),recipient(${Z})&limit=${Q}&offset=${J}`,G)).filter(({is_spent:W})=>!W).map(({script_hex:W,block_id:q,transaction_hash:j,index:B,value:U,spending_signature_hex:D})=>({hash:j,index:B,value:U,txHex:D,script_hex:W,is_confirmed:q!==-1}))}async function TX({chain:X,address:Z,apiKey:G,offset:J=0,limit:Q=100}){if(!Z)throw new N("toolbox_utxo_invalid_params",{error:"Address is required"});try{let L=await cX({chain:X,address:Z,apiKey:G,offset:J,limit:Q});if(L.length<=Q)return L;let $=await TX({chain:X,address:Z,apiKey:G,offset:J+Q,limit:Q});return[...L,...$]}catch(L){return console.error("Failed to fetch unspent UTXOs:",L),[]}}async function uX({address:X,chain:Z,apiKey:G,fetchTxHex:J=!0}){let Q=await TX({chain:Z,address:X,apiKey:G}),L=[];for(let{hash:$,index:W,script_hex:q,value:j}of Q){let B;if(J)B=await MX({txHash:$,chain:Z,apiKey:G});L.push({address:X,hash:$,index:W,txHex:B,value:j,witnessUtxo:{value:j,script:Buffer.from(q,"hex")}})}return L}function pX(X){let Z=h.get("apiKeys").blockchair||"";return UX(!Z,"No Blockchair API key found. Functionality will be limited."),{broadcastTx:(G)=>gX({txHash:G,chain:X}),getRawTx:(G)=>MX({txHash:G,chain:X,apiKey:Z}),getSuggestedTxFee:()=>lX(X),getBalance:(G)=>hX({address:G,chain:X,apiKey:Z}),getAddressData:(G)=>zX({address:G,chain:X,apiKey:Z}),scanUTXOs:(G)=>uX({...G,chain:X,apiKey:Z})}}function ZG(X){return X}function _(X){let Z=h.get("apis")[X];if(Z)return UX(!0,"Using custom UTXO API. Be sure to implement all methods to avoid issues."),Z;return pX(X)}var oX={messagePrefix:`\x19Zcash Signed Message:
1
+ import{a as DX,b as AX}from"../../chunk-0h4xdrwz.js";import"../../chunk-s47y8512.js";import{Chain as E,SwapKitError as aZ}from"@swapkit/helpers";import{Transaction as xZ,TransactionBuilder as gZ,address as mZ}from"@psf/bitcoincashjs-lib";import{Chain as lZ,FeeOption as hZ,NetworkDerivationPath as cZ,SwapKitError as K,derivationPathToString as uZ,updateDerivationPath as pZ}from"@swapkit/helpers";import{Psbt as oZ}from"bitcoinjs-lib";import{Chain as Y,RequestClient as l,SKConfig as h,SwapKitError as N,warnOnce as UX}from"@swapkit/helpers";import{networks as xX}from"bitcoinjs-lib";import S from"coininfo";async function gX({chain:X,txHash:Z}){let G=h.get("rpcUrls")[X],J=JSON.stringify({jsonrpc:"2.0",method:"sendrawtransaction",params:[Z],id:DX()}),Q=await l.post(G,{headers:{"Content-Type":"application/json"},body:J});if(Q.error)throw new N("toolbox_utxo_broadcast_failed",{error:Q.error?.message});if(Q.result.includes('"code":-26'))throw new N("toolbox_utxo_invalid_transaction",{error:"Transaction amount was too low"});return Q.result}function a(X){return`https://api.blockchair.com/${mX(X)}`}function BX(X){switch(X){case Y.Bitcoin:return 5;case Y.Dogecoin:return 1e4;case Y.Litecoin:return 1;case Y.Zcash:return 1;default:return 2}}function mX(X){switch(X){case Y.BitcoinCash:return"bitcoin-cash";case Y.Litecoin:return"litecoin";case Y.Dash:return"dash";case Y.Dogecoin:return"dogecoin";case Y.Zcash:return"zcash";case Y.Polkadot:return"polkadot";default:return"bitcoin"}}async function lX(X){try{let{feePerKb:Z}=await l.get(`https://app.bitgo.com/api/v2/${X.toLowerCase()}/tx/fee`),G=Z/1000;return Math.max(G,BX(X))}catch(Z){return BX(X)}}async function s(X,Z){try{let G=await l.get(X);if(!G||G.context.code!==200)throw new N("toolbox_utxo_api_error",{error:`Failed to query ${X}`});return G.data}catch(G){if(!Z)throw G;let J=await l.get(`${X}${Z?`&key=${Z}`:""}`);if(!J||J.context.code!==200)throw new N("toolbox_utxo_api_error",{error:`Failed to query ${X}`});return J.data}}async function zX({address:X,chain:Z,apiKey:G}){if(!X)throw new N("toolbox_utxo_invalid_params",{error:"Address is required"});try{return(await s(`${a(Z)}/dashboards/address/${X}?transaction_details=true`,G))[X]}catch(J){return{utxo:[],address:{balance:0,transaction_count:0}}}}async function hX({address:X,chain:Z,apiKey:G}){return(await zX({address:X,chain:Z,apiKey:G}))?.address.balance||0}async function MX({chain:X,apiKey:Z,txHash:G}){if(!G)throw new N("toolbox_utxo_invalid_params",{error:"TxHash is required"});try{return(await s(`${a(X)}/raw/transaction/${G}`,Z))?.[G]?.raw_transaction||""}catch(J){return console.error("Failed to fetch raw transaction:",J),""}}async function cX({chain:X,address:Z,apiKey:G,offset:J=0,limit:Q=100}){return(await s(`${a(X)}/outputs?q=is_spent(false),recipient(${Z})&limit=${Q}&offset=${J}`,G)).filter(({is_spent:W})=>!W).map(({script_hex:W,block_id:q,transaction_hash:j,index:B,value:U,spending_signature_hex:D})=>({hash:j,index:B,value:U,txHex:D,script_hex:W,is_confirmed:q!==-1}))}async function TX({chain:X,address:Z,apiKey:G,offset:J=0,limit:Q=100}){if(!Z)throw new N("toolbox_utxo_invalid_params",{error:"Address is required"});try{let L=await cX({chain:X,address:Z,apiKey:G,offset:J,limit:Q});if(L.length<=Q)return L;let $=await TX({chain:X,address:Z,apiKey:G,offset:J+Q,limit:Q});return[...L,...$]}catch(L){return console.error("Failed to fetch unspent UTXOs:",L),[]}}async function uX({address:X,chain:Z,apiKey:G,fetchTxHex:J=!0}){let Q=await TX({chain:Z,address:X,apiKey:G}),L=[];for(let{hash:$,index:W,script_hex:q,value:j}of Q){let B;if(J)B=await MX({txHash:$,chain:Z,apiKey:G});L.push({address:X,hash:$,index:W,txHex:B,value:j,witnessUtxo:{value:j,script:Buffer.from(q,"hex")}})}return L}function pX(X){let Z=h.get("apiKeys").blockchair||"";return UX(!Z,"No Blockchair API key found. Functionality will be limited."),{broadcastTx:(G)=>gX({txHash:G,chain:X}),getRawTx:(G)=>MX({txHash:G,chain:X,apiKey:Z}),getSuggestedTxFee:()=>lX(X),getBalance:(G)=>hX({address:G,chain:X,apiKey:Z}),getAddressData:(G)=>zX({address:G,chain:X,apiKey:Z}),scanUTXOs:(G)=>uX({...G,chain:X,apiKey:Z})}}function ZG(X){return X}function _(X){let Z=h.get("apis")[X];if(Z)return UX(!0,"Using custom UTXO API. Be sure to implement all methods to avoid issues."),Z;return pX(X)}var oX={messagePrefix:`\x19Zcash Signed Message:
2
2
  `,bech32:"zc",bip32:{public:76067358,private:76066276},pubKeyHash:28,scriptHash:28,wif:128},nX={messagePrefix:`\x19Zcash Signed Message:
3
3
  `,bech32:"ztestsapling",bip32:{public:70617039,private:70615956},pubKeyHash:29,scriptHash:28,wif:239};function C(){return function X(Z){switch(Z){case Y.Bitcoin:return xX.bitcoin;case Y.BitcoinCash:return S.bitcoincash.main.toBitcoinJS();case Y.Dash:return S.dash.main.toBitcoinJS();case Y.Litecoin:return S.litecoin.main.toBitcoinJS();case Y.Dogecoin:{let G={private:70615956,public:70617039},J=S.dogecoin.test;return J.versions.bip32=G,S.dogecoin.main.toBitcoinJS()}case Y.Zcash:{let{isStagenet:G}=h.get("envs");return G?nX:oX}default:throw new N("toolbox_utxo_not_supported",{chain:Z})}}}import{SwapKitError as R}from"@swapkit/helpers";import HX from"bs58check";import CX from"cashaddrjs";var vX;((G)=>{G.Mainnet="mainnet";G.Testnet="testnet"})(vX||={});var z={["legacy"]:{["mainnet"]:{["p2pkh"]:0,["p2sh"]:5},["testnet"]:{["p2pkh"]:111,["p2sh"]:196}},["bitpay"]:{["mainnet"]:{["p2pkh"]:28,["p2sh"]:40},["testnet"]:{["p2pkh"]:111,["p2sh"]:196}}};function IX(X){try{return u(X),!0}catch(Z){return!1}}function _X(X){return u(X)?.network}function x(X){let Z=u(X);if(Z?.format==="legacy")return X;return iX(Z)}function c(X){let Z=u(X);return aX(Z)}function u(X){try{return dX(X)}catch(Z){}try{return rX(X)}catch(Z){}throw new R("toolbox_utxo_invalid_address",{address:X})}function dX(X){try{let Z=HX.decode(X);if(Z.length!==21)throw new R("toolbox_utxo_invalid_address",{address:X});let G=Z[0],J=Array.prototype.slice.call(Z,1);switch(G){case z.legacy.mainnet.p2pkh:return{hash:J,format:"legacy",network:"mainnet",type:"p2pkh"};case z.legacy.mainnet.p2sh:return{hash:J,format:"legacy",network:"mainnet",type:"p2sh"};case z.legacy.testnet.p2pkh:return{hash:J,format:"legacy",network:"testnet",type:"p2pkh"};case z.legacy.testnet.p2sh:return{hash:J,format:"legacy",network:"testnet",type:"p2sh"};case z.bitpay.mainnet.p2pkh:return{hash:J,format:"bitpay",network:"mainnet",type:"p2pkh"};case z.bitpay.mainnet.p2sh:return{hash:J,format:"bitpay",network:"mainnet",type:"p2sh"};default:throw new R("toolbox_utxo_invalid_address",{address:X})}}catch(Z){throw new R("toolbox_utxo_invalid_address",{address:X})}}function rX(X){if(X.indexOf(":")!==-1)try{return YX(X)}catch(Z){}else{let Z=["bitcoincash","bchtest","bchreg"];for(let G of Z)try{return YX(`${G}:${X}`)}catch(J){}}throw new R("toolbox_utxo_invalid_address",{address:X})}function YX(X){try{let{hash:Z,prefix:G,type:J}=CX.decode(X);return{format:"cashaddr",hash:Array.prototype.slice.call(Z,0),network:G==="bitcoincash"?"mainnet":"testnet",type:J==="P2PKH"?"p2pkh":"p2sh"}}catch(Z){throw new R("toolbox_utxo_invalid_address",{address:X})}}function iX(X){let Z=z.legacy[X.network][X.type],G=Buffer.alloc(1+X.hash.length);return G[0]=Z,G.set(X.hash,1),HX.encode(G)}function aX(X){let Z=X.network==="mainnet"?"bitcoincash":"bchtest",G=X.type==="p2pkh"?"P2PKH":"P2SH",J=new Uint8Array(X.hash);return CX.encode(Z,G,J)}import{Chain as P,SwapKitError as sX}from"@swapkit/helpers";var t=(X)=>{switch(X){case P.Bitcoin:case P.BitcoinCash:return 550;case P.Dash:case P.Litecoin:return 5500;case P.Dogecoin:return 1e5;case P.Zcash:return 546;default:throw new sX("toolbox_utxo_not_supported",{chain:X})}},k=({inputs:X,outputs:Z,feeRate:G=1,chain:J=P.Bitcoin})=>{let Q=Math.ceil(G),L=X[0]&&"address"in X[0]&&X[0].address?o(X[0].address):"P2PKH",$=X.filter((D)=>V(D)*Q<=D.value),W=e+Z.reduce((D,T)=>D+p(T,L),0),q=Z.reduce((D,T)=>D+T.value,0),j=W*Q,B=0,U=[];for(let D of $){let T=V(D),M=Q*T;j+=M,B+=D.value,U.push(D);let H=j+q;if(B<H)continue;let O=B-H,WX=Q*p({address:"",value:0},L);if(O>WX){let qX=WX+j,jX=B-(q+qX);if(jX>Math.max(V({})*Q,t(J)))return{inputs:U,outputs:Z.concat({value:jX,address:""}),fee:qX}}return{inputs:U,outputs:Z,fee:j}}return{fee:Q*g({inputs:X,outputs:Z,feeRate:Q})}};import{SwapKitError as tX}from"@swapkit/helpers";import{opcodes as eX,script as XZ}from"bitcoinjs-lib";var UG=1000,e=10,ZZ=10,GZ=41,JZ=107;function A(X){let Z=Buffer.from(X,"utf8");return XZ.compile([eX.OP_RETURN,Z])}var XX;((G)=>{G.P2PKH="P2PKH";G.P2WPKH="P2WPKH"})(XX||={});var ZX={["P2PKH"]:148,["P2WPKH"]:68},n={["P2PKH"]:34,["P2WPKH"]:31},o=(X)=>{if(X.startsWith("bc1")||X.startsWith("ltc1"))return"P2WPKH";if(X.startsWith("1")||X.startsWith("3")||X.startsWith("L")||X.startsWith("M")||X.startsWith("X")||X.startsWith("D")||X.startsWith("bitcoincash:q")||X.startsWith("q"))return"P2PKH";throw new tX("toolbox_utxo_invalid_address",{address:X})},g=({inputs:X,outputs:Z,feeRate:G})=>{let J=X[0]&&"address"in X[0]&&X[0].address?o(X[0].address):"P2PKH",Q=X.filter(($)=>$.value>=ZX["type"in $?$.type:"P2PKH"]*Math.ceil(G)).reduce(($,W)=>$+V(W),0),L=Z?.reduce(($,W)=>$+p(W),0)||n[J];return e+Q+L},V=(X)=>{if("type"in X)return ZX[X.type];if("address"in X&&X.address)return ZX[o(X.address)];return GZ+JZ},p=(X,Z)=>{if(X?.script)return ZZ+X.script.length+(X.script.length>=74?2:1);if(Z)return n[Z];return n.P2PKH};import{AssetValue as $X,Chain as v,DerivationPath as IZ,FeeOption as y,NetworkDerivationPath as _Z,SwapKitError as F,SwapKitNumber as FZ,applyFeeMultiplier as PX,derivationPathToString as OZ,updateDerivationPath as NZ}from"@swapkit/helpers";import{Psbt as yZ,address as PZ,initEccLib as RX,payments as VX}from"bitcoinjs-lib";import{ECPairFactory as VZ}from"ecpair";import LX from"@bitcoinerlab/secp256k1";import{ECPair as kZ,HDNode as AZ}from"@psf/bitcoincashjs-lib";import{HDKey as RZ}from"@scure/bip32";import{mnemonicToSeedSync as kX}from"@scure/bip39";import QZ from"@bitcoinerlab/secp256k1";import{HDKey as $Z}from"@scure/bip32";import{mnemonicToSeedSync as LZ}from"@scure/bip39";import{Chain as JX,FeeOption as WZ,NetworkDerivationPath as qZ,SKConfig as FX,SwapKitError as jZ,derivationPathToString as BZ,updateDerivationPath as DZ}from"@swapkit/helpers";import{hash160 as UZ}from"bitcoinjs-lib/src/crypto";import OX from"bs58check";import{ECPairFactory as zZ}from"ecpair";import{P as GX,match as MZ}from"ts-pattern";var TZ=JX.Zcash,NX=C()(TZ);function YZ(X,Z=!1){let G=UZ(X),J=Z?Buffer.from([28,186]):Buffer.from([28,184]),Q=Buffer.concat([J,G]);return OX.encode(Q)}function QX(X){try{if(X.startsWith("z"))return console.warn("Shielded Zcash addresses (z-addresses) are not supported. Use transparent addresses (t1/t3) only."),!1;let Z=X.startsWith("t1"),G=X.startsWith("t3");if(!(Z||G))return!1;let{isStagenet:J}=FX.get("envs");if(Z&&J||G&&!J)return!1;return HZ(X,NX)}catch{return!1}}function HZ(X,Z){try{let G=OX.decode(X);if(G.length<21)return!1;let J=G[0];return J===Z.pubKeyHash||J===Z.scriptHash}catch{return!1}}var CZ=zZ(QZ);async function vZ({phrase:X,derivationPathString:Z}){let G=LZ(X),Q=$Z.fromMasterSeed(G).derive(Z);if(!Q.privateKey)throw new Error("Unable to derive private key");let L=CZ.fromPrivateKey(Buffer.from(Q.privateKey),{network:NX}),{isStagenet:$}=FX.get("envs"),W=YZ(L.publicKey,$);return{getAddress(){return Promise.resolve(W)},signTransaction(q){for(let j=0;j<q.inputCount;j++)q.signInput(j,L);return Promise.resolve(q)}}}async function yX(X){let Z=await MZ(X).with({signer:GX.not(GX.nullish)},({signer:W})=>Promise.resolve(W)).with({phrase:GX.string},({phrase:W,derivationPath:q,index:j=0})=>{let B=q||qZ[JX.Zcash]||[44,133,0,0,0],U=DZ(B,{index:j}),D=BZ(U);return vZ({phrase:W,derivationPathString:D})}).otherwise(()=>Promise.resolve(void 0)),{getFeeRates:G,broadcastTx:J,...Q}=await b({chain:JX.Zcash,signer:Z});function L(W){return W.getAddress()}async function $({recipient:W,assetValue:q,feeOptionKey:j=WZ.Fast,...B}){let U=await Z?.getAddress();if(!(Z&&U))throw new jZ("toolbox_utxo_no_signer");let D=B.feeRate||(await G())[j],T={...B,assetValue:q,feeRate:D,recipient:W,sender:U},{psbt:M}=await Q.createTransaction(T),H=await Z.signTransaction(M);H.finalizeAllInputs();let O=H.extractTransaction().toHex();return J(O)}return{...Q,broadcastTx:J,getFeeRates:G,transfer:$,getAddressFromKeys:L,validateAddress:QX}}var d=[v.Dash,v.Dogecoin];function bZ({inputs:X,outputs:Z,chain:G,psbt:J,sender:Q,compiledMemo:L}){for(let $ of X){let W=!!$.witnessUtxo&&!d.includes(G)&&{witnessUtxo:$.witnessUtxo},q=d.includes(G)&&{nonWitnessUtxo:$.txHex?Buffer.from($.txHex,"hex"):void 0};J.addInput({hash:$.hash,index:$.index,...W,...q})}for(let $ of Z){let W="address"in $&&$.address?$.address:Q,q=$.script;if(q&&!L)continue;let j=q?{script:L,value:0}:{address:W,value:$.value};RX(LX),J.addOutput(j)}return{psbt:J,inputs:X}}async function bX({assetValue:X,recipient:Z,memo:G,feeRate:J,sender:Q,fetchTxHex:L=!1}){let $=X.chain,W=G?await A(G):null,q=await fX({assetValue:X,recipient:Z,memo:G,sender:Q,fetchTxHex:L}),{inputs:j,outputs:B}=k({...q,feeRate:J,chain:$});if(!(j&&B))throw new F("toolbox_utxo_insufficient_balance",{sender:Q,assetValue:X});let U=await C(),D=new yZ({network:U($)});if($===v.Dogecoin)D.setMaximumFeeRate(650000000);let{psbt:T,inputs:M}=await bZ({inputs:j,outputs:B,chain:$,psbt:D,sender:Q,compiledMemo:W});return{psbt:T,utxos:q.inputs,inputs:M}}async function wZ(){let X=await C();return function Z({address:G,chain:J}){if(J===v.BitcoinCash)return w(G);if(J===v.Zcash)return QX(G);try{return RX(LX),PZ.toOutputScript(G,X(J)),!0}catch(Q){return!1}}}async function KZ({chain:X,phrase:Z,derivationPath:G}){let J=(await r(X))({phrase:Z,derivationPath:G});async function Q($){return await $.signAllInputs(J),$}async function L(){return(await KX(X))(J)}return{getAddress:L,signTransaction:Q}}async function b({chain:X,...Z}){let G="phrase"in Z?Z.phrase:void 0,J="index"in Z?Z.index||0:0,Q=OZ("derivationPath"in Z&&Z.derivationPath?Z.derivationPath:NZ(_Z[X],{index:J})),L=G?await KZ({chain:X,phrase:G,derivationPath:Q}):("signer"in Z)?Z.signer:void 0;function $(){return Promise.resolve(L?.getAddress())}let W=await KX(X),q=await wZ(),j=await r(X);return{accumulative:k,calculateTxSize:g,getAddressFromKeys:W,getAddress:$,validateAddress:(B)=>q({address:B,chain:X}),broadcastTx:(B)=>_(X).broadcastTx(B),createTransaction:bX,createKeysForPath:j,getFeeRates:()=>i(X),getInputsOutputsFee:wX,transfer:SZ(L),getPrivateKeyFromMnemonic:(B)=>{return j(B).toWIF()},getBalance:AX(X),estimateTransactionFee:EZ(X),estimateMaxSendableAmount:fZ(X)}}async function wX({assetValue:X,feeOptionKey:Z=y.Fast,feeRate:G,memo:J,sender:Q,recipient:L}){let $=X.chain,W=await fX({assetValue:X,sender:Q,memo:J,recipient:L}),q=G?Math.floor(G):(await i($))[Z];return k({...W,feeRate:q,chain:$})}function fZ(X){return async function Z({from:G,memo:J,feeRate:Q,feeOptionKey:L=y.Fast,recipients:$=1}){let W=await _(X).getAddressData(G),q=Q?Math.ceil(Q):(await i(X))[L],j=W?.utxo.map((M)=>({...M,type:"P2PKH",hash:""})).filter((M)=>M.value>Math.max(t(X),V(M)*q));if(!j?.length)return $X.from({chain:X});let B=$X.from({chain:X,value:j.reduce((M,H)=>M+H.value,0)}),U=typeof $==="number"?Array.from({length:$},()=>({address:G,value:0})):$;if(J){let M=await A(J);U.push({address:G,script:M,value:0})}let T=g({inputs:j,outputs:U,feeRate:q})*q;return B.sub(T)}}function EZ(X){return async(Z)=>{let G=await wX(Z);return $X.from({chain:X,value:FZ.fromBigInt(BigInt(G.fee),8).getValue("string")})}}async function r(X){let Z=await C();switch(X){case v.BitcoinCash:return function G({phrase:J,derivationPath:Q=`${IZ.BCH}/0`,wif:L}){let $=Z(X);if(L)return kZ.fromWIF(L,$);if(!J)throw new F("toolbox_utxo_invalid_params",{error:"No phrase provided"});return AZ.fromSeedBuffer(Buffer.from(kX(J)),$).derivePath(Q).keyPair};case v.Bitcoin:case v.Dogecoin:case v.Litecoin:case v.Zcash:case v.Dash:return function G({phrase:J,wif:Q,derivationPath:L}){if(!(Q||J))throw new F("toolbox_utxo_invalid_params",{error:"Either phrase or wif must be provided"});let $=VZ(LX),W=Z(X);if(Q)return $.fromWIF(Q,W);let q=kX(J),j=RZ.fromMasterSeed(q,W).derive(L);if(!j.privateKey)throw new F("toolbox_utxo_invalid_params",{error:"Could not get private key from phrase"});return $.fromPrivateKey(Buffer.from(j.privateKey),{network:W})};default:throw new F("toolbox_utxo_not_supported",{chain:X})}}async function KX(X){let Z=await C();return function G(J){if(!J)throw new F("toolbox_utxo_invalid_params",{error:"Keys must be provided"});let Q=d.includes(X)?VX.p2pkh:VX.p2wpkh,{address:L}=Q({pubkey:J.publicKey,network:Z(X)});if(!L)throw new F("toolbox_utxo_invalid_address",{error:"Address not defined"});return L}}function SZ(X){return async function Z({memo:G,recipient:J,feeOptionKey:Q,feeRate:L,assetValue:$}){let W=await X?.getAddress(),q=$.chain;if(!(X&&W))throw new F("toolbox_utxo_no_signer");if(!J)throw new F("toolbox_utxo_invalid_params",{error:"Recipient address must be provided"});let j=L||(await i(q))[Q||y.Fast],{psbt:B}=await bX({recipient:J,feeRate:j,sender:W,assetValue:$,memo:G}),U=await X.signTransaction(B);return U.finalizeAllInputs(),_(q).broadcastTx(U.extractTransaction().toHex())}}async function i(X){let Z=await _(X).getSuggestedTxFee();return{[y.Average]:Z,[y.Fast]:PX(Z,y.Fast),[y.Fastest]:PX(Z,y.Fastest)}}async function fX({assetValue:X,recipient:Z,memo:G,sender:J,fetchTxHex:Q=!1}){let L=X.chain,$=Q||d.includes(L);return{inputs:await _(L).scanUTXOs({address:J,fetchTxHex:$}),outputs:[{address:Z,value:Number(X.bigIntValue)},...G?[{address:"",script:await A(G),value:0}]:[]]}}var I=lZ.BitcoinCash;function m(X){return X.replace(/(bchtest:|bitcoincash:)/,"")}function w(X){let Z=m(X);return IX(Z)&&_X(Z)==="mainnet"}function f(X){return m(c(X))}async function nZ(X){async function Z({builder:J,utxos:Q}){return Q.forEach((L,$)=>{J.sign($,X,void 0,65,L.witnessUtxo?.value)}),J.build()}return{getAddress:()=>{let J=X.getAddress(0);return Promise.resolve(f(J))},signTransaction:Z}}async function EX(X){let Z="phrase"in X?X.phrase:void 0,G="index"in X?X.index||0:0,J=uZ("derivationPath"in X&&X.derivationPath?X.derivationPath:pZ(cZ[I],{index:G})),Q=(await r(I))({phrase:Z,derivationPath:J}),L=Q?await nZ(Q):("signer"in X)?X.signer:void 0;function $(){return Promise.resolve(L?.getAddress())}let{getBalance:W,getFeeRates:q,broadcastTx:j,...B}=await b({chain:I});function U(D,T=!0){return W(m(c(D)))}return{...B,getAddress:$,broadcastTx:j,createTransaction:SX,buildTx:rZ,getAddressFromKeys:iZ,getBalance:U,getFeeRates:q,stripPrefix:m,stripToCashAddress:f,validateAddress:w,transfer:dZ({getFeeRates:q,broadcastTx:j,signer:L})}}async function SX({assetValue:X,recipient:Z,memo:G,feeRate:J,sender:Q}){if(!w(Z))throw new K("toolbox_utxo_invalid_address",{address:Z});let L=await _(I).scanUTXOs({address:f(Q),fetchTxHex:!0}),$=G?await A(G):null,W=[];W.push({address:Z,value:X.getBaseValue("number")});let{inputs:q,outputs:j}=k({inputs:L,outputs:W,feeRate:J,chain:I});if(!(q&&j))throw new K("toolbox_utxo_insufficient_balance",{sender:Q,assetValue:X});let B=await C(),U=new gZ(B(I));await Promise.all(q.map(async(D)=>{let T=await _(I).getRawTx(D.hash);U.addInput(xZ.fromBuffer(Buffer.from(T,"hex")),D.index)}));for(let D of j){let T="address"in D&&D.address?D.address:x(Q),M=await C(),H=mZ.toOutputScript(x(T),M(I));U.addOutput(H,D.value)}if($)U.addOutput($,0);return{builder:U,utxos:q}}function dZ({broadcastTx:X,getFeeRates:Z,signer:G}){return async function J({recipient:Q,assetValue:L,feeOptionKey:$=hZ.Fast,...W}){let q=await G?.getAddress();if(!(G&&q))throw new K("toolbox_utxo_no_signer");if(!Q)throw new K("toolbox_utxo_invalid_params",{error:"Recipient address must be provided"});let j=W.feeRate||(await Z())[$],{builder:B,utxos:U}=await SX({...W,assetValue:L,feeRate:j,recipient:Q,sender:q}),T=(await G.signTransaction({builder:B,utxos:U})).toHex();return X(T)}}async function rZ({assetValue:X,recipient:Z,memo:G,feeRate:J,sender:Q}){let L=c(Z);if(!w(L))throw new K("toolbox_utxo_invalid_address",{address:L});let $=await _(I).scanUTXOs({address:f(Q),fetchTxHex:!0}),W=Number(J.toFixed(0)),q=G?await A(G):null,j=[];if(j.push({address:x(Z),value:X.getBaseValue("number")}),q)j.push({script:q,value:0});let{inputs:B,outputs:U}=k({inputs:$,outputs:j,feeRate:W,chain:I});if(!(B&&U))throw new K("toolbox_utxo_insufficient_balance",{sender:Q,assetValue:X});let D=await C(),T=new oZ({network:D(I)});for(let{hash:M,index:H,witnessUtxo:O}of B)T.addInput({hash:M,index:H,witnessUtxo:O});for(let M of U){let H="address"in M&&M.address?M.address:x(Q),O=M.script?q?{script:q,value:0}:void 0:{address:H,value:M.value};if(O)T.addOutput(O)}return{psbt:T,utxos:$,inputs:B}}function iZ(X){let Z=X.getAddress(0);return f(Z)}async function tG(X,Z){switch(X){case E.BitcoinCash:return await EX(Z);case E.Zcash:return await yX(Z);case E.Bitcoin:case E.Dogecoin:case E.Litecoin:case E.Dash:return await b({chain:X,...Z});default:throw new aZ("toolbox_utxo_not_supported",{chain:X})}}export{QX as validateZcashAddress,x as toLegacyAddress,c as toCashAddress,f as stripToCashAddress,m as stripPrefix,d as nonSegwitChains,IX as isValidAddress,tG as getUtxoToolbox,C as getUtxoNetwork,_ as getUtxoApi,wZ as getUTXOAddressValidator,o as getScriptTypeForAddress,p as getOutputSize,V as getInputSize,t as getDustThreshold,r as getCreateKeysForPath,_X as detectAddressNetwork,yX as createZcashToolbox,b as createUTXOToolbox,ZG as createCustomUtxoApi,EX as createBCHToolbox,A as compileMemo,g as calculateTxSize,w as bchValidateAddress,KX as addressFromKeysGetter,k as accumulative,vX as UtxoNetwork,XX as UTXOScriptType,e as TX_OVERHEAD,n as OutputSizes,ZZ as OP_RETURN_OVERHEAD,UG as MIN_TX_FEE,ZX as InputSizes};
4
4
 
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "@solana/spl-memo": "^0.2.5",
19
19
  "@solana/spl-token": "^0.4.13",
20
20
  "@solana/web3.js": "^1.98.0",
21
- "@swapkit/helpers": "^4.0.0-beta.25",
21
+ "@swapkit/helpers": "^4.0.0-beta.27",
22
22
  "base64-js": "^1.5.1",
23
23
  "bitcoinjs-lib": "^6.1.0",
24
24
  "bs58check": "^4.0.0",
@@ -59,7 +59,7 @@
59
59
  "@solana/spl-memo": "0.2.5",
60
60
  "@solana/spl-token": "0.4.13",
61
61
  "@solana/web3.js": "1.98.2",
62
- "@swapkit/helpers": "4.0.0-beta.25",
62
+ "@swapkit/helpers": "4.0.0-beta.27",
63
63
  "@types/bn.js": "5.2.0",
64
64
  "@types/crypto-js": "4.2.2",
65
65
  "@types/elliptic": "6.4.18",
@@ -137,12 +137,12 @@
137
137
  "src/",
138
138
  "dist/"
139
139
  ],
140
- "homepage": "https://github.com/thorswap/SwapKit",
140
+ "homepage": "https://github.com/swapkit/SwapKit",
141
141
  "license": "Apache-2.0",
142
142
  "name": "@swapkit/toolboxes",
143
143
  "repository": {
144
144
  "type": "git",
145
- "url": "git+https://github.com/thorswap/SwapKit.git"
145
+ "url": "git+https://github.com/swapkit/SwapKit.git"
146
146
  },
147
147
  "scripts": {
148
148
  "build": "bun run ./build.ts",
@@ -154,5 +154,5 @@
154
154
  "type-check:go": "tsgo"
155
155
  },
156
156
  "type": "module",
157
- "version": "4.0.0-beta.37"
157
+ "version": "4.0.0-beta.39"
158
158
  }
@@ -225,7 +225,7 @@ export async function createCosmosToolbox({ chain, ...toolboxParams }: CosmosToo
225
225
  };
226
226
  }
227
227
 
228
- export async function getFeeRateFromThorswap(chainId: ChainId, safeDefault: number) {
228
+ export async function getFeeRateFromSwapKit(chainId: ChainId, safeDefault: number) {
229
229
  try {
230
230
  const response = await SwapKitApi.getGasRate();
231
231
  const responseGasRate = response.find((gas) => gas.chainId === chainId)?.value;
@@ -236,6 +236,11 @@ export async function getFeeRateFromThorswap(chainId: ChainId, safeDefault: numb
236
236
  }
237
237
  }
238
238
 
239
+ /**
240
+ * @deprecated use getFeeRateFromSwapKit instead
241
+ */
242
+ export const getFeeRateFromThorswap = getFeeRateFromSwapKit;
243
+
239
244
  export function cosmosValidateAddress({
240
245
  address,
241
246
  chain,
@@ -84,7 +84,7 @@ export async function createStargateClient(url: string) {
84
84
  const defaultRequestHeaders =
85
85
  typeof window !== "undefined"
86
86
  ? ({} as Record<string, string>)
87
- : { referrer: "https://sk.thorswap.net", referer: "https://sk.thorswap.net" };
87
+ : { referrer: "https://sdk.swapkit.dev", referer: "https://sdk.swapkit.dev" };
88
88
 
89
89
  return StargateClient.connect({
90
90
  url,
@@ -0,0 +1,54 @@
1
+ import { SwapKitError } from "@swapkit/helpers";
2
+ import { TronWeb } from "tronweb";
3
+ import type { TronGridAccountResponse } from "../types.js";
4
+
5
+ const TRONGRID_API_BASE = "https://api.trongrid.io";
6
+
7
+ /**
8
+ * Fetch account information including TRC20 balances from TronGrid API
9
+ */
10
+ export async function fetchAccountFromTronGrid(address: string) {
11
+ try {
12
+ const response = await fetch(`${TRONGRID_API_BASE}/v1/accounts/${address}`);
13
+
14
+ if (!response.ok) {
15
+ throw new Error(`TronGrid API error: ${response.status} ${response.statusText}`);
16
+ }
17
+
18
+ const data = (await response.json()) as TronGridAccountResponse;
19
+
20
+ if (!(data.success && data.data) || data.data.length === 0) {
21
+ throw new Error("Invalid response from TronGrid API");
22
+ }
23
+
24
+ // Convert search address to hex format for comparison
25
+ let searchAddressHex: string;
26
+ try {
27
+ // If address is base58, convert to hex
28
+ searchAddressHex = TronWeb.address.toHex(address).toLowerCase();
29
+ } catch {
30
+ // If conversion fails, assume it's already hex
31
+ searchAddressHex = address.toLowerCase();
32
+ }
33
+
34
+ // Find the account that matches the requested address
35
+ const account = data.data.find((acc) => {
36
+ return acc.address.toLowerCase() === searchAddressHex;
37
+ });
38
+
39
+ if (!account) {
40
+ return;
41
+ }
42
+
43
+ // Return simplified object with balance and trc20 array
44
+ return {
45
+ balance: account.balance,
46
+ trc20: account.trc20 || [],
47
+ };
48
+ } catch (error) {
49
+ throw new SwapKitError("toolbox_tron_trongrid_api_error", {
50
+ message: error instanceof Error ? error.message : "Unknown error",
51
+ address,
52
+ });
53
+ }
54
+ }
@@ -11,6 +11,7 @@ import {
11
11
  import { P, match } from "ts-pattern";
12
12
 
13
13
  import { trc20ABI } from "./helpers/trc20.abi.js";
14
+ import { fetchAccountFromTronGrid } from "./helpers/trongrid.js";
14
15
  import type {
15
16
  TronCreateTransactionParams,
16
17
  TronSignedTransaction,
@@ -22,6 +23,14 @@ import type {
22
23
 
23
24
  import { TronWeb } from "tronweb";
24
25
 
26
+ // Constants for TRON resource calculation
27
+ const TRX_TRANSFER_BANDWIDTH = 268; // Bandwidth consumed by a TRX transfer
28
+ const TRC20_TRANSFER_ENERGY = 13000; // Average energy consumed by TRC20 transfer
29
+ const TRC20_TRANSFER_BANDWIDTH = 345; // Bandwidth consumed by TRC20 transfer
30
+
31
+ // Known TRON tokens
32
+ const TRON_USDT_CONTRACT = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
33
+
25
34
  export async function getTronAddressValidator() {
26
35
  return (address: string) => {
27
36
  return TronWeb.isAddress(address);
@@ -131,11 +140,6 @@ export const createTronToolbox = async (options: TronToolboxOptions = {}) => {
131
140
  return 100_000_000; // 100 TRX in SUN
132
141
  };
133
142
 
134
- // Constants for TRON resource calculation
135
- const TRX_TRANSFER_BANDWIDTH = 268; // Bandwidth consumed by a TRX transfer
136
- const TRC20_TRANSFER_ENERGY = 13000; // Average energy consumed by TRC20 transfer
137
- const TRC20_TRANSFER_BANDWIDTH = 345; // Bandwidth consumed by TRC20 transfer
138
-
139
143
  /**
140
144
  * Get current chain parameters including resource prices
141
145
  */
@@ -202,50 +206,135 @@ export const createTronToolbox = async (options: TronToolboxOptions = {}) => {
202
206
  }
203
207
  };
204
208
 
205
- const getBalance = async (address: string, scamFilter = true) => {
206
- const { getBalance: getBalanceFromApi } = await import("../utils.js");
207
-
209
+ /**
210
+ * Get token balance and info directly from contract
211
+ */
212
+ const fetchTokenBalance = async (address: string, contractAddress: string) => {
208
213
  try {
209
- // Use SwapKit API for comprehensive balance fetching (includes TRX + TRC20 tokens)
210
- const apiBalances = await getBalanceFromApi(Chain.Tron)(address, scamFilter);
214
+ const contract = tronWeb.contract(trc20ABI, contractAddress);
211
215
 
212
- // If API returns balances, use those
213
- if (apiBalances.length > 0) {
214
- return apiBalances;
216
+ if (!contract.methods?.balanceOf) {
217
+ return 0n;
215
218
  }
216
219
 
217
- // Fallback to on-chain TRX balance if API fails or returns empty
218
- const trxBalanceInSun = await tronWeb.trx.getBalance(address);
219
- return [
220
- AssetValue.from({
221
- chain: Chain.Tron,
222
- value: trxBalanceInSun,
223
- fromBaseDecimal: 6, // TRX has 6 decimals
224
- }),
225
- ];
220
+ const balance = (await contract.methods.balanceOf(address).call())[0] as string;
221
+
222
+ return BigInt(balance || 0); // Convert to BigInt for consistency
223
+ } catch (err) {
224
+ console.warn(`balanceOf() failed for ${contractAddress}:`, err);
225
+ return 0n;
226
+ }
227
+ };
228
+
229
+ /**
230
+ * Get token balance and info directly from contract
231
+ */
232
+ const fetchTokenMetadata = async (contractAddress: string, address: string) => {
233
+ try {
234
+ tronWeb.setAddress(address); // Set address for contract calls
235
+ const contract = tronWeb.contract(trc20ABI, contractAddress);
236
+
237
+ const [symbolRaw, decimalsRaw] = await Promise.all([
238
+ contract
239
+ .symbol()
240
+ .call()
241
+ .catch(() => "UNKNOWN"),
242
+ contract
243
+ .decimals()
244
+ .call()
245
+ .catch(() => "18"),
246
+ ]);
247
+
248
+ return {
249
+ symbol: symbolRaw ?? "UNKNOWN",
250
+ decimals: Number(decimalsRaw ?? 18),
251
+ };
226
252
  } catch (error) {
227
253
  warnOnce(
228
254
  true,
229
- `Failed to get Tron balance for ${address}: ${error instanceof Error ? error.message : error}`,
255
+ `Failed to get token balance for ${contractAddress}: ${error instanceof Error ? error.message : error}`,
230
256
  );
257
+ return null;
258
+ }
259
+ };
231
260
 
232
- // Final fallback: try to get just the native TRX balance
233
- try {
234
- const trxBalanceInSun = await tronWeb.trx.getBalance(address);
235
- return [
261
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>
262
+ const getBalance = async (address: string, _scamFilter = true) => {
263
+ const fallbackBalance = [
264
+ AssetValue.from({
265
+ chain: Chain.Tron,
266
+ }),
267
+ ];
268
+ // Try primary source (TronGrid)
269
+ try {
270
+ const accountData = await fetchAccountFromTronGrid(address);
271
+ if (accountData) {
272
+ const balances: AssetValue[] = [];
273
+
274
+ // Add TRX balance
275
+ balances.push(
276
+ AssetValue.from({
277
+ chain: Chain.Tron,
278
+ value: accountData.balance,
279
+ fromBaseDecimal: 6,
280
+ }),
281
+ );
282
+
283
+ // Add TRC20 balances
284
+
285
+ for (const token of accountData.trc20) {
286
+ const [contractAddress, balance] = Object.entries(token)[0] || [];
287
+
288
+ if (!(contractAddress && balance)) continue;
289
+
290
+ const tokenMetaData = await fetchTokenMetadata(contractAddress, address);
291
+
292
+ if (!tokenMetaData) continue;
293
+
294
+ balances.push(
295
+ AssetValue.from({
296
+ asset: `TRX.${tokenMetaData.symbol}-${contractAddress}`,
297
+ value: BigInt(balance || 0),
298
+ fromBaseDecimal: tokenMetaData.decimals,
299
+ }),
300
+ );
301
+ }
302
+
303
+ return balances;
304
+ }
305
+ return fallbackBalance;
306
+ } catch (error) {
307
+ warnOnce(
308
+ true,
309
+ `Tron API getBalance failed: ${error instanceof Error ? error.message : error}`,
310
+ );
311
+
312
+ // Fallback: get TRX and USDT directly
313
+ const balances: AssetValue[] = [];
314
+
315
+ const trxBalanceInSun = await tronWeb.trx.getBalance(address);
316
+ if (trxBalanceInSun && Number(trxBalanceInSun) > 0) {
317
+ balances.push(
236
318
  AssetValue.from({
237
319
  chain: Chain.Tron,
238
320
  value: trxBalanceInSun,
239
321
  fromBaseDecimal: 6,
240
322
  }),
241
- ];
242
- } catch (fallbackError) {
243
- warnOnce(
244
- true,
245
- `Failed to get native TRX balance for ${address}: ${fallbackError instanceof Error ? fallbackError.message : fallbackError}`,
246
323
  );
247
- return [];
248
324
  }
325
+
326
+ const usdtBalance = await fetchTokenBalance(address, TRON_USDT_CONTRACT);
327
+ if (usdtBalance) {
328
+ balances.push(
329
+ AssetValue.from({
330
+ asset: `TRX.USDT-${TRON_USDT_CONTRACT}`,
331
+ value: usdtBalance,
332
+ fromBaseDecimal: 6,
333
+ }),
334
+ );
335
+ }
336
+
337
+ return balances;
249
338
  }
250
339
  };
251
340