@elmntl/jlpd-sdk 0.2.0 → 0.13.4
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/LICENSE +201 -0
- package/README.md +185 -404
- package/dist/common/ata.d.ts +26 -0
- package/dist/common/ata.js +48 -0
- package/dist/common/buffer.d.ts +15 -0
- package/dist/common/buffer.js +118 -0
- package/dist/common/connection.d.ts +13 -0
- package/dist/common/connection.js +2 -0
- package/dist/common/constants.d.ts +14 -0
- package/dist/common/constants.js +31 -0
- package/dist/common/index.d.ts +6 -0
- package/dist/common/index.js +28 -0
- package/dist/common/strategy-interface.d.ts +59 -0
- package/dist/common/strategy-interface.js +42 -0
- package/dist/elemental-lend/accounts.d.ts +103 -0
- package/dist/elemental-lend/accounts.js +354 -0
- package/dist/elemental-lend/constants.d.ts +25 -0
- package/dist/elemental-lend/constants.js +48 -0
- package/dist/elemental-lend/index.d.ts +8 -0
- package/dist/elemental-lend/index.js +24 -0
- package/dist/elemental-lend/instructions.d.ts +104 -0
- package/dist/elemental-lend/instructions.js +266 -0
- package/dist/elemental-lend/jupiter-lend.d.ts +91 -0
- package/dist/elemental-lend/jupiter-lend.js +189 -0
- package/dist/elemental-lend/kamino-vault.d.ts +173 -0
- package/dist/elemental-lend/kamino-vault.js +483 -0
- package/dist/elemental-lend/pda.d.ts +12 -0
- package/dist/elemental-lend/pda.js +24 -0
- package/dist/elemental-lend/protocol-actions.d.ts +56 -0
- package/dist/elemental-lend/protocol-actions.js +244 -0
- package/dist/elemental-lend/types.d.ts +113 -0
- package/dist/elemental-lend/types.js +2 -0
- package/dist/elemental-lend-v2/accounts.d.ts +14 -0
- package/dist/elemental-lend-v2/accounts.js +136 -0
- package/dist/elemental-lend-v2/adapters.d.ts +22 -0
- package/dist/elemental-lend-v2/adapters.js +50 -0
- package/dist/elemental-lend-v2/constants.d.ts +48 -0
- package/dist/elemental-lend-v2/constants.js +104 -0
- package/dist/elemental-lend-v2/index.d.ts +8 -0
- package/dist/elemental-lend-v2/index.js +24 -0
- package/dist/elemental-lend-v2/instructions.d.ts +96 -0
- package/dist/elemental-lend-v2/instructions.js +190 -0
- package/dist/elemental-lend-v2/lut.d.ts +20 -0
- package/dist/elemental-lend-v2/lut.js +65 -0
- package/dist/elemental-lend-v2/pda.d.ts +9 -0
- package/dist/elemental-lend-v2/pda.js +27 -0
- package/dist/elemental-lend-v2/types.d.ts +105 -0
- package/dist/elemental-lend-v2/types.js +2 -0
- package/dist/elemental-lend-v2/update-aum.d.ts +29 -0
- package/dist/elemental-lend-v2/update-aum.js +82 -0
- package/dist/index.d.ts +5 -4199
- package/dist/index.js +37 -5187
- package/dist/jlpd-strategy/accounts.d.ts +83 -0
- package/dist/jlpd-strategy/accounts.js +216 -0
- package/dist/jlpd-strategy/adapter.d.ts +81 -0
- package/dist/jlpd-strategy/adapter.js +118 -0
- package/dist/jlpd-strategy/base-to-base-swap.d.ts +74 -0
- package/dist/jlpd-strategy/base-to-base-swap.js +205 -0
- package/dist/jlpd-strategy/constants.d.ts +127 -0
- package/dist/jlpd-strategy/constants.js +174 -0
- package/dist/jlpd-strategy/fluid-view.d.ts +199 -0
- package/dist/jlpd-strategy/fluid-view.js +799 -0
- package/dist/jlpd-strategy/hedge-derived.d.ts +135 -0
- package/dist/jlpd-strategy/hedge-derived.js +231 -0
- package/dist/jlpd-strategy/hedge-instructions.d.ts +210 -0
- package/dist/jlpd-strategy/hedge-instructions.js +300 -0
- package/dist/jlpd-strategy/hedge-state.d.ts +88 -0
- package/dist/jlpd-strategy/hedge-state.js +110 -0
- package/dist/jlpd-strategy/index.d.ts +17 -0
- package/dist/jlpd-strategy/index.js +33 -0
- package/dist/jlpd-strategy/instructions.d.ts +159 -0
- package/dist/jlpd-strategy/instructions.js +234 -0
- package/dist/jlpd-strategy/jlp-borrow.d.ts +63 -0
- package/dist/jlpd-strategy/jlp-borrow.js +87 -0
- package/dist/jlpd-strategy/jlp-data.d.ts +166 -0
- package/dist/jlpd-strategy/jlp-data.js +611 -0
- package/dist/jlpd-strategy/jupusd-earn.d.ts +90 -0
- package/dist/jlpd-strategy/jupusd-earn.js +166 -0
- package/dist/jlpd-strategy/live-jlp-price.d.ts +46 -0
- package/dist/jlpd-strategy/live-jlp-price.js +267 -0
- package/dist/jlpd-strategy/pda.d.ts +13 -0
- package/dist/jlpd-strategy/pda.js +28 -0
- package/dist/jlpd-strategy/settle-yield.d.ts +45 -0
- package/dist/jlpd-strategy/settle-yield.js +113 -0
- package/dist/jlpd-strategy/swap-jlp.d.ts +198 -0
- package/dist/jlpd-strategy/swap-jlp.js +586 -0
- package/dist/jlpd-strategy/types.d.ts +101 -0
- package/dist/jlpd-strategy/types.js +29 -0
- package/dist/p-stv-core/accounts.d.ts +152 -0
- package/dist/p-stv-core/accounts.js +407 -0
- package/dist/p-stv-core/constants.d.ts +138 -0
- package/dist/p-stv-core/constants.js +181 -0
- package/dist/p-stv-core/events.d.ts +7 -0
- package/dist/p-stv-core/events.js +246 -0
- package/dist/p-stv-core/index.d.ts +11 -0
- package/dist/p-stv-core/index.js +27 -0
- package/dist/p-stv-core/instructions.d.ts +637 -0
- package/dist/p-stv-core/instructions.js +670 -0
- package/dist/p-stv-core/lut.d.ts +41 -0
- package/dist/p-stv-core/lut.js +81 -0
- package/dist/p-stv-core/pda.d.ts +30 -0
- package/dist/p-stv-core/pda.js +65 -0
- package/dist/p-stv-core/prices.d.ts +20 -0
- package/dist/p-stv-core/prices.js +77 -0
- package/dist/p-stv-core/remaining-accounts.d.ts +107 -0
- package/dist/p-stv-core/remaining-accounts.js +326 -0
- package/dist/p-stv-core/send-tx.d.ts +72 -0
- package/dist/p-stv-core/send-tx.js +290 -0
- package/dist/p-stv-core/sol-wrap.d.ts +34 -0
- package/dist/p-stv-core/sol-wrap.js +74 -0
- package/dist/p-stv-core/types.d.ts +361 -0
- package/dist/p-stv-core/types.js +2 -0
- package/package.json +56 -15
- package/dist/index.d.mts +0 -4199
- package/dist/index.mjs +0 -5090
package/README.md
CHANGED
|
@@ -1,469 +1,250 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @elmntl/jlpd-sdk
|
|
2
2
|
|
|
3
|
-
SDK for
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
##
|
|
13
|
+
## At a glance
|
|
44
14
|
|
|
45
|
-
|
|
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
|
-
|
|
22
|
+
## Module layout
|
|
48
23
|
|
|
49
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
43
|
+
Naming conventions hold across modules:
|
|
70
44
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
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
|
-
##
|
|
55
|
+
## Naming exceptions worth knowing
|
|
82
56
|
|
|
83
|
-
|
|
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
|
-
|
|
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
|
-
|
|
88
|
-
import { BN } from "@coral-xyz/anchor";
|
|
65
|
+
## Cross-cutting design
|
|
89
66
|
|
|
90
|
-
|
|
67
|
+
### `SolanaConnection` (structural type)
|
|
91
68
|
|
|
92
|
-
|
|
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
|
-
|
|
98
|
-
const signature = await wallet.sendTransaction(tx, connection);
|
|
99
|
-
```
|
|
71
|
+
### Numeric convention (BN vs number)
|
|
100
72
|
|
|
101
|
-
|
|
73
|
+
Documented at the top of `p-stv-core/types.ts`:
|
|
102
74
|
|
|
103
|
-
|
|
75
|
+
- **u64 fields** are deserialized as `BN` (bn.js)
|
|
76
|
+
- **u32 / u16 / u8 fields** are deserialized as plain JavaScript `number`
|
|
104
77
|
|
|
105
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
88
|
+
### Buffer reads
|
|
119
89
|
|
|
120
|
-
|
|
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
|
-
|
|
124
|
-
console.log("Manager:", vault.manager.toBase58());
|
|
125
|
-
```
|
|
92
|
+
### Send-tx layer
|
|
126
93
|
|
|
127
|
-
|
|
94
|
+
`p-stv-core/send-tx.ts` exposes `sendSmartTx(connection, instructions, payer, signTransaction, options?)`:
|
|
128
95
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
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
|
-
|
|
104
|
+
### Address Lookup Tables
|
|
148
105
|
|
|
149
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
//
|
|
159
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
const pool = client.pool("SOL");
|
|
128
|
+
Peer dependencies must be installed in the consumer:
|
|
195
129
|
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
134
|
+
## Quick examples
|
|
212
135
|
|
|
213
|
-
|
|
214
|
-
const pool = client.pool("SOL");
|
|
136
|
+
### Deposit base into a vault from a frontend
|
|
215
137
|
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
-
|
|
169
|
+
```ts
|
|
170
|
+
import { fetchJlpStrategyState } from "@elmntl/jlpd-sdk/jlpd-strategy";
|
|
242
171
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
###
|
|
177
|
+
### Build a manager-only `swap_jlp` rebalance from base → JLP
|
|
271
178
|
|
|
272
|
-
```
|
|
273
|
-
|
|
179
|
+
```ts
|
|
180
|
+
import { buildSwapJlpTransaction } from "@elmntl/jlpd-sdk/jlpd-strategy";
|
|
274
181
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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.
|