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

目录

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, // 替换为你的项目IDmetadata: 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: []}}})// 调用回调函数处理 approvalif (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)//设置最新的区块hashtransaction.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(),//最近区块链hashrecentBlockhash: transaction.recentBlockhash,//transaction中数据遍历封装instructions: transaction.instructions.map((i) => ({//合约IDprogramId: 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,//链IDchainId:'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 格式解码为 Uint8Arrayconst signatureBytes = bs58.decode(signature);// 将消息字符串转换为 Uint8Arrayconst 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.rhkb.cn/news/391957.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装VMware16

安装VMware16的步骤主要包括下载、‌安装和激活。‌ 下载VMware16 首先&#xff0c;‌需要从VMware官网下载VMware Workstation Pro 16的安装包。‌下载链接为https://customerconnect.vmware.com/cn/downloads/info/slug/desktop_end_user_computing/vmware_workstation_pro…

关于LLC知识2

LLC拓扑如下图所示&#xff0c;虚线框住的是LLC的核心部分&#xff0c;前面的部分是把输入交流电压经过整流和滤波使得在进入LLC的时候是直流电压&#xff08;带有纹波&#xff09;&#xff0c;如果忽略纹波&#xff0c;那么给LLC供电的就是稳定的直流电压。 LLC的稳态分析即&a…

浅谈线程组插件之jp@gc - Stepping Thread Group

浅谈线程组插件之jpgc - Stepping Thread Group jpgc - Stepping Thread Group 是一个高级线程组插件&#xff0c;专为Apache JMeter设计。相较于JMeter自带的基本线程组&#xff0c;此插件提供了更灵活、更精细的用户模拟方式&#xff0c;特别适合于模拟真实用户逐步增加的场…

MySQL--数据库备份

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、为什么要备份 备份&#xff1a;能够防止由于机械故障以及人为误操作带来的数据丢失&#xff0c;例如将数据库文件保存在了其它地方。 冗余&#…

密码学基础:搞懂Hash函数SHA1、SHA-2、SHA3(2)

目录 1.引入 2. SHA512-224\256 3.SHA-3 4.MD5 5.SM3 1.引入 上篇密码学基础&#xff1a;搞懂Hash函数SHA1、SHA-2、SHA3(1)-CSDN博客&#xff0c;我们先就将基础的SHA1\2讲解了&#xff0c;接下来我们继续聊SHA-3、SHA2变体SHA512_224\256等 2. SHA512-224\256 SHA512…

TPS和QPS达到多少才算高并发?

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

pytorch学习笔记3 tensor索引和切片

dim 0 占先 切片 &#xff08;前N或者后N个&#xff09; &#xff1a;2 表示 0到2&#xff08;不包含2&#xff09;&#xff0c; 1&#xff1a;表示 1到末尾&#xff0c; -1表示最后一个元素&#xff0c;-2表示倒数第二个 0:28:2 表示从0到27隔点采样 &#xff1a;&#xff…

AC+AP组网

配置DHCP Switch1 <Huawei>sys [Huawei]undo in en [Huawei]vlan batch 10 20 30 40[Huawei]int vlan 10 [Huawei-Vlanif10]ip add 192.168.10.1 24 [Huawei-Vlanif10]quit[Huawei]int vlan 20 [Huawei-Vlanif20]ip add 192.168.20.1 24 [Huawei-Vlanif20]quit[Huawei]…

华水2022年专升本计算机培养方案

华水2022年专升本计算机培养方案 文章目录 华水2022年专升本计算机培养方案计科第一学期第二学期第三学期第四学期 软工第一学期第二学期第三学期第四学期 计科 第一学期 通识必修课 大学外语线性代数离散数学 专业基础课 高级语言程序设计 专业选修课 Java 第二学期 通识…

centos7安装zabbix

可以联网的centos7系统 关闭防火墙 selinux也关了 1、配置镜像源 wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo2、安装nginx并配置 yum ins…

