Skip to main content

API Reference

Complete reference for solana-privacy-scanner-core library.

Installation

npm install solana-privacy-scanner-core

Quick Start

Most common workflow for scanning a wallet:

import {
collectWalletData,
normalizeWalletData,
generateReport,
createDefaultLabelProvider
} from 'solana-privacy-scanner-core';

const labels = createDefaultLabelProvider();
const rawData = await collectWalletData('WALLET_ADDRESS');
const context = normalizeWalletData(rawData, labels);
const report = generateReport(context);

console.log(`Risk: ${report.overallRisk}`);
Default RPC

The scanner uses a QuickNode RPC endpoint by default - no configuration needed. For custom RPC endpoints, see the RPCClient section below.

For specific use cases, import only what you need. Each section below shows the relevant imports.


RPCClient

The RPC client handles all Solana blockchain data fetching with automatic retries, rate limiting, and error handling.

import { RPCClient } from 'solana-privacy-scanner-core';

Constructor

new RPCClient(config?: RPCClientConfig | string)

Parameters:

ParameterTypeRequiredDescription
configRPCClientConfig | stringNoConfiguration object or RPC URL string. Uses default QuickNode RPC if omitted - no configuration needed.

RPCClientConfig Interface:

PropertyTypeDefaultDescription
rpcUrlstringQuickNode defaultCustom RPC endpoint URL
maxRetriesnumber3Maximum retry attempts for failed requests
retryDelaynumber1000Initial delay for exponential backoff (ms)
timeoutnumber30000Request timeout in milliseconds
maxConcurrencynumber10Maximum concurrent requests
debugbooleanfalseEnable debug logging

Examples:

// Use default RPC (no configuration required)
const rpc = new RPCClient();

// Use custom RPC URL (string)
const rpc = new RPCClient('https://api.mainnet-beta.solana.com');

// Use custom configuration
const rpc = new RPCClient({
rpcUrl: process.env.QUICKNODE_RPC_URL,
maxRetries: 5,
timeout: 60000,
debug: true
});

Methods

getSignaturesForAddress()

async getSignaturesForAddress(
address: string,
options?: {
limit?: number;
before?: string;
until?: string;
}
): Promise<ConfirmedSignatureInfo[]>

Fetches transaction signatures for an address.

ParameterTypeRequiredDescription
addressstringYesSolana wallet address
options.limitnumberNoMaximum number of signatures to fetch
options.beforestringNoFetch signatures before this transaction
options.untilstringNoFetch signatures until this transaction

getTransaction()

async getTransaction(
signature: string,
options?: { maxSupportedTransactionVersion?: number }
): Promise<ParsedTransactionWithMeta | null>

Fetches a single transaction by signature.

ParameterTypeRequiredDescription
signaturestringYesTransaction signature
options.maxSupportedTransactionVersionnumberNoMax version (default: 0)

getTransactions()

async getTransactions(
signatures: string[],
options?: { maxSupportedTransactionVersion?: number }
): Promise<Array<ParsedTransactionWithMeta | null>>

Fetches multiple transactions in parallel.

ParameterTypeRequiredDescription
signaturesstring[]YesArray of transaction signatures
options.maxSupportedTransactionVersionnumberNoMax version (default: 0)

getTokenAccountsByOwner()

async getTokenAccountsByOwner(
ownerAddress: string,
mintAddress?: string
): Promise<{ value: TokenAccountBalancePair[] }>

Fetches SPL token accounts owned by an address.

ParameterTypeRequiredDescription
ownerAddressstringYesWallet address
mintAddressstringNoFilter by specific token mint

getProgramAccounts()

async getProgramAccounts(
programId: string,
config?: any
): Promise<Array<{ pubkey: PublicKey; account: AccountInfo<Buffer> }>>

Fetches all accounts owned by a program.

ParameterTypeRequiredDescription
programIdstringYesProgram ID
configanyNoRPC configuration (encoding, filters, etc.)

getAccountInfo()

async getAccountInfo(address: string): Promise<AccountInfo<Buffer> | null>

