@kamino-finance/klend-sdk 7.1.1 → 7.1.3

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.
Files changed (175) hide show
  1. package/dist/@codegen/unstaking_pool/accounts/PoolState.d.ts +53 -0
  2. package/dist/@codegen/unstaking_pool/accounts/PoolState.d.ts.map +1 -0
  3. package/dist/@codegen/unstaking_pool/accounts/PoolState.js +167 -0
  4. package/dist/@codegen/unstaking_pool/accounts/PoolState.js.map +1 -0
  5. package/dist/@codegen/unstaking_pool/accounts/UnstakeTicket.d.ts +41 -0
  6. package/dist/@codegen/unstaking_pool/accounts/UnstakeTicket.d.ts.map +1 -0
  7. package/dist/@codegen/unstaking_pool/accounts/UnstakeTicket.js +143 -0
  8. package/dist/@codegen/unstaking_pool/accounts/UnstakeTicket.js.map +1 -0
  9. package/dist/@codegen/unstaking_pool/accounts/index.d.ts +5 -0
  10. package/dist/@codegen/unstaking_pool/accounts/index.d.ts.map +1 -0
  11. package/dist/@codegen/unstaking_pool/accounts/index.js +8 -0
  12. package/dist/@codegen/unstaking_pool/accounts/index.js.map +1 -0
  13. package/dist/@codegen/unstaking_pool/errors/anchor.d.ts +435 -0
  14. package/dist/@codegen/unstaking_pool/errors/anchor.d.ts.map +1 -0
  15. package/dist/@codegen/unstaking_pool/errors/anchor.js +767 -0
  16. package/dist/@codegen/unstaking_pool/errors/anchor.js.map +1 -0
  17. package/dist/@codegen/unstaking_pool/errors/custom.d.ts +259 -0
  18. package/dist/@codegen/unstaking_pool/errors/custom.d.ts.map +1 -0
  19. package/dist/@codegen/unstaking_pool/errors/custom.js +458 -0
  20. package/dist/@codegen/unstaking_pool/errors/custom.js.map +1 -0
  21. package/dist/@codegen/unstaking_pool/errors/index.d.ts +6 -0
  22. package/dist/@codegen/unstaking_pool/errors/index.d.ts.map +1 -0
  23. package/dist/@codegen/unstaking_pool/errors/index.js +86 -0
  24. package/dist/@codegen/unstaking_pool/errors/index.js.map +1 -0
  25. package/dist/@codegen/unstaking_pool/instructions/burn.d.ts +21 -0
  26. package/dist/@codegen/unstaking_pool/instructions/burn.d.ts.map +1 -0
  27. package/dist/@codegen/unstaking_pool/instructions/burn.js +67 -0
  28. package/dist/@codegen/unstaking_pool/instructions/burn.js.map +1 -0
  29. package/dist/@codegen/unstaking_pool/instructions/changeTicketAuthority.d.ts +8 -0
  30. package/dist/@codegen/unstaking_pool/instructions/changeTicketAuthority.d.ts.map +1 -0
  31. package/dist/@codegen/unstaking_pool/instructions/changeTicketAuthority.js +16 -0
  32. package/dist/@codegen/unstaking_pool/instructions/changeTicketAuthority.js.map +1 -0
  33. package/dist/@codegen/unstaking_pool/instructions/collect.d.ts +16 -0
  34. package/dist/@codegen/unstaking_pool/instructions/collect.d.ts.map +1 -0
  35. package/dist/@codegen/unstaking_pool/instructions/collect.js +24 -0
  36. package/dist/@codegen/unstaking_pool/instructions/collect.js.map +1 -0
  37. package/dist/@codegen/unstaking_pool/instructions/index.d.ts +17 -0
  38. package/dist/@codegen/unstaking_pool/instructions/index.d.ts.map +1 -0
  39. package/dist/@codegen/unstaking_pool/instructions/index.js +20 -0
  40. package/dist/@codegen/unstaking_pool/instructions/index.js.map +1 -0
  41. package/dist/@codegen/unstaking_pool/instructions/initializePool.d.ts +14 -0
  42. package/dist/@codegen/unstaking_pool/instructions/initializePool.d.ts.map +1 -0
  43. package/dist/@codegen/unstaking_pool/instructions/initializePool.js +22 -0
  44. package/dist/@codegen/unstaking_pool/instructions/initializePool.js.map +1 -0
  45. package/dist/@codegen/unstaking_pool/instructions/mint.d.ts +24 -0
  46. package/dist/@codegen/unstaking_pool/instructions/mint.d.ts.map +1 -0
  47. package/dist/@codegen/unstaking_pool/instructions/mint.js +74 -0
  48. package/dist/@codegen/unstaking_pool/instructions/mint.js.map +1 -0
  49. package/dist/@codegen/unstaking_pool/instructions/splitTicket.d.ts +15 -0
  50. package/dist/@codegen/unstaking_pool/instructions/splitTicket.d.ts.map +1 -0
  51. package/dist/@codegen/unstaking_pool/instructions/splitTicket.js +62 -0
  52. package/dist/@codegen/unstaking_pool/instructions/splitTicket.js.map +1 -0
  53. package/dist/@codegen/unstaking_pool/instructions/updateAdmin.d.ts +7 -0
  54. package/dist/@codegen/unstaking_pool/instructions/updateAdmin.d.ts.map +1 -0
  55. package/dist/@codegen/unstaking_pool/instructions/updateAdmin.js +19 -0
  56. package/dist/@codegen/unstaking_pool/instructions/updateAdmin.js.map +1 -0
  57. package/dist/@codegen/unstaking_pool/instructions/updatePoolConfig.d.ts +13 -0
  58. package/dist/@codegen/unstaking_pool/instructions/updatePoolConfig.d.ts.map +1 -0
  59. package/dist/@codegen/unstaking_pool/instructions/updatePoolConfig.js +60 -0
  60. package/dist/@codegen/unstaking_pool/instructions/updatePoolConfig.js.map +1 -0
  61. package/dist/@codegen/unstaking_pool/programId.d.ts +4 -0
  62. package/dist/@codegen/unstaking_pool/programId.d.ts.map +1 -0
  63. package/dist/@codegen/unstaking_pool/programId.js +9 -0
  64. package/dist/@codegen/unstaking_pool/programId.js.map +1 -0
  65. package/dist/@codegen/unstaking_pool/types/PoolConfigField.d.ts +45 -0
  66. package/dist/@codegen/unstaking_pool/types/PoolConfigField.d.ts.map +1 -0
  67. package/dist/@codegen/unstaking_pool/types/PoolConfigField.js +132 -0
  68. package/dist/@codegen/unstaking_pool/types/PoolConfigField.js.map +1 -0
  69. package/dist/@codegen/unstaking_pool/types/index.d.ts +5 -0
  70. package/dist/@codegen/unstaking_pool/types/index.d.ts.map +1 -0
  71. package/dist/@codegen/unstaking_pool/types/index.js +39 -0
  72. package/dist/@codegen/unstaking_pool/types/index.js.map +1 -0
  73. package/dist/@codegen/unstaking_pool/utils/borshAddress.d.ts +4 -0
  74. package/dist/@codegen/unstaking_pool/utils/borshAddress.d.ts.map +1 -0
  75. package/dist/@codegen/unstaking_pool/utils/borshAddress.js +30 -0
  76. package/dist/@codegen/unstaking_pool/utils/borshAddress.js.map +1 -0
  77. package/dist/@codegen/unstaking_pool/utils/index.d.ts +2 -0
  78. package/dist/@codegen/unstaking_pool/utils/index.d.ts.map +1 -0
  79. package/dist/@codegen/unstaking_pool/utils/index.js +18 -0
  80. package/dist/@codegen/unstaking_pool/utils/index.js.map +1 -0
  81. package/dist/classes/action.d.ts.map +1 -1
  82. package/dist/classes/action.js +5 -5
  83. package/dist/classes/action.js.map +1 -1
  84. package/dist/classes/index.d.ts +5 -0
  85. package/dist/classes/index.d.ts.map +1 -1
  86. package/dist/classes/index.js +5 -0
  87. package/dist/classes/index.js.map +1 -1
  88. package/dist/classes/manager.d.ts.map +1 -1
  89. package/dist/classes/manager.js +2 -3
  90. package/dist/classes/manager.js.map +1 -1
  91. package/dist/classes/stakePool.d.ts +8 -0
  92. package/dist/classes/stakePool.d.ts.map +1 -0
  93. package/dist/classes/stakePool.js +18 -0
  94. package/dist/classes/stakePool.js.map +1 -0
  95. package/dist/classes/standardStakePool.d.ts +76 -0
  96. package/dist/classes/standardStakePool.d.ts.map +1 -0
  97. package/dist/classes/standardStakePool.js +400 -0
  98. package/dist/classes/standardStakePool.js.map +1 -0
  99. package/dist/classes/unstakingPool.d.ts +115 -0
  100. package/dist/classes/unstakingPool.d.ts.map +1 -0
  101. package/dist/classes/unstakingPool.js +372 -0
  102. package/dist/classes/unstakingPool.js.map +1 -0
  103. package/dist/classes/unstakingPoolTypes.d.ts +10 -0
  104. package/dist/classes/unstakingPoolTypes.d.ts.map +1 -0
  105. package/dist/classes/unstakingPoolTypes.js +3 -0
  106. package/dist/classes/unstakingPoolTypes.js.map +1 -0
  107. package/dist/classes/vault.d.ts +0 -9
  108. package/dist/classes/vault.d.ts.map +1 -1
  109. package/dist/classes/vault.js +6 -41
  110. package/dist/classes/vault.js.map +1 -1
  111. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  112. package/dist/lending_operations/repay_with_collateral_operations.js +0 -2
  113. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  114. package/dist/lending_operations/swap_collateral_operations.js +0 -1
  115. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  116. package/dist/leverage/calcs.d.ts +2 -27
  117. package/dist/leverage/calcs.d.ts.map +1 -1
  118. package/dist/leverage/calcs.js +6 -136
  119. package/dist/leverage/calcs.js.map +1 -1
  120. package/dist/leverage/operations.d.ts +8 -9
  121. package/dist/leverage/operations.d.ts.map +1 -1
  122. package/dist/leverage/operations.js +72 -228
  123. package/dist/leverage/operations.js.map +1 -1
  124. package/dist/leverage/types.d.ts +0 -19
  125. package/dist/leverage/types.d.ts.map +1 -1
  126. package/dist/leverage/utils.d.ts +2 -19
  127. package/dist/leverage/utils.d.ts.map +1 -1
  128. package/dist/leverage/utils.js +0 -164
  129. package/dist/leverage/utils.js.map +1 -1
  130. package/dist/lib.d.ts +1 -0
  131. package/dist/lib.d.ts.map +1 -1
  132. package/dist/lib.js +3 -1
  133. package/dist/lib.js.map +1 -1
  134. package/dist/utils/lookupTable.d.ts +9 -0
  135. package/dist/utils/lookupTable.d.ts.map +1 -1
  136. package/dist/utils/lookupTable.js +37 -0
  137. package/dist/utils/lookupTable.js.map +1 -1
  138. package/package.json +4 -2
  139. package/src/@codegen/unstaking_pool/accounts/PoolState.ts +188 -0
  140. package/src/@codegen/unstaking_pool/accounts/UnstakeTicket.ts +156 -0
  141. package/src/@codegen/unstaking_pool/accounts/index.ts +4 -0
  142. package/src/@codegen/unstaking_pool/errors/anchor.ts +773 -0
  143. package/src/@codegen/unstaking_pool/errors/custom.ts +477 -0
  144. package/src/@codegen/unstaking_pool/errors/index.ts +68 -0
  145. package/src/@codegen/unstaking_pool/instructions/burn.ts +70 -0
  146. package/src/@codegen/unstaking_pool/instructions/changeTicketAuthority.ts +37 -0
  147. package/src/@codegen/unstaking_pool/instructions/collect.ts +53 -0
  148. package/src/@codegen/unstaking_pool/instructions/index.ts +19 -0
  149. package/src/@codegen/unstaking_pool/instructions/initializePool.ts +49 -0
  150. package/src/@codegen/unstaking_pool/instructions/mint.ts +80 -0
  151. package/src/@codegen/unstaking_pool/instructions/splitTicket.ts +59 -0
  152. package/src/@codegen/unstaking_pool/instructions/updateAdmin.ts +39 -0
  153. package/src/@codegen/unstaking_pool/instructions/updatePoolConfig.ts +58 -0
  154. package/src/@codegen/unstaking_pool/programId.ts +9 -0
  155. package/src/@codegen/unstaking_pool/types/PoolConfigField.ts +121 -0
  156. package/src/@codegen/unstaking_pool/types/index.ts +12 -0
  157. package/src/@codegen/unstaking_pool/utils/borshAddress.ts +43 -0
  158. package/src/@codegen/unstaking_pool/utils/index.ts +1 -0
  159. package/src/classes/action.ts +10 -5
  160. package/src/classes/index.ts +5 -0
  161. package/src/classes/manager.ts +3 -4
  162. package/src/classes/stakePool.ts +21 -0
  163. package/src/classes/standardStakePool.ts +487 -0
  164. package/src/classes/unstakingPool.ts +504 -0
  165. package/src/classes/unstakingPoolTypes.ts +12 -0
  166. package/src/classes/vault.ts +43 -56
  167. package/src/idl/unstaking_pool.json +662 -0
  168. package/src/lending_operations/repay_with_collateral_operations.ts +0 -2
  169. package/src/lending_operations/swap_collateral_operations.ts +0 -1
  170. package/src/leverage/calcs.ts +2 -201
  171. package/src/leverage/operations.ts +45 -377
  172. package/src/leverage/types.ts +0 -20
  173. package/src/leverage/utils.ts +3 -320
  174. package/src/lib.ts +1 -0
  175. package/src/utils/lookupTable.ts +48 -0
