Web3
exchange.IO("abi", ...)
In the FMZ Quant Trading Platform, various blockchain-related functions are mainly implemented through the exchange.IO() function. The following documentation will describe the different functions of the exchange.IO() function separately. The exchange.IO("abi", ...) function call is used to register ABI.
-
Supports Ethereum (eth)
-
Supports TRON (tron)
exchange.IO(k, address, abiContent)Examples
javascript
function main() {
// register Uniswap SwapRouter02 abi
var routerAddress = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
var abi = `[{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct IV3SwapRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"exactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"}]`
// abi only uses partial exactOutput method content, complete abi can be searched online
exchange.IO("abi", routerAddress, abi)
}Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
address | string | Yes | The |
abiContent | string | Yes | The |
Remarks
If the called smart contract method is a standard ERC20 method, registration is not required.
To obtain the contract's ABI content, you can use the following URL, just take the result field, for example:
url
https://api.etherscan.io/api?module=contract&action=getabi&address=0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
exchange.IO("api", blockChain, ...)
The exchange.IO("api", "eth", ...) function call is used to invoke Ethereum RPC methods (requires selecting eth when configuring the Web3 exchange object).
exchange.IO("api", "tron", ...) function call is used to invoke TRON RPC methods (requires selecting tron when configuring the Web3 exchange object).
exchange.IO(k, blockChain, rpcMethod)
exchange.IO(k, blockChain, rpcMethod, ...args)Examples
-
Query ETH balance in wallet:
javascriptfunction main() { // "owner" needs to be replaced with the actual wallet address // Parameter label at "latest" string position: 'latest', 'earliest' or 'pending', refer to https://eth.wiki/json-rpc/API#the-default-block-parameter // Return value ethBalance is a hexadecimal string: 0x9b19ce56113070 var ethBalance = exchange.IO("api", "eth", "eth_getBalance", "owner", "latest") // ETH precision unit is 1e18 var ethDecimal = 18 // Due to JavaScript language precision limitations, need to use system-level encapsulated functions BigInt, BigDecimal for processing // Convert ethBalance to readable amount, 0x9b19ce56113070 converts to 0.043656995388076145 Log(Number((BigDecimal(BigInt(ethBalance))/BigDecimal(Math.pow(10, ethDecimal))).toString())) } -
ETH transfer, you can set
{gasPrice: 11, gasLimit: 111, nonce: 111}parameters according to specific requirements, this parameter is set as the last parameter of theexchange.IO()function. You can omitnonceto use system default value, or not setgasLimit/gasPrice/nonceto use all system default values.javascriptfunction mian() { // ETH precision unit is 1e18 var ethDecimal = 18 // Transfer amount, readable amount for example: 0.01 ETH var sendAmount = 0.01 // Due to JavaScript language precision limitations, need to use system-level encapsulated functions BigInt, BigDecimal for processing, and convert readable amount to on-chain processing data var toAmount = (BigDecimal(sendAmount)*BigDecimal(Math.pow(10, ethDecimal))).toFixed(0) // "toAddress" is the recipient's ETH wallet address for the transfer, needs to be specifically filled in, toAmount is the transfer amount exchange.IO("api", "eth", "send", "toAddress", toAmount) } -
Query
gasPrice:javascriptfunction toAmount(s, decimals) { return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString()) } function main() { var gasPrice = exchange.IO("api", "eth", "eth_gasPrice") Log("gasPrice:", toAmount(gasPrice, 0)) // 5000000000 , in wei (5 gwei) } -
Query
eth_estimateGas:javascriptfunction toAmount(s, decimals) { // toAmount函数可以将十六进制编码的数值转换为十进制数值 return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString()) } function main() { // 编码approve(授权)方法的调用 var data = exchange.IO("encode", "0x111111111117dC0aa78b770fA6A738034120C302", "approve", "0xe592427a0aece92de3edee1f18e0157c05861564", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") Log("data:", data) var gasPrice = exchange.IO("api", "eth", "eth_gasPrice") Log("gasPrice:", toAmount(gasPrice, 0)) var obj = { "from" : "0x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // walletAddress "to" : "0x111111111117dC0aa78b770fA6A738034120C302", "gasPrice" : gasPrice, "value" : "0x0", "data" : "0x" + data, } var gasLimit = exchange.IO("api", "eth", "eth_estimateGas", obj) Log("gasLimit:", toAmount(gasLimit, 0)) Log("gas fee", toAmount(gasLimit, 0) * toAmount(gasPrice, 0) / 1e18) }
Returns
| Type | Description |
string / number / bool / object / array / any (any type supported by the platform) | The |
Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
blockChain | string | Yes | The |
rpcMethod | string | Yes | The |
arg | string / number / bool / object / array / function / any (any type supported by the platform) | No | The There may be multiple |
See Also
Remarks
When the second parameter of the exchange.IO() function is "eth", you can directly call RPC methods available on Ethereum node servers.
exchange.IO("encode", ...)
The exchange.IO("encode", ...) function is used for data encoding operations.
exchange.IO(k, dataFormat, ...args)
exchange.IO(k, address, dataFormat)
exchange.IO(k, address, dataFormat, ...args)Examples
-
Taking the encoding of
unwrapWETH9method call as an example:javascriptfunction main() { // ContractV3SwapRouterV2 主网地址 : 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 // 调用unwrapWETH9方法需要先注册ABI,此处省略注册 // "owner"代表钱包地址,需要具体填写,1代表解包装数量,把一个WETH解包装为ETH var data = exchange.IO("encode", "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", "unwrapWETH9(uint256,address)", 1, "owner") Log(data) } -
Encoding example equivalent to
abi.encodeinSolidity:javascriptfunction main() { var x = 10 var address = "0x02a5fBb259d20A3Ad2Fdf9CCADeF86F6C1c1Ccc9" var str = "Hello World" var array = [1, 2, 3] var ret = exchange.IO("encode", "uint256,address,string,uint256[]", x, address, str, array) // uint 即 uint256 , FMZ上需要指定类型长度 Log("ret:", ret) /* 000000000000000000000000000000000000000000000000000000000000000a // x 00000000000000000000000002a5fbb259d20a3ad2fdf9ccadef86f6c1c1ccc9 // address 0000000000000000000000000000000000000000000000000000000000000080 // str 的偏移 00000000000000000000000000000000000000000000000000000000000000c0 // array 的偏移 000000000000000000000000000000000000000000000000000000000000000b // str 的长度 48656c6c6f20576f726c64000000000000000000000000000000000000000000 // str 数据 0000000000000000000000000000000000000000000000000000000000000003 // array 的长度 0000000000000000000000000000000000000000000000000000000000000001 // array 第一个数据 0000000000000000000000000000000000000000000000000000000000000002 // array 第二个数据 0000000000000000000000000000000000000000000000000000000000000003 // array 第三个数据 */ } -
Supports encoding of tuples or type sequences containing tuples. This type sequence consists of
tupleandbytes, so when callingexchange.IO()for encoding, two corresponding parameters need to be passed:-
- Variable corresponding to tuple type:
The passed parameters must be consistent with the structure and types of thejavascript{ a: 30, b: 20, c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" }tuple, as defined in thetypesparameter:tuple(a uint256,b uint8,c address). -
- Variable corresponding to
bytestype:
javascript"0011" - Variable corresponding to
javascriptfunction main() { var types = "tuple(a uint256,b uint8,c address),bytes" var ret = exchange.IO("encode", types, { a: 30, b: 20, c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" }, "0011") Log("encode: ", ret) } -
-
Supports encoding of arrays or type sequences containing arrays:
javascriptfunction main() { var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"] // ETH address, USDT address var ret = exchange.IO("encode", "address[]", path) Log("encode: ", ret) }
Returns
| Type | Description |
string | The |
Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
address | string | No | The |
dataFormat | string | Yes | The |
arg | string / number / tuple / array / any (any type supported by the platform) | No | The There may be multiple |
Remarks
The exchange.IO() function encapsulates the encode method, which can encode function calls and return them as hex string format. For specific usage, please refer to the platform's public "Uniswap V3 Trading Library" template.
When encoding smart contract method calls, the corresponding ABI must be registered first.
exchange.IO("encodePacked", ...)
The exchange.IO("encodePacked", ...) function is used to perform encodePacked encoding operations.
exchange.IO(k, dataFormat, ...args)Examples
When using Uniswap V3, parameters such as trading path need to be passed in, which requires the use of encodePacked encoding operations:
javascript
function main() {
var fee = exchange.IO("encodePacked", "uint24", 3000)
var tokenInAddress = "0x111111111117dC0aa78b770fA6A738034120C302"
var tokenOutAddress = "0x6b175474e89094c44da98b954eedeac495271d0f"
var path = tokenInAddress.slice(2).toLowerCase()
path += fee + tokenOutAddress.slice(2).toLowerCase()
Log("path:", path)
}Returns
| Type | Description |
string | The |
Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
dataFormat | string | Yes | The |
arg | string / number / tuple / array / any (any type supported by the platform) | Yes | The There can be multiple |
exchange.IO("decode", ...)
The exchange.IO("decode", ...) function is used for data decoding operations.
exchange.IO(k, dataFormat, data)Examples
-
Example of reverse operation for
exchange.IO("encode", ...)function:javascriptfunction main() { var types = "tuple(a uint256,b uint8,c address),bytes" var ret = exchange.IO("encode", types, { a: 30, b: 20, c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" }, "0011") Log("encode: ", ret) var rawData = exchange.IO("decode", types, ret) Log("decode:", rawData) } -
The following example first performs an
encodePackedoperation on thepathparameter, as the subsequentexactOutputmethod call that needs to be encoded requirespathas a parameter. Then it encodes theexactOutputmethod of the router contract, which has only one parameter oftupletype. The encoded result of theexactOutputmethod name is:0x09b81346. Using theexchange.IO("decode", ...)method to decode yieldsdecodeRaw, whose result is consistent with the variabledataTuple.javascriptfunction main() { // register SwapRouter02 abi var walletAddress = "0x398a93ca23CBdd2642a07445bCD2b8435e0a373f" var routerAddress = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45" var abi = `[{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct IV3SwapRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"exactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"}]` exchange.IO("abi", routerAddress, abi) // abi只使用了局部的exactOutput方法的内容,完整的abi可以在网上搜索 // encode path var fee = exchange.IO("encodePacked", "uint24", 3000) var tokenInAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" var tokenOutAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7" var path = tokenInAddress.slice(2).toLowerCase() path += fee + tokenOutAddress.slice(2).toLowerCase() Log("path:", path) var dataTuple = { "path" : path, "recipient" : walletAddress, "amountOut" : 1000, "amountInMaximum" : 1, } // encode SwapRouter02 exactOutput var rawData = exchange.IO("encode", routerAddress, "exactOutput", dataTuple) Log("method hash:", rawData.slice(0, 8)) // 09b81346 Log("params hash:", rawData.slice(8)) // decode exactOutput params var decodeRaw = exchange.IO("decode", "tuple(path bytes,recipient address,amountOut uint256,amountInMaximum uint256)", rawData.slice(8)) Log("decodeRaw:", decodeRaw) }
Returns
| Type | Description |
array / string | The |
Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
dataFormat | string | Yes | The |
data | string | Yes | The |
Remarks
The exchange.IO() function supports bidirectional data processing, capable of both encoding (encode) and decoding (decode) operations.
exchange.IO("key", ...)
The exchange.IO("key", ...) function is used to switch the private key calling method.
exchange.IO(k, key)Examples
javascript
function main() {
exchange.IO("key", "Private Key") // "Private Key" represents the private key string, which needs to be filled in specifically
}Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
key | string | Yes | The |
Remarks
The exchange.IO() function supports private key switching functionality, allowing operations on multiple wallet addresses. You can also add multiple exchange objects (refer to: exchanges) to operate multiple wallet addresses.
For private key switching operations: exchange.IO("key", "xxx"), concurrent switching is not supported.
exchange.IO("api", ...)
The exchange.IO("api", ...) function is used to call smart contract methods.
exchange.IO(k, address, method)
exchange.IO(k, address, method, ...args)
exchange.IO(k, address, method, value, ...args)Examples
-
The
decimalsmethod is aconstantmethod of ERC20 that does not consume gas and can query the precision data of a token.The
decimalsmethod requires no parameters. Return value: the precision data of the token.javascriptfunction main(){ var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302" // 代币的合约地址,例子中的代币为1INCH Log(exchange.IO("api", tokenAddress, "decimals")) // 查询,打印1INCH代币的精度指数为18 } -
The
allowancemethod is aconstantmethod of ERC20 that does not consume gas and can query the authorized amount of a token for a specific contract address.The
allowancemethod requires 2 parameters: the first parameter is the wallet address, and the second parameter is the authorized address. Return value: the authorized amount of the token.owner: wallet address, represented by the string "owner" in the example, actual use requires filling in the specific address.spender: the authorized contract address, represented by the string "spender" in the example, actual use requires filling in the specific address, for example, it can be theUniswap V3 router v1address.javascriptfunction main(){ // 代币的合约地址,例子中的代币为1INCH var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302" // 例如查询得出1000000000000000000,除以该token的精度单位1e18,得出当前交易所对象绑定的钱包给spender地址授权了1个1INCH数量 Log(exchange.IO("api", tokenAddress, "allowance", "owner", "spender")) } -
The
approvemethod is a non-constantmethod of ERC20 that consumes gas and is used to authorize a contract address with an operational amount of tokens.The
approvemethod requires 2 parameters: the first parameter is the authorized address, and the second parameter is the authorized amount. Return value: txid.spender: the authorized contract address, represented by the string "spender" in the example, actual use requires filling in the specific address, for example, it can be theUniswap V3 router v1address.0xde0b6b3a7640000: the authorized amount, represented here as a hexadecimal string, corresponding to the decimal value of 1e18, divided by the token precision unit in the example (i.e., 1e18), resulting in authorization of 1 token.The third parameter of the
exchange.IO()function passes the method nameapprove, which can also be written in methodId form, for example: "0x571ac8b0". It can also be written as the complete standard method name, for example: "approve(address,uint256)".javascriptfunction main(){ // 代币的合约地址,例子中的代币为1INCH var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302" // 授权量的十六进制字符串: 0xde0b6b3a7640000 , 对应的十进制字符串: 1e18 , 1e18除以该token的精度单位,即1个代币数量 , 所以这里指授权一个代币 Log(exchange.IO("api", tokenAddress, "approve", "spender", "0xde0b6b3a7640000")) } -
The
multicallmethod is a non-constantmethod ofUniswap V3that consumes gas and is used for multi-path token swaps.The
multicallmethod may have multiple parameter passing methods. You can query the ABI containing this method for details. The ABI needs to be registered before calling this method. Return value: txid.For specific
multicallmethod call examples, you can refer to the platform's public "Uniswap V3 Trading Library" templateHere we use pseudocode to describe some details:
javascriptexchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data)ContractV3SwapRouterV2: The router v2 address of Uniswap V3.value: The amount of ETH to transfer. If the tokenIn token for the swap operation is not ETH, set it to 0.deadline:deadlineis a parameter of themulticallmethod, which can be set to (new Date().getTime() / 1000) + 3600, indicating validity within one hour.data:datais a parameter of themulticallmethod, the packed operation data to be executed. Similar toexchange.IO("api", "eth", "send", "toAddress", toAmount), when calling themulticallmethod, you can also specify thegasLimit/gasPrice/noncesettings for the method call, also described using pseudocode:javascriptexchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data, {gasPrice: 123456, gasLimit: 21000})You can set the
{gasPrice: 11, gasLimit: 111, nonce: 111}parameters according to specific requirements. This parameter is set as the last parameter of theexchange.IO()function.You can omit
nonceto use the system default value, or not setgasLimit/gasPrice/nonceto use all system default values.javascriptfunction main() { var ContractV3SwapRouterV2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45" var tokenInName = "ETH" var amountIn = 0.01 var options = {gasPrice: 5000000000, gasLimit: 21000, nonce: 100} // 此处为举例,具体要根据实际场景设置 var data = "" // 编码后的数据,此处为空字符串,具体要根据实际场景设置 var tx = exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", (tokenInName == 'ETH' ? amountIn : 0), (new Date().getTime() / 1000) + 3600, data, options || {}) }
Returns
| Type | Description |
string / number / bool / object / array / any (any type supported by the platform) | The |
Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
address | string | Yes | The |
method | string | Yes | The |
value | number / string | No | The |
arg | string / number / bool / any (any type supported by the platform) | No | The There may be multiple |
exchange.IO("address")
The exchange.IO("address") function is used to get the wallet address configured for the exchange exchange object.
exchange.IO(k)Examples
javascript
function main() {
Log(exchange.IO("address")) // 打印exchange交易所对象上配置的私钥对应的钱包地址
}Returns
| Type | Description |
string | The |
Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
exchange.IO("base", ...)
The exchange.IO("base", ...) function call is used to set the RPC node address.
exchange.IO(k, address)Examples
javascript
function main() {
var chainRpc = "https://bsc-dataseed.binance.org"
e.IO("base", chainRpc) // 切换到BSC链
}Arguments
| Name | Type | Required | Description |
k | string | Yes | The |
address | string | Yes | The |