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

@gemini-wallet/core

v0.3.2

Published

Core SDK for Gemini Wallet integration with popup communication

Readme

@gemini-wallet/core

Complete SDK for integrating with Gemini Wallet, providing wallet connection, transaction signing, and EVM provider functionality.

Overview

@gemini-wallet/core is a comprehensive wallet SDK that provides everything needed to integrate Gemini Wallet into your application. It includes a complete EVM-compatible provider, wallet connection management, secure storage, and seamless popup-based user interactions.

Features

  • 🔗 EVM Provider: Complete Ethereum provider implementation (EIP-1193 compatible)
  • 🔒 Secure Communication: PostMessage-based cross-origin communication
  • 🪟 Popup Management: Automatic popup window lifecycle management
  • 💾 Storage Layer: Persistent storage with localStorage fallback
  • 🔄 Event-Driven: Promise-based request/response pattern with event emitters
  • ⛓️ Multi-Chain: Support for Ethereum, Polygon, Base, Arbitrum, and testnets
  • 🖊️ Sign Operations: Message signing and EIP-712 typed data signing
  • 💸 Transaction Support: Send transactions with built-in error handling
  • 🌐 Cross-Platform: Works in web browsers and React Native
  • Lightweight: Minimal dependencies for optimal bundle size

Installation

bun add @gemini-wallet/core
# or
npm install @gemini-wallet/core
# or
yarn add @gemini-wallet/core
# or
pnpm add @gemini-wallet/core

⚠️ YOU MIGHT NOT NEED THIS

For most applications, you should use Wagmi's built-in Gemini connector instead:

import { gemini } from "wagmi/connectors";
import { createConfig } from "wagmi";

const config = createConfig({
  connectors: [
    gemini({
      appMetadata: {
        name: "My DApp",
        url: "https://mydapp.com",
        icon: "https://mydapp.com/icon.png",
      },
    }),
  ],
  // ... rest of wagmi config
});

🎯 Wagmi Integration: Gemini Wallet is available as a default connector in [email protected]+ & @wagmi/[email protected]+ 📚 Wagmi Docs: https://wagmi.sh/core/api/connectors/gemini
Status: Readily available

Usage

This core SDK provides multiple integration levels for advanced use cases:

🚀 Level 1: EVM Provider (Recommended for Custom Implementations)

Use when you need direct provider access or aren't using Wagmi:

import { GeminiWalletProvider } from "@gemini-wallet/core";

const provider = new GeminiWalletProvider({
  appMetadata: {
    name: "My DApp",
    url: "https://mydapp.com",
    icon: "https://mydapp.com/icon.png",
  },
  chain: { id: 42161 }, // Arbitrum One
});

// Connect and get accounts
const accounts = await provider.request({
  method: "eth_requestAccounts",
});

// Send transaction
const txHash = await provider.request({
  method: "eth_sendTransaction",
  params: [
    {
      from: accounts[0],
      to: "0x742E4C3B7dcD26e7Ca95C0Ad2F38C61f6F02C4c0",
      value: "0x38D7EA4C68000", // 0.001 ETH
    },
  ],
});

// Listen for events
provider.on("accountsChanged", (accounts) => {
  console.log("Accounts changed:", accounts);
});

⚡ Level 2: Direct Wallet API

Use the wallet class for fine-grained control:

import { GeminiWallet } from "@gemini-wallet/core";

const wallet = new GeminiWallet({
  appMetadata: {
    name: "My DApp",
    url: "https://mydapp.com",
    icon: "https://mydapp.com/icon.png",
  },
  chain: { id: 42161 },
});

// Connect
const accounts = await wallet.connect();

// Send transaction with error handling
const result = await wallet.sendTransaction({
  to: "0x742E4C3B7dcD26e7Ca95C0Ad2F38C61f6F02C4c0",
  value: "1000000000000000000", // 1 ETH in wei
});

if (result.error) {
  console.error("Transaction failed:", result.error);
} else {
  console.log("Transaction hash:", result.hash);
}

⚙️ Level 3: Low-Level Communication

For maximum control over the popup communication:

import { Communicator, GeminiSdkEvent } from "@gemini-wallet/core";

const communicator = new Communicator({
  appMetadata: {
    name: "My DApp",
    url: "https://mydapp.com",
    icon: "https://mydapp.com/icon.png",
  },
});

// Send connect request
const response = await communicator.postRequestAndWaitForResponse({
  event: GeminiSdkEvent.SDK_CONNECT,
  requestId: crypto.randomUUID(),
  chainId: 42161,
  origin: window.location.origin,
});

console.log("Connected address:", response.data.address);

// Listen for specific events
communicator
  .onMessage((message) => message.event === GeminiSdkEvent.SDK_DISCONNECT)
  .then(() => {
    console.log("User disconnected");
  });

API Reference

GeminiWalletProvider

EIP-1193 compatible Ethereum provider implementation.

interface GeminiProviderConfig {
  appMetadata: AppMetadata;
  chain: Chain;
  onDisconnectCallback?: () => void;
  storage?: IStorage;
}

Methods

  • request<T>(args: RpcRequestArgs): Promise<T> - Send RPC requests
  • disconnect(): Promise<void> - Disconnect wallet
  • openSettings(): Promise<void> - Open wallet settings

