小试牛刀-walletconnect二维码及交互

news2024/11/16 2:25:46

目录

1.编写目的

2.实现功能

3.功能详解

依赖组件

3.1 二维码生成

3.1.1 初始化SignClient

 3.1.2 创建会话空间获取WC协议uri

3.1.3 生成二维码供用户扫描

3.1.4 等待扫描

3.2 发送交易事务

3.2.1 创建交易事务

3.2.2 向用户发送交易事务

3.3 签名事务

3.3.1 接收签名事务并验证

3.3.2 发送签名并发送到链上

3.4 签名任意数据并验证


Welcome to Code Block's blog

本篇文章主要介绍了

[walletconnect二维码及交互]
❤博主广交技术好友,喜欢文章的可以关注一下❤

1.编写目的

       最近在使用walletconnect协议和typescript语言实现相关交互功能,在此对从walletconnet协议二维码生成连接后发送交易事务签名事务签名任意信息的处理进行记录,加深对walletconnect的理解,熟悉对其组件的使用,同时希望帮助到有实现相关功能的朋友。

2.实现功能

  1. 二维码生成:生成wc:协议二维码供用户扫码连接.
  2. 发送交易事务:向用户发送Transaction以供用户签名.
  3. 签名事务:用户签名后将transaction提交的链上.
  4. 签名任意信息:用户对任意信息签名,同时可以完成对签名信息的验证.

3.功能详解

依赖组件

名称版本作用

@solana/web3.js

1.95.2

链上相关操作:生成交易事务,提交事务到链上

@walletconnect/sign-client

2.14.0

walletconnect协议相关操作:生成二维码、发送事务

solana/spl-token

0.4.8

SPL代币事务操作:生成SPL代币事务

qrcode

1.5.3

生成二维码

注:这里的链是SOL链,其它链用法类似.SPL代币即除主要代币之外的代币. 

3.1 二维码生成

3.1.1 初始化SignClient

        SignClient作为与用户wallet交互的主要实现类,在开始时要进行初始化,初始化要使用参数分别是metadataprojectId,metadata是项目相关信息,这些信息会在连接时进行展示.projectId是在walletconnect官网申请的项目ID.代码如下:

const metadata={
  //项目名称
  name: 'BoggyGame',
  //项目解释
  description: 'BoggyGame Bot',
  //项目官网
  url: 'https://www.boggycoin.com',
  //项目图片
  icons: [
    "https://i.postimg.cc/sftPCk3M/photo-2024-07-12-14-12-43.jpg"
  ]
}
//项目ID
const projectId="0176e783e7c5b0713450333ff866c2d6"

        然后就可以对SignClient进行初始化,为保证性能,这里SignClient使用单例,代码如下:

async function getSignClient() {
  if (!signClient) {
    signClient = await SignClient.init({
      projectId: projectId, // 替换为你的项目ID
      metadata: metadata
    });
  }
  return signClient;
}

 3.1.2 创建会话空间获取WC协议uri

        使用signClient进行和中继器的对等连接配对(实际为websocket链接),并获取订阅的主题(topic),然后将会话空间数据上传到对应的主题,即可获取uri和等待授权方法,实现代码如下:

export async function initWalletConnect(onApproval: (approval: any) => void):Promise<String|undefined> {
    const signClient = await getSignClient()

    // 创建对等连接获取主题
    const {topic} = await signClient.core.pairing.create()
    // 发送命名空间,获取uri和等待授权的函数
    const { uri,approval } = await signClient.connect({
      pairingTopic: topic,
       //空间方法
      requiredNamespaces: {
        solana: {
          methods: [
            "solana_signTransaction",
            "solana_signMessage",
          ],
          chains: [
            "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
          ],
          events: []
        }
      }
    })
    // 调用回调函数处理 approval
    if (approval) {
        onApproval(approval);
    }
    
    return uri;

}

        这里存在两个方法solana_signTransactionsolana_signMessage方法,分别是签名交易事务和签名消息,空间内未定义的方法将无法调用.onApproval: (approval: any)用于接收外部传输的监听方法,方便在外部获取approval.

3.1.3 生成二维码供用户扫描

        生成二维码可以使用qrcode库,直接将uri的连接字符串生成为二维码,代码如下:

import QRCode from 'qrcode';

export async function generateQR(data: string): Promise<any> {
    const qrBuffer = await QRCode.toBuffer(data, {
        width: 300,  //宽度和高度
        margin: 4    //边框距离
    });
    return qrBuffer;
}

