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

@tomo-inc/wallet-connect-protocol

v0.0.17

Published

WalletConnect protocol SDK for Tomo Wallet - Pure JavaScript

Readme

@tomo-inc/wallet-connect-protocol

WalletConnect Protocol SDK for Tomo Wallet - Pure JavaScript / Framework-Agnostic

📖 Introduction

@tomo-inc/wallet-connect-protocol is a lightweight, framework-agnostic WalletConnect SDK designed specifically for the Tomo Wallet ecosystem. It provides a clean JavaScript API for integrating WalletConnect protocol into any application, regardless of the framework you use.

✨ Features

  • 🚀 Framework-Agnostic - Works with vanilla JavaScript, Vue, Angular, Svelte, React, or any other framework
  • 🌐 Multi-Chain Support - Supports Ethereum, Solana, Aptos, Cosmos, and more
  • 📱 QR Code Generation - Built-in QR code generation with multiple format support
  • 🔗 URI Management - Automatic generation and management of WalletConnect URIs
  • 📦 TypeScript Support - Full type definitions
  • Lightweight - Minimal dependencies, no framework overhead
  • 🎯 Simple API - Clean, intuitive API design

📦 Installation

# Using pnpm
pnpm add @tomo-inc/wallet-connect-protocol

# Using npm
npm install @tomo-inc/wallet-connect-protocol

# Using yarn
yarn add @tomo-inc/wallet-connect-protocol

🚀 Quick Start

1. Get Project ID

First, obtain a free Project ID from WalletConnect Cloud.

2. Create Client

import { WalletConnectClient } from "@tomo-inc/wallet-connect-protocol";

const client = new WalletConnectClient({
  projectId: "YOUR_PROJECT_ID",
  metadata: {
    name: "My DApp",
    description: "My awesome decentralized application",
    url: "https://myapp.com",
    icons: ["https://myapp.com/icon.png"],
  },
});

// Initialize the client
await client.initialize();

3. Connect

// Create connection and get URI
const uri = await client.connect();

// Generate QR code
const qrCodeBase64 = await client.generateQRCode(uri, {
  width: 300,
  margin: 4,
});

// Display QR code
document.getElementById("qr-code").src = qrCodeBase64;

4. Listen to Events

// Listen for session approval
client.on("session_update", (session) => {
  console.log("Session approved:", session);
  // Handle successful connection
});

// Listen for disconnection
client.on("session_delete", (data) => {
  console.log("Session disconnected:", data);
});

📚 API Documentation

WalletConnectClient

Core client class providing all WalletConnect functionality.

Constructor

new WalletConnectClient(config: WalletConnectConfig)

WalletConnectConfig:

interface WalletConnectConfig {
  projectId: string; // WalletConnect Project ID
  metadata: {
    name: string; // App name
    description: string; // App description
    url: string; // App URL
    icons: string[]; // App icons
  };
  relayUrl?: string; // Optional relay server URL
}

Methods

initialize(): Promise<void>

Initialize the WalletConnect client. Must be called before any other operations.

await client.initialize();
connect(params?: ConnectParams): Promise<string>

Create a pairing connection and generate WalletConnect URI.

const uri = await client.connect();

// With custom namespaces
const uri = await client.connect({
  requiredNamespaces: {
    eip155: {
      methods: ["eth_sendTransaction", "personal_sign"],
      chains: ["eip155:1"],
      events: ["chainChanged", "accountsChanged"],
    },
  },
});
generateQRCode(uri: string, options?: QRCodeOptions): Promise<string>

Generate QR code as Base64 data URL.

const qrCode = await client.generateQRCode(uri, {
  width: 300,
  margin: 4,
  errorCorrectionLevel: "M",
  color: {
    dark: "#000000",
    light: "#ffffff",
  },
});

QRCodeOptions:

interface QRCodeOptions {
  width?: number; // QR code width (default: 300)
  margin?: number; // Margin size (default: 4)
  errorCorrectionLevel?: "L" | "M" | "Q" | "H"; // Error correction (default: 'M')
  color?: {
    dark?: string; // Dark color (default: '#000000')
    light?: string; // Light color (default: '#ffffff')
  };
}
generateQRCodeToCanvas(canvas: HTMLCanvasElement, uri: string, options?: QRCodeOptions): Promise<void>

Generate QR code directly to a canvas element.

const canvas = document.getElementById("qr-canvas") as HTMLCanvasElement;
await client.generateQRCodeToCanvas(canvas, uri, {
  width: 300,
  margin: 4,
});
getActiveSessions(): SessionInfo[]

Get all active WalletConnect sessions.

const sessions = client.getActiveSessions();
sessions.forEach((session) => {
  console.log("Session:", session.topic);
  console.log("Peer:", session.peer.metadata.name);
  console.log("Chains:", session.namespaces);
});
disconnectSession(topic: string): Promise<void>

Disconnect a specific session.

await client.disconnectSession(sessionTopic);
sendRequest(params): Promise<any>

Send JSON-RPC request to the connected wallet.

const result = await client.sendRequest({
  topic: sessionTopic,
  chainId: "eip155:1",
  request: {
    method: "personal_sign",
    params: ["0x...message", "0x...address"],
  },
});
on<T>(event: WalletConnectEvent, handler: EventHandler<T>): void

Listen to WalletConnect events.

client.on("session_proposal", (proposal) => {
  console.log("Session proposal:", proposal);
});

client.on("session_update", (session) => {
  console.log("Session updated:", session);
});

client.on("session_delete", (data) => {
  console.log("Session deleted:", data);
});

client.on("display_uri", ({ uri }) => {
  console.log("WalletConnect URI:", uri);
});

Available Events:

  • session_proposal - New session proposal received
  • session_update - Session updated or approved
  • session_delete - Session disconnected
  • session_request - Request received from wallet
  • display_uri - URI generated and ready to display
off<T>(event: WalletConnectEvent, handler: EventHandler<T>): void

Remove event listener.

const handler = (data) => console.log(data);
client.on("session_update", handler);
client.off("session_update", handler);
destroy(): Promise<void>

Destroy the client and clean up resources.

await client.destroy();
isInitialized(): boolean

Check if the client is initialized.

if (client.isInitialized()) {
  // Client is ready
}
getConfig(): WalletConnectConfig

Get the current configuration.

const config = client.getConfig();
console.log("Project ID:", config.projectId);

🎯 Usage Examples

Vanilla JavaScript

<!DOCTYPE html>
<html>
  <head>
    <title>WalletConnect Example</title>
  </head>
  <body>
    <button id="connect-btn">Connect Wallet</button>
    <div id="qr-container" style="display: none;">
      <h3>Scan QR Code</h3>
      <img id="qr-code" />
    </div>
    <div id="session-info"></div>

    <script type="module">
      import { WalletConnectClient } from "@tomo-inc/wallet-connect-protocol";

      const client = new WalletConnectClient({
        projectId: "YOUR_PROJECT_ID",
        metadata: {
          name: "My DApp",
          description: "Example DApp",
          url: "https://myapp.com",
          icons: ["https://myapp.com/icon.png"],
        },
      });

      await client.initialize();

      document
        .getElementById("connect-btn")
        .addEventListener("click", async () => {
          const uri = await client.connect();
          const qrCode = await client.generateQRCode(uri);

          document.getElementById("qr-code").src = qrCode;
          document.getElementById("qr-container").style.display = "block";
        });

      client.on("session_update", (session) => {
        document.getElementById("session-info").innerHTML =
          `Connected to: ${session.peer.metadata.name}`;
        document.getElementById("qr-container").style.display = "none";
      });
    </script>
  </body>
</html>

Vue 3

<template>
  <div>
    <button @click="handleConnect">Connect Wallet</button>
    <div v-if="qrCode">
      <h3>Scan QR Code</h3>
      <img :src="qrCode" />
    </div>
    <div v-if="sessions.length > 0">
      <h3>Connected Sessions</h3>
      <ul>
        <li v-for="session in sessions" :key="session.topic">
          {{ session.peer.metadata.name }}
          <button @click="disconnect(session.topic)">Disconnect</button>
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
import { WalletConnectClient } from "@tomo-inc/wallet-connect-protocol";

const client = new WalletConnectClient({
  projectId: "YOUR_PROJECT_ID",
  metadata: {
    name: "My Vue DApp",
    description: "Example Vue DApp",
    url: "https://myapp.com",
    icons: ["https://myapp.com/icon.png"],
  },
});

const qrCode = ref<string | null>(null);
const sessions = ref<any[]>([]);

onMounted(async () => {
  await client.initialize();

  client.on("session_update", (session) => {
    sessions.value = client.getActiveSessions();
    qrCode.value = null;
  });
});

const handleConnect = async () => {
  const uri = await client.connect();
  qrCode.value = await client.generateQRCode(uri);
};

const disconnect = async (topic: string) => {
  await client.disconnectSession(topic);
  sessions.value = client.getActiveSessions();
};

onUnmounted(async () => {
  await client.destroy();
});
</script>

