连接以太坊

这里是我是使用 Metamask 钱包连接
MetaMask SDK

准备工作

  1. 安装 SDK

    yarn add @metamask/sdk
    // or
    npm install @metamask/sdk
  2. 安装 ethers(我这里是直接引入 JS 文件)

     <!-- 会导出一个全局的变量: ethers -->
    <script src="https://cdn.ethers.io/scripts/ethers-v4.min.js"
     charset="utf-8"
     type="text/javascript">
    </script>

    编写逻辑

    // 1. 这里按照官网提供的代码引入 SDK
    import { MetaMaskSDK } from '@metamask/sdk'
    
    // 实例化
    const MMSDK = new MetaMaskSDK(options);
    const ethereum = MMSDK.getProvider();
    
    // 获取钱包地址, 没有安装钱包会提示安装 MetaMask 钱包插件
    const accounts = await ethereum.request({ method: 'eth_requestAccounts' })
    console.log(accounts, 'accounts')
    
    // 2. 获取签名和公钥
    const provider = new window.ethers.providers.Web3Provider(ethereum)
    const signer = provider.getSigner()
     const signature = await signer.signMessage(`${Number(new Date())}`)
     console.log('签名结果:', signature)
     const publicKey = await signer.getAddress()
     console.log('公钥(以太坊地址):', publicKey)

连接UniSat

这里是我是使用 UniSat 钱包连接
Docs

编写逻辑(UniSat 文档很不错,我就不做过多解释了)

import { getAddress, signTransaction, signMessage } from 'sats-connect'
// 判断是否安装了 UniSat 钱包
const iUniSat = () => {
  if (typeof window.unisat === 'undefined') {
      // Element-ui Message 组件
    Message({
      type: 'error',
      dangerouslyUseHTMLString: true,
      duration: '20000',
      message: `
        Please install UniSat!
        <a style="text-decoration: underline; font-weight: bold" target="_blank" href='https://chrome.google.com/webstore/detail/unisat-wallet/ppbibelpcjmhbdihakflkdcoccbgbkpo'>Download</a>
      `
    })
    return false
  }
  return true
}

// 链接UniSat钱包
const connectUniSat = async () => {
  if (iUniSat()) {
    try {
      const accounts = await window.unisat.requestAccounts()
      console.log('链接成功', accounts)
      const r = await window.unisat.getAccounts()
      console.log('钱包', r)
      const publicKey = await window.unisat.getPublicKey()
      console.log('公钥', publicKey)
      const sign = await window.unisat.signMessage(`${Number(new Date())}`)
      console.log('签名', sign)      
    } catch (err) {
      if (err.message) {
        Message.error(err.message)
      }
      console.log(err, 'err')
    }
  }
}

连接 Xverse 钱包

Docs 连接钱包部分可以参照文档,但是生成 PSBT 文档写的很烂,有些变量都不知道哪里来的

准备工作

  1. 安装 获取地址以及签名等 依赖包

    yarn add sats-connect
    // or
    npm install sats-connect
  2. 安装生成 Psbt 依赖包(也可以用 npm

    yarn add @scure/base @scure/btc-signer

编写逻辑

  try {
    let addresses = []
    // 获取地址
    await getAddress({
      payload: {
          // 这两都要
        purposes: ['ordinals', 'payment'],
        message: 'Address for receiving Ordinals',
        network: {
          type: 'Testnet'
        }
      },
      onFinish: (response) => {
        addresses = response.addresses
        console.log('地址', addresses)
      },
      onCancel: () => {
        console.log('取消')
      }
    })
  } catch (err) {
    console.log(err)
    // 没有安装钱包提示去安装钱包
    if (err.message === 'No Bitcoin Wallet installed') {
      Message({
        type: 'error',
        dangerouslyUseHTMLString: true,
        duration: '20000',
        message: `
          No Bitcoin Wallet installed!
          <a style="text-decoration: underline; font-weight: bold" target="_blank" href='https://chrome.google.com/webstore/detail/xverse-wallet/idnnbdplmphpflfnlkomgpfbpcgelopg'>Download</a>
        `
      })
    }
  }

需要注意的是钱包中也要选择为测试网
在这里插入图片描述

拿到地址数据后再获取地址代码后面添加生成签名代码


// await getAddress({
//...
// })
// 获取签名写在获取地址下面
 await signTransaction({
   payload: {
     network: {
         // 测试网 Testnet,主网 Mainnet。先用测试网测试
       type: 'Testnet'
     },
     message: 'Sign Transaction',
     // 调用生成Psbt函数
     psbtBase64: createPsbt(addresses),
     broadcast: false,
     inputsToSign: [
       {
           // 这里为 payment address. payment address 在获取的值的时候拿到
         address: addresses[1].address,
         signingIndexes: [0]
       }
     ]
   },
   onFinish: (response) => {
     data.signatureBase64 = response.psbtBase64
     console.log('签名', response)
   },
   onCancel: () => {
     console.log('sign cancel')
   }
 })

生成 Psbt。 先把 Docs 文档地址代码 copy 过来。然后更改相应变量值
在这里插入图片描述
完整代码如下:

const createPsbt = (addresses) => {
  // 文档上没有声明 tx 这里找了好久 tx 是什么
  const tx = new btc.Transaction()

  const bitcoinTestnet = {
    bech32: 'tb',
    pubKeyHash: 0x6f,
    scriptHash: 0xc4,
    wif: 0xef
  }

  const output = {
    tx_hash: 'f39d37ec885de70c598648a2f80f103e1cdf34f7021ddfcb22216b7076169226',
    block_height: 780179,
    tx_input_n: -1,
    tx_output_n: 1,
    value: 300000,
    ref_balance: 22681,
    spent: false,
    confirmations: 123,
    confirmed: '2023-03-10T10:02:21Z',
    double_spend: false
  }

  // addresses[1].publicKey 就是 payment publicKey,在获取地址时拿到
  const publicKey = hex.decode(addresses[1].publicKey)
  const p2wpkh = btc.p2wpkh(publicKey, bitcoinTestnet)
  const p2sh = btc.p2sh(p2wpkh, bitcoinTestnet)

  tx.addInput({
    txid: output.tx_hash,
    index: output.tx_output_n,
    witnessUtxo: {
      script: p2sh.script,
      amount: BigInt(output.value)
    },
    redeemScript: p2sh.redeemScript
  })

  const recipient = addresses[0].address
  const changeAddress = addresses[1].address

  tx.addOutputAddress(recipient, BigInt(200000), bitcoinTestnet)
  tx.addOutputAddress(changeAddress, BigInt(80000), bitcoinTestnet)

  const psbt = tx.toPSBT(0)
  const psbtB64 = base64.encode(psbt)

  return psbtB64
}

如果要改成 Mainnet 情况下,需要将获取地址 getAddress,signTransaction 中的 network 对象下 type 属性的值都改成 Mainnet。并且 bitcoinTestnet 变量也需要相应更改。

  const bitcoinTestnet = {
    bech32: 'bc',
    pubKeyHash: 0x00,
    scriptHash: 0x05,
    wif: 0x80
  }

以上就是 连接以太坊、Xverse、UniSat钱包并获取签名 全部代码了,希望可以帮助到有需要的小伙伴。


彭小黑
26 声望2 粉丝