SDK with ethers
ethers
is arguably the most popular and widely used Ethereum JavaScript library. You can spot it in almost any popular DApp. If your DApp doesn't leverage a high-level state management library like web3-react
but solely relies on ethers
for the most basic wallet connections, our Ruby One SDK
fully supports it. This tutorial demonstrates how to connect Ruby One
using just ethers
.
The latest version of ethers
is 6.x
. It underwent significant refactoring compared to its predecessor, version 5.x
. The two versions are not compatible. In this example, we will be using the latest 6.x
version.
This example parallels the functionality of the previous tutorial about web3-react
. Most of the code remains the same, so this article will omit some detailed explanations for brevity.
Create a React Project
pnpm create vite rubyone-ethers --template react-ts
Install dependencies:
cd rubyone-ethers
pnpm install @rubyone/jssdk react-toastify ethers
Here, we didn't specify the ethers
version, meaning the latest 6.x
will be installed.
Creating a Provider
This step is identical to our previous example. Code the following in the sdk.ts
file:
import { RubyOneProvider } from '@rubyone/jssdk'
const rubyOneProvider = new RubyOneProvider()
export default rubyOneProvider
Configure Connector
This step majorly differs from web3-react
. In the prior example, we relied on web3-react
's initializeConnector
to create an EIP1193
connector. However, with ethers
, we'll utilize BrowserProvider
to achieve a similar goal. Here's the core code:
import { BrowserProvider } from 'ethers'
const provider = new BrowserProvider(rubyOneProvider)
Write the Hook
The basic functionality remains consistent with the previous example. The key differences are:
- Using the
BrowserProvider
instance for reading/writing data. - Manually activating the wallet.
- Handling wallet events on our own.
Complete code is as follows:
import { useCallback, useEffect, useMemo, useState } from 'react'
import { BrowserProvider, formatUnits, parseUnits, Contract } from 'ethers'
import rubyOneProvider from './sdk'
import ERC20 from './ERC20.json'
const RBT = '0xffFDFC767016f7a3Baa9895D70f895302f82Cfe9'
const DEAD = '0x000000000000000000000000000000000000dEaD'
export default function useWallet() {
const [account, setAccount] = useState('')
const [chainId, setChainId] = useState('')
const [ethBalance, setEthBalance] = useState(0)
const [rbtBalance, setRbtBalance] = useState(0)
const provider = useMemo(() => {
return new BrowserProvider(rubyOneProvider)
}, [])
const getData = useCallback(async () => {
if (!account) return
const contract = new Contract(RBT, ERC20, provider)
const ethBalance = await provider.getBalance(account)
const rbtBalance = await contract.balanceOf(account)
const ethValue = Number(formatUnits(ethBalance))
const rbtValue = Number(formatUnits(rbtBalance))
setEthBalance(ethValue)
setRbtBalance(rbtValue)
}, [provider, account])
const transferRBT = useCallback(async () => {
if (!account) return
const signer = await provider.getSigner()
const contract = new Contract(RBT, ERC20, signer)
const value = parseUnits('10')
const trans = await contract.transfer(DEAD, value)
await trans.wait(1)
getData()
return trans.hash
}, [provider, account, getData])
const init = useCallback(async () =>{
rubyOneProvider.on('accountsChanged', (accounts: string[]) => {
setAccount(accounts[0] || '')
})
rubyOneProvider.on('chainChanged', (chainId: string) => {
setChainId(chainId)
})
rubyOneProvider.on('disconnect', () => {
setAccount('')
})
const network = await provider.getNetwork()
const accounts = await rubyOneProvider.request({
method: 'eth_accounts',
params: []
})
setChainId(network.chainId.toString())
setAccount(accounts[0] || '')
}, [provider])
const connect = useCallback(async () => {
const accounts = await rubyOneProvider.request({
method: 'eth_requestAccounts',
params: []
})
setAccount(accounts[0] || '')
}, [])
useEffect(() => {
getData()
}, [getData])
useEffect(() => {
init()
}, [init])
return {
chainId,
account,
ethBalance,
rbtBalance,
provider,
connect,
getData,
transferRBT
}
}
Write the Component
For component code, you can refer to the example in the previous article.
Be sure not to forget to include the CSS style files required by the SDK into the page.
import '@rubyone/jssdk/dist/style.css'
Conclusion
As illustrated by the example above, even if you're directly utilizing the raw ethers
to connect to Ruby One
, it's incredibly straightforward. You can easily transfer your MetaMask
development experience over.