# 6. 常见问题

### 错误代码与调试工具

#### 常见错误代码

```javascript
// JuCoin钱包错误代码对照表
const ERROR_CODES = {
    // 标准错误码
    4001: {
        message: "User rejected the request",
        description: "用户拒绝了请求",
        solution: "请引导用户重新发起请求并确认"
    },
    4100: {
        message: "The requested account and/or method has not been authorized",
        description: "账户或方法未授权",
        solution: "先调用 eth_requestAccounts 获取授权"
    },
    4200: {
        message: "The requested method is not supported",
        description: "不支持的方法",
        solution: "检查方法名称是否正确，查看API文档"
    },
    4900: {
        message: "The provider is disconnected",
        description: "Provider已断开连接",
        solution: "检查网络连接，重新连接钱包"
    },
    4901: {
        message: "The provider is disconnected from the specified chain",
        description: "与指定链断开连接",
        solution: "切换到正确的网络"
    },
    
    // JSON-RPC错误码
    "-32700": {
        message: "Parse error",
        description: "JSON解析错误",
        solution: "检查请求参数格式"
    },
    "-32600": {
        message: "Invalid request",
        description: "无效请求",
        solution: "检查请求结构是否符合JSON-RPC规范"
    },
    "-32601": {
        message: "Method not found",
        description: "方法不存在",
        solution: "检查方法名拼写"
    },
    "-32602": {
        message: "Invalid params",
        description: "无效参数",
        solution: "检查参数类型和格式"
    },
    "-32603": {
        message: "Internal error",
        description: "内部错误",
        solution: "重试请求，如持续出现请联系支持"
    },
    "-32000": {
        message: "Invalid input",
        description: "无效输入",
        solution: "检查交易数据格式"
    },
    "-32001": {
        message: "Resource not found",
        description: "资源未找到",
        solution: "确认地址或交易哈希是否正确"
    },
    "-32002": {
        message: "Resource unavailable",
        description: "资源不可用",
        solution: "请求可能已在处理中，检查钱包弹窗"
    },
    "-32003": {
        message: "Transaction rejected",
        description: "交易被拒绝",
        solution: "检查交易参数，如gas价格、余额等"
    },
    "-32005": {
        message: "Method not supported",
        description: "方法不支持",
        solution: "该方法在当前版本不可用"
    }
};
```

#### 调试工具

```javascript
// JuCoin调试助手
class JuCoinDebugger {
    constructor() {
        this.logs = [];
        this.enabled = localStorage.getItem('jucoin_debug') === 'true';
    }
    
    // 启用/禁用调试模式
    toggle() {
        this.enabled = !this.enabled;
        localStorage.setItem('jucoin_debug', this.enabled);
        console.log(`JuCoin调试模式: ${this.enabled ? '开启' : '关闭'}`);
    }
    
    // 拦截并记录所有请求
    interceptRequests() {
        const originalRequest = window.jcEthereum.request;
        
        window.jcEthereum.request = async (args) => {
            const startTime = Date.now();
            const requestId = Math.random().toString(36).substring(7);
            
            if (this.enabled) {
                console.group(`🔵 JuCoin Request [${requestId}]`);
                console.log('Method:', args.method);
                console.log('Params:', args.params);
                console.groupEnd();
            }
            
            try {
                const result = await originalRequest.call(window.jucoin, args);
                
                if (this.enabled) {
                    console.group(`✅ JuCoin Response [${requestId}]`);
                    console.log('Duration:', Date.now() - startTime + 'ms');
                    console.log('Result:', result);
                    console.groupEnd();
                }
                
                this.logs.push({
                    id: requestId,
                    timestamp: startTime,
                    duration: Date.now() - startTime,
                    request: args,
                    response: result,
                    status: 'success'
                });
                
                return result;
            } catch (error) {
                if (this.enabled) {
                    console.group(`❌ JuCoin Error [${requestId}]`);
                    console.log('Duration:', Date.now() - startTime + 'ms');
                    console.log('Error:', error);
                    console.log('Error Code:', error.code);
                    console.log('Solution:', ERROR_CODES[error.code]?.solution);
                    console.groupEnd();
                }
                
                this.logs.push({
                    id: requestId,
                    timestamp: startTime,
                    duration: Date.now() - startTime,
                    request: args,
                    error: error,
                    status: 'error'
                });
                
                throw error;
            }
        };
    }
    
    // 导出调试日志
    exportLogs() {
        const data = JSON.stringify(this.logs, null, 2);
        const blob = new Blob([data], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `jucoin-debug-${Date.now()}.json`;
        a.click();
    }
    
    // 清除日志
    clearLogs() {
        this.logs = [];
        console.log('调试日志已清除');
    }
}

// 使用示例
const debugger = new JuCoinDebugger();
debugger.toggle(); // 开启调试
debugger.interceptRequests(); // 开始拦截请求
```

