Skip to content

Latest commit

Β 

History

310 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Project 0 TypeScript SDK

npm version npm downloads License: MIT TypeScript GitHub

A modern, type-safe TypeScript SDK for interacting with the P0 Protocol on Solana. Lend, borrow, and manage leveraged DeFi positions with a clean, developer-friendly API.

πŸ“– Read the Full Documentation

Features

  • πŸ”’ Type-safe: Full TypeScript support with comprehensive type definitions
  • πŸ“¦ Tree-shakeable: Optimized ESM and CJS builds (<1MB)
  • πŸ§ͺ Well-tested: Unit and integration tests with Vitest
  • πŸ“š Rich examples: 7+ runnable examples covering all core features
  • πŸ”„ Modern tooling: Built with tsup, ESLint, Prettier
  • 🎯 Solana-native: Built on Anchor with full on-chain integration
  • ⚑ Production-ready: Used in production applications

Installation

npm install @0dotxyz/p0-ts-sdk
# or
yarn add @0dotxyz/p0-ts-sdk
# or
pnpm add @0dotxyz/p0-ts-sdk

Quick Start

1. Initialize the Client

import { Connection, PublicKey } from "@solana/web3.js";
import { Project0Client, getConfig } from "@0dotxyz/p0-ts-sdk";

// Connect to Solana
const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed");

// Get configuration (mainnet-beta)
const config = getConfig("production");

// Initialize the client (loads all banks and oracle prices)
const client = await Project0Client.initialize(connection, config);

console.log(`Loaded ${client.banks.length} banks`);

2. Load Your Account

import { MarginfiAccount, MarginfiAccountWrapper } from "@0dotxyz/p0-ts-sdk";

const accountAddress = new PublicKey("YOUR_MARGINFI_ACCOUNT_ADDRESS");

// Fetch your account
const account = await MarginfiAccount.fetch(accountAddress, client.program);

// Wrap it for cleaner API
const wrappedAccount = new MarginfiAccountWrapper(account, client);

3. Find a Bank

import { AssetTag } from "@0dotxyz/p0-ts-sdk";

// Option 1: Get bank by address
const bank = client.getBank(new PublicKey("BANK_ADDRESS"));

// Option 2: Get all banks for a mint (e.g., USDC)
const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const usdcBanks = client.getBanksByMint(USDC_MINT);

4. Deposit Tokens

// Build deposit transaction
const depositTx = await wrappedAccount.makeDepositTx(
  usdcBank.address,
  "100" // Amount in UI units (100 USDC)
);

// Simulate (optional, but recommended)
const simulation = await connection.simulateTransaction(depositTx);
console.log(`Compute units: ${simulation.value.unitsConsumed}`);

// Sign and send
// depositTx.sign([wallet]);
// await connection.sendTransaction(depositTx);

5. Borrow Against Collateral

// Check how much you can borrow (account health + bank borrow cap + bank liquidity)
const maxBorrow = wrappedAccount.computeMaxBorrowForBank(usdcBank.address);
console.log(`Max borrow: $${maxBorrow.toString()}`);

// Build borrow transaction
const borrowTx = await wrappedAccount.makeBorrowTx(
  usdcBank.address,
  "100" // Borrow 100 USDC
);

// Send transaction...

6. Monitor Account Health

import { MarginRequirementType } from "@0dotxyz/p0-ts-sdk";

// Get free collateral in USD
const freeCollateral = wrappedAccount.computeFreeCollateral();
console.log(`Free collateral: $${freeCollateral.toString()}`);

// Get health components
const health = wrappedAccount.computeHealthComponents(MarginRequirementType.Initial);

const healthFactor = health.assets.div(health.liabilities);
console.log(`Health factor: ${healthFactor.toString()}`);

πŸ“š Examples

Check out the examples/ directory for complete, runnable examples:

Each example includes:

  • βœ… Full setup instructions
  • βœ… Detailed comments
  • βœ… Error handling
  • βœ… Transaction simulation

Running Examples

cd examples
cp .env.example .env
# Edit .env with your values
tsx 01-deposit.ts