3.1.4 等待扫描

        可以使用await approval()方法实现等待扫描授权,授权完成会获得当前连接session,同时可以获得当前连接的account,实现代码如下:

    //等待扫码后授权
    const session=await approval();
    //获取链接的账号
    const account=session.namespaces.solana.accounts[0].split(':')[2];
    //打印账号
    console.log(account)


3.2 发送交易事务

3.2.1 创建交易事务

        创建交易事务时需要用到@solana/web3.js库,这里我们创建一个转移SPL代币事务,我们需要两个地址(即发送方和接收方),同时因为是Solana链,所以需要获取这两个账户实际的AssociatedToken地址(即实际存储SPL代币的账户地址),同时需要代币的Mint地址和合约地址以及发送的数量,同时为加快交易的速度,需要设置UnitPriceUnitLimit(即增加一些交易费用来保证用户交易速度),实现代码如下:

export async function getTransaction(    
    senderPublicKey: string, 
    drawPublicKey: string,
    tokenAmount: number):Promise<Transaction> {
    //发送方公钥
    const senderPubkey = new PublicKey(senderPublicKey); 
    //接收方公钥
    const drawPubkey = new PublicKey(drawPublicKey);
    //代币MINT地址
    const tokenMintAddress = BOGGY_TOKEN_MINT;  
    //获取发送方AssociatedToken账户
    const sourceTokenAccount = await getAssociatedTokenAddress(tokenMintAddress,senderPubkey); //获取ACT账户
     //获取接收方AssociatedToke账户
    const destTokenAccount = await     getAssociatedTokenAddress(tokenMintAddress,drawPubkey);  
    //创建转移数据
    const transferInstruction = createTransferInstruction( 
        sourceTokenAccount,
        destTokenAccount,
        senderPubkey,
        tokenAmount * 1e9,
        [],
        TOKEN_PROGRAM_ID
    );
    // 创建 compute unit price 指令,提高交易速度
    const computeUnitPriceInstruction = ComputeBudgetProgram.setComputeUnitPrice({
        microLamports: 7500,
    });
    const computeUnitLimitInstruction=ComputeBudgetProgram.setComputeUnitLimit({
        units:200000
    })
    //创建事务并添加上面的三个交易数据信息
    const transaction=new Transaction().add(computeUnitPriceInstruction,computeUnitLimitInstruction,transferInstruction)
    //设置最新的区块hash
    transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
    //设置交易费用由发送方支出
    transaction.feePayer=senderPubkey;
    
    return transaction;
}

3.2.2 向用户发送交易事务

        通过SignClient.request方法可以向用户发送(通过中继器转发)交易事务,并等待用户的签名,实现代码如下:

    const transaction=await getTransaction(
        发送方地址,接收方地址,代币数量
    )
    const result = await signClient!.request<{ signature: string }>({
        chainId:'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
        topic: session!.topic,
        request: {
        method: "solana_signTransaction",
        params: {
            //付款方地址
            feePayer: transaction.feePayer!.toBase58(),
            //最近区块链hash
            recentBlockhash: transaction.recentBlockhash,
            //transaction中数据遍历封装
            instructions: transaction.instructions.map((i) => ({
            //合约ID
            programId: i.programId.toBase58(),
            //数据
            data: Array.from(i.data),
            //发送方和接收方
            keys: i.keys.map((k) => ({
                isSigner: k.isSigner,
                isWritable: k.isWritable,
                pubkey: k.pubkey.toBase58(),
            })),
            })),
        },
        },
    });

        这里因为transaction没有直接转换为walletconnect通信格式的方法,所以需要将transaction中的数据取出重新封装,当然也可以直接封装为walletconnet通信数据格式使用.

3.3 签名事务

3.3.1 接收签名事务并验证

        用户签名数据后,即可获得签名后的Signature值,这里需要对返回后的Signature验证是否有效,然后添加到签名到transaction中,实现代码如下:

//添加签名
transaction.addSignature(
     //签名方即发送方
     transaction.feePayer,
     //获取到的签名信息
     Buffer.from(bs58.decode(result.signature))
    );
//验证签名是否有效
const valid = transaction.verifySignatures();

3.3.2 发送签名并发送到链上

        直接使用sendRawTransaction方法,将数据发送到链上,返回的txId值应该和用户的签名值相同,实现代码如下:

export async function sendTransaction(transaction:Transaction){
    const txId =await connection.sendRawTransaction(transaction.serialize())
    return txId;
}

3.4 签名任意数据并验证

        可以使用签名完成任意数据的认证,这种认证主要用于用户登录的确认,如让用户签名一段随机信息,签名有效则可以认为用户完成登录,从而完成用户wallet网站登录,实现代码如下:

