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

@loopprotocol/sdk

v0.1.3

Published

Loop Protocol SDK — value capture infrastructure for AI agents on Solana.

Readme

@loopprotocol/sdk

The official TypeScript SDK for Loop Protocol — value capture infrastructure for AI agents on Solana.

npm version License: MIT

Installation

npm install @loopprotocol/sdk
# or
yarn add @loopprotocol/sdk
# or
pnpm add @loopprotocol/sdk

Quick Start

import { Loop, CaptureType, PermissionLevel } from '@loopprotocol/sdk';
import { Connection, PublicKey } from '@solana/web3.js';
import { BN } from '@coral-xyz/anchor';

// Initialize the SDK
const connection = new Connection('https://api.mainnet-beta.solana.com');
const loop = new Loop({ connection });

// Create a vault for value storage
const initVaultIx = await loop.vault.initializeVault(userWallet.publicKey);

// Capture value from a purchase (3% cashback)
const captureIx = await loop.vault.capture(
  vaultPda,
  new BN(3_000_000), // 3 Cred
  CaptureType.Shopping,
  'Amazon purchase',
  captureModulePubkey,
  credMint,
  vaultCredAccount
);

// Stack Cred for yield (15% APY for 90 days)
const stackIx = await loop.vault.stack(
  userWallet.publicKey,
  new BN(100_000_000), // 100 Cred
  90 // days
);

Runtime Sandbox + BYOAA/KYA interop

@loopprotocol/sdk is the full Loop protocol SDK: on-chain modules, PDAs, program IDs, IDLs, and enclave/broker primitives. It is the canonical home for the Runtime Sandbox signer contract (EnclaveSigner, EnclavePolicyInputs, and EnclaveClient) under @loopprotocol/sdk/enclave. Use it with @loopprotocol/sdk-byoaa for the KYA + BYOAA adopter flow instead of copying private broker code; sdk-byoaa/runtime-sandbox adapts this root signer contract for BYOAA receipt submission.

npm install @loopprotocol/sdk @loopprotocol/sdk-byoaa @solana/web3.js @coral-xyz/anchor
import { EnclaveClient } from "@loopprotocol/sdk/enclave";
import { DEVNET_PROGRAM_IDS } from "@loopprotocol/sdk/network";
import { LoopByoaaClient } from "@loopprotocol/sdk-byoaa/rest";
import { AttestedReceiptSubmitter } from "@loopprotocol/sdk-byoaa/solana";

const signer = new EnclaveClient({
  // Runtime Sandbox scoped broker proxy. This route requires a user/profile
  // scoped token; do not embed a shared public token in apps or docs.
  brokerUrl: "https://runtime-api-devnet-v0.looplocal.io/api/v1/runtime-sandboxes/byoaa-devnet-nitro-v0/broker",
  brokerPathMode: "root",
  tokenProvider: async () => getRuntimeTokenFromLoggedInUserProfile(),
});

const sessionPubkey = await signer.refreshSessionPubkey();
console.log("Runtime Sandbox session", sessionPubkey.toBase58());
console.log("Shopping", DEVNET_PROGRAM_IDS.SHOPPING.toBase58());
console.log("Vault", DEVNET_PROGRAM_IDS.VAULT.toBase58());

const kya = new LoopByoaaClient({ apiKey: process.env.LOOP_API_KEY!, env: "dev" });
// Use sdk-byoaa to register agents/permissions, submit BYOAA receipts, and
// export KYA audit packs. Use this SDK for Loop program IDs, on-chain modules,
// and enclave/Nitro broker primitives.

Runtime Sandbox v0 uses canonical BYOAA devnet IDs:

  • Shopping: FSqRkH7nkGHP3VpHwFE667PVAfLKfSGaPMgTrXpJZJoJ
  • Vault: 9gKRCrUpHv9CRHwYMmm2zP5bN1bUKgyi7BxuS5jifX4x

If an enclave or broker restarts, call refreshSessionPubkey() and compare it to the Runtime Sandbox status/profile before submitting on-chain. The enclave session key is intentionally enclave-local and can rotate after reboot.

Simplified API (for UI Integration)

For simpler use cases like launching agents and trading tokens, use LoopSDK:

import { LoopSDK } from '@loopprotocol/sdk';

const sdk = new LoopSDK(); // Defaults to mainnet

// Launch a service agent (pays 500 OXO)
const tx = await sdk.registerServiceAgent({
  name: 'ComputeRental v1',
  capabilities: ['Compute Rental', 'Data Licensing'],
  feePercentage: 5,
  launchToken: true
});
const signed = await wallet.signTransaction(tx);
await sdk.sendRaw(signed);

// Get bonding curve price
const price = await sdk.getBondingCurvePrice('agent-mint-address');
console.log(`Current price: $${price}`);

// Buy agent tokens
const buyTx = await sdk.buyAgentToken('agent-mint-address', 100);
const signedBuy = await wallet.signTransaction(buyTx);
await sdk.sendRaw(signedBuy);

// Access full SDK when needed
const fullLoop = sdk.core;
await fullLoop.vault.initializeVault(userWallet.publicKey);

LoopSDK vs Loop

| Feature | LoopSDK | Loop | |---------|-----------|--------| | API Style | Flat, simple | Modular, detailed | | Best For | UI integration | Advanced control | | Account Resolution | Automatic | Manual | | Use Case | Launch/trade agents | Full protocol access |

Features

  • 🏦 Vault Management - Create, deposit, withdraw, stack for yield
  • 💰 Cred Operations - Wrap/unwrap USDC, 1:1 backed stable value
  • 🎫 OXO Staking - Lock OXO for veOXO, earn fee share, governance
  • 🛒 11 Capture Modules - Shopping, Referral, Attention, Data, Compute, Network, Skill, Liquidity, Energy, Social, Insurance
  • 🔐 Security Integrations - Para (passkeys), Squads (policies), Reclaim (ZK proofs), TEE

API Reference

Initialization

import { Loop, LoopConfig } from '@loopprotocol/sdk';

const config: LoopConfig = {
  connection: new Connection(clusterApiUrl('mainnet-beta')),
  wallet: anchorWallet // optional, for signing
};

const loop = new Loop(config);

// Access program IDs
console.log(loop.programIds.VAULT);  // 76FgGQNTw9maaV82og6U33KMZw4FCw9yGJu4M75hJ3Z7
console.log(loop.programIds.CRED);   // FHVp7WrnUZq69aNZgYw2YNmitSdj8UCwoJ8C2A1M98JA
console.log(loop.programIds.OXO);    // 3qxTuF17rTdGFECPimRWu51uUycSwAL4ebd7w9s2xx4z

// Access constants
console.log(loop.constants.EXTRACTION_FEE_BPS); // 500 (5%)

Vault Module

// Check if vault exists
const exists = await loop.vault.exists(userPubkey);

// Get vault data
const vault = await loop.vault.getVault(userPubkey);
console.log(vault.credBalance.toString());
console.log(vault.stackedBalance.toString());

// Initialize vault
const initIx = await loop.vault.initializeVault(owner);

// Deposit Cred
const depositIx = await loop.vault.deposit(
  owner,
  new BN(100_000_000), // 100 Cred
  userCredAccount,
  vaultCredAccount
);

// Stack for yield (5-20% APY based on duration)
const stackIx = await loop.vault.stack(
  owner,
  new BN(50_000_000), // 50 Cred
  180 // 180 days = 18% APY
);

// Calculate APY for duration
const apy = loop.vault.calculateApy(365); // 2000 = 20%

// Claim yield from stack
const claimIx = await loop.vault.claimYield(owner, stackAddress);

// Unstack (after lock period)
const unstackIx = await loop.vault.unstack(owner, stackAddress);

// Withdraw Cred
const withdrawIx = await loop.vault.withdraw(
  owner,
  new BN(25_000_000),
  userCredAccount,
  vaultCredAccount
);

// Set agent permissions
const permIx = await loop.vault.setAgentPermission(
  owner,
  agentPubkey,
  PermissionLevel.Guided, // Can capture with limits
  new BN(100_000_000) // 100 Cred daily limit
);