πŸ—οΈ Core Concepts

Project0Client

The main SDK client that manages protocol interactions.

const client = await Project0Client.initialize(connection, config);

// Pre-loaded data (fetched once at initialization)
client.banks                // All available banks
client.bankMap              // Banks indexed by address
client.oraclePriceByBank   // Latest oracle prices
client.mintDataByBank      // Token mint metadata
client.addressLookupTables // For transaction optimization

// Methods
client.getBank(address)             // Get bank by address
client.getBanksByMint(mint, tag?)   // Get all banks for a mint

Benefits:

  • Single initialization loads all chain data
  • Reuse throughout your application
  • Automatic oracle price caching
  • Built-in lookup table support

MarginfiAccount & Wrapper

Your lending account on the protocol.

// Fetch raw account
const account = await MarginfiAccount.fetch(address, client.program);

// Wrap for clean API (recommended)
const wrapped = new MarginfiAccountWrapper(account, client);

// All methods have access to banks, oracles, etc.
wrapped.computeMaxBorrowForBank(bankAddress);
wrapped.makeDepositTx(bankAddress, amount);
wrapped.computeFreeCollateral();

Bank

A lending pool for a specific token.

const bank = client.getBank(bankAddress);

bank.mint; // Token mint address
bank.config; // Interest rates, weights, limits
bank.config.assetWeightInit; // Collateral factor (LTV)
bank.config.liabilityWeightInit; // Borrow weight

Balance

Your position in a specific bank.

const balance = account.balances[0];

balance.bankPk; // Bank address
balance.assetShares; // Deposit shares
balance.liabilityShares; // Borrow shares
balance.active; // Is position active?

πŸ“¦ Package Structure

The SDK provides optimized entry points:

// Main SDK (core functionality)
import { Project0Client, MarginfiAccount, getConfig } from "@0dotxyz/p0-ts-sdk";

// Vendor utilities (oracle integrations, Jupiter, etc.)
import { fetchOracleData, OraclePrice } from "@0dotxyz/p0-ts-sdk/vendor";

Why separate vendor exports?

  • Reduces bundle size for simple use cases
  • Oracle libraries (Pyth, Switchboard) are large
  • Tree-shake what you don't need

🎯 Key Features

Type Safety

Full TypeScript support with exported types:

import type {
  MarginfiAccountType,
  BankType,
  BalanceType,
  OraclePrice,
  MarginRequirementType,
  Project0Config,
} from "@0dotxyz/p0-ts-sdk";

Multiple Bank Support

Handle cases where multiple banks exist for the same mint:

// Get ALL SOL banks (main + Kamino)
const solBanks = client.getBanksByMint(WSOL_MINT);

// Filter by tag
const mainSolBanks = client.getBanksByMint(WSOL_MINT, AssetTag.SOL);
const kaminoBanks = client.getBanksByMint(WSOL_MINT, AssetTag.KAMINO);

Health Calculations

Built-in account health monitoring:

import { MarginRequirementType } from "@0dotxyz/p0-ts-sdk";

// Free collateral (how much you can still borrow)
const free = wrapped.computeFreeCollateral();

// Health components (assets vs liabilities)
const health = wrapped.computeHealthComponents(
  MarginRequirementType.Initial // or Maintenance
);

// Max amounts β€” bank-aware:
//   borrow   = min(health-based, remaining borrow cap, available bank liquidity, rate-limit headroom)
//   withdraw = min(health-based, available bank liquidity, rate-limit headroom)
//   deposit  = remaining deposit cap (optionally min'd with your wallet balance)
// (rate-limit headroom = bank net-outflow limiter in tokens + group USD limiter, if enabled)
const maxBorrow = wrapped.computeMaxBorrowForBank(bankAddress);
const maxWithdraw = wrapped.computeMaxWithdrawForBank(bankAddress);
const maxDeposit = wrapped.computeMaxDepositForBank(bankAddress, { walletBalance: 1_000 });

// Pass { ignoreBankLimits: true } to get the purely health-based borrow/withdraw amount

πŸ§ͺ Testing

