@ignitionfi/spl-stake-pool 1.1.8

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,2570 @@
1
+ 'use strict';
2
+
3
+ var splToken = require('@solana/spl-token');
4
+ var web3_js = require('@solana/web3.js');
5
+ var BN = require('bn.js');
6
+ var node_buffer = require('node:buffer');
7
+ var BufferLayout = require('@solana/buffer-layout');
8
+ var bufferLayout = require('buffer-layout');
9
+
10
+ function _interopNamespaceDefault(e) {
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var BufferLayout__namespace = /*#__PURE__*/_interopNamespaceDefault(BufferLayout);
28
+
29
+ /**
30
+ * A `StructFailure` represents a single specific failure in validation.
31
+ */
32
+ /**
33
+ * `StructError` objects are thrown (or returned) when validation fails.
34
+ *
35
+ * Validation logic is design to exit early for maximum performance. The error
36
+ * represents the first error encountered during validation. For more detail,
37
+ * the `error.failures` property is a generator function that can be run to
38
+ * continue validation and receive all the failures in the data.
39
+ */
40
+ class StructError extends TypeError {
41
+ constructor(failure, failures) {
42
+ let cached;
43
+ const { message, explanation, ...rest } = failure;
44
+ const { path } = failure;
45
+ const msg = path.length === 0 ? message : `At path: ${path.join('.')} -- ${message}`;
46
+ super(explanation ?? msg);
47
+ if (explanation != null)
48
+ this.cause = msg;
49
+ Object.assign(this, rest);
50
+ this.name = this.constructor.name;
51
+ this.failures = () => {
52
+ return (cached ?? (cached = [failure, ...failures()]));
53
+ };
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Check if a value is an iterator.
59
+ */
60
+ function isIterable(x) {
61
+ return isObject(x) && typeof x[Symbol.iterator] === 'function';
62
+ }
63
+ /**
64
+ * Check if a value is a plain object.
65
+ */
66
+ function isObject(x) {
67
+ return typeof x === 'object' && x != null;
68
+ }
69
+ /**
70
+ * Check if a value is a non-array object.
71
+ */
72
+ function isNonArrayObject(x) {
73
+ return isObject(x) && !Array.isArray(x);
74
+ }
75
+ /**
76
+ * Return a value as a printable string.
77
+ */
78
+ function print(value) {
79
+ if (typeof value === 'symbol') {
80
+ return value.toString();
81
+ }
82
+ return typeof value === 'string' ? JSON.stringify(value) : `${value}`;
83
+ }
84
+ /**
85
+ * Shifts (removes and returns) the first value from the `input` iterator.
86
+ * Like `Array.prototype.shift()` but for an `Iterator`.
87
+ */
88
+ function shiftIterator(input) {
89
+ const { done, value } = input.next();
90
+ return done ? undefined : value;
91
+ }
92
+ /**
93
+ * Convert a single validation result to a failure.
94
+ */
95
+ function toFailure(result, context, struct, value) {
96
+ if (result === true) {
97
+ return;
98
+ }
99
+ else if (result === false) {
100
+ result = {};
101
+ }
102
+ else if (typeof result === 'string') {
103
+ result = { message: result };
104
+ }
105
+ const { path, branch } = context;
106
+ const { type } = struct;
107
+ const { refinement, message = `Expected a value of type \`${type}\`${refinement ? ` with refinement \`${refinement}\`` : ''}, but received: \`${print(value)}\``, } = result;
108
+ return {
109
+ value,
110
+ type,
111
+ refinement,
112
+ key: path[path.length - 1],
113
+ path,
114
+ branch,
115
+ ...result,
116
+ message,
117
+ };
118
+ }
119
+ /**
120
+ * Convert a validation result to an iterable of failures.
121
+ */
122
+ function* toFailures(result, context, struct, value) {
123
+ if (!isIterable(result)) {
124
+ result = [result];
125
+ }
126
+ for (const r of result) {
127
+ const failure = toFailure(r, context, struct, value);
128
+ if (failure) {
129
+ yield failure;
130
+ }
131
+ }
132
+ }
133
+ /**
134
+ * Check a value against a struct, traversing deeply into nested values, and
135
+ * returning an iterator of failures or success.
136
+ */
137
+ function* run(value, struct, options = {}) {
138
+ const { path = [], branch = [value], coerce = false, mask = false } = options;
139
+ const ctx = { path, branch, mask };
140
+ if (coerce) {
141
+ value = struct.coercer(value, ctx);
142
+ }
143
+ let status = 'valid';
144
+ for (const failure of struct.validator(value, ctx)) {
145
+ failure.explanation = options.message;
146
+ status = 'not_valid';
147
+ yield [failure, undefined];
148
+ }
149
+ for (let [k, v, s] of struct.entries(value, ctx)) {
150
+ const ts = run(v, s, {
151
+ path: k === undefined ? path : [...path, k],
152
+ branch: k === undefined ? branch : [...branch, v],
153
+ coerce,
154
+ mask,
155
+ message: options.message,
156
+ });
157
+ for (const t of ts) {
158
+ if (t[0]) {
159
+ status = t[0].refinement != null ? 'not_refined' : 'not_valid';
160
+ yield [t[0], undefined];
161
+ }
162
+ else if (coerce) {
163
+ v = t[1];
164
+ if (k === undefined) {
165
+ value = v;
166
+ }
167
+ else if (value instanceof Map) {
168
+ value.set(k, v);
169
+ }
170
+ else if (value instanceof Set) {
171
+ value.add(v);
172
+ }
173
+ else if (isObject(value)) {
174
+ if (v !== undefined || k in value)
175
+ value[k] = v;
176
+ }
177
+ }
178
+ }
179
+ }
180
+ if (status !== 'not_valid') {
181
+ for (const failure of struct.refiner(value, ctx)) {
182
+ failure.explanation = options.message;
183
+ status = 'not_refined';
184
+ yield [failure, undefined];
185
+ }
186
+ }
187
+ if (status === 'valid') {
188
+ yield [undefined, value];
189
+ }
190
+ }
191
+
192
+ /**
193
+ * `Struct` objects encapsulate the validation logic for a specific type of
194
+ * values. Once constructed, you use the `assert`, `is` or `validate` helpers to
195
+ * validate unknown input data against the struct.
196
+ */
197
+ class Struct {
198
+ constructor(props) {
199
+ const { type, schema, validator, refiner, coercer = (value) => value, entries = function* () { }, } = props;
200
+ this.type = type;
201
+ this.schema = schema;
202
+ this.entries = entries;
203
+ this.coercer = coercer;
204
+ if (validator) {
205
+ this.validator = (value, context) => {
206
+ const result = validator(value, context);
207
+ return toFailures(result, context, this, value);
208
+ };
209
+ }
210
+ else {
211
+ this.validator = () => [];
212
+ }
213
+ if (refiner) {
214
+ this.refiner = (value, context) => {
215
+ const result = refiner(value, context);
216
+ return toFailures(result, context, this, value);
217
+ };
218
+ }
219
+ else {
220
+ this.refiner = () => [];
221
+ }
222
+ }
223
+ /**
224
+ * Assert that a value passes the struct's validation, throwing if it doesn't.
225
+ */
226
+ assert(value, message) {
227
+ return assert(value, this, message);
228
+ }
229
+ /**
230
+ * Create a value with the struct's coercion logic, then validate it.
231
+ */
232
+ create(value, message) {
233
+ return create(value, this, message);
234
+ }
235
+ /**
236
+ * Check if a value passes the struct's validation.
237
+ */
238
+ is(value) {
239
+ return is(value, this);
240
+ }
241
+ /**
242
+ * Mask a value, coercing and validating it, but returning only the subset of
243
+ * properties defined by the struct's schema. Masking applies recursively to
244
+ * props of `object` structs only.
245
+ */
246
+ mask(value, message) {
247
+ return mask(value, this, message);
248
+ }
249
+ /**
250
+ * Validate a value with the struct's validation logic, returning a tuple
251
+ * representing the result.
252
+ *
253
+ * You may optionally pass `true` for the `coerce` argument to coerce
254
+ * the value before attempting to validate it. If you do, the result will
255
+ * contain the coerced result when successful. Also, `mask` will turn on
256
+ * masking of the unknown `object` props recursively if passed.
257
+ */
258
+ validate(value, options = {}) {
259
+ return validate(value, this, options);
260
+ }
261
+ }
262
+ /**
263
+ * Assert that a value passes a struct, throwing if it doesn't.
264
+ */
265
+ function assert(value, struct, message) {
266
+ const result = validate(value, struct, { message });
267
+ if (result[0]) {
268
+ throw result[0];
269
+ }
270
+ }
271
+ /**
272
+ * Create a value with the coercion logic of struct and validate it.
273
+ */
274
+ function create(value, struct, message) {
275
+ const result = validate(value, struct, { coerce: true, message });
276
+ if (result[0]) {
277
+ throw result[0];
278
+ }
279
+ else {
280
+ return result[1];
281
+ }
282
+ }
283
+ /**
284
+ * Mask a value, returning only the subset of properties defined by a struct.
285
+ */
286
+ function mask(value, struct, message) {
287
+ const result = validate(value, struct, { coerce: true, mask: true, message });
288
+ if (result[0]) {
289
+ throw result[0];
290
+ }
291
+ else {
292
+ return result[1];
293
+ }
294
+ }
295
+ /**
296
+ * Check if a value passes a struct.
297
+ */
298
+ function is(value, struct) {
299
+ const result = validate(value, struct);
300
+ return !result[0];
301
+ }
302
+ /**
303
+ * Validate a value against a struct, returning an error if invalid, or the
304
+ * value (with potential coercion) if valid.
305
+ */
306
+ function validate(value, struct, options = {}) {
307
+ const tuples = run(value, struct, options);
308
+ const tuple = shiftIterator(tuples);
309
+ if (tuple[0]) {
310
+ const error = new StructError(tuple[0], function* () {
311
+ for (const t of tuples) {
312
+ if (t[0]) {
313
+ yield t[0];
314
+ }
315
+ }
316
+ });
317
+ return [error, undefined];
318
+ }
319
+ else {
320
+ const v = tuple[1];
321
+ return [undefined, v];
322
+ }
323
+ }
324
+ /**
325
+ * Define a new struct type with a custom validation function.
326
+ */
327
+ function define(name, validator) {
328
+ return new Struct({ type: name, schema: null, validator });
329
+ }
330
+ function enums(values) {
331
+ const schema = {};
332
+ const description = values.map((v) => print(v)).join();
333
+ for (const key of values) {
334
+ schema[key] = key;
335
+ }
336
+ return new Struct({
337
+ type: 'enums',
338
+ schema,
339
+ validator(value) {
340
+ return (values.includes(value) ||
341
+ `Expected one of \`${description}\`, but received: ${print(value)}`);
342
+ },
343
+ });
344
+ }
345
+ /**
346
+ * Ensure that a value is an instance of a specific class.
347
+ */
348
+ function instance(Class) {
349
+ return define('instance', (value) => {
350
+ return (value instanceof Class ||
351
+ `Expected a \`${Class.name}\` instance, but received: ${print(value)}`);
352
+ });
353
+ }
354
+ /**
355
+ * Augment an existing struct to allow `null` values.
356
+ */
357
+ function nullable(struct) {
358
+ return new Struct({
359
+ ...struct,
360
+ validator: (value, ctx) => value === null || struct.validator(value, ctx),
361
+ refiner: (value, ctx) => value === null || struct.refiner(value, ctx),
362
+ });
363
+ }
364
+ /**
365
+ * Ensure that a value is a number.
366
+ */
367
+ function number() {
368
+ return define('number', (value) => {
369
+ return ((typeof value === 'number' && !isNaN(value)) ||
370
+ `Expected a number, but received: ${print(value)}`);
371
+ });
372
+ }
373
+ /**
374
+ * Augment a struct to allow `undefined` values.
375
+ */
376
+ function optional(struct) {
377
+ return new Struct({
378
+ ...struct,
379
+ validator: (value, ctx) => value === undefined || struct.validator(value, ctx),
380
+ refiner: (value, ctx) => value === undefined || struct.refiner(value, ctx),
381
+ });
382
+ }
383
+ /**
384
+ * Ensure that a value is a string.
385
+ */
386
+ function string() {
387
+ return define('string', (value) => {
388
+ return (typeof value === 'string' ||
389
+ `Expected a string, but received: ${print(value)}`);
390
+ });
391
+ }
392
+ /**
393
+ * Ensure that a value has a set of known properties of specific types.
394
+ *
395
+ * Note: Unrecognized properties are allowed and untouched. This is similar to
396
+ * how TypeScript's structural typing works.
397
+ */
398
+ function type(schema) {
399
+ const keys = Object.keys(schema);
400
+ return new Struct({
401
+ type: 'type',
402
+ schema,
403
+ *entries(value) {
404
+ if (isObject(value)) {
405
+ for (const k of keys) {
406
+ yield [k, value[k], schema[k]];
407
+ }
408
+ }
409
+ },
410
+ validator(value) {
411
+ return (isNonArrayObject(value) ||
412
+ `Expected an object, but received: ${print(value)}`);
413
+ },
414
+ coercer(value) {
415
+ return isNonArrayObject(value) ? { ...value } : value;
416
+ },
417
+ });
418
+ }
419
+
420
+ /**
421
+ * Augment a `Struct` to add an additional coercion step to its input.
422
+ *
423
+ * This allows you to transform input data before validating it, to increase the
424
+ * likelihood that it passes validation—for example for default values, parsing
425
+ * different formats, etc.
426
+ *
427
+ * Note: You must use `create(value, Struct)` on the value to have the coercion
428
+ * take effect! Using simply `assert()` or `is()` will not use coercion.
429
+ */
430
+ function coerce(struct, condition, coercer) {
431
+ return new Struct({
432
+ ...struct,
433
+ coercer: (value, ctx) => {
434
+ return is(value, condition)
435
+ ? struct.coercer(coercer(value, ctx), ctx)
436
+ : struct.coercer(value, ctx);
437
+ },
438
+ });
439
+ }
440
+
441
+ // Public key that identifies the metadata program.
442
+ const METADATA_PROGRAM_ID = new web3_js.PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s');
443
+ const METADATA_MAX_NAME_LENGTH = 32;
444
+ const METADATA_MAX_SYMBOL_LENGTH = 10;
445
+ const METADATA_MAX_URI_LENGTH = 200;
446
+ // Public key that identifies the SPL Stake Pool program.
447
+ const STAKE_POOL_PROGRAM_ID = new web3_js.PublicKey('SP1s4uFeTAX9jsXXmwyDs1gxYYf7cdDZ8qHUHVxE1yr');
448
+ // Public key that identifies the SPL Stake Pool program deployed to devnet.
449
+ const DEVNET_STAKE_POOL_PROGRAM_ID = new web3_js.PublicKey('DPoo15wWDqpPJJtS2MUZ49aRxqz5ZaaJCJP4z8bLuib');
450
+ // Maximum number of validators to update during UpdateValidatorListBalance.
451
+ const MAX_VALIDATORS_TO_UPDATE = 4;
452
+ // Seed for ephemeral stake account
453
+ const EPHEMERAL_STAKE_SEED_PREFIX = node_buffer.Buffer.from('ephemeral');
454
+ // Seed used to derive transient stake accounts.
455
+ const TRANSIENT_STAKE_SEED_PREFIX = node_buffer.Buffer.from('transient');
456
+ // Minimum amount of staked SOL required in a validator stake account to allow
457
+ // for merges without a mismatch on credits observed
458
+ const MINIMUM_ACTIVE_STAKE = web3_js.LAMPORTS_PER_SOL;
459
+
460
+ /**
461
+ * Populate a buffer of instruction data using an InstructionType
462
+ * @internal
463
+ */
464
+ function encodeData(type, fields) {
465
+ const allocLength = type.layout.span;
466
+ const data = node_buffer.Buffer.alloc(allocLength);
467
+ const layoutFields = Object.assign({ instruction: type.index }, fields);
468
+ type.layout.encode(layoutFields, data);
469
+ return data;
470
+ }
471
+ /**
472
+ * Decode instruction data buffer using an InstructionType
473
+ * @internal
474
+ */
475
+ function decodeData(type, buffer) {
476
+ let data;
477
+ try {
478
+ data = type.layout.decode(buffer);
479
+ }
480
+ catch (err) {
481
+ throw new Error(`invalid instruction; ${err}`);
482
+ }
483
+ if (data.instruction !== type.index) {
484
+ throw new Error(`invalid instruction; instruction index mismatch ${data.instruction} != ${type.index}`);
485
+ }
486
+ return data;
487
+ }
488
+
489
+ function solToLamports(amount) {
490
+ if (isNaN(amount)) {
491
+ return Number(0);
492
+ }
493
+ return Number(amount * web3_js.LAMPORTS_PER_SOL);
494
+ }
495
+ function lamportsToSol(lamports) {
496
+ if (typeof lamports === 'number') {
497
+ return Math.abs(lamports) / web3_js.LAMPORTS_PER_SOL;
498
+ }
499
+ if (typeof lamports === 'bigint') {
500
+ return Math.abs(Number(lamports)) / web3_js.LAMPORTS_PER_SOL;
501
+ }
502
+ let signMultiplier = 1;
503
+ if (lamports.isNeg()) {
504
+ signMultiplier = -1;
505
+ }
506
+ const absLamports = lamports.abs();
507
+ const lamportsString = absLamports.toString(10).padStart(10, '0');
508
+ const splitIndex = lamportsString.length - 9;
509
+ const solString = `${lamportsString.slice(0, splitIndex)}.${lamportsString.slice(splitIndex)}`;
510
+ return signMultiplier * Number.parseFloat(solString);
511
+ }
512
+
513
+ /**
514
+ * Generates the wSOL transient program address for the stake pool
515
+ */
516
+ function findWsolTransientProgramAddress(programId, userPubkey) {
517
+ const [publicKey] = web3_js.PublicKey.findProgramAddressSync([node_buffer.Buffer.from('transient_wsol'), userPubkey.toBuffer()], programId);
518
+ return publicKey;
519
+ }
520
+ /**
521
+ * Generates the withdraw authority program address for the stake pool
522
+ */
523
+ async function findWithdrawAuthorityProgramAddress(programId, stakePoolAddress) {
524
+ const [publicKey] = web3_js.PublicKey.findProgramAddressSync([stakePoolAddress.toBuffer(), node_buffer.Buffer.from('withdraw')], programId);
525
+ return publicKey;
526
+ }
527
+ /**
528
+ * Generates the stake program address for a validator's vote account
529
+ */
530
+ async function findStakeProgramAddress(programId, voteAccountAddress, stakePoolAddress, seed) {
531
+ const [publicKey] = web3_js.PublicKey.findProgramAddressSync([
532
+ voteAccountAddress.toBuffer(),
533
+ stakePoolAddress.toBuffer(),
534
+ seed ? new BN(seed).toArrayLike(node_buffer.Buffer, 'le', 4) : node_buffer.Buffer.alloc(0),
535
+ ], programId);
536
+ return publicKey;
537
+ }
538
+ /**
539
+ * Generates the stake program address for a validator's vote account
540
+ */
541
+ async function findTransientStakeProgramAddress(programId, voteAccountAddress, stakePoolAddress, seed) {
542
+ const [publicKey] = web3_js.PublicKey.findProgramAddressSync([
543
+ TRANSIENT_STAKE_SEED_PREFIX,
544
+ voteAccountAddress.toBuffer(),
545
+ stakePoolAddress.toBuffer(),
546
+ seed.toArrayLike(node_buffer.Buffer, 'le', 8),
547
+ ], programId);
548
+ return publicKey;
549
+ }
550
+ /**
551
+ * Generates the ephemeral program address for stake pool redelegation
552
+ */
553
+ async function findEphemeralStakeProgramAddress(programId, stakePoolAddress, seed) {
554
+ const [publicKey] = web3_js.PublicKey.findProgramAddressSync([EPHEMERAL_STAKE_SEED_PREFIX, stakePoolAddress.toBuffer(), seed.toArrayLike(node_buffer.Buffer, 'le', 8)], programId);
555
+ return publicKey;
556
+ }
557
+ /**
558
+ * Generates the metadata program address for the stake pool
559
+ */
560
+ function findMetadataAddress(stakePoolMintAddress) {
561
+ const [publicKey] = web3_js.PublicKey.findProgramAddressSync([node_buffer.Buffer.from('metadata'), METADATA_PROGRAM_ID.toBuffer(), stakePoolMintAddress.toBuffer()], METADATA_PROGRAM_ID);
562
+ return publicKey;
563
+ }
564
+
565
+ class BNLayout extends bufferLayout.Layout {
566
+ constructor(span, signed, property) {
567
+ super(span, property);
568
+ this.blob = bufferLayout.blob(span);
569
+ this.signed = signed;
570
+ }
571
+ decode(b, offset = 0) {
572
+ const num = new BN(this.blob.decode(b, offset), 10, 'le');
573
+ if (this.signed) {
574
+ return num.fromTwos(this.span * 8).clone();
575
+ }
576
+ return num;
577
+ }
578
+ encode(src, b, offset = 0) {
579
+ if (this.signed) {
580
+ src = src.toTwos(this.span * 8);
581
+ }
582
+ return this.blob.encode(src.toArrayLike(Buffer, 'le', this.span), b, offset);
583
+ }
584
+ }
585
+ function u64(property) {
586
+ return new BNLayout(8, false, property);
587
+ }
588
+ class WrappedLayout extends bufferLayout.Layout {
589
+ constructor(layout, decoder, encoder, property) {
590
+ super(layout.span, property);
591
+ this.layout = layout;
592
+ this.decoder = decoder;
593
+ this.encoder = encoder;
594
+ }
595
+ decode(b, offset) {
596
+ return this.decoder(this.layout.decode(b, offset));
597
+ }
598
+ encode(src, b, offset) {
599
+ return this.layout.encode(this.encoder(src), b, offset);
600
+ }
601
+ getSpan(b, offset) {
602
+ return this.layout.getSpan(b, offset);
603
+ }
604
+ }
605
+ function publicKey(property) {
606
+ return new WrappedLayout(bufferLayout.blob(32), (b) => new web3_js.PublicKey(b), (key) => key.toBuffer(), property);
607
+ }
608
+ class OptionLayout extends bufferLayout.Layout {
609
+ constructor(layout, property) {
610
+ super(-1, property);
611
+ this.layout = layout;
612
+ this.discriminator = bufferLayout.u8();
613
+ }
614
+ encode(src, b, offset = 0) {
615
+ if (src === null || src === undefined) {
616
+ return this.discriminator.encode(0, b, offset);
617
+ }
618
+ this.discriminator.encode(1, b, offset);
619
+ return this.layout.encode(src, b, offset + 1) + 1;
620
+ }
621
+ decode(b, offset = 0) {
622
+ const discriminator = this.discriminator.decode(b, offset);
623
+ if (discriminator === 0) {
624
+ return null;
625
+ }
626
+ else if (discriminator === 1) {
627
+ return this.layout.decode(b, offset + 1);
628
+ }
629
+ throw new Error(`Invalid option ${this.property}`);
630
+ }
631
+ getSpan(b, offset = 0) {
632
+ const discriminator = this.discriminator.decode(b, offset);
633
+ if (discriminator === 0) {
634
+ return 1;
635
+ }
636
+ else if (discriminator === 1) {
637
+ return this.layout.getSpan(b, offset + 1) + 1;
638
+ }
639
+ throw new Error(`Invalid option ${this.property}`);
640
+ }
641
+ }
642
+ function option(layout, property) {
643
+ return new OptionLayout(layout, property);
644
+ }
645
+ function vec(elementLayout, property) {
646
+ const length = bufferLayout.u32('length');
647
+ const layout = bufferLayout.struct([
648
+ length,
649
+ bufferLayout.seq(elementLayout, bufferLayout.offset(length, -length.span), 'values'),
650
+ ]);
651
+ return new WrappedLayout(layout, ({ values }) => values, values => ({ values }), property);
652
+ }
653
+
654
+ const feeFields = [u64('denominator'), u64('numerator')];
655
+ var AccountType;
656
+ (function (AccountType) {
657
+ AccountType[AccountType["Uninitialized"] = 0] = "Uninitialized";
658
+ AccountType[AccountType["StakePool"] = 1] = "StakePool";
659
+ AccountType[AccountType["ValidatorList"] = 2] = "ValidatorList";
660
+ })(AccountType || (AccountType = {}));
661
+ const BigNumFromString = coerce(instance(BN), string(), (value) => {
662
+ if (typeof value === 'string') {
663
+ return new BN(value, 10);
664
+ }
665
+ throw new Error('invalid big num');
666
+ });
667
+ const PublicKeyFromString = coerce(instance(web3_js.PublicKey), string(), value => new web3_js.PublicKey(value));
668
+ class FutureEpochLayout extends bufferLayout.Layout {
669
+ constructor(layout, property) {
670
+ super(-1, property);
671
+ this.layout = layout;
672
+ this.discriminator = bufferLayout.u8();
673
+ }
674
+ encode(src, b, offset = 0) {
675
+ if (src === null || src === undefined) {
676
+ return this.discriminator.encode(0, b, offset);
677
+ }
678
+ // This isn't right, but we don't typically encode outside of tests
679
+ this.discriminator.encode(2, b, offset);
680
+ return this.layout.encode(src, b, offset + 1) + 1;
681
+ }
682
+ decode(b, offset = 0) {
683
+ const discriminator = this.discriminator.decode(b, offset);
684
+ if (discriminator === 0) {
685
+ return null;
686
+ }
687
+ else if (discriminator === 1 || discriminator === 2) {
688
+ return this.layout.decode(b, offset + 1);
689
+ }
690
+ throw new Error(`Invalid future epoch ${this.property}`);
691
+ }
692
+ getSpan(b, offset = 0) {
693
+ const discriminator = this.discriminator.decode(b, offset);
694
+ if (discriminator === 0) {
695
+ return 1;
696
+ }
697
+ else if (discriminator === 1 || discriminator === 2) {
698
+ return this.layout.getSpan(b, offset + 1) + 1;
699
+ }
700
+ throw new Error(`Invalid future epoch ${this.property}`);
701
+ }
702
+ }
703
+ function futureEpoch(layout, property) {
704
+ return new FutureEpochLayout(layout, property);
705
+ }
706
+ const StakeAccountType = enums(['uninitialized', 'initialized', 'delegated', 'rewardsPool']);
707
+ const StakeMeta = type({
708
+ rentExemptReserve: BigNumFromString,
709
+ authorized: type({
710
+ staker: PublicKeyFromString,
711
+ withdrawer: PublicKeyFromString,
712
+ }),
713
+ lockup: type({
714
+ unixTimestamp: number(),
715
+ epoch: number(),
716
+ custodian: PublicKeyFromString,
717
+ }),
718
+ });
719
+ const StakeAccountInfo = type({
720
+ meta: StakeMeta,
721
+ stake: nullable(type({
722
+ delegation: type({
723
+ voter: PublicKeyFromString,
724
+ stake: BigNumFromString,
725
+ activationEpoch: BigNumFromString,
726
+ deactivationEpoch: BigNumFromString,
727
+ warmupCooldownRate: number(),
728
+ }),
729
+ creditsObserved: number(),
730
+ })),
731
+ });
732
+ const StakeAccount = type({
733
+ type: StakeAccountType,
734
+ info: optional(StakeAccountInfo),
735
+ });
736
+ const StakePoolLayout = bufferLayout.struct([
737
+ bufferLayout.u8('accountType'),
738
+ publicKey('manager'),
739
+ publicKey('staker'),
740
+ publicKey('stakeDepositAuthority'),
741
+ bufferLayout.u8('stakeWithdrawBumpSeed'),
742
+ publicKey('validatorList'),
743
+ publicKey('reserveStake'),
744
+ publicKey('poolMint'),
745
+ publicKey('managerFeeAccount'),
746
+ publicKey('tokenProgramId'),
747
+ u64('totalLamports'),
748
+ u64('poolTokenSupply'),
749
+ u64('lastUpdateEpoch'),
750
+ bufferLayout.struct([u64('unixTimestamp'), u64('epoch'), publicKey('custodian')], 'lockup'),
751
+ bufferLayout.struct(feeFields, 'epochFee'),
752
+ futureEpoch(bufferLayout.struct(feeFields), 'nextEpochFee'),
753
+ option(publicKey(), 'preferredDepositValidatorVoteAddress'),
754
+ option(publicKey(), 'preferredWithdrawValidatorVoteAddress'),
755
+ bufferLayout.struct(feeFields, 'stakeDepositFee'),
756
+ bufferLayout.struct(feeFields, 'stakeWithdrawalFee'),
757
+ futureEpoch(bufferLayout.struct(feeFields), 'nextStakeWithdrawalFee'),
758
+ bufferLayout.u8('stakeReferralFee'),
759
+ option(publicKey(), 'solDepositAuthority'),
760
+ bufferLayout.struct(feeFields, 'solDepositFee'),
761
+ bufferLayout.u8('solReferralFee'),
762
+ option(publicKey(), 'solWithdrawAuthority'),
763
+ bufferLayout.struct(feeFields, 'solWithdrawalFee'),
764
+ futureEpoch(bufferLayout.struct(feeFields), 'nextSolWithdrawalFee'),
765
+ u64('lastEpochPoolTokenSupply'),
766
+ u64('lastEpochTotalLamports'),
767
+ ]);
768
+ var ValidatorStakeInfoStatus;
769
+ (function (ValidatorStakeInfoStatus) {
770
+ ValidatorStakeInfoStatus[ValidatorStakeInfoStatus["Active"] = 0] = "Active";
771
+ ValidatorStakeInfoStatus[ValidatorStakeInfoStatus["DeactivatingTransient"] = 1] = "DeactivatingTransient";
772
+ ValidatorStakeInfoStatus[ValidatorStakeInfoStatus["ReadyForRemoval"] = 2] = "ReadyForRemoval";
773
+ })(ValidatorStakeInfoStatus || (ValidatorStakeInfoStatus = {}));
774
+ const ValidatorStakeInfoLayout = bufferLayout.struct([
775
+ /// Amount of active stake delegated to this validator
776
+ /// Note that if `last_update_epoch` does not match the current epoch then
777
+ /// this field may not be accurate
778
+ u64('activeStakeLamports'),
779
+ /// Amount of transient stake delegated to this validator
780
+ /// Note that if `last_update_epoch` does not match the current epoch then
781
+ /// this field may not be accurate
782
+ u64('transientStakeLamports'),
783
+ /// Last epoch the active and transient stake lamports fields were updated
784
+ u64('lastUpdateEpoch'),
785
+ /// Start of the validator transient account seed suffixes
786
+ u64('transientSeedSuffixStart'),
787
+ /// End of the validator transient account seed suffixes
788
+ u64('transientSeedSuffixEnd'),
789
+ /// Status of the validator stake account
790
+ bufferLayout.u8('status'),
791
+ /// Validator vote account address
792
+ publicKey('voteAccountAddress'),
793
+ ]);
794
+ const ValidatorListLayout = bufferLayout.struct([
795
+ bufferLayout.u8('accountType'),
796
+ bufferLayout.u32('maxValidators'),
797
+ vec(ValidatorStakeInfoLayout, 'validators'),
798
+ ]);
799
+
800
+ async function getValidatorListAccount(connection, pubkey) {
801
+ const account = await connection.getAccountInfo(pubkey);
802
+ if (!account) {
803
+ throw new Error('Invalid validator list account');
804
+ }
805
+ return {
806
+ pubkey,
807
+ account: {
808
+ data: ValidatorListLayout.decode(account === null || account === void 0 ? void 0 : account.data),
809
+ executable: account.executable,
810
+ lamports: account.lamports,
811
+ owner: account.owner,
812
+ },
813
+ };
814
+ }
815
+ async function prepareWithdrawAccounts(connection, stakePool, stakePoolAddress, amount, compareFn, skipFee) {
816
+ var _a, _b;
817
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
818
+ const validatorListAcc = await connection.getAccountInfo(stakePool.validatorList);
819
+ const validatorList = ValidatorListLayout.decode(validatorListAcc === null || validatorListAcc === void 0 ? void 0 : validatorListAcc.data);
820
+ if (!(validatorList === null || validatorList === void 0 ? void 0 : validatorList.validators) || (validatorList === null || validatorList === void 0 ? void 0 : validatorList.validators.length) == 0) {
821
+ throw new Error('No accounts found');
822
+ }
823
+ const minBalanceForRentExemption = await connection.getMinimumBalanceForRentExemption(web3_js.StakeProgram.space);
824
+ const minBalance = new BN(minBalanceForRentExemption + MINIMUM_ACTIVE_STAKE);
825
+ let accounts = [];
826
+ // Prepare accounts
827
+ for (const validator of validatorList.validators) {
828
+ if (validator.status !== ValidatorStakeInfoStatus.Active) {
829
+ continue;
830
+ }
831
+ const stakeAccountAddress = await findStakeProgramAddress(stakePoolProgramId, validator.voteAccountAddress, stakePoolAddress);
832
+ if (!validator.activeStakeLamports.isZero()) {
833
+ const isPreferred = (_a = stakePool === null || stakePool === void 0 ? void 0 : stakePool.preferredWithdrawValidatorVoteAddress) === null || _a === void 0 ? void 0 : _a.equals(validator.voteAccountAddress);
834
+ accounts.push({
835
+ type: isPreferred ? 'preferred' : 'active',
836
+ voteAddress: validator.voteAccountAddress,
837
+ stakeAddress: stakeAccountAddress,
838
+ lamports: validator.activeStakeLamports,
839
+ });
840
+ }
841
+ const transientStakeLamports = validator.transientStakeLamports.sub(minBalance);
842
+ if (transientStakeLamports.gt(new BN(0))) {
843
+ const transientStakeAccountAddress = await findTransientStakeProgramAddress(stakePoolProgramId, validator.voteAccountAddress, stakePoolAddress, validator.transientSeedSuffixStart);
844
+ accounts.push({
845
+ type: 'transient',
846
+ voteAddress: validator.voteAccountAddress,
847
+ stakeAddress: transientStakeAccountAddress,
848
+ lamports: transientStakeLamports,
849
+ });
850
+ }
851
+ }
852
+ // Sort from highest to lowest balance
853
+ accounts = accounts.sort(compareFn || ((a, b) => b.lamports.sub(a.lamports).toNumber()));
854
+ const reserveStake = await connection.getAccountInfo(stakePool.reserveStake);
855
+ const reserveStakeBalance = new BN(((_b = reserveStake === null || reserveStake === void 0 ? void 0 : reserveStake.lamports) !== null && _b !== void 0 ? _b : 0) - minBalanceForRentExemption);
856
+ if (reserveStakeBalance.gt(new BN(0))) {
857
+ accounts.push({
858
+ type: 'reserve',
859
+ stakeAddress: stakePool.reserveStake,
860
+ lamports: reserveStakeBalance,
861
+ });
862
+ }
863
+ // Prepare the list of accounts to withdraw from
864
+ const withdrawFrom = [];
865
+ let remainingAmount = new BN(amount);
866
+ const fee = stakePool.stakeWithdrawalFee;
867
+ const inverseFee = {
868
+ numerator: fee.denominator.sub(fee.numerator),
869
+ denominator: fee.denominator,
870
+ };
871
+ for (const type of ['preferred', 'active', 'transient', 'reserve']) {
872
+ const filteredAccounts = accounts.filter(a => a.type == type);
873
+ for (const { stakeAddress, voteAddress, lamports } of filteredAccounts) {
874
+ if (lamports.lte(minBalance) && type == 'transient') {
875
+ continue;
876
+ }
877
+ let availableForWithdrawal = calcPoolTokensForDeposit(stakePool, lamports);
878
+ if (!skipFee && !inverseFee.numerator.isZero()) {
879
+ availableForWithdrawal = availableForWithdrawal
880
+ .mul(inverseFee.denominator)
881
+ .div(inverseFee.numerator);
882
+ }
883
+ const poolAmount = BN.min(availableForWithdrawal, remainingAmount);
884
+ if (poolAmount.lte(new BN(0))) {
885
+ continue;
886
+ }
887
+ // Those accounts will be withdrawn completely with `claim` instruction
888
+ withdrawFrom.push({ stakeAddress, voteAddress, poolAmount });
889
+ remainingAmount = remainingAmount.sub(poolAmount);
890
+ if (remainingAmount.isZero()) {
891
+ break;
892
+ }
893
+ }
894
+ if (remainingAmount.isZero()) {
895
+ break;
896
+ }
897
+ }
898
+ // Not enough stake to withdraw the specified amount
899
+ if (remainingAmount.gt(new BN(0))) {
900
+ throw new Error(`No stake accounts found in this pool with enough balance to withdraw ${lamportsToSol(amount)} pool tokens.`);
901
+ }
902
+ return withdrawFrom;
903
+ }
904
+ /**
905
+ * Calculate the pool tokens that should be minted for a deposit of `stakeLamports`
906
+ */
907
+ function calcPoolTokensForDeposit(stakePool, stakeLamports) {
908
+ if (stakePool.poolTokenSupply.isZero() || stakePool.totalLamports.isZero()) {
909
+ return stakeLamports;
910
+ }
911
+ const numerator = stakeLamports.mul(stakePool.poolTokenSupply);
912
+ return numerator.div(stakePool.totalLamports);
913
+ }
914
+ /**
915
+ * Calculate lamports amount on withdrawal
916
+ */
917
+ function calcLamportsWithdrawAmount(stakePool, poolTokens) {
918
+ const numerator = poolTokens.mul(stakePool.totalLamports);
919
+ const denominator = stakePool.poolTokenSupply;
920
+ if (numerator.lt(denominator)) {
921
+ return new BN(0);
922
+ }
923
+ return numerator.div(denominator);
924
+ }
925
+ function newStakeAccount(feePayer, instructions, lamports) {
926
+ // Account for tokens not specified, creating one
927
+ const stakeReceiverKeypair = web3_js.Keypair.generate();
928
+ console.log(`Creating account to receive stake ${stakeReceiverKeypair.publicKey}`);
929
+ instructions.push(
930
+ // Creating new account
931
+ web3_js.SystemProgram.createAccount({
932
+ fromPubkey: feePayer,
933
+ newAccountPubkey: stakeReceiverKeypair.publicKey,
934
+ lamports,
935
+ space: web3_js.StakeProgram.space,
936
+ programId: web3_js.StakeProgram.programId,
937
+ }));
938
+ return stakeReceiverKeypair;
939
+ }
940
+
941
+ function arrayChunk(array, size) {
942
+ const result = [];
943
+ for (let i = 0; i < array.length; i += size) {
944
+ result.push(array.slice(i, i + size));
945
+ }
946
+ return result;
947
+ }
948
+
949
+ // 'UpdateTokenMetadata' and 'CreateTokenMetadata' have dynamic layouts
950
+ const MOVE_STAKE_LAYOUT = BufferLayout__namespace.struct([
951
+ BufferLayout__namespace.u8('instruction'),
952
+ BufferLayout__namespace.ns64('lamports'),
953
+ BufferLayout__namespace.ns64('transientStakeSeed'),
954
+ ]);
955
+ const UPDATE_VALIDATOR_LIST_BALANCE_LAYOUT = BufferLayout__namespace.struct([
956
+ BufferLayout__namespace.u8('instruction'),
957
+ BufferLayout__namespace.u32('startIndex'),
958
+ BufferLayout__namespace.u8('noMerge'),
959
+ ]);
960
+ function tokenMetadataLayout(instruction, nameLength, symbolLength, uriLength) {
961
+ if (nameLength > METADATA_MAX_NAME_LENGTH) {
962
+ // eslint-disable-next-line no-throw-literal
963
+ throw 'maximum token name length is 32 characters';
964
+ }
965
+ if (symbolLength > METADATA_MAX_SYMBOL_LENGTH) {
966
+ // eslint-disable-next-line no-throw-literal
967
+ throw 'maximum token symbol length is 10 characters';
968
+ }
969
+ if (uriLength > METADATA_MAX_URI_LENGTH) {
970
+ // eslint-disable-next-line no-throw-literal
971
+ throw 'maximum token uri length is 200 characters';
972
+ }
973
+ return {
974
+ index: instruction,
975
+ layout: BufferLayout__namespace.struct([
976
+ BufferLayout__namespace.u8('instruction'),
977
+ BufferLayout__namespace.u32('nameLen'),
978
+ BufferLayout__namespace.blob(nameLength, 'name'),
979
+ BufferLayout__namespace.u32('symbolLen'),
980
+ BufferLayout__namespace.blob(symbolLength, 'symbol'),
981
+ BufferLayout__namespace.u32('uriLen'),
982
+ BufferLayout__namespace.blob(uriLength, 'uri'),
983
+ ]),
984
+ };
985
+ }
986
+ /**
987
+ * An enumeration of valid stake InstructionType's
988
+ * @internal
989
+ */
990
+ const STAKE_POOL_INSTRUCTION_LAYOUTS = Object.freeze({
991
+ AddValidatorToPool: {
992
+ index: 1,
993
+ layout: BufferLayout__namespace.struct([BufferLayout__namespace.u8('instruction'), BufferLayout__namespace.u32('seed')]),
994
+ },
995
+ RemoveValidatorFromPool: {
996
+ index: 2,
997
+ layout: BufferLayout__namespace.struct([BufferLayout__namespace.u8('instruction')]),
998
+ },
999
+ DecreaseValidatorStake: {
1000
+ index: 3,
1001
+ layout: MOVE_STAKE_LAYOUT,
1002
+ },
1003
+ IncreaseValidatorStake: {
1004
+ index: 4,
1005
+ layout: MOVE_STAKE_LAYOUT,
1006
+ },
1007
+ UpdateValidatorListBalance: {
1008
+ index: 6,
1009
+ layout: UPDATE_VALIDATOR_LIST_BALANCE_LAYOUT,
1010
+ },
1011
+ UpdateStakePoolBalance: {
1012
+ index: 7,
1013
+ layout: BufferLayout__namespace.struct([BufferLayout__namespace.u8('instruction')]),
1014
+ },
1015
+ CleanupRemovedValidatorEntries: {
1016
+ index: 8,
1017
+ layout: BufferLayout__namespace.struct([BufferLayout__namespace.u8('instruction')]),
1018
+ },
1019
+ DepositStake: {
1020
+ index: 9,
1021
+ layout: BufferLayout__namespace.struct([BufferLayout__namespace.u8('instruction')]),
1022
+ },
1023
+ /// Withdraw the token from the pool at the current ratio.
1024
+ WithdrawStake: {
1025
+ index: 10,
1026
+ layout: BufferLayout__namespace.struct([
1027
+ BufferLayout__namespace.u8('instruction'),
1028
+ BufferLayout__namespace.ns64('poolTokens'),
1029
+ ]),
1030
+ },
1031
+ /// Deposit SOL directly into the pool's reserve account. The output is a "pool" token
1032
+ /// representing ownership into the pool. Inputs are converted to the current ratio.
1033
+ DepositSol: {
1034
+ index: 14,
1035
+ layout: BufferLayout__namespace.struct([
1036
+ BufferLayout__namespace.u8('instruction'),
1037
+ BufferLayout__namespace.ns64('lamports'),
1038
+ ]),
1039
+ },
1040
+ /// Withdraw SOL directly from the pool's reserve account. Fails if the
1041
+ /// reserve does not have enough SOL.
1042
+ WithdrawSol: {
1043
+ index: 16,
1044
+ layout: BufferLayout__namespace.struct([
1045
+ BufferLayout__namespace.u8('instruction'),
1046
+ BufferLayout__namespace.ns64('poolTokens'),
1047
+ ]),
1048
+ },
1049
+ IncreaseAdditionalValidatorStake: {
1050
+ index: 19,
1051
+ layout: BufferLayout__namespace.struct([
1052
+ BufferLayout__namespace.u8('instruction'),
1053
+ BufferLayout__namespace.ns64('lamports'),
1054
+ BufferLayout__namespace.ns64('transientStakeSeed'),
1055
+ BufferLayout__namespace.ns64('ephemeralStakeSeed'),
1056
+ ]),
1057
+ },
1058
+ DecreaseAdditionalValidatorStake: {
1059
+ index: 20,
1060
+ layout: BufferLayout__namespace.struct([
1061
+ BufferLayout__namespace.u8('instruction'),
1062
+ BufferLayout__namespace.ns64('lamports'),
1063
+ BufferLayout__namespace.ns64('transientStakeSeed'),
1064
+ BufferLayout__namespace.ns64('ephemeralStakeSeed'),
1065
+ ]),
1066
+ },
1067
+ DecreaseValidatorStakeWithReserve: {
1068
+ index: 21,
1069
+ layout: MOVE_STAKE_LAYOUT,
1070
+ },
1071
+ Redelegate: {
1072
+ index: 22,
1073
+ layout: BufferLayout__namespace.struct([BufferLayout__namespace.u8('instruction')]),
1074
+ },
1075
+ DepositStakeWithSlippage: {
1076
+ index: 23,
1077
+ layout: BufferLayout__namespace.struct([
1078
+ BufferLayout__namespace.u8('instruction'),
1079
+ BufferLayout__namespace.ns64('lamports'),
1080
+ ]),
1081
+ },
1082
+ WithdrawStakeWithSlippage: {
1083
+ index: 24,
1084
+ layout: BufferLayout__namespace.struct([
1085
+ BufferLayout__namespace.u8('instruction'),
1086
+ BufferLayout__namespace.ns64('lamports'),
1087
+ ]),
1088
+ },
1089
+ DepositSolWithSlippage: {
1090
+ index: 25,
1091
+ layout: BufferLayout__namespace.struct([
1092
+ BufferLayout__namespace.u8('instruction'),
1093
+ BufferLayout__namespace.ns64('lamports'),
1094
+ ]),
1095
+ },
1096
+ WithdrawSolWithSlippage: {
1097
+ index: 26,
1098
+ layout: BufferLayout__namespace.struct([
1099
+ BufferLayout__namespace.u8('instruction'),
1100
+ BufferLayout__namespace.ns64('lamports'),
1101
+ ]),
1102
+ },
1103
+ DepositWsolWithSession: {
1104
+ index: 27,
1105
+ layout: BufferLayout__namespace.struct([
1106
+ BufferLayout__namespace.u8('instruction'),
1107
+ BufferLayout__namespace.ns64('lamports'),
1108
+ ]),
1109
+ },
1110
+ WithdrawWsolWithSession: {
1111
+ index: 28,
1112
+ layout: BufferLayout__namespace.struct([
1113
+ BufferLayout__namespace.u8('instruction'),
1114
+ BufferLayout__namespace.ns64('poolTokens'),
1115
+ ]),
1116
+ },
1117
+ });
1118
+ /**
1119
+ * Stake Pool Instruction class
1120
+ */
1121
+ class StakePoolInstruction {
1122
+ /**
1123
+ * Creates instruction to add a validator into the stake pool.
1124
+ */
1125
+ static addValidatorToPool(params) {
1126
+ const { programId, stakePool, staker, reserveStake, withdrawAuthority, validatorList, validatorStake, validatorVote, seed, } = params;
1127
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.AddValidatorToPool;
1128
+ const data = encodeData(type, { seed: seed !== null && seed !== void 0 ? seed : 0 });
1129
+ const keys = [
1130
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1131
+ { pubkey: staker, isSigner: true, isWritable: false },
1132
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1133
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1134
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1135
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1136
+ { pubkey: validatorVote, isSigner: false, isWritable: false },
1137
+ { pubkey: web3_js.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
1138
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1139
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1140
+ { pubkey: web3_js.STAKE_CONFIG_ID, isSigner: false, isWritable: false },
1141
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1142
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1143
+ ];
1144
+ return new web3_js.TransactionInstruction({
1145
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1146
+ keys,
1147
+ data,
1148
+ });
1149
+ }
1150
+ /**
1151
+ * Creates instruction to remove a validator from the stake pool.
1152
+ */
1153
+ static removeValidatorFromPool(params) {
1154
+ const { programId, stakePool, staker, withdrawAuthority, validatorList, validatorStake, transientStake, } = params;
1155
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.RemoveValidatorFromPool;
1156
+ const data = encodeData(type);
1157
+ const keys = [
1158
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1159
+ { pubkey: staker, isSigner: true, isWritable: false },
1160
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1161
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1162
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1163
+ { pubkey: transientStake, isSigner: false, isWritable: true },
1164
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1165
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1166
+ ];
1167
+ return new web3_js.TransactionInstruction({
1168
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1169
+ keys,
1170
+ data,
1171
+ });
1172
+ }
1173
+ /**
1174
+ * Creates instruction to update a set of validators in the stake pool.
1175
+ */
1176
+ static updateValidatorListBalance(params) {
1177
+ const { programId, stakePool, withdrawAuthority, validatorList, reserveStake, startIndex, noMerge, validatorAndTransientStakePairs, } = params;
1178
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.UpdateValidatorListBalance;
1179
+ const data = encodeData(type, { startIndex, noMerge: noMerge ? 1 : 0 });
1180
+ const keys = [
1181
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1182
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1183
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1184
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1185
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1186
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1187
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1188
+ ...validatorAndTransientStakePairs.map(pubkey => ({
1189
+ pubkey,
1190
+ isSigner: false,
1191
+ isWritable: true,
1192
+ })),
1193
+ ];
1194
+ return new web3_js.TransactionInstruction({
1195
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1196
+ keys,
1197
+ data,
1198
+ });
1199
+ }
1200
+ /**
1201
+ * Creates instruction to update the overall stake pool balance.
1202
+ */
1203
+ static updateStakePoolBalance(params) {
1204
+ const { programId, stakePool, withdrawAuthority, validatorList, reserveStake, managerFeeAccount, poolMint, } = params;
1205
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.UpdateStakePoolBalance;
1206
+ const data = encodeData(type);
1207
+ const keys = [
1208
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1209
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1210
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1211
+ { pubkey: reserveStake, isSigner: false, isWritable: false },
1212
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
1213
+ { pubkey: poolMint, isSigner: false, isWritable: true },
1214
+ { pubkey: splToken.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
1215
+ ];
1216
+ return new web3_js.TransactionInstruction({
1217
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1218
+ keys,
1219
+ data,
1220
+ });
1221
+ }
1222
+ /**
1223
+ * Creates instruction to cleanup removed validator entries.
1224
+ */
1225
+ static cleanupRemovedValidatorEntries(params) {
1226
+ const { programId, stakePool, validatorList } = params;
1227
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.CleanupRemovedValidatorEntries;
1228
+ const data = encodeData(type);
1229
+ const keys = [
1230
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1231
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1232
+ ];
1233
+ return new web3_js.TransactionInstruction({
1234
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1235
+ keys,
1236
+ data,
1237
+ });
1238
+ }
1239
+ /**
1240
+ * Creates `IncreaseValidatorStake` instruction (rebalance from reserve account to
1241
+ * transient account)
1242
+ */
1243
+ static increaseValidatorStake(params) {
1244
+ const { programId, stakePool, staker, withdrawAuthority, validatorList, reserveStake, transientStake, validatorStake, validatorVote, lamports, transientStakeSeed, } = params;
1245
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.IncreaseValidatorStake;
1246
+ const data = encodeData(type, { lamports, transientStakeSeed });
1247
+ const keys = [
1248
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1249
+ { pubkey: staker, isSigner: true, isWritable: false },
1250
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1251
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1252
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1253
+ { pubkey: transientStake, isSigner: false, isWritable: true },
1254
+ { pubkey: validatorStake, isSigner: false, isWritable: false },
1255
+ { pubkey: validatorVote, isSigner: false, isWritable: false },
1256
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1257
+ { pubkey: web3_js.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
1258
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1259
+ { pubkey: web3_js.STAKE_CONFIG_ID, isSigner: false, isWritable: false },
1260
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1261
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1262
+ ];
1263
+ return new web3_js.TransactionInstruction({
1264
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1265
+ keys,
1266
+ data,
1267
+ });
1268
+ }
1269
+ /**
1270
+ * Creates `IncreaseAdditionalValidatorStake` instruction (rebalance from reserve account to
1271
+ * transient account)
1272
+ */
1273
+ static increaseAdditionalValidatorStake(params) {
1274
+ const { programId, stakePool, staker, withdrawAuthority, validatorList, reserveStake, transientStake, validatorStake, validatorVote, lamports, transientStakeSeed, ephemeralStake, ephemeralStakeSeed, } = params;
1275
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.IncreaseAdditionalValidatorStake;
1276
+ const data = encodeData(type, { lamports, transientStakeSeed, ephemeralStakeSeed });
1277
+ const keys = [
1278
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1279
+ { pubkey: staker, isSigner: true, isWritable: false },
1280
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1281
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1282
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1283
+ { pubkey: ephemeralStake, isSigner: false, isWritable: true },
1284
+ { pubkey: transientStake, isSigner: false, isWritable: true },
1285
+ { pubkey: validatorStake, isSigner: false, isWritable: false },
1286
+ { pubkey: validatorVote, isSigner: false, isWritable: false },
1287
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1288
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1289
+ { pubkey: web3_js.STAKE_CONFIG_ID, isSigner: false, isWritable: false },
1290
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1291
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1292
+ ];
1293
+ return new web3_js.TransactionInstruction({
1294
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1295
+ keys,
1296
+ data,
1297
+ });
1298
+ }
1299
+ /**
1300
+ * Creates `DecreaseValidatorStake` instruction (rebalance from validator account to
1301
+ * transient account)
1302
+ */
1303
+ static decreaseValidatorStake(params) {
1304
+ const { programId, stakePool, staker, withdrawAuthority, validatorList, validatorStake, transientStake, lamports, transientStakeSeed, } = params;
1305
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DecreaseValidatorStake;
1306
+ const data = encodeData(type, { lamports, transientStakeSeed });
1307
+ const keys = [
1308
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1309
+ { pubkey: staker, isSigner: true, isWritable: false },
1310
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1311
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1312
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1313
+ { pubkey: transientStake, isSigner: false, isWritable: true },
1314
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1315
+ { pubkey: web3_js.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
1316
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1317
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1318
+ ];
1319
+ return new web3_js.TransactionInstruction({
1320
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1321
+ keys,
1322
+ data,
1323
+ });
1324
+ }
1325
+ /**
1326
+ * Creates `DecreaseValidatorStakeWithReserve` instruction (rebalance from
1327
+ * validator account to transient account)
1328
+ */
1329
+ static decreaseValidatorStakeWithReserve(params) {
1330
+ const { programId, stakePool, staker, withdrawAuthority, validatorList, reserveStake, validatorStake, transientStake, lamports, transientStakeSeed, } = params;
1331
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DecreaseValidatorStakeWithReserve;
1332
+ const data = encodeData(type, { lamports, transientStakeSeed });
1333
+ const keys = [
1334
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1335
+ { pubkey: staker, isSigner: true, isWritable: false },
1336
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1337
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1338
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1339
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1340
+ { pubkey: transientStake, isSigner: false, isWritable: true },
1341
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1342
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1343
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1344
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1345
+ ];
1346
+ return new web3_js.TransactionInstruction({
1347
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1348
+ keys,
1349
+ data,
1350
+ });
1351
+ }
1352
+ /**
1353
+ * Creates `DecreaseAdditionalValidatorStake` instruction (rebalance from
1354
+ * validator account to transient account)
1355
+ */
1356
+ static decreaseAdditionalValidatorStake(params) {
1357
+ const { programId, stakePool, staker, withdrawAuthority, validatorList, reserveStake, validatorStake, transientStake, lamports, transientStakeSeed, ephemeralStakeSeed, ephemeralStake, } = params;
1358
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DecreaseAdditionalValidatorStake;
1359
+ const data = encodeData(type, { lamports, transientStakeSeed, ephemeralStakeSeed });
1360
+ const keys = [
1361
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1362
+ { pubkey: staker, isSigner: true, isWritable: false },
1363
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1364
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1365
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1366
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1367
+ { pubkey: ephemeralStake, isSigner: false, isWritable: true },
1368
+ { pubkey: transientStake, isSigner: false, isWritable: true },
1369
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1370
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1371
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1372
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1373
+ ];
1374
+ return new web3_js.TransactionInstruction({
1375
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1376
+ keys,
1377
+ data,
1378
+ });
1379
+ }
1380
+ /**
1381
+ * Creates a transaction instruction to deposit a stake account into a stake pool.
1382
+ */
1383
+ static depositStake(params) {
1384
+ const { programId, stakePool, validatorList, depositAuthority, withdrawAuthority, depositStake, validatorStake, reserveStake, destinationPoolAccount, managerFeeAccount, referralPoolAccount, poolMint, } = params;
1385
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DepositStake;
1386
+ const data = encodeData(type);
1387
+ const keys = [
1388
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1389
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1390
+ { pubkey: depositAuthority, isSigner: false, isWritable: false },
1391
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1392
+ { pubkey: depositStake, isSigner: false, isWritable: true },
1393
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1394
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1395
+ { pubkey: destinationPoolAccount, isSigner: false, isWritable: true },
1396
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
1397
+ { pubkey: referralPoolAccount, isSigner: false, isWritable: true },
1398
+ { pubkey: poolMint, isSigner: false, isWritable: true },
1399
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1400
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1401
+ { pubkey: splToken.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
1402
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1403
+ ];
1404
+ return new web3_js.TransactionInstruction({
1405
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1406
+ keys,
1407
+ data,
1408
+ });
1409
+ }
1410
+ /**
1411
+ * Creates a transaction instruction to deposit SOL into a stake pool.
1412
+ */
1413
+ static depositSol(params) {
1414
+ const { programId, stakePool, withdrawAuthority, depositAuthority, reserveStake, fundingAccount, destinationPoolAccount, managerFeeAccount, referralPoolAccount, poolMint, lamports, } = params;
1415
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DepositSol;
1416
+ const data = encodeData(type, { lamports });
1417
+ const keys = [
1418
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1419
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1420
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1421
+ { pubkey: fundingAccount, isSigner: true, isWritable: true },
1422
+ { pubkey: destinationPoolAccount, isSigner: false, isWritable: true },
1423
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
1424
+ { pubkey: referralPoolAccount, isSigner: false, isWritable: true },
1425
+ { pubkey: poolMint, isSigner: false, isWritable: true },
1426
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1427
+ { pubkey: splToken.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
1428
+ ];
1429
+ if (depositAuthority) {
1430
+ keys.push({
1431
+ pubkey: depositAuthority,
1432
+ isSigner: true,
1433
+ isWritable: false,
1434
+ });
1435
+ }
1436
+ return new web3_js.TransactionInstruction({
1437
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1438
+ keys,
1439
+ data,
1440
+ });
1441
+ }
1442
+ /**
1443
+ * Creates a transaction instruction to deposit WSOL into a stake pool.
1444
+ */
1445
+ static depositWsolWithSession(params) {
1446
+ var _a;
1447
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.DepositWsolWithSession;
1448
+ const data = encodeData(type, { lamports: params.lamports });
1449
+ const keys = [
1450
+ { pubkey: params.stakePool, isSigner: false, isWritable: true },
1451
+ { pubkey: params.withdrawAuthority, isSigner: false, isWritable: false },
1452
+ { pubkey: params.reserveStake, isSigner: false, isWritable: true },
1453
+ { pubkey: params.fundingAccount, isSigner: true, isWritable: true },
1454
+ { pubkey: params.destinationPoolAccount, isSigner: false, isWritable: true },
1455
+ { pubkey: params.managerFeeAccount, isSigner: false, isWritable: true },
1456
+ { pubkey: params.referralPoolAccount, isSigner: false, isWritable: true },
1457
+ { pubkey: params.poolMint, isSigner: false, isWritable: true },
1458
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1459
+ { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
1460
+ // wsol specific accounts
1461
+ { pubkey: params.wsolMint, isSigner: false, isWritable: false },
1462
+ { pubkey: params.wsolTokenAccount, isSigner: false, isWritable: true },
1463
+ { pubkey: params.wsolTransientAccount, isSigner: false, isWritable: true },
1464
+ { pubkey: params.programSigner, isSigner: false, isWritable: true },
1465
+ { pubkey: (_a = params.payer) !== null && _a !== void 0 ? _a : params.fundingAccount, isSigner: true, isWritable: true },
1466
+ ];
1467
+ if (params.depositAuthority) {
1468
+ keys.push({
1469
+ pubkey: params.depositAuthority,
1470
+ isSigner: true,
1471
+ isWritable: false,
1472
+ });
1473
+ }
1474
+ return new web3_js.TransactionInstruction({
1475
+ programId: params.programId,
1476
+ keys,
1477
+ data,
1478
+ });
1479
+ }
1480
+ /**
1481
+ * Creates a transaction instruction to withdraw active stake from a stake pool.
1482
+ */
1483
+ static withdrawStake(params) {
1484
+ const { programId, stakePool, validatorList, withdrawAuthority, validatorStake, destinationStake, destinationStakeAuthority, sourceTransferAuthority, sourcePoolAccount, managerFeeAccount, poolMint, poolTokens, } = params;
1485
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawStake;
1486
+ const data = encodeData(type, { poolTokens });
1487
+ const keys = [
1488
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1489
+ { pubkey: validatorList, isSigner: false, isWritable: true },
1490
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1491
+ { pubkey: validatorStake, isSigner: false, isWritable: true },
1492
+ { pubkey: destinationStake, isSigner: false, isWritable: true },
1493
+ { pubkey: destinationStakeAuthority, isSigner: false, isWritable: false },
1494
+ { pubkey: sourceTransferAuthority, isSigner: true, isWritable: false },
1495
+ { pubkey: sourcePoolAccount, isSigner: false, isWritable: true },
1496
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
1497
+ { pubkey: poolMint, isSigner: false, isWritable: true },
1498
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1499
+ { pubkey: splToken.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
1500
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1501
+ ];
1502
+ return new web3_js.TransactionInstruction({
1503
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1504
+ keys,
1505
+ data,
1506
+ });
1507
+ }
1508
+ /**
1509
+ * Creates a transaction instruction to withdraw SOL from a stake pool.
1510
+ */
1511
+ static withdrawSol(params) {
1512
+ const { programId, stakePool, withdrawAuthority, sourceTransferAuthority, sourcePoolAccount, reserveStake, destinationSystemAccount, managerFeeAccount, solWithdrawAuthority, poolMint, poolTokens, } = params;
1513
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawSol;
1514
+ const data = encodeData(type, { poolTokens });
1515
+ const keys = [
1516
+ { pubkey: stakePool, isSigner: false, isWritable: true },
1517
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1518
+ { pubkey: sourceTransferAuthority, isSigner: true, isWritable: false },
1519
+ { pubkey: sourcePoolAccount, isSigner: false, isWritable: true },
1520
+ { pubkey: reserveStake, isSigner: false, isWritable: true },
1521
+ { pubkey: destinationSystemAccount, isSigner: false, isWritable: true },
1522
+ { pubkey: managerFeeAccount, isSigner: false, isWritable: true },
1523
+ { pubkey: poolMint, isSigner: false, isWritable: true },
1524
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1525
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1526
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1527
+ { pubkey: splToken.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
1528
+ ];
1529
+ if (solWithdrawAuthority) {
1530
+ keys.push({
1531
+ pubkey: solWithdrawAuthority,
1532
+ isSigner: true,
1533
+ isWritable: false,
1534
+ });
1535
+ }
1536
+ return new web3_js.TransactionInstruction({
1537
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1538
+ keys,
1539
+ data,
1540
+ });
1541
+ }
1542
+ /**
1543
+ * Creates a transaction instruction to withdraw WSOL from a stake pool using a session.
1544
+ */
1545
+ static withdrawWsolWithSession(params) {
1546
+ const type = STAKE_POOL_INSTRUCTION_LAYOUTS.WithdrawWsolWithSession;
1547
+ const data = encodeData(type, { poolTokens: params.poolTokens });
1548
+ const keys = [
1549
+ { pubkey: params.stakePool, isSigner: false, isWritable: true },
1550
+ { pubkey: params.withdrawAuthority, isSigner: false, isWritable: false },
1551
+ { pubkey: params.userTransferAuthority, isSigner: true, isWritable: true },
1552
+ { pubkey: params.poolTokensFrom, isSigner: false, isWritable: true },
1553
+ { pubkey: params.reserveStake, isSigner: false, isWritable: true },
1554
+ { pubkey: params.userWsolAccount, isSigner: false, isWritable: true },
1555
+ { pubkey: params.managerFeeAccount, isSigner: false, isWritable: true },
1556
+ { pubkey: params.poolMint, isSigner: false, isWritable: true },
1557
+ { pubkey: web3_js.SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
1558
+ { pubkey: web3_js.SYSVAR_STAKE_HISTORY_PUBKEY, isSigner: false, isWritable: false },
1559
+ { pubkey: web3_js.StakeProgram.programId, isSigner: false, isWritable: false },
1560
+ { pubkey: params.tokenProgramId, isSigner: false, isWritable: false },
1561
+ { pubkey: params.wsolMint, isSigner: false, isWritable: false },
1562
+ { pubkey: params.programSigner, isSigner: false, isWritable: true },
1563
+ ];
1564
+ if (params.solWithdrawAuthority) {
1565
+ keys.push({
1566
+ pubkey: params.solWithdrawAuthority,
1567
+ isSigner: true,
1568
+ isWritable: false,
1569
+ });
1570
+ }
1571
+ return new web3_js.TransactionInstruction({
1572
+ programId: params.programId,
1573
+ keys,
1574
+ data,
1575
+ });
1576
+ }
1577
+ /**
1578
+ * Creates an instruction to create metadata
1579
+ * using the mpl token metadata program for the pool token
1580
+ */
1581
+ static createTokenMetadata(params) {
1582
+ const { programId, stakePool, withdrawAuthority, tokenMetadata, manager, payer, poolMint, name, symbol, uri, } = params;
1583
+ const keys = [
1584
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1585
+ { pubkey: manager, isSigner: true, isWritable: false },
1586
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1587
+ { pubkey: poolMint, isSigner: false, isWritable: false },
1588
+ { pubkey: payer, isSigner: true, isWritable: true },
1589
+ { pubkey: tokenMetadata, isSigner: false, isWritable: true },
1590
+ { pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false },
1591
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
1592
+ { pubkey: web3_js.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
1593
+ ];
1594
+ const type = tokenMetadataLayout(17, name.length, symbol.length, uri.length);
1595
+ const data = encodeData(type, {
1596
+ nameLen: name.length,
1597
+ name: Buffer.from(name),
1598
+ symbolLen: symbol.length,
1599
+ symbol: Buffer.from(symbol),
1600
+ uriLen: uri.length,
1601
+ uri: Buffer.from(uri),
1602
+ });
1603
+ return new web3_js.TransactionInstruction({
1604
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1605
+ keys,
1606
+ data,
1607
+ });
1608
+ }
1609
+ /**
1610
+ * Creates an instruction to update metadata
1611
+ * in the mpl token metadata program account for the pool token
1612
+ */
1613
+ static updateTokenMetadata(params) {
1614
+ const { programId, stakePool, withdrawAuthority, tokenMetadata, manager, name, symbol, uri } = params;
1615
+ const keys = [
1616
+ { pubkey: stakePool, isSigner: false, isWritable: false },
1617
+ { pubkey: manager, isSigner: true, isWritable: false },
1618
+ { pubkey: withdrawAuthority, isSigner: false, isWritable: false },
1619
+ { pubkey: tokenMetadata, isSigner: false, isWritable: true },
1620
+ { pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false },
1621
+ ];
1622
+ const type = tokenMetadataLayout(18, name.length, symbol.length, uri.length);
1623
+ const data = encodeData(type, {
1624
+ nameLen: name.length,
1625
+ name: Buffer.from(name),
1626
+ symbolLen: symbol.length,
1627
+ symbol: Buffer.from(symbol),
1628
+ uriLen: uri.length,
1629
+ uri: Buffer.from(uri),
1630
+ });
1631
+ return new web3_js.TransactionInstruction({
1632
+ programId: programId !== null && programId !== void 0 ? programId : STAKE_POOL_PROGRAM_ID,
1633
+ keys,
1634
+ data,
1635
+ });
1636
+ }
1637
+ /**
1638
+ * Decode a deposit stake pool instruction and retrieve the instruction params.
1639
+ */
1640
+ static decodeDepositStake(instruction) {
1641
+ this.checkProgramId(instruction.programId);
1642
+ this.checkKeyLength(instruction.keys, 11);
1643
+ decodeData(STAKE_POOL_INSTRUCTION_LAYOUTS.DepositStake, instruction.data);
1644
+ return {
1645
+ programId: instruction.programId,
1646
+ stakePool: instruction.keys[0].pubkey,
1647
+ validatorList: instruction.keys[1].pubkey,
1648
+ depositAuthority: instruction.keys[2].pubkey,
1649
+ withdrawAuthority: instruction.keys[3].pubkey,
1650
+ depositStake: instruction.keys[4].pubkey,
1651
+ validatorStake: instruction.keys[5].pubkey,
1652
+ reserveStake: instruction.keys[6].pubkey,
1653
+ destinationPoolAccount: instruction.keys[7].pubkey,
1654
+ managerFeeAccount: instruction.keys[8].pubkey,
1655
+ referralPoolAccount: instruction.keys[9].pubkey,
1656
+ poolMint: instruction.keys[10].pubkey,
1657
+ };
1658
+ }
1659
+ /**
1660
+ * Decode a deposit sol instruction and retrieve the instruction params.
1661
+ */
1662
+ static decodeDepositSol(instruction) {
1663
+ this.checkProgramId(instruction.programId);
1664
+ this.checkKeyLength(instruction.keys, 9);
1665
+ const { amount } = decodeData(STAKE_POOL_INSTRUCTION_LAYOUTS.DepositSol, instruction.data);
1666
+ return {
1667
+ programId: instruction.programId,
1668
+ stakePool: instruction.keys[0].pubkey,
1669
+ depositAuthority: instruction.keys[1].pubkey,
1670
+ withdrawAuthority: instruction.keys[2].pubkey,
1671
+ reserveStake: instruction.keys[3].pubkey,
1672
+ fundingAccount: instruction.keys[4].pubkey,
1673
+ destinationPoolAccount: instruction.keys[5].pubkey,
1674
+ managerFeeAccount: instruction.keys[6].pubkey,
1675
+ referralPoolAccount: instruction.keys[7].pubkey,
1676
+ poolMint: instruction.keys[8].pubkey,
1677
+ lamports: amount,
1678
+ };
1679
+ }
1680
+ /**
1681
+ * @internal
1682
+ */
1683
+ static checkProgramId(programId) {
1684
+ if (!programId.equals(STAKE_POOL_PROGRAM_ID)
1685
+ && !programId.equals(DEVNET_STAKE_POOL_PROGRAM_ID)) {
1686
+ throw new Error('Invalid instruction; programId is not the stake pool program');
1687
+ }
1688
+ }
1689
+ /**
1690
+ * @internal
1691
+ */
1692
+ static checkKeyLength(keys, expectedLength) {
1693
+ if (keys.length < expectedLength) {
1694
+ throw new Error(`Invalid instruction; found ${keys.length} keys, expected at least ${expectedLength}`);
1695
+ }
1696
+ }
1697
+ }
1698
+
1699
+ function getStakePoolProgramId(rpcEndpoint) {
1700
+ if (rpcEndpoint.includes('devnet')) {
1701
+ return DEVNET_STAKE_POOL_PROGRAM_ID;
1702
+ }
1703
+ else {
1704
+ return STAKE_POOL_PROGRAM_ID;
1705
+ }
1706
+ }
1707
+ /**
1708
+ * Retrieves and deserializes a StakePool account using a web3js connection and the stake pool address.
1709
+ * @param connection An active web3js connection.
1710
+ * @param stakePoolAddress The public key (address) of the stake pool account.
1711
+ */
1712
+ async function getStakePoolAccount(connection, stakePoolAddress) {
1713
+ const account = await connection.getAccountInfo(stakePoolAddress);
1714
+ if (!account) {
1715
+ throw new Error('Invalid stake pool account');
1716
+ }
1717
+ return {
1718
+ pubkey: stakePoolAddress,
1719
+ account: {
1720
+ data: StakePoolLayout.decode(account.data),
1721
+ executable: account.executable,
1722
+ lamports: account.lamports,
1723
+ owner: account.owner,
1724
+ },
1725
+ };
1726
+ }
1727
+ /**
1728
+ * Retrieves and deserializes a Stake account using a web3js connection and the stake address.
1729
+ * @param connection An active web3js connection.
1730
+ * @param stakeAccount The public key (address) of the stake account.
1731
+ */
1732
+ async function getStakeAccount(connection, stakeAccount) {
1733
+ const result = (await connection.getParsedAccountInfo(stakeAccount)).value;
1734
+ if (!result || !('parsed' in result.data)) {
1735
+ throw new Error('Invalid stake account');
1736
+ }
1737
+ const program = result.data.program;
1738
+ if (program !== 'stake') {
1739
+ throw new Error('Not a stake account');
1740
+ }
1741
+ return create(result.data.parsed, StakeAccount);
1742
+ }
1743
+ /**
1744
+ * Retrieves all StakePool and ValidatorList accounts that are running a particular StakePool program.
1745
+ * @param connection An active web3js connection.
1746
+ * @param stakePoolProgramAddress The public key (address) of the StakePool program.
1747
+ */
1748
+ async function getStakePoolAccounts(connection, stakePoolProgramAddress) {
1749
+ const response = await connection.getProgramAccounts(stakePoolProgramAddress);
1750
+ return response
1751
+ .map((a) => {
1752
+ try {
1753
+ if (a.account.data.readUInt8() === 1) {
1754
+ const data = StakePoolLayout.decode(a.account.data);
1755
+ return {
1756
+ pubkey: a.pubkey,
1757
+ account: {
1758
+ data,
1759
+ executable: a.account.executable,
1760
+ lamports: a.account.lamports,
1761
+ owner: a.account.owner,
1762
+ },
1763
+ };
1764
+ }
1765
+ else if (a.account.data.readUInt8() === 2) {
1766
+ const data = ValidatorListLayout.decode(a.account.data);
1767
+ return {
1768
+ pubkey: a.pubkey,
1769
+ account: {
1770
+ data,
1771
+ executable: a.account.executable,
1772
+ lamports: a.account.lamports,
1773
+ owner: a.account.owner,
1774
+ },
1775
+ };
1776
+ }
1777
+ else {
1778
+ console.error(`Could not decode. StakePoolAccount Enum is ${a.account.data.readUInt8()}, expected 1 or 2!`);
1779
+ return undefined;
1780
+ }
1781
+ }
1782
+ catch (error) {
1783
+ console.error('Could not decode account. Error:', error);
1784
+ return undefined;
1785
+ }
1786
+ })
1787
+ .filter(a => a !== undefined);
1788
+ }
1789
+ /**
1790
+ * Creates instructions required to deposit stake to stake pool.
1791
+ */
1792
+ async function depositStake(connection, stakePoolAddress, authorizedPubkey, validatorVote, depositStake, poolTokenReceiverAccount) {
1793
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
1794
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
1795
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
1796
+ const validatorStake = await findStakeProgramAddress(stakePoolProgramId, validatorVote, stakePoolAddress);
1797
+ const instructions = [];
1798
+ const signers = [];
1799
+ const poolMint = stakePool.account.data.poolMint;
1800
+ // Create token account if not specified
1801
+ if (!poolTokenReceiverAccount) {
1802
+ const associatedAddress = splToken.getAssociatedTokenAddressSync(poolMint, authorizedPubkey);
1803
+ instructions.push(splToken.createAssociatedTokenAccountIdempotentInstruction(authorizedPubkey, associatedAddress, authorizedPubkey, poolMint));
1804
+ poolTokenReceiverAccount = associatedAddress;
1805
+ }
1806
+ instructions.push(...web3_js.StakeProgram.authorize({
1807
+ stakePubkey: depositStake,
1808
+ authorizedPubkey,
1809
+ newAuthorizedPubkey: stakePool.account.data.stakeDepositAuthority,
1810
+ stakeAuthorizationType: web3_js.StakeAuthorizationLayout.Staker,
1811
+ }).instructions);
1812
+ instructions.push(...web3_js.StakeProgram.authorize({
1813
+ stakePubkey: depositStake,
1814
+ authorizedPubkey,
1815
+ newAuthorizedPubkey: stakePool.account.data.stakeDepositAuthority,
1816
+ stakeAuthorizationType: web3_js.StakeAuthorizationLayout.Withdrawer,
1817
+ }).instructions);
1818
+ instructions.push(StakePoolInstruction.depositStake({
1819
+ programId: stakePoolProgramId,
1820
+ stakePool: stakePoolAddress,
1821
+ validatorList: stakePool.account.data.validatorList,
1822
+ depositAuthority: stakePool.account.data.stakeDepositAuthority,
1823
+ reserveStake: stakePool.account.data.reserveStake,
1824
+ managerFeeAccount: stakePool.account.data.managerFeeAccount,
1825
+ referralPoolAccount: poolTokenReceiverAccount,
1826
+ destinationPoolAccount: poolTokenReceiverAccount,
1827
+ withdrawAuthority,
1828
+ depositStake,
1829
+ validatorStake,
1830
+ poolMint,
1831
+ }));
1832
+ return {
1833
+ instructions,
1834
+ signers,
1835
+ };
1836
+ }
1837
+ /**
1838
+ * Creates instructions required to deposit sol to stake pool.
1839
+ */
1840
+ async function depositWsolWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, lamports, destinationTokenAccount, referrerTokenAccount, depositAuthority, payer) {
1841
+ const wsolTokenAccount = splToken.getAssociatedTokenAddressSync(splToken.NATIVE_MINT, userPubkey);
1842
+ const tokenAccountInfo = await connection.getTokenAccountBalance(wsolTokenAccount, 'confirmed');
1843
+ const wsolBalance = tokenAccountInfo
1844
+ ? parseInt(tokenAccountInfo.value.amount)
1845
+ : 0;
1846
+ if (wsolBalance < lamports) {
1847
+ throw new Error(`Not enough WSOL to deposit into pool. Maximum deposit amount is ${lamportsToSol(wsolBalance)} WSOL.`);
1848
+ }
1849
+ const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
1850
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
1851
+ const stakePool = stakePoolAccount.account.data;
1852
+ // stakePool.tokenProgramId
1853
+ const instructions = [];
1854
+ // Create token account if not specified
1855
+ if (!destinationTokenAccount) {
1856
+ const associatedAddress = splToken.getAssociatedTokenAddressSync(stakePool.poolMint, userPubkey);
1857
+ instructions.push(splToken.createAssociatedTokenAccountIdempotentInstruction(payer !== null && payer !== void 0 ? payer : signerOrSession, associatedAddress, userPubkey, stakePool.poolMint));
1858
+ destinationTokenAccount = associatedAddress;
1859
+ }
1860
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
1861
+ const [programSigner] = web3_js.PublicKey.findProgramAddressSync([Buffer.from('fogo_session_program_signer')], stakePoolProgramId);
1862
+ const wsolTransientAccount = findWsolTransientProgramAddress(stakePoolProgramId, userPubkey);
1863
+ instructions.push(StakePoolInstruction.depositWsolWithSession({
1864
+ programId: stakePoolProgramId,
1865
+ stakePool: stakePoolAddress,
1866
+ reserveStake: stakePool.reserveStake,
1867
+ fundingAccount: signerOrSession,
1868
+ destinationPoolAccount: destinationTokenAccount,
1869
+ managerFeeAccount: stakePool.managerFeeAccount,
1870
+ referralPoolAccount: referrerTokenAccount !== null && referrerTokenAccount !== void 0 ? referrerTokenAccount : destinationTokenAccount,
1871
+ poolMint: stakePool.poolMint,
1872
+ lamports,
1873
+ withdrawAuthority,
1874
+ depositAuthority,
1875
+ wsolMint: splToken.NATIVE_MINT,
1876
+ wsolTokenAccount,
1877
+ wsolTransientAccount,
1878
+ tokenProgramId: stakePool.tokenProgramId,
1879
+ programSigner,
1880
+ payer,
1881
+ }));
1882
+ return {
1883
+ instructions,
1884
+ signers: [],
1885
+ };
1886
+ }
1887
+ /**
1888
+ * Creates instructions required to deposit sol to stake pool.
1889
+ */
1890
+ async function depositSol(connection, stakePoolAddress, from, lamports, destinationTokenAccount, referrerTokenAccount, depositAuthority) {
1891
+ const fromBalance = await connection.getBalance(from, 'confirmed');
1892
+ if (fromBalance < lamports) {
1893
+ throw new Error(`Not enough SOL to deposit into pool. Maximum deposit amount is ${lamportsToSol(fromBalance)} SOL.`);
1894
+ }
1895
+ const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
1896
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
1897
+ const stakePool = stakePoolAccount.account.data;
1898
+ // Ephemeral SOL account just to do the transfer
1899
+ const userSolTransfer = new web3_js.Keypair();
1900
+ const signers = [userSolTransfer];
1901
+ const instructions = [];
1902
+ // Create the ephemeral SOL account
1903
+ instructions.push(web3_js.SystemProgram.transfer({
1904
+ fromPubkey: from,
1905
+ toPubkey: userSolTransfer.publicKey,
1906
+ lamports,
1907
+ }));
1908
+ // Create token account if not specified
1909
+ if (!destinationTokenAccount) {
1910
+ const associatedAddress = splToken.getAssociatedTokenAddressSync(stakePool.poolMint, from);
1911
+ instructions.push(splToken.createAssociatedTokenAccountIdempotentInstruction(from, associatedAddress, from, stakePool.poolMint));
1912
+ destinationTokenAccount = associatedAddress;
1913
+ }
1914
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
1915
+ instructions.push(StakePoolInstruction.depositSol({
1916
+ programId: stakePoolProgramId,
1917
+ stakePool: stakePoolAddress,
1918
+ reserveStake: stakePool.reserveStake,
1919
+ fundingAccount: userSolTransfer.publicKey,
1920
+ destinationPoolAccount: destinationTokenAccount,
1921
+ managerFeeAccount: stakePool.managerFeeAccount,
1922
+ referralPoolAccount: referrerTokenAccount !== null && referrerTokenAccount !== void 0 ? referrerTokenAccount : destinationTokenAccount,
1923
+ poolMint: stakePool.poolMint,
1924
+ lamports,
1925
+ withdrawAuthority,
1926
+ depositAuthority,
1927
+ }));
1928
+ return {
1929
+ instructions,
1930
+ signers,
1931
+ };
1932
+ }
1933
+ /**
1934
+ * Creates instructions required to withdraw stake from a stake pool.
1935
+ */
1936
+ async function withdrawStake(connection, stakePoolAddress, tokenOwner, amount, useReserve = false, voteAccountAddress, stakeReceiver, poolTokenAccount, validatorComparator) {
1937
+ var _c, _d, _e, _f;
1938
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
1939
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
1940
+ const poolAmount = new BN(solToLamports(amount));
1941
+ if (!poolTokenAccount) {
1942
+ poolTokenAccount = splToken.getAssociatedTokenAddressSync(stakePool.account.data.poolMint, tokenOwner);
1943
+ }
1944
+ const tokenAccount = await splToken.getAccount(connection, poolTokenAccount);
1945
+ // Check withdrawFrom balance
1946
+ if (tokenAccount.amount < poolAmount.toNumber()) {
1947
+ throw new Error(`Not enough token balance to withdraw ${lamportsToSol(poolAmount)} pool tokens.
1948
+ Maximum withdraw amount is ${lamportsToSol(tokenAccount.amount)} pool tokens.`);
1949
+ }
1950
+ const stakeAccountRentExemption = await connection.getMinimumBalanceForRentExemption(web3_js.StakeProgram.space);
1951
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
1952
+ let stakeReceiverAccount = null;
1953
+ if (stakeReceiver) {
1954
+ stakeReceiverAccount = await getStakeAccount(connection, stakeReceiver);
1955
+ }
1956
+ const withdrawAccounts = [];
1957
+ if (useReserve) {
1958
+ withdrawAccounts.push({
1959
+ stakeAddress: stakePool.account.data.reserveStake,
1960
+ voteAddress: undefined,
1961
+ poolAmount,
1962
+ });
1963
+ }
1964
+ else if (stakeReceiverAccount
1965
+ && (stakeReceiverAccount === null || stakeReceiverAccount === void 0 ? void 0 : stakeReceiverAccount.type) === 'delegated') {
1966
+ const voteAccount = (_d = (_c = stakeReceiverAccount.info) === null || _c === void 0 ? void 0 : _c.stake) === null || _d === void 0 ? void 0 : _d.delegation.voter;
1967
+ if (!voteAccount) {
1968
+ throw new Error(`Invalid stake receiver ${stakeReceiver} delegation`);
1969
+ }
1970
+ const validatorListAccount = await connection.getAccountInfo(stakePool.account.data.validatorList);
1971
+ const validatorList = ValidatorListLayout.decode(validatorListAccount === null || validatorListAccount === void 0 ? void 0 : validatorListAccount.data);
1972
+ const isValidVoter = validatorList.validators.find(val => val.voteAccountAddress.equals(voteAccount));
1973
+ if (voteAccountAddress && voteAccountAddress !== voteAccount) {
1974
+ throw new Error(`Provided withdrawal vote account ${voteAccountAddress} does not match delegation on stake receiver account ${voteAccount},
1975
+ remove this flag or provide a different stake account delegated to ${voteAccountAddress}`);
1976
+ }
1977
+ if (isValidVoter) {
1978
+ const stakeAccountAddress = await findStakeProgramAddress(stakePoolProgramId, voteAccount, stakePoolAddress);
1979
+ const stakeAccount = await connection.getAccountInfo(stakeAccountAddress);
1980
+ if (!stakeAccount) {
1981
+ throw new Error(`Preferred withdraw valdator's stake account is invalid`);
1982
+ }
1983
+ const availableForWithdrawal = calcLamportsWithdrawAmount(stakePool.account.data, new BN(stakeAccount.lamports
1984
+ - MINIMUM_ACTIVE_STAKE
1985
+ - stakeAccountRentExemption));
1986
+ if (availableForWithdrawal.lt(poolAmount)) {
1987
+ throw new Error(`Not enough lamports available for withdrawal from ${stakeAccountAddress},
1988
+ ${poolAmount} asked, ${availableForWithdrawal} available.`);
1989
+ }
1990
+ withdrawAccounts.push({
1991
+ stakeAddress: stakeAccountAddress,
1992
+ voteAddress: voteAccount,
1993
+ poolAmount,
1994
+ });
1995
+ }
1996
+ else {
1997
+ throw new Error(`Provided stake account is delegated to a vote account ${voteAccount} which does not exist in the stake pool`);
1998
+ }
1999
+ }
2000
+ else if (voteAccountAddress) {
2001
+ const stakeAccountAddress = await findStakeProgramAddress(stakePoolProgramId, voteAccountAddress, stakePoolAddress);
2002
+ const stakeAccount = await connection.getAccountInfo(stakeAccountAddress);
2003
+ if (!stakeAccount) {
2004
+ throw new Error('Invalid Stake Account');
2005
+ }
2006
+ const availableLamports = new BN(stakeAccount.lamports - MINIMUM_ACTIVE_STAKE - stakeAccountRentExemption);
2007
+ if (availableLamports.lt(new BN(0))) {
2008
+ throw new Error('Invalid Stake Account');
2009
+ }
2010
+ const availableForWithdrawal = calcLamportsWithdrawAmount(stakePool.account.data, availableLamports);
2011
+ if (availableForWithdrawal.lt(poolAmount)) {
2012
+ // noinspection ExceptionCaughtLocallyJS
2013
+ throw new Error(`Not enough lamports available for withdrawal from ${stakeAccountAddress},
2014
+ ${poolAmount} asked, ${availableForWithdrawal} available.`);
2015
+ }
2016
+ withdrawAccounts.push({
2017
+ stakeAddress: stakeAccountAddress,
2018
+ voteAddress: voteAccountAddress,
2019
+ poolAmount,
2020
+ });
2021
+ }
2022
+ else {
2023
+ // Get the list of accounts to withdraw from
2024
+ withdrawAccounts.push(...(await prepareWithdrawAccounts(connection, stakePool.account.data, stakePoolAddress, poolAmount, validatorComparator, poolTokenAccount.equals(stakePool.account.data.managerFeeAccount))));
2025
+ }
2026
+ // Construct transaction to withdraw from withdrawAccounts account list
2027
+ const instructions = [];
2028
+ const userTransferAuthority = web3_js.Keypair.generate();
2029
+ const signers = [userTransferAuthority];
2030
+ instructions.push(splToken.createApproveInstruction(poolTokenAccount, userTransferAuthority.publicKey, tokenOwner, poolAmount.toNumber()));
2031
+ let totalRentFreeBalances = 0;
2032
+ // Max 5 accounts to prevent an error: "Transaction too large"
2033
+ const maxWithdrawAccounts = 5;
2034
+ let i = 0;
2035
+ // Go through prepared accounts and withdraw/claim them
2036
+ for (const withdrawAccount of withdrawAccounts) {
2037
+ if (i > maxWithdrawAccounts) {
2038
+ break;
2039
+ }
2040
+ // Convert pool tokens amount to lamports
2041
+ const solWithdrawAmount = calcLamportsWithdrawAmount(stakePool.account.data, withdrawAccount.poolAmount);
2042
+ let infoMsg = `Withdrawing ◎${solWithdrawAmount},
2043
+ from stake account ${(_e = withdrawAccount.stakeAddress) === null || _e === void 0 ? void 0 : _e.toBase58()}`;
2044
+ if (withdrawAccount.voteAddress) {
2045
+ infoMsg = `${infoMsg}, delegated to ${(_f = withdrawAccount.voteAddress) === null || _f === void 0 ? void 0 : _f.toBase58()}`;
2046
+ }
2047
+ console.info(infoMsg);
2048
+ let stakeToReceive;
2049
+ if (!stakeReceiver
2050
+ || (stakeReceiverAccount && stakeReceiverAccount.type === 'delegated')) {
2051
+ const stakeKeypair = newStakeAccount(tokenOwner, instructions, stakeAccountRentExemption);
2052
+ signers.push(stakeKeypair);
2053
+ totalRentFreeBalances += stakeAccountRentExemption;
2054
+ stakeToReceive = stakeKeypair.publicKey;
2055
+ }
2056
+ else {
2057
+ stakeToReceive = stakeReceiver;
2058
+ }
2059
+ instructions.push(StakePoolInstruction.withdrawStake({
2060
+ programId: stakePoolProgramId,
2061
+ stakePool: stakePoolAddress,
2062
+ validatorList: stakePool.account.data.validatorList,
2063
+ validatorStake: withdrawAccount.stakeAddress,
2064
+ destinationStake: stakeToReceive,
2065
+ destinationStakeAuthority: tokenOwner,
2066
+ sourceTransferAuthority: userTransferAuthority.publicKey,
2067
+ sourcePoolAccount: poolTokenAccount,
2068
+ managerFeeAccount: stakePool.account.data.managerFeeAccount,
2069
+ poolMint: stakePool.account.data.poolMint,
2070
+ poolTokens: withdrawAccount.poolAmount.toNumber(),
2071
+ withdrawAuthority,
2072
+ }));
2073
+ i++;
2074
+ }
2075
+ if (stakeReceiver
2076
+ && stakeReceiverAccount
2077
+ && stakeReceiverAccount.type === 'delegated') {
2078
+ signers.forEach((newStakeKeypair) => {
2079
+ instructions.concat(web3_js.StakeProgram.merge({
2080
+ stakePubkey: stakeReceiver,
2081
+ sourceStakePubKey: newStakeKeypair.publicKey,
2082
+ authorizedPubkey: tokenOwner,
2083
+ }).instructions);
2084
+ });
2085
+ }
2086
+ return {
2087
+ instructions,
2088
+ signers,
2089
+ stakeReceiver,
2090
+ totalRentFreeBalances,
2091
+ };
2092
+ }
2093
+ /**
2094
+ * Creates instructions required to withdraw SOL directly from a stake pool.
2095
+ */
2096
+ async function withdrawSol(connection, stakePoolAddress, tokenOwner, solReceiver, amount, solWithdrawAuthority) {
2097
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
2098
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2099
+ const poolAmount = solToLamports(amount);
2100
+ const poolTokenAccount = splToken.getAssociatedTokenAddressSync(stakePool.account.data.poolMint, tokenOwner);
2101
+ const tokenAccount = await splToken.getAccount(connection, poolTokenAccount);
2102
+ // Check withdrawFrom balance
2103
+ if (tokenAccount.amount < poolAmount) {
2104
+ throw new Error(`Not enough token balance to withdraw ${lamportsToSol(poolAmount)} pool tokens.
2105
+ Maximum withdraw amount is ${lamportsToSol(tokenAccount.amount)} pool tokens.`);
2106
+ }
2107
+ // Construct transaction to withdraw from withdrawAccounts account list
2108
+ const instructions = [];
2109
+ const userTransferAuthority = web3_js.Keypair.generate();
2110
+ const signers = [userTransferAuthority];
2111
+ instructions.push(splToken.createApproveInstruction(poolTokenAccount, userTransferAuthority.publicKey, tokenOwner, poolAmount));
2112
+ const poolWithdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2113
+ if (solWithdrawAuthority) {
2114
+ const expectedSolWithdrawAuthority = stakePool.account.data.solWithdrawAuthority;
2115
+ if (!expectedSolWithdrawAuthority) {
2116
+ throw new Error('SOL withdraw authority specified in arguments but stake pool has none');
2117
+ }
2118
+ if (solWithdrawAuthority.toBase58() !== expectedSolWithdrawAuthority.toBase58()) {
2119
+ throw new Error(`Invalid deposit withdraw specified, expected ${expectedSolWithdrawAuthority.toBase58()}, received ${solWithdrawAuthority.toBase58()}`);
2120
+ }
2121
+ }
2122
+ const withdrawTransaction = StakePoolInstruction.withdrawSol({
2123
+ programId: stakePoolProgramId,
2124
+ stakePool: stakePoolAddress,
2125
+ withdrawAuthority: poolWithdrawAuthority,
2126
+ reserveStake: stakePool.account.data.reserveStake,
2127
+ sourcePoolAccount: poolTokenAccount,
2128
+ sourceTransferAuthority: userTransferAuthority.publicKey,
2129
+ destinationSystemAccount: solReceiver,
2130
+ managerFeeAccount: stakePool.account.data.managerFeeAccount,
2131
+ poolMint: stakePool.account.data.poolMint,
2132
+ poolTokens: poolAmount,
2133
+ solWithdrawAuthority,
2134
+ });
2135
+ instructions.push(withdrawTransaction);
2136
+ return {
2137
+ instructions,
2138
+ signers,
2139
+ };
2140
+ }
2141
+ /**
2142
+ * Creates instructions required to withdraw wSOL from a stake pool.
2143
+ */
2144
+ async function withdrawWsolWithSession(connection, stakePoolAddress, signerOrSession, userPubkey, amount, solWithdrawAuthority) {
2145
+ const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
2146
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2147
+ const stakePool = stakePoolAccount.account.data;
2148
+ const poolTokens = solToLamports(amount);
2149
+ const poolTokenAccount = splToken.getAssociatedTokenAddressSync(stakePool.poolMint, userPubkey);
2150
+ const tokenAccount = await splToken.getAccount(connection, poolTokenAccount);
2151
+ if (tokenAccount.amount < poolTokens) {
2152
+ throw new Error(`Not enough token balance to withdraw ${amount} pool tokens.
2153
+ Maximum withdraw amount is ${lamportsToSol(tokenAccount.amount)} pool tokens.`);
2154
+ }
2155
+ const userWsolAccount = splToken.getAssociatedTokenAddressSync(splToken.NATIVE_MINT, userPubkey);
2156
+ const instructions = [];
2157
+ const signers = [];
2158
+ instructions.push(splToken.createAssociatedTokenAccountIdempotentInstruction(signerOrSession, userWsolAccount, userPubkey, splToken.NATIVE_MINT));
2159
+ const [programSigner] = web3_js.PublicKey.findProgramAddressSync([Buffer.from('fogo_session_program_signer')], stakePoolProgramId);
2160
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2161
+ instructions.push(StakePoolInstruction.withdrawWsolWithSession({
2162
+ programId: stakePoolProgramId,
2163
+ stakePool: stakePoolAddress,
2164
+ withdrawAuthority,
2165
+ userTransferAuthority: signerOrSession,
2166
+ poolTokensFrom: poolTokenAccount,
2167
+ reserveStake: stakePool.reserveStake,
2168
+ userWsolAccount,
2169
+ managerFeeAccount: stakePool.managerFeeAccount,
2170
+ poolMint: stakePool.poolMint,
2171
+ tokenProgramId: stakePool.tokenProgramId,
2172
+ solWithdrawAuthority,
2173
+ wsolMint: splToken.NATIVE_MINT,
2174
+ programSigner,
2175
+ poolTokens,
2176
+ }));
2177
+ return {
2178
+ instructions,
2179
+ signers,
2180
+ };
2181
+ }
2182
+ async function addValidatorToPool(connection, stakePoolAddress, validatorVote, seed) {
2183
+ const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
2184
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2185
+ const stakePool = stakePoolAccount.account.data;
2186
+ const { reserveStake, staker, validatorList } = stakePool;
2187
+ const validatorListAccount = await getValidatorListAccount(connection, validatorList);
2188
+ const validatorInfo = validatorListAccount.account.data.validators.find(v => v.voteAccountAddress.toBase58() === validatorVote.toBase58());
2189
+ if (validatorInfo) {
2190
+ throw new Error('Vote account is already in validator list');
2191
+ }
2192
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2193
+ const validatorStake = await findStakeProgramAddress(stakePoolProgramId, validatorVote, stakePoolAddress, seed);
2194
+ const instructions = [
2195
+ StakePoolInstruction.addValidatorToPool({
2196
+ programId: stakePoolProgramId,
2197
+ stakePool: stakePoolAddress,
2198
+ staker,
2199
+ reserveStake,
2200
+ withdrawAuthority,
2201
+ validatorList,
2202
+ validatorStake,
2203
+ validatorVote,
2204
+ }),
2205
+ ];
2206
+ return {
2207
+ instructions,
2208
+ };
2209
+ }
2210
+ async function removeValidatorFromPool(connection, stakePoolAddress, validatorVote, seed) {
2211
+ const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress);
2212
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2213
+ const stakePool = stakePoolAccount.account.data;
2214
+ const { staker, validatorList } = stakePool;
2215
+ const validatorListAccount = await getValidatorListAccount(connection, validatorList);
2216
+ const validatorInfo = validatorListAccount.account.data.validators.find(v => v.voteAccountAddress.toBase58() === validatorVote.toBase58());
2217
+ if (!validatorInfo) {
2218
+ throw new Error('Vote account is not already in validator list');
2219
+ }
2220
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2221
+ const validatorStake = await findStakeProgramAddress(stakePoolProgramId, validatorVote, stakePoolAddress, seed);
2222
+ const transientStakeSeed = validatorInfo.transientSeedSuffixStart;
2223
+ const transientStake = await findTransientStakeProgramAddress(stakePoolProgramId, validatorInfo.voteAccountAddress, stakePoolAddress, transientStakeSeed);
2224
+ const instructions = [
2225
+ StakePoolInstruction.removeValidatorFromPool({
2226
+ programId: stakePoolProgramId,
2227
+ stakePool: stakePoolAddress,
2228
+ staker,
2229
+ withdrawAuthority,
2230
+ validatorList,
2231
+ validatorStake,
2232
+ transientStake,
2233
+ }),
2234
+ ];
2235
+ return {
2236
+ instructions,
2237
+ };
2238
+ }
2239
+ /**
2240
+ * Creates instructions required to increase validator stake.
2241
+ */
2242
+ async function increaseValidatorStake(connection, stakePoolAddress, validatorVote, lamports, ephemeralStakeSeed) {
2243
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
2244
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2245
+ const validatorList = await getValidatorListAccount(connection, stakePool.account.data.validatorList);
2246
+ const validatorInfo = validatorList.account.data.validators.find(v => v.voteAccountAddress.toBase58() === validatorVote.toBase58());
2247
+ if (!validatorInfo) {
2248
+ throw new Error('Vote account not found in validator list');
2249
+ }
2250
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2251
+ // Bump transient seed suffix by one to avoid reuse when not using the increaseAdditionalStake instruction
2252
+ const transientStakeSeed = ephemeralStakeSeed === undefined
2253
+ ? validatorInfo.transientSeedSuffixStart.addn(1)
2254
+ : validatorInfo.transientSeedSuffixStart;
2255
+ const transientStake = await findTransientStakeProgramAddress(stakePoolProgramId, validatorInfo.voteAccountAddress, stakePoolAddress, transientStakeSeed);
2256
+ const validatorStake = await findStakeProgramAddress(stakePoolProgramId, validatorInfo.voteAccountAddress, stakePoolAddress);
2257
+ const instructions = [];
2258
+ if (ephemeralStakeSeed !== undefined) {
2259
+ const ephemeralStake = await findEphemeralStakeProgramAddress(stakePoolProgramId, stakePoolAddress, new BN(ephemeralStakeSeed));
2260
+ instructions.push(StakePoolInstruction.increaseAdditionalValidatorStake({
2261
+ programId: stakePoolProgramId,
2262
+ stakePool: stakePoolAddress,
2263
+ staker: stakePool.account.data.staker,
2264
+ validatorList: stakePool.account.data.validatorList,
2265
+ reserveStake: stakePool.account.data.reserveStake,
2266
+ transientStakeSeed: transientStakeSeed.toNumber(),
2267
+ withdrawAuthority,
2268
+ transientStake,
2269
+ validatorStake,
2270
+ validatorVote,
2271
+ lamports,
2272
+ ephemeralStake,
2273
+ ephemeralStakeSeed,
2274
+ }));
2275
+ }
2276
+ else {
2277
+ instructions.push(StakePoolInstruction.increaseValidatorStake({
2278
+ programId: stakePoolProgramId,
2279
+ stakePool: stakePoolAddress,
2280
+ staker: stakePool.account.data.staker,
2281
+ validatorList: stakePool.account.data.validatorList,
2282
+ reserveStake: stakePool.account.data.reserveStake,
2283
+ transientStakeSeed: transientStakeSeed.toNumber(),
2284
+ withdrawAuthority,
2285
+ transientStake,
2286
+ validatorStake,
2287
+ validatorVote,
2288
+ lamports,
2289
+ }));
2290
+ }
2291
+ return {
2292
+ instructions,
2293
+ };
2294
+ }
2295
+ /**
2296
+ * Creates instructions required to decrease validator stake.
2297
+ */
2298
+ async function decreaseValidatorStake(connection, stakePoolAddress, validatorVote, lamports, ephemeralStakeSeed) {
2299
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
2300
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2301
+ const validatorList = await getValidatorListAccount(connection, stakePool.account.data.validatorList);
2302
+ const validatorInfo = validatorList.account.data.validators.find(v => v.voteAccountAddress.toBase58() === validatorVote.toBase58());
2303
+ if (!validatorInfo) {
2304
+ throw new Error('Vote account not found in validator list');
2305
+ }
2306
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2307
+ const validatorStake = await findStakeProgramAddress(stakePoolProgramId, validatorInfo.voteAccountAddress, stakePoolAddress);
2308
+ // Bump transient seed suffix by one to avoid reuse when not using the decreaseAdditionalStake instruction
2309
+ const transientStakeSeed = ephemeralStakeSeed === undefined
2310
+ ? validatorInfo.transientSeedSuffixStart.addn(1)
2311
+ : validatorInfo.transientSeedSuffixStart;
2312
+ const transientStake = await findTransientStakeProgramAddress(stakePoolProgramId, validatorInfo.voteAccountAddress, stakePoolAddress, transientStakeSeed);
2313
+ const instructions = [];
2314
+ if (ephemeralStakeSeed !== undefined) {
2315
+ const ephemeralStake = await findEphemeralStakeProgramAddress(stakePoolProgramId, stakePoolAddress, new BN(ephemeralStakeSeed));
2316
+ instructions.push(StakePoolInstruction.decreaseAdditionalValidatorStake({
2317
+ programId: stakePoolProgramId,
2318
+ stakePool: stakePoolAddress,
2319
+ staker: stakePool.account.data.staker,
2320
+ validatorList: stakePool.account.data.validatorList,
2321
+ reserveStake: stakePool.account.data.reserveStake,
2322
+ transientStakeSeed: transientStakeSeed.toNumber(),
2323
+ withdrawAuthority,
2324
+ validatorStake,
2325
+ transientStake,
2326
+ lamports,
2327
+ ephemeralStake,
2328
+ ephemeralStakeSeed,
2329
+ }));
2330
+ }
2331
+ else {
2332
+ instructions.push(StakePoolInstruction.decreaseValidatorStakeWithReserve({
2333
+ programId: stakePoolProgramId,
2334
+ stakePool: stakePoolAddress,
2335
+ staker: stakePool.account.data.staker,
2336
+ validatorList: stakePool.account.data.validatorList,
2337
+ reserveStake: stakePool.account.data.reserveStake,
2338
+ transientStakeSeed: transientStakeSeed.toNumber(),
2339
+ withdrawAuthority,
2340
+ validatorStake,
2341
+ transientStake,
2342
+ lamports,
2343
+ }));
2344
+ }
2345
+ return {
2346
+ instructions,
2347
+ };
2348
+ }
2349
+ /**
2350
+ * Creates instructions required to completely update a stake pool after epoch change.
2351
+ */
2352
+ async function updateStakePool(connection, stakePool, noMerge = false) {
2353
+ const stakePoolAddress = stakePool.pubkey;
2354
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2355
+ const validatorList = await getValidatorListAccount(connection, stakePool.account.data.validatorList);
2356
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2357
+ const updateListInstructions = [];
2358
+ const instructions = [];
2359
+ let startIndex = 0;
2360
+ const validatorChunks = arrayChunk(validatorList.account.data.validators, MAX_VALIDATORS_TO_UPDATE);
2361
+ for (const validatorChunk of validatorChunks) {
2362
+ const validatorAndTransientStakePairs = [];
2363
+ for (const validator of validatorChunk) {
2364
+ const validatorStake = await findStakeProgramAddress(stakePoolProgramId, validator.voteAccountAddress, stakePoolAddress);
2365
+ validatorAndTransientStakePairs.push(validatorStake);
2366
+ const transientStake = await findTransientStakeProgramAddress(stakePoolProgramId, validator.voteAccountAddress, stakePoolAddress, validator.transientSeedSuffixStart);
2367
+ validatorAndTransientStakePairs.push(transientStake);
2368
+ }
2369
+ updateListInstructions.push(StakePoolInstruction.updateValidatorListBalance({
2370
+ programId: stakePoolProgramId,
2371
+ stakePool: stakePoolAddress,
2372
+ validatorList: stakePool.account.data.validatorList,
2373
+ reserveStake: stakePool.account.data.reserveStake,
2374
+ validatorAndTransientStakePairs,
2375
+ withdrawAuthority,
2376
+ startIndex,
2377
+ noMerge,
2378
+ }));
2379
+ startIndex += MAX_VALIDATORS_TO_UPDATE;
2380
+ }
2381
+ instructions.push(StakePoolInstruction.updateStakePoolBalance({
2382
+ programId: stakePoolProgramId,
2383
+ stakePool: stakePoolAddress,
2384
+ validatorList: stakePool.account.data.validatorList,
2385
+ reserveStake: stakePool.account.data.reserveStake,
2386
+ managerFeeAccount: stakePool.account.data.managerFeeAccount,
2387
+ poolMint: stakePool.account.data.poolMint,
2388
+ withdrawAuthority,
2389
+ }));
2390
+ instructions.push(StakePoolInstruction.cleanupRemovedValidatorEntries({
2391
+ programId: stakePoolProgramId,
2392
+ stakePool: stakePoolAddress,
2393
+ validatorList: stakePool.account.data.validatorList,
2394
+ }));
2395
+ return {
2396
+ updateListInstructions,
2397
+ finalInstructions: instructions,
2398
+ };
2399
+ }
2400
+ /**
2401
+ * Retrieves detailed information about the StakePool.
2402
+ */
2403
+ async function stakePoolInfo(connection, stakePoolAddress) {
2404
+ var _c, _d;
2405
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
2406
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2407
+ const reserveAccountStakeAddress = stakePool.account.data.reserveStake;
2408
+ const totalLamports = stakePool.account.data.totalLamports;
2409
+ const lastUpdateEpoch = stakePool.account.data.lastUpdateEpoch;
2410
+ const validatorList = await getValidatorListAccount(connection, stakePool.account.data.validatorList);
2411
+ const maxNumberOfValidators = validatorList.account.data.maxValidators;
2412
+ const currentNumberOfValidators = validatorList.account.data.validators.length;
2413
+ const epochInfo = await connection.getEpochInfo();
2414
+ const reserveStake = await connection.getAccountInfo(reserveAccountStakeAddress);
2415
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2416
+ const minimumReserveStakeBalance = await connection.getMinimumBalanceForRentExemption(web3_js.StakeProgram.space);
2417
+ const stakeAccounts = await Promise.all(validatorList.account.data.validators.map(async (validator) => {
2418
+ const stakeAccountAddress = await findStakeProgramAddress(stakePoolProgramId, validator.voteAccountAddress, stakePoolAddress);
2419
+ const transientStakeAccountAddress = await findTransientStakeProgramAddress(stakePoolProgramId, validator.voteAccountAddress, stakePoolAddress, validator.transientSeedSuffixStart);
2420
+ const updateRequired = !validator.lastUpdateEpoch.eqn(epochInfo.epoch);
2421
+ return {
2422
+ voteAccountAddress: validator.voteAccountAddress.toBase58(),
2423
+ stakeAccountAddress: stakeAccountAddress.toBase58(),
2424
+ validatorActiveStakeLamports: validator.activeStakeLamports.toString(),
2425
+ validatorLastUpdateEpoch: validator.lastUpdateEpoch.toString(),
2426
+ validatorLamports: validator.activeStakeLamports
2427
+ .add(validator.transientStakeLamports)
2428
+ .toString(),
2429
+ validatorTransientStakeAccountAddress: transientStakeAccountAddress.toBase58(),
2430
+ validatorTransientStakeLamports: validator.transientStakeLamports.toString(),
2431
+ updateRequired,
2432
+ };
2433
+ }));
2434
+ const totalPoolTokens = lamportsToSol(stakePool.account.data.poolTokenSupply);
2435
+ const updateRequired = !lastUpdateEpoch.eqn(epochInfo.epoch);
2436
+ return {
2437
+ address: stakePoolAddress.toBase58(),
2438
+ poolWithdrawAuthority: withdrawAuthority.toBase58(),
2439
+ manager: stakePool.account.data.manager.toBase58(),
2440
+ staker: stakePool.account.data.staker.toBase58(),
2441
+ stakeDepositAuthority: stakePool.account.data.stakeDepositAuthority.toBase58(),
2442
+ stakeWithdrawBumpSeed: stakePool.account.data.stakeWithdrawBumpSeed,
2443
+ maxValidators: maxNumberOfValidators,
2444
+ validatorList: validatorList.account.data.validators.map((validator) => {
2445
+ return {
2446
+ activeStakeLamports: validator.activeStakeLamports.toString(),
2447
+ transientStakeLamports: validator.transientStakeLamports.toString(),
2448
+ lastUpdateEpoch: validator.lastUpdateEpoch.toString(),
2449
+ transientSeedSuffixStart: validator.transientSeedSuffixStart.toString(),
2450
+ transientSeedSuffixEnd: validator.transientSeedSuffixEnd.toString(),
2451
+ status: validator.status.toString(),
2452
+ voteAccountAddress: validator.voteAccountAddress.toString(),
2453
+ };
2454
+ }), // CliStakePoolValidator
2455
+ validatorListStorageAccount: stakePool.account.data.validatorList.toBase58(),
2456
+ reserveStake: stakePool.account.data.reserveStake.toBase58(),
2457
+ poolMint: stakePool.account.data.poolMint.toBase58(),
2458
+ managerFeeAccount: stakePool.account.data.managerFeeAccount.toBase58(),
2459
+ tokenProgramId: stakePool.account.data.tokenProgramId.toBase58(),
2460
+ totalLamports: stakePool.account.data.totalLamports.toString(),
2461
+ poolTokenSupply: stakePool.account.data.poolTokenSupply.toString(),
2462
+ lastUpdateEpoch: stakePool.account.data.lastUpdateEpoch.toString(),
2463
+ lockup: stakePool.account.data.lockup, // pub lockup: CliStakePoolLockup
2464
+ epochFee: stakePool.account.data.epochFee,
2465
+ nextEpochFee: stakePool.account.data.nextEpochFee,
2466
+ preferredDepositValidatorVoteAddress: stakePool.account.data.preferredDepositValidatorVoteAddress,
2467
+ preferredWithdrawValidatorVoteAddress: stakePool.account.data.preferredWithdrawValidatorVoteAddress,
2468
+ stakeDepositFee: stakePool.account.data.stakeDepositFee,
2469
+ stakeWithdrawalFee: stakePool.account.data.stakeWithdrawalFee,
2470
+ // CliStakePool the same
2471
+ nextStakeWithdrawalFee: stakePool.account.data.nextStakeWithdrawalFee,
2472
+ stakeReferralFee: stakePool.account.data.stakeReferralFee,
2473
+ solDepositAuthority: (_c = stakePool.account.data.solDepositAuthority) === null || _c === void 0 ? void 0 : _c.toBase58(),
2474
+ solDepositFee: stakePool.account.data.solDepositFee,
2475
+ solReferralFee: stakePool.account.data.solReferralFee,
2476
+ solWithdrawAuthority: (_d = stakePool.account.data.solWithdrawAuthority) === null || _d === void 0 ? void 0 : _d.toBase58(),
2477
+ solWithdrawalFee: stakePool.account.data.solWithdrawalFee,
2478
+ nextSolWithdrawalFee: stakePool.account.data.nextSolWithdrawalFee,
2479
+ lastEpochPoolTokenSupply: stakePool.account.data.lastEpochPoolTokenSupply.toString(),
2480
+ lastEpochTotalLamports: stakePool.account.data.lastEpochTotalLamports.toString(),
2481
+ details: {
2482
+ reserveStakeLamports: reserveStake === null || reserveStake === void 0 ? void 0 : reserveStake.lamports,
2483
+ reserveAccountStakeAddress: reserveAccountStakeAddress.toBase58(),
2484
+ minimumReserveStakeBalance,
2485
+ stakeAccounts,
2486
+ totalLamports,
2487
+ totalPoolTokens,
2488
+ currentNumberOfValidators,
2489
+ maxNumberOfValidators,
2490
+ updateRequired,
2491
+ }, // CliStakePoolDetails
2492
+ };
2493
+ }
2494
+ /**
2495
+ * Creates instructions required to create pool token metadata.
2496
+ */
2497
+ async function createPoolTokenMetadata(connection, stakePoolAddress, payer, name, symbol, uri) {
2498
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
2499
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2500
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2501
+ const tokenMetadata = findMetadataAddress(stakePool.account.data.poolMint);
2502
+ const manager = stakePool.account.data.manager;
2503
+ const instructions = [];
2504
+ instructions.push(StakePoolInstruction.createTokenMetadata({
2505
+ programId: stakePoolProgramId,
2506
+ stakePool: stakePoolAddress,
2507
+ poolMint: stakePool.account.data.poolMint,
2508
+ payer,
2509
+ manager,
2510
+ tokenMetadata,
2511
+ withdrawAuthority,
2512
+ name,
2513
+ symbol,
2514
+ uri,
2515
+ }));
2516
+ return {
2517
+ instructions,
2518
+ };
2519
+ }
2520
+ /**
2521
+ * Creates instructions required to update pool token metadata.
2522
+ */
2523
+ async function updatePoolTokenMetadata(connection, stakePoolAddress, name, symbol, uri) {
2524
+ const stakePool = await getStakePoolAccount(connection, stakePoolAddress);
2525
+ const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint);
2526
+ const withdrawAuthority = await findWithdrawAuthorityProgramAddress(stakePoolProgramId, stakePoolAddress);
2527
+ const tokenMetadata = findMetadataAddress(stakePool.account.data.poolMint);
2528
+ const instructions = [];
2529
+ instructions.push(StakePoolInstruction.updateTokenMetadata({
2530
+ programId: stakePoolProgramId,
2531
+ stakePool: stakePoolAddress,
2532
+ manager: stakePool.account.data.manager,
2533
+ tokenMetadata,
2534
+ withdrawAuthority,
2535
+ name,
2536
+ symbol,
2537
+ uri,
2538
+ }));
2539
+ return {
2540
+ instructions,
2541
+ };
2542
+ }
2543
+
2544
+ exports.DEVNET_STAKE_POOL_PROGRAM_ID = DEVNET_STAKE_POOL_PROGRAM_ID;
2545
+ exports.STAKE_POOL_INSTRUCTION_LAYOUTS = STAKE_POOL_INSTRUCTION_LAYOUTS;
2546
+ exports.STAKE_POOL_PROGRAM_ID = STAKE_POOL_PROGRAM_ID;
2547
+ exports.StakePoolInstruction = StakePoolInstruction;
2548
+ exports.StakePoolLayout = StakePoolLayout;
2549
+ exports.ValidatorListLayout = ValidatorListLayout;
2550
+ exports.ValidatorStakeInfoLayout = ValidatorStakeInfoLayout;
2551
+ exports.addValidatorToPool = addValidatorToPool;
2552
+ exports.createPoolTokenMetadata = createPoolTokenMetadata;
2553
+ exports.decreaseValidatorStake = decreaseValidatorStake;
2554
+ exports.depositSol = depositSol;
2555
+ exports.depositStake = depositStake;
2556
+ exports.depositWsolWithSession = depositWsolWithSession;
2557
+ exports.getStakeAccount = getStakeAccount;
2558
+ exports.getStakePoolAccount = getStakePoolAccount;
2559
+ exports.getStakePoolAccounts = getStakePoolAccounts;
2560
+ exports.getStakePoolProgramId = getStakePoolProgramId;
2561
+ exports.increaseValidatorStake = increaseValidatorStake;
2562
+ exports.removeValidatorFromPool = removeValidatorFromPool;
2563
+ exports.stakePoolInfo = stakePoolInfo;
2564
+ exports.tokenMetadataLayout = tokenMetadataLayout;
2565
+ exports.updatePoolTokenMetadata = updatePoolTokenMetadata;
2566
+ exports.updateStakePool = updateStakePool;
2567
+ exports.withdrawSol = withdrawSol;
2568
+ exports.withdrawStake = withdrawStake;
2569
+ exports.withdrawWsolWithSession = withdrawWsolWithSession;
2570
+ //# sourceMappingURL=index.cjs.js.map