// Inheritance lives in the loop-vtp program — not loop-vault.
// See loop-vtp's setup_inheritance / fund_inheritance / execute_inheritance.
// loop-vault only exposes `closeInheritanceConfig` as a one-shot migration
// to reclaim rent from legacy InheritanceConfig PDAs created by the
// now-removed `set_heir` instruction (V-H7).

// Extract all value (5% fee, emergency only)
const extractIx = await loop.vault.extract(
  owner,
  userCredAccount,
  vaultCredAccount,
  feeAccount
);

Cred Module

// Wrap USDC to Cred (1:1)
const wrapIx = await loop.cred.wrap(
  user,
  new BN(100_000_000), // 100 USDC → 100 Cred
  userUsdcAccount,
  userCredAccount,
  credMint,
  reserveVault
);

// Unwrap Cred to USDC (1:1)
const unwrapIx = await loop.cred.unwrap(
  user,
  new BN(50_000_000), // 50 Cred → 50 USDC
  userCredAccount,
  userUsdcAccount,
  credMint,
  reserveVault
);

// Check reserve status
const status = await loop.cred.getReserveStatus(reserveVault, credMint);
console.log(`Backing ratio: ${status.backingRatio.toNumber() / 100}%`);

OXO Module

// Lock OXO for veOXO (voting power)
// Duration multiplier: 6mo=0.25x, 1yr=0.5x, 2yr=1x, 4yr=2x
const lockIx = await loop.oxo.lockOxo(
  owner,
  new BN(1000_000_000), // 1000 OXO
  new BN(126144000), // 4 years = 2x → 2000 veOXO
  userOxoAccount,
  protocolOxoAccount
);

// Calculate veOXO for amount/duration
const veOxo = loop.oxo.calculateVeOxo(
  new BN(1000_000_000),
  new BN(63072000) // 2 years
);
console.log(veOxo.toString()); // 1000 veOXO

// Get current decayed veOXO balance
const currentVeOxo = await loop.oxo.getCurrentVeOxo(owner);

// Extend lock duration
const extendIx = await loop.oxo.extendLock(
  owner,
  new BN(31536000) // Add 1 year
);

// Claim fee share (for veOXO holders)
const claimFeesIx = await loop.oxo.claimFeeShare(
  owner,
  feePoolAccount,
  userCredAccount
);

// Unlock OXO (after lock expires)
const unlockIx = await loop.oxo.unlockOxo(
  owner,
  userOxoAccount,
  protocolOxoAccount
);

// Create agent token (500 OXO fee)
const createTokenIx = await loop.oxo.createAgentToken(
  creator,
  agentMint,
  'Agent Alpha',
  'AGENTA',
  'https://metadata.uri',
  creatorOxoAccount,
  treasuryOxoAccount
);

// Buy agent token on bonding curve
const buyIx = await loop.oxo.buyAgentToken(
  buyer,
  agentMint,
  new BN(100_000_000), // 100 OXO
  buyerOxoAccount,
  buyerAgentAccount,
  curveOxoAccount
);

// Sell agent token (1% fee)
const sellIx = await loop.oxo.sellAgentToken(
  seller,
  agentMint,
  new BN(500_000_000), // 500 agent tokens
  sellerOxoAccount,
  sellerAgentAccount,
  curveOxoAccount
);

Capture Modules

Shopping Capture

Value captured automatically via vault capture:

const captureIx = await loop.vault.capture(
  vaultPda,
  new BN(5_000_000), // 5 Cred cashback
  CaptureType.Shopping,
  'Target purchase #12345',
  captureModulePubkey,
  credMint,
  vaultCredAccount
);

Referral Capture

// Create tracked affiliate link
const link = await loop.referral.trackLink(
  'https://merchant.com/product/123',
  'my-affiliate-tag'
);

// Register conversion (called by merchant integration)
const conversion = await loop.referral.registerConversion(
  link.id,
  new BN(100_000_000), // 100 Cred purchase
  'tx_signature_proof'
);

// Claim earned commission
const claimIx = await loop.referral.claimCommission(
  user,
  ['conv_1', 'conv_2']
);

// Get affiliate stats
const stats = await loop.referral.getAffiliateStats(user);
console.log(`Conversion rate: ${stats.conversionRateBps / 100}%`);

Attention Capture

