@ignitionfi/fogo-stake-pool 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,15 @@
1
1
  import * as BufferLayout from '@solana/buffer-layout';
2
2
  import { PublicKey, TransactionInstruction } from '@solana/web3.js';
3
+ import BN from 'bn.js';
3
4
  import { InstructionType } from './utils';
5
+ /**
6
+ * Type for amounts that can be converted to BN.
7
+ * Accepts number, bigint, BN, or string representations.
8
+ *
9
+ * IMPORTANT: For values > 9,007,199,254,740,991 (Number.MAX_SAFE_INTEGER),
10
+ * you MUST use bigint, BN, or string to avoid precision loss.
11
+ */
12
+ export type AmountInput = number | bigint | BN | string;
4
13
  /**
5
14
  * An enumeration of valid StakePoolInstructionType's
6
15
  */
@@ -60,8 +69,8 @@ export type DecreaseValidatorStakeParams = {
60
69
  validatorList: PublicKey;
61
70
  validatorStake: PublicKey;
62
71
  transientStake: PublicKey;
63
- lamports: number;
64
- transientStakeSeed: number;
72
+ lamports: AmountInput;
73
+ transientStakeSeed: AmountInput;
65
74
  };
66
75
  export interface DecreaseValidatorStakeWithReserveParams extends DecreaseValidatorStakeParams {
67
76
  reserveStake: PublicKey;
@@ -69,7 +78,7 @@ export interface DecreaseValidatorStakeWithReserveParams extends DecreaseValidat
69
78
  export interface DecreaseAdditionalValidatorStakeParams extends DecreaseValidatorStakeParams {
70
79
  reserveStake: PublicKey;
71
80
  ephemeralStake: PublicKey;
72
- ephemeralStakeSeed: number;
81
+ ephemeralStakeSeed: AmountInput;
73
82
  }
74
83
  /**
75
84
  * (Staker only) Increase stake on a validator from the reserve account.
@@ -84,12 +93,12 @@ export type IncreaseValidatorStakeParams = {
84
93
  transientStake: PublicKey;
85
94
  validatorStake: PublicKey;
86
95
  validatorVote: PublicKey;
87
- lamports: number;
88
- transientStakeSeed: number;
96
+ lamports: AmountInput;
97
+ transientStakeSeed: AmountInput;
89
98
  };
90
99
  export interface IncreaseAdditionalValidatorStakeParams extends IncreaseValidatorStakeParams {
91
100
  ephemeralStake: PublicKey;
92
- ephemeralStakeSeed: number;
101
+ ephemeralStakeSeed: AmountInput;
93
102
  }
94
103
  /**
95
104
  * Deposits a stake account into the pool in exchange for pool tokens
@@ -123,7 +132,7 @@ export type WithdrawStakeParams = {
123
132
  sourcePoolAccount: PublicKey;
124
133
  managerFeeAccount: PublicKey;
125
134
  poolMint: PublicKey;
126
- poolTokens: number;
135
+ poolTokens: AmountInput;
127
136
  };
128
137
  /**
129
138
  * Withdraw sol instruction params
@@ -139,7 +148,7 @@ export type WithdrawSolParams = {
139
148
  solWithdrawAuthority?: PublicKey | undefined;
140
149
  managerFeeAccount: PublicKey;
141
150
  poolMint: PublicKey;
142
- poolTokens: number;
151
+ poolTokens: AmountInput;
143
152
  };
144
153
  /**
145
154
  * Withdraw WSOL with session instruction params
@@ -158,8 +167,8 @@ export type WithdrawWsolWithSessionParams = {
158
167
  wsolMint: PublicKey;
159
168
  programSigner: PublicKey;
160
169
  userWallet: PublicKey;
161
- poolTokensIn: number;
162
- minimumLamportsOut: number;
170
+ poolTokensIn: AmountInput;
171
+ minimumLamportsOut: AmountInput;
163
172
  solWithdrawAuthority?: PublicKey;
164
173
  };
165
174
  export type WithdrawStakeWithSessionParams = {
@@ -178,12 +187,12 @@ export type WithdrawStakeWithSessionParams = {
178
187
  tokenProgramId: PublicKey;
179
188
  /** The program signer PDA derived from PROGRAM_SIGNER_SEED */
180
189
  programSigner: PublicKey;
181
- /** The payer for stake account rent (typically the paymaster) */
182
- payer: PublicKey;
183
- poolTokensIn: number;
184
- minimumLamportsOut: number;
190
+ /** Reserve stake account for rent funding */
191
+ reserveStake: PublicKey;
192
+ poolTokensIn: AmountInput;
193
+ minimumLamportsOut: AmountInput;
185
194
  /** Seed used to derive the user stake PDA */
186
- userStakeSeed: number;
195
+ userStakeSeed: AmountInput;
187
196
  };
