Skip to main content
The ThreatClient provides access to Webacy’s threat and risk analysis APIs. Use it to analyze addresses for security risks, screen for sanctions, check smart contract vulnerabilities, verify URL safety, assess ERC-4626 vault risk, and monitor stablecoin/RWA depeg risk.

Initialization

import { ThreatClient, Chain } from '@webacy-xyz/sdk';

const client = new ThreatClient({
  apiKey: process.env.WEBACY_API_KEY,
  defaultChain: Chain.ETH, // Optional: set default chain
});

Resources

The ThreatClient provides access to these resources:
ResourceDescription
addressesAddress risk analysis, sanctions screening, poisoning detection, quick profiles
contractsSmart contract security analysis and code analysis
urlURL safety and phishing detection
walletsWallet activity and approval analysis
ledgerHardware wallet transaction scanning
accountTraceFund flow tracing
transactionsTransaction risk analysis
scanTransaction and EIP-712 message scanning
batchBatch analysis for addresses, contracts, and transactions
vaultsERC-4626 vault risk scoring and due diligence
rwaStablecoin and RWA depeg risk monitoring
usageAPI usage statistics

Addresses

Analyze Address Risk

Get comprehensive risk analysis for any blockchain address.
const result = await client.addresses.analyze(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  { chain: Chain.ETH }
);

console.log(result.overallRisk);  // 0-100 risk score
console.log(result.issues);       // Array of risk factors
console.log(result.isContract);   // true if smart contract
Response:
{
  "count": 1,
  "medium": 0,
  "high": 1,
  "overallRisk": 75.5,
  "issues": [
    {
      "tag": "Mixer User",
      "severity": "high",
      "description": "Address has interacted with mixing services"
    }
  ],
  "isContract": false
}
Options:
OptionTypeDescription
chainChainBlockchain to analyze (optional if defaultChain set)
modulesRiskModule[]Specific risk modules to run
detailedbooleanInclude detailed analysis data
deployerRiskbooleanInclude deployer risk for contracts

Check Sanctions

Screen an address against OFAC and other sanctions lists.
const result = await client.addresses.checkSanctioned(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  { chain: Chain.ETH }
);

if (result.is_sanctioned) {
  console.error('Address is sanctioned!');
  console.log(result.sanction_details);
}

Check Address Poisoning

Detect address poisoning (dust attack) attempts.
const result = await client.addresses.checkPoisoning(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  { chain: Chain.ETH }
);

if (result.is_poisoned) {
  console.warn('Address poisoning detected!');
  console.log(result.poisoning_details?.similar_addresses);
}

Get Quick Profile

Get a lightweight risk profile with optional token approvals.
const result = await client.addresses.getQuickProfile(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  {
    chain: Chain.ETH,
    withApprovals: true,  // Include token approvals
  }
);

console.log(`Risk score: ${result.riskScore}`);
console.log(`Risk level: ${result.riskLevel}`);
console.log(`Account age: ${result.accountAge} days`);

// Check approvals if requested
for (const approval of result.approvals ?? []) {
  console.log(`${approval.symbol} approved to ${approval.spenderName}`);
}
Options:
OptionTypeDescription
chainChainBlockchain to analyze (ETH, BASE, BSC, POL, OPT, ARB, SOL)
withApprovalsbooleanInclude token approval data
hideTrustFlagsbooleanHide trust flags in response

Contracts

Analyze Contract

Get security analysis for a smart contract.
const result = await client.contracts.analyze(
  '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
  { chain: Chain.ETH }
);

console.log(result.overallRisk);
console.log(result.vulnerabilities);

Get Contract Tax

Check buy/sell tax for a token contract.
const result = await client.contracts.getTax(
  '0xTokenAddress...',
  { chain: Chain.ETH }
);

console.log(`Buy tax: ${result.buyTax}%`);
console.log(`Sell tax: ${result.sellTax}%`);

Get Code Analysis

Perform static code analysis on a contract’s source code.
const result = await client.contracts.getCodeAnalysis(
  '0xContractAddress...',
  {
    chain: Chain.ETH,
    refreshCache: false,  // Use cached results if available
  }
);

