@ignitionfi/fogo-stake-pool 1.0.0

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.
@@ -0,0 +1,1439 @@
1
+ import * as BufferLayout from '@solana/buffer-layout'
2
+ import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token'
3
+ import {
4
+ PublicKey,
5
+ STAKE_CONFIG_ID,
6
+ StakeProgram,
7
+ SystemProgram,
8
+ SYSVAR_CLOCK_PUBKEY,
9
+ SYSVAR_RENT_PUBKEY,
10
+ SYSVAR_STAKE_HISTORY_PUBKEY,
11
+ TransactionInstruction,
12
+ } from '@solana/web3.js'
13
+ import {
14
+ DEVNET_STAKE_POOL_PROGRAM_ID,
15
+ METADATA_MAX_NAME_LENGTH,
16
+ METADATA_MAX_SYMBOL_LENGTH,
17
+ METADATA_MAX_URI_LENGTH,
18
+ METADATA_PROGRAM_ID,
19
+ STAKE_POOL_PROGRAM_ID,
20
+ } from './constants'
21
+ import { decodeData, encodeData, InstructionType } from './utils'
22
+
23
+ /**
24
+ * An enumeration of valid StakePoolInstructionType's
25
+ */
26
+ export type StakePoolInstructionType
27
+ = | 'IncreaseValidatorStake'
28
+ | 'DecreaseValidatorStake'
29
+ | 'UpdateValidatorListBalance'
30
+ | 'UpdateStakePoolBalance'
31
+ | 'CleanupRemovedValidatorEntries'
32
+ | 'DepositStake'
33
+ | 'DepositSol'
34
+ | 'WithdrawStake'
35
+ | 'WithdrawSol'
36
+ | 'IncreaseAdditionalValidatorStake'
37
+ | 'DecreaseAdditionalValidatorStake'
38
+ | 'DecreaseValidatorStakeWithReserve'
39
+ | 'Redelegate'
40
+ | 'AddValidatorToPool'
41
+ | 'RemoveValidatorFromPool'
42
+ | 'DepositWsolWithSession'
43
+ | 'WithdrawWsolWithSession'
44
+ | 'WithdrawStakeWithSession'
45
+ | 'WithdrawFromStakeAccountWithSession'
46
+
47
+ // 'UpdateTokenMetadata' and 'CreateTokenMetadata' have dynamic layouts
48
+
49
+ const MOVE_STAKE_LAYOUT = BufferLayout.struct<any>([
50
+ BufferLayout.u8('instruction'),
51
+ BufferLayout.ns64('lamports'),
52
+ BufferLayout.ns64('transientStakeSeed'),
53
+ ])
54
+
55
+ const UPDATE_VALIDATOR_LIST_BALANCE_LAYOUT = BufferLayout.struct<any>([
56
+ BufferLayout.u8('instruction'),
57
+ BufferLayout.u32('startIndex'),
58
+ BufferLayout.u8('noMerge'),
59
+ ])
60
+
61
+ export function tokenMetadataLayout(
62
+ instruction: number,
63
+ nameLength: number,
64
+ symbolLength: number,
65
+ uriLength: number,
66
+ ) {
67
+ if (nameLength > METADATA_MAX_NAME_LENGTH) {
68
+ // eslint-disable-next-line no-throw-literal
69
+ throw 'maximum token name length is 32 characters'
70
+ }
71
+
72
+ if (symbolLength > METADATA_MAX_SYMBOL_LENGTH) {
73
+ // eslint-disable-next-line no-throw-literal
74
+ throw 'maximum token symbol length is 10 characters'
75
+ }
76
+
77
+ if (uriLength > METADATA_MAX_URI_LENGTH) {
78
+ // eslint-disable-next-line no-throw-literal
79
+ throw 'maximum token uri length is 200 characters'
80
+ }
81
+
82
+ return {
83
+ index: instruction,
84
+ layout: BufferLayout.struct<any>([
85
+ BufferLayout.u8('instruction'),
86
+ BufferLayout.u32('nameLen'),
87
+ BufferLayout.blob(nameLength, 'name'),
88
+ BufferLayout.u32('symbolLen'),
89
+ BufferLayout.blob(symbolLength, 'symbol'),
90
+ BufferLayout.u32('uriLen'),
91
+ BufferLayout.blob(uriLength, 'uri'),
92
+ ]),
93
+ }
94
+ }
95
+
96
+ /**
97
+ * An enumeration of valid stake InstructionType's
98
+ * @internal
99
+ */
100
+ export const STAKE_POOL_INSTRUCTION_LAYOUTS: {
101
+ [type in StakePoolInstructionType]: InstructionType;
102
+ } = Object.freeze({
103
+ AddValidatorToPool: {
104
+ index: 1,
105
+ layout: BufferLayout.struct<any>([BufferLayout.u8('instruction'), BufferLayout.u32('seed')]),
106
+ },
107
+ RemoveValidatorFromPool: {
108
+ index: 2,
109
+ layout: BufferLayout.struct<any>([BufferLayout.u8('instruction')]),
110
+ },
111
+ DecreaseValidatorStake: {
112
+ index: 3,
113
+ layout: MOVE_STAKE_LAYOUT,
114
+ },
115
+ IncreaseValidatorStake: {
116
+ index: 4,
117
+ layout: MOVE_STAKE_LAYOUT,
118
+ },
119
+ UpdateValidatorListBalance: {
120
+ index: 6,
121
+ layout: UPDATE_VALIDATOR_LIST_BALANCE_LAYOUT,
122
+ },
123
+ UpdateStakePoolBalance: {
124
+ index: 7,
125
+ layout: BufferLayout.struct<any>([BufferLayout.u8('instruction')]),
126
+ },
127
+ CleanupRemovedValidatorEntries: {
128
+ index: 8,
129
+ layout: BufferLayout.struct<any>([BufferLayout.u8('instruction')]),
130
+ },
131
+ DepositStake: {
132
+ index: 9,
133
+ layout: BufferLayout.struct<any>([BufferLayout.u8('instruction')]),
134
+ },
135
+ /// Withdraw the token from the pool at the current ratio.
136
+ WithdrawStake: {
137
+ index: 10,
138
+ layout: BufferLayout.struct<any>([
139
+ BufferLayout.u8('instruction'),
140
+ BufferLayout.ns64('poolTokens'),
141
+ ]),
142
+ },
143
+ /// Deposit SOL directly into the pool's reserve account. The output is a "pool" token
144
+ /// representing ownership into the pool. Inputs are converted to the current ratio.
145
+ DepositSol: {
146
+ index: 14,
147
+ layout: BufferLayout.struct<any>([
148
+ BufferLayout.u8('instruction'),
149
+ BufferLayout.ns64('lamports'),
150
+ ]),
151
+ },
152
+ /// Withdraw SOL directly from the pool's reserve account. Fails if the
153
+ /// reserve does not have enough SOL.
154
+ WithdrawSol: {
155
+ index: 16,
156
+ layout: BufferLayout.struct<any>([
157
+ BufferLayout.u8('instruction'),
158
+ BufferLayout.ns64('poolTokens'),
159
+ ]),
160
+ },
161
+ IncreaseAdditionalValidatorStake: {
162
+ index: 19,
163
+ layout: BufferLayout.struct<any>([
164
+ BufferLayout.u8('instruction'),
165
+ BufferLayout.ns64('lamports'),
166
+ BufferLayout.ns64('transientStakeSeed'),
167
+ BufferLayout.ns64('ephemeralStakeSeed'),
168
+ ]),
169
+ },
170
+ DecreaseAdditionalValidatorStake: {
171
+ index: 20,
172
+ layout: BufferLayout.struct<any>([
173
+ BufferLayout.u8('instruction'),
174
+ BufferLayout.ns64('lamports'),
175
+ BufferLayout.ns64('transientStakeSeed'),
176
+ BufferLayout.ns64('ephemeralStakeSeed'),
177
+ ]),
178
+ },
179
+ DecreaseValidatorStakeWithReserve: {
180
+ index: 21,
181
+ layout: MOVE_STAKE_LAYOUT,
182
+ },
183
+ Redelegate: {
184
+ index: 22,
185
+ layout: BufferLayout.struct<any>([BufferLayout.u8('instruction')]),
186
+ },
187
+ DepositStakeWithSlippage: {
188
+ index: 23,
189
+ layout: BufferLayout.struct<any>([
190
+ BufferLayout.u8('instruction'),
191
+ BufferLayout.ns64('lamports'),
192
+ ]),
193
+ },
194
+ WithdrawStakeWithSlippage: {
195
+ index: 24,
196
+ layout: BufferLayout.struct<any>([
197
+ BufferLayout.u8('instruction'),
198
+ BufferLayout.ns64('poolTokensIn'),
199
+ BufferLayout.ns64('minimumLamportsOut'),
200
+ ]),
201
+ },
202
+ DepositSolWithSlippage: {
203
+ index: 25,
204
+ layout: BufferLayout.struct<any>([
205
+ BufferLayout.u8('instruction'),
206
+ BufferLayout.ns64('lamports'),
207
+ ]),
208
+ },
209
+ WithdrawSolWithSlippage: {
210
+ index: 26,
211
+ layout: BufferLayout.struct<any>([
212
+ BufferLayout.u8('instruction'),
213
+ BufferLayout.ns64('lamports'),
214
+ ]),
215
+ },
216
+ DepositWsolWithSession: {
217
+ index: 27,
218
+ layout: BufferLayout.struct<any>([
219
+ BufferLayout.u8('instruction'),
220
+ BufferLayout.ns64('lamportsIn'),
221
+ BufferLayout.ns64('minimumPoolTokensOut'),
222
+ ]),
223
+ },
224
+ WithdrawWsolWithSession: {
225
+ index: 28,
226
+ layout: BufferLayout.struct<any>([
227
+ BufferLayout.u8('instruction'),
228
+ BufferLayout.ns64('poolTokensIn'),
229
+ BufferLayout.ns64('minimumLamportsOut'),
230
+ ]),
231
+ },
232
+ WithdrawStakeWithSession: {
233
+ index: 29,
234
+ layout: BufferLayout.struct<any>([
235
+ BufferLayout.u8('instruction'),
236
+ BufferLayout.ns64('poolTokensIn'),
237
+ BufferLayout.ns64('minimumLamportsOut'),
238
+ BufferLayout.ns64('userStakeSeed'),
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
+ },
249
+ })
250
+
251
+ /**
252
+ * Cleans up validator stake account entries marked as `ReadyForRemoval`
253
+ */
254
+ export type CleanupRemovedValidatorEntriesParams = {
255
+ programId?: PublicKey | undefined
256
+ stakePool: PublicKey
257
+ validatorList: PublicKey
258
+ }
259
+
260
+ /**
261
+ * Updates balances of validator and transient stake accounts in the pool.
262
+ */
263
+ export type UpdateValidatorListBalanceParams = {
264
+ programId?: PublicKey | undefined
265
+ stakePool: PublicKey
266
+ withdrawAuthority: PublicKey
267
+ validatorList: PublicKey
268
+ reserveStake: PublicKey
269
+ validatorAndTransientStakePairs: PublicKey[]
270
+ startIndex: number
271
+ noMerge: boolean
272
+ }
273
+
274
+ /**
275
+ * Updates total pool balance based on balances in the reserve and validator list.
276
+ */
277
+ export type UpdateStakePoolBalanceParams = {
278
+ programId?: PublicKey | undefined
279
+ stakePool: PublicKey
280
+ withdrawAuthority: PublicKey
281
+ validatorList: PublicKey
282
+ reserveStake: PublicKey
283
+ managerFeeAccount: PublicKey
284
+ poolMint: PublicKey
285
+ }
286
+
287
+ /**
288
+ * (Staker only) Decrease active stake on a validator, eventually moving it to the reserve
289
+ */
290
+ export type DecreaseValidatorStakeParams = {
291
+ programId?: PublicKey | undefined
292
+ stakePool: PublicKey
293
+ staker: PublicKey
294
+ withdrawAuthority: PublicKey
295
+ validatorList: PublicKey
296
+ validatorStake: PublicKey
297
+ transientStake: PublicKey
298
+ // Amount of lamports to split into the transient stake account
299
+ lamports: number
300
+ // Seed to used to create the transient stake account
301
+ transientStakeSeed: number
302
+ }
303
+
304
+ export interface DecreaseValidatorStakeWithReserveParams extends DecreaseValidatorStakeParams {
305
+ reserveStake: PublicKey
306
+ }
307
+
308
+ export interface DecreaseAdditionalValidatorStakeParams extends DecreaseValidatorStakeParams {
309
+ reserveStake: PublicKey
310
+ ephemeralStake: PublicKey
311
+ ephemeralStakeSeed: number
312
+ }
313
+
314
+ /**
315
+ * (Staker only) Increase stake on a validator from the reserve account.
316
+ */
317
+ export type IncreaseValidatorStakeParams = {
318
+ programId?: PublicKey | undefined
319
+ stakePool: PublicKey
320
+ staker: PublicKey
321
+ withdrawAuthority: PublicKey
322
+ validatorList: PublicKey
323
+ reserveStake: PublicKey
324
+ transientStake: PublicKey
325
+ validatorStake: PublicKey
326
+ validatorVote: PublicKey
327
+ // Amount of lamports to split into the transient stake account
328
+ lamports: number
329
+ // Seed to used to create the transient stake account
330
+ transientStakeSeed: number
331
+ }
332
+
333
+ export interface IncreaseAdditionalValidatorStakeParams extends IncreaseValidatorStakeParams {
334
+ ephemeralStake: PublicKey
335
+ ephemeralStakeSeed: number
336
+ }
337
+
338
+ /**
339
+ * Deposits a stake account into the pool in exchange for pool tokens
340
+ */
341
+ export type DepositStakeParams = {
342
+ programId?: PublicKey | undefined
343
+ stakePool: PublicKey
344
+ validatorList: PublicKey
345
+ depositAuthority: PublicKey
346
+ withdrawAuthority: PublicKey
347
+ depositStake: PublicKey
348
+ validatorStake: PublicKey
349
+ reserveStake: PublicKey
350
+ destinationPoolAccount: PublicKey
351
+ managerFeeAccount: PublicKey
352
+ referralPoolAccount: PublicKey
353
+ poolMint: PublicKey
354
+ }
355
+
356
+ /**
357
+ * Withdraws a stake account from the pool in exchange for pool tokens
358
+ */
359
+ export type WithdrawStakeParams = {
360
+ programId?: PublicKey | undefined
361
+ stakePool: PublicKey
362
+ validatorList: PublicKey
363
+ withdrawAuthority: PublicKey
364
+ validatorStake: PublicKey
365
+ destinationStake: PublicKey
366
+ destinationStakeAuthority: PublicKey
367
+ sourceTransferAuthority: PublicKey
368
+ sourcePoolAccount: PublicKey
369
+ managerFeeAccount: PublicKey
370
+ poolMint: PublicKey
371
+ poolTokens: number
372
+ }
373
+
374
+ /**
375
+ * Withdraw sol instruction params
376
+ */
377
+ export type WithdrawSolParams = {
378
+ programId?: PublicKey | undefined
379
+ stakePool: PublicKey
380
+ sourcePoolAccount: PublicKey
381
+ withdrawAuthority: PublicKey
382
+ reserveStake: PublicKey
383
+ destinationSystemAccount: PublicKey
384
+ sourceTransferAuthority: PublicKey
385
+ solWithdrawAuthority?: PublicKey | undefined
386
+ managerFeeAccount: PublicKey
387
+ poolMint: PublicKey
388
+ poolTokens: number
389
+ }
390
+
391
+ /**
392
+ * Withdraw WSOL with session instruction params
393
+ */
394
+ export type WithdrawWsolWithSessionParams = {
395
+ programId: PublicKey
396
+ stakePool: PublicKey
397
+ withdrawAuthority: PublicKey
398
+ userTransferAuthority: PublicKey
399
+ poolTokensFrom: PublicKey
400
+ reserveStake: PublicKey
401
+ userWsolAccount: PublicKey
402
+ managerFeeAccount: PublicKey
403
+ poolMint: PublicKey
404
+ tokenProgramId: PublicKey
405
+ wsolMint: PublicKey
406
+ programSigner: PublicKey
407
+ userWallet: PublicKey
408
+ poolTokensIn: number
409
+ minimumLamportsOut: number
410
+ solWithdrawAuthority?: PublicKey
411
+ }
412
+
413
+ export type WithdrawStakeWithSessionParams = {
414
+ programId: PublicKey
415
+ stakePool: PublicKey
416
+ validatorList: PublicKey
417
+ withdrawAuthority: PublicKey
418
+ stakeToSplit: PublicKey
419
+ /** The stake account PDA that will receive the withdrawn stake (derived from user wallet + seed) */
420
+ stakeToReceive: PublicKey
421
+ /** The session signer (user or session) - used as both stake authority and transfer authority */
422
+ sessionSigner: PublicKey
423
+ burnFromPool: PublicKey
424
+ managerFeeAccount: PublicKey
425
+ poolMint: PublicKey
426
+ tokenProgramId: PublicKey
427
+ /** The program signer PDA derived from PROGRAM_SIGNER_SEED */
428
+ programSigner: PublicKey
429
+ /** The payer for stake account rent (typically the paymaster) */
430
+ payer: PublicKey
431
+ poolTokensIn: number
432
+ minimumLamportsOut: number
433
+ /** Seed used to derive the user stake PDA */
434
+ userStakeSeed: number
435
+ }
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 Number.MAX_SAFE_INTEGER for full withdrawal) */
448
+ lamports: number
449
+ }
450
+
451
+ /**
452
+ * Deposit SOL directly into the pool's reserve account. The output is a "pool" token
453
+ * representing ownership into the pool. Inputs are converted to the current ratio.
454
+ */
455
+ export type DepositSolParams = {
456
+ programId?: PublicKey | undefined
457
+ stakePool: PublicKey
458
+ depositAuthority?: PublicKey | undefined
459
+ withdrawAuthority: PublicKey
460
+ reserveStake: PublicKey
461
+ fundingAccount: PublicKey
462
+ destinationPoolAccount: PublicKey
463
+ managerFeeAccount: PublicKey
464
+ referralPoolAccount: PublicKey
465
+ poolMint: PublicKey
466
+ lamports: number
467
+ }
468
+
469
+ export type CreateTokenMetadataParams = {
470
+ programId?: PublicKey | undefined
471
+ stakePool: PublicKey
472
+ manager: PublicKey
473
+ tokenMetadata: PublicKey
474
+ withdrawAuthority: PublicKey
475
+ poolMint: PublicKey
476
+ payer: PublicKey
477
+ name: string
478
+ symbol: string
479
+ uri: string
480
+ }
481
+
482
+ export type UpdateTokenMetadataParams = {
483
+ programId?: PublicKey | undefined
484
+ stakePool: PublicKey
485
+ manager: PublicKey
486
+ tokenMetadata: PublicKey
487
+ withdrawAuthority: PublicKey
488
+ name: string
489
+ symbol: string
490
+ uri: string
491
+ }
492
+
493
+ export type AddValidatorToPoolParams = {
494
+ programId?: PublicKey | undefined
495
+ stakePool: PublicKey
496
+ staker: PublicKey
497
+ reserveStake: PublicKey
498
+ withdrawAuthority: PublicKey
499
+ validatorList: PublicKey
500
+ validatorStake: PublicKey
501
+ validatorVote: PublicKey
502
+ seed?: number
503
+ }
504
+
505
+ export type RemoveValidatorFromPoolParams = {
506
+ programId?: PublicKey | undefined
507
+ stakePool: PublicKey
508
+ staker: PublicKey
509
+ withdrawAuthority: PublicKey
510
+ validatorList: PublicKey
511
+ validatorStake: PublicKey
512
+ transientStake: PublicKey
513
+ }
514
+
515
+ /**
516
+ * Stake Pool Instruction class
517
+ */
518
+ export class StakePoolInstruction {
519
+ /**
520
+ * Creates instruction to add a validator into the stake pool.
521
+ */
522
+ static addValidatorToPool(params: AddValidatorToPoolParams): TransactionInstruction {
523
+ const {
524
+ programId,
525
+ stakePool,
526
+ staker,
527
+ reserveStake,
528
+ withdrawAuthority,
529
+ validatorList,
530
+ validatorStake,
531
+ validatorVote,
532
+ seed,
533
+ } = params
534
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.AddValidatorToPool
535
+ const data = encodeData(type, { seed: seed ?? 0 })
536
+
537
+ const keys = [
538
+ { pubkey: stakePool, isSigner: false, isWritable: true },
539
+ { pubkey: staker, isSigner: true, isWritable: false },
540
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
541
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
542
+ { pubkey: validatorList, isSigner: false, isWritable: true },
543
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
544
+ { pubkey: validatorVote, isSigner: false, isWritable: false },
545
+ { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
546
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
547
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
548
+ { pubkey: STAKE_CONFIG_ID, isSigner: false, isWritable: false },
549
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
550
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
551
+ ]
552
+
553
+ return new TransactionInstruction({
554
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
555
+ keys,
556
+ data,
557
+ })
558
+ }
559
+
560
+ /**
561
+ * Creates instruction to remove a validator from the stake pool.
562
+ */
563
+ static removeValidatorFromPool(params: RemoveValidatorFromPoolParams): TransactionInstruction {
564
+ const {
565
+ programId,
566
+ stakePool,
567
+ staker,
568
+ withdrawAuthority,
569
+ validatorList,
570
+ validatorStake,
571
+ transientStake,
572
+ } = params
573
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.RemoveValidatorFromPool
574
+ const data = encodeData(type)
575
+
576
+ const keys = [
577
+ { pubkey: stakePool, isSigner: false, isWritable: true },
578
+ { pubkey: staker, isSigner: true, isWritable: false },
579
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
580
+ { pubkey: validatorList, isSigner: false, isWritable: true },
581
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
582
+ { pubkey: transientStake, isSigner: false, isWritable: true },
583
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
584
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
585
+ ]
586
+
587
+ return new TransactionInstruction({
588
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
589
+ keys,
590
+ data,
591
+ })
592
+ }
593
+
594
+ /**
595
+ * Creates instruction to update a set of validators in the stake pool.
596
+ */
597
+ static updateValidatorListBalance(
598
+ params: UpdateValidatorListBalanceParams,
599
+ ): TransactionInstruction {
600
+ const {
601
+ programId,
602
+ stakePool,
603
+ withdrawAuthority,
604
+ validatorList,
605
+ reserveStake,
606
+ startIndex,
607
+ noMerge,
608
+ validatorAndTransientStakePairs,
609
+ } = params
610
+
611
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.UpdateValidatorListBalance
612
+ const data = encodeData(type, { startIndex, noMerge: noMerge ? 1 : 0 })
613
+
614
+ const keys = [
615
+ { pubkey: stakePool, isSigner: false, isWritable: false },
616
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
617
+ { pubkey: validatorList, isSigner: false, isWritable: true },
618
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
619
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
620
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
621
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
622
+ ...validatorAndTransientStakePairs.map(pubkey => ({
623
+ pubkey,
624
+ isSigner: false,
625
+ isWritable: true,
626
+ })),
627
+ ]
628
+
629
+ return new TransactionInstruction({
630
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
631
+ keys,
632
+ data,
633
+ })
634
+ }
635
+
636
+ /**
637
+ * Creates instruction to update the overall stake pool balance.
638
+ */
639
+ static updateStakePoolBalance(params: UpdateStakePoolBalanceParams): TransactionInstruction {
640
+ const {
641
+ programId,
642
+ stakePool,
643
+ withdrawAuthority,
644
+ validatorList,
645
+ reserveStake,
646
+ managerFeeAccount,
647
+ poolMint,
648
+ } = params
649
+
650
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.UpdateStakePoolBalance
651
+ const data = encodeData(type)
652
+
653
+ const keys = [
654
+ { pubkey: stakePool, isSigner: false, isWritable: true },
655
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
656
+ { pubkey: validatorList, isSigner: false, isWritable: true },
657
+ { pubkey: reserveStake, isSigner: false, isWritable: false },
658
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
659
+ { pubkey: poolMint, isSigner: false, isWritable: true },
660
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
661
+ ]
662
+
663
+ return new TransactionInstruction({
664
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
665
+ keys,
666
+ data,
667
+ })
668
+ }
669
+
670
+ /**
671
+ * Creates instruction to cleanup removed validator entries.
672
+ */
673
+ static cleanupRemovedValidatorEntries(
674
+ params: CleanupRemovedValidatorEntriesParams,
675
+ ): TransactionInstruction {
676
+ const { programId, stakePool, validatorList } = params
677
+
678
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.CleanupRemovedValidatorEntries
679
+ const data = encodeData(type)
680
+
681
+ const keys = [
682
+ { pubkey: stakePool, isSigner: false, isWritable: false },
683
+ { pubkey: validatorList, isSigner: false, isWritable: true },
684
+ ]
685
+
686
+ return new TransactionInstruction({
687
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
688
+ keys,
689
+ data,
690
+ })
691
+ }
692
+
693
+ /**
694
+ * Creates `IncreaseValidatorStake` instruction (rebalance from reserve account to
695
+ * transient account)
696
+ */
697
+ static increaseValidatorStake(params: IncreaseValidatorStakeParams): TransactionInstruction {
698
+ const {
699
+ programId,
700
+ stakePool,
701
+ staker,
702
+ withdrawAuthority,
703
+ validatorList,
704
+ reserveStake,
705
+ transientStake,
706
+ validatorStake,
707
+ validatorVote,
708
+ lamports,
709
+ transientStakeSeed,
710
+ } = params
711
+
712
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.IncreaseValidatorStake
713
+ const data = encodeData(type, { lamports, transientStakeSeed })
714
+
715
+ const keys = [
716
+ { pubkey: stakePool, isSigner: false, isWritable: false },
717
+ { pubkey: staker, isSigner: true, isWritable: false },
718
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
719
+ { pubkey: validatorList, isSigner: false, isWritable: true },
720
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
721
+ { pubkey: transientStake, isSigner: false, isWritable: true },
722
+ { pubkey: validatorStake, isSigner: false, isWritable: false },
723
+ { pubkey: validatorVote, isSigner: false, isWritable: false },
724
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
725
+ { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
726
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
727
+ { pubkey: STAKE_CONFIG_ID, isSigner: false, isWritable: false },
728
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
729
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
730
+ ]
731
+
732
+ return new TransactionInstruction({
733
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
734
+ keys,
735
+ data,
736
+ })
737
+ }
738
+
739
+ /**
740
+ * Creates `IncreaseAdditionalValidatorStake` instruction (rebalance from reserve account to
741
+ * transient account)
742
+ */
743
+ static increaseAdditionalValidatorStake(
744
+ params: IncreaseAdditionalValidatorStakeParams,
745
+ ): TransactionInstruction {
746
+ const {
747
+ programId,
748
+ stakePool,
749
+ staker,
750
+ withdrawAuthority,
751
+ validatorList,
752
+ reserveStake,
753
+ transientStake,
754
+ validatorStake,
755
+ validatorVote,
756
+ lamports,
757
+ transientStakeSeed,
758
+ ephemeralStake,
759
+ ephemeralStakeSeed,
760
+ } = params
761
+
762
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.IncreaseAdditionalValidatorStake
763
+ const data = encodeData(type, { lamports, transientStakeSeed, ephemeralStakeSeed })
764
+
765
+ const keys = [
766
+ { pubkey: stakePool, isSigner: false, isWritable: false },
767
+ { pubkey: staker, isSigner: true, isWritable: false },
768
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
769
+ { pubkey: validatorList, isSigner: false, isWritable: true },
770
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
771
+ { pubkey: ephemeralStake, isSigner: false, isWritable: true },
772
+ { pubkey: transientStake, isSigner: false, isWritable: true },
773
+ { pubkey: validatorStake, isSigner: false, isWritable: false },
774
+ { pubkey: validatorVote, isSigner: false, isWritable: false },
775
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
776
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
777
+ { pubkey: STAKE_CONFIG_ID, isSigner: false, isWritable: false },
778
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
779
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
780
+ ]
781
+
782
+ return new TransactionInstruction({
783
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
784
+ keys,
785
+ data,
786
+ })
787
+ }
788
+
789
+ /**
790
+ * Creates `DecreaseValidatorStake` instruction (rebalance from validator account to
791
+ * transient account)
792
+ */
793
+ static decreaseValidatorStake(params: DecreaseValidatorStakeParams): TransactionInstruction {
794
+ const {
795
+ programId,
796
+ stakePool,
797
+ staker,
798
+ withdrawAuthority,
799
+ validatorList,
800
+ validatorStake,
801
+ transientStake,
802
+ lamports,
803
+ transientStakeSeed,
804
+ } = params
805
+
806
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DecreaseValidatorStake
807
+ const data = encodeData(type, { lamports, transientStakeSeed })
808
+
809
+ const keys = [
810
+ { pubkey: stakePool, isSigner: false, isWritable: false },
811
+ { pubkey: staker, isSigner: true, isWritable: false },
812
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
813
+ { pubkey: validatorList, isSigner: false, isWritable: true },
814
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
815
+ { pubkey: transientStake, isSigner: false, isWritable: true },
816
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
817
+ { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
818
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
819
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
820
+ ]
821
+
822
+ return new TransactionInstruction({
823
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
824
+ keys,
825
+ data,
826
+ })
827
+ }
828
+
829
+ /**
830
+ * Creates `DecreaseValidatorStakeWithReserve` instruction (rebalance from
831
+ * validator account to transient account)
832
+ */
833
+ static decreaseValidatorStakeWithReserve(
834
+ params: DecreaseValidatorStakeWithReserveParams,
835
+ ): TransactionInstruction {
836
+ const {
837
+ programId,
838
+ stakePool,
839
+ staker,
840
+ withdrawAuthority,
841
+ validatorList,
842
+ reserveStake,
843
+ validatorStake,
844
+ transientStake,
845
+ lamports,
846
+ transientStakeSeed,
847
+ } = params
848
+
849
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DecreaseValidatorStakeWithReserve
850
+ const data = encodeData(type, { lamports, transientStakeSeed })
851
+
852
+ const keys = [
853
+ { pubkey: stakePool, isSigner: false, isWritable: false },
854
+ { pubkey: staker, isSigner: true, isWritable: false },
855
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
856
+ { pubkey: validatorList, isSigner: false, isWritable: true },
857
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
858
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
859
+ { pubkey: transientStake, isSigner: false, isWritable: true },
860
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
861
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
862
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
863
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
864
+ ]
865
+
866
+ return new TransactionInstruction({
867
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
868
+ keys,
869
+ data,
870
+ })
871
+ }
872
+
873
+ /**
874
+ * Creates `DecreaseAdditionalValidatorStake` instruction (rebalance from
875
+ * validator account to transient account)
876
+ */
877
+ static decreaseAdditionalValidatorStake(
878
+ params: DecreaseAdditionalValidatorStakeParams,
879
+ ): TransactionInstruction {
880
+ const {
881
+ programId,
882
+ stakePool,
883
+ staker,
884
+ withdrawAuthority,
885
+ validatorList,
886
+ reserveStake,
887
+ validatorStake,
888
+ transientStake,
889
+ lamports,
890
+ transientStakeSeed,
891
+ ephemeralStakeSeed,
892
+ ephemeralStake,
893
+ } = params
894
+
895
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DecreaseAdditionalValidatorStake
896
+ const data = encodeData(type, { lamports, transientStakeSeed, ephemeralStakeSeed })
897
+
898
+ const keys = [
899
+ { pubkey: stakePool, isSigner: false, isWritable: false },
900
+ { pubkey: staker, isSigner: true, isWritable: false },
901
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
902
+ { pubkey: validatorList, isSigner: false, isWritable: true },
903
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
904
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
905
+ { pubkey: ephemeralStake, isSigner: false, isWritable: true },
906
+ { pubkey: transientStake, isSigner: false, isWritable: true },
907
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
908
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
909
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
910
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
911
+ ]
912
+
913
+ return new TransactionInstruction({
914
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
915
+ keys,
916
+ data,
917
+ })
918
+ }
919
+
920
+ /**
921
+ * Creates a transaction instruction to deposit a stake account into a stake pool.
922
+ */
923
+ static depositStake(params: DepositStakeParams): TransactionInstruction {
924
+ const {
925
+ programId,
926
+ stakePool,
927
+ validatorList,
928
+ depositAuthority,
929
+ withdrawAuthority,
930
+ depositStake,
931
+ validatorStake,
932
+ reserveStake,
933
+ destinationPoolAccount,
934
+ managerFeeAccount,
935
+ referralPoolAccount,
936
+ poolMint,
937
+ } = params
938
+
939
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DepositStake
940
+ const data = encodeData(type)
941
+
942
+ const keys = [
943
+ { pubkey: stakePool, isSigner: false, isWritable: true },
944
+ { pubkey: validatorList, isSigner: false, isWritable: true },
945
+ { pubkey: depositAuthority, isSigner: false, isWritable: false },
946
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
947
+ { pubkey: depositStake, isSigner: false, isWritable: true },
948
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
949
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
950
+ { pubkey: destinationPoolAccount, isSigner: false, isWritable: true },
951
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
952
+ { pubkey: referralPoolAccount, isSigner: false, isWritable: true },
953
+ { pubkey: poolMint, isSigner: false, isWritable: true },
954
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
955
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
956
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
957
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
958
+ ]
959
+
960
+ return new TransactionInstruction({
961
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
962
+ keys,
963
+ data,
964
+ })
965
+ }
966
+
967
+ /**
968
+ * Creates a transaction instruction to deposit SOL into a stake pool.
969
+ */
970
+ static depositSol(params: DepositSolParams): TransactionInstruction {
971
+ const {
972
+ programId,
973
+ stakePool,
974
+ withdrawAuthority,
975
+ depositAuthority,
976
+ reserveStake,
977
+ fundingAccount,
978
+ destinationPoolAccount,
979
+ managerFeeAccount,
980
+ referralPoolAccount,
981
+ poolMint,
982
+ lamports,
983
+ } = params
984
+
985
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DepositSol
986
+ const data = encodeData(type, { lamports })
987
+
988
+ const keys = [
989
+ { pubkey: stakePool, isSigner: false, isWritable: true },
990
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
991
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
992
+ { pubkey: fundingAccount, isSigner: true, isWritable: true },
993
+ { pubkey: destinationPoolAccount, isSigner: false, isWritable: true },
994
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
995
+ { pubkey: referralPoolAccount, isSigner: false, isWritable: true },
996
+ { pubkey: poolMint, isSigner: false, isWritable: true },
997
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
998
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
999
+ ]
1000
+
1001
+ if (depositAuthority) {
1002
+ keys.push({
1003
+ pubkey: depositAuthority,
1004
+ isSigner: true,
1005
+ isWritable: false,
1006
+ })
1007
+ }
1008
+
1009
+ return new TransactionInstruction({
1010
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
1011
+ keys,
1012
+ data,
1013
+ })
1014
+ }
1015
+
1016
+ /**
1017
+ * Creates a transaction instruction to deposit WSOL into a stake pool.
1018
+ */
1019
+ static depositWsolWithSession(params: Omit<DepositSolParams, 'lamports'> & {
1020
+ wsolMint: PublicKey
1021
+ wsolTokenAccount: PublicKey
1022
+ wsolTransientAccount: PublicKey
1023
+ programSigner: PublicKey
1024
+ tokenProgramId: PublicKey
1025
+ programId: PublicKey
1026
+ userWallet: PublicKey
1027
+ lamportsIn: number
1028
+ minimumPoolTokensOut: number
1029
+ payer?: PublicKey
1030
+ }): TransactionInstruction {
1031
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DepositWsolWithSession
1032
+ const data = encodeData(type, {
1033
+ lamportsIn: params.lamportsIn,
1034
+ minimumPoolTokensOut: params.minimumPoolTokensOut,
1035
+ })
1036
+
1037
+ const keys = [
1038
+ { pubkey: params.stakePool, isSigner: false, isWritable: true },
1039
+ { pubkey: params.withdrawAuthority, isSigner: false, isWritable: false },
1040
+ { pubkey: params.reserveStake, isSigner: false, isWritable: true },
1041
+ { pubkey: params.fundingAccount, isSigner: true, isWritable: true },
1042
+ { pubkey: params.destinationPoolAccount, isSigner: false, isWritable: true },
1043
+ { pubkey: params.managerFeeAccount, isSigner: false, isWritable: true },
1044
+ { pubkey: params.referralPoolAccount, isSigner: false, isWritable: true },
1045
+ { pubkey: params.poolMint, isSigner: false, isWritable: true },
1046
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
1047
+ { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
1048
+
1049
+ // wsol specific accounts
1050
+ { pubkey: params.wsolMint, isSigner: false, isWritable: false },
1051
+ { pubkey: params.wsolTokenAccount, isSigner: false, isWritable: true },
1052
+ { pubkey: params.wsolTransientAccount, isSigner: false, isWritable: true },
1053
+ { pubkey: params.programSigner, isSigner: false, isWritable: true },
1054
+ { pubkey: params.payer ?? params.fundingAccount, isSigner: true, isWritable: true },
1055
+ { pubkey: params.userWallet, isSigner: false, isWritable: false },
1056
+ ]
1057
+
1058
+ if (params.depositAuthority) {
1059
+ keys.push({
1060
+ pubkey: params.depositAuthority,
1061
+ isSigner: true,
1062
+ isWritable: false,
1063
+ })
1064
+ }
1065
+
1066
+ // Associated Token Program must be last - only needed in transaction for CPI routing
1067
+ keys.push({ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false })
1068
+
1069
+ return new TransactionInstruction({
1070
+ programId: params.programId,
1071
+ keys,
1072
+ data,
1073
+ })
1074
+ }
1075
+
1076
+ /**
1077
+ * Creates a transaction instruction to withdraw active stake from a stake pool.
1078
+ */
1079
+ static withdrawStake(params: WithdrawStakeParams): TransactionInstruction {
1080
+ const {
1081
+ programId,
1082
+ stakePool,
1083
+ validatorList,
1084
+ withdrawAuthority,
1085
+ validatorStake,
1086
+ destinationStake,
1087
+ destinationStakeAuthority,
1088
+ sourceTransferAuthority,
1089
+ sourcePoolAccount,
1090
+ managerFeeAccount,
1091
+ poolMint,
1092
+ poolTokens,
1093
+ } = params
1094
+
1095
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawStake
1096
+ const data = encodeData(type, { poolTokens })
1097
+
1098
+ const keys = [
1099
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1100
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1101
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1102
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1103
+ { pubkey: destinationStake, isSigner: false, isWritable: true },
1104
+ { pubkey: destinationStakeAuthority, isSigner: false, isWritable: false },
1105
+ { pubkey: sourceTransferAuthority, isSigner: true, isWritable: false },
1106
+ { pubkey: sourcePoolAccount, isSigner: false, isWritable: true },
1107
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
1108
+ { pubkey: poolMint, isSigner: false, isWritable: true },
1109
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1110
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
1111
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
1112
+ ]
1113
+
1114
+ return new TransactionInstruction({
1115
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
1116
+ keys,
1117
+ data,
1118
+ })
1119
+ }
1120
+
1121
+ /**
1122
+ * Creates a transaction instruction to withdraw SOL from a stake pool.
1123
+ */
1124
+ static withdrawSol(params: WithdrawSolParams): TransactionInstruction {
1125
+ const {
1126
+ programId,
1127
+ stakePool,
1128
+ withdrawAuthority,
1129
+ sourceTransferAuthority,
1130
+ sourcePoolAccount,
1131
+ reserveStake,
1132
+ destinationSystemAccount,
1133
+ managerFeeAccount,
1134
+ solWithdrawAuthority,
1135
+ poolMint,
1136
+ poolTokens,
1137
+ } = params
1138
+
1139
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawSol
1140
+ const data = encodeData(type, { poolTokens })
1141
+
1142
+ const keys = [
1143
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1144
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1145
+ { pubkey: sourceTransferAuthority, isSigner: true, isWritable: false },
1146
+ { pubkey: sourcePoolAccount, isSigner: false, isWritable: true },
1147
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1148
+ { pubkey: destinationSystemAccount, isSigner: false, isWritable: true },
1149
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
1150
+ { pubkey: poolMint, isSigner: false, isWritable: true },
1151
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1152
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1153
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
1154
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
1155
+ ]
1156
+
1157
+ if (solWithdrawAuthority) {
1158
+ keys.push({
1159
+ pubkey: solWithdrawAuthority,
1160
+ isSigner: true,
1161
+ isWritable: false,
1162
+ })
1163
+ }
1164
+
1165
+ return new TransactionInstruction({
1166
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
1167
+ keys,
1168
+ data,
1169
+ })
1170
+ }
1171
+
1172
+ /**
1173
+ * Creates a transaction instruction to withdraw WSOL from a stake pool using a session.
1174
+ * Rent for ATA creation (if needed) is paid from the withdrawal amount.
1175
+ */
1176
+ static withdrawWsolWithSession(
1177
+ params: WithdrawWsolWithSessionParams,
1178
+ ): TransactionInstruction {
1179
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawWsolWithSession
1180
+ const data = encodeData(type, {
1181
+ poolTokensIn: params.poolTokensIn,
1182
+ minimumLamportsOut: params.minimumLamportsOut,
1183
+ })
1184
+
1185
+ const keys = [
1186
+ { pubkey: params.stakePool, isSigner: false, isWritable: true },
1187
+ { pubkey: params.withdrawAuthority, isSigner: false, isWritable: false },
1188
+ { pubkey: params.userTransferAuthority, isSigner: true, isWritable: true },
1189
+ { pubkey: params.poolTokensFrom, isSigner: false, isWritable: true },
1190
+ { pubkey: params.reserveStake, isSigner: false, isWritable: true },
1191
+ { pubkey: params.userWsolAccount, isSigner: false, isWritable: true },
1192
+ { pubkey: params.managerFeeAccount, isSigner: false, isWritable: true },
1193
+ { pubkey: params.poolMint, isSigner: false, isWritable: true },
1194
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1195
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1196
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
1197
+ { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
1198
+
1199
+ { pubkey: params.wsolMint, isSigner: false, isWritable: false },
1200
+ { pubkey: params.programSigner, isSigner: false, isWritable: true },
1201
+ { pubkey: params.userWallet, isSigner: false, isWritable: false },
1202
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
1203
+ ]
1204
+
1205
+ if (params.solWithdrawAuthority) {
1206
+ keys.push({
1207
+ pubkey: params.solWithdrawAuthority,
1208
+ isSigner: true,
1209
+ isWritable: false,
1210
+ })
1211
+ }
1212
+
1213
+ // Associated Token Program must be last - only needed in transaction for CPI routing
1214
+ keys.push({ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false })
1215
+
1216
+ return new TransactionInstruction({
1217
+ programId: params.programId,
1218
+ keys,
1219
+ data,
1220
+ })
1221
+ }
1222
+
1223
+ /**
1224
+ * Creates a transaction instruction to withdraw stake from a stake pool using a Fogo session.
1225
+ * The stake account is created as a PDA and rent is paid by the payer (typically paymaster).
1226
+ */
1227
+ static withdrawStakeWithSession(params: WithdrawStakeWithSessionParams): TransactionInstruction {
1228
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawStakeWithSession
1229
+ const data = encodeData(type, {
1230
+ poolTokensIn: params.poolTokensIn,
1231
+ minimumLamportsOut: params.minimumLamportsOut,
1232
+ userStakeSeed: params.userStakeSeed,
1233
+ })
1234
+
1235
+ const keys = [
1236
+ { pubkey: params.stakePool, isSigner: false, isWritable: true },
1237
+ { pubkey: params.validatorList, isSigner: false, isWritable: true },
1238
+ { pubkey: params.withdrawAuthority, isSigner: false, isWritable: false },
1239
+ { pubkey: params.stakeToSplit, isSigner: false, isWritable: true },
1240
+ { pubkey: params.stakeToReceive, isSigner: false, isWritable: true },
1241
+ { pubkey: params.sessionSigner, isSigner: true, isWritable: false }, // user_stake_authority_info (signer_or_session)
1242
+ { pubkey: params.sessionSigner, isSigner: false, isWritable: false }, // user_transfer_authority_info (not used in session path)
1243
+ { pubkey: params.burnFromPool, isSigner: false, isWritable: true },
1244
+ { pubkey: params.managerFeeAccount, isSigner: false, isWritable: true },
1245
+ { pubkey: params.poolMint, isSigner: false, isWritable: true },
1246
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1247
+ { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
1248
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
1249
+ { pubkey: params.programSigner, isSigner: false, isWritable: false },
1250
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
1251
+ { pubkey: params.payer, isSigner: true, isWritable: true },
1252
+ ]
1253
+
1254
+ return new TransactionInstruction({
1255
+ programId: params.programId,
1256
+ keys,
1257
+ data,
1258
+ })
1259
+ }
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
+ */
1265
+ static withdrawFromStakeAccountWithSession(params: WithdrawFromStakeAccountWithSessionParams): TransactionInstruction {
1266
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawFromStakeAccountWithSession
1267
+ const data = encodeData(type, {
1268
+ lamports: params.lamports,
1269
+ userStakeSeed: params.userStakeSeed,
1270
+ })
1271
+
1272
+ const keys = [
1273
+ { pubkey: params.userStakeAccount, isSigner: false, isWritable: true },
1274
+ { pubkey: params.userWallet, isSigner: false, isWritable: true },
1275
+ { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1276
+ { pubkey: SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1277
+ { pubkey: params.sessionSigner, isSigner: true, isWritable: false },
1278
+ { pubkey: StakeProgram.programId, isSigner: false, isWritable: false },
1279
+ ]
1280
+
1281
+ return new TransactionInstruction({
1282
+ programId: params.programId,
1283
+ keys,
1284
+ data,
1285
+ })
1286
+ }
1287
+
1288
+ /**
1289
+ * Creates an instruction to create metadata
1290
+ * using the mpl token metadata program for the pool token
1291
+ */
1292
+ static createTokenMetadata(params: CreateTokenMetadataParams): TransactionInstruction {
1293
+ const {
1294
+ programId,
1295
+ stakePool,
1296
+ withdrawAuthority,
1297
+ tokenMetadata,
1298
+ manager,
1299
+ payer,
1300
+ poolMint,
1301
+ name,
1302
+ symbol,
1303
+ uri,
1304
+ } = params
1305
+
1306
+ const keys = [
1307
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1308
+ { pubkey: manager, isSigner: true, isWritable: false },
1309
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1310
+ { pubkey: poolMint, isSigner: false, isWritable: false },
1311
+ { pubkey: payer, isSigner: true, isWritable: true },
1312
+ { pubkey: tokenMetadata, isSigner: false, isWritable: true },
1313
+ { pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false },
1314
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
1315
+ { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
1316
+ ]
1317
+
1318
+ const type = tokenMetadataLayout(17, name.length, symbol.length, uri.length)
1319
+ const data = encodeData(type, {
1320
+ nameLen: name.length,
1321
+ name: Buffer.from(name),
1322
+ symbolLen: symbol.length,
1323
+ symbol: Buffer.from(symbol),
1324
+ uriLen: uri.length,
1325
+ uri: Buffer.from(uri),
1326
+ })
1327
+
1328
+ return new TransactionInstruction({
1329
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
1330
+ keys,
1331
+ data,
1332
+ })
1333
+ }
1334
+
1335
+ /**
1336
+ * Creates an instruction to update metadata
1337
+ * in the mpl token metadata program account for the pool token
1338
+ */
1339
+ static updateTokenMetadata(params: UpdateTokenMetadataParams): TransactionInstruction {
1340
+ const { programId, stakePool, withdrawAuthority, tokenMetadata, manager, name, symbol, uri }
1341
+ = params
1342
+
1343
+ const keys = [
1344
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1345
+ { pubkey: manager, isSigner: true, isWritable: false },
1346
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1347
+ { pubkey: tokenMetadata, isSigner: false, isWritable: true },
1348
+ { pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false },
1349
+ ]
1350
+
1351
+ const type = tokenMetadataLayout(18, name.length, symbol.length, uri.length)
1352
+ const data = encodeData(type, {
1353
+ nameLen: name.length,
1354
+ name: Buffer.from(name),
1355
+ symbolLen: symbol.length,
1356
+ symbol: Buffer.from(symbol),
1357
+ uriLen: uri.length,
1358
+ uri: Buffer.from(uri),
1359
+ })
1360
+
1361
+ return new TransactionInstruction({
1362
+ programId: programId ?? STAKE_POOL_PROGRAM_ID,
1363
+ keys,
1364
+ data,
1365
+ })
1366
+ }
1367
+
1368
+ /**
1369
+ * Decode a deposit stake pool instruction and retrieve the instruction params.
1370
+ */
1371
+ static decodeDepositStake(instruction: TransactionInstruction): DepositStakeParams {
1372
+ this.checkProgramId(instruction.programId)
1373
+ this.checkKeyLength(instruction.keys, 11)
1374
+
1375
+ decodeData(STAKE_POOL_INSTRUCTION_LAYOUTS.DepositStake, instruction.data)
1376
+
1377
+ return {
1378
+ programId: instruction.programId,
1379
+ stakePool: instruction.keys[0].pubkey,
1380
+ validatorList: instruction.keys[1].pubkey,
1381
+ depositAuthority: instruction.keys[2].pubkey,
1382
+ withdrawAuthority: instruction.keys[3].pubkey,
1383
+ depositStake: instruction.keys[4].pubkey,
1384
+ validatorStake: instruction.keys[5].pubkey,
1385
+ reserveStake: instruction.keys[6].pubkey,
1386
+ destinationPoolAccount: instruction.keys[7].pubkey,
1387
+ managerFeeAccount: instruction.keys[8].pubkey,
1388
+ referralPoolAccount: instruction.keys[9].pubkey,
1389
+ poolMint: instruction.keys[10].pubkey,
1390
+ }
1391
+ }
1392
+
1393
+ /**
1394
+ * Decode a deposit sol instruction and retrieve the instruction params.
1395
+ */
1396
+ static decodeDepositSol(instruction: TransactionInstruction): DepositSolParams {
1397
+ this.checkProgramId(instruction.programId)
1398
+ this.checkKeyLength(instruction.keys, 9)
1399
+
1400
+ const { amount } = decodeData(STAKE_POOL_INSTRUCTION_LAYOUTS.DepositSol, instruction.data)
1401
+
1402
+ return {
1403
+ programId: instruction.programId,
1404
+ stakePool: instruction.keys[0].pubkey,
1405
+ depositAuthority: instruction.keys[1].pubkey,
1406
+ withdrawAuthority: instruction.keys[2].pubkey,
1407
+ reserveStake: instruction.keys[3].pubkey,
1408
+ fundingAccount: instruction.keys[4].pubkey,
1409
+ destinationPoolAccount: instruction.keys[5].pubkey,
1410
+ managerFeeAccount: instruction.keys[6].pubkey,
1411
+ referralPoolAccount: instruction.keys[7].pubkey,
1412
+ poolMint: instruction.keys[8].pubkey,
1413
+ lamports: amount,
1414
+ }
1415
+ }
1416
+
1417
+ /**
1418
+ * @internal
1419
+ */
1420
+ private static checkProgramId(programId: PublicKey) {
1421
+ if (
1422
+ !programId.equals(STAKE_POOL_PROGRAM_ID)
1423
+ && !programId.equals(DEVNET_STAKE_POOL_PROGRAM_ID)
1424
+ ) {
1425
+ throw new Error('Invalid instruction; programId is not the stake pool program')
1426
+ }
1427
+ }
1428
+
1429
+ /**
1430
+ * @internal
1431
+ */
1432
+ private static checkKeyLength(keys: Array<any>, expectedLength: number) {
1433
+ if (keys.length < expectedLength) {
1434
+ throw new Error(
1435
+ `Invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`,
1436
+ )
1437
+ }
1438
+ }
1439
+ }