使用 React+ethers.js 开发简单加密钱包(一)

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 使用 React+ethers.js 开发简单加密钱包

最近在开发一个 NFT 二创平台,其中包含了很多概念和技术。我会更新一个系列的文章来总结和沉淀在这个过程中的一些知识与思考。

本文是对 ethers.js 进行一个全方位介绍,非常适合 web3 入门学习。


什么是 ethers.js?


Web3 中的各类 DApp,都需要与智能合约进行交互。如果用原生 JS 来做这些事会很麻烦。这时就需要使用专属的 SDK。

目前 JS 环境中有两个主流的库可以用来和智能合约进行交互,一个是 web3.js,另一个是 ethers.js。


ethers.js VS web3.js


web3.js 比 ethers.js 出现的更早。但是目前 ethers.js 更受欢迎。

主要原因有如下两点:

  1. 体积:ethers.js 体积仅有 116.5kb,web3.js 有 590.6kb。相差 5 倍左右。
  2. 设计理念:由于设计理念不同。web3.js 认为用户会在本地部署以太坊节点,私钥和网络连接状态由这个节点管理。但实际上大部分人都不会在本地部署以太坊节点。ethers.js 充分考虑了这一点,它是用 Provider 管理网络连接状态,用 Wallet 管理密钥,更加安全和灵活。而且原生支持 ENS。

ethers.js 基本使用介绍


节点即服务


由于在本地部署一个区块链节点的成本并不低,很少会有人真的部署一个节点,而是选择使用节点即服务。

这类服务有很多,比如老牌的 Alchemy、Infura、Moralis 以及今年估值 102 亿美金的新秀 Tenderly。

在这里我们选择 Alchemy,目前它的市场占有率是最高的。

alchemy 的网址在这:dashboard.alchemy.com/。具体的注册登陆就不讲了。

登陆之后我们创建一个 App。

image.png

Chain 选择 Ethereum,Network 选择 Goerli。

image.png

这样就成功创建了一个 App,点击后面的 view key,就可以查看 key。

image.png

我们把它复制下来,后面会用到。

image.png


构造合约


在对合约进行读取或交互之前,我们首先需要构造一个合约对象。

合约对象有三个构造参数,第一个是合约地址,是一个字符串。第二个是合约的 abi,可以是一个 JSON,第三个参数是 provider 对象,它用于管理网络连接状态。

下面的例子中就是使用 alchemy 提供的 JSON RPC 接口作为网络连接。


const rpc = `https://eth-goerli.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`;
const provider = new ethers.providers.JsonRpcProvider(rpc);
const contract = new ethers.Contract(contractAddress, abi, provider)

除了 JsonRpcProvider 以外,ethers 还有 IpcProvider、InfuraProvider、AlchemyProvider、Web3Provider 等多种 Provider。


读取合约信息


abi 中的方法会直接挂载到 contract 对象上,我们可以直接调用。

不过需要注意,所有的操作都是异步的。


(async () => {
  const owner = await contract.owner();
  console.log(owner);
})();


连接钱包


由于和合约交互需要支付 gas 费用,所以必须有一个数字钱包。

钱包有很多种,比如 MetaMask、Rainbow、Coinbase Wallet 等。其中 MetaMask 是最常用的一种数字钱包。

这里主要介绍如何连接到 MetaMask。

MetaMask 有一个浏览器插件,如果用户安装了该插件,在 window 对象下会有一个 ethereum 对象。我们可以调用 ethereum.request 方法发起请求,参数是一个对象,对象的 method 描述该次请求的操作。

ethereum.request 方法是异步的,会返回一个数组,该数组是所有登陆钱包的账户地址字符串,第一个账户就是当前激活的账户。如果返回的数组长度为 0,则意味着没有登陆任何账户。


(async ()=> {
  const accounts = await ethereum.request({ method: 'eth_requestAccounts' })
  if(accounts.length === 0) {
    throw Error('未登录任何账户')
  }
  const activeAccount = accounts[0]
  console.log(activeAccount)
})()

我们还可以通过 ethereum.request 方法获取当前的网络状态。


(async ()=> {
  const chainId = await ethereum.request({ method: 'eth_chainId' })
  console.log(chainId)
})()

它会返回一个字符串。0x1 表示以太网主网;0x5 表示 Goerli 测试网,更多网络的 chainId 可以在这个网站查看:chainlist.org/

下面是使用 ethers.js 来连接 MetaMask 的代码。


(async ()=> {
  const provider = new ethers.providers.Web3Provider(window.ethereum)
  const accounts = await provider.send("eth_requestAccounts", [])
  const activeAccount = accounts[0]
})()

如果使用 MetaMask 作为 provider,那么就不需要再使用 alchemy 了。


钱包


在转账交易之前,我们需要创建一个 Wallet 实例,它的作用是对交易和消息进行签名。

创建 Wallet 对象的方法有三种。

通过 Wallet.createRandom 创建随机钱包

这种方式创建的是一个单机钱包,需要连接网络。


const wallet = ethers.Wallet.createRandom()
wallet.connect(provider)

通过助记词创建


const wallet = new ethers.Wallet.fromMnemonic(mnenonic.phrase)

通过私钥和 provider 创建


const wallet = new ethers.Wallet(privateKey, provider)


钱包信息


我们可以在创建好的钱包上面获取很多有用的信息,比如钱包地址、助记词、私钥、交易次数等。


console.log(wallet.address)
console.log(await wallet.getAddress())
console.log(wallet.mnemonic)
console.log(wallet.privateKey)
console.log(wallet.getTransactionCount())


转账


一旦又了钱包,我们就可以向其他人发起转账交易。

创建一个 tx 对象,它最少需要两个属性,to 和 value,分别表示接受钱包地址和转账额度。

然后使用 wallet.sendTransaction 方法发送转账,它会返回一个 receipt 对象。这个对象有一个异步的 wait 方法,当交易上链后会返回。


const tx = {
  to: address,
  value: ethers.utils.parseEther("0.1"),
}
console.log('开始转账')
const receipt = await wallet.sendTransaction(tx)
await receipt.wait()
console.log('完成转账')


通过合约转账交易


交易需要使用 Wallet 对象。再通过 wallet 作为合约的第三个构造参数创建 Contract 对象。

调用合约的 transfer 方法,进行转账交易。该方法需要两个参数,转入的钱包地址字符串和转入的数量。

transfer 会返回一个 tx 对象,该对象有一个异步的 wait 方法,会在交易完成后执行。


const wallet = new ethers.Wallet(privateKey, provider)
const contract = new ethers.Contract(contractAddress, abi, wallet)
(async ()=> {
  const tx = await contract.transfer(toAddress, ethers.utils.parseEther("1"))
  await tx.wait()
})()


通过 signer 进行转账


通常我们无法直接拿到 privateKey,但是可以通过 signer 对象间接使用 privateKey。只需要进行签名就可以进行交易。这也是最常用的交易方式。


const signer = walletProvider.getSigner();
const tx = {
  to,
  value,
};
const receipt = await signer.sendTransaction(tx);
await receipt.wait();


使用 React 和 ethers.js 开发加密钱包


接下来我们开发一个最简单的加密钱包,具备最基础的转账功能和查询余额功能。


创建项目


我们首先创建一个 Next.js 项目。


npx create-next-app

需要选择 TypeScript。


安装依赖


安装 ethers.js


npm i ethers


安装 tailwindcss


npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

修改 tailwind.cinfig.js。


/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

修改 styles/globals.css。


@tailwind base;
@tailwind components;
@tailwind utilities;


安装 headless-ui


npm install @headlessui/react

相关文章
|
2月前
|
前端开发 JavaScript API
React开发需要了解的10个库
本文首发于微信公众号“前端徐徐”,介绍了React及其常用库。React是由Meta开发的JavaScript库,用于构建动态用户界面,广泛应用于Facebook、Instagram等知名网站。文章详细讲解了Axios、Formik、React Helmet、React-Redux、React Router DOM、Dotenv、ESLint、Storybook、Framer Motion和React Bootstrap等库的使用方法和应用场景,帮助开发者提升开发效率和代码质量。
123 4
React开发需要了解的10个库
|
16天前
|
资源调度 前端开发 JavaScript
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第10天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤,包括安装依赖、创建混淆脚本、修改 `package.json` 脚本命令、构建项目并执行混淆,以及在 HTML 文件中引用混淆后的文件。通过这些步骤,可以有效提高代码的安全性。
|
1月前
|
监控 前端开发 JavaScript
React 静态网站生成工具 Next.js 入门指南
【10月更文挑战第20天】Next.js 是一个基于 React 的服务器端渲染框架,由 Vercel 开发。本文从基础概念出发,逐步探讨 Next.js 的常见问题、易错点及解决方法,并通过具体代码示例进行说明,帮助开发者快速构建高性能的 Web 应用。
70 10
|
29天前
|
资源调度 前端开发 数据可视化
构建高效的数据可视化仪表板:D3.js与React的融合之道
【10月更文挑战第25天】在数据驱动的时代,将复杂的数据集转换为直观、互动式的可视化表示已成为一项至关重要的技能。本文深入探讨了如何结合D3.js的强大可视化功能和React框架的响应式特性来构建高效、动态的数据可视化仪表板。文章首先介绍了D3.js和React的基础知识,然后通过一个实际的项目案例,详细阐述了如何将两者结合使用,并提供了实用的代码示例。无论你是数据科学家、前端开发者还是可视化爱好者,这篇文章都将为你提供宝贵的洞见和实用技能。
55 5
|
18天前
|
前端开发 JavaScript 安全
vite3+vue3 实现前端部署加密混淆 javascript-obfuscator
【11月更文挑战第7天】本文介绍了在 Vite 3 + Vue 3 项目中使用 `javascript-obfuscator` 实现前端代码加密混淆的详细步骤。包括项目准备、安装 `javascript-obfuscator`、配置 Vite 构建以应用混淆,以及最终构建项目进行混淆。通过这些步骤,可以有效提升前端代码的安全性,防止被他人轻易分析和盗用。
|
2月前
|
前端开发 JavaScript 开发者
React 组件化开发最佳实践
【10月更文挑战第4天】React 组件化开发最佳实践
50 4
|
2月前
|
开发框架 前端开发 JavaScript
React、Vue.js 和 Angular主流前端框架和选择指南
在当今的前端开发领域,选择合适的框架对于项目的成功至关重要。本文将介绍几个主流的前端框架——React、Vue.js 和 Angular,探讨它们各自的特点、开发场景、优缺点,并提供选择框架的建议。
44 6
|
3月前
|
前端开发 JavaScript 开发者
React 和 Vue.js 框架的区别是什么?
React 和 Vue.js 框架的区别是什么?
|
3月前
|
JavaScript 前端开发 安全
js逆向实战之烯牛数据请求参数加密和返回数据解密
【9月更文挑战第20天】在JavaScript逆向工程中,处理烯牛数据的请求参数加密和返回数据解密颇具挑战。本文详细分析了这一过程,包括网络请求监测、代码分析、加密算法推测及解密逻辑研究,并提供了实战步骤,如确定加密入口点、逆向分析算法及模拟加密解密过程。此外,还强调了法律合规性和安全性的重要性,帮助读者合法且安全地进行逆向工程。
97 11
|
3月前
|
XML 移动开发 前端开发
使用duxapp开发 React Native App 事半功倍
对于Taro的壳子,或者原生React Native,都会存在 `android` `ios`这两个文件夹,而在duxapp中,这些文件夹的内容是自动生成的,那么对于需要在这些文件夹中修改的配置内容,例如包名、版本号、新架构开关等,都通过配置文件的方式配置了,而不需要需修改具体的文件