console.log(`Total findings: ${result.findings.length}`);

for (const finding of result.findings) {
  console.log(`[${finding.severity}] ${finding.title}`);
  console.log(`  ${finding.description}`);
  console.log(`  Location: ${finding.location}`);
}
Response:
{
  "contractAddress": "0x...",
  "chain": "eth",
  "findings": [
    {
      "title": "Reentrancy vulnerability",
      "description": "External call before state update",
      "severity": "high",
      "location": "withdraw() line 45",
      "recommendation": "Use checks-effects-interactions pattern"
    }
  ],
  "analyzedAt": "2024-01-20T12:00:00Z"
}

URL Safety

Check URL

Analyze a URL for phishing and malware.
const result = await client.url.check('https://suspicious-site.com');

if (result.isPhishing) {
  console.error('Phishing site detected!');
}

console.log(result.riskScore);
console.log(result.categories);

Wallets

Get Approvals

List token approvals for a wallet.
const result = await client.wallets.getApprovals(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  { chain: Chain.ETH }
);

for (const approval of result.approvals) {
  console.log(`${approval.token} approved to ${approval.spender}`);
  console.log(`Amount: ${approval.amount}`);
}

Get Transactions

Get risk-scored transaction history for a wallet.
const result = await client.wallets.getTransactions(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  { chain: Chain.ETH }
);

console.log(`Risk score: ${result.overallRisk}`);
console.log(`Issues found: ${result.count}`);

for (const issue of result.issues) {
  console.log(`[${issue.severity}] ${issue.tag}: ${issue.description}`);
}
Response:
{
  "count": 2,
  "overallRisk": 45,
  "issues": [
    {
      "tag": "Risky Interaction",
      "severity": "medium",
      "description": "Interacted with flagged address"
    }
  ]
}

Account Trace

Trace Fund Flows

Trace multi-hop fund flows for compliance and forensics.
const result = await client.accountTrace.trace(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  { chain: Chain.ETH }
);

console.log(`Total connections: ${result.summary.totalConnections}`);
console.log(`High-risk: ${result.summary.highRiskConnections}`);

for (const conn of result.connections) {
  console.log(`${conn.address}: ${conn.relationship} - ${conn.riskFlags.join(', ')}`);
}
Response:
{
  "summary": {
    "totalConnections": 15,
    "highRiskConnections": 3
  },
  "connections": [
    {
      "address": "0xabc...",
      "relationship": "direct_transfer",
      "riskFlags": ["mixer_user", "high_risk"],
      "depth": 1
    }
  ]
}

Usage

Get API Usage

Monitor your API usage and quotas.
const usage = await client.usage.get();

console.log(`Requests used: ${usage.requestsUsed}`);
console.log(`Requests remaining: ${usage.requestsRemaining}`);
console.log(`Reset date: ${usage.resetDate}`);

Get Max RPS

Get maximum requests per second for an organization over a time period.
const maxRps = await client.usage.getMaxRps({
  organization: 'my-org',
  from: Date.now() - 86400000, // 24 hours ago
  to: Date.now(),
});

console.log(`Max RPS: ${maxRps}`);
Options:
OptionTypeRequiredDescription
organizationstringYesOrganization identifier
fromnumberYesStart time as Unix timestamp in milliseconds (e.g., Date.now() - 86400000)
tonumberYesEnd time as Unix timestamp in milliseconds (e.g., Date.now())

Transactions

Analyze Transaction

Get risk analysis for a blockchain transaction.
const result = await client.transactions.analyze(
  '0xTransactionHash...',
  { chain: Chain.ETH }
);

console.log(`Risk score: ${result.riskScore}`);
console.log(`Risk level: ${result.riskLevel}`);

for (const tag of result.riskTags ?? []) {
  console.log(`Risk: ${tag.tag} - ${tag.description}`);
}
Supported chains: ETH, BASE, BSC, POL, OPT, ARB, SOL, STELLAR Options:
OptionTypeDescription
chainChainBlockchain to analyze
hideTrustFlagsbooleanHide trust flags in response