Events

  • accountsChanged - Emitted when accounts change
  • chainChanged - Emitted when chain changes
  • connect - Emitted on connection
  • disconnect - Emitted on disconnection

GeminiWallet

Direct wallet interface for advanced use cases.

interface GeminiWalletConfig {
  appMetadata: AppMetadata;
  chain?: Chain;
  onDisconnectCallback?: () => void;
  storage?: IStorage;
}

Methods

  • connect(): Promise<Address[]> - Connect to wallet
  • sendTransaction(tx: TransactionRequest): Promise<SendTransactionResponse> - Send transaction
  • signData(params: SignMessageParameters): Promise<SignMessageResponse> - Sign message
  • signTypedData(params: SignTypedDataParameters): Promise<SignTypedDataResponse> - Sign typed data
  • switchChain(params: SwitchChainParameters): Promise<string | null> - Switch chains
  • openSettings(): Promise<void> - Open wallet settings

GeminiStorage

Storage interface for persisting wallet state.

interface IStorage {
  setItem(key: string, value: string): Promise<void>;
  getItem(key: string): Promise<string | null>;
  removeItem(key: string): Promise<void>;
  storeObject<T>(key: string, item: T): Promise<void>;
  loadObject<T>(key: string, fallback: T): Promise<T>;
}

Communicator

Low-level communication class.

interface CommunicatorConfigParams {
  appMetadata: AppMetadata;
  onDisconnectCallback?: () => void;
}

Methods

  • postMessage(message: GeminiSdkMessage): Promise<void> - Send message
  • postRequestAndWaitForResponse<M, R>(request: GeminiSdkMessage): Promise<R> - Send request and wait
  • onMessage<M, R>(predicate: (message: Partial<M>) => boolean): Promise<R> - Listen for messages
  • waitForPopupLoaded(): Promise<Window> - Wait for popup to load

Message Types

GeminiSdkEvent

Enumeration of all supported events:

  • POPUP_LOADED - Popup window has loaded
  • POPUP_UNLOADED - Popup window was closed
  • POPUP_APP_CONTEXT - App metadata sent to popup
  • SDK_CONNECT - Connect wallet request
  • SDK_DISCONNECT - Disconnect wallet request
  • SDK_SEND_TRANSACTION - Send transaction request
  • SDK_SIGN_MESSAGE - Sign message request
  • SDK_SIGN_TYPED_DATA - Sign typed data request
  • SDK_SWITCH_CHAIN - Switch chain request
  • ACCOUNTS_CHANGED - Accounts changed event
  • CHAIN_CHANGED - Chain changed event
  • DISCONNECT - Disconnect event

Supported Chains

Gemini Wallet supports the following networks:

Mainnets:

  • Ethereum (1)
  • Arbitrum One (42161) - Default
  • OP Mainnet (10)
  • Base (8453)
  • Polygon (137)

Testnets:

  • Sepolia (11155111)
  • Arbitrum Sepolia (421614)
  • OP Sepolia (11155420)
  • Base Sepolia (84532)
  • Polygon Amoy (80002)

Constants

  • SDK_BACKEND_URL: "https://keys.gemini.com"
  • DEFAULT_CHAIN_ID: 42161 (Arbitrum One)
  • SUPPORTED_CHAIN_IDS: Array of supported chain IDs
  • POPUP_WIDTH: 420
  • POPUP_HEIGHT: 650

Security Considerations

  1. Origin Validation: All messages are validated against the expected origin
  2. Request ID Matching: Responses are matched to requests using unique IDs
  3. User Consent: All actions require explicit user approval in the popup
  4. No Private Keys: The SDK never handles private keys directly

Browser Support

  • Chrome/Edge 80+
  • Firefox 78+
  • Safari 14+
  • Opera 67+

Try Gemini Wallet

Experience Gemini Wallet in action:

🔗 keys.gemini.com - Try the wallet interface and see how the SDK integrations work

Integration Examples

The core SDK enables various integration patterns:

  • ✅ EIP-1193 compatible provider for any web3 library
  • ✅ Custom storage implementations for mobile platforms
  • ✅ Event-driven architecture with TypeScript support
  • ✅ Multi-chain support with automatic chain switching
  • ✅ Error handling with user-friendly error messages

Development

This project uses Bun as the package manager and build tool.

Setup

# Install dependencies
bun install

# Run tests
bun test

# Run tests in watch mode
bun test --watch

# Type checking
bun run typecheck

# Build the package
bun run build

# Development mode (watch mode)
bun run dev

Available Scripts

  • bun run build - Build the package for production
  • bun run dev - Build in watch mode for development
  • bun run test - Run tests
  • bun run test:watch - Run tests in watch mode
  • bun run typecheck - Run TypeScript type checking
  • bun run lint - Run ESLint (requires configuration)
  • bun run lint:fix - Fix ESLint issues automatically

Build Output

The build process generates:

  • dist/index.js - ESM bundle for Node.js
  • dist/index.d.ts - TypeScript declarations
  • dist/*.d.ts.map - Source maps for declarations

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

MIT License - see LICENSE for details.