Fetches account information.

ParameterTypeRequiredDescription
addressstringYesAccount address

getMultipleAccountsInfo()

async getMultipleAccountsInfo(
addresses: string[]
): Promise<Array<AccountInfo<Buffer> | null>>

Fetches multiple account infos in one request.

ParameterTypeRequiredDescription
addressesstring[]YesArray of account addresses

getConnection()

getConnection(): Connection

Returns the underlying Solana Connection object. Use sparingly - prefer wrapped methods.


getStats()

getStats(): { activeRequests: number; queueLength: number }

Returns current rate limiter statistics.


healthCheck()

async healthCheck(): Promise<boolean>

Checks if the RPC connection is healthy.


Data Collection Functions

These functions fetch raw blockchain data from Solana RPC.

import {
collectWalletData,
collectTransactionData,
collectProgramData
} from 'solana-privacy-scanner-core';

collectWalletData()

async function collectWalletData(
client: RPCClient,
address: string,
options?: WalletCollectionOptions
): Promise<RawWalletData>

Collects all transaction and token account data for a wallet.

Parameters:

ParameterTypeRequiredDescription
clientRPCClientYesRPC client instance
addressstringYesWallet address to scan
optionsWalletCollectionOptionsNoCollection options

WalletCollectionOptions:

PropertyTypeDefaultDescription
maxSignaturesnumber100Maximum signatures to fetch
includeTokenAccountsbooleantrueInclude SPL token accounts

Returns: Promise<RawWalletData>

Example:

const rpc = new RPCClient();
const rawData = await collectWalletData(rpc, 'WALLET_ADDRESS', {
maxSignatures: 200,
includeTokenAccounts: true
});

collectTransactionData()

async function collectTransactionData(
client: RPCClient,
signature: string
): Promise<RawTransactionData>

Collects data for a single transaction.

Parameters:

ParameterTypeRequiredDescription
clientRPCClientYesRPC client instance
signaturestringYesTransaction signature

Returns: Promise<RawTransactionData>

Example:

const rawData = await collectTransactionData(rpc, 'TRANSACTION_SIGNATURE');

collectProgramData()

async function collectProgramData(
client: RPCClient,
programId: string,
options?: ProgramCollectionOptions
): Promise<RawProgramData>

Collects data for a program (accounts and related transactions).

Parameters:

ParameterTypeRequiredDescription
clientRPCClientYesRPC client instance
programIdstringYesProgram ID to analyze
optionsProgramCollectionOptionsNoCollection options

ProgramCollectionOptions:

PropertyTypeDefaultDescription
maxAccountsnumber100Maximum accounts to fetch
maxTransactionsnumber50Maximum related transactions to fetch

Returns: Promise<RawProgramData>

Example:

const rawData = await collectProgramData(rpc, 'PROGRAM_ID', {
maxAccounts: 50,
maxTransactions: 100
});

Normalization Functions

These functions convert raw blockchain data into standardized ScanContext objects for analysis.

import {
normalizeWalletData,
normalizeTransactionData,
normalizeProgramData
} from 'solana-privacy-scanner-core';

normalizeWalletData()

function normalizeWalletData(
rawData: RawWalletData,
labelProvider?: LabelProvider
): ScanContext

Normalizes wallet data into a scan context.

Parameters:

ParameterTypeRequiredDescription
rawDataRawWalletDataYesRaw wallet data from collector
labelProviderLabelProviderNoLabel provider for known entity detection

Returns: ScanContext

Example:

const labels = createDefaultLabelProvider();
const context = normalizeWalletData(rawData, labels);

normalizeTransactionData()

function normalizeTransactionData(
rawData: RawTransactionData,
labelProvider?: LabelProvider
): ScanContext

Normalizes transaction data into a scan context.

Parameters:

ParameterTypeRequiredDescription
rawDataRawTransactionDataYesRaw transaction data from collector
labelProviderLabelProviderNoLabel provider for known entity detection

Returns: ScanContext

Example:

const context = normalizeTransactionData(rawData, labels);

normalizeProgramData()

function normalizeProgramData(
rawData: RawProgramData,
labelProvider?: LabelProvider
): ScanContext

Normalizes program data into a scan context.

Parameters:

ParameterTypeRequiredDescription
rawDataRawProgramDataYesRaw program data from collector
labelProviderLabelProviderNoLabel provider for known entity detection

Returns: ScanContext

Example:

const context = normalizeProgramData(rawData, labels);

Report Generation

import { generateReport, evaluateHeuristics } from 'solana-privacy-scanner-core';

generateReport()

function generateReport(context: ScanContext): PrivacyReport

Generates a complete privacy report from a scan context. This is the main function that orchestrates all heuristics and produces the final report.

Parameters:

ParameterTypeRequiredDescription
contextScanContextYesNormalized scan context

Returns: PrivacyReport

PrivacyReport Structure:

PropertyTypeDescription
versionstringReport schema version
timestampnumberReport generation timestamp (ms)
targetType'wallet' | 'transaction' | 'program'Type of scan performed
targetstringAddress/signature/program ID scanned
overallRisk'LOW' | 'MEDIUM' | 'HIGH'Aggregated risk level
signalsPrivacySignal[]Array of detected privacy risks
summaryobjectSummary statistics
summary.totalSignalsnumberTotal number of signals
summary.highRiskSignalsnumberCount of HIGH severity signals
summary.mediumRiskSignalsnumberCount of MEDIUM severity signals
summary.lowRiskSignalsnumberCount of LOW severity signals
summary.transactionsAnalyzednumberNumber of transactions analyzed
mitigationsstring[]Recommended privacy improvements
knownEntitiesLabel[]Detected known entities (CEXs, bridges, etc.)

Example:

const report = generateReport(context);

console.log(`Overall Risk: ${report.overallRisk}`);
console.log(`Total Signals: ${report.summary.totalSignals}`);
console.log(`Transactions Analyzed: ${report.summary.transactionsAnalyzed}`);

// Check for specific signal types
const hasFeePayerReuse = report.signals.some(s => s.id === 'fee-payer-never-self');

evaluateHeuristics()

function evaluateHeuristics(context: ScanContext): PrivacySignal[]

Evaluates all heuristics against a scan context and returns detected signals. This is used internally by generateReport() but can be called directly for custom workflows.

Parameters:

ParameterTypeRequiredDescription
contextScanContextYesNormalized scan context

Returns: PrivacySignal[] - Array of privacy signals sorted by severity

PrivacySignal Structure:

PropertyTypeDescription
idstringUnique signal identifier
namestringHuman-readable signal name
severity'LOW' | 'MEDIUM' | 'HIGH'Risk severity level
confidencenumberConfidence score (0-1)
reasonstringExplanation of the privacy risk
evidenceEvidence[]Supporting evidence data
mitigationstring (optional)Specific remediation advice

Example:

const signals = evaluateHeuristics(context);

// Filter HIGH severity signals
const criticalSignals = signals.filter(s => s.severity === 'HIGH');

// Get all fee payer related issues
const feePayerSignals = signals.filter(s => s.id.includes('fee-payer'));

Label Provider

The label provider identifies known entities (exchanges, bridges, etc.) in scan results.

import {
createDefaultLabelProvider,
StaticLabelProvider
} from 'solana-privacy-scanner-core';

createDefaultLabelProvider()

function createDefaultLabelProvider(): StaticLabelProvider

Creates a label provider with the built-in known addresses database.

Returns: StaticLabelProvider

Example:

const labels = createDefaultLabelProvider();
const context = normalizeWalletData(rawData, labels);

StaticLabelProvider

Class for loading and querying known address labels.

Constructor

new StaticLabelProvider(labelsPath?: string)

Parameters:

ParameterTypeRequiredDescription
labelsPathstringNoCustom path to labels JSON file. Uses built-in database if omitted.

Methods

lookup()
lookup(address: string): Label | null

Looks up a single address.

ParameterTypeRequiredDescription
addressstringYesSolana address to look up

Returns: Label | null


lookupMany()
lookupMany(addresses: string[]): Map<string, Label>

Looks up multiple addresses at once.

ParameterTypeRequiredDescription
addressesstring[]YesArray of addresses to look up

Returns: Map<string, Label>


getAllLabels()
getAllLabels(): Label[]

Returns all loaded labels.

Returns: Label[]


getCount()
getCount(): number

Returns the number of loaded labels.

Returns: number


Label Structure:

PropertyTypeDescription
addressstringSolana address
namestringEntity name (e.g., "Binance Hot Wallet")
type'exchange' | 'bridge' | 'protocol' | 'service' | 'other'Entity type
descriptionstring (optional)Additional information
relatedAddressesstring[] (optional)Related addresses

Example:

// Use custom labels
const customLabels = new StaticLabelProvider('./my-labels.json');

// Query labels
const label = customLabels.lookup('ADDRESS');
if (label) {
console.log(`${label.name} (${label.type})`);
}

// Get all exchange addresses
const allLabels = customLabels.getAllLabels();
const exchanges = allLabels.filter(l => l.type === 'exchange');

Heuristic Functions

All heuristics are pure functions that take a ScanContext and return PrivacySignal[].

info

Most users don't need to import these directly - generateReport() runs all heuristics automatically. Only import individual heuristics if you're building custom analysis workflows.

import {
// Import only what you need for custom workflows
detectFeePayerReuse,
detectSignerOverlap,
detectMemoExposure,
// ... etc
} from 'solana-privacy-scanner-core';

Critical Heuristics

detectFeePayerReuse()

function detectFeePayerReuse(context: ScanContext): PrivacySignal[]

Detects when external addresses pay transaction fees, creating strong linkage between accounts.

Signal IDs:

  • fee-payer-never-self - Target never pays own fees (HIGH)
  • fee-payer-external - External fee payers detected (HIGH/MEDIUM)

detectSignerOverlap()

function detectSignerOverlap(context: ScanContext): PrivacySignal[]

Identifies repeated signer combinations across transactions.

Signal IDs:

  • signer-repeated - Same signers appear together multiple times (HIGH/MEDIUM)
  • signer-set-reuse - Identical signer sets detected (HIGH)

detectMemoExposure()

function detectMemoExposure(context: ScanContext): PrivacySignal[]

Scans transaction memos for personally identifiable information.

Signal IDs:

  • memo-pii-exposure - PII detected in memos (HIGH)
  • memo-descriptive-content - Descriptive memo content (MEDIUM)
  • memo-usage - Memos used (LOW)

detectAddressReuse()

function detectAddressReuse(context: ScanContext): PrivacySignal[]

Analyzes address usage patterns and diversity.

Signal IDs:

  • address-high-diversity - Many unique counterparties (LOW)
  • address-moderate-diversity - Moderate diversity (MEDIUM)
  • address-long-term-usage - Long-term address usage (LOW)

detectInstructionFingerprinting()

function detectInstructionFingerprinting(context: ScanContext): PrivacySignal[]

Detects unique behavioral patterns from instruction sequences.

Signal IDs:

  • instruction-sequence-pattern - Repeated instruction patterns (MEDIUM)
  • program-usage-profile - Unique program usage profile (MEDIUM)

detectTokenAccountLifecycle()

function detectTokenAccountLifecycle(context: ScanContext): PrivacySignal[]

Tracks token account creation/closure patterns and rent refunds.

Signal IDs:

  • token-account-churn - High token account turnover (MEDIUM)
  • rent-refund-clustering - Rent refunds link accounts (MEDIUM)

Behavioral Heuristics

detectKnownEntityInteraction()

function detectKnownEntityInteraction(context: ScanContext): PrivacySignal[]

Identifies interactions with known entities (exchanges, bridges, etc.).

Signal IDs:

  • known-entity-exchange - CEX interaction (HIGH)
  • known-entity-bridge - Bridge interaction (MEDIUM)
  • known-entity-other - Other known entity (varies)

detectCounterpartyReuse()

function detectCounterpartyReuse(context: ScanContext): PrivacySignal[]

Tracks repeated interactions with the same counterparties.

Signal IDs:

  • counterparty-reuse - Repeated counterparty patterns (varies)
  • pda-reuse - Repeated PDA interactions (varies)

detectTimingPatterns()

function detectTimingPatterns(context: ScanContext): PrivacySignal[]

Analyzes transaction timing for correlation patterns.

Signal IDs:

  • timing-burst - Transaction bursts detected (MEDIUM)
  • timing-regular-interval - Regular timing patterns (MEDIUM)
  • timing-timezone-pattern - Timezone patterns (LOW)

Traditional Heuristics

detectAmountReuse()

function detectAmountReuse(context: ScanContext): PrivacySignal[]

Detects repeated transaction amounts (less critical on Solana).

Signal IDs:

  • amount-reuse - Repeated amounts detected (LOW)

detectBalanceTraceability()

function detectBalanceTraceability(context: ScanContext): PrivacySignal[]

Analyzes balance flow patterns for traceability.

Signal IDs:

  • balance-matching-pairs - Matching transfer pairs (MEDIUM)
  • balance-sequential-similar - Sequential similar amounts (MEDIUM)
  • balance-full-movement - Full balance movements (MEDIUM)

Types

Import TypeScript types for type safety:

import type {
ScanContext,
PrivacyReport,
PrivacySignal,
RiskLevel
} from 'solana-privacy-scanner-core';

ScanContext

The normalized input to all heuristics and report generation.

interface ScanContext {
target: string; // Address/signature/program being scanned
targetType: 'wallet' | 'transaction' | 'program';
transfers: Transfer[]; // SOL and SPL token transfers
instructions: NormalizedInstruction[]; // Program instructions
counterparties: Set<string>; // Unique addresses interacted with
labels: Map<string, Label>; // Known entity labels
tokenAccounts: Array<{
mint: string;
address: string;
balance: number;
}>;
timeRange: {
earliest: number | null; // Unix timestamp
latest: number | null;
};
transactionCount: number;

// Additional context fields
transactions: TransactionMetadata[]; // Fee payers, signers, memos
tokenAccountEvents: TokenAccountEvent[]; // Create/close events
pdaInteractions: PDAInteraction[]; // Program-derived address usage
feePayers: Set<string>; // Unique fee payers
signers: Set<string>; // Unique signers
programs: Set<string>; // Programs interacted with
}

RiskLevel

type RiskLevel = 'LOW' | 'MEDIUM' | 'HIGH';

Static Code Analysis

import { analyze } from 'solana-privacy-scanner-core';

analyze()

async function analyze(
paths: string[],
options?: AnalyzerOptions
): Promise<AnalyzerResult>

Analyzes TypeScript/JavaScript source code for privacy anti-patterns.

Parameters:

ParameterTypeRequiredDescription
pathsstring[]YesFile paths or glob patterns to analyze
optionsAnalyzerOptionsNoAnalysis options

AnalyzerOptions:

PropertyTypeDefaultDescription
includeLowbooleantrueInclude low severity issues

Returns: Promise<AnalyzerResult>

AnalyzerResult Structure:

PropertyTypeDescription
filesAnalyzednumberNumber of files analyzed
issuesIssue[]Array of detected issues
summaryobjectSummary of issues by severity
summary.totalnumberTotal number of issues
summary.criticalnumberCritical severity count
summary.highnumberHigh severity count
summary.mediumnumberMedium severity count
summary.lownumberLow severity count

Issue Structure:

PropertyTypeDescription
typestringIssue type (e.g., "fee-payer-reuse")
severity'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW'Issue severity
messagestringHuman-readable description
filestringFile path
linenumberLine number
columnnumberColumn number
codeSnippetstring (optional)Code excerpt
suggestionstring (optional)Fix suggestion

Example:

import { analyze } from 'solana-privacy-scanner-core';

const result = await analyze(['src/**/*.ts'], {
includeLow: false
});

console.log(`Analyzed ${result.filesAnalyzed} files`);
console.log(`Found ${result.summary.critical} critical issues`);

result.issues.forEach(issue => {
console.log(`[${issue.severity}] ${issue.file}:${issue.line} - ${issue.message}`);
});

Transaction Simulation

import {
simulateTransactionPrivacy,
simulateTransactionFlow,
compareImplementations
} from 'solana-privacy-scanner-core';

simulateTransactionPrivacy()

async function simulateTransactionPrivacy(
transaction: Transaction | VersionedTransaction,
connection: Connection,
options?: SimulatorOptions
): Promise<PrivacyReport>

Simulates a transaction's privacy impact without sending to network.

Parameters:

ParameterTypeRequiredDescription
transactionTransaction | VersionedTransactionYesTransaction to simulate
connectionConnectionYesSolana RPC connection
optionsSimulatorOptionsNoSimulation options

SimulatorOptions:

PropertyTypeDefaultDescription
labelProviderLabelProviderDefaultCustom label provider
commitment'processed' | 'confirmed' | 'finalized''confirmed'Commitment level
includeAccountsbooleantrueInclude account details

Returns: Promise<PrivacyReport>

Example:

import { Connection, Transaction } from '@solana/web3.js';
import { simulateTransactionPrivacy } from 'solana-privacy-scanner-core';

const connection = new Connection('https://api.mainnet-beta.solana.com');
const report = await simulateTransactionPrivacy(tx, connection);

if (report.overallRisk === 'HIGH') {
console.warn('High privacy risk detected');
}

simulateTransactionFlow()

async function simulateTransactionFlow(
transactions: Array<Transaction | VersionedTransaction>,
connection: Connection,
options?: SimulatorOptions
): Promise<PrivacyFlowReport>

Simulates a sequence of transactions to analyze cumulative privacy impact.

Returns: Promise<PrivacyFlowReport>

PrivacyFlowReport Structure:

PropertyTypeDescription
individualReportsPrivacyReport[]Reports for each transaction
cumulativeRisk'LOW' | 'MEDIUM' | 'HIGH'Overall flow risk
cumulativeScorenumberAggregate privacy score (0-100)
emergentPatternsEmergentPattern[]Patterns across transactions
recommendationsstring[]Flow-specific recommendations

Example:

const flow = [depositTx, swapTx, withdrawTx];
const report = await simulateTransactionFlow(flow, connection);

console.log(`Cumulative Risk: ${report.cumulativeRisk}`);
console.log(`Emergent Patterns: ${report.emergentPatterns.length}`);

compareImplementations()

async function compareImplementations(
implA: Transaction | VersionedTransaction,
implB: Transaction | VersionedTransaction,
connection: Connection,
options?: SimulatorOptions
): Promise<PrivacyComparison>

Compares two transaction implementations for privacy characteristics.

Returns: Promise<PrivacyComparison>

PrivacyComparison Structure:

PropertyTypeDescription
implementationAPrivacyReportReport for first implementation
implementationBPrivacyReportReport for second implementation
winner'A' | 'B' | 'EQUAL'Which implementation is more private
differencenumberPrivacy score difference
recommendationstringComparison summary

Example:

const directTransfer = buildDirectTransfer(from, to, amount);
const intermediaryTransfer = buildIntermediaryTransfer(from, to, amount);

const comparison = await compareImplementations(
directTransfer,
intermediaryTransfer,
connection
);

console.log(`Winner: Implementation ${comparison.winner}`);
console.log(`Privacy improvement: ${comparison.difference} points`);

Test Matchers

Custom assertions for Vitest/Jest. Import as: import 'solana-privacy-scanner-core/matchers';

Available Matchers

All matchers are used with expect(report):

Risk Level:

  • toHavePrivacyRisk(level: 'LOW' | 'MEDIUM' | 'HIGH') - Assert specific risk level

Signals:

  • toHaveNoHighRiskSignals() - No HIGH severity signals
  • toHaveSignal(type: string) - Contains specific signal type
  • toNotHaveSignal(type: string) - Does not contain signal type
  • toHaveAtMostSignals(max: number) - Maximum signal count