// Register for ad rewards
const profile = await loop.attention.registerForAds(
  user,
  {
    categories: ['tech', 'finance'],
    blockedCategories: ['gambling'],
    dailyLimit: 10,
    minReward: new BN(100_000) // 0.1 Cred minimum
  }
);

// Get available ads
const ads = await loop.attention.getAvailableAds(user);

// Submit view proof
const verification = await loop.attention.verifyView(
  user,
  'ad_123',
  viewProofData
);

// Claim rewards
const claimIx = await loop.attention.claimAttentionReward(user, []);

Data Capture

// Set data pricing
const config = await loop.data.setDataPricing(
  user,
  ['browsing', 'preferences'],
  new Map([
    ['browsing', new BN(5_000_000)],
    ['preferences', new BN(2_000_000)]
  ])
);

// License data to buyer
const license = await loop.data.licenseData(
  user,
  buyerPubkey,
  'browsing',
  {
    durationSeconds: new BN(2592000), // 30 days
    allowReshare: false,
    maxAccessCount: 100,
    allowedUseCases: ['analytics'],
    geoRestrictions: []
  }
);

// Revoke license
const revokeIx = await loop.data.revokeDataLicense(user, license.id);

// Claim revenue
const claimIx = await loop.data.claimDataRevenue(user);

Compute Capture

// Register compute resources
const profile = await loop.compute.registerResources(user, {
  cpu: 8,
  gpu: 2,
  storage: 500,
  bandwidth: 1000
});

// Accept task
const acceptance = await loop.compute.acceptTask(
  user,
  'task-abc123',
  new BN(50_000_000) // 50 Cred bid
);

// Submit result
const submission = await loop.compute.submitTaskResult(
  user,
  'task-abc123',
  resultHash,
  proof
);

// Claim rewards
const claimIx = await loop.compute.claimComputeReward(user, ['task-abc123']);

Network Capture

// Register as network node
const registration = await loop.network.registerNode(
  user,
  NodeType.Oracle,
  ['price_feed', 'data_attestation']
);

// Submit governance vote
const vote = await loop.network.submitVote(
  user,
  'prop-upgrade-v2',
  true,
  eligibilityProof
);

// Submit attestation
const attestation = await loop.network.submitAttestation(
  user,
  dataHash,
  AttestationType.PriceOracle
);

// Claim participation rewards
const claimIx = await loop.network.claimParticipationReward(user, activityIds);

Skill Capture

// Export behavior model
const model = await loop.skill.exportBehaviorModel(
  user,
  SkillType.Trading,
  AnonymizationLevel.Differential
);

// License skill to buyer
const license = await loop.skill.licenseSkill(
  user,
  buyerPubkey,
  model.modelId,
  {
    duration: new BN(31536000), // 1 year
    price: new BN(100_000_000), // 100 Cred
    usageLimit: new BN(0), // unlimited
    allowSublicense: false,
    commercialUse: true
  }
);

// Claim skill revenue
const claimIx = await loop.skill.claimSkillRevenue(user);

Security Integrations

Para (Passkeys)

// Create passkey wallet
const wallet = await loop.para.createPasskeyWallet(userId, {
  deviceId: 'device-123',
  deviceType: 'mobile',
  platform: 'iOS',
  biometricCapable: true
});

// Get scoped session key
const sessionKey = await loop.para.getSessionKey(userId, {
  canCapture: true,
  canStack: true,
  canTransfer: false,
  maxTransferAmount: 0,
  allowedPrograms: [loop.programIds.VAULT]
}, 3600); // 1 hour

// Sign with passkey
const signed = await loop.para.signWithPasskey(userId, transaction);

Squads (Policies)

// Create smart account
const account = await loop.squads.createSmartAccount(owner, {
  threshold: 2,
  members: [
    { pubkey: member1, weight: 1 },
    { pubkey: member2, weight: 1 }
  ],
  timeLockSeconds: 86400 // 24 hours
});

// Set agent policy
const policy = await loop.squads.setAgentPolicy(
  account.address,
  agentKey,
  {
    dailyLimit: 1000_000_000, // 1000 Cred
    allowedInstructions: ['capture', 'stack'],
    timelock: 0,
    requiresApproval: false
  }
);