#### 快速诊断工具

```javascript
// 环境检测
async function diagnoseEnvironment() {
    const diagnosis = {
        wallet: {
            installed: !!window.jcEthereum,
            version: window.jcEthereum?.version,
            isConnected: window.jcEthereum?.isConnected()
        },
        network: null,
        account: null,
        permissions: null
    };
    
    if (window.jucoin) {
        try {
            diagnosis.network = await window.jcEthereum.request({
                method: 'eth_chainId'
            });
            
            diagnosis.account = await window.jcEthereum.request({
                method: 'eth_accounts'
            });
            
            diagnosis.permissions = await window.jcEthereum.request({
                method: 'wallet_getPermissions'
            });
        } catch (error) {
            console.error('诊断过程中出错:', error);
        }
    }
    
    console.table(diagnosis);
    return diagnosis;
}
```

### 兼容性说明

#### 浏览器兼容性

```javascript
// 支持的浏览器及版本
const BROWSER_SUPPORT = {
    Chrome: '90+',
    Firefox: '89+',
    Edge: '90+',
    Safari: '14+',
    Brave: '1.25+',
    Opera: '76+'
};

// 浏览器检测
function checkBrowserCompatibility() {
    const ua = navigator.userAgent;
    const browser = {
        chrome: /Chrome\/(\d+)/.test(ua),
        firefox: /Firefox\/(\d+)/.test(ua),
        safari: /Safari\/(\d+)/.test(ua) && !/Chrome/.test(ua),
        edge: /Edg\/(\d+)/.test(ua)
    };
    
    // 检查是否支持必要的Web API
    const requiredAPIs = {
        'Web Crypto API': typeof crypto !== 'undefined',
        'IndexedDB': 'indexedDB' in window,
        'Web Storage': 'localStorage' in window,
        'Promises': typeof Promise !== 'undefined',
        'Async/Await': (async () => {})().constructor.name === 'AsyncFunction'
    };
    
    return {
        browser,
        apis: requiredAPIs,
        compatible: Object.values(requiredAPIs).every(v => v)
    };
}
```

#### MetaMask兼容模式

```javascript
// JuCoin提供MetaMask兼容模式
class MetaMaskCompatibility {
    static enable() {
        // 将jucoin对象也绑定到ethereum
        if (window.jucoin && !window.ethereum) {
            window.ethereum = window.jcEthereum;
            window.ethereum.isMetaMask = true; // 兼容性标记
            console.log('MetaMask兼容模式已启用');
        }
    }
    
    static detectWallet() {
        // 优先使用JuCoin
        if (window.jcEthereum) {
            return {
                type: 'JuCoin',
                provider: window.jcEthereum
            };
        }
        
        // 检查其他钱包
        if (window.ethereum) {
            if (window.ethereum.isMetaMask) {
                return {
                    type: 'MetaMask',
                    provider: window.ethereum
                };
            }
            
            return {
                type: 'Unknown',
                provider: window.ethereum
            };
        }
        
        return null;
    }
}
```

### 迁移指南

#### 从MetaMask迁移

