@renec-foundation/redex-sdk
Version:
Typescript SDK to interact with Orca's Whirlpool program.
165 lines (164 loc) • 8.79 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SwapUtils = void 0;
const common_sdk_1 = require("@orca-so/common-sdk");
const bn_js_1 = __importDefault(require("bn.js"));
const public_1 = require("../../types/public");
const token_math_1 = require("../math/token-math");
const pda_utils_1 = require("./pda-utils");
const pool_utils_1 = require("./pool-utils");
const tick_utils_1 = require("./tick-utils");
const types_1 = require("./types");
/**
* @category Whirlpool Utils
*/
class SwapUtils {
/**
* Get the default values for the sqrtPriceLimit parameter in a swap.
* @param aToB - The direction of a swap
* @returns The default values for the sqrtPriceLimit parameter in a swap.
*/
static getDefaultSqrtPriceLimit(aToB) {
return new bn_js_1.default(aToB ? public_1.MIN_SQRT_PRICE : public_1.MAX_SQRT_PRICE);
}
/**
* Get the default values for the otherAmountThreshold parameter in a swap.
* @param amountSpecifiedIsInput - The direction of a swap
* @returns The default values for the otherAmountThreshold parameter in a swap.
*/
static getDefaultOtherAmountThreshold(amountSpecifiedIsInput) {
return amountSpecifiedIsInput ? common_sdk_1.ZERO : common_sdk_1.U64_MAX;
}
/**
* Given the intended token mint to swap, return the swap direction of a swap for a Whirlpool
* @param pool The Whirlpool to evaluate the mint against
* @param swapTokenMint The token mint PublicKey the user bases their swap against
* @param swapTokenIsInput Whether the swap token is the input token. (similar to amountSpecifiedIsInput from swap Ix)
* @returns The direction of the swap given the swapTokenMint. undefined if the token mint is not part of the trade pair of the pool.
*/
static getSwapDirection(pool, swapTokenMint, swapTokenIsInput) {
const tokenType = pool_utils_1.PoolUtil.getTokenType(pool, swapTokenMint);
if (!tokenType) {
return undefined;
}
return (tokenType === types_1.TokenType.TokenA) === swapTokenIsInput
? types_1.SwapDirection.AtoB
: types_1.SwapDirection.BtoA;
}
/**
* Given the current tick-index, returns the dervied PDA and fetched data
* for the tick-arrays that this swap may traverse across.
*
* @category Whirlpool Utils
* @param tickCurrentIndex - The current tickIndex for the Whirlpool to swap on.
* @param tickSpacing - The tickSpacing for the Whirlpool.
* @param aToB - The direction of the trade.
* @param programId - The Whirlpool programId which the Whirlpool lives on.
* @param whirlpoolAddress - PublicKey of the whirlpool to swap on.
* @returns An array of PublicKey[] for the tickArray accounts that this swap may traverse across.
*/
static getTickArrayPublicKeys(tickCurrentIndex, tickSpacing, aToB, programId, whirlpoolAddress) {
const shift = aToB ? 0 : tickSpacing;
let offset = 0;
let tickArrayAddresses = [];
for (let i = 0; i < public_1.MAX_SWAP_TICK_ARRAYS; i++) {
let startIndex;
try {
startIndex = tick_utils_1.TickUtil.getStartTickIndex(tickCurrentIndex + shift, tickSpacing, offset);
}
catch (_a) {
return tickArrayAddresses;
}
const pda = pda_utils_1.PDAUtil.getTickArray(programId, whirlpoolAddress, startIndex);
tickArrayAddresses.push(pda.publicKey);
offset = aToB ? offset - 1 : offset + 1;
}
return tickArrayAddresses;
}
/**
* Given the current tick-index, returns TickArray objects that this swap may traverse across.
*
* @category Whirlpool Utils
* @param tickCurrentIndex - The current tickIndex for the Whirlpool to swap on.
* @param tickSpacing - The tickSpacing for the Whirlpool.
* @param aToB - The direction of the trade.
* @param programId - The Whirlpool programId which the Whirlpool lives on.
* @param whirlpoolAddress - PublicKey of the whirlpool to swap on.
* @param fetcher - AccountFetcher object to fetch solana accounts
* @param refresh - If true, fetcher would default to fetching the latest accounts
* @returns An array of PublicKey[] for the tickArray accounts that this swap may traverse across.
*/
static getTickArrays(tickCurrentIndex, tickSpacing, aToB, programId, whirlpoolAddress, fetcher, refresh) {
return __awaiter(this, void 0, void 0, function* () {
const addresses = SwapUtils.getTickArrayPublicKeys(tickCurrentIndex, tickSpacing, aToB, programId, whirlpoolAddress);
const data = yield fetcher.listTickArrays(addresses, refresh);
return addresses.map((addr, index) => {
return {
address: addr,
data: data[index],
};
});
});
}
/**
* Calculate the SwapInput parameters `amount` & `otherAmountThreshold` based on the amountIn & amountOut estimates from a quote.
* @param amount - The amount of tokens the user wanted to swap from.
* @param estAmountIn - The estimated amount of input tokens expected in a `SwapQuote`
* @param estAmountOut - The estimated amount of output tokens expected from a `SwapQuote`
* @param slippageTolerance - The amount of slippage to adjust for.
* @param amountSpecifiedIsInput - Specifies the token the parameter `amount`represents in the swap quote. If true, the amount represents
* the input token of the swap.
* @returns A Partial `SwapInput` object containing the slippage adjusted 'amount' & 'otherAmountThreshold' parameters.
*/
static calculateSwapAmountsFromQuote(amount, estAmountIn, estAmountOut, slippageTolerance, amountSpecifiedIsInput) {
if (amountSpecifiedIsInput) {
return {
amount,
otherAmountThreshold: (0, token_math_1.adjustForSlippage)(estAmountOut, slippageTolerance, false),
};
}
else {
return {
amount,
otherAmountThreshold: (0, token_math_1.adjustForSlippage)(estAmountIn, slippageTolerance, true),
};
}
}
/**
* Convert a quote object and WhirlpoolClient's {@link Whirlpool} object into a {@link SwapParams} type
* to be plugged into {@link WhirlpoolIx.swapIx}.
*
* @param quote - A {@link SwapQuote} type generated from {@link swapQuoteWithParams}
* @param ctx - {@link WhirlpoolContext}
* @param whirlpool - A {@link Whirlpool} object from WhirlpoolClient
* @param inputTokenAssociatedAddress - The public key for the ATA of the input token in the swap
* @param outputTokenAssociatedAddress - The public key for the ATA of the input token in the swap
* @param wallet - The token authority for this swap
* @returns A converted {@link SwapParams} generated from the input
*/
static getSwapParamsFromQuote(quote, ctx, whirlpool, inputTokenAssociatedAddress, outputTokenAssociatedAddress, wallet) {
const addr = whirlpool.getAddress();
const data = whirlpool.getData();
const aToB = quote.aToB;
const [inputTokenATA, outputTokenATA] = common_sdk_1.AddressUtil.toPubKeys([
inputTokenAssociatedAddress,
outputTokenAssociatedAddress,
]);
const oraclePda = pda_utils_1.PDAUtil.getOracle(ctx.program.programId, addr);
const params = Object.assign({ whirlpool: whirlpool.getAddress(), tokenOwnerAccountA: aToB ? inputTokenATA : outputTokenATA, tokenOwnerAccountB: aToB ? outputTokenATA : inputTokenATA, tokenVaultA: data.tokenVaultA, tokenVaultB: data.tokenVaultB, oracle: oraclePda.publicKey, tokenAuthority: wallet }, quote);
return params;
}
}
exports.SwapUtils = SwapUtils;