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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@ledgerhq/ledger-wallet-provider

v1.0.2

Published

A comprehensive Web Components-based library that provides a complete Ledger hardware wallet integration solution for web applications. Built with Lit and designed to work with any frontend framework.

Readme

@ledgerhq/ledger-wallet-provider

A comprehensive Web Components-based library that provides a complete Ledger hardware wallet integration solution for web applications. Built with Lit and designed to work with any frontend framework.

Features

  • EIP-1193 Provider: Complete Ethereum Provider implementation with full JSON-RPC support
  • EIP-6963 Support: Multi-wallet discovery and selection
  • Framework Agnostic: Works with any frontend framework (React, Vue, Angular, Svelte, etc.)
  • Hardware Wallet Integration: Direct connection to Ledger devices via USB and Bluetooth
  • Modern UI: Pre-built components with Tailwind CSS styling and dark mode support
  • Transaction Signing: Support for Ethereum transactions, typed data, and personal messages
  • Account Management: Multi-account support and switching
  • Ledger Sync Integration: Seamless integration with Ledger's cloud services
  • Device Management: Support for multiple device types and connection methods

Installation

npm install @ledgerhq/ledger-wallet-provider

Quick Start

Basic Setup

import { initializeLedgerProvider } from '@ledgerhq/ledger-wallet-provider';
import '@ledgerhq/ledger-wallet-provider/styles.css';

// Initialize the Ledger provider
const cleanup = initializeLedgerProvider({
  devConfig: {
    stub: {
      base: false,              // Enable base stub mode for development
      account: false,           // Enable account stubbing
      device: false,            // Enable device stubbing
      web3Provider: false,      // Enable Web3 provider stubbing
      dAppConfig: false,        // Enable dApp config stubbing
    },
  },
  target: document.body,        // Optional: specify where to mount the UI
  dAppIdentifier: 'my-dapp',   // Your dApp identifier
  apiKey: 'your-api-key',      // Your Ledger API key
  loggerLevel: 'info',         // Log level: 'debug', 'info', 'warn', 'error'
  dmkConfig: undefined,        // Device Management Kit configuration (optional)
});

// Request provider discovery
window.dispatchEvent(new Event('eip6963:requestProvider'));

React Integration

import { useEffect, useState, useCallback } from 'react';
import type { EIP6963ProviderDetail } from '@ledgerhq/ledger-wallet-provider';

function useProviders() {
  const [providers, setProviders] = useState<EIP6963ProviderDetail[]>([]);
  const [selectedProvider, setSelectedProvider] = useState<EIP6963ProviderDetail | null>(null);

  const handleAnnounceProvider = useCallback((e: CustomEvent<EIP6963ProviderDetail>) => {
    setProviders(prev => {
      const found = prev.find(p => p.info.uuid === e.detail.info.uuid);
      if (found) return prev;
      return [...prev, e.detail];
    });
  }, []);

  useEffect(() => {
    // Dynamic import is required because the library uses browser APIs
    // and won't work with Server-Side Rendering (SSR)
    const initializeProvider = async () => {
      const { initializeLedgerProvider } = await import('@ledgerhq/ledger-wallet-provider');
      
      const cleanup = initializeLedgerProvider({
        devConfig: {
          stub: {
            base: false,              // Set to true for development
            account: false,           // Enable account stubbing
            device: false,            // Enable device stubbing
            web3Provider: false,      // Enable Web3 provider stubbing
            dAppConfig: false,        // Enable dApp config stubbing
          },
        },
        dAppIdentifier: 'my-dapp',
        apiKey: 'your-api-key',
        loggerLevel: 'info',         // Log level configuration
        dmkConfig: undefined,       // Device Management Kit config (optional)
      });

      window.addEventListener('eip6963:announceProvider', handleAnnounceProvider);
      
      return cleanup;
    };

    let cleanup: (() => void) | undefined;
    
    initializeProvider().then(cleanupFn => {
      cleanup = cleanupFn;
    });
    
    return () => {
      cleanup?.();
      window.removeEventListener('eip6963:announceProvider', handleAnnounceProvider);
    };
  }, [handleAnnounceProvider]);

  return { providers, selectedProvider, setSelectedProvider };
}

function App() {
  const { providers, selectedProvider, setSelectedProvider } = useProviders();
  const [account, setAccount] = useState<string | null>(null);

  const connectWallet = async () => {
    if (!selectedProvider) return;
    
    try {
      const accounts = await selectedProvider.provider.request({
        method: 'eth_requestAccounts',
        params: []
      });
      setAccount(accounts[0]);
    } catch (error) {
      console.error('Failed to connect:', error);
    }
  };

  const signTransaction = async (transaction: any) => {
    if (!selectedProvider) return;
    
    try {
      const result = await selectedProvider.provider.request({
        method: 'eth_signTransaction',
        params: [transaction]
      });
      return result;
    } catch (error) {
      console.error('Failed to sign transaction:', error);
    }
  };

  return (
    <div>
      {providers.map(provider => (
        <button 
          key={provider.info.uuid}
          onClick={() => setSelectedProvider(provider)}
        >
          Connect {provider.info.name}
        </button>
      ))}
      
      {selectedProvider && (
        <button onClick={connectWallet}>
          Request Accounts
        </button>
      )}
      
      {account && <p>Connected: {account}</p>}
    </div>
  );
}

