UNPKG

blub-sdk

Version:

A modular SDK for interacting with the BLUB ecosystem on the Sui blockchain.

169 lines (168 loc) 6.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports._queryUserPositionIds = _queryUserPositionIds; exports._getPositions = _getPositions; exports.parseUserPosition = parseUserPosition; exports._getUserTotalStaked = _getUserTotalStaked; exports._calculatePendingReward = _calculatePendingReward; exports.queryRewardManager = queryRewardManager; exports.queryRewardInfo = queryRewardInfo; /* eslint-disable @typescript-eslint/no-explicit-any */ // src/queries/stakingRepository.ts const transactions_1 = require("@mysten/sui/transactions"); const StakingBuilder_1 = require("../../builder/StakingBuilder"); const sui_1 = require("../../utils/sui"); const client_1 = require("../../utils/client"); /** * Fetches all stake position IDs registered for the given user. */ async function _queryUserPositionIds(client, userPositionRecordId, wallet) { const resq = await client.getDynamicFieldObject({ parentId: userPositionRecordId, name: { type: "address", value: wallet, }, }); const fields = (0, sui_1.getObjectFields)(resq); if (!fields) { throw new Error("fields is null"); } const tableId = fields.value.fields.id.id; const positionFields = await client.getDynamicFields({ parentId: tableId }); return positionFields.data.map((item) => item.name.value); } /** * Fetches and parses all stake positions for the given IDs. */ async function _getPositions(positionIds, client = client_1.defaultSuiClient) { // const resq = await client.multiGetObjects({ ids: positionIds, options: { showContent: true }, }); const positions = []; for (const item of resq) { const fields = (0, sui_1.getObjectFields)(item); if (!fields) { throw new Error("fields is null"); } const position = await parseUserPosition(client, fields); positions.push(position); } return positions; } /** * Parses a single stake position object into a StakePosition structure. */ async function parseUserPosition(client, fields) { const waitingClaim = new Map(); const rewardDebt = new Map(); const waitClaimRewardTableId = fields.waiting_claim_reward.fields.id.id; const waitClaimRewardFields = await client.getDynamicFields({ parentId: waitClaimRewardTableId, }); for (const item of waitClaimRewardFields.data) { const object = await client.getObject({ id: item.objectId, options: { showContent: true }, }); const f = (0, sui_1.getObjectFields)(object); if (!f) throw new Error("fields is null"); waitingClaim.set(f.name.fields.name, BigInt(f.value)); } const rewardDebtTableId = fields.reward_debt.fields.id.id; const rewardDebtFields = await client.getDynamicFields({ parentId: rewardDebtTableId, }); for (const item of rewardDebtFields.data) { const object = await client.getObject({ id: item.objectId, options: { showContent: true }, }); const f = (0, sui_1.getObjectFields)(object); if (!f) throw new Error("fields is null"); rewardDebt.set(f.name.fields.name, BigInt(f.value)); } return { id: fields.id.id, stakedAmount: BigInt(fields.staked_amount), rewardDebt, waitingClaimReward: waitingClaim, }; } /** * Calculates the total staked amount across all user positions. */ async function _getUserTotalStaked(client, userPositionRecordId, wallet) { const positionIds = await _queryUserPositionIds(client, userPositionRecordId, wallet); if (!positionIds || positionIds.length === 0) return BigInt(0); const positions = await _getPositions(positionIds); if (!positions || positions.length === 0) return BigInt(0); return positions.reduce((total, p) => (p.stakedAmount > BigInt(0) ? total + p.stakedAmount : total), BigInt(0)); } /** * Simulates a reward calculation for a position using `devInspectTransactionBlock`, * without executing a real on-chain transaction. */ async function _calculatePendingReward(owner, { position, coinType }, packageId, client = client_1.defaultSuiClient) { const builder = new StakingBuilder_1.StakingBuilder(); const txb = builder.calculatePendingReward({ position, coinType }, new transactions_1.Transaction()); const inspection = await client.devInspectTransactionBlock({ transactionBlock: txb, sender: owner, }); const events = inspection.events ?? []; const pending = []; for (const e of events) { if (e.type === `${packageId}::events::CalculatePendingRewardEvent`) { const dat = e.parsedJson.reward_info; pending.push({ coinType: dat.coin_type.name, pendingReward: BigInt(dat.pending_reward_amount), }); } } return pending; } async function queryRewardManager(client, rewardManagerId) { const resq = await client.getObject({ id: rewardManagerId, options: { showContent: true }, }); const fields = (0, sui_1.getObjectFields)(resq); if (!fields) throw new Error("fields is null"); const rewardsInfos = new Map(); const contents = fields.rewards_infos?.fields?.contents ?? []; contents.forEach((item) => { const rewardCoinType = (0, sui_1.completionCoin)(item.fields.key.fields.name); const rewardInfo = parseRewardInfo(item.fields.value.fields); rewardsInfos.set(rewardCoinType, rewardInfo); }); return { id: rewardManagerId, totalStakedAmount: BigInt(fields.total_staked_amount), rewardsInfos, userPositionsRecordId: fields.user_positions_record.fields.id.id, }; } function parseRewardInfo(fields) { const rewardInfo = { rewardCoinType: (0, sui_1.completionCoin)(fields.reward_coin_type.fields.name), accRewardPerShare: BigInt(fields.acc_reward_per_share), lastRewardTime: BigInt(fields.last_reward_time), }; return rewardInfo; } async function queryRewardInfo(client, rewardManagerId, rewardCoinType) { const rewardManager = await queryRewardManager(client, rewardManagerId); if (!rewardManager) { return null; } return rewardManager.rewardsInfos.get((0, sui_1.completionCoin)(rewardCoinType)) ?? null; }