Overview
The SDK exports all TypeScript types for full type safety in your application.Import
Web SDK:import type {
ClientOptions,
TraceOptions,
AddEventOptions,
ChainName,
Severity,
Logger,
ClientMetadata,
TraceEvent,
TxHashHint,
SafeMsgHintData,
SafeTxHintData,
TxHintOptions,
TransactionLike,
TransactionRequest,
EIP1193Provider,
MiradorProviderOptions,
StackFrame,
StackTrace,
TraceCallbacks,
MiradorPlugin,
TraceContext,
PluginSetupResult,
FlushBuilder,
Web3Plugin,
Web3Methods,
EvmMethods,
SafeNamespaceMethods,
NoopTrace,
HintType
} from '@miradorlabs/web-sdk';
import type {
ClientOptions,
TraceOptions,
AddEventOptions,
ChainName,
Severity,
Logger,
TraceEvent,
TxHashHint,
SafeMsgHintData,
SafeTxHintData,
TxHintOptions,
TransactionLike,
TransactionRequest,
EIP1193Provider,
MiradorProviderOptions,
StackFrame,
StackTrace,
TraceCallbacks,
MiradorPlugin,
TraceContext,
PluginSetupResult,
FlushBuilder,
Web3Plugin,
Web3Methods,
EvmMethods,
SafeNamespaceMethods,
NoopTrace,
HintType
} from '@miradorlabs/nodejs-sdk';
ClientOptions
Configuration options for the client. Web SDK:interface ClientOptions {
/**
* Gateway URL for the Mirador Ingest API
* @default 'ingest.mirador.org:443'
*/
apiUrl?: string;
/**
* Keep-alive ping interval in milliseconds
* @default 10000
*/
keepAliveIntervalMs?: number;
/**
* Timeout for individual API calls in milliseconds
* @default 5000
*/
callTimeoutMs?: number;
/**
* Maximum trace lifetime in milliseconds. When exceeded, the trace is automatically closed.
* Set to 0 to disable.
* @default 0
*/
maxTraceLifetimeMs?: number;
/**
* Enable debug logging
* @default false
*/
debug?: boolean;
/**
* Custom logger implementation
*/
logger?: Logger;
/**
* Lifecycle callbacks for all traces created by this client
*/
callbacks?: TraceCallbacks;
/**
* Sample rate for traces (0 to 1). 0 = drop all, 1 = keep all.
* Unsampled traces return a NoopTrace.
* @default 1
*/
sampleRate?: number;
/**
* Custom sampler function. Takes precedence over sampleRate.
* Return true to keep the trace, false to drop it.
*/
sampler?: (name: string | undefined, options: TraceOptions) => boolean;
/**
* Plugins to install on all traces created by this client.
*/
plugins?: MiradorPlugin[];
}
interface ClientOptions {
/**
* Gateway URL for the Mirador Ingest API
* @default 'ingest.mirador.org:443'
*/
apiUrl?: string;
/**
* Keep-alive ping interval in milliseconds
* @default 10000
*/
keepAliveIntervalMs?: number;
/**
* Timeout for individual API calls in milliseconds
* @default 5000
*/
callTimeoutMs?: number;
/**
* Maximum trace lifetime in milliseconds. When exceeded, the trace is automatically closed.
* Set to 0 to disable.
* @default 0
*/
maxTraceLifetimeMs?: number;
/**
* Enable debug logging
* @default false
*/
debug?: boolean;
/**
* Custom logger implementation
*/
logger?: Logger;
/**
* Lifecycle callbacks for all traces created by this client
*/
callbacks?: TraceCallbacks;
/**
* Sample rate for traces (0 to 1). 0 = drop all, 1 = keep all.
* Unsampled traces return a NoopTrace.
* @default 1
*/
sampleRate?: number;
/**
* Custom sampler function. Takes precedence over sampleRate.
* Return true to keep the trace, false to drop it.
*/
sampler?: (name: string | undefined, options: TraceOptions) => boolean;
/**
* Plugins to install on all traces created by this client.
*/
plugins?: MiradorPlugin[];
/**
* Use SSL for the gRPC connection
* @default true
*/
useSsl?: boolean;
}
Usage
const options: ClientOptions = {
apiUrl: 'https://custom-gateway.example.com:443'
};
const client = new Client('api-key', options);
import { Client, Web3Plugin } from '@miradorlabs/web-sdk';
const client = new Client('api-key', {
plugins: [Web3Plugin({ provider: window.ethereum })]
});
// All traces created by this client will have web3 methods available
const client = new Client('api-key', {
apiUrl: 'localhost:50053',
useSsl: false
});
TraceOptions
Configuration options for individual traces. Web SDK:interface TraceOptions {
/**
* Name identifying the trace
*/
name?: string;
/**
* Resume an existing trace by ID, or provide a pre-generated W3C Tracing Context
* compatible ID (32-char hex string).
* When set, the flush uses the provided ID instead of generating a new one.
*/
traceId?: string;
/**
* Include browser metadata on first flush
* @default true
*/
includeUserMeta?: boolean;
/**
* Maximum retry attempts on network failure
* @default 2
*/
maxRetries?: number;
/**
* Base delay in ms for exponential backoff
* @default 500
*/
retryBackoff?: number;
/**
* Automatically close trace on page unload
* @default false
*/
autoClose?: boolean;
/**
* Automatically start the keep-alive timer.
* Defaults to true for new traces, false when traceId is set (resumed traces).
*/
autoKeepAlive?: boolean;
/**
* Maximum number of events/items in the flush queue before dropping.
* @default 4096
*/
maxQueueSize?: number;
/**
* Lifecycle callbacks for this specific trace (merged with client-level callbacks).
*/
callbacks?: TraceCallbacks;
}
interface TraceOptions {
/**
* Name identifying the trace
*/
name?: string;
/**
* Resume an existing trace by ID, or provide a pre-generated W3C Tracing Context
* compatible ID (32-char hex string).
* When set, the flush uses the provided ID instead of generating a new one.
*/
traceId?: string;
/**
* Capture stack trace at trace creation point
* @default true
*/
captureStackTrace?: boolean;
/**
* Maximum retry attempts on network failure
* @default 2
*/
maxRetries?: number;
/**
* Base delay in ms for exponential backoff
* @default 500
*/
retryBackoff?: number;
/**
* Automatically start the keep-alive timer.
* Defaults to true for new traces, false when traceId is set (resumed traces).
*/
autoKeepAlive?: boolean;
/**
* Maximum number of events/items in the flush queue before dropping.
* @default 4096
*/
maxQueueSize?: number;
/**
* Lifecycle callbacks for this specific trace (merged with client-level callbacks).
*/
callbacks?: TraceCallbacks;
}
Usage
Web SDK:const options: TraceOptions = {
name: 'MyTrace',
includeUserMeta: true,
maxRetries: 5,
retryBackoff: 1000
};
const trace = client.trace(options);
const options: TraceOptions = {
name: 'MyTrace',
captureStackTrace: false
};
const trace = client.trace(options);
// Backend receives trace ID from frontend (e.g., via HTTP header)
const trace = client.trace({
name: 'BackendProcessing',
traceId: req.headers['x-mirador-trace-id']
});
trace.addEvent('backend:received');
// → FlushTrace sent automatically (uses the provided traceId)
TraceCallbacks
Lifecycle callbacks for observing trace events programmatically. See the Lifecycle Callbacks guide for detailed usage patterns.interface TraceCallbacks {
/** Called once when the trace is first created on the server (first successful flush) */
onCreated?: (traceId: string) => void;
/** Called after each successful flush */
onFlushed?: (traceId: string, itemCount: number) => void;
/** Called when a flush operation fails after retries */
onFlushError?: (error: Error, operation: string) => void;
/** Called when the trace is closed */
onClosed?: (traceId: string, reason?: string) => void;
/** Called when items are dropped (e.g., queue full) */
onDropped?: (count: number, reason: string) => void;
}
Usage
const client = new Client('api-key', {
callbacks: {
onCreated: (traceId) => console.log('Trace created:', traceId),
onFlushed: (traceId, itemCount) => console.log(`Flushed ${itemCount} items`),
onFlushError: (error, operation) => console.error(`${operation} failed:`, error),
onClosed: (traceId, reason) => console.log('Closed:', traceId, reason),
onDropped: (count, reason) => console.warn(`Dropped ${count} items: ${reason}`)
}
});
Logger
Interface for custom logging implementations. See the Custom Logging guide for integration examples.interface Logger {
debug(...args: unknown[]): void;
warn(...args: unknown[]): void;
error(...args: unknown[]): void;
}
Usage
// Use the built-in console logger
const client = new Client('api-key', { debug: true });
// Or provide a custom logger
const client = new Client('api-key', {
logger: {
debug: (...args) => myLogger.debug(args.join(' ')),
warn: (...args) => myLogger.warn(args.join(' ')),
error: (...args) => myLogger.error(args.join(' '))
}
});
Severity
Event severity levels used by convenience methods.type Severity = 'info' | 'warn' | 'error';
Usage
trace.info('User action completed');
trace.warn('Approaching rate limit');
trace.error('Transaction failed', { code: 'REVERT' });
MiradorPlugin
Interface for creating plugins that extend trace functionality.interface MiradorPlugin {
/** Unique plugin name — used as the namespace on the trace */
name: string;
/** Called when a trace is created. Returns methods and lifecycle hooks. */
setup(context: TraceContext): PluginSetupResult;
}
TraceContext
Read/write access to the trace, passed to pluginsetup().
interface TraceContext {
/** Add an event to the trace */
addEvent(name: string, details?: string | object, options?: AddEventOptions): void;
/** Add a single attribute */
addAttribute(key: string, value: string | number | boolean | object): void;
/** Add multiple attributes at once */
addAttributes(attrs: Record<string, string | number | boolean | object>): void;
/** Add a single tag */
addTag(tag: string): void;
/** Add multiple tags at once */
addTags(tags: string[]): void;
/** Get the W3C trace ID */
getTraceId(): string;
/** Check if the trace has been closed */
isClosed(): boolean;
/** Schedule a flush (batched via microtask) */
scheduleFlush(): void;
/** Logger instance respecting client configuration */
logger: Logger;
}
PluginSetupResult
Object returned by a plugin’ssetup() method.
interface PluginSetupResult<TMethods> {
/** Methods to merge onto the Trace instance under the plugin's name */
methods: TMethods;
/** No-op versions of methods for NoopTrace (sampled-out traces).
* If not provided, methods default to returning `this` for chaining. */
noopMethods?: DeepPartial<TMethods>;
/** Called during flush to contribute data to the payload */
onFlush?: (builder: FlushBuilder) => void;
/** Called when the trace is being closed */
onClose?: () => void;
/** Return true if this plugin has unflushed data */
hasPendingData?: () => boolean;
}
FlushBuilder
Interface for contributing data to a flush payload from a plugin’sonFlush hook.
interface FlushBuilder {
/** Add a hint (type-safe for known hint types) */
addHint<T extends HintTypeName>(type: T, data: HintDataMap[T]): void;
/** Add a hint with a custom type (extensibility fallback) */
addHint(type: string, data: Record<string, unknown>): void;
/** Add an event to the flush payload */
addEvent(event: { name: string; details?: string; timestamp: Date; severity?: Severity }): void;
/** Add an attribute */
addAttribute(key: string, value: string): void;
/** Add a tag */
addTag(tag: string): void;
}
Web3Methods
Methods available ontrace.web3 when using the Web3Plugin.
interface Web3Methods {
evm: EvmMethods;
safe: SafeNamespaceMethods;
}
EvmMethods
EVM transaction methods available ontrace.web3.evm.
interface EvmMethods {
addTxHint(txHash: string, chain: ChainName, options?: string | TxHintOptions): Trace;
addTxInputData(inputData: string): Trace;
addTx(tx: TransactionLike, chain?: ChainName): Trace;
sendTransaction(tx: TransactionRequest): Promise<string>;
}
SafeNamespaceMethods
Safe multisig methods available ontrace.web3.safe.
interface SafeNamespaceMethods {
addMsgHint(msgHint: string, chain: ChainName, details?: string): Trace;
addTxHint(safeTxHash: string, chain: ChainName, details?: string): Trace;
}
NoopTrace
A trace implementation that silently discards all operations. Returned when a trace is not sampled.class NoopTrace {
// All Trace methods are available but do nothing
addAttribute(key: string, value: any): NoopTrace;
addEvent(name: string, details?: any): NoopTrace;
getTraceId(): string; // Returns the generated ID
// ... etc
}
Usage
const client = new Client('api-key', { sampleRate: 0.5 });
const trace = client.trace({ name: 'MaybeRecorded' });
// Safe to call all methods — if unsampled, they're silently ignored
trace.addEvent('action');
HintType
Discriminator for the type of transaction hint.type HintType = 'tx' | 'safe_msg' | 'safe_tx';
ChainName
Supported blockchain networks for transaction hints.type ChainName =
| 'ethereum'
| 'polygon'
| 'arbitrum'
| 'base'
| 'optimism'
| 'bsc';
Usage
const chain: ChainName = 'ethereum';
trace.web3.evm.addTxHint(txHash, chain);
// Type-safe: only valid chains allowed
trace.web3.evm.addTxHint(hash, 'polygon'); // OK
trace.web3.evm.addTxHint(hash, 'invalid'); // Type error
TraceEvent
Structure of events added to traces.interface TraceEvent {
/**
* Event name
*/
eventName: string;
/**
* Optional event details (stringified if object)
*/
details?: string;
/**
* Timestamp of the event
*/
timestamp: Date;
}
Usage
// Events are created internally by addEvent()
trace.addEvent('my_event', { key: 'value' });
// The SDK creates a TraceEvent like:
// {
// eventName: 'my_event',
// details: '{"key":"value"}',
// timestamp: new Date()
// }
TxHashHint
Structure of blockchain transaction hints.interface TxHashHint {
/**
* Transaction hash
*/
txHash: string;
/**
* Blockchain network
*/
chain: ChainName;
/**
* Optional description
*/
details?: string;
/**
* Timestamp of the hint
*/
timestamp: Date;
}
Usage
// TxHashHints are created internally by web3.evm.addTxHint()
trace.web3.evm.addTxHint('0x123...', 'ethereum', 'Swap transaction');
SafeMsgHintData
Structure of Safe multisig message hints.interface SafeMsgHintData {
/**
* Safe message hash
*/
messageHash: string;
/**
* Blockchain network the Safe is deployed on
*/
chain: ChainName;
/**
* Optional description
*/
details?: string;
/**
* Timestamp of the hint
*/
timestamp: Date;
}
Usage
// SafeMsgHintData is created internally by web3.safe.addMsgHint()
trace.web3.safe.addMsgHint('0xabc...', 'ethereum', 'Multisig approval');
SafeTxHintData
Structure of Safe multisig transaction hints.interface SafeTxHintData {
/**
* Safe transaction hash
*/
safeTxHash: string;
/**
* Blockchain network the Safe is deployed on
*/
chain: ChainName;
/**
* Optional description
*/
details?: string;
/**
* Timestamp of the hint
*/
timestamp: Date;
}
Usage
// SafeTxHintData is created internally by web3.safe.addTxHint()
trace.web3.safe.addTxHint('0xdef...', 'ethereum', 'Safe execution');
AddEventOptions
Options for theaddEvent() method.
interface AddEventOptions {
/**
* Capture stack trace at event location
* @default false
*/
captureStackTrace?: boolean;
/**
* Custom timestamp for the event
*/
timestamp?: Date;
}
Usage
// Capture stack trace for debugging
trace.addEvent('error_occurred', { code: 500 }, { captureStackTrace: true });
// Custom timestamp
trace.addEvent('operation_started', null, { timestamp: new Date('2024-01-01') });
StackFrame
Represents a single frame in a stack trace.interface StackFrame {
/**
* Function name (or '<anonymous>')
*/
functionName: string;
/**
* File name or URL
*/
fileName: string;
/**
* Line number
*/
lineNumber: number;
/**
* Column number
*/
columnNumber: number;
}
StackTrace
Captured stack trace information.interface StackTrace {
/**
* Parsed stack frames
*/
frames: StackFrame[];
/**
* Original Error.stack string
*/
raw: string;
}
Usage
import { captureStackTrace, formatStackTrace } from '@miradorlabs/web-sdk';
// Capture current stack trace
const stack = captureStackTrace();
// Format for storage
const json = formatStackTrace(stack);
// Format for display
const readable = formatStackTraceReadable(stack);
ClientMetadata (Web SDK Only)
Browser environment metadata collected automatically.interface ClientMetadata {
// Browser
browser?: string;
browserVersion?: string;
userAgent?: string;
// Operating System
os?: string;
osVersion?: string;
deviceType?: string;
// Display
screenWidth?: string;
screenHeight?: string;
viewportWidth?: string;
viewportHeight?: string;
colorDepth?: string;
pixelRatio?: string;
// Hardware
cpuCores?: string;
deviceMemory?: string;
touchSupport?: string;
// Network
connectionType?: string;
online?: string;
// Locale
language?: string;
languages?: string;
timezone?: string;
timezoneOffset?: string;
// Page Context
url?: string;
origin?: string;
pathname?: string;
referrer?: string;
documentVisibility?: string;
// Privacy
cookiesEnabled?: string;
doNotTrack?: string;
}
Usage
import { getClientMetadata } from '@miradorlabs/web-sdk';
const metadata: ClientMetadata = getClientMetadata();
console.log(metadata.browser); // 'Chrome'
console.log(metadata.deviceType); // 'desktop'
EIP1193Provider
Standard EIP-1193 provider interface. Compatible with MetaMask, WalletConnect, and any EIP-1193 compliant wallet.interface EIP1193Provider {
request(args: { method: string; params?: unknown[] }): Promise<unknown>;
}
Usage
// window.ethereum is an EIP1193Provider
const provider: EIP1193Provider = window.ethereum;
// viem walletClient.transport is compatible
// ethers.js BrowserProvider is compatible
TxHintOptions
Structured options forweb3.evm.addTxHint(), extending the simple string details.
interface TxHintOptions {
/** Transaction input data / calldata */
input?: string;
/** Additional details string */
details?: string;
}
When
input is provided, it is emitted as a "Tx input data" event via web3.evm.addTxInputData(). Only details is stored in the hint itself.Usage
// Simple string details
trace.web3.evm.addTxHint(txHash, 'ethereum', 'Swap transaction');
// Structured options with calldata
trace.web3.evm.addTxHint(txHash, 'ethereum', {
input: '0xa9059cbb000000000000000000000000...',
details: 'ERC-20 transfer'
});
TransactionLike
A transaction-like object that matches common library shapes (ethers v5/v6, viem, raw RPC).interface TransactionLike {
/** Transaction hash */
hash: string;
/** Transaction input data (ethers v5 style) */
data?: string;
/** Transaction input data (ethers v6 / viem / raw RPC style) */
input?: string;
/** Chain ID */
chainId?: number | bigint | string;
}
Usage
// Works with ethers v5 TransactionResponse
const tx = await signer.sendTransaction(txData);
trace.web3.evm.addTx(tx); // tx.hash and tx.data are used
// Works with viem transaction objects
const hash = await walletClient.sendTransaction(request);
trace.web3.evm.addTx({ hash, input: request.data, chainId: request.chain.id });
TransactionRequest
Transaction parameters forweb3.evm.sendTransaction(), matching the EIP-1193 eth_sendTransaction format.
interface TransactionRequest {
/** Sender address */
from: string;
/** Recipient address */
to?: string;
/** Transaction input data / calldata */
data?: string;
/** Value in wei */
value?: string | bigint;
/** Gas limit */
gas?: string | bigint;
/** Gas price (legacy) */
gasPrice?: string | bigint;
/** Max fee per gas (EIP-1559) */
maxFeePerGas?: string | bigint;
/** Max priority fee per gas (EIP-1559) */
maxPriorityFeePerGas?: string | bigint;
/** Transaction nonce */
nonce?: number | string;
/** Chain ID */
chainId?: number | string;
}
Usage
const tx: TransactionRequest = {
from: '0xabc...',
to: '0xdef...',
data: '0xa9059cbb...',
value: '0x0',
chainId: 1
};
const txHash = await trace.web3.evm.sendTransaction(tx);
MiradorProviderOptions
Configuration for theMiradorProvider wrapper.
interface MiradorProviderOptions {
/** Bind to an existing trace instead of auto-creating per transaction */
trace?: Trace;
/** Trace options for auto-created traces (ignored if trace is provided) */
traceOptions?: TraceOptions;
}
Usage
import { Client, MiradorProvider } from '@miradorlabs/web-sdk';
const client = new Client('api-key');
// Auto-create a new trace per transaction
const provider = new MiradorProvider(window.ethereum, client);
// Or bind to an existing trace
const trace = client.trace({ name: 'MyFlow' });
const provider = new MiradorProvider(window.ethereum, client, { trace });
Utility Functions
Both SDKs export utility functions for stack traces and chain ID mapping. The Web SDK additionally exports browser metadata utilities. Both SDKs:import {
captureStackTrace,
formatStackTrace,
formatStackTraceReadable,
chainIdToName
} from '@miradorlabs/web-sdk'; // or '@miradorlabs/nodejs-sdk'
// Capture current stack trace
const stack = captureStackTrace();
// Format for storage (JSON)
const json = formatStackTrace(stack);
// Format for display (human-readable)
const readable = formatStackTraceReadable(stack);
// Convert chain ID to chain name
chainIdToName(1); // 'ethereum'
chainIdToName(137); // 'polygon'
chainIdToName(42161); // 'arbitrum'
chainIdToName(8453); // 'base'
chainIdToName(10); // 'optimism'
chainIdToName(56); // 'bsc'
chainIdToName(999); // undefined
import {
getClientMetadata,
detectBrowser,
detectOS,
detectDeviceType,
} from '@miradorlabs/web-sdk';
// Get full metadata object
const metadata = getClientMetadata();
// Individual detection
const browser = detectBrowser();
// { name: 'Chrome', version: '120.0.0' }
const os = detectOS();
// { name: 'macOS', version: '14.0' }
const device = detectDeviceType();
// 'desktop' | 'mobile' | 'tablet'
Next Steps
Client
Client class reference
Trace
Trace builder reference