JS `Blockchain` `Web3.js` / `ethers.js` 交互:去中心化应用 (DApp) 开发

各位靓仔靓女们,今天老司机我带大家飙车,不对,是带大家玩转区块链上的DApp开发!准备好安全带,咱们要用JS、Web3.js/ethers.js,在去中心化的世界里横冲直撞啦!

第一站:DApp是什么鬼?

DApp,全称Decentralized Application,翻译过来就是“去中心化应用”。 简单来说,它就像我们平时用的App,但数据和逻辑不是存在中心服务器上,而是存在区块链上,人人都可以参与,公开透明,谁也别想偷偷改数据!

想象一下,你玩的游戏,装备不是游戏公司说了算,而是你的,你可以拿到市场上自由交易,不用担心账号被封号,数据被篡改,是不是想想都刺激?这就是DApp的魅力!

第二站:JS,我们的得力助手

JS(JavaScript),这门语言大家应该不陌生,前端后端都能搞,简直是万金油。在DApp开发中,我们主要用它来跟区块链进行交互,比如调用智能合约,读取链上数据等等。

第三站:Web3.js vs ethers.js,两大门派之争

要用JS跟区块链交互,就得借助一些库,其中最流行的就是Web3.js和ethers.js。 这两个库都是用来连接以太坊区块链的桥梁,但风格和用法上有些区别。

  • Web3.js:老牌劲旅,功能全面

    Web3.js是老牌的库,功能非常全面,几乎能满足你所有的需求。但有时候用起来稍微繁琐一点。

  • ethers.js:后起之秀,简洁高效

    ethers.js是后起之秀,它的特点是简洁、高效、安全。用起来更现代化,更符合JS的习惯。

选择哪个库取决于你的个人喜好和项目需求。 如果你是新手,我建议先从ethers.js入手,因为它更容易上手。 老司机们可以根据情况选择。

第四站:实战演练,写个简单的DApp

光说不练假把式,咱们来写个简单的DApp,感受一下DApp开发的流程。

这个DApp的功能很简单:

  1. 连接MetaMask钱包
  2. 读取智能合约中的数据
  3. 调用智能合约的方法

4.1 准备工作

  • MetaMask: 你的区块链钱包,用来管理你的以太坊账号。
  • Node.js: JS的运行环境,没有的赶紧装一个。
  • VS Code: 代码编辑器,用你喜欢的就行。

4.2 创建项目

  1. 创建一个新的文件夹,作为你的项目目录。
  2. 在项目目录下打开终端,运行以下命令,初始化项目:
npm init -y
  1. 安装ethers.js:
npm install ethers

4.3 编写HTML页面

创建一个index.html文件,内容如下:

<!DOCTYPE html>
<html>
<head>
  <title>My First DApp</title>
</head>
<body>
  <h1>My First DApp</h1>

  <button id="connectWallet">Connect Wallet</button>

  <p>Contract Data: <span id="contractData"></span></p>

  <button id="callContract">Call Contract</button>

  <script src="https://cdn.ethers.io/lib/ethers-5.6.umd.min.js" type="application/javascript"></script>
  <script src="app.js"></script>
</body>
</html>

这个HTML页面很简单,包含:

  • 一个标题
  • 一个连接钱包的按钮
  • 一个显示合约数据的区域
  • 一个调用合约方法的按钮
  • 引入了ethers.js库
  • 引入了我们自己编写的app.js文件

4.4 编写JS代码

创建一个app.js文件,内容如下:

// 1. 连接MetaMask钱包
const connectWalletButton = document.getElementById('connectWallet');
const contractDataElement = document.getElementById('contractData');
const callContractButton = document.getElementById('callContract');

let provider;
let signer;
let contract;

connectWalletButton.addEventListener('click', async () => {
  if (window.ethereum) {
    try {
      await window.ethereum.request({ method: 'eth_requestAccounts' });

      provider = new ethers.providers.Web3Provider(window.ethereum);
      signer = provider.getSigner();

      console.log('Wallet connected:', await signer.getAddress());

      // 连接成功后,可以禁用连接钱包按钮
      connectWalletButton.disabled = true;

      // 连接成功后,读取合约数据
      await getContractData();

    } catch (error) {
      console.error('Error connecting wallet:', error);
    }
  } else {
    alert('Please install MetaMask!');
  }
});

// 2. 读取智能合约中的数据
async function getContractData() {
  // 你的合约地址和ABI
  const contractAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3'; // 替换成你自己的合约地址
  const contractABI = [
    {
      "inputs": [],
      "name": "greet",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "pure",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "_greeting",
          "type": "string"
        }
      ],
      "name": "setGreeting",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ]; // 替换成你自己的合约ABI

  contract = new ethers.Contract(contractAddress, contractABI, signer);

  try {
    const data = await contract.greet();
    contractDataElement.textContent = data;
  } catch (error) {
    console.error('Error getting contract data:', error);
    contractDataElement.textContent = 'Error loading data';
  }
}

// 3. 调用智能合约的方法
callContractButton.addEventListener('click', async () => {
  try {
    const tx = await contract.setGreeting("Hello DApp!");
    await tx.wait(); // 等待交易被确认
    alert('Contract method called successfully!');
    await getContractData(); // 重新读取合约数据
  } catch (error) {
    console.error('Error calling contract method:', error);
    alert('Error calling contract method');
  }
});

这个JS代码主要做了以下几件事:

  • 连接MetaMask钱包: 点击按钮后,会弹出MetaMask窗口,让你授权连接你的钱包。
  • 读取智能合约中的数据: 连接成功后,会读取智能合约中的数据,并显示在页面上。
  • 调用智能合约的方法: 点击按钮后,会调用智能合约的方法,并弹出MetaMask窗口,让你确认交易。

4.5 部署智能合约 (重要!)

上面的代码中,我们需要一个智能合约地址和ABI。 这里我们使用一个简单的Greeter合约,用Remix IDE在线编写和部署。

  1. 打开 Remix IDE: 访问 https://remix.ethereum.org/

  2. 创建合约: 创建一个新的 Solidity 文件,例如 Greeter.sol,并输入以下代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Greeter {
    string greeting;

    constructor(string memory _greeting) {
        greeting = _greeting;
    }

    function greet() public view returns (string memory) {
        return greeting;
    }

    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
    }
}
  1. 编译合约: 点击左侧导航栏的 Solidity 编译器图标,然后点击 "Compile Greeter.sol" 按钮。

  2. 部署合约: 点击左侧导航栏的 "Deploy & Run Transactions" 图标。

    • 在 "Environment" 下拉菜单中,选择 "Injected Provider – MetaMask"。 这会连接你的 Remix 到你的 MetaMask 钱包。
    • 确保你的 MetaMask 连接到你想部署合约的网络(例如,Goerli 测试网)。
    • 在 "Contract" 下拉菜单中,选择 "Greeter"。
    • 在 "greeting" 字段中,输入一个初始问候语,例如 "Hello World!"。
    • 点击 "Deploy" 按钮。 MetaMask 会弹出一个窗口,让你确认交易。 支付 gas 费后,合约就被部署到区块链上了。
  3. 获取合约地址和 ABI:

    • 部署完成后,在 Remix IDE 的 "Deployed Contracts" 部分,你可以看到你的合约实例。
    • 复制合约地址。 这就是你需要填入 app.js 中的 contractAddress 的值。
    • 点击合约实例旁边的 "ABI" 按钮。 这会复制合约的 ABI 到你的剪贴板。 将这个 ABI 格式化成 JavaScript 数组,然后填入 app.js 中的 contractABI。 例如,如果ABI是 [{"inputs":[],"stateMutability":"view","type":"function","name":"greet","outputs":[{"type":"string","name":"","internalType":"string"}]},{"inputs":[{"internalType":"string","name":"_greeting","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"setGreeting","outputs":[]}], 那么你的 contractABI 应该是:
const contractABI = [
    {
      "inputs": [],
      "name": "greet",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "_greeting",
          "type": "string"
        }
      ],
      "name": "setGreeting",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ];

重要提示:

  • 替换合约地址和ABI:app.js中的contractAddresscontractABI替换成你部署的智能合约的地址和ABI。
  • 使用测试网络: 在测试DApp的时候,一定要使用测试网络(比如Goerli),不要在主网上瞎搞,不然你的钱可能就打水漂了。
  • Gas Fee: 调用智能合约的方法需要支付Gas Fee,这是给矿工的报酬,用来激励他们帮你处理交易。

4.6 运行DApp

  1. 用浏览器打开index.html文件。
  2. 点击"Connect Wallet"按钮,连接你的MetaMask钱包。
  3. 如果一切顺利,你应该能看到合约数据显示在页面上。
  4. 点击"Call Contract"按钮,调用智能合约的方法。
  5. MetaMask会弹出窗口,让你确认交易,确认后等待交易被确认。
  6. 交易成功后,页面上的合约数据会更新。

第五站:DApp开发进阶

恭喜你,已经成功开发了一个简单的DApp! 但这只是DApp开发的冰山一角,还有很多东西等着你去探索。

  • 前端框架: 可以使用React、Vue.js等前端框架来构建更复杂的用户界面。
  • 后端服务: 可以使用Node.js、Express等后端技术来处理一些链下逻辑。
  • 智能合约: 可以编写更复杂的智能合约,实现更丰富的功能。
  • 安全: DApp安全非常重要,要学习如何防止各种攻击,比如重放攻击、溢出攻击等等。
  • 优化: DApp的性能也很重要,要学习如何优化合约代码,减少Gas Fee。

一些常用的DApp开发工具和框架:

工具/框架 描述
Truffle Suite 一个全面的开发环境,包括Truffle(构建框架)、Ganache(本地区块链)和Drizzle(前端数据管理)。
Hardhat 另一个流行的以太坊开发环境,专注于速度、灵活性和可扩展性。
OpenZeppelin 一个提供安全、可重用智能合约的库,包含ERC20、ERC721等标准合约的实现,以及权限控制、升级等功能。
Brownie 一个用于开发和部署智能合约的Python框架。
The Graph 一个用于索引和查询区块链数据的协议。 可以让你更高效地从区块链上获取数据,而无需自己编写复杂的查询逻辑。
IPFS 星际文件系统,一个去中心化的存储网络。 可以将你的DApp的静态资源(比如图片、视频)存储在IPFS上,而不是中心服务器上。

第六站:DApp开发的未来

DApp开发还处于早期阶段,但它具有巨大的潜力。 随着区块链技术的不断发展,DApp将会越来越普及,改变我们的生活方式。

  • DeFi: 去中心化金融,利用DApp实现借贷、交易、投资等金融服务。
  • NFT: 非同质化代币,利用DApp实现数字资产的发行、交易和管理。
  • GameFi: 游戏金融,将游戏和金融结合起来,让玩家在玩游戏的同时也能赚钱。
  • Web3.0: 下一代互联网,基于区块链技术构建,更加去中心化、安全、透明。

总结:

DApp开发是一个充满挑战和机遇的领域。 掌握JS、Web3.js/ethers.js,你就可以在这个领域里大展身手,创造出属于你的DApp。

记住,学习DApp开发没有捷径,需要不断地学习、实践、总结。 希望今天的分享能帮助你入门DApp开发,祝你在区块链的世界里玩得开心!

下课! 有问题可以随时提问,老司机我随时待命!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注