Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

test-npm-den

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

test-npm-den - npm Package Compare versions

Comparing version 1.0.16 to 1.0.17

lib/service/constants.d.ts

1

lib/eSol.d.ts

@@ -8,2 +8,3 @@ import { ESolConfig, ClusterType } from './config';

unDelegateSol(userAddress: PublicKey, lamports: number, solWithdrawAuthority?: PublicKey): Promise<Transaction>;
withdrawSol(userAddress: PublicKey, lamports: number, stakeReceiver?: PublicKey, poolTokenAccount?: PublicKey): Promise<Transaction>;
}
import { ESolConfig } from './config';
import { PublicKey, Transaction, Keypair, SystemProgram, StakeProgram, } from '@solana/web3.js';
import { lamportsToSol, solToLamports } from './utils';
import { getStakePoolAccount, addAssociatedTokenAccount, findWithdrawAuthorityProgramAddress, getTokenAccount, } from './service/service';
import { getStakePoolAccount, addAssociatedTokenAccount, findWithdrawAuthorityProgramAddress, getTokenAccount, prepareWithdrawAccounts, calcLamportsWithdrawAmount, newStakeAccount, } from './service/service';
import { StakePoolProgram } from './service/stakepool-program';

@@ -254,2 +254,140 @@ import { DAO_STATE_LAYOUT, COMMUNITY_TOKEN_LAYOUT } from './service/layouts';

}
async withdrawSol(userAddress, lamports, stakeReceiver, poolTokenAccount) {
var _a, _b;
const CONNECTION = this.config.connection;
const stakePoolAddress = this.config.eSOLStakePoolAddress;
const stakePool = await getStakePoolAccount(CONNECTION, stakePoolAddress);
const poolAmount = solToLamports(lamports);
// dao part
const daoStateDtoInfo = await PublicKey.findProgramAddress([Buffer.from(this.config.seedPrefixDaoState), stakePoolAddress.toBuffer(), StakePoolProgram.programId.toBuffer()], StakePoolProgram.programId);
const daoStateDtoPubkey = daoStateDtoInfo[0];
const daoStateDtoInfoAccount = await CONNECTION.getAccountInfo(daoStateDtoPubkey);
if (!daoStateDtoInfoAccount) {
throw Error("Didn't find dao state account");
}
const daoState = DAO_STATE_LAYOUT.decode(daoStateDtoInfoAccount.data);
const isDaoEnabled = daoState.isEnabled;
if (!isDaoEnabled) {
throw Error('Dao is not enable'); // it should never happened!!!
}
if (!poolTokenAccount) {
poolTokenAccount = await Token.getAssociatedTokenAddress(ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, stakePool.account.data.poolMint, userAddress);
}
const tokenAccount = await getTokenAccount(CONNECTION, poolTokenAccount, stakePool.account.data.poolMint);
if (!tokenAccount) {
throw new Error('Invalid token account');
}
// Check withdrawFrom balance
if (tokenAccount.amount.toNumber() < poolAmount) {
throw new Error(`Not enough token balance to withdraw ${lamportsToSol(poolAmount)} pool tokens.
Maximum withdraw amount is ${lamportsToSol(tokenAccount.amount.toNumber())} pool tokens.`);
}
const withdrawAuthority = await findWithdrawAuthorityProgramAddress(StakePoolProgram.programId, stakePoolAddress);
// Construct transaction to withdraw from withdrawAccounts account list
const instructions = [];
const userTransferAuthority = Keypair.generate();
const signers = [userTransferAuthority];
// dao
const communityTokenStakingRewardsInfo = await PublicKey.findProgramAddress([
Buffer.from(this.config.seedPrefixCommunityTokenStakingRewards),
stakePoolAddress.toBuffer(),
userAddress.toBuffer(),
StakePoolProgram.programId.toBuffer(),
], StakePoolProgram.programId);
const communityTokenStakingRewardsPubkey = communityTokenStakingRewardsInfo[0];
const communityTokenStakingRewardsAccount = await CONNECTION.getAccountInfo(communityTokenStakingRewardsPubkey);
// WE SHOULD CHECK NEXT PART IF USER WITHDRAW !!NOT!! ALL ESOL
// We can be sure that this account already exists, as it is created when you deposit.
// But there are some number of users who made a deposit before updating the code with DAO strategy,
// so here we create an account especially for them.
// {
const communityTokenDtoInfo = await PublicKey.findProgramAddress([
Buffer.from(this.config.seedPrefixCommunityToken),
stakePoolAddress.toBuffer(),
StakePoolProgram.programId.toBuffer(),
], StakePoolProgram.programId);
const communityTokenPubkey = communityTokenDtoInfo[0];
const communityTokenAccount = await CONNECTION.getAccountInfo(communityTokenPubkey);
if (!communityTokenAccount) {
throw Error('Community token is not exist'); // if isDaoEnabled -> error should NOT happened
}
const communityTokenInfo = COMMUNITY_TOKEN_LAYOUT.decode(communityTokenAccount.data);
// check associatedTokenAccount for RENT 165 BYTES FOR RENTs
const daoCommunityTokenReceiverAccount = await addAssociatedTokenAccount(CONNECTION, userAddress, communityTokenInfo.tokenMint, instructions);
// }
// communityTokenStakingRewardsCounter
const communityTokenStakingRewardsCounterDtoInfo = await PublicKey.findProgramAddress([
Buffer.from(this.config.seedPrefixCommunityTokenStakingRewardsCounter),
stakePoolAddress.toBuffer(),
StakePoolProgram.programId.toBuffer(),
], StakePoolProgram.programId);
const communityStakingRewardsCounterPubkey = communityTokenStakingRewardsCounterDtoInfo[0];
const communityTokenStakingRewardsCounterAccount = await CONNECTION.getAccountInfo(communityStakingRewardsCounterPubkey);
if (!communityTokenStakingRewardsCounterAccount) {
throw Error('Community token staking reward counter is not exist'); // if isDaoEnabled -> error should NOT happened
}
if (!communityTokenStakingRewardsAccount) {
// create CommunityTokenStakingRewards
instructions.push(StakePoolProgram.createCommunityTokenStakingRewards({
stakePoolPubkey: stakePoolAddress,
ownerWallet: userAddress,
communityTokenStakingRewardsDTO: communityTokenStakingRewardsPubkey,
communityTokenStakingRewardsCounterDTO: communityStakingRewardsCounterPubkey,
}));
}
instructions.push(Token.createApproveInstruction(TOKEN_PROGRAM_ID, poolTokenAccount, userTransferAuthority.publicKey, userAddress, [], poolAmount));
const withdrawAccount = await prepareWithdrawAccounts(CONNECTION, stakePool.account.data, stakePoolAddress, poolAmount);
if (!withdrawAccount) {
throw Error(`Not available at the moment. Please try again later. Sorry for the inconvenience.`);
}
const availableSol = lamportsToSol(withdrawAccount.poolAmount);
if (withdrawAccount.poolAmount < poolAmount) {
throw Error(`Currently, you can undelegate only ${availableSol} SOL within one transaction due to delayed unstake limitations. Please unstake the desired amount in few transactions. Note that you will be able to track your unstaked SOL in the “Wallet” tab as a summary of transactions!.`);
}
const solWithdrawAmount = Math.ceil(calcLamportsWithdrawAmount(stakePool.account.data, withdrawAccount.poolAmount));
let infoMsg = `Withdrawing ◎${solWithdrawAmount},
from stake account ${(_a = withdrawAccount.stakeAddress) === null || _a === void 0 ? void 0 : _a.toBase58()}`;
if (withdrawAccount.voteAddress) {
infoMsg = `${infoMsg}, delegated to ${(_b = withdrawAccount.voteAddress) === null || _b === void 0 ? void 0 : _b.toBase58()}`;
}
let stakeToReceive;
let numberOfStakeAccounts = 1;
let totalRentFreeBalances = 0;
function incrementStakeAccount() {
numberOfStakeAccounts++;
}
const stakeReceiverAccountBalance = await CONNECTION.getMinimumBalanceForRentExemption(StakeProgram.space);
const stakeAccountPubkey = await newStakeAccount(CONNECTION, userAddress, instructions, stakeReceiverAccountBalance, numberOfStakeAccounts, incrementStakeAccount);
totalRentFreeBalances += stakeReceiverAccountBalance;
stakeToReceive = stakeAccountPubkey;
stakeReceiver = stakeAccountPubkey;
instructions.push(StakePoolProgram.withdrawStakeWithDao({
daoCommunityTokenReceiverAccount,
communityTokenStakingRewards: communityTokenStakingRewardsPubkey,
ownerWallet: userAddress,
communityTokenPubkey,
stakePool: stakePoolAddress,
validatorList: stakePool.account.data.validatorList,
validatorStake: withdrawAccount.stakeAddress,
destinationStake: stakeToReceive,
destinationStakeAuthority: userAddress,
sourceTransferAuthority: userTransferAuthority.publicKey,
sourcePoolAccount: poolTokenAccount,
managerFeeAccount: stakePool.account.data.managerFeeAccount,
poolMint: stakePool.account.data.poolMint,
poolTokens: withdrawAccount.poolAmount,
withdrawAuthority,
}));
const deactivateTransaction = StakeProgram.deactivate({
stakePubkey: stakeToReceive,
authorizedPubkey: userAddress,
});
instructions.push(...deactivateTransaction.instructions);
const transaction = new Transaction();
instructions.forEach((instruction) => transaction.add(instruction));
transaction.feePayer = userAddress;
transaction.recentBlockhash = (await CONNECTION.getRecentBlockhash()).blockhash;
transaction.sign(...signers);
return transaction;
}
}

