Skip to main content

Interacting with 0x API using JavaScript

Created on
Updated on
Nov 26, 2024

15 min read

Overview

We have seen tremendous growth in trade volume in DEXs. With many of these coming to the market, it is tough to decide which DEX to choose when you want to swap your token for another. That's where 0x and its APIs come into the picture. It helps us to fetch the DEX with the best price quote. This will give a much better output for the number of tokens we want to swap, which you will eventually see towards the end. So, make sure to follow through till the end.

Prerequisites:

1. Terminal

2. Node

3. Code Editor

4. Curious mind

What is a DEX?

A Decentralised EXchanges, popularly known as DEX, is a crucial part of the blockchain ecosystem. It is a decentralized marketplace that connects cryptocurrency buyers and sellers in a peer-to-peer fashion without involving any controlling/central authority. Some of the popular DEX in the space are UniSwap, SuhiSwap, and PancakeSwap. Smart contracts power every DEX to operate in a deterministic and unstoppable manner. DEXs has gained popularity and has seen a massive surge in numbers because they are permissionless. In any Centralised Exchange, you will have to verify your identity through KYC, and the exchange is in control of your private key. So, if the organization gets hacked or freezes your account, your funds will be gone forever. But in a DEX, a user is in control of the private key. The only limiting factor is the security flaw in the contract. Any good DEX would audit their contract from multiple agencies to make sure they are less prone to attacks. So in case, you want to swap your ETH for some DAI, you can easily do that using a DEX. 

Heart of DEX→AMM

Automated Market Maker or AMM drives the DEX. AMM, at its core, uses a mathematical formula that decides the price for a pair of tokens and facilitates the trading of tokens. It helps in quoting the exchange rate for two assets and allows anyone to build the market for the duo by providing liquidity, i.e., become a market maker. For example, Uniswap uses x*y=k as AMM. Here x is the quantity of one token, and y is the quantity of another token. Now, the product of both tokens should be constant, which is denoted by k.  Ideally, no matter how many tokens are added or removed, it will balance out to keep the product steady. Other functionalities come into the picture, including swapping, liquidity mining, and many more.

About 0X

Following the official docs:

0x is a protocol that facilitates the peer-to-peer exchange of Ethereum-based assets. The protocol serves as an open standard and common building block for any developer needing exchange functionality.

0x is one of its kind that enables peer-to-peer trading in the traditional book order method. Book orders are a standard trading method that matches buyers and sellers based on the price they quote. Though it is a feasible and trendy option for a centralized exchange, it becomes a very costly and time-consuming affair for a DEX. Every transaction and smart contract interaction would consume gas, aka money. 0x promises to get rid of this pain point by taking some of the procedures off-chain. This would save a lot of money for the participants and the procedure would be much faster. In a nutshell, a trade initiation takes place off-chain, and the settlement is done on-chain, which makes the dream of a frictionless decentralized order book a reality.

The key participants in the protocols are Makers, Takers, and Relayers. Makers are the market entity that initiates a trade, while Takers are entities that fulfill the transaction. In between is the Relayers that connects Makers and Takers, which again keeps a record of all off-chain settlements. Let's say Maker wants to swap Token A for Token B. It would go like this:

1. Maker approves the 0x contract to access their balance of Token A and initiates an order to exchange it for Token B. Maker signs the transaction with its private key, converting the order into a **message format** that is ready to be transmitted to off-chain channels.

2. The Maker broadcasts it over Relayer. 0x has an explorer page that lists the Relayers. 

3. A Taker, who wants to fill the order, approves the 0x contract to access their balance of Token B.

4. The Taker filled the order by submitting it to the 0x contract on the Ethereum blockchain.

5. The Relayer receives fees in the form of XRZ, which is the native token of 0x.

0x is a next-generation DEX that lets developers leverage its open software to build Dapps and projects around it. 0x has developer-friendly resources and provides support to develop projects on top of 0x. This way, 0x is a lucrative choice among both business people and developers. 0x believes in the motto that any ownable assets can be tokenized, i.e., represented as a token in the blockchain. This means that soon, your house can be defined as a token in blockchain and can be traded in a decentralized fashion without involving an intermediary like a lawyer or brokerage firm. 0x is evolving and aiming to fulfill such needs.

Code

Now, we will leverage the APIs provided by 0x to build an application that will assist us in finding the best DEX to swap our token.

Installation

1.  For that, create a folder named ZRX_Swap.  Inside the folder, open your terminal and enter:

npm init -y

2. Now open the folder in your favorite editor. For this article, we will be using VS Code editor. Now, run the following command to open the folder in VS editor:

code .

3.We will need to install a package called qs. For that:

npm install qs --save

4.Now, we also need to install a package called axios. It will help us to call the 0x API. For that:

npm install axios --save

Writing the code

Create a file called index.js which will house our main code. In this, we will fetch the best quotation sent by 0x, and we will separately try to fetch the same from UniSwapV3. This highlights that we can either go for a specific exchange of our choice or let 0x decide the best one for us. Copy and paste the following code in the file:

const { default: axios } = require('axios')
const qs = require('qs')
const params = {
buyToken: 'DAI',
sellToken: 'ETH',
sellAmount: 0.05 * Math.pow(10, 18).toString(), // Always denominated in wei
}
const URL = 'https://api.0x.org/swap/v1/quote?'

//Get Default Quote
const getDefaultQuote = async () => {
let response
try {
response = await axios.get(`${URL}${qs.stringify(params)}`)
} catch (err) {
console.error(err)
}
console.log("Default Quote")
console.log("%O",response.data)
console.log("%O",response.data.sources)

}

//Get Quote from a specific DEX
const getUniSwapV3Quote = async (inputToken, outputToken, value) => {
const exchangeList = 'Uniswap_V3'
const params = {
buyToken: 'DAI',
sellToken: 'ETH',
sellAmount: 0.05 * Math.pow(10, 18).toString(), // Always denominated in wei
includedSources: exchangeList,
}
let response
try {
response = await axios.get(
`${URL}${qs.stringify(params)}`,
)
} catch (err) {
console.error(err)
}
console.log("Uniswap Quote",)
console.log("%O",response.data)
console.log("%O",response.data.sources)
}

getDefaultQuote()
getUniSwapV3Quote()

Line1: We are importing axios, a popular node module for making HTTPS request.

Line2: Next, we are importing qs which is mainly used for formatting our query string for our API to work.

Line3-7: We are creating an object that contains details about:

1. The token we want to sell. In this case, it is Ether (i.e., ETH).

2. The token we want to buy. So, we will buy some DAI.

3. The amount of token you want to sell. In this case, we are selling 0.005 Ether or 0.005 * 10^8 Wei.

Line 8: We are storing the base URL in a variable.

Line 11: We define a function that would fetch us the best price quotation by 0x for the given pair.

Line 12:We are defining a variable to store the response we got from the API.

Line 13:Start of the try block.

Line 14:We are calling the API using axios. In the get parameter, we are passing the base URL and the formatted query object. We are storing the output in the response variable.

Lines 15-17:End of the try block. We have a catch block to log any error from API.

Lines 18-21: We are displaying the quotation for the pair of tokens and the source from which we are getting them.

Lines 24-41: We are following the same procedure as above except that we are passing an additional field i.e. includedSources in the params object, which contains the DEXs name from which we want to fetch the quote. In this case, we want to fetch the quotation from UniSwapV3.

Lines 43-44: We are calling the above functions to see their output.

Now, in the terminal, run:

node index

Output

You should see an output similar to the ones below:

1. For Default Quote

Default Quote
{
chainId: 1,
price: '1813.2127887520304968',
guaranteedPrice: '1795.0806608645101918',
to: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
data: '0xd9627aa400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000007c8f09c066034caf00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f869584cd0000000000000000000000001000000000000000000000000000000000000011000000000000000000000000000000000000000000000083951146f160f5b444',
value: '5000000000000000',
gas: '136000',
estimatedGas: '136000',
gasPrice: '59000000000',
protocolFee: '0',
minimumProtocolFee: '0',
buyTokenAddress: '0x6b175474e89094c44da98b954eedeac495271d0f',
sellTokenAddress: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
buyAmount: '9066063943760152484',
sellAmount: '5000000000000000',
sources: [
{ name: '0x', proportion: '0' },
{ name: 'Uniswap', proportion: '0' },
{ name: 'Uniswap_V2', proportion: '0' },
{ name: 'Eth2Dai', proportion: '0' },
{ name: 'Kyber', proportion: '0' },
{ name: 'Curve', proportion: '0' },
{ name: 'Balancer', proportion: '0' },
{ name: 'Balancer_V2', proportion: '0' },
{ name: 'Bancor', proportion: '0' },
{ name: 'mStable', proportion: '0' },
{ name: 'Mooniswap', proportion: '0' },
{ name: 'Swerve', proportion: '0' },
{ name: 'SnowSwap', proportion: '0' },
{ name: 'SuiSwap', proportion: '1' },
{ name: 'Shell', proportion: '0' },
{ name: 'MultiHop', proportion: '0' },
{ name: 'DODO', proportion: '0' },
{ name: 'DODO_V2', proportion: '0' },
{ name: 'CREAM', proportion: '0' },
{ name: 'LiquidityProvider', proportion: '0' },
{ name: 'CryptoCom', proportion: '0' },
{ name: 'Linkswap', proportion: '0' },
{ name: 'Lido', proportion: '0' },
{ name: 'MakerPsm', proportion: '0' },
{ name: 'KyberDMM', proportion: '0' },
{ name: 'Smoothy', proportion: '0' },
{ name: 'Component', proportion: '0' },
{ name: 'Saddle', proportion: '0' },
{ name: 'xSigma', proportion: '0' },
{ name: 'Uniswap_V3', proportion: '0' },
{ name: 'Curve_V2', proportion: '0' },
{ name: 'ShibaSwap', proportion: '0' }
],
orders: [
{
makerToken: '0x6b175474e89094c44da98b954eedeac495271d0f',
takerToken: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
makerAmount: '9066063943760152484',
takerAmount: '5000000000000000',
fillData: [Object],
source: 'SuiSwap',
sourcePathId: '0x2ea41c4f046aa0e743deb854fb95d19a4c011243a12d190f8a22cf14e974c86b',
type: 0
}
],
allowanceTarget: '0x0000000000000000000000000000000000000000',
sellTokenToEthRate: '1',
buyTokenToEthRate: '1813.2096453862199738'
}
[
{ name: '0x', proportion: '0' },
{ name: 'Uniswap', proportion: '0' },
{ name: 'Uniswap_V2', proportion: '0' },
{ name: 'Eth2Dai', proportion: '0' },
{ name: 'Kyber', proportion: '0' },
{ name: 'Curve', proportion: '0' },
{ name: 'Balancer', proportion: '0' },
{ name: 'Balancer_V2', proportion: '0' },
{ name: 'Bancor', proportion: '0' },
{ name: 'mStable', proportion: '0' },
{ name: 'Mooniswap', proportion: '0' },
{ name: 'Swerve', proportion: '0' },
{ name: 'SnowSwap', proportion: '0' },
{ name: 'SuiSwap', proportion: '1' },
{ name: 'Shell', proportion: '0' },
{ name: 'MultiHop', proportion: '0' },
{ name: 'DODO', proportion: '0' },
{ name: 'DODO_V2', proportion: '0' },
{ name: 'CREAM', proportion: '0' },
{ name: 'LiquidityProvider', proportion: '0' },
{ name: 'CryptoCom', proportion: '0' },
{ name: 'Linkswap', proportion: '0' },
{ name: 'Lido', proportion: '0' },
{ name: 'MakerPsm', proportion: '0' },
{ name: 'KyberDMM', proportion: '0' },
{ name: 'Smoothy', proportion: '0' },
{ name: 'Component', proportion: '0' },
{ name: 'Saddle', proportion: '0' },
{ name: 'xSigma', proportion: '0' },
{ name: 'Uniswap_V3', proportion: '0' },
{ name: 'Curve_V2', proportion: '0' },
{ name: 'ShibaSwap', proportion: '0' }
]

2. For UniSwapV3 Quote

UniswapV3 Quote
{
chainId: 1,
price: '1819.24780097598123892',
guaranteedPrice: '1801.05532296622142652',
to: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
data: '0x3598d8ab0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000004e1bbb1b11f673a5e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f46b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000869584cd00000000000000000000000010000000000000000000000000000000000000110000000000000000000000000000000000000000000000c2bfe11f3560f5b443',
value: '50000000000000000',
gas: '151000',
estimatedGas: '151000',
gasPrice: '59000000000',
protocolFee: '0',
minimumProtocolFee: '0',
buyTokenAddress: '0x6b175474e89094c44da98b954eedeac495271d0f',
sellTokenAddress: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
buyAmount: '90962390048799061946',
sellAmount: '50000000000000000',
sources: [
{ name: '0x', proportion: '0' },
{ name: 'Uniswap', proportion: '0' },
{ name: 'Uniswap_V2', proportion: '0' },
{ name: 'Eth2Dai', proportion: '0' },
{ name: 'Kyber', proportion: '0' },
{ name: 'Curve', proportion: '0' },
{ name: 'Balancer', proportion: '0' },
{ name: 'Balancer_V2', proportion: '0' },
{ name: 'Bancor', proportion: '0' },
{ name: 'mStable', proportion: '0' },
{ name: 'Mooniswap', proportion: '0' },
{ name: 'Swerve', proportion: '0' },
{ name: 'SnowSwap', proportion: '0' },
{ name: 'SuiSwap', proportion: '0' },
{ name: 'Shell', proportion: '0' },
{ name: 'MultiHop', proportion: '0' },
{ name: 'DODO', proportion: '0' },
{ name: 'DODO_V2', proportion: '0' },
{ name: 'CREAM', proportion: '0' },
{ name: 'LiquidityProvider', proportion: '0' },
{ name: 'CryptoCom', proportion: '0' },
{ name: 'Linkswap', proportion: '0' },
{ name: 'Lido', proportion: '0' },
{ name: 'MakerPsm', proportion: '0' },
{ name: 'KyberDMM', proportion: '0' },
{ name: 'Smoothy', proportion: '0' },
{ name: 'Component', proportion: '0' },
{ name: 'Saddle', proportion: '0' },
{ name: 'xSigma', proportion: '0' },
{ name: 'Uniswap_V3', proportion: '1' },
{ name: 'Curve_V2', proportion: '0' },
{ name: 'ShibaSwap', proportion: '0' }
],
orders: [
{
makerToken: '0x6b175474e89094c44da98b954eedeac495271d0f',
takerToken: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
makerAmount: '90962390048799061946',
takerAmount: '50000000000000000',
fillData: [Object],
source: 'Uniswap_V3',
sourcePathId: '0xfe215f0d81d8367ed86f2044b4b354d556f564f8bcb5bfec85fa07c54f31015c',
type: 0
}
],
allowanceTarget: '0x0000000000000000000000000000000000000000',
sellTokenToEthRate: '1',
buyTokenToEthRate: '1813.2096453862199738'
}
[
{ name: '0x', proportion: '0' },
{ name: 'Uniswap', proportion: '0' },
{ name: 'Uniswap_V2', proportion: '0' },
{ name: 'Eth2Dai', proportion: '0' },
{ name: 'Kyber', proportion: '0' },
{ name: 'Curve', proportion: '0' },
{ name: 'Balancer', proportion: '0' },
{ name: 'Balancer_V2', proportion: '0' },
{ name: 'Bancor', proportion: '0' },
{ name: 'mStable', proportion: '0' },
{ name: 'Mooniswap', proportion: '0' },
{ name: 'Swerve', proportion: '0' },
{ name: 'SnowSwap', proportion: '0' },
{ name: 'SuiSwap', proportion: '0' },
{ name: 'Shell', proportion: '0' },
{ name: 'MultiHop', proportion: '0' },
{ name: 'DODO', proportion: '0' },
{ name: 'DODO_V2', proportion: '0' },
{ name: 'CREAM', proportion: '0' },
{ name: 'LiquidityProvider', proportion: '0' },
{ name: 'CryptoCom', proportion: '0' },
{ name: 'Linkswap', proportion: '0' },
{ name: 'Lido', proportion: '0' },
{ name: 'MakerPsm', proportion: '0' },
{ name: 'KyberDMM', proportion: '0' },
{ name: 'Smoothy', proportion: '0' },
{ name: 'Component', proportion: '0' },
{ name: 'Saddle', proportion: '0' },
{ name: 'xSigma', proportion: '0' },
{ name: 'Uniswap_V3', proportion: '1' },
{ name: 'Curve_V2', proportion: '0' },
{ name: 'ShibaSwap', proportion: '0' }
]

Here are some things to look for:

1. price: It gives us the best price for the token pair, which doesn't involve slippage rate

2. guranteedPrice: It gives us the price for the pair in case there is a large slippage rate. API will revert the call if this price isn't met.

3. buyAmount: The amount of token we will get in Wei.

4. sellAmount: The amount of token we sold in Wei.

5. sources: It gives us the proportion in which the amount is split among different DEXs. We are getting the whole amount from a single DEXs, so we have a proportion of 1 for both cases. 

If you observe closely, you can see that you are getting higher buyAmount from SushiSwap compared UniswapV3. Now, you can swap our ETH for DAI in SushiSwap for a higher amount of DAI. It is recommended that you try out different token pairs and compare default quotes with your favorite DEX. Here is list of DEXs that you can pass in the params:

If you want to get quotes from multiple DEXs, you can specify them in the includedSources separted by commas. So, if you want to fetch from SushiSwap and UniSwapV3, you can specify it as:

const exchangeList = 'Uniswap_V3,SushiSwap'
const params = {
buyToken: 'DAI',
sellToken: 'ETH',
sellAmount: 0.05 * Math.pow(10, 18).toString(), // Always denominated in wei
includedSources: exchangeList,
}

Conclusion

We were able to get the best price quotation for a pair of tokens using 0x API. We didn't have to go through all the DEXs, compare the quote to fetch the best quote, and make a trade. Instead, we leveraged the API to fetch the best price quote. This can be a base upon which you can build an arbitrage bot. You can go through the official documentation to build your next innovative project.

Subscribe to our newsletter for more articles and guides on Ethereum. If you have any feedback, feel free to reach out to us via Twitter. You can always chat with us on our Discord community server, featuring some of the coolest developers you’ll ever meet :)

Share this guide