Metamask API简介
#javascript #react #web3 #ethereum

如果您打算将身份验证和身份集成到您的Web3应用程序中,则适应Metamask API是一种开始学习提供给您的能力的好方法。

TOC

此信息中的此信息扩展了我从纽约的Chainlink SmartCon 2022的演讲中扩展。本文的目的是让您尽快使用MetAmask API加速,并且估计是15分钟的读取。

什么是metamask API?

每当我们使用诸如Chrome,Firefox或Brave之类的浏览器以及安装MetAmask之类的钱包扩展程序时,我们都可以使用以太坊提供商(如EIP-1193指定)注入window.ethereum的浏览器页面。从历史上看,提供商的实施表现出钱包之间的界面和行为冲突。该EIP正式为以太坊提供商API促进钱包互操作性。

我们将此提供商与DAPP一起使用,以请求用户以太坊帐户,阅读链数据并具有用户签名消息和交易。

metAmask API调用是用we will explain further的JSON-RPC规格定义的。

我们可以在开发人员工具中通过开发人员工具安装和启用MetAmask时,使用Chrome您可以查看源/页面,您将看到一个表示MetAmask的图标。

页面用于查看当前网页上的可用资源。
在最高级别,我们看到了主要文档及其所有资源的表示。

如果我们在此处看到以云图标为代表的元掩体,我们知道元掩as是安装而不是禁用的。

window.ethereum对象被注入页面,使我们能够与metamask和以太坊进行交互。

我们可以直接访问开发人员工具控制台中的window.ethereum对象。可以说我们想获得当前的链条。

通过在我们的控制台中运行上面的代码,如果我们目前已连接到Polygon,我们会看到从此方法调用中返回0x89。

当您开始使用MetAmask API方法时,您可能需要从我们的主要DX工程师Gui Bibeau中查看我们的一些beginner-level videos,这些Gui Bibeau可以帮助您开始使用MetAmask API。

什么是JSON RPC?

JSON-RPC是使用JSON数据格式的运输不可知论RPC。与JSON-RPC服务器进行通信时,尽管该服务器是如何构建或建立了什么语言或平台,但您仍会发送轻巧的JSON。它设计为简单,使用正确的工具学习相对简单。

这很方便,因为这意味着无论我们是通过HTTP还是Web插座发送,我们一直在发送JSON,这对所有开发人员都很容易。

JSON RPC IMHO,是一项非常重要的技术,可以学习何时首次进入Web3并学习在DAPP层上构建,我认为您应该熟悉的其他一些技术是:

您可以在jsonrpc.org/specification

上了解有关JSON RPC规范的更多信息

JSON RPC请求和响应示例

在这里,我们有一个典型的请求和响应,以JSON格式。第一个示例使用EIP-695中概述的eth_chainId rpc api方法,该方法返回单个 string hexadecimal 格式中的整数值的结果,描述了当前配置的CHAIN_ID值 - 由EIP-155引入的保护交易。

要求

我们在metAmask中调用eth_chainId方法,该方法不需要任何参数输入。请求就像一个函数调用,并且需要为结果响应而采取的零或许多参数。

{
  "id": 0,
  "jsonrpc": "2.0",
  "method": "eth_chainId",
  "params": []
}

什么是ID:这是一个唯一的ID,因此客户可以将响应与其原始请求相关联
就像在HTTP上下文中使用Web插座时,这与批处理请求不那么相关。
什么是jsonrpc:这表示您正在使用的JSONRPC版本。

回复

{
  "jsonrpc": "2.0",
  "result": "0x1",
  "id": 0
}

它返回了用户在结果字段中连接的当前链。我们可以确定这是主网,因为数字1在十六进制值中确实很容易读取,但是由于十六进制值更难阅读,因此返回的其他链条返回。在下面的JavaScript示例中,我们将致力于将十六进制值转换为数字。

JSON RPC很简单。上面,我们调用MetAmask API方法,但您也可以调用自定义RPC端点。在下一个示例中,我们正在查看一个自定义的RPC端点,该端点只返回链条列表。

要求

{
  "id": 0,
  "jsonrpc": "2.0",
  "method": "list_chains",
  "params": [1]
}

采用一个代表我们要返回的链数的参数。为简单起见,我们只是返回一个。

回复

{
  "id": 0
  "jsonrpc": "2.0",
  "result": [{
    "chain": "Ethereum Mainnet",
    "chainId": "0x1"
  }]
}

请注意,响应实际上是链的数组。

在JavaScript中工作时,很容易使用DAPP中的window.ethereum对象调用RPC端点,该对象已连接到MetAmask中的RPC提供商。
如您在此处看到的那样,我们只是将该请求设置为对象,然后调用通过metamask API方法eth_chainId的请求方法。

const chainIdHex = await window.ethereum.request({
  "method": "eth_chainId",
  "params": []
})

console.log(chainIdHex)
// 0x1

let chainIdNumber = parseInt(chainIdHex, 16)
console.log(chainIdNumber)
// 1