@@ -0,0 +1,504 @@
1
+ import {
2
+ initializePool,
3
+ InitializePoolAccounts,
4
+ updatePoolConfig,
5
+ UpdatePoolConfigAccounts,
6
+ UpdatePoolConfigArgs,
7
+ collect,
8
+ CollectAccounts,
9
+ burn,
10
+ BurnAccounts,
11
+ BurnArgs,
12
+ mint,
13
+ MintAccounts,
14
+ MintArgs,
15
+ } from '../@codegen/unstaking_pool/instructions';
16
+ import { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';
17
+ import { getAssociatedTokenAddress } from '../lib';
18
+ import { PoolState, UnstakeTicket } from '../@codegen/unstaking_pool/accounts';
19
+ import {
20
+ createLookupTableIx,
21
+ DEFAULT_PUBLIC_KEY,
22
+ extendLookupTableIxs,
23
+ insertIntoLookupTableIxs,
24
+ WRAPPED_SOL_MINT,
25
+ } from '../utils';
26
+ import bs58 from 'bs58';
27
+ import { getProgramAccounts } from '../utils/rpc';
28
+ import { InitPoolIxs, MintIxs } from './unstakingPoolTypes';
29
+ import { PoolConfigField, PoolConfigFieldKind } from '../@codegen/unstaking_pool/types';
30
+ import BN from 'bn.js';
31
+ import { mapStakedSolMintToPool, StakePoolType } from './stakePool';
32
+ import { getStandardPoolMintRemainingAccounts, STAKE_POOL_PROGRAM_ID, StakeAccount } from './standardStakePool';
33
+ import {
34
+ Address,
35
+ address,
36
+ Base58EncodedBytes,
37
+ generateKeyPairSigner,
38
+ GetAccountInfoApi,
39
+ getAddressEncoder,
40
+ GetProgramAccountsApi,
41
+ GetProgramAccountsDatasizeFilter,
42
+ GetProgramAccountsMemcmpFilter,
43
+ getProgramDerivedAddress,
44
+ AccountMeta,
45
+ AccountSignerMeta,
46
+ Instruction,
47
+ KeyPairSigner,
48
+ ProgramDerivedAddress,
49
+ Rpc,
50
+ SolanaRpcApi,
51
+ TransactionSigner,
52
+ } from '@solana/kit';
53
+ import { getCreateAccountInstruction, SYSTEM_PROGRAM_ADDRESS } from '@solana-program/system';
54
+ import { SYSVAR_CLOCK_ADDRESS, SYSVAR_INSTRUCTIONS_ADDRESS, SYSVAR_RENT_ADDRESS } from '@solana/sysvars';
55
+ import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
56
+ import { fromLegacyPublicKey } from '@solana/compat';
57
+ import { PROGRAM_ID as UNSTAKING_POOL_ID } from '../@codegen/unstaking_pool/programId';
58
+ export const UNSTAKING_POOL_STAGING_ID: Address = address('SUPFzSvjWnK9AbQ5bQksKaDKeAZBx56Gtjx1AjJsUdj');
59
+ export const STAKE_PROGRAM_ID: Address = address('Stake11111111111111111111111111111111111111');
60
+ export const CLOCK_PROGRAM_ID: Address = address('SysvarC1ock11111111111111111111111111111111');
61
+ const STAKE_HISTORY_PROGRAM_ID: Address = address('SysvarStakeHistory1111111111111111111111111');
62
+ const STAKE_ACCOUNT_SIZE: number = 200;
63
+ export const STAKE_POOL_SIZE: number = 611;
64
+ const addressEncoder = getAddressEncoder();
65
+
66
+ /**
67
+ * Unstaking sol mint seed
68
+ */
69
+ export const UNSTAKING_SOL_MINT_SEED = Buffer.from('unstaking_sol_mint');
70
+
71
+ /**
72
+ * Unstaking sol pool base authority seed
73
+ */
74
+ export const BASE_POOL_AUTHORITY_SEED = Buffer.from('authority');
75
+
76
+ /**
77
+ * KaminoPoolClient is a class that provides a high-level interface to interact with the Kamino Pool program.
78
+ */
79
+ export class UnstakingPoolClient {
80
+ private readonly _rpc: Rpc<SolanaRpcApi>;
81
+ private readonly _unstakingPoolProgramId: Address;
82
+
83
+ constructor(rpc: Rpc<SolanaRpcApi>, unstakingPoolprogramId?: Address) {
84
+ this._rpc = rpc;
85
+ this._unstakingPoolProgramId = unstakingPoolprogramId ? unstakingPoolprogramId : UNSTAKING_POOL_ID;
86
+ }
87
+
88
+ getConnection() {
89
+ return this._rpc;
90
+ }
91
+
92
+ getProgramID() {
93
+ return this._unstakingPoolProgramId;
94
+ }
95
+
96
+ /**
97
+ * This method will create a pool with a given config. The config can be changed later on, but it is recommended to set it up correctly from the start
98
+ * @param poolConfig - the config object used to create a pool
99
+ * @returns pool - keypair, should be used to sign the transaction which creates the pool account
100
+ * @returns pool: the keypair of the pool, used to sign the initialization transaction; initPoolIxs: a struct with ixs to initialize the pool and its lookup table + populateLUTIxs, a list to populate the lookup table which has to be executed in a separate transaction
101
+ */
102
+ async createPoolIxs(poolConfig: UnstakingPoolConfig): Promise<{ pool: KeyPairSigner; initPoolIxs: InitPoolIxs }> {
103
+ const poolState = await generateKeyPairSigner();
104
+ const size = PoolState.layout.span + 8;
105
+
106
+ const createPoolIx = getCreateAccountInstruction({
107
+ payer: poolConfig.admin,
108
+ newAccount: poolState,
109
+ lamports: await this.getConnection().getMinimumBalanceForRentExemption(BigInt(size)).send(),
110
+ space: size,
111
+ programAddress: this._unstakingPoolProgramId,
112
+ });
113
+
114
+ const unstakingSolMint = (await unstakingPoolMintPda(poolState.address))[0];
115
+ const basePoolAuthority = (await unstakingPoolAuthorityPda(poolState.address))[0];
116
+ const wsolVault = await getAssociatedTokenAddress(WRAPPED_SOL_MINT, basePoolAuthority);
117
+
118
+ const initPoolAccounts: InitializePoolAccounts = {
119
+ admin: poolConfig.admin,
120
+ poolState: poolState.address,
121
+ basePoolAuthority,
122
+ systemProgram: SYSTEM_PROGRAM_ADDRESS,
123
+ rent: SYSVAR_RENT_ADDRESS,
124
+ tokenProgram: TOKEN_PROGRAM_ADDRESS,
125
+ unstakingSolMint,
126
+ wsolMint: WRAPPED_SOL_MINT,
127
+ wsolVault,
128
+ };
129
+ const initPoolIx = initializePool(initPoolAccounts, this._unstakingPoolProgramId);
130
+
131
+ // create and set up the pool lookup table
132
+ const [createLUTIx, lut] = await createLookupTableIx(this.getConnection(), poolConfig.admin);
133
+
134
+ const allAccountsToBeInserted = [
135
+ poolState.address,
136
+ basePoolAuthority,
137
+ wsolVault,
138
+ unstakingSolMint,
139
+ poolConfig.admin.address,
140
+ WRAPPED_SOL_MINT,
141
+ this._unstakingPoolProgramId,
142
+ SYSTEM_PROGRAM_ADDRESS,
143
+ SYSVAR_RENT_ADDRESS,
144
+ TOKEN_PROGRAM_ADDRESS,
145
+ TOKEN_2022_PROGRAM_ADDRESS,
146
+ SYSVAR_INSTRUCTIONS_ADDRESS,
147
+ SYSVAR_CLOCK_ADDRESS,
148
+ STAKE_PROGRAM_ID,
149
+ STAKE_POOL_PROGRAM_ID,
150
+ ];
151
+ const insertIntoLUTIxs = extendLookupTableIxs(poolConfig.admin, lut, allAccountsToBeInserted, poolConfig.admin);
152
+ const updateLUTIx = await this.updatePoolConfigIxs(
153
+ poolState.address,
154
+ poolConfig.admin,
155
+ new PoolConfigField.LookupTable(),
156
+ lut.toString()
157
+ );
158
+ const ixns = [createPoolIx, initPoolIx, createLUTIx, ...insertIntoLUTIxs, updateLUTIx];
159
+
160
+ if (poolConfig.actionAuthority) {
161
+ const updateActionAuthorityIx = await this.updatePoolConfigIxs(
162
+ poolState.address,
163
+ poolConfig.admin,
164
+ new PoolConfigField.ActionAuthority(),
165
+ poolConfig.actionAuthority.toString()
166
+ );
167
+ ixns.push(updateActionAuthorityIx);
168
+ }
169
+
170
+ return { pool: poolState, initPoolIxs: { initPoolIxs: ixns, populateLUTIxs: [] } };
171
+ }
172
+
173
+ /**
174
+ * Update pool configuration such as admin authority (or fees/minimum depositable in the future)
175
+ * @param poolState - the pool to update and set the LUT for if needed or only the pool pubkey if updating LUT is not needed
176
+ * @param admin - admin of the specified pool
177
+ * @param mode - what field to update for pool
178
+ * @param value - new value that is converted .toString()
179
+ * @returns a struct that contains a list of ix to update the pool config
180
+ */
181
+ async updatePoolConfigIxs(
182
+ poolState: UnstakingPool | Address,
183
+ admin: TransactionSigner,
184
+ mode: PoolConfigFieldKind,
185
+ value: string
186
+ ): Promise<Instruction> {
187
+ const updatePoolConfigAccounts: UpdatePoolConfigAccounts = {
188
+ admin,
189
+ poolState: poolState instanceof UnstakingPool ? poolState.address : poolState,
190
+ };
191
+ const args: UpdatePoolConfigArgs = {
192
+ entry: mode,
193
+ data: Buffer.from([0]),
194
+ };
195
+
196
+ if (isNaN(+value)) {
197
+ const data = address(value);
198
+ args.data = Buffer.from(addressEncoder.encode(data));
199
+ } else {
200
+ const buffer = Buffer.alloc(8);
201
+ buffer.writeBigUInt64LE(BigInt(value.toString()));
202
+ args.data = buffer;
203
+ }
204
+
205
+ const updatePoolConfigIx = updatePoolConfig(args, updatePoolConfigAccounts, this._unstakingPoolProgramId);
206
+
207
+ return updatePoolConfigIx;
208
+ }
209
+
210
+ /**
211
+ * Collect a stake account SOL if the needed epoch was reached
212
+ * @param poolState - the pool to collect SOL into
213
+ * @param payer - payer for the operation (ix is permissionless)
214
+ * @param stakeAccount - stake account that was deactivated this epoch and has base pool authority as owner
215
+ * @returns collect instruction
216
+ */
217
+ async collectIx(poolState: UnstakingPool, payer: TransactionSigner, stakeAccount: Address): Promise<Instruction> {
218
+ const pool = await poolState.getState(this.getConnection());
219
+ const accounts: CollectAccounts = {
220
+ poolState: poolState.address,
221
+ payer,
222
+ stakeAccount,
223
+ basePoolAuthority: pool.basePoolAuthority,
224
+ wsolVault: pool.wsolVault,
225
+ wsolMint: WRAPPED_SOL_MINT,
226
+ tokenProgram: TOKEN_PROGRAM_ADDRESS,
227
+ systemProgram: SYSTEM_PROGRAM_ADDRESS,
228
+ clockProgramId: SYSVAR_CLOCK_ADDRESS,
229
+ stakeProgramId: STAKE_PROGRAM_ID,
230
+ stakeHistoryProgramId: STAKE_HISTORY_PROGRAM_ID,
231
+ };
232
+ return collect(accounts, this._unstakingPoolProgramId);
233
+ }
234
+
235
+ /**
236
+ * Burn a number of shares (USOL) in exchange for SOL
237
+ * @param poolState - the pool to burn USOL from
238
+ * @param user - user that burns (ix is not gated by action authority)
239
+ * @param unstakeTicket - ticket where to burn the shares from
240
+ * @param sharesToBurn - number of shares that are equivalent 1:1 with SOL
241
+ * @returns burn instruction
242
+ */
243
+ async burnIx(
244
+ poolState: UnstakingPool,
245
+ user: TransactionSigner,
246
+ unstakeTicket: Address,
247
+ sharesToBurn: BN
248
+ ): Promise<Instruction> {
249
+ const pool = await poolState.getState(this.getConnection());
250
+ const accounts: BurnAccounts = {
251
+ poolState: poolState.address,
252
+ basePoolAuthority: pool.basePoolAuthority,
253
+ wsolVault: pool.wsolVault,
254
+ wsolMint: WRAPPED_SOL_MINT,
255
+ user,
256
+ userWsolToken: await getAssociatedTokenAddress(WRAPPED_SOL_MINT, user.address),
257
+ userUnstakingSolToken: await getAssociatedTokenAddress(pool.unstakingSolMint, user.address),
258
+ unstakingSolMint: pool.unstakingSolMint,
259
+ tokenProgram: TOKEN_PROGRAM_ADDRESS,
260
+ unstakeTicket,
261
+ };
262
+ const args: BurnArgs = {
263
+ sharesToBurn,
264
+ minWsolToReceive: sharesToBurn,
265
+ };
266
+ return burn(args, accounts, this._unstakingPoolProgramId);
267
+ }
268
+
269
+ /**
270
+ * Mints a number of unstaking sol (USOL) in exchange for staked SOL
271
+ * NOTE: this ix is permissioned by action authority
272
+ * @param poolState - the pool to mint USOL from
273
+ * @param user - user that mints
274
+ * @param actionAuthority - user that has authority to mint in that pool (== poolState.actionAuthority)
275
+ * @param unstakeTicket - empty keypair where unstake ticket will be stored
276
+ * @param stakedSolMint - staked sol mint
277
+ * @param stakedSolToDeposit - staked sol to convert to USOL (at the pool ratio)
278
+ * @param minSharesToReceive - parameter to control slippage
279
+ * @returns burn instruction
280
+ */
281
+ async mintIx(
282
+ poolState: UnstakingPool,
283
+ user: TransactionSigner,
284
+ actionAuthority: TransactionSigner,
285
+ unstakeTicket: TransactionSigner,
286
+ stakedSolMint: Address,
287
+ stakedSolToDeposit: BN,
288
+ minSharesToReceive: BN
289
+ ): Promise<MintIxs> {
290
+ const pool = await poolState.getState(this.getConnection());
291
+ // Create unstake ticket ix
292
+ const size = UnstakeTicket.layout.span + 8;
293
+ const createUnstakeTicketIx = getCreateAccountInstruction({
294
+ payer: user,
295
+ newAccount: unstakeTicket,
296
+ lamports: await this.getConnection().getMinimumBalanceForRentExemption(BigInt(size)).send(),
297
+ space: size,
298
+ programAddress: this._unstakingPoolProgramId,
299
+ });
300
+
301
+ // Actual mint ix
302
+ const [stakedSolPool, stakedSolPoolPk, stakePoolType] = await mapStakedSolMintToPool(
303
+ this.getConnection(),
304
+ stakedSolMint
305
+ );
306
+ const accounts: MintAccounts = {
307
+ poolState: poolState.address,
308
+ basePoolAuthority: pool.basePoolAuthority,
309
+ systemProgram: SYSTEM_PROGRAM_ADDRESS,
310
+ unstakingSolMint: pool.unstakingSolMint,
311
+ unstakingSolTokenProgram: TOKEN_PROGRAM_ADDRESS,
312
+ user,
313
+ actionAuthority,
314
+ userStakedSolToken: await getAssociatedTokenAddress(stakedSolMint, user.address),
315
+ userUnstakingSolToken: await getAssociatedTokenAddress(pool.unstakingSolMint, user.address),
316
+ stakedSolMint,
317
+ stakedSolTokenProgram: fromLegacyPublicKey(stakedSolPool.tokenProgramId),
318
+ unstakingTicketAuthority: user.address,
319
+ unstakeTicket: unstakeTicket.address,
320
+ };
321
+ const args: MintArgs = {
322
+ stakedSolToDeposit,
323
+ minSharesToReceive,
324
+ };
325
+ const ix = mint(args, accounts, this._unstakingPoolProgramId);
326
+ let remainingAccounts: (AccountMeta | AccountSignerMeta)[] = [];
327
+ let remainingSigners: KeyPairSigner[] = [];
328
+ switch (stakePoolType) {
329
+ case StakePoolType.Standard:
330
+ [remainingAccounts, remainingSigners] = await getStandardPoolMintRemainingAccounts(
331
+ this.getConnection(),
332
+ stakedSolPool,
333
+ stakedSolPoolPk,
334
+ stakedSolToDeposit
335
+ );
336
+ }
337
+ const ixAccounts = ix.accounts || [];
338
+ const mintIx: Instruction = {
339
+ programAddress: ix.programAddress,
340
+ accounts: ixAccounts.concat(remainingAccounts),
341
+ data: ix.data,
342
+ };
343
+ return { mintIxs: [createUnstakeTicketIx, mintIx], additionalSigners: remainingSigners };
344
+ }
345
+
346
+ /**
347
+ * Sync a pool for lookup table;
348
+ * @param pool the pool to sync the LUT for
349
+ * @param owner the pool lut owner
350
+ * @returns a struct that contains a list of ix to create the LUT and assign it to the pool if needed + a list of ixs to insert all the accounts in the LUT
351
+ */
352
+ async syncPoolLookupTable(pool: UnstakingPool, owner: TransactionSigner): Promise<Instruction[]> {
353
+ const poolState = await pool.getState(this.getConnection());
354
+ if (poolState.poolLookupTable == DEFAULT_PUBLIC_KEY) {
355
+ throw new Error(`Pool ${pool.address} has no lut set`);
356
+ }
357
+ const allAccountsToBeInserted = [
358
+ pool.address,
359
+ poolState.basePoolAuthority,
360
+ poolState.wsolVault,
361
+ poolState.unstakingSolMint,
362
+ poolState.actionAuthority,
363
+ poolState.admin,
364
+ this._unstakingPoolProgramId,
365
+ SYSTEM_PROGRAM_ADDRESS,
366
+ SYSVAR_RENT_ADDRESS,
367
+ TOKEN_PROGRAM_ADDRESS,
368
+ TOKEN_2022_PROGRAM_ADDRESS,
369
+ SYSVAR_INSTRUCTIONS_ADDRESS,
370
+ SYSVAR_CLOCK_ADDRESS,
371
+ STAKE_PROGRAM_ID,
372
+ STAKE_POOL_PROGRAM_ID,
373
+ ];
374
+
375
+ // Passing [] as accountsInLut will not fetch anything
376
+ const syncIxs = insertIntoLookupTableIxs(
377
+ this.getConnection(),
378
+ owner,
379
+ poolState.poolLookupTable,
380
+ allAccountsToBeInserted,
381
+ []
382
+ );
383
+ return syncIxs;
384
+ }
385
+
386
+ /**
387
+ * Get all pools
388
+ * @returns an array of all pools
389
+ */
390
+ async getAllPools(): Promise<UnstakingPool[]> {
391
+ const filters: (GetProgramAccountsDatasizeFilter | GetProgramAccountsMemcmpFilter)[] = [
392
+ {
393
+ dataSize: BigInt(PoolState.layout.span + 8),
394
+ },
395
+ {
396
+ memcmp: {
397
+ offset: 0n,
398
+ bytes: bs58.encode(PoolState.discriminator) as Base58EncodedBytes,
399
+ encoding: 'base58',
400
+ },
401
+ },
402
+ ];
403
+
404
+ const unstakingPools = await getProgramAccounts(
405
+ this.getConnection(),
406
+ this._unstakingPoolProgramId,
407
+ PoolState.layout.span + 8,
408
+ filters
409
+ );
410
+
411
+ return unstakingPools.map((unstakingPool) => {
412
+ const unstakingPoolAccount = PoolState.decode(unstakingPool.data);
413
+ if (!unstakingPoolAccount) {
414
+ throw Error(`unstakingPool with pubkey ${unstakingPool.address.toString()} could not be decoded`);
415
+ }
416
+
417
+ return new UnstakingPool(unstakingPool.address, unstakingPoolAccount, this._unstakingPoolProgramId);
418
+ });
419
+ }
420
+ } // UnstakingPoolClient
421
+
422
+ export class UnstakingPool {
423
+ readonly address: Address;
424
+ state: PoolState | undefined | null;
425
+ programId: Address;
426
+
427
+ constructor(poolAddress: Address, state?: PoolState, programId: Address = UNSTAKING_POOL_ID) {
428
+ this.address = poolAddress;
429
+ this.state = state;
430
+ this.programId = programId;
431
+ }
432
+
433
+ async getState(rpc: Rpc<GetAccountInfoApi>): Promise<PoolState> {
434
+ if (!this.state) {
435
+ this.state = await this.reloadState(rpc);
436
+ }
437
+ return this.state;
438
+ }
439
+
440
+ async reloadState(rpc: Rpc<GetAccountInfoApi>): Promise<PoolState> {
441
+ this.state = await PoolState.fetch(rpc, this.address, this.programId);
442
+ if (!this.state) {
443
+ throw new Error(`Could not fetch pool ${this.address.toString()}`);
444
+ }
445
+ return this.state;
446
+ }
447
+
448
+ async getStakeAccountsForPool(rpc: Rpc<GetProgramAccountsApi>): Promise<Array<StakeAccountInfo>> {
449
+ if (!this.state) {
450
+ throw new Error('Need to have pool state to fetch stake accounts');
451
+ }
452
+ // Filter only accounts that have withdraw authority the base pool authority
453
+ // and are delegating
454
+ const results = await getProgramAccounts(rpc, STAKE_PROGRAM_ID, STAKE_ACCOUNT_SIZE, [
455
+ { memcmp: { offset: 0n, bytes: bs58.encode([2]) as Base58EncodedBytes, encoding: 'base58' } },
456
+ {
457
+ memcmp: {
458
+ offset: 44n,
459
+ bytes: this.state.basePoolAuthority.toString() as Base58EncodedBytes,
460
+ encoding: 'base58',
461
+ },
462
+ },
463
+ ]);
464
+ return results.map((result) => {
465
+ return { stakeAccount: StakeAccount.decode(result.data), pk: result.address, lamports: new BN(result.lamports) };
466
+ });
467
+ }
468
+ }
469
+
470
+ export type StakeAccountInfo = {
471
+ pk: Address;
472
+ stakeAccount: StakeAccount;
473
+ lamports: BN;
474
+ };
475
+
476
+ /**
477
+ * Used to initialize a Kamino Pool
478
+ */
479
+ export type UnstakingPoolConfig = {
480
+ /** The admin of the pool */
481
+ admin: TransactionSigner;
482
+ /** Pubkey that can mint new tokens */
483
+ actionAuthority: Address | null;
484
+ };
485
+
486
+ export function unstakingPoolMintPda(
487
+ pool: Address,
488
+ programId: Address = UNSTAKING_POOL_ID
489
+ ): Promise<ProgramDerivedAddress> {
490
+ return getProgramDerivedAddress({
491
+ seeds: [UNSTAKING_SOL_MINT_SEED, addressEncoder.encode(pool)],
492
+ programAddress: programId,
493
+ });
494
+ }
495
+
496
+ export function unstakingPoolAuthorityPda(
497
+ pool: Address,
498
+ programId: Address = UNSTAKING_POOL_ID
499
+ ): Promise<ProgramDerivedAddress> {
500
+ return getProgramDerivedAddress({
501
+ seeds: [BASE_POOL_AUTHORITY_SEED, addressEncoder.encode(pool)],
502
+ programAddress: programId,
503
+ });
504
+ }
@@ -0,0 +1,12 @@
1
+ import { Instruction, KeyPairSigner } from '@solana/kit';
2
+
3
+ export type InitPoolIxs = {
4
+ initPoolIxs: Instruction[];
5
+ populateLUTIxs: Instruction[];
6
+ };
7
+
8
+ export type MintIxs = {
9
+ // Should return unstake ticket creation ix + mint ix
10
+ mintIxs: Instruction[];
11
+ additionalSigners: KeyPairSigner[];
12
+ };
@@ -102,7 +102,7 @@ import {
102
102
  import { batchFetch, collToLamportsDecimal, ZERO } from '@kamino-finance/kliquidity-sdk';
103
103
  import { FullBPSDecimal } from '@kamino-finance/kliquidity-sdk/dist/utils/CreationParameters';
104
104
  import { FarmIncentives, FarmState } from '@kamino-finance/farms-sdk/dist';
105
- import { getAccountsInLut, initLookupTableIx } from '../utils/lookupTable';
105
+ import { getAccountsInLut, initLookupTableIx, insertIntoLookupTableIxs } from '../utils/lookupTable';
106
106
  import {
107
107
  getFarmStakeIxs,
108
108
  getFarmUnstakeAndWithdrawIxs,
@@ -121,7 +121,6 @@ import {
121
121
  import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
122
122
  import { SYSVAR_INSTRUCTIONS_ADDRESS, SYSVAR_RENT_ADDRESS } from '@solana/sysvars';
123
123
  import { noopSigner } from '../utils/signer';
124
- import { getExtendLookupTableInstruction } from '@solana-program/address-lookup-table';
125
124
  import { Farms } from '@kamino-finance/farms-sdk';
126
125
  import { getFarmIncentives } from '@kamino-finance/farms-sdk/dist/utils/apy';
127
126
  import { computeReservesAllocation } from '../utils/vaultAllocation';
@@ -296,7 +295,13 @@ export class KaminoVaultClient {
296
295
  this._kaminoLendProgramId,
297
296
  SYSVAR_INSTRUCTIONS_ADDRESS,
298
297
  ];
299
- const insertIntoLUTIxs = await this.insertIntoLookupTableIxs(vaultConfig.admin, lut, accountsToBeInserted, []);
298
+ const insertIntoLUTIxs = await insertIntoLookupTableIxs(
299
+ this.getConnection(),
300
+ vaultConfig.admin,
301
+ lut,
302
+ accountsToBeInserted,
303
+ []
304
+ );
300
305
 
301
306
  const setLUTIx = this.updateUninitialisedVaultConfigIx(
302
307
  vaultConfig.admin,
@@ -445,7 +450,8 @@ export class KaminoVaultClient {
445
450
  const [lendingMarketAuth] = await lendingMarketAuthPda(reserveState.lendingMarket, this._kaminoLendProgramId);
446
451
  accountsToAddToLut.push(lendingMarketAuth);
447
452
 
448
- const insertIntoLutIxs = await this.insertIntoLookupTableIxs(
453
+ const insertIntoLutIxs = await insertIntoLookupTableIxs(
454
+ this.getConnection(),
449
455
  vaultAdmin,
450
456
  vaultState.vaultLookupTable,
451
457
  accountsToAddToLut
@@ -743,7 +749,12 @@ export class KaminoVaultClient {
743
749
 
744
750
  if (mode.kind === new VaultConfigField.PendingVaultAdmin().kind) {
745
751
  const newPubkey = address(value);
746
- const insertIntoLutIxs = await this.insertIntoLookupTableIxs(admin, vaultState.vaultLookupTable, [newPubkey]);
752
+ const insertIntoLutIxs = await insertIntoLookupTableIxs(
753
+ this.getConnection(),
754
+ admin,
755
+ vaultState.vaultLookupTable,
756
+ [newPubkey]
757
+ );
747
758
  updateLUTIxs.push(...insertIntoLutIxs);
748
759
  } else if (mode.kind === new VaultConfigField.Farm().kind) {
749
760
  const keysToAddToLUT = [address(value)];
@@ -757,7 +768,8 @@ export class KaminoVaultClient {
757
768
  farmState!.scopePrices,
758
769
  farmState!.globalConfig
759
770
  );
760
- const insertIntoLutIxs = await this.insertIntoLookupTableIxs(
771
+ const insertIntoLutIxs = await insertIntoLookupTableIxs(
772
+ this.getConnection(),
761
773
  admin,
762
774
  vaultState.vaultLookupTable,
763
775
  keysToAddToLUT
@@ -876,7 +888,13 @@ export class KaminoVaultClient {
876
888
  await this.getConnection().getSlot({ commitment: 'finalized' }).send()
877
889
  );
878
890
 
879
- const insertIntoLUTIxs = await this.insertIntoLookupTableIxs(signer, newLut, accountsInExistentLUT, []);
891
+ const insertIntoLUTIxs = await insertIntoLookupTableIxs(
892
+ this.getConnection(),
893
+ signer,
894
+ newLut,
895
+ accountsInExistentLUT,
896
+ []
897
+ );
880
898
 
881
899
  lutIxs.push(...insertIntoLUTIxs);
882
900
 
@@ -1689,7 +1707,12 @@ export class KaminoVaultClient {
1689
1707
  sharesAmount: new BN(shareAmountLamports.floor().toString()),
1690
1708
  };
1691
1709
 
1692
- return withdrawFromAvailable(withdrawFromAvailableArgs, withdrawFromAvailableAccounts, undefined, this._kaminoVaultProgramId);
1710
+ return withdrawFromAvailable(
1711
+ withdrawFromAvailableArgs,
1712
+ withdrawFromAvailableAccounts,
1713
+ undefined,
1714
+ this._kaminoVaultProgramId
1715
+ );
1693
1716
  }
1694
1717
 
1695
1718
  private async withdrawPendingFeesIx(
@@ -1722,7 +1745,11 @@ export class KaminoVaultClient {
1722
1745
  reserveCollateralTokenProgram: TOKEN_PROGRAM_ADDRESS,
1723
1746
  };
1724
1747
 
1725
- let withdrawPendingFeesIxn = withdrawPendingFees(withdrawPendingFeesAccounts, undefined, this._kaminoVaultProgramId);
1748
+ let withdrawPendingFeesIxn = withdrawPendingFees(
1749
+ withdrawPendingFeesAccounts,
1750
+ undefined,
1751
+ this._kaminoVaultProgramId
1752
+ );
1726
1753
 
1727
1754
  const vaultReserves = this.getVaultReserves(vaultState);
1728
1755
  const vaultReservesState = await this.loadVaultReserves(vaultState);
@@ -1814,7 +1841,13 @@ export class KaminoVaultClient {
1814
1841
  overriddenExistentAccounts = [];
1815
1842
  }
1816
1843
  ixs.push(
1817
- ...(await this.insertIntoLookupTableIxs(authority, lut, allAccountsToBeInserted, overriddenExistentAccounts))
1844
+ ...(await insertIntoLookupTableIxs(
1845
+ this.getConnection(),
1846
+ authority,
1847
+ lut,
1848
+ allAccountsToBeInserted,
1849
+ overriddenExistentAccounts
1850
+ ))
1818
1851
  );
1819
1852
 
1820
1853
  return {
@@ -1836,52 +1869,6 @@ export class KaminoVaultClient {
1836
1869
  ];
1837
1870
  }
1838
1871
 
1839
- /**
1840
- * This method inserts the missing keys from the provided keys into an existent lookup table
1841
- * @param authority - payer wallet pubkey
1842
- * @param lookupTable - lookup table to insert the keys into
1843
- * @param keys - keys to insert into the lookup table
1844
- * @param [accountsInLut] - the existent accounts in the lookup table. Optional. If provided, the function will not fetch the accounts in the lookup table
1845
- * @returns - an array of instructions to insert the missing keys into the lookup table
1846
- */
1847
- async insertIntoLookupTableIxs(
1848
- authority: TransactionSigner,
1849
- lookupTable: Address,
1850
- keys: Address[],
1851
- accountsInLut?: Address[]
1852
- ): Promise<Instruction[]> {
1853
- let lutContentsList = accountsInLut;
1854
- if (!accountsInLut) {
1855
- lutContentsList = await getAccountsInLut(this.getConnection(), lookupTable);
1856
- } else {
1857
- lutContentsList = accountsInLut;
1858
- }
1859
-
1860
- const lutContents = new Set<Address>(lutContentsList);
1861
-
1862
- const missingAccounts = keys.filter((key) => !lutContents.has(key) && key !== DEFAULT_PUBLIC_KEY);
1863
- // deduplicate missing accounts and remove default accounts and convert it back to an array
1864
- const missingAccountsList = [...new Set<Address>(missingAccounts)];
1865
-
1866
- const chunkSize = 10;
1867
- const ixs: Instruction[] = [];
1868
-
1869
- for (let i = 0; i < missingAccountsList.length; i += chunkSize) {
1870
- const chunk = missingAccountsList.slice(i, i + chunkSize);
1871
- ixs.push(
1872
- getExtendLookupTableInstruction({
1873
- payer: authority,
1874
- authority,
1875
- address: lookupTable,
1876
- systemProgram: SYSTEM_PROGRAM_ADDRESS,
1877
- addresses: chunk,
1878
- })
1879
- );
1880
- }
1881
-
1882
- return ixs;
1883
- }
1884
-
1885
1872
  /** Read the total holdings of a vault and the reserve weights and returns a map from each reserve to how many tokens should be deposited.
1886
1873
  * @param vaultState - the vault state to calculate the allocation for
1887
1874
  * @param [slot] - the slot for which to calculate the allocation. Optional. If not provided the function will fetch the current slot