Skip to content

Commit 3aa3bf8

Browse files
Merge pull request #18 from multiversx/hw-04
Example for signing guarded transactions via Ledger
2 parents e3f97d8 + 4eae65f commit 3aa3bf8

File tree

6 files changed

+125
-34
lines changed

6 files changed

+125
-34
lines changed

signing-providers/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ npm run build
3030
Start the server (with a HTTPS binding):
3131

3232
```bash
33-
http-server -S -C ./dummy-certificate.pem -K ./dummy-certificate-key.pem --port=8080
33+
http-server -c-1 -S -C ./dummy-certificate.pem -K ./dummy-certificate-key.pem --port=8080
3434
```
3535

3636
Afterwards, navigate to [https://localhost:8080/index.html](https://localhost:8080/index.html).

signing-providers/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ <h3>Hardware Wallet</h3>
132132

133133
<div>
134134
<button class="btn btn-info" onclick="hw.signTransaction()">Sign transaction</button>
135+
<button class="btn btn-info" onclick="hw.signGuardedTransaction()">Sign guarded
136+
transaction</button>
135137
<button class="btn btn-info" onclick="hw.signTransactions()">Sign transactions</button>
136138
<button class="btn btn-info" onclick="hw.signMessage()">Sign
137139
message</button>

signing-providers/package-lock.json

Lines changed: 58 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

signing-providers/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
"author": "MultiversX",
1010
"dependencies": {
1111
"@multiversx/sdk-wallet": "4.0.0",
12-
"@multiversx/sdk-core": "12.0.1-beta.4",
12+
"@multiversx/sdk-core": "12.1.0",
1313
"@multiversx/sdk-extension-provider": "2.0.7",
14-
"@multiversx/sdk-hw-provider": "3.0.3",
14+
"@multiversx/sdk-hw-provider": "4.0.0",
1515
"@multiversx/sdk-web-wallet-provider": "2.3.0",
1616
"@multiversx/sdk-wallet-connect-provider": "3.2.0",
1717
"qrcode": "1.5.1",

signing-providers/src/backendFacade.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ export function verifyAuthTokenSignature(address, authToken, signature) {
1919
const verifier = UserVerifier.fromAddress(new Address(address));
2020

2121
const message = new SignableMessage({
22-
signature: { hex: () => signature },
2322
message: Buffer.from(`${address}${authToken}{}`)
2423
});
2524

26-
const ok = verifier.verify(message);
25+
const serializedMessage = message.serializeForSigning();
26+
const ok = verifier.verify(serializedMessage, Buffer.from(signature, "hex"));
2727
if (ok) {
2828
return `The bearer of the token [${authToken}] is also the owner of the address [${address}].`;
2929
}

signing-providers/src/hw.js

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Address, SignableMessage, Transaction, TransactionPayload } from "@multiversx/sdk-core";
1+
import { Address, SignableMessage, Transaction, TransactionOptions, TransactionPayload, TransactionVersion } from "@multiversx/sdk-core";
22
import { HWProvider } from "@multiversx/sdk-hw-provider";
33
import { acquireThirdPartyAuthToken, verifyAuthTokenSignature } from "./backendFacade";
44

@@ -15,7 +15,9 @@ export class HW {
1515

1616
await this.provider.login({ addressIndex: addressIndex });
1717

18-
alert(`Logged in. Address: ${await this.provider.getAddress()}`);
18+
const address = await this.provider.getAddress();
19+
20+
this.displayOutcome("Logged in. Address:", address);
1921
}
2022

2123
async loginWithToken() {
@@ -27,9 +29,10 @@ export class HW {
2729
const authToken = acquireThirdPartyAuthToken();
2830
const payloadToSign = Buffer.from(`${authToken}{}`);
2931
const { address, signature } = await this.provider.tokenLogin({ addressIndex: addressIndex, token: payloadToSign });
32+
const verifyResult = verifyAuthTokenSignature(address, authToken, signature.hex());
3033

31-
alert(`Logged in.\nAddress: ${address}\nSignature: ${signature.hex()}`);
32-
alert(verifyAuthTokenSignature(address, authToken, signature.hex()));
34+
this.displayOutcome(`Logged in.\nAddress: ${address}\nSignature: ${signature.hex()}`);
35+
this.displayOutcome(`Verification result: ${verifyResult}`);
3336
}
3437

3538
async displayAddresses() {
@@ -47,7 +50,7 @@ export class HW {
4750

4851
await this.provider.setAddressIndex(addressIndex);
4952

50-
alert(`Address has been set: ${await this.provider.getAddress()}.`);
53+
this.displayOutcome(`Address has been set: ${await this.provider.getAddress()}.`)
5154
}
5255

5356
async signTransaction() {
@@ -66,7 +69,7 @@ export class HW {
6669

6770
await this.provider.signTransaction(transaction);
6871

69-
alert(JSON.stringify(transaction.toSendable(), null, 4));
72+
this.displayOutcome("Transaction signed.", transaction.toSendable());
7073
}
7174

7275
async signTransactions() {
@@ -100,7 +103,39 @@ export class HW {
100103
const transactions = [firstTransaction, secondTransaction];
101104
await this.provider.signTransactions(transactions);
102105

103-
alert(JSON.stringify([firstTransaction.toSendable(), secondTransaction.toSendable()], null, 4));
106+
this.displayOutcome("Transactions signed.", transactions.map((transaction) => transaction.toSendable()));
107+
}
108+
109+
async signGuardedTransaction() {
110+
try {
111+
await this.doSignGuardedTransaction();
112+
} catch (error) {
113+
this.displayError(error);
114+
}
115+
}
116+
117+
async doSignGuardedTransaction() {
118+
await this.provider.init();
119+
120+
const sender = await this.provider.getAddress();
121+
const transaction = new Transaction({
122+
nonce: 42,
123+
value: "1",
124+
gasLimit: 200000,
125+
sender: Address.fromBech32(sender),
126+
receiver: Address.fromBech32("erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa"),
127+
guardian: Address.fromBech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"),
128+
data: new TransactionPayload("hello"),
129+
chainID: "T",
130+
version: TransactionVersion.withTxOptions(),
131+
options: TransactionOptions.withOptions({
132+
guarded: true
133+
})
134+
});
135+
136+
await this.provider.signTransaction(transaction);
137+
138+
this.displayOutcome("Transaction signed.", transaction.toSendable());
104139
}
105140

106141
async signMessage() {
@@ -111,6 +146,23 @@ export class HW {
111146
});
112147

113148
await this.provider.signMessage(message);
114-
alert(JSON.stringify(message, null, 4));
149+
150+
this.displayOutcome("Message signed.", message);
151+
}
152+
153+
displayOutcome(message, outcome) {
154+
if (!outcome) {
155+
console.log(message);
156+
alert(message);
157+
return;
158+
}
159+
160+
console.log(message, outcome);
161+
alert(`${message}\n${JSON.stringify(outcome, null, 4)}`);
162+
}
163+
164+
displayError(error) {
165+
console.error(error);
166+
alert(`Error: ${error}`);
115167
}
116168
}

0 commit comments

Comments
 (0)