@carrot-protocol/clend-vaults-rpc 0.0.2 → 0.0.3-pub2-dev-be4bd59

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/math.ts DELETED
@@ -1,103 +0,0 @@
1
- import { LendingAccount } from "@carrot-protocol/clend-rpc";
2
- import { BN } from "@coral-xyz/anchor";
3
-
4
- /**
5
- * Computes the net asset value (NAV) per share based on vault equity and share supply.
6
- */
7
- export function calculateVaultNav(
8
- equity: number,
9
- sharesSupplyUi: number,
10
- ): number {
11
- if (equity === 0 || sharesSupplyUi === 0) {
12
- return 0;
13
- }
14
- return equity / sharesSupplyUi;
15
- }
16
-
17
- /**
18
- * Calculates the USD value earned from a given number of shares and NAV.
19
- */
20
- export function usdEarned(sharesUi: number, nav: number): number {
21
- return sharesUi * nav;
22
- }
23
-
24
- /**
25
- * Convert a UI number to a token amount BN
26
- * @param uiAmount Amount in UI format (e.g., 1.5 USDC)
27
- * @param decimals Token decimals
28
- * @returns BN representing the token amount in smallest units (lamports)
29
- */
30
- export function uiToAmount(uiAmount: number, decimals: number): BN {
31
- // floor to avoid over-minting
32
- return new BN(Math.floor(uiAmount * 10 ** decimals));
33
- }
34
-
35
- /**
36
- * Convert a token amount BN to a UI number
37
- * @param amount BN representing the token amount in smallest units (lamports)
38
- * @param decimals Token decimals
39
- * @returns Number in UI format (e.g., 1.5 USDC)
40
- */
41
- export function amountToUi(amount: BN, decimals: number): number {
42
- return amount.toNumber() / 10 ** decimals;
43
- }
44
-
45
- export function calculateLendingAccountEquity(
46
- lendingAccount: LendingAccount,
47
- ): number {
48
- let accountEquity = 0;
49
- for (const balance of lendingAccount.balances) {
50
- accountEquity =
51
- accountEquity + (balance.assetValue - balance.liabilityValue);
52
- }
53
- return accountEquity;
54
- }
55
-
56
- /**
57
- * Converts a token amount to its USD value based on price and decimals.
58
- */
59
- export function amountToUsd(
60
- amount: BN,
61
- decimals: number,
62
- price: number,
63
- ): number {
64
- return amountToUi(amount, decimals) * price;
65
- }
66
-
67
- /**
68
- * Converts a USD amount to its token representation based on price and decimals.
69
- */
70
- export function usdToAmount(
71
- usdAmount: number,
72
- decimals: number,
73
- price: number,
74
- ): BN {
75
- return uiToAmount(usdAmount / price, decimals);
76
- }
77
-
78
- /**
79
- * Converts shares to asset tokens.
80
- */
81
- export function convertSharesToAsset(
82
- vaultNav: number,
83
- sharesAmountUi: number,
84
- assetDecimals: number,
85
- assetPrice: number,
86
- ): BN {
87
- const sharesUsd = usdEarned(sharesAmountUi, vaultNav);
88
-
89
- const tokenAmount = usdToAmount(sharesUsd, assetDecimals, assetPrice);
90
-
91
- return tokenAmount;
92
- }
93
-
94
- export function convertAssetToShares(
95
- vaultNav: number,
96
- assetAmount: BN,
97
- assetDecimals: number,
98
- sharesDecimals: number,
99
- assetPrice: number,
100
- ): BN {
101
- const assetUsd = amountToUsd(assetAmount, assetDecimals, assetPrice);
102
- return usdToAmount(assetUsd, sharesDecimals, vaultNav);
103
- }
package/src/program.ts DELETED
@@ -1,551 +0,0 @@
1
- // instructions.ts
2
- import { AnchorProvider, BN, Program, web3 } from "@coral-xyz/anchor";
3
- import {
4
- AuthorityType,
5
- createAssociatedTokenAccountIdempotentInstruction,
6
- createSetAuthorityInstruction,
7
- getAssociatedTokenAddressSync,
8
- TOKEN_2022_PROGRAM_ID,
9
- } from "@solana/spl-token";
10
- import { getVaultPda, JUPITER_SWAP_PROGRAM_ID } from "./addresses";
11
- import { type ClendVaults } from "./idl/clend_vaults";
12
- import idl from "./idl/clend_vaults.json";
13
- import { Vault } from "./state";
14
- import {
15
- CLEND_PROGRAM_ID,
16
- getBankLiquidityVaultAuthorityPda,
17
- getBankLiquidityVaultPda,
18
- getBankPda,
19
- } from "@carrot-protocol/clend-rpc";
20
- import { getDummyProvider } from "./utils";
21
-
22
- export class ClendVaultsProgram {
23
- readonly program: Program<ClendVaults>;
24
-
25
- constructor(provider?: AnchorProvider) {
26
- if (!provider) {
27
- provider = getDummyProvider();
28
- }
29
- this.program = new Program<ClendVaults>(idl, provider);
30
- }
31
-
32
- async initVault(
33
- vaultSharesMint: web3.PublicKey,
34
- manager: web3.PublicKey,
35
- managementFeeBps: number,
36
- ): Promise<{ vault: web3.PublicKey; ixns: web3.TransactionInstruction[] }> {
37
- const vault = getVaultPda(vaultSharesMint);
38
-
39
- const transferMintAuthorityIx = createSetAuthorityInstruction(
40
- vaultSharesMint,
41
- manager,
42
- AuthorityType.MintTokens,
43
- vault,
44
- [],
45
- TOKEN_2022_PROGRAM_ID,
46
- );
47
-
48
- const args = {
49
- managementFeeBps,
50
- };
51
-
52
- const ix = await this.program.methods
53
- .initVault(args)
54
- .accountsStrict({
55
- manager,
56
- payer: manager,
57
- vault,
58
- vaultShares: vaultSharesMint,
59
- systemProgram: web3.SystemProgram.programId,
60
- })
61
- .instruction();
62
-
63
- return { vault, ixns: [transferMintAuthorityIx, ix] };
64
- }
65
-
66
- async addAsset(
67
- vault: web3.PublicKey,
68
- manager: web3.PublicKey,
69
- assetMint: web3.PublicKey,
70
- assetOracle: web3.PublicKey,
71
- assetTokenProgram: web3.PublicKey,
72
- addAssetArgs: AddAssetArgs,
73
- ): Promise<web3.TransactionInstruction[]> {
74
- const vaultAssetReserve = getAssociatedTokenAddressSync(
75
- assetMint,
76
- vault,
77
- true,
78
- assetTokenProgram,
79
- );
80
-
81
- // Create ATA idempotently
82
- const createVaultReserveIx =
83
- createAssociatedTokenAccountIdempotentInstruction(
84
- manager, // payer
85
- vaultAssetReserve,
86
- vault,
87
- assetMint,
88
- assetTokenProgram,
89
- );
90
-
91
- const addAssetIx = await this.program.methods
92
- .addAsset(addAssetArgs)
93
- .accountsStrict({
94
- vault,
95
- assetMint,
96
- assetOracle,
97
- vaultAssetReserve,
98
- manager,
99
- tokenProgram: assetTokenProgram,
100
- systemProgram: web3.SystemProgram.programId,
101
- })
102
- .instruction();
103
-
104
- return [createVaultReserveIx, addAssetIx];
105
- }
106
-
107
- async addClendAccount(
108
- vault: web3.PublicKey,
109
- manager: web3.PublicKey,
110
- clendGroup: web3.PublicKey,
111
- clendAccount: web3.Keypair,
112
- ): Promise<web3.TransactionInstruction[]> {
113
- const ix = await this.program.methods
114
- .addClendAccount()
115
- .accountsStrict({
116
- vault,
117
- clendAccount: clendAccount.publicKey,
118
- clendGroup,
119
- manager,
120
- clendProgram: CLEND_PROGRAM_ID,
121
- systemProgram: web3.SystemProgram.programId,
122
- })
123
- .instruction();
124
-
125
- return [ix];
126
- }
127
-
128
- async updateVaultManager(
129
- vault: web3.PublicKey,
130
- currentManager: web3.PublicKey,
131
- newManager: web3.PublicKey,
132
- ): Promise<web3.TransactionInstruction[]> {
133
- const ix = await this.program.methods
134
- .updateVaultManager()
135
- .accountsStrict({
136
- vault,
137
- newManager,
138
- manager: currentManager,
139
- })
140
- .instruction();
141
- return [ix];
142
- }
143
-
144
- // -----------------
145
- // Shares ops
146
- // -----------------
147
-
148
- async issue(
149
- vault: web3.PublicKey,
150
- sharesMint: web3.PublicKey,
151
- user: web3.PublicKey,
152
- assetMint: web3.PublicKey,
153
- assetOracle: web3.PublicKey,
154
- amount: BN | number,
155
- assetTokenProgram: web3.PublicKey,
156
- sharesTokenProgram: web3.PublicKey,
157
- remainingAccounts: web3.AccountMeta[],
158
- ): Promise<web3.TransactionInstruction[]> {
159
- const amt = new BN(amount as any);
160
-
161
- // Vault reserve (owner is vault PDA)
162
- const vaultAssetReserve = getAssociatedTokenAddressSync(
163
- assetMint,
164
- vault,
165
- true,
166
- assetTokenProgram,
167
- );
168
-
169
- // User ATAs (owner is user)
170
- const userAssetAccount = getAssociatedTokenAddressSync(
171
- assetMint,
172
- user,
173
- true,
174
- assetTokenProgram,
175
- );
176
- const userSharesAccount = getAssociatedTokenAddressSync(
177
- sharesMint,
178
- user,
179
- true,
180
- sharesTokenProgram,
181
- );
182
-
183
- // Ensure user's ATAs exist (idempotent)
184
- const createUserAssetIx = createAssociatedTokenAccountIdempotentInstruction(
185
- user,
186
- userAssetAccount,
187
- user,
188
- assetMint,
189
- assetTokenProgram,
190
- );
191
- const createUserSharesIx =
192
- createAssociatedTokenAccountIdempotentInstruction(
193
- user,
194
- userSharesAccount,
195
- user,
196
- sharesMint,
197
- sharesTokenProgram,
198
- );
199
-
200
- const ix = await this.program.methods
201
- .issue({ amount: amt })
202
- .accountsStrict({
203
- vault,
204
- shares: sharesMint,
205
- assetMint,
206
- assetOracle,
207
- vaultAssetReserve,
208
- userAssetAccount,
209
- userSharesAccount,
210
- user,
211
- assetTokenProgram,
212
- sharesTokenProgram,
213
- systemProgram: web3.SystemProgram.programId,
214
- })
215
- .remainingAccounts(remainingAccounts)
216
- .instruction();
217
-
218
- return [createUserAssetIx, createUserSharesIx, ix];
219
- }
220
-
221
- async redeem(
222
- vault: web3.PublicKey,
223
- sharesMint: web3.PublicKey,
224
- user: web3.PublicKey,
225
- assetMint: web3.PublicKey,
226
- assetOracle: web3.PublicKey,
227
- amount: BN,
228
- assetTokenProgram: web3.PublicKey,
229
- sharesTokenProgram: web3.PublicKey,
230
- remainingAccounts: web3.AccountMeta[],
231
- ): Promise<web3.TransactionInstruction[]> {
232
- const amt = new BN(amount as any);
233
-
234
- const vaultAssetReserve = getAssociatedTokenAddressSync(
235
- assetMint,
236
- vault,
237
- true,
238
- assetTokenProgram,
239
- );
240
- const userAssetAccount = getAssociatedTokenAddressSync(
241
- assetMint,
242
- user,
243
- true,
244
- assetTokenProgram,
245
- );
246
- const userSharesAccount = getAssociatedTokenAddressSync(
247
- sharesMint,
248
- user,
249
- true,
250
- sharesTokenProgram,
251
- );
252
-
253
- // Make sure the user asset ATA exists
254
- const createUserAssetIx = createAssociatedTokenAccountIdempotentInstruction(
255
- user,
256
- userAssetAccount,
257
- user,
258
- assetMint,
259
- assetTokenProgram,
260
- );
261
-
262
- const ix = await this.program.methods
263
- .redeem({ amount: amt })
264
- .accountsStrict({
265
- vault,
266
- shares: sharesMint,
267
- assetMint,
268
- assetOracle,
269
- vaultAssetReserve,
270
- userAssetAccount,
271
- userSharesAccount,
272
- user,
273
- assetTokenProgram,
274
- sharesTokenProgram,
275
- systemProgram: web3.SystemProgram.programId,
276
- })
277
- .remainingAccounts(remainingAccounts)
278
- .instruction();
279
-
280
- return [createUserAssetIx, ix];
281
- }
282
-
283
- // -----------------
284
- // Clend-account ops (builders; vault PDA signs via seeds)
285
- // -----------------
286
-
287
- async clendAccountDeposit(
288
- vault: web3.PublicKey,
289
- vaultManager: web3.PublicKey,
290
- clendGroup: web3.PublicKey,
291
- clendAccount: web3.PublicKey,
292
- assetMint: web3.PublicKey,
293
- assetMintTokenProgram: web3.PublicKey,
294
- amount: BN,
295
- vaultReserve: web3.PublicKey,
296
- remainingAccounts: web3.AccountMeta[],
297
- ): Promise<web3.TransactionInstruction[]> {
298
- const bank = getBankPda(clendGroup, assetMint);
299
- const bankLiquidityVault = getBankLiquidityVaultPda(bank);
300
-
301
- const ix = await this.program.methods
302
- .clendAccountDeposit({ amount })
303
- .accountsStrict({
304
- vault,
305
- assetMint,
306
- clendGroup,
307
- clendAccount,
308
- bank,
309
- vaultReserve,
310
- bankLiquidityVault,
311
- manager: vaultManager,
312
- tokenProgram: assetMintTokenProgram,
313
- clendProgram: CLEND_PROGRAM_ID,
314
- systemProgram: web3.SystemProgram.programId,
315
- })
316
- .remainingAccounts(remainingAccounts)
317
- .instruction();
318
-
319
- return [ix];
320
- }
321
-
322
- async clendAccountWithdraw(
323
- vault: web3.PublicKey,
324
- vaultManager: web3.PublicKey,
325
- clendGroup: web3.PublicKey,
326
- clendAccount: web3.PublicKey,
327
- assetMint: web3.PublicKey,
328
- assetMintTokenProgram: web3.PublicKey,
329
- amount: BN,
330
- remainingAccounts: web3.AccountMeta[],
331
- ): Promise<web3.TransactionInstruction[]> {
332
- const bank = getBankPda(clendGroup, assetMint);
333
- const bankLiquidityVault = getBankLiquidityVaultPda(bank);
334
- const bankLiquidityVaultAuthority = getBankLiquidityVaultAuthorityPda(bank);
335
-
336
- const destinationTokenAccount = getAssociatedTokenAddressSync(
337
- assetMint,
338
- vault,
339
- true,
340
- assetMintTokenProgram,
341
- );
342
-
343
- const ix = await this.program.methods
344
- .clendAccountWithdraw({ amount })
345
- .accountsStrict({
346
- vault,
347
- assetMint,
348
- clendGroup,
349
- clendAccount,
350
- bank,
351
- destinationTokenAccount,
352
- bankLiquidityVaultAuthority,
353
- bankLiquidityVault,
354
- manager: vaultManager,
355
- tokenProgram: assetMintTokenProgram,
356
- clendProgram: CLEND_PROGRAM_ID,
357
- systemProgram: web3.SystemProgram.programId,
358
- })
359
- .remainingAccounts(remainingAccounts)
360
- .instruction();
361
-
362
- return [ix];
363
- }
364
-
365
- async clendAccountRepay(
366
- vault: web3.PublicKey,
367
- vaultManager: web3.PublicKey,
368
- clendGroup: web3.PublicKey,
369
- clendAccount: web3.PublicKey,
370
- assetMint: web3.PublicKey,
371
- mintTokenProgram: web3.PublicKey,
372
- amount: BN,
373
- remainingAccounts: web3.AccountMeta[],
374
- ): Promise<web3.TransactionInstruction[]> {
375
- const bank = getBankPda(clendGroup, assetMint);
376
- const bankLiquidityVault = getBankLiquidityVaultPda(bank);
377
-
378
- const signerTokenAccount = getAssociatedTokenAddressSync(
379
- assetMint,
380
- vault,
381
- true,
382
- mintTokenProgram,
383
- );
384
-
385
- const ix = await this.program.methods
386
- .clendAccountRepay({ amount: new BN(amount as any) })
387
- .accountsStrict({
388
- vault,
389
- assetMint,
390
- clendGroup,
391
- clendAccount,
392
- bank,
393
- signerTokenAccount,
394
- bankLiquidityVault,
395
- manager: vaultManager,
396
- tokenProgram: mintTokenProgram,
397
- clendProgram: CLEND_PROGRAM_ID,
398
- systemProgram: web3.SystemProgram.programId,
399
- })
400
- .remainingAccounts(remainingAccounts)
401
- .instruction();
402
-
403
- return [ix];
404
- }
405
-
406
- async clendAccountBorrow(
407
- vault: web3.PublicKey,
408
- vaultManager: web3.PublicKey,
409
- clendGroup: web3.PublicKey,
410
- clendAccount: web3.PublicKey,
411
- assetMint: web3.PublicKey,
412
- mintTokenProgram: web3.PublicKey,
413
- amount: BN,
414
- remainingAccounts: web3.AccountMeta[],
415
- ): Promise<web3.TransactionInstruction[]> {
416
- const bank = getBankPda(clendGroup, assetMint);
417
- const bankLiquidityVault = getBankLiquidityVaultPda(bank);
418
- const bankLiquidityVaultAuthority = getBankLiquidityVaultAuthorityPda(bank);
419
-
420
- const destinationTokenAccount = getAssociatedTokenAddressSync(
421
- assetMint,
422
- vault,
423
- true,
424
- mintTokenProgram,
425
- );
426
-
427
- const ix = await this.program.methods
428
- .clendAccountBorrow({ amount })
429
- .accountsStrict({
430
- vault,
431
- assetMint,
432
- clendGroup,
433
- clendAccount,
434
- bank,
435
- destinationTokenAccount,
436
- bankLiquidityVaultAuthority,
437
- bankLiquidityVault,
438
- manager: vaultManager,
439
- tokenProgram: mintTokenProgram,
440
- clendProgram: CLEND_PROGRAM_ID,
441
- systemProgram: web3.SystemProgram.programId,
442
- })
443
- .remainingAccounts(remainingAccounts)
444
- .instruction();
445
-
446
- return [ix];
447
- }
448
-
449
- async clendAccountClaimEmissions(
450
- vault: web3.PublicKey,
451
- vaultManager: web3.PublicKey,
452
- clendGroup: web3.PublicKey,
453
- clendAccount: web3.PublicKey,
454
- bank: web3.PublicKey,
455
- assetMint: web3.PublicKey,
456
- emissionsMint: web3.PublicKey,
457
- destinationAccount: web3.PublicKey, // vault-owned ATA for emissions mint
458
- mintTokenProgram: web3.PublicKey,
459
- emissionsVault: web3.PublicKey,
460
- emissionsAuthority: web3.PublicKey,
461
- clendProgramId: web3.PublicKey,
462
- ): Promise<web3.TransactionInstruction[]> {
463
- const ix = await this.program.methods
464
- .clendAccountClaimEmissions()
465
- .accountsStrict({
466
- vault,
467
- assetMint,
468
- clendGroup,
469
- clendAccount,
470
- bank,
471
- emissionsMint,
472
- emissionsAuth: emissionsAuthority,
473
- emissionsVault,
474
- destinationAccount,
475
- manager: vaultManager,
476
- tokenProgram: mintTokenProgram,
477
- clendProgram: clendProgramId,
478
- systemProgram: web3.SystemProgram.programId,
479
- })
480
- .instruction();
481
-
482
- return [ix];
483
- }
484
-
485
- async swap(
486
- vault: web3.PublicKey,
487
- vaultManager: web3.PublicKey,
488
- assetInMint: web3.PublicKey,
489
- assetOutMint: web3.PublicKey,
490
- vaultAssetInReserve: web3.PublicKey,
491
- vaultAssetOutReserve: web3.PublicKey,
492
- swapData: Buffer,
493
- remainingAccounts: web3.AccountMeta[],
494
- swapProgram: web3.PublicKey = JUPITER_SWAP_PROGRAM_ID,
495
- ): Promise<web3.TransactionInstruction[]> {
496
- const ix = await this.program.methods
497
- .swap({ swapData: Buffer.from(swapData) })
498
- .accountsStrict({
499
- vault,
500
- assetInMint,
501
- assetOutMint,
502
- vaultAssetInReserve,
503
- vaultAssetOutReserve,
504
- manager: vaultManager,
505
- swapProgram,
506
- })
507
- .remainingAccounts(remainingAccounts)
508
- .instruction();
509
-
510
- return [ix];
511
- }
512
-
513
- async distributeFees(
514
- vault: web3.PublicKey,
515
- manager: web3.PublicKey,
516
- shares: web3.PublicKey,
517
- sharesDestinationOwner: web3.PublicKey,
518
- ): Promise<web3.TransactionInstruction[]> {
519
- const sharesDestination = getAssociatedTokenAddressSync(
520
- shares,
521
- sharesDestinationOwner,
522
- true,
523
- TOKEN_2022_PROGRAM_ID,
524
- );
525
- const createSharesDestinationIx =
526
- createAssociatedTokenAccountIdempotentInstruction(
527
- manager,
528
- sharesDestination,
529
- sharesDestinationOwner,
530
- shares,
531
- TOKEN_2022_PROGRAM_ID,
532
- );
533
- const ix = await this.program.methods
534
- .distributeFees()
535
- .accountsStrict({
536
- vault,
537
- manager,
538
- shares,
539
- sharesDestination,
540
- tokenProgram: TOKEN_2022_PROGRAM_ID,
541
- })
542
- .instruction();
543
-
544
- return [createSharesDestinationIx, ix];
545
- }
546
- }
547
-
548
- export interface AddAssetArgs {
549
- issueFeeBps: number;
550
- redemptionFeeBps: number;
551
- }