Skip to content

Commit 9eaa34d

Browse files
Problem: missing verification api for wc 2.0 (fix #474) (#475)
feat: enable personal signing in web3_v2.rs example feat: Add personal signature verification method feat: Update wallet_connect.cc to use Walletconnect2Client feat: Update wallet_connect.cc to use Walletconnect2Client tidy up reformat change warning error level chore: update cargo test command in CI workflow chore: add RUSTFLAGS to enable dead code linting in CI workflow chore: enable dead code linting in CI workflow chore: update cargo test command in CI workflow chore: update clippy command in CI workflow feat: Update wallet_connect.cc to use Walletconnect2Client feat: Update wallet_connect.cc to improve personal message signing and verification feat: Fix c++ walletconnect example to use wc 2.0 and add verification for sign_personal feat: Remove unnecessary include in wallet_connect.cc
1 parent 3b41318 commit 9eaa34d

File tree

6 files changed

+94
-61
lines changed

6 files changed

+94
-61
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ jobs:
1919
check:
2020
name: cargo check
2121
runs-on: ubuntu-latest
22+
env:
23+
RUSTFLAGS: -A dead_code
2224
steps:
2325
- uses: actions/checkout@v3
2426
with:
@@ -35,6 +37,8 @@ jobs:
3537
test:
3638
name: cargo test
3739
runs-on: ubuntu-latest
40+
env:
41+
RUSTFLAGS: -A dead_code
3842
steps:
3943
- uses: actions/checkout@v3
4044
with:
@@ -73,6 +77,8 @@ jobs:
7377
clippy:
7478
name: cargo clippy
7579
runs-on: ubuntu-latest
80+
env:
81+
RUSTFLAGS: -A dead_code
7682
steps:
7783
- uses: actions/checkout@v3
7884
with:

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Changelog
22
## [Unreleased]
33

4+
## [v0.0.27-alpha] - 2004-5-22
5+
- fix c++ walletconnect example to use wc 2.0
6+
- add verification for sign_personal
7+
48
## [v0.0.26-alpha] - 2024-4-24
59
- fix null `data` field in wc 2.0
610

demo/examples/src/wallet_connect.cc

Lines changed: 43 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -34,35 +34,36 @@ rust::String address_to_hex_string(::std::array<::std::uint8_t, 20> bytes) {
3434
}
3535

3636
// if session already exists, restore session
37-
rust::Box<WalletconnectClient> make_new_client(std::string filename) {
37+
rust::Box<Walletconnect2Client> make_new_client(std::string filename) {
3838

3939
std::ifstream file(filename.c_str());
4040
if (file.is_open()) {
4141
std::string sessioninfostring((std::istreambuf_iterator<char>(file)),
4242
std::istreambuf_iterator<char>());
43-
rust::Box<WalletconnectClient> client =
44-
walletconnect_restore_client(sessioninfostring);
43+
rust::Box<Walletconnect2Client> client =
44+
walletconnect2_restore_client(sessioninfostring);
4545
return client;
4646
} else {
47-
rust::Box<WalletconnectClient> client = walletconnect_new_client(
48-
"Defi WalletConnect example.", "http://localhost:8080/",
49-
rust::Vec<rust::String>(), "Defi WalletConnect Web3 Example",
50-
338); // ChainId of Cronos Testnet
47+
std::string projectid = std::getenv("NEXT_PUBLIC_PROJECT_ID")
48+
? std::getenv("NEXT_PUBLIC_PROJECT_ID")
49+
: "";
50+
// assert projectid not ""
51+
assert(projectid != "");
52+
53+
rust::Box<Walletconnect2Client> client = walletconnect2_client_new(
54+
"wss://relay.walletconnect.org", projectid,
55+
"{\"eip155\":{\"methods\":[\"eth_sendTransaction\",\"eth_"
56+
"signTransaction\",\"eth_sign\",\"personal_sign\",\"eth_"
57+
"signTypedData\"],\"chains\":[\"eip155:338\"],\"events\":["
58+
"\"chainChanged\",\"accountsChanged\"]}}",
59+
"{\"description\":\"Defi WalletConnect v2 "
60+
"example.\",\"url\":\"http://localhost:8080/"
61+
"\",\"icons\":[],\"name\":\"Defi WalletConnect Web3 Example\"}");
5162
std::cout << "qrcode= " << client->get_connection_string() << std::endl;
5263

5364
return client;
5465
}
5566
}
56-
57-
class UserWalletConnectCallback : public WalletConnectCallback {
58-
public:
59-
UserWalletConnectCallback() {}
60-
virtual ~UserWalletConnectCallback() {}
61-
void onConnected(const WalletConnectSessionInfo &sessioninfo) const;
62-
void onDisconnected(const WalletConnectSessionInfo &sessioninfo) const;
63-
void onConnecting(const WalletConnectSessionInfo &sessioninfo) const;
64-
void onUpdated(const WalletConnectSessionInfo &sessioninfo) const;
65-
};
6667
void print_session(const WalletConnectSessionInfo &sessioninfo) {
6768
std::cout << "connected: " << sessioninfo.connected << std::endl;
6869
std::cout << "chain_id: " << sessioninfo.chain_id << std::endl;
@@ -78,50 +79,21 @@ void print_session(const WalletConnectSessionInfo &sessioninfo) {
7879
std::cout << "handshake_topic: " << sessioninfo.handshake_topic
7980
<< std::endl;
8081
}
81-
void UserWalletConnectCallback::onConnected(
82-
const WalletConnectSessionInfo &sessioninfo) const {
83-
std::cout << "user c++ onConnected" << std::endl;
84-
print_session(sessioninfo);
85-
}
86-
void UserWalletConnectCallback::onDisconnected(
87-
const WalletConnectSessionInfo &sessioninfo) const {
88-
std::cout << "user c++ onDisconnected" << std::endl;
89-
print_session(sessioninfo);
90-
exit(0);
91-
}
92-
void UserWalletConnectCallback::onConnecting(
93-
const WalletConnectSessionInfo &sessioninfo) const {
94-
std::cout << "user c++ onConnecting" << std::endl;
95-
print_session(sessioninfo);
96-
// !!! Important !!!
97-
// Comment out this line for actual test
98-
exit(0);
99-
}
100-
void UserWalletConnectCallback::onUpdated(
101-
const WalletConnectSessionInfo &sessioninfo) const {
102-
std::cout << "user c++ onUpdated" << std::endl;
103-
print_session(sessioninfo);
104-
}
10582

10683
int main(int argc, char *argv[]) {
10784
std::string filename = "sessioninfo.json";
10885
try {
109-
rust::Box<WalletconnectClient> client = make_new_client(filename);
110-
WalletConnectCallback *usercallbackraw =
111-
new UserWalletConnectCallback();
112-
std::unique_ptr<WalletConnectCallback> usercallback(usercallbackraw);
113-
client->setup_callback_blocking(std::move(usercallback));
86+
rust::Box<Walletconnect2Client> client = make_new_client(filename);
11487

11588
// Print the QR code on terminal
11689
rust::String uri = client->print_uri();
11790

11891
// program is blocked here for waiting connecting
119-
WalletConnectEnsureSessionResult result =
120-
client->ensure_session_blocking();
92+
WalletConnect2EnsureSessionResult result =
93+
client->ensure_session_blocking(60000);
12194

12295
// once connected, program continues
123-
std::cout << "connected chain_id: " << result.chain_id << std::endl;
124-
assert(result.addresses.size() > 0);
96+
assert(result.eip155.accounts.size() > 0);
12597

12698
// get the connected session info as string and save it into a file
12799
rust::String sessioninfo = client->save_client();
@@ -138,11 +110,21 @@ int main(int argc, char *argv[]) {
138110
// sign personal message
139111
if (test_personal) {
140112
/* message signing */
141-
rust::Vec<uint8_t> sig1 = client->sign_personal_blocking(
142-
"hello", result.addresses[0].address);
113+
::std::uint64_t testchainid = result.eip155.accounts[0].chain_id;
114+
::std::array<::std::uint8_t, 20> testaddress =
115+
result.eip155.accounts[0].address.address;
116+
std::cout << "chainid=" << testchainid << std::endl;
117+
std::cout << "address="
118+
<< address_to_hex_string(testaddress).c_str()
119+
<< std::endl;
120+
rust::Vec<uint8_t> sig1 =
121+
client->sign_personal_blocking("hello", testaddress);
143122
std::cout << "signature=" << bytes_to_hex_string(sig1).c_str()
144123
<< std::endl;
145124
std::cout << "signature length=" << sig1.size() << std::endl;
125+
bool verifyresult =
126+
client->verify_personal_blocking("hello", sig1, testaddress);
127+
std::cout << "verify result=" << verifyresult << std::endl;
146128
}
147129

148130
// send transaction
@@ -166,12 +148,13 @@ int main(int argc, char *argv[]) {
166148
// info.to = "0x....";
167149
info.to = rust::String(
168150
std::string("0x") +
169-
address_to_hex_string(result.addresses[0].address).c_str());
151+
address_to_hex_string(result.eip155.accounts[0].address.address)
152+
.c_str());
170153
info.value = "1000000000000000000"; // 1 TCRO
171-
info.common.chainid = result.chain_id;
154+
info.common.chainid = result.eip155.accounts[0].chain_id;
172155
rust::Vec<uint8_t> tx_hash =
173156
client->send_eip155_transaction_blocking(
174-
info, result.addresses[0].address);
157+
info, result.eip155.accounts[0].address.address);
175158

176159
std::cout << "transaction_hash="
177160
<< bytes_to_hex_string(tx_hash).c_str() << std::endl;
@@ -205,7 +188,8 @@ int main(int argc, char *argv[]) {
205188
assert(erc20.decimals() == 18);
206189
rust::String from_address = rust::String(
207190
std::string("0x") +
208-
address_to_hex_string(result.addresses[0].address).c_str());
191+
address_to_hex_string(result.eip155.accounts[0].address.address)
192+
.c_str());
209193
U256 erc20_balance = erc20.balance_of(from_address);
210194
std::cout << "erc20 balance=" << erc20_balance.to_string()
211195
<< std::endl;
@@ -222,13 +206,14 @@ int main(int argc, char *argv[]) {
222206
}
223207
})";
224208

225-
common.chainid = result.chain_id;
209+
common.chainid = result.eip155.accounts[0].chain_id;
226210
common.web3api_url =
227211
"https://evm-dev-t3.cronos.org"; // TODO unnessary for
228212
// walletconnect
229213

230214
rust::Vec<uint8_t> tx_hash = client->send_contract_transaction(
231-
contract_action, common, result.addresses[0].address);
215+
contract_action, common,
216+
result.eip155.accounts[0].address.address);
232217

233218
std::cout << "transaction_hash="
234219
<< bytes_to_hex_string(tx_hash).c_str() << std::endl;

extra-cpp-bindings/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,13 @@ mod ffi {
347347
message: String,
348348
address: [u8; 20],
349349
) -> Result<Vec<u8>>;
350+
/// verify message
351+
pub fn verify_personal_blocking(
352+
self: &mut Walletconnect2Client,
353+
message: String,
354+
signature_bytes: Vec<u8>,
355+
user_address: [u8; 20],
356+
) -> Result<bool>;
350357
pub fn ping_blocking(self: &mut Walletconnect2Client, waitmillis: u64) -> Result<String>;
351358

352359
/// build cronos(eth) eip155 transaction

extra-cpp-bindings/src/walletconnect2.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,25 @@ impl Walletconnect2Client {
141141
}
142142
}
143143

144+
// signature: 65 bytes (r:32, s:32,v:1)
145+
pub fn verify_personal_blocking(
146+
&mut self,
147+
message: String,
148+
signature_bytes: Vec<u8>,
149+
user_address: [u8; 20],
150+
) -> Result<bool> {
151+
let address = ethers::types::Address::from_slice(&user_address);
152+
let signature = Signature::try_from(signature_bytes.as_slice())
153+
.map_err(|e| anyhow!("Invalid signature: {}", e))?;
154+
155+
Ok(signature.verify(message, address).is_ok())
156+
}
157+
158+
// signature
159+
// r: 32 bytes
160+
// s: 32 bytees
161+
// v: 1 byte
162+
// total 65 bytes
144163
pub fn sign_personal_blocking(
145164
&mut self,
146165
message: String,

wallet-connect/examples/web3_v2.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
264264
};
265265

266266
let test_ping = false;
267-
let test_personal_signing = false;
267+
let test_personal_signing = true;
268268
let test_sign_tx = false;
269-
let test_send_tx = true;
269+
let test_send_tx = false;
270270
let test_send_typedtx = false;
271271
let test_event_listening = false;
272272

@@ -288,9 +288,21 @@ async fn main() -> Result<(), Box<dyn Error>> {
288288
}
289289
if test_personal_signing {
290290
// 0xaddress
291+
let message = "Hello Crypto";
291292
let address1 = namespaces.get_ethereum_addresses()[0].address.clone();
292-
let sig1 = client.personal_sign("Hello Crypto", &address1).await?;
293+
let sig1 = client.personal_sign(message, &address1).await?;
293294
println!("sig1: {:?}", sig1);
295+
296+
// Verify the signature
297+
let signer = sig1.verify(message, address1);
298+
match signer {
299+
Ok(_) => {
300+
println!("Signature verified");
301+
}
302+
Err(err) => {
303+
println!("Error verifying signature: {:?}", err);
304+
}
305+
}
294306
}
295307

296308
if test_sign_tx {

0 commit comments

Comments
 (0)