npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lavarage/telemetry

v1.2.2

Published

Production telemetry SDK for Lavarage and partner applications

Downloads

56

Readme

@lavarage/telemetry

Production telemetry SDK for Lavarage and partner applications. Track user activity, network requests, and errors with comprehensive filtering and privacy controls.

Installation

npm install @lavarage/telemetry

Quick Start

import { LavarageTelemetry } from '@lavarage/telemetry';

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
});

// Intercept network requests
telemetry.interceptFetch();

// Connect wallet (triggers login event)
// Wallet platform is automatically detected (MetaMask, Phantom, etc.)
// or you can specify it manually:
telemetry.setWallet('YourWalletAddress123...', 'MetaMask');

// Track trading pair views
telemetry.trackPairView('SOL/USDC', { source: 'homepage' });

Configuration

Basic Configuration

const telemetry = new LavarageTelemetry({
  apiEndpoint: string;        // Required: Backend API endpoint
  platform: string;           // Required: Platform identifier (e.g., 'lavarage-web')
  captureHosts?: HostFilterInput;  // Optional: Host filtering configuration
  errorFilters?: ErrorFilterConfig; // Optional: Error filtering configuration
  batchSize?: number;         // Optional: Max events per batch (default: 50)
  flushInterval?: number;     // Optional: Flush interval in ms (default: 5000)
});

Host Filtering

Control which network requests are captured using flexible host filtering.

String Configuration

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
  captureHosts: 'api.lavarage.com', // Only capture requests to this host
});

Array Configuration

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
  captureHosts: [
    'api.lavarage.com',
    'partner-api.com',
    '*.example.com' // Wildcard: matches any subdomain
  ],
});

Object Configuration

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
  captureHosts: {
    mode: 'include', // 'all' | 'none' | 'include' | 'exclude'
    hosts: ['api.lavarage.com', '*.partner.com'],
    patterns: ['^api\\..*\\.lavarage\\.com$'] // Regex patterns
  },
});

Wildcard Matching

  • *.example.com - Matches any subdomain (e.g., api.example.com, www.example.com)
  • example.com - Matches the domain and all subdomains

Update Host Filter at Runtime

telemetry.updateHostFilter({
  mode: 'exclude',
  hosts: ['analytics.google.com', '*.tracking.com']
});

Error Filtering

Filter which errors are captured using include/exclude patterns.

Example 1: Only Capture Specific Errors

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
  errorFilters: {
    include: [
      'Failed to fetch',
      'Network error',
      'Transaction.*failed',
      'RPC.*error'
    ]
  }
});

Example 2: Exclude Noisy Errors

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
  errorFilters: {
    exclude: [
      'ResizeObserver',
      'Extension context invalidated',
      'Script error',
      'Non-Error promise rejection'
    ]
  }
});

Example 3: Combined Filtering

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
  errorFilters: {
    include: ['.*'], // Capture everything
    exclude: [
      'chrome-extension://',
      'moz-extension://',
      'webkit-masked-url://',
      'ResizeObserver loop',
      'Script error\\.'
    ]
  }
});

Filter Logic:

  • If include patterns are provided, ONLY errors matching those patterns are captured
  • If exclude patterns are provided, all errors EXCEPT those matching patterns are captured
  • If both are provided, include is applied first, then exclude

Axios Integration

If you're using Axios, you can intercept Axios requests:

import axios from 'axios';
import { LavarageTelemetry } from '@lavarage/telemetry';

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
});

const axiosInstance = axios.create({
  baseURL: 'https://api.lavarage.com',
});

// Intercept Axios requests
telemetry.interceptAxios(axiosInstance);

Security Features

Automatic Data Sanitization

The SDK automatically sanitizes sensitive data in all payloads and responses:

  • privateKey
  • mnemonic
  • password
  • secret
  • token
  • apiKey
  • authorization

Sensitive fields are replaced with [REDACTED] recursively in nested objects and arrays.

Silent Error Handling

All telemetry operations are wrapped in try-catch blocks. Telemetry errors will never disrupt your application.

API Reference

Methods

setWallet(walletAddress: string, walletPlatform?: string)

Set the current wallet address and trigger a login event. The wallet platform (e.g., 'MetaMask', 'Phantom', 'WalletConnect') is automatically detected from the browser environment, but you can also specify it manually.

