В процессе загрузки ресурсов... загрузка...

Веб3

обмен. IO ((abi,...)

На изобретательских квантовых торговых платформах в основном используютсяexchange.IO()Функции реализуют различные функции, связанные с блокчейном.exchange.IO()Функции описываются в зависимости от их функций.exchange.IO("abi", ...)Способ вызова функции используется для регистрации ABI.

обмен.IO(k, адрес, abiContent)

k
true
string
```address```参数用于指定智能合约的地址。
address
true
string
```abiContent```参数用于指定智能合约的```ABI```。
abiContent
true
string

```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只使用了局部的exactOutput方法的内容,完整的abi可以在网上搜索
    exchange.IO("abi", routerAddress, abi)
}

Применение метода смарт-контракта не требует регистрации, если он является стандартным методом ERC20. Получение контрактаABIКонтент доступен по следующему URL-адресуresultПоле, например:

https://api.etherscan.io/api?module=contract&action=getabi&address=0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45

обмен.IO ((api, eth,...)


```exchange.IO("api", "eth", ...)```函数返回调用的RPC方法的返回值。
string、number、bool、object、array、空值等系统支持的所有类型

exchange.IO(k, blockChain, rpcMethod)
exchange.IO(k, blockChain, rpcMethod, ...args)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"api"```表示该函数用于扩展调用请求。
k
true
string
```blockChain```参数用于设置```exchange.IO()```函数的功能,设置为```"eth"```表示该函数用于以太坊网络的RPC方法调用。
blockChain
true
string
```rpcMethod```参数用于设置```exchange.IO()```函数调用的RPC方法。
rpcMethod
true
string
```arg```参数用于指定所要调用的RPC方法的参数。 ```arg```参数可能有多个,```arg```参数的类型与个数根据```rpcMethod```参数指定的RPC方法而定。
arg
false
string、number、bool、object、array、function、空值等系统支持的所有类型

```javascript
function main() {
    // "owner" 需要替换为具体钱包地址
    // "latest"字符串位置的参数标签:'latest'、'earliest'或'pending',参考https://eth.wiki/json-rpc/API#the-default-block-parameter
    // 返回值 ethBalance 为十六进制字符串:0x9b19ce56113070
    var ethBalance = exchange.IO("api", "eth", "eth_getBalance", "owner", "latest")              

    // ETH的精度单位为1e18
    var ethDecimal = 18              

    // 由于JavaScript语言精度原因,需要使用系统底层封装的函数BigInt、BigDecimal处理
    // 将ethBalance转换为可读数量,0x9b19ce56113070转换为0.043656995388076145
    Log(Number((BigDecimal(BigInt(ethBalance))/BigDecimal(Math.pow(10, ethDecimal))).toString()))
}

Посмотрите на баланс ETH в кошельке:

function mian() {
    // ETH的精度单位为1e18
    var ethDecimal = 18  

    // 转账数量,可读的数量例如:0.01个ETH
    var sendAmount = 0.01  

    // 由于JavaScript语言精度原因,需要使用系统底层封装的函数BigInt、BigDecimal处理,并且将可读数量转换为链上处理的数据
    var toAmount = (BigDecimal(sendAmount)*BigDecimal(Math.pow(10, ethDecimal))).toFixed(0)
    
    // "toAddress"为转账时接收方的ETH钱包地址,需要具体填写,toAmount为转账数量
    exchange.IO("api", "eth", "send", "toAddress", toAmount)
}

Перевод ETH, настраиваемый в зависимости от конкретных потребностей{gasPrice: 11, gasLimit: 111, nonce: 111}Параметры, которые установлены наexchange.IO()На последнем параметре функции.nonceИспользовать систему по умолчанию или не устанавливатьgasLimit/gasPrice/nonceВсе используют систему по умолчанию.

function 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)
}

ЗапросgasPrice

function toAmount(s, decimals) {
    // toAmount函数可以把hex编码的数值转换为十进制数值
    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)
}

Запросeth_estimateGas


{@fun BigDecimal}, {@fun BigInt}

### exchange.IO("encode", ...)

```exchange.IO("encode", ...)```函数的调用方式用于数据编码。

```exchange.IO("encode", ...)```函数返回编码后的数据。
string

exchange.IO(k, dataFormat, ...args)
exchange.IO(k, address, dataFormat)
exchange.IO(k, address, dataFormat, ...args)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"encode"```表示该函数用于数据编码。
k
true
string
```address```参数用于设置智能合约的地址。 在调用```exchange.IO("encode", ...)```函数时,如果传入```address```参数表示编码(encode)智能合约上的方法调用。 在调用```exchange.IO("encode", ...)```函数时,如果未传入```address```参数,则该函数用于编码指定的类型顺序,功能等同```Solidity```中的```abi.encode```。
address
false
string
```dataFormat```参数用于指定编码数据的方法、类型、顺序。
dataFormat
true
string
```arg```参数用于指定与```dataFormat```参数匹配的具体数据值。 ```arg```参数可能有多个,```arg```参数的类型与个数根据```dataFormat```参数设置而定。
arg
false
string、number、tuple、array等系统支持的所有类型

```javascript
function main() {
    // ContractV3SwapRouterV2 主网地址 : 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
    // 调用unwrapWETH9方法需要先注册ABI,此处省略注册
    // "owner"代表钱包地址,需要具体填写,1代表解包装数量,把一个WETH解包装为ETH
    var data = exchange.IO("encode", "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", "unwrapWETH9(uint256,address)", 1, "owner")
    Log(data)
}

КодированиеunwrapWETH9Примеры вызовов методов:

function 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 第三个数据
    */
}

РавныеSolidityСреднийabi.encodeПримеры кодирования:

function 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)
}

Поддержка кодировки типа последовательности элементов (tuple) или элементов, содержащих элементы. Этот тип последовательностиtuplebytesСостав, так что вызыватьexchange.IO()В процессе кодирования необходимо продолжить передачу двух параметров:

  • 1, соответствующая типам тупелей:
  {
      a: 30,
      b: 20,
      c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
  }

Входящие параметры также должны соответствоватьtupleВ этом случае, если вы хотите, чтобы ваша система была более эффективной, вы должны использовать эту систему для того, чтобы удерживать ее.typesФорма, определенная в параметрах:tuple(a uint256,b uint8,c address)Я не знаю. -2, соответственно.bytesТип переменной:

  "0011"
function main() {
    var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"]   // ETH address, USDT address
    var ret = exchange.IO("encode", "address[]", path)
    Log("encode: ", ret)
}

Поддерживает кодирование по типу последовательности для матриц или матриц, содержащих:

编码智能合约上的方法调用时,需要先注册对应的ABI。

### exchange.IO("encodePacked", ...)

```exchange.IO("encodePacked", ...)```函数的调用方式用于```encodePacked```编码。

```exchange.IO("encodePacked", ...)```函数返回```encodePacked```编码后的数据。
string

exchange.IO(k, dataFormat, ...args)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"encodePacked"```表示该函数用于数据```encodePacked```编码。
k
true
string
```dataFormat```参数用于指定```encodePacked```编码数据的类型、顺序。
dataFormat
true
string
```arg```参数用于指定与```dataFormat```参数匹配的具体数据值。 ```arg```参数可能有多个,```arg```参数的类型与个数根据```dataFormat```参数设置而定。
arg
true
string、number、tuple、array等系统支持的所有类型

```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)
}

ИспользованиеUniswap V3Для того, чтобы перевести параметры, такие как путь конвертации, необходимо использоватьencodePackedКодирование:

обмен.IO ((декодировать,...)


```exchange.IO("decode", ...)```函数返回解码后的数据。 当```dataFormat```参数指定的数据只有一个时返回一个字符串。 当```dataFormat```参数指定的数据有多个时返回一个数组。
array、string

exchange.IO(k, dataFormat, data)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"decode"```表示该函数用于数据解码。
k
true
string
```dataFormat```参数用于指定解码数据的类型、顺序。
dataFormat
true
string
```data```参数用于设置所要解码的数据。
data
true
string

```javascript
function 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)
}
```javascript
function 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)
}

