Skip to main content

TypeScript SDK

The official TypeScript SDK — zero dependencies, works in Node 18+ and any modern runtime with native fetch.

Installation

npm install @sova-intel/sdk
# or
pnpm add @sova-intel/sdk

Setup

API key

import { SovaIntelClient } from "@sova-intel/sdk";

const client = new SovaIntelClient({
baseUrl: "https://api.sova-intel.com/api/v1",
auth: {
kind: "apikey",
apiKey: process.env.SOVA_API_KEY!,
},
});

X402 autonomous payment

import { SovaIntelClient } from "@sova-intel/sdk";

const client = new SovaIntelClient({
baseUrl: "https://api.sova-intel.com/api/v1",
auth: {
kind: "x402",
buildPayment: async (payTo, amountBaseUnits) => {
// build USDC transferChecked tx, return base64 payment header
// see Authentication page for full implementation
},
},
});

Examples

Get a wallet HUD (1cr)

const hud = await client.getWalletHud("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU");

console.log(hud.behaviorCode); // "W"
console.log(hud.winRate); // 0.67
console.log(hud.trimmedMeanPnl); // 12.4
console.log(hud.dataQualityTier); // "GOLD"
console.log(hud.isBot); // false

The SDK handles cold wallet 202 fallback automatically — you always get back a WalletHud.

Full wallet profile (5cr)

const profile = await client.getWalletProfile("7xKXtg...");

console.log(profile.summary.realizedPnl); // 142.87
console.log(profile.behavior?.tradingStyle); // "swing"
console.log(profile.pnl?.allTime?.netPnlSol); // 152.17

// KOL identity — present when the wallet belongs to a known trader
if (profile.kol) {
console.log(profile.kol.name); // "Ansem"
console.log(profile.kol.twitter); // "https://x.com/blknoiz06"
}

Per-token PnL table (3cr)

const tokens = await client.getWalletTokens("7xKXtg...", {
pageSize: 50,
sortBy: "realizedPnlSol",
sortOrder: "DESC",
});

for (const token of tokens.data) {
console.log(token.tokenAddress, token.realizedPnlSol, token.roi);
}

Batch HUD for multiple wallets (5cr flat)

const batch = await client.batchHud(["addr1", "addr2", "addr3"]);

for (const [address, hud] of Object.entries(batch.huds)) {
console.log(address, hud.behaviorCode, hud.winRate);
}

// Wallets queued for analysis (missing/stale) — each has a jobId to poll
console.log("Queued:", batch.queued);
// Wallets skipped (invalid, over limit, etc.)
console.log("Skipped:", batch.skipped);

Holder profiles — async (20cr)

The poll variant queues the job, polls until complete, and returns the result:

import type { HolderProfilesResult } from "@sova-intel/sdk";

const result = await client.pollHolderProfiles<HolderProfilesResult>(
"So11111111111111111111111111111111111111112",
20, // top N holders
);

for (const holder of result.profiles) {
console.log(holder.rank, holder.walletAddress, holder.supplyPercent, holder.behaviorType);
}

Similarity analysis — async (20cr)

import type { SimilarityResult } from "@sova-intel/sdk";

const result = await client.pollSimilarity<SimilarityResult>(["addr1", "addr2", "addr3"]);

console.log(result.globalMetrics.averageSimilarity); // 0.73
for (const pair of result.pairwiseSimilarities) {
console.log(pair.walletA, pair.walletB, pair.binaryScore, pair.capitalScore);
}

Bundled deep analysis — async (35cr)

Holder profiles + similarity in one call. The server discovers holder addresses itself — no need to supply them upfront. Results are returned sequentially: holder-profiles first, then similarity (chained automatically by the processor).

import type { HolderProfilesResult, SimilarityResult } from "@sova-intel/sdk";

const { holderProfiles, similarity } = await client.pollDeepAnalysis<
HolderProfilesResult,
SimilarityResult
>("So11111111111111111111111111111111111111112", 20);

for (const holder of holderProfiles.profiles) {
console.log(holder.rank, holder.walletAddress, holder.behaviorType);
}
console.log(similarity.globalMetrics.averageSimilarity);

If you want the job descriptors without blocking, use queueDeepAnalysis:

const jobs = await client.queueDeepAnalysis("TOKEN_MINT", 20);

// jobs.holderProfiles.jobId — poll this first
// jobs.similarity.resultKey — poll this after holderProfiles completes
console.log(jobs.holderProfiles.monitoringUrl);
console.log(jobs.similarity.resultKey);

Agent-optimised holder profiles (20cr)

Returns the same behavioral data as pollHolderProfiles but in a compact, agent-friendly shape: a population-level aggregate block first, then slim per-holder profiles (~1–2k tokens vs ~10k+ for the full shape).

import type { AgentHolderProfilesResult } from "@sova-intel/sdk";

const result = await client.pollTokenHoldersAgent(
"So11111111111111111111111111111111111111112",
20,
);