5

lib/service/service.d.ts

@@ -7,2 +7,3 @@ import { PublicKey, Connection, AccountInfo, TransactionInstruction } from '@solana/web3.js';

}
declare function calcLamportsWithdrawAmount(stakePool: StakePool, poolTokens: number): number;
declare function getStakePoolAccount(connection: Connection, stakePoolPubKey: PublicKey): Promise<StakePoolAccount>;

@@ -12,2 +13,4 @@ declare function addAssociatedTokenAccount(connection: Connection, owner: PublicKey, mint: PublicKey, instructions: TransactionInstruction[]): Promise<PublicKey>;

declare function getTokenAccount(connection: Connection, tokenAccountAddress: PublicKey, expectedTokenMint: PublicKey): Promise<any>;
export { getStakePoolAccount, addAssociatedTokenAccount, findWithdrawAuthorityProgramAddress, getTokenAccount };
declare function prepareWithdrawAccounts(connection: Connection, stakePool: StakePool, stakePoolAddress: PublicKey, amount: number): Promise<any>;
declare function newStakeAccount(CONNECTION: any, feePayer: PublicKey, instructions: TransactionInstruction[], lamports: number, numberOfStakeAccounts: number, incrementStakeAccount: any): Promise<PublicKey>;
export { getStakePoolAccount, addAssociatedTokenAccount, findWithdrawAuthorityProgramAddress, getTokenAccount, prepareWithdrawAccounts, calcLamportsWithdrawAmount, newStakeAccount, };