Вот пример:pathЭто было сделано при обработке параметров.encodePackedНо это не значит, что мы не можем работать с этими функциями.exactOutputМетоды вызоваpathВ качестве параметров.encodeДоговорный маршрутexactOutputМетод, который имеет только один параметр, тип параметраtupleТип.exactOutputЗа кодовым названием этого метода следует:0x09b81346Использованиеexchange.IO("decode", ...)Как это сделать?decodeRaw, с переменнымиdataTupleВстречается.

В частности, в 2010 году было принято решение о созданииexchange.IO()Функция поддерживает не только кодирование, но и декодирование.

обмен.IO ((key,...)


exchange.IO(k, key)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"key"```表示该函数用于切换私钥。
k
true
string
```key```参数用于设置私钥。
key
true
string

```javascript
function main() {
    exchange.IO("key", "Private Key")   // "Private Key"代表私钥字符串,需要具体填写
}

### exchange.IO("api", ...)

```exchange.IO("api", ...)```函数的调用方式用于调用智能合约的方法。

```exchange.IO("api", ...)```函数返回所调用的智能合约方法的返回值。
string、number、bool、object、array、空值等系统支持的所有类型

exchange.IO(k, address, method)
exchange.IO(k, address, method, ...args)
exchange.IO(k, address, method, value, ...args)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"api"```表示该函数用于扩展调用请求。
k
true
string
```address```参数用于指定智能合约的地址。
address
true
string
```method```参数用于指定所要调用的智能合约的方法。
method
true
string
```value```参数用于设置发送的ETH数量。 所要执行的智能合约方法的```stateMutability```属性是```payable```,则需要传```value```参数。 ```"stateMutability":"payable"```属性可以从ABI中查看,```exchange.IO()```函数会根据已经注册的ABI中的```stateMutability```属性判断所需要的参数, 如果```stateMutability```属性是```nonpayable```则不需要传```value```参数。
value
false
number、string
```arg```参数用于指定所要调用智能合约的方法的参数。 ```arg```参数可能有多个,```arg```参数的类型与个数根据所要调用的智能合约的方法而定。
arg
false
string、number、bool等系统支持的所有类型

```javascript
function main(){
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"    // 代币的合约地址,例子中的代币为1INCH
    Log(exchange.IO("api", tokenAddress, "decimals"))                  // 查询,打印1INCH代币的精度指数为18
}
```javascript
function main(){
    // 代币的合约地址,例子中的代币为1INCH
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"                          

    // 例如查询得出1000000000000000000,除以该token的精度单位1e18,得出当前交易所对象绑定的钱包给spender地址授权了1个1INCH数量
    Log(exchange.IO("api", tokenAddress, "allowance", "owner", "spender"))   
}
```owner```:钱包地址,例子中以字符串"owner"代替,实际使用需要具体填写地址。 ```spender```:被授权的合约地址,例子中以字符串"spender"代替,实际使用需要具体填写地址,例如可以是```Uniswap V3 router v1```地址。
```javascript
function main(){
    // 代币的合约地址,例子中的代币为1INCH
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"                 

    // 授权量的十六进制字符串: 0xde0b6b3a7640000 , 对应的十进制字符串: 1e18 , 1e18除以该token的精度单位,即1个代币数量 , 所以这里指授权一个代币
    Log(exchange.IO("api", tokenAddress, "approve", "spender", "0xde0b6b3a7640000"))  
}
```spender```:被授权的合约地址,例子中以字符串"spender"代替,实际使用需要具体填写地址,例如可以是```Uniswap V3 router v1```地址。 ```0xde0b6b3a7640000```:授权数量,这里使用的是十六进制字符串表示,对应的十进制数值为1e18,除以例子中的token精度单位(即1e18), 得出授权了1个token。 ```exchange.IO()```函数的第三个参数传入方法名```approve```,也可以写methodId的形式,例如:"0x571ac8b0"。 也可以写完整标准方法名,例如:"approve(address,uint256)"。
```javascript
function 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 || {})
}
```multicall```方法可能有多种传参方式,具体可以查询包含该方法的ABI,调用该方法之前需要先注册ABI。返回值:txid。  

具体的```multicall```方法调用例子,可以参考平台公开的[「Uniswap V3 交易类库」模板](https://www.fmz.com/strategy/397260)  

这里使用伪代码来描述一些细节:

exchange.IO ((api, ContractV3SwapRouterV2, multicall(uint256,bytes[]) , значение, срок, данные)



```ContractV3SwapRouterV2```:Uniswap V3的router v2地址。
```value```:转账的ETH数量,如果兑换操作的tokenIn代币不是ETH,则设置为0。
```deadline```:```deadline```是```multicall```方法的参数,可以设置为(new Date().getTime() / 1000) + 3600,表示一小时内有效。
```data```:```data```是```multicall```方法的参数,需要执行的打包操作数据。  

与```exchange.IO("api", "eth", "send", "toAddress", toAmount)```类似,在调用```multicall```方法时也可以指定方法调用的```gasLimit/gasPrice/nonce```设置,
同样使用伪代码来描述:

exchange.IO ((api, ContractV3SwapRouterV2, multicall ((uint256,bytes[]), значение, срок, данные, {gasPrice: 123456, gasLimit: 21000})


可以根据具体需求设置```{gasPrice: 11, gasLimit: 111, nonce: 111}```参数,该参数设置在```exchange.IO()```函数的最后一个参数上。
可以省略其中的```nonce```使用系统默认的值,或者不设置```gasLimit/gasPrice/nonce```,全部使用系统默认值。


### exchange.IO("address")

```exchange.IO("address")```函数的调用方式用于获取{@var/EXCHANGE exchange}交易所对象配置的钱包的地址。

```exchange.IO("address")```函数返回配置的钱包地址。
string

exchange.IO(k)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"address"```表示该函数用于获取配置的钱包地址。
k
true
string

```javascript
function main() {
    Log(exchange.IO("address"))         // 打印exchange交易所对象上配置的私钥的钱包地址
}

обмен.IO ((база,...)


exchange.IO(k, address)

```k```参数用于设置```exchange.IO()```函数的功能,设置为```"base"```表示该函数用于切换RPC节点。
k
true
string
```address```参数用于设置RPC节点地址。
address
true
string

```javascript
function main() {
    var chainRpc = "https://bsc-dataseed.binance.org"
    e.IO("base", chainRpc)    // 切换到BSC链
}
Нитки ТА