Na plataforma de negociação FMZ Quant, implementa principalmente várias funções, chamadas relacionadas ao blockchain através deexchange.IO()
O seguinte documento descreve a funçãoexchange.IO()
O método de chamada do sistema deexchange.IO("abi", ...)
A função é utilizada para registar um ABI.
exchange.IO(k, endereço, abiContent)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"abi"
significa que a função é utilizada para registarABI
- Não.
k
verdade
cordel
Oaddress
O parâmetro é utilizado para especificar o endereço do contrato inteligente.
Endereço
verdade
cordel
OabiContent
Parâmetro utilizado para especificar oABI
do contrato inteligente.
AbiContent
verdade
cordel
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)
}
Os métodos de chamada de contratos inteligentes não precisam de ser registados se forem métodos ERC20 padrão.
Apanha oABI
O conteúdo do contrato pode ser obtido através do seguinte endereço URL:result
apenas campo, por exemplo:
https://api.etherscan.io/api?module=contract&action=getabi&address=0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
O método de chamada deexchange.IO("api", "eth", ...)
função é usada para chamar o método Ethereum RPC.
Oexchange.IO("api", "eth", ...)
A função retorna o valor de retorno do método RPC chamado.
string, number, bool, object, array, null e todos os outros tipos suportados pelo sistema
exchange.IO(k, blockChain, rpcMétodo)exchange.IO(k, blockChain, rpcMethod,...args)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"api"
indica que a função é utilizada para estender a solicitação de chamada.
k
verdade
cordel
OblockChain
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"eth"
indica que a função é utilizada para chamadas de métodos RPC na Rede Ethereum.
BlockChain
verdade
cordel
OrpcMethod
Parâmetro é usado para definir o método RPC a ser chamado peloexchange.IO()
função.
Método rpc
verdade
cordel
Oarg
O parâmetro é usado para especificar os parâmetros do método RPC a ser chamado.arg
O tipo e o número dearg
Os parâmetros dependem do método RPC especificado pelorpcMethod
Parâmetro.
arg
Falso
string, number, bool, object, array, function, null e todos os outros tipos suportados pelo sistema
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()))
}
Verifique o saldo de ETH na sua carteira:
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)
}
Para transferências de ETH, pode definir o{gasPrice: 11, gasLimit: 111, nonce: 111}
Parâmetro, que é definido no último parâmetro doexchange.IO()
A sua função, de acordo com as suas necessidades específicas.nonce
e usar o sistema padrão, ou deixargasLimit/gasPrice/nonce
Desativar e usar o valor padrão do sistema para todos.
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)
}
PerguntagasPrice
:
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)
}
Perguntaeth_estimateGas
:
O segundo parâmetro doexchange.IO()
função com"eth"
pode chamar diretamente os métodos RPC disponíveis para o servidor de nó Ethereum.
- O que é que queres?
Oexchange.IO("encode", ...)
A função é chamada para codificação de dados.
Oexchange.IO("encode", ...)
função retorna os dados codificados.
cordel
exchange.IO(k, dataFormat,...args)exchange.IO(k, endereço, dataFormat)exchange.IO(k, endereço, dataFormat,...args)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"encode"
significa que a função é utilizada para codificação de dados.
k
verdade
cordel
Oaddress
O parâmetro é usado para definir o endereço do contrato inteligente.exchange.IO("encode", ...)
função, passando noaddress
O parâmetro indica a codificação da chamada do método no contrato inteligente.exchange.IO("encode", ...)
Função, se oaddress
se o parâmetro não for transmitido, a função é utilizada para codificar a ordem de tipo especificada e é funcionalmente equivalente aabi.encode
emSolidity
- Não.
Endereço
Falso
cordel
OdataFormat
O parâmetro é utilizado para especificar o método, tipo e ordem dos dados codificados.
DataFormat
verdade
cordel
Oarg
Parâmetro é usado para especificar o valor de dados específico que corresponde aodataFormat
Pode haver mais de umarg
Parâmetro, tipo e número dearg
Os parâmetros dependem dadataFormat
Configuração de parâmetros.
arg
Falso
string, number, tuple, array, e todos os outros tipos suportados pelo sistema
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)
}
Por exemplo, chamando o método de codificaçãounwrapWETH9
:
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
*/
}
É equivalente ao exemplo de codificação deabi.encode
emSolidity
:
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)
}
Suporta a codificação de uma tupla ou uma ordem de tipo contendo uma tupla.
Esta ordem de tipo consiste em:tuple
, bytes
, então quando ligarexchange.IO()
para codificação, você precisa continuar passando dois parâmetros:
{
a: 30,
b: 20,
c: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
}
Os parâmetros transmitidos devem igualmente ser coerentes com a estrutura e o tipo detuple
, tal como definido notypes
Parâmetro do formulário:tuple(a uint256,b uint8,c address)
.
bytes
:"0011"
function main() {
var path = ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0xdac17f958d2ee523a2206206994597c13d831ec7"] // ETH address, USDT address
var ret = exchange.IO("encode", "address[]", path)
Log("encode: ", ret)
}
Suporta a codificação sequencial de matrizes ou tipos contendo matrizes:
Oexchange.IO()
A função encapsula oencode
método, que pode retornar o código de chamada de função parahex
Para utilização específica, pode consultar as plataformas disponíveis publicamente
Oexchange.IO("encodePacked", ...)
função é chamado de uma forma que é usado paraencodePacked
encoding.
Oexchange.IO("encodePacked", ...)
função retorna oencodePacked
dados codificados.
cordel
exchange.IO(k, dataFormat,...args)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"encodePacked"
significa que a função é utilizada para dadosencodePacked
codificação.
k
verdade
cordel
OdataFormat
Parâmetro utilizado para especificar o tipo e a ordem doencodePacked
dados codificados.
DataFormat
verdade
cordel
Oarg
Parâmetro é usado para especificar o valor de dados específico que corresponde aodataFormat
Pode haver mais de umarg
Parâmetro, tipo e número dearg
Os parâmetros dependem dadataFormat
Configuração de parâmetros.
arg
verdade
string, number, tuple, array, e todos os outros tipos suportados pelo sistema
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)
}
Quando utilizadoUniswap V3
, você precisa passar em parâmetros como o caminho de troca, você precisa usar oencodePacked
Operação de codificação:
Oexchange.IO("decode", ...)
A função é chamada de uma forma que é usada para decodificação.
Oexchange.IO("decode", ...)
Retorna uma cadeia quando há apenas um dado especificado pelodataFormat
Retorna uma matriz quando há mais de um dado especificado pelodataFormat
Parâmetro.
matriz, string
exchange.IO(k, dadosFormato, dados)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, e configurá-lo para"decode"
significa que a função é utilizada para decodificação de dados.
k
verdade
cordel
OdataFormat
O parâmetro é utilizado para especificar o tipo e a ordem dos dados decodificados.
DataFormat
verdade
cordel
Odata
Parâmetro utilizado para definir os dados a decodificar.
dados
verdade
cordel
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)
}
Função inversa doexchange.IO("encode", ...)
Função:
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)
}
O seguinte exemplo realiza primeiro umencodePacked
operação nopath
Processamento de parâmetros, porque oexactOutput
chamada de método que precisa ser codificada mais tarde requerpath
como um parâmetro.encode
OexactOutput
método do contrato de roteamento, que tem apenas um parâmetro de tipotuple
. Nome do métodoexactOutput
é codificado como:0x09b81346
, e utilizando oexchange.IO("decode", ...)
método para decodificar o resultadodecodeRaw
, consistente com a variáveldataTuple
.
Para o processamento de dados, oexchange.IO()
Função suporta não só codificação, mas também decodificação.
Oexchange.IO("key", ...)
A função é chamada de uma forma para trocar chaves privadas.
exchange.IO(K, tecla)
O parâmetrok
é utilizado para definir a função doexchange.IO()
função, definida em"key"
significa que a função é utilizada para trocar a chave privada.
k
verdade
cordel
Okey
O parâmetro é usado para definir a chave privada.
Chave
verdade
cordel
function main() {
exchange.IO("key", "Private Key") // "Private Key" represents the private key string, which needs to be filled in specifically
}
Oexchange.IO()
A função suporta a troca de chaves privadas e pode manipular vários endereços de carteira.
Oexchange.IO("api", ...)
A função é chamada de uma forma que é usada para chamar os métodos do contrato inteligente.
Oexchange.IO("api", ...)
A função retorna o valor de retorno do método chamado contrato inteligente.
string, number, bool, object, array, null e todos os outros tipos suportados pelo sistema
exchange.IO(k, endereço, método)exchange.IO(k, endereço, método,...args)exchange.IO(k, endereço, método, valor,...args)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"api"
indica que a função é utilizada para estender a solicitação de chamada.
k
verdade
cordel
Oaddress
O parâmetro é utilizado para especificar o endereço do contrato inteligente.
Endereço
verdade
cordel
Omethod
O parâmetro é utilizado para especificar o método do contrato inteligente a ser chamado.
Método
verdade
cordel
Ovalue
O parâmetro é usado para definir a quantidade de ETH a ser enviada.stateMutability
Atributo do método de contrato inteligente a executar épayable
, em seguida, ovalue
O parâmetro precisa ser passado."stateMutability": "payable"
O atributo pode ser visualizado a partir do ABI.exchange.IO()
A função determinará o parâmetro requerido com base nostateMutability
O atributo no ABI que foi registrado.stateMutability
atributo énonpayable
, em seguida, ovalue
Parâmetro não precisa ser transmitido.
Valor
Falso
número, string
Oarg
O parâmetro é usado para especificar os parâmetros do método do contrato inteligente a ser chamado.arg
Parâmetro, tipo e número dearg
Os parâmetros dependem do método do contrato inteligente a ser chamado.
arg
Falso
string, number, bool e todos os outros tipos suportados pelo sistema
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
}
Odecimals
O método éconstant
O método ERC20 que não incorre no consumo de gás e que pode consultar os dados de precisão de um token.decimals
O método não possui parâmetros. Valor de retorno: dados de precisão do token.
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"))
}
Oallowance
O método éconstant
O ERC20 é um método de ERC20 que não gera consumo de gás e pode consultar a quantidade autorizada de um token para um determinado endereço de contrato.allowance
O método leva 2 parâmetros, o primeiro é o endereço da carteira e o segundo é o endereço autorizado.
owner
: o endereço da carteira, o exemplo é substituído pela cadeia spender
: o endereço do contrato autorizado, o exemplo é substituído pela cadeia 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 || {})
}
Omulticall
O método é um não-constant
método deUniswap V3
que gera consumo de gás e é usado para resgatar tokens de várias maneiras.
Omulticall
método pode ter várias maneiras de passar parâmetros, você pode verificar o ABI que contém o método especificamente, você precisa registrar o ABI antes de chamar o método.
Para exemplos específicos demulticall
Os métodos de chamadas podem ser consultados nas plataformas disponíveis publicamente.
Alguns detalhes são descritos aqui usando pseudo-código:
exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data)
ContractV3SwapRouterV2
: endereço do roteador v2 do Uniswap V3.value
: o montante de ETH a transferir, definido em 0 se o tokenIn da operação de troca não for o ETH.deadline
: deadline
é o parâmetro domulticall
método, que pode ser definido como (new Date().getTime() / 1000) + 3600, indicando que é válido por uma hora.data
: data
é o parâmetro domulticall
método, os dados da operação de embalagem a realizar.
Semelhante aexchange.IO("api", "eth", "send", "toAddress", toAmount)
, ogasLimit/gasPrice/nonce
configuração do método chamada pode ser especificado ao chamar omulticall
método.
Novamente, usamos pseudo-código para descrever:
exchange.IO("api", ContractV3SwapRouterV2, "multicall(uint256,bytes[])", value, deadline, data, {gasPrice: 123456, gasLimit: 21000})
O parâmetro{gasPrice: 11, gasLimit: 111, nonce: 111}
O sistema pode ser definido de acordo com as necessidades específicas, que é definido para o último parâmetro doexchange.IO()
função.
Pode omitir ononce
e usar o valor padrão do sistema, ou deixargasLimit/gasPrice/nonce
Desativar e usar o valor padrão do sistema para todos.
Oexchange.IO("address")
A função é chamada de forma a obter o endereço da carteira configurada pelo objeto de troca {@var/EXCHANGE exchange}.
Oexchange.IO("address")
A função devolve o endereço de carteira configurado.
cordel
exchange.IO(k)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"address"
significa que a função é utilizada para obter o endereço de carteira configurado.
k
verdade
cordel
function main() {
Log(exchange.IO("address")) // Print the wallet address of the private key configured on the exchange object
}
Oexchange.IO("base", ...)
A função é chamada de forma a definir o endereço do nó RPC.
exchange.IO(k, endereço)
Ok
Parâmetro utilizado para definir a função doexchange.IO()
função, definida em"base"
significa que a função é utilizada para alternar os nós RPC.
k
verdade
cordel
Oaddress
Parâmetro utilizado para definir o endereço do nó RPC.
Endereço
verdade
cordel
function main() {
var chainRpc = "https://bsc-dataseed.binance.org"
e.IO("base", chainRpc) // Switching to BSC chain
}
Fios
TA