Web3 全栈指南

本文我们将了解到web3/区块链/智能合约应用如何在前端(HTML和Javascript)一起工作。如何将Metamask、Phantom或其他区块链钱包地址连接到前端页面。以及了解有哪些流行的前端框架(Nextjs / React 等),使我们开发更轻松

将你的智能合约连接到前端的六种方法

也许你刚刚用solidity、rust 编写了一个链上程序,但是如果没有一个很好的前端交互,几乎没有人可以使用它。

在这篇文章中,我们将了解如何在前端应用中,使用HTML和JavaScript与链上应用(智能合约或其他应用)交互。

并通过六种不同的方式,将你的Metamask、Phantom或其他区块链钱包地址连接到前端。最后,我们将看看有哪些流行的Nextjs / React前端软件包,可以辅助我们进行 web3 应用开发。

那么,让我们开始吧。

介绍

为了让web3体验友好,我们需要有用户友好的前端网站。全栈软件工程师在刚进入区块链领域可能会遇到一些挑战:

  1. 如何将Metamask(或Walletconnect, Phantom, 等等)连接到用户界面?
  2. 如何在网站上调用我的智能合约执行交易?
  3. 最好的实践都在做什么工具?

我在问自己这个问题时,看了几乎所有最流行的解决方案,并试图弄清楚应该向开发者推荐什么。因此,在这篇文章中,我们将了解到:

  1. 了解当我们想与区块链交互或向区块链发送交易时,浏览器中发生了什么。
  2. 看一下六种最流行的方法,来连接到我们的web3应用程序。
  3. 给出代码示例,并展示该领域所有最大的参与者在使用的哪些工具,这样我们也可以使用同样的工具。

如果你想看看现在一些专业的前端是什么样子,可以看一下AaveUniswap网站。

兴奋吗?我也是。我们开始吧。

如何将使用Metamask连接到智能合约

当然也可以是其他的钱包,如浏览器中的另一个钱包,如Phantom、Walletconnect等。

如何将我的hardhat、brownie、dapptools、foundry智能合约应用连接到以太坊钱包

大多数区块链应用程序使用HardhatBrownieDappToolsAnchorFoundry等框架构建(或者Remix 工具)。而前端则使用在传统web2开发里学到的哪些东西:HTML、JavaScript、CSS,以及NextJSReactAngular等框架。

因此,如果你熟悉传统的网络开发,你就会走在别人的前面!

在浏览器中使用Metamask

现在,跟上步伐,先安装Metamask观看这个视频以获得更深入的了解,安装完成之后,在页面右键单击,然后点击”检查(inspect)“:

点击检查,这样我们就可以看到浏览器中的metamask是怎么回事

右击屏幕,点击 检查(inspect)检查元素(inspect element)之后,可以看到像如下的内容:

浏览器调试工具

他们是显示渲染网站页面的代码。然后,如果你点击顶部栏中的 sources,会看到如下图内容。(如果你找到sources,你可以点击>>按钮来显示更多选项)。

Let’s look at how wallets are injected into the browser.

如果你在浏览器中安装了Metamask,你会在左边看到一个 Metamask文件。如果你安装了Phantom,你会看到一个 Phantom

他们是浏览器插件做的一些有趣的事情,它们自动 注入你的浏览器,并作为你所在网站的一部分显示出来,让网站有机会与它们交互。

每个浏览器中都有一个 window对象。我们可以通过点击console(控制台),进入 JavaScript控制台, 输入window,查看这个对象:

让我们继续输入window,看看我们得到什么。

在浏览器中查看window.ethereum。(还有window.solana)

我们在浏览器中看到了JavaScript的window对象。因为我们安装了Metamask,此时会有一个ethereum属性附加到window对象上。输入window.ethereum,看看返回了什么(如果你有Phantom,你可以试试 window.solana)。

