波场(TRON)
Web3交易所对象选择ChainType为TRON时连接波场节点。用法与以太坊(EVM)基本一致:注册ABI、调用合约、编码解码、签名、切换私钥等exchange.IO()指令相同,地址使用波场格式(T开头),TRX数量的单位是sun(1 TRX = 1000000 sun)。本页说明配置和波场特有的部分。
配置交易所对象
| 字段 | 说明 |
|---|---|
| ChainType | 选择TRON |
| Private Key | 钱包私钥(十六进制字符串)。支持把私钥本地化部署在托管者上,参看密钥安全性 |
| Rpc Address | 波场全节点的HTTP地址,例如官方节点https://api.trongrid.io(测试网:https://nile.trongrid.io、https://api.shasta.trongrid.io) |
| Rpc Api Key | TronGrid的API Key,只填Key本身,会作为TRON-PRO-API-KEY请求头发送。不填也能使用,但TronGrid对没有Key的请求限频更严格 |
托管者通过全节点的HTTP接口(/wallet/...)访问波场,不再使用gRPC。选择TRON时表单默认填入的旧gRPC地址grpc.trongrid.io:50051会自动换成https://api.trongrid.io(grpc.nile.trongrid.io:50051、grpc.shasta.trongrid.io:50051同样换成对应测试网的HTTP地址);其它gRPC地址会报错,请改填节点的HTTP地址。
运行中可以用exchange.IO("base", 节点地址)切换节点,用exchange.IO("key", 私钥)切换钱包,用exchange.IO("address")获取当前钱包地址(T开头)。标准函数exchange.GetAccount()、exchange.GetAssets()返回钱包的TRX余额。账户还未激活(链上没有记录)时余额为0。
调用智能合约
与以太坊相同,使用exchange.IO("api", 合约地址, 方法, ...参数):只读方法直接返回结果,写方法签名并广播交易,返回交易ID。TRC20标准方法已内置;其它合约没有注册ABI时,会自动从链上读取该合约的ABI,读取不到时再用exchange.IO("abi", 合约地址, ABI)手动注册。写方法的最后一个参数可以传{gasLimit: 数量}设置手续费上限(feeLimit,单位sun)。
javascript
// USDT(TRC20)合约
var usdt = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
Log(exchange.IO("api", usdt, "balanceOf", exchange.IO("address"))) // 链上整数,USDT精度为6
编码解码与以太坊一致,地址参数可以直接写T开头的地址:
javascript
exchange.IO("encode", "address", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")
// 000000000000000000000000a614f803b6fd780986a42c78ec9c7f77e6ded13c
exchange.IO("encodePacked", "address", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")
// a614f803b6fd780986a42c78ec9c7f77e6ded13c
exchange.IO("decode", "string", "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a5465746865722055534400000000000000000000000000000000000000000000")
// Tether USD
调用波场节点的方法
exchange.IO("api", "tron", 方法, ...参数)调用波场节点的方法,方法名不区分大小写。需要签名的方法(转账、触发合约等)会自动签名并广播。常用方法:
| 方法 | 参数 | 说明 |
|---|---|---|
send | 收款地址, 数量(sun) | 从当前钱包转出TRX |
Transfer | 付款地址, 收款地址, 数量(sun) | 转出TRX,付款地址必须是当前钱包 |
GetAccount | 地址 | 账户信息 |
GetAccountResource | 地址 | 账户的能量、带宽资源 |
GetContractABI | 合约地址 | 合约在链上的ABI |
GetAssetIssueByName | 名称 | TRC10资产信息 |
GetNowBlock | 无 | 当前区块 |
GetBlockByNum | 区块高度 | 指定区块 |
GetTransactionByID | 交易ID | 交易内容 |
GetTransactionInfoByID | 交易ID | 交易执行结果(手续费、能量消耗、日志等) |
GetChainParameters | 无 | 链参数 |
TriggerConstantContract | 调用者地址(可为空), 合约地址, 方法, 参数编码 | 只读调用合约,结果在constant_result中(十六进制字符串,可以用exchange.IO("decode", ...)解码) |
TRC20ContractBalance | 地址, 合约地址 | TRC20余额(链上整数) |
TRC20GetName、TRC20GetSymbol、TRC20GetDecimals | 合约地址 | TRC20的名称、符号、精度 |
TRC20Send、TRC20Approve | 付款地址, 收款或被授权地址, 合约地址, 数量, feeLimit | TRC20转账、授权 |
TRC20Call | 调用者地址(可为空), 合约地址, 调用数据, 是否只读, feeLimit | 用原始调用数据调用合约 |
ParseTRC20NumericProperty、ParseTRC20StringProperty | 十六进制数据 | 解析TRC20返回的数值、字符串 |
表中没有的节点接口,可以直接传路径和请求体:exchange.IO("api", "tron", "/wallet/接口名", {请求体})。
与以太坊的差异
以下指令只支持以太坊(EVM),在波场上调用会报错:call、multicall、logs、waitReceipt、nonce、speedUp、cancelTx、contracts;sendBase和多个节点互为备用也只对以太坊有效。在波场上模拟执行合约调用可以用节点方法TriggerConstantContract,查询交易的执行结果用GetTransactionInfoByID。
toUnits、fromUnits、uniswapV3、编码解码和签名指令在波场上同样可用,精度参数可以直接传TRC20合约地址:
javascript
var usdt = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
var raw = exchange.IO("api", usdt, "balanceOf", exchange.IO("address"))
Log(exchange.IO("fromUnits", raw, usdt)) // 按合约的 decimals() 换算为可读数量
合约调用在节点校验阶段被拒绝时(例如合约不存在),错误信息中是节点给出的原因,例如tron contract call rejected (CONTRACT_VALIDATE_ERROR): Smart contract is not exist.;合约执行失败(revert)时报tron contract execution failed及失败原因。
签名
exchange.IO("hash", "sign", "hex", "hex", 交易哈希)用当前私钥对32字节哈希签名,返回65字节签名r‖s‖v(v为0或1);hash的其它算法(如"sha256")用于计算摘要,功能与Encode()函数相同。需要分别取得r、s、v(v为27或28)用于合约校验时,使用exchange.IO("sign", ...),见语法手册Web3分类。
示例
-
示例
查询TRX与USDT余额,读取代币信息
javascriptfunction main() { var usdt = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" var wallet = exchange.IO("address") // TRX 余额(标准函数,单位 TRX) Log("账户:", exchange.GetAccount()) // USDT 余额:链上整数,按精度换算 var raw = exchange.IO("api", "tron", "TRC20ContractBalance", wallet, usdt) var decimals = exchange.IO("api", "tron", "TRC20GetDecimals", usdt) Log("USDT:", raw / Math.pow(10, decimals)) // 用 TRC20Call 只读调用 name()(选择器 0x06fdde03),再解析返回的字符串 var ret = exchange.IO("api", "tron", "TRC20Call", "", usdt, "0x06fdde03", true, 0) // constant_result 中是十六进制字符串,直接解析 Log("名称:", exchange.IO("api", "tron", "ParseTRC20StringProperty", ret.constant_result[0])) } -
用Multicall合约一次读取多个合约方法
javascriptfunction main() { var usdt = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" var multicall = "TGXuuKAb4bnrn137u39EKbYzKNXvdCes98" var wallet = exchange.IO("address") var calls = [ [usdt, exchange.IO("encode", usdt, "name")], [usdt, exchange.IO("encode", usdt, "decimals")], [usdt, exchange.IO("encode", usdt, "balanceOf", wallet)] ] // 注册 Multicall 合约的 aggregate 方法 exchange.IO("abi", multicall, `[{"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"}]`) var ret = exchange.IO("api", multicall, "aggregate", calls) Log("name:", exchange.IO("decode", "string", ret.returnData[0])) Log("decimals:", exchange.IO("decode", "uint8", ret.returnData[1])) Log("balanceOf:", exchange.IO("decode", "uint256", ret.returnData[2])) }
参考