```javascript
// MetaMask到JuCoin迁移助手
class MigrationHelper {
    // 1. 检测并切换Provider
    static async migrateProvider() {
        // 原MetaMask代码
        // const provider = window.ethereum;
        
        // 迁移后的代码
        const provider = window.jcEthereum || window.ethereum;
        
        return provider;
    }
    
    // 2. API调用迁移
    static async migrateAPICalls() {
        // MetaMask特有的API映射
        const apiMapping = {
            // MetaMask的ethereum.request已经兼容
            'eth_requestAccounts': 'eth_requestAccounts',
            
            // JuCoin扩展功能
            'metamask_getProviderState': 'jucoin_getProviderState',
            'metamask_watchAsset': 'jucoin_watchAsset',
            
            // 网络切换
            'wallet_switchEthereumChain': 'wallet_switchEthereumChain',
            'wallet_addEthereumChain': 'wallet_addEthereumChain'
        };
        
        return apiMapping;
    }
    
    // 3. 事件监听迁移
    static migrateEventListeners(oldProvider, newProvider) {
        // 获取所有事件监听器
        const events = ['accountsChanged', 'chainChanged', 'disconnect'];
        
        events.forEach(event => {
            const listeners = oldProvider.listeners(event);
            listeners.forEach(listener => {
                newProvider.on(event, listener);
            });
        });
    }
    
    // 4. 完整迁移示例
    static async performMigration() {
        console.log('开始从MetaMask迁移到JuCoin...');
        
        // 检查JuCoin是否已安装
        if (!window.jucoin) {
            console.error('请先安装JuCoin钱包');
            return false;
        }
        
        // 保存MetaMask的数据（如果需要）
        const backup = {
            accounts: await window.ethereum?.request({
                method: 'eth_accounts'
            }),
            chainId: await window.ethereum?.request({
                method: 'eth_chainId'
            })
        };
        
        // 切换到JuCoin
        window.ethereum = window.jcEthereum;
        
        // 恢复连接
        if (backup.accounts?.length > 0) {
            await window.jcEthereum.request({
                method: 'eth_requestAccounts'
            });
        }
        
        console.log('迁移完成！');
        return true;
    }
}
```

#### Web3.js项目迁移

```javascript
// Web3.js兼容层
class Web3Migration {
    static async migrateWeb3() {
        // 原Web3.js代码
        // const web3 = new Web3(window.ethereum);
        
        // 兼容JuCoin的代码
        const provider = window.jcEthereum || window.ethereum;
        const web3 = new Web3(provider);
        
        // 确保provider方法兼容
        if (!provider.send) {
            provider.send = provider.request;
        }
        
        return web3;
    }
    
    // 迁移常用Web3方法
    static getCompatibleMethods() {
        return {
            // 账户相关
            getAccounts: async (web3) => {
                return await web3.eth.getAccounts();
            },
            
            // 交易相关
            sendTransaction: async (web3, tx) => {
                return await web3.eth.sendTransaction(tx);
            },
            
            // 合约相关
            contractCall: async (web3, contract, method, params) => {
                return await contract.methods[method](...params).call();
            },
            
            // 签名相关
            signMessage: async (web3, message, account) => {
                return await web3.eth.personal.sign(message, account);
            }
        };
    }
}
```

#### Ethers.js项目迁移

```javascript
// Ethers.js迁移更简单，因为它使用标准的Provider接口
class EthersMigration {
    static async migrateEthers() {
        // 原Ethers.js代码
        // const provider = new ethers.providers.Web3Provider(window.ethereum);
        
        // 兼容JuCoin的代码
        const provider = new ethers.providers.Web3Provider(
            window.jcEthereum || window.ethereum
        );
        
        return provider;
    }
    
    // 使用示例
    static async example() {
        const provider = await this.migrateEthers();
        const signer = provider.getSigner();
        
        // 所有Ethers.js功能都正常工作
        const address = await signer.getAddress();
        const balance = await provider.getBalance(address);
        
        return { address, balance };
    }
}
```

#### 快速迁移检查清单

```javascript
// 迁移检查清单
const MIGRATION_CHECKLIST = {
    '1. 安装检测': {
        check: () => !!window.jcEthereum,
        fix: '请安装JuCoin钱包扩展'
    },
    '2. Provider切换': {
        check: () => window.ethereum === window.jcEthereum,
        fix: 'window.ethereum = window.jcEthereum'
    },
    '3. API兼容性': {
        check: () => typeof window.jucoin.request === 'function',
        fix: '确保使用request方法调用API'
    },
    '4. 事件监听': {
        check: () => typeof window.jucoin.on === 'function',
        fix: '使用on/off方法替代addListener/removeListener'
    },
    '5. 网络支持': {
        check: async () => {
            const chainId = await window.jcEthereum.request({ method: 'eth_chainId' });
            return ['0x1', '0x38', '0x8956'].includes(chainId);
        },
        fix: '添加所需的网络配置'
    }
};

// 自动检查工具
async function runMigrationCheck() {
    console.log('=== JuCoin迁移检查 ===');
    
    for (const [name, item] of Object.entries(MIGRATION_CHECKLIST)) {
        try {
            const result = await item.check();
            console.log(`${result ? '✅' : '❌'} ${name}`);
            if (!result) {
                console.log(`   修复方法: ${item.fix}`);
            }
        } catch (error) {
            console.log(`❌ ${name}`);
            console.log(`   错误: ${error.message}`);
        }
    }
}
```

#### 版本兼容性对照表

```javascript
// 版本兼容性
const VERSION_COMPATIBILITY = {
    'JuCoin Wallet': {
        '1.0.0': {
            features: ['基础钱包功能', 'ETH/BSC支持'],
            breaking: []
        },
        '1.1.0': {
            features: ['JuChain支持', '批量交易'],
            breaking: []
        },
        '1.2.0': {
            features: ['硬件钱包支持', '高级安全功能'],
            breaking: ['jucoin_batchSendTransactions参数格式变更']
        }
    },
    'Web3.js': {
        '1.x': '完全兼容',
        '4.x': '完全兼容'
    },
    'Ethers.js': {
        '5.x': '完全兼容',
        '6.x': '完全兼容'
    }
};
```

#### 常见迁移问题解决方案

```javascript
// 问题解决方案集合
const MIGRATION_SOLUTIONS = {
    // 问题1: window.ethereum未定义
    ethereumUndefined: {
        problem: 'window.ethereum is undefined',
        solution: `
            // 在应用初始化时添加
            if (window.jucoin && !window.ethereum) {
                window.ethereum = window.jcEthereum;
            }
        `
    },
    
    // 问题2: 事件监听器不工作
    eventListenerNotWorking: {
        problem: '事件监听器迁移后不触发',
        solution: `
            // 确保移除旧监听器并重新添加
            provider.removeAllListeners();
            provider.on('accountsChanged', handleAccountsChanged);
            provider.on('chainChanged', handleChainChanged);
        `
    },
    
    // 问题3: 交易签名失败
    transactionSigningFailed: {
        problem: '交易签名失败或被拒绝',
        solution: `
            // 检查gas参数格式
            const tx = {
                from: account,
                to: recipient,
                value: '0x' + value.toString(16), // 确保是16进制
                gas: '0x' + gasLimit.toString(16),
                gasPrice: '0x' + gasPrice.toString(16)
            };
        `
    },
    
    // 问题4: 网络切换失败
    networkSwitchFailed: {
        problem: '切换网络时出错',
        solution: `
            // 先尝试切换，如果失败则添加网络
            try {
                await provider.request({
                    method: 'wallet_switchEthereumChain',
                    params: [{ chainId: '0x8956' }]
                });
            } catch (error) {
                if (error.code === 4902) {
                    await provider.request({
                        method: 'wallet_addEthereumChain',
                        params: [networkConfig]
                    });
                }
            }
        `
    }
};
```

#### 一键迁移脚本

```javascript
// 一键迁移脚本
async function migrateToJuCoin() {
    console.log('🚀 开始迁移到JuCoin钱包...');
    
    try {
        // 步骤1: 检查环境
        if (!window.jcEthereum) {
            throw new Error('请先安装JuCoin钱包');
        }
        
        // 步骤2: 备份现有配置
        const backup = {
            provider: window.ethereum,
            listeners: {}
        };
        
        // 步骤3: 设置兼容性
        window.ethereum = window.jcEthereum;
        window.ethereum.isMetaMask = true; // 兼容依赖MetaMask的库
        
        // 步骤4: 迁移事件监听
        ['accountsChanged', 'chainChanged', 'disconnect'].forEach(event => {
            const listeners = backup.provider?.listeners?.(event) || [];
            listeners.forEach(listener => {
                window.jucoin.on(event, listener);
            });
        });
        
        // 步骤5: 测试连接
        const accounts = await window.jcEthereum.request({
            method: 'eth_requestAccounts'
        });
        
        // 步骤6: 验证功能
        const chainId = await window.jcEthereum.request({
            method: 'eth_chainId'
        });
        
        console.log('✅ 迁移成功！');
        console.log('- 已连接账户:', accounts[0]);
        console.log('- 当前网络:', chainId);
        console.log('- Provider:', window.ethereum);
        
        return {
            success: true,
            account: accounts[0],
            chainId: chainId
        };
        
    } catch (error) {
        console.error('❌ 迁移失败:', error);
        return {
            success: false,
            error: error.message
        };
    }
}

// 使用方法
// await migrateToJuCoin();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jucoin-wallet.gitbook.io/jucoin-wallet-docs/6.-chang-jian-wen-ti.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