Supported auto-detected platforms:

  • MetaMask
  • Coinbase Wallet
  • Trust Wallet
  • WalletConnect
  • Phantom (Solana)
  • Solflare (Solana)
  • Generic Ethereum/Solana providers
// Auto-detect wallet platform
telemetry.setWallet('YourWalletAddress123...');

// Or specify manually
telemetry.setWallet('YourWalletAddress123...', 'MetaMask');

interceptFetch()

Intercept the global fetch API to capture network requests.

telemetry.interceptFetch();

interceptAxios(axiosInstance: any)

Intercept an Axios instance to capture network requests.

telemetry.interceptAxios(axiosInstance);

trackPairView(pair: string, metadata?: object)

Track a trading pair view event.

telemetry.trackPairView('SOL/USDC', {
  source: 'homepage',
  category: 'trending'
});

trackSystemEvent(category: string, message: string, level?: string, metadata?: object)

Track a system event (not tied to any wallet address). System events are displayed in a separate panel in the dashboard.

// Track app startup
telemetry.trackSystemEvent('app_start', 'Application initialized', 'info');

trackStateChange(stateName: string, previousValue?: any, newValue?: any, action?: string, metadata?: object)

Track a React state change. Useful for debugging and understanding user interactions.

// Track a state change manually
telemetry.trackStateChange(
  'userPreferences',
  { theme: 'light' },
  { theme: 'dark' },
  'TOGGLE_THEME',
  { source: 'settings-panel' }
);

// Track feature usage telemetry.trackSystemEvent('feature_used', 'User enabled dark mode', 'info', { feature: 'dark_mode', version: '1.2.3' });

// Track configuration changes telemetry.trackSystemEvent('config_change', 'API endpoint updated', 'warning', { old_endpoint: 'https://api.example.com', new_endpoint: 'https://api2.example.com' });

// Track errors telemetry.trackSystemEvent('system_error', 'Failed to load configuration', 'error', { error_code: 'CONFIG_LOAD_FAILED' });


**Parameters:**
- `category` - Event category (e.g., 'app_start', 'feature_used', 'config_change')
- `message` - Event message
- `level` - Event level: 'info' | 'warning' | 'error' | 'debug' (default: 'info')
- `metadata` - Optional additional metadata object

#### `updateHostFilter(captureHosts: HostFilterInput)`

Update the host filter configuration at runtime.

