引言
在上文末尾,讲到了合约侧如何使用元交易,而对于前端和用户层面如何使用,还未有一个细致的讲解,这部分将是本文的目标。
前置知识
本文内容需要你掌握 remix
或 truffle
部署智能合约,对前端开发的基础知识(对 HTML、Javascript)有一定了解,了解 Web3.js,了解 Metamask 基本使用。如果你对这些内容还不熟,建议不要过于追求理解本文细节,先了解整体的内容,再自己深入研究你尤其不理解的部分。
部署合约
在一切开始前,当然是首先得部署智能合约,这包括 MinimalForwarder 合约与我们实现的 NFT 合约。
部署的方式有很多种,你可以采用 remix
进行部署,也可以使用一些框架,例如 truffle
来部署,在本文使用 truffle
作为示例。
由于 truffle 只会生成 contracts 目录下的合约的 artifacts,为了部署 MinimalForwarder 合约,我们需要简单的在 contracts 目录中写一个名为 MetaTx 的合约来继承 MinimalForwarder,来达到生成对应 artifacts 的目的。
// SPDX-License-Identifier: GPL3.0
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/metatx/MinimalForwarder.sol";
/**
* This file copy from openzeppelin, and make some changes.
*/
/**
* @dev Simple minimal forwarder to be used together with an ERC2771 compatible contract. See {ERC2771Context}.
*/
contract MetaTx is MinimalForwarder {
constructor() MinimalForwarder() {}
}
编译合约
truffle compile
使用以太坊测试网络 ropsten
启动 console
,如果报错,请确认你的 truffle-config.js
配置正确
truffle console --network ropsten
部署 MetaTx 合约并查看地址
truffle(ropsten)> let metaTx = await MetaTx.new()
truffle(ropsten)> metaTx.address
'0xC24b78c1E6FA961B2C6AFD33a3c5b84B0EDC1f8A'
部署 NFT 合约并查看地址
truffle(ropsten)> let nft = await NFT.new('NFT Collection', 'NFTC', metaTx.address)
truffle(ropsten)> nft.address
'0x7E6cDc21d391895d159B3D8A52ACb647407EaAf6'
至此,合约已经准备完毕。
前端代码发起元交易
首先判断是否已经安装了 MetaMask 浏览器插件,这里默认你已经安装,省略了未安装的提示处理。
var ethereum
if (typeof window.ethereum !== 'undefined') {
console.log('MetaMask is installed!');
ethereum = window.ethereum
}
如果 MetaMask 已经安装,要与之交互的话,首先需要连接 MetaMask。
<button id="enableEthereumButton">Enable Ethereum</button>
这个按钮将用于启动与 MetaMask 交互。
const ethereumButton = window.document.getElementById("enableEthereumButton")
var accounts
ethereumButton.addEventListener('click', () => {
//Will Start the metamask extension
accounts = ethereum.request({
method: 'eth_requestAccounts'
}).then(() => {
console.log('chainId: ', ethereum.chainId)
if (ethereum.chainId != '0x3') {
ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{
chainId: '0x3' }],
})
}
})
})
为连接 MetaMask 的按钮添加点击事件,调用 MetaMask 的 API eth_requestAccounts
申请用户授权连接到此网站。连接成功后,因为我们的智能合约被部署在 ropsten 网络,所以判断 chainId
是否为 3,如果不是,需要调用 wallet_switchEthereumChain
提示用户切换到 ropsten 网络。
接下来涉及到元交易的构造,我们先编写一个 button。
<div>
<h3>Generage `SafeMint` Metatransaction</h3>
<button type="button" id="genMintMetaTxButton">Generate SafeMint MetaTx</button>
</div>
<div>
<h3>Sign Typed Data</h3>
input:
<div>
<span>
from<input id="metaTxFrom" value="0x" />
</span>
</div&