@elmntl/jlpd-sdk 0.2.0 → 0.13.5

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 (115) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +185 -404
  3. package/dist/common/ata.d.ts +26 -0
  4. package/dist/common/ata.js +48 -0
  5. package/dist/common/buffer.d.ts +15 -0
  6. package/dist/common/buffer.js +118 -0
  7. package/dist/common/connection.d.ts +13 -0
  8. package/dist/common/connection.js +2 -0
  9. package/dist/common/constants.d.ts +14 -0
  10. package/dist/common/constants.js +31 -0
  11. package/dist/common/index.d.ts +6 -0
  12. package/dist/common/index.js +28 -0
  13. package/dist/common/strategy-interface.d.ts +59 -0
  14. package/dist/common/strategy-interface.js +42 -0
  15. package/dist/elemental-lend/accounts.d.ts +103 -0
  16. package/dist/elemental-lend/accounts.js +354 -0
  17. package/dist/elemental-lend/constants.d.ts +25 -0
  18. package/dist/elemental-lend/constants.js +48 -0
  19. package/dist/elemental-lend/index.d.ts +8 -0
  20. package/dist/elemental-lend/index.js +24 -0
  21. package/dist/elemental-lend/instructions.d.ts +104 -0
  22. package/dist/elemental-lend/instructions.js +266 -0
  23. package/dist/elemental-lend/jupiter-lend.d.ts +91 -0
  24. package/dist/elemental-lend/jupiter-lend.js +189 -0
  25. package/dist/elemental-lend/kamino-vault.d.ts +173 -0
  26. package/dist/elemental-lend/kamino-vault.js +483 -0
  27. package/dist/elemental-lend/pda.d.ts +12 -0
  28. package/dist/elemental-lend/pda.js +24 -0
  29. package/dist/elemental-lend/protocol-actions.d.ts +56 -0
  30. package/dist/elemental-lend/protocol-actions.js +244 -0
  31. package/dist/elemental-lend/types.d.ts +113 -0
  32. package/dist/elemental-lend/types.js +2 -0
  33. package/dist/elemental-lend-v2/accounts.d.ts +14 -0
  34. package/dist/elemental-lend-v2/accounts.js +136 -0
  35. package/dist/elemental-lend-v2/adapters.d.ts +22 -0
  36. package/dist/elemental-lend-v2/adapters.js +50 -0
  37. package/dist/elemental-lend-v2/constants.d.ts +48 -0
  38. package/dist/elemental-lend-v2/constants.js +104 -0
  39. package/dist/elemental-lend-v2/index.d.ts +8 -0
  40. package/dist/elemental-lend-v2/index.js +24 -0
  41. package/dist/elemental-lend-v2/instructions.d.ts +96 -0
  42. package/dist/elemental-lend-v2/instructions.js +190 -0
  43. package/dist/elemental-lend-v2/lut.d.ts +20 -0
  44. package/dist/elemental-lend-v2/lut.js +65 -0
  45. package/dist/elemental-lend-v2/pda.d.ts +9 -0
  46. package/dist/elemental-lend-v2/pda.js +27 -0
  47. package/dist/elemental-lend-v2/types.d.ts +105 -0
  48. package/dist/elemental-lend-v2/types.js +2 -0
  49. package/dist/elemental-lend-v2/update-aum.d.ts +29 -0
  50. package/dist/elemental-lend-v2/update-aum.js +82 -0
  51. package/dist/index.d.ts +5 -4199
  52. package/dist/index.js +37 -5187
  53. package/dist/jlpd-strategy/accounts.d.ts +83 -0
  54. package/dist/jlpd-strategy/accounts.js +216 -0
  55. package/dist/jlpd-strategy/adapter.d.ts +81 -0
  56. package/dist/jlpd-strategy/adapter.js +118 -0
  57. package/dist/jlpd-strategy/base-to-base-swap.d.ts +74 -0
  58. package/dist/jlpd-strategy/base-to-base-swap.js +205 -0
  59. package/dist/jlpd-strategy/constants.d.ts +127 -0
  60. package/dist/jlpd-strategy/constants.js +174 -0
  61. package/dist/jlpd-strategy/fluid-view.d.ts +199 -0
  62. package/dist/jlpd-strategy/fluid-view.js +799 -0
  63. package/dist/jlpd-strategy/hedge-derived.d.ts +135 -0
  64. package/dist/jlpd-strategy/hedge-derived.js +231 -0
  65. package/dist/jlpd-strategy/hedge-instructions.d.ts +206 -0
  66. package/dist/jlpd-strategy/hedge-instructions.js +296 -0
  67. package/dist/jlpd-strategy/hedge-state.d.ts +88 -0
  68. package/dist/jlpd-strategy/hedge-state.js +110 -0
  69. package/dist/jlpd-strategy/index.d.ts +17 -0
  70. package/dist/jlpd-strategy/index.js +33 -0
  71. package/dist/jlpd-strategy/instructions.d.ts +159 -0
  72. package/dist/jlpd-strategy/instructions.js +234 -0
  73. package/dist/jlpd-strategy/jlp-borrow.d.ts +63 -0
  74. package/dist/jlpd-strategy/jlp-borrow.js +87 -0
  75. package/dist/jlpd-strategy/jlp-data.d.ts +166 -0
  76. package/dist/jlpd-strategy/jlp-data.js +611 -0
  77. package/dist/jlpd-strategy/jupusd-earn.d.ts +90 -0
  78. package/dist/jlpd-strategy/jupusd-earn.js +166 -0
  79. package/dist/jlpd-strategy/live-jlp-price.d.ts +46 -0
  80. package/dist/jlpd-strategy/live-jlp-price.js +267 -0
  81. package/dist/jlpd-strategy/pda.d.ts +13 -0
  82. package/dist/jlpd-strategy/pda.js +28 -0
  83. package/dist/jlpd-strategy/settle-yield.d.ts +45 -0
  84. package/dist/jlpd-strategy/settle-yield.js +113 -0
  85. package/dist/jlpd-strategy/swap-jlp.d.ts +198 -0
  86. package/dist/jlpd-strategy/swap-jlp.js +586 -0
  87. package/dist/jlpd-strategy/types.d.ts +101 -0
  88. package/dist/jlpd-strategy/types.js +29 -0
  89. package/dist/p-stv-core/accounts.d.ts +152 -0
  90. package/dist/p-stv-core/accounts.js +407 -0
  91. package/dist/p-stv-core/constants.d.ts +138 -0
  92. package/dist/p-stv-core/constants.js +181 -0
  93. package/dist/p-stv-core/events.d.ts +7 -0
  94. package/dist/p-stv-core/events.js +246 -0
  95. package/dist/p-stv-core/index.d.ts +11 -0
  96. package/dist/p-stv-core/index.js +27 -0
  97. package/dist/p-stv-core/instructions.d.ts +637 -0
  98. package/dist/p-stv-core/instructions.js +670 -0
  99. package/dist/p-stv-core/lut.d.ts +41 -0
  100. package/dist/p-stv-core/lut.js +81 -0
  101. package/dist/p-stv-core/pda.d.ts +30 -0
  102. package/dist/p-stv-core/pda.js +65 -0
  103. package/dist/p-stv-core/prices.d.ts +20 -0
  104. package/dist/p-stv-core/prices.js +77 -0
  105. package/dist/p-stv-core/remaining-accounts.d.ts +107 -0
  106. package/dist/p-stv-core/remaining-accounts.js +326 -0
  107. package/dist/p-stv-core/send-tx.d.ts +72 -0
  108. package/dist/p-stv-core/send-tx.js +290 -0
  109. package/dist/p-stv-core/sol-wrap.d.ts +34 -0
  110. package/dist/p-stv-core/sol-wrap.js +74 -0
  111. package/dist/p-stv-core/types.d.ts +361 -0
  112. package/dist/p-stv-core/types.js +2 -0
  113. package/package.json +56 -15
  114. package/dist/index.d.mts +0 -4199
  115. package/dist/index.mjs +0 -5090