const response=await signClient.request({
         topic:session.topic,
         //链ID
         chainId:'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
         request:{
             method: 'solana_signMessage',
             params: {
                //随机字符串 
message:"37u9WtQpcm6ULa3VtWDFAWoQc1hUvybPrA3dtx99tgHvvcE7pKRZjuGmn7VX2tC3JmYDYGG7",
                 pubkey: 链接后用户地址
             }
         }
     })

 签名后可以使用公钥对签名后的数据进行验证,代码如下:


async function verifyMessageSignature(message: string, signature: string, userPublicKeyBase58: string) {
    try {
        const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
        
        // 将 Base58 格式的用户公钥转换为 PublicKey 对象
        const userPublicKey = new PublicKey(userPublicKeyBase58);

        // 将签名数据从 Base58 格式解码为 Uint8Array
        const signatureBytes = bs58.decode(signature);

        // 将消息字符串转换为 Uint8Array
        const messageBytes = new TextEncoder().encode(message);

        // 使用 PublicKey 对象和消息数据来验证签名
        const isSignatureValid = await connection.verifySignature(
            messageBytes,
            signatureBytes,
            userPublicKey
        );

        return isSignatureValid;
    } catch (error) {
        console.error('Error verifying signature:', error);
        return false;
    }
}

区块链内容感兴趣可以查看我的专栏:小试牛刀-区块链

感谢您的关注和收藏!!!!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1982069.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用AI绘图工具生成风景图像的教程

随着人工智能技术的飞速发展&#xff0c;AI绘图工具在图像生成和艺术创作方面变得越来越强大&#xff0c;无论你是一个设计师、艺术家&#xff0c;还是仅仅对生成艺术感兴趣的爱好者&#xff0c;AI绘图工具都可以帮助你轻松地创作出惊艳的风景图像。 在这篇教程中&#xff0c;…

医疗设备漏费控制管理系统的必然性及未来发展性

医疗设备控费的必然性 医疗改革的要求 随着医疗改革的不断深入&#xff0c;原有的医药模式已经发生了改变。药品和耗材零差价的执行&#xff0c;使得医院需要寻找新的开源节流、降耗增效的方法。医疗设备控费系统的出现&#xff0c;正是为了满足这种管理需求。 控制成本和优…

【AI】人工智能核心三要素

上图来自甲子光年的资料&#xff0c;如有侵权&#xff0c;请联系删除。 在当今科技飞速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;作为引领未来科技变革的重要力量&#xff0c;正以前所未有的速度改变着我们的生活、工作乃至整个社会的面貌。人工智能之所以能…

文件Io编程基础

1. 标准I/O (stdio.h) stdio.h 是标准C库的头文件&#xff0c;包含了输入输出函数的声明。位置&#xff1a;/usr/include/stdio.h 2. 文件I/O操作步骤 打开文件: 使用 fopen 函数&#xff0c;返回 FILE* 指针。读/写操作: 使用 fread、fwrite、fgets、fputs、fprintf、fscan…

【SOC】SoC架构系统总线的QoS管理——QoS generator

#工具文档理解# QoS——Quality of Service 目录 一、概念 Master对于Latency的敏感性 流量控制和事务级概念 Splitting Pending order IDs 数据包创建和传输的QoS 序列化 一、概念 这一部分描述了QoS机制如何平衡不同发起者的流量访问&#xff0c;以适应互连的有限可…

都2024年了,SQL语句还需要手写吗?

前言 在当今的AI时代&#xff0c;数据库管理和SQL开发已不再是单调的编码过程。借助AI的智能化工具&#xff0c;数据库操作变得更加简洁高效&#xff0c;错误率也大大降低。特别是当AI与强大的数据库管理工具Navicat相结合时&#xff0c;开发者可以更加专注于数据的分析和应用…

home assistant 接入国家电网

一、安装加载项 在 配置 - 加载项 File editorAdvanced SSH & Web Terminal 二、安装state_grid 上传压缩包 在 File editor中&#xff0c;进入 homeassistant - custom_components 文件夹中&#xff0c;点击上传文件。 文件下载路径 https://download.csdn.net/downl…

密码学基础-身份认证

密码学基础-身份认证 概述 书信的亲笔签名&#xff1b;公文、证书的印章起到了核准、认证的功能。 如前文密码学基础-数据加密所述&#xff0c;信息安全少不了身份认证的话题。只有认证了信息的来源&#xff0c;我们才能知道这条信息是否是正确的&#xff0c;合法的&#xff…

如何让贵人一直帮你?