@@ -1,6 +0,36 @@

import { PublicKey } from '@solana/web3.js';
import { PublicKey, SystemProgram, StakeProgram, } from '@solana/web3.js';
import { Token, TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token';
import { STAKE_POOL_LAYOUT, ACCOUNT_LAYOUT } from '../layouts/index';
import { STAKE_POOL_LAYOUT, ACCOUNT_LAYOUT, VALIDATOR_LIST_LAYOUT, ValidatorStakeInfoStatus, } from '../layouts/index';
import { findTransientStakeProgramAddress } from './program-address';
import { StakePoolProgram } from './stakepool-program';
import BN from 'bn.js';
const FAILED_TO_FIND_ACCOUNT = 'Failed to find account';
const INVALID_ACCOUNT_OWNER = 'Invalid account owner';
async function findStakeProgramAddress(programId, voteAccountAddress, stakePoolAddress) {
const [publicKey] = await PublicKey.findProgramAddress([voteAccountAddress.toBuffer(), stakePoolAddress.toBuffer()], programId);
return publicKey;
}
function calcLamportsWithdrawAmount(stakePool, poolTokens) {
const numerator = new BN(poolTokens).mul(stakePool.totalLamports);
const denominator = stakePool.poolTokenSupply;
if (numerator.lt(denominator)) {
return 0;
}
return divideBnToNumber(numerator, denominator);
}
function calcPoolTokensForDeposit(stakePool, stakeLamports) {
if (stakePool.poolTokenSupply.isZero() || stakePool.totalLamports.isZero()) {
return stakeLamports;
}
return divideBnToNumber(new BN(stakeLamports).mul(stakePool.poolTokenSupply), stakePool.totalLamports);
}
function divideBnToNumber(numerator, denominator) {
if (denominator.isZero()) {
return 0;
}
const quotient = numerator.div(denominator).toNumber();
const rem = numerator.umod(denominator);
const gcd = rem.gcd(denominator);
return quotient + rem.div(gcd).toNumber() / denominator.div(gcd).toNumber();
}
async function getStakePoolAccount(connection, stakePoolPubKey) {

@@ -83,2 +113,119 @@ const account = await connection.getAccountInfo(stakePoolPubKey);

}
export { getStakePoolAccount, addAssociatedTokenAccount, findWithdrawAuthorityProgramAddress, getTokenAccount };
async function prepareWithdrawAccounts(connection, stakePool, stakePoolAddress, amount) {
var _a;
const validatorListAcc = await connection.getAccountInfo(stakePool.validatorList);
const validatorList = VALIDATOR_LIST_LAYOUT.decode(validatorListAcc.data);
if (!(validatorList === null || validatorList === void 0 ? void 0 : validatorList.validators) || (validatorList === null || validatorList === void 0 ? void 0 : validatorList.validators.length) === 0) {
throw new Error('No accounts found');
}
let accounts = [];
// Prepare accounts
for (const validator of validatorList.validators) {
if (validator.status !== ValidatorStakeInfoStatus.Active) {
continue;
}
const stakeAccountAddress = await findStakeProgramAddress(StakePoolProgram.programId, validator.voteAccountAddress, stakePoolAddress);
if (!validator.activeStakeLamports.isZero()) {
const isPreferred = stakePool.preferredWithdrawValidatorVoteAddress &&
stakePool.preferredWithdrawValidatorVoteAddress.toBase58() === validator.voteAccountAddress.toBase58();
accounts.push({
type: isPreferred ? 'preferred' : 'active',
voteAddress: validator.voteAccountAddress,
stakeAddress: stakeAccountAddress,
lamports: validator.activeStakeLamports.toNumber(),
});
}
const transientStakeAccountAddress = await findTransientStakeProgramAddress(StakePoolProgram.programId, validator.voteAccountAddress, stakePoolAddress, validator.transientSeedSuffixStart);
if (!((_a = validator.transientStakeLamports) === null || _a === void 0 ? void 0 : _a.isZero())) {
accounts.push({
type: 'transient',
voteAddress: validator.voteAccountAddress,
stakeAddress: transientStakeAccountAddress,
lamports: validator.transientStakeLamports.toNumber(),
});
}
}
// Sort from highest to lowest balance
accounts = accounts.sort((a, b) => b.lamports - a.lamports);
// const reserveStake = await connection.getAccountInfo(stakePool.reserveStake);
// if (reserveStake && reserveStake.lamports > 0) {
// accounts.push({
// type: "reserve",
// stakeAddress: stakePool.reserveStake,
// lamports: reserveStake?.lamports,
// });
// }
// Prepare the list of accounts to withdraw from
// const withdrawFrom: WithdrawAccount[] = [];
let withdrawFrom;
const remainingAmount = amount;
// for (const type of ["preferred", "active", "transient", "reserve"]) {
for (const type of ['active']) {
const filteredAccounts = accounts.filter((a) => a.type === type);
for (const { stakeAddress, voteAddress, lamports } of filteredAccounts) {
let availableForWithdrawal = Math.floor(calcPoolTokensForDeposit(stakePool, lamports));
if (!stakePool.stakeWithdrawalFee.denominator.isZero()) {
availableForWithdrawal = divideBnToNumber(new BN(availableForWithdrawal).mul(stakePool.stakeWithdrawalFee.denominator), stakePool.stakeWithdrawalFee.denominator.sub(stakePool.stakeWithdrawalFee.numerator));
}
const poolAmount = Math.min(availableForWithdrawal, remainingAmount);
if (poolAmount <= 0) {
continue;
}
// Those accounts will be withdrawn completely with `claim` instruction
withdrawFrom = { stakeAddress, voteAddress, poolAmount };
// new
break;
// remainingAmount -= poolAmount;
// if (remainingAmount == 0) {
// break;
// }
}
if (remainingAmount === 0) {
break;
}
}
// Not enough stake to withdraw the specified amount
// if (remainingAmount > 0) {
// throw new Error(
// `No stake accounts found in this pool with enough balance to withdraw ${lamportsToSol(
// amount,
// )} pool tokens.`,
// );
// }
return withdrawFrom;
}
async function newStakeAccount(CONNECTION, feePayer, instructions, lamports, numberOfStakeAccounts, incrementStakeAccount) {
// Account for tokens not specified, creating one
const programId = StakePoolProgram.programId.toString();
let counter = numberOfStakeAccounts;
let stakeReceiverPubkey;
let seed;
while (counter < 12) {
seed = `${feePayer.toString().slice(0, 4)}${programId.slice(0, 4)}everstake${counter}`;
stakeReceiverPubkey = await PublicKey.createWithSeed(feePayer, seed, StakeProgram.programId);
const stakeAccount = await CONNECTION.getAccountInfo(stakeReceiverPubkey);
if (stakeAccount) {
incrementStakeAccount();
counter++;
}
else {
break;
}
}
incrementStakeAccount();
if (counter === 12) {
throw Error('This transaction cannot be processed due to the withdrawal accounts limit. Try to use the “Instant unstake” or wait for a new epoch to undelegate. You can also withdraw already deactivated SOL if you have any.');
}
// Creating new account
instructions.push(SystemProgram.createAccountWithSeed({
fromPubkey: feePayer,
newAccountPubkey: stakeReceiverPubkey,
basePubkey: feePayer,
seed,
lamports,
space: StakeProgram.space,
programId: StakeProgram.programId,
}));
return stakeReceiverPubkey;
}
export { getStakePoolAccount, addAssociatedTokenAccount, findWithdrawAuthorityProgramAddress, getTokenAccount, prepareWithdrawAccounts, calcLamportsWithdrawAmount, newStakeAccount, };
{
"name": "test-npm-den",
"version": "1.0.16",
"version": "1.0.17",
"description": "Test",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc