Performing Swaps
Before we begin, you should have an understanding of what ticks are and how they are stored. If not, you can reference this page.
Trade with WhirlpoolClient
You can use the swap quote and WhirlpoolClient to easily perform a trade.
Learn more about amountSpecifiedIsInput
, aToB
in the section below.
Generating a swap quote by input or output token
Generate quote with one of the quote functions:
swapQuoteByInputToken if you want an estimate on the amount of outputToken received on an amount of inputToken.
swapQuoteByOutputToken if you want an estimate on the amount of inputToken needed to receive a set amount of outputToken.
The resulting SwapQuote object contains the estimations on the expected amount of tokenIn, tokenOut, fees, projected ending sqrtPrice. When you are ready, plug the quote object directly into the swapIx to perform the trade.
Adding a developer fee to the swap
The SDK provides an alternate quote & swap function to let developers take a fee as a percentage of the input asset. This feature is a convenient way to calculate the percentage, build a transfer instruction for the fee, and use the remaining input asset in a swap instruction.
Note: The developer fee transfer is performed by the SPL Token program or System program, and not the Whirlpools program.
Best practice is to pre-create Associated Token Accounts (ATA) for each token type which will be sent to the developer wallet. Also, if the fee will be payed in SOL, make sure that the developer wallet has at least 0.001 SOL to ensure that the wallet account will meet rent exemption.
The Manual Way
Manually constructing your own parameters gives you more flexibility in defining the boundaries of your trade.
Trade Parameters
The swap instruction requires the following input (and other common accounts) to execute the trade.
Decide the trade direction with
aToB
If true, you are trading from token A to B
If false, you are trading from token B to A
Decide the token you would like to cap with
amountSpecifiedIsInput
If true,
amount
is the value representing the token being traded from. This amount is subject to trade fees before the trade calculation.If false,
amount
is the value representing the token being traded to. This amount is the required token out amount from a trade after fees.
Decide whether you want to cap the other token of the trade using
otherAmountThreshold
If
amountSpecifiedIsInput
is true, this amount represents the minimum amount of output token expected from this trade. If you do not want to cap, use 0.If
amountSpecifiedIsInput
is false, this amount represents the maximum amount of input token that can be used to trade to an expectedamount
of the output token. If you do not want to cap, use the maximum amount of tokens in your wallet.
Decide the price limit that you would like to cap this trade to with
sqrtPriceLimit
.If
aToB
is true, the trade will push the price lower. This amount is minimum sqrt-price that the trade will trade to if input token amount is sufficient.If
aToB
is false, the trade will push the price higher. This amount is the maximum sqrt-price that the trade will trade to if the the input token amount is sufficient.If you don't have a cap and want to trade as much as you've defined with
amount
andotherAmountThreshold
, use the minimum price of your tick-array range forbToA
and maximum price of your tick-range foraToB
. If you don't mind hitting tick-array errors or you know your swap won't move the price too much, you can use MIN_SQRT_PRICE or MAX_SQRT_PRICE.sqrt-price is a x64 number. So your number would need to multiplied by 2^64. Use PriceMath utils here to help you do the conversion.
amount
andotherAmountThreshold
are u64 numbers. So make sure you shift your expected token numbers by the token's decimal.
Tick Arrays
The tick-array parameters are a sequence of tick-arrays that your swap may traverse through. tickArray0
will always be the PublicKey of the TickArray that houses the current tick-index.
In almost all cases, you can use the SwapUtils.getTickArrays to generate the sequence of tick-arrays that you need.
If you opt for building it yourself and you know that your swap is small enough that it's unlikely to traverse through an array, simply provide the same tickArray0
account for all 3 accounts. Once you have the sequence of tick-array public keys, you can use the AccountFetcher to check that the tick-arrays are initialized.
To learn more about tick-arrays and how its traversal works, read here.
Common usage examples
Assume all tokens below have a decimal of 6
Trading 100 token A for some amount of token B.
otherAmountThreshold
- 0,sqrt_price_limit
- MIN_SQRT_PRICE
Trading a max amount of 50 token B for 100 token A
otherAmountThreshold
- 50,sqrt_price_limit
- MAX_SQRT_PRICE
Trade whatever amount needed to move the price from current sqrt-price 50_x64 to sqrt_price 250_x64
aToB
- false,amount
- max amount in your wallet,amountSpecifiedIsInput
- trueotherAmountThreshold
- 0,sqrt_price_limit
- 250_x64
Sample Code
Note: Price Oracle has to be provided but it's not being used at the moment.
Compute Budget Limitation
The swap
instruction can be the most computational expensive operation, depending on how big of a price impact the swap. When you are operating in a low liquidity pool with a lot of gaps, this may be an issue that you would have to consider. If you cannot complete your swap under the current compute budget, you will have to split up your trade across multiple transactions.
Baseline compute budget for
swap
is around 70k.The maximum amount of swap loop iterations that can fit in the current maximum budget of 200k is around 10 loops.
The amount of price impact a single swap can make is based on a couple of factors:
The spacing of the initialized ticks. If a lot of positions have been initialized such that all initializable ticks in the sequence are all initialized, the more iterations is needed to cross the price range.
The tick spacing of the pool. The larger the tick spacing, the larger the price difference is between initializable ticks, the larger the price jump is on every swap iteration.
Common Errors
ZeroTradableAmount
(0x1793) - User provided parameteramount
is 0.InvalidSqrtPriceLimitDirection
(0x1792) - User provided parametersqrt_price_limit
does not match the direction of the trade.SqrtPriceOutOfBounds
(0x177b) - User provided parametersqrt_price_limit
is not between the bounds of [ MIN_SQRT_PRICE, MAX_SQRT_PRICE]InvalidTickArraySequence
(0x1787) - The swap traversal has landed on a tick-array that is out of sequence or uninitialized. Double check the tick-array sequence that is being passed in.TickArrayIndexOutofBounds
(0x1773) - The swap loop attempted to access an invalid array index during tick crossing.LiquidityOverflow
(0x177e)- Liquidity value overflowed 128bits during tick crossing.InvalidTickSpacing
(0x1774) - The swap pool was initialized with tick-spacing of 0.
Last updated