如何显示“正确”的页面

当用户进入活动页面时,用户链接的是非当前页面期望的网络,例如当前页面接入合约为 BSC 链,用户 MetaMask 链接的为 ETH 链,如果直接请求合约会报错导致页面显示数据错乱甚至无法打开。

如何做到获取合约的信息是正确的?

参考官方示例: Connecting to a Contract

// A Human-Readable ABI; for interacting with the contract, we
// must include any fragment we wish to use
const 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 name
const 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 functions
const erc20_rw = new ethers.Contract(address, abi, signer);

这时可以在构建合约对象同步注入 JsonRpcProvider 以支撑运行合约

const rpcUrls = 'https://bsc-dataseed1.ninicoin.io' // bsc rpc url
const jsonProvider = new ethers.providers.JsonRpcProvider(rpcUrls);
const erc20 = new ethers.Contract(address, abi, jsonProvider);

需要注意的是该方法只能读取合约只读方法,无法调用写方法(如:Transfer),若需要实施交互性操作,应提醒用户切换至正确的链。

切链操作

wallet_addEthereumChain32e87515f76cc907122b31920f4e562c.png

构建多链数组,数组结构如下:

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.
}
  1. 尝试调用 ethereum 方法 wallet_switchEthereumChain 切换至用户已添加过的链

wallet_switchEthereumChain 方法入参为 指定链ID: [{ chainId: '0x38' }]

ethereum.request({
    method: 'wallet_switchEthereumChain',
    params: [{ chainId: '0x38' }],
});
  1. 如果请求成功,该方法返回null,否则返回错误。
  2. 如果报错则监测报错信息,报错代码为 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

Last Updated: