Type/to search
8
Follow
1364
Followers
FMZ प्लेटफॉर्म पर आधारित वेब3 ट्रॉन पैकेजिंग और सनस्वैप DEX तक पहुंच का अभ्यास
Discussions
Created 2025-03-21 15:17:05  Updated 2025-03-28 09:52:32
 0
 1113

प्रस्तावना

ब्लॉकचेन लेनदेन के क्षेत्र में, विकेन्द्रीकृत एक्सचेंज (DEX) परिसंपत्तियों के आदान-प्रदान के लिए एक भरोसेमंद तरीका प्रदान करते हैं, और ट्रॉन पारिस्थितिकी तंत्र में एक प्रतिनिधि DEX के रूप में सनस्वैप, वेब 3 पर आधारित स्मार्ट अनुबंध इंटरैक्शन का समर्थन करता है। एफएमजेड प्लेटफॉर्म (एफएमजेड क्वांटिटेटिव) एक शक्तिशाली मात्रात्मक ट्रेडिंग ढांचा प्रदान करता है जो डेवलपर्स को कई ट्रेडिंग रणनीतियों को एकीकृत करने में सक्षम बनाता है।

FMZ प्लेटफॉर्म पहले से ही Web3 Ethereum (ETH) एक्सचेंज ऑब्जेक्ट्स के एनकैप्सुलेशन का समर्थन करता है, और हाल ही में TRON श्रृंखला के एक्सचेंज ऑब्जेक्ट्स को एनकैप्सुलेट करते हुए Web3 TRON के लिए समर्थन जोड़ा गया है। UniSwap DEX तक पहुंचने की तरह, SunSwap DEX तक भी पहुंच प्राप्त की जा सकती है।

यह आलेख यह पता लगाएगा कि FMZ मात्रात्मक प्लेटफॉर्म पर आधारित Web3 इंटरफ़ेस को कैसे समाहित किया जाए और लेनदेन के लिए SunSwap DEX से कैसे जोड़ा जाए। हम ट्रॉन नेटवर्क की वेब3 इंटरैक्शन विधि, सनस्वैप स्मार्ट कॉन्ट्रैक्ट कॉल का परिचय देंगे, और कोड उदाहरणों के माध्यम से दिखाएंगे कि तरलता की जांच कैसे करें, लेनदेन निष्पादित करें और लेनदेन परिणाम प्राप्त करें, ताकि एक कुशल मात्रात्मक व्यापार रणनीति बनाई जा सके।

कथन

इस आलेख में साझा किए गए सभी कोड और डिज़ाइन का परीक्षण किया गया है और वे सीखने और संचार के लिए हैं। हालाँकि, परीक्षण के बाद भी वास्तविक आवश्यकताओं के आधार पर इन्हें समायोजित करने की आवश्यकता हो सकती है। यदि आपको इसे वास्तविक ट्रेडिंग में लागू करने की आवश्यकता है, तो कृपया स्वयं इसका मूल्यांकन, अनुकूलन और संशोधन करना सुनिश्चित करें ताकि यह आपकी आवश्यकताओं को पूरा कर सके।

तैयारी

  • FMZ प्लेटफ़ॉर्म के Web3 TRON एक्सचेंज ऑब्जेक्ट को कॉन्फ़िगर करें

    पिछले लेख में「FMZ क्वांटिटेटिव वेब3 विस्तार: ट्रॉन समर्थन जोड़ें और ऑन-चेन लेनदेन क्षमताओं का विस्तार करें」इस लेख में हमने प्रस्तुत किया हैTron gRPC हमने नोड्स स्थापित करने के सामान्य तरीकों और FMZ पर Web3 TRON एक्सचेंज ऑब्जेक्ट को कॉन्फ़िगर करने के तरीके को सीखा है। इस लेख में इन सामग्रियों को दोहराया नहीं जाएगा। जहां तक ​​नोड पते की बात है, हम सीधे TRON द्वारा आधिकारिक तौर पर उपलब्ध कराए गए नोड का उपयोग करेंगे।

  • होस्ट तैनात करें