package/README.md CHANGED
@@ -1,469 +1,250 @@
1
- # JLP.D SDK
1
+ # @elmntl/jlpd-sdk
2
2
 
3
- SDK for interacting with the JLP.D (JLP Deconstructed) protocol on Solana.
3
+ TypeScript SDK for the **Elemental Vaults** on-chain stack. Wraps three Solana programs through one consistent surface so frontends, indexers, and back-end services don't need to hand-roll discriminators, PDA derivation, or account layouts.
4
4
 
5
- ## Installation
6
-
7
- ```bash
8
- # Using npm
9
- npm install git+https://github.com/elementalfund/jlpd-sdk.git
10
-
11
- # Using yarn
12
- yarn add git+https://github.com/elementalfund/jlpd-sdk.git
13
5
  ```
14
-
15
- Or add directly to `package.json`:
16
- ```json
17
- {
18
- "dependencies": {
19
- "jlpd-sdk": "git+https://github.com/elementalfund/jlpd-sdk.git"
20
- }
21
- }
22
- ```
23
-
24
- ### Peer Dependencies
25
-
26
- | Package | Version |
27
- |---|---|
28
- | `@coral-xyz/anchor` | `^0.32.1` |
29
- | `@solana/web3.js` | `^1.95.0` |
30
- | `@solana/spl-token` | `^0.4.0` |
31
-
32
- ## Quick Start
33
-
34
- ```typescript
35
- import { Connection } from "@solana/web3.js";
36
- import { JlpdClient } from "jlpd-sdk";
37
-
38
- // Connect to Solana mainnet
39
- const connection = new Connection("https://api.mainnet-beta.solana.com");
40
- const client = JlpdClient.mainnet(connection);
6
+ @elmntl/jlpd-sdk
7
+ ├── /common shared types, buffer helpers, connection type, discriminators
8
+ ├── /p-stv-core vault management — deposits, withdraws, epochs, fees (level N)
9
+ ├── /elemental-lend idle-base lending sweep into Kamino + Jupiter Lend Earn (level N − 1)
10
+ └── /jlpd-strategy JLP-Deconstructed yield strategy + lend-adapter wiring (level N + 1 / N + 2)
41
11
  ```
