SOR API Guide
This guide will help you get started with the Odos API endpoints for generating a quote (/sor/quote/v2
) and assembling a transaction (/sor/assemble
).
This guide is meant to be the simplest implementation possible for getting and executing Odos quotes via the API. For advanced usage and detailed explanation of each parameter and feature, please explore other areas of the documentation such as our detailed interactive documentation.
Anatomy of a Swap
This diagram shows the flow of a swap transaction using the Odos API. The following steps will show how to do each part of this diagram.
Setup
Firstly, you'll need to setup your project. This involves importing the required libraries for making HTTP requests.
Recommended HTTP libraries (examples below):
- Python: requests (Requires installation from here)
- Javascript: fetch (natively supported in most environments)
Step 1: Generate a Quote
The first step in using the Odos SOR API is generating a quote. This can be achieved by sending a POST
request to the /sor/quote/v2
endpoint. It is recommended to start with the example request body and customize as necessary.
Required Quote Request Parameters:
chainId
: the ID of the chain you are requesting the quote oninputTokens
: a list of token addresses and input amounts, currently anywhere from 1-6 input assets at once. Input amounts should be strings representing fixed precision integer amounts relative to each asset's decimalsoutputTokens
: a list of token addresses and output proportions, currently anywhere from 1-6 output assets at once. The proportions should always total up to 1slippageLimitPercent
: the slippage tolerance for the quote, meaning the maximum percentage of the quote the user is willing to lose to slippage, where 1 represents 1% (99% of the original quoted output)userAddr
: the checksummed address of the user who will eventually assemble and execute the quote (required to get apathId
in the response for assembly)
Recommended Optional Quote Request Parameters:
referralCode
: a referral code for tracking your projects activity using the Odos API and enabling partner relationships based on usage, learn more here. Defaults to 0 for unregistered activity.disableRFQs
: Whether or not to disable RFQ liquidity sources, which have third-party API dependencies and quote expirations, both of which can cause an increase in failed quotes and TXN reverts. Defaults totrue
to maximize reliability, but can be set tofalse
in order to access these additional liquidity sources.compact
: a flag for enabling compact call data for quote assembly, setting totrue
is recommended, learn more here. Defaults totrue
.
For path route visualization parameters, refer to the Path Viz Quick Start Guide.
- Python
- JavaScript
import json
import requests
quote_url = "https://api.odos.xyz/sor/quote/v2"
quote_request_body = {
"chainId": 1, # Replace with desired chainId
"inputTokens": [
{
"tokenAddress": "0x...", # checksummed input token address
"amount": "100000", # input amount as a string in fixed integer precision
}
],
"outputTokens": [
{
"tokenAddress": "0x...", # checksummed output token address
"proportion": 1
}
],
"slippageLimitPercent": 0.3, # set your slippage limit percentage (1 = 1%)
"userAddr": "0x...", # checksummed user address
"referralCode": 0, # referral code (recommended)
"disableRFQs": True,
"compact": True,
}
response = requests.post(
quote_url,
headers={"Content-Type": "application/json"},
json=quote_request_body
)
if response.status_code == 200:
quote = response.json()
# handle quote response data
else:
print(f"Error in Quote: {response.json()}")
# handle quote failure cases
const quoteUrl = 'https://api.odos.xyz/sor/quote/v2';
const quoteRequestBody = {
chainId: 1, // Replace with desired chainId
inputTokens: [
{
tokenAddress: '0x...', // checksummed input token address
amount: '100000', // input amount as a string in fixed integer precision
}
],
outputTokens: [
{
tokenAddress: '0x...', // checksummed output token address
proportion: 1
}
],
userAddr: '0x...', // checksummed user address
slippageLimitPercent: 0.3, // set your slippage limit percentage (1 = 1%),
referralCode: 0, // referral code (recommended)
disableRFQs: true,
compact: true,
};
const response = await fetch(
quoteUrl,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(quoteRequestBody),
});
if (response.status === 200) {
const quote = await response.json();
// handle quote response data
} else {
console.error('Error in Quote:', response);
// handle quote failure cases
}
Replace the placeholder values in the request body with actual values for your desired quote. The userAddr
should be the checksummed address of the user who may eventually assemble and execute the transaction.
You'll receive a response with the quote details. The pathId
response field will be necessary for assembling your transactions in the next step. Paths are valid for 60 seconds after the quote is received, after which a new quote will have to be requested.
Step 2: Assemble the Transaction
In order to execute an Odos quote on chain, the transaction must be assembled. The Odos API will completely assemble the transaction for you, manual assembly is discouraged and not supported. Once you have the pathId
from the quote, you can send a POST
request to the /sor/assemble
endpoint to get the on-chain transaction data.
- Python
- JavaScript
assemble_url = "https://api.odos.xyz/sor/assemble"
assemble_request_body = {
"userAddr": "0x...", # the checksummed address used to generate the quote
"pathId": quote["pathId"], # Replace with the pathId from quote response in step 1
"simulate": False, # this can be set to true if the user isn't doing their own estimate gas call for the transaction
}
response = requests.post(
assemble_url,
headers={"Content-Type": "application/json"},
json=assemble_request_body
)
if response.status_code == 200:
assembled_transaction = response.json()
# handle Transaction Assembly response data
else:
print(f"Error in Transaction Assembly: {response.json()}")
# handle Transaction Assembly failure cases
const assembleUrl = 'https://api.odos.xyz/sor/assemble';
const assembleRequestBody = {
userAddr: '0x...', // the checksummed address used to generate the quote
pathId: quote.pathId, // Replace with the pathId from quote response in step 1
simulate: true, // this can be set to true if the user isn't doing their own estimate gas call for the transaction
};
const response = await fetch(
assembleUrl,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(assembleRequestBody),
});
if (response.status === 200) {
const assembledTransaction = await response.json();
// handle Transaction Assembly response data
} else {
console.error('Error in Transaction Assembly:', response);
// handle quote failure cases
}
Replace the placeholder values in the request body with actual values. The userAddr
should be the checksummed address of the user who requested the quote and will be executing the transaction.
The response will contain all of the necessary parameters for transaction execution in the transaction
field which can be used to sign and execute the swap on-chain.
Step 3: Execute the Transaction
Once you have the transaction details from the /sor/assemble
response, you can use the transaction
object to sign and send directly with an EOA wallet or conduct a low level call from a smart contract with the transaction.data
field. Reminder that modifying transaction.data
or assembling any Odos router function call from scratch is not officially supported and 100% at your own risk.
Recommended Web3 libraries (examples below):
- Python: web3py (Requires installation from here)
- Javascript: web3.js (Requires installation from here)
- Python
- JavaScript
from web3 import Web3
# 1. create web3 provider
w3 = Web3(Web3.HTTPProvider("node http endpoint for your network"))
# 2. Extract transaction object from assemble API response
transaction = assembled_transaction["transaction"]
# 3. Sign tx with a private key
pk = "Your EOA private key"
# web3py requires the value to be an integer
transaction["value"] = int(transaction["value"])
signed_tx = w3.eth.account.sign_transaction(transaction, pk)
# 4. Send the signed transaction
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
const Web3 = require('web3');
// 1. create web3 provider
const web3 = new Web3('node http endpoint for your network or wallet provider');
// 2. Extract transaction object from assemble API response
const transaction = assembledTransaction.transaction;
let txHash;
// 3a. Sign transaction with a web3 provider / wallet
txHash = await web3.eth.accounts.signTransaction(transaction);
// 3b. sign transaction with private key
const pk = 'Your EOA private key';
const signedTx = web3.eth.accounts.signTransaction(transaction, pk);
txHash = await web3.eth.send_raw_transaction(signedTx.rawTransaction);
If executing from another smart contract, the transaction.data
field of the transaction given in the response can be used in a low level call from another contract:
(bool success, bytes memory result) = router.call{value: $ethInput}(data)
Where $ethInput
is 0
unless the native coin of the network is an input, in which case the value should be set to the corresponding path input amount. Approvals for ERC20 inputs should be made to the router address prior to the call. The address of the router can be found in the to
field of the response, as well as from the /info/router/{version}/{chain_id}
endpoint.
Need Help?
- For a deeper dive, the API Endpoints page is your go-to resource, providing an extensive look at all available endpoints, parameters, and more.
- For technical assistance, visit our Support Page.
- Join the Odos Discord Community to connect with other developers and our team.