@orca-so/whirlpool-sdk
Version:
Whirlpool SDK for the Orca protocol.
153 lines (152 loc) • 8.67 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.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;
});
});
}
;