The SDK includes comprehensive tests:

# Unit tests (fast, no RPC needed)
pnpm test:unit

# Integration tests (requires RPC)
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com pnpm test:integration

# All tests
pnpm test

# With coverage
pnpm test:coverage

Testing Strategy:

  • Unit tests: Pure calculations, conversions, validations
  • Integration tests: Real chain data, transaction building, simulations

See TESTING.md for details.

πŸ› οΈ Development

Prerequisites

  • Node.js >= 18.0.0
  • pnpm (recommended)

Setup

# Install dependencies
pnpm install

# Build the SDK
pnpm build

# Watch mode (for development)
pnpm dev

# Type check
pnpm typecheck

# Lint and format
pnpm lint
pnpm format

Project Structure

p0-ts-sdk/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts              # Main SDK exports
β”‚   β”œβ”€β”€ vendor/               # Vendor entry point (oracles, etc.)
β”‚   β”œβ”€β”€ config.ts             # Network configurations
β”‚   β”œβ”€β”€ models/               # Core models
β”‚   β”‚   β”œβ”€β”€ client.ts         # Project0Client
β”‚   β”‚   β”œβ”€β”€ account.ts        # MarginfiAccount
β”‚   β”‚   β”œβ”€β”€ account-wrapper.ts # MarginfiAccountWrapper
β”‚   β”‚   β”œβ”€β”€ bank.ts           # Bank model
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ services/             # Business logic
β”‚   β”‚   β”œβ”€β”€ account/          # Account operations
β”‚   β”‚   β”œβ”€β”€ price/            # Oracle price fetching
β”‚   β”‚   └── ...
β”‚   β”œβ”€β”€ instructions/         # Transaction builders
β”‚   β”œβ”€β”€ types/                # TypeScript types
β”‚   β”œβ”€β”€ idl/                  # Anchor IDL
β”‚   └── utils/                # Helpers
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ unit/                 # Unit tests (mocked)
β”‚   β”œβ”€β”€ integration/          # Integration tests (real RPC)
β”‚   └── fixtures/             # Test data
β”œβ”€β”€ examples/                 # 7+ runnable examples
└── dist/                     # Build output
    β”œβ”€β”€ index.js              # ESM bundle
    β”œβ”€β”€ index.cjs             # CJS bundle
    β”œβ”€β”€ index.d.ts            # Type definitions
    └── vendor.*              # Vendor bundles

Available Scripts

Script Description
pnpm build Build ESM + CJS bundles
pnpm dev Watch mode for development
pnpm test Run all tests
pnpm test:unit Run unit tests only
pnpm test:integration Run integration tests
pnpm test:coverage Generate coverage report
pnpm lint Lint with ESLint
pnpm format Format with Prettier
pnpm typecheck TypeScript type checking
pnpm clean Remove build artifacts
pnpm changeset Create a changeset for releases
pnpm version Bump version from changesets
pnpm release Build and publish to npm

πŸ“¦ Publishing

This package uses Changesets for version management and npm publishing.

See RELEASING.md for detailed instructions, or .changeset/QUICKSTART.md for a quick reference.

Quick publish:

npm login
pnpm changeset    # Document changes
pnpm version      # Bump version
pnpm release      # Publish to npm
git push --follow-tags

🀝 Contributing

We welcome contributions! Please see our contributing guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Run pnpm test and pnpm lint
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Development Workflow

# 1. Make changes
vim src/models/client.ts

# 2. Add tests
vim tests/unit/models/client.test.ts

# 3. Run tests
pnpm test:unit

# 4. Build
pnpm build

# 5. Test with examples
cd examples && tsx 01-deposit.ts

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

This SDK is built on top of the marginfi protocol, leveraging its on-chain programs and infrastructure.

Additional thanks to:

⚠️ Disclaimer

This SDK is provided as-is. Always:

  • Understand the risks of DeFi protocols
  • Monitor your account health
  • Use appropriate risk management
  • Audit your integration code

Built for builders πŸ› οΈ by the P0 team

About

Resources

Contributing

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages