TypeScript SDK for the DEPEG protocol — programmatic access to DEPEG's stablecoin swap, staking, and booster surface on Solana.
DEPEG (https://depeg.app) wraps pump.fun memecoins with a 1:1 USDC-backed companion stablecoin. Trade fees from the underlying pump.fun bonding curve flow into the staking pool as yield. Holders stake stablecoins for lock-period-boosted rewards and can buy temporary booster multipliers paid in SOL.
npm install @depegprotocol/sdk @solana/web3.js @coral-xyz/anchor @solana/spl-token bn.jsimport { Connection, Keypair, PublicKey } from "@solana/web3.js";
import { Wallet } from "@coral-xyz/anchor";
import { DepegClient, LockPeriod, BOOSTER_TIERS } from "@depegprotocol/sdk";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const wallet = new Wallet(Keypair.generate()); // your signer
const client = new DepegClient({ connection, wallet });The client has three surfaces:
client.pdas.* |
Derive any DEPEG PDA (config, stablecoin mint, staking pool, position, …). |
client.fetchXxx(...) |
Read on-chain accounts (Config, StakingPool, StakePosition, UserPoolState). |
client.ix.* |
Build instructions for the public ix surface. |
client.logs.* |
Parse / subscribe to the DEPEG_PROTOCOL on-chain log format. |
import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import BN from "bn.js";
const coinMint = new PublicKey("..."); // any DEPEG-registered pump.fun coin
const ixs = await client.ix.swapUsdcToStablecoin({
user: wallet.publicKey,
coinMint,
amount: new BN(1_000_000), // 1 USDC (6 decimals)
createAtaIfMissing: true, // prepends idempotent ATA create
});
const tx = new Transaction().add(...ixs);
await sendAndConfirmTransaction(connection, tx, [wallet.payer]);import { positionPda } from "@depegprotocol/sdk";
const positionId = Date.now(); // any unique u64 within this user/pool
const ix = await client.ix.stake({
owner: wallet.publicKey,
coinMint,
positionId,
amount: new BN(100_000_000), // 100 stablecoin (6 decimals)
lockPeriod: LockPeriod.OneMonth, // 164.317× reward boost
});
const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [wallet.payer]);
const positionAddr = positionPda(coinMint, wallet.publicKey, positionId);const ix = await client.ix.claimRewards({
owner: wallet.publicKey,
coinMint,
position: positionAddr,
});const ix = await client.ix.unstake({
owner: wallet.publicKey,
coinMint,
position: positionAddr,
});You must pass every one of the user's current positions in this pool in positions (all writable). Length must equal UserPoolState.positionCount exactly.
const userState = await client.fetchUserPoolState(coinMint, wallet.publicKey);
const positions = (await client.fetchUserPositions(coinMint, wallet.publicKey))
.map((p) => p.pubkey);
if (positions.length !== (userState?.positionCount ?? 0)) {
throw new Error("position count mismatch — index your positions before calling buy_booster");
}
const ix = await client.ix.buyBooster({
user: wallet.publicKey,
coinMint,
tier: 0, // 1.25× for 0.05 SOL
positions,
});
// Cross-reference the price you're paying:
console.log("paying", BOOSTER_TIERS[0].priceLamports.toString(), "lamports for", BOOSTER_TIERS[0].boostBps, "bps");For a UI showing "claimable" amounts without sending a tx:
import { REWARDS_SCALE, BPS_DENOM } from "@depegprotocol/sdk";
const pool = await client.fetchStakingPool(coinMint);
const position = await client.fetchPosition(positionAddr);
const userState = await client.fetchUserPoolState(coinMint, wallet.publicKey);
const boosterActive = userState?.boostExpiresAt && Date.now() / 1000 < userState.boostExpiresAt.toNumber();
const userBoostBps = boosterActive ? BigInt(userState!.boostBps) : BPS_DENOM;
const effectiveWithBoost =
(BigInt(position!.effectiveStake.toString()) * userBoostBps) / BPS_DENOM;
const totalDue =
(effectiveWithBoost * BigInt(pool!.accRewardsPerStake.toString())) / REWARDS_SCALE;
const pending = totalDue > BigInt(position!.rewardDebt.toString())
? totalDue - BigInt(position!.rewardDebt.toString())
: 0n;
console.log("pending stablecoin rewards (raw u64):", pending);const subId = client.logs.subscribe((event, signature) => {
console.log("[" + event.ixName + "]", event.body, "in", signature);
});
// Later:
// connection.removeOnLogsListener(subId);Example events:
[stake] 4f7…dZ is staking 100.000000 stablecoin of coin AB…YZ for 30 days (position #1738, locked_until=1715000000)
[buy_booster] 9aB…XY bought tier-0 booster (12500bps multiplier) on coin AB…YZ for 0.050000000 SOL — applies to 2 position(s), expires_at=1715604800 (replaced_previous=false)
[swap_usdc_to_stablecoin] 3xQ…Lp swapped 5.000000 USDC for stablecoin … (coin AB…YZ)
Wrap a pump.fun coin as a DEPEG pool. The instruction requires PLATFORM_ADMIN to co-sign — typically you build the unsigned tx with the SDK, then POST it to DEPEG's co-sign endpoint to add the admin signature, then submit.
import { MIN_SEED_USDC } from "@depegprotocol/sdk";
const ix = await client.ix.initializeUserPool({
creator: wallet.publicKey,
coinMint: pumpFunCoinMint,
usdcMint: client.usdcMint,
stablecoinName: "MEMECOIN stable",
stablecoinSymbol: "sMEME",
stablecoinUri: "https://example.com/metadata.json",
seedAmount: MIN_SEED_USDC, // 5 USDC minimum
vaultBps: 4000, // 40% to USDC vault
stakingBps: 4000, // 40% to stakers
// remainder (1000 bps after platform+treasury cuts) → deployer
});
// Build the partial tx, sign as `creator`, send to DEPEG's co-sign endpoint, then submit.The IDL ships with the full event schema so indexers can decode any DEPEG transaction. For example, to decode a YieldInjected event from a confirmed signature:
import { BorshCoder, EventParser } from "@coral-xyz/anchor";
import { DEPEG_IDL, PROGRAM_ID } from "@depegprotocol/sdk";
const parser = new EventParser(PROGRAM_ID, new BorshCoder(DEPEG_IDL as any));
const tx = await connection.getTransaction(sig, { maxSupportedTransactionVersion: 0 });
for (const ev of parser.parseLogs(tx?.meta?.logMessages ?? [])) {
console.log(ev.name, ev.data);
}import { USDC_DEVNET } from "@depegprotocol/sdk";
const client = new DepegClient({
connection: new Connection("https://api.devnet.solana.com"),
wallet,
usdcMint: USDC_DEVNET,
});import {
PROGRAM_ID,
USDC_MAINNET, USDC_DEVNET,
LockPeriod, LOCK_PERIOD_NAMES, LOCK_PERIOD_SECONDS, LOCK_PERIOD_BOOST_BPS,
BOOSTER_TIERS, BOOSTER_DURATION_SEC,
MIN_STAKE_AMOUNT, MAX_POSITIONS_PER_USER_PER_COIN,
REWARDS_SCALE, BPS_DENOM,
} from "@depegprotocol/sdk";Every ix builder is also exported as a standalone function. Useful if you're building a higher-level orchestrator or if you want to skip the DepegClient wrapper:
import { Program, AnchorProvider } from "@coral-xyz/anchor";
import { DEPEG_IDL, swapUsdcToStablecoin, USDC_MAINNET } from "@depegprotocol/sdk";
const provider = new AnchorProvider(connection, wallet, {});
const program = new Program(DEPEG_IDL as any, provider);
const ixs = await swapUsdcToStablecoin(program, {
user: wallet.publicKey,
coinMint,
usdcMint: USDC_MAINNET,
amount: new BN(1_000_000),
createAtaIfMissing: true,
});MIT