你会看到返回了一个对象! 如果你没有Metamask,你会得到一个undefined。每个浏览器的钱包都会给window对象添加自己的属性,你通常可以在各自钱包的文档中找到它。这里是Metamask文档,明确的介绍了window.ethereum

注意:在以前的版本中,为window.web3,后来改为window.ethereum

这就是所谓的区块链提供者(provider),那么我们为什么需要这个呢?

区块链连接与提供者(Provider)

每当我们想从区块链上读取数据,调用函数,或进行交易时,都需要连接到区块链网络。如果我们发送交易,还需要将签名的交易发送到一个区块链节点,这样它就可以将其发送到网络中的所有其他区块链节点。

你可能曾经在区块链应用程序中使用过AlchemyInfuraMoralis Speedy NodesRPC URL。这些都是 ”节点即服务(node-as-a-service)“提供者,他们会提供我们一个HTTP端点来向区块链节点发送请求。加密货币钱包也是如此,Metamasks内置有一个与区块链节点的连接。事实上,如果你去Metamask network标签,你可以看到Metamask正在使用的RPC URL!

Metamask网络标签--连接你的前端的RPC URL

因此,每当我们用Metamask做一些事情,都会通过这个RPC URL进行API调用。

用HTML和JavaScript连接到加密货币钱包

我们将首先展示这一切是如何在HTML和JavaScript中完成的,然后我们将转向使用Nextjs/React例子。在我的Github这里有一个使用HTML/JavaScript连接到加密货币钱包的完整例子,所有例子的列表也在我的GitHub里。

首先,让我们创建一个标准的HTML文档,我们会给它一个连接(connect)按钮:

<!DOCTYPE html>
<html>
  <head>
    <title>Javascript Test</title>
  </head><body>
    <button id="connectButton">Connect</button>
  </body>
</html>

可以给我们的按钮添加一些功能,添加一个script标签,并创建一个JavaScript函数,寻找window.ethereum,如果找到它,就发出连接请求:

<!DOCTYPE html>
<head>
    <title>Javascript Test</title>
</head>
<body>
    <button id="connectButton" onclick="connect()">Connect</button>
</body>
<script>
async function connect() {
  if (typeof window.ethereum !== "undefined") {
    try {
      await window.ethereum.request({ method: "eth_requestAccounts" });
    } catch (error) {
      console.log(error);
    }
}}
</script>
</html>

这就是连接需要的全部代码。 eth_requestAccounts直接来自Metamask文档。如果你把文件命名为index.html并在浏览器中运行,你的metamask就会弹出要求连接:

使用智能合约将你的dapp与Metamask连接

发送交易

现在已经连接了Metamask,是时候发送一个交易了。这时我们可以使用ethersjsweb3js等包来连接我们的提供者,然后发送一个交易。通常情况下,在JavaScript中执行一个函数/发送一个交易的JavaScript 类似于这样:

const etheres = require("ethers")

contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
const abi = // some big javascript ABI here...

const provider = new ethers.providers.JsonRpcProvider(/* alchemy or infura */)
const wallet = new ethers.Wallet(/* Private key */, provider)

const contract = new ethers.Contract(contractAddress, abi, wallet)
const contractWithSigner = contract.connect(wallet)
const transactionResponse = contract.someFunction()

在浏览器中发送交易的唯一区别是,我们将提供者改为window.ethereum,现在wallet将直接来provider。由于Metamask即是我们的提供者也是钱包(或签名者),代码将看起来像这样:

const etheres = require("ethers")

contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
const abi = // some big javascript ABI here...

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

const contract = new ethers.Contract(contractAddress, abi, signer)
const contractWithSigner = contract.connect(wallet)
const transactionResponse = contract.someFunction()

你会注意到,只有中间的两行改变了,现在从window.ethereum获得钱包,我们的签名者(signer)来自提供者(即metamask)。

现在,这里有一个问题。我们的浏览器无法识别require(有时import也有问题),所以需要添加一些包来帮助我们。

