UNPKG

multipool-staking-sdk

Version:

This is an sdk for solmask staking pool program

251 lines 15.5 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.StakingService = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); const buffer_1 = require("buffer"); const anchor_1 = require("@project-serum/anchor"); const spl_token_1 = require("@solana/spl-token"); const web3_js_1 = require("@solana/web3.js"); const constants_1 = require("./constants"); const payload_1 = require("./payload"); const utils_1 = require("./utils"); class StakingService { static deriveLockupInfoAddress(lockerName, programId) { const _programId = new web3_js_1.PublicKey(programId); const [lockupAddress] = web3_js_1.PublicKey.findProgramAddressSync([ buffer_1.Buffer.from(anchor_1.utils.bytes.utf8.encode(constants_1.PROGRAM_SEEDS_PHRASES.LockupInfo)), buffer_1.Buffer.from(anchor_1.utils.bytes.utf8.encode(lockerName)), ], _programId); return lockupAddress; } static deriveStakeVaultAddress(lockupAddress, programId) { const _lockupAddress = new web3_js_1.PublicKey(lockupAddress); const _programId = new web3_js_1.PublicKey(programId); const [stakeVaultAddress] = web3_js_1.PublicKey.findProgramAddressSync([ buffer_1.Buffer.from(anchor_1.utils.bytes.utf8.encode(constants_1.PROGRAM_SEEDS_PHRASES.LockupVault)), _lockupAddress.toBuffer(), ], _programId); return stakeVaultAddress; } static deriveStakeInfoAddress(lockupAddress, stakerAddress, programId) { const _lockupAddress = new web3_js_1.PublicKey(lockupAddress); const _stakerAddress = new web3_js_1.PublicKey(stakerAddress); const _programId = new web3_js_1.PublicKey(programId); const [stakeInfoAddress] = web3_js_1.PublicKey.findProgramAddressSync([_stakerAddress.toBuffer(), _lockupAddress.toBuffer()], _programId); return stakeInfoAddress; } constructor(instructions, _connection, _signTransaction) { this.instructions = instructions; this._connection = _connection; this._signTransaction = _signTransaction; this._programId = this.instructions.program.programId; this._programErrorMap = new Map(); for (const error of this.instructions.program.idl.errors) { this._programErrorMap.set(error.code, error.msg); } } _createPayload(tx, signers) { return new payload_1.TransactionPayload(this._connection, this._signTransaction, this._programErrorMap, tx, signers); } initLockup(params) { return __awaiter(this, void 0, void 0, function* () { const { creatorAddress, rewardTokenAddress, stakeTokenAddress } = params; const creator = new web3_js_1.PublicKey(creatorAddress); const rewardToken = new web3_js_1.PublicKey(rewardTokenAddress); const stakeToken = new web3_js_1.PublicKey(stakeTokenAddress); const lockup = StakingService.deriveLockupInfoAddress(params.name, this._programId); console.debug("lockup: %s", lockup.toString()); const stakeVault = StakingService.deriveStakeVaultAddress(lockup, this._programId); console.debug("stakeVault: %s", stakeVault.toString()); const stakeVaultRewardTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(rewardToken, stakeVault, true); const stakeVaultStakeTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(stakeToken, stakeVault, true); const rewardTokenDecimals = yield (0, utils_1.getDecimals)(this._connection, rewardToken); const totalAllocationReward = (0, bignumber_js_1.default)(params.totalAllocationReward) .times((0, bignumber_js_1.default)(10).pow(rewardTokenDecimals)) .toFixed(0); const ix = yield this.instructions.getInitLockupInstruction(creator, lockup, stakeVaultRewardTokenAccount, stakeVaultStakeTokenAccount, rewardToken, stakeToken, stakeVault, { totalAllocationReward: new anchor_1.BN(totalAllocationReward), lockTimespan: new anchor_1.BN(params.lockTimespan), name: params.name, stakingEndTime: new anchor_1.BN(params.stakingEndTime), stakingStartTime: new anchor_1.BN(params.stakingStartTime), }); const { blockhash, lastValidBlockHeight } = yield this._connection.getLatestBlockhash(); const tx = new web3_js_1.Transaction({ feePayer: creator, blockhash, lastValidBlockHeight, }).add(ix); return this._createPayload(tx, []); }); } stake(params) { return __awaiter(this, void 0, void 0, function* () { const { lockupAddress, stakeAmount, stakerAddress } = params; const lockup = new web3_js_1.PublicKey(lockupAddress); const decoded = yield this.instructions.program.account.lockupInfo.fetch(lockup); const stakeToken = decoded.stakedToken; const staker = new web3_js_1.PublicKey(stakerAddress); const stakeVault = StakingService.deriveStakeVaultAddress(lockup, this._programId); const stakeInfo = StakingService.deriveStakeInfoAddress(lockup, staker, this._programId); const stakerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(stakeToken, staker); const stakeVaultTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(stakeToken, stakeVault, true); const stakeTokenDecimals = yield (0, utils_1.getDecimals)(this._connection, stakeToken); const amount = (0, bignumber_js_1.default)(stakeAmount).times((0, bignumber_js_1.default)(10).pow(stakeTokenDecimals)).toFixed(0); const ix = yield this.instructions.getStakeInstruction(lockup, stakeInfo, staker, stakerTokenAccount, stakeToken, stakeVault, stakeVaultTokenAccount, new anchor_1.BN(amount)); const { blockhash, lastValidBlockHeight } = yield this._connection.getLatestBlockhash(); const tx = new web3_js_1.Transaction({ feePayer: staker, blockhash, lastValidBlockHeight, }).add(ix); return this._createPayload(tx, []); }); } unstake(params) { return __awaiter(this, void 0, void 0, function* () { const { lockupAddress, stakerAddress } = params; const lockup = new web3_js_1.PublicKey(lockupAddress); const decoded = yield this.instructions.program.account.lockupInfo.fetch(lockup); const stakeToken = decoded.stakedToken; const staker = new web3_js_1.PublicKey(stakerAddress); const stakeInfo = StakingService.deriveStakeInfoAddress(lockup, staker, this._programId); const stakeVault = StakingService.deriveStakeVaultAddress(lockup, this._programId); const stakerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(stakeToken, staker); const stakeVaultTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(stakeToken, stakeVault, true); const ix = yield this.instructions.getUnstakeInstruction(lockup, stakeInfo, staker, stakerTokenAccount, stakeToken, stakeVault, stakeVaultTokenAccount); const { blockhash, lastValidBlockHeight } = yield this._connection.getLatestBlockhash(); const tx = new web3_js_1.Transaction({ feePayer: staker, blockhash, lastValidBlockHeight, }).add(ix); return this._createPayload(tx, []); }); } claimRewardToken(params) { return __awaiter(this, void 0, void 0, function* () { const { lockupAddress, stakerAddress } = params; const lockup = new web3_js_1.PublicKey(lockupAddress); const decoded = yield this.instructions.program.account.lockupInfo.fetch(lockup); const rewardToken = decoded.rewardToken; const stakeToken = decoded.stakedToken; const staker = new web3_js_1.PublicKey(stakerAddress); const stakeInfo = StakingService.deriveStakeInfoAddress(lockup, staker, this._programId); const stakeVault = StakingService.deriveStakeVaultAddress(lockup, this._programId); const stakerRewardTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(rewardToken, staker); const stakeVaultRewardTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(rewardToken, stakeVault, true); const ix = yield this.instructions.getClaimRewardTokenInstruction(lockup, rewardToken, stakeInfo, staker, stakerRewardTokenAccount, stakeToken, stakeVault, stakeVaultRewardTokenAccount); const { blockhash, lastValidBlockHeight } = yield this._connection.getLatestBlockhash(); const tx = new web3_js_1.Transaction({ feePayer: staker, blockhash, lastValidBlockHeight, }).add(ix); return this._createPayload(tx, []); }); } getLockupInfo(lockupAddress) { return __awaiter(this, void 0, void 0, function* () { const lockup = new web3_js_1.PublicKey(lockupAddress); const decoded = yield this.instructions.program.account.lockupInfo.fetch(lockup); const rewardTokenDecimals = yield (0, utils_1.getDecimals)(this._connection, decoded.rewardToken); const stakeTokenDecimals = yield (0, utils_1.getDecimals)(this._connection, decoded.stakedToken); const totalAllocationReward = (0, bignumber_js_1.default)(decoded.totalAllocationReward.toString()) .div((0, bignumber_js_1.default)(10).pow(rewardTokenDecimals)) .toFixed(); const globalStaked = (0, bignumber_js_1.default)(decoded.globalStaked.toString()) .div((0, bignumber_js_1.default)(10).pow(stakeTokenDecimals)) .toFixed(); return { creator: decoded.creator.toString(), globalStaked, lockupCreatedTime: decoded.lockupCreatedTime.toString(), lockupTimespan: decoded.lockTimespan.toString(), name: decoded.name, rewardToken: decoded.rewardToken.toString(), stakedToken: decoded.stakedToken.toString(), stakingEndTime: decoded.stakingEndTime.toString(), stakingStartTime: decoded.stakingStartTime.toString(), totalAllocationReward, }; }); } getStakeInfo(lockupAddress, stakerAddress) { return __awaiter(this, void 0, void 0, function* () { const lockup = new web3_js_1.PublicKey(lockupAddress); const staker = new web3_js_1.PublicKey(stakerAddress); const stakerInfo = StakingService.deriveStakeInfoAddress(lockup, staker, this._programId); const decodedLockup = yield this.instructions.program.account.lockupInfo.fetch(lockup); const rewardTokenDecimals = yield (0, utils_1.getDecimals)(this._connection, decodedLockup.rewardToken); const stakeTokenDecimals = yield (0, utils_1.getDecimals)(this._connection, decodedLockup.stakedToken); const decoded = yield this.instructions.program.account.stakeInfo.fetch(stakerInfo); const rewardAmount = (0, bignumber_js_1.default)(decoded.rewardAmount.toString()) .div((0, bignumber_js_1.default)(10).pow(rewardTokenDecimals)) .toFixed(); const stakedAmount = (0, bignumber_js_1.default)(decoded.stakedAmount.toString()) .div((0, bignumber_js_1.default)(10).pow(stakeTokenDecimals)) .toFixed(); return { createdTime: decoded.createdTime.toString(), rewardAmount, stakedAmount, staker: decoded.staker.toString(), rewardClaimed: decoded.rewardClaimed, stakeClaimed: decoded.stakeClaimed, }; }); } calculateReward(lockupAdress, stakerAddress) { return __awaiter(this, void 0, void 0, function* () { const lockup = new web3_js_1.PublicKey(lockupAdress); const staker = new web3_js_1.PublicKey(stakerAddress); const stakerInfo = StakingService.deriveStakeInfoAddress(lockup, staker, this._programId); const [lockInfoDecoded, stakeInfoDecoded] = yield Promise.all([ this.instructions.program.account.lockupInfo.fetch(lockup, "confirmed"), this.instructions.program.account.stakeInfo.fetch(stakerInfo, "confirmed"), ]); const rewardTokenDecimals = yield (0, utils_1.getDecimals)(this._connection, lockInfoDecoded.rewardToken); const slot = yield this._connection.getSlot("confirmed"); const blockTime = yield this._connection.getBlockTime(slot); (0, utils_1.assert)(blockTime, "blocktime is null!"); if ((0, bignumber_js_1.default)(lockInfoDecoded.stakingEndTime.toString()).isGreaterThanOrEqualTo(blockTime)) { return "0"; } const lockTimeSpanInDays = (0, bignumber_js_1.default)(lockInfoDecoded.lockTimespan.toString()).div(constants_1.ONE_DAY_BIGNUM); let stakedTimespan; if ((0, bignumber_js_1.default)(lockInfoDecoded.stakingEndTime.toString()) .plus(lockInfoDecoded.lockTimespan.toString()) .isLessThan(blockTime)) { stakedTimespan = lockTimeSpanInDays; } else { stakedTimespan = (0, bignumber_js_1.default)(blockTime) .minus(lockInfoDecoded.stakingEndTime.toString()) .div(constants_1.ONE_DAY_BIGNUM); } const stakerShare = (0, bignumber_js_1.default)(stakeInfoDecoded.stakedAmount.toString()).div(lockInfoDecoded.globalStaked.toString()); const dailyAllocationReward = (0, bignumber_js_1.default)(lockInfoDecoded.totalAllocationReward.toString()).div(lockTimeSpanInDays); const totalRewardAmount = dailyAllocationReward .times(stakedTimespan) .times(stakerShare) .decimalPlaces(0, bignumber_js_1.default.ROUND_DOWN); const parsedReward = totalRewardAmount.div((0, bignumber_js_1.default)(10).pow(rewardTokenDecimals)).toFixed(); return parsedReward; }); } } exports.StakingService = StakingService; //# sourceMappingURL=service.js.map