🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenVorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf(11.09.2026 um 09:35 Uhr)
🕵️ SicherheitslückenMicrosoft geht endlich eines der nervigsten Probleme von Windows 11 an(11.09.2026 um 11:58 Uhr)
💾 IT Security ToolsSysinternals Suite(11.09.2026 um 12:00 Uhr)
🕵️ SicherheitslückenDefender 0-Day ShieldBreak (CVE-2026-69414) nicht sauber gepatcht - BornCity(11.09.2026 um 12:52 Uhr)
🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
⚠️ Malware / Trojaner / VirenWindows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC(10.09.2026 um 20:11 Uhr)
⚠️ Malware / Trojaner / VirenVorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf(11.09.2026 um 09:35 Uhr)
🕵️ SicherheitslückenMicrosoft geht endlich eines der nervigsten Probleme von Windows 11 an(11.09.2026 um 11:58 Uhr)
💾 IT Security ToolsSysinternals Suite(11.09.2026 um 12:00 Uhr)
🕵️ SicherheitslückenDefender 0-Day ShieldBreak (CVE-2026-69414) nicht sauber gepatcht - BornCity(11.09.2026 um 12:52 Uhr)

🔧 Programmierung 🕛 vor 6 Monaten 30 Min Lesezeit
0

Practice of Web3 Tron Encapsulated and Access to SunSwap DEX Based on FMZ Platform

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht
📺
dev.to




Preface



In the field of blockchain tradings, decentralized exchanges (DEX) provide a trustless way to exchange assets, and SunSwap, as a representative DEX in the Tron ecosystem, supports smart contract interactions based on Web3. We FMZ platform provides a powerful quantitative trading framework that enables developers to integrate multiple trading strategies.



The FMZ platform already supports the encapsulation of Web3 Ethereum (ETH) exchange objects, and added support for Web3 TRON recently, encapsulating the exchange objects of the TRON chain. Just like accessing UniSwap DEX, access to SunSwap DEX is also possible.



This article will explore how to encapsulate the Web3 interface based on the FMZ Quant platform and access SunSwap DEX for trading. We will introduce the Web3 interaction method of the Tron network, the SunSwap smart contract call, and show how to query liquidity, execute transactions, and obtain transaction results through code examples, so as to build an efficient quantitative trading strategy.






Disclaimer



All codes and designs shared in this article have been tested and are intended for learning and communication. However, even after testing, these contents may still need to be adjusted according to actual needs. If you want to apply them to live trading, please be sure to evaluate, optimize and modify them yourself to ensure that they meet your needs.






Preparation




  • Configure the Web3 TRON exchange object of the FMZ platform



In the previous article FMZ Quant Web3 Expansion: Tron Support Added, Expand On-chain Tradings, we have introduced the common methods of Tron gRPC nodes and learned how to configure Web3 TRON exchange objects on FMZ. This article will not repeat these contents. As for the node address, we will use the node provided by TRON official directly.




  • Deploy the docker







Open the front-end page of SunSwap in the browser, you can connect to the wallet and observe the data conveniently.




  • tronscan


    The code has removed some of the contract addresses currently seen, such as "phishing contracts" and "invalid contracts".



    GetTicker




    CODE
        let ticker1 = e.GetTicker("WTRX_USDT")
    Log("symbol:", "WTRX_USDT", ", ticker:", ticker1)
    let ticker2 = e.GetTicker("iCMX_USDT", "TLVDozYEBgeaJXH7oKBsougzEJKNrogFun") // iCMX_USDT
    Log("symbol:", "iCMX_USDT", ", ticker:", ticker2)







    You can use the GetTicker() function to query the price of a certain exchange pool, and you can specify the address of a specific pool. Note that some pools have poor liquidity and the price is only for reference.



    multicall




    CODE
        let data = []
    let walletAddress = exchange.IO("address")
    data.push(["TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "0x" + exchange.IO("encode", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", walletAddress)])
    data.push(["TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "0x" + exchange.IO("encode", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", walletAddress)])
    Log(data)
    let ret = multicall(exchange, "TGXuuKAb4bnrn137u39EKbYzKNXvdCes98", data, ["uint256", "uint256"])
    Log(ret, toAmount(ret[0], 6))







    This function can be used for subsequent function encapsulation. For example, in the example, two balanceOf method calls can be encoded and the data can be requested once.



    GetSwapOutAmount




    CODE
        let retBuy = e.GetSwapOutAmount("WTRX_USDT", 1, "buy")     // 1 quote -> base
    Log("WTRX_USDT", "buy outAmount:", retBuy["outAmount"], ", ask:", (1 / retBuy["outAmount"]))
    let retSell = e.GetSwapOutAmount("WTRX_USDT", 1, "sell") // 1 base -> quote
    Log("WTRX_USDT", "sell outAmount:", retSell["outAmount"], ", bid:", (retSell["outAmount"] / 1))







    This is an important function, which encapsulates SunSwap's intelligent routing service. Given tokenInSymbol and tokenOutSymbol, it can return possible exchange paths, the number of output tokens and other information.



    GetAssets




    CODE
        let assets = e.GetAssets()
    let tbl = {"type": "table", "title": "test GetAssets", "cols": ["Name", "Address", "Decimals", "Balance"], "rows": []}
    for (let asset of assets) {
    tbl["rows"].push([asset.Currency, asset.Address, asset.Decimals, asset.Amount])
    }
    LogStatus("`" + JSON.stringify(tbl) + "`")







    Since there is no good mechanism to traverse TRC20 tokens, with the help of tronscan's function, this third-party interface is used to query account asset information.








    Swap






    CODE
        // 6 USDT -> ? WTRX
    let ret = e.Swap("WTRX_USDT", 6, "buy")
    Log(ret)

    // 10 TRX -> ? WTRX
    // let ret = e.Swap("TRX_WTRX", 10, "sell")
    // Log(ret)







    The most important function is this exchange. When executing the exchange, the exchange path will be formulated according to the smart routing first, and then the exchange method will be called to exchange the token.

    It should be noted that if it is a TRX package/unpackage exchange, it is only executed using the WTRX contract method.



    We perform the following tests:




    CODE
    let ret = e.Swap("TRX_USDT", 5, "sell")
    Log(ret)








    Other Encapsulations

    There are some other functions such as "staking" and "unstaking". You can check them in the main() function in the template code, so I won't go into details.

    You can also expand and add functions such as adding liquidity and removing liquidity.



    Template Code

    This template does not have any interaction design and interface parameters. It only implements the basic function of accessing SunSwap DEX. More functions can be optimized and added later.




    CODE
    function isEmptyObject(obj) {
    return Object.keys(obj).length === 0
    }

    function computePoolPrice(decimals0, decimals1, sqrtPriceX96) {
    [decimals0, decimals1, sqrtPriceX96] = [decimals0, decimals1, sqrtPriceX96].map(BigInt)
    const TWO = BigInt(2)
    const TEN = BigInt(10)
    const SIX_TENTH = BigInt(1000000)
    const Q192 = (TWO ** BigInt(96)) ** TWO
    return (Number((sqrtPriceX96 ** TWO * TEN ** decimals0 * SIX_TENTH) / (Q192 * TEN ** decimals1)) / Number(SIX_TENTH))
    }

    function multicall(e, multicallContractAddress, data, outTypes) {
    let ret = e.IO("api", multicallContractAddress, "aggregate", data)
    if (!ret || !ret["returnData"] || !Array.isArray(ret["returnData"])) {
    Log("invalid ret:", ret)
    return null
    }

    let arrRet = ret["returnData"]
    if (outTypes.length != arrRet.length) {
    Log("Arrays have unequal lengths:", arrRet, outTypes)
    return null
    }

    let outData = []
    for (let i in arrRet) {
    outData.push(e.IO("decode", outTypes[i], arrRet[i]))
    }

    return outData
    }

    function toAmount(s, decimals) {
    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
    }

    function toInnerAmount(n, decimals) {
    return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0)
    }

    function hexToUint8Array(hex) {
    if (hex.length % 2 !== 0) {
    throw new Error("Invalid hex string length")
    }
    return Uint8Array.from(
    hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16))
    )
    }

    function uint8ArrayToHex(array) {
    return Array.from(array).map(byte => byte.toString(16).padStart(2, "0")).join("")
    }

    function ethAddressToTron(ethAddress) {
    if (!/^0x[0-9a-fA-F]{40}$/.test(ethAddress)) {
    throw "Invalid Ethereum address"
    }

    const ethAddressBytes = new Uint8Array(20)
    for (let i = 0; i < 20; i++) {
    ethAddressBytes[i] = parseInt(ethAddress.substr(2 + i * 2, 2), 16)
    }

    const tronAddressBytes = new Uint8Array(21)
    tronAddressBytes[0] = 0x41
    tronAddressBytes.set(ethAddressBytes, 1)

    const hash1 = Encode("sha256", "hex", "hex", uint8ArrayToHex(tronAddressBytes))
    const hash2 = Encode("sha256", "hex", "hex", hash1)
    const checksum = hash2.slice(0, 8)

    const fullAddress = new Uint8Array(25)
    fullAddress.set(tronAddressBytes, 0)
    fullAddress.set(hexToUint8Array(checksum), 21)

    return base58Encode(fullAddress)
    }

    function base58Encode(buffer) {
    const base58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
    let num = BigInt("0x" + Array.from(buffer).map(b => b.toString(16).padStart(2, "0")).join(""))
    let encoded = ""
    while (num > 0) {
    let remainder = num % 58n
    num = num / 58n
    encoded = base58Alphabet[Number(remainder)] + encoded
    }
    for (let byte of buffer) {
    if (byte === 0) {
    encoded = base58Alphabet[0] + encoded
    } else {
    break
    }
    }

    return encoded
    }

    function base58ToHex(base58Str) {
    const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

    var num = BigInt(0)
    for (var char of base58Str) {
    var digit = BigInt(ALPHABET.indexOf(char))
    if (digit === BigInt(-1)) throw new Error("Invalid Base58 character: " + char)
    num = num * BigInt(58) + digit
    }

    var hex = num.toString(16)
    if (hex.length % 2 !== 0) {
    hex = "0" + hex
    }

    return "0x" + hex
    }

    $.CreateSunSwapEx = function(e) {
    let sunSwapEx = {}

    sunSwapEx.registerABI = function(address, codeABI) {
    let e = sunSwapEx.e

    if (typeof(address) == "undefined" || typeof(codeABI) == "undefined") {
    throw "need address, codeABI"
    }

    return e.IO("abi", address, codeABI)
    }

    sunSwapEx.getCurrencyInfo = function(token0Address, token1Address) {
    let e = sunSwapEx.e

    let arrTokenAddress = [token0Address, token1Address]
    let tokenInfoCallData = []
    let tokenInfoRetType = []
    for (let tokenAddress of arrTokenAddress) {
    tokenInfoCallData.push([tokenAddress, "0x" + e.IO("encode", tokenAddress, "symbol")])
    tokenInfoRetType.push("string")
    tokenInfoCallData.push([tokenAddress, "0x" + e.IO("encode", tokenAddress, "name")])
    tokenInfoRetType.push("string")
    tokenInfoCallData.push([tokenAddress, "0x" + e.IO("encode", tokenAddress, "decimals")])
    tokenInfoRetType.push("uint8")
    }
    let currencyInfo = _C(multicall, e, multicallContractAddress, tokenInfoCallData, tokenInfoRetType)
    if (currencyInfo.length != 6) {
    Log("invalid currency Info:", currencyInfo)
    return null
    }
    let ret = {
    "token0Symbol": currencyInfo[0],
    "token0Name": currencyInfo[1],
    "token0Decimals": currencyInfo[2],
    "token1Symbol": currencyInfo[3],
    "token1Name": currencyInfo[4],
    "token1Decimals": currencyInfo[5]
    }

    return ret
    }

    sunSwapEx.waitMined = function(tx) {
    let e = sunSwapEx.e
    let i = 0
    let maxLoop = 10

    while (true) {
    Sleep(3000)

    let info = e.IO("api", "tron", "GetTransactionInfoByID", tx)
    if (info && info.receipt && typeof(info.receipt.result) == "number") {
    Log("GetTransactionInfoByID:", info)
    if (info.receipt.result == 1) {
    return true
    } else {
    return false
    }
    }

    Log("Transaction not yet mined", tx)
    if (i > maxLoop) {
    break
    }
    i++
    }

    Log(`Transaction: ${tx} not found`)
    return false
    }

    sunSwapEx.getTokenInfo = function(tokenSymbol) {
    let markets = sunSwapEx.markets
    if (!markets || isEmptyObject(markets)) {
    markets = sunSwapEx.GetMarkets()
    }

    if (tokenSymbol == "TRX") {
    return {"tokenSymbol": tokenSymbol, "tokenName": tokenSymbol, "tokenDecimals": 6, "tokenAddress": "--"}
    }

    for (let currency in markets) {
    for (let market of markets[currency]) {
    if (market["BaseAsset"] == tokenSymbol) {
    return {"tokenSymbol": market["BaseAsset"], "tokenName": market["BaseName"], "tokenDecimals": market["BaseDecimals"], "tokenAddress": market["BaseAddress"]}
    } else if (market["QuoteAsset"] == tokenSymbol) {
    return {"tokenSymbol": market["QuoteAsset"], "tokenName": market["QuoteName"], "tokenDecimals": market["QuoteDecimals"], "tokenAddress": market["QuoteAddress"]}
    }
    }
    }

    Log("not found token symbol:", tokenSymbol)
    return null
    }

    sunSwapEx.dealStakeTRX = function(methodName, resourceName, amount) {
    let e = sunSwapEx.e

    let walletAddress = e.IO("address")
    let balance = toInnerAmount(amount, 6)
    let resourceCode = -1

    if (resourceName == "BANDWIDTH") {
    resourceCode = 0
    } else if (resourceName == "ENERGY") {
    resourceCode = 1
    } else if (resourceName == "TRON_POWER") {
    resourceCode = 2
    } else {
    Log("not support resourceName:", resourceName)
    return null
    }

    return e.IO("api", "tron", methodName, walletAddress, resourceCode, balance)
    }

    sunSwapEx.GetMarkets = function() {
    // sunswap v3 pool

    let e = sunSwapEx.e

    if (!sunSwapEx.markets) {
    sunSwapEx.markets = {}
    }

    let markets = sunSwapEx.markets
    if (!isEmptyObject(markets)) {
    return markets
    }

    let factoryV3Address = sunSwapEx.factoryV3Address

    // allPoolsLength
    let poolIdx = e.IO("api", factoryV3Address, "allPoolsLength")
    if (!poolIdx) {
    Log("invalid poolIdx:", poolIdx)
    return null
    }
    Log("allPoolsLength:", poolIdx)

    // multicallContractAddress
    let multicallContractAddress = sunSwapEx.multicallContractAddress

    // get All pool address
    let retPools = []
    let getPoolsData = []
    let retPoolsType = []
    for (let i = 0; i < poolIdx; i++) {
    getPoolsData.push([factoryV3Address, "0x" + e.IO("encode", factoryV3Address, "allPools", String(i))])
    retPoolsType.push("address")

    if (getPoolsData.length > 30 || i == poolIdx - 1) {
    let arr = _C(multicall, e, multicallContractAddress, getPoolsData, retPoolsType)

    retPools.push(...arr)
    getPoolsData = []
    retPoolsType = []
    }
    }

    // allPools
    let poolABI = sunSwapEx.poolABI
    for (let i in retPools) {
    // poolAddress
    let poolAddress = ethAddressToTron(retPools[i])

    // register pool ABI
    sunSwapEx.registerABI(poolAddress, poolABI)

    // get token address of the pool
    let tokenCallData = [[poolAddress, "0x" + e.IO("encode", poolAddress, "token0")], [poolAddress, "0x" + e.IO("encode", poolAddress, "token1")]]
    let tokenRetType = ["address", "address"]
    let arrTokenAddress = _C(multicall, e, multicallContractAddress, tokenCallData, tokenRetType)

    let token0Address = ethAddressToTron(arrTokenAddress[0])
    let token1Address = ethAddressToTron(arrTokenAddress[1])

    // symbol , name , decimals
    let currencyInfo = sunSwapEx.getCurrencyInfo(token0Address, token1Address)
    if (!currencyInfo) {
    return null
    }

    let token0Symbol = currencyInfo["token0Symbol"]
    let token0Name = currencyInfo["token0Name"]
    let token0Decimals = currencyInfo["token0Decimals"]
    let token1Symbol = currencyInfo["token1Symbol"]
    let token1Name = currencyInfo["token1Name"]
    let token1Decimals = currencyInfo["token1Decimals"]

    // Alias
    let mapAlias = {
    "TJWm3jWaJeCdyRckEXfopsJBvZi6wXVK2p": "PAPA",
    "TPYmHEhy5n8TCEfYGqW2rPxsghSfzghPDn": "USDDOLD",
    "TTiwtPv4MFHMoCpGDBEF85qQjD2v4e99ck": "HOUSDOLD",
    "TRFe3hT5oYhjSZ6f3ji5FJ7YCfrkWnHRvh": "ETHB"
    }
    if (typeof(mapAlias[token0Address]) != "undefined") {
    token0Symbol = mapAlias[token0Address]
    }
    if (typeof(mapAlias[token1Address]) != "undefined") {
    token1Symbol = mapAlias[token1Address]
    }

    // bad
    let mapBad = {
    "TMEmRKPob42vhkqEGopCnfBPixN5XTkdUc": "U S D T", // Attention: Fishing contract
    "TXioUZK8ju3R54KvzSqPc6Ufq5wkxFqpq9": "U S D T", // Attention: Fishing contract
    "TU41FWQQT8hZ6t72gVEjtSGn1Dshbevi7g": "CNY Coin", // Attention: Invalid
    "TYB7oXNq4VyuiH5BHb4os8rTh7Ca8pxqSx": "BULL", // Attention: Fishing contract
    "TYJxozCVMUiHg3TbQp9PKeuXdTsX9ugJz9": "SHISHA", // Attention: Not circulated
    "TF9io9LGyjuK3uTpr73pAaQ5m9scxd9xvr": "TestToken18", // Attention: Test trading pairs
    "TK8E3sFhBt3EB6gTT6d6co8RMB6DFUnNwE": "TestToken6" // Attention: Test trading pairs
    }
    if (typeof(mapBad[token0Address]) != "undefined" || typeof(mapBad[token1Address]) != "undefined") {
    continue
    }

    // market
    let currency = token0Symbol + "_" + token1Symbol
    let market = {
    "Symbol": currency,
    "BaseAsset": token0Symbol,
    "QuoteAsset": token1Symbol,
    "BaseName": token0Name,
    "QuoteName": token1Name,
    "BaseDecimals": token0Decimals,
    "QuoteDecimals": token1Decimals,
    "BaseAddress": token0Address,
    "QuoteAddress": token1Address,
    "PoolAddress": poolAddress,
    "PoolIndex": i
    }

    if (!Array.isArray(markets[currency])) {
    markets[currency] = []
    }
    markets[currency].push(market)
    LogStatus(_D(), "get markets, length:", Object.keys(markets).length)

    Sleep(200)
    }

    _G("sunswap_markets", markets)
    sunSwapEx.markets = markets

    return markets
    }

    sunSwapEx.GetTicker = function(symbol, targetPoolAddress) {
    let e = sunSwapEx.e

    let markets = sunSwapEx.markets
    if (!markets || isEmptyObject(markets)) {
    markets = sunSwapEx.GetMarkets()
    }

    let arrPoolAddress = []
    let arrToken0Decimals = []
    let arrToken1Decimals = []
    for (let currency in markets) {
    if (!Array.isArray(markets[currency]) || markets[currency].length == 0) {
    continue
    }

    if (currency == symbol) {
    for (let ele of markets[currency]) {
    if (typeof(targetPoolAddress) != "undefined" && ele["PoolAddress"] != targetPoolAddress) {
    continue
    }
    arrPoolAddress.push(ele["PoolAddress"])
    arrToken0Decimals.push(ele["BaseDecimals"])
    arrToken1Decimals.push(ele["QuoteDecimals"])
    }
    }
    }

    if (arrPoolAddress.length == 0) {
    Log(`${symbol} and ${targetPoolAddress} not found`)
    sunSwapEx.markets = {}
    return null
    }

    let arrPrice = []
    let slot0CallData = []
    let slot0RetType = []
    for (let i in arrPoolAddress) {
    let poolAddress = arrPoolAddress[i]
    let poolABI = sunSwapEx.poolABI
    e.IO("abi", poolAddress, poolABI)
    slot0CallData.push([poolAddress, "0x" + e.IO("encode", poolAddress, "slot0")])
    slot0RetType.push("(uint160,int24,uint16,uint16,uint16,uint8,bool)")
    }
    let multicallContractAddress = sunSwapEx.multicallContractAddress
    let arrSlot0 = _C(multicall, e, multicallContractAddress, slot0CallData, slot0RetType)

    for (let i in arrSlot0) {
    let slot0 = arrSlot0[i]
    let token0Decimals = arrToken0Decimals[i]
    let token1Decimals = arrToken1Decimals[i]
    let sqrtPriceX96 = slot0["Field1"]
    let poolAddress = arrPoolAddress[i]
    let price = computePoolPrice(token0Decimals, token1Decimals, sqrtPriceX96)

    arrPrice.push({"price": price, "poolAddress": poolAddress})
    }

    return arrPrice
    }

    sunSwapEx.GetSwapOutAmount = function(symbol, amountIn, type) {
    let arrCurrency = symbol.split("_")
    if (arrCurrency.length != 2) {
    Log("invalid symbol:", symbol)
    return null
    }

    let baseCurrencyInfo = sunSwapEx.getTokenInfo(arrCurrency[0])
    let quoteCurrencyInfo = sunSwapEx.getTokenInfo(arrCurrency[1])
    if (!baseCurrencyInfo || !quoteCurrencyInfo) {
    return null
    }

    let baseSymbol = baseCurrencyInfo["tokenSymbol"]
    let baseAddress = baseCurrencyInfo["tokenAddress"]
    let baseDecimals = baseCurrencyInfo["tokenDecimals"]
    let quoteSymbol = quoteCurrencyInfo["tokenSymbol"]
    let quoteAddress = quoteCurrencyInfo["tokenAddress"]
    let quoteDecimals = quoteCurrencyInfo["tokenDecimals"]

    // black hole address
    if (baseSymbol == "TRX") {
    baseAddress = "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb"
    }
    if (quoteSymbol == "TRX") {
    quoteAddress = "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb"
    }

    let query = null
    if (type == "buy") {
    let amount = toInnerAmount(amountIn, quoteDecimals)
    query = `?fromToken=${quoteAddress}&toToken=${baseAddress}&amountIn=${amount}&typeList=WTRX,SUNSWAP_V1,SUNSWAP_V2,SUNSWAP_V3`
    } else if (type == "sell") {
    let amount = toInnerAmount(amountIn, baseDecimals)
    query = `?fromToken=${baseAddress}&toToken=${quoteAddress}&amountIn=${amount}&typeList=WTRX,SUNSWAP_V1,SUNSWAP_V2,SUNSWAP_V3`
    } else {
    Log("not support type:", type)
    return null
    }

    try {
    let ret = JSON.parse(HttpQuery("https://rot.endjgfsv.link/swap/router" + query))
    Log("https://rot.endjgfsv.link/swap/router" + query, "GetSwapOutAmount ret:", ret)

    if (!ret || ret["message"] != "SUCCESS") {
    Log("invalid data:", ret)
    return null
    }

    let outAmount = null
    let best = null
    let info = ret["data"]
    for (let ele of info) {
    if (!outAmount) {
    outAmount = parseFloat(ele["amountOut"])
    best = ele
    } else {
    let amount = parseFloat(ele["amountOut"])
    if (amount > outAmount) {
    outAmount = amount
    best = ele
    }
    }
    }

    if (!outAmount || !best) {
    Log("info:", info)
    return null
    }

    return {"info": info, "outAmount": outAmount, "best": best, "baseCurrencyInfo": baseCurrencyInfo, "quoteCurrencyInfo": quoteCurrencyInfo}
    } catch(e) {
    Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
    return null
    }
    }

    sunSwapEx.GetAccount = function() {
    let e = sunSwapEx.e

    let walletAddress = e.IO("address")
    let account = e.IO("api", "tron", "GetAccount", walletAddress)
    if (!account) {
    Log("get account failed, account:", account)
    return null
    }

    let trxBalance = toAmount(account["balance"], 6)

    let resource = e.IO("api", "tron", "GetAccountResource", walletAddress)
    if (!resource) {
    Log("get resource failed, resource:", resource)
    return null
    }

    let energyLimit = resource["EnergyLimit"] ? resource["EnergyLimit"] : 0
    let freeNetLimit = resource["freeNetLimit"] ? resource["freeNetLimit"] : 0

    return {"Info": {"GetAccount": account, "GetAccountResource": resource}, "TRX": trxBalance, "Bandwidth": freeNetLimit, "Energy": energyLimit}
    }

    sunSwapEx.GetAssets = function() {
    let e = sunSwapEx.e
    let walletAddress = e.IO("address")

    try {
    let ret = JSON.parse(HttpQuery("https://apilist.tronscanapi.com/api/account/token_asset_overview?address=" + walletAddress))

    let assets = []
    for (let info of ret["data"]) {
    let decimals = parseInt(info["tokenDecimal"])
    let asset = {
    "Currency": info["tokenAbbr"] == "trx" ? "TRX" : info["tokenAbbr"],
    "Decimals": decimals,
    "Amount": toAmount(info["balance"], decimals),
    "Address": info["tokenId"],
    }

    assets.push(asset)
    }

    return assets
    } catch(e) {
    Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
    return null
    }
    }

    sunSwapEx.StakeTRX = function(resourceName, frozenBalance) {
    return sunSwapEx.dealStakeTRX("FreezeBalanceV2", resourceName, frozenBalance)
    }

    sunSwapEx.UnStakeTRX = function(resourceName, unfreezeBalance) {
    return sunSwapEx.dealStakeTRX("UnfreezeBalanceV2", resourceName, unfreezeBalance)
    }

    sunSwapEx.WrappedTRX = function(actionType, amountIn) {
    let e = sunSwapEx.e

    let tx = null
    if (actionType == "deposit") {
    let amount = toInnerAmount(amountIn, 6)
    tx = e.IO("api", "TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR", "deposit", amount, {gasLimit: toInnerAmount(sunSwapEx.feeLimit, 6)})
    } else if (actionType == "withdraw") {
    tx = e.IO("api", "TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR", "withdraw(uint256)", toInnerAmount(amountIn, 6), {gasLimit: toInnerAmount(sunSwapEx.feeLimit, 6)})
    } else {
    Log("not support actionType:", actionType)
    return false
    }

    if (tx) {
    Log("tx: ", tx)
    let txRet = sunSwapEx.waitMined(tx)
    if (!txRet) {
    Log(actionType, "failed")
    return false
    } else {
    Log(actionType, "success")
    return true
    }
    } else {
    Log("trans error")
    return false
    }
    }

    sunSwapEx.Swap = function(symbol, amountIn, type) {
    let e = sunSwapEx.e
    let smartRouterAddress = sunSwapEx.smartRouterAddress

    if (symbol == "TRX_WTRX" || symbol == "WTRX_TRX") {
    let actionType = null
    if (type == "buy") {
    actionType = symbol == "TRX_WTRX" ? "withdraw" : "deposit"
    } else if (type == "sell") {
    actionType = symbol == "TRX_WTRX" ? "deposit" : "withdraw"
    } else {
    Log("invalid type:", type)
    return false
    }

    return sunSwapEx.WrappedTRX(actionType, amountIn)
    }

    let swapInfo = sunSwapEx.GetSwapOutAmount(symbol, amountIn, type)
    if (!swapInfo || !swapInfo["best"]) {
    Log("invalid swapInfo:", swapInfo)
    return false
    }

    let outAmount = swapInfo["outAmount"]
    let best = swapInfo["best"]

    // path
    let path = best["tokens"]
    if (!path || path.length < 2) {
    Log("invalid path:", path)
    return false
    }

    // poolVersions and versionsLen
    let poolVersions = []
    let versionsLen = []
    for (var v of best["poolVersions"]) {
    if (poolVersions.length == 0) {
    poolVersions.push(v)
    versionsLen.push(2)
    } else {
    if (poolVersions[poolVersions.length - 1] == v) {
    versionsLen[versionsLen.length - 1] += 1
    } else {
    poolVersions.push(v)
    versionsLen.push(1)
    }
    }
    }

    // fees
    let poolFees = best["poolFees"]

    // get decimals , token name
    let token0Decimals = swapInfo["baseCurrencyInfo"]["tokenDecimals"]
    let token1Decimals = swapInfo["quoteCurrencyInfo"]["tokenDecimals"]

    let tokenInName = type == "buy" ? swapInfo["quoteCurrencyInfo"]["tokenSymbol"] : swapInfo["baseCurrencyInfo"]["tokenSymbol"]
    let tokenOutName = type == "buy" ? swapInfo["baseCurrencyInfo"]["tokenSymbol"] : swapInfo["quoteCurrencyInfo"]["tokenSymbol"]
    let tokenInAddress = type == "buy" ? swapInfo["quoteCurrencyInfo"]["tokenAddress"] : swapInfo["baseCurrencyInfo"]["tokenAddress"]
    let tokenOutAddress = type == "buy" ? swapInfo["baseCurrencyInfo"]["tokenAddress"] : swapInfo["quoteCurrencyInfo"]["tokenAddress"]
    let tokenInDecimals = type == "buy" ? token1Decimals : token0Decimals

    // calc amount
    let amount = null
    let minAmount = null
    if (type == "buy") {
    amount = toInnerAmount(amountIn, token1Decimals)
    minAmount = toInnerAmount(outAmount * 0.99, token0Decimals)
    } else if (type == "sell") {
    amount = toInnerAmount(amountIn, token0Decimals)
    minAmount = toInnerAmount(outAmount * 0.99, token1Decimals)
    } else {
    Log("invalid type:", type)
    return false
    }

    // wallet address
    let walletAddress = e.IO("address")

    // expired timestamp
    let expiredTS = parseInt((new Date().getTime() + 1000 * 60 * 5) / 1000)

    // [amount of the token to be swapped, minimum acceptable amount of the token obtained from the swap, address to receive the token obtained from the swap, deadline]
    let data = [String(amount), String(minAmount), walletAddress, expiredTS]

    // allowance
    if (tokenInName != "TRX" && !(tokenInName == "WTRX" && tokenOutName == "TRX")) {
    let allowanceAmount = e.IO("api", tokenInAddress, "allowance", walletAddress, smartRouterAddress)
    let realAmount = toAmount(allowanceAmount, tokenInDecimals)
    if (realAmount < amountIn) {
    // approve
    Log("realAmount is", realAmount, "too small, try to approve large amount")
    let txApprove = e.IO("api", tokenInAddress, "approve(address,uint256)", smartRouterAddress, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", {gasLimit: toInnerAmount(sunSwapEx.feeLimit, 6)})
    if (!txApprove) {
    throw "approve error"
    }

    let txRet = sunSwapEx.waitMined(txApprove)
    if (!txRet) {
    Log("approve failed")
    return false
    } else {
    Log("approve success")
    }
    } else {
    Log("allowance", realAmount, "no need to approve")
    }
    }

    // swap
    Log(`path:${path}, poolVersions:${poolVersions}, versionsLen:${versionsLen}, poolFees:${poolFees}, data:${data}`)
    Log("best swap:", best)
    let tx = e.IO("api", smartRouterAddress, "swapExactInput(address[],string[],uint256[],uint24[],(uint256,uint256,address,uint256))", tokenInName == "TRX" ? toInnerAmount(amountIn, 6) : 0, path, poolVersions, versionsLen, poolFees, data, {gasLimit: toInnerAmount(sunSwapEx.feeLimit, 6)})
    if (tx) {
    Log("tx: ", tx)
    let txRet = sunSwapEx.waitMined(tx)
    if (!txRet) {
    Log("swap", tokenInName, "to", tokenOutName, "failed")
    return false
    } else {
    Log("swap", tokenInName, "to", tokenOutName, "success")
    return true
    }
    } else {
    Log("trans error")
    return false
    }
    }

    sunSwapEx.SendTRX = function(to, amount) {
    let e = sunSwapEx.e
    return e.IO("api", "tron", "send", to, toInnerAmount(amount, 6))
    }

    sunSwapEx.SetFeeLimit = function(feeLimit) {
    sunSwapEx.feeLimit = feeLimit
    Log("SetFeeLimit, feeLimit:", sunSwapEx.feeLimit, ", toInnerAmount:", toInnerAmount(sunSwapEx.feeLimit, 6))
    }

    // init
    if (typeof(e) == "undefined") {
    e = exchange
    Log("By default, the exchange configuration is used")
    }
    sunSwapEx.e = e

    // tron
    let ret = e.IO("api", "tron", "GetNodeInfo")
    if (!ret) {
    throw "The current Web3 tron ​​exchange object may be misconfigured"
    } else {
    Log("node information:", ret)
    }

    // feeLimit
    sunSwapEx.feeLimit = 50

    // register abi
    let factoryV3Address = "TThJt8zaJzJMhCEScH7zWKnp5buVZqys9x"
    sunSwapEx.factoryV3Address = factoryV3Address

    let poolABI = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"indexed":true,"name":"owner","internalType":"address","type":"address"},{"indexed":true,"name":"tickLower","internalType":"int24","type":"int24"},{"indexed":true,"name":"tickUpper","internalType":"int24","type":"int24"},{"indexed":false,"name":"amount","internalType":"uint128","type":"uint128"},{"indexed":false,"name":"amount0","internalType":"uint256","type":"uint256"},{"indexed":false,"name":"amount1","internalType":"uint256","type":"uint256"}],"name":"Burn","anonymous":false,"type":"event"},{"inputs":[{"indexed":true,"name":"owner","internalType":"address","type":"address"},{"indexed":false,"name":"recipient","internalType":"address","type":"address"},{"indexed":true,"name":"tickLower","internalType":"int24","type":"int24"},{"indexed":true,"name":"tickUpper","internalType":"int24","type":"int24"},{"indexed":false,"name":"amount0","internalType":"uint128","type":"uint128"},{"indexed":false,"name":"amount1","internalType":"uint128","type":"uint128"}],"name":"Collect","anonymous":false,"type":"event"},{"inputs":[{"indexed":true,"name":"sender","internalType":"address","type":"address"},{"indexed":true,"name":"recipient","internalType":"address","type":"address"},{"indexed":false,"name":"amount0","internalType":"uint128","type":"uint128"},{"indexed":false,"name":"amount1","internalType":"uint128","type":"uint128"}],"name":"CollectProtocol","anonymous":false,"type":"event"},{"inputs":[{"indexed":true,"name":"sender","internalType":"address","type":"address"},{"indexed":true,"name":"recipient","internalType":"address","type":"address"},{"indexed":false,"name":"amount0","internalType":"uint256","type":"uint256"},{"indexed":false,"name":"amount1","internalType":"uint256","type":"uint256"},{"indexed":false,"name":"paid0","internalType":"uint256","type":"uint256"},{"indexed":false,"name":"paid1","internalType":"uint256","type":"uint256"}],"name":"Flash","anonymous":false,"type":"event"},{"inputs":[{"indexed":false,"name":"observationCardinalityNextOld","internalType":"uint16","type":"uint16"},{"indexed":false,"name":"observationCardinalityNextNew","internalType":"uint16","type":"uint16"}],"name":"IncreaseObservationCardinalityNext","anonymous":false,"type":"event"},{"inputs":[{"indexed":false,"name":"sqrtPriceX96","internalType":"uint160","type":"uint160"},{"indexed":false,"name":"tick","internalType":"int24","type":"int24"}],"name":"Initialize","anonymous":false,"type":"event"},{"inputs":[{"indexed":false,"name":"sender","internalType":"address","type":"address"},{"indexed":true,"name":"owner","internalType":"address","type":"address"},{"indexed":true,"name":"tickLower","internalType":"int24","type":"int24"},{"indexed":true,"name":"tickUpper","internalType":"int24","type":"int24"},{"indexed":false,"name":"amount","internalType":"uint128","type":"uint128"},{"indexed":false,"name":"amount0","internalType":"uint256","type":"uint256"},{"indexed":false,"name":"amount1","internalType":"uint256","type":"uint256"}],"name":"Mint","anonymous":false,"type":"event"},{"inputs":[{"indexed":false,"name":"feeProtocol0Old","internalType":"uint8","type":"uint8"},{"indexed":false,"name":"feeProtocol1Old","internalType":"uint8","type":"uint8"},{"indexed":false,"name":"feeProtocol0New","internalType":"uint8","type":"uint8"},{"indexed":false,"name":"feeProtocol1New","internalType":"uint8","type":"uint8"}],"name":"SetFeeProtocol","anonymous":false,"type":"event"},{"inputs":[{"indexed":true,"name":"sender","internalType":"address","type":"address"},{"indexed":true,"name":"recipient","internalType":"address","type":"address"},{"indexed":false,"name":"amount0","internalType":"int256","type":"int256"},{"indexed":false,"name":"amount1","internalType":"int256","type":"int256"},{"indexed":false,"name":"sqrtPriceX96","internalType":"uint160","type":"uint160"},{"indexed":false,"name":"liquidity","internalType":"uint128","type":"uint128"},{"indexed":false,"name":"tick","internalType":"int24","type":"int24"}],"name":"Swap","anonymous":false,"type":"event"},{"outputs":[{"name":"","internalType":"address","type":"address"}],"inputs":[],"name":"factory","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"uint24","type":"uint24"}],"inputs":[],"name":"fee","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"uint256","type":"uint256"}],"inputs":[],"name":"feeGrowthGlobal0X128","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"uint256","type":"uint256"}],"inputs":[],"name":"feeGrowthGlobal1X128","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"uint128","type":"uint128"}],"inputs":[],"name":"liquidity","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"uint128","type":"uint128"}],"inputs":[],"name":"maxLiquidityPerTick","stateMutability":"view","type":"function"},{"outputs":[{"name":"blockTimestamp","internalType":"uint32","type":"uint32"},{"name":"tickCumulative","internalType":"int56","type":"int56"},{"name":"secondsPerLiquidityCumulativeX128","internalType":"uint160","type":"uint160"},{"name":"initialized","internalType":"bool","type":"bool"}],"inputs":[{"name":"","internalType":"uint256","type":"uint256"}],"name":"observations","stateMutability":"view","type":"function"},{"outputs":[{"name":"liquidity","internalType":"uint128","type":"uint128"},{"name":"feeGrowthInside0LastX128","internalType":"uint256","type":"uint256"},{"name":"feeGrowthInside1LastX128","internalType":"uint256","type":"uint256"},{"name":"tokensOwed0","internalType":"uint128","type":"uint128"},{"name":"tokensOwed1","internalType":"uint128","type":"uint128"}],"inputs":[{"name":"","internalType":"bytes32","type":"bytes32"}],"name":"positions","stateMutability":"view","type":"function"},{"outputs":[{"name":"token0","internalType":"uint128","type":"uint128"},{"name":"token1","internalType":"uint128","type":"uint128"}],"inputs":[],"name":"protocolFees","stateMutability":"view","type":"function"},{"outputs":[{"name":"sqrtPriceX96","internalType":"uint160","type":"uint160"},{"name":"tick","internalType":"int24","type":"int24"},{"name":"observationIndex","internalType":"uint16","type":"uint16"},{"name":"observationCardinality","internalType":"uint16","type":"uint16"},{"name":"observationCardinalityNext","internalType":"uint16","type":"uint16"},{"name":"feeProtocol","internalType":"uint8","type":"uint8"},{"name":"unlocked","internalType":"bool","type":"bool"}],"inputs":[],"name":"slot0","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"uint256","type":"uint256"}],"inputs":[{"name":"","internalType":"int16","type":"int16"}],"name":"tickBitmap","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"int24","type":"int24"}],"inputs":[],"name":"tickSpacing","stateMutability":"view","type":"function"},{"outputs":[{"name":"liquidityGross","internalType":"uint128","type":"uint128"},{"name":"liquidityNet","internalType":"int128","type":"int128"},{"name":"feeGrowthOutside0X128","internalType":"uint256","type":"uint256"},{"name":"feeGrowthOutside1X128","internalType":"uint256","type":"uint256"},{"name":"tickCumulativeOutside","internalType":"int56","type":"int56"},{"name":"secondsPerLiquidityOutsideX128","internalType":"uint160","type":"uint160"},{"name":"secondsOutside","internalType":"uint32","type":"uint32"},{"name":"initialized","internalType":"bool","type":"bool"}],"inputs":[{"name":"","internalType":"int24","type":"int24"}],"name":"ticks","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"address","type":"address"}],"inputs":[],"name":"token0","stateMutability":"view","type":"function"},{"outputs":[{"name":"","internalType":"address","type":"address"}],"inputs":[],"name":"token1","stateMutability":"view","type":"function"},{"outputs":[{"name":"tickCumulativeInside","internalType":"int56","type":"int56"},{"name":"secondsPerLiquidityInsideX128","internalType":"uint160","type":"uint160"},{"name":"secondsInside","internalType":"uint32","type":"uint32"}],"inputs":[{"name":"tickLower","internalType":"int24","type":"int24"},{"name":"tickUpper","internalType":"int24","type":"int24"}],"name":"snapshotCumulativesInside","stateMutability":"view","type":"function"},{"outputs":[{"name":"tickCumulatives","internalType":"int56[]","type":"int56[]"},{"name":"secondsPerLiquidityCumulativeX128s","internalType":"uint160[]","type":"uint160[]"}],"inputs":[{"name":"secondsAgos","internalType":"uint32[]","type":"uint32[]"}],"name":"observe","stateMutability":"view","type":"function"},{"outputs":[],"inputs":[{"name":"observationCardinalityNext","internalType":"uint16","type":"uint16"}],"name":"increaseObservationCardinalityNext","stateMutability":"nonpayable","type":"function"},{"outputs":[],"inputs":[{"name":"sqrtPriceX96","internalType":"uint160","type":"uint160"}],"name":"initialize","stateMutability":"nonpayable","type":"function"},{"outputs":[{"name":"amount0","internalType":"uint256","type":"uint256"},{"name":"amount1","internalType":"uint256","type":"uint256"}],"inputs":[{"name":"recipient","internalType":"address","type":"address"},{"name":"tickLower","internalType":"int24","type":"int24"},{"name":"tickUpper","internalType":"int24","type":"int24"},{"name":"amount","internalType":"uint128","type":"uint128"},{"name":"data","internalType":"bytes","type":"bytes"}],"name":"mint","stateMutability":"nonpayable","type":"function"},{"outputs":[{"name":"amount0","internalType":"uint128","type":"uint128"},{"name":"amount1","internalType":"uint128","type":"uint128"}],"inputs":[{"name":"recipient","internalType":"address","type":"address"},{"name":"tickLower","internalType":"int24","type":"int24"},{"name":"tickUpper","internalType":"int24","type":"int24"},{"name":"amount0Requested","internalType":"uint128","type":"uint128"},{"name":"amount1Requested","internalType":"uint128","type":"uint128"}],"name":"collect","stateMutability":"nonpayable","type":"function"},{"outputs":[{"name":"amount0","internalType":"uint256","type":"uint256"},{"name":"amount1","internalType":"uint256","type":"uint256"}],"inputs":[{"name":"tickLower","internalType":"int24","type":"int24"},{"name":"tickUpper","internalType":"int24","type":"int24"},{"name":"amount","internalType":"uint128","type":"uint128"}],"name":"burn","stateMutability":"nonpayable","type":"function"},{"outputs":[{"name":"amount0","internalType":"int256","type":"int256"},{"name":"amount1","internalType":"int256","type":"int256"}],"inputs":[{"name":"recipient","internalType":"address","type":"address"},{"name":"zeroForOne","internalType":"bool","type":"bool"},{"name":"amountSpecified","internalType":"int256","type":"int256"},{"name":"sqrtPriceLimitX96","internalType":"uint160","type":"uint160"},{"name":"data","internalType":"bytes","type":"bytes"}],"name":"swap","stateMutability":"nonpayable","type":"function"},{"outputs":[],"inputs":[{"name":"recipient","internalType":"address","type":"address"},{"name":"amount0","internalType":"uint256","type":"uint256"},{"name":"amount1","internalType":"uint256","type":"uint256"},{"name":"data","internalType":"bytes","type":"bytes"}],"name":"flash","stateMutability":"nonpayable","type":"function"},{"outputs":[],"inputs":[{"name":"feeProtocol0","internalType":"uint8","type":"uint8"},{"name":"feeProtocol1","internalType":"uint8","type":"uint8"}],"name":"setFeeProtocol","stateMutability":"nonpayable","type":"function"},{"outputs":[{"name":"amount0","internalType":"uint128","type":"uint128"},{"name":"amount1","internalType":"uint128","type":"uint128"}],"inputs":[{"name":"recipient","internalType":"address","type":"address"},{"name":"amount0Requested","internalType":"uint128","type":"uint128"},{"name":"amount1Requested","internalType":"uint128","type":"uint128"}],"name":"collectProtocol","stateMutability":"nonpayable","type":"function"}]`
    sunSwapEx.poolABI = poolABI

    let multicallContractAddress = "TGXuuKAb4bnrn137u39EKbYzKNXvdCes98"
    sunSwapEx.multicallContractAddress = multicallContractAddress
    let multicallContractABI = `[{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct TronMulticall.Call[]","name":"calls","type":"tuple[]"}],"name":"aggregate","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes[]","name":"returnData","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBasefee","outputs":[{"internalType":"uint256","name":"basefee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getBlockHash","outputs":[{"internalType":"bytes32","name":"blockHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockNumber","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"chainid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentBlockCoinbase","outputs":[{"internalType":"address","name":"coinbase","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentBlockDifficulty","outputs":[{"internalType":"uint256","name":"difficulty","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentBlockTimestamp","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getEthBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastBlockHash","outputs":[{"internalType":"bytes32","name":"blockHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountAddress","type":"address"},{"internalType":"trcToken","name":"id","type":"trcToken"}],"name":"getTokenBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isContract","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"view","type":"function"}]`
    sunSwapEx.registerABI(multicallContractAddress, multicallContractABI)

    let smartRouterAddress = "TCFNp179Lg46D16zKoumd4Poa2WFFdtqYj"
    sunSwapEx.smartRouterAddress = smartRouterAddress
    let smartRouterABI = `[{"outputs":[{"name":"amountsOut","type":"uint256[]"}],"inputs":[{"name":"path","type":"address[]"},{"name":"poolVersion","type":"string[]"},{"name":"versionLen","type":"uint256[]"},{"name":"fees","type":"uint24[]"},{"name":"data","type":"tuple"}],"name":"swapExactInput","stateMutability":"payable","type":"function","payable":true}]`
    sunSwapEx.registerABI(smartRouterAddress, smartRouterABI)

    // get sunswap_markets
    sunSwapEx.markets = _G("sunswap_markets")

    return sunSwapEx
    }

    // for test
    function main() {
    // reset log
    LogReset(1)
    // reset _G()
    // _G(null)

    // Create SunswapEx
    let e = $.CreateSunSwapEx()
    // let e = $.CreateSunSwapEx(exchanges[1])

    // /* GetMarkets
    let markets = e.GetMarkets()
    let idx = 0
    let tbl = {"type": "table", "title": "test GetMarkets", "cols": ["Index", "PoolAddress", "Symbol", "BaseAsset", "QuoteAsset", "BaseName", "QuoteName", "BaseDecimals", "QuoteDecimals", "BaseAddress", "QuoteAddress"], "rows": []}
    for (let currency in markets) {
    let arrMarket = markets[currency]
    for (let market of arrMarket) {
    tbl["rows"].push([idx, market["PoolAddress"], market["Symbol"], market["BaseAsset"], market["QuoteAsset"], market["BaseName"], market["QuoteName"], market["BaseDecimals"], market["QuoteDecimals"], market["BaseAddress"], market["QuoteAddress"]])
    idx++
    }
    }
    LogStatus("`" + JSON.stringify(tbl) + "`")
    // */

    /* GetTicker
    let ticker1 = e.GetTicker("WTRX_USDT")
    Log("symbol:", "WTRX_USDT", ", ticker:", ticker1)
    let ticker2 = e.GetTicker("iCMX_USDT", "TLVDozYEBgeaJXH7oKBsougzEJKNrogFun") // iCMX_USDT
    Log("symbol:", "iCMX_USDT", ", ticker:", ticker2)
    */

    /* multicall
    let data = []
    let walletAddress = exchange.IO("address")
    data.push(["TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "0x" + exchange.IO("encode", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", walletAddress)])
    data.push(["TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "0x" + exchange.IO("encode", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", walletAddress)])
    Log(data)
    let ret = multicall(exchange, "TGXuuKAb4bnrn137u39EKbYzKNXvdCes98", data, ["uint256", "uint256"])
    Log(ret, toAmount(ret[0], 6))
    */

    /* GetSwapOutAmount
    let retBuy = e.GetSwapOutAmount("WTRX_USDT", 1, "buy") // 1 quote -> base
    Log("WTRX_USDT", "buy outAmount:", retBuy["outAmount"], ", ask:", (1 / retBuy["outAmount"]))
    let retSell = e.GetSwapOutAmount("WTRX_USDT", 1, "sell") // 1 base -> quote
    Log("WTRX_USDT", "sell outAmount:", retSell["outAmount"], ", bid:", (retSell["outAmount"] / 1))
    */

    /* GetAssets
    let assets = e.GetAssets()
    let tbl = {"type": "table", "title": "test GetAssets", "cols": ["Name", "Address", "Decimals", "Balance"], "rows": []}
    for (let asset of assets) {
    tbl["rows"].push([asset.Currency, asset.Address, asset.Decimals, asset.Amount])
    }
    LogStatus("`" + JSON.stringify(tbl) + "`")
    */

    /* Swap
    // let ret = e.Swap("WTRX_USDT", 6, "buy")
    // let ret = e.Swap("WTRX_TUSD", 6, "buy")
    // let ret = e.Swap("WTRX_TUSD", 10, "sell")
    // let ret = e.Swap("TRX_WTRX", 10, "sell")
    // let ret = e.Swap("TRX_WTRX", 10, "buy")
    // let ret = e.Swap("TUSD_TRX", 0.3, "sell")
    // let ret = e.Swap("WTRX_USDT", 20, "sell")
    // let ret = e.Swap("USDT_TRX", 6, "sell")
    Log(ret)
    */

    /* check token
    let mapFilter = {}
    let checkMarkets = e.GetMarkets()
    for (let currency in checkMarkets) {
    for (let market of checkMarkets[currency]) {
    let base = market["BaseAsset"]
    let quote = market["QuoteAsset"]
    if (typeof(mapFilter[base]) == "undefined") {
    mapFilter[base] = market["BaseAddress"]
    }
    if (typeof(mapFilter[quote]) == "undefined") {
    mapFilter[quote] = market["QuoteAddress"]
    }

    if (market["BaseAddress"] != mapFilter[base]) {
    Log(market["BaseAsset"], market["BaseAddress"], " --- ", base, mapFilter[base])
    }
    if (market["QuoteAddress"] != mapFilter[quote]) {
    Log(market["QuoteAsset"], market["QuoteAddress"], " --- ", quote, mapFilter[quote])
    }
    }
    }
    */

    /* GetAccount
    let account = e.GetAccount()
    Log(account)
    */

    /* StakeTRX
    // BANDWIDTH, ENERGY, TRON_POWER
    let retStakeTRX = e.StakeTRX("ENERGY", 10) // Stake TRX
    Log("retStakeTRX:", retStakeTRX)
    // let retUnStakeTRX = e.UnStakeTRX("ENERGY", 100) // UnStake TRX
    // Log("retUnStakeTRX:", retUnStakeTRX)
    */

    /* send
    // let ret = e.SendTRX("...", 180)
    // Log("SendTRX ret:", ret)
    */
    }









    END



    Through this article, we have realized the Web3 Tron package based on the FMZ Quant platform, and connected to SunSwap DEX successfully, completing the complete process from querying the trading pool to executing the exchange and parsing the transaction results. This not only provides an efficient automation solution for DEX transactions in the Tron ecosystem, but also demonstrates the powerful scalability of the FMZ Quant platform.



    I hope that the practical experience in this article can provide valuable reference for your quantitative trading system. Next, I will study the DEX on SOL.

    Thank you for reading~

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
The Gemini desktop app is now available for Windows
1 Quelle
Windows 11 just dropped the tool ransomware abused, Microsoft says don’t restore WMIC
1 Quelle
Vorsicht: Android-Malware verschlüsselt Ihre Handys und nimmt heimlich Fotos auf
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Practice of Web3 Tron Encapsulated and Access to SunSwap DEX Based on FMZ Platform

Thematisch verwandte Begriffe: Practice, Web3, Tron, Encapsulated · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...