MetaMask官方文档

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器

MetaMask简明教程

如果你的目的是拷贝粘贴一些可以直接运行的MetaMask代码,这里 的简单示例刚好可以满足你的需求:它很简单,但是使用MetaMask完整地实现了 以太币小费收取的应用。

代码

// 假设你要收取以太币消费
const yourAddress = '0x0c54FcCd2e384b4BB6f2E405Bf5Cbc15a017AaFb'
const value = '0xde0b6b3a7640000' // 16进制表示的以太币数量,单位:wei
const desiredNetwork = '1' // '1' 表示以太坊主网

//检测当前浏览器是否以太坊兼容,并进行相应的处理
if (typeof window.ethereum === 'undefined') {
  alert('Looks like you need a Dapp browser to get started.')
  alert('Consider installing MetaMask!')

} else {

  //如果用户安装了MetaMask,你可以要求他们授权应用登录并获取其账号
  ethereum.enable()

  //如果用户拒绝了登录请求
  .catch(function (reason) {
    if (reason === 'User rejected provider access') {
      // 用户不想登录,你看该怎么办?
    } else {
      // 本不该执行到这里,但是真到这里了,说明发生了意外
      alert('There was an issue signing you in.')
    }
  })

  //如果用户同意了登录请求,你就可以拿到用户的账号
  .then(function (accounts) {
    // You also should verify the user is on the correct network:
    //你也可以验证用户接入了正确的网络
    if (ethereum.networkVersion !== desiredNetwork) {
      alert('This application requires the main network, please switch it in your MetaMask UI.')

      //我们计划在最近补充一个有关网络切换的API,参考下面链接
      // https://github.com/MetaMask/metamask-extension/issues/3663
    }

    //一旦获取了用户账号,你就可以签名交易
    const account = accounts[0]
    sendEtherFrom(account, function (err, transaction) {
      if (err) {
        return alert(`Sorry you weren't able to contribute!`)
      }

      alert('Thanks for your successful contribution!')
    })

  })
}

function sendEtherFrom (account, callback) {

  //在这里我们要使用底层API
  const method = 'eth_sendTransaction'
  const parameters = [{
    from: account,
    to: yourAddress,
    value: value,
  }]
  const from = account

  //现在把所有数据整合为一个RPC请求
  const payload = {
    method: method,
    params: parameters,
    from: from,
  }

  //需要用户授权的方法,类似于这个,都会弹出一个对话框提醒用户交互
  //其他方法,例如只是读取区块链的数据,可能就不会弹框提醒
  ethereum.sendAsync(payload, function (err, response) {
    const rejected = 'User denied transaction signature.'
    if (response.error && response.error.message.includes(rejected)) {
      return alert(`We can't take your money without your permission.`)
    }

    if (err) {
      return alert('There was an issue, please try again.')
    }

    if (response.result) {
      //如果存在response.result,那么调用就是成功的
      //在这种情况下,它就是交易哈希
      const txHash = response.result
      alert('Thank you for your generosity!')

      //你可以轮询区块链来查看交易何时被打包进区块
      pollForCompletion(txHash, callback)
    }
  })
}

function pollForCompletion (txHash, callback) {
  let calledBack = false

  //正常情况下,以太坊区块大约15秒钟出一块
  //这里我们每隔2秒钟轮询一次
  const checkInterval = setInterval(function () {

    const notYet = 'response has no error or result'
    ethereum.sendAsync({
      method: 'eth_getTransactionByHash',
      params: [ txHash ],
    }, function (err, response) {
      if (calledBack) return
      if (err || response.error) {
        if (err.message.includes(notYet)) {
          return 'transaction is not yet mined'
        }

        callback(err || response.error)
      }

      //我们已经成功地验证了打包入块的交易
      //提醒一下,我们应当在服务端使用我们的区块链连接进行验证
      //在客户端做的话,就意味着我们信任用户的区块链连接
      const transaction = response.result
      clearInterval(checkInterval)
      calledBack = true
      callback(null, transaction)
    })
  }, 2000)
}