// Propose transaction for multi-sig
const proposal = await loop.squads.proposeTransaction(
  account.address,
  transaction
);

// Emergency pause
const pauseIx = await loop.squads.pauseAgent(account.address, agentKey);

Reclaim (ZK Proofs)

// Generate ZK proof of capture
const proof = await loop.reclaim.generateCaptureProof(
  CaptureType.Shopping,
  { orderId: '123', amount: 100, merchant: 'Amazon' }
);

// Verify proof
const result = await loop.reclaim.verifyProof(proof, {
  merchant: 'Amazon'
});

// Submit verified capture
const capture = await loop.reclaim.submitVerifiedCapture(
  user,
  proof,
  CaptureType.Shopping
);

TEE (Trusted Execution)

// Get enclave attestation
const attestation = await loop.tee.getEnclaveAttestation('enclave-123');

// Verify enclave code
const verified = await loop.tee.verifyEnclaveCode(
  attestation,
  expectedCodeHash
);

// Register trusted agent
const agent = await loop.tee.registerTrustedAgent(user, attestation);

Configuration

Network Selection

import { Connection, clusterApiUrl } from '@solana/web3.js';

// Mainnet
const mainnet = new Connection(clusterApiUrl('mainnet-beta'));

// Devnet
const devnet = new Connection(clusterApiUrl('devnet'));

const loop = new Loop({ connection: mainnet });

Custom RPC

const connection = new Connection('https://your-rpc-endpoint.com', {
  commitment: 'confirmed',
  confirmTransactionInitialTimeout: 60000
});

Commitment Levels

const connection = new Connection(rpcUrl, {
  commitment: 'finalized' // 'processed' | 'confirmed' | 'finalized'
});

Error Handling

import { Loop } from '@loopprotocol/sdk';

try {
  const vault = await loop.vault.getVault(userPubkey);
  if (!vault) {
    console.log('Vault does not exist');
    return;
  }
  
  const withdrawIx = await loop.vault.withdraw(
    owner,
    new BN(amount),
    userCredAccount,
    vaultCredAccount
  );
} catch (error) {
  if (error.message.includes('insufficient funds')) {
    console.error('Not enough Cred in vault');
  } else if (error.message.includes('stack locked')) {
    console.error('Cannot withdraw stacked Cred before lock expires');
  } else {
    console.error('Unexpected error:', error);
  }
}

Examples

See the examples folder for complete working examples:

PDA Derivation

All PDAs can be derived using the LoopPDA helper:

import { LoopPDA } from '@loopprotocol/sdk';

// Vault PDA
const [vaultPda, bump] = LoopPDA.vault(owner);

// Stack record PDA
const [stackPda, stackBump] = LoopPDA.stackRecord(vault, stackIndex);

// Agent permission PDA
const [permPda, permBump] = LoopPDA.agentPermission(vault, agent);

// veOXO position PDA
const [vePda, veBump] = LoopPDA.veOxoPosition(owner);

// Bonding curve PDA
const [curvePda, curveBump] = LoopPDA.bondingCurve(agentMint);

// Escrow PDA
const [escrowPda, escrowBump] = LoopPDA.escrow(sender, recipient, createdAt);

Contributing

We welcome contributions! Please see our Contributing Guide for details.

# Clone the repo
git clone https://github.com/southerncory/loop-protocol.git
cd loop-protocol/sdk

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Lint
npm run lint

License

MIT © Loop Protocol


Built with ❤️ by Loop Protocol

Package exports and lighter imports

The root import remains backward-compatible:

import { Loop } from "@loopprotocol/sdk";

For new integrations, prefer narrower subpath imports so bundlers and tests do not need to traverse the full SDK surface:

import { PROGRAM_IDS } from "@loopprotocol/sdk/constants";
import { LoopPDA } from "@loopprotocol/sdk/pda";
import { fetchAndVerify } from "@loopprotocol/sdk/security";
import { createReadOnlyShoppingModule } from "@loopprotocol/sdk/shopping";

Available additive subpaths include constants, devnet, network, pda, errors, simple, types, utils, modules, security, enclave, idl, vault, cred, oxo, avp, vtp, and shopping. These are additive organization exports; existing root imports continue to work.