```typescript
telemetry.updateHostFilter({
  mode: 'exclude',
  hosts: ['analytics.google.com']
});

logWalletEvent(walletAddress: string, eventType: string, message: string, metadata?: object)

Log a custom event with wallet address (backend-friendly method). Events are queued and sent in batches.

telemetry.logWalletEvent(
  'WalletAddress123...',
  'transaction',
  'Transaction completed',
  { txHash: '0x...', amount: '100' }
);

sendLog(walletAddress: string, eventType: string, message: string, metadata?: object): Promise<void>

Send a log event immediately, bypassing the batch queue. Useful for critical logs.

await telemetry.sendLog(
  'WalletAddress123...',
  'critical',
  'Security alert',
  { alertType: 'suspicious_activity' }
);

destroy()

Clean up the telemetry instance, restore original functions, and flush remaining events.

telemetry.destroy();

React State Tracking

The SDK provides React hooks for automatically tracking state changes in your React components.

Installation

# Install the SDK
npm install @lavarage/telemetry

# If you want to use React hooks, also install React (peer dependency)
npm install react

Quick Start

import { LavarageTelemetry } from '@lavarage/telemetry';
// Import React hooks from the separate entry point
import { useTrackedState } from '@lavarage/telemetry/react';

const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'lavarage-web',
});

function MyComponent() {
  // Automatically tracks all state changes
  const [count, setCount] = useTrackedState(0, {
    stateName: 'counter',
    telemetry: telemetry,
    action: 'SET_COUNT'
  });

  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}

Available Hooks

useTrackedState(initialState, config)

Wraps React's useState and automatically tracks state changes.

const [state, setState] = useTrackedState(initialValue, {
  stateName: 'userPreferences',  // Required: name for this state
  telemetry: telemetryInstance,   // Required: telemetry instance
  trackInitial: false,             // Optional: track initial state (default: false)
  action: 'UPDATE_PREFERENCES',    // Optional: action name
  metadata: { source: 'settings' }, // Optional: additional metadata
  shouldTrack: (prev, next) => {   // Optional: filter which changes to track
    return prev !== next;          // Only track if values actually changed
  }
});

useTrackedReducer(reducer, initialState, config)

Wraps React's useReducer and automatically tracks state changes with action information.

const [state, dispatch] = useTrackedReducer(reducer, initialState, {
  stateName: 'cart',
  telemetry: telemetryInstance,
  trackInitial: false,
  metadata: { userId: '123' }
});

// Dispatch actions normally - they'll be tracked automatically
dispatch({ type: 'ADD_ITEM', payload: { id: 1, name: 'Product' } });

useStateTracker(telemetry)

Returns a function to manually track state changes with more control.

const trackState = useStateTracker(telemetry);

const handleChange = (newValue) => {
  trackState('theme', currentValue, newValue, 'SET_THEME', {
    source: 'user-action'
  });
  setCurrentValue(newValue);
};

Configuration Options

  • stateName (required): A unique identifier for this state (e.g., 'cart', 'userPreferences', 'theme')
  • telemetry (required): Your telemetry instance
  • trackInitial (optional): Whether to track the initial state value (default: false)
  • action (optional): Action name to use when tracking (default: 'STATE_CHANGE')
  • metadata (optional): Additional context to include with each state change
  • shouldTrack (optional): Function to filter which changes to track - useful for avoiding noise

Example: Shopping Cart

import { useTrackedState } from '@lavarage/telemetry/react';

function ShoppingCart() {
  const [items, setItems] = useTrackedState([], {
    stateName: 'cartItems',
    telemetry: telemetry,
    action: 'CART_UPDATE',
    shouldTrack: (prev, next) => {
      // Only track if cart actually changed (not just reference)
      return JSON.stringify(prev) !== JSON.stringify(next);
    }
  });

  const addItem = (item) => {
    setItems([...items, item]);
    // State change is automatically tracked!
  };

  return (
    <div>
      {items.map(item => <div key={item.id}>{item.name}</div>)}
      <button onClick={() => addItem({ id: 1, name: 'Product' })}>
        Add Item
      </button>
    </div>
  );
}

Example: User Preferences with useReducer

import { useTrackedReducer } from '@lavarage/telemetry/react';

function preferencesReducer(state, action) {
  switch (action.type) {
    case 'SET_THEME':
      return { ...state, theme: action.payload };
    case 'SET_LANGUAGE':
      return { ...state, language: action.payload };
    default:
      return state;
  }
}

function UserPreferences() {
  const [prefs, dispatch] = useTrackedReducer(
    preferencesReducer,
    { theme: 'light', language: 'en' },
    {
      stateName: 'userPreferences',
      telemetry: telemetry,
      metadata: { userId: currentUser.id }
    }
  );

  return (
    <div>
      <button onClick={() => dispatch({ type: 'SET_THEME', payload: 'dark' })}>
        Dark Mode
      </button>
      {/* State changes are automatically tracked with action type! */}
    </div>
  );
}

Event Types

The SDK tracks the following event types:

  • login: Triggered when setWallet() is called
  • pair_view: Trading pair view events
  • error: Console errors, uncaught exceptions, and unhandled promise rejections
  • request: Network requests (fetch/Axios)
  • system_event: System-level events not tied to any wallet address (displayed in separate dashboard panel)
  • log: Custom log events (via logWalletEvent() or sendLog())
  • state_change: React state changes (via trackStateChange() or React hooks)

Batching

Events are automatically batched and sent to the backend:

  • Default batch size: 50 events
  • Default flush interval: 5 seconds
  • Automatic flush: On page unload (using keepalive for reliable delivery)

Backend Usage

The SDK works in both browser and Node.js environments. For backend applications, you can use a subset of features focused on manual logging.

Installation for Backend

npm install @lavarage/telemetry
# For Node.js < 18, also install node-fetch:
npm install node-fetch@2

Backend Quick Start

import { LavarageTelemetry } from '@lavarage/telemetry';

// Initialize telemetry for backend
const telemetry = new LavarageTelemetry({
  apiEndpoint: 'https://telemetry.lavarage.com',
  platform: 'my-backend-service',
  batchSize: 100, // Larger batches for backend
  flushInterval: 10000, // Flush every 10 seconds
});

// Log events related to a wallet address
telemetry.logWalletEvent(
  'DummyWallet123456789',
  'transaction',
  'Transaction completed successfully',
  {
    txHash: '0x123...',
    amount: '100.5',
    token: 'USDC'
  }
);

// Log errors with wallet context
telemetry.logWalletEvent(
  'DummyWallet123456789',
  'error',
  'Failed to process transaction',
  {
    errorCode: 'INSUFFICIENT_FUNDS',
    attemptedAmount: '200.0'
  }
);

// Send critical logs immediately (bypasses batching)
await telemetry.sendLog(
  'DummyWallet123456789',
  'critical',
  'Security alert: suspicious activity detected',
  {
    alertType: 'unusual_pattern',
    severity: 'high'
  }
);

Backend API Methods

logWalletEvent(walletAddress: string, eventType: string, message: string, metadata?: object)

Queue a log event with a wallet address. Events are batched and sent automatically.

telemetry.logWalletEvent(
  'WalletAddress123...',
  'transaction', // Event type (e.g., 'transaction', 'error', 'action')
  'Transaction completed', // Log message
  { txHash: '0x...', amount: '100' } // Optional metadata
);

sendLog(walletAddress: string, eventType: string, message: string, metadata?: object): Promise<void>

Send a log event immediately, bypassing the batch queue. Useful for critical logs that need immediate delivery.

await telemetry.sendLog(
  'WalletAddress123...',
  'critical',
  'Security alert',
  { alertType: 'suspicious_activity' }
);

setWallet(walletAddress: string, walletPlatform?: string)

Set the default wallet address for subsequent events. This is optional for backend use since you can specify the wallet in each log call. You can also optionally specify the wallet platform.

telemetry.setWallet('WalletAddress123...', 'MetaMask');
// Now all events will use this wallet by default
telemetry.logWalletEvent(
  null, // Will use the wallet set above
  'action',
  'User performed action'
);

Backend Example: Express.js Middleware

import express from 'express';
import { LavarageTelemetry } from '@lavarage/telemetry';

const telemetry = new LavarageTelemetry({
  apiEndpoint: process.env.TELEMETRY_ENDPOINT!,
  platform: 'api-server',
});

const app = express();

// Middleware to log wallet-related requests
app.use('/api/wallet/:walletAddress', (req, res, next) => {
  const walletAddress = req.params.walletAddress;
  
  // Log the request
  telemetry.logWalletEvent(
    walletAddress,
    'api_request',
    `${req.method} ${req.path}`,
    {
      method: req.method,
      path: req.path,
      userAgent: req.get('user-agent'),
    }
  );
  
  next();
});

// Log transaction events
app.post('/api/transactions', async (req, res) => {
  const { walletAddress, txHash } = req.body;
  
  try {
    // Process transaction...
    
    telemetry.logWalletEvent(
      walletAddress,
      'transaction',
      'Transaction processed successfully',
      { txHash, status: 'success' }
    );
    
    res.json({ success: true });
  } catch (error) {
    telemetry.logWalletEvent(
      walletAddress,
      'error',
      'Transaction failed',
      { txHash, error: error.message }
    );
    
    res.status(500).json({ error: error.message });
  }
});

Backend Example: Error Handler

import { LavarageTelemetry } from '@lavarage/telemetry';

const telemetry = new LavarageTelemetry({
  apiEndpoint: process.env.TELEMETRY_ENDPOINT!,
  platform: 'api-server',
});

// Global error handler
process.on('uncaughtException', (error) => {
  // Extract wallet from error context if available
  const walletAddress = (error as any).walletAddress || null;
  
  if (walletAddress) {
    telemetry.logWalletEvent(
      walletAddress,
      'error',
      `Uncaught exception: ${error.message}`,
      {
        stack: error.stack,
        name: error.name,
      }
    );
  }
});

Browser Support

  • Modern browsers with ES2020 support
  • Node.js 18+ (native fetch support)
  • Node.js < 18 requires node-fetch package

License

MIT