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

gala-web3-provider-sdk

v1.0.2

Published

Gala Web3 Provider SDK. A lightweight and easy-to-use JavaScript/TypeScript SDK that provides wallet connection utilities for Gala blockchain applications.

Readme

Gala Web3 Provider SDK Documentation

Demo URL

Demo URL

Release Notes

1.0.0

  • Initial release

1.0.1

  • Updated README
  • Fixed bugs

1.0.2

  • Updated README
  • Fixed bugs

Prerequisites

  • React 19.1.0 or higher
  • Node.js 18.17.1 or higher
  • npm 9.6.7 or higher
  • yarn 4.5.0 or higher
  • pnpm 9.14.2 or higher

Overview

The Gala Web3 Provider SDK is a React hook-based utility designed to detect, manage, and connect to EIP-1193-compliant Ethereum wallet providers, with a special focus on the gala provider.

It provides:

  • Automatic wallet detection
  • Connection management (connect, disconnect)
  • Account and chain updates
  • Provider events handling

This SDK is lightweight, customizable, and perfect for decentralized applications (dApps) that need a reliable wallet connection.


Installation

# NPM
npm install gala-web3-provider-sdk

# Yarn
yarn add gala-web3-provider-sdk

# PNPM
pnpm add gala-web3-provider-sdk

API Reference

useGalaProvider(config?: Web3ProviderConfig)

The main hook to interact with wallet providers.

Parameters

  • config (optional) - Configuration object:
    • preferred: WalletProviderName[] - List of preferred wallet names (default: ["gala"])
    • fallbackToAny: boolean - Fallback to any provider if preferred not found (default: true)
    • checkInterval: number - Time interval in ms to re-check providers (default: 1000)
    • onAccountsChanged: (accounts: string[]) => void - Callback when user changes accounts
    • onChainChanged: (chainId: string) => void - Callback when chain changes
    • onDisconnect: (error: any) => void - Callback when provider disconnects

Returns

| Property | Type | Description | | :-------------------------------------------- | :------------------------------------ | :--------------------------------------- | | providers | DetectedWalletProvider[] | List of all detected providers | | currentProvider | DetectedWalletProvider \| null | Currently connected provider | | accounts | string[] | Connected wallet accounts | | chainId | string \| null | Current network chain ID | | error | Error \| null | Last encountered error | | isConnecting | boolean | Indicates if a connection is in progress | | isDetecting | boolean | Indicates if detection is happening | | connect(name: WalletProviderName) | Promise<string[]> | Connects to a wallet provider | | disconnect() | void | Disconnects from the provider | | getPreferredProvider() | DetectedWalletProvider \| undefined | Get preferred available provider | | getProviderByName(name: WalletProviderName) | EthereumProvider \| undefined | Get provider by name | | refreshProviders() | DetectedWalletProvider[] | Force re-detect providers |


Usage Example

1. Basic React Integration

import { useState, useEffect } from 'react';
import { useGalaProvider, WalletProviderName } from 'gala-web3-provider-sdk';