因为我不希望这里变成一个介绍前端的文章,你可以参看我的html-js-ethers-connect的例子,它向我们展示了如何自己运行示例。你只需要安装以下东西就可以了:

然后,你可以按照README.md中的说明进行初始化,用纯HTML和JavaScript做一个完整的例子,在浏览器中发送交易!

你将拥有一个与智能合约一起工作的简约的前端!

5个最佳前端Web3的实践

没有特别的顺序

顶级全栈和前端web3/区块链/智能合约dapp设置

现在,让我们开始为全栈应用提供所需的工具。这些配置将包括:

  1. 如何初始化
  2. 极简的演示
  3. 真实世界的例子

你可以选择最适合你的那一个! 我们用NextJS来做这些工作,因为ReactJS是目前地球上最流行的前端框架,而NextJS是建立在它之上的,在我看来,它比原始的ReactJS更方便使用。然而,你100%可以用Angular、Svelte或其他方式工作。

你可以找到我所有的简约代码示例full-stack-web3-metamask-connectors仓库,其中链接出所有的演示。

初始化一个基本的NextJS项目

为了方便入门,所有这些项目都将从一个基本的NextJS项目开始。需要安装NodeGitYarn才能继续。你还可以跟随nextjs入门文档

运行以下命令:

yarn create next-app full-stack-web3
cd full-stack-web3

现在有了一个基本的项目框架,现在可以运行yarn dev,看看现在的网站会是什么样子。最后,删除所有开始时的 示例代码,进入index.js文件,删除所有内容,仅保留:

export default function Home() {
  return <div>Hi</div>;
}

现在前端就显示一个 Hi

设置本地Hardhat区块链和合约

现在,由于我们要测试函数交互,因此需要一个区块链来发送交易,以及相应的智能合约。代码已经为准备好了,在代码库hardhat-simple-storage GitHub。你可以按照README.md来进行设置,或者新开一个命令终端(与前端不同的终端)运行以下程序。

git clone https://github.com/PatrickAlphaC/hardhat-simple-storage
cd hardhat-simple-storage
yarn
yarn hardhat node

此时会启动一个本地区块链,给你一些临时私钥(账号),可用于部署 SimpleStorage合约,合约有一个 store函数。它接收一个uint256 _favoriteNumber作为输入参数,并将该数字存储到一个公共变量中。在SimpleStorage.sol文件中可以查看该合约代码。

用本地区块链设置你的MetaMask

现在,要将Metamask连接到我们的本地区块链。这样就可以快速发送交易和测试。本地区块链和真实的区块链类似,但这个区块链是我们可以控制的。如果你愿意,你也可以使用测试网,跳过这一步,但你必须等待很长的时间来处理交易,这是没有人愿意的。

在区块链节点运行的终端,你会看到一个类似的输出:Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/。这就是RPC URL,类似于Alchemy。

现在,在Metamask中(请永远不要使用有真实资金的Metamask进行开发。最好创建一个新的浏览器账号配置(Profile)或下载另一个有Metamask插件的浏览器)点击顶部的网络按钮,然后 添加网络(Add Network)

1_eJAES6wp7DpqBABoke_kkg

按如下内容设置它,然后点击保存,然后确保你切换到该网络(在网络下拉列表中选择刚设置的网络)。

img

现在,点击右上方的大圆圈(账号),然后点击 导入账户(import account)

img

然后从 yarn hardhat node命令的输出中添加一个私钥。之后,你应该看到一个账户,在本地网络上,并且有一些测试ETH。Metamask应该看起来像这样:

img

然后我们就可以开始了 :)

重要提示:如果你遇到了 nonce被关闭的问题,或者交易不能正常发送。在metamask中,去右上方的圆圈->设置->高级->重置账户。就可以消除nonce的问题。

使用原始 Ethers

完整代码在这里

用Ethersjs将你的智能合约连接到一个前端

