[TOC]
区块链技术的发展正在推动量化交易进入Web3时代。FMZ量化交易平台作为领先的量化交易工具,早已在Web3方向上进行探索,并提供了 以太坊 (Ethereum) 相关功能,使用户能够直接在链上进行智能合约交互、资金管理和自动化交易策略执行。
如今,FMZ平台进一步扩展了Web3交易能力,支持Tron(TRX)网络,让用户可以在以太坊和Tron两大主流公链 上部署量化交易策略。这一升级不仅提升了跨链交易的灵活性,也为交易者提供了更多链上资产管理的可能性。
在本篇文章中,我们将详细介绍:
TRX-波场 简介详情 (引用于非小号)
波场TRON由孙宇晨阁下于2017年9月创立,自2018年5月主网上线以来已经取得诸多杰出成就。2018年7月,波场TRON生态完成与BitTorrent的整合,后者是一家提供去中心化Web 3.0服务的先驱企业,拥有超过1亿月活用户。近年来,波场TRON网络表现亮眼。TRONSCAN数据显示,截至2022年10月,波场TRON公链用户总数突破1.15亿,交易笔数超40亿,总锁仓量(TVL)超132亿美元。波场网络于2021年12月实现完全去中心化,现为由社区治理的去中心化自治组织(DAO)。2022年5月,波场TRON宣布推出去中心化超抵押稳定币USDD,由业内加密货币央行波场联合储备支持,标志着波场TRON正式进入去中心化稳定币时代。2022年10月,多米尼克宣布波场TRON为其官方指定的国家级区块链基础设施,波场TRON也由此成为一个与主权国家达成合作发展区块链基础设施的大型公链。 波场TRON被授权发行多米尼克粉丝代币——多米尼克币(Dominica Coin, DMC),以此提升多米尼克自然遗产和旅游景点在全球的知名度。同时,波场TRON旗下七大代币被授予多米尼克法定数字货币与法币地位。
高吞吐量:高吞吐量是通过改善TRON中的TPS实现的,日常使用实用程度已经超过比特币和以太坊。
可扩展性:基于良好的可扩展性和高效的智能合约,应用程序可以在TRON中有更多部署方式,TRON可以支持大量的用户。
高可靠性:TRON具有更可靠的网络结构,用户资产,内在价值,并且更高程度的分权化共识带来了改进的奖励分配机制。
grpc.trongrid.io:50051
可以使用其它节点提供商的JSON-RPC节点、REST节点等(可以使用HttpQuery方式请求)。在FMZ上对于exchange交易所对象封装的调用仅为grpc方法。
需要准备一个波场钱包,可以用OKX、imToken等,也可以自己直接生成。
在 FMZ 平台支持 Tron 之前,已率先支持以太坊的 Web3 方向开发。你可以回顾往期文章,了解如何接入 UniSwap 去中心化交易所。由于 Tron 兼容以太坊,同时融合了 ETH 和 EOS 的一些特性,其在智能合约执行和链上交互方面具备独特优势。在FMZ平台上配置Tron交易所对象(钱包、节点信息)与配置以太坊交易所对象(钱包、节点信息)几乎一致。
在添加交易所页面:
配置钱包,ChainType选择TRON,可以使用默认的RPC节点地址。
我们可以使用平台的调试工具测试。
这个方法看名字就知道和以太坊的方法一模一样,功能也是一模一样。该方法用于读取指定的Tron钱包中的TRX余额。
curl https://docs-demo.tron-mainnet.quiknode.pro/jsonrpc \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_getBalance","params":["0x41f0cc5a2a84cd0f68ed1667070934542d673acbd8", "latest"],"id":1,"jsonrpc":"2.0"}'
请求到的余额数据是一个非常大的十六进制数值,需要用到我们之前用于以太坊相关策略中的转换函数。
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)
}
由于Tron钱包上复制出的钱包地址为base58编码的地址,需要转换为hex编码传入参数才可以用。
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
}
我们转换好地址,就可以调用这个eth_getBalance
方法了。
完整的测试代码:
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 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
}
function main() {
var tronAddress = "Tron 钱包地址"
var hexAddress = base58ToHex(tronAddress).substring(2, 44)
var jsonrpcBase = "https://go.getblock.io/xxx/jsonrpc" // 具体的JSON-RPC节点
var body = {
"method": "eth_getBalance",
"params": [hexAddress, "latest"],
"id":1,
"jsonrpc":"2.0"
}
var options = {
method: "POST",
body: JSON.stringify(body),
headers: {"accept": "application/json", "content-type": "application/json"},
timeout: 1000
}
var ret = JSON.parse(HttpQuery(jsonrpcBase, options))
var balance = ret.result
return toAmount(balance, 6)
}
TRX的代币精度为6,所以处理bigNumber时填写参数6。
在FMZ平台的调试工具中测试:
对比在tronscan上查询到的钱包中TRX余额,数据一致。
在FMZ平台上主要实践的内容还是grpc节点的方法调用,因为篇幅有限,这里只列举常用的方法调用。
调用原型:exchange.IO("api", "tron", "method name", ...)
。”method name”为所要调用的方法名称。
查询钱包账户信息。
function main() {
var account = exchange.IO("api", "tron", "GetAccount", "tron 钱包地址") // tron 钱包地址 :填写实际的钱包地址。
return account
}
返回调用信息(节选):
{
"address": {},
"balance": 72767348, // 即钱包的TRX余额:72.767348
"asset_optimized": true,
"create_time": 1693463943000,
...
查询转账。
function main() {
return exchange.IO("api", "tron", "GetTransactionInfoByID", "305f0c2487095effcf9e2db61f021f976707611424cba57e1d6464736f7f49e7")
}
返回的数据:
{"id":{},"fee":1100000,"blockNumber":70192360,"blockTimeStamp":1741229766000,"contractResult":[{}],"receipt":{"net_fee":100000}}
返回所有节点信息。
function main() {
return exchange.IO("api", "tron", "ListNodes")
}
查询TRC20代币的精度信息
function main() {
return exchange.IO("api", "tron", "TRC20GetDecimals", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t") // USDT
}
查询某个钱包地址的某个TRC20代币余额。
function main() {
return exchange.IO("api", "tron", "TRC20ContractBalance", "TRX 钱包地址", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")
}
返回当前区块链上的最新区块信息。
function main() {
return exchange.IO("api", "tron", "GetNowBlock")
}
返回的数据:
{
"transactions": [
{
"transaction": {
"raw_data": {
"ref_block_bytes": {},
"ref_block_hash": {},
"expiration": 1741489083000,
"contract": [
{
"type": 1,
"parameter": {
"type_url": "type.googleapis.com/protocol.TransferContract",
"value": {}
...
查询 TRON 账户的带宽信息。
function main() {
return exchange.IO("api", "tron", "GetAccountNet", "TWTbnQuiWvEg...")
}
返回的数据:
{
"freeNetLimit": 600,
"TotalNetLimit": 43200000000,
"TotalNetWeight": 26982826755
}
创建Tron账户。
function main() {
return exchange.IO("api", "tron", "CreateAccount", "TWTbnQ...", "TKCG9...")
}
尝试创建一个已经存在的账户,会返回错误:
Futures_OP 4: Contract validate error : Account has existed
根据区块高度获取区块信息。
function main() {
return exchange.IO("api", "tron", "GetBlockByNum", 70227286)
}
返回的数据:
{
"transactions": [
{
"transaction": {
"raw_data": {
"ref_block_bytes": {},
"ref_block_hash": {},
"expiration": 1741334628000,
"contract": [
...
TRC20GetName,根据合约地址,查询TRC20代币名称。 TRC20GetSymbol,根据合约地址,查询TRC20代币符号
function main() {
Log("TRC20GetName:", exchange.IO("api", "tron", "TRC20GetName", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"))
Log("TRC20GetSymbol:", exchange.IO("api", "tron", "TRC20GetSymbol", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"))
}
返回的数据:
2025-03-09 11:18:43.083 信息 TRC20GetSymbol: USDT
2025-03-09 11:18:43.006 信息 TRC20GetName: Tether USD
function main() {
// 例如某个转账数据中的Data,转换为可读数值
Log("ParseTRC20NumericProperty:", exchange.IO("api", "tron", "ParseTRC20NumericProperty", "0x00000000000000000000000000000000000000000000000000000001a13b8600")) // 7000000000
// 例如某个转账数据中的Data,转换为可读字符串
Log("ParseTRC20StringProperty:", exchange.IO("api", "tron", "ParseTRC20StringProperty", "0x0000000000000000000000000000000000000000000000000000000055534454")) // USDT
}
调用TRC20合约的方法,我们使用TRC20合约的balanceOf方法,首先编码,然后使用TRC20Call调用。
function main() {
var data = exchange.IO("pack", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", "TWTbnQuiWvEg...")
var tx = exchange.IO("api", "tron", "TRC20Call", "TWTbnQuiWvEg...", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", data, true, 0)
return tx.constant_result
}
Constant方法不需要广播。tx.constant_result 中记录调用结果。
构造一个trans数据。
function main() {
var trans = exchange.IO("api", "tron", "Transfer", "TWTb...", "TKCG9FN...", 1000000)
return trans
}
TWTb...
: TRX钱包A的地址。TKCG9FN...
: TRX钱包B的地址。返回的数据:
{
"transaction": {
"raw_data": {
"ref_block_bytes": {},
"ref_block_hash": {},
"expiration": 1741493085000,
"contract": [
{
"type": 1,
"parameter": {
"type_url": "type.googleapis.com/protocol.TransferContract",
"value": {}
}
}
],
"timestamp": 1741493025759
}
},
"txid": {},
"result": {
"result": true
}
}
根据合约地址,获取合约的ABI。
function main() {
var usdtABI = exchange.IO("api", "tron", "GetContractABI", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")
return usdtABI
}
返回的数据:
{
"entrys": [
{
"constant": true,
"name": "name",
"outputs": [
{
"type": "string"
}
],
"type": 2,
"stateMutability": 2
},
{
"constant": true,
"name": "deprecated",
"outputs": [
{
"type": "bool"
}
],
"type": 2,
"stateMutability": 2
},
...
向TKCG9FN1j...
tron钱包地址转账1TRX。
function main() {
var ownerAddress = exchange.IO("address")
var ret = exchange.IO("api", "tron", "Transfer", ownerAddress, "TKCG9FN1j...", 1000000)
return ret
}
调用智能合约的方法。
function main() {
var tx = exchange.IO("api", "tron", "TriggerConstantContract", "TWTbnQu...", "TSUUVjysXV8YqHytSNjfkNXnnB49QDvZpx", "token0()", "")
var ret2 = Encode("raw", "raw", "hex", tx.constant_result[0])
Log(ret2) // 000000000000000000000000891cdb91d149f23b1a45d9c5ca78a88d0cb44c18
}
返回的数据为sunSwap交易池的token0代币地址。
调用tron链上的智能合约方法balanceOf
,TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t
为USDT
代币的智能合约地址。
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
var balance = exchange.IO("api", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", "Tron 钱包地址")
return toAmount(balance, 6)
}
可以查询到钱包中USDT的余额为:0.000019
FMZ平台的Web3 tron交易所对象的exchange.IO
函数实现以下功能。
function main() {
var ret = exchange.IO("api", "tron", "send", "目标TRX钱包地址", 1) // 需要注意,参数1 表示 0.000001 TRX ,需要转换数值为链上数值。
return ret // 转账hash: 305f0c2487095effcf9e2db61f021f9767076114...
}
切换节点地址
exchange.IO("base", "rpc address") // rpc address 替换为具体的节点地址
// 或者
exchange.IO("rpc", "rpc address")
注册智能合约ABI
exchange.IO("abi", "contract ABI") // contract ABI 替换为具体的合约ABI内容
获取当前交易所对象绑定的钱包的地址
exchange.IO("address") // 返回tron钱包地址
pack / encode / encodePacked
pack / encode :编码/打包数据、方法调用。
function main() {
// 打包TRC20合约的balanceOf方法调用
var data1 = exchange.IO("pack", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", "TWTbnQu...") // TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t 为USDT合约地址
Log(data1)
var data2 = exchange.IO("encode", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", "TWTbnQu...")
Log(data2)
Log("data1 == data2:", data1 == data2) // true
// 编码数据为uint256
var data3 = exchange.IO("pack", "uint256", 19) // 数据为: 19
Log(data3)
var data4 = exchange.IO("encode", "uint256", 19)
Log(data4)
Log("data3 == data4:", data3 == data4)
}
encodePacked :编码并打包
function main() {
var data1 = exchange.IO("encodePacked", "address", "TWTbnQu...")
Log(data1)
// e0c12e16a9f713e5f104c...
var data2 = exchange.IO("encode", "address", "TWTbnQu...")
Log(data2)
// 000000000000000000000000 e0c12e16a9f713e5f104c...
}
unpack / decode :解包/解码数据、方法调用。
function main() {
var data = exchange.IO("pack", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "balanceOf", "TWTbnQu...")
Log(data)
var tx = exchange.IO("api", "tron", "TRC20Call", "TWTbnQu...", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", data, true, 0)
var ret = Encode("raw", "raw", "hex", tx.constant_result[0])
Log(ret)
// 解码
var usdtBalance = exchange.IO("decode", "uint256", ret)
Log("usdtBalance:", usdtBalance)
// 解码
return exchange.IO("unpack", "uint256", ret)
}
exchange.IO("key", "xxx") // xxx 为私钥
exchange.IO("hash", algo, inputFormat, outputFormat, data)
使用当前配置的私钥签名,返回签名数据。
var signature = exchange.IO("hash", "sign", "string", "hex", "txHash") // txHash: 具体hash值
初步实践关于Tron链上的DEX交易所:sunSwap。我们调用sunSwap的工厂合约,请求所有交易对的索引,然后再请求索引为1的交易对地址。
function main() {
var poolIndexs = exchange.IO("api", "TThJt8zaJzJMhCEScH7zWKnp5buVZqys9x", "allPoolsLength")
Log("poolIndexs:", poolIndexs) // 交易对索引总数
var hexAddress = exchange.IO("api", "TThJt8zaJzJMhCEScH7zWKnp5buVZqys9x", "allPools", exchange.IO("encode", "uint256", 1))
Log("hexAddress:", hexAddress) // 索引为1的交易对地址
}
因为篇幅有限,详细的sunSwap内容我们将在下期文章中分享给读者,感谢您的支持。
FMZ量化交易平台在Web3时代持续创新,为量化交易者提供了更广阔的链上交易空间。通过支持Tron网络,FMZ不仅增强了跨链交易能力,还让用户能够在Tron生态中高效执行智能合约交互、资金管理以及自动化交易策略。
在本文中,我们介绍了FMZ平台对Tron网络的支持,并实践了Tron链上的SunSwap DEX的合约方法调用。随着区块链技术的发展,Web3量化交易的可能性将不断拓展。FMZ将持续优化和完善其Web3能力,为量化交易者提供更加灵活、安全、高效的交易环境,助力用户在链上市场中获得更大优势。
感谢阅读,感谢您的支持。