function App() {
  const {
    providers,
    currentProvider,
    accounts,
    chainId,
    error,
    isConnecting,
    connect,
    disconnect,
    signMessage,
    signTypedData,
    sendTransaction,
  } = useGalaProvider({
    preferred: ['gala'],
    onAccountsChanged: (accounts) => {
      if (accounts.length === 0) setConnected(false);
    },
    onChainChanged: (chainId) => {
      setChainInfo(chainId);
    },
    onDisconnect: (error) => {
      setConnected(false);
    },
  });

  const [selectedProvider, setSelectedProvider] =
    useState<WalletProviderName>('gala');
  const [connected, setConnected] = useState(false);
  const [chainInfo, setChainInfo] = useState<string | null>(null);
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const [actionResults, setActionResults] = useState<Record<string, any>>({});
  const [isActionLoading, setIsActionLoading] = useState<
    Record<string, boolean>
  >({});
  const [messageToSign, setMessageToSign] = useState('Hello Antier!');
  const [txParams, setTxParams] = useState({
    to: '0x0000000000000000000000000000000000000000',
    value: '0x0',
    data: '0x',
  });

  // Auto-select first available provider if current selection isn't available
  useEffect(() => {
    const availableProviderNames = providers.map((p) => p.name);
    if (
      availableProviderNames.length > 0 &&
      !availableProviderNames.includes(selectedProvider)
    ) {
      setSelectedProvider(availableProviderNames[0]);
    }
  }, [providers, selectedProvider]);

  const handleConnect = async () => {
    try {
      await connect(selectedProvider);
      setConnected(true);
    } catch (err) {
      console.error(err);
    }
  };

  const handleDisconnect = () => {
    disconnect();
    setConnected(false);
    setActionResults({});
  };

  const executeWalletAction = async (
    actionName: string,
    actionFn: () => Promise<unknown>
  ) => {
    try {
      setIsActionLoading((prev) => ({ ...prev, [actionName]: true }));
      const result = await actionFn();
      setActionResults((prev) => ({ ...prev, [actionName]: result }));
      console.log(`${actionName} result:`, result);
    } catch (err) {
      console.error(`${actionName} error:`, err);

      setActionResults((prev) => ({
        ...prev,
        [actionName]: err instanceof Error ? err.message : String(err),
      }));
    } finally {
      setIsActionLoading((prev) => ({ ...prev, [actionName]: false }));
    }
  };

  const testSignMessage = async () => {
    if (!signMessage) return;
    await executeWalletAction('signMessage', () => signMessage(messageToSign));
  };

  const testSignTypedData = async () => {
    if (!signTypedData) return;
    const typedData = {
      types: {
        EIP712Domain: [
          { name: 'name', type: 'string' },
          { name: 'version', type: 'string' },
          { name: 'chainId', type: 'uint256' },
          { name: 'verifyingContract', type: 'address' },
        ],
        Person: [
          { name: 'name', type: 'string' },
          { name: 'wallet', type: 'address' },
        ],
        Mail: [
          { name: 'from', type: 'Person' },
          { name: 'to', type: 'Person' },
          { name: 'contents', type: 'string' },
        ],
      },
      primaryType: 'Mail',
      domain: {
        name: 'Ether Mail',
        version: '1',
        chainId: chainId ? parseInt(chainId, 16) : 1,
        verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
      },
      message: {
        from: {
          name: 'Cow',
          wallet: accounts[0],
        },
        to: {
          name: 'Bob',
          wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
        },
        contents: 'Hello, Bob!',
      },
    };
    await executeWalletAction('signTypedData', () => signTypedData(typedData));
  };

  const testSendTransaction = async () => {
    if (!sendTransaction) return;
    await executeWalletAction('sendTransaction', () =>
      sendTransaction({
        to: '0x4B0897b0513FdBeEc7C469D9aF4fA6C0752aBea7',
        from: accounts[0],
        gas: '0x76c0',
        value: '0x8ac7230489e80000',
        data: '0x',
        maxFeePerGas: '0x4a817c800',
        maxPriorityFeePerGas: '0x4a817c800',
        chainId: '0x1',
      })
    );
  };

  return (
    <div className='app'>
      <h1>Gala Wallet Provider Test Suite</h1>

      <div className='provider-section'>
        <h2>Wallet Connection</h2>
        <div className='provider-selection'>
          <select
            value={selectedProvider}
            onChange={(e) =>
              setSelectedProvider(e.target.value as WalletProviderName)
            }
            disabled={connected}
          >
            {providers.length > 0 ? (
              providers.map((provider) => (
                <option key={provider.name} value={provider.name}>
                  {provider.name}
                </option>
              ))
            ) : (
              <option value=''>No providers detected</option>
            )}
          </select>

          {!connected ? (
            <button
              onClick={handleConnect}
              disabled={providers.length === 0 || isConnecting}
            >
              {isConnecting ? 'Connecting...' : 'Connect Wallet'}
            </button>
          ) : (
            <button onClick={handleDisconnect}>Disconnect</button>
          )}
        </div>

        {providers.length === 0 && (
          <div className='warning'>
            No wallet providers detected. Please install the Gala wallet.
          </div>
        )}

        {error && <div className='error'>{error.message}</div>}
      </div>

      {connected && currentProvider && (
        <div className='wallet-info'>
          <h2>Wallet Information</h2>
          <div>
            <strong>Connected Provider:</strong> {currentProvider.name}
          </div>
          <div>
            <strong>Chain ID:</strong> {chainId}{' '}
            {chainInfo && `(Hex: ${chainInfo})`}
          </div>
          <div>
            <strong>Accounts:</strong>
            <ul>
              {accounts.map((account) => (
                <li key={account}>{account}</li>
              ))}
            </ul>
          </div>
        </div>
      )}

      {connected && (
        <div className='wallet-actions'>
          <h2>Wallet Actions</h2>

          <div className='action-group'>
            <h3>Message Signing</h3>
            <div>
              <label>
                Message to sign:
                <input
                  type='text'
                  value={messageToSign}
                  onChange={(e) => setMessageToSign(e.target.value)}
                />
              </label>
              <button
                onClick={testSignMessage}
                disabled={isActionLoading.signMessage}
              >
                {isActionLoading.signMessage ? 'Signing...' : 'Sign Message'}
              </button>
              {actionResults.signMessage && (
                <div className='result'>
                  <strong>Signature:</strong> {actionResults.signMessage}
                </div>
              )}
            </div>
          </div>

          <div className='action-group'>
            <h3>Typed Data Signing</h3>
            <button
              onClick={testSignTypedData}
              disabled={isActionLoading.signTypedData}
            >
              {isActionLoading.signTypedData ? 'Signing...' : 'Sign Typed Data'}
            </button>
            {actionResults.signTypedData && (
              <div className='result'>
                <strong>Signature:</strong> {actionResults.signTypedData}
              </div>
            )}
          </div>

          <div className='action-group'>
            <h3>Transaction Actions</h3>
            <div>
              <label>
                To:
                <input
                  type='text'
                  value={txParams.to}
                  onChange={(e) =>
                    setTxParams({ ...txParams, to: e.target.value })
                  }
                />
              </label>
            </div>
            <div>
              <label>
                Value (wei):
                <input
                  type='text'
                  value={txParams.value}
                  onChange={(e) =>
                    setTxParams({ ...txParams, value: e.target.value })
                  }
                />
              </label>
            </div>
            <div>
              <label>
                Data:
                <input
                  type='text'
                  value={txParams.data}
                  onChange={(e) =>
                    setTxParams({ ...txParams, data: e.target.value })
                  }
                />
              </label>
            </div>

            <div className='action-buttons'>
              <button
                onClick={testSendTransaction}
                disabled={isActionLoading.sendTransaction}
              >
                {isActionLoading.sendTransaction
                  ? 'Sending...'
                  : 'Send Transaction'}
              </button>
            </div>

            {actionResults.signTransaction && (
              <div className='result'>
                <strong>Signed Tx:</strong> {actionResults.signTransaction}
              </div>
            )}
            {actionResults.sendTransaction && (
              <div className='result'>
                <strong>Tx Hash:</strong> {actionResults.sendTransaction}
              </div>
            )}
            {actionResults.sendRawTransaction && (
              <div className='result'>
                <strong>Raw Tx Hash:</strong> {actionResults.sendRawTransaction}
              </div>
            )}
          </div>
        </div>
      )}

      <div className='providers-list'>
        <h2>Detected Providers</h2>
        <ul>
          {providers.map((provider) => (
            <li key={provider.name}>
              {provider.name}{' '}
              {currentProvider?.name === provider.name && '(Connected)'}
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

export default App;

Concepts Explained

1. Provider Detection

  • The hook periodically checks if a provider like gala is injected into window.gala.
  • When a provider is detected or removed, the onProvidersChanged callback fires.

2. Connection Lifecycle

  • connect() triggers eth_requestAccounts and eth_chainId requests.
  • Wallet events (accountsChanged, chainChanged, disconnect) are handled automatically.
  • disconnect() clears listeners and resets connection state.

3. Fallback Behavior

  • If no preferred provider is found and fallbackToAny: true, the hook will fallback to the first available provider.

4. Events Handling

  • Accounts Change: Updates accounts.
  • Chain Change: Updates chainId.
  • Disconnect: Resets all internal states.

Types

WalletProviderName

type WalletProviderName = 'gala';

EIP1559Transaction

interface EIP1559Transaction {
  /**
   * The recipient's address (optional for contract creation)
   * @pattern ^0x[0-9a-fA-F]{40}$
   * @example "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
   */
  to?: string;

  /**
   * The sender's address
   * @pattern ^0x[0-9a-fA-F]{40}$
   * @example "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
   */
  from: string;

  /**
   * The maximum amount of gas the transaction is allowed to use
   * @pattern ^0x([1-9a-f]+[0-9a-f]*|0)$
   * @example "0x5208" (21000 gas)
   */
  gas?: string;

  /**
   * The amount to transfer in wei
   * @pattern ^0x([1-9a-f]+[0-9a-f]*|0)$
   * @example "0x16345785d8a0000" (100 ether in wei)
   */
  value?: string;

  /**
   * The data payload (used for contract calls/creation)
   * @pattern ^0x[0-9a-f]*$
   * @example "0xa9059cbb000000000000000000000000..."
   */
  data?: string;

  /**
   * Maximum fee per gas (includes base + priority fee) in wei
   * @pattern ^0x([1-9a-f]+[0-9a-f]*|0)$
   * @example "0x2540be400" (100 gwei)
   */
  maxFeePerGas: string;

  /**
   * Maximum priority fee per gas (tip to miner) in wei
   * @pattern ^0x([1-9a-f]+[0-9a-f]*|0)$
   * @example "0x3b9aca00" (1 gwei)
   */
  maxPriorityFeePerGas: string;

  /**
   * Chain ID (EIP-155)
   * @example "0x1" for Ethereum Mainnet
   */
  chainId?: string;
}

AvailableEIP1193Methods

type AvailableEIP1193Methods =
  | 'eth_requestAccounts'
  | 'eth_chainId'
  | 'eth_signTypedData_v4'
  | 'personal_sign'
  | 'eth_sendTransaction'
  | 'eth_accounts';

EthereumProvider

interface EthereumProvider {
  isGala?: boolean;
  request: (args: {
    method: AvailableEIP1193Methods;
    params?: any[];
  }) => Promise<any>;
  on?: (event: string, handler: (...args: any[]) => void) => void;
  removeListener?: (event: string, handler: (...args: any[]) => void) => void;
  [key: string]: any;
}

DetectedWalletProvider

interface DetectedWalletProvider {
  name: WalletProviderName;
  provider: EthereumProvider;
}

Web3ProviderConfig

interface Web3ProviderConfig {
  /**
   * List of wallet provider names to prioritize when selecting a provider.
   * Defaults to ["metamask", "trustwallet", "gala"].
   */
  preferred?: WalletProviderName[];

  /**
   * Whether to fallback to any available provider if no preferred ones are found.
   * Defaults to true.
   */
  fallbackToAny?: boolean;

  /**
   * Callback when accounts are changed.
   */
  onAccountsChanged?: (accounts: string[]) => void;

  /**
   * Callback when the chain changes.
   */
  onChainChanged?: (chainId: string) => void;

  /**
   * Callback when the provider disconnects.
   */
  onDisconnect?: (error: any) => void;

  /**
   * Callback when the list of available providers changes.
   */
  onProvidersChanged?: (providers: DetectedWalletProvider[]) => void;

  /**
   * Time interval (in ms) to check for new providers. Defaults to 1000ms.
   * Set to 0 to disable periodic checking.
   */
  checkInterval?: number;
}

Final Notes

  • This SDK focuses primarily on the Gala wallet integration but can be extended to other wallets easily.
  • The design emphasizes simplicity, flexibility, and event safety.
  • Feel free to modify the WalletProviderName type and detectProviders logic to support more wallets!

License

MIT License


Author

Antier PVT LTD.


Happy building decentralized apps with Gala Web3 Provider SDK! ✨