npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@elemental-stv-core/sdk

v0.9.3

Published

TypeScript SDK for Elemental Vaults — p-STV Core, Elemental Lend, JLPD Strategy

Readme

@elemental-stv-core/sdk

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.

@elemental-stv-core/sdk
├── /common          shared types, buffer helpers, connection type, discriminators
├── /p-stv-core      vault management — deposits, withdraws, epochs, fees      (level N)
├── /elemental-lend  idle-base lending sweep into Kamino + Jupiter Lend Earn   (level N − 1)
└── /jlpd-strategy   JLP-Deconstructed yield strategy + lend-adapter wiring    (level N + 1 / N + 2)

At a glance

| Module | Wraps program | What it gives you | | ---------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | @elemental-stv-core/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 | | @elemental-stv-core/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 | | @elemental-stv-core/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 | | @elemental-stv-core/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 |

Module layout

Every program-specific module follows the same file shape, so you only have to learn the pattern once:

<module>/
├── constants.ts           program ID, seeds, instruction discriminators, sizes, flags
├── pda.ts                 findXxxPda() helpers — pure synchronous PDA derivation
├── types.ts               account interfaces + event types
├── accounts.ts            deserializeXxx() + fetchXxx() readers + GPA queries
├── instructions.ts        createXxxIx() instruction builders
├── events.ts              event decoders (p-stv-core: 1-byte disc; Anchor: 8-byte)
└── (module-specific files)

Module-specific files:
  p-stv-core:       remaining-accounts.ts, send-tx.ts, sol-wrap.ts, prices.ts
  elemental-lend:   kamino-vault.ts, jupiter-lend.ts, protocol-actions.ts
  jlpd-strategy:    swap-jlp.ts, settle-yield.ts, jlp-data.ts,
                    jlp-borrow.ts, jupusd-earn.ts, adapter.ts

Naming conventions hold across modules:

| Pattern | Returns | Side effects | | --------------- | ------------------------- | ------------ | | findXxxPda | [PublicKey, number] | none | | deserializeXxx| typed account | none | | fetchXxx | typed account | one RPC call | | createXxxIx | TransactionInstruction | none | | buildXxx* | helper objects | none |

build* is reserved for helpers that produce ephemeral data (remaining accounts, batched instruction lists). Anything that returns a wire-ready instruction is named createXxxIx.

Naming exceptions worth knowing

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:

| Program | Function | PDA seeds | | --------------- | ------------------------- | ---------------------------------------- | | p-stv-core | findStvManagerRolePda | ["manager", stv, manager] | | elemental-lend | findLendManagerRolePda | ["manager", strategy_state, manager] | | jlpd-strategy | findJlpdManagerRolePda | ["manager", config, manager] |

Cross-cutting design

SolanaConnection (structural type)

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">).

Numeric convention (BN vs number)

Documented at the top of p-stv-core/types.ts:

  • u64 fields are deserialized as BN (bn.js)
  • u32 / u16 / u8 fields are deserialized as plain JavaScript number

Mixing the two does not auto-convert and silently truncates — when adding new fields to any account interface, follow the rule.

Discriminators

  • p-stv-core (Pinocchio) uses 1-byte instruction discriminators (0x00–0x0C, 13 instructions). Account discriminators are still 8 bytes for Anchor compatibility.
  • elemental-lend and jlpd-strategy are Anchor 0.32.1 programs and use 8-byte instruction discriminators throughout.
  • Account discriminators that are truly shared across programs (ManagerRole, StrategyState, StvPosition) live once in common/constants.ts and are re-exported by each module.

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.

Buffer reads

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.

Send-tx layer

p-stv-core/send-tx.ts exposes sendSmartTx(connection, instructions, payer, signTransaction, options?):

  1. Pre-checks the legacy serialized size to decide if a versioned tx is needed (no double-sign).
  2. Fetches blockhash + every default LUT (lend / stv / jlpd) + Helius priority-fee in parallel.
  3. Simulates with an inflated CU limit, takes the actual unitsConsumed, applies a 5% buffer, and prepends the right ComputeBudgetProgram instructions.
  4. Falls back from legacy → versioned automatically when CU instructions push the size over MAX_LEGACY_SIZE.
  5. Confirms via lastValidBlockHeight.

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.

Address Lookup Tables

p-stv-core/send-tx.ts exports DEFAULT_LUT_ADDRESSES:

{
  lend: PublicKey,   // Elemental Lend infrastructure
  stv:  PublicKey,   // p-STV Core vaults / evMints / vault ATAs
  jlpd: PublicKey,   // JLPD Strategy state / positions / oracles
}

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.

Installation

npm install @elemental-stv-core/sdk
# or
yarn add @elemental-stv-core/sdk
# or
pnpm add @elemental-stv-core/sdk

Peer dependencies must be installed in the consumer:

npm install @solana/web3.js@^1.95.0 @solana/spl-token@^0.4.0

Quick examples

Deposit base into a vault from a frontend

import {
  findConfigPda,
  findStvPda,
  findEvMintPda,
  createDepositIx,
  buildDepositContext,
  sendSmartTx,
} from "@elemental-stv-core/sdk/p-stv-core";

const [config] = findConfigPda();
const [stv]    = findStvPda(vaultId);
const [evMint] = findEvMintPda(vaultId);

const ctx = await buildDepositContext(connection, vault);

const ix = createDepositIx({
  user, config, stv, evMint, vaultAta, baseMint, userBaseAta, userEvAta,
  baseAmount, autoRouteCount: ctx.autoRouteCount, ...
});

const sig = await sendSmartTx(
  connection,
  [...ctx.preInstructions, ix],
  user,
  signTransaction,
);

Read a JLPD strategy state from a server job

import { fetchJlpStrategyState } from "@elemental-stv-core/sdk/jlpd-strategy";

const state = await fetchJlpStrategyState(connection, baseMint);
console.log(`PPS: ${state.pps.toString()}`);
console.log(`base_loaned: ${state.baseLoaned.toString()}`);

Build a manager-only swap_jlp rebalance from base → JLP

import { buildSwapJlpTransaction } from "@elemental-stv-core/sdk/jlpd-strategy";

const result = await buildSwapJlpTransaction({
  connection,
  manager,
  baseMint,
  vaultId,
  direction: "BaseToJlp",
  amount: 1_000_000n,
  slippageBps: 30,
});

const sig = await sendSmartTx(
  connection,
  [...result.preInstructions, ...result.instructions],
  manager,
  signTransaction,
  { additionalLuts: result.addressLookupTables },
);

Quality bar

This SDK is the artifact submitted for external audit. The following invariants are enforced:

  • tsc strict mode with noUnusedLocals and noUnusedParameters. Zero suppressions in source.
  • No any in source code. All wallet / connection seams use proper structural types.
  • No @deprecated exports. Deprecated aliases were removed during the audit cleanup; if you find one, it's a bug.
  • Buffer reads are bounds-checked. Every helper in common/buffer.ts throws on out-of-range offsets.
  • Discriminators are documented inline with their derivation (// sha256("global:deposit")[..8]).
  • Each module follows the same file shape so the audit pattern is the same per program.

Project structure

sdk/
├── README.md                       (this file)
├── package.json
├── tsconfig.json                   strict + noUnusedLocals + noUnusedParameters
├── src/
│   ├── index.ts                    namespace re-exports
│   ├── common/
│   │   ├── index.ts
│   │   ├── constants.ts            shared discriminators, PPS_DECIMALS, BPS, staleness
│   │   ├── connection.ts           SolanaConnection structural type
│   │   ├── buffer.ts               bounds-checked readers / writers
│   │   ├── ata.ts                  findAta()
│   │   └── strategy-interface.ts   StrategyStateHeader + StvPosition + decoders
│   ├── p-stv-core/                 vault management — Pinocchio program (13 instructions, 0x00–0x0C)
│   │   ├── constants.ts, pda.ts, types.ts, accounts.ts, instructions.ts, events.ts
│   │   ├── remaining-accounts.ts   context builders for deposit/claim/epoch/strategy ops
│   │   ├── send-tx.ts              smart tx: simulate CU → priority fee → LUT → sign → confirm
│   │   ├── sol-wrap.ts             native SOL wrap/unwrap for SOL-denominated vaults
│   │   └── prices.ts               Jupiter Quote API USD price fetcher
│   ├── elemental-lend/             idle-base lending — Anchor 0.32.1 program
│   │   ├── constants.ts, pda.ts, types.ts, accounts.ts, instructions.ts
│   │   ├── kamino-vault.ts         Kamino kVault account derivation + CPI + staleness check
│   │   ├── jupiter-lend.ts         Jupiter Lend pool configs + auto-route account builders
│   │   └── protocol-actions.ts     high-level protocol action tx builders
│   └── jlpd-strategy/              JLP yield strategy — Anchor 0.32.1 program
│       ├── constants.ts, pda.ts, types.ts, accounts.ts, instructions.ts
│       ├── swap-jlp.ts             Jupiter swap tx builders (BaseToJlp / JlpToBase)
│       ├── settle-yield.ts         settle_yield instruction builder
│       ├── jlp-data.ts             JLP pool data reader (custody weights, AUM, prices)
│       ├── jlp-borrow.ts           Jupiter Lend Borrow constants + position reading
│       ├── jupusd-earn.ts           Jupiter Lend Earn position + APR helpers
│       └── adapter.ts              JLPD Lend Adapter instruction builders
├── dist/                           tsc output (published to npm; also committed for internal `file:` link consumers)
└── scripts/
    └── create-luts.ts              admin tool: create / extend address lookup tables