42
12
 
43
- ## Architecture
13
+ ## At a glance
44
14
 
45
- The SDK uses the Anchor IDL (`@coral-xyz/anchor` 0.32.1) for instruction serialization. All instruction builders call `program.methods.<instruction>().accounts({}).instruction()` under the hood, which ensures correct serialization from the on-chain IDL.
15
+ | Module | Wraps program | What it gives you |
16
+ | ---------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
+ | `@elmntl/jlpd-sdk/p-stv-core` | `PSTVH77GiPqA3msXmpjAyUXdh3MytK37GCPbPzWu3Rc` | STV / GlobalConfig / WithdrawRequest / ManagerRole accounts; all 14 instruction builders (`createDepositIx`, `createClaimWithdrawIx`, `createProcessEpochIx`, `createMigrateLendIx`, …); event decoders (18 event types); the `sendSmartTx` smart sender (auto CU sim, priority fee, LUT merge); wSOL wrap/unwrap helpers; USD price fetcher |
18
+ | `@elmntl/jlpd-sdk/elemental-lend` | `EHaGVh7p6xSxZsq4CcEEZhnV5adDvWg1gS1Rc5rLiBpC` | StrategyState / StvPosition / ManagerRole accounts; CPI + protocol instruction builders; Kamino kVault and Jupiter Lend Earn account-resolution helpers; auto-route / auto-unroute account builders for sweep flows |
19
+ | `@elmntl/jlpd-sdk/jlpd-strategy` | `GXqt4ZH2UUBsLWwMNJiZMXza3q7xEGChfW8XjVRjLxr5` | JlpdConfig / per-asset StrategyState / StvPosition; CPI + rebalance instruction builders (`createSwapJlpIx`, `createSettleYieldIx`, `createDepositToAdapterIx`, …); Jupiter swap quote / instruction fetchers; on-chain JLP price + custody readers |
20
+ | `@elmntl/jlpd-sdk/common` | (no program) | Buffer reads with bounds checks, ATA derivation, the canonical `SolanaConnection` structural type, and the `StrategyStateHeader` / `StvPosition` interfaces shared across the two strategy programs |
46
21
 
47
- The `JlpdClient` exposes an Anchor `Program` instance for advanced use:
22
+ ## Module layout
48
23
 
49
- ```typescript
50
- // Access the typed Anchor program directly
51
- const program = client.program;
24
+ Every program-specific module follows the **same file shape**, so you only have to learn the pattern once:
52
25
 
53
- // Build instructions manually if needed
54
- const ix = await program.methods
55
- .deposit(new BN(1_000_000_000))
56
- .accounts({ user: walletPublicKey, jlpVault: client.vaultPda, /* ... */ })
57
- .instruction();
58
26
  ```
27
+ <module>/
28
+ ├── constants.ts program ID, seeds, instruction discriminators, sizes, flags
29
+ ├── pda.ts findXxxPda() helpers — pure synchronous PDA derivation
30
+ ├── types.ts account interfaces + event types
31
+ ├── accounts.ts deserializeXxx() + fetchXxx() readers + GPA queries
32
+ ├── instructions.ts createXxxIx() instruction builders
33
+ ├── events.ts event decoders (p-stv-core: 1-byte disc; Anchor: 8-byte)
34
+ └── (module-specific files)
59
35
 
60
- You can also create a standalone program instance:
61
-
62
- ```typescript
63
- import { createProgram } from "jlpd-sdk";
64
- import type { JlpDProgram } from "jlpd-sdk";
65
-
66
- const program = createProgram(connection);
36
+ Module-specific files:
37
+ p-stv-core: remaining-accounts.ts, send-tx.ts, sol-wrap.ts, prices.ts
38
+ elemental-lend: kamino-vault.ts, jupiter-lend.ts, protocol-actions.ts
39
+ jlpd-strategy: swap-jlp.ts, settle-yield.ts, jlp-data.ts,
40
+ jlp-borrow.ts, jupusd-earn.ts, adapter.ts
67
41
  ```
68
42
 
69
- ## Available Pools
43
+ Naming conventions hold across modules:
70
44
 
71
- | Pool | Description |
72
- | ---------- | ----------- |
73
- | `"SOL"` | Solana |
74
- | `"USDC"` | USD Coin |
75
- | `"JupUSD"` | Jupiter USD |
76
- | `"BTC"` | Bitcoin |
77
- | `"ETH"` | Ethereum |
45
+ | Pattern | Returns | Side effects |
46
+ | --------------- | ------------------------- | ------------ |
47
+ | `findXxxPda` | `[PublicKey, number]` | none |
48
+ | `deserializeXxx`| typed account | none |
49
+ | `fetchXxx` | typed account | one RPC call |
50
+ | `createXxxIx` | `TransactionInstruction` | none |
51
+ | `buildXxx*` | helper objects | none |
78
52
 
79
- ---
53
+ `build*` is reserved for helpers that produce ephemeral data (remaining accounts, batched instruction lists). Anything that returns a wire-ready instruction is named `createXxxIx`.
80
54
 
81
- ## User Operations
55
+ ## Naming exceptions worth knowing
82
56
 
83
- ### Deposit
57
+ Each program has its own `ManagerRole` PDA scoped to a different anchor account. To prevent same-named imports from shadowing each other, the helpers carry a per-program prefix:
84
58
 
85
- Deposit tokens and receive vault shares (jvX tokens).
59
+ | Program | Function | PDA seeds |
60
+ | --------------- | ------------------------- | ---------------------------------------- |
61
+ | p-stv-core | `findStvManagerRolePda` | `["manager", stv, manager]` |
62
+ | elemental-lend | `findLendManagerRolePda` | `["manager", strategy_state, manager]` |
63
+ | jlpd-strategy | `findJlpdManagerRolePda` | `["manager", config, manager]` |
86
64
 
87
- ```typescript
88
- import { BN } from "@coral-xyz/anchor";
65
+ ## Cross-cutting design
89
66
 
90
- const pool = client.pool("SOL");
67
+ ### `SolanaConnection` (structural type)
91
68
 
92
- const tx = await pool.deposit({
93
- user: walletPublicKey,
94
- amount: new BN(1_000_000_000), // 1 SOL (9 decimals)
95
- });
69
+ Every helper that needs RPC accepts `SolanaConnection`, defined in `common/connection.ts` as a `Pick<Connection, ...>` of just the methods we use. This means callers can pass any version of `@solana/web3.js` without nominal type mismatches across SDK / consumer versions. Narrower call sites use a further `Pick` (e.g. `ProtocolActionConnection` in `elemental-lend/protocol-actions.ts` is `Pick<SolanaConnection, "getAccountInfo" | "getMultipleAccountsInfo">`).
96
70
 
97
- // Sign and send transaction with your wallet
98
- const signature = await wallet.sendTransaction(tx, connection);
99
- ```
71
+ ### Numeric convention (BN vs number)
100
72
 
101
- ### Withdraw
73
+ Documented at the top of `p-stv-core/types.ts`:
102
74
 
103
- Burn vault shares and receive tokens back.
75
+ - **u64 fields** are deserialized as `BN` (bn.js)
76
+ - **u32 / u16 / u8 fields** are deserialized as plain JavaScript `number`
104
77
 
105
- ```typescript
106
- const tx = await pool.withdraw({
107
- user: walletPublicKey,
108
- shares: new BN(500_000_000), // Amount of jvX shares to burn
109
- });
78
+ Mixing the two does not auto-convert and silently truncates — when adding new fields to any account interface, follow the rule.
110
79
 
111
- const signature = await wallet.sendTransaction(tx, connection);
112
- ```
80
+ ### Discriminators
113
81
 
114
- ---
82
+ - **p-stv-core (Pinocchio)** uses 1-byte instruction discriminators (0x00–0x0C, 13 instructions). Account discriminators are still 8 bytes for Anchor compatibility.
83
+ - **elemental-lend** and **jlpd-strategy** are Anchor 0.32.1 programs and use 8-byte instruction discriminators throughout.
84
+ - Account discriminators that are truly shared across programs (`ManagerRole`, `StrategyState`, `StvPosition`) live once in `common/constants.ts` and are re-exported by each module.
115
85
 
116
- ## Reading Data
86
+ Each constant is documented inline with the source — for example `IX_ADD_MANAGER` in elemental-lend has a `// sha256("global:add_manager")[..8]` comment so an auditor can re-derive it.
117
87
 
118
- ### Get Vault Info
88
+ ### Buffer reads
119
89
 
120
- ```typescript
121
- const vault = await client.fetchVault();
90
+ `common/buffer.ts` provides bounds-checked readers (`readPubkey`, `readU64`, `readU32`, `readU16`, `readU8`) and the corresponding writers / optional-encoders. Each read helper validates `offset + width <= data.length` and throws a descriptive `RangeError` rather than silently reading garbage when the offset is wrong.
122
91
 
123
- console.log("Admin:", vault.admin.toBase58());
124
- console.log("Manager:", vault.manager.toBase58());
125
- ```
92
+ ### Send-tx layer
126
93
 
127
- ### Get Pool (STV) Info
94
+ `p-stv-core/send-tx.ts` exposes `sendSmartTx(connection, instructions, payer, signTransaction, options?)`:
128
95
 
129
- ```typescript
130
- const stv = await client.fetchStv(MINTS.SOL);
131
-
132
- console.log("Price per share:", stv.pps.toString());
133
- console.log("Total fees accrued:", stv.accruedFeesJlx.toString());
134
- ```
135
-
136
- ### Get Exchange Rate
137
-
138
- ```typescript
139
- const rate = await client.fetchExchangeRate("SOL");
140
-
141
- console.log("Exchange rate:", rate.rate); // e.g., 1.05 means 5% yield
142
- console.log("Is fresh:", rate.isFresh);
143
- ```
96
+ 1. Pre-checks the legacy serialized size to decide if a versioned tx is needed (no double-sign).
97
+ 2. Fetches blockhash + every default LUT (lend / stv / jlpd) + Helius priority-fee in parallel.
98
+ 3. Simulates with an inflated CU limit, takes the actual `unitsConsumed`, applies a 5% buffer, and prepends the right `ComputeBudgetProgram` instructions.
99
+ 4. Falls back from legacy → versioned automatically when CU instructions push the size over `MAX_LEGACY_SIZE`.
100
+ 5. Confirms via `lastValidBlockHeight`.
144
101
 
145
- ### Calculate APY
102
+ The `signTransaction` callback is generic over `Transaction | VersionedTransaction` so wallets pass the same callback the SDK uses on either path. The optional `rpcUrl` field in `SmartTxOptions` is the only way the SDK reaches a Helius endpoint — it never reads private fields off the connection object.
146
103
 
147
- Calculate annualized return based on PPS (price per share) growth over time.
104
+ ### Address Lookup Tables
148
105
 
149
- ```typescript
150
- // You need a starting PPS and timestamp (e.g., from when user deposited)
151
- const startPps = new BN("1000000000"); // 1.0 (9 decimals)
152
- const startTime = 1706140800; // Unix timestamp when PPS was recorded
106
+ `p-stv-core/send-tx.ts` exports `DEFAULT_LUT_ADDRESSES`:
153
107
 
154
- // Calculate compound APY
155
- const apy = await client.calculateApy("SOL", startPps, startTime);
156
- console.log(`APY: ${(apy * 100).toFixed(2)}%`); // e.g., "APY: 12.50%"
157
-
158
- // Or calculate simple APY (non-compounded)
159
- const simpleApy = await client.calculateSimpleApy("SOL", startPps, startTime);
160
- console.log(`Simple APY: ${(simpleApy * 100).toFixed(2)}%`);
108
+ ```ts
109
+ {
110
+ lend: PublicKey, // Elemental Lend infrastructure
111
+ stv: PublicKey, // p-STV Core vaults / evMints / vault ATAs
112
+ jlpd: PublicKey, // JLPD Strategy state / positions / oracles
113
+ }
161
114
  ```
162
115
 
163
- **Note:** Store the user's PPS and timestamp when they deposit to calculate their personal returns later.
164
-
165
- ---
166
-
167
- ## Manager Operations
168
-
169
- These operations require manager permissions.
170
-
171
- ### Jupiter Earn (Deposit/Withdraw to Jupiter Lend)
116
+ `sendSmartTx` always fetches all three. Consumers building transactions outside `sendSmartTx` should import these and merge them into their own LUT list. Server-side jobs (`jlpd-server/src/jobs/ltv-rebalance.ts`) use this same export — the SDK is the single source of truth.
172
117
 
173
- ```typescript
174
- const pool = client.pool("SOL");
175
-
176
- // Deposit base tokens to Jupiter Lend
177
- const depositTx = await pool.jupEarn({
178
- manager: managerPublicKey,
179
- direction: "Deposit",
180
- amount: new BN(1_000_000_000),
181
- });
118
+ ## Installation
182
119
 
183
- // Withdraw from Jupiter Lend
184
- const withdrawTx = await pool.jupEarn({
185
- manager: managerPublicKey,
186
- direction: "Withdraw",
187
- amount: new BN(1_000_000_000),
188
- });
120
+ ```bash
121
+ npm install @elmntl/jlpd-sdk
122
+ # or
123
+ yarn add @elmntl/jlpd-sdk
124
+ # or
125
+ pnpm add @elmntl/jlpd-sdk
189
126
  ```
190
127
 
191
- ### Move Tokens Between STV and Vault
192
-
193
- ```typescript
194
- const pool = client.pool("SOL");
128
+ Peer dependencies must be installed in the consumer:
195
129
 
196
- // Move jlX tokens to vault (for JLP conversion)
197
- const toVaultTx = await pool.moveJlx({
198
- manager: managerPublicKey,
199
- direction: "ToVault",
200
- jlxAmount: new BN(1_000_000_000),
201
- });
202
-
203
- // Move jlX tokens back from vault to STV
204
- const fromVaultTx = await pool.moveJlx({
205
- manager: managerPublicKey,
206
- direction: "FromVault",
207
- jlxAmount: new BN(1_000_000_000),
208
- });
130
+ ```bash
131
+ npm install @solana/web3.js@^1.95.0 @solana/spl-token@^0.4.0
209
132
  ```
210
133
 
211
- ### Claim Fees
134
+ ## Quick examples
212
135
 
213
- ```typescript
214
- const pool = client.pool("SOL");
136
+ ### Deposit base into a vault from a frontend
215
137
 
216
- const tx = await pool.claimFees({
217
- manager: managerPublicKey,
138
+ ```ts
139
+ import {
140
+ findConfigPda,
141
+ findStvPda,
142
+ findEvMintPda,
143
+ createDepositIx,
144
+ buildDepositContext,
145
+ sendSmartTx,
146
+ } from "@elmntl/jlpd-sdk/p-stv-core";
147
+
148
+ const [config] = findConfigPda();
149
+ const [stv] = findStvPda(vaultId);
150
+ const [evMint] = findEvMintPda(vaultId);
151
+
152
+ const ctx = await buildDepositContext(connection, vault);
153
+
154
+ const ix = createDepositIx({
155
+ user, config, stv, evMint, vaultAta, baseMint, userBaseAta, userEvAta,
156
+ baseAmount, autoRouteCount: ctx.autoRouteCount, ...
218
157
  });
219
- ```
220
158
 
221
- ### Settle Yield
222
-
223
- Distributes JLP yield across all pools. Requires fetching the current JLP price.
224
-
225
- ```typescript
226
- import { fetchJlpRate, MINTS } from "jlpd-sdk";
227
-
228
- // Fetch current JLP price from Jupiter
229
- const jlpRate = await fetchJlpRate(MINTS.JLP.toBase58());
230
-
231
- // Settle yield
232
- const admin = client.admin();
233
- const tx = await admin.settleYield({
234
- manager: managerPublicKey,
235
- jlpRate,
236
- });
159
+ const sig = await sendSmartTx(
160
+ connection,
161
+ [...ctx.preInstructions, ix],
162
+ user,
163
+ signTransaction,
164
+ );
237
165
  ```
238
166
 
239
- ---
167
+ ### Read a JLPD strategy state from a server job
240
168
 
241
- ## Swap Operations
169
+ ```ts
170
+ import { fetchJlpStrategyState } from "@elmntl/jlpd-sdk/jlpd-strategy";
242
171
 
243
- ### Swap jlX to/from JLP
244
-
245
- ```typescript
246
- const swap = client.swap();
247
-
248
- // Get a quote first
249
- const quote = await swap.quoteJlxJlp({
250
- pool: "SOL",
251
- direction: "JlxToJlp", // or "JlpToJlx"
252
- amountIn: new BN(1_000_000_000),
253
- slippageBps: 30, // 0.3% slippage
254
- });
255
-
256
- console.log("Expected output:", quote.outAmount.toString());
257
- console.log("Price impact:", quote.priceImpactPct, "%");
258
-
259
- // Execute the swap
260
- const tx = await swap.swapJlxJlp({
261
- manager: managerPublicKey,
262
- pool: "SOL",
263
- direction: "JlxToJlp",
264
- amountIn: new BN(1_000_000_000),
265
- expectedOut: quote.outAmount,
266
- quote,
267
- });
172
+ const state = await fetchJlpStrategyState(connection, baseMint);
173
+ console.log(`PPS: ${state.pps.toString()}`);
174
+ console.log(`base_loaned: ${state.baseLoaned.toString()}`);
268
175
  ```
269
176
 
270
- ### Swap Between jlX Types
177
+ ### Build a manager-only `swap_jlp` rebalance from base → JLP
271
178
 
272
- ```typescript
273
- const swap = client.swap();
179
+ ```ts
180
+ import { buildSwapJlpTransaction } from "@elmntl/jlpd-sdk/jlpd-strategy";
274
181
 
275
- // Get a quote
276
- const quote = await swap.quoteJlxJlx({
277
- fromPool: "SOL",
278
- toPool: "USDC",
279
- amountIn: new BN(1_000_000_000),
182
+ const result = await buildSwapJlpTransaction({
183
+ connection,
184
+ manager,
185
+ baseMint,
186
+ vaultId,
187
+ direction: "BaseToJlp",
188
+ amount: 1_000_000n,
280
189
  slippageBps: 30,
281
190
  });
282
191
 
283
- // Execute the swap
284
- const tx = await swap.swapJlxJlx({
285
- manager: managerPublicKey,
286
- fromPool: "SOL",
287
- toPool: "USDC",
288
- amountIn: new BN(1_000_000_000),
289
- minOut: quote.minOutAmount,
290
- quote,
291
- });
292
- ```
293
-
294
- ---
295
-
296
- ## Token Decimals Reference
297
-
298
- | Token | Decimals | Example |
299
- | ------ | -------- | ----------------------- |
300
- | SOL | 9 | `1 SOL = 1_000_000_000` |
301
- | USDC | 6 | `1 USDC = 1_000_000` |
302
- | JupUSD | 6 | `1 JupUSD = 1_000_000` |
303
- | BTC | 8 | `1 BTC = 100_000_000` |
304
- | ETH | 8 | `1 ETH = 100_000_000` |
305
-
306
- ---
307
-
308
- ## Working with BN (Big Numbers)
309
-
310
- Solana uses big integers for token amounts. Use the `BN` class:
311
-
312
- ```typescript
313
- import { BN } from "@coral-xyz/anchor";
314
-
315
- // Create from number (small amounts only)
316
- const small = new BN(1000);
317
-
318
- // Create from string (recommended for large amounts)
319
- const large = new BN("1000000000000");
320
-
321
- // Arithmetic
322
- const sum = a.add(b);
323
- const diff = a.sub(b);
324
- const product = a.mul(b);
325
- const quotient = a.div(b);
326
-
327
- // Comparison
328
- a.gt(b); // greater than
329
- a.lt(b); // less than
330
- a.eq(b); // equal
331
- a.isZero();
332
-
333
- // Convert to display string
334
- const displayAmount = amount.toString();
335
- ```
336
-
337
- ---
338
-
339
- ## Error Handling
340
-
341
- ```typescript
342
- import { JlpdClientError } from "jlpd-sdk";
343
-
344
- try {
345
- const tx = await pool.deposit({
346
- user: walletPublicKey,
347
- amount: new BN(0), // Invalid amount
348
- });
349
- } catch (error) {
350
- if (error instanceof JlpdClientError) {
351
- console.error("SDK Error:", error.message);
352
- } else {
353
- console.error("Unexpected error:", error);
354
- }
355
- }
356
- ```
357
-
358
- ---
359
-
360
- ## Low-Level Instruction Builders
361
-
362
- For direct transaction construction (e.g., from a backend server), the SDK exports individual instruction builders. Each takes an Anchor `Program` instance as the first argument.
363
-
364
- ```typescript
365
- import {
366
- createProgram,
367
- createDepositInstruction,
368
- createWithdrawInstruction,
369
- createInitOrUpdateVaultInstruction,
370
- createUpdateStvInstruction,
371
- createJupEarnInstruction,
372
- createMoveJlxInstruction,
373
- createSwapJlxJlxInstruction,
374
- createSwapJlxJlpInstruction,
375
- createSettleYieldInstruction,
376
- createClaimFeesInstruction,
377
- } from "jlpd-sdk";
378
-
379
- const program = createProgram(connection);
380
-
381
- // Example: build a deposit instruction
382
- const ix = await createDepositInstruction(
383
- program,
384
- new BN(1_000_000_000),
385
- {
386
- user: userPubkey,
387
- jlpVault: vaultPda,
388
- stv: stvPda,
389
- baseMint: MINTS.SOL,
390
- jlMint: jlSolMint,
391
- jvMint: jvSolMint,
392
- userBaseAta: userSolAta,
393
- userJvxAta: userJvSolAta,
394
- stvBaseAta: stvSolAta,
395
- stvJlxAta: stvJlSolAta,
396
- tokenProgram: TOKEN_PROGRAM_ID,
397
- },
398
- remainingAccounts, // optional exchange rate accounts
192
+ const sig = await sendSmartTx(
193
+ connection,
194
+ [...result.preInstructions, ...result.instructions],
195
+ manager,
196
+ signTransaction,
197
+ { additionalLuts: result.addressLookupTables },
399
198
  );
400
199
  ```
401
200
 
402
- Some accounts are auto-resolved by Anchor from the IDL (PDAs and known addresses) and should be omitted from `.accounts()`:
403
-
404
- | Instruction | Auto-resolved accounts |
405
- |---|---|
406
- | `initOrUpdateJlpVault` | `jlpVault` (PDA), `systemProgram` |
407
- | `initializeStv` | `stv` (PDA), `stvJlxAta` (PDA), `systemProgram`, `associatedTokenProgram`, `rent` |
408
- | `jupEarnDepositWithdraw` | `tokenProgram` |
409
-
410
- ---
411
-
412
- ## Constants
413
-
414
- ```typescript
415
- import { MINTS, JLPD_PROGRAM_ID } from "jlpd-sdk";
416
-
417
- // Token mints
418
- MINTS.SOL; // Native SOL mint
419
- MINTS.USDC; // USDC mint
420
- MINTS.JLP; // JLP token mint
421
- MINTS.WBTC; // Wrapped BTC mint
422
- MINTS.WETH; // Wrapped ETH mint
423
-
424
- // Program ID
425
- JLPD_PROGRAM_ID; // Main program address
201
+ ## Quality bar
202
+
203
+ This SDK is the artifact submitted for external audit. The following invariants are enforced:
204
+
205
+ - **`tsc` strict mode** with `noUnusedLocals` and `noUnusedParameters`. Zero suppressions in source.
206
+ - **No `any`** in source code. All wallet / connection seams use proper structural types.
207
+ - **No `@deprecated` exports.** Deprecated aliases were removed during the audit cleanup; if you find one, it's a bug.
208
+ - **Buffer reads are bounds-checked.** Every helper in `common/buffer.ts` throws on out-of-range offsets.
209
+ - **Discriminators are documented inline** with their derivation (`// sha256("global:deposit")[..8]`).
210
+ - **Each module follows the same file shape** so the audit pattern is the same per program.
211
+
212
+ ## Project structure
213
+
214
+ ```
215
+ sdk/
216
+ ├── README.md (this file)
217
+ ├── package.json
218
+ ├── tsconfig.json strict + noUnusedLocals + noUnusedParameters
219
+ ├── src/
220
+ │ ├── index.ts namespace re-exports
221
+ │ ├── common/
222
+ │ │ ├── index.ts
223
+ │ │ ├── constants.ts shared discriminators, PPS_DECIMALS, BPS, staleness
224
+ │ │ ├── connection.ts SolanaConnection structural type
225
+ │ │ ├── buffer.ts bounds-checked readers / writers
226
+ │ │ ├── ata.ts findAta()
227
+ │ │ └── strategy-interface.ts StrategyStateHeader + StvPosition + decoders
228
+ │ ├── p-stv-core/ vault management — Pinocchio program (13 instructions, 0x00–0x0C)
229
+ │ │ ├── constants.ts, pda.ts, types.ts, accounts.ts, instructions.ts, events.ts
230
+ │ │ ├── remaining-accounts.ts context builders for deposit/claim/epoch/strategy ops
231
+ │ │ ├── send-tx.ts smart tx: simulate CU → priority fee → LUT → sign → confirm
232
+ │ │ ├── sol-wrap.ts native SOL wrap/unwrap for SOL-denominated vaults
233
+ │ │ └── prices.ts Jupiter Quote API USD price fetcher
234
+ │ ├── elemental-lend/ idle-base lending — Anchor 0.32.1 program
235
+ │ │ ├── constants.ts, pda.ts, types.ts, accounts.ts, instructions.ts
236
+ │ │ ├── kamino-vault.ts Kamino kVault account derivation + CPI + staleness check
237
+ │ │ ├── jupiter-lend.ts Jupiter Lend pool configs + auto-route account builders
238
+ │ │ └── protocol-actions.ts high-level protocol action tx builders
239
+ │ └── jlpd-strategy/ JLP yield strategy — Anchor 0.32.1 program
240
+ │ ├── constants.ts, pda.ts, types.ts, accounts.ts, instructions.ts
241
+ │ ├── swap-jlp.ts Jupiter swap tx builders (BaseToJlp / JlpToBase)
242
+ │ ├── settle-yield.ts settle_yield instruction builder
243
+ │ ├── jlp-data.ts JLP pool data reader (custody weights, AUM, prices)
244
+ │ ├── jlp-borrow.ts Jupiter Lend Borrow constants + position reading
245
+ │ ├── jupusd-earn.ts Jupiter Lend Earn position + APR helpers
246
+ │ └── adapter.ts JLPD Lend Adapter instruction builders
247
+ ├── dist/ tsc output (published to npm; also committed for internal `file:` link consumers)
248
+ └── scripts/
249
+ └── create-luts.ts admin tool: create / extend address lookup tables
426
250
  ```
427
-
428
- ---
429
-
430
- ## Full Example: Deposit Flow
431
-
432
- ```typescript
433
- import { Connection, PublicKey } from "@solana/web3.js";
434
- import { BN } from "@coral-xyz/anchor";
435
- import { JlpdClient } from "jlpd-sdk";
436
-
437
- async function deposit(walletPublicKey: PublicKey, wallet: any) {
438
- // 1. Create client
439
- const connection = new Connection("https://api.mainnet-beta.solana.com");
440
- const client = JlpdClient.mainnet(connection);
441
-
442
- // 2. Get pool context
443
- const pool = client.pool("SOL");
444
-
445
- // 3. Check current exchange rate (optional)
446
- const rate = await client.fetchExchangeRate("SOL");
447
- console.log(`Current yield: ${((rate.rate - 1) * 100).toFixed(2)}%`);
448
-
449
- // 4. Build deposit transaction
450
- const tx = await pool.deposit({
451
- user: walletPublicKey,
452
- amount: new BN(1_000_000_000), // 1 SOL
453
- });
454
-
455
- // 5. Send transaction
456
- const signature = await wallet.sendTransaction(tx, connection);
457
- console.log("Transaction sent:", signature);
458
-
459
- // 6. Confirm transaction
460
- await connection.confirmTransaction(signature, "confirmed");
461
- console.log("Deposit confirmed!");
462
- }
463
- ```
464
-
465
- ---
466
-
467
- ## Support
468
-
469
- For issues or questions, contact the Elemental team.