@carrot-protocol/clend-rpc 0.0.1-mrgn-fork1-dev-7be6ef2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts ADDED
@@ -0,0 +1,31 @@
1
+ export { ClendClient } from "./rpc";
2
+ export { Instructions } from "./instructions";
3
+ export { MockJupiterUtils } from "./mockJupiterUtils";
4
+ export {
5
+ IJupiterUtils,
6
+ JupiterUtils,
7
+ SwapInputs,
8
+ SwapQuote,
9
+ SwapIxs,
10
+ } from "./jupiterUtils";
11
+ export * from "./addresses";
12
+ export {
13
+ BankConfigCompact,
14
+ ClendGroup,
15
+ Bank,
16
+ ClendAccount,
17
+ FeeState,
18
+ Balance,
19
+ newInterestRateConfigCompact,
20
+ newBankConfigCompact,
21
+ RiskTier,
22
+ BankOperationalState,
23
+ AssetTag,
24
+ newClendAccountBalance,
25
+ InterestRateConfigCompact,
26
+ TOKEN_DECIMALS,
27
+ TOKEN_PROGRAMS,
28
+ USDC_MINT,
29
+ JLP_MINT,
30
+ } from "./state";
31
+ export * from "./math";
@@ -0,0 +1,466 @@
1
+ import { AnchorProvider, Program, web3, BN } from "@coral-xyz/anchor";
2
+ import { Clend, IDL } from "./idl/clend";
3
+ import {
4
+ CLEND_PROGRAM_ID,
5
+ getBankFeeVaultAuthorityPda,
6
+ getBankFeeVaultPda,
7
+ getBankInsuranceVaultAuthorityPda,
8
+ getBankInsuranceVaultPda,
9
+ getBankLiquidityVaultAuthorityPda,
10
+ getBankLiquidityVaultPda,
11
+ getBankPda,
12
+ getFeeStatePda,
13
+ } from "./addresses";
14
+ import { bigNumberToWrappedI80F48, getTokenProgramForMint } from "./utils";
15
+ import {
16
+ BankConfigCompact,
17
+ BankOperationalState,
18
+ InterestRateConfigCompact,
19
+ InterestRateConfigOpt,
20
+ OracleSetup,
21
+ RiskTier,
22
+ } from "./state";
23
+ import { createInitializeAccount3Instruction } from "@solana/spl-token";
24
+
25
+ // Types for configuration
26
+ export type GroupConfig = {
27
+ admin?: web3.PublicKey;
28
+ };
29
+
30
+ export type FeeStateConfig = {
31
+ admin: web3.PublicKey;
32
+ feeWallet: web3.PublicKey;
33
+ bankInitFlatSolFee: number;
34
+ programFeeFixed: BN;
35
+ programFeeRate: BN;
36
+ };
37
+
38
+ export class Instructions {
39
+ readonly program: Program<Clend>;
40
+
41
+ constructor(provider: AnchorProvider) {
42
+ this.program = new Program(IDL, CLEND_PROGRAM_ID, provider);
43
+ }
44
+
45
+ // Group Instructions
46
+ async initializeGroup(
47
+ clendGroup: web3.Keypair,
48
+ admin: web3.PublicKey,
49
+ feeState: web3.PublicKey,
50
+ ): Promise<web3.TransactionInstruction> {
51
+ return this.program.methods
52
+ .clendGroupInitialize()
53
+ .accounts({
54
+ clendGroup: clendGroup.publicKey,
55
+ admin,
56
+ feeState,
57
+ systemProgram: web3.SystemProgram.programId,
58
+ })
59
+ .signers([clendGroup])
60
+ .instruction();
61
+ }
62
+
63
+ async configureGroup(
64
+ clendGroup: web3.PublicKey,
65
+ admin: web3.PublicKey,
66
+ config: GroupConfig,
67
+ ): Promise<web3.TransactionInstruction> {
68
+ return this.program.methods
69
+ .clendGroupConfigure(config)
70
+ .accounts({
71
+ clendGroup,
72
+ admin,
73
+ })
74
+ .instruction();
75
+ }
76
+
77
+ // Fee State Instructions
78
+ async initGlobalFeeState(
79
+ admin: web3.PublicKey,
80
+ feeWallet: web3.PublicKey,
81
+ bankInitFlatSolFee: number,
82
+ programFeeFixed: BN,
83
+ programFeeRate: BN,
84
+ ): Promise<web3.TransactionInstruction> {
85
+ const feeState = getFeeStatePda();
86
+
87
+ const programFeeFixedWrapped = bigNumberToWrappedI80F48(programFeeFixed);
88
+ const programFeeRateWrapped = bigNumberToWrappedI80F48(programFeeRate);
89
+
90
+ return this.program.methods
91
+ .initGlobalFeeState(
92
+ admin,
93
+ feeWallet,
94
+ bankInitFlatSolFee,
95
+ programFeeFixedWrapped,
96
+ programFeeRateWrapped,
97
+ )
98
+ .accounts({
99
+ feeState,
100
+ payer: admin,
101
+ rent: web3.SYSVAR_RENT_PUBKEY,
102
+ systemProgram: web3.SystemProgram.programId,
103
+ })
104
+ .instruction();
105
+ }
106
+
107
+ // Bank Instructions
108
+ async addBank(
109
+ clendGroup: web3.PublicKey,
110
+ admin: web3.PublicKey,
111
+ globalFeeWallet: web3.PublicKey,
112
+ bankMint: web3.PublicKey,
113
+ tokenProgram: web3.PublicKey,
114
+ pythOracle: web3.PublicKey,
115
+ pythOracleFeedId: web3.PublicKey,
116
+ bankConfig: BankConfigCompact,
117
+ interestRateConfig: InterestRateConfigCompact,
118
+ ): Promise<{ bank: web3.PublicKey; ixns: web3.TransactionInstruction[] }> {
119
+ const bank = getBankPda(clendGroup, bankMint);
120
+ const liquidityVault = getBankLiquidityVaultPda(bank);
121
+ const insuranceVault = getBankInsuranceVaultPda(bank);
122
+ const feeVault = getBankFeeVaultPda(bank);
123
+ const liquidityVaultAuthority = getBankLiquidityVaultAuthorityPda(bank);
124
+ const insuranceVaultAuthority = getBankInsuranceVaultAuthorityPda(bank);
125
+ const feeVaultAuthority = getBankFeeVaultAuthorityPda(bank);
126
+ const feeState = getFeeStatePda();
127
+
128
+ const formattedConfig = {
129
+ ...bankConfig,
130
+ operationalState: formatBankOperationalState(bankConfig.operationalState),
131
+ riskTier: formatRiskTier(bankConfig.riskTier),
132
+ };
133
+
134
+ const addBankIx = await this.program.methods
135
+ .lendingPoolAddBankWithSeed(formattedConfig, interestRateConfig)
136
+ .accounts({
137
+ clendGroup,
138
+ admin,
139
+ feeState,
140
+ globalFeeWallet,
141
+ bankMint,
142
+ bank,
143
+ liquidityVaultAuthority,
144
+ liquidityVault,
145
+ insuranceVaultAuthority,
146
+ insuranceVault,
147
+ feeVaultAuthority,
148
+ feeVault,
149
+ tokenProgram,
150
+ systemProgram: web3.SystemProgram.programId,
151
+ })
152
+ .instruction();
153
+
154
+ const configBankOracleIx = await this.configureBankOracle(
155
+ clendGroup,
156
+ admin,
157
+ bank,
158
+ pythOracle,
159
+ pythOracleFeedId,
160
+ );
161
+
162
+ return {
163
+ bank,
164
+ ixns: [addBankIx, configBankOracleIx],
165
+ };
166
+ }
167
+
168
+ async configureBankOracle(
169
+ clendGroup: web3.PublicKey,
170
+ admin: web3.PublicKey,
171
+ bank: web3.PublicKey,
172
+ pythOracle: web3.PublicKey,
173
+ pythOracleFeedId: web3.PublicKey,
174
+ ): Promise<web3.TransactionInstruction> {
175
+ // hardcode this type for now
176
+ const oracleSetup = OracleSetup.PythPushOracle;
177
+
178
+ const oracleRA: web3.AccountMeta = {
179
+ isSigner: false,
180
+ isWritable: false,
181
+ pubkey: pythOracle,
182
+ };
183
+
184
+ const ix = await this.program.methods
185
+ .lendingPoolConfigureBankOracle(oracleSetup, pythOracleFeedId)
186
+ .accounts({
187
+ group: clendGroup,
188
+ admin,
189
+ bank,
190
+ })
191
+ .remainingAccounts([oracleRA])
192
+ .instruction();
193
+ return ix;
194
+ }
195
+
196
+ // Account Instructions
197
+ async initializeClendAccount(
198
+ clendGroup: web3.PublicKey,
199
+ authority: web3.PublicKey,
200
+ clendAccount: web3.Keypair,
201
+ ): Promise<web3.TransactionInstruction> {
202
+ return this.program.methods
203
+ .clendAccountInitialize()
204
+ .accounts({
205
+ clendGroup,
206
+ authority,
207
+ clendAccount: clendAccount.publicKey,
208
+ feePayer: authority,
209
+ systemProgram: web3.SystemProgram.programId,
210
+ })
211
+ .signers([clendAccount])
212
+ .instruction();
213
+ }
214
+
215
+ // Deposit/Withdraw/Borrow/Repay Instructions
216
+ async deposit(
217
+ clendGroup: web3.PublicKey,
218
+ clendAccount: web3.PublicKey,
219
+ user: web3.PublicKey,
220
+ bank: web3.PublicKey,
221
+ userTokenAccount: web3.PublicKey,
222
+ tokenProgram: web3.PublicKey,
223
+ amount: BN,
224
+ remainingAccounts: web3.AccountMeta[],
225
+ ): Promise<web3.TransactionInstruction> {
226
+ const bankLiquidityVault = getBankLiquidityVaultPda(bank);
227
+
228
+ return this.program.methods
229
+ .lendingAccountDeposit(amount)
230
+ .accounts({
231
+ clendGroup,
232
+ clendAccount,
233
+ signer: user,
234
+ bank,
235
+ signerTokenAccount: userTokenAccount,
236
+ bankLiquidityVault,
237
+ tokenProgram,
238
+ })
239
+ .remainingAccounts(remainingAccounts)
240
+ .instruction();
241
+ }
242
+
243
+ async withdraw(
244
+ clendGroup: web3.PublicKey,
245
+ clendAccount: web3.PublicKey,
246
+ user: web3.PublicKey,
247
+ bank: web3.PublicKey,
248
+ destinationTokenAccount: web3.PublicKey,
249
+ tokenProgram: web3.PublicKey,
250
+ amount: BN,
251
+ withdrawAll: boolean | null = null,
252
+ remainingAccounts: web3.AccountMeta[],
253
+ ): Promise<web3.TransactionInstruction> {
254
+ const bankLiquidityVault = getBankLiquidityVaultPda(bank);
255
+ const bankLiquidityVaultAuthority = getBankLiquidityVaultAuthorityPda(bank);
256
+
257
+ return this.program.methods
258
+ .lendingAccountWithdraw(amount, withdrawAll)
259
+ .accounts({
260
+ clendGroup,
261
+ clendAccount,
262
+ signer: user,
263
+ bank,
264
+ bankLiquidityVault,
265
+ bankLiquidityVaultAuthority,
266
+ destinationTokenAccount,
267
+ tokenProgram,
268
+ })
269
+ .remainingAccounts(remainingAccounts)
270
+ .instruction();
271
+ }
272
+
273
+ async borrow(
274
+ clendGroup: web3.PublicKey,
275
+ clendAccount: web3.PublicKey,
276
+ user: web3.PublicKey,
277
+ bank: web3.PublicKey,
278
+ destinationTokenAccount: web3.PublicKey,
279
+ tokenProgram: web3.PublicKey,
280
+ amount: BN,
281
+ remainingAccounts: web3.AccountMeta[],
282
+ ): Promise<web3.TransactionInstruction> {
283
+ const bankLiquidityVaultAuthority = getBankLiquidityVaultAuthorityPda(bank);
284
+ const bankLiquidityVault = getBankLiquidityVaultPda(bank);
285
+
286
+ return this.program.methods
287
+ .lendingAccountBorrow(amount)
288
+ .accounts({
289
+ clendGroup,
290
+ clendAccount,
291
+ signer: user,
292
+ bank,
293
+ destinationTokenAccount,
294
+ bankLiquidityVaultAuthority,
295
+ bankLiquidityVault,
296
+ tokenProgram,
297
+ })
298
+ .remainingAccounts(remainingAccounts)
299
+ .instruction();
300
+ }
301
+
302
+ async repay(
303
+ clendGroup: web3.PublicKey,
304
+ clendAccount: web3.PublicKey,
305
+ user: web3.PublicKey,
306
+ bank: web3.PublicKey,
307
+ userTokenAccount: web3.PublicKey,
308
+ tokenProgram: web3.PublicKey,
309
+ amount: BN,
310
+ repayAll: boolean | null = null,
311
+ remainingAccounts: web3.AccountMeta[],
312
+ ): Promise<web3.TransactionInstruction> {
313
+ const bankLiquidityVault = getBankLiquidityVaultPda(bank);
314
+
315
+ return this.program.methods
316
+ .lendingAccountRepay(amount, repayAll)
317
+ .accounts({
318
+ clendGroup,
319
+ clendAccount,
320
+ signer: user,
321
+ bank,
322
+ signerTokenAccount: userTokenAccount,
323
+ bankLiquidityVault,
324
+ tokenProgram,
325
+ })
326
+ .remainingAccounts(remainingAccounts)
327
+ .instruction();
328
+ }
329
+
330
+ // Flash Loan Instructions
331
+ async createFlashLoanInstructions(
332
+ clendAccount: web3.PublicKey,
333
+ user: web3.PublicKey,
334
+ endIndex: BN,
335
+ remainingAccounts: web3.AccountMeta[],
336
+ ): Promise<{
337
+ beginFlashLoanIx: web3.TransactionInstruction;
338
+ endFlashLoanIx: web3.TransactionInstruction;
339
+ }> {
340
+ const beginFlashLoanIx = await this.program.methods
341
+ .lendingAccountStartFlashloan(endIndex)
342
+ .accounts({
343
+ clendAccount,
344
+ signer: user,
345
+ ixsSysvar: web3.SYSVAR_INSTRUCTIONS_PUBKEY,
346
+ })
347
+ .instruction();
348
+
349
+ const endFlashLoanIx = await this.program.methods
350
+ .lendingAccountEndFlashloan()
351
+ .accounts({
352
+ clendAccount,
353
+ signer: user,
354
+ })
355
+ .remainingAccounts(remainingAccounts)
356
+ .instruction();
357
+
358
+ return {
359
+ beginFlashLoanIx,
360
+ endFlashLoanIx,
361
+ };
362
+ }
363
+
364
+ async configureBankInterestRate(
365
+ clendGroup: web3.PublicKey,
366
+ admin: web3.PublicKey,
367
+ bank: web3.PublicKey,
368
+ interestRateConfig: InterestRateConfigOpt,
369
+ ): Promise<web3.TransactionInstruction> {
370
+ return this.program.methods
371
+ .lendingPoolConfigureBankIr(interestRateConfig)
372
+ .accounts({
373
+ clendGroup,
374
+ admin,
375
+ bank,
376
+ })
377
+ .instruction();
378
+ }
379
+
380
+ async editGlobalFeeWallet(
381
+ admin: web3.PublicKey,
382
+ newGlobalFeeWallet: web3.PublicKey,
383
+ ): Promise<web3.TransactionInstruction> {
384
+ const feeState = getFeeStatePda();
385
+
386
+ return this.program.methods
387
+ .editGlobalFeeState(newGlobalFeeWallet, 10000, new BN(0), new BN(10000))
388
+ .accounts({
389
+ globalFeeAdmin: admin,
390
+ feeState,
391
+ })
392
+ .instruction();
393
+ }
394
+ }
395
+
396
+ export function formatBankOperationalState(state: number): any {
397
+ switch (state) {
398
+ case 0:
399
+ return { paused: {} };
400
+ case 1:
401
+ return { operational: {} };
402
+ case 2:
403
+ return { reduceOnly: {} };
404
+ default:
405
+ throw new Error(
406
+ `Invalid bank operational state: ${state}, expected 0 (Paused), 1 (Operational), or 2 (ReduceOnly)`,
407
+ );
408
+ }
409
+ }
410
+
411
+ export function parseBankOperationalState(state: any): BankOperationalState {
412
+ if ("paused" in state) {
413
+ return BankOperationalState.Paused;
414
+ }
415
+ if ("operational" in state) {
416
+ return BankOperationalState.Operational;
417
+ }
418
+ if ("reduceOnly" in state) {
419
+ return BankOperationalState.ReduceOnly;
420
+ }
421
+ throw new Error(
422
+ `Invalid bank operational state format: ${JSON.stringify(state)}, expected object with 'paused', 'operational', or 'reduceOnly' key`,
423
+ );
424
+ }
425
+
426
+ export function formatRiskTier(tier: number): any {
427
+ switch (tier) {
428
+ case 0:
429
+ return { collateral: {} };
430
+ case 1:
431
+ return { isolated: {} };
432
+ default:
433
+ throw new Error(
434
+ `Invalid risk tier: ${tier}, expected 0 (Collateral) or 1 (Isolated)`,
435
+ );
436
+ }
437
+ }
438
+
439
+ export function parseRiskTier(tier: any): RiskTier {
440
+ if ("collateral" in tier) {
441
+ return RiskTier.Collateral;
442
+ }
443
+ if ("isolated" in tier) {
444
+ return RiskTier.Isolated;
445
+ }
446
+ throw new Error(
447
+ `Invalid risk tier format: ${JSON.stringify(tier)}, expected object with 'collateral' or 'isolated' key`,
448
+ );
449
+ }
450
+
451
+ export function parseOracleSetup(setup: number): OracleSetup {
452
+ switch (setup) {
453
+ case 0:
454
+ return OracleSetup.None;
455
+ case 1:
456
+ return OracleSetup.PythLegacy;
457
+ case 2:
458
+ return OracleSetup.PythPushOracle;
459
+ case 3:
460
+ return OracleSetup.StakedWithPythPush;
461
+ default:
462
+ throw new Error(
463
+ `Invalid oracle setup value: ${setup}, expected 0, 1, 2, or 3`,
464
+ );
465
+ }
466
+ }