सीईएक्स एक्सचेंजों के विपरीत, यहां चिंता करने वाली कोई दीवार नहीं है। आप स्थानीय स्तर पर होस्ट तैनात करके आधिकारिक नोड तक पहुंच सकते हैं।

  • SunSwap DEX

    https://sun.io/

    ब्राउज़र में SunSwap का फ्रंट-एंड पेज खोलें, आप वॉलेट से कनेक्ट कर सकते हैं और डेटा को सुविधाजनक रूप से देख सकते हैं।

  • tronscan

    https://tronscan.org/

    डेटा देखने और विश्लेषण के लिए आवश्यक उपकरण।

  • base58

    ट्रॉन पर पते बेस58 एनकोडेड हैं, जो एथेरियम से अलग है। कभी-कभी डेटा को देखने और तुलना करने के लिए कुछ रूपांतरण की आवश्यकता होती है। FMZ पर, आप सीधे बेस58-एन्कोडेड पते का उपयोग कर सकते हैं। कुछ स्मार्ट अनुबंध HEX एन्कोडिंग में डेटा लौटाते हैं, जिसके लिए कुछ रूपांतरण की आवश्यकता होती है। पता प्रारूपों को परिवर्तित करने के लिए कई कार्यों को सरलता से क्रियान्वित किया जाता है:

    मुख्य रूपांतरण कार्य निम्नलिखित हैं। सीमित स्थान के कारण, मैं सभी कोड पोस्ट नहीं कर पाऊंगा। पूरा कोड "ट्रॉन सनस्वैप V3 ट्रेडिंग लाइब्रेरी" टेम्पलेट लाइब्रेरी में है जिसका खुलासा लेख के अंत में किया गया है।

    javascript
    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) }
  • पैकेज कॉल

    चूंकि कभी-कभी आपको एक साथ कई विधियों से डेटा पढ़ने की आवश्यकता होती है, इसलिए उन्हें एक-एक करके कॉल करना समय लेने वाला और श्रमसाध्य होता है। अतः पैकेज्ड कॉलिंग फ़ंक्शन को इस प्रकार समाहित किया जाता है:

    javascript
    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 }

ट्रॉन सनस्वैप V3 ट्रेडिंग लाइब्रेरी

सनस्वैप V3 ट्रेडिंग लाइब्रेरी का डिज़ाइन FMZ प्लेटफॉर्म के यूनीस्वैप ट्रेडिंग लाइब्रेरी टेम्पलेट के आधार पर तैयार किया गया है। चूंकि सनस्वैप टेम्पलेट कोड अपेक्षाकृत लंबा है, इसलिए मैं इसे यहां पोस्ट नहीं करूंगा, लेकिन मुख्य रूप से कार्यान्वित कार्यों को समझाऊंगा।

SunSwap लेनदेन ऑब्जेक्ट बनाएँ

javascript
let e = $.CreateSunSwapEx() // 默认使用exchange即exchanges[0]初始化SunSwap交易对象。 // let e = $.CreateSunSwapEx(exchanges[1]) // 使用次交易所对象初始化SunSwap交易对象。

इस टेम्पलेट में केवल एक इंटरफ़ेस फ़ंक्शन है, अर्थात्:$.CreateSunSwapEx()सनस्वैप लेनदेन ऑब्जेक्ट बनाने के लिए उपयोग किया जाता है। ऑब्जेक्ट बनने के बाद, आप कुछ कार्यात्मक कॉल करने के लिए इस ऑब्जेक्ट की विधि को कॉल कर सकते हैं, जैसे: मोचन लेनदेन, क्वेरी पूल की कीमतें, सभी V3 पूल जानकारी प्राप्त करना, प्रतिज्ञा, विघटन, आदि।

GetMarkets

"ट्रॉन सनस्वैप V3 ट्रेडिंग लाइब्रेरी" का परीक्षण कोड टेम्पलेट में हैmain()यह समारोह रिकार्ड कर लिया गया है और इसे यहां दोहराया नहीं जाएगा।

javascript
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) + "`")

समारोहGetMarkets()इसका उपयोग सनस्वैप V3 पूल के सभी एक्सचेंज पूल की प्रासंगिक जानकारी प्राप्त करने के लिए किया जाता है, जो सनस्वैप लेनदेन ऑब्जेक्ट के चरों में कैश किया जाता है, तथा अन्य कार्यों के दौरान सटीकता, पता और अन्य जानकारी की क्वेरी करने के लिए उपयोग किया जाता है।

यह परीक्षण कोड चलाने के बाद सभी V3 पूल के बारे में जानकारी प्रदर्शित करेगा:

img

कोड ने वर्तमान में देखे जा रहे कुछ अनुबंध पतों को हटा दिया है, जैसे "फ़िशिंग अनुबंध" और "अमान्य अनुबंध"।

GetTicker

javascript
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)

इस्तेमाल किया जा सकता हैGetTicker()यह फ़ंक्शन किसी निश्चित एक्सचेंज पूल की कीमत की क्वेरी करता है और किसी विशिष्ट पूल का पता निर्दिष्ट कर सकता है। ध्यान दें कि कुछ पूलों में तरलता बहुत कम होती है और कीमतें केवल संदर्भ के लिए होती हैं।

