From be94b5bcd0f2b59f22e3d24c1bdd213399d7fa1d Mon Sep 17 00:00:00 2001 From: Jeason Date: Tue, 14 Oct 2025 16:25:30 +0800 Subject: [PATCH 1/4] feat: add new provider for ledger hd wallet --- .changeset/vast-tools-poke.md | 5 + packages/ledger/.fatherrc.ts | 5 + packages/ledger/CHANGELOG.md | 7 + packages/ledger/README.md | 120 ++++ packages/ledger/docs/basic.tsx | 19 + packages/ledger/docs/index.md | 204 +++++++ packages/ledger/docs/index.zh-CN.md | 204 +++++++ packages/ledger/global.d.ts | 8 + packages/ledger/package.json | 70 +++ packages/ledger/src/adapter/index.ts | 1 + .../ledger/src/adapter/useLedgerWallet.tsx | 9 + packages/ledger/src/index.ts | 5 + packages/ledger/src/ledger/dmk.ts | 29 + packages/ledger/src/ledger/index.ts | 6 + packages/ledger/src/ledger/useAppCommand.ts | 66 ++ .../ledger/src/ledger/useAvailableDevices.ts | 71 +++ packages/ledger/src/ledger/useConnect.ts | 67 +++ packages/ledger/src/ledger/useDeviceStatus.ts | 65 ++ .../ledger/src/ledger/useEthereumSigner.ts | 161 +++++ .../src/provider/__tests__/index.test.tsx | 25 + .../ledger/src/provider/config-provider.tsx | 69 +++ packages/ledger/src/provider/index.tsx | 72 +++ packages/ledger/src/types.ts | 30 + .../src/wallets/__tests__/ledger.test.ts | 29 + packages/ledger/src/wallets/index.ts | 1 + packages/ledger/src/wallets/ledger.tsx | 180 ++++++ .../ledger/src/wallets/useLatestWallet.tsx | 29 + packages/ledger/tsconfig.json | 7 + pnpm-lock.yaml | 567 +++++++++++++----- 29 files changed, 1995 insertions(+), 136 deletions(-) create mode 100644 .changeset/vast-tools-poke.md create mode 100644 packages/ledger/.fatherrc.ts create mode 100644 packages/ledger/CHANGELOG.md create mode 100644 packages/ledger/README.md create mode 100644 packages/ledger/docs/basic.tsx create mode 100644 packages/ledger/docs/index.md create mode 100644 packages/ledger/docs/index.zh-CN.md create mode 100644 packages/ledger/global.d.ts create mode 100644 packages/ledger/package.json create mode 100644 packages/ledger/src/adapter/index.ts create mode 100644 packages/ledger/src/adapter/useLedgerWallet.tsx create mode 100644 packages/ledger/src/index.ts create mode 100644 packages/ledger/src/ledger/dmk.ts create mode 100644 packages/ledger/src/ledger/index.ts create mode 100644 packages/ledger/src/ledger/useAppCommand.ts create mode 100644 packages/ledger/src/ledger/useAvailableDevices.ts create mode 100644 packages/ledger/src/ledger/useConnect.ts create mode 100644 packages/ledger/src/ledger/useDeviceStatus.ts create mode 100644 packages/ledger/src/ledger/useEthereumSigner.ts create mode 100644 packages/ledger/src/provider/__tests__/index.test.tsx create mode 100644 packages/ledger/src/provider/config-provider.tsx create mode 100644 packages/ledger/src/provider/index.tsx create mode 100644 packages/ledger/src/types.ts create mode 100644 packages/ledger/src/wallets/__tests__/ledger.test.ts create mode 100644 packages/ledger/src/wallets/index.ts create mode 100644 packages/ledger/src/wallets/ledger.tsx create mode 100644 packages/ledger/src/wallets/useLatestWallet.tsx create mode 100644 packages/ledger/tsconfig.json diff --git a/.changeset/vast-tools-poke.md b/.changeset/vast-tools-poke.md new file mode 100644 index 000000000..4372a1fb2 --- /dev/null +++ b/.changeset/vast-tools-poke.md @@ -0,0 +1,5 @@ +--- +'@ant-design/web3-ledger': minor +--- + +add new provider for ledger hardware wallet diff --git a/packages/ledger/.fatherrc.ts b/packages/ledger/.fatherrc.ts new file mode 100644 index 000000000..3305dd5a7 --- /dev/null +++ b/packages/ledger/.fatherrc.ts @@ -0,0 +1,5 @@ +import { defineConfig } from 'father'; + +export default defineConfig({ + extends: '../../.fatherrc.base.ts', +}); diff --git a/packages/ledger/CHANGELOG.md b/packages/ledger/CHANGELOG.md new file mode 100644 index 000000000..e8671f75b --- /dev/null +++ b/packages/ledger/CHANGELOG.md @@ -0,0 +1,7 @@ +# @ant-design/web3-ledger + +## 0.1.0 + +### Minor Changes + +- Initial release of Ledger hardware wallet adapter diff --git a/packages/ledger/README.md b/packages/ledger/README.md new file mode 100644 index 000000000..66a66fc08 --- /dev/null +++ b/packages/ledger/README.md @@ -0,0 +1,120 @@ +# @ant-design/web3-ledger + +This package provides a Ledger hardware wallet adapter for [@ant-design/web3](https://www.npmjs.com/package/@ant-design/web3). + +Ledger is a hardware wallet that provides secure storage for cryptocurrency private keys. This adapter integrates Ledger devices with Ant Design Web3 components using the official Ledger SDK. + +## Features + +- 🔐 **Secure Hardware Wallet**: Connect to Ledger hardware devices via WebHID +- 📱 **Device Management**: Auto-discover and manage Ledger devices +- ✍️ **Message Signing**: Sign messages and typed data with Ledger +- 🔄 **Session Management**: Maintain persistent sessions with connected devices +- 📊 **Device Status**: Monitor device lock status and current app + +## Installation + +```bash +npm install @ant-design/web3 @ant-design/web3-ledger +``` + +or + +```bash +pnpm add @ant-design/web3 @ant-design/web3-ledger +``` + +## Basic Usage + +```tsx +import { ConnectButton, Connector } from '@ant-design/web3'; +import { Ledger, LedgerWeb3ConfigProvider } from '@ant-design/web3-ledger'; + +const App: React.FC = () => { + return ( + + + + + + ); +}; + +export default App; +``` + +## Prerequisites + +### Browser Requirements + +Ledger integration requires a browser that supports WebHID API: + +- Chrome/Edge 89+ +- Opera 76+ +- Not supported: Firefox, Safari + +### Device Setup + +1. Connect your Ledger device via USB +2. Unlock the device with your PIN +3. Open the Ethereum app on your Ledger +4. Ensure browser permissions for WebHID are granted + +## Advanced Usage + +### Custom Derivation Path + +```tsx +import { Ledger } from '@ant-design/web3-ledger'; + +const wallet = Ledger({ + derivationPath: "44'/60'/1'/0/0", // Custom path +}); +``` + +### Monitoring Device Status + +```tsx +import { useDeviceStatus } from '@ant-design/web3-ledger'; + +function DeviceMonitor() { + const { deviceStatus, currentApp } = useDeviceStatus({ sessionId }); + + return ( +
+

Status: {deviceStatus}

+

Current App: {currentApp}