如果有贵人提携了你一把&#xff0c;牢记一定要抱住大腿。 如果一个段位比你高很多的贵人帮了你一个忙&#xff0c;他什么都不缺&#xff0c;他缺的也不是你这个层次的人能够给的了的&#xff0c;但你千万不要以为这个事儿就翻篇儿了。牢记一招&#xff0c;每隔半年给他汇报一下…

超声波眼镜清洗机有用吗?品质上等的超声波清洗机评选

超声波眼镜清洗机有用吗&#xff1f;眼镜是我们日常生活中不可或缺的配件&#xff0c;其卫生状况对健康至关重要。由于眼镜经常与外界环境接触&#xff0c;容易积聚细菌。为了有效解决这一问题&#xff0c;大家都纷纷选择使用超声波清洗机来进行彻底清洁。所以&#xff0c;超声…

C语言基础知识点(十三)结构体的深拷贝与浅拷贝

在C或C等语言中&#xff0c;结构体&#xff08;Struct&#xff09;是一种用户自定义的数据类型&#xff0c;它允许将不同类型的数据项组合成一个单一的类型。对于结构体的拷贝&#xff0c;存在深拷贝&#xff08;Deep Copy&#xff09;和浅拷贝&#xff08;Shallow Copy&#x…

DataWhale市场博弈和价格预测

文章目录 市场博弈和价格预测任务数据出清价格的形成步骤代码运行 Task1&#xff1a;跑通baseline使用ABM估计市场出清价格转换耗煤量为机组报价保存结果为submit.csv Task2&#xff1a;时间序列挖掘ABM构建学习数据基本信息统计指标分析数据分布分时统计特征不同小时的总负荷和…

错误代码0x80004005:全面解析与解决策略

在Windows操作系统中&#xff0c;错误代码0x80004005是一个相当常见的提示&#xff0c;它通常表示一个未指定的错误或一个无法找到的错误。这个错误可能出现在多种场景中&#xff0c;包括软件安装、系统更新、网络连接、文件操作等。由于其普遍性和模糊性&#xff0c;理解和解决…

搭建链路追踪系统 Jaeger

搭建链路追踪系统 Jaeger 架构 架构图 架构设计 在设计以 Jaeger 为中心的链路追踪系统时&#xff0c;我们采用微服务架构模式。 Jaeger 作为核心追踪系统&#xff0c;负责收集、存储和展示分布式追踪数据。Elasticsearch 作为后端存储&#xff0c;提供数据的持久化和高效…

网鼎杯之unfinish

题目来源&#xff1a;网鼎杯 2018 题目描述&#xff1a;SQL 问题&#xff1a;给一个页面&#xff0c;如何判断其有漏洞 通过awvs扫描得知存在 register.php 注册页面&#xff0c;并且注册界面存在SQL盲注漏洞。 题目提示SQL&#xff0c;在注册页面测试无果&#xff0c;且发现输…

解决Ubuntu报“无法解析域名cn.archive.ubuntu.com“问题

今天在Ubuntu系统上&#xff0c;使用sudo apt update命令&#xff0c;进行更新时&#xff0c;弹出"无法解析域名 cn.archive.ubuntu.com"问题&#xff0c;如图(1)所示&#xff1a; 图(1) 弹出"无法解析域名 cn.archive.ubuntu.com" 错误 出现这种现象的原因…

C++并发编程(一):线程基础

简介 本文学习的是 b 站 up 恋恋风辰的并发编程教学视频做的一些笔记补充。 教程视频链接如下&#xff1a;线程基础&#xff1a;视频教程 文档链接如下&#xff1a;线程基础&#xff1a;笔记文档 理论上直接看 up 提供的笔记文档即可&#xff0c;我这里主要是记录一些我自己…

免费qq号码估价的工具和软件

目前有多种 qq 号码估价的工具和软件。例如&#xff0c;晒号网的 QQ 估价器可以根据 QQ 号码等级、QQ 号码资深度、QQ 号码年限、活跃时间等进行准确的 QQ 号码估价。此外&#xff0c;还有其他一些相关的估价软件和平台&#xff0c;如 QQ 号码估价 2.0 全新玩法&#xff0c;利用…

复现opendrivelab的“点云预测”项目

本文的主要工作就是复现下述论文中的算法。 该论文全称&#xff1a;Visual Point Cloud Forecasting 论文内容在此不做过多介绍&#xff0c;直接上项目。 一、准备工作 首先通读readme.md文件的内容&#xff0c;了解所需要的相关依赖和数据等内容。 一定要多读几遍&#xf…

C# udp通信测试助手

1、UI界面和最终实现功能测试 2、代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threa…