exchange.IO("api", blockChain, ...)
Calls Ethereum RPC methods (select eth when configuring the Web3 exchange object).
exchange.IO("api", "tron", ...) calling method is used to call TRON RPC methods (select tron when configuring the Web3 exchange object).
exchange.IO(k, blockChain, rpcMethod)
exchange.IO(k, blockChain, rpcMethod, ...args)Examples
-
Query the ETH balance in the wallet.
javascript// Convert an on-chain integer amount into a human-readable amount. decimals is the token precision: // 18 for ETH, 6 for USDT/USDC. // Supports both decimal strings and hexadecimal strings prefixed with 0x: RPC methods such as // eth_getBalance return hexadecimal strings prefixed with 0x. function toAmount(raw, decimals) { var t = String(raw).trim() if (t.slice(0, 2).toLowerCase() == "0x") t = BigInt(t).toString() var d = Number(decimals) || 0 if (d == 0) return Number(t) var s = t.length > d ? t : new Array(d - t.length + 2).join("0") + t var frac = s.slice(s.length - d).replace(/0+$/, "") return Number(s.slice(0, s.length - d) + (frac ? "." + frac : "")) } function main() { // "owner" needs to be replaced with the actual wallet address // The position of "latest" is the block parameter, with optional values: 'latest', 'earliest' // or 'pending'. For details, see https://eth.wiki/json-rpc/API#the-default-block-parameter // The return value ethBalance is a hexadecimal string, for example: 0x9b19ce56113070 var ethBalance = exchange.IO("api", "eth", "eth_getBalance", "owner", "latest") // The precision of ETH is 18, i.e. 1 ETH equals 1e18 of the smallest unit var ethDecimal = 18 // On-chain amounts are all integers; converting to a human-readable amount requires shifting // the decimal point according to the precision. The shift is done on the string, // and only the final Number() conversion may round the last digit: 0x9b19ce56113070 // (43656995388076144) prints as 0.043656995388076145, the exact value being // 0.043656995388076144. // For an exact result use exchange.IO("fromUnits", ethBalance, 18), which returns a decimal // string Log(toAmount(ethBalance, ethDecimal)) } -
For ETH transfers, you can set the
{gasPrice: 11, gasLimit: 111, nonce: 111}parameter according to your specific needs. This parameter is passed as the last argument of theexchange.IO()function. Options you do not need can be omitted. Note that a plain transfer withoutgasPriceis priced at a fixed 100 Gwei with a defaultgasLimitof 21000, so query the gas price witheth_gasPricefirst and pass it in.This parameter also supports the
dataanddryRunfields:datais arbitrary call data (a hexadecimal string starting with0x), used to directly send the transaction{to, data, value}returned by APIs such as aggregators and Pendle; whendatais set, the gas price and gasLimit are estimated by the node in the same way as for a contract call. WhendryRunis set totrue, the transaction is only signed and not broadcast, and an object containing fields such ashash,raw(the signed transaction),nonce, andgasLimitis returned, which can be used to inspect the transaction content or to send it through another channel. For example:exchange.IO("api", "eth", "send", router, value, {data: calldata, dryRun: true}). Before sending, you can first useexchange.IO("call", router, calldata, {value: value})to simulate the call. Whennonceis not set, the system automatically assigns a nonce and keeps it in sync with the chain, so nonces are not reused when sending transactions consecutively; seeexchange.IO("nonce", ...)for details. If a transaction remains unconfirmed on-chain for a long time, you can useexchange.IO("speedUp", ...)to resend it with a higher gas price, or useexchange.IO("cancelTx", ...)to cancel the transaction.javascript// Human-readable amount -> on-chain integer amount (string). The decimal point is shifted purely // via string operations, without any floating-point arithmetic, // so amounts exceeding 2^53 do not lose precision either. When 17 or more significant digits are // needed, pass amount as a string. function toInnerAmount(amount, decimals) { var t = String(amount), d = Number(decimals) || 0 var m = /^([0-9]*)(?:\.([0-9]*))?[eE]([+-]?[0-9]+)$/.exec(t) if (m) { // Expand scientific notation: 0.0000001 is represented by JavaScript as 1e-7 var digits = (m[1] || "") + (m[2] || ""), point = (m[1] || "").length + parseInt(m[3], 10) t = point <= 0 ? "0." + new Array(1 - point).join("0") + digits : point >= digits.length ? digits + new Array(point - digits.length + 1).join("0") : digits.slice(0, point) + "." + digits.slice(point) } var dot = t.indexOf("."), int = dot < 0 ? t : t.slice(0, dot) var frac = dot < 0 ? "" : t.slice(dot + 1) // Decimal places beyond the precision are truncated directly frac = frac.slice(0, d) while (frac.length < d) frac += "0" return (int + frac).replace(/^0+(?=[0-9])/, "") } function main() { // The precision unit of ETH is 1e18 var ethDecimal = 18 // Transfer amount (human-readable amount), e.g., 0.01 ETH var sendAmount = 0.01 // Convert to the integer amount used on-chain: 0.01 -> "10000000000000000" var amount = toInnerAmount(sendAmount, ethDecimal) // "toAddress" is the ETH wallet address of the transfer recipient and must be filled in // according to the actual situation; amount is the transfer amount exchange.IO("api", "eth", "send", "toAddress", amount) } -
Query
gasPrice.javascript// The toAmount function is used to convert a hex-encoded value to a decimal value. Passing 0 for // decimals means the decimal point is not shifted function toAmount(raw, decimals) { var t = String(raw).trim() if (t.slice(0, 2).toLowerCase() == "0x") t = BigInt(t).toString() var d = Number(decimals) || 0 if (d == 0) return Number(t) var s = t.length > d ? t : new Array(d - t.length + 2).join("0") + t var frac = s.slice(s.length - d).replace(/0+$/, "") return Number(s.slice(0, s.length - d) + (frac ? "." + frac : "")) } function main() { var gasPrice = exchange.IO("api", "eth", "eth_gasPrice") Log("gasPrice:", toAmount(gasPrice, 0)) // Output: gasPrice: 5000000000 (in wei, i.e. 5 gwei) Log("gasPrice:", toAmount(gasPrice, 9), "gwei") // The precision unit of gwei is 1e9 } -
Call
eth_estimateGasto estimate the Gas required for a transaction.javascript// The toAmount function is used to convert a hexadecimal-encoded value to a decimal value function toAmount(raw, decimals) { var t = String(raw).trim() if (t.slice(0, 2).toLowerCase() == "0x") t = BigInt(t).toString() var d = Number(decimals) || 0 if (d == 0) return Number(t) var s = t.length > d ? t : new Array(d - t.length + 2).join("0") + t var frac = s.slice(s.length - d).replace(/0+$/, "") return Number(s.slice(0, s.length - d) + (frac ? "." + frac : "")) } function main() { // Encode the call to the approve (authorization) method 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)) // Gas fee = gasLimit * gasPrice. Both are large integers in wei, so multiply them using BigInt // to avoid precision loss, // then convert by 1e18 into a human-readable ETH amount Log("gas fee", toAmount((BigInt(gasLimit) * BigInt(gasPrice)).toString(), 18)) }
Returns
| Type | Description |
string / number / bool / object / array / any | Return value of the called RPC method. |
Arguments
| Name | Type | Required | Description |
k | string | Yes | Function of the |
blockChain | string | Yes | Blockchain network called by the |
rpcMethod | string | Yes | RPC method to be called by the |
arg | string / number / bool / object / array / any | No | Parameters of the RPC method to be called. |
See Also
Web3 exchange.IO exchange.IO("fromUnits") exchange.IO("toUnits") exchange.IO("api") exchange.IO("nonce")
Remarks
When the second parameter of the exchange.IO() function is set to eth, you can directly call the RPC methods supported by the Ethereum node server.
Node methods return the node's result as is. When the node returns null (for example eth_getTransactionReceipt for a transaction not yet mined), a null value is returned without an error; when the node returns an error, a null value is returned with the error in GetLastError(), and a contract revert reason is decoded into readable text.
exchange.IO("api", "eth", "send", toAddress, value[, options]) sends native coin from the current wallet; value is an on-chain integer (wei), and the transaction hash is returned. A plain transfer without data is sent as a legacy transaction: without gasPrice it is priced at a fixed 100 Gwei (plus a tiny random amount), and without gasLimit the limit is 21000. That is usually too high on Ethereum mainnet, so query eth_gasPrice first and pass it in. With data the transfer is handled as a contract call: the gas limit is estimated by the node and the gas price is set the same way as for contract write methods (an EIP-1559 transaction on chains that support it; see exchange.IO("api", ...)).
On TRON the second argument is tron and method names are case-insensitive, for example GetNowBlock, GetAccount, GetTransactionInfoByID and TRC20ContractBalance. send takes the recipient address and the TRX amount (in sun, 1 TRX = 1000000 sun) and returns the transaction ID without 0x. Methods that need a signature (transfers, contract triggers and so on) are signed and broadcast automatically. Full-node endpoints that are not built in can be called with the path and request body directly: exchange.IO("api", "tron", "/wallet/endpointName", {body}).