+
+ ); +} +``` + +## API Reference + +For detailed API documentation, visit [Ledger - Ant Design Web3](https://web3.ant.design/components/ledger). + +## Troubleshooting + +### Device Not Detected + +1. Ensure WebHID is enabled in your browser +2. Check USB connection and try a different port +3. Update Ledger firmware to the latest version +4. Grant browser permissions when prompted + +### Connection Fails + +1. Unlock your Ledger device +2. Open the Ethereum app on the device +3. Check that no other application is using the device +4. Try disconnecting and reconnecting + +## Related Links + +- [Ant Design Web3 Documentation](https://web3.ant.design) +- [Ledger Official Website](https://www.ledger.com) +- [Ledger Developer Portal](https://developers.ledger.com) + +## License + +MIT diff --git a/packages/ledger/docs/basic.tsx b/packages/ledger/docs/basic.tsx new file mode 100644 index 000000000..ac35f487f --- /dev/null +++ b/packages/ledger/docs/basic.tsx @@ -0,0 +1,19 @@ +/** + * title: Basic Usage + * description: Connect to Ledger hardware wallet + */ + +import { ConnectButton, Connector } from '@ant-design/web3'; +import { Ledger, LedgerWeb3ConfigProvider } from '@ant-design/web3-ledger'; + +const App: React.FC = () => { + return ( + + + + + + ); +}; + +export default App; diff --git a/packages/ledger/docs/index.md b/packages/ledger/docs/index.md new file mode 100644 index 000000000..e77024ed2 --- /dev/null +++ b/packages/ledger/docs/index.md @@ -0,0 +1,204 @@ +--- +nav: Components +group: Adapter +order: 10 +--- + +# Ledger + +Ledger hardware wallet adapter for Ant Design Web3. + +Ledger is a hardware wallet that provides secure storage for cryptocurrency private keys. This adapter integrates Ledger devices with Ant Design Web3 using the official Ledger SDK. + +## When to Use + +- When you need to support hardware wallet for enhanced security +- For applications requiring physical signature confirmation +- When building DApps that prioritize security +- For enterprise applications with compliance requirements + +## Installation + +```bash +npm install @ant-design/web3 @ant-design/web3-ledger +``` + +## Code Demo + +### Basic Usage + +Connect to Ledger hardware wallet. + + + +## Prerequisites + +### Browser Requirements + +Ledger integration requires browsers supporting WebHID API: + +- ✅ Chrome/Edge 89+ +- ✅ Opera 76+ +- ❌ Firefox (not supported) +- ❌ Safari (not supported) + +### Device Setup + +1. **Connect Device**: Plug Ledger into your computer via USB +2. **Unlock Device**: Enter PIN on the device +3. **Open App**: Navigate to and open the Ethereum app +4. **Grant Permissions**: Allow browser to access the device when prompted + +## API + +### LedgerWeb3ConfigProvider + +| Property | Description | Type | Default | Version | +| ----------- | --------------------------- | ----------------- | ------- | ------- | +| wallets | Supported wallet list | `WalletFactory[]` | `[]` | - | +| locale | Internationalization | `Locale` | - | - | +| balance | Display balance | `boolean` | `false` | - | +| autoConnect | Auto-connect to last wallet | `boolean` | `false` | - | + +### Ledger Wallet + +```tsx +import { Ledger } from '@ant-design/web3-ledger'; + +const wallet = Ledger(); +``` + +Ledger hardware wallet factory function. + +### Hooks + +#### useAvailableDevices + +Monitor and discover Ledger devices. + +```tsx +import { useAvailableDevices } from '@ant-design/web3-ledger'; + +const { devices, discover, isDiscovering } = useAvailableDevices(); +``` + +**Returns:** + +- `devices`: Array of discovered devices +- `discover`: Function to manually trigger device discovery +- `isDiscovering`: Boolean indicating if discovery is in progress + +#### useConnect + +Manage device connection. + +```tsx +import { useConnect } from '@ant-design/web3-ledger'; + +const { sessionId, connect, disconnect, isConnecting, isDisconnecting } = useConnect(); +``` + +**Returns:** + +- `sessionId`: Current session ID if connected +- `connect`: Function to connect to a device +- `disconnect`: Function to disconnect +- `isConnecting`: Boolean for connection status +- `isDisconnecting`: Boolean for disconnection status + +#### useDeviceStatus + +Monitor device status and current app. + +```tsx +import { useDeviceStatus } from '@ant-design/web3-ledger'; + +const { deviceStatus, currentApp } = useDeviceStatus({ sessionId }); +``` + +**Returns:** + +- `deviceStatus`: Current device status (CONNECTED, LOCKED, BUSY, etc.) +- `currentApp`: Name of currently open app on device + +#### useEthereumSigner + +Interact with Ethereum on Ledger. + +```tsx +import { useEthereumSigner } from '@ant-design/web3-ledger'; + +const { + address, + isLoadingAddress, + signMessage, + signTypedData, + isSigningMessage, + isSigningTypedData, +} = useEthereumSigner({ sessionId, derivationPath: "44'/60'/0'/0/0" }); +``` + +**Returns:** + +- `address`: Current Ethereum address +- `isLoadingAddress`: Loading state for address +- `signMessage`: Function to sign plain messages +- `signTypedData`: Function to sign EIP-712 typed data +- `isSigningMessage`: Signing state for messages +- `isSigningTypedData`: Signing state for typed data + +## Troubleshooting + +### Common Issues + +**Device Not Detected** + +1. Verify WebHID is enabled in browser +2. Check USB connection +3. Update Ledger firmware +4. Ensure no other apps are using the device + +**Connection Timeout** + +1. Unlock the device +2. Open the Ethereum app +3. Check USB cable quality +4. Try a different USB port + +**Signature Rejected** + +1. Verify the message content on device screen +2. Ensure you're confirming the correct transaction +3. Check device battery level +4. Restart the device if frozen + +## FAQ + +### Why isn't Firefox supported? + +Firefox has not yet implemented the WebHID API which is required for communication with Ledger devices. + +### Can I use Ledger with mobile browsers? + +No, WebHID is currently only available in desktop browsers. + +### How do I change the derivation path? + +You can customize the derivation path when using the Ethereum signer hook: + +```tsx +const { address } = useEthereumSigner({ + sessionId, + derivationPath: "44'/60'/1'/0/0", // Custom path +}); +``` + +### Is it safe to use Ledger with web applications? + +Yes, Ledger provides hardware-level security. Private keys never leave the device, and all transactions must be physically confirmed on the device screen. + +## Related Resources + +- [Ledger Developer Documentation](https://developers.ledger.com/) +- [WebHID API](https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API) +- [Ethereum BIP44 Paths](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) diff --git a/packages/ledger/docs/index.zh-CN.md b/packages/ledger/docs/index.zh-CN.md new file mode 100644 index 000000000..808731126 --- /dev/null +++ b/packages/ledger/docs/index.zh-CN.md @@ -0,0 +1,204 @@ +--- +nav: 组件 +group: 适配器 +order: 10 +--- + +# Ledger + +Ledger 硬件钱包适配器,用于 Ant Design Web3。 + +Ledger 是一款硬件钱包,为加密货币私钥提供安全存储。该适配器使用官方 Ledger SDK 将 Ledger 设备集成到 Ant Design Web3 中。 + +## 何时使用 + +- 需要硬件钱包支持以增强安全性时 +- 需要物理签名确认的应用场景 +- 构建优先考虑安全性的 DApp 时 +- 具有合规要求的企业应用 + +## 安装 + +```bash +npm install @ant-design/web3 @ant-design/web3-ledger +``` + +## 代码演示 + +### 基本使用 + +连接到 Ledger 硬件钱包。 + + + +## 前置条件 + +### 浏览器要求 + +Ledger 集成需要支持 WebHID API 的浏览器: + +- ✅ Chrome/Edge 89+ +- ✅ Opera 76+ +- ❌ Firefox(不支持) +- ❌ Safari(不支持) + +### 设备设置 + +1. **连接设备**:通过 USB 将 Ledger 插入电脑 +2. **解锁设备**:在设备上输入 PIN 码 +3. **打开应用**:在设备上导航并打开 Ethereum 应用 +4. **授予权限**:在浏览器提示时允许访问设备 + +## API + +### LedgerWeb3ConfigProvider + +| 属性 | 描述 | 类型 | 默认值 | 版本 | +| ----------- | -------------------------- | ----------------- | ------- | ---- | +| wallets | 支持的钱包列表 | `WalletFactory[]` | `[]` | - | +| locale | 国际化设置 | `Locale` | - | - | +| balance | 是否显示余额 | `boolean` | `false` | - | +| autoConnect | 是否自动连接上次使用的钱包 | `boolean` | `false` | - | + +### Ledger 钱包 + +```tsx +import { Ledger } from '@ant-design/web3-ledger'; + +const wallet = Ledger(); +``` + +Ledger 硬件钱包工厂函数。 + +### Hooks + +#### useAvailableDevices + +监控和发现 Ledger 设备。 + +```tsx +import { useAvailableDevices } from '@ant-design/web3-ledger'; + +const { devices, discover, isDiscovering } = useAvailableDevices(); +``` + +**返回值:** + +- `devices`:已发现的设备数组 +- `discover`:手动触发设备发现的函数 +- `isDiscovering`:表示是否正在发现设备的布尔值 + +#### useConnect + +管理设备连接。 + +```tsx +import { useConnect } from '@ant-design/web3-ledger'; + +const { sessionId, connect, disconnect, isConnecting, isDisconnecting } = useConnect(); +``` + +**返回值:** + +- `sessionId`:连接时的当前会话 ID +- `connect`:连接设备的函数 +- `disconnect`:断开连接的函数 +- `isConnecting`:连接状态的布尔值 +- `isDisconnecting`:断开连接状态的布尔值 + +#### useDeviceStatus + +监控设备状态和当前应用。 + +```tsx +import { useDeviceStatus } from '@ant-design/web3-ledger'; + +const { deviceStatus, currentApp } = useDeviceStatus({ sessionId }); +``` + +**返回值:** + +- `deviceStatus`:当前设备状态(CONNECTED、LOCKED、BUSY 等) +- `currentApp`:设备上当前打开的应用名称 + +#### useEthereumSigner + +与 Ledger 上的以太坊交互。 + +```tsx +import { useEthereumSigner } from '@ant-design/web3-ledger'; + +const { + address, + isLoadingAddress, + signMessage, + signTypedData, + isSigningMessage, + isSigningTypedData, +} = useEthereumSigner({ sessionId, derivationPath: "44'/60'/0'/0/0" }); +``` + +**返回值:** + +- `address`:当前以太坊地址 +- `isLoadingAddress`:地址加载状态 +- `signMessage`:签名普通消息的函数 +- `signTypedData`:签名 EIP-712 类型化数据的函数 +- `isSigningMessage`:消息签名状态 +- `isSigningTypedData`:类型化数据签名状态 + +## 故障排除 + +### 常见问题 + +**设备未检测到** + +1. 验证浏览器中已启用 WebHID +2. 检查 USB 连接 +3. 更新 Ledger 固件 +4. 确保没有其他应用在使用设备 + +**连接超时** + +1. 解锁设备 +2. 打开 Ethereum 应用 +3. 检查 USB 线缆质量 +4. 尝试不同的 USB 端口 + +**签名被拒绝** + +1. 在设备屏幕上验证消息内容 +2. 确保您正在确认正确的交易 +3. 检查设备电量 +4. 如果设备冻结,请重启设备 + +## 常见问题 + +### 为什么不支持 Firefox? + +Firefox 尚未实现与 Ledger 设备通信所需的 WebHID API。 + +### 可以在移动浏览器中使用 Ledger 吗? + +不可以,WebHID 目前仅在桌面浏览器中可用。 + +### 如何更改派生路径? + +您可以在使用以太坊签名器 hook 时自定义派生路径: + +```tsx +const { address } = useEthereumSigner({ + sessionId, + derivationPath: "44'/60'/1'/0/0", // 自定义路径 +}); +``` + +### 在 Web 应用中使用 Ledger 安全吗? + +是的,Ledger 提供硬件级别的安全性。私钥永远不会离开设备,所有交易都必须在设备屏幕上进行物理确认。 + +## 相关资源 + +- [Ledger 开发者文档](https://developers.ledger.com/) +- [WebHID API](https://developer.mozilla.org/zh-CN/docs/Web/API/WebHID_API) +- [以太坊 BIP44 路径](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) diff --git a/packages/ledger/global.d.ts b/packages/ledger/global.d.ts new file mode 100644 index 000000000..2979a5f60 --- /dev/null +++ b/packages/ledger/global.d.ts @@ -0,0 +1,8 @@ +declare module '*.svg' { + export const ReactComponent: React.FunctionComponent< + React.SVGProps & { title?: string } + >; + + const src: string; + export default src; +} diff --git a/packages/ledger/package.json b/packages/ledger/package.json new file mode 100644 index 000000000..07a165274 --- /dev/null +++ b/packages/ledger/package.json @@ -0,0 +1,70 @@ +{ + "name": "@ant-design/web3-ledger", + "version": "0.1.0", + "main": "dist/lib/index.js", + "module": "dist/esm/index.js", + "typings": "dist/esm/index.d.ts", + "exports": { + "import": "./dist/esm/index.js", + "require": "./dist/lib/index.js", + "types": "./dist/esm/index.d.ts" + }, + "sideEffects": false, + "files": [ + "dist", + "CHANGELOG.md", + "README.md" + ], + "keywords": [ + "ant", + "design", + "web3", + "antd", + "component", + "components", + "framework", + "frontend", + "react", + "react-component", + "ui", + "ledger", + "hardware-wallet" + ], + "homepage": "https://web3.ant.design", + "bugs": { + "url": "https://github.com/ant-design/ant-design-web3/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/ant-design/ant-design-web3" + }, + "scripts": { + "dev": "father dev", + "build": "father build" + }, + "dependencies": { + "@ant-design/web3-common": "workspace:*", + "@ant-design/web3-icons": "workspace:*", + "@ledgerhq/device-management-kit": "^0.9.1", + "@ledgerhq/device-signer-kit-ethereum": "^1.8.0", + "@ledgerhq/device-transport-kit-web-hid": "^1.2.0", + "rxjs": "^7.8.1" + }, + "devDependencies": { + "father": "^4.6.2", + "typescript": "^5.6.2" + }, + "peerDependencies": { + "react": ">=18.0.0" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org", + "access": "public" + }, + "browserslist": [ + "last 2 versions", + "Firefox ESR", + "> 1%", + "ie >= 11" + ] +} diff --git a/packages/ledger/src/adapter/index.ts b/packages/ledger/src/adapter/index.ts new file mode 100644 index 000000000..b8bbc2709 --- /dev/null +++ b/packages/ledger/src/adapter/index.ts @@ -0,0 +1 @@ +export * from './useLedgerWallet'; diff --git a/packages/ledger/src/adapter/useLedgerWallet.tsx b/packages/ledger/src/adapter/useLedgerWallet.tsx new file mode 100644 index 000000000..b210f68a9 --- /dev/null +++ b/packages/ledger/src/adapter/useLedgerWallet.tsx @@ -0,0 +1,9 @@ +import { createContext, useContext } from 'react'; + +import type { LedgerWallet } from '../types'; + +export const LedgerAdapterContext = createContext({} as LedgerWallet); + +export const useLedgerWallet = (): LedgerWallet => { + return useContext(LedgerAdapterContext); +}; diff --git a/packages/ledger/src/index.ts b/packages/ledger/src/index.ts new file mode 100644 index 000000000..75e98e889 --- /dev/null +++ b/packages/ledger/src/index.ts @@ -0,0 +1,5 @@ +export * from './provider'; +export * from './wallets'; +export * from './types'; +export * from './ledger'; +export { useLedgerWallet } from './adapter/useLedgerWallet'; diff --git a/packages/ledger/src/ledger/dmk.ts b/packages/ledger/src/ledger/dmk.ts new file mode 100644 index 000000000..4762904de --- /dev/null +++ b/packages/ledger/src/ledger/dmk.ts @@ -0,0 +1,29 @@ +import { + ConsoleLogger, + DeviceManagementKitBuilder, + type DeviceManagementKit, +} from '@ledgerhq/device-management-kit'; +import { webHidTransportFactory } from '@ledgerhq/device-transport-kit-web-hid'; + +let dmkInstance: DeviceManagementKit | null = null; + +/** + * Get or create the DeviceManagementKit instance + * Using singleton pattern to ensure only one instance exists + */ +export const getDMK = (): DeviceManagementKit => { + if (!dmkInstance) { + dmkInstance = new DeviceManagementKitBuilder() + .addLogger(new ConsoleLogger()) + .addTransport(webHidTransportFactory) + .build(); + } + return dmkInstance; +}; + +/** + * Reset the DMK instance (useful for testing) + */ +export const resetDMK = (): void => { + dmkInstance = null; +}; diff --git a/packages/ledger/src/ledger/index.ts b/packages/ledger/src/ledger/index.ts new file mode 100644 index 000000000..92e9f13d5 --- /dev/null +++ b/packages/ledger/src/ledger/index.ts @@ -0,0 +1,6 @@ +export * from './dmk'; +export * from './useAvailableDevices'; +export * from './useConnect'; +export * from './useDeviceStatus'; +export * from './useAppCommand'; +export * from './useEthereumSigner'; diff --git a/packages/ledger/src/ledger/useAppCommand.ts b/packages/ledger/src/ledger/useAppCommand.ts new file mode 100644 index 000000000..2b2388007 --- /dev/null +++ b/packages/ledger/src/ledger/useAppCommand.ts @@ -0,0 +1,66 @@ +import { useCallback, useState } from 'react'; +import type { CommandResult, DeviceSessionId } from '@ledgerhq/device-management-kit'; +import { CloseAppCommand, OpenAppCommand } from '@ledgerhq/device-management-kit'; + +import { getDMK } from './dmk'; + +export interface UseAppCommandOptions { + sessionId?: DeviceSessionId | null; +} + +/** + * Hook to manage Ledger device app commands + */ +export const useAppCommand = (options: UseAppCommandOptions = {}) => { + const { sessionId } = options; + const [isOpeningApp, setIsOpeningApp] = useState(false); + const [isClosingApp, setIsClosingApp] = useState(false); + + const openApp = useCallback( + async (appName: string, abortTimeout?: number): Promise> => { + if (!sessionId) { + throw new Error('No session ID available'); + } + + const dmk = getDMK(); + setIsOpeningApp(true); + + try { + const command = new OpenAppCommand({ appName }); + const result = await dmk.sendCommand({ sessionId, command, abortTimeout }); + setIsOpeningApp(false); + return result; + } catch (error) { + setIsOpeningApp(false); + throw error; + } + }, + [sessionId], + ); + + const closeApp = useCallback(async (): Promise> => { + if (!sessionId) { + throw new Error('No session ID available'); + } + + const dmk = getDMK(); + setIsClosingApp(true); + + try { + const command = new CloseAppCommand(); + const result = await dmk.sendCommand({ sessionId, command }); + setIsClosingApp(false); + return result; + } catch (error) { + setIsClosingApp(false); + throw error; + } + }, [sessionId]); + + return { + openApp, + closeApp, + isOpeningApp, + isClosingApp, + }; +}; diff --git a/packages/ledger/src/ledger/useAvailableDevices.ts b/packages/ledger/src/ledger/useAvailableDevices.ts new file mode 100644 index 000000000..76b32ac74 --- /dev/null +++ b/packages/ledger/src/ledger/useAvailableDevices.ts @@ -0,0 +1,71 @@ +import { useEffect, useRef, useState } from 'react'; +import type { DiscoveredDevice } from '@ledgerhq/device-management-kit'; +import type { Subscription } from 'rxjs'; + +import { getDMK } from './dmk'; + +export interface UseAvailableDevicesOptions { + onDevicesChange?: (devices: DiscoveredDevice[]) => void; + onError?: (error: Error) => void; +} + +/** + * Hook to listen to available Ledger devices + */ +export const useAvailableDevices = (options: UseAvailableDevicesOptions = {}) => { + const { onDevicesChange, onError } = options; + const [devices, setDevices] = useState([]); + const [isDiscovering, setIsDiscovering] = useState(false); + const subscriptionRef = useRef(null); + + useEffect(() => { + const dmk = getDMK(); + + // Subscribe to available devices + if (subscriptionRef.current) { + subscriptionRef.current.unsubscribe(); + } + + subscriptionRef.current = dmk.listenToAvailableDevices({}).subscribe({ + next: (deviceList) => { + setDevices(deviceList); + onDevicesChange?.(deviceList); + }, + error: (error) => { + console.error('Device monitoring error:', error); + onError?.(error); + }, + }); + + return () => { + if (subscriptionRef.current) { + subscriptionRef.current.unsubscribe(); + subscriptionRef.current = null; + } + }; + }, [onDevicesChange, onError]); + + const discover = (): Promise => { + const dmk = getDMK(); + setIsDiscovering(true); + + return new Promise((resolve, reject) => { + dmk.startDiscovering({}).subscribe({ + next: (device) => { + setIsDiscovering(false); + resolve(device); + }, + error: (error) => { + setIsDiscovering(false); + reject(error); + }, + }); + }); + }; + + return { + devices, + discover, + isDiscovering, + }; +}; diff --git a/packages/ledger/src/ledger/useConnect.ts b/packages/ledger/src/ledger/useConnect.ts new file mode 100644 index 000000000..0c2fc493a --- /dev/null +++ b/packages/ledger/src/ledger/useConnect.ts @@ -0,0 +1,67 @@ +import { useCallback, useEffect, useState } from 'react'; +import type { ConnectUseCaseArgs, DeviceSessionId } from '@ledgerhq/device-management-kit'; + +import { getDMK } from './dmk'; + +/** + * Hook to manage Ledger device connection + */ +export const useConnect = () => { + const [sessionId, setSessionId] = useState(null); + const [isConnecting, setIsConnecting] = useState(false); + const [isDisconnecting, setIsDisconnecting] = useState(false); + const [error, setError] = useState(null); + + const connect = useCallback(async (args: ConnectUseCaseArgs): Promise => { + const dmk = getDMK(); + setIsConnecting(true); + setError(null); + + try { + const newSessionId = await dmk.connect(args); + setSessionId(newSessionId); + setIsConnecting(false); + return newSessionId; + } catch (err) { + const error = err instanceof Error ? err : new Error('Connection failed'); + setError(error); + setIsConnecting(false); + throw error; + } + }, []); + + const disconnect = useCallback( + async (sessionIdToDisconnect?: DeviceSessionId) => { + const dmk = getDMK(); + const targetSessionId = sessionIdToDisconnect || sessionId; + + if (!targetSessionId) { + return; + } + + setIsDisconnecting(true); + setError(null); + + try { + await dmk.disconnect({ sessionId: targetSessionId }); + setSessionId(null); + setIsDisconnecting(false); + } catch (err) { + const error = err instanceof Error ? err : new Error('Disconnection failed'); + setError(error); + setIsDisconnecting(false); + throw error; + } + }, + [sessionId], + ); + + return { + sessionId, + connect, + disconnect, + isConnecting, + isDisconnecting, + error, + }; +}; diff --git a/packages/ledger/src/ledger/useDeviceStatus.ts b/packages/ledger/src/ledger/useDeviceStatus.ts new file mode 100644 index 000000000..32a0adca4 --- /dev/null +++ b/packages/ledger/src/ledger/useDeviceStatus.ts @@ -0,0 +1,65 @@ +import { useEffect, useRef, useState } from 'react'; +import type { DeviceSessionState, DeviceStatus } from '@ledgerhq/device-management-kit'; +import type { Subscription } from 'rxjs'; + +import { getDMK } from './dmk'; + +export interface UseDeviceStatusOptions { + sessionId?: string | null; + onStateChange?: (state: DeviceSessionState) => void; + onError?: (error: Error) => void; +} + +/** + * Hook to monitor Ledger device status + */ +export const useDeviceStatus = (options: UseDeviceStatusOptions = {}) => { + const { sessionId, onStateChange, onError } = options; + const [deviceStatus, setDeviceStatus] = useState(null); + const [currentApp, setCurrentApp] = useState(null); + const subscriptionRef = useRef(null); + + useEffect(() => { + if (!sessionId) { + setDeviceStatus(null); + setCurrentApp(null); + return; + } + + const dmk = getDMK(); + + if (subscriptionRef.current) { + subscriptionRef.current.unsubscribe(); + } + + subscriptionRef.current = dmk.getDeviceSessionState({ sessionId }).subscribe({ + next: (state) => { + setDeviceStatus(state.deviceStatus); + + // Extract current app name if available + const appName = (state as any)?.currentApp?.name; + if (appName) { + setCurrentApp(appName); + } + + onStateChange?.(state); + }, + error: (error) => { + console.error('Device status monitoring error:', error); + onError?.(error); + }, + }); + + return () => { + if (subscriptionRef.current) { + subscriptionRef.current.unsubscribe(); + subscriptionRef.current = null; + } + }; + }, [sessionId, onStateChange, onError]); + + return { + deviceStatus, + currentApp, + }; +}; diff --git a/packages/ledger/src/ledger/useEthereumSigner.ts b/packages/ledger/src/ledger/useEthereumSigner.ts new file mode 100644 index 000000000..cf8295576 --- /dev/null +++ b/packages/ledger/src/ledger/useEthereumSigner.ts @@ -0,0 +1,161 @@ +import { useCallback, useEffect, useState } from 'react'; +import { DeviceActionStatus } from '@ledgerhq/device-management-kit'; +import type { DeviceSessionId } from '@ledgerhq/device-management-kit'; +import { + SignerEthBuilder, + type AddressOptions, + type Signature, + type TypedData, +} from '@ledgerhq/device-signer-kit-ethereum'; + +import { getDMK } from './dmk'; + +export interface UseEthereumSignerOptions { + sessionId?: DeviceSessionId | null; + derivationPath?: string; + addressOptions?: AddressOptions; +} + +/** + * Convert Ledger signature to hash signature format + */ +export function toHashSignature(sig: Signature): `0x${string}` { + const { r, s, v } = sig; + const rHex = r.slice(2); + const sHex = s.slice(2); + const vHex = v.toString(16).padStart(2, '0'); + return `0x${rHex}${sHex}${vHex}`; +} + +/** + * Hook to interact with Ethereum on Ledger device + */ +export const useEthereumSigner = (options: UseEthereumSignerOptions = {}) => { + const { sessionId, derivationPath = "44'/60'/0'/0/0", addressOptions } = options; + + const [address, setAddress] = useState(null); + const [isLoadingAddress, setIsLoadingAddress] = useState(false); + const [isSigningMessage, setIsSigningMessage] = useState(false); + const [isSigningTypedData, setIsSigningTypedData] = useState(false); + + // Get address when sessionId changes + useEffect(() => { + if (!sessionId) { + setAddress(null); + return; + } + + const dmk = getDMK(); + const signer = new SignerEthBuilder({ + dmk, + sessionId, + originToken: 'ant-design-web3-ledger', + }).build(); + + setIsLoadingAddress(true); + + const { observable } = signer.getAddress(derivationPath, addressOptions); + + const subscription = observable.subscribe({ + next: (response) => { + if (response.status === DeviceActionStatus.Completed) { + setAddress(response.output.address); + setIsLoadingAddress(false); + } + }, + error: (error) => { + console.error('Get address error:', error); + setIsLoadingAddress(false); + }, + }); + + return () => { + subscription.unsubscribe(); + }; + }, [sessionId, derivationPath, addressOptions]); + + const signMessage = useCallback( + async (message: string): Promise => { + if (!sessionId) { + throw new Error('No session ID available'); + } + + const dmk = getDMK(); + const signer = new SignerEthBuilder({ + dmk, + sessionId, + originToken: 'ant-design-web3-ledger', + }).build(); + + setIsSigningMessage(true); + + return new Promise((resolve, reject) => { + const { observable } = signer.signMessage(derivationPath, message); + + observable.subscribe({ + next: (response) => { + if (response.status === DeviceActionStatus.Completed) { + setIsSigningMessage(false); + resolve(response.output); + } else if (response.status === DeviceActionStatus.Error) { + setIsSigningMessage(false); + reject(response.error); + } + }, + error: (error) => { + setIsSigningMessage(false); + reject(error); + }, + }); + }); + }, + [sessionId, derivationPath], + ); + + const signTypedData = useCallback( + async (typedData: TypedData): Promise => { + if (!sessionId) { + throw new Error('No session ID available'); + } + + const dmk = getDMK(); + const signer = new SignerEthBuilder({ + dmk, + sessionId, + originToken: 'ant-design-web3-ledger', + }).build(); + + setIsSigningTypedData(true); + + return new Promise((resolve, reject) => { + const { observable } = signer.signTypedData(derivationPath, typedData); + + observable.subscribe({ + next: (response) => { + if (response.status === DeviceActionStatus.Completed) { + setIsSigningTypedData(false); + resolve(response.output); + } else if (response.status === DeviceActionStatus.Error) { + setIsSigningTypedData(false); + reject(response.error); + } + }, + error: (error) => { + setIsSigningTypedData(false); + reject(error); + }, + }); + }); + }, + [sessionId, derivationPath], + ); + + return { + address, + isLoadingAddress, + signMessage, + isSigningMessage, + signTypedData, + isSigningTypedData, + }; +}; diff --git a/packages/ledger/src/provider/__tests__/index.test.tsx b/packages/ledger/src/provider/__tests__/index.test.tsx new file mode 100644 index 000000000..a402d11eb --- /dev/null +++ b/packages/ledger/src/provider/__tests__/index.test.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; + +import { LedgerWeb3ConfigProvider } from '../index'; + +describe('LedgerWeb3ConfigProvider', () => { + it('should render without crashing', () => { + const { container } = render( + +
Test
+
, + ); + expect(container).toBeTruthy(); + }); + + it('should render children', () => { + const { getByText } = render( + +
Test Content
+
, + ); + expect(getByText('Test Content')).toBeTruthy(); + }); +}); diff --git a/packages/ledger/src/provider/config-provider.tsx b/packages/ledger/src/provider/config-provider.tsx new file mode 100644 index 000000000..49959649d --- /dev/null +++ b/packages/ledger/src/provider/config-provider.tsx @@ -0,0 +1,69 @@ +import { useEffect, useMemo, useState, type FC, type PropsWithChildren } from 'react'; +import type { Account, Locale, Wallet } from '@ant-design/web3-common'; +import { Web3ConfigProvider } from '@ant-design/web3-common'; + +import { useLedgerWallet } from '../adapter/useLedgerWallet'; +import type { WalletWithAdapter } from '../types'; + +export interface LedgerConfigProviderProps { + selectWallet: (wallet?: Wallet | null) => void; + wallets?: WalletWithAdapter[]; + balance?: boolean; + locale?: Locale; +} + +export const LedgerConfigProvider: FC> = ({ + children, + selectWallet, + wallets, + balance: showBalance, + locale, +}) => { + const adapter = useLedgerWallet(); + const [account, setAccount] = useState(undefined); + + const disconnect = async () => { + await adapter.disconnect?.(); + setAccount(undefined); + }; + + const connect = async (wallet?: Wallet) => { + if (!wallet) { + return; + } + + await selectWallet(wallet); + }; + + useEffect(() => { + if (adapter.name && adapter.accounts?.length > 0) { + setAccount(adapter.accounts[0]); + } else { + setAccount(undefined); + } + }, [adapter, wallets]); + + const availableWallets = useMemo(() => { + return wallets?.map((wallet) => { + return { + name: wallet.name, + icon: wallet.icon, + group: wallet.group, + remark: wallet.remark, + extensions: wallet.extensions, + } as Wallet; + }); + }, [wallets]); + + return ( + + {children} + + ); +}; diff --git a/packages/ledger/src/provider/index.tsx b/packages/ledger/src/provider/index.tsx new file mode 100644 index 000000000..b9611f4a8 --- /dev/null +++ b/packages/ledger/src/provider/index.tsx @@ -0,0 +1,72 @@ +import { useEffect, useState, type FC, type PropsWithChildren } from 'react'; +import type { Locale, Wallet } from '@ant-design/web3-common'; + +import { LedgerAdapterContext, useLedgerWallet } from '../adapter/useLedgerWallet'; +import type { LedgerWallet, WalletFactory, WalletWithAdapter } from '../types'; +import { useLatestWallet } from '../wallets/useLatestWallet'; +import { LedgerConfigProvider } from './config-provider'; + +export interface LedgerWeb3ConfigProviderProps { + wallets?: WalletFactory[]; + locale?: Locale; + balance?: boolean; + autoConnect?: boolean; +} + +export const LedgerWeb3ConfigProvider: FC> = ({ + children, + wallets: initWallets = [], + balance = false, + locale, + autoConnect, +}) => { + const [adapter, setAdapter] = useState({} as LedgerWallet); + const [wallets, setWallets] = useState([]); + const { name: adapterName } = useLedgerWallet(); + + const { latestWalletNameRef, cacheSelectedWallet } = useLatestWallet(); + + useEffect(() => { + if (initWallets.length === 0) return; + setWallets(initWallets.map((w) => w.create())); + }, [initWallets]); + + const selectWallet = async (wallet?: Wallet | null) => { + if (!wallet) { + // disconnect + if (adapter) setAdapter({} as LedgerWallet); + cacheSelectedWallet(); + return; + } + + const walletWithAdapter = wallets.find((w) => w.name === wallet.name); + const provider = walletWithAdapter?.adapter; + await provider?.connect(); + // @ts-ignore provider is not undefined + setAdapter(provider); + cacheSelectedWallet(wallet.name); + }; + + // auto connect + useEffect(() => { + if (autoConnect && latestWalletNameRef.current && !adapterName) { + const wallet = wallets.find((w) => w.name === latestWalletNameRef.current); + if (wallet) { + selectWallet(wallet); + } + } + }, [wallets]); + + return ( + + + {children} + + + ); +}; diff --git a/packages/ledger/src/types.ts b/packages/ledger/src/types.ts new file mode 100644 index 000000000..004231b80 --- /dev/null +++ b/packages/ledger/src/types.ts @@ -0,0 +1,30 @@ +import type { Account, WalletExtensionItem } from '@ant-design/web3-common'; + +export interface LedgerAccount extends Account { + path?: string; +} + +export interface LedgerWallet { + name: string; + accounts: LedgerAccount[]; + connect: () => Promise; + disconnect: () => Promise; + signMessage?: (message: string) => Promise; + signTypedData?: (typedData: any) => Promise; + _setupHooks?: (hooks: any) => void; + useLedgerHooks?: () => any; +} + +export interface WalletFactory { + name?: string; + create: () => WalletWithAdapter; +} + +export interface WalletWithAdapter { + name: string; + adapter?: LedgerWallet; + icon?: React.ReactNode; + group?: string; + remark: string; + extensions?: false | WalletExtensionItem[]; +} diff --git a/packages/ledger/src/wallets/__tests__/ledger.test.ts b/packages/ledger/src/wallets/__tests__/ledger.test.ts new file mode 100644 index 000000000..fd81501b1 --- /dev/null +++ b/packages/ledger/src/wallets/__tests__/ledger.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it, vi } from 'vitest'; + +import type { LedgerWallet } from '../../types'; +import { Ledger } from '../ledger'; + +describe('Ledger wallet', () => { + it('should create Ledger wallet factory', () => { + const walletFactory = Ledger(); + expect(walletFactory.name).toBe('Ledger'); + expect(walletFactory.create).toBeDefined(); + }); + + it('should create Ledger wallet adapter', () => { + const walletFactory = Ledger(); + const wallet = walletFactory.create(); + + expect(wallet.name).toBe('Ledger'); + expect(wallet.adapter).toBeDefined(); + expect(wallet.group).toBe('Hardware'); + }); + + it('should have connect and disconnect methods', async () => { + const walletFactory = Ledger(); + const wallet = walletFactory.create(); + + expect(wallet.adapter?.connect).toBeDefined(); + expect(wallet.adapter?.disconnect).toBeDefined(); + }); +}); diff --git a/packages/ledger/src/wallets/index.ts b/packages/ledger/src/wallets/index.ts new file mode 100644 index 000000000..2dc9c1283 --- /dev/null +++ b/packages/ledger/src/wallets/index.ts @@ -0,0 +1 @@ +export { Ledger } from './ledger'; diff --git a/packages/ledger/src/wallets/ledger.tsx b/packages/ledger/src/wallets/ledger.tsx new file mode 100644 index 000000000..0a02487f0 --- /dev/null +++ b/packages/ledger/src/wallets/ledger.tsx @@ -0,0 +1,180 @@ +import type { DeviceSessionId, DiscoveredDevice } from '@ledgerhq/device-management-kit'; +import { DeviceStatus } from '@ledgerhq/device-management-kit'; + +import { + useAppCommand, + useAvailableDevices, + useConnect, + useDeviceStatus, + useEthereumSigner, +} from '../ledger'; +import type { LedgerAccount, LedgerWallet, WalletFactory } from '../types'; + +export const Ledger = (): WalletFactory => { + return { + name: 'Ledger', + create: () => { + let sessionId: DeviceSessionId | null = null; + let currentAddress: string | null = null; + let derivationPath = "44'/60'/0'/0/0"; + + // These will be set up when the wallet is used in a React component + let devicesRef: DiscoveredDevice[] = []; + let connectFn: ((args: any) => Promise) | null = null; + let disconnectFn: ((id?: DeviceSessionId) => Promise) | null = null; + let openAppFn: ((appName: string) => Promise) | null = null; + let getAddressFn: (() => string | null) | null = null; + let signMessageFn: ((message: string) => Promise) | null = null; + let signTypedDataFn: ((typedData: any) => Promise) | null = null; + let deviceStatusRef: DeviceStatus | null = null; + let currentAppRef: string | null = null; + + const adapter: LedgerWallet = { + name: 'Ledger', + accounts: [] as LedgerAccount[], + + connect: async () => { + console.log('Connecting to Ledger...'); + + // Wait for device to be available + if (devicesRef.length === 0) { + throw new Error('No Ledger device found. Please connect your device.'); + } + + const device = devicesRef[0]; + + if (connectFn) { + sessionId = await connectFn({ device }); + + // Wait for device to be unlocked and Ethereum app to be open + let retries = 0; + const maxRetries = 30; // 15 seconds total (500ms * 30) + + while (retries < maxRetries) { + if (deviceStatusRef === DeviceStatus.CONNECTED && currentAppRef === 'Ethereum') { + break; + } + + if ( + deviceStatusRef === DeviceStatus.CONNECTED && + currentAppRef !== 'Ethereum' && + openAppFn + ) { + try { + await openAppFn('Ethereum'); + } catch (error) { + console.error('Failed to open Ethereum app:', error); + } + } + + await new Promise((resolve) => setTimeout(resolve, 500)); + retries++; + } + + // Get address + if (getAddressFn) { + currentAddress = getAddressFn(); + + if (currentAddress) { + adapter.accounts = [ + { + address: currentAddress, + path: derivationPath, + }, + ]; + } + } + } + }, + + disconnect: async () => { + console.log('Disconnecting from Ledger...'); + + if (disconnectFn && sessionId) { + await disconnectFn(sessionId); + sessionId = null; + currentAddress = null; + adapter.accounts = []; + } + }, + + signMessage: async (message: string) => { + console.log('Signing message:', message); + + if (!signMessageFn) { + throw new Error('Sign message function not available'); + } + + const signature = await signMessageFn(message); + return signature; + }, + + signTypedData: async (typedData: any) => { + console.log('Signing typed data:', typedData); + + if (!signTypedDataFn) { + throw new Error('Sign typed data function not available'); + } + + const signature = await signTypedDataFn(typedData); + return signature; + }, + + // Internal methods to set up hooks + _setupHooks: (hooks: { + devices: DiscoveredDevice[]; + connect: (args: any) => Promise; + disconnect: (id?: DeviceSessionId) => Promise; + openApp: (appName: string) => Promise; + getAddress: () => string | null; + signMessage: (message: string) => Promise; + signTypedData: (typedData: any) => Promise; + deviceStatus: DeviceStatus | null; + currentApp: string | null; + }) => { + devicesRef = hooks.devices; + connectFn = hooks.connect; + disconnectFn = hooks.disconnect; + openAppFn = hooks.openApp; + getAddressFn = hooks.getAddress; + signMessageFn = hooks.signMessage; + signTypedDataFn = hooks.signTypedData; + deviceStatusRef = hooks.deviceStatus; + currentAppRef = hooks.currentApp; + }, + + // Hook to use in React components + useLedgerHooks: () => { + const { devices } = useAvailableDevices(); + const { sessionId: connectedSessionId, connect, disconnect } = useConnect(); + const { deviceStatus, currentApp } = useDeviceStatus({ sessionId: connectedSessionId }); + const { openApp } = useAppCommand({ sessionId: connectedSessionId }); + const { address, signMessage, signTypedData } = useEthereumSigner({ + sessionId: connectedSessionId, + derivationPath, + }); + + return { + devices, + connect, + disconnect, + openApp, + getAddress: () => address, + signMessage, + signTypedData, + deviceStatus, + currentApp, + }; + }, + }; + + return { + name: 'Ledger', + adapter, + icon: undefined, // TODO: Add Ledger icon + group: 'Hardware', + remark: 'Ledger Hardware Wallet', + }; + }, + }; +}; diff --git a/packages/ledger/src/wallets/useLatestWallet.tsx b/packages/ledger/src/wallets/useLatestWallet.tsx new file mode 100644 index 000000000..3cd96c7fe --- /dev/null +++ b/packages/ledger/src/wallets/useLatestWallet.tsx @@ -0,0 +1,29 @@ +import { useEffect, useRef } from 'react'; + +const LATEST_WALLET_STORAGE_KEY = 'ANT_DESIGN_WEB3_LEDGER_LATEST_WALLET'; + +export const useLatestWallet = () => { + const latestWalletNameRef = useRef(); + + useEffect(() => { + const latestWallet = localStorage.getItem(LATEST_WALLET_STORAGE_KEY); + if (latestWallet) { + latestWalletNameRef.current = latestWallet; + } + }, []); + + const cacheSelectedWallet = (walletName?: string) => { + if (walletName) { + localStorage.setItem(LATEST_WALLET_STORAGE_KEY, walletName); + latestWalletNameRef.current = walletName; + } else { + localStorage.removeItem(LATEST_WALLET_STORAGE_KEY); + latestWalletNameRef.current = undefined; + } + }; + + return { + latestWalletNameRef, + cacheSelectedWallet, + }; +}; diff --git a/packages/ledger/tsconfig.json b/packages/ledger/tsconfig.json new file mode 100644 index 000000000..7d99fd73a --- /dev/null +++ b/packages/ledger/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "moduleResolution": "bundler" + }, + "include": ["src", "global.d.ts"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f05dd87c..f7267b54f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -155,7 +155,7 @@ importers: version: 18.3.7(@types/react@18.3.21) '@umijs/fabric': specifier: ^4.0.1 - version: 4.0.1(postcss@8.5.3) + version: 4.0.1(postcss@8.5.6) '@vitest/coverage-v8': specifier: ^3.2.2 version: 3.2.2(vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.21)(jiti@1.21.7)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(less@4.4.0)(lightningcss@1.22.1)(sass@1.89.0)(terser@5.44.0)(yaml@2.8.0)) @@ -413,7 +413,7 @@ importers: version: 5.76.1(react@18.3.1) debug: specifier: ^4.4.0 - version: 4.4.1(supports-color@5.5.0) + version: 4.4.1 viem: specifier: ^2.33.2 version: 2.33.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.13) @@ -450,7 +450,7 @@ importers: version: 5.76.1(react@18.3.1) debug: specifier: ^4.4.0 - version: 4.4.1(supports-color@5.5.0) + version: 4.4.1 viem: specifier: ^2.33.2 version: 2.33.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.13) @@ -490,7 +490,7 @@ importers: version: 5.76.1(react@18.3.1) debug: specifier: ^4.4.0 - version: 4.4.1(supports-color@5.5.0) + version: 4.4.1 viem: specifier: ^2.33.2 version: 2.33.3(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.13) @@ -548,6 +548,37 @@ importers: specifier: ^5.6.2 version: 5.8.3 + packages/ledger: + dependencies: + '@ant-design/web3-common': + specifier: workspace:* + version: link:../common + '@ant-design/web3-icons': + specifier: workspace:* + version: link:../icons + '@ledgerhq/device-management-kit': + specifier: ^0.9.1 + version: 0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10) + '@ledgerhq/device-signer-kit-ethereum': + specifier: ^1.8.0 + version: 1.8.0(@ledgerhq/context-module@1.8.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@ledgerhq/device-transport-kit-web-hid': + specifier: ^1.2.0 + version: 1.2.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(rxjs@7.8.2) + react: + specifier: '>=18.0.0' + version: 18.3.1 + rxjs: + specifier: ^7.8.1 + version: 7.8.2 + devDependencies: + father: + specifier: ^4.6.2 + version: 4.6.2(@babel/core@7.27.1)(@types/node@24.7.2)(@types/webpack@5.28.5(@swc/core@1.9.2(@swc/helpers@0.5.17)))(bufferutil@4.0.9)(styled-components@5.3.11(@babel/core@7.27.1)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(type-fest@1.4.0)(utf-8-validate@5.0.10)(webpack@5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17))) + typescript: + specifier: ^5.6.2 + version: 5.8.3 + packages/solana: dependencies: '@ant-design/web3-assets': @@ -594,7 +625,7 @@ importers: version: 6.0.0 debug: specifier: ^4.4.0 - version: 4.4.1(supports-color@5.5.0) + version: 4.4.1 devDependencies: '@solana/wallet-adapter-phantom': specifier: ^0.9.24 @@ -619,7 +650,7 @@ importers: version: link:../common debug: specifier: ^4.4.0 - version: 4.4.1(supports-color@5.5.0) + version: 4.4.1 devDependencies: '@mysten/dapp-kit': specifier: ^0.14.50 @@ -709,7 +740,7 @@ importers: version: link:../common debug: specifier: ^4.4.0 - version: 4.4.1(supports-color@5.5.0) + version: 4.4.1 devDependencies: '@tanstack/react-query': specifier: ^5.51.11 @@ -1710,24 +1741,28 @@ packages: engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [musl] '@biomejs/cli-linux-arm64@1.9.4': resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [glibc] '@biomejs/cli-linux-x64-musl@1.9.4': resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [musl] '@biomejs/cli-linux-x64@1.9.4': resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [glibc] '@biomejs/cli-win32-arm64@1.9.4': resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} @@ -2857,6 +2892,25 @@ packages: '@interactjs/types@1.10.27': resolution: {integrity: sha512-BUdv0cvs4H5ODuwft2Xp4eL8Vmi3LcihK42z0Ft/FbVJZoRioBsxH+LlsBdK4tAie7PqlKGy+1oyOncu1nQ6eA==} + '@inversifyjs/common@1.5.0': + resolution: {integrity: sha512-Qj5BELk11AfI2rgZEAaLPmOftmQRLLmoCXgAjmaF0IngQN5vHomVT5ML7DZ3+CA5fgGcEVMcGbUDAun+Rz+oNg==} + + '@inversifyjs/container@1.9.1': + resolution: {integrity: sha512-8EhjFoAx1LoD7TpCuP9ptitwc+7kVXEpZB0IeoEsCQb9sWaNYYaBi+7Lommu3/1nYxdMbX2t7AJhQnryT1EEsg==} + peerDependencies: + reflect-metadata: ~0.2.2 + + '@inversifyjs/core@5.2.0': + resolution: {integrity: sha512-MMaHGGRjQWT9uAof63sbZyEhRl4XptEAE17DJwrgUcN9LsdIEvecKP3r53pE9VF88PFR41knUKKzagUBvWLHmw==} + + '@inversifyjs/prototype-utils@0.1.0': + resolution: {integrity: sha512-lNz1yyajMRDXBHLvJsYYX81FcmeD15e5Qz1zAZ/3zeYTl+u7ZF/GxNRKJzNOloeMPMtuR8BnvzHA1SZxjR+J9w==} + + '@inversifyjs/reflect-metadata-utils@1.1.0': + resolution: {integrity: sha512-jmuAuC3eL1GnFAYfJGJOMKRDL9q1mgzOyrban6zxfM8Yg1FUHsj25h27bW2G7p8X1Amvhg3MLkaOuogszkrofA==} + peerDependencies: + reflect-metadata: 0.2.2 + '@irys/arweave@0.0.2': resolution: {integrity: sha512-ddE5h4qXbl0xfGlxrtBIwzflaxZUDlDs43TuT0u1OMfyobHul4AA1VEX72Rpzw2bOh4vzoytSqA1jCM7x9YtHg==} @@ -2965,6 +3019,33 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@ledgerhq/context-module@1.8.0': + resolution: {integrity: sha512-lsKjhGbSQbyRGhGpoj9QrBM9WEzbFhuMvZirEIBqHBpAfv7GXUECfOsVgaPPnrUa/cDJhvudmCHQlHWId7unMw==} + peerDependencies: + '@ledgerhq/device-management-kit': ^0.9.0 + + '@ledgerhq/device-management-kit@0.9.1': + resolution: {integrity: sha512-CI4c9Q/EWMGOzUnhpHUyo1DX+WLTD6AJWC8wKfbTbb6TZCaOtD0xN4qsNwZb4GG+CNC4IDlEfOw+EX8584hemg==} + peerDependencies: + rxjs: 7.8.2 + + '@ledgerhq/device-signer-kit-ethereum@1.8.0': + resolution: {integrity: sha512-rhnjD3R0lhW/ksNcnoFbJStaMVgNkkuoBRzgG2addVab9CxsUE+F/OEZjLc65wt9x5VLyVEMPW/EqXJ5Xglp6Q==} + peerDependencies: + '@ledgerhq/context-module': 1.8.0 + '@ledgerhq/device-management-kit': ^0.9.0 + + '@ledgerhq/device-transport-kit-web-hid@1.2.0': + resolution: {integrity: sha512-51kLHqrn1dP+0ZQLRyUBHIPSBNvx74hiIAMHrBkiCAedpmND/W522nslpX42bVf3tU3+I0Y51qn3WFvd8ZtIow==} + peerDependencies: + '@ledgerhq/device-management-kit': 0.8.0 + rxjs: ^7.8.2 + + '@ledgerhq/signer-utils@1.1.0': + resolution: {integrity: sha512-zp8kyNF0sNMUG2VkgOL7rDu8W6U1P8yvTA3wIDjjlqoIOPanvodfezeub69fOuHJ2QG/JmnS8YZCGIoSWpQYkA==} + peerDependencies: + '@ledgerhq/device-management-kit': 0.9.0 + '@lit-labs/ssr-dom-shim@1.3.0': resolution: {integrity: sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==} @@ -3227,42 +3308,49 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-arm64-musl@1.1.1': resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@napi-rs/nice-linux-ppc64-gnu@1.1.1': resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==} engines: {node: '>= 10'} cpu: [ppc64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-riscv64-gnu@1.1.1': resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-s390x-gnu@1.1.1': resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==} engines: {node: '>= 10'} cpu: [s390x] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-x64-gnu@1.1.1': resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-x64-musl@1.1.1': resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@napi-rs/nice-openharmony-arm64@1.1.1': resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==} @@ -3459,36 +3547,42 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.1': resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.1': resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.1': resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.1': resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.1': resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [musl] '@parcel/watcher-win32-arm64@2.5.1': resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} @@ -4030,56 +4124,67 @@ packages: resolution: {integrity: sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.41.0': resolution: {integrity: sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.41.0': resolution: {integrity: sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.41.0': resolution: {integrity: sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loongarch64-gnu@4.41.0': resolution: {integrity: sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-powerpc64le-gnu@4.41.0': resolution: {integrity: sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.41.0': resolution: {integrity: sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.41.0': resolution: {integrity: sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.41.0': resolution: {integrity: sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.41.0': resolution: {integrity: sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.41.0': resolution: {integrity: sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.41.0': resolution: {integrity: sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==} @@ -4191,6 +4296,22 @@ packages: '@selderee/plugin-htmlparser2@0.11.0': resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} + '@sentry/hub@6.19.7': + resolution: {integrity: sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==} + engines: {node: '>=6'} + + '@sentry/minimal@6.19.7': + resolution: {integrity: sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==} + engines: {node: '>=6'} + + '@sentry/types@6.19.7': + resolution: {integrity: sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==} + engines: {node: '>=6'} + + '@sentry/utils@6.19.7': + resolution: {integrity: sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==} + engines: {node: '>=6'} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -4606,24 +4727,28 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [linux] + libc: [glibc] '@swc/core-linux-arm64-musl@1.9.2': resolution: {integrity: sha512-8xzrOmsyCC1zrx2Wzx/h8dVsdewO1oMCwBTLc1gSJ/YllZYTb04pNm6NsVbzUX2tKddJVRgSJXV10j/NECLwpA==} engines: {node: '>=10'} cpu: [arm64] os: [linux] + libc: [musl] '@swc/core-linux-x64-gnu@1.9.2': resolution: {integrity: sha512-kZrNz/PjRQKcchWF6W292jk3K44EoVu1ad5w+zbS4jekIAxsM8WwQ1kd+yjUlN9jFcF8XBat5NKIs9WphJCVXg==} engines: {node: '>=10'} cpu: [x64] os: [linux] + libc: [glibc] '@swc/core-linux-x64-musl@1.9.2': resolution: {integrity: sha512-TTIpR4rjMkhX1lnFR+PSXpaL83TrQzp9znRdp2TzYrODlUd/R20zOwSo9vFLCyH6ZoD47bccY7QeGZDYT3nlRg==} engines: {node: '>=10'} cpu: [x64] os: [linux] + libc: [musl] '@swc/core-win32-arm64-msvc@1.9.2': resolution: {integrity: sha512-+Eg2d4icItKC0PMjZxH7cSYFLWk0aIp94LNmOw6tPq0e69ax6oh10upeq0D1fjWsKLmOJAWEvnXlayZcijEXDw==} @@ -5191,24 +5316,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@umijs/es-module-parser-linux-arm64-musl@0.0.7': resolution: {integrity: sha512-cqQffARWkmQ3n1RYNKZR3aD6X8YaP6u1maASjDgPQOpZMAlv/OSDrM/7iGujWTs0PD0haockNG9/DcP6lgPHMw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@umijs/es-module-parser-linux-x64-gnu@0.0.7': resolution: {integrity: sha512-PHrKHtT665Za0Ydjch4ACrNpRU+WIIden12YyF1CtMdhuLDSoU6UfdhF3NoDbgEUcXVDX/ftOqmj0SbH3R1uew==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@umijs/es-module-parser-linux-x64-musl@0.0.7': resolution: {integrity: sha512-cyZvUK5lcECLWzLp/eU1lFlCETcz+LEb+wrdARQSST1dgoIGZsT4cqM1WzYmdZNk3o883tiZizLt58SieEiHBQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@umijs/es-module-parser-win32-arm64-msvc@0.0.7': resolution: {integrity: sha512-V7WxnUI88RboSl0RWLNQeKBT7EDW35fW6Tn92zqtoHHxrhAIL9DtDyvC8REP4qTxeZ6Oej/Ax5I6IjsLx3yTOg==} @@ -5253,24 +5382,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@umijs/mako-linux-arm64-musl@0.11.10': resolution: {integrity: sha512-kqI1Jw6IHtDwrcsqPZrYxsV3pHzZyOR+6fCFnF5MSURnXbUbJb6Rk66VsKKpMqbyfsEO6nt0WT9FrRBlFvRU2A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@umijs/mako-linux-x64-gnu@0.11.10': resolution: {integrity: sha512-jlhXVvWJuumMmiE3z3ViugOMx9ZasNM1anng0PsusCgDwfy0IOfGzfwfwagqtzfsC5MwyRcfnRQyDdbfbroaSA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@umijs/mako-linux-x64-musl@0.11.10': resolution: {integrity: sha512-SLV/PRdL12dFEKlQGenW3OboZXmdYi25y+JblgVJLBhpdxZrHFqpCsTZn4L3hVEhyl0/ksR1iY0wtfK3urR29g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@umijs/mako-win32-ia32-msvc@0.11.10': resolution: {integrity: sha512-quCWpVl7yQjG+ccGhkF81GxO3orXdPW1OZWXWxJgOI0uPk7Hczh2EYMEVqqQGbi/83eJ1e3iE1jRTl/+2eHryQ==} @@ -5371,24 +5504,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@utoo/pack-linux-arm64-musl@0.0.1-alpha.36': resolution: {integrity: sha512-AxYsYQAc/c0xoxQUCK1oGO0M40793bPGXJ6DZ9Kki37skNybDqLSEw3TOKqaXQb6eCkANb6bS7cx4SQikenDWw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@utoo/pack-linux-x64-gnu@0.0.1-alpha.36': resolution: {integrity: sha512-RqgPTseIdaohv8iLWG4kcOyr0Xnf1PgX6d+u4kSqnc77Mlgk5a8hn62VLIv3Bv6YWHP0La/Jx1WvORPM/tE8cg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@utoo/pack-linux-x64-musl@0.0.1-alpha.36': resolution: {integrity: sha512-KK5ZE5zo/e46zTuYiqETfirWRaG/Z48zHxeWmH1dCJP9WBbv6ke6Ir0Wo+FXuCU4DoCaMwzTgPby40+ePqlTpQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@utoo/pack-win32-x64-msvc@0.0.1-alpha.36': resolution: {integrity: sha512-G+QFeEYsoMt9x+nZA0pIx6tj4IQyflKv68Q4hoQCSIqttuwygrWVmYky5DOF+HN/Nc4Q2+0yow8JMlZVAGljtQ==} @@ -6165,6 +6302,9 @@ packages: axios@0.27.2: resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + axios@1.8.2: + resolution: {integrity: sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==} + axios@1.8.3: resolution: {integrity: sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==} @@ -8554,6 +8694,11 @@ packages: invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + inversify@7.5.1: + resolution: {integrity: sha512-oWWFDU2BXiuqZynGcLDDD4tqiWAeaEUCALlCj0vk/QwHGgZY/tzDFPuTmWMY3jwRmDIHxVDkcj9SL3MFTlCEDw==} + peerDependencies: + reflect-metadata: ~0.2.2 + invert-kv@3.0.1: resolution: {integrity: sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==} engines: {node: '>=8'} @@ -9182,24 +9327,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.22.1: resolution: {integrity: sha512-MCV6RuRpzXbunvzwY644iz8cw4oQxvW7oer9xPkdadYqlEyiJJ6wl7FyJOH7Q6ZYH4yjGAUCvxDBxPbnDu9ZVg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.22.1: resolution: {integrity: sha512-RjNgpdM20VUXgV7us/VmlO3Vn2ZRiDnc3/bUxCVvySZWPiVPprpqW/QDWuzkGa+NCUf6saAM5CLsZLSxncXJwg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.22.1: resolution: {integrity: sha512-ZgO4C7Rd6Hv/5MnyY2KxOYmIlzk4rplVolDt3NbkNR8DndnyX0Q5IR4acJWNTBICQ21j3zySzKbcJaiJpk/4YA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-x64-msvc@1.22.1: resolution: {integrity: sha512-4pozV4eyD0MDET41ZLHAeBo+H04Nm2UEYIk5w/ts40231dRFV7E0cjwbnZvSoc1DXFgecAhiC0L16ruv/ZDCpg==} @@ -10740,6 +10889,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + purify-ts@2.1.0: + resolution: {integrity: sha512-+KNUHV9FxB9BbjadFdvxa+LNJIaqZmSF7CQH5Rv6+f0rBzsxm9FEqrvkALQbWYJobAja2ZCbBDUY7O4fH2znMA==} + q@1.5.1: resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} engines: {node: '>=0.6.0', teleport: '>=0.2.0'} @@ -11285,6 +11437,9 @@ packages: resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} engines: {node: '>=12'} + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -12732,6 +12887,10 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@11.0.3: + resolution: {integrity: sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==} + hasBin: true + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -13292,6 +13451,9 @@ packages: resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} engines: {node: '>=0.4.0'} + xstate@5.19.2: + resolution: {integrity: sha512-B8fL2aP0ogn5aviAXFzI5oZseAMqN00fg/TeDa3ZtatyDcViYLIfuQl4y8qmHCiKZgGEzmnTyNtNQL9oeJE2gw==} + xtend@2.1.2: resolution: {integrity: sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==} engines: {node: '>=0.4'} @@ -13439,7 +13601,7 @@ snapshots: '@ant-design/cssinjs-utils@1.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@ant-design/cssinjs': 1.23.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13470,7 +13632,7 @@ snapshots: '@ant-design/fast-color@2.0.6': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@ant-design/icons-svg@4.4.2': {} @@ -13507,7 +13669,7 @@ snapshots: '@ant-design/react-slick@1.1.2(react@18.3.1)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 json2mq: 0.2.0 react: 18.3.1 @@ -13563,7 +13725,7 @@ snapshots: '@babel/traverse': 7.27.1(supports-color@5.5.0) '@babel/types': 7.27.1 convert-source-map: 2.0.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -13583,7 +13745,7 @@ snapshots: '@babel/traverse': 7.27.1(supports-color@5.5.0) '@babel/types': 7.27.1 convert-source-map: 2.0.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -13673,7 +13835,7 @@ snapshots: '@babel/core': 7.27.1 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.10 transitivePeerDependencies: @@ -14475,7 +14637,7 @@ snapshots: '@babel/parser': 7.27.2 '@babel/template': 7.27.2 '@babel/types': 7.27.1 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -14488,7 +14650,7 @@ snapshots: '@babel/parser': 7.28.3 '@babel/template': 7.27.2 '@babel/types': 7.28.2 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -14500,7 +14662,7 @@ snapshots: '@babel/parser': 7.28.4 '@babel/template': 7.27.2 '@babel/types': 7.28.4 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -14577,7 +14739,7 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.7.2 + semver: 7.7.3 '@changesets/assemble-release-plan@6.0.8': dependencies: @@ -14586,7 +14748,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 - semver: 7.7.2 + semver: 7.7.3 '@changesets/changelog-git@0.2.1': dependencies: @@ -14642,7 +14804,7 @@ snapshots: '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 picocolors: 1.1.1 - semver: 7.7.2 + semver: 7.7.3 '@changesets/get-release-plan@4.0.12': dependencies: @@ -15310,7 +15472,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 @@ -15730,7 +15892,7 @@ snapshots: '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -15757,7 +15919,7 @@ snapshots: '@antfu/install-pkg': 0.1.1 '@antfu/utils': 0.7.10 '@iconify/types': 2.0.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 kolorist: 1.8.0 local-pkg: 0.4.3 transitivePeerDependencies: @@ -15769,6 +15931,31 @@ snapshots: '@interactjs/types@1.10.27': {} + '@inversifyjs/common@1.5.0': {} + + '@inversifyjs/container@1.9.1(reflect-metadata@0.2.2)': + dependencies: + '@inversifyjs/common': 1.5.0 + '@inversifyjs/core': 5.2.0(reflect-metadata@0.2.2) + '@inversifyjs/reflect-metadata-utils': 1.1.0(reflect-metadata@0.2.2) + reflect-metadata: 0.2.2 + + '@inversifyjs/core@5.2.0(reflect-metadata@0.2.2)': + dependencies: + '@inversifyjs/common': 1.5.0 + '@inversifyjs/prototype-utils': 0.1.0 + '@inversifyjs/reflect-metadata-utils': 1.1.0(reflect-metadata@0.2.2) + transitivePeerDependencies: + - reflect-metadata + + '@inversifyjs/prototype-utils@0.1.0': + dependencies: + '@inversifyjs/common': 1.5.0 + + '@inversifyjs/reflect-metadata-utils@1.1.0(reflect-metadata@0.2.2)': + dependencies: + reflect-metadata: 0.2.2 + '@irys/arweave@0.0.2(debug@4.4.1)': dependencies: asn1.js: 5.4.1 @@ -15964,6 +16151,66 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@ledgerhq/context-module@1.8.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + dependencies: + '@ledgerhq/device-management-kit': 0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10) + axios: 1.8.2 + crypto-js: 4.2.0 + ethers: 6.14.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + inversify: 7.5.1(reflect-metadata@0.2.2) + purify-ts: 2.1.0 + reflect-metadata: 0.2.2 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10)': + dependencies: + '@sentry/minimal': 6.19.7 + axios: 1.8.2 + inversify: 7.5.1(reflect-metadata@0.2.2) + isomorphic-ws: 5.0.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + purify-ts: 2.1.0 + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + semver: 7.7.2 + url: 0.11.4 + uuid: 11.0.3 + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + xstate: 5.19.2 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@ledgerhq/device-signer-kit-ethereum@1.8.0(@ledgerhq/context-module@1.8.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + dependencies: + '@ledgerhq/context-module': 1.8.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@ledgerhq/device-management-kit': 0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10) + '@ledgerhq/signer-utils': 1.1.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10)) + ethers: 6.14.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) + inversify: 7.5.1(reflect-metadata@0.2.2) + purify-ts: 2.1.0 + reflect-metadata: 0.2.2 + semver: 7.7.2 + xstate: 5.19.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@ledgerhq/device-transport-kit-web-hid@1.2.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))(rxjs@7.8.2)': + dependencies: + '@ledgerhq/device-management-kit': 0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10) + '@sentry/minimal': 6.19.7 + purify-ts: 2.1.0 + rxjs: 7.8.2 + uuid: 11.0.3 + + '@ledgerhq/signer-utils@1.1.0(@ledgerhq/device-management-kit@0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10))': + dependencies: + '@ledgerhq/device-management-kit': 0.9.1(bufferutil@4.0.9)(rxjs@7.8.2)(utf-8-validate@5.0.10) + '@lit-labs/ssr-dom-shim@1.3.0': {} '@lit/reactive-element@1.6.3': @@ -15987,14 +16234,14 @@ snapshots: '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -16076,7 +16323,7 @@ snapshots: bufferutil: 4.0.9 cross-fetch: 4.1.0 date-fns: 2.30.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) eciesjs: 0.4.15 eventemitter2: 6.4.9 readable-stream: 3.6.2 @@ -16092,7 +16339,7 @@ snapshots: '@metamask/sdk@0.32.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)': dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@metamask/onboarding': 1.0.1 '@metamask/providers': 16.1.0 '@metamask/sdk-communication-layer': 0.32.0(cross-fetch@4.1.0)(eciesjs@0.4.15)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -16100,7 +16347,7 @@ snapshots: '@paulmillr/qr': 0.2.1 bowser: 2.11.0 cross-fetch: 4.1.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) eciesjs: 0.4.15 eth-rpc-errors: 4.0.3 eventemitter2: 6.4.9 @@ -16123,7 +16370,7 @@ snapshots: dependencies: '@ethereumjs/tx': 4.2.0 '@types/debug': 4.1.12 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) semver: 7.7.3 superstruct: 1.0.4 transitivePeerDependencies: @@ -16136,9 +16383,9 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) pony-cause: 2.1.11 - semver: 7.7.2 + semver: 7.7.3 uuid: 9.0.1 transitivePeerDependencies: - supports-color @@ -16150,7 +16397,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.12 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) pony-cause: 2.1.11 semver: 7.7.3 uuid: 9.0.1 @@ -16162,7 +16409,7 @@ snapshots: '@metaplex-foundation/beet': 0.7.1 '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) bs58: 5.0.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - bufferutil - encoding @@ -16175,7 +16422,7 @@ snapshots: '@metaplex-foundation/beet': 0.7.1 '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) bs58: 5.0.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - bufferutil - encoding @@ -16188,7 +16435,7 @@ snapshots: '@metaplex-foundation/beet': 0.7.1 '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) bs58: 5.0.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - bufferutil - encoding @@ -16200,7 +16447,7 @@ snapshots: dependencies: ansicolors: 0.3.2 bn.js: 5.2.2 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -16208,7 +16455,7 @@ snapshots: dependencies: ansicolors: 0.3.2 bn.js: 5.2.2 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -16216,7 +16463,7 @@ snapshots: dependencies: ansicolors: 0.3.2 bn.js: 5.2.2 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -16241,7 +16488,7 @@ snapshots: bn.js: 5.2.2 bs58: 5.0.0 buffer: 6.0.3 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 eventemitter3: 4.0.7 lodash.clonedeep: 4.5.0 lodash.isequal: 4.5.0 @@ -16343,7 +16590,7 @@ snapshots: '@solana/spl-token': 0.3.11(@solana/web3.js@1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10) bn.js: 5.2.2 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - bufferutil - encoding @@ -17169,12 +17416,12 @@ snapshots: '@rc-component/async-validator@5.0.4': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/color-picker@2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@ant-design/fast-color': 2.0.6 - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -17182,18 +17429,18 @@ snapshots: '@rc-component/context@1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) '@rc-component/mini-decimal@1.1.0': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/mutate-observer@1.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -17209,7 +17456,7 @@ snapshots: '@rc-component/qrcode@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -17217,7 +17464,7 @@ snapshots: '@rc-component/tour@1.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@rc-component/trigger': 2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 @@ -17227,7 +17474,7 @@ snapshots: '@rc-component/trigger@1.18.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17238,7 +17485,7 @@ snapshots: '@rc-component/trigger@2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17863,6 +18110,25 @@ snapshots: domhandler: 5.0.3 selderee: 0.11.0 + '@sentry/hub@6.19.7': + dependencies: + '@sentry/types': 6.19.7 + '@sentry/utils': 6.19.7 + tslib: 1.14.1 + + '@sentry/minimal@6.19.7': + dependencies: + '@sentry/hub': 6.19.7 + '@sentry/types': 6.19.7 + tslib: 1.14.1 + + '@sentry/types@6.19.7': {} + + '@sentry/utils@6.19.7': + dependencies: + '@sentry/types': 6.19.7 + tslib: 1.14.1 + '@sinclair/typebox@0.27.8': {} '@sinonjs/commons@3.0.1': @@ -19078,12 +19344,12 @@ snapshots: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 natural-compare-lite: 1.4.0 - semver: 7.7.2 + semver: 7.7.3 tsutils: 3.21.0(typescript@5.8.3) optionalDependencies: typescript: 5.8.3 @@ -19095,7 +19361,7 @@ snapshots: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.3) - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) eslint: 8.57.1 optionalDependencies: typescript: 5.8.3 @@ -19111,7 +19377,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.3) '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.8.3) - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) eslint: 8.57.1 tsutils: 3.21.0(typescript@5.8.3) optionalDependencies: @@ -19125,10 +19391,10 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.7.2 + semver: 7.7.3 tsutils: 3.21.0(typescript@5.8.3) optionalDependencies: typescript: 5.8.3 @@ -19145,7 +19411,7 @@ snapshots: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.3) eslint: 8.57.1 eslint-scope: 5.1.1 - semver: 7.7.2 + semver: 7.7.3 transitivePeerDependencies: - supports-color - typescript @@ -19418,7 +19684,7 @@ snapshots: '@umijs/es-module-parser-win32-arm64-msvc': 0.0.7 '@umijs/es-module-parser-win32-x64-msvc': 0.0.7 - '@umijs/fabric@4.0.1(postcss@8.5.3)': + '@umijs/fabric@4.0.1(postcss@8.5.6)': dependencies: '@babel/core': 7.27.1 '@babel/eslint-parser': 7.27.1(@babel/core@7.27.1)(eslint@8.57.1) @@ -19440,7 +19706,7 @@ snapshots: eslint-plugin-unicorn: 47.0.0(eslint@8.57.1) fast-glob: 3.3.3 os-locale: 5.0.0 - postcss-less: 6.0.0(postcss@8.5.3) + postcss-less: 6.0.0(postcss@8.5.6) prettier: 2.8.8 prettier-plugin-organize-imports: 3.2.4(prettier@2.8.8)(typescript@5.8.3) prettier-plugin-two-style-order: 1.0.1(prettier@2.8.8) @@ -19531,7 +19797,7 @@ snapshots: react-refresh: 0.14.2 resolve: 1.22.10 sass-loader: 16.0.5(sass@1.89.0)(webpack@5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17))) - semver: 7.7.2 + semver: 7.7.3 yargs-parser: 21.1.1 optionalDependencies: '@umijs/mako-darwin-arm64': 0.11.10 @@ -19793,7 +20059,7 @@ snapshots: '@utoo/style-loader': 1.0.1 less: 4.4.0 less-loader: 12.3.0(less@4.4.0)(webpack@5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17))) - loader-runner: 4.3.0 + loader-runner: 4.3.1 nanoid: 3.3.11 picocolors: 1.1.1 postcss: 8.4.31 @@ -19877,7 +20143,7 @@ snapshots: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 ast-v8-to-istanbul: 0.3.3 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -22010,7 +22276,15 @@ snapshots: axios@0.27.2(debug@4.4.1): dependencies: follow-redirects: 1.15.9(debug@4.4.1) - form-data: 4.0.0 + form-data: 4.0.2 + transitivePeerDependencies: + - debug + + axios@1.8.2: + dependencies: + follow-redirects: 1.15.9(debug@4.4.1) + form-data: 4.0.2 + proxy-from-env: 1.1.0 transitivePeerDependencies: - debug @@ -22926,7 +23200,7 @@ snapshots: postcss-modules-scope: 3.2.1(postcss@8.5.3) postcss-modules-values: 4.0.0(postcss@8.5.3) postcss-value-parser: 4.2.0 - semver: 7.7.2 + semver: 7.7.3 webpack: 5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17)) css-prefers-color-scheme@6.0.3(postcss@8.5.3): @@ -23084,7 +23358,7 @@ snapshots: date-fns@2.30.0: dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 dayjs@1.11.13: {} @@ -23102,15 +23376,15 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.1(supports-color@5.5.0): + debug@4.4.1: dependencies: ms: 2.1.3 - optionalDependencies: - supports-color: 5.5.0 - debug@4.4.3: + debug@4.4.3(supports-color@5.5.0): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 5.5.0 decamelize-keys@1.1.1: dependencies: @@ -23931,7 +24205,7 @@ snapshots: regexp-tree: 0.1.27 regjsparser: 0.10.0 safe-regex: 2.1.1 - semver: 7.7.2 + semver: 7.7.3 strip-indent: 3.0.0 eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1): @@ -23971,7 +24245,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -24031,7 +24305,7 @@ snapshots: dependencies: '@types/estree-jsx': 1.0.5 astring: 1.9.0 - source-map: 0.7.4 + source-map: 0.7.6 estree-util-visit@1.2.1: dependencies: @@ -24510,7 +24784,7 @@ snapshots: follow-redirects@1.15.9(debug@4.4.1): optionalDependencies: - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 for-each@0.3.5: dependencies: @@ -24533,7 +24807,7 @@ snapshots: minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.3.0 - semver: 7.7.2 + semver: 7.7.3 tapable: 2.2.2 typescript: 5.4.2 webpack: 5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17)) @@ -24550,7 +24824,7 @@ snapshots: minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.3.0 - semver: 7.7.2 + semver: 7.7.3 tapable: 2.2.2 typescript: 5.8.3 webpack: 5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17)) @@ -25126,7 +25400,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -25135,7 +25409,7 @@ snapshots: https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -25258,6 +25532,13 @@ snapshots: dependencies: loose-envify: 1.4.0 + inversify@7.5.1(reflect-metadata@0.2.2): + dependencies: + '@inversifyjs/common': 1.5.0 + '@inversifyjs/container': 1.9.1(reflect-metadata@0.2.2) + '@inversifyjs/core': 5.2.0(reflect-metadata@0.2.2) + reflect-metadata: 0.2.2 + invert-kv@3.0.1: {} ipaddr.js@1.9.1: {} @@ -25538,6 +25819,10 @@ snapshots: dependencies: ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) + isomorphic-ws@5.0.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)): + dependencies: + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + isows@1.0.3(ws@8.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: ws: 8.13.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -25571,7 +25856,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -25971,7 +26256,7 @@ snapshots: dependencies: chalk: 5.4.1 commander: 14.0.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 lilconfig: 3.1.3 listr2: 8.3.3 micromatch: 4.0.8 @@ -26133,7 +26418,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 make-error@1.3.6: {} @@ -26320,7 +26605,7 @@ snapshots: media-query-parser@2.0.2: dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 media-typer@0.3.0: {} @@ -26417,7 +26702,7 @@ snapshots: metro-file-map@0.82.5: dependencies: - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) fb-watchman: 2.0.2 flow-enums-runtime: 0.0.6 graceful-fs: 4.2.11 @@ -26513,7 +26798,7 @@ snapshots: chalk: 4.1.2 ci-info: 2.0.0 connect: 3.7.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@5.5.0) error-stack-parser: 2.1.4 flow-enums-runtime: 0.0.6 graceful-fs: 4.2.11 @@ -26738,7 +27023,7 @@ snapshots: micromark@3.2.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) decode-named-character-reference: 1.1.0 micromark-core-commonmark: 1.1.0 micromark-factory-space: 1.1.0 @@ -27009,7 +27294,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.1 - semver: 7.7.2 + semver: 7.7.3 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -27659,16 +27944,16 @@ snapshots: dependencies: postcss: 8.5.6 - postcss-less@6.0.0(postcss@8.5.3): + postcss-less@6.0.0(postcss@8.5.6): dependencies: - postcss: 8.5.3 + postcss: 8.5.6 postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.8.3)(webpack@5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17))): dependencies: cosmiconfig: 9.0.0(typescript@5.8.3) jiti: 1.21.7 postcss: 8.5.3 - semver: 7.7.2 + semver: 7.7.3 optionalDependencies: webpack: 5.99.9(@swc/core@1.9.2(@swc/helpers@0.5.17)) transitivePeerDependencies: @@ -27884,9 +28169,9 @@ snapshots: postcss-resolve-nested-selector@0.1.6: {} - postcss-safe-parser@6.0.0(postcss@8.5.3): + postcss-safe-parser@6.0.0(postcss@8.5.6): dependencies: - postcss: 8.5.3 + postcss: 8.5.6 postcss-selector-not@5.0.0(postcss@8.5.3): dependencies: @@ -27908,10 +28193,10 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-sorting@6.0.0(postcss@8.5.3): + postcss-sorting@6.0.0(postcss@8.5.6): dependencies: lodash: 4.17.21 - postcss: 8.5.3 + postcss: 8.5.6 postcss-syntax@0.36.2(postcss@8.5.3): dependencies: @@ -27962,9 +28247,9 @@ snapshots: prettier-plugin-two-style-order@1.0.1(prettier@2.8.8): dependencies: - postcss: 8.5.3 + postcss: 8.5.6 postcss-less: 4.0.1 - postcss-sorting: 6.0.0(postcss@8.5.3) + postcss-sorting: 6.0.0(postcss@8.5.6) prettier: 2.8.8 prettier@2.8.8: {} @@ -28063,6 +28348,10 @@ snapshots: punycode@2.3.1: {} + purify-ts@2.1.0: + dependencies: + '@types/json-schema': 7.0.15 + q@1.5.1: {} qrcode@1.5.3: @@ -28146,7 +28435,7 @@ snapshots: rc-cascader@3.34.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-select: 14.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-tree: 5.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28156,7 +28445,7 @@ snapshots: rc-checkbox@3.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28164,7 +28453,7 @@ snapshots: rc-collapse@3.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28173,7 +28462,7 @@ snapshots: rc-dialog@9.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28193,7 +28482,7 @@ snapshots: rc-drawer@7.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28203,7 +28492,7 @@ snapshots: rc-dropdown@4.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 1.18.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28212,7 +28501,7 @@ snapshots: rc-dropdown@4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28221,7 +28510,7 @@ snapshots: rc-field-form@2.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/async-validator': 5.0.4 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28236,7 +28525,7 @@ snapshots: rc-image@7.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/portal': 1.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-dialog: 9.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28247,7 +28536,7 @@ snapshots: rc-input-number@9.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/mini-decimal': 1.1.0 classnames: 2.5.1 rc-input: 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28257,7 +28546,7 @@ snapshots: rc-input@1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28265,7 +28554,7 @@ snapshots: rc-mentions@2.20.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-input: 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28277,7 +28566,7 @@ snapshots: rc-menu@9.12.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 1.18.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28288,7 +28577,7 @@ snapshots: rc-menu@9.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28299,7 +28588,7 @@ snapshots: rc-motion@2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28307,7 +28596,7 @@ snapshots: rc-notification@5.6.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28316,7 +28605,7 @@ snapshots: rc-overflow@1.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28325,7 +28614,7 @@ snapshots: rc-pagination@5.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28333,7 +28622,7 @@ snapshots: rc-picker@4.11.3(date-fns@2.30.0)(dayjs@1.11.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-overflow: 1.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28347,7 +28636,7 @@ snapshots: rc-progress@4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28355,7 +28644,7 @@ snapshots: rc-rate@2.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28363,7 +28652,7 @@ snapshots: rc-resize-observer@1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28372,7 +28661,7 @@ snapshots: rc-segmented@2.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28381,7 +28670,7 @@ snapshots: rc-select@14.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28393,7 +28682,7 @@ snapshots: rc-slider@11.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28401,7 +28690,7 @@ snapshots: rc-steps@6.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28409,7 +28698,7 @@ snapshots: rc-switch@4.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28417,7 +28706,7 @@ snapshots: rc-table@7.50.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/context': 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28428,7 +28717,7 @@ snapshots: rc-tabs@12.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-dropdown: 4.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-menu: 9.12.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28440,7 +28729,7 @@ snapshots: rc-tabs@15.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-dropdown: 4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-menu: 9.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28452,7 +28741,7 @@ snapshots: rc-textarea@1.10.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-input: 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28462,7 +28751,7 @@ snapshots: rc-tooltip@6.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 '@rc-component/trigger': 2.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28471,7 +28760,7 @@ snapshots: rc-tree-select@5.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-select: 14.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-tree: 5.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28481,7 +28770,7 @@ snapshots: rc-tree@5.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-motion: 2.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28491,7 +28780,7 @@ snapshots: rc-upload@4.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -28513,7 +28802,7 @@ snapshots: rc-virtual-list@3.18.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 classnames: 2.5.1 rc-resize-observer: 1.4.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rc-util: 5.44.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -28547,7 +28836,7 @@ snapshots: react-error-boundary@4.1.2(react@18.3.1): dependencies: - '@babel/runtime': 7.27.1 + '@babel/runtime': 7.28.4 react: 18.3.1 react-error-overlay@6.0.9: {} @@ -28781,6 +29070,8 @@ snapshots: indent-string: 5.0.0 strip-indent: 4.0.0 + reflect-metadata@0.2.2: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -29448,7 +29739,7 @@ snapshots: spdy-transport@3.0.0: dependencies: - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -29459,7 +29750,7 @@ snapshots: spdy@4.0.2: dependencies: - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -29723,7 +30014,7 @@ snapshots: cosmiconfig: 8.3.6(typescript@5.8.3) css-functions-list: 3.2.3 css-tree: 2.3.1 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.3(supports-color@5.5.0) fast-glob: 3.3.3 fastest-levenshtein: 1.0.16 file-entry-cache: 7.0.2 @@ -29741,9 +30032,9 @@ snapshots: micromatch: 4.0.8 normalize-path: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.3 + postcss: 8.5.6 postcss-resolve-nested-selector: 0.1.6 - postcss-safe-parser: 6.0.0(postcss@8.5.3) + postcss-safe-parser: 6.0.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 @@ -30481,6 +30772,8 @@ snapshots: utils-merge@1.0.1: {} + uuid@11.0.3: {} + uuid@8.3.2: {} uuid@9.0.1: {} @@ -30637,7 +30930,7 @@ snapshots: vite-node@3.1.4(@types/node@22.15.21)(jiti@1.21.7)(less@4.4.0)(lightningcss@1.22.1)(sass@1.89.0)(terser@5.44.0)(yaml@2.8.0): dependencies: cac: 6.7.14 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 6.3.5(@types/node@22.15.21)(jiti@1.21.7)(less@4.4.0)(lightningcss@1.22.1)(sass@1.89.0)(terser@5.44.0)(yaml@2.8.0) @@ -30720,7 +31013,7 @@ snapshots: '@vitest/spy': 3.1.4 '@vitest/utils': 3.1.4 chai: 5.2.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 @@ -31269,6 +31562,8 @@ snapshots: xmlhttprequest-ssl@2.1.2: {} + xstate@5.19.2: {} + xtend@2.1.2: dependencies: object-keys: 0.4.0 From 0116b2eb3b5ca0fa2d4ab4493f33d81ba28a3c23 Mon Sep 17 00:00:00 2001 From: Jeason Date: Tue, 14 Oct 2025 16:26:23 +0800 Subject: [PATCH 2/4] docs: add copilot instructions --- .github/copilot-instructions.md | 158 ++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..4a1dc1c17 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,158 @@ +# Ant Design Web3 - AI Coding Agent Instructions + +## Project Overview + +Ant Design Web3 is a multi-chain Web3 React component library built on Ant Design, providing UI components and blockchain adapters for building DApps. The architecture separates UI (`@ant-design/web3`) from blockchain-specific adapters (wagmi, ethers, solana, bitcoin, sui, ton, tron). + +**Key architectural principle**: UI components are pure React components that consume blockchain capabilities through `Web3ConfigProvider` context, while adapter packages bridge UI and chain SDKs. + +## Monorepo Structure + +This is a pnpm workspace with packages organized by function: + +- `packages/web3/` - Core UI components (ConnectButton, Address, NFTCard, etc.) +- `packages/common/` - Shared types, utilities, and base Web3ConfigProvider +- `packages/wagmi/` - Ethereum adapter using wagmi v2 +- `packages/ethers/` - Ethereum adapter using ethers v6 +- `packages/solana/`, `packages/bitcoin/`, `packages/sui/`, etc. - Chain-specific adapters +- `packages/icons/` - Blockchain and wallet icon components (auto-generated) +- `packages/assets/` - Chain and token metadata + +**Docs location**: All component docs live in `packages/web3/*/index.md` and `*.zh-CN.md`, NOT in the package's own directory (except wagmi docs are in `packages/web3/ethereum/`). + +## Critical Workflows + +### Development + +```bash +pnpm start # Start dumi dev server (docs + demos) +pnpm dev:lib # Run father dev for all packages in watch mode +pnpm build # Build all packages (required before testing dist) +``` + +### Testing + +- Framework: Vitest with jsdom +- Tests: Located in `packages/*/src/**/__tests__/*.test.{ts,tsx}` +- Commands: + ```bash + pnpm test # Run tests in watch mode + pnpm test:ci # Run tests with coverage (CI mode) + pnpm test:dist # Test against built dist files + ``` +- **Coverage requirement**: 100% coverage expected + +### Build System + +- Uses `father` (not Rollup/Webpack) for package building +- Config: `.fatherrc.base.ts` defines babel transforms with SVG inlining +- Each package has `.fatherrc.ts` extending the base config +- Outputs both ESM (`dist/esm/`) and CJS (`dist/lib/`) + +### Version Management + +**Always run `pnpm changeset` before submitting PRs that change package code** (docs-only PRs exempt). + +- Uses changesets for version management +- Command: `pnpm changeset` to add changelog entry +- Files generated in `.changeset/` directory +- Release process handled by core maintainers via `pnpm run release` + +## Code Conventions + +### Styling + +- CSS-in-JS via `@ant-design/cssinjs` with Ant Design tokens +- Styles in `packages/web3/*/style/index.{ts,tsx}` (not co-located with components) +- Use Design Tokens for themability - never hardcode colors/spacing + +### TypeScript Patterns + +- Strict mode enabled +- Types exported from `@ant-design/web3-common` for cross-package sharing +- Key interfaces: `UniversalWeb3ProviderInterface`, `Wallet`, `Chain`, `Account` +- Use `React.FC>` for components with children + +### Adapter Pattern + +Adapters implement blockchain connectivity by: + +1. Creating a chain-specific `Web3ConfigProvider` wrapper (e.g., `WagmiWeb3ConfigProvider`) +2. Internally using the chain's SDK (wagmi, @solana/wallet-adapter-react, etc.) +3. Mapping chain SDK state to `UniversalWeb3ProviderInterface` props +4. Passing mapped props to `@ant-design/web3-common`'s base `Web3ConfigProvider` + +**Example**: `packages/wagmi/src/wagmi-provider/index.tsx` wraps `WagmiProvider` and `QueryClientProvider`, then maps wagmi hooks to `UniversalWeb3ProviderInterface`. + +### Component Patterns + +- UI components use `useProvider()` hook to access blockchain context +- Provider props: `account`, `chain`, `balance`, `connect()`, `disconnect()`, `switchChain()`, etc. +- Props can be overridden at component level (merged with context via `useProvider(props)`) +- Components should handle both connected and disconnected states gracefully + +## Code Quality + +- Linter: Biome (not ESLint for most checks) +- Format: `pnpm biome:format` or `pnpm prettier` +- Run `pnpm lint` before committing +- Pre-commit: Husky + lint-staged auto-formats staged files + +## Common Tasks + +### Adding a new UI component + +1. Create in `packages/web3/src/your-component/` +2. Add styles in `packages/web3/src/your-component/style/index.tsx` +3. Add demos in `packages/web3/src/your-component/demos/*.tsx` +4. Create docs: `packages/web3/src/your-component/index.md` and `index.zh-CN.md` +5. Export from `packages/web3/src/index.ts` +6. Add tests in `__tests__/` directory + +### Adding wallet/chain metadata + +- Wallets: `packages/assets/src/wallets/` - Follow existing pattern +- Chains: `packages/assets/src/chains/` - Export from appropriate file +- Tokens: `packages/assets/src/tokens/` - Use `Token` type from common + +### Generating icons + +Icons are auto-generated. Don't manually edit files in `packages/icons/src/components/`: + +```bash +pnpm icons:generate +``` + +## Testing Patterns + +- Mock blockchain providers in tests - see `packages/solana/src/solana-provider/__tests__/` for examples +- Use `vi.mock()` to mock SDK modules like `@solana/wallet-adapter-react` +- Test both component rendering and blockchain interaction logic +- Snapshot tests for UI components are acceptable but prefer behavioral tests + +## Path Aliases + +When importing cross-package code, use aliases defined in `tsconfig.base.json`: + +```typescript +import { Address } from '@ant-design/web3'; +import { Web3ConfigProvider } from '@ant-design/web3-common'; +import { WagmiWeb3ConfigProvider } from '@ant-design/web3-wagmi'; +``` + +These resolve to `src/` in dev and `dist/esm/` in builds. + +## Documentation + +- Framework: Dumi v2 with custom theme (`dumi-theme-antd-web3`) +- Demos are live code - use `` in markdown +- Both English and Chinese docs required for new features +- Course content in `docs/course/` for educational materials + +## Common Pitfalls + +- Don't put component docs in package root - they belong in `packages/web3/` +- Don't skip changesets for code changes +- Don't hardcode chain IDs - use enums from `@ant-design/web3-common` +- Don't test against source when `LIB_DIR=dist` - vitest config handles aliasing +- Remember wagmi docs live under `packages/web3/ethereum/` not `packages/wagmi/` From 1ae0048c7b084c9e71015e403f96107a581b82e2 Mon Sep 17 00:00:00 2001 From: Jeason Date: Tue, 14 Oct 2025 18:14:20 +0800 Subject: [PATCH 3/4] chore: apply suggestions from code review by github copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/ledger/src/provider/index.tsx | 7 ++++--- packages/ledger/src/types.ts | 6 +++--- packages/ledger/src/wallets/ledger.tsx | 7 ++----- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/ledger/src/provider/index.tsx b/packages/ledger/src/provider/index.tsx index b9611f4a8..43d40862c 100644 --- a/packages/ledger/src/provider/index.tsx +++ b/packages/ledger/src/provider/index.tsx @@ -42,9 +42,10 @@ export const LedgerWeb3ConfigProvider: FC w.name === wallet.name); const provider = walletWithAdapter?.adapter; await provider?.connect(); - // @ts-ignore provider is not undefined - setAdapter(provider); - cacheSelectedWallet(wallet.name); + if (provider) { + setAdapter(provider); + cacheSelectedWallet(wallet.name); + } }; // auto connect diff --git a/packages/ledger/src/types.ts b/packages/ledger/src/types.ts index 004231b80..db5fbbd56 100644 --- a/packages/ledger/src/types.ts +++ b/packages/ledger/src/types.ts @@ -10,9 +10,9 @@ export interface LedgerWallet { connect: () => Promise; disconnect: () => Promise; signMessage?: (message: string) => Promise; - signTypedData?: (typedData: any) => Promise; - _setupHooks?: (hooks: any) => void; - useLedgerHooks?: () => any; + signTypedData?: (typedData: unknown) => Promise; + _setupHooks?: (hooks: LedgerHooks) => void; + useLedgerHooks?: () => LedgerHooksResult; } export interface WalletFactory { diff --git a/packages/ledger/src/wallets/ledger.tsx b/packages/ledger/src/wallets/ledger.tsx index 0a02487f0..11584c621 100644 --- a/packages/ledger/src/wallets/ledger.tsx +++ b/packages/ledger/src/wallets/ledger.tsx @@ -13,10 +13,10 @@ import type { LedgerAccount, LedgerWallet, WalletFactory } from '../types'; export const Ledger = (): WalletFactory => { return { name: 'Ledger', - create: () => { + create: (options?: { derivationPath?: string }) => { let sessionId: DeviceSessionId | null = null; let currentAddress: string | null = null; - let derivationPath = "44'/60'/0'/0/0"; + let derivationPath = options?.derivationPath ?? "44'/60'/0'/0/0"; // These will be set up when the wallet is used in a React component let devicesRef: DiscoveredDevice[] = []; @@ -34,7 +34,6 @@ export const Ledger = (): WalletFactory => { accounts: [] as LedgerAccount[], connect: async () => { - console.log('Connecting to Ledger...'); // Wait for device to be available if (devicesRef.length === 0) { @@ -88,7 +87,6 @@ export const Ledger = (): WalletFactory => { }, disconnect: async () => { - console.log('Disconnecting from Ledger...'); if (disconnectFn && sessionId) { await disconnectFn(sessionId); @@ -110,7 +108,6 @@ export const Ledger = (): WalletFactory => { }, signTypedData: async (typedData: any) => { - console.log('Signing typed data:', typedData); if (!signTypedDataFn) { throw new Error('Sign typed data function not available'); From cdff3b87d66febd55cffadc0b7196f071ba7ce73 Mon Sep 17 00:00:00 2001 From: Jeason Date: Wed, 15 Oct 2025 13:51:33 +0800 Subject: [PATCH 4/4] chore: add agents for repo --- .github/copilot-instructions.md => AGENTS.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/copilot-instructions.md => AGENTS.md (100%) diff --git a/.github/copilot-instructions.md b/AGENTS.md similarity index 100% rename from .github/copilot-instructions.md rename to AGENTS.md