Developers
TypeScript SDK
@pinecode/sdk reference. Recall, contribute, stake, and earn — typed and signed.
Install
-accent">pnpm add @pinecode/sdkRequires Node 20+. Browser builds ship as ESM. No peer dependencies — ethers v6 is bundled.
Pinecode client
import { Pinecode, type PinecodeOptions } from class="text-success/90">"@pinecode/sdk";const pinecode = new Pinecode({ network: class="text-success/90">"base", class=class="text-success/90">"text-fg-subtle italic">// class="text-success/90">"base" | class="text-success/90">"base-sepolia" | { rpcUrl, chainId } gateway: class="text-success/90">"https:class="text-fg-subtle italicclass="text-success/90">">//api.pinecode.xyz", // override the default gateway privateKey: process.env.PRIVATE_KEY, class=class="text-success/90">"text-fg-subtle italic">// optional — read-only without it defaultModel: class="text-success/90">"openai/text-embedding-3-large", timeoutMs: 8_000,});The client is safe to share across requests and threads. It maintains a small recall cache and a nonce queue.
recall()
type RecallParams = { query: string; limit?: number; class=class="text-success/90">"text-fg-subtle italic">// default 5, max 50 minScore?: number; class=class="text-success/90">"text-fg-subtle italic">// 0–1 similarity threshold tags?: string[]; class=class="text-success/90">"text-fg-subtle italic">// restrict to seeds tagged with all of these paymentMax?: string; class=class="text-success/90">"text-fg-subtle italic">// USDC ceiling per call, e.g. class="text-success/90">"0.01" embeddingModel?: string; preferIndexer?: string; class=class="text-success/90">"text-fg-subtle italic">// pin to a specific indexer};type RecallHit = { seedId: number; cid: string; title?: string; content: string; score: number; contributor: class="text-success/90">`0x${string}`; contributorEns?: string; tags: string[]; qualityScore: number; feePaid: string; class=class="text-success/90">"text-fg-subtle italic">// USDC};const hits: RecallHit[] = await pinecode.recall({ query: class="text-success/90">"..." });✓Streaming recall
Use
pinecode.recall.stream(...) to receive partial results via Server-Sent Events. Useful when you want to start summarizing while the indexer is still ranking.contribute()
type ContributeParams = { content: string | Uint8Array; title?: string; source?: string; tags?: string[]; embeddingModel?: string; bond?: string; class=class="text-success/90">"text-fg-subtle italic">// PINE bond, default = protocol minimum};type ContributeReceipt = { seedId: number; cid: string; txHash: class="text-success/90">`0x${string}`; bondLocked: string;};const receipt = await pinecode.contribute({ content: class="text-success/90">"ERC-4337 introduces UserOperations…", source: class="text-success/90">"https:class="text-fg-subtle italicclass="text-success/90">">//eips.ethereum.org/EIPS/eip-4337", tags: [class="text-success/90">"ethereum", class="text-success/90">"erc-4337"],});stake()
await pinecode.stake({ seedId: 418293, amount: class="text-success/90">"250", class=class="text-success/90">"text-fg-subtle italic">// PINE duration: class="text-success/90">"30d", class=class="text-success/90">"text-fg-subtle italic">// class="text-success/90">"7d" | class="text-success/90">"30d" | class="text-success/90">"90d" | class="text-success/90">"365d"});class=class="text-success/90">"text-fg-subtle italic">// Withdraw after lock expiresawait pinecode.unstake({ seedId: 418293, positionId: 42 });rewards()
const summary = await pinecode.rewards.summary();class=class="text-success/90">"text-fg-subtle italic">// { unclaimedUsdc: class="text-success/90">"12.40", unclaimedPinecode: class="text-success/90">"184.2", nextEpoch: class="text-success/90">"2026-05-22T00:00:00Z" }await pinecode.rewards.claim({ epochs: [142, 143] });Events & streams
pinecode.events.on(class="text-success/90">"recall", (e) => { 90">console.log(e.seedId, e.feePaid, e.querier);});pinecode.events.on(class="text-success/90">"contribute", (e) => { 90">console.log(e.seedId, e.contributor);});const stop = pinecode.events.subscribe({ topics: [class="text-success/90">"challenge", class="text-success/90">"slash"], fromBlock: class="text-success/90">"latest",});Errors
The SDK throws typed errors that you can switch on:
import { isPinecodeError, PinecodeErrorCode } from class="text-success/90">"@pinecode/sdk";try { await pinecode.recall({ query: class="text-success/90">"..." });} catch (err) { if (isPinecodeError(err)) { switch (err.code) { case PinecodeErrorCode.PaymentExceedsCeiling: /* ... */ break; case PinecodeErrorCode.GatewayUnavailable: /* ... */ break; case PinecodeErrorCode.IndexerStale: /* ... */ break; case PinecodeErrorCode.InsufficientBalance: /* ... */ break; } }}Docs v0.6.2