再次,我们注意到我们将chainId作为十六进制值重新获得。在此示例中,链条变量包含以十六进制格式的以太坊链ID的字符串表示(以0x的前缀)。 parseInt函数用于通过将基数指定为16(十六进制)来将此字符串转换为整数。这返回以太坊链ID的数值等效,在这种情况下为1

请注意,这只是一个示例,确切的实现将取决于特定上下文和用例。您可能需要处理错误和异常,例如输入字符串不是有效的十六进制数字,或者当输入不是有效的以太坊链ID时。

什么是开放的RPC?

OpenRPC规范定义了JSON-RPC 2.0 API的标准,编程语言 - 不可能的接口描述。 JSON-RPC API的ADL(API描述语言)

OpenRPC规范

  • 语言不可知接口描述
  • 发现带有源或文档的服务功能
  • 能够与最小实现逻辑的远程服务互动
  • 类似于下级编程的接口描述langs
  • 删除调用JSON RPC服务的猜测

将OpenRPC视为Open API/Swagger,但对于JSON-RPC API(是规格/工具)

这是一种可以交换功能的人类可读格式。换句话说,它允许人类和计算机发现和理解服务的功能,而无需访问其源代码,文档或网络流量检查。

OpenRPC提供了描述API的结构和参数的标准化方法,以及所接受和返回的数据的类型和格式。这使开发人员可以创建可以轻松理解和集成其他开发人员的API,而无需花费时间和精力来学习每个单独API的细节。

例如,如果开发人员想创建一个允许用户与以太坊区块链交互的API,则可以使用OpenRPC以与其他与以太坊相关的API一致的方式来定义API。这使其他开发人员更容易理解和使用API​​,并允许他们将其集成到自己的应用程序中,而无需花费时间来学习API实施的详细信息。

这是一个很高的概述,但是如果您想深入研究OpenRPC,我建议您从API Specification Conference 2022中检查ZaneStarrIntroduction to OpenRPC会话。

基本工具

本节重点介绍了一些工具,可以在处理时可以为您提供帮助:

  • 测试JSON RPC服务器
  • 创建开放的RPC规格
  • 使用Metamask API
  • 使用智能合约与MetAmask互动

链接到工具

使用metamask构建时,注射的window.ethereum对象是我们相应的以太坊提供商API文档。
想知道MetAmask支持的所有eth_wallet_方法吗?

以太坊提供商

检查相应的RPC API文档,这些文档具有有关我们从eth_requestAccountswallet_addEthereumChainwallet_switchEthereumChain等JS代码中调用的方法的信息。也许您需要将网络/链添加到MetAmask ADN将用户切换到该链条,您可以找到文档和代码以向您展示如何在此处进行操作:

metamask RPC API

下一个链接将允许您连接钱包并在浏览器中尝试这些RPC API调用,我们计划将操场与未来版本合并我们的文档。

metamask API操场

ChainLink维护一个名为chainlist.org的站点,这是网络/链条信息的重要资源。我经常浏览该网站,只是寻找各种以太坊网络和测试网,它们的链条以及与它们连接所需的其他信息。此信息也有其他来源,但这是快速找到每个链条的信息和RPC服务器地址的好入侵,并提供有关其延迟和隐私的信息。

您可以在MetAmask确认弹出时添加并切换到列表中的任何链条,您可以看到需要哪些信息将该链添加到MetAmask中。

链清单

下面是使用链清单的一个示例,我可以看到幻想歌剧(mainnet),它的链条可以添加到metamask,在确认中,请参见用于将网络添加到我的钱包中的信息。

静止

recerialize是一种工具,可以序列化并应将十六进制的字符串或数字序列化为十六进制或相反的方式,下面是如何将其用于简单的事物的示例.org。

用法的示例

MetAmask Playground列表我们在API中支持的JSON-RPC方法。

大多数方法都以wallet_eth_为前缀。

一些最受欢迎和IMO最常用的方法是:

  • eth_accounts:获取帐户和钱包地址
  • eth_chainId:返回当前链ID作为十六进制
  • wallet_addEthereumChain:添加以太坊链
  • wallet_switchEthereumChain:将用户切换到正确的链
  • contract.mint:调用智能合约功能,该功能在区块链上触发用户的元掩体

以下示例使用metamask API游乐场

扩展每种方法时,您拥有有关参数和结果的信息,并且可以在浏览器中检查并运行每个方法示例。

在这里,我们正在测试eth_accounts方法以获取连接的帐户:

接下来是一个示例调用eth_chainId,它将返回我们已连接到的网络的当前链条:

另一种广泛使用的方法是wallet_addEthereumChain

这允许DAPP建议将链条添加到用户的钱包中。

只是指定链条和一些链元数据。钱包申请可以任意拒绝或接受该请求。如果添加链条,则返回值null,否则错误。

EIP 3085引入了此API端点。

这是用户在添加链时看到的:

下一个API方法切换其主动以太坊链。由EIP 3326引入。

用户将看到与下面类似的对话:

注意:如果您没有试图切换到已经添加到用户钱包的链条,此方法将丢弃错误。

因此,当我们想将用户切换到DAPP中的另一个链时,我们可以将wallet_addEthereumChainwallet_switchEthereumChain方法组合在尝试 /捕获中。< / p>

让我们看一下如何将以太坊链添加到React组件中的Polygon Mainnet:

import { useContext } from 'react'
import { MetaMaskContext } from '../../../context/MetaMaskProvider'
import MyButton from '../atoms/MyButton'

const ConnectNetwork = () => {
  const { provider } = useContext(MetaMaskContext)

  const addSwitchNetwork = async () => {
    if (provider) {
      try {
        await window.ethereum.request({
          method: 'wallet_switchEthereumChain',
          params: [{ chainId: '0x4' }],
        })
      } catch (error) {
        try {
          await window.ethereum.request({
            method: 'wallet_addEthereumChain',
            params: [
              {
                chainId: '0x313337',
                blockExplorerUrls: ['https://polygonscan.com/'],
                chainName: 'Polygon Mainnet',
                nativeCurrency: {
                  decimals: 18,
                  name: 'Polygon',
                  symbol: 'MATIC'
                },
                rpcUrls: ['https://polygon-rpc.com']
              },
            ],
          })
        } catch (error) {
          // user rejects the request to "add chain" or param values are wrong, maybe you didn't use hex above for `chainId`?
          console.log(`wallet_addEthereumChain Error: ${error.message}`)
        }
      }
    }
  }

  return (
    <MyButton handleClick={addSwitchNetwork}>
      <p>Connect Rinkeby</p>
    </MyButton>
  )
}

export default ConnectNetwork

上面的代码假设您使用某种类型的上下文API组件来跟踪钱包状态并将其提供给应用程序中的组件,但是如果您不使用React,则可以专注于try/catch extion代码并修改它以适合您的应用程序。

使用SDK连接到metamask移动

您想为用户提供轻松连接到MetAmask扩展名或MetAmask Mobile(来自各种平台)的选项,您应该考虑使用MetaMask SDK,您可以在其中了解更多信息并链接到文档。我们有React和NextJ中的示例应用程序。 MetAmask SDK利用幕后的metamask API,尽管这是另一个话题,但值得注意的是。

有关如何在NextJS应用程序中集成MetAmask SDK的示例,请查看我们的"Getting Started" example

智能合约示例

如果我们想调用具有应付款关键字的智能合约功能,则以下是您如何从智能合约触发metamask的示例:

contract MyNFT {
  uint256 public totalSupply;
  uint256 public maxSupply;
  mapping(uint256 => address) public tokenOwners;

  function mint(uint256 tokenId) public payable {
    require(totalSupply + 1 <= maxSupply, "Cannot mint more tokens: maximum supply reached");
    require(tokenOwners[tokenId] == address(0), "Token ID already in use");
    tokenOwners[tokenId] = msg.sender;
    totalSupply++;
  }
}

添加了payable关键字,可以使用包含付款的交易来调用此mint()函数。带有交易的以太币的数量将作为MSG.Value参数可用。请注意,您可能还需要在功能中添加其他逻辑才能处理接收的以太,例如将其转移到合同所有者的帐户中。

该函数采用一个uint256参数,代表要铸造的NFT的唯一令牌ID。该功能首先检查铸造新令牌后,totalSupply是否比maxSupply大。如果是这种情况,则该功能将带有错误消息。然后,该函数检查是否已经使用了指定的令牌ID。如果已使用令牌ID,则该函数将带有错误消息。否则,该函数将更新令牌所有权映射,以将令牌分配给函数的呼叫者(使用msg.sender变量),并增加totalSupply

然后,我们可以通过可能看起来像这样的反应组件在我们的智能合约中调用此功能:

const MintingPage = ({nft}) => {

  const [isMinting, setIsMinting] = useState(false)
  const [error, setError] = useState(false)
  const [errorMessage, setErrorMessage] = useState("")
  const { user, nftContract, chainId } = useContext(MetaMaskContext)
  const { address } = user

  const mintNFT = async () => {
    console.log("start minting")
    setIsMinting(true)

    nftContract.mint({
      from: address,
      value: nft.priceHexValue
    })
    .then(async(tx) => {
      await tx.await()
      console.lgo(`minting complete, mined: ${tx}`)
      setIsMinting(false)
    })
    .catch((error) => {
      console.log(error)
      setError(true)
      setErrorMessage(error?.message)
      setIsMinting(false)
    })
  }
}

我们使用await关键字等待在继续执行代码之前在区块链上开采交易。

.then.catch语法用于处理交易结果。如果交易成功,将执行.then块。如果交易失败,将执行.catch块,并且将使用错误消息更新组件的状态。

mint函数在合同上调用mint方法,然后等待使用wait方法挖掘交易。这将确保mint函数直到在区块链上成功开采交易后才继续执行。这对于确保在代码继续执行之前更新合同的状态可能很有用。