从零开始的合约交互小知识(2)
f8ae6f63d6bd4c55bdd6989335ad2375
如何显示“正确”的页面
当用户进入活动页面时,用户链接的是非当前页面期望的网络,例如当前页面接入合约为 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),若需要实施交互性操作,应提醒用户切换至正确的链。
切链操作
构建多链数组,数组结构如下:
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
- 如何显示“正确”的页面
- 切链操作