Scan

Scan Transaction

Scan a raw transaction for risks before signing.
const result = await client.scan.scanTransaction(
  '0xSignerAddress...',
  {
    tx: {
      from: '0xSignerAddress...',
      raw: '0xRawTransactionData...',
    },
    chain: 1, // Chain ID (1 = Ethereum)
    domain: 'app.example.com',  // Optional: dApp domain
  }
);

console.log(`Risk level: ${result.riskLevel}`);  // low, medium, high
console.log(`Warnings: ${result.warnings.length}`);

// Check asset changes
for (const change of result.assetChanges ?? []) {
  console.log(`${change.type}: ${change.amount} ${change.symbol}`);
}
Supported chain IDs: 1 (ETH), 56 (BSC), 137 (POL), 10 (OPT), 42161 (ARB), 8453 (BASE)

Scan EIP-712 Message

Scan an EIP-712 typed data message before signing.
const result = await client.scan.scanEip712(
  '0xSignerAddress...',
  {
    msg: {
      from: '0xSignerAddress...',
      data: {
        types: {
          EIP712Domain: [
            { name: 'name', type: 'string' },
            { name: 'version', type: 'string' },
            { name: 'chainId', type: 'uint256' },
          ],
          Permit: [
            { name: 'owner', type: 'address' },
            { name: 'spender', type: 'address' },
            { name: 'value', type: 'uint256' },
          ],
        },
        primaryType: 'Permit',
        domain: {
          name: 'MyToken',
          version: '1',
          chainId: 1,
        },
        message: {
          owner: '0x...',
          spender: '0x...',
          value: '1000000000000000000',
        },
      },
    },
    domain: 'app.example.com',
  }
);

console.log(`Risk level: ${result.riskLevel}`);
console.log(`Message type: ${result.messageType}`);

Batch

You can analyze multiple addresses, contracts, or transactions in a single request using the batch methods.
Prerequisites: You need an initialized ThreatClient and a Chain import. See Installation if you haven’t set up the SDK yet.

Batch Addresses

You can analyze multiple addresses for risk in one call.
const result = await client.batch.addresses({
  addresses: [
    '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
    '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  ],
  chain: Chain.ETH,
});

Batch Contracts

You can analyze multiple smart contracts for risk in one call.
const result = await client.batch.contracts({
  addresses: [
    '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
    '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  ],
  chain: Chain.ETH,
});

Batch Transactions

You can analyze multiple transactions for risk in one call.
const result = await client.batch.transactions({
  transactions: [
    '0xabc123...',
    '0xdef456...',
  ],
  chain: Chain.ETH,
});
Request parameters:
ParameterTypeDescription
addresses / transactionsstring[]List of addresses or transaction hashes to analyze
chainChainTarget blockchain

Advanced: Large Batches

When you have a large number of items to analyze, you can split them into chunks and handle partial failures gracefully.
import { ThreatClient, Chain } from '@webacy-xyz/sdk';

const client = new ThreatClient({ apiKey: process.env.WEBACY_API_KEY });

async function batchAnalyzeAddresses(addresses: string[], chain: Chain) {
  const CHUNK_SIZE = 50;
  const successes: Record<string, unknown>[] = [];
  const failures: { addresses: string[]; error: string }[] = [];

  // Split into chunks
  for (let i = 0; i < addresses.length; i += CHUNK_SIZE) {
    const chunk = addresses.slice(i, i + CHUNK_SIZE);

    try {
      const result = await client.batch.addresses({
        addresses: chunk,
        chain,
      });
      successes.push(result);
    } catch (error) {
      failures.push({
        addresses: chunk,
        error: error instanceof Error ? error.message : String(error),
      });
    }
  }

  console.log(`Completed: ${successes.length} chunks succeeded, ${failures.length} failed`);
  return { successes, failures };
}

Vaults

List Vaults

Get a paginated list of ERC-4626 vaults with risk scores and ecosystem aggregates.
const result = await client.vaults.list();

console.log(`Total vaults: ${result.pagination.total}`);
console.log(`Total TVL: $${result.aggregates.total_tvl_usd}`);

for (const vault of result.items) {
  console.log(`${vault.metadata.name} — score: ${vault.risk.score}, TVL: $${vault.metadata.tvl_usd}`);
}
Filtering and sorting:
// Filter by protocol, chain, and risk tier
const risky = await client.vaults.list({
  protocol: 'morpho',
  chain: Chain.ETH,
  tier: 'high',
  sort: 'score_desc',
});

// Filter by underlying asset and attention needed
const urgent = await client.vaults.list({
  underlying: 'USDC',
  attentionNeeded: true,
});

// Filter by risk flags
const looping = await client.vaults.list({
  riskFlags: 'vault-high-looping,vault-upgradeable',
  riskFlagsMode: 'any',
});
Options:
OptionTypeDescription
chainChainFilter by chain (ETH, ARB, BASE, OPT, POL, BSC)
tierstringRisk tier: low, medium, high, critical, unknown
protocolstringDeFi protocol: morpho, aave, compound, euler, spark, fluid, beefy, yearn
contractTypestringVault type: erc4626_vault, strategy_vault, lending_wrapper, bridge_vault
underlyingstringUnderlying asset symbol (e.g. USDC)
underlyingRiskstringUnderlying risk tier: battle_tested, medium_risk, high_risk, crypto, unknown
minTvlnumberMinimum TVL in USD
minScorenumberMinimum risk score (0-100)
maxScorenumberMaximum risk score (0-100)
attentionNeededbooleanOnly vaults needing attention
riskFlagsstringComma-separated risk tag keys (e.g. vault-high-looping,vault-upgradeable)
riskFlagsModestringCombine flags with any (OR) or all (AND)
qstringSearch by name, symbol, or address
sortstringSort: score_desc, score_asc, tvl_desc, tvl_asc, apy_desc, looping_desc, name_asc
pagenumberPage number (1-indexed, default 1)
pageSizenumberItems per page (default 50, max 500)

List Vaults with Cursor Pagination

For efficient sequential pagination, use cursor-based pagination.
// First page using offset pagination
const first = await client.vaults.list({ pageSize: 100 });

// Subsequent pages using cursor
const second = await client.vaults.listCursor({
  cursor: 'opaque-cursor-from-previous-response',
  limit: 100,
});

if (second.next_cursor) {
  const third = await client.vaults.listCursor({
    cursor: second.next_cursor,
    limit: 100,
  });
}

Get Vault Detail

Get detailed risk data for a specific vault, including looping markets, composition, and protocol-specific data.
const detail = await client.vaults.get(
  '0x1234...abcd',
  { chain: Chain.ETH }
);

console.log(`Score: ${detail.risk.score}`);
console.log(`TVL: $${detail.metadata.tvl_usd}`);
console.log(`Protocol: ${detail.metadata.protocol}`);
console.log(`Listing verdict: ${detail.metadata.listing_verdict}`);

// Check risk issues
for (const issue of detail.risk.issues) {
  for (const tag of issue.tags) {
    console.log(`[${tag.severity}] ${tag.name}: ${tag.description}`);
  }
}

// Check Morpho-specific data
if (detail.morpho) {
  console.log(`Morpho liquidity: $${detail.morpho.liquidity_usd}`);
  console.log(`Bad debt: $${detail.morpho.bad_debt_usd}`);
}

// Check vault composition
for (const asset of detail.vault_composition) {
  console.log(`${asset.symbol}: ${asset.share_pct}%`);
}

// Check Webacy code analysis findings
console.log(`Code risk: ${detail.webacy.code_risk_score}`);
console.log(`Contract risk: ${detail.webacy.contract_risk_score}`);
Options:
OptionTypeRequiredDescription
chainChainYesBlockchain network

Depeg Monitor (RWA)

List Pegged Tokens

Get a paginated list of stablecoins and RWAs with depeg risk scores and ecosystem aggregates.
const result = await client.rwa.list();

console.log(`Total tokens: ${result.pagination.total}`);
console.log(`Stability index: ${result.aggregates.stability_index}`);

for (const token of result.items) {
  console.log(`${token.symbol} — score: ${token.score}, tier: ${token.tier}, price: ${token.price}`);
}
Filtering and sorting:
// Filter by denomination and risk tier
const usdCritical = await client.rwa.list({
  denomination: 'USD',
  tier: 'critical',
  sort: 'score',
  order: 'desc',
});

// Filter by token type tags
const goldTokens = await client.rwa.list({
  tags: ['gold', 'rwa'],
  minMcap: 1_000_000,
});

// View collapsed/dead tokens (graveyard)
const graveyard = await client.rwa.list({ collapsedOnly: true });
Options:
OptionTypeDescription
chainChainFilter by chain (ETH, ARB, POL, OPT, BASE, BSC, LINEA)
tierstringRisk tier: critical, warning, watch, ok
tagsstring[]Token types (OR logic): standard, yield, rwa, gold, bridged, vault
denominationstringDenomination code (e.g. USD, EUR, XAU)
minScorenumberMinimum depeg risk score (0-100)
maxScorenumberMaximum depeg risk score (0-100)
minMcapnumberMinimum market cap in USD
liquiditystringLiquidity tier: high, medium, low, very_low
qstringSearch by symbol, name, or address
sortstringSort field: score, symbol, chain, tier, abs_dev_clean, market_cap_usd, ts
orderstringSort direction: asc, desc
showAllbooleanInclude excluded/problematic tokens
collapsedOnlybooleanOnly collapsed/dead tokens (graveyard)
pagenumberPage number (1-indexed, default 1)
pageSizenumberItems per page (default 50, max 500)

Get Token Detail

Get detailed depeg risk for a specific pegged token, including historical time series and depeg events.
// Default 24h history
const detail24h = await client.rwa.get('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');

// Specify chain and 7 days of history
const detail = await client.rwa.get(
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  { chain: Chain.ETH, hours: 168 }
);

console.log(`Score: ${detail.snapshot.score}`);
console.log(`Tier: ${detail.snapshot.tier}`);
console.log(`Price: ${detail.snapshot.price}`);
console.log(`Deviation: ${detail.snapshot.abs_dev_clean}`);

// Check history
console.log(`History points: ${detail.history.series.length}`);
for (const point of detail.history.series) {
  console.log(`${point.ts}: score=${point.score}, price=${point.price}`);
}

// Check depeg events
for (const event of detail.depegEvents) {
  console.log(`${event.detectedAt}: ${event.oldTier}${event.newTier} (score: ${event.riskScore})`);
}
Options:
OptionTypeRequiredDescription
chainChainNoBlockchain network (auto-resolved if token exists on one chain)
hoursnumberNoHours of history (default 24, max 168 = 7 days)

Full Example

import { ThreatClient, Chain, ValidationError, RateLimitError } from '@webacy-xyz/sdk';

const client = new ThreatClient({
  apiKey: process.env.WEBACY_API_KEY,
  defaultChain: Chain.ETH,
});

async function analyzeWallet(address: string) {
  try {
    // Get overall risk
    const risk = await client.addresses.analyze(address);

    if (risk.overallRisk > 70) {
      console.warn(`High risk wallet: ${risk.overallRisk}`);

      // Check sanctions
      const sanctions = await client.addresses.checkSanctioned(address);
      if (sanctions.is_sanctioned) {
        throw new Error('Sanctioned address - cannot proceed');
      }

      // Check for address poisoning
      const poisoning = await client.addresses.checkPoisoning(address);
      if (poisoning.is_poisoned) {
        console.warn('Address may be a poisoning attempt');
      }
    }

    return { safe: risk.overallRisk < 50, risk };

  } catch (error) {
    if (error instanceof ValidationError) {
      console.error('Invalid address:', error.message);
    } else if (error instanceof RateLimitError) {
      console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
    }
    throw error;
  }
}

Next Steps

TradingClient

Holder analysis and sniper detection

Vault Risk API

Full vault risk API reference

Depeg Monitor API

Full depeg monitoring API reference

Error Handling

Handle errors gracefully

Chains

Supported blockchain networks

API Reference

Full API documentation