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

Веб3

exchange.IO("Аби",...)

В FMZ Quant Trading Platform, он в основном реализует различные функции, вызовы, связанные с блокчейном черезexchange.IO()В следующем документе описываетсяexchange.IO()Применение метода вызоваexchange.IO("abi", ...)функция используется для регистрации ABI.

exchange.IO(k, адрес, abiContent)

ВkПараметр используется для установки функцииexchange.IO()функция, установленная на"abi"означает, что функция используется для регистрацииABI- Да. k неправда строка Вaddressпараметр используется для указания адреса смарт-контракта. Адрес неправда строка ВabiContentПараметр используется для указанияABIумного контракта. abiСодержание неправда строка

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"}]`
    
    // Get the ```ABI``` content of the contract can be obtained with the following URL, taking the ```result``` field only, e.g:
    exchange.IO("abi", routerAddress, abi)
}

Способы вызова смарт-контракта не должны регистрироваться, если это стандартные методы ERC20. ВозьмиABIСодержание контракта можно получить по следующему адресуresultтолько поле, например:

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

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

Способ вызоваexchange.IO("api", "eth", ...)функция используется для вызова метода Ethereum RPC.

Вexchange.IO("api", "eth", ...)функция возвращает возвращаемое значение метода RPC. string, number, bool, object, array, null и все другие типы, поддерживаемые системой

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

ВkПараметр используется для установки функцииexchange.IO()функция, установленная на"api"указывает, что функция используется для расширения запроса вызова. k неправда строка ВblockChainПараметр используется для установки функцииexchange.IO()функция, установленная на"eth"указывает, что функция используется для вызовов методов RPC в сети Ethereum. блок-цепочка Истинно строка ВrpcMethodПараметр используется для установки метода RPC, который должен быть вызванexchange.IO()Функция. Метод rpc неправда строка Вargпараметр используется для указания параметров метода RPC, который должен быть вызван.argтип и количествоargпараметры зависят от метода RPC, указанногоrpcMethodПараметр. арг ложное string, number, bool, object, array, function, null и все другие типы, поддерживаемые системой

function main() {
    // "owner" needs to be replaced with the specific wallet address
    // Parameter labels for the "latest" string position: 'latest', 'earliest' or 'pending', please refrer to https://eth.wiki/json-rpc/API#the-default-block-parameter
    // The return value ethBalance is a hexadecimal string: 0x9b19ce56113070
    var ethBalance = exchange.IO("api", "eth", "eth_getBalance", "owner", "latest")              

    // ETH has a precision unit of 1e18
    var ethDecimal = 18              

    // Because of the JavaScript language precision, it is necessary to use the system underlying package function BigInt, BigDecimal to process
    // Convert ethBalance to readable amount, 0x9b19ce56113070 to 0.043656995388076145
    Log(Number((BigDecimal(BigInt(ethBalance))/BigDecimal(Math.pow(10, ethDecimal))).toString()))
}

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

function mian() {
    // ETH has a precision unit of 1e18
    var ethDecimal = 18  

    // Number of transfers, readable amount e.g. 0.01 ETH
    var sendAmount = 0.01  

    // Due to the JavaScript language precision, it is necessary to use the system underlying encapsulated functions BigInt, BigDecimal to process, and to convert the readable amount to the data processed on the chain
    var toAmount = (BigDecimal(sendAmount)*BigDecimal(Math.pow(10, ethDecimal))).toFixed(0)
    
    // "toAddress" is the address of the recipient's ETH wallet at the time of the transfer, which needs to be filled in specifically, and toAmount is the number of transfers
    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) {
    // The toAmount function can convert hex-encoded values to decimal values
    return Number((BigDecimal(BigInt(s))/BigDecimal(Math.pow(10, decimals))).toString())
}                

