@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/state.ts ADDED
@@ -0,0 +1,512 @@
1
+ import { web3, BN } from "@coral-xyz/anchor";
2
+ import { bigNumberToWrappedI80F48 } from "./utils";
3
+
4
+ /**
5
+ * Clend Group account interface
6
+ * Represents a lending pool group
7
+ */
8
+ export interface ClendGroup {
9
+ // Pubkey (32 bytes)
10
+ admin: web3.PublicKey;
11
+ // u64 (8 bytes)
12
+ flags: number;
13
+ // Padding for future use (503 bytes)
14
+ padding: number[];
15
+ }
16
+
17
+ /**
18
+ * Bank account interface
19
+ * Represents a token bank within a lending pool
20
+ */
21
+ export interface Bank {
22
+ // The pubkey of the bank
23
+ // not on chain
24
+ key: web3.PublicKey;
25
+
26
+ // The mint of the token for this bank
27
+ mint: web3.PublicKey;
28
+ // The number of decimals for the mint
29
+ mintDecimals: number;
30
+ // The clend group this bank belongs to
31
+ group: web3.PublicKey;
32
+ // The value of each asset share
33
+ assetShareValue: WrappedI80F48;
34
+ // The value of each liability share
35
+ liabilityShareValue: WrappedI80F48;
36
+ // The vault holding deposited tokens
37
+ liquidityVault: web3.PublicKey;
38
+ // The bump seed for the liquidity vault PDA
39
+ liquidityVaultBump: number;
40
+ // The bump seed for the liquidity vault authority PDA
41
+ liquidityVaultAuthorityBump: number;
42
+ // The vault holding insurance funds
43
+ insuranceVault: web3.PublicKey;
44
+ // The bump seed for the insurance vault PDA
45
+ insuranceVaultBump: number;
46
+ // The bump seed for the insurance vault authority PDA
47
+ insuranceVaultAuthorityBump: number;
48
+ // Fees collected and pending withdraw for the insurance vault
49
+ collectedInsuranceFeesOutstanding: WrappedI80F48;
50
+ // The vault holding collected fees
51
+ feeVault: web3.PublicKey;
52
+ // The bump seed for the fee vault PDA
53
+ feeVaultBump: number;
54
+ // The bump seed for the fee vault authority PDA
55
+ feeVaultAuthorityBump: number;
56
+ // Fees collected and pending withdraw for the fee vault
57
+ collectedGroupFeesOutstanding: WrappedI80F48;
58
+ // Total amount of liability shares
59
+ totalLiabilityShares: WrappedI80F48;
60
+ // Total amount of asset shares
61
+ totalAssetShares: WrappedI80F48;
62
+ // Last time the bank was updated
63
+ lastUpdate: BN;
64
+ // Bank configuration
65
+ config: BankConfig;
66
+ // Bank flags
67
+ flags: BN;
68
+ // Emissions APR
69
+ emissionsRate: BN;
70
+ // Remaining emissions
71
+ emissionsRemaining: WrappedI80F48;
72
+ // The mint for emissions
73
+ emissionsMint: web3.PublicKey;
74
+ // Fees collected and pending withdraw for the global fee wallet
75
+ collectedProgramFeesOutstanding: WrappedI80F48;
76
+ }
77
+
78
+ /**
79
+ * Bank configuration interface
80
+ * Represents the configuration settings for a bank
81
+ */
82
+ export interface BankConfig {
83
+ // Asset weight for initial margin requirements
84
+ assetWeightInit: WrappedI80F48;
85
+ // Asset weight for maintenance margin requirements
86
+ assetWeightMaint: WrappedI80F48;
87
+ // Liability weight for initial margin requirements
88
+ liabilityWeightInit: WrappedI80F48;
89
+ // Liability weight for maintenance margin requirements
90
+ liabilityWeightMaint: WrappedI80F48;
91
+ // Maximum deposit limit
92
+ depositLimit: BN;
93
+ // Interest rate configuration
94
+ interestRateConfig: InterestRateConfig;
95
+ // Bank operational state
96
+ operationalState: BankOperationalState;
97
+ // Oracle setup configuration
98
+ oracleSetup: number;
99
+ // Oracle keys array
100
+ oracleKeys: web3.PublicKey[];
101
+ // Maximum borrow limit
102
+ borrowLimit: BN;
103
+ // Risk tier classification
104
+ riskTier: RiskTier;
105
+ // Asset tag classification
106
+ assetTag: AssetTag;
107
+ // USD denominated limit for calculating asset value for initialization margin requirements
108
+ totalAssetValueInitLimit: BN;
109
+ // Time window in seconds for the oracle price feed to be considered live
110
+ oracleMaxAge: number;
111
+ }
112
+
113
+ /**
114
+ * Interest rate configuration interface
115
+ */
116
+ export interface InterestRateConfig {
117
+ // Optimal utilization rate
118
+ optimalUtilizationRate: WrappedI80F48;
119
+ // Plateau interest rate
120
+ plateauInterestRate: WrappedI80F48;
121
+ // Maximum interest rate
122
+ maxInterestRate: WrappedI80F48;
123
+ // Insurance fee fixed APR
124
+ insuranceFeeFixedApr: WrappedI80F48;
125
+ // Insurance interest rate fee
126
+ insuranceIrFee: WrappedI80F48;
127
+ // Protocol fixed fee APR
128
+ protocolFixedFeeApr: WrappedI80F48;
129
+ // Protocol interest rate fee
130
+ protocolIrFee: WrappedI80F48;
131
+ // Protocol origination fee
132
+ protocolOriginationFee: WrappedI80F48;
133
+ }
134
+
135
+ /**
136
+ * Clend Account interface
137
+ * Represents a user's lending/borrowing account
138
+ */
139
+ export interface ClendAccount {
140
+ // The owner of this account
141
+ authority: web3.PublicKey;
142
+ // The clend group this account belongs to
143
+ group: web3.PublicKey;
144
+
145
+ // The lending account for this clend account
146
+ lendingAccount: LendingAccount;
147
+
148
+ // Account flags
149
+ accountFlags: number;
150
+ }
151
+
152
+ /**
153
+ * Lending account interface
154
+ * Represents a user's lending account
155
+ */
156
+ export interface LendingAccount {
157
+ balances: Balance[];
158
+ }
159
+
160
+ /**
161
+ * Balance interface
162
+ * Represents a user's balance in a specific bank
163
+ */
164
+ export interface Balance {
165
+ active: boolean;
166
+ bankPk: web3.PublicKey;
167
+ bankAssetTag: number;
168
+ assetShares: WrappedI80F48;
169
+ liabilityShares: WrappedI80F48;
170
+ emissionsOutstanding: WrappedI80F48;
171
+ lastUpdate: BN;
172
+ }
173
+
174
+ /**
175
+ * Fee State interface
176
+ * Represents global fee configuration
177
+ */
178
+ export interface FeeState {
179
+ key: web3.PublicKey;
180
+
181
+ // Authority that can modify fee settings
182
+ globalFeeAdmin: web3.PublicKey;
183
+ // Wallet to receive fees
184
+ globalFeeWallet: web3.PublicKey;
185
+ // Flat fee in SOL for bank initialization
186
+ bankInitFlatSolFee: number;
187
+
188
+ // Fixed fee amount
189
+ programFeeFixed: BN;
190
+ // Fee rate as a percentage
191
+ programFeeRate: BN;
192
+ }
193
+
194
+ /**
195
+ * Oracle Price interface
196
+ * Represents price data from an oracle
197
+ */
198
+ export interface OraclePrice {
199
+ // Price value
200
+ price: BN;
201
+ // Confidence interval
202
+ confidence: BN;
203
+ // Timestamp of the price
204
+ timestamp: BN;
205
+ // Status of the price (valid, stale, etc.)
206
+ status: number;
207
+ // Type of oracle
208
+ oracleType: number;
209
+ }
210
+
211
+ /**
212
+ * Wrapped I80F48 interface
213
+ * Represents a wrapped I80F48 value
214
+ */
215
+ export interface WrappedI80F48 {
216
+ value: number[];
217
+ }
218
+
219
+ export enum BankOperationalState {
220
+ Paused = 0,
221
+ Operational = 1,
222
+ ReduceOnly = 2,
223
+ }
224
+
225
+ export enum RiskTier {
226
+ Collateral = 0,
227
+ Isolated = 1,
228
+ }
229
+
230
+ export enum AssetTag {
231
+ Default = 0, // Regular asset that can be comingled with any other regular asset or SOL
232
+ Sol = 1, // Can be comingled with either DEFAULT or STAKED positions, but not both
233
+ Staked = 2, // Can only deposit other STAKED assets or SOL and can only borrow SOL
234
+ }
235
+
236
+ export enum OracleSetup {
237
+ None = 0,
238
+ PythLegacy = 1,
239
+ PythPushOracle = 2,
240
+ StakedWithPythPush = 3,
241
+ }
242
+
243
+ export type InterestRateConfigCompact = {
244
+ optimalUtilizationRate: WrappedI80F48;
245
+ plateauInterestRate: WrappedI80F48;
246
+ maxInterestRate: WrappedI80F48;
247
+ insuranceFeeFixedApr: WrappedI80F48;
248
+ insuranceIrFee: WrappedI80F48;
249
+ protocolFixedFeeApr: WrappedI80F48;
250
+ protocolIrFee: WrappedI80F48;
251
+ protocolOriginationFee: WrappedI80F48;
252
+ };
253
+
254
+ export type BankConfigCompact = {
255
+ // WrappedI80F48 fields: 4 * 16 = 64 bytes
256
+ assetWeightInit: WrappedI80F48;
257
+ // WrappedI80F48 fields: 4 * 16 = 64 bytes
258
+ assetWeightMaint: WrappedI80F48;
259
+ // WrappedI80F48 fields: 4 * 16 = 64 bytes
260
+ liabilityWeightInit: WrappedI80F48;
261
+ // WrappedI80F48 fields: 4 * 16 = 64 bytes
262
+ liabilityWeightMaint: WrappedI80F48;
263
+ // u64 (8 bytes)
264
+ depositLimit: BN;
265
+ //// InterestRateConfigCompact (8 * 8 = 64 bytes)
266
+ //interestRateConfig: InterestRateConfigCompact;
267
+ // BankOperationalState (1 byte)
268
+ operationalState: BankOperationalState;
269
+ // u64 (8 bytes)
270
+ borrowLimit: BN;
271
+ // RiskTier (1 byte)
272
+ riskTier: RiskTier;
273
+ // u8 (1 byte)
274
+ assetTag: number;
275
+ // 8 bytes
276
+ totalAssetValueInitLimit: BN;
277
+ // u16 (2 bytes)
278
+ oracleMaxAge: number;
279
+ };
280
+
281
+ // Total size breakdown:
282
+ // - WrappedI80F48 fields: 4 * 16 = 64 bytes
283
+ // - BN fields: 4 * 8 = 32 bytes
284
+ // - RiskTier: 1 byte
285
+ // - totalAssetValueInitLimit: 8 bytes
286
+ // - interestRateConfig: 64 bytes
287
+ // - operationalState: 1 byte
288
+ // - assetTag: 1 byte
289
+ // - stakeRateBps: 2 bytes
290
+ // - depositFee: 8 bytes
291
+ // - borrowFee: 8 bytes
292
+ // - oracleMaxAge: 2 bytes
293
+ // - _padding_0: [[u64; 2]; 27] = 27 * 2 * 8 = 432 bytes
294
+ // Total: 784 bytes
295
+
296
+ export type BankConfigOpt = {
297
+ assetWeightInit: WrappedI80F48;
298
+ assetWeightMaint: WrappedI80F48;
299
+ liabilityWeightInit: WrappedI80F48;
300
+ liabilityWeightMaint: WrappedI80F48;
301
+ depositLimit: BN;
302
+ borrowLimit: BN;
303
+ operationalState: BankOperationalState;
304
+ interestRateConfig: InterestRateConfigOpt;
305
+ riskTier: RiskTier;
306
+ assetTag: number;
307
+ totalAssetValueInitLimit: BN;
308
+ oracleMaxAge: number;
309
+ permissionlessBadDebtSettlement: boolean;
310
+ freezeSettings: boolean;
311
+ };
312
+
313
+ export type InterestRateConfigOpt = {
314
+ optimalUtilizationRate: WrappedI80F48 | null;
315
+ plateauInterestRate: WrappedI80F48 | null;
316
+ maxInterestRate: WrappedI80F48 | null;
317
+ insuranceFeeFixedApr: WrappedI80F48 | null;
318
+ insuranceIrFee: WrappedI80F48 | null;
319
+ protocolFixedFeeApr: WrappedI80F48 | null;
320
+ protocolIrFee: WrappedI80F48 | null;
321
+ protocolOriginationFee: WrappedI80F48 | null;
322
+ };
323
+
324
+ export function newInterestRateConfigCompact({
325
+ optimalUtilizationRate,
326
+ plateauInterestRate,
327
+ maxInterestRate,
328
+ insuranceFeeFixedApr,
329
+ insuranceIrFee,
330
+ protocolFixedFeeApr,
331
+ protocolIrFee,
332
+ protocolOriginationFee,
333
+ }: {
334
+ optimalUtilizationRate: number;
335
+ plateauInterestRate: number;
336
+ maxInterestRate: number;
337
+ insuranceFeeFixedApr: number;
338
+ insuranceIrFee: number;
339
+ protocolFixedFeeApr: number;
340
+ protocolIrFee: number;
341
+ protocolOriginationFee: number;
342
+ }): InterestRateConfigCompact {
343
+ return {
344
+ optimalUtilizationRate: bigNumberToWrappedI80F48(optimalUtilizationRate),
345
+ plateauInterestRate: bigNumberToWrappedI80F48(plateauInterestRate),
346
+ maxInterestRate: bigNumberToWrappedI80F48(maxInterestRate),
347
+ insuranceFeeFixedApr: bigNumberToWrappedI80F48(insuranceFeeFixedApr),
348
+ insuranceIrFee: bigNumberToWrappedI80F48(insuranceIrFee),
349
+ protocolFixedFeeApr: bigNumberToWrappedI80F48(protocolFixedFeeApr),
350
+ protocolIrFee: bigNumberToWrappedI80F48(protocolIrFee),
351
+ protocolOriginationFee: bigNumberToWrappedI80F48(protocolOriginationFee),
352
+ };
353
+ }
354
+
355
+ export function newInterestRateConfigOpt({
356
+ optimalUtilizationRate,
357
+ plateauInterestRate,
358
+ maxInterestRate,
359
+ insuranceFeeFixedApr,
360
+ insuranceIrFee,
361
+ protocolFixedFeeApr,
362
+ protocolIrFee,
363
+ protocolOriginationFee,
364
+ }: {
365
+ optimalUtilizationRate: number | null;
366
+ plateauInterestRate: number | null;
367
+ maxInterestRate: number | null;
368
+ insuranceFeeFixedApr: number | null;
369
+ insuranceIrFee: number | null;
370
+ protocolFixedFeeApr: number | null;
371
+ protocolIrFee: number | null;
372
+ protocolOriginationFee: number | null;
373
+ }): InterestRateConfigOpt {
374
+ return {
375
+ optimalUtilizationRate: optimalUtilizationRate
376
+ ? bigNumberToWrappedI80F48(optimalUtilizationRate)
377
+ : null,
378
+ plateauInterestRate: plateauInterestRate
379
+ ? bigNumberToWrappedI80F48(plateauInterestRate)
380
+ : null,
381
+ maxInterestRate: maxInterestRate
382
+ ? bigNumberToWrappedI80F48(maxInterestRate)
383
+ : null,
384
+ insuranceFeeFixedApr: insuranceFeeFixedApr
385
+ ? bigNumberToWrappedI80F48(insuranceFeeFixedApr)
386
+ : null,
387
+ insuranceIrFee: insuranceIrFee
388
+ ? bigNumberToWrappedI80F48(insuranceIrFee)
389
+ : null,
390
+ protocolFixedFeeApr: protocolFixedFeeApr
391
+ ? bigNumberToWrappedI80F48(protocolFixedFeeApr)
392
+ : null,
393
+ protocolIrFee: protocolIrFee
394
+ ? bigNumberToWrappedI80F48(protocolIrFee)
395
+ : null,
396
+ protocolOriginationFee: protocolOriginationFee
397
+ ? bigNumberToWrappedI80F48(protocolOriginationFee)
398
+ : null,
399
+ };
400
+ }
401
+
402
+ export function newBankConfigCompact({
403
+ assetWeightInit,
404
+ assetWeightMaint,
405
+ liabilityWeightInit,
406
+ liabilityWeightMaint,
407
+ depositLimit,
408
+ borrowLimit,
409
+ riskTier,
410
+ totalAssetValueInitLimit,
411
+ operationalState,
412
+ assetTag,
413
+ oracleMaxAge,
414
+ }: {
415
+ assetWeightInit: number;
416
+ assetWeightMaint: number;
417
+ liabilityWeightInit: number;
418
+ liabilityWeightMaint: number;
419
+ depositLimit: BN;
420
+ borrowLimit: BN;
421
+ riskTier: RiskTier;
422
+ totalAssetValueInitLimit: BN;
423
+ operationalState: BankOperationalState;
424
+ assetTag: number;
425
+ oracleMaxAge: number;
426
+ }): BankConfigCompact {
427
+ const bc: BankConfigCompact = {
428
+ assetWeightInit: bigNumberToWrappedI80F48(assetWeightInit),
429
+ assetWeightMaint: bigNumberToWrappedI80F48(assetWeightMaint),
430
+ liabilityWeightInit: bigNumberToWrappedI80F48(liabilityWeightInit),
431
+ liabilityWeightMaint: bigNumberToWrappedI80F48(liabilityWeightMaint),
432
+ depositLimit,
433
+ borrowLimit,
434
+ riskTier,
435
+ totalAssetValueInitLimit,
436
+ operationalState,
437
+ assetTag,
438
+ oracleMaxAge,
439
+ };
440
+ return bc;
441
+ }
442
+
443
+ export function newClendAccountBalance({
444
+ active,
445
+ bankPk,
446
+ bankAssetTag,
447
+ assetShares,
448
+ liabilityShares,
449
+ emissionsOutstanding,
450
+ lastUpdate,
451
+ }: {
452
+ active: boolean;
453
+ bankPk: web3.PublicKey;
454
+ bankAssetTag: number;
455
+ assetShares: WrappedI80F48;
456
+ liabilityShares: WrappedI80F48;
457
+ emissionsOutstanding: WrappedI80F48;
458
+ lastUpdate: BN;
459
+ }): Balance {
460
+ return {
461
+ active,
462
+ bankPk,
463
+ bankAssetTag,
464
+ assetShares,
465
+ liabilityShares,
466
+ emissionsOutstanding,
467
+ lastUpdate,
468
+ };
469
+ }
470
+
471
+ // Token mints
472
+ export const JLP_MINT = new web3.PublicKey(
473
+ "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4",
474
+ );
475
+ export const USDC_MINT = new web3.PublicKey(
476
+ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
477
+ );
478
+
479
+ // Oracle addresses
480
+ export const JLP_ORACLE = new web3.PublicKey(
481
+ "2TTGSRSezqFzeLUH8JwRUbtN66XLLaymfYsWRTMjfiMw",
482
+ );
483
+ export const USDC_ORACLE = new web3.PublicKey(
484
+ "Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX",
485
+ );
486
+
487
+ // Token decimals
488
+ export const TOKEN_DECIMALS = {
489
+ USDC: 6,
490
+ JLP: 6,
491
+ };
492
+
493
+ // Token programs
494
+ export const TOKEN_PROGRAMS = {
495
+ USDC: new web3.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
496
+ JLP: new web3.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
497
+ };
498
+
499
+ // Map of mint addresses to their corresponding oracle addresses
500
+ export const ORACLE_MAP: Map<string, string> = new Map([
501
+ [JLP_MINT.toString(), JLP_ORACLE.toString()],
502
+ [USDC_MINT.toString(), USDC_ORACLE.toString()],
503
+ ]);
504
+
505
+ // Helper function to get oracle for a mint
506
+ export function getOracle(mint: web3.PublicKey): web3.PublicKey {
507
+ const oracleStr = ORACLE_MAP.get(mint.toString());
508
+ if (!oracleStr) {
509
+ throw new Error(`No oracle found for mint ${mint.toString()}`);
510
+ }
511
+ return new web3.PublicKey(oracleStr);
512
+ }