@ignitionfi/spl-stake-pool 1.1.20 → 1.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.cjs.js +147 -1
- package/dist/index.browser.cjs.js.map +1 -1
- package/dist/index.browser.esm.js +147 -2
- package/dist/index.browser.esm.js.map +1 -1
- package/dist/index.cjs.js +147 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.esm.js +147 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +147 -1
- package/dist/index.iife.js.map +1 -1
- package/dist/index.iife.min.js +1 -1
- package/dist/index.iife.min.js.map +1 -1
- package/dist/instructions.d.ts +23 -1
- package/package.json +1 -1
- package/src/index.ts +167 -0
- package/src/instructions.ts +64 -1
|
@@ -1083,7 +1083,8 @@ const STAKE_POOL_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
|
1083
1083
|
index: 24,
|
|
1084
1084
|
layout: BufferLayout__namespace.struct([
|
|
1085
1085
|
BufferLayout__namespace.u8('instruction'),
|
|
1086
|
-
BufferLayout__namespace.ns64('
|
|
1086
|
+
BufferLayout__namespace.ns64('poolTokensIn'),
|
|
1087
|
+
BufferLayout__namespace.ns64('minimumLamportsOut'),
|
|
1087
1088
|
]),
|
|
1088
1089
|
},
|
|
1089
1090
|
DepositSolWithSlippage: {
|
|
@@ -1116,6 +1117,14 @@ const STAKE_POOL_INSTRUCTION_LAYOUTS = Object.freeze({
|
|
|
1116
1117
|
BufferLayout__namespace.ns64('minimumLamportsOut'),
|
|
1117
1118
|
]),
|
|
1118
1119
|
},
|
|
1120
|
+
WithdrawStakeWithSession: {
|
|
1121
|
+
index: 29,
|
|
1122
|
+
layout: BufferLayout__namespace.struct([
|
|
1123
|
+
BufferLayout__namespace.u8('instruction'),
|
|
1124
|
+
BufferLayout__namespace.ns64('poolTokensIn'),
|
|
1125
|
+
BufferLayout__namespace.ns64('minimumLamportsOut'),
|
|
1126
|
+
]),
|
|
1127
|
+
},
|
|
1119
1128
|
});
|
|
1120
1129
|
/**
|
|
1121
1130
|
* Stake Pool Instruction class
|
|
@@ -1591,6 +1600,37 @@ class StakePoolInstruction {
|
|
|
1591
1600
|
data,
|
|
1592
1601
|
});
|
|
1593
1602
|
}
|
|
1603
|
+
/**
|
|
1604
|
+
* Creates a transaction instruction to withdraw stake from a stake pool using a Fogo session.
|
|
1605
|
+
*/
|
|
1606
|
+
static withdrawStakeWithSession(params) {
|
|
1607
|
+
const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawStakeWithSession;
|
|
1608
|
+
const data = encodeData(type, {
|
|
1609
|
+
poolTokensIn: params.poolTokensIn,
|
|
1610
|
+
minimumLamportsOut: params.minimumLamportsOut,
|
|
1611
|
+
});
|
|
1612
|
+
const keys = [
|
|
1613
|
+
{ pubkey: params.stakePool, isSigner: false, isWritable: true },
|
|
1614
|
+
{ pubkey: params.validatorList, isSigner: false, isWritable: true },
|
|
1615
|
+
{ pubkey: params.withdrawAuthority, isSigner: false, isWritable: false },
|
|
1616
|
+
{ pubkey: params.stakeToSplit, isSigner: false, isWritable: true },
|
|
1617
|
+
{ pubkey: params.stakeToReceive, isSigner: false, isWritable: true },
|
|
1618
|
+
{ pubkey: params.sessionSigner, isSigner: true, isWritable: false }, // user_stake_authority_info (signer_or_session)
|
|
1619
|
+
{ pubkey: params.sessionSigner, isSigner: false, isWritable: false }, // user_transfer_authority_info (not used in session path)
|
|
1620
|
+
{ pubkey: params.burnFromPool, isSigner: false, isWritable: true },
|
|
1621
|
+
{ pubkey: params.managerFeeAccount, isSigner: false, isWritable: true },
|
|
1622
|
+
{ pubkey: params.poolMint, isSigner: false, isWritable: true },
|
|
1623
|
+
{ pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
|
|
1624
|
+
{ pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
|
|
1625
|
+
{ pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
|
|
1626
|
+
{ pubkey: params.programSigner, isSigner: false, isWritable: false },
|
|
1627
|
+
];
|
|
1628
|
+
return new web3_js.TransactionInstruction({
|
|
1629
|
+
programId: params.programId,
|
|
1630
|
+
keys,
|
|
1631
|
+
data,
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1594
1634
|
/**
|
|
1595
1635
|
* Creates an instruction to create metadata
|
|
1596
1636
|
* using the mpl token metadata program for the pool token
|
|
@@ -2200,6 +2240,111 @@ async function withdrawWsolWithSession(connection, stakePoolAddress, signerOrSes
|
|
|
2200
2240
|
signers,
|
|
2201
2241
|
};
|
|
2202
2242
|
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Creates instructions required to withdraw stake from a stake pool using a Fogo session.
|
|
2245
|
+
* The withdrawn stake account will be authorized to the user's wallet.
|
|
2246
|
+
*/
|
|
2247
|
+
async function withdrawStakeWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, amount, payer, useReserve = false, voteAccountAddress, minimumLamportsOut = 0, validatorComparator) {
|
|
2248
|
+
const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
|
|
2249
|
+
const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
|
|
2250
|
+
const stakePool = stakePoolAccount.account.data;
|
|
2251
|
+
const poolTokens = solToLamports(amount);
|
|
2252
|
+
const poolAmount = new BN(poolTokens);
|
|
2253
|
+
const poolTokenAccount = splToken.getAssociatedTokenAddressSync(stakePool.poolMint, userPubkey);
|
|
2254
|
+
const tokenAccount = await splToken.getAccount(connection, poolTokenAccount);
|
|
2255
|
+
if (tokenAccount.amount < poolTokens) {
|
|
2256
|
+
throw new Error(`Not enough token balance to withdraw ${amount} pool tokens.
|
|
2257
|
+
Maximum withdraw amount is ${lamportsToSol(tokenAccount.amount)} pool tokens.`);
|
|
2258
|
+
}
|
|
2259
|
+
const [programSigner] = web3_js.PublicKey.findProgramAddressSync([Buffer.from('fogo_session_program_signer')], stakePoolProgramId);
|
|
2260
|
+
const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
|
|
2261
|
+
const stakeAccountRentExemption = await connection.getMinimumBalanceForRentExemption(web3_js.StakeProgram.space);
|
|
2262
|
+
// Determine which stake accounts to withdraw from
|
|
2263
|
+
const withdrawAccounts = [];
|
|
2264
|
+
if (useReserve) {
|
|
2265
|
+
withdrawAccounts.push({
|
|
2266
|
+
stakeAddress: stakePool.reserveStake,
|
|
2267
|
+
voteAddress: undefined,
|
|
2268
|
+
poolAmount,
|
|
2269
|
+
});
|
|
2270
|
+
}
|
|
2271
|
+
else if (voteAccountAddress) {
|
|
2272
|
+
const stakeAccountAddress = await findStakeProgramAddress(stakePoolProgramId, voteAccountAddress, stakePoolAddress);
|
|
2273
|
+
const stakeAccount = await connection.getAccountInfo(stakeAccountAddress);
|
|
2274
|
+
if (!stakeAccount) {
|
|
2275
|
+
throw new Error(`Validator stake account not found for vote address ${voteAccountAddress.toBase58()}`);
|
|
2276
|
+
}
|
|
2277
|
+
const availableLamports = new BN(stakeAccount.lamports - MINIMUM_ACTIVE_STAKE - stakeAccountRentExemption);
|
|
2278
|
+
if (availableLamports.lt(new BN(0))) {
|
|
2279
|
+
throw new Error('Invalid Stake Account');
|
|
2280
|
+
}
|
|
2281
|
+
const availableForWithdrawal = calcLamportsWithdrawAmount(stakePool, availableLamports);
|
|
2282
|
+
if (availableForWithdrawal.lt(poolAmount)) {
|
|
2283
|
+
throw new Error(`Not enough lamports available for withdrawal from ${stakeAccountAddress},
|
|
2284
|
+
${poolAmount} asked, ${availableForWithdrawal} available.`);
|
|
2285
|
+
}
|
|
2286
|
+
withdrawAccounts.push({
|
|
2287
|
+
stakeAddress: stakeAccountAddress,
|
|
2288
|
+
voteAddress: voteAccountAddress,
|
|
2289
|
+
poolAmount,
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2292
|
+
else {
|
|
2293
|
+
// Get the list of accounts to withdraw from automatically
|
|
2294
|
+
withdrawAccounts.push(...(await prepareWithdrawAccounts(connection, stakePool, stakePoolAddress, poolAmount, validatorComparator, poolTokenAccount.equals(stakePool.managerFeeAccount))));
|
|
2295
|
+
}
|
|
2296
|
+
const instructions = [];
|
|
2297
|
+
const stakeAccountPubkeys = [];
|
|
2298
|
+
// Max 5 accounts to prevent an error: "Transaction too large"
|
|
2299
|
+
const maxWithdrawAccounts = 5;
|
|
2300
|
+
let i = 0;
|
|
2301
|
+
for (const withdrawAccount of withdrawAccounts) {
|
|
2302
|
+
if (i >= maxWithdrawAccounts) {
|
|
2303
|
+
break;
|
|
2304
|
+
}
|
|
2305
|
+
// Create a deterministic stake account address using a seed
|
|
2306
|
+
// This avoids needing the new account to sign (required for sessions)
|
|
2307
|
+
// We use payer as base so only payer needs to sign (payer = basePubkey)
|
|
2308
|
+
// The seed includes timestamp + random component to ensure uniqueness
|
|
2309
|
+
const uniqueId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2310
|
+
const seed = `ws:${uniqueId}:${i}`.slice(0, 32); // Seed max 32 chars
|
|
2311
|
+
const stakeReceiverPubkey = await web3_js.PublicKey.createWithSeed(payer, seed, web3_js.StakeProgram.programId);
|
|
2312
|
+
stakeAccountPubkeys.push(stakeReceiverPubkey);
|
|
2313
|
+
// Create the stake account using createAccountWithSeed
|
|
2314
|
+
// Since basePubkey === fromPubkey (both are payer), only payer needs to sign
|
|
2315
|
+
instructions.push(web3_js.SystemProgram.createAccountWithSeed({
|
|
2316
|
+
fromPubkey: payer,
|
|
2317
|
+
newAccountPubkey: stakeReceiverPubkey,
|
|
2318
|
+
basePubkey: payer,
|
|
2319
|
+
seed,
|
|
2320
|
+
lamports: stakeAccountRentExemption,
|
|
2321
|
+
space: web3_js.StakeProgram.space,
|
|
2322
|
+
programId: web3_js.StakeProgram.programId,
|
|
2323
|
+
}));
|
|
2324
|
+
// Add the withdraw stake with session instruction
|
|
2325
|
+
instructions.push(StakePoolInstruction.withdrawStakeWithSession({
|
|
2326
|
+
programId: stakePoolProgramId,
|
|
2327
|
+
stakePool: stakePoolAddress,
|
|
2328
|
+
validatorList: stakePool.validatorList,
|
|
2329
|
+
withdrawAuthority,
|
|
2330
|
+
stakeToSplit: withdrawAccount.stakeAddress,
|
|
2331
|
+
stakeToReceive: stakeReceiverPubkey,
|
|
2332
|
+
sessionSigner: signerOrSession,
|
|
2333
|
+
burnFromPool: poolTokenAccount,
|
|
2334
|
+
managerFeeAccount: stakePool.managerFeeAccount,
|
|
2335
|
+
poolMint: stakePool.poolMint,
|
|
2336
|
+
tokenProgramId: stakePool.tokenProgramId,
|
|
2337
|
+
programSigner,
|
|
2338
|
+
poolTokensIn: withdrawAccount.poolAmount.toNumber(),
|
|
2339
|
+
minimumLamportsOut,
|
|
2340
|
+
}));
|
|
2341
|
+
i++;
|
|
2342
|
+
}
|
|
2343
|
+
return {
|
|
2344
|
+
instructions,
|
|
2345
|
+
stakeAccountPubkeys,
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2203
2348
|
async function addValidatorToPool(connection, stakePoolAddress, validatorVote, seed) {
|
|
2204
2349
|
const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
|
|
2205
2350
|
const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
|
|
@@ -2587,5 +2732,6 @@ exports.updatePoolTokenMetadata = updatePoolTokenMetadata;
|
|
|
2587
2732
|
exports.updateStakePool = updateStakePool;
|
|
2588
2733
|
exports.withdrawSol = withdrawSol;
|
|
2589
2734
|
exports.withdrawStake = withdrawStake;
|
|
2735
|
+
exports.withdrawStakeWithSession = withdrawStakeWithSession;
|
|
2590
2736
|
exports.withdrawWsolWithSession = withdrawWsolWithSession;
|
|
2591
2737
|
//# sourceMappingURL=index.browser.cjs.js.map
|