WalletConnect C++开发包
WalletConnect C++开发包完整实现WallectConnect协议,可以为C++应用快速添加对 以太坊等EVM兼容区块链的支持能力。
一键发币: SOL | BNB | ETH | BASE | Blast | ARB | OP | POLYGON | AVAX | FTM | OK
WalletConnect C++开发包完整实现WallectConnect协议,可以为C++应用快速添加对 以太坊等EVM兼容区块链的支持能力,适用于Web3应用开发的学习与实践。下载请联系邮箱: kukapaycrypto#gmail.com
。
1、概述
WalletConnect C++开发包主要特性如下:
- 支持以太坊及EVM兼容区块链,例如BSC、Polygon、Fantom等
- 支持Metamask、imtoken等多种区块链钱包
- 内置ABI编解码器,支持以太坊及EVM兼容链智能合约的部署、读取及交易
- 内置ERC20和ERC721规范支持
WalletConnect C++开发包当前版本1.0.0,运行于64位Windows环境,主要类及关系如下图所示:
WalletConnect C++开发包的主要代码文件清单如下:
代码文件 | 说明 |
---|---|
WalletConnect/WalletConnect.sln | WalletConnect解决方案文件 |
WalletConnect/WalletConnect/WalletConnect.vcxproj | WalletConnect DLL库项目文件 |
WalletConnect/WalletConnect/WalletConnect.h | 库入口类C++头文件 |
WalletConnect/WalletConnect/WalletConnect.cpp | 库入口类C++实现文件 |
WalletConnect/WalletConnect/ClientMeta.h | 客户端元信息C++头文件 |
WalletConnect/WalletConnect/ClientMeta.cpp | 客户端元信息C++实现文件 |
WalletConnect/WalletConnect/Erc20.h | ERC20合约类C++头文件 |
WalletConnect/WalletConnect/Erc20.cpp | ERC20合约类C++实现文件 |
WalletConnect/WalletConnect/Erc721.h | ERC721合约类C++头文件 |
WalletConnect/WalletConnect/Erc721.cpp | ERC721合约类C++实现文件 |
WalletConnect/WalletConnect/Contract.h | 智能合约类C++头文件 |
WalletConnect/WalletConnect/Contract.cpp | 智能合约类C++实现文件 |
WalletConnect/WalletConnect/EthAbi.h | Solidity ABI编解码器类C++头文件 |
WalletConnect/WalletConnect/EthAbi.cpp | Solidity ABI编解码器类C++实现文件 |
WalletConnect/WalletConnect/AbiType.h | Solidity ABI数据类型C++头文件 |
WalletConnect/WalletConnect/AbiType.cpp | Solidity ABI数据类型C++实现文件 |
WalletConnect/WalletConnect/JsonRpcClient.h | JsonRpc客户端类C++头文件 |
WalletConnect/WalletConnect/JsonRpcClient.cpp | JsonRpc客户端类C++实现文件 |
WalletConnect/WalletConnect/SocketClient.h | Socket传输类头C++文件 |
WalletConnect/WalletConnect/SocketClient.cpp | Socket传输类C++实现文件 |
WalletConnect/WalletConnect/CryptoLib.h | 密码学算法类C++头文件 |
WalletConnect/WalletConnect/CryptoLib.cpp | 密码学算法类C++实现文件 |
WalletConnect/WalletConnect/QrCodeGen.h | QR二维码生成器C++头文件 |
WalletConnect/WalletConnect/QrCodeGen.cpp | QR二维码生成器C++实现文件 |
WalletConnect/Demo/Demo.vcxprj | 演示项目文件 |
WalletConnect/Demo/Demo.cpp | 演示代码实现文件 |
WalletConnect/SmartContract/ | 演示用合约目录 |
2、使用示例代码
2.1 连接手机钱包
第一次运行Demo演示项目时,将弹出二维码提示扫码连接钱包:
使用MetaMask等手机钱包扫描二维码并确认连接后,可以看到终端显示授权成功:
2.2 原生token的余额查询和转账交易
在command>
下输入native
,然后按回车,将演示原生token的余额查询和转账交易。
演示程序首先显示所连接手机钱包账户的余额,然后执行一个转账交易:
注意:执行转账时,将在手机钱包弹出提示信息,确认后即可完成交易。如果在手机钱包的提示中选择拒绝, 则终端提示如下:
2.3 部署ERC20合约
在command>
下输入deploy erc20
,然后按回车,将演示ERC20合约的部署:
注意:合约部署也是交易,因此将在手机钱包弹出提示信息,需确认后才可完成合约部署交易。
2.4 ERC20 token的查询和转账
在command>
下输入erc20
,然后按回车,将演示ERC20 token的余额查询和转账交易:
注意:Erc20 token转账时,需在手机钱包中确认弹出的提示信息。
2.5 部署ERC721合约
在command>
下输入deploy erc721
,然后按回车,将演示ERC721合约的部署:
注意:合约部署也是交易,因此将在手机钱包弹出提示信息,需确认后才可完成合约部署交易。
2.6 ERC721 token的查询和转账
在command>
下输入erc721
,然后按回车,将演示ERC721 token的余额查询和转账交易:
注意:Erc721 token转账时,需在手机钱包中确认弹出的提示信息。
3、使用WalletConnect
WalletConnect协议可以帮助桌面PC应用利用手机钱包完成区块链的访问,其时序如下图所示:
WalletConnect是入口类,可以利用它完成协议会话的建立,并在此会话基础上,完成余额查询、 转账、部署合约、合约调用等任务。
3.1 WalletConnect的实例化
创建WalletConnect实例需要传入一个描述应用的ClientMeta对象。例如,下面的代码使用指定 的ClientMeta创建一个新的WalletConnect实例:
ClientMeta meta(
"sample app", //名称
"http://app.mysite.com", //网址
{"http://app.mysite.com/icon.ico"}, //图标集
"my first c++ blockchain app" //描述信息
);
WalletConnect wc(meta); //创建WalletConnect对象
ClientMeta对象包含四个字段:
- name:应用名称,字符串。
- url:应用的线上地址,也作为应用的唯一标识符,字符串。
- icons:应用的图标地址,可多个,字符串数组。
- description:应用的描述信息,字符串。
当应用通过WalletConnect协议提交交易时,该名称将出现在手机钱包的提示信息中心。
3.2 创建协议会话
使用WalletConnect对象的createSession()
方法创建与WalletConnect服务器和手机钱包的 三方会话连接,在此过程中,WalletConnect对象将调用开发者提供的DisplayQrCode
事件处理 代码,开发者应当向用户展示可供手机钱包扫描的二维码。
例如,下面的代码在DisplayQrCode
事件处理中将传入的二维码对象转换为SVG文件并打开该文件, 以便用户扫码确认连接:
if(!wc.isConnected()) //仅当未建立会话时执行
{
wc.addEventListener<void(QrCode)>(
"DisplayQrCode", //监听DisplayQrCode事件
[](QrCode qrc){ //事件处理程序
std::ofstream fout("wc.svg");
fout << qrc.toSVG(); //将二维码转为SVG写入文件
fout.close();
ShellExecuteA(NULL, "open", "wc.svg", NULL, NULL, SW_SHOW); //打开生成的SVG文件
}
);
wc.createSession(); //创建三方会话
}
用户使用手机钱包扫码后,将在手机钱包上弹出连接请求信息,用户确认后即完成会话的建立。 使用WalletConnect对象的getAccount()
方法可查询当前连接的账号:
if(wc.isConnected())
{
std::cout << wc.getAccount() << std::endl;
}
3.3 原生token的查询和转账
当会话建立后,可以利用WalletConnect对象查询原生token的余额或提交转账等交易。
例如,下面的代码利用getBalance()
方法查询当前所连接账号的余额:
u256 balance = wc.getBalance(wc.getAccount());
std::cout << "balance: " << balance << std::endl;
u256
表示256bits(32 bytes)的无符号整数,对应EVM虚拟机中的u256类型。
使用WalletConnect对象的transfer()
方法向指定账号进行转账,并返回交易ID。 例如:
std::string txid = wc.transfer( //转账
"0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", //目标地址
u256("1000000000") //转账数量
);
std::cout << "txid: " << txid << std::endl;
3.4 ERC20 token的查询、转账
WalletConnect对象的erc20()
方法返回一个Erc20
对象,可用于ERC20 token的 查询与转账。
例如,下面的代码读取指定ERC20 token的基本信息、查询当前账号的余额,并向其他账号转账:
Erc20 token = wc.erc20(
"0xcfeb869f69431e42cdb54a4f4f105c19c080a601" //ERC20 token的地址
);
std::string name = token.name(); //查询名称
std::string symbol = token.symbol(); //查询符号
int decimals = token.decimals(); //查询小数位数
u256 balance = token.balanceOf(wc.getAccount()); //查询余额
std::string txid = token.transfer( //转账
"0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", //目标地址
u256("1000000000") //转账数量
);
3.5 ERC721 token的查询与转账
WalletConnect对象的erc721()
方法返回一个Erc721
对象,可用于ERC721 token的 查询与交易。
例如,下面的代码读取指定ERC721 token的基本信息、铸造并转账:
Erc721 token = wc.erc721(
"0xe982e462b094850f12af94d21d470e21be9d0e9c" //ERC721 token的地址
);
std::cout << "name" << token.name() << std::endl; //显示名称
std::cout << "symbol" << token.symbol() << std::endl; //显示符号
std::string txid = token.min( //铸造NFT
wc.getAccount() //接收账号
);
wc.waitForReceipt(txid); //等待交易确认
u256 id = token.totalSupply(); //读取NFT ID
std::cout << "owner: " << token.ownerOf(id) << std::endl; //显示持有NFT的账号
txid = token.transferFrom( //转账
wc.getAccount(), //转出账号
"0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", //转入账号
id //NFT ID
);
wc.waitForReceipt(txid); //等待交易确认
std::cout << "owner: " << token.ownerOf(id) << std::endl; //显示持有NFT的账号
3.6 查询合约事件
使用Erc20、Erc721等合约对象的getEvents()
方法查询指定区块范围内触发的合约事件, 例如查询最近10个区块的事件:
u256 lastblk = wc.blockNumber(); //读取最新区块高度
auto events = token.getEvents(lastblk - 10, lastblk); //查询事件
for(int i=0;i<events.size();i++){ //遍历返回的事件
std::cout << "event: " << events[i].name << std::endl; //显示事件名称
for(int j=0;j<events[i].params.size();j++){ //遍历事件参数
std::cout << j << ": "
<< events[i].params[j].toString() //显示ABI解码后的参数值
<< std::endl;
}
}
3.7 部署合约
使用WalletConnect对象的deployContract()
方法部署智能合约,需要传入合约编译后生成 的ABI和字节码。
例如,下面的代码部署合约并显示最终的部署地址:
std::string abi = "..."; //合约abi
std::string bin = "..."; //合约字节码
std::string txid = wc.deployContract(abi, bin); //部署合约
auto receipt = wc.waitForReceipt(txid);
std::cout << "deployed at: "
<< receipt["contractAddress"].get<std::string>() //显示部署地址
<< std::endl;
如果合约的构造函数需要参数,可以直接在deployContract()
的参数列表中追加。 例如:
std::string txid = wc.deployContract(
abi, bin, //ABI和字节码
param1, param2, param3 //构造函数参数
)
3.8 WallectConnect事件监听
WallectConnect对象提供了addEventListener()
方法用于监听会话过程中的事件:
- ConnectionOpened
当与服务器成功建立Socket连接时触发。例如:
wc.addEventListener<void()>("ConnectionOpened", [](){
std::cout << "connection opened" << std::endl;
});
- ConnectionClosed
当与服务器的Socket连接关闭时触发。例如:
wc.addEventListener<void()>("ConnectionClosed", [](){
std::cout << "connection closed" << std::endl;
});
- ConnectionFailed
当与服务器的Socket连接失败时触发。例如:
wc.addEventListener<void()>("ConnectionFailed", [](){
std::cout << "connection failed" << std::endl;
});
- SessionApproved
当用户在手机钱包中确认三方会话时触发。例如:
wc.addEventListener<void(int, std::vector<std::string>)>(
"SessionApproved", [](int chainId, std::vector<std::string>){
std::cout << "session approved" << std::endl;
std::cout << "chain id: " << chainId << std::endl;
std::cout << "accounts[0]: " << accounts[0] << std::endl;
});
- SessionRejected
当用户在手机钱包中拒绝三方会话时触发。例如:
wc.addEventListener<void()>("SessionRejected", [](){
std::cout << "session rejected" << std::endl;
});
- SessionUpdated
当用户在手机钱包中切换账号或切换接入的区块链时触发。例如:
wc.addEventListener<void(int, std::vector<std::string>)>(
"SessionUpdated", [](int chainId, std::vector<std::string>){
std::cout << "session updated" << std::endl;
std::cout << "chain id: " << chainId << std::endl;
std::cout << "accounts[0]: " << accounts[0] << std::endl;
});
- SessionKilled
当用户在手机钱包中移除之前确认的三方会话时触发。例如:
wc.addEventListener<void()>("SessionKilled", [](){
std::cout << "session killed" << std::endl;
});