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

otx-btc-wallet-connectors

v0.1.0

Published

Bitcoin wallet connectors for otx-btc-wallet

Readme

otx-btc-wallet-connectors

Bitcoin wallet connectors, blockchain services, and PSBT utilities for the otx-btc-wallet library.

Installation

pnpm add otx-btc-wallet-connectors otx-btc-wallet-core

Supported Wallets

| Wallet | Connector | Type | Sign PSBT | Batch PSBT | Send BTC | Network Switch | |--------|-----------|------|-----------|------------|----------|----------------| | Unisat | UnisatConnector | Extension | Yes | Yes | Yes | Yes | | Xverse | XverseConnector | Extension | Yes | No | Yes | Yes | | OKX | OKXConnector | Extension | Yes | No | Yes | No* | | Phantom | PhantomConnector | Extension | Yes | No | Yes | No** | | Bitget | BitgetConnector | Extension | Yes | No | Yes | Yes | | Binance | BinanceConnector | Extension | Yes | No | Yes | Yes | | imToken | ImTokenConnector | Mobile | Yes | No | Yes | Yes | | Ledger | LedgerConnector | Hardware | No*** | No | Yes | N/A | | Trezor | TrezorConnector | Hardware | No*** | No | Yes | N/A |

* OKX: Users switch network in the extension manually. ** Phantom: Only supports mainnet for Bitcoin. *** Hardware wallets use sendTransaction() directly with built-in PSBT construction.

Quick Start

import {
  UnisatConnector,
  XverseConnector,
  OKXConnector,
  PhantomConnector,
  BitgetConnector,
  BinanceConnector,
  ImTokenConnector,
  LedgerConnector,
  TrezorConnector,
} from 'otx-btc-wallet-connectors';

// Create a connector
const unisat = new UnisatConnector();

// Check if wallet is installed
if (unisat.ready) {
  // Connect
  const account = await unisat.connect('mainnet');
  console.log(account.address, account.publicKey, account.type);

  // Sign message
  const signature = await unisat.signMessage('Hello Bitcoin!');

  // Sign PSBT
  const signedPsbt = await unisat.signPsbt(psbtHex, {
    autoFinalize: true,
  });

  // Batch sign PSBTs (Unisat only)
  const signedPsbts = await unisat.signPsbts([psbt1, psbt2], {
    autoFinalize: true,
  });

  // Send Bitcoin (amount in satoshis)
  const txid = await unisat.sendTransaction('bc1q...', 10000);

  // Disconnect
  await unisat.disconnect();
}

Connector Interface

All connectors implement the BitcoinConnector interface from otx-btc-wallet-core:

interface BitcoinConnector {
  readonly id: string;         // Unique identifier (e.g. 'unisat')
  readonly name: string;       // Display name (e.g. 'Unisat')
  readonly icon: string;       // Base64 SVG/PNG icon
  ready: boolean;              // Is the wallet installed/available?

  connect(network?: BitcoinNetwork): Promise<WalletAccount>;
  disconnect(): Promise<void>;
  getAccounts(): Promise<WalletAccount[]>;
  signMessage(message: string): Promise<string>;
  signPsbt(psbtHex: string, options?: SignPsbtOptions): Promise<string>;
  signPsbts?(psbtHexs: string[], options?: SignPsbtOptions): Promise<string[]>;
  sendTransaction(to: string, satoshis: number): Promise<string>;
  getNetwork(): Promise<BitcoinNetwork>;
  switchNetwork?(network: BitcoinNetwork): Promise<void>;
  onAccountsChanged(callback: (accounts: WalletAccount[]) => void): () => void;
  onNetworkChanged(callback: (network: BitcoinNetwork) => void): () => void;
}

Event Listeners

All connectors support account and network change events:

// Listen for account changes
const unsubscribe = connector.onAccountsChanged((accounts) => {
  if (accounts.length === 0) {
    console.log('Wallet disconnected');
  } else {
    console.log('Account changed:', accounts[0].address);
  }
});

// Listen for network changes
const unsubNetwork = connector.onNetworkChanged((network) => {
  console.log('Network changed to:', network);
});

// Cleanup listeners
unsubscribe();
unsubNetwork();

Hardware Wallets

Ledger

Connects via WebUSB. Requires a Chromium-based browser (Chrome, Edge, Brave).

import { LedgerConnector } from 'otx-btc-wallet-connectors';
import type { LedgerConnectorOptions } from 'otx-btc-wallet-connectors';

const ledger = new LedgerConnector({
  addressType: 'segwit',  // 'legacy' | 'nested-segwit' | 'segwit' | 'taproot'
});

// Connect - opens USB device picker
const account = await ledger.connect('mainnet');

// Send Bitcoin (PSBT is built and signed internally)
const txid = await ledger.sendTransaction('bc1q...', 50000);

// Get multiple addresses from the device
const addresses = await ledger.getAddresses(0, 5); // indices 0-4

// Get extended public key
const xpub = await ledger.getExtendedPublicKey();

// Disconnect (closes USB transport)
await ledger.disconnect();