基于SpringBoot+Vue的科研管理系统(带1w+文档)

基于SpringBootVue的科研管理系统(带1w文档) 基于SpringBootVue的科研管理系统(带1w文档) 科研的管理系统设计过程中采用Java开发语言,B/S结构&#xff0c;采取springboot框架&#xff0c;并以MySql为数据库进行开发。结合以上技术&#xff0c;对本系统的整体、数据库、功能模块…

如何使用nodejs的fsPromise.access()判断文件权限

同学们可以私信我加入学习群&#xff01; 正文开始 一种错误示范fsPromise.access正确的书写总结 一种错误示范 我们操作文件的时候&#xff0c;经常需要提前判断文件的状态&#xff1a;文件是否存在、文件是否可读、文件是否可写。 查看官网介绍后&#xff0c;按照我们平时的…

数学建模评价类—Topsis法

目录 文章目录 前言 切记&#xff1a;以下内容仅用于参考理解&#xff0c;不可用于数模竞赛&#xff01;&#xff01;&#xff01; 一、Topsis的基本原理 二、Topsis的建模过程 1.判断矩阵是否需要正向化 2.原始矩阵正向化 3.矩阵标准化 4.计算距离&#xff0c;给出得…

FPGA的工作本科可以做吗?

在FPGA行业中&#xff0c;这样的偏见一直存在。 很多人认为&#xff0c;只有985、211的硕士才有资格涉足这一领域&#xff0c;甚至有人表示&#xff0c;即使是9、2本硕也难以找到工作&#xff0c;本科生就不要想了。 难到真的只有985&#xff0c;211的研究生才能有机会入行FPG…

安卓常用控件ListView

文章目录 ListView的常用属性ListView的常用APIListView的简单使用 ListView是一个列表样式的 ViewGroup&#xff0c;将若干 item 按行排列。它是一个很基本的控件也是 Android 中最重要的控件之一。它可以实现多个 View 的垂直排列并支持滚动显示效果。 ListView的常用属性 常…

农场游戏中的时间管理实例

一、准备工作 在Unity中创建承载日期和时间的文本 二、设置游戏的时间戳 using System.Collections; using System.Collections.Generic; using UnityEngine; //标识这个类可以被序列化 [System.Serializable] public class GameTimestamp {// 游戏时间戳的成员变量public in…

鸿蒙next 评分组件来了 我不允许你不会

前言导读 各位同学大家,有段时间没有跟大家见面了,因为最近一直在更新鸿蒙的那个实战课程所以就没有去更新文章实在是不好意思, 所以今天就给大家更新一期实战案例 评分组件 希望帮助到各位同学工作和学习 效果图 接口 Rating(options?: { rating: number, indicator?:…

48天笔试训练错题——day40

目录 选择题 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 编程题 1. 发邮件 2. 最长上升子序列 选择题 1. DNS 劫持又称域名劫持&#xff0c;是指在劫持的网络范围内拦截域名解析的请求&#xff0c;分析请求的域名&#xff0c;把审查范围以外的请求放行&#xff0c;否则返回…

开关电源之电压的影响因素和指标

开关电源并不是一个简单的小盒子&#xff0c;它相当于有源器件的心脏&#xff0c;不断地为元件提供能量。电源质量的好坏直接影响到元器件的性能。开关电源的设计、制造和质量管理需要精密的电子仪器来模拟电源的实际工作特性&#xff08;即各种规格&#xff09;&#xff0c;经…

docker、k8s部署 mysql group replication 和 ProxySQL 读写分离

MySQL Group Replication&#xff08;简称MGR&#xff09;是MySQL官方推出的一个高可用与高扩展的解决方案。MySQL组复制它提供了高可用、高扩展、高可靠的MySQL集群服务&#xff0c;这里部署的 mysql 版本 5.7.33&#xff0c;架构是一读一写。特别要注意一个关键点: 必须保证各…