API Reference

initializeLedgerProvider(options)

Initializes the Ledger Wallet Provider and injects the UI components into the DOM.

Parameters

{
  devConfig?: {
    stub?: {
      base?: boolean;            // Enable base stub mode for development (default: false)
      account?: boolean;         // Enable account stubbing (default: false)
      device?: boolean;          // Enable device stubbing (default: false)
      web3Provider?: boolean;    // Enable Web3 provider stubbing (default: false)
      dAppConfig?: boolean;      // Enable dApp config stubbing (default: false)
    };
  };
  target?: HTMLElement;        // Target element to mount UI (default: document.body)
  dAppIdentifier?: string;     // Your dApp identifier
  apiKey?: string;             // Your Ledger API key
  loggerLevel?: string;        // Log level: 'debug', 'info', 'warn', 'error' (default: 'info')
  dmkConfig?: any;             // Device Management Kit configuration (optional)
}

Returns

A cleanup function to remove the provider and UI components.

LedgerEIP1193Provider

The main provider class that implements the EIP-1193 standard.

Methods

  • request({ method, params }) - Make JSON-RPC requests
  • on(event, listener) - Listen to provider events
  • removeListener(event, listener) - Remove event listeners
  • isConnected() - Check connection status
  • disconnect() - Disconnect from the provider

Supported Methods

  • eth_requestAccounts - Request user accounts
  • eth_accounts - Get current accounts
  • eth_chainId - Get current chain ID
  • eth_sendTransaction - Send and sign transactions
  • eth_signTransaction - Sign transactions
  • eth_signRawTransaction - Sign raw transactions
  • eth_sign - Sign messages
  • personal_sign - Sign personal messages
  • eth_sendRawTransaction - Send raw transactions
  • eth_signTypedData - Sign typed data (EIP-712)
  • eth_signTypedData_v4 - Sign typed data v4 (EIP-712)
  • eth_getBalance - Get account balance (delegated to core)

Events

  • accountsChanged - Fired when accounts change
  • chainChanged - Fired when chain changes
  • connect - Fired when provider connects
  • disconnect - Fired when provider disconnects

Server-Side Rendering (SSR) Compatibility

The library uses browser-specific APIs and requires dynamic imports in SSR environments:

// ❌ Don't do this in SSR environments
import { initializeLedgerProvider } from '@ledgerhq/ledger-wallet-provider';

// ✅ Use dynamic imports instead
useEffect(() => {
  const initializeProvider = async () => {
    const { initializeLedgerProvider } = await import('@ledgerhq/ledger-wallet-provider');
    return initializeLedgerProvider({ /* options */ });
  };
  
  initializeProvider();
}, []);

Why dynamic imports are necessary:

  • The library uses Web APIs (window, document, CustomEvent) that don't exist in Node.js
  • Direct imports will cause build errors in SSR frameworks (Next.js, Nuxt, SvelteKit, etc.)
  • Dynamic imports ensure the code only runs in the browser environment

Styling

Import the CSS file to get the default styling:

import '@ledgerhq/ledger-wallet-provider/styles.css';

Development Mode

For development and testing, you can enable stub mode:

const cleanup = initializeLedgerProvider({
  devConfig: {
    stub: {
      base: true,              // Enable base stub mode
      account: true,           // Mock account operations
      device: true,            // Mock device interactions
      web3Provider: true,      // Mock Web3 provider responses
      dAppConfig: true,        // Mock dApp configuration
    },
  },
  dAppIdentifier: 'my-dapp',
  apiKey: 'your-api-key',
});

Requirements

  • ES2020+ support
  • Modern bundler (Vite, Webpack 5+, etc.)
  • Browser environment (no Node.js server-side execution)
  • Web HID API support (for USB connections)
  • Web Bluetooth API support (for Bluetooth connections)
  • Note: Mobile browsers are not supported due to Web HID/BLE API not being implemented

Browser Support

  • Desktop: Chrome 89+, Firefox 89+, Safari 14.1+, Edge 89+
  • Mobile: Not supported (Web HID/BLE APIs not available)
  • Web Extensions: Supported in manifest v3 extensions

Building

Run nx build ledger-wallet-provider to build the library.

Testing

Run nx test ledger-wallet-provider to execute the unit tests via Vitest.

Storybook

Run nx storybook ledger-wallet-provider to start the Storybook development server for component development and testing.

Version

Current version: 1.0.0-rc.5

This is a release candidate version. The API is stable but may have minor changes before the final 1.0.0 release.

License

This project is licensed under the MIT License.