Ledger Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | addressType | AddressType | 'segwit' | Address derivation type |

Trezor

Connects via Trezor Connect.

import { TrezorConnector } from 'otx-btc-wallet-connectors';
import type { TrezorConnectorOptions } from 'otx-btc-wallet-connectors';

const trezor = new TrezorConnector({
  addressType: 'segwit',
  manifest: {
    email: '[email protected]',
    appUrl: 'https://your-app.com',
  },
});

// Connect - opens Trezor Connect popup
const account = await trezor.connect('mainnet');

// Send Bitcoin
const txid = await trezor.sendTransaction('bc1q...', 50000);

// Get multiple addresses
const addresses = await trezor.getAddresses(0, 5);

// Get extended public key
const xpub = await trezor.getExtendedPublicKey();

// Verify address on device screen
const verified = await trezor.getAddressWithVerification();

await trezor.disconnect();

Trezor Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | addressType | AddressType | 'segwit' | Address derivation type | | manifest.email | string | '[email protected]' | Contact email for Trezor | | manifest.appUrl | string | 'https://optimex.com' | App URL for Trezor |

Custom Connectors

Extend BaseConnector to add support for any Bitcoin wallet:

import { BaseConnector } from 'otx-btc-wallet-connectors';
import type {
  WalletAccount,
  BitcoinNetwork,
  SignPsbtOptions,
} from 'otx-btc-wallet-core';

export class MyWalletConnector extends BaseConnector {
  readonly id = 'my-wallet';
  readonly name = 'My Wallet';
  readonly icon = 'data:image/svg+xml;base64,...';

  // Return the wallet's injected provider, or null if not installed
  protected getProvider() {
    return (window as any).myWallet ?? null;
  }

  async connect(network: BitcoinNetwork = 'mainnet'): Promise<WalletAccount> {
    this.ensureInstalled(); // Throws if getProvider() returns null
    const provider = this.getProvider()!;

    const accounts = await provider.requestAccounts();
    const publicKey = await provider.getPublicKey();

    return {
      address: accounts[0],
      publicKey,
      type: this.inferAddressType(accounts[0]), // Auto-detect from address prefix
    };
  }

  async disconnect(): Promise<void> {
    this.cleanup(); // Removes event listeners
  }

  async getAccounts(): Promise<WalletAccount[]> {
    const provider = this.getProvider()!;
    const accounts = await provider.getAccounts();
    const publicKey = await provider.getPublicKey();
    return accounts.map((addr: string) => ({
      address: addr,
      publicKey,
      type: this.inferAddressType(addr),
    }));
  }

  async signMessage(message: string): Promise<string> {
    return this.getProvider()!.signMessage(message);
  }

  async signPsbt(psbtHex: string, options?: SignPsbtOptions): Promise<string> {
    return this.getProvider()!.signPsbt(psbtHex, options);
  }

  async sendTransaction(to: string, satoshis: number): Promise<string> {
    return this.getProvider()!.sendBitcoin(to, satoshis);
  }

  async getNetwork(): Promise<BitcoinNetwork> {
    return this.getProvider()!.getNetwork();
  }
}

BaseConnector Protected Methods

| Method | Description | |--------|-------------| | getProvider() | Abstract. Return the wallet's injected provider object | | ensureInstalled() | Throws error if getProvider() returns null/undefined | | inferAddressType(address) | Detects address type from prefix (1... = legacy, 3... = nested-segwit, bc1q... = segwit, bc1p... = taproot) | | handleError(error) | Wraps errors with connector context | | emitAccountsChanged(accounts) | Notify listeners of account changes | | emitNetworkChanged(network) | Notify listeners of network changes | | cleanup() | Remove all registered event listeners |

BtcService

BtcService provides a unified API for querying Bitcoin blockchain data. It uses a dual-provider architecture with Mempool.space and Blockstream.info for reliability.

Basic Usage

import { BtcService } from 'otx-btc-wallet-connectors';

const service = new BtcService('mainnet');

// Get UTXOs for an address
const utxos = await service.getUtxos('bc1q...');

// Get transaction hex
const txHex = await service.getTxHex('txid...');

// Get full transaction details
const tx = await service.getTransaction('txid...');

// Broadcast a signed transaction
const txid = await service.broadcastTransaction(signedTxHex);

// Get address balance
const balance = await service.getBalance('bc1q...');

// Get current fee rates (sat/vB)
const fees = await service.getFeeRates();
// { fastest: number, halfHour: number, hour: number, economy: number, minimum: number }

Standalone Functions

For convenience, you can also use standalone functions without creating an instance:

import {
  getUtxos,
  getTxHex,
  getTransaction,
  broadcastTransaction,
  getBalance,
  getFeeRates,
} from 'otx-btc-wallet-connectors';

const utxos = await getUtxos('mainnet', 'bc1q...');
const fees = await getFeeRates('mainnet');

Custom RPC Endpoints

Configure custom Mempool.space or Blockstream.info endpoints globally:

import { configureBtcService } from 'otx-btc-wallet-connectors';

configureBtcService({
  mempool: {
    mainnet: 'https://my-mempool.example.com/api',
    testnet: 'https://my-mempool.example.com/testnet/api',
  },
  blockstream: {
    mainnet: 'https://my-blockstream.example.com/api',
  },
  preferredProvider: 'mempool', // 'mempool' | 'blockstream' | 'race' (default)
});

Provider Modes:

| Mode | Description | |------|-------------| | 'race' | (Default) Sends requests to both providers simultaneously, uses whichever responds first | | 'mempool' | Only use Mempool.space | | 'blockstream' | Only use Blockstream.info |

Per-Instance Configuration

You can also pass config when creating a BtcService instance:

const service = new BtcService('mainnet', {
  mempool: { mainnet: 'https://my-mempool.example.com/api' },
  preferredProvider: 'mempool',
});

Configuration Types

import type { BtcServiceConfig, NetworkEndpoints } from 'otx-btc-wallet-connectors';

interface NetworkEndpoints {
  mainnet?: string;
  testnet?: string;
  testnet4?: string;
  signet?: string;
}

interface BtcServiceConfig {
  mempool?: NetworkEndpoints;
  blockstream?: NetworkEndpoints;
  preferredProvider?: 'mempool' | 'blockstream' | 'race';
}

Get Current Config

import { getBtcServiceConfig } from 'otx-btc-wallet-connectors';

const currentConfig = getBtcServiceConfig();

Service Types

import type {
  Utxo,
  UtxoWithTx,
  FeeRates,
  Transaction,
  FullTransaction,
  AddressBalance,
  IBtcService,
} from 'otx-btc-wallet-connectors';

interface Utxo {
  txid: string;
  vout: number;
  value: number;
  status: { confirmed: boolean; block_height?: number };
}

interface FeeRates {
  fastest: number;
  halfHour: number;
  hour: number;
  economy: number;
  minimum: number;
}

interface AddressBalance {
  confirmed: number;
  unconfirmed: number;
  total: number;
}

PSBT Builder Utilities

Low-level utilities for building Bitcoin transactions:

import {
  deriveAddressFromPublicKey,
  detectAddressType,
  estimateVBytes,
  selectUtxos,
  buildPsbt,
} from 'otx-btc-wallet-connectors';

Derive Address from Public Key

import { deriveAddressFromPublicKey } from 'otx-btc-wallet-connectors';

const address = deriveAddressFromPublicKey(
  publicKeyHex,    // Hex-encoded public key
  'segwit',        // 'legacy' | 'nested-segwit' | 'segwit' | 'taproot'
  'mainnet',       // Bitcoin network
);

Individual Service Classes

You can use Mempool or Blockstream services directly:

import { MempoolService, BlockstreamService } from 'otx-btc-wallet-connectors';

// Use Mempool.space directly
const mempool = new MempoolService('mainnet');
const utxos = await mempool.getUtxos('bc1q...');

// Use Blockstream.info directly
const blockstream = new BlockstreamService('mainnet');
const balance = await blockstream.getBalance('bc1q...');

// With custom endpoints
const customMempool = new MempoolService('mainnet', {
  mainnet: 'https://my-mempool.example.com/api',
});

Default API Endpoints

Mempool.space

| Network | Endpoint | |---------|----------| | mainnet | https://mempool.space/api | | testnet | https://mempool.space/testnet/api | | testnet4 | https://mempool.space/testnet4/api | | signet | https://mempool.space/signet/api |

Blockstream.info

| Network | Endpoint | |---------|----------| | mainnet | https://blockstream.info/api | | testnet | https://blockstream.info/testnet/api | | testnet4 | https://mempool.space/testnet4/api (fallback) | | signet | https://mempool.space/signet/api (fallback) |

Full Exports

// Connectors
export { UnisatConnector } from './unisat';
export { XverseConnector } from './xverse';
export { OKXConnector } from './okx';
export { PhantomConnector } from './phantom';
export { BitgetConnector } from './bitget';
export { BinanceConnector } from './binance';
export { ImTokenConnector } from './imtoken';
export { LedgerConnector } from './ledger';
export type { LedgerConnectorOptions } from './ledger';
export { TrezorConnector } from './trezor';
export type { TrezorConnectorOptions } from './trezor';

// Base class for custom connectors
export { BaseConnector } from './base';

// Services
export { BtcService } from './utils/btc-service';
export { MempoolService } from './utils/mempool';
export { BlockstreamService } from './utils/blockstream';

// Configuration
export { configureBtcService, getBtcServiceConfig } from './utils/btc-service';

// PSBT Builder
export { deriveAddressFromPublicKey } from './utils/psbt-builder';

// Standalone functions
export {
  getUtxos,
  getTxHex,
  getTransaction,
  broadcastTransaction,
  getBalance,
  getFeeRates,
} from './utils/btc-service';

// Types
export type {
  Utxo,
  UtxoWithTx,
  FeeRates,
  Transaction,
  FullTransaction,
  AddressBalance,
  IBtcService,
  BtcServiceConfig,
  NetworkEndpoints,
} from './utils/types';

License

MIT