// Population-level signal — make a buy/skip decision without scanning profiles
console.log(result.aggregate.top5SupplyPct); // supply % by top 5 holders
console.log(result.aggregate.avgWalletPnlSol); // average holder PnL
console.log(result.aggregate.behaviorDistribution);
// [{ behaviorType: "SWING_TRADER", count: 8, supplyPct: 31.2 }, ...]

// Per-holder profiles — currentHoldings[] replaced with holdingsSummary
for (const holder of result.profiles) {
console.log(holder.rank, holder.behaviorType, holder.holdingsSummary.totalPositions);
}

Use the queue variant if you need the job descriptor:

const job = await client.queueTokenHoldersAgent("TOKEN_MINT", 20);
// job.agentResultKey — fetch via GET /jobs/result/by-key?key={agentResultKey}
// job.resultKey — full developer result still available here

Agent-optimised similarity (20cr)

Returns a compact similarity result with a single coordinationScore (0–1), filtered meaningful pairs, and coordination flags. Debug fields and low-signal pairs are dropped.

import type { AgentSimilarityResult } from "@sova-intel/sdk";

const result = await client.pollWalletSimilarityAgent(["addr1", "addr2", "addr3"]);

// Single number for quick agent decisions
console.log(result.coordinationScore); // 0.82 — high coordination signal

// Only pairs that cleared the signal filter (score >= 0.15 OR >=20 shared tokens)
for (const pair of result.pairs) {
console.log(pair.walletA, pair.walletB, pair.similarityScore);
if (pair.flag) {
console.log("Flag:", pair.flag);
// "HIGH_SIMILARITY" | "HIGH_OVERLAP" | "HIGH_SIMILARITY_AND_OVERLAP"
}
}

console.log(result.metadata.flaggedPairs); // pairs with coordination signal
console.log(result.metadata.meaningfulPairs); // total pairs with signal

Client Configuration

const client = new SovaIntelClient({
baseUrl: "https://api.sova-intel.com/api/v1", // required
auth: { ... }, // required
pollIntervalMs: 5000, // default: 5000ms
maxPollAttempts: 60, // default: 60 (~5 min)
});

Error Handling

import { SovaIntelClient, SovaHttpError, X402PaymentError } from "@sova-intel/sdk";

try {
const hud = await client.getWalletHud(address);
} catch (err) {
if (err instanceof X402PaymentError) {
// Payment failed
console.error("Payment error:", err.body);
} else if (err instanceof SovaHttpError) {
switch (err.status) {
case 404: console.error("Wallet not found or result expired"); break;
case 422: console.error("System/program wallet — skip"); break;
case 500: console.error("Server error — retry with backoff"); break;
}
}
}

Exported Types

import type {
WalletHud,
WalletProfileResponse,
WalletSummary,
WalletBehavior,
KolIdentity,
PnlAllTime,
DataQualityTier,
TokenPnlRow,
TokenPnlResponse,
TokenPnlParams,
BatchHudResponse,
BatchHudQueuedEntry,
HolderProfile,
HolderProfilesResult,
SimilarityResult,
SimilarityPairResult,
SimilarityGlobalMetrics,
// Agent-optimised results
AgentHolderProfilesResult,
AgentHolderAggregate,
AgentHolderProfile,
AgentHoldingsSummary,
AgentSimilarityResult,
AgentSimilarityPair,
// Job accepted responses (agent variants)
HolderProfilesAgentJobAcceptedResponse,
SimilarityAgentJobAcceptedResponse,
// Async jobs
JobAcceptedResponse,
DeepJobAcceptedResponse,
JobStatus,
SovaIntelClientConfig,
Auth,
ApiKeyAuth,
X402Auth,
} from "@sova-intel/sdk";

Method Reference

MethodEndpointCredits
getWalletProfile(addr)GET /intel/wallet/:addr5
getWalletHud(addr)GET /intel/wallet/:addr/hud1
getWalletTokens(addr, params?)GET /intel/wallet/:addr/tokens3
batchHud(wallets[])POST /intel/wallets/batch-hud5
queueHolderProfiles(mint, topN?)POST /intel/token/:mint/holders20
pollHolderProfiles(mint, topN?)queue + auto-poll helperno extra charge
queueTokenHoldersAgent(mint, topN?)POST /intel/token/:mint/holders/agent20
pollTokenHoldersAgent(mint, topN?)queue + auto-poll helperno extra charge
queueSimilarity(wallets[])POST /intel/wallets/similarity20
pollSimilarity(wallets[])queue + auto-poll helperno extra charge
queueWalletSimilarityAgent(wallets[])POST /intel/wallets/similarity/agent20
pollWalletSimilarityAgent(wallets[])queue + auto-poll helperno extra charge
queueDeepAnalysis(mint, topN?)POST /intel/token/:mint/holders/deep35
pollDeepAnalysis(mint, topN?)queue + auto-poll helperno extra charge