function main() {
    // Coding approve (authorization) method calls
    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:

Второй параметрexchange.IO()функция с"eth"может напрямую вызвать методы RPC, доступные серверу узла Ethereum.

# # Забавный Большой Десятиметровый # # Забавный Большой Интеллект #

exchange.IO("кодировать",...)

Вexchange.IO("encode", ...)функция вызвана для кодирования данных.

Вexchange.IO("encode", ...)функция возвращает закодированные данные. строка

exchange.IO(k, dataFormat,...args)exchange.IO(k, адрес, формат данных)exchange.IO(k, адрес, данныеФормат,...args)

ВkПараметр используется для установки функцииexchange.IO()функция, установленная на"encode"означает, что функция используется для кодирования данных. k неправда строка ВaddressПараметр используется для установки адреса смарт-контракта.exchange.IO("encode", ...)Функция, проходящая вaddressПараметр указывает на кодирование метода вызова на умный контракт.exchange.IO("encode", ...)функции, еслиaddressпараметр не передается, функция используется для кодирования указанного порядка типа и функционально эквивалентнаabi.encodeвSolidity- Да. Адрес ложное строка ВdataFormatПараметр используется для указания метода, типа и порядка кодируемых данных. DataFormat (Формат данных) Истинно строка ВargПараметр используется для указания значения конкретных данных, соответствующегоdataFormatпараметр. может быть более одногоargпараметр, а также тип и количествоargпараметров зависит отdataFormatпараметры. арг ложное строка, число, тупл, массив и все другие типы, поддерживаемые системой

function main() {
    // Main network address of ContractV3SwapRouterV2: 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
    // Calling the unwrapWETH9 method requires registering the ABI first, which is omitted here
    // "owner" represents the wallet address, which need to fill in the specific, 1 represents the number of unpacking, unpacking a WETH into 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 i.e. uint256 , the type length needs to be specified on FMZ
    Log("ret:", ret)
    /*
    000000000000000000000000000000000000000000000000000000000000000a    // x
    00000000000000000000000002a5fbb259d20a3ad2fdf9ccadef86f6c1c1ccc9    // address
    0000000000000000000000000000000000000000000000000000000000000080    // Offset of str
    00000000000000000000000000000000000000000000000000000000000000c0    // Offset of array
    000000000000000000000000000000000000000000000000000000000000000b    // The length of str
    48656c6c6f20576f726c64000000000000000000000000000000000000000000    // str data
    0000000000000000000000000000000000000000000000000000000000000003    // The length of the array
    0000000000000000000000000000000000000000000000000000000000000001    // array the first data
    0000000000000000000000000000000000000000000000000000000000000002    // array the second data
    0000000000000000000000000000000000000000000000000000000000000003    // array the third data
    */
}

Это эквивалентно примеру кодированияabi.encodeвSolidity:

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, bytes, так что когда звонишьexchange.IO()для кодирования, вам нужно продолжить передачу двух параметров:

    1. Переменные, соответствующие типу тупла:
    
    {
        a: 30,
        b: 20,
        c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
    }
    
    

    Переданные параметры также должны соответствовать структуре и типуtuple, как определено вtypesпараметр формы:tuple(a uint256,b uint8,c address).

    1. Переменные, соответствующие типуbytes:
    "0011"
    
function main() {
    var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"]   // ETH address, USDT address
    var ret = exchange.IO("encode", "address[]", path)
    Log("encode: ", ret)
}

Он поддерживает последовательное кодирование массивов или типов, содержащих массивы:

Вexchange.IO()Функция включает в себяencodeметод, который может вернуть код вызова функцииhexДля конкретного использования вы можете обратиться к публично доступным платформамUniswap V3 Trade Шаблон- Да. При использовании метода кодирования для поиска смарт-контрактов, в первую очередь необходимо зарегистрировать соответствующий ABI.

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

Вexchange.IO("encodePacked", ...)функция называется таким образом, что используется дляencodePacked encoding.

Вexchange.IO("encodePacked", ...)функция возвращаетencodePackedзашифрованные данные. строка

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

ВkПараметр используется для установки функцииexchange.IO()функция, установленная на"encodePacked"означает, что функция используется для данныхencodePackedкодирование. k неправда строка ВdataFormatПараметр используется для указания типа и порядкаencodePackedзашифрованные данные. DataFormat (Формат данных) неправда строка ВargПараметр используется для указания значения конкретных данных, соответствующегоdataFormatпараметр. может быть более одногоargпараметр, а также тип и количествоargпараметров зависит отdataFormatпараметры. арг Истинно строка, число, тупл, массив и все другие типы, поддерживаемые системой

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операция кодирования:

exchange.IO("Декодировать",...)

Вexchange.IO("decode", ...)Функция называется таким образом, который используется для декодирования.

Вexchange.IO("decode", ...)возвращает декодированные данные. возвращает строку, когда есть только один данный, указанныйdataFormatвозвращает массив, когда есть более одного данного, указанногоdataFormatПараметр. массив, строка

exchange.IO(k, dataФормат, данные)

ВkПараметр используется для установки функцииexchange.IO()Функция и настройка на"decode"означает, что функция используется для декодирования данных. k неправда строка ВdataFormatПараметр используется для определения типа и порядка декодированных данных. DataFormat (Формат данных) Истинно строка ВdataПараметр используется для настройки данных для декодирования. данные неправда строка

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

Обратное действиеexchange.IO("encode", ...)Функция:

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 only uses the contents of the local exactOutput method, the full abi can be searched on the Internet              

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

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

Для обработки данныхexchange.IO()функция поддерживает не только кодирование, но и декодирование.

exchange.IO("ключ",...)

Вexchange.IO("key", ...)Функция называется таким образом, чтобы переключать частные ключи.

exchange.IO(K, ключ)

Параметрkиспользуется для настройки функцииexchange.IO()функция, установленная на"key"означает, что функция используется для переключения частного ключа. k неправда строка ВkeyПараметр используется для настройки частного ключа. ключ неправда строка

function main() {
    exchange.IO("key", "Private Key")   // "Private Key" represents the private key string, which needs to be filled in specifically
}

Вexchange.IO()Функция поддерживает переключение частных ключей и может манипулировать несколькими адресами кошельков.

exchange.IO("апи",...)

Вexchange.IO("api", ...)функция вызвана таким образом, который используется для вызова методов умного контракта.

Вexchange.IO("api", ...)функция возвращает возвращаемое значение метода, называемого умным контрактом. string, number, bool, object, array, null и все другие типы, поддерживаемые системой

exchange.IO(k, адрес, метод)exchange.IO(k, адрес, метод,...arg)exchange.IO(k, адрес, метод, значение,...args)

ВkПараметр используется для установки функцииexchange.IO()функция, установленная на"api"указывает, что функция используется для расширения запроса вызова. k неправда строка Вaddressпараметр используется для указания адреса смарт-контракта. Адрес неправда строка Вmethodпараметр используется для указания метода, который должен быть вызван для смарт-контракта. метод Истинно строка ВvalueПараметр используется для установки количества ETH, которое будет отправлено.stateMutabilityатрибут метода смарт-контракта, который должен быть выполнен:payable, затемvalueПараметр должен быть передан."stateMutability": "payable"Атрибут может быть просмотрен из ABI.exchange.IO()Функция будет определять требуемый параметр на основеstateMutabilityатрибут в ABI, который был зарегистрирован.stateMutabilityатрибут - этоnonpayable, затемvalueПараметр не нужно передавать. стоимость ложное число, строка Вargпараметр используется для указания параметров метода смарт-контракта, который должен быть вызван.argпараметр, а также тип и количествоargпараметры зависит от метода умного контракта, который будет вызван. арг ложное строка, число, bool и все другие типы, поддерживаемые системой

function main(){
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"    // The contract address of the token, the token is 1INCH in the example
    Log(exchange.IO("api", tokenAddress, "decimals"))                  // Query, print 1INCH tokens with precision index of 18
}

ВdecimalsМетод являетсяconstantЭто позволяет использовать ERC20 без потребления газа и запросить точные данные токенов.decimalsВозвращаемое значение: данные точности токена.

function main(){
    // The contract address of the token, in the example the token is 1INCH
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"                          

    // For example, the query yields 1000000000000000000, divided by the precision unit of the token 1e18, the wallet to which the current exchange object is bound has authorized 1 1INCH to the spender address
    Log(exchange.IO("api", tokenAddress, "allowance", "owner", "spender"))   
}

ВallowanceМетод являетсяconstantВ этом случае, если вы используете ERC20, вы не будете потреблять газ и сможете запросить разрешенный объем токена для определенного контрактного адреса.allowanceМетод принимает 2 параметра, первый - адрес кошелька, а второй - авторизованный адрес.
owner: адрес кошелька, пример заменен строкой owner, фактическое использование необходимо заполнить конкретный адрес.spender: адрес уполномоченного контракта, пример заменяется строкой spender, фактическое использование необходимо заполнить конкретный адрес, например, это может бытьUniswap V3 router v1 address.

function main(){
    // The contract address of the token, the token is 1INCH in the example
    var tokenAddress = "0x111111111117dC0aa78b770fA6A738034120C302"                 

    // The hexadecimal string of the authorization amount: 0xde0b6b3a7640000 , the corresponding decimal string: 1e18 , 1e18 divided by the precision unit of the token, i.e. 1 token amount, so this refers to the authorization of one token
    Log(exchange.IO("api", tokenAddress, "approve", "spender", "0xde0b6b3a7640000"))  
}```
The ```approve``` method is a non-```constant``` method of ERC20, which generates gas consumption and is used to authorize the operation amount of a token to a contract address. The ```approve``` method takes 2 parameters, the first one is the address to be authorized and the second one is the amount to be authorized. Return value: txid.  
```spender```: the address of the authorized contract, the example is replaced by the string "spender", the actual use needs to fill in the specific address, for example, it can be ```Uniswap V3 router v1``` address. ```0xde0b6b3a7640000```: the number of authorizations, here is the hexadecimal string, the corresponding decimal value is 1e18, divided by the token precision unit in the example (i.e. 1e18). The result is that 1 token is authorized. The third parameter of the ```exchange.IO()``` function is passed to the method name ```approve```, which can also be written in the form of methodId, such as "0x571ac8b0". It is also possible to write the full standard method name, for example: "approve(address,uint256)".
```javascript
function main() {
    var ContractV3SwapRouterV2 = "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
    var tokenInName = "ETH"
    var amountIn = 0.01
    var options = {gasPrice: 5000000000, gasLimit: 21000, nonce: 100}   // This is an example, depending on the actual scene settings
    var data = ""                                                       // The encoded data, here is the empty string, depending on the actual scene settings
    var tx = exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", (tokenInName == 'ETH' ? amountIn : 0), (new Date().getTime() / 1000) + 3600, data, options || {})
}

ВmulticallМетод не является...constantМетодUniswap V3который генерирует потребление газа и используется для выкупа токенов несколькими способами. ВmulticallМетод может иметь различные способы передачи параметров, вы можете проверить ABI, который содержит метод конкретно, вам нужно зарегистрировать ABI перед вызовом метода.

Для конкретных примеровmulticallВы можете обратиться к публично доступным платформам.Uniswap V3 Trade Шаблон

Некоторые детали описаны здесь с использованием псевдокода:


exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data)

ContractV3SwapRouterV2: адрес маршрутизатора v2 Uniswap V3.value: сумма ETH для перевода, установленная на 0, если токен-токен обменной операции не является ETH.deadline: deadlineявляется параметромmulticallМетод, который может быть установлен на (new Date().getTime() / 1000) + 3600, что указывает на его действие в течение одного часа.data: dataявляется параметромmulticallметод, данные о проведении операции упаковки.

Похожиеexchange.IO("api", "eth", "send", "toAddress", toAmount),gasLimit/gasPrice/nonceУстановка вызова метода может быть указана при вызовеmulticallметодом. Опять же, мы используем псевдокод для описания:


exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data, {gasPrice: 123456, gasLimit: 21000})

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

exchange.IO("адрес")

Вexchange.IO("address")функция вызвана таким образом, чтобы получить адрес кошелька, настроенного объектом обмена {@var/EXCHANGE exchange}.

Вexchange.IO("address")функция возвращает конфигурированный адрес кошелька. строка

exchange.IO(k)

ВkПараметр используется для установки функцииexchange.IO()функция, установленная на"address"означает, что функция используется для получения настроенного адреса кошелька. k Истинно строка

function main() {
    Log(exchange.IO("address"))         // Print the wallet address of the private key configured on the exchange object
}

exchange.IO("база",...)

Вexchange.IO("base", ...)функция вызвана таким образом, чтобы установить адрес узла RPC.

exchange.IO(k, адрес)

ВkПараметр используется для установки функцииexchange.IO()функция, установленная на"base"означает, что функция используется для переключения узлов RPC. k неправда строка Вaddressпараметр используется для установки адреса узла RPC. Адрес неправда строка

function main() {
    var chainRpc = "https://bsc-dataseed.binance.org"
    e.IO("base", chainRpc)    // Switching to BSC chain
}
Нитки ТА