WLOP | 北漠
614 words
3 minutes
从零开始的合约交互小知识(2)
如何显示“正确”的页面
当用户进入活动页面时,用户链接的是非当前页面期望的网络,例如当前页面接入合约为 BSC 链,用户 MetaMask 链接的为 ETH 链,如果直接请求合约会报错导致页面显示数据错乱甚至无法打开。
如何做到获取合约的信息是正确的?
参考官方示例: Connecting to a Contract
// A Human-Readable ABI; for interacting with the contract, we// must include any fragment we wish to useconst abi = [ // Read-Only Functions "function balanceOf(address owner) view returns (uint256)", "function decimals() view returns (uint8)", "function symbol() view returns (string)",
// Authenticated Functions "function transfer(address to, uint amount) returns (bool)",
// Events "event Transfer(address indexed from, address indexed to, uint amount)"];
// This can be an address or an ENS nameconst address = "0x764a06fDdcE6b8895b6E7F9ba2874711BF31edEa";
// Read-Only; By connecting to a Provider, allows:// - Any constant function// - Querying Filters// - Populating Unsigned Transactions for non-constant methods// - Estimating Gas for non-constant (as an anonymous sender)// - Static Calling non-constant methods (as anonymous sender)const erc20 = new ethers.Contract(address, abi, provider);
// Read-Write; By connecting to a Signer, allows:// - Everything from Read-Only (except as Signer, not anonymous)// - Sending transactions for non-constant functionsconst erc20_rw = new ethers.Contract(address, abi, signer);这时可以在构建合约对象同步注入 JsonRpcProvider 以支撑运行合约
const rpcUrls = 'https://bsc-dataseed1.ninicoin.io' // bsc rpc urlconst jsonProvider = new ethers.providers.JsonRpcProvider(rpcUrls);const erc20 = new ethers.Contract(address, abi, jsonProvider);需要注意的是该方法只能读取合约只读方法,无法调用写方法(如:Transfer),若需要实施交互性操作,应提醒用户切换至正确的链。
切链操作
构建多链数组,数组结构如下:
interface AddEthereumChainParameter { chainId: string; // A 0x-prefixed hexadecimal string chainName: string; nativeCurrency: { name: string; symbol: string; // 2-6 characters long decimals: 18; }; rpcUrls: string[]; blockExplorerUrls?: string[]; iconUrls?: string[]; // Currently ignored.}- 尝试调用 ethereum 方法
wallet_switchEthereumChain切换至用户已添加过的链
wallet_switchEthereumChain方法入参为 指定链ID:[{ chainId: '0x38' }]
ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: '0x38' }],});- 如果请求成功,该方法返回null,否则返回错误。
- 如果报错则监测报错信息,报错代码为 4902 则表示未添加过目标链至 MetaMask ,调用
wallet_addEthereumChain新增目标链
ethereum.request({ method: 'wallet_addEthereumChain', params: supportedChains,});完整示例:
const supportedChains = [ { chainId: '0x38', chainName: 'Binance Smart Chain', nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18, }, rpcUrls: ['https://bsc-dataseed1.ninicoin.io'], blockExplorerUrls: ['https://bscscan.com/'], }]
try { await ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: '0x38' }], });} catch (switchError) { // This error code indicates that the chain has not been added to MetaMask. if (switchError.code === 4902) { try { await ethereum.request({ method: 'wallet_addEthereumChain', params: supportedChains, }); } catch (addError) { // handle "add" error } } // handle other "switch" errors}ps: ETH chainId 为 0x1
