@ignitionfi/spl-stake-pool 1.1.24 → 1.1.25
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 +139 -14
- package/dist/index.browser.cjs.js.map +1 -1
- package/dist/index.browser.esm.js +139 -15
- package/dist/index.browser.esm.js.map +1 -1
- package/dist/index.cjs.js +139 -14
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +40 -4
- package/dist/index.esm.js +139 -15
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +139 -14
- 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 -2
- package/package.json +1 -1
- package/src/constants.ts +1 -3
- package/src/index.ts +122 -16
- package/src/instructions.ts +70 -1
- package/src/utils/stake.ts +5 -2
package/dist/instructions.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { InstructionType } from './utils';
|
|
|
4
4
|
/**
|
|
5
5
|
* An enumeration of valid StakePoolInstructionType's
|
|
6
6
|
*/
|
|
7
|
-
export type StakePoolInstructionType = 'IncreaseValidatorStake' | 'DecreaseValidatorStake' | 'UpdateValidatorListBalance' | 'UpdateStakePoolBalance' | 'CleanupRemovedValidatorEntries' | 'DepositStake' | 'DepositSol' | 'WithdrawStake' | 'WithdrawSol' | 'IncreaseAdditionalValidatorStake' | 'DecreaseAdditionalValidatorStake' | 'DecreaseValidatorStakeWithReserve' | 'Redelegate' | 'AddValidatorToPool' | 'RemoveValidatorFromPool' | 'DepositWsolWithSession' | 'WithdrawWsolWithSession' | 'WithdrawStakeWithSession';
|
|
7
|
+
export type StakePoolInstructionType = 'IncreaseValidatorStake' | 'DecreaseValidatorStake' | 'UpdateValidatorListBalance' | 'UpdateStakePoolBalance' | 'CleanupRemovedValidatorEntries' | 'DepositStake' | 'DepositSol' | 'WithdrawStake' | 'WithdrawSol' | 'IncreaseAdditionalValidatorStake' | 'DecreaseAdditionalValidatorStake' | 'DecreaseValidatorStakeWithReserve' | 'Redelegate' | 'AddValidatorToPool' | 'RemoveValidatorFromPool' | 'DepositWsolWithSession' | 'WithdrawWsolWithSession' | 'WithdrawStakeWithSession' | 'WithdrawFromStakeAccountWithSession';
|
|
8
8
|
export declare function tokenMetadataLayout(instruction: number, nameLength: number, symbolLength: number, uriLength: number): {
|
|
9
9
|
index: number;
|
|
10
10
|
layout: BufferLayout.Structure<any>;
|
|
@@ -178,11 +178,26 @@ export type WithdrawStakeWithSessionParams = {
|
|
|
178
178
|
tokenProgramId: PublicKey;
|
|
179
179
|
/** The program signer PDA derived from PROGRAM_SIGNER_SEED */
|
|
180
180
|
programSigner: PublicKey;
|
|
181
|
+
/** The payer for stake account rent (typically the paymaster) */
|
|
182
|
+
payer: PublicKey;
|
|
181
183
|
poolTokensIn: number;
|
|
182
184
|
minimumLamportsOut: number;
|
|
183
185
|
/** Seed used to derive the user stake PDA */
|
|
184
186
|
userStakeSeed: number;
|
|
185
187
|
};
|
|
188
|
+
export type WithdrawFromStakeAccountWithSessionParams = {
|
|
189
|
+
programId: PublicKey;
|
|
190
|
+
/** The user stake account PDA to withdraw from */
|
|
191
|
+
userStakeAccount: PublicKey;
|
|
192
|
+
/** The user's wallet to receive the withdrawn SOL */
|
|
193
|
+
userWallet: PublicKey;
|
|
194
|
+
/** The session signer (user or session) */
|
|
195
|
+
sessionSigner: PublicKey;
|
|
196
|
+
/** Seed used to derive the user stake PDA */
|
|
197
|
+
userStakeSeed: number;
|
|
198
|
+
/** Lamports to withdraw (use BigInt max for full withdrawal) */
|
|
199
|
+
lamports: bigint;
|
|
200
|
+
};
|
|
186
201
|
/**
|
|
187
202
|
* Deposit SOL directly into the pool's reserve account. The output is a "pool" token
|
|
188
203
|
* representing ownership into the pool. Inputs are converted to the current ratio.
|
|
@@ -329,9 +344,15 @@ export declare class StakePoolInstruction {
|
|
|
329
344
|
static withdrawWsolWithSession(params: WithdrawWsolWithSessionParams): TransactionInstruction;
|
|
330
345
|
/**
|
|
331
346
|
* Creates a transaction instruction to withdraw stake from a stake pool using a Fogo session.
|
|
332
|
-
* The stake account is created as a PDA and rent is paid
|
|
347
|
+
* The stake account is created as a PDA and rent is paid by the payer (typically paymaster).
|
|
333
348
|
*/
|
|
334
349
|
static withdrawStakeWithSession(params: WithdrawStakeWithSessionParams): TransactionInstruction;
|
|
350
|
+
/**
|
|
351
|
+
* Creates a transaction instruction to withdraw SOL from a deactivated user stake account using a Fogo session.
|
|
352
|
+
* The stake account must be fully deactivated (inactive).
|
|
353
|
+
* User receives full stake balance (payer's rent contribution compensates for reduced split).
|
|
354
|
+
*/
|
|
355
|
+
static withdrawFromStakeAccountWithSession(params: WithdrawFromStakeAccountWithSessionParams): TransactionInstruction;
|
|
335
356
|
/**
|
|
336
357
|
* Creates an instruction to create metadata
|
|
337
358
|
* using the mpl token metadata program for the pool token
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -11,9 +11,7 @@ export const METADATA_MAX_URI_LENGTH = 200
|
|
|
11
11
|
export const STAKE_POOL_PROGRAM_ID = new PublicKey('SP1s4uFeTAX9jsXXmwyDs1gxYYf7cdDZ8qHUHVxE1yr')
|
|
12
12
|
|
|
13
13
|
// Public key that identifies the SPL Stake Pool program deployed to devnet.
|
|
14
|
-
export const DEVNET_STAKE_POOL_PROGRAM_ID = new PublicKey(
|
|
15
|
-
'DPoo15wWDqpPJJtS2MUZ49aRxqz5ZaaJCJP4z8bLuib',
|
|
16
|
-
)
|
|
14
|
+
export const DEVNET_STAKE_POOL_PROGRAM_ID = new PublicKey('DPoo15wWDqpPJJtS2MUZ49aRxqz5ZaaJCJP4z8bLuib')
|
|
17
15
|
|
|
18
16
|
// Maximum number of validators to update during UpdateValidatorListBalance.
|
|
19
17
|
export const MAX_VALIDATORS_TO_UPDATE = 4
|
package/src/index.ts
CHANGED
|
@@ -309,23 +309,30 @@ export async function depositWsolWithSession(
|
|
|
309
309
|
referrerTokenAccount?: PublicKey,
|
|
310
310
|
depositAuthority?: PublicKey,
|
|
311
311
|
payer?: PublicKey,
|
|
312
|
+
/**
|
|
313
|
+
* Skip WSOL balance validation. Set to true when adding wrap instructions
|
|
314
|
+
* in the same transaction that will fund the WSOL account before deposit.
|
|
315
|
+
*/
|
|
316
|
+
skipBalanceCheck: boolean = false,
|
|
312
317
|
) {
|
|
313
318
|
const wsolTokenAccount = getAssociatedTokenAddressSync(NATIVE_MINT, userPubkey)
|
|
314
319
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const wsolBalance = tokenAccountInfo
|
|
320
|
-
? parseInt(tokenAccountInfo.value.amount)
|
|
321
|
-
: 0
|
|
322
|
-
|
|
323
|
-
if (wsolBalance < lamports) {
|
|
324
|
-
throw new Error(
|
|
325
|
-
`Not enough WSOL to deposit into pool. Maximum deposit amount is ${lamportsToSol(
|
|
326
|
-
wsolBalance,
|
|
327
|
-
)} WSOL.`,
|
|
320
|
+
if (!skipBalanceCheck) {
|
|
321
|
+
const tokenAccountInfo = await connection.getTokenAccountBalance(
|
|
322
|
+
wsolTokenAccount,
|
|
323
|
+
'confirmed',
|
|
328
324
|
)
|
|
325
|
+
const wsolBalance = tokenAccountInfo
|
|
326
|
+
? parseInt(tokenAccountInfo.value.amount)
|
|
327
|
+
: 0
|
|
328
|
+
|
|
329
|
+
if (wsolBalance < lamports) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
`Not enough WSOL to deposit into pool. Maximum deposit amount is ${lamportsToSol(
|
|
332
|
+
wsolBalance,
|
|
333
|
+
)} WSOL.`,
|
|
334
|
+
)
|
|
335
|
+
}
|
|
329
336
|
}
|
|
330
337
|
|
|
331
338
|
const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress)
|
|
@@ -927,16 +934,113 @@ export async function findNextUserStakeSeed(
|
|
|
927
934
|
throw new Error(`No available user stake seed found between ${startSeed} and ${startSeed + maxSeed - 1}`)
|
|
928
935
|
}
|
|
929
936
|
|
|
937
|
+
/**
|
|
938
|
+
* Represents a user stake account with its details
|
|
939
|
+
*/
|
|
940
|
+
export interface UserStakeAccount {
|
|
941
|
+
/** The stake account public key (PDA) */
|
|
942
|
+
pubkey: PublicKey
|
|
943
|
+
/** The seed used to derive this PDA */
|
|
944
|
+
seed: number
|
|
945
|
+
/** Lamports in the stake account */
|
|
946
|
+
lamports: number
|
|
947
|
+
/** Parsed stake state */
|
|
948
|
+
state: 'inactive' | 'activating' | 'active' | 'deactivating'
|
|
949
|
+
/** Validator vote account (if delegated) */
|
|
950
|
+
voter?: PublicKey
|
|
951
|
+
/** Activation epoch (if active/activating) */
|
|
952
|
+
activationEpoch?: number
|
|
953
|
+
/** Deactivation epoch (if deactivating) */
|
|
954
|
+
deactivationEpoch?: number
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Fetches all user stake accounts created via WithdrawStakeWithSession.
|
|
959
|
+
* These are PDAs derived from [b"user_stake", user_wallet, seed].
|
|
960
|
+
*
|
|
961
|
+
* @param connection - Solana connection
|
|
962
|
+
* @param programId - The stake pool program ID
|
|
963
|
+
* @param userPubkey - User's wallet address
|
|
964
|
+
* @param maxSeed - Maximum seed to check (default: 100)
|
|
965
|
+
* @returns Array of user stake accounts with their details
|
|
966
|
+
*/
|
|
967
|
+
export async function getUserStakeAccounts(
|
|
968
|
+
connection: Connection,
|
|
969
|
+
programId: PublicKey,
|
|
970
|
+
userPubkey: PublicKey,
|
|
971
|
+
maxSeed: number = 100,
|
|
972
|
+
): Promise<UserStakeAccount[]> {
|
|
973
|
+
const stakeAccounts: UserStakeAccount[] = []
|
|
974
|
+
const currentEpoch = (await connection.getEpochInfo()).epoch
|
|
975
|
+
|
|
976
|
+
for (let seed = 0; seed < maxSeed; seed++) {
|
|
977
|
+
const pda = findUserStakeProgramAddress(programId, userPubkey, seed)
|
|
978
|
+
const accountInfo = await connection.getAccountInfo(pda)
|
|
979
|
+
|
|
980
|
+
if (!accountInfo) {
|
|
981
|
+
continue // Skip empty slots, there might be gaps
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// Check if owned by stake program
|
|
985
|
+
if (!accountInfo.owner.equals(StakeProgram.programId)) {
|
|
986
|
+
continue
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// Parse stake account data
|
|
990
|
+
const stakeAccount: UserStakeAccount = {
|
|
991
|
+
pubkey: pda,
|
|
992
|
+
seed,
|
|
993
|
+
lamports: accountInfo.lamports,
|
|
994
|
+
state: 'inactive',
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
try {
|
|
998
|
+
// Parse the stake account to get delegation info
|
|
999
|
+
const parsedAccount = await connection.getParsedAccountInfo(pda)
|
|
1000
|
+
if (parsedAccount.value && 'parsed' in parsedAccount.value.data) {
|
|
1001
|
+
const parsed = parsedAccount.value.data.parsed
|
|
1002
|
+
if (parsed.type === 'delegated' && parsed.info?.stake?.delegation) {
|
|
1003
|
+
const delegation = parsed.info.stake.delegation
|
|
1004
|
+
stakeAccount.voter = new PublicKey(delegation.voter)
|
|
1005
|
+
stakeAccount.activationEpoch = Number(delegation.activationEpoch)
|
|
1006
|
+
stakeAccount.deactivationEpoch = Number(delegation.deactivationEpoch)
|
|
1007
|
+
|
|
1008
|
+
// Determine state based on epochs
|
|
1009
|
+
const activationEpoch = stakeAccount.activationEpoch
|
|
1010
|
+
const deactivationEpoch = stakeAccount.deactivationEpoch
|
|
1011
|
+
|
|
1012
|
+
if (deactivationEpoch !== undefined && deactivationEpoch < Number.MAX_SAFE_INTEGER && deactivationEpoch <= currentEpoch) {
|
|
1013
|
+
stakeAccount.state = 'inactive'
|
|
1014
|
+
} else if (deactivationEpoch !== undefined && deactivationEpoch < Number.MAX_SAFE_INTEGER) {
|
|
1015
|
+
stakeAccount.state = 'deactivating'
|
|
1016
|
+
} else if (activationEpoch !== undefined && activationEpoch <= currentEpoch) {
|
|
1017
|
+
stakeAccount.state = 'active'
|
|
1018
|
+
} else {
|
|
1019
|
+
stakeAccount.state = 'activating'
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
} catch {
|
|
1024
|
+
// If parsing fails, keep default 'inactive' state
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
stakeAccounts.push(stakeAccount)
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
return stakeAccounts
|
|
1031
|
+
}
|
|
1032
|
+
|
|
930
1033
|
/**
|
|
931
1034
|
* Withdraws stake from a stake pool using a Fogo session.
|
|
932
1035
|
*
|
|
933
|
-
* The on-chain program creates stake account PDAs
|
|
934
|
-
*
|
|
1036
|
+
* The on-chain program creates stake account PDAs. The rent for these accounts
|
|
1037
|
+
* is paid by the payer (typically the paymaster), not deducted from the user's withdrawal.
|
|
935
1038
|
*
|
|
936
1039
|
* @param connection - Solana connection
|
|
937
1040
|
* @param stakePoolAddress - The stake pool to withdraw from
|
|
938
1041
|
* @param signerOrSession - The session signer public key
|
|
939
1042
|
* @param userPubkey - User's wallet (used for PDA derivation and token ownership)
|
|
1043
|
+
* @param payer - Payer for stake account rent (typically paymaster)
|
|
940
1044
|
* @param amount - Amount of pool tokens to withdraw
|
|
941
1045
|
* @param userStakeSeedStart - Starting seed for user stake PDA derivation (default: 0)
|
|
942
1046
|
* @param useReserve - Whether to withdraw from reserve (default: false)
|
|
@@ -949,6 +1053,7 @@ export async function withdrawStakeWithSession(
|
|
|
949
1053
|
stakePoolAddress: PublicKey,
|
|
950
1054
|
signerOrSession: PublicKey,
|
|
951
1055
|
userPubkey: PublicKey,
|
|
1056
|
+
payer: PublicKey,
|
|
952
1057
|
amount: number,
|
|
953
1058
|
userStakeSeedStart: number = 0,
|
|
954
1059
|
useReserve = false,
|
|
@@ -1064,7 +1169,7 @@ export async function withdrawStakeWithSession(
|
|
|
1064
1169
|
stakeAccountPubkeys.push(stakeReceiverPubkey)
|
|
1065
1170
|
userStakeSeeds.push(userStakeSeed)
|
|
1066
1171
|
|
|
1067
|
-
// The on-chain program
|
|
1172
|
+
// The on-chain program creates the stake account PDA and rent is paid by payer.
|
|
1068
1173
|
instructions.push(
|
|
1069
1174
|
StakePoolInstruction.withdrawStakeWithSession({
|
|
1070
1175
|
programId: stakePoolProgramId,
|
|
@@ -1079,6 +1184,7 @@ export async function withdrawStakeWithSession(
|
|
|
1079
1184
|
poolMint: stakePool.poolMint,
|
|
1080
1185
|
tokenProgramId: stakePool.tokenProgramId,
|
|
1081
1186
|
programSigner,
|
|
1187
|
+
payer,
|
|
1082
1188
|
poolTokensIn: withdrawAccount.poolAmount.toNumber(),
|
|
1083
1189
|
minimumLamportsOut,
|
|
1084
1190
|
userStakeSeed,
|
package/src/instructions.ts
CHANGED
|
@@ -42,6 +42,7 @@ export type StakePoolInstructionType
|
|
|
42
42
|
| 'DepositWsolWithSession'
|
|
43
43
|
| 'WithdrawWsolWithSession'
|
|
44
44
|
| 'WithdrawStakeWithSession'
|
|
45
|
+
| 'WithdrawFromStakeAccountWithSession'
|
|
45
46
|
|
|
46
47
|
// 'UpdateTokenMetadata' and 'CreateTokenMetadata' have dynamic layouts
|
|
47
48
|
|
|
@@ -237,6 +238,14 @@ export const STAKE_POOL_INSTRUCTION_LAYOUTS: {
|
|
|
237
238
|
BufferLayout.ns64('userStakeSeed'),
|
|
238
239
|
]),
|
|
239
240
|
},
|
|
241
|
+
WithdrawFromStakeAccountWithSession: {
|
|
242
|
+
index: 30,
|
|
243
|
+
layout: BufferLayout.struct<any>([
|
|
244
|
+
BufferLayout.u8('instruction'),
|
|
245
|
+
BufferLayout.ns64('lamports'),
|
|
246
|
+
BufferLayout.ns64('userStakeSeed'),
|
|
247
|
+
]),
|
|
248
|
+
},
|
|
240
249
|
})
|
|
241
250
|
|
|
242
251
|
/**
|
|
@@ -417,12 +426,28 @@ export type WithdrawStakeWithSessionParams = {
|
|
|
417
426
|
tokenProgramId: PublicKey
|
|
418
427
|
/** The program signer PDA derived from PROGRAM_SIGNER_SEED */
|
|
419
428
|
programSigner: PublicKey
|
|
429
|
+
/** The payer for stake account rent (typically the paymaster) */
|
|
430
|
+
payer: PublicKey
|
|
420
431
|
poolTokensIn: number
|
|
421
432
|
minimumLamportsOut: number
|
|
422
433
|
/** Seed used to derive the user stake PDA */
|
|
423
434
|
userStakeSeed: number
|
|
424
435
|
}
|
|
425
436
|
|
|
437
|
+
export type WithdrawFromStakeAccountWithSessionParams = {
|
|
438
|
+
programId: PublicKey
|
|
439
|
+
/** The user stake account PDA to withdraw from */
|
|
440
|
+
userStakeAccount: PublicKey
|
|
441
|
+
/** The user's wallet to receive the withdrawn SOL */
|
|
442
|
+
userWallet: PublicKey
|
|
443
|
+
/** The session signer (user or session) */
|
|
444
|
+
sessionSigner: PublicKey
|
|
445
|
+
/** Seed used to derive the user stake PDA */
|
|
446
|
+
userStakeSeed: number
|
|
447
|
+
/** Lamports to withdraw (use BigInt max for full withdrawal) */
|
|
448
|
+
lamports: bigint
|
|
449
|
+
}
|
|
450
|
+
|
|
426
451
|
/**
|
|
427
452
|
* Deposit SOL directly into the pool's reserve account. The output is a "pool" token
|
|
428
453
|
* representing ownership into the pool. Inputs are converted to the current ratio.
|
|
@@ -1197,7 +1222,7 @@ export class StakePoolInstruction {
|
|
|
1197
1222
|
|
|
1198
1223
|
/**
|
|
1199
1224
|
* Creates a transaction instruction to withdraw stake from a stake pool using a Fogo session.
|
|
1200
|
-
* The stake account is created as a PDA and rent is paid
|
|
1225
|
+
* The stake account is created as a PDA and rent is paid by the payer (typically paymaster).
|
|
1201
1226
|
*/
|
|
1202
1227
|
static withdrawStakeWithSession(params: WithdrawStakeWithSessionParams): TransactionInstruction {
|
|
1203
1228
|
const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawStakeWithSession
|
|
@@ -1223,6 +1248,7 @@ export class StakePoolInstruction {
|
|
|
1223
1248
|
{ pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
|
|
1224
1249
|
{ pubkey: params.programSigner, isSigner: false, isWritable: false },
|
|
1225
1250
|
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
1251
|
+
{ pubkey: params.payer, isSigner: true, isWritable: true },
|
|
1226
1252
|
]
|
|
1227
1253
|
|
|
1228
1254
|
return new TransactionInstruction({
|
|
@@ -1232,6 +1258,49 @@ export class StakePoolInstruction {
|
|
|
1232
1258
|
})
|
|
1233
1259
|
}
|
|
1234
1260
|
|
|
1261
|
+
/**
|
|
1262
|
+
* Creates a transaction instruction to withdraw SOL from a deactivated user stake account using a Fogo session.
|
|
1263
|
+
* The stake account must be fully deactivated (inactive).
|
|
1264
|
+
* User receives full stake balance (payer's rent contribution compensates for reduced split).
|
|
1265
|
+
*/
|
|
1266
|
+
static withdrawFromStakeAccountWithSession(params: WithdrawFromStakeAccountWithSessionParams): TransactionInstruction {
|
|
1267
|
+
// For u64::MAX (full withdrawal), we need to manually encode since buffer-layout doesn't handle bigint well
|
|
1268
|
+
const U64_MAX = BigInt('18446744073709551615')
|
|
1269
|
+
const isFullWithdrawal = params.lamports >= U64_MAX
|
|
1270
|
+
|
|
1271
|
+
// Manually create the instruction data buffer using Uint8Array for browser compatibility
|
|
1272
|
+
// Layout: u8 instruction (1) + u64 lamports (8) + u64 userStakeSeed (8) = 17 bytes
|
|
1273
|
+
const data = new Uint8Array(17)
|
|
1274
|
+
data[0] = 30 // instruction discriminator (WithdrawFromStakeAccountWithSession = 30)
|
|
1275
|
+
|
|
1276
|
+
// Write lamports as u64 little-endian (bytes 1-8)
|
|
1277
|
+
const lamportsBigInt = isFullWithdrawal ? U64_MAX : params.lamports
|
|
1278
|
+
for (let i = 0; i < 8; i++) {
|
|
1279
|
+
data[1 + i] = Number((lamportsBigInt >> BigInt(i * 8)) & BigInt(0xff))
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
// Write userStakeSeed as u64 little-endian (bytes 9-16)
|
|
1283
|
+
const seedBigInt = BigInt(params.userStakeSeed)
|
|
1284
|
+
for (let i = 0; i < 8; i++) {
|
|
1285
|
+
data[9 + i] = Number((seedBigInt >> BigInt(i * 8)) & BigInt(0xff))
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
// Account order matches Rust: stake_account, recipient, clock, stake_history, session_signer
|
|
1289
|
+
const keys = [
|
|
1290
|
+
{ pubkey: params.userStakeAccount, isSigner: false, isWritable: true },
|
|
1291
|
+
{ pubkey: params.userWallet, isSigner: false, isWritable: true },
|
|
1292
|
+
{ pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
|
|
1293
|
+
{ pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
|
|
1294
|
+
{ pubkey: params.sessionSigner, isSigner: true, isWritable: false },
|
|
1295
|
+
]
|
|
1296
|
+
|
|
1297
|
+
return new TransactionInstruction({
|
|
1298
|
+
programId: params.programId,
|
|
1299
|
+
keys,
|
|
1300
|
+
data: Buffer.from(data),
|
|
1301
|
+
})
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1235
1304
|
/**
|
|
1236
1305
|
* Creates an instruction to create metadata
|
|
1237
1306
|
* using the mpl token metadata program for the pool token
|
package/src/utils/stake.ts
CHANGED
|
@@ -84,7 +84,10 @@ export async function prepareWithdrawAccounts(
|
|
|
84
84
|
stakePoolAddress,
|
|
85
85
|
)
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
// For active stake accounts, subtract the minimum balance that must remain
|
|
88
|
+
// to allow for merges and maintain rent exemption
|
|
89
|
+
const availableActiveLamports = validator.activeStakeLamports.sub(minBalance)
|
|
90
|
+
if (availableActiveLamports.gt(new BN(0))) {
|
|
88
91
|
const isPreferred = stakePool?.preferredWithdrawValidatorVoteAddress?.equals(
|
|
89
92
|
validator.voteAccountAddress,
|
|
90
93
|
)
|
|
@@ -92,7 +95,7 @@ export async function prepareWithdrawAccounts(
|
|
|
92
95
|
type: isPreferred ? 'preferred' : 'active',
|
|
93
96
|
voteAddress: validator.voteAccountAddress,
|
|
94
97
|
stakeAddress: stakeAccountAddress,
|
|
95
|
-
lamports:
|
|
98
|
+
lamports: availableActiveLamports,
|
|
96
99
|
})
|
|
97
100
|
}
|
|
98
101
|
|