Open FezBox opened 2 months ago
@FezBox
- Instructions for programmatically querying routes and prices
- Instructions for programmatically querying a pool and submitting transactions to it
I don't think this is a matter of documenting as of now. This functionality is not accessible outside of Balanced frontend app context. It needs to be extracted to a standalone package or a backend service, which is not a trivial task.
Hey @hetfly , @FidelVe was able to write about programmatically querying prices and pools here https://docs.balanced.network/dex-aggregator.
To my understanding, the rest is possible too from calling the DEX contract or some endpoint. Otherwise I'm not sure I see how the frontend would be able to do it either.
the execution of a swap is initiated by a contract call on the ICON chain, what we want to know is how to create the payload of that call and explain the steps, basically what information do we need to be able to create the transaction calls that initiates the swap.
here are a couple of examples:
The following is a swap between sICX and bnUSD: https://tracker.icon.community/transaction/0xe360d39a6daa7d7228de00e8616a783d289bafe87ca7b509315a42dbbf45f899
The amount of sICX sent for the swap was 1723.9820658217857
( in hex "0x5d750eaad103a369d9")
the transaction called the transfer
method of the sICX token smart contract, with the following payload
{
"method": "transfer",
"params": {
"_data": "0x7b226d6574686f64223a225f73776170222c22706172616d73223a7b22746f546f6b656e223a22637838386664376466376464666638326637636337333563383731646335313938333863623233356262222c226d696e696d756d52656365697665223a22333038353236353631383738363534383137323436222c2270617468223a5b22637838386664376466376464666638326637636337333563383731646335313938333863623233356262225d2c227265636569766572223a22687830653034306438646637656664353738343239396566333438366237313838313738623461386337227d7d",
"_to": "cx21e94c08c03daee80c25d8ee3ea22a20786ec231",
"_value": "0x5d750eaad103a369d9"
}
}
the receiver was the contract cx21e94c08c03daee80c25d8ee3ea22a20786ec231 which is the balance router contract.
decoding the _data
field we get the following:
{
"method": "_swap",
"params": {
"toToken": "cx88fd7df7ddff82f7cc735c871dc519838cb235bb",
"minimumReceive": "308526561878654817246",
"path": [
"cx88fd7df7ddff82f7cc735c871dc519838cb235bb"
],
"receiver": "hx0e040d8df7efd5784299ef3486b7188178b4a8c7"
}
}
For this case it seems pretty straightforward, the steps to initiate a swap between sICX and bnUSD are:
in the _data
field send a hex string representation of a json object with the following shape
"method": "_swap",
"params": {
"toToken": "cx88fd7df7ddff82f7cc735c871dc519838cb235bb", # bnUSD token contract address
"minimumReceive": "308526561878654817246", #How do we calculate this value?
"path": [
"cx88fd7df7ddff82f7cc735c871dc519838cb235bb" # This is the same contract address for the bnUSD token
],
"receiver": "hx0e040d8df7efd5784299ef3486b7188178b4a8c7" # the receiver
}
}
It looks simple enough, the only thing I dont know yet is how to calculate the minimuReceive
value
The following is a swap from ICX to bnUSD for an amount of 480 ICX https://tracker.icon.community/transaction/0x41faf6b36cf8ab2dc9c580c8f3fa708dc8a38f6e2fbc9232debeaf77bc759650
In this case what is being called is the method routeV2
of the balanced router contract (cx21e94c08c03daee80c25d8ee3ea22a20786ec231
)
The JSON RPC payload is the following:
{
"method": "routeV2",
"params": {
"_minReceive": "0x36a2512d49f1fad7c",
"_path": "f0d70195012609b924e33ef00b648a409245c7ea394c467824d701950188fd7df7ddff82f7cc735c871dc519838cb235bb",
"_receiver": "hx9fa9d224306b0722099d30471b3c2306421aead7"
}
}
the _receiver
is the same wallet that initiated the transaction (since is a swap the sender sends ICX and receives bnUSD) the _minReceive
I still dont know how to calculate and the _path
field is a complete mystery to me, the only thing I was able to piece together is that is was encoded using RLP and this is the decoded string
[
[ '01', '012609b924e33ef00b648a409245c7ea394c467824' ],
[ '01', '0188fd7df7ddff82f7cc735c871dc519838cb235bb' ]
]
How do we create the values in this RLP encoded hex string?
We are working on growing Balanced, one part of that process is having well documented how to do all of these stuffs, even if we create a library that will make this easy to execute (which is something that we will have to eventually create) we still are going to be needing to have these things documented in detail somewhere
Hey @CyrusVorwald
To my understanding, the rest is possible too from calling the DEX contract or some endpoint.
Yeah, you're right of course. You can manually query the contracts from the frontend. What I meant is that we are missing an sdk / api abstraction accessible to others.
Hey @FidelVe thanks, I understand now. I'll try to answer some of those question later today.
These are accessible by anyone without any additional layers of abstraction. Please answer with how it is done currently, not considering additional abstraction.
@FidelVe I hope this helps. Feel free to DM me on the Discord with any additional questions.
Trade route contains token contracts through which the trade hops, ending on the last token contract, being the swap currency output. For trades ending in ICX, the trade route ends with null
item.
(*) Pair info is fetched from the DEX contract: getPoolStatsForPair
on cxa0af3165c08318e988cb30993b3048335b94af6c
Price and currency output amount are derived during the route selection, https://github.com/balancednetwork/v1-sdk/blob/main/src/entities/trade.ts#L86
Determining _minReceive
is just getting the currency output amount and applying user set slippage tolerance to it. Default slippage tolerance is set to half a percent.
Here is a function that encodes the swap data to RLP format https://github.com/balancednetwork/balanced-network-interface/blob/master/apps/web/src/lib/xcall/utils.ts#L27
With the route, minReceive and RLP encoding described above, you should have everything needed for ICON-ICON swaps.
For ICON-SPOKE swaps, only difference is adding _receiver
param with network address, so for arbitrum for example: 0xa4b1.arbitrum /0xE1598501d3ec2b0094eDc14487b01eB042919c2F
, which is networkID/address
or networkID/contract
List of network Ids:
'0x1.icon': icon,
'archway-1': archway,
'0xa4b1.arbitrum': arbitrum,
'0xa86a.avax': avalanche,
'0x100.icon': havah,
'0x38.bsc': bsc,
'0x2105.base': base,
'injective-1': injective
For SPOKE-ICON and SPOKE-SPOKE, its a bit more complicated, there are 3 different types.
Swapping:
depositNative
method on spoke Asset Manager contract (for ETH on arbitrum, AVAX on avalanche)deposit
method on spoke Asset Manager contract (for ETH on BNB chain, sARCH on Archway)crossTransfer
method on token contract address (currently only for bnUSD, will be the case for sICX and BALN, as well)For EVM chains, here is a code for initiating the swap transaction https://github.com/balancednetwork/balanced-network-interface/blob/master/apps/web/src/xwagmi/xchains/evm/EvmXWalletClient.ts#L56
Only difference between SPOKE-ICON and SPOKE-SPOKE is again the receiver network address.
Note that swaps ending or starting on a SPOKE chain consists of multiple xCall transactions, user however must sign only the initial transaction, the rest is executed automatically by the Balanced contracts.
@FidelVe I hope this helps. Feel free to DM me on the Discord with any additional questions.
Determining the trade route
Trade route contains token contracts through which the trade hops, ending on the last token contract, being the swap currency output. For trades ending in ICX, the trade route ends with
null
item.1. Get all common pairs(*) for currncyIn and currencyOut https://github.com/balancednetwork/balanced-network-interface/blob/master/apps/web/src/store/swap/trade.ts#L13 2. Determine the best swap route using the common pairs (the best swap route gives the highest output currency amount) https://github.com/balancednetwork/balanced-network-interface/blob/master/apps/web/src/store/swap/trade.ts#L54
(*) Pair info is fetched from the DEX contract:
getPoolStatsForPair
oncxa0af3165c08318e988cb30993b3048335b94af6c
Determining price and _minReceive
Price and currency output amount are derived during the route selection, https://github.com/balancednetwork/v1-sdk/blob/main/src/entities/trade.ts#L86
Determining
_minReceive
is just getting the currency output amount and applying user set slippage tolerance to it. Default slippage tolerance is set to half a percent.Getting RLP encoded data
Here is a function that encodes the swap data to RLP format https://github.com/balancednetwork/balanced-network-interface/blob/master/apps/web/src/lib/xcall/utils.ts#L27
With the route, minReceive and RLP encoding described above, you should have everything needed for ICON-ICON swaps.
For ICON-SPOKE swaps, only difference is adding
_receiver
param with network address, so for arbitrum for example:0xa4b1.arbitrum /0xE1598501d3ec2b0094eDc14487b01eB042919c2F
, which isnetworkID/address
ornetworkID/contract
List of network Ids:
'0x1.icon': icon, 'archway-1': archway, '0xa4b1.arbitrum': arbitrum, '0xa86a.avax': avalanche, '0x100.icon': havah, '0x38.bsc': bsc, '0x2105.base': base, 'injective-1': injective
For SPOKE-ICON and SPOKE-SPOKE, its a bit more complicated, there are 3 different types.
Swapping:
1. native asset - `depositNative` method on spoke Asset Manager contract (for ETH on arbitrum, AVAX on avalanche) 2. assetManager asset - `deposit` method on spoke Asset Manager contract (for ETH on BNB chain, sARCH on Archway) 3. crosschain token - `crossTransfer` method on token contract address (currently only for bnUSD, will be the case for sICX and BALN, as well)
For EVM chains, here is a code for initiating the swap transaction https://github.com/balancednetwork/balanced-network-interface/blob/master/apps/web/src/xwagmi/xchains/evm/EvmXWalletClient.ts#L56
Only difference between SPOKE-ICON and SPOKE-SPOKE is again the receiver network address.
Note that swaps ending or starting on a SPOKE chain consists of multiple xCall transactions, user however must sign only the initial transaction, the rest is executed automatically by the Balanced contracts.
thanks for the reply, ill work on a draft document detailing these trade executions, ill let you know if I need any extra info.
Here is a function that encodes the swap data to RLP format https://github.com/balancednetwork/balanced-network-interface/blob/master/apps/web/src/lib/xcall/utils.ts#L27
@hetfly this link is broken, please share again the correct link to the RLP function for the swaps
For ICON-SPOKE swaps, only difference is adding
_receiver
param with network address, so for arbitrum for example:0xa4b1.arbitrum /0xE1598501d3ec2b0094eDc14487b01eB042919c2F
, which isnetworkID/address
ornetworkID/contract
List of network Ids:
'0x1.icon': icon, 'archway-1': archway, '0xa4b1.arbitrum': arbitrum, '0xa86a.avax': avalanche, '0x100.icon': havah, '0x38.bsc': bsc, '0x2105.base': base, 'injective-1': injective
where can I find the list of networks ids for testnet?
@hetfly @AntonAndell
Im getting a bit confused with the subject of making a token to token swap on ICON, more specifically on how to properly format the data that is encoded and being sent to the smart contract.
Take for example the case of swapping bnusd to baln token, it would be something like this:
transfer
method of the bnusd contract{
"method": "transfer",
"params": {
"_data": CUSTOM_ENCODED_MSG_FOR_THE_ROUTER_CONTRACT,
"_to": ADDRESS_OF_THE_ROUTER_CONTRACT,
"_value": AMOUNT_TO_SENT
}
}
I want to know how to properly encode the information in the _data
field, I have found 2 different transactions where the data is encoded in different ways:
payload:
{
"method": "transfer",
"params": {
"_data": "f852855f73776170aa687834303663653637653462326430396537313465616634383232346632653062613439653134666263880c0c78540bfeda96d7019501f61cd5a45dc9f91c15aa65831a30a90d59a09619",
"_to": "cx21e94c08c03daee80c25d8ee3ea22a20786ec231",
"_value": "0x351da03b95eb6b4"
}
}
Decoded _data
using RLP:
[
'_swap',
'hx406ce67e4b2d09e714eaf48224f2e0ba49e14fbc',
'0c0c78540bfeda96',
[ 1, 'cxf61cd5a45dc9f91c15aa65831a30a90d59a09619' ]
]
Payload:
{
"method": "transfer",
"params": {
"_data": "0x7b226d6574686f64223a225f73776170222c22706172616d73223a7b22746f546f6b656e223a22637863336335353230353462613638323331303762353630383631333463326166633236616231646661222c226d696e696d756d52656365697665223a22343237373330343635353930323232393035313231222c2270617468223a5b22637863336335353230353462613638323331303762353630383631333463326166633236616231646661225d7d7d",
"_to": "cx2576925d931f3be8ff195914c10a87da2094c5e5",
"_value": "0x3635c9adc5dea00000"
}
}
Decoded data using IconConverter.toUtf8():
{
method: '_swap',
params: {
toToken: 'cxc3c552054ba6823107b56086134c2afc26ab1dfa',
minimumReceive: '427730465590222905121',
path: [ 'cxc3c552054ba6823107b56086134c2afc26ab1dfa' ]
}
}
Which of these 2 is the one i should be documenting in the docs or it doesnt matter which one?
we need to get updated documentation for use to get on aggregator services. A lot of what we need is inside your brains hehe
can we please document all the the below asap please The following is information relevant to dex aggregators that is being added to a new page called “DEX Aggregator Integration” on docs.balanced.network
FAQ
POST requests are submitted to source chain and propagated to the destination chain thru ICON chain.
GET requests are submitted to ICON chain. ICON integration is useful for swapping native ICON assets but not necessary beyond that.
also a few more things
can you please look at this form and document everything we need in this link that we know https://forms.fillout.com/t/xrsvjHm85Hus