mcpField
R
react-wallet-connector

react-wallet-connector

github.com/kali-decoder开发18127 次安装1 天前更新
代码仓库

关于 react-wallet-connector

此技能可生成可运行的 React 与 TypeScript 应用,通过 DApp Connector API 连接 Midnight 钱包扩展。它提供前端连接基础,包括钱包发现、授权、地址展示和可选的钱包选择。

主要功能

  1. 01Vite React TypeScript 应用脚手架
  2. 02发现注入的 Midnight 钱包
  3. 03通过 DApp Connector API 连接
  4. 04显示连接状态与未屏蔽地址
  5. 05可选的多钱包选择器
  6. 06网络选择指导

适用场景

  1. 01创建连接钱包的 React 应用
  2. 02让用户从已安装的钱包中选择
  3. 03请求钱包授权并连接网络
  4. 04展示钱包连接状态和地址信息

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kali-decoder/midnight-skills --skill react-wallet-connector

安装后在 Claude Code 中输入/react-wallet-connector确认已加载。

详细介绍

React 钱包连接器技能

此技能可生成一个完整、可运行的 React 应用,通过 DApp Connector API 连接 Midnight 钱包扩展。涵盖所需的所有文件:Vite + React + TypeScript 脚手架、钱包选择、连接逻辑,以及 WalletCard UI 组件。

主要参考资料:

  • docs.midnight.network — React 钱包连接器指南(DApp Connector API)
  • llms.txt — Midnight 完整文档索引
  • @midnight-ntwrk/[email protected] — 最新稳定版连接器软件包(2026 年 2 月)

关键架构说明:

  • 钱包会在 window.midnight 上注入 InitialAPI 实例,每个实例都由一个 UUID 标识 — 切勿使用 window.midnight.mnLace 这类硬编码键
  • 使用 Object.values(window.midnight) 枚举钱包;存在多个钱包时,让用户选择
  • 将 @midnight-ntwrk/dapp-connector-api 作为副作用导入,以扩展全局 window.midnight 类型
  • 仅在应用确实需要时才请求屏蔽地址;此模板使用 getUnshieldedAddress()
  • 网络 ID:'undeployed'(本地)、'preview'、'preprod'、'mainnet' — 必须与钱包配置的网络一致
  • 代码示例有意省略 CSS 样式;搭建脚手架后,可添加你偏好的样式方案

与其他技能的关系:

  • 如需通过 1AM 钱包完整部署合约并调用电路 → 使用 1am-wallet/
  • 如需无头 Node.js 钱包和测试 → 使用 example-hello-world/ 或 midnight-js/
  • 此技能仅作为前端钱包连接基础

1) 项目结构

my-wallet-app/
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.app.json
├── tsconfig.node.json
├── vite.config.ts
└── src/
    ├── main.tsx
    ├── App.tsx
    ├── WalletCard.tsx
    ├── types.ts
    ├── selectWallet.ts
    └── vite-env.d.ts

2) 先决条件

  • Node.js 18+ 和 npm
  • 熟悉 React + TypeScript 基础知识
  • 已安装 Midnight 钱包浏览器扩展(1AM、Lace 或任何兼容 DApp Connector 的钱包)

3) 搭建脚手架并安装

npm create vite@latest my-wallet-app -- --template react-ts
cd my-wallet-app
npm install @midnight-ntwrk/[email protected]

4) package.json

使用 Vite react-ts 模板的输出,并确保其中列出了 @midnight-ntwrk/dapp-connector-api:

{
  "name": "my-wallet-app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@midnight-ntwrk/dapp-connector-api": "4.0.1",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "@vitejs/plugin-react": "^4.3.0",
    "typescript": "~5.7.0",
    "vite": "^6.0.0"
  }
}

除非用户另有说明,否则将 @midnight-ntwrk/dapp-connector-api 固定为 4.0.1。如果安装因 ETARGET 失败,请检查 npm view @midnight-ntwrk/dapp-connector-api version。


5) vite.config.ts

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
});

