UNPKG

@orca-so/whirlpool-sdk

Version:

Whirlpool SDK for the Orca protocol.

153 lines (152 loc) 8.67 kB
"use strict"; 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.convertPositionDataToUserPositionData = void 0; const web3_js_1 = require("@solana/web3.js"); const tiny_invariant_1 = __importDefault(require("tiny-invariant")); const decimal_utils_1 = require("../utils/public/decimal-utils"); const address_1 = require("../utils/address"); const tick_util_1 = require("../utils/whirlpool/tick-util"); const collect_fees_1 = require("./quotes/collect-fees"); const collect_rewards_1 = require("./quotes/collect-rewards"); const whirlpool_client_sdk_1 = require("@orca-so/whirlpool-client-sdk"); const __1 = require(".."); function convertPositionDataToUserPositionData(dal, walletAddress, refresh) { var _a, _b, _c; return __awaiter(this, void 0, void 0, function* () { const positionAddresses = yield getUserPositions(dal, walletAddress, refresh); const result = {}; for (const address of positionAddresses) { const positionId = (0, address_1.toPubKey)(address).toBase58(); // if `refresh` is true, then these position/pools are already refreshed in line 20 // so there is no need to refresh on each individual position/pool call following const position = yield dal.getPosition(address, false); if (!position) { console.error(`error - position not found`); continue; } const whirlpool = yield dal.getPool(position.whirlpool, false); if (!whirlpool) { console.error(`error - whirlpool not found`); continue; } const [tickLowerAddress, tickUpperAddress] = tick_util_1.TickUtil.getLowerAndUpperTickArrayAddresses(position.tickLowerIndex, position.tickUpperIndex, whirlpool.tickSpacing, position.whirlpool, dal.programId); const tickArrayLower = yield dal.getTickArray(tickLowerAddress, false); const tickArrayUpper = yield dal.getTickArray(tickUpperAddress, false); if (!tickArrayLower || !tickArrayUpper) { console.error(`error - tick array not found`); continue; } const tickLower = tick_util_1.TickUtil.getTick(tickArrayLower, position.tickLowerIndex, whirlpool.tickSpacing); const tickUpper = tick_util_1.TickUtil.getTick(tickArrayUpper, position.tickUpperIndex, whirlpool.tickSpacing); const quoteParam = { whirlpool, position, tickLower, tickUpper }; const feesQuote = (0, collect_fees_1.getCollectFeesQuoteInternal)(quoteParam); const decimalsA = (_a = (yield dal.getMintInfo(whirlpool.tokenMintA, false))) === null || _a === void 0 ? void 0 : _a.decimals; const decimalsB = (_b = (yield dal.getMintInfo(whirlpool.tokenMintB, false))) === null || _b === void 0 ? void 0 : _b.decimals; if (decimalsA === undefined || decimalsB === undefined) { console.error(`error - decimals not found`); continue; } const decimalFeeOwedA = decimal_utils_1.DecimalUtil.fromU64(feesQuote.feeOwedA, decimalsA); const decimalFeeOwedB = decimal_utils_1.DecimalUtil.fromU64(feesQuote.feeOwedB, decimalsB); const rewardsQuote = (0, collect_rewards_1.getCollectRewardsQuoteInternal)(quoteParam); const rewards = []; for (const [index, { mint, vault }] of whirlpool.rewardInfos.entries()) { const amountOwed = rewardsQuote[index]; const decimals = !mint.equals(web3_js_1.PublicKey.default) && !vault.equals(web3_js_1.PublicKey.default) ? (_c = (yield dal.getMintInfo(mint, false))) === null || _c === void 0 ? void 0 : _c.decimals : undefined; const decimalAmountOwed = amountOwed && decimals ? decimal_utils_1.DecimalUtil.fromU64(amountOwed, decimals) : undefined; rewards.push({ mint, amountOwed, decimalAmountOwed, }); } result[positionId] = { address: (0, address_1.toPubKey)(address), poolAddress: position.whirlpool, positionMint: position.positionMint, liquidity: position.liquidity, tickLowerIndex: position.tickLowerIndex, tickUpperIndex: position.tickUpperIndex, feeOwedA: feesQuote.feeOwedA, feeOwedB: feesQuote.feeOwedB, rewards, // Derived helper fields priceLower: (0, __1.tickIndexToPrice)(position.tickLowerIndex, decimalsA, decimalsB), priceUpper: (0, __1.tickIndexToPrice)(position.tickUpperIndex, decimalsA, decimalsB), decimalFeeOwedA, decimalFeeOwedB, }; } return result; }); } exports.convertPositionDataToUserPositionData = convertPositionDataToUserPositionData; function getUserPositions(dal, walletAddress, refresh) { return __awaiter(this, void 0, void 0, function* () { const potentialPositionAddresses = []; const userTokens = yield dal.listUserTokens(walletAddress, refresh); userTokens.forEach(({ amount, decimals, mint }) => { if (amount === "1" && decimals === 0 && !!mint) { potentialPositionAddresses.push((0, whirlpool_client_sdk_1.getPositionPda)(dal.programId, (0, address_1.toPubKey)(mint)).publicKey); } }); const positions = yield dal.listPositions(potentialPositionAddresses, refresh); (0, tiny_invariant_1.default)(potentialPositionAddresses.length === positions.length, "not enough positions data"); if (refresh) { /*** Refresh pools ***/ const whirlpoolAddresses = new Set(); positions.forEach((position) => { if (position) { whirlpoolAddresses.add(position.whirlpool.toBase58()); } }); const pools = yield dal.listPools(Array.from(whirlpoolAddresses), refresh); /*** Refresh mint infos ***/ const allMintInfos = new Set(); pools.forEach((pool) => { if (pool) { allMintInfos.add(pool.tokenMintA.toBase58()); allMintInfos.add(pool.tokenMintB.toBase58()); pool.rewardInfos.forEach(({ mint, vault }) => { if (!mint.equals(web3_js_1.PublicKey.default) && !vault.equals(web3_js_1.PublicKey.default)) { allMintInfos.add(mint.toBase58()); } }); } }); /*** Refresh tick arrays ***/ const tickArrayAddresses = new Set(); for (const position of positions) { if (position) { const whirlpool = yield dal.getPool(position.whirlpool, false); if (whirlpool) { const [tickLowerAddress, tickUpperAddress] = tick_util_1.TickUtil.getLowerAndUpperTickArrayAddresses(position.tickLowerIndex, position.tickUpperIndex, whirlpool.tickSpacing, position.whirlpool, dal.programId); tickArrayAddresses.add(tickLowerAddress.toBase58()); tickArrayAddresses.add(tickUpperAddress.toBase58()); } } } yield Promise.all([ dal.listMintInfos(Array.from(allMintInfos), false), dal.listTickArrays(Array.from(tickArrayAddresses), true), ]); } return potentialPositionAddresses.filter((_, index) => { return positions[index] !== null; }); }); }