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

@xid/walletkit

v0.0.23

Published

A React component library for wallet functionality

Readme

@xid/walletkit

一个强大的 React 多链钱包连接组件库,支持 EVM、Solana、Tron 和 BTC 等多种区块链网络,提供统一的 API 接口。

特性

  • 🔗 多链支持: EVM、Solana、Tron 和 BTC 区块链
  • 💼 钱包连接器: 支持 MetaMask、OKX Wallet、Phantom、TronLink、Trust Wallet、Bitget Wallet、TokenPocket 和 TokenUp
  • 🎨 主题与国际化: 内置明暗主题切换和多语言支持(8种语言)
  • 📱 响应式设计: 移动端优先设计,桌面端优化
  • 🔄 自动重连: 页面刷新时自动重连钱包
  • 📝 合约交互: 内置合约读写和批量调用支持
  • 🌐 RPC 支持: 无需连接钱包的直接 RPC 调用
  • 🌍 域名解析: ENS 域名解析和反向查询
  • 🎯 TypeScript: 完整的 TypeScript 支持和全面的类型定义
  • 性能优化: 优化的包大小,支持 tree-shaking

安装

NPM 安装

npm install @xid/walletkit
# 或
yarn add @xid/walletkit
# 或
pnpm add @xid/walletkit

CDN 引入(UMD 格式)

<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/@xid/walletkit@latest/dist/style.css">

<!-- 引入 React 和 ReactDOM -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<!-- 引入 WalletKit UMD 版本 -->
<script src="https://unpkg.com/@xid/walletkit@latest/dist/index.umd.js"></script>

<script>
  const { WalletKitProvider, ConnectButton, useWalletKit, ChainType } = WalletKit;

  // 使用 WalletKit 组件
  function App() {
    const { walletAddress, connect, disconnect } = useWalletKit();

    return React.createElement('div', null, [
      React.createElement('h1', null, 'WalletKit 示例'),
      React.createElement('p', null, `钱包地址: ${walletAddress || '未连接'}`),
      React.createElement(ConnectButton)
    ]);
  }

  ReactDOM.render(
    React.createElement(WalletKitProvider, {
      language: 'zh',
      defaultChainType: ChainType.EVM
    }, React.createElement(App)),
    document.getElementById('root')
  );
</script>

快速开始

基本用法

import { WalletKitProvider, ConnectButton, useWalletKit } from '@xid/walletkit';
// 导入样式(必需)
import '@xid/walletkit/style.css';

function App() {
  return (
    <WalletKitProvider
      language="zh"
      theme="light"
      defaultChainType={ChainType.EVM}
      defaultChainId={1}
      showNetwork={true}
      allowSwitchWallet={true}
    >
      <YourApp />
    </WalletKitProvider>
  );
}

function YourApp() {
  const { connect, walletAddress, currentChainType, disconnect } = useWalletKit();

  return (
    <div>
      <ConnectButton />
      {walletAddress ? (
        <div>
          <p>已连接钱包: {walletAddress}</p>
          <button onClick={disconnect}>断开连接</button>
        </div>
      ) : (
        <button onClick={connect}>连接钱包</button>
      )}
      <div>当前链类型: {currentChainType}</div>
    </div>
  );
}

⚠️ 重要: 请务必导入 CSS 文件 @xid/walletkit/style.css 以确保正确的样式显示。

样式

组件库包含内置样式,导入 CSS 文件后会自动加载。样式支持明暗主题,并且完全响应式。

CSS 导入方法

// 方法 1: 直接导入(推荐)
import '@xid/walletkit/style.css';

// 方法 2: 从 dist 目录导入
import '@xid/walletkit/dist/style.css';

主题变量

组件库使用 CSS 自定义属性进行主题设置。您可以覆盖这些变量来自定义外观:

:root {
  --walletkit-primary-color: #1890ff;
  --walletkit-text-color: rgba(0, 0, 0, 0.88);
  --walletkit-background-color: #ffffff;
  /* ... 更多变量 */
}

API 文档

组件

WalletKitProvider

提供钱包连接上下文,必须包裹在应用最外层。

<WalletKitProvider
  language="zh" // 多语言,支持 zh、en、ja、ko、ms、th、vi、zhTW
  theme="light" // 主题,支持 dark、light
  defaultChainType={ChainType.EVM}
  defaultChainId={1}
  reconnect={true}
  supportWallets={[]}
  customEvmNetworks={[]}
  showNetwork={true}
  allowSwitchWallet={true}
  productName="My App"
>
  <YourApp />
</WalletKitProvider>
参数