最简单的方法是使用一些你已经熟悉的工具,比如Ethers,我们可以从复制粘贴在HTML设置中的内容到index.js文件中:

import styles from "../styles/Home.module.css";
import { ethers } from "ethers";
import { useEffect, useState } from "react";
export default function Home() {
  const [isConnected, setIsConnected] = useState(false);
  const [hasMetamask, setHasMetamask] = useState(false);
  const [signer, setSigner] = useState(undefined);
useEffect(() => {
    if (typeof window.ethereum !== "undefined") {
      setHasMetamask(true);
    }
  });
async function connect() {
    if (typeof window.ethereum !== "undefined") {
      try {
        await ethereum.request({ method: "eth_requestAccounts" });
        setIsConnected(true);
        const provider = new ethers.providers.Web3Provider(window.ethereum);
        setSigner(provider.getSigner());
      } catch (e) {
        console.log(e);
      }
    } else {
      setIsConnected(false);
    }
  }
async function execute() {
    if (typeof window.ethereum !== "undefined") {
      const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
      const abi = [
        {
          inputs: [
            {
              internalType: "string",
              name: "_name",
              type: "string",
            },
            {
              internalType: "uint256",
              name: "_favoriteNumber",
              type: "uint256",
            },
          ],
          name: "addPerson",
          outputs: [],
          stateMutability: "nonpayable",
          type: "function",
        },
        {
          inputs: [
            {
              internalType: "string",
              name: "",
              type: "string",
            },
          ],
          name: "nameToFavoriteNumber",
          outputs: [
            {
              internalType: "uint256",
              name: "",
              type: "uint256",
            },
          ],
          stateMutability: "view",
          type: "function",
        },
        {
          inputs: [
            {
              internalType: "uint256",
              name: "",
              type: "uint256",
            },
          ],
          name: "people",
          outputs: [
            {
              internalType: "uint256",
              name: "favoriteNumber",
              type: "uint256",
            },
            {
              internalType: "string",
              name: "name",
              type: "string",
            },
          ],
          stateMutability: "view",
          type: "function",
        },
        {
          inputs: [],
          name: "retrieve",
          outputs: [
            {
              internalType: "uint256",
              name: "",
              type: "uint256",
            },
          ],
          stateMutability: "view",
          type: "function",
        },
        {
          inputs: [
            {
              internalType: "uint256",
              name: "_favoriteNumber",
              type: "uint256",
            },
          ],
          name: "store",
          outputs: [],
          stateMutability: "nonpayable",
          type: "function",
        },
      ];
      const contract = new ethers.Contract(contractAddress, abi, signer);
      try {
        await contract.store(42);
      } catch (error) {
        console.log(error);
      }
    } else {
      console.log("Please install MetaMask");
    }
  }
  return (
    <div>
      {hasMetamask ? (
        isConnected ? (
          "Connected! "
        ) : (
          <button onClick={() => connect()}>Connect</button>
        )
      ) : (
        "Please install metamask"
      )}
{isConnected ? <button onClick={() => execute()}>Execute</button> : ""}
    </div>
  );
}

为此,我们添加了一些额外的功能,以便在连接或用户没有Metamask时显示 请安装Metamask已连接。你还会看到像useStateuseEffect这样的命令,这些被称为React Hooks,你可以从这个Fireship视频react docs.中了解它们的全部内容。虽然没有它们,这个应用也可以正常工作,只是我们无法在渲染之间保存应用的状态。

优点

  • 直接使用Ethers对UI进行最精细的控制

缺点

  • 我们必须写很多自己的代码,包括Contexts
  • 如果支持更多的钱包连接会比较麻烦。

使用示例

Nader Dabit Explainer

另外,在下面的例子中,我打算从另一个文件中导入abi,这样就不会让文章的内容臃肿了。

使用 Web3Modal

完整代码在这里

将你的智能合约应用程序连接到metamask和walletconnect

