Links
🔄

Step-by-step Swap Example

Routing API usage by example

Swap Avalanche (AAVE) for Avalanche (USDT)

This particular route (swap) consists of two transactions. However, the number of transactions required for swapping different coins and across different chains may vary and depend on several factors such as the source coin, the destination coin, and the number of available addresses for signing transactions.

Step 1

In this step, we prepare the data for the chains and assets that our routing system supports. This data enables us to display the source and destination tokens to users and query and display swap route in the next step.

1.1 Get list of supported chains

Query
Response
query ChainsV2 {
routingV2 {
chainsV2 {
name
}
}
}
{
"data": {
"routingV2": {
"chainsV2": [
{
"name": "BNB"
},
{
"name": "BTC"
},
{
"name": "BCH"
},
{
"name": "LTC"
},
{
"name": "ETH"
},
{
"name": "THOR"
},
{
"name": "DOGE"
},
{
"name": "BSC"
},
{
"name": "POLYGON"
},
{
"name": "FTM"
},
{
"name": "AVAX"
},
{
"name": "ARBITRUM"
},
{
"name": "AURORA"
},
{
"name": "NEAR"
},
{
"name": "SOL"
},
{
"name": "COSMOS"
},
{
"name": "OSMOSIS"
}
]
}
}
}

1.2 Get list of assets for supported chain

Query
Variables
Response
query ChainV2($name: String!) {
routingV2 {
chainV2(name: $name) {
name
tokens {
asset {
contract
symbol
}
}
}
}
}
{
"name": "AVAX"
}
{
"data": {
"routingV2": {
"chainV2": {
"name": "AVAX",
"tokens": [
...
{
"asset": {
"contract": "0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7",
"symbol": "USDT"
}
},
{
"asset": {
"contract": "0x63a72806098bd3d9520cc43356dd78afe5d386d9",
"symbol": "AAVE"
}
}
...
]
}
}
}
}

Step 2

Query swap route. This query returns a tradesRoute collection, along with other properties. Based on this data, we can show the user which providers we will use, the amount of fees in dollars and assets for each transaction, and thus calculate the total fees and approximate transaction time in seconds.
Query
Variables
Response
Snippets
query RouteV2($srcToken: String!, $destToken: String!, $slippage: String!, $addresses: [AddressRouteInputTypeV2!]!, $destAddress: String!, $amountSource: String, $infiniteApproval: Boolean) {
routingV2 {
routeV2(srcToken: $srcToken, destToken: $destToken, slippage: $slippage, addresses: $addresses, destAddress: $destAddress, amountSource: $amountSource, infiniteApproval: $infiniteApproval) {
addresses {
chain
address
}
destAddress
priceRate
priceRateText
slippage
priceImpact
amountIn
tradesRoute {
provider {
id
}
amountIn
amountOut
minAmountReceived
assetIn {
id
}
assetOut {
id
}
fee {
networkFeeDollar
networkFeeAsset
inboundFeeDollar
inboundFeeAsset
swapFee
feeRateTransaction
xdefiSwapFee
xdefiSwapFeeDollar
}
priceRateUsdAssetOut
priceRateUsdAssetIn
tradeType
}
gasPrices
approvalInfiniteFlag
errorBuildingRoute
}
}
}srcToken
  • chainName: This variable is obtained from step 1.1.
  • contract: This variable is obtained from step 1.2.
  • srcToken: This variable has the format ${chainName}.${contract} and represents the token to be swapped.
  • destToken: This variable also has the format ${chainName}.${contract} and represents the token to receive in exchange.
    • For native tokens, the format is ${chainName}.${nativeTokenName}. For example, Ethereum's native token is "ETH", so the format would be "ETH.ETH". For Polygon, it's "POLYGON.MATIC", and for Binance Smart Chain, it's "BSC.BNB".
  • slippage: This variable represents the percentage of slippage tolerance for the trade.
  • addresses: This variable is a collection of addresses available to sign transactions. For this swap, we only need one, as the trade takes place within the Avalanche chain.
  • destAddress: This variable represents the address that will receive the swapped Avalanche (USDT) upon completion of the trade.
  • amountSource: This variable represents the amount of Avalanche (AAVE) to be swapped.
  • infiniteApproval: Using this prop is not mandatory, but it allows users to avoid approving trades when swapping ERC20 tokens. However, it's important to note that the first approval still needs to be granted.
{
"srcToken": "AVAX.0x63a72806098bd3d9520cc43356dd78afe5d386d9",
"destToken": "AVAX.0xc7198437980c041c805a1edcba50c1ce5db95118",
"slippage": "1",
"addresses": [
{
"chain": "AVAX",
"address": "0x5329ebC5903bE1Ca544762191343F60EDb5C9Ca3"
},
],
"destAddress": "0x5329ebC5903bE1Ca544762191343F60EDb5C9Ca3",
"amountSource": "0.23",
"infiniteApproval": null
}
  • networkFeeDollar: Provider fee. 1Inch in example.
  • networkFeeAsset: Provider fee in asset value.
  • inboundFeeDollar: Network fee for transaction. Cost of Avalanche transaction.
  • inboundFeeAsset: Network fee for transaction in native token. AVAX in example.
{
"data": {
"routingV2": {
"routeV2": {
"addresses": [
{
"chain": "AVAX",
"address": "0x5329ebC5903bE1Ca544762191343F60EDb5C9Ca3"
}
],
"destAddress": "0x5329ebC5903bE1Ca544762191343F60EDb5C9Ca3",
"priceRate": "83.41570269977431352948063293",
"priceRateText": "1 AAVE = 83.415703 USDT",
"slippage": "1",
"priceImpact": "-1.71%",
"amountIn": "0.23",
"tradesRoute": [
{
"provider": {
"id": "87c6a323-45ef-4153-9d6c-143cb5b9e98b"
},
"amountIn": "0.23",
"amountOut": "0.23",
"minAmountReceived": "0.23",
"assetIn": {
"id": "4a4edfe5-1cdb-4142-b068-de4ee7e3a1d1"
},
"assetOut": {
"id": "4a4edfe5-1cdb-4142-b068-de4ee7e3a1d1"
},
"fee": {
"networkFeeDollar": "0",
"networkFeeAsset": "0",
"inboundFeeDollar": "0.03291354",
"inboundFeeAsset": "0.001782",
"swapFee": "0.03291354",
"feeRateTransaction": "29.7",
"xdefiSwapFee": "0",
"xdefiSwapFeeDollar": "0"
},
"priceRateUsdAssetOut": "83.36156590872216",
"priceRateUsdAssetIn": "83.36156590872216",
"tradeType": "APPROVAL"
},
{
"provider": {
"id": "87c6a323-45ef-4153-9d6c-143cb5b9e98b"
},
"amountIn": "0.23",
"amountOut": "18.857786",
"minAmountReceived": "18.66920814",
"assetIn": {
"id": "4a4edfe5-1cdb-4142-b068-de4ee7e3a1d1"
},
"assetOut": {
"id": "bead7daf-8652-43b8-8d85-676e385b1ec2"
},
"fee": {
"networkFeeDollar": "0",
"networkFeeAsset": "0",
"inboundFeeDollar": "0.26013688099740",
"inboundFeeAsset": "0.014084292420",
"swapFee": "0.26013688099740",
"feeRateTransaction": "29.7",
"xdefiSwapFee": "0",
"xdefiSwapFeeDollar": "0E-14"
},
"priceRateUsdAssetOut": "0.999351",
"priceRateUsdAssetIn": "83.36156590872216",
"tradeType": "SWAP"
}
],
"gasPrices": {},
"approvalInfiniteFlag": false,
"errorBuildingRoute": null
}
}
}
}
Enum describes all possible values for tradeType property from the response.
enum TradeType {
APPROVAL = 'APPROVAL',
BRIDGE = 'BRIDGE',
REDEEM = 'REDEEM',
SWAP = 'SWAP',
}

Step 3

The mutation creates a new route and generates a unique routeId, which is essential for the subsequent steps to retrieve trades (transactions) related to the current route (swap). The input for this mutation is of type RouteInputTypeV2, and all the necessary properties are obtained from the response of the previous query.
Mutation
Variables
Response
mutation TransactionsV2($routeData: RouteInputTypeV2!) {
transactionsV2(routeData: $routeData) {
routeId
}
}
{
"routeData": {
"addresses": [
{
"chain": "AVAX",
"address": "0x5329ebC5903bE1Ca544762191343F60EDb5C9Ca3"
}
],
"destAddress": "0x5329ebC5903bE1Ca544762191343F60EDb5C9Ca3",
"priceRate": "83.46324511888209790209790210",
"priceRateText": "1 AAVE = 83.463245 USDT",
"slippage": "1",
"priceImpact": "-1.76%",
"amountIn": "0.23",
"tradesRoute": [
{
"provider": {
"id": "87c6a323-45ef-4153-9d6c-143cb5b9e98b"
},
"amountIn": "0.23",
"amountOut": "0.23",
"minAmountReceived": "0.23",
"assetIn": {
"id": "4a4edfe5-1cdb-4142-b068-de4ee7e3a1d1"
},
"assetOut": {
"id": "4a4edfe5-1cdb-4142-b068-de4ee7e3a1d1"
},
"fee": {
"networkFeeDollar": "0",
"networkFeeAsset": "0",
"inboundFeeDollar": "0.03289572",
"inboundFeeAsset": "0.001782",
"swapFee": "0.03289572",
"feeRateTransaction": "29.7",
"xdefiSwapFee": "0",
"xdefiSwapFeeDollar": "0"
},
"priceRateUsdAssetOut": "83.54670836400098",
"priceRateUsdAssetIn": "83.54670836400098",
"tradeType": "APPROVAL"
},
{
"provider": {
"id": "87c6a323-45ef-4153-9d6c-143cb5b9e98b"
},
"amountIn": "0.23",
"amountOut": "18.857786",
"minAmountReceived": "18.66920814",
"assetIn": {
"id": "4a4edfe5-1cdb-4142-b068-de4ee7e3a1d1"
},
"assetOut": {
"id": "bead7daf-8652-43b8-8d85-676e385b1ec2"
},
"fee": {
"networkFeeDollar": "0",
"networkFeeAsset": "0",
"inboundFeeDollar": "0.25999603807320",
"inboundFeeAsset": "0.014084292420",
"swapFee": "0.25999603807320",
"feeRateTransaction": "29.7",
"xdefiSwapFee": "0",
"xdefiSwapFeeDollar": "0"
},
"priceRateUsdAssetOut": "1.001",
"priceRateUsdAssetIn": "83.54670836400098",
"tradeType": "SWAP"
}
],
"gasPrices": null,
"approvalInfiniteFlag": null,
"errorBuildingRoute": null
}
}
{
"data": {
"transactionsV2": {
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9"
}
}
}

Step 4

To retrieve trades associated with a particular routeId, which is obtained as a response from the previous step, execute the relevant query. Note that the response to this query will change in subsequent steps, and therefore, it's necessary to periodically poll this query to keep track of the transaction statuses.
Query
Variables
Response
query TradesV2($routeId: String!) {
routingV2 {
tradesV2(routeId: $routeId) {
transaction {
chain
amount
recipient
feeRate
txType
tradeId
routeId
gasPrice
data
unsignedStdTx
gasLimit
memo
actions
signerId
receiverId
}
routeId
status {
status
txHash
}
}
}
}
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9"
}
In this step, the query returns collections of two trades, both with null values for their status and txHash, as we haven't signed or broadcasted any transactions yet. The first transaction on the route can be signed and broadcasted. If a transaction property is not required by the current network, its value is set to null e.g. property unsignedStdTx for bitcoin like transactions. In the next step, the tradeId field in the transaction is required to update the trade and track the transaction status.
{
"data": {
"routingV2": {
"tradesV2": [
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"status": {
"status": null,
"txHash": null
},
"transaction": {
"chain": "AVAX",
"amount": "0",
"recipient": "0x63a72806098Bd3D9520cC43356dD78afe5D386D9",
"feeRate": "29150000000",
"txType": "approval",
"tradeId": "12900",
"gasPrice": "29150000000",
"data": "0x095ea7b30000000000000000000000001111111254fb6c44bac0bed2854e76f90643097d0000000000000000000000000000000000000000000000000323706866aa4000",
"unsignedStdTx": null,
"gasLimit": "80000",
"routeId": null,
"memo": null
}
},
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"status": {
"status": null,
"txHash": null
},
"transaction": null
}
]
}
}
}

Step 5

The process of signing, broadcasting, and updating the trade is repeated for each transaction in the trades obtained from the previous step.

5.1 Sign and broadcast transaction to the network.

On this stage, we have a transaction prepared as a response to the previous step's query (TradesV2). We need to sign this transaction and broadcast it in order to obtain its hash.
Transaction hash
0x7c1c1a08a9607768b8acde0ebd2cb4a3fa0126cb5020e3efef3e5e43307163f8

5.2 Update route trade by mutation that takes routeId, tradeId, transactionHash.

When we receive the broadcasted transaction hash, we update the trade by performing a mutation that allows us to track the transaction status and obtain the next transaction to sign.
Mutation
Variables
mutation TransactionHashV2($routeId: String!, $tradeId: String!, $transactionHash: String!) {
transactionHashV2(routeId: $routeId, tradeId: $tradeId, transactionHash: $transactionHash)
}
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"transactionHash": "0x7c1c1a08a9607768b8acde0ebd2cb4a3fa0126cb5020e3efef3e5e43307163f8",
"tradeId": "12900"
}

Step 6

Re query of trades (step 4) in this step returns different response.
Response
Snippets
The first trade now has a status of SUCCESS, indicating that the transaction has been confirmed, and the txHash has been assigned the value of the first signed transaction in step 5.2. Right after previous step the status of the transaction could be PENDING and transaction property gets null value. As for the second trade, it now has transaction data that needs to be signed, which we will do in the next step.
{
"data": {
"routingV2": {
"tradesV2": [
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"status": {
"status": "SUCCESS",
"txHash": "0x7c1c1a08a9607768b8acde0ebd2cb4a3fa0126cb5020e3efef3e5e43307163f8"
},
"transaction": null
},
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"status": {
"status": null,
"txHash": null
},
"transaction": {
"chain": "AVAX",
"amount": "0",
"recipient": "0x1111111254fb6c44bac0bed2854e76f90643097d",
"feeRate": "25000000001",
"txType": "SWAP",
"tradeId": "12902",
"gasPrice": "25000000001",
"data": "0x7c025200000000000000000000000000f01ef4051130cc8871fa0c17024a6d62e379e8560000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000018000000000000000000000000063a72806098bd3d9520cc43356dd78afe5d386d9000000000000000000000000c7198437980c041c805a1edcba50c1ce5db95118000000000000000000000000c3e6d9f7a3a5e3e223356383c7c055ee3f26a34f0000000000000000000000005329ebc5903be1ca544762191343f60edb5c9ca300000000000000000000000000000000000000000000000003311fc80a57000000000000000000000000000000000000000000000000000000000000010d0fca00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000f200a007e5c0d20000000000000000000000000000000000000000000000000000ce00006700206ae40711b8002dc6c0c3e6d9f7a3a5e3e223356383c7c055ee3f26a34f1f0bc5c91518d903c0c097bde9741746b44230080000000000000000000000000000000000000000000000000df489a8970d864b63a72806098bd3d9520cc43356dd78afe5d386d900206ae40711b8001e84801f0bc5c91518d903c0c097bde9741746b44230081111111254fb6c44bac0bed2854e76f90643097d00000000000000000000000000000000000000000000000000000000010d0fcab31f66aa3c1e785363f0875a1b74e27b85fd66c700000000000000000000000000000000000000000000000003311fc80a5700000000000000000000000000000000000014e67b34",
"unsignedStdTx": null,
"gasLimit": "265913",
"routeId": null,
"memo": null
}
}
]
}
}
}
Enum describes all possible values for status property from the response.
enum Status {
Successful = 'SUCCESS',
Pending = 'PENDING',
Revert = 'REVERT',
Idle = 'IDLE',
}

Step 7

7.1 Sign and broadcast transaction to the network.

Transaction hash
0xf305ff5b3031797a4404ac535ff90d4e974917f72449711ab9403d78a792b37d

7.2 Update route trade by mutation that takes routeId, tradeId, transactionHash.

The mutation is the same as in step 5.2 but with variables related two the second transaction.
Mutation
Variables
mutation TransactionHashV2($routeId: String!, $tradeId: String!, $transactionHash: String!) {
transactionHashV2(routeId: $routeId, tradeId: $tradeId, transactionHash: $transactionHash)
}
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"transactionHash": "0xf305ff5b3031797a4404ac535ff90d4e974917f72449711ab9403d78a792b37d",
"tradeId": "12902"
}

Step 8

Continuously query (step 4) until all trade statuses show as SUCCESS. Once all trades have a SUCCESS status, the current swap is considered complete and the amount of Avalanche (USDT) will be transferred to the destination address.
Response
{
"data": {
"routingV2": {
"tradesV2": [
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"status": {
"status": "SUCCESS",
"txHash": "0x7c1c1a08a9607768b8acde0ebd2cb4a3fa0126cb5020e3efef3e5e43307163f8"
},
"transaction": null
},
{
"routeId": "3923c390-ff4a-44b7-b9be-5dd84d538ab9",
"status": {
"status": "SUCCESS",
"txHash": "0xf305ff5b3031797a4404ac535ff90d4e974917f72449711ab9403d78a792b37d"
},
"transaction": null
}
]
}
}
}
XDEFI Technologies 2024