为什么选择 Ethers.js?想象一下,你需要处理承诺和回调,同时还要解读区块链交互的神秘之处。听起来像是头痛的配方,不是吗?Ethers.js 就像披着斗篷的英雄,提供了一个干净、直观的 API,让与以太坊的交互变得轻而易举。这就像从与章鱼搏斗变成抚摸小猫。

设置我们的 Web3 指挥中心

首先,让我们准备好开发环境。我们需要安装 Node.js 和 npm。完成后,创建一个新目录用于你的项目并运行:


npm init -y
npm install ethers express dotenv

现在,让我们在一个名为 server.js 的文件中创建我们的基本 Express 服务器:


const express = require('express');
const { ethers } = require('ethers');
require('dotenv').config();

const app = express();
app.use(express.json());

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

连接到以太坊网络:这不是火箭科学,这是区块链!

现在我们的服务器已经启动并运行,是时候建立与以太坊网络的连接了。在这个例子中,我们将使用 Infura 端点,但你可以使用任何你熟悉的提供商。

在项目根目录中创建一个 .env 文件,并添加你的 Infura API 密钥:


INFURA_API_KEY=your_infura_api_key_here

现在,让我们设置我们的以太坊提供商:


const provider = new ethers.providers.JsonRpcProvider(`https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`);

与智能合约交互:魔法发生的地方

这里是事情变得有趣的地方。我们将创建一个简单的端点来与智能合约交互。在这个例子中,我们将使用 DAI 稳定币合约,因为谁不喜欢一个好的稳定币呢?

首先,让我们定义我们的合约 ABI 和地址:


const DAI_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
const DAI_ABI = [
  'function balanceOf(address owner) view returns (uint256)',
  'function transfer(address to, uint amount) returns (bool)',
];

const daiContract = new ethers.Contract(DAI_ADDRESS, DAI_ABI, provider);

现在,让我们创建一个端点来检查某个地址的 DAI 余额:


app.get('/balance/:address', async (req, res) => {
  try {
    const balance = await daiContract.balanceOf(req.params.address);
    res.json({ balance: ethers.utils.formatEther(balance) });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

处理交易:不要丢失你的 ETH!

与智能合约交互通常涉及发送交易。让我们创建一个端点来转移 DAI 代币。但请记住,能力越大,责任越大(以及燃气费)!

首先,我们需要设置一个钱包。将你的私钥添加到 .env 文件中(但永远不要分享或提交到版本控制中!):


PRIVATE_KEY=your_private_key_here

现在,让我们创建我们的钱包和一个连接到它的新合约实例:


const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const daiContractWithSigner = daiContract.connect(wallet);

这是我们的转账端点:


app.post('/transfer', async (req, res) => {
  const { to, amount } = req.body;
  try {
    const tx = await daiContractWithSigner.transfer(to, ethers.utils.parseEther(amount));
    await tx.wait();
    res.json({ txHash: tx.hash });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

错误处理:因为即使是区块链开发者也会犯错

在处理区块链交互时,很多事情可能会出错。燃气价格可能会飙升,交易可能会失败,或者网络可能会拥堵。让我们添加一些错误处理来让我们的生活更轻松:


app.use((err, req, res, next) => {
  if (err instanceof ethers.errors.TransactionError) {
    res.status(400).json({ error: 'Transaction failed', details: err.message });
  } else if (err.code === 'INSUFFICIENT_FUNDS') {
    res.status(400).json({ error: 'Insufficient funds for transaction' });
  } else {
    res.status(500).json({ error: 'Internal server error', details: err.message });
  }
});

测试你的 Web3 后端:信任,但要验证

在你部署新的 Web3 后端之前,彻底测试它是至关重要的。这里有一个简单的测试脚本,你可以运行它来检查一切是否按预期工作:


const axios = require('axios');

async function testBackend() {
  const baseURL = 'http://localhost:3000';

  // 测试余额端点
  const balanceResponse = await axios.get(`${baseURL}/balance/0x6B175474E89094C44Da98b954EedeAC495271d0F`);
  console.log('Balance:', balanceResponse.data);

  // 测试转账端点(小心使用!)
  const transferResponse = await axios.post(`${baseURL}/transfer`, {
    to: '0x1234567890123456789012345678901234567890',
    amount: '0.1'
  });
  console.log('Transfer TX Hash:', transferResponse.data);
}

testBackend().catch(console.error);

部署:将你的 Web3 野兽释放到世界上

现在你已经构建并测试了你的 Web3 后端,是时候部署它了。你可以使用像 Heroku 或 DigitalOcean 这样的平台,但请记住要安全地设置你的环境变量。永远不要在代码或公共存储库中暴露你的私钥或 API 密钥!

结论:你现在是 Web3 后端的巫师!

恭喜!你已经成功地架起了传统后端开发与 Web3 新世界之间的桥梁。以 Ethers.js 为你的可靠伙伴,你创建了一个可以与智能合约交互、处理交易并应对区块链开发怪癖的后端。

记住,这只是冰山一角。Web3 领域在不断发展,新的协议、标准和最佳实践不断涌现。保持好奇,继续学习,谁知道呢?也许你会成为下一个在去中心化网络中构建大事的人。

思考:Web3 后端的未来

在我们结束时,这里有一些问题供你思考:

  • 后端架构如何演变以更好地支持去中心化应用程序?
  • Web3 后端有哪些独特的安全考虑,我们如何解决它们?
  • 在处理区块链交互时,我们如何优化可扩展性?

这些问题的答案可能会塑造 Web3 开发的未来。所以继续编码,继续提问,最重要的是,继续推动去中心化网络中可能性的边界!