188
197
  export type WithdrawFromStakeAccountWithSessionParams = {
189
198
  programId: PublicKey;
@@ -194,9 +203,9 @@ export type WithdrawFromStakeAccountWithSessionParams = {
194
203
  /** The session signer (user or session) */
195
204
  sessionSigner: PublicKey;
196
205
  /** Seed used to derive the user stake PDA */
197
- userStakeSeed: number;
198
- /** Lamports to withdraw (use Number.MAX_SAFE_INTEGER for full withdrawal) */
199
- lamports: number;
206
+ userStakeSeed: AmountInput;
207
+ /** Lamports to withdraw (use BigInt(Number.MAX_SAFE_INTEGER) for full withdrawal) */
208
+ lamports: AmountInput;
200
209
  };
201
210
  /**
202
211
  * Deposit SOL directly into the pool's reserve account. The output is a "pool" token
@@ -213,7 +222,7 @@ export type DepositSolParams = {
213
222
  managerFeeAccount: PublicKey;
214
223
  referralPoolAccount: PublicKey;
215
224
  poolMint: PublicKey;
216
- lamports: number;
225
+ lamports: AmountInput;
217
226
  };
218
227
  export type CreateTokenMetadataParams = {
219
228
  programId?: PublicKey | undefined;
@@ -325,8 +334,8 @@ export declare class StakePoolInstruction {
325
334
  tokenProgramId: PublicKey;
326
335
  programId: PublicKey;
327
336
  userWallet: PublicKey;
328
- lamportsIn: number;
329
- minimumPoolTokensOut: number;
337
+ lamportsIn: AmountInput;
338
+ minimumPoolTokensOut: AmountInput;
330
339
  payer?: PublicKey;
331
340
  }): TransactionInstruction;
332
341
  /**
@@ -344,7 +353,7 @@ export declare class StakePoolInstruction {
344
353
  static withdrawWsolWithSession(params: WithdrawWsolWithSessionParams): TransactionInstruction;
345
354
  /**
346
355
  * Creates a transaction instruction to withdraw stake from a stake pool using a Fogo session.
347
- * The stake account is created as a PDA and rent is paid by the payer (typically paymaster).
356
+ * The stake account is created as a PDA and rent is funded from the reserve.
348
357
  */
349
358
  static withdrawStakeWithSession(params: WithdrawStakeWithSessionParams): TransactionInstruction;
350
359
  /**
@@ -12,12 +12,29 @@ export declare function getValidatorListAccount(connection: Connection, pubkey:
12
12
  };
13
13
  }>;
14
14
  export interface ValidatorAccount {
15
- type: 'preferred' | 'active' | 'transient' | 'reserve';
15
+ type: 'preferred' | 'active' | 'transient';
16
16
  voteAddress?: PublicKey | undefined;
17
17
  stakeAddress: PublicKey;
18
18
  lamports: BN;
19
19
  }
20
- export declare function prepareWithdrawAccounts(connection: Connection, stakePool: StakePool, stakePoolAddress: PublicKey, amount: BN, compareFn?: (a: ValidatorAccount, b: ValidatorAccount) => number, skipFee?: boolean): Promise<WithdrawAccount[]>;
20
+ export interface PrepareWithdrawResult {
21
+ withdrawAccounts: WithdrawAccount[];
22
+ /** Pool tokens that will be withdrawn via delayed unstake */
23
+ delayedAmount: BN;
24
+ /** Pool tokens remaining that need instant unstake */
25
+ remainingAmount: BN;
26
+ }
27
+ /** Pre-fetched data to avoid duplicate RPC calls */
28
+ export interface PrepareWithdrawPrefetchedData {
29
+ /** Raw validator list account data from getAccountInfo */
30
+ validatorListData: Buffer | null;
31
+ /** Rent exemption for stake accounts in lamports */
32
+ minBalanceForRentExemption: number;
33
+ /** Minimum stake delegation in lamports */
34
+ stakeMinimumDelegation: number;
35
+ }
36
+ export declare function prepareWithdrawAccounts(connection: Connection, stakePool: StakePool, stakePoolAddress: PublicKey, amount: BN, compareFn?: (a: ValidatorAccount, b: ValidatorAccount) => number, skipFee?: boolean, allowPartial?: boolean, prefetchedData?: PrepareWithdrawPrefetchedData): Promise<WithdrawAccount[]>;
37
+ export declare function prepareWithdrawAccounts(connection: Connection, stakePool: StakePool, stakePoolAddress: PublicKey, amount: BN, compareFn: ((a: ValidatorAccount, b: ValidatorAccount) => number) | undefined, skipFee: boolean | undefined, allowPartial: true, prefetchedData?: PrepareWithdrawPrefetchedData): Promise<PrepareWithdrawResult>;
21
38
  /**
22
39
  * Calculate the pool tokens that should be minted for a deposit of `stakeLamports`
23
40
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ignitionfi/fogo-stake-pool",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Fogo Stake Pool SDK",
5
5
  "contributors": [
6
6
  "Anza Maintainers <maintainers@anza.xyz>",
package/src/codecs.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import * as BufferLayout from '@solana/buffer-layout'
1
2
  import { PublicKey } from '@solana/web3.js'
2
3
  import BN from 'bn.js'
3
4
  import { blob, Layout as LayoutCls, offset, seq, struct, u8, u32 } from 'buffer-layout'
@@ -15,18 +16,22 @@ export interface Layout<T> {
15
16
  replicate: (name: string) => this
16
17
  }
17
18
 
18
- class BNLayout extends LayoutCls<BN> {
19
- blob: Layout<Buffer>
19
+ /**
20
+ * BN-based layout for data decoding using buffer-layout.
21
+ * Used for decoding on-chain account data (StakePool, ValidatorList, etc.)
22
+ */
23
+ class BNDataLayout extends LayoutCls<BN> {
24
+ blobLayout: Layout<Buffer>
20
25
  signed: boolean
21
26
 
22
27
  constructor(span: number, signed: boolean, property?: string) {
23
28
  super(span, property)
24
- this.blob = blob(span)
29
+ this.blobLayout = blob(span)
25
30
  this.signed = signed
26
31
  }
27
32
 
28
33
  decode(b: Buffer, offset = 0) {
29
- const num = new BN(this.blob.decode(b, offset), 10, 'le')
34
+ const num = new BN(this.blobLayout.decode(b, offset), 10, 'le')
30
35
  if (this.signed) {
31
36
  return num.fromTwos(this.span * 8).clone()
32
37
  }
@@ -37,12 +42,60 @@ class BNLayout extends LayoutCls<BN> {
37
42
  if (this.signed) {
38
43
  src = src.toTwos(this.span * 8)
39
44
  }
40
- return this.blob.encode(src.toArrayLike(Buffer, 'le', this.span), b, offset)
45
+ return this.blobLayout.encode(src.toArrayLike(Buffer, 'le', this.span), b, offset)
41
46
  }
42
47
  }
43
48
 
49
+ /**
50
+ * Creates a u64 layout for data decoding (account layouts).
51
+ * Used in StakePoolLayout, ValidatorListLayout, etc.
52
+ */
44
53
  export function u64(property?: string): Layout<BN> {
45
- return new BNLayout(8, false, property)
54
+ return new BNDataLayout(8, false, property)
55
+ }
56
+
57
+ /**
58
+ * BN-based layout for 64-bit unsigned integers using @solana/buffer-layout.
59
+ * Used for encoding instruction data with support for values > MAX_SAFE_INTEGER.
60
+ */
61
+ class BNInstructionLayout extends BufferLayout.Layout<BN> {
62
+ blobLayout: BufferLayout.Blob
63
+ signed: boolean
64
+
65
+ constructor(span: number, signed: boolean, property?: string) {
66
+ super(span, property)
67
+ this.blobLayout = BufferLayout.blob(span)
68
+ this.signed = signed
69
+ }
70
+
71
+ decode(b: Uint8Array, offset = 0): BN {
72
+ const num = new BN(this.blobLayout.decode(b, offset), 10, 'le')
73
+ if (this.signed) {
74
+ return num.fromTwos(this.span * 8).clone()
75
+ }
76
+ return num
77
+ }
78
+
79
+ encode(src: BN, b: Uint8Array, offset = 0): number {
80
+ if (this.signed) {
81
+ src = src.toTwos(this.span * 8)
82
+ }
83
+ return this.blobLayout.encode(src.toArrayLike(Buffer, 'le', this.span), b, offset)
84
+ }
85
+
86
+ getSpan(_b?: Uint8Array, _offset?: number): number {
87
+ return this.span
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Creates a u64 layout for instruction encoding.
93
+ * Properly handles BN values larger than Number.MAX_SAFE_INTEGER.
94
+ * Compatible with @solana/buffer-layout.struct().
95
+ */
96
+ // eslint-disable-next-line ts/no-explicit-any
97
+ export function u64Instruction(property?: string): any {
98
+ return new BNInstructionLayout(8, false, property)
46
99
  }
47
100
 
48
101
  class WrappedLayout<T, U> extends LayoutCls<U> {
package/src/constants.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Buffer } from 'node:buffer'
2
- import { LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js'
2
+ import { PublicKey } from '@solana/web3.js'
3
3
 
4
4
  // Public key that identifies the metadata program.
5
5
  export const METADATA_PROGRAM_ID = new PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s')
package/src/index.ts CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  MINIMUM_ACTIVE_STAKE,
25
25
  STAKE_POOL_PROGRAM_ID,
26
26
  } from './constants'
27
- import { StakePoolInstruction } from './instructions'
27
+ import { AmountInput, StakePoolInstruction } from './instructions'
28
28
  import {
29
29
  StakeAccount,
30
30
  StakePool,
@@ -47,6 +47,7 @@ import {
47
47
  lamportsToSol,
48
48
  newStakeAccount,
49
49
  prepareWithdrawAccounts,
50
+ PrepareWithdrawPrefetchedData,
50
51
  solToLamports,
51
52
  ValidatorAccount,
52
53
  } from './utils'
@@ -303,8 +304,8 @@ export async function depositWsolWithSession(
303
304
  stakePoolAddress: PublicKey,
304
305
  signerOrSession: PublicKey,
305
306
  userPubkey: PublicKey,
306
- lamports: number,
307
- minimumPoolTokensOut: number = 0,
307
+ lamports: AmountInput,
308
+ minimumPoolTokensOut: AmountInput = 0,
308
309
  destinationTokenAccount?: PublicKey,
309
310
  referrerTokenAccount?: PublicKey,
310
311
  depositAuthority?: PublicKey,
@@ -323,13 +324,22 @@ export async function depositWsolWithSession(
323
324
  'confirmed',
324
325
  )
325
326
  const wsolBalance = tokenAccountInfo
326
- ? parseInt(tokenAccountInfo.value.amount)
327
- : 0
328
-
329
- if (wsolBalance < lamports) {
327
+ ? BigInt(tokenAccountInfo.value.amount)
328
+ : BigInt(0)
329
+
330
+ // Convert lamports to BigInt for comparison
331
+ const lamportsBigInt = typeof lamports === 'bigint'
332
+ ? lamports
333
+ : typeof lamports === 'string'
334
+ ? BigInt(lamports)
335
+ : BN.isBN(lamports)
336
+ ? BigInt(lamports.toString())
337
+ : BigInt(lamports)
338
+
339
+ if (wsolBalance < lamportsBigInt) {
330
340
  throw new Error(
331
341
  `Not enough WSOL to deposit into pool. Maximum deposit amount is ${lamportsToSol(
332
- wsolBalance,
342
+ Number(wsolBalance),
333
343
  )} WSOL.`,
334
344
  )
335
345
  }
@@ -401,13 +411,23 @@ export async function depositSol(
401
411
  connection: Connection,
402
412
  stakePoolAddress: PublicKey,
403
413
  from: PublicKey,
404
- lamports: number,
414
+ lamports: AmountInput,
405
415
  destinationTokenAccount?: PublicKey,
406
416
  referrerTokenAccount?: PublicKey,
407
417
  depositAuthority?: PublicKey,
408
418
  ) {
409
419
  const fromBalance = await connection.getBalance(from, 'confirmed')
410
- if (fromBalance < lamports) {
420
+
421
+ // Convert lamports to BigInt for comparison
422
+ const lamportsBigInt = typeof lamports === 'bigint'
423
+ ? lamports
424
+ : typeof lamports === 'string'
425
+ ? BigInt(lamports)
426
+ : BN.isBN(lamports)
427
+ ? BigInt(lamports.toString())
428
+ : BigInt(lamports)
429
+
430
+ if (BigInt(fromBalance) < lamportsBigInt) {
411
431
  throw new Error(
412
432
  `Not enough SOL to deposit into pool. Maximum deposit amount is ${lamportsToSol(
413
433
  fromBalance,
@@ -432,7 +452,7 @@ export async function depositSol(
432
452
  SystemProgram.transfer({
433
453
  fromPubkey: from,
434
454
  toPubkey: userSolTransfer.publicKey,
435
- lamports,
455
+ lamports: lamportsBigInt,
436
456
  }),
437
457
  )
438
458
 
@@ -1034,41 +1054,57 @@ export async function getUserStakeAccounts(
1034
1054
  * Withdraws stake from a stake pool using a Fogo session.
1035
1055
  *
1036
1056
  * The on-chain program creates stake account PDAs. The rent for these accounts
1037
- * is paid by the payer (typically the paymaster), not deducted from the user's withdrawal.
1057
+ * is funded from the reserve stake.
1038
1058
  *
1039
1059
  * @param connection - Solana connection
1040
1060
  * @param stakePoolAddress - The stake pool to withdraw from
1041
1061
  * @param signerOrSession - The session signer public key
1042
1062
  * @param userPubkey - User's wallet (used for PDA derivation and token ownership)
1043
- * @param payer - Payer for stake account rent (typically paymaster)
1044
1063
  * @param amount - Amount of pool tokens to withdraw
1045
1064
  * @param userStakeSeedStart - Starting seed for user stake PDA derivation (default: 0)
1046
1065
  * @param useReserve - Whether to withdraw from reserve (default: false)
1047
1066
  * @param voteAccountAddress - Optional specific validator to withdraw from
1048
1067
  * @param minimumLamportsOut - Minimum lamports to receive (slippage protection)
1049
1068
  * @param validatorComparator - Optional comparator for validator selection
1069
+ * @param allowPartial - If true, returns partial results instead of throwing when not enough stake available
1050
1070
  */
1051
1071
  export async function withdrawStakeWithSession(
1052
1072
  connection: Connection,
1053
1073
  stakePoolAddress: PublicKey,
1054
1074
  signerOrSession: PublicKey,
1055
1075
  userPubkey: PublicKey,
1056
- payer: PublicKey,
1057
1076
  amount: number,
1058
1077
  userStakeSeedStart: number = 0,
1059
1078
  useReserve = false,
1060
1079
  voteAccountAddress?: PublicKey,
1061
1080
  minimumLamportsOut: number = 0,
1062
1081
  validatorComparator?: (_a: ValidatorAccount, _b: ValidatorAccount) => number,
1082
+ allowPartial = false,
1063
1083
  ) {
1064
- const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress)
1065
1084
  const stakePoolProgramId = getStakePoolProgramId(connection.rpcEndpoint)
1085
+
1086
+ // First fetch: get stake pool to know other account addresses
1087
+ const stakePoolAccount = await getStakePoolAccount(connection, stakePoolAddress)
1066
1088
  const stakePool = stakePoolAccount.account.data
1067
1089
  const poolTokens = solToLamports(amount)
1068
1090
  const poolAmount = new BN(poolTokens)
1069
1091
 
1070
1092
  const poolTokenAccount = getAssociatedTokenAddressSync(stakePool.poolMint, userPubkey)
1071
- const tokenAccount = await getAccount(connection, poolTokenAccount)
1093
+
1094
+ // Second fetch: get ALL remaining data in parallel
1095
+ const [tokenAccount, stakeAccountRentExemption, validatorListAcc, stakeMinimumDelegationResponse] = await Promise.all([
1096
+ getAccount(connection, poolTokenAccount),
1097
+ connection.getMinimumBalanceForRentExemption(StakeProgram.space),
1098
+ connection.getAccountInfo(stakePool.validatorList),
1099
+ connection.getStakeMinimumDelegation(),
1100
+ ])
1101
+
1102
+ // Pre-fetch data to avoid duplicate RPC calls in prepareWithdrawAccounts
1103
+ const prefetchedData: PrepareWithdrawPrefetchedData = {
1104
+ validatorListData: validatorListAcc?.data ?? null,
1105
+ minBalanceForRentExemption: stakeAccountRentExemption,
1106
+ stakeMinimumDelegation: Number(stakeMinimumDelegationResponse.value),
1107
+ }
1072
1108
 
1073
1109
  if (tokenAccount.amount < poolTokens) {
1074
1110
  throw new Error(
@@ -1087,10 +1123,9 @@ export async function withdrawStakeWithSession(
1087
1123
  stakePoolAddress,
1088
1124
  )
1089
1125
 
1090
- const stakeAccountRentExemption = await connection.getMinimumBalanceForRentExemption(StakeProgram.space)
1091
-
1092
1126
  // Determine which stake accounts to withdraw from
1093
1127
  const withdrawAccounts: WithdrawAccount[] = []
1128
+ let partialRemainingAmount: BN | undefined
1094
1129
 
1095
1130
  if (useReserve) {
1096
1131
  withdrawAccounts.push({
@@ -1133,16 +1168,33 @@ export async function withdrawStakeWithSession(
1133
1168
  })
1134
1169
  } else {
1135
1170
  // Get the list of accounts to withdraw from automatically
1136
- withdrawAccounts.push(
1137
- ...(await prepareWithdrawAccounts(
1171
+ if (allowPartial) {
1172
+ const result = await prepareWithdrawAccounts(
1138
1173
  connection,
1139
1174
  stakePool,
1140
1175
  stakePoolAddress,
1141
1176
  poolAmount,
1142
1177
  validatorComparator,
1143
1178
  poolTokenAccount.equals(stakePool.managerFeeAccount),
1144
- )),
1145
- )
1179
+ true,
1180
+ prefetchedData,
1181
+ )
1182
+ withdrawAccounts.push(...result.withdrawAccounts)
1183
+ partialRemainingAmount = result.remainingAmount
1184
+ } else {
1185
+ withdrawAccounts.push(
1186
+ ...(await prepareWithdrawAccounts(
1187
+ connection,
1188
+ stakePool,
1189
+ stakePoolAddress,
1190
+ poolAmount,
1191
+ validatorComparator,
1192
+ poolTokenAccount.equals(stakePool.managerFeeAccount),
1193
+ undefined,
1194
+ prefetchedData,
1195
+ )),
1196
+ )
1197
+ }
1146
1198
  }
1147
1199
 
1148
1200
  const instructions: TransactionInstruction[] = []
@@ -1169,7 +1221,7 @@ export async function withdrawStakeWithSession(
1169
1221
  stakeAccountPubkeys.push(stakeReceiverPubkey)
1170
1222
  userStakeSeeds.push(userStakeSeed)
1171
1223
 
1172
- // The on-chain program creates the stake account PDA and rent is paid by payer.
1224
+ // The on-chain program creates the stake account PDA and rent is funded from reserve.
1173
1225
  instructions.push(
1174
1226
  StakePoolInstruction.withdrawStakeWithSession({
1175
1227
  programId: stakePoolProgramId,
@@ -1184,7 +1236,7 @@ export async function withdrawStakeWithSession(
1184
1236
  poolMint: stakePool.poolMint,
1185
1237
  tokenProgramId: stakePool.tokenProgramId,
1186
1238
  programSigner,
1187
- payer,
1239
+ reserveStake: stakePool.reserveStake,
1188
1240
  poolTokensIn: withdrawAccount.poolAmount.toNumber(),
1189
1241
  minimumLamportsOut,
1190
1242
  userStakeSeed,
@@ -1197,6 +1249,7 @@ export async function withdrawStakeWithSession(
1197
1249
  instructions,
1198
1250
  stakeAccountPubkeys,
1199
1251
  userStakeSeeds,
1252
+ remainingPoolTokens: partialRemainingAmount ? lamportsToSol(partialRemainingAmount) : 0,
1200
1253
  }
1201
1254
  }
1202
1255
 
@@ -1329,7 +1382,7 @@ export async function increaseValidatorStake(
1329
1382
  connection: Connection,
1330
1383
  stakePoolAddress: PublicKey,
1331
1384
  validatorVote: PublicKey,
1332
- lamports: number,
1385
+ lamports: AmountInput,
1333
1386
  ephemeralStakeSeed?: number,
1334
1387
  ) {
1335
1388
  const stakePool = await getStakePoolAccount(connection, stakePoolAddress)
@@ -1427,7 +1480,7 @@ export async function decreaseValidatorStake(
1427
1480
  connection: Connection,
1428
1481
  stakePoolAddress: PublicKey,
1429
1482
  validatorVote: PublicKey,
1430
- lamports: number,
1483
+ lamports: AmountInput,
1431
1484
  ephemeralStakeSeed?: number,
1432
1485
  ) {
1433
1486
  const stakePool = await getStakePoolAccount(connection, stakePoolAddress)