Connecting AlphaDEX to your React JS app.
This is a quick tutorial on how to connect your React JS app to the AlphaDEX decentralized exchange platform on Radix DLT. You can find more AlphaDEX related tutorials like this here.
This tutorial assumes you have a basic knowledge of how React apps work. If you don't, then you can learn more about React at reactjs.org.
You will need Node.js installed on your machine to follow this tutorial. If you do not have it installed yet, you can follow the instructions to do so on their website nodejs.org.
Set up new React app
If you have an existing React app already, you can jump straight to the “Install AlphaDEX SDK” step.
Create a new app
The fastest way to create a new React app is to use a Node.js package called create-react-app
. To use it, move to the folder in which you want to create your new app and run the following command:
npx create-react-app hello-alphadex-react
This might take a few seconds and will create a new folder called hello-alphadex-react
which contains all the files needed for a new React app.
Run your new app
Move to the newly created app directory with this command:
cd hello-alphadex-react
Run your new app with this command:
npm start
A new browser window should open up with your new app. If it does not open automatically, you can open your browser and type localhost:3000
into the address bar. You should see a blank screen with a spinning React logo and a link to the React website.
Clean up the app
For this tutorial, we want a clean slate to work with, so open the App.js
file in the src
directory and change it to look like this:
function App() {
return (
<div>
<h1>Hello AlphaDEX</h1>
</div>
);
}
export default App;
Save the file with your changes and the browser window will automatically be updated to only show “Hello AlphaDEX” on a blank screen. Not the prettiest screen, but we now have a blank slate to show you how to connect your app to AlphaDEX.
Install AlphaDEX SDK
Before we can connect to AlphaDEX, we need to install the SDK in our project. To do this, make sure you are in your project directory and run the command:
npm install alphadex-sdk-js
This will install the AlphaDEX SDK files in your project’s node_modules
directory, ready to be used in your project.
Import the AlphaDEX SDK
OK, we are ready to connect our app with AlphaDEX (finally!).
In order to use the functionality in the SDK, you need to import the required functionality into your app. You can do this in 2 ways.
Method 1 (Import functionality as needed)
With this method you only import the functions and variables that you will need for a specific task e.g. if we only want to import the init
function and clientState
variable, we will do it like this:
import {init, clientState} from "alphadex-sdk-js"
Now you can access the imported functions/variables directly using their name. E.g. I can call the init
function and access the clientState
variable like this in my code:
init();
const myOwnVariable = clientState;
Method 2 (Import all functionality at once)
With this method you import all the SDK functions, variables and types at once into a reference variable like this: (I called the reference variable adex
below, but you can call it anything you like.)
import * as adex from "alphadex-sdk-js"
Using this method you use the reference variable to get access to the SDK functions, variables and types. E.g. to call the init
function and access the clientState
variable in your code, you would do it like this:
adex.init();
const myOwnVariable = adex.clientState;
Initialize the SDK
In order to connect to the AlphaDEX exchange (we are actually connecting to an AlphaDEX API/Websocket server), we need to run the init
function of the SDK once somewhere near the start of our application.
In our example we are going to run the init
function in our App.js
file as this is the first (root) component in our app. You can also run the init
function in the index.js
file of your project. Add the following lines just below the existing import statements in your App.js
file:
import { init } from "alphadex-sdk-js";
init();
If you save the changes, you application will attempt to connect to the AlphaDEX exchange. You wont see any changes on the screen yet, but if you want you can go into the “Developer Tools” section of your browser, you should see a message like below on the Console:
Websocket connection 1 established with AlphaDEX server ws://ws.alphadex.net
This confirms that you are now connected to AlphaDEX.
Display AlphaDEX information
Now that you are connected to AlphaDEX, you can access all the different variables made available by the SDK in your app.
Save AlphaDEX variables in your app state
The AlphaDEX clientState
object contains all the variables that can be used by your app. These variables are automatically kept up to date by the SDK, which means they are constantly changed to reflect the latest values on the exchange.
To use the clientState
object in your app, you need to import it from alphadex-sdk-js
. If you followed Method 1 above for importing the sdk variables, then you need to add clientState
to your import statement:
import {init, clientState} from "alphadex-sdk-js";
If you used Method 2 by importing all the variables as a reference variable, then clientState
is already imported and can be accessed as adex.clientState
in your code.
To display the constantly changing values of the clientState
object in your react app, you want to save them in your app state using the useState
hook.
To import the useState
function into your App.js file, add this line at the top of the file:
import { useState } from "react";
Then add the following line to your App.js file as the first line in your App() function:
const [adexState, setAdexState] = useState(clientState);
This line sets a state variable called adexState
equal to the initial value of clientState
and also provides a function called setAdexState
which we can use to update the adexState
variable in our app.
Display AlphaDEX data on the screen
Lets display some AlphaDEX information on the screen. Add the following line to the App.js file just below the “Hello AlphaDEX” heading:
<p> AlphaDEX SDK connection status: {adexState.status} </p>
This line prints out the status of the SDK connection on the screen. Save the file and you should see a new line on your screen showing the status as “LOADING”.
Well done! You have just displayed your first AlphaDEX value to the screen.
There is a problem though. The status should actually be “READY” to indicate that the AlphaDEX connection is live and all variables are being updated and not “LOADING”, which is the initial status of the connection while it is fetching information from AlphaDEX. So our app is displaying the status as it was when we first loaded the clientState
object, but it is not showing any updates to the data after that. Lets fix that…
Display live AlphaDEX data on the screen
The problem is occurring because React does not know that the fields in the clientState
object has changed in the background (that is what the SDK is doing), so it does not know to show the new information on the screen. We need to explicitly tell it that the clientState
object has changed to force it to display the new updated information on the screen.
To do this, we will subscribe to an observable variable that the SDK makes available for this purpose. I will not go into the details of how observables work in this tutorial, but suffice to know that is will let our app know every time data changes happen in the clientState
object, which allows us to tell the app to show the new information on the screen.
We will subscribe to the observable variable in a React useEffect
hook. First, we need to add useEffect
to our import statement at the top of the App.js file:
import { useEffect, useState } from "react";
Now we add the useEffect
code as the second line in our App() function:
...
const [adexState, setAdexState] = useState(clientState);
// new useEffect code starts here
useEffect(() => {
let sub = clientState.stateChanged$.subscribe(newState => setAdexState(newState));
return () => if (sub) {sub.unsubscribe()};
}, []);
// new useEffect code stops here
Lets quickly run through what the new code does:
- We setup a React
useEffect
hook by calling theuseEffect
function and passing it two parameters, a function that it will run only once in this case and an empty array[]
to indicate that the effect must only run once when the App component is loaded. - The function we pass into the
useEffect
will create a new subscription calledsub
to an observable variable calledclientState.stateChanged$
. Every time the observable variable changes, it will emit a new variable callednewState
which we will then use to update ouradexState
variable to. By using the functionsetAdexState
to set ouradexState
variable, we are also telling React to update what is displayed on the screen to reflect the new value. - We also create a return function in the
useEffect
which will be called when the App component is destroyed by React (probably when you exit the app website) to make sure we destroy our subscriptionsub
to prevent memory leaks in our app.
If you save the data and look at the output on the screen, it should now correctly reflect the status as “READY”. You can click the refresh button on your browser to see the value briefly showing “LOADING” and then “READY” as it gets updated after the connection with AlphaDEX is established.
Showing more interesting information
Now that the hard work is done, you can let your creativity run free and display all kinds of live data from the AlphaDEX exchange.
Display all AlphaDEX pairs
Lets see if we can display the pairs that are available on the AlphaDEX exchange.
Add the following lines of code to your App.js file:
<p>AlphaDEX SDK Connection status: {adexState.status}</p>
// new code to add start here
<h3>AlphaDEX Pairs</h3>
<ul>
{adexState.pairsList.map((pair, index) => <li key={index}>{pair.name}</li>)}
</ul>
// new code to add ends here
Save your file and you should now see a list of names of the pairs available on AlphaDEX.
Create a separate PairsList component
Lets rather move our list of pairs into its own component so we can re-use it in our app.
Delete the code you added to App.js in the previous section to display the list of pairs and replace it with this line:
<PairsList adexState={adexState} />
Add the import of the PairsList
component (we will create it next) below the other imports in the App.js file:
import{ PairsList } from "./PairsList";
In the src
directory create a new file called PairsList.js
with the following code:
export function PairsList(props) {
return (
<div>
<h3>AlphaDEX Pairs</h3>
<ul>
{props.adexState.pairsList
.map((pair, index) => <li key={index}>{pair.name}</li>)
}
</ul>
</div>
)
}
Notice that we pass the adexState
variable as a prop to our new PairsList
component. This is the simplest way to pass the AlphaDEX data between your components.
Save your new PairsList.js
file as well as the changes to your App.js
file and you should again see the list of pairs just like you did before, but now they are displayed in their own separate component.
Accessing AlphaDEX data in all components
There are several approaches you can follow to access the AlphaDEX data in all your components. We have already implemented one approach, which is to pass the AlphaDEX data between components using props, but this can get quite complicated in more advanced apps with many different levels of components.
Another approach would be to implement a state management library like Redux to hold the AlphaDEX data, but that is beyond the scope of this tutorial.
One other approach that is easy to implement and avoids the complexity of passing props, is to create a React Context variable that can then be shared with all child components in your app.
Create a context variable for AlphaDEX data
To create a React context variable for the AlphaDEX data, add createContext
to your import from “react” and create a context called AdexStateContext
with the following lines of code in your App.js file:
// new import statement that includes createContext
import { createContext, useEffect, useState } from "react";
// create a new context - add as first line after import statements
export const AdexStateContext = createContext();
Add a context provider to the App component
To pass the context variable to all child components of your app, you need to wrap the contents of your App component with a Context Provider component. Change the return portion of your App component to look like this:
return (
<AdexStateContext.Provider value={adexState}>
<h1>Hello AlphaDEX</h1>
<p>AlphaDEX SDK connection status: {adexState.status}</p>
<PairsList />
</AdexStateContext.Provider>
);
Note that we replaced the wrapping <div>
component with the AdexState.Provider
component and removed the adexState
prop from the PairsList
component.
We assigned the adexState
state variable to the AdexStateContext
. This means we can now access the adexState
variable in any of the child components using the AdexStateContext
.
In PairsList.js we now need to import the useContext
function and the AdexStateContext
we just created to access the AlphaDEX data in the component. We can then assign the data to a local variable and use that variable in our component. The updated PairsList.js file should look like this:
import { useContext } from "react";
import { AdexStateContext } from "./App";
export function PairsList() {
const adexState = useContext(AdexStateContext);
return (
<div>
<h3>AlphaDEX Pairs</h3>
<ul>
{adexState.pairsList
.map((pair, index) => <li key={index}>{pair.name}</li>)
}
</ul>
</div>
)
}
Note that we removed any reference to props from the PairsList
component.
You can now access the AdexStateContext
in any of the components in your app as long as they are a child component of the App component.
Changing AlphaDEX variables
So far we have only been reading variables with AlphaDEX data, but the AlphaDEX SDK also have some variables that you can change that will affect the data that is available through the SDK (see a full list of these variables in the SDK documentation).
For example, the AlphaDEX SDK only keeps a fully updated order book and order history for one pair at a time (it will take way too much bandwidth and memory to keep this information for all pairs on AlphaDEX). This pair is specified by the currentPairAddress
field in the clientState
object. If you change this field, the SDK will automatically update a number of other variables to reflect the newly selected pair. Lets incorporate this functionality in our app.
Update the PairsList component
First, lets update our PairsList component to enable the user to select a specific pair and set it as the current pair of the SDK.
Change your PairsList.js file to look like this:
import { useContext } from "react";
import { AdexStateContext } from "./App";
import { clientState } from "alphadex-sdk-js";
export function PairsList() {
const adexState = useContext(AdexStateContext);
const selectPair = (pairAddress) => {
clientState.currentPairAddress = pairAddress;
}
return (
<div>
<h3>AlphaDEX Pairs</h3>
<ul>
{adexState.pairsList
.map((pair, index) =>
<li key={index}>
<button = onClick={() => selectPair(pair.address)}>
{pair.name}
</button>
</li>)
}
</ul>
</div>
)
}
Lets quickly run through the changes.
- We added an import of the
clientState
object from the AlphaDEX SDK. We need to update the fields in this object when we want the SDK to fetch new information from the AlphaDEX exchange. - We added a new function called
selectPair
to our component. This function takes apairAddress
parameter and then sets theclientState.currentPairAddress
field to the new pair address. This will prompt the SDK to update all the other fields in theclientState
object that are related to the currently selected pair. - We also changed our list of pairs to now consist of buttons that will call the
selectPair
function with the appropriate pair address when they are clicked.
Once you save your new PairsList.js file, you will notice the list now consist of buttons that you can click.
Add a PairInfo component
At the moment we can’t see any changes when we select a new pair, so lets add a component to show the details of the currently selected pair.
Create a file called PairInfo.js in your src
directory and add the following lines of code to the file:
import { useContext } from "react"
import { AdexStateContext } from "./App"
export function PairInfo() {
const adexState = useContext(AdexStateContext);
return (
<div>
<h3> Information for currently selectd pair</h3>
<p>Name: {adexState.currentPairInfo.name}</p>
<p>Address: {adexState.currentPairInfo.address}</p>
<p>Last Price: {adexState.currentPairInfo.lastPrice}</p>
<p>No of sell prices in orderbook: {adexState.currentPairOrderbook.sells.length}</p>
<p>No of buy prices in orderbook: {adexState.currentPairOrderbook.buys.length}</p>
</div>
)
}
This file adds no new functionality to what we have learned so far. It uses the AdexStateContext to access the AlphaDEX data and then displays a number of data points related to the currently selected pair.
Add the PairInfo component to your App.js file by importing it and adding it as a child component in the App component:
...
// add the following line below the other import statements
import { PairInfo } from "./PairInfo";
...
// add the following line below the <PairsList/> line
<PairInfo/>
Save the PairInfo.js and App.js files and you should now see a display of the currently selected pair’s info on the screen. The info should change when you click on another pair in the list.
Can you build your own exchange?
Congratulations! You now know how to display live exchange information in a React app. At the moment it might not look like the information is live as there is still very little activity on the AlphaDEX test instance, but rest assured that your application will automatically update every time there is a change on the AlphaDEX exchange.
We only touched on the very basics of what the AlphaDEX SDK allows you to do. If you want to find out more about what information is available through the SDK, you can find its developer documentation here.
The only aspect we have not touched on is how to submit a transaction to the AlphaDEX on-ledger component, but we will leave that for another tutorial.
Can you build the best looking exchange front-end for the Radix network? We are keen to see what you come up with and remember, you can earn a fee for all orders that get placed through your app, so there is a real incentive to build you own exchange using the AlphaDEX SDK.
If you get stuck on this tutorial or have any further questions about AlphaDEX, give us a shout on our telegram channel.