| 参数名 | 类型 | 默认值 | 描述 | |---------------------|---------------------------------------------------|------------------|------------------------------| | language | 'zh'|'en'|'ja'|'ko'|'ms'|'th'|'vi'|'zhTW' | 'zh' | 界面语言 | | theme | 'dark'|'light' | 'light' | 主题 | | defaultChainType | ChainType | ChainType.EVM | 默认链类型 | | defaultChainId | number | 1 | 默认链 ID | | reconnect | boolean | true | 是否自动重连 | | supportWallets | SupportWallet[] | 全部支持 | 支持的钱包类型 | | customEvmNetworks | NetworkInfo[] | [] | 自定义 EVM 网络列表 | | showNetwork | boolean | false | 是否显示网络切换 | | allowSwitchWallet | boolean | false | 是否允许切换钱包 | | productName | string | undefined | 展示由...提供 |

  • ChainTypeSupportWalletNetworkInfo 类型见下文。

ConnectButton

内置钱包连接按钮组件,支持响应式设计。

<ConnectButton />

ConnectModal

钱包选择和连接弹窗组件。

<ConnectModal />

ThemeToggle

主题切换组件。

<ThemeToggle />

Hooks

useWalletKit

提供钱包连接相关的所有状态和方法。

const {
  connect,                // 连接钱包
  disconnect,             // 断开钱包
  currentChainType,       // 当前链类型
  setChainType,           // 设置链类型
  currentConnector,       // 当前连接器实例
  theme,                  // 当前主题
  toggleTheme,            // 切换主题
  language,               // 当前语言
  setLanguage,            // 设置语言
  walletAddress,          // 钱包地址
  currentNetwork,         // 当前网络信息
  setCurrentNetwork,      // 设置当前网络
  getProvider,            // 获取 provider
  provider,               // provider 实例
  showWalletInfo,         // 显示钱包信息弹窗
  signMessage,            // 签名消息
  signTransaction,        // 签名交易
  sendTransaction,        // 发送交易
  readContract,           // 读取合约
  writeContract,          // 写入合约
  multicall,              // 批量调用合约
  switchNetwork,          // 切换网络
  waitForTransactionReceipt, // 等待交易收据
  getSupportNets          // 获取支持的网络列表
} = useWalletKit();

主要 API 说明

连接与断开

  • connect(): 连接钱包,返回 Promise<Connector>
  • disconnect(): 断开钱包连接
  • getProvider(): 获取当前 provider 实例

链和网络管理

  • currentChainType: 当前链类型 (EVM, SOL, Tron, BTC)
  • setChainType(chainType): 设置链类型
  • currentNetwork: 当前网络信息
  • setCurrentNetwork(networkId): 设置当前网络
  • switchNetwork(chainId): 切换网络
  • getSupportNets(): 获取支持的网络列表

交易与合约

  • signMessage(message): 签名消息
  • signTransaction(tx): 签名交易
  • sendTransaction(tx): 发送交易
  • readContract(params): 读取合约数据
  • writeContract(params): 写入合约数据
  • multicall(calls, option): 批量调用合约
  • waitForTransactionReceipt(hash, timeout?): 等待交易收据

UI 相关

  • theme: 当前主题
  • toggleTheme(): 切换主题
  • language: 当前语言
  • setLanguage(lang): 设置语言
  • showWalletInfo(): 显示钱包信息弹窗

其他高级用法

  • readContractRpc(params): 直接通过 RPC 读取合约(无需连接钱包)
  • multicallRpc(calls, option): 直接通过 RPC 批量读取合约
  • evmSilentConnect(walletType, chainId): EVM 静默连接
  • getWalletKit(): 获取全局 walletKit 实例(适合非 React 场景)

域名解析

  • resolveDomainToAddress(name, chainId): 将 ENS 域名解析为地址
  • reverseResolveAddressToName(addr, chainId, verifyForward?): 将地址反向解析为 ENS 域名
  • resolveDomainToAddresses(name, chainId, coinTypes?): 批量解析域名到多个链的地址(返回以链名称为键的对象)

类型说明

主题类型

  • Theme: 'dark' | 'light'

语言类型

  • Locals: 'zh' | 'en' | 'ja' | 'ko' | 'ms' | 'th' | 'vi' | 'zhTW'

链类型

import { ChainType } from '@xid/walletkit';
// ChainType.EVM    // 以太坊虚拟机链
// ChainType.SOL    // Solana 链
// ChainType.Tron   // Tron 链
// ChainType.BTC    // 比特币链

钱包类型

import { SupportWallet } from '@xid/walletkit';
// 例如:SupportWallet.METAMASK、SupportWallet.OKX_WALLET 等

网络类型

import type { NetworkInfo } from '@xid/walletkit';
// chainId, chainName, rpcUrls, nativeCurrency, blockExplorerUrls 等

支持的钱包

EVM 钱包

  • MetaMask
  • OKX Wallet
  • Trust Wallet
  • Bitget Wallet
  • TokenPocket
  • TokenUp

Solana 钱包

  • Phantom
  • OKX Wallet
  • Bitget Wallet
  • TokenUp

Tron 钱包

  • TronLink
  • OKX Wallet
  • TokenUp

Bitcoin 钱包

  • Phantom

示例

切换链类型

import { ChainType, useWalletKit } from '@xid/walletkit';

function ChainSwitcher() {
  const { setChainType, currentChainType } = useWalletKit();
  return (
    <div>
      <button onClick={() => setChainType(ChainType.EVM)}>切换到EVM</button>
      <button onClick={() => setChainType(ChainType.SOL)}>切换到Solana</button>
      <button onClick={() => setChainType(ChainType.Tron)}>切换到Tron</button>
      <button onClick={() => setChainType(ChainType.BTC)}>切换到BTC</button>
      <div>当前链类型: {currentChainType}</div>
    </div>
  );
}

切换网络

import { useWalletKit } from '@xid/walletkit';

function NetworkSwitcher() {
  const { getSupportNets, switchNetwork, setCurrentNetwork, provider, currentNetwork } = useWalletKit();
  return (
    <div>
      <h3>切换网络</h3>
      <div>
        {getSupportNets().map((net) => (
          <button
            key={net.chainId}
            onClick={async () => {
              if (provider) {
                await switchNetwork(net.chainId);
              } else {
                setCurrentNetwork(net.chainId);
              }
            }}
          >
            切换到 {net.chainName}
          </button>
        ))}
      </div>
      <div>当前网络: {currentNetwork?.chainName}</div>
    </div>
  );
}

合约交互

import { useWalletKit } from '@xid/walletkit';

function ContractInteraction() {
  const { readContract, writeContract, multicall } = useWalletKit();

  const handleReadContract = async () => {
    const result = await readContract({
      address: '0x...', // 合约地址
      abi: [...], // 合约ABI
      functionName: 'balanceOf',
      args: ['0x...'] // 参数
    });
    console.log('读取结果:', result);
  };

  const handleWriteContract = async () => {
    const result = await writeContract({
      address: '0x...', // 合约地址
      abi: [...], // 合约ABI
      functionName: 'transfer',
      args: ['0x...', 1000000] // 参数
    });
    console.log('写入结果:', result);
  };

  const handleMulticall = async () => {
    const result = await multicall(
      [
        {
          address: '0x...',
          abi: [...],
          functionName: 'balanceOf',
          args: ['0x...']
        },
        {
          address: '0x...',
          abi: [...],
          functionName: 'totalSupply'
        }
      ],
      {
        multicallAddress: '0x...',
        multicallAbi: [...]
      }
    );
    console.log('批量调用结果:', result);
  };

  return (
    <div>
      <button onClick={handleReadContract}>读取合约</button>
      <button onClick={handleWriteContract}>写入合约</button>
      <button onClick={handleMulticall}>批量调用</button>
    </div>
  );
}

直接 RPC 合约调用

import { readContractRpc, multicallRpc } from '@xid/walletkit';

// 单个合约读取
const res = await readContractRpc({
  abi: [...],
  address: '0x...',
  functionName: 'balanceOf',
  args: ['0x...'],
  rpcUrl: 'https://<your-rpc-url>'
});

// 批量合约读取
const res2 = await multicallRpc(
  [
    {
      address: '0x...',
      abi: [...],
      functionName: 'totalSupply'
    },
    {
      address: '0x...',
      abi: [...],
      functionName: 'balanceOf',
      args: ['0x...']
    }
  ],
  {
    multicallAddress: '0x...',
    multicallAbi: [...],
    rpcUrl: 'https://<your-rpc-url>'
  }
);

域名解析

import { resolveDomainToAddress, reverseResolveAddressToName, resolveDomainToAddresses } from '@xid/walletkit';
import { useState } from 'react';

function DomainResolver() {
  const [domain, setDomain] = useState('<your-domain>.xone');
  const [address, setAddress] = useState('0x...');
  const [result, setResult] = useState('');
  const [chainId, setChainId] = useState(33772211);

  // 将域名解析为地址
  const handleResolveDomain = async () => {
    try {
      const resolvedAddress = await resolveDomainToAddress(
        domain,
        chainId
      );
      setResult(`域名解析地址: ${domain} -> ${resolvedAddress || 'null'}`);
    } catch (error) {
      setResult(`错误: ${error.message}`);
    }
  };

  // 将地址反向解析为域名
  const handleReverseResolve = async () => {
    try {
      const resolvedDomain = await reverseResolveAddressToName(
        address,
        chainId,
        true // 启用前向验证
      );
      setResult(`地址解析域名: ${address} -> ${resolvedDomain || 'null'}`);
    } catch (error) {
      setResult(`错误: ${error.message}`);
    }
  };

  // 批量解析域名到多个链的地址
  const handleResolveDomainToAddresses = async () => {
    try {
      const multiAddresses = await resolveDomainToAddresses(domain, chainId);
      if (multiAddresses) {
        const formatted = Object.entries(multiAddresses)
          .map(([chain, addr]) => `${chain}: ${addr}`)
          .join('\n');
        setResult(`域名解析到多个地址:\n${formatted}`);
      } else {
        setResult('未找到地址');
      }
    } catch (error) {
      setResult(`错误: ${error.message}`);
    }
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 640 }}>
      <select
        value={chainId}
        onChange={(e) => setChainId(Number(e.target.value))}
      >
        <option value={33772211}>测试网 (33772211)</option>
        <option value={3721}>主网 (3721)</option>
      </select>
      <div style={{ display: 'flex', gap: 8 }}>
        <input
          style={{ flex: 1 }}
          placeholder="域名 例如 <your-domain>.xone"
          value={domain}
          onChange={(e) => setDomain(e.target.value)}
        />
        <button onClick={handleResolveDomain}>域名 → 地址</button>
        <button onClick={handleResolveDomainToAddresses}>域名 → 多个地址</button>
      </div>
      <div style={{ display: 'flex', gap: 8 }}>
        <input
          style={{ flex: 1 }}
          placeholder="地址 0x..."
          value={address}
          onChange={(e) => setAddress(e.target.value)}
        />
        <button onClick={handleReverseResolve}>地址 → 域名</button>
      </div>
      <pre style={{ padding: 8, borderRadius: 6, backgroundColor: '#f5f5f5' }}>
        {result}
      </pre>
    </div>
  );
}

// 基本使用示例
const basicExamples = async () => {
  // 将 ENS 域名解析为地址(使用测试网 chainId)
  const address = await resolveDomainToAddress('<your-domain>.xone', 33772211);
  console.log('解析的地址:', address);

  // 将地址反向解析为 ENS 域名(使用测试网 chainId)
  const name = await reverseResolveAddressToName('0x...', 33772211);
  console.log('解析的域名:', name);

  // 使用主网 chainId 解析域名
  const mainnetAddress = await resolveDomainToAddress('<your-domain>.xone', 3721);

  // 禁用前向验证的反向解析
  const nameWithoutVerification = await reverseResolveAddressToName(
    '0x...',
    33772211,
    false // 禁用前向验证
  );

  // 批量解析域名到多个链的地址
  const multiAddresses = await resolveDomainToAddresses('<your-domain>.xone', 33772211);
  console.log('多链地址:', multiAddresses);
  // 示例输出: { "Ethereum": "0x...", "Solana": "5Q544...", "Tron": "TXYZ..." }
};

主题和国际化

import { useWalletKit, supportedLanguages } from '@xid/walletkit';
import type { Locals } from '@xid/walletkit';

function ThemeAndLanguage() {
  const { theme, toggleTheme, language, setLanguage } = useWalletKit();
  return (
    <div>
      <div>当前主题: {theme},当前语言: {language}</div>
      <div>
        <button onClick={() => toggleTheme()}>切换主题</button>
        <select
          value={language}
          onChange={e => setLanguage(e.target.value as Locals)}
        >
          {supportedLanguages.map(lng => (
            <option key={lng} value={lng}>
              {lng}
            </option>
          ))}
        </select>
      </div>
    </div>
  );
}

supportedLanguages 为内置多语言列表,可用于动态渲染语言选择项。

事件监听

import { useEffect } from 'react';
import { useWalletKit } from '@xid/walletkit';

function EventListener() {
  const { currentConnector } = useWalletKit();
  useEffect(() => {
    const handleConnect = (address) => {
      console.log('钱包已连接:', address);
    };
    const handleChainChanged = (chainId) => {
      console.log('链已更改:', chainId);
    };
    const handleAccountChanged = (address) => {
      console.log('账户已更改:', address);
    };
    const handleDisconnect = () => {
      console.log('钱包已断开连接');
    };
    if (currentConnector) {
      currentConnector.on('connect', handleConnect);
      currentConnector.on('chainChanged', handleChainChanged);
      currentConnector.on('accountsChanged', handleAccountChanged);
      currentConnector.on('disconnect', handleDisconnect);
    }
    return () => {
      if (currentConnector) {
        currentConnector.off('connect', handleConnect);
        currentConnector.off('chainChanged', handleChainChanged);
        currentConnector.off('accountsChanged', handleAccountChanged);
        currentConnector.off('disconnect', handleDisconnect);
      }
    };
  }, [currentConnector]);
  return <div>事件监听示例</div>;
}

许可证

MIT