Privacy Properties:

  • toNotLeakUserRelationships() - No counterparty/signer/fee payer linking
  • toHavePrivacyScore(minScore: number) - Minimum privacy score (0-100)

Known Entities:

  • toHaveNoKnownEntities() - No CEX/bridge interactions
  • toNotInteractWith(entityType: string) - Avoid entity type (e.g., 'exchange')

Example:

import { expect } from 'vitest';
import 'solana-privacy-scanner-core/matchers';

test('transaction maintains privacy', async () => {
const report = await simulateTransactionPrivacy(tx, connection);

expect(report).toHavePrivacyRisk('LOW');
expect(report).toHaveNoHighRiskSignals();
expect(report).toNotLeakUserRelationships();
expect(report).toHavePrivacyScore(80);
expect(report).toHaveAtMostSignals(2);
expect(report).toNotInteractWith('exchange');
});

Configuration Management

import { loadConfig, validateConfig } from 'solana-privacy-scanner-core';

loadConfig()

async function loadConfig(path?: string): Promise<PrivacyConfig | null>

Loads privacy policy configuration from .privacyrc file.

Parameters:

ParameterTypeRequiredDescription
pathstringNoConfig file path (default: .privacyrc)

Returns: Promise<PrivacyConfig | null>

Example:

import { loadConfig } from 'solana-privacy-scanner-core';

const config = await loadConfig('.privacyrc');

if (config) {
console.log(`Max risk level: ${config.maxRiskLevel}`);
console.log(`Enforce in CI: ${config.enforceInCI}`);
}

validateConfig()

function validateConfig(config: unknown): PrivacyConfig

Validates and parses configuration object.

Parameters:

ParameterTypeRequiredDescription
configunknownYesConfiguration to validate

Returns: PrivacyConfig (throws on invalid config)


PrivacyConfig

interface PrivacyConfig {
maxRiskLevel: 'LOW' | 'MEDIUM' | 'HIGH';
enforceInCI: boolean;
blockOnFailure: boolean;
thresholds?: {
maxHighSeverity?: number;
maxMediumSeverity?: number;
minPrivacyScore?: number;
};
testWallets?: {
devnet?: string;
testnet?: string;
};
}

Example .privacyrc file:

{
"maxRiskLevel": "MEDIUM",
"enforceInCI": true,
"blockOnFailure": true,
"thresholds": {
"maxHighSeverity": 0,
"maxMediumSeverity": 2,
"minPrivacyScore": 80
},
"testWallets": {
"devnet": "YourDevnetWalletAddress"
}
}

Complete Workflow Example

import {
RPCClient,
collectWalletData,
normalizeWalletData,
generateReport,
createDefaultLabelProvider,
type PrivacyReport
} from 'solana-privacy-scanner-core';

async function analyzeWallet(address: string): Promise<PrivacyReport> {
// 1. Initialize RPC client
const rpc = new RPCClient({
rpcUrl: process.env.SOLANA_RPC_URL,
maxRetries: 5,
debug: false
});

// 2. Initialize label provider
const labels = createDefaultLabelProvider();

// 3. Collect raw blockchain data
const rawData = await collectWalletData(rpc, address, {
maxSignatures: 200,
includeTokenAccounts: true
});

// 4. Normalize data into scan context
const context = normalizeWalletData(rawData, labels);

// 5. Generate privacy report
const report = generateReport(context);

return report;
}

// Usage
const report = await analyzeWallet('YOUR_WALLET_ADDRESS');

console.log(`Risk: ${report.overallRisk}`);
console.log(`Signals: ${report.summary.totalSignals}`);
console.log(`HIGH: ${report.summary.highRiskSignals}`);
console.log(`MEDIUM: ${report.summary.mediumRiskSignals}`);
console.log(`LOW: ${report.summary.lowRiskSignals}`);

// Access specific data
report.signals.forEach(signal => {
console.log(`[${signal.severity}] ${signal.name}: ${signal.reason}`);
});

report.mitigations.forEach(mitigation => {
console.log(`- ${mitigation}`);
});

Next Steps