6) tsconfig.json

{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ]
}

7) tsconfig.app.json

{
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true
  },
  "include": ["src"]
}

8) tsconfig.node.json

{
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
    "target": "ES2022",
    "lib": ["ES2023"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": true,
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true
  },
  "include": ["vite.config.ts"]
}

9) src/vite-env.d.ts

/// <reference types="vite/client" />

App.tsx 中对 @midnight-ntwrk/dapp-connector-api 的副作用导入会扩展 window.midnight 类型 — 无需手动声明。


10) src/types.ts

export interface WalletCardProps {
  isConnected: boolean;
  walletAddress: string | null;
  onConnect: () => void;
  onDisconnect: () => void;
}

11) src/selectWallet.ts

钱包会在 window.midnight 下以 UUID 键注入。始终枚举钱包 — 切勿硬编码钱包名称。

import type { InitialAPI } from '@midnight-ntwrk/dapp-connector-api';

export const listWallets = (): InitialAPI[] => {
  const injected = window.midnight;
  return injected ? Object.values(injected) : [];
};

export const selectWallet = (): InitialAPI => {
  const wallets = listWallets();

  if (wallets.length === 0) {
    throw new Error(
      'No Midnight wallet found. Please install a Midnight wallet extension.',
    );
  }

  return wallets[0];
};

如果有多个可用钱包,请使用 listWallets() 显示选择器,让用户选择。安全地显示每个钱包的名称和图标,以防止 XSS。


12) src/WalletCard.tsx

展示层 — 连接状态、地址显示、连接/断开连接按钮。不包含 CSS;可按需添加样式。

import React from 'react';
import type { WalletCardProps } from './types';

const WalletCard: React.FC<WalletCardProps> = ({
  isConnected,
  walletAddress,
  onConnect,
  onDisconnect,
}) => {
  return (
    <div>
      <div>
        <h2>Connection Status</h2>
        <div>{isConnected ? 'Connected' : 'Disconnected'}</div>
      </div>

      <div>
        {isConnected && walletAddress ? (
          <>
            <p>Wallet Address:</p>
            <p title={walletAddress}>{walletAddress}</p>
          </>
        ) : (
          <p>Please connect your wallet to proceed.</p>
        )}
      </div>

      <div>
        {isConnected ? (
          <button onClick={onDisconnect}>Disconnect Wallet</button>
        ) : (
          <button onClick={onConnect}>Connect Wallet</button>
        )}
      </div>
    </div>
  );
};

export default WalletCard;

13) src/App.tsx

使用 DApp Connector API 的连接逻辑。

import React, { useState } from 'react';
import WalletCard from './WalletCard';
import '@midnight-ntwrk/dapp-connector-api';
import { selectWallet } from './selectWallet';

const App: React.FC = () => {
  const [isConnected, setIsConnected] = useState<boolean>(false);
  const [walletAddress, setWalletAddress] = useState<string | null>(null);

  const handleConnect = async () => {
    console.log('Connect button clicked');
    let connected = false;
    let address: string | null = null;

    try {
      const wallet = selectWallet();

      // 'undeployed' for local dev; 'preprod' | 'preview' | 'mainnet' for live networks
      const connectedApi = await wallet.connect('preprod');

      const { unshieldedAddress } = await connectedApi.getUnshieldedAddress();
      address = unshieldedAddress;

      const serviceUriConfig = await connectedApi.getConfiguration();
      console.log('Service URI Config:', serviceUriConfig);

      const connectionStatus = await connectedApi.getConnectionStatus();
      if (connectionStatus.status === 'connected') {
        connected = true;
        console.log('Connected to the wallet:', address);
      }
    } catch (error) {
      console.log('An error occurred:', error);
    }

    setIsConnected(connected);
    setWalletAddress(address);
  };

  const handleDisconnect = () => {
    setWalletAddress(null);
    setIsConnected(false);
  };

  return (
    <div>
      <header>
        <h1>Midnight Wallet Connector</h1>
      </header>
      <main>
        <WalletCard
          isConnected={isConnected}
          walletAddress={walletAddress}
          onConnect={handleConnect}
          onDisconnect={handleDisconnect}
        />
      </main>
    </div>
  );
};