multicall

javascript
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))

इस फ़ंक्शन का उपयोग बाद के फ़ंक्शन एनकैप्सुलेशन के लिए किया जा सकता है। उदाहरण के लिए, उदाहरण में, आप डाल सकते हैंbalanceOfविधि कॉल को एनकोड किया जाता है और डेटा एक बार अनुरोध किया जाता है।

GetSwapOutAmount

javascript
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))

यह एक अपेक्षाकृत महत्वपूर्ण कार्य है, जो सनस्वैप की बुद्धिमान रूटिंग सेवा को समाहित करता है। tokenInSymbol और tokenOutSymbol दिए जाने पर, यह संभावित विनिमय पथ, आउटपुट टोकन की संख्या और अन्य जानकारी लौटा सकता है।

img

GetAssets

javascript
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) + "`")

चूंकि TRC20 टोकन को पार करने के लिए कोई अच्छा तंत्र नहीं है, इसलिए ट्रॉनस्कैन के ट्रैवर्सल की मदद से, इस तृतीय-पक्ष इंटरफ़ेस का उपयोग खाता परिसंपत्ति की जानकारी क्वेरी करने के लिए किया जाता है।

img

img

Swap

javascript
// 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)

सबसे महत्वपूर्ण कार्य विनिमय है। एक्सचेंज को निष्पादित करते समय, एक्सचेंज पथ को बुद्धिमान रूटिंग के अनुसार तैयार किया जाएगा, और फिर टोकन का आदान-प्रदान करने के लिए एक्सचेंज विधि को बुलाया जाएगा।
कृपया ध्यान दें कि यदि यह TRX पैकेजिंग/अनपैकिंग एक्सचेंज है, तो इसे केवल WTRX अनुबंध विधि का उपयोग करके निष्पादित किया जाता है।

कुछ अन्य फ़ंक्शन हैं जिन्हें टेम्पलेट कोड में जोड़ा जा सकता हैmain()मैं इसके कार्य के बारे में विस्तार से नहीं बताऊंगा।

टेम्पलेट कोड

इस टेम्पलेट में कोई भी नहीं हैइंटरेक्शन डिज़ाइनऔरइंटरफ़ेस पैरामीटर, यह केवल SunSwap DEX तक पहुँचने के मूल कार्य को महसूस करता है, और भविष्य में अधिक कार्यों को अनुकूलित और जोड़ा जा सकता है।

javascript
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", // 注意:钓鱼合约 "TXioUZK8ju3R54KvzSqPc6Ufq5wkxFqpq9": "U S D T", // 注意:钓鱼合约 "TU41FWQQT8hZ6t72gVEjtSGn1Dshbevi7g": "CNY Coin", // 注意:无效 "TYB7oXNq4VyuiH5BHb4os8rTh7Ca8pxqSx": "BULL", // 注意:钓鱼合约 "TYJxozCVMUiHg3TbQp9PKeuXdTsX9ugJz9": "SHISHA", // 注意:不流通 "TF9io9LGyjuK3uTpr73pAaQ5m9scxd9xvr": "TestToken18", // 注意:测试交易对 "TK8E3sFhBt3EB6gTT6d6co8RMB6DFUnNwE": "TestToken6" // 注意:测试交易对 } 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("默认使用exchange配置") } sunSwapEx.e = e // tron let ret = e.IO("api", "tron", "GetNodeInfo") if (!ret) { throw "当前Web3 tron交易所对象可能配置有误" } else { Log("node节点信息:", 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

इस लेख के माध्यम से, हमने FMZ मात्रात्मक मंच पर आधारित वेब 3 ट्रॉन एनकैप्सुलेशन का एहसास किया है और सफलतापूर्वक सनस्वैप DEX से जुड़ा है, ट्रेडिंग पूल को क्वेरी करने से लेकर एक्सचेंज को निष्पादित करने और लेनदेन के परिणामों को पार्स करने तक की पूरी प्रक्रिया को पूरा किया है। यह न केवल ट्रॉन पारिस्थितिकी तंत्र में DEX लेनदेन के लिए एक कुशल स्वचालन समाधान प्रदान करता है, बल्कि FMZ मात्रात्मक मंच की शक्तिशाली मापनीयता को भी प्रदर्शित करता है।

मुझे आशा है कि इस लेख में दिया गया व्यावहारिक अनुभव आपकी मात्रात्मक व्यापार प्रणाली के लिए मूल्यवान संदर्भ प्रदान कर सकता है। इसके बाद, मैं SOL पर DEX का अध्ययन करूंगा।
पढ़ने के लिए धन्यवाद~

Comment
All comments (0)
No data
No data
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)