Angular

import { Component, OnInit, OnDestroy } from "@angular/core";
import {
  WalletConnectClient,
  SessionInfo,
} from "@tomo-inc/wallet-connect-protocol";

@Component({
  selector: "app-wallet-connect",
  template: `
    <button (click)="handleConnect()">Connect Wallet</button>
    <div *ngIf="qrCode">
      <h3>Scan QR Code</h3>
      <img [src]="qrCode" />
    </div>
    <div *ngIf="sessions.length > 0">
      <h3>Connected Sessions</h3>
      <ul>
        <li *ngFor="let session of sessions">
          {{ session.peer.metadata.name }}
          <button (click)="disconnect(session.topic)">Disconnect</button>
        </li>
      </ul>
    </div>
  `,
})
export class WalletConnectComponent implements OnInit, OnDestroy {
  private client: WalletConnectClient;
  qrCode: string | null = null;
  sessions: SessionInfo[] = [];

  constructor() {
    this.client = new WalletConnectClient({
      projectId: "YOUR_PROJECT_ID",
      metadata: {
        name: "My Angular DApp",
        description: "Example Angular DApp",
        url: "https://myapp.com",
        icons: ["https://myapp.com/icon.png"],
      },
    });
  }

  async ngOnInit() {
    await this.client.initialize();

    this.client.on("session_update", () => {
      this.sessions = this.client.getActiveSessions();
      this.qrCode = null;
    });
  }

  async handleConnect() {
    const uri = await this.client.connect();
    this.qrCode = await this.client.generateQRCode(uri);
  }

  async disconnect(topic: string) {
    await this.client.disconnectSession(topic);
    this.sessions = this.client.getActiveSessions();
  }

  async ngOnDestroy() {
    await this.client.destroy();
  }
}

Svelte

<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import { WalletConnectClient } from '@tomo-inc/wallet-connect-protocol';

  let client: WalletConnectClient;
  let qrCode: string | null = null;
  let sessions: any[] = [];

  onMount(async () => {
    client = new WalletConnectClient({
      projectId: 'YOUR_PROJECT_ID',
      metadata: {
        name: 'My Svelte DApp',
        description: 'Example Svelte DApp',
        url: 'https://myapp.com',
        icons: ['https://myapp.com/icon.png'],
      },
    });

    await client.initialize();

    client.on('session_update', () => {
      sessions = client.getActiveSessions();
      qrCode = null;
    });
  });

  async function handleConnect() {
    const uri = await client.connect();
    qrCode = await client.generateQRCode(uri);
  }

  async function disconnect(topic: string) {
    await client.disconnectSession(topic);
    sessions = client.getActiveSessions();
  }

  onDestroy(async () => {
    if (client) {
      await client.destroy();
    }
  });
</script>

<button on:click={handleConnect}>Connect Wallet</button>

{#if qrCode}
  <div>
    <h3>Scan QR Code</h3>
    <img src={qrCode} alt="WalletConnect QR Code" />
  </div>
{/if}

{#if sessions.length > 0}
  <div>
    <h3>Connected Sessions</h3>
    <ul>
      {#each sessions as session}
        <li>
          {session.peer.metadata.name}
          <button on:click={() => disconnect(session.topic)}>Disconnect</button>
        </li>
      {/each}
    </ul>
  </div>
{/if}

React

import { useEffect, useState } from "react";
import {
  WalletConnectClient,
  SessionInfo,
} from "@tomo-inc/wallet-connect-protocol";

function WalletConnect() {
  const [client] = useState(
    () =>
      new WalletConnectClient({
        projectId: "YOUR_PROJECT_ID",
        metadata: {
          name: "My React DApp",
          description: "Example React DApp",
          url: "https://myapp.com",
          icons: ["https://myapp.com/icon.png"],
        },
      }),
  );

  const [qrCode, setQrCode] = useState<string | null>(null);
  const [sessions, setSessions] = useState<SessionInfo[]>([]);

  useEffect(() => {
    client.initialize();

    const handleSessionUpdate = () => {
      setSessions(client.getActiveSessions());
      setQrCode(null);
    };

    client.on("session_update", handleSessionUpdate);

    return () => {
      client.off("session_update", handleSessionUpdate);
      client.destroy();
    };
  }, [client]);

  const handleConnect = async () => {
    const uri = await client.connect();
    const qr = await client.generateQRCode(uri);
    setQrCode(qr);
  };

  const disconnect = async (topic: string) => {
    await client.disconnectSession(topic);
    setSessions(client.getActiveSessions());
  };

  return (
    <div>
      <button onClick={handleConnect}>Connect Wallet</button>
      {qrCode && (
        <div>
          <h3>Scan QR Code</h3>
          <img src={qrCode} alt="WalletConnect QR Code" />
        </div>
      )}
      {sessions.length > 0 && (
        <div>
          <h3>Connected Sessions</h3>
          <ul>
            {sessions.map((session) => (
              <li key={session.topic}>
                {session.peer.metadata.name}
                <button onClick={() => disconnect(session.topic)}>
                  Disconnect
                </button>
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

🔧 Advanced Usage

Multi-Chain Support

import {
  createMultiChainNamespaces,
  EVM_CHAINS,
  SOLANA_CHAINS,
} from "@tomo-inc/wallet-connect-protocol";

// Create multi-chain namespaces configuration
const namespaces = createMultiChainNamespaces({
  evm: {
    chains: [EVM_CHAINS.ethereum, EVM_CHAINS.polygon],
    methods: ["eth_sendTransaction", "personal_sign"],
  },
  solana: {
    chains: [SOLANA_CHAINS.mainnet],
    methods: ["solana_signTransaction", "solana_signMessage"],
  },
});

const uri = await client.connect({
  requiredNamespaces: namespaces,
});

SIWE (Sign-In with Ethereum)

import { SiweAuth, createSiweMessage } from "@tomo-inc/wallet-connect-protocol";

const siwe = new SiweAuth({
  domain: "myapp.com",
  uri: "https://myapp.com",
  statement: "Sign in to My DApp",
});

// Create SIWE message
const message = createSiweMessage({
  domain: "myapp.com",
  address: "0x...",
  chainId: 1,
  uri: "https://myapp.com",
  statement: "Sign in to My DApp",
});

// Request signature from wallet
const signature = await client.sendRequest({
  topic: sessionTopic,
  chainId: "eip155:1",
  request: {
    method: "personal_sign",
    params: [message, address],
  },
});

// Verify signature
const isValid = await siwe.verify(message, signature);

Custom QR Code Styling

const qrCode = await client.generateQRCode(uri, {
  width: 400,
  margin: 8,
  errorCorrectionLevel: "H",
  color: {
    dark: "#1a1a1a",
    light: "#f0f0f0",
  },
});

Wallet Discovery

import {
  getAllWallets,
  getRecommendedWallets,
  searchWallets,
} from "@tomo-inc/wallet-connect-protocol";

// Get all available wallets
const allWallets = await getAllWallets();

// Get recommended wallets
const recommended = await getRecommendedWallets();

// Search for specific wallets
const results = await searchWallets("metamask");

🌐 Utility Functions

The SDK provides various utility functions:

import {
  formatAddress, // Format address: 0x1234...5678
  isValidWalletConnectUri, // Validate WC URI
  parseWalletConnectUri, // Parse WC URI
  extractChainIdFromAccount, // Extract chain ID from account
  extractAddressFromAccount, // Extract address from account
  isSessionExpired, // Check if session expired
  getSessionTimeRemaining, // Get remaining session time
  generateDeepLink, // Generate wallet deep link
  isMobile, // Check if on mobile device
  copyToClipboard, // Copy text to clipboard
} from "@tomo-inc/wallet-connect-protocol";

// Example usage
const shortAddress = formatAddress("0x1234567890abcdef");
// Returns: '0x1234...cdef'

const isValid = isValidWalletConnectUri(uri);
// Returns: true or false

const deepLink = generateDeepLink("metamask", uri);
// Returns: 'metamask://wc?uri=...'

❓ FAQ

How to get Project ID?

Visit WalletConnect Cloud, sign up and create a new project to get a free Project ID.

QR Code not showing?

Ensure dependencies are correctly installed and the URI is a valid WalletConnect URI (starts with wc:).

How to handle connection errors?

Use try-catch to handle errors:

try {
  await client.connect();
} catch (error) {
  console.error("Connection failed:", error);
  // Handle error, e.g., show error message
}

Which browsers are supported?

All modern browsers (Chrome, Firefox, Safari, Edge) are supported. ES2022+ support required.

Can I use this with React?

Yes! This SDK is framework-agnostic and works perfectly with React. See the React example above.

How do I support multiple chains?

Use the createMultiChainNamespaces utility to configure support for multiple blockchain networks.

🤝 Contributing

Contributions are welcome! Please check our Contributing Guide for more information.

📄 License

MIT © Tomo Inc.

🔗 Related Links

📞 Support

For questions or suggestions, please submit an issue.