export default App;
连接流程分解
  1. 选择钱包 — selectWallet() 读取 window.midnight 条目;如果未找到钱包则抛出错误(由 try/catch 捕获)
  2. 连接到网络 — wallet.connect(networkId) 会提示用户授权
  3. 获取地址 — getUnshieldedAddress() 返回公开的非屏蔽地址
  4. 检查状态 — getConnectionStatus() 返回 { status: 'connected' | 'disconnected' }
  5. 可选配置 — getConfiguration() 返回服务 URI(索引器、节点等),供下游 SDK 配置使用

14) src/main.tsx

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
);

15) index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Midnight Wallet Connector</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

16) 运行

npm install
npm run dev

打开 http://localhost:5173。点击 Connect Wallet — 扩展会提示授权。批准后,应用会显示连接状态和非屏蔽地址。

17) 多钱包选择器(可选增强)

当 listWallets() 返回多个条目时,将 selectWallet() 的自动选择替换为面向用户的选择器:

// src/WalletPicker.tsx
import type { InitialAPI } from '@midnight-ntwrk/dapp-connector-api';
import { listWallets } from './selectWallet';

type Props = {
  onSelect: (wallet: InitialAPI) => void;
};

export function WalletPicker({ onSelect }: Props) {
  const wallets = listWallets();

  if (wallets.length === 0) {
    return <p>No Midnight wallet found. Install a wallet extension and refresh.</p>;
  }

  return (
    <ul>
      {wallets.map((wallet) => (
        <li key={wallet.name}>
          <button type="button" onClick={() => onSelect(wallet)}>
            {wallet.name}
          </button>
        </li>
      ))}
    </ul>
  );
}

除非对 HTML 进行清理,否则只能将钱包的 name 和 icon 作为文本呈现。切勿对钱包提供的图标 URL 使用 dangerouslySetInnerHTML。


18) 故障排除

错误原因修复方法
window.midnight 为 undefined未安装扩展,或页面在注入前已加载安装 Midnight 钱包;安装后刷新页面
No Midnight wallet found扩展已停用,或检测模式不正确使用 Object.values(window.midnight)——不要使用 window.midnight.mnLace 或其他硬编码键
连接被拒绝/失败网络不匹配确保 connect('preprod') 与钱包当前使用的网络一致
连接一直挂起钱包已锁定或尚未同步解锁钱包;等待同步完成
安装时出现 ETARGET软件包版本过旧运行 npm view @midnight-ntwrk/dapp-connector-api version 并固定到最新版本
window.midnight 上的类型错误缺少副作用导入在 App.tsx 中添加 import '@midnight-ntwrk/dapp-connector-api'

19) 后续步骤

连接器正常运行后,可扩展应用:

功能技能/API
部署并调用 Compact 合约1am-wallet/
代币转账token-transfers/
查询余额和交易历史indexer/
签署任意消息connectedApi 签名方法(参见 DApp Connector API 文档)
多网络选择器调用 wallet.connect(selectedNetwork) 的网络下拉菜单
完整 SDK 提供方接线midnight-js/

20) Agent 检查清单

为用户生成此模板时:

  • 使用 Vite react-ts 搭建项目,或根据此技能编写所有文件
  • 安装 @midnight-ntwrk/[email protected]
  • 创建 types.ts、selectWallet.ts、WalletCard.tsx、App.tsx、main.tsx
  • 在 App.tsx 中加入副作用导入 @midnight-ntwrk/dapp-connector-api
  • 使用 Object.values(window.midnight) 检测钱包——切勿硬编码钱包键
  • 默认网络设为 'preprod',除非用户指定本地网络('undeployed')或其他网络
  • 除非用户要求设置样式,否则省略 CSS
  • 提醒用户测试前必须安装钱包扩展

评论

支持 Markdown