web3 连接以太坊、Xverse、UniSat钱包,获取签名

1,161 阅读3分钟

连接以太坊

这里是我是使用 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)

    // 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!                                                           &lt;a style="text-decoration: underline; font-weight: bold" target="_blank" href='https://chrome.google.com/webstore/detail/unisat-wallet/ppbibelpcjmhbdihakflkdcoccbgbkpo'&gt;Download&lt;/a&gt;                                                                
})
return false
}
return true
}



                                                                        // 链接UniSat钱包
                                                                        const connectUniSat = async () =&gt; {
                                                                          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')
                                                                                                                                                                }
                                                                                                                                                                  }
                                                                                                                                                                  }</code></pre><h3 id="item-0-6">连接 <code>Xverse</code> 钱包</h3><p><a target="_blank" href="https://link.segmentfault.com/?enc=QhlLQwZFUS17v%2BtDvkdS5Q%3D%3D.hfQ7%2B3cHWxmirNm8%2BKk3d%2B0P8kP%2BPdeIUcIwhwzqKjE9pMzLITLaZSgPhnU7%2BT3GK2bpuIRzXUtQADdvUB4BdB8bXRnSc42EmwTaayzeq%2FA%3D"><strong>Docs</strong></a> 连接钱包部分可以参照文档,但是生成 <code>PSBT</code> 文档写的很烂,有些变量都不知道哪里来的</p><h3 id="item-0-7">准备工作</h3><ol><li><p>安装 获取地址以及签名等 依赖包</p><pre><code class="base">yarn add sats-connect
                                                                                                                                                                  // or
                                                                                                                                                                  npm install sats-connect</code></pre></li><li><p>安装生成 <code>Psbt  依赖包</code>(也可以用  <code>npm</code></p><pre><code class="base">yarn add @scure/base @scure/btc-signer</code></pre></li></ol><h3 id="item-0-8">编写逻辑</h3><pre><code class="js">  try {
                                                                                                                                                                      let addresses = []
                                                                                                                                                                          // 获取地址
                                                                                                                                                                              await getAddress({
                                                                                                                                                                                    payload: {
                                                                                                                                                                                              // 这两都要
                                                                                                                                                                                                      purposes: ['ordinals', 'payment'],
                                                                                                                                                                                                              message: 'Address for receiving Ordinals',
                                                                                                                                                                                                                      network: {
                                                                                                                                                                                                                                type: 'Testnet'
                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                              },
                                                                                                                                                                                                                                                    onFinish: (response) =&gt; {
                                                                                                                                                                                                                                                            addresses = response.addresses
                                                                                                                                                                                                                                                                    console.log('地址', addresses)
                                                                                                                                                                                                                                                                          },
                                                                                                                                                                                                                                                                                onCancel: () =&gt; {
                                                                                                                                                                                                                                                                                        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!
                                                                                                                                                                                                                                                                                                                                                                          &lt;a style="text-decoration: underline; font-weight: bold" target="_blank" href='https://chrome.google.com/webstore/detail/xverse-wallet/idnnbdplmphpflfnlkomgpfbpcgelopg'&gt;Download&lt;/a&gt;
                                                                                                                                                                                                                                                                                                                                                                                  `
                                                                                                                                                                                                                                                                                                                                                                                        })
                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                              }</code></pre><p><strong><code>需要注意的是钱包中也要选择为测试网</code></strong><br></p><p>拿到地址数据后再获取地址代码后面添加生成签名代码</p><pre><code class="js">
                                                                                                                                                                                                                                                                                                                                                                                              // 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) =&gt; {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                data.signatureBase64 = response.psbtBase64
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     console.log('签名', response)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        },
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           onCancel: () =&gt; {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                console.log('sign cancel')
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    })</code></pre><p>生成 <code>Psbt</code>。 先把 <a target="_blank" href="https://link.segmentfault.com/?enc=yghIjALfyB0w2lzvRm1NAQ%3D%3D.3aqYOZNZhAU%2FG0E7qDjf4VQkc3YVBCHkZ9mlziwd5%2B3oqwvOUS7VnvCAbOWtZBHmEkAi80L5YWvealMnC%2FCABSILIU5uDeBOndJpHrgS2CHWzT78irojElC55%2Fb9PxyC9iCCAi1SOpJ25HZbyGArlufNxww3PRG3d9rlvpY1pws%3D">Docs</a> 文档地址代码 <code>copy</code> 过来。然后更改相应变量值<br><br>完整代码如下:</p><pre><code class="js">const createPsbt = (addresses) =&gt; {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 文档上没有声明 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }</code></pre><p>如果要改成 <code>Mainnet</code> 情况下,需要将获取地址 <code>getAddress,signTransaction</code> 中的 <code>network</code> 对象下 <code>type</code> 属性的值都改成 <code>Mainnet</code>。并且 <code>bitcoinTestnet</code> 变量也需要相应更改。</p><pre><code class="js">  const bitcoinTestnet = {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      bech32: 'bc',
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          pubKeyHash: 0x00,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              scriptHash: 0x05,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  wif: 0x80
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    }</code></pre><p>以上就是 <strong><code>连接以太坊、Xverse、UniSat钱包并获取签名</code></strong> 全部代码了,希望可以帮助到有需要的小伙伴。</p>