将基于EVM的区块链应用程序连接到钱包的另一种最流行的方式是使用Walletconnect。我将要展示的所有例子(包括原始Ethers的例子)都可以连接到Walletconnect(而且应该连接),使用 Web3Modal 并不是唯一可选的工具。Walletconnect 团队成员创建的创建了这个奇妙的Web3Modal工具,它允许使用一个框架来连接到任何Provider,包括Ledger、WalletConnect、TorusCoinbase Wallet,等等。

我们只需要导入这个包,之后index.js可能看起来像这样:

import styles from "../styles/Home.module.css";
import Web3Modal from "web3modal";
import { useState, useEffect } from "react";
import { ethers } from "ethers";
import WalletConnectProvider from "@walletconnect/web3-provider";
import { abi } from "../constants/abi";
let web3Modal;
const providerOptions = {
  walletconnect: {
    package: WalletConnectProvider, // required
    options: {
      rpc: { 42: process.env.NEXT_PUBLIC_RPC_URL }, // required
    },
  },
};
if (typeof window !== "undefined") {
  web3Modal = new Web3Modal({
    cacheProvider: false,
    providerOptions, // required
  });
}
export default function Home() {
  const [isConnected, setIsConnected] = useState(false);
  const [hasMetamask, setHasMetamask] = useState(false);
  const [signer, setSigner] = useState(undefined);
useEffect(() => {
    if (typeof window.ethereum !== "undefined") {
      setHasMetamask(true);
    }
  });
async function connect() {
    if (typeof window.ethereum !== "undefined") {
      try {
        const web3ModalProvider = await web3Modal.connect();
        setIsConnected(true);
        const provider = new ethers.providers.Web3Provider(web3ModalProvider);
        setSigner(provider.getSigner());
      } catch (e) {
        console.log(e);
      }
    } else {
      setIsConnected(false);
    }
  }
async function execute() {
    if (typeof window.ethereum !== "undefined") {
      const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
      const contract = new ethers.Contract(contractAddress, abi, signer);
      try {
        await contract.store(42);
      } catch (error) {
        console.log(error);
      }
    } else {
      console.log("Please install MetaMask");
    }
  }
return (
    <div>
      {hasMetamask ? (
        isConnected ? (
          "Connected! "
        ) : (
          <button onClick={() => connect()}>Connect</button>
        )
      ) : (
        "Please install metamask"
      )}
{isConnected ? <button onClick={() => execute()}>Execute</button> : ""}
    </div>
  );
}

你会看到,我们设置了一些providerOptions来告诉前端要支持哪些钱包,以及我们要支持哪些链以及需要设置一个NEXT_PUBLIC_RPC_URL,它指向一个RPC_URL来连接到区块链。如果我们使用walletconnect,我们实际上不使用用户的metamasks的内置区块链节点。

优点

  • 易于整合多个钱包
  • Ethers 很好集成

缺点

  • 仍然没有内置的上下文组件

使用示例

如果你想看看Web3Modal、区块链等的一些前沿的前端使用,可以查看Scaffold-ETH。这是一个了不起的学习工具,由Austin Griffith编写,你可以用来解构一些最佳实践。

Moralis

完整代码在这里

使用Moralis的全栈智能合约/Web3/区块链设置

Moralis(或者更具体地说,react-moralis)是第一个包含上下文管理组件的软件包,它是非常有用的。它允许整个应用在组件之间轻松地共享状态,这是必要的,因为我们需要传递Metamask的授权。

Moralis是由Ivan on Tech及其团队创建,不仅可以帮助开发者连接到Metamask,还可以帮助开发其他后端系统(全栈应用可能需要)。EtherscanOpensea都是web3应用程序的例子,它们仍然需要后台和数据库。为什么呢?因为很多时候,你想添加大量的功能,在链上做起来会花费太多Gas!所以你仍然想有一个后台和数据库。

因此,你仍然让智能合约做主要工作,而Moralis可以做所有围绕它的一些工作。下面是使用Moralis的代码:

import styles from "../styles/Home.module.css";
import { useMoralis, useWeb3Contract } from "react-moralis";
import { abi } from "../constants/abi";
import { useState, useEffect } from "react";
export default function Home() {
  const [hasMetamask, setHasMetamask] = useState(false);
  const { enableWeb3, isWeb3Enabled } = useMoralis();
  const { data, error, runContractFunction, isFetching, isLoading } =
    useWeb3Contract({
      abi: abi,
      contractAddress: "0x5FbDB2315678afecb367f032d93F642f64180aa3",   // your contract address here
      functionName: "store",
      params: {
        _favoriteNumber: 42,
      },
    });
useEffect(() => {
    if (typeof window.ethereum !== "undefined") {
      setHasMetamask(true);
    }
  });
return (
    <div>
      {hasMetamask ? (
        isWeb3Enabled ? (
          "Connected! "
        ) : (
          <button onClick={() => enableWeb3()}>Connect</button>
        )
      ) : (
        "Please install metamask"
      )}
{isWeb3Enabled ? (
        <button onClick={() => runContractFunction()}>Execute</button>
      ) : (
        ""
      )}
    </div>
  );
}

你会看到Moralis带有强大的Hook函数,如useWeb3Contract,使获得状态和与合约交互更加容易,而且不需要ethers。

Moralis 还提供的enableWeb3函数代替了自己编写的connect函数。

此外,在_app.js中,需要用一个Context提供者来包装整个应用程序:

import "../styles/globals.css";
import { MoralisProvider } from "react-moralis";

function MyApp({ Component, pageProps }) {
  return (
    <MoralisProvider initializeOnMount={false}>
      <Component {...pageProps} />
    </MoralisProvider>
  );
}

export default MyApp;

Morlais有内置的属性选项,例如:可以用数据库设置前端,然而,如果你只想使用钩子和函数,你可以把initializeOnMount设置为false,等将来需要时才设置服务器

优点

  • 有上下文提供者
  • 内置与智能合约交互功能
  • 可以选择引入后端,以获得更丰富的前端功能

缺点

  • 必须手动添加自己的钱包

真实案例

Web3-React

完整代码在这里

用web3-react建立一个全栈的dapp

Uniswap工程负责人Noah Zinsmeister和朋友们建立了一个优秀的软件包,叫做web3-react。这是被UniswapAaveCompound等顶级项目最广泛使用的包之一。它还包含了一个上下文组件管理器和一些令人难以置信的强大的Hook 函数,让你可以直接上手并开始工作,还内置了一些web3钱包连接。

以下是index.js修改后的代码:

import styles from "../styles/Home.module.css";
import { useWeb3React } from "@web3-react/core";
import { InjectedConnector } from "@web3-react/injected-connector";
import { abi } from "../constants/abi";
import { useState, useEffect } from "react";
import { ethers } from "ethers";
export const injected = new InjectedConnector();
export default function Home() {
  const [hasMetamask, setHasMetamask] = useState(false);
useEffect(() => {
    if (typeof window.ethereum !== "undefined") {
      setHasMetamask(true);
    }
  });
const {
    active,
    activate,
    chainId,
    account,
    library: provider,
  } = useWeb3React();
async function connect() {
    if (typeof window.ethereum !== "undefined") {
      try {
        await activate(injected);
        setHasMetamask(true);
      } catch (e) {
        console.log(e);
      }
    }
  }
async function execute() {
    if (active) {
      const signer = provider.getSigner();
      const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
      const contract = new ethers.Contract(contractAddress, abi, signer);
      try {
        await contract.store(42);
      } catch (error) {
        console.log(error);
      }
    } else {
      console.log("Please install MetaMask");
    }
  }
return (
    <div>
      {hasMetamask ? (
        active ? (
          "Connected! "
        ) : (
          <button onClick={() => connect()}>Connect</button>
        )
      ) : (
        "Please install metamask"
      )}
{active ? <button onClick={() => execute()}>Execute</button> : ""}
    </div>
  );
}

_app.js代码:

import "../styles/globals.css";
import { Web3ReactProvider } from "@web3-react/core";
import { Web3Provider } from "@ethersproject/providers";
const getLibrary = (provider) => {
  return new Web3Provider(provider);
};
function MyApp({ Component, pageProps }) {
  return (
    <Web3ReactProvider getLibrary={getLibrary}>
      <Component {...pageProps} />
    </Web3ReactProvider>
  );
}
export default MyApp;

正如你所看到的,我们仍然使用ethers与智能合约交互,但我们使用Hook 函数来启用Metamask和任何其他想要的钱包Provider

优点

  • 上下文提供者
  • 内置与智能合约交互的功能
  • 内置钱包连接

缺点

  • 不像web3modal那样容易设置钱包
  • 需要编写或使用自己的Hook来与智能合约交互。

真实案例

使用Dapp

完整代码的代码在这里

用usedapp建立一个全栈的web3应用程序

Ethworks 和最流行的测试框架 waffle , 他们背后是同一个团队,waffle被hardhat使用。现在他们又做了一个类似moralis的框架,你可以利用所有的Hooks和工具来构建一个前端,还包括一个上下文提供者。

下面是使用Ethworks后index.js 的代码:

import styles from "../styles/Home.module.css";
import { useEthers, useContractFunction } from "@usedapp/core";
import { useState, useEffect } from "react";
import { ethers } from "ethers";
import { abi } from "../constants/abi";
export default function Home() {
  const { activateBrowserWallet, account } = useEthers();
  const [hasMetamask, setHasMetamask] = useState(false);
useEffect(() => {
    if (typeof window.ethereum !== "undefined") {
      setHasMetamask(true);
    }
  });

async function connect() {
    await activateBrowserWallet();
  }
  const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
  const contract = new ethers.Contract(contractAddress, abi);
const { send, state } = useContractFunction(contract, "store", {
    transactionName: "store",
  });
useEffect(() => {
    console.log(`State: ${state.status}`);
  }, [state]);
return (
    <div>
      {hasMetamask ? (
        account ? (
          "Connected! "
        ) : (
          <button onClick={() => connect()}>Connect</button>
        )
      ) : (
        "Please install metamask"
      )}
{account ? <button onClick={() => send(42)}>Execute</button> : ""}
    </div>
  );
}

_app.js如下:

import "../styles/globals.css";
import { DAppProvider } from "@usedapp/core";
const config = {
  multicallAddresses: ["0x5FbDB2315678afecb367f032d93F642f64180aa3"],
};
function MyApp({ Component, pageProps }) {
  return (
    <DAppProvider config={config}>
      <Component {...pageProps} />
    </DAppProvider>
  );
}
export default MyApp;

向应用程序传递参数,用于配置如:支持的区块链和其他连接属性。与Moralis类似,useDapp带有activateBrowserWallet功能,用来激活metamask/浏览器钱包,以及像useContractFunction这样的 hook 函数,与智能合约交互(你不必使用ethers)。

优点

  • 上下文提供者
  • 内置智能合约交互功能

缺点

  • 不像web3modal那样容易设置钱包
  • 没有内置数据库的选项

真实案例

小结

每个工具都有其各自的优缺点,你可以根据自己的喜好、醒目的需求进行选择。

编码愉快!


本翻译由 Duet Protocol 赞助支持。

点赞 7
收藏 21
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
翻译小组
翻译小组
0x9e64...7c84
大家看到好的文章可以在 GitHub 提 Issue: https://github.com/lbc-team/Pioneer/issues 欢迎关注我的 Twitter: https://twitter.com/UpchainDAO