Transfer RON
Overview
This tutorial shows how to transfer RON from one account to another, and verify the transaction using Ronin JSON-RPC methods.
Before you start
Before you start the tutorial, you should have the following:
- Node.js or your preferred web3 client written in another language.
- npm or yarn for package installation. This tutorial uses npm.
- Basic knowledge of JavaScript.
- Basic knowledge of HTTP.
- Basic knowledge of JSON-RPC. For more information, see the JSON-RPC specification.
Environment
Throughout this tutorial, you use the public RPC endpoint for the Saigon testnet: https://saigon-testnet.roninchain.com/rpc
.
We recommend using the public endpoint only for testing. For production, make sure to use the developer portal's endpoint https://api-gateway.skymavis.com/rpc/testnet
.
Step 1. Create a project
- Create a new directory for your project and open the terminal in that directory:
cd ~/
mkdir ronin_rpc_contract_sample
cd ronin_rpc_contract_sample
- Initialize a new Node.js project:
npm init -y
You should see output similar to this:
Wrote to ***/ronin_rpc_contract_sample/package.json:
{
"name": "ronin_rpc_sample",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
- Install the
ethers.js
library:
npm install ethers@5.7.2
This tutorial uses ethers.js
version 5.7.2.
Step 2. Create wallets
You need to create two wallets: one for the sender and one for the receiver. We recommend using the Ronin Wallet browser extension for wallet creation. To create a wallet, open the extension > select Account > Create Account.
- Create a sender's wallet. The example address used in this tutorial
0xf6fd5fca4bd769ba495b29b98dba5f2ecf4ceed3
. - Create a receiver's wallet. The example address in this tutorial is
0x283b4baa1d0415603c81edc1c68fadd3c790837c
. - Retrieve the private key from the sender's Ronin Wallet. Open the Ronin Wallet browser extension, go to Account > Manage, select the sender's account, and then click View private key.
- Claim some RON to the sender's wallet using Ronin Faucet before transferring to others. You can create up to five requests a day, 1 RON per request.
Step 3. Create a script and run it
At this step, you create a script to transfer RON between wallets and verify the balance after.
- Create a file called
transfer_ron.js
and paste the following code:
const { ethers } = require('ethers');
// Initialize the provider
const provider = new ethers.providers.JsonRpcProvider('https://saigon-testnet.roninchain.com/rpc');
This code imports the required libraries and initializes the node provider, which is the public Ronin RPC endpoint.
- Create a function to send RON and verify the balance.
To run this code, you need the following:
- The private key from the sender's Ronin Wallet. To retrieve the private key, open the Ronin Wallet browser extension, go to Account > Manage, select the sender's account, and then click View private key.
- The receiver's wallet, which you created at the previous step.
Replace YOUR_PRIVATE_KEY
and RECIPIENT_ADDRESS
with the sender's private key and receiver's wallet address, respectively.
const { ethers } = require('ethers');
// Initialize the Provider
const provider = new ethers.providers.JsonRpcProvider('https://saigon-testnet.roninchain.com/rpc');
async function sendRON(privateKey, toAddress, amount) {
// Create a wallet from the private key
const wallet = new ethers.Wallet(privateKey, provider);
// Convert amount to Wei
const weiAmount = ethers.utils.parseEther(amount);
// Create a transaction object
const transaction = {
to: toAddress,
value: weiAmount,
};
// Sign and send the transaction
const transactionResponse = await wallet.sendTransaction(transaction);
console.log(transactionResponse)
// Wait for the transaction to be confirmed
await transactionResponse.wait();
// Verify the balance after the transaction
const balance = await provider.getBalance(wallet.address);
console.log('Balance after sending RON:', ethers.utils.formatEther(balance), 'RON');
}
// Call the sendRON function with the necessary parameters
const privateKey = 'YOUR_PRIVATE_KEY';
const toAddress = 'RECIPIENT_ADDRESS';
const amount = '0.1'; // Amount of RON to send
sendRON(privateKey, toAddress, amount);
- Execute the code:
node transfer_ron.js
You should see output similar to this:
{
nonce: 55925,
gasPrice: BigNumber { _hex: '0x04a817c800', _isBigNumber: true },
gasLimit: BigNumber { _hex: '0x5208', _isBigNumber: true },
to: '0x283b4Baa1d0415603C81edc1C68FadD3C790837C',
value: BigNumber { _hex: '0x016345785d8a0000', _isBigNumber: true },
data: '0x',
chainId: 2021,
v: 4078,
r: '0x384a2ed47a690349e47383af78b065d9b36c2a8e716d3027fc386d7b0f354106',
s: '0x51b068a8f9ff66daa1b52611ad87dffb434179d5f615dfe3d97497fbd60dee97',
from: '0xf6fd5FcA4Bd769BA495B29B98dba5F2eCF4CEED3',
hash: '0x0c11bfd6035665c34377d0eb9de4cff98ed9e27ada4ab087aa842a8eaa6fa55d',
type: null,
confirmations: 0,
wait: [Function (anonymous)]
}
Balance after sending RON: 976242834.971306728277726832 RON
Step 4. Verify the result
Verify the transaction detail
Use the Ronin app
Open the Ronin app and paste the transaction hash 0x0c11bfd6035665c34377d0eb9de4cff98ed9e27ada4ab087aa842a8eaa6fa55d
into the search field.
Use Ronin JSON-RPC
Make a request to the eth_getTransactionReceipt
method by running the following command:
curl --location 'https://saigon-testnet.roninchain.com/rpc' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc":"2.0",
"method":"eth_getTransactionReceipt",
"params":[
"0x0c11bfd6035665c34377d0eb9de4cff98ed9e27ada4ab087aa842a8eaa6fa55d"
],
"id":1
}'
The response is the transaction's receipt:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0x0dcaa2ebb57531322c80e2b9d8165d5d947f25ee0aa66745349b5c4067a7c80e",
"blockNumber": "0x116fcd5",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"effectiveGasPrice": "0x4a817c800",
"from": "0xf6fd5fca4bd769ba495b29b98dba5f2ecf4ceed3",
"gasUsed": "0x5208",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x283b4baa1d0415603c81edc1c68fadd3c790837c",
"transactionHash": "0x0c11bfd6035665c34377d0eb9de4cff98ed9e27ada4ab087aa842a8eaa6fa55d",
"transactionIndex": "0x0",
"type": "0x0",
"logs": []
}
}
Check the receiver's balance
Use the Ronin app
Open the Ronin app and paste the receiver's address 0x283b4baa1d0415603c81edc1c68fadd3c790837c
into the search field.
Use Ronin JSON-RPC
Make a request to the eth_getBalance
method by running the following command:
curl --location 'https://saigon-testnet.roninchain.com/rpc' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc":"2.0",
"method":"eth_getBalance",
"params":[
"0x283b4baa1d0415603c81edc1c68fadd3c790837c",
"latest"
],
"id":1
}'
The latest
parameter is used to request the most recent result, which means that the response you receive may be different from the example:
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x110c3344c12ff03a994c5d"
}
Code explanation
This section walks you through the code of the sendRON
function.
- This line creates a wallet using the private key by creating a new
Wallet
object with the private key and provider.
const wallet = new ethers.Wallet(privateKey, provider);
- This line converts the amount of RON to Wei using the
parseEther
function fromethers.js
:
const weiAmount = ethers.utils.parseEther(amount);
- Here, the code creates a transaction object with the recipient address and the Wei amount:
const transaction = {
to: toAddress,
value: weiAmount,
};
- The following line signs and sends the transaction by using the
sendTransaction
method of the wallet:
const transactionResponse = await wallet.sendTransaction(transaction);
The RPC methods used by this function are as follows:
eth_getTransactionCount
{
"method": "eth_getTransactionCount",
"params": [
"<YOUR_PUBLIC_KEY (detect from YOUR_PRIVATE_KEY)>",
"pending"
],
"id": 47,
"jsonrpc": "2.0"
}
eth_gasPrice
{
"method": "eth_gasPrice",
"params": [],
"id": 50,
"jsonrpc": "2.0"
}
eth_estimateGas
{
"method": "eth_estimateGas",
"params": [
{
"gasPrice": "0x4a817c800",
"value": "0x8ac7230489e80000",
"from": "<YOUR_PUBLIC_KEY (detect from YOUR_PRIVATE_KEY)>",
"to": "<RECIPIENT_ADDRESS>"
}
],
"id": 52,
"jsonrpc": "2.0"
}
eth_sendRawTransaction
{
"method": "eth_sendRawTransaction",
"params": [
"<Signature when use YOUR_PRIVATE_KEY sign transaction>"
],
"id": 56,
"jsonrpc": "2.0"
}
- This line waits for the transaction to be confirmed using the
wait
method of the transaction response.
await transactionResponse.wait();
The RPC method used by this function is eth_getTransactionReceipt
:
{
"method": "eth_getTransactionReceipt",
"params": [
"<Your transaction hash after call eth_sendRawTransaction success>"
],
"id": 68,
"jsonrpc": "2.0"
}
- The following line verifies the balance after the transaction by getting the balance of the wallet's address using the
getBalance
method of the provider and printing it out in RON using theformatEther
function.
const balance = await provider.getBalance(wallet.address);
The RPC method used by this function is eth_getBalance
:
{
"method": "eth_getBalance",
"params": [
"<YOUR_PUBLIC_KEY (detect from YOUR_PRIVATE_KEY)>",
"latest"
],
"id": 72,
"jsonrpc": "2.0"
}