DERO RPC BRIDGE API Tutorial
For this example we will be using the React Framework with vite and yarn tools.
Lets get right into it:
Quick app setup
# create project using vite
yarn create vite
Then enter the project name, select react
and react-ts
.
When the project is created, you need to move to this folder, add the bridge to your project and install packages :
# Move into the project folder
cd PROJECT_NAME # change that to your actual project name
# Add the bridge to your project
yarn add dero-rpc-bridge-api
# Install dependencies and start dev server
yarn && yarn dev
Now you should have a running development server!
Initialising the connection with the Bridge
Let’s start with the main component (App.ts):
import './App.css'
// Simply return a div
function App() {
return (
<div className='App'>
</div>
)
}
We will declare a state variable bridge
that will hold the object imported from the dero-rpc-bridge-api
.
import { useState } from 'react' // Import useState
import './App.css'
import DeroBridgeApi from 'dero-rpc-bridge-api' // Import the brigde
function App() {
// Add the state variable using useState hook
const [bridge, setBridge] = useState<DeroBridgeApi>()
return (
<div className='App'>
</div>
)
}
Then add a button to connect to the bridge !
import { useCallback, useState } from 'react' // Import useCallback
import './App.css'
import DeroBridgeApi from 'dero-rpc-bridge-api'
function App() {
const [bridge, setBridge] = useState<DeroBridgeApi>()
// Add the button callback function
const connect = useCallback(async () => {
...
}, [])
return (
<div className='App'>
// Add the button calling the connect function on click
<button onClick={connect}>connect</button>
</div>
)
}
We will also setup a state variable, to handle the status of the connection to the bridge. We will start by declaring an enumeration of the different states:
In utils/connection-status.ts
:
// Declare the enumeration. We will move this in a separate file later to
export enum ConnectionStatus {
NotConnected = "not connected",
Connected = "connected to the bridge!",
Connecting = "connecting...",
Failed = 'connection failed !'
}
And declare the variable in App.tsx
:
import { useCallback, useState } from 'react'
import './App.css'
import DeroBridgeApi from 'dero-rpc-bridge-api'
import { ConnectionStatus } from './utils/connection-status' // Import ConnectionStatus enumeration
function App() {
const [bridge, setBridge] = useState<DeroBridgeApi>()
// Add status initialized with NotConnected
const [status, setStatus] = useState<ConnectionStatus>(ConnectionStatus.NotConnected)
const connect = useCallback(async () => {
...
}, [])
return (
<div className='App'>
<button onClick={connect}>connect</button>
</div>
)
}
We’re almost done with the first part ! We need to handle the click of the button :
...
const connect = useCallback(async () => {
// Start by setting the status of the connection to connecting when we click.
setStatus(ConnectionStatus.Connecting);
// Load the bridge in a local constant variable
const deroBridgeApi = new DeroBridgeApi();
// Initialise the object and handle the different Promise cases
deroBridgeApi.init()
.then(() => { // When connection is successful
// We set status to Connected !
setStatus(ConnectionStatus.Connected);
})
.catch((err: any) => { // If an error occured
// We just put the error message as the status. We could handle it better, but it works for this example !
setStatus(err.message);
})
// Then we save the object in the app's state variable.
setBridge(deroBridgeApi);
}, [])
...
Great ! Now we should end up with this :
App.tsx
import { useCallback, useState } from 'react'
import logo from './logo.svg'
import './App.css'
// @ts-ignore
import DeroBridgeApi from 'dero-rpc-bridge-api'
import { ConnectionStatus } from './utils/connection-status'
function App() {
const [bridge, setBridge] = useState<DeroBridgeApi>()
const [status, setStatus] = useState<ConnectionStatus>()
const connect = useCallback(async () => {
setStatus(ConnectionStatus.Connecting);
const deroBridgeApi = new DeroBridgeApi();
deroBridgeApi.init()
.then(() => {
setStatus(ConnectionStatus.Connected);
})
.catch((err: any) => {
setStatus(err.message);
})
setBridge(deroBridgeApi);
}, [])
return (
<div className='App'>
<button onClick={connect}>connect</button>
<div>Status: {status}</div>
</div>
)
}
export default App
connection-status.ts
export enum ConnectionStatus {
NotConnected = "not connected",
Connected = "connected to the bridge!",
Connecting = "connecting...",
Failed = 'connection failed !'
}
And click on connect :
Create a context to access the bridge anywhere in the app.
Now we’ll setup a context with the useContext hook in App.tsx
:
import { useCallback, useState } from 'react'
import './App.css'
// @ts-ignore
import DeroBridgeApi from 'dero-rpc-bridge-api'
import React from 'react';
import GetBalanceComponent from './components/GetBalanceComponent';
import { ConnectionStatus } from './utils/connection-status';
// Global context variable to use all across the app
export const DeroContext = React.createContext<DeroBridgeApi>(null);
// App component
function App() {
const [bridge, setBridge] = useState<DeroBridgeApi>()
const [status, setStatus] = useState<ConnectionStatus>(ConnectionStatus.NotConnected)
// Callback when we click the connect button
const connect = useCallback(async () => {
setStatus(ConnectionStatus.Connecting);
const deroBridgeApi = new DeroBridgeApi();
deroBridgeApi.init()
.then(() => {
setStatus(ConnectionStatus.Connected);
})
.catch((err: any) => {
setStatus(err.message);
})
setBridge(deroBridgeApi);
}, [])
return (
// Pass the bridge object to the context provider
// The app has a title a button calling the connect callback defined earlier and a custom components defined in components/
<DeroContext.Provider value={bridge}>
// App wrapper
<div className='App'>
<h1>Dero RPC Bridge API example app</h1>
<button onClick={connect}>connect</button>
<div>Status:</div>
<div><i>{status}</i></div>
// A GetBalanceComponent that we are going to create soon !
<GetBalanceComponent status={status}/>
</div>
</DeroContext.Provider>
)
}
export default App
Then create a component that gets the balance in components/GetBalanceComponent.ts
:
import { useCallback, useContext, useState } from "react"
import { DeroContext } from "../App";
import { ConnectionStatus } from "../utils/connection-status";
// Define the props of our component
interface Props {
status: ConnectionStatus
}
// GetBalanceComponent definition
export default (props: Props) => {
// Balance and error message, updated when clicking the Get Balance button
const [balance, setBalance] = useState<string | number>('unknown');
const [errorMessage, setErrorMessage] = useState<string>();
// Here we get the bridge object from the context
const deroBridgeApi = useContext(DeroContext);
// Callback when clicking the Get Balance button
const getBalance = useCallback(async () => {
// Call the GetBalance method from the wallet
deroBridgeApi.wallet('get-balance')
.then((response: any) => { // When successful
// Update the balance state of the component
setBalance(response.data.result.balance / 100000)
// Empty the error message
setErrorMessage("");
})
.catch((err: any) => { // When failed
// Update the balance to unknown
setBalance('unknown');
// Update the error message
setErrorMessage(err.message);
})
}, [props.status]) // Update the function when the connection status change so that the context actually provide a deroBridgeApi object
// We render the component only if status is connected
if (props.status == ConnectionStatus.Connected) {
return <div className='GetBalanceComponent'>
// Title
<h2>GetBalance Component</h2>
// Button
<button onClick={getBalance}>Get Wallet Balance</button>
// Balance display
<div>Balance:</div>
<div>{balance}</div>
<div>{errorMessage}</div>
</div>
} else {
return <div></div>
}
}
And it gives us :
Clicking on the Connect
button :
Clicking on the Get Balance
button :
Done !
We’ve got a fonctional connection to the bridge, usable in all the application with a Context !