@aptos-labs/wallet-adapter-core 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @aptos-labs/wallet-adapter-core
2
2
 
3
+ ## 0.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - d4e298f: Support Lodable wallet
8
+ Implement multi signature verification
9
+ Add a new optional property propertyName for multi-chain wallet
10
+ - 5fc6981: Throw wallet not found error when trying to connect to an uninstalled wallet
11
+ - d711f43: Import tweetnacl package via default export to support commonJS
12
+
3
13
  ## 0.2.1
4
14
 
5
15
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -66,6 +66,7 @@ interface AdapterPluginProps<Name extends string = string> {
66
66
  name: WalletName<Name>;
67
67
  url: string;
68
68
  icon: `data:image/${"svg+xml" | "webp" | "png" | "gif"};base64,${string}`;
69
+ providerName?: string;
69
70
  provider: any;
70
71
  connect(): Promise<any>;
71
72
  disconnect: () => Promise<any>;
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ module.exports = __toCommonJS(src_exports);
35
35
  // src/WalletCore.ts
36
36
  var import_aptos = require("aptos");
37
37
  var import_eventemitter3 = __toESM(require("eventemitter3"));
38
- var import_tweetnacl = require("tweetnacl");
38
+ var import_tweetnacl = __toESM(require("tweetnacl"));
39
39
  var import_buffer = require("buffer");
40
40
 
41
41
  // src/constants.ts
@@ -200,12 +200,15 @@ var WalletCore = class extends import_eventemitter3.default {
200
200
  scopePollingDetectionStrategy() {
201
201
  var _a;
202
202
  (_a = this._wallets) == null ? void 0 : _a.forEach((wallet) => {
203
- wallet.readyState = typeof window === "undefined" || typeof document === "undefined" ? "Unsupported" /* Unsupported */ : "NotDetected" /* NotDetected */;
203
+ if (!wallet.readyState) {
204
+ wallet.readyState = typeof window === "undefined" || typeof document === "undefined" ? "Unsupported" /* Unsupported */ : "NotDetected" /* NotDetected */;
205
+ }
204
206
  if (typeof window !== "undefined") {
205
207
  scopePollingDetectionStrategy(() => {
206
- if (Object.keys(window).includes(wallet.name.toLowerCase())) {
208
+ const providerName = wallet.providerName || wallet.name.toLowerCase();
209
+ if (Object.keys(window).includes(providerName)) {
207
210
  wallet.readyState = "Installed" /* Installed */;
208
- wallet.provider = window[wallet.name.toLowerCase()];
211
+ wallet.provider = window[providerName];
209
212
  this.emit("readyStateChange", wallet);
210
213
  return true;
211
214
  }
@@ -276,10 +279,9 @@ var WalletCore = class extends import_eventemitter3.default {
276
279
  const selectedWallet = (_a = this._wallets) == null ? void 0 : _a.find(
277
280
  (wallet) => wallet.name === walletName
278
281
  );
279
- if (!selectedWallet)
280
- return;
281
- if (selectedWallet.readyState !== "Installed" /* Installed */)
282
- return;
282
+ if (!selectedWallet || selectedWallet.readyState !== "Installed" /* Installed */ && selectedWallet.readyState !== "Loadable" /* Loadable */) {
283
+ throw new WalletConnectionError(`${walletName} wallet not found`).message;
284
+ }
283
285
  if (this._connected) {
284
286
  await this.disconnect();
285
287
  }
@@ -389,12 +391,42 @@ var WalletCore = class extends import_eventemitter3.default {
389
391
  throw new WalletSignMessageAndVerifyError("Failed to sign a message").message;
390
392
  let verified = false;
391
393
  if (Array.isArray(response.signature)) {
394
+ const { fullMessage, signature, bitmap } = response;
395
+ if (bitmap) {
396
+ const minKeysRequired = this._account.minKeysRequired;
397
+ if (signature.length < minKeysRequired) {
398
+ verified = false;
399
+ } else {
400
+ const bits = Array.from(bitmap).flatMap(
401
+ (n) => Array.from({ length: 8 }).map((_, i) => n >> i & 1)
402
+ );
403
+ const index = bits.map((_, i) => i).filter((i) => bits[i]);
404
+ const publicKeys = this._account.publicKey;
405
+ const matchedPublicKeys = publicKeys.filter(
406
+ (_, i) => index.includes(i)
407
+ );
408
+ verified = true;
409
+ for (let i = 0; i < signature.length; i++) {
410
+ const isSigVerified = import_tweetnacl.default.sign.detached.verify(
411
+ import_buffer.Buffer.from(fullMessage),
412
+ import_buffer.Buffer.from(signature[i], "hex"),
413
+ import_buffer.Buffer.from(matchedPublicKeys[i], "hex")
414
+ );
415
+ if (!isSigVerified) {
416
+ verified = false;
417
+ break;
418
+ }
419
+ }
420
+ }
421
+ } else {
422
+ throw new WalletSignMessageAndVerifyError("Failed to get a bitmap").message;
423
+ }
392
424
  } else {
393
425
  const currentAccountPublicKey = new import_aptos.HexString(
394
426
  this._account.publicKey
395
427
  );
396
428
  const signature = new import_aptos.HexString(response.signature);
397
- verified = import_tweetnacl.sign.detached.verify(
429
+ verified = import_tweetnacl.default.sign.detached.verify(
398
430
  import_buffer.Buffer.from(response.fullMessage),
399
431
  import_buffer.Buffer.from(signature.noPrefix(), "hex"),
400
432
  import_buffer.Buffer.from(currentAccountPublicKey.noPrefix(), "hex")
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/WalletCore.ts
2
2
  import { HexString } from "aptos";
3
3
  import EventEmitter from "eventemitter3";
4
- import { sign } from "tweetnacl";
4
+ import nacl from "tweetnacl";
5
5
  import { Buffer } from "buffer";
6
6
 
7
7
  // src/constants.ts
@@ -166,12 +166,15 @@ var WalletCore = class extends EventEmitter {
166
166
  scopePollingDetectionStrategy() {
167
167
  var _a;
168
168
  (_a = this._wallets) == null ? void 0 : _a.forEach((wallet) => {
169
- wallet.readyState = typeof window === "undefined" || typeof document === "undefined" ? "Unsupported" /* Unsupported */ : "NotDetected" /* NotDetected */;
169
+ if (!wallet.readyState) {
170
+ wallet.readyState = typeof window === "undefined" || typeof document === "undefined" ? "Unsupported" /* Unsupported */ : "NotDetected" /* NotDetected */;
171
+ }
170
172
  if (typeof window !== "undefined") {
171
173
  scopePollingDetectionStrategy(() => {
172
- if (Object.keys(window).includes(wallet.name.toLowerCase())) {
174
+ const providerName = wallet.providerName || wallet.name.toLowerCase();
175
+ if (Object.keys(window).includes(providerName)) {
173
176
  wallet.readyState = "Installed" /* Installed */;
174
- wallet.provider = window[wallet.name.toLowerCase()];
177
+ wallet.provider = window[providerName];
175
178
  this.emit("readyStateChange", wallet);
176
179
  return true;
177
180
  }
@@ -242,10 +245,9 @@ var WalletCore = class extends EventEmitter {
242
245
  const selectedWallet = (_a = this._wallets) == null ? void 0 : _a.find(
243
246
  (wallet) => wallet.name === walletName
244
247
  );
245
- if (!selectedWallet)
246
- return;
247
- if (selectedWallet.readyState !== "Installed" /* Installed */)
248
- return;
248
+ if (!selectedWallet || selectedWallet.readyState !== "Installed" /* Installed */ && selectedWallet.readyState !== "Loadable" /* Loadable */) {
249
+ throw new WalletConnectionError(`${walletName} wallet not found`).message;
250
+ }
249
251
  if (this._connected) {
250
252
  await this.disconnect();
251
253
  }
@@ -355,12 +357,42 @@ var WalletCore = class extends EventEmitter {
355
357
  throw new WalletSignMessageAndVerifyError("Failed to sign a message").message;
356
358
  let verified = false;
357
359
  if (Array.isArray(response.signature)) {
360
+ const { fullMessage, signature, bitmap } = response;
361
+ if (bitmap) {
362
+ const minKeysRequired = this._account.minKeysRequired;
363
+ if (signature.length < minKeysRequired) {
364
+ verified = false;
365
+ } else {
366
+ const bits = Array.from(bitmap).flatMap(
367
+ (n) => Array.from({ length: 8 }).map((_, i) => n >> i & 1)
368
+ );
369
+ const index = bits.map((_, i) => i).filter((i) => bits[i]);
370
+ const publicKeys = this._account.publicKey;
371
+ const matchedPublicKeys = publicKeys.filter(
372
+ (_, i) => index.includes(i)
373
+ );
374
+ verified = true;
375
+ for (let i = 0; i < signature.length; i++) {
376
+ const isSigVerified = nacl.sign.detached.verify(
377
+ Buffer.from(fullMessage),
378
+ Buffer.from(signature[i], "hex"),
379
+ Buffer.from(matchedPublicKeys[i], "hex")
380
+ );
381
+ if (!isSigVerified) {
382
+ verified = false;
383
+ break;
384
+ }
385
+ }
386
+ }
387
+ } else {
388
+ throw new WalletSignMessageAndVerifyError("Failed to get a bitmap").message;
389
+ }
358
390
  } else {
359
391
  const currentAccountPublicKey = new HexString(
360
392
  this._account.publicKey
361
393
  );
362
394
  const signature = new HexString(response.signature);
363
- verified = sign.detached.verify(
395
+ verified = nacl.sign.detached.verify(
364
396
  Buffer.from(response.fullMessage),
365
397
  Buffer.from(signature.noPrefix(), "hex"),
366
398
  Buffer.from(currentAccountPublicKey.noPrefix(), "hex")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aptos-labs/wallet-adapter-core",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Aptos Wallet Adapter Core",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
package/src/WalletCore.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { HexString, Types } from "aptos";
2
2
  import EventEmitter from "eventemitter3";
3
- import { sign } from "tweetnacl";
3
+ import nacl from "tweetnacl";
4
4
  import { Buffer } from "buffer";
5
5
 
6
6
  import { WalletReadyState } from "./constants";
@@ -53,15 +53,18 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
53
53
 
54
54
  private scopePollingDetectionStrategy() {
55
55
  this._wallets?.forEach((wallet: Wallet) => {
56
- wallet.readyState =
57
- typeof window === "undefined" || typeof document === "undefined"
58
- ? WalletReadyState.Unsupported
59
- : WalletReadyState.NotDetected;
56
+ if (!wallet.readyState) {
57
+ wallet.readyState =
58
+ typeof window === "undefined" || typeof document === "undefined"
59
+ ? WalletReadyState.Unsupported
60
+ : WalletReadyState.NotDetected;
61
+ }
60
62
  if (typeof window !== "undefined") {
61
63
  scopePollingDetectionStrategy(() => {
62
- if (Object.keys(window).includes(wallet.name.toLowerCase())) {
64
+ const providerName = wallet.providerName || wallet.name.toLowerCase();
65
+ if (Object.keys(window).includes(providerName)) {
63
66
  wallet.readyState = WalletReadyState.Installed;
64
- wallet.provider = window[wallet.name.toLowerCase() as any];
67
+ wallet.provider = window[providerName as any];
65
68
  this.emit("readyStateChange", wallet);
66
69
  return true;
67
70
  }
@@ -171,8 +174,16 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
171
174
  const selectedWallet = this._wallets?.find(
172
175
  (wallet: Wallet) => wallet.name === walletName
173
176
  );
174
- if (!selectedWallet) return;
175
- if (selectedWallet.readyState !== WalletReadyState.Installed) return;
177
+
178
+ if (
179
+ !selectedWallet ||
180
+ (selectedWallet.readyState !== WalletReadyState.Installed &&
181
+ selectedWallet.readyState !== WalletReadyState.Loadable)
182
+ ) {
183
+ throw new WalletConnectionError(`${walletName} wallet not found`)
184
+ .message;
185
+ }
186
+
176
187
  if (this._connected) {
177
188
  await this.disconnect();
178
189
  }
@@ -329,7 +340,42 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
329
340
  let verified = false;
330
341
  if (Array.isArray(response.signature)) {
331
342
  // multi sig wallets
332
- // TODO - implement multi sig wallets
343
+ const { fullMessage, signature, bitmap } = response;
344
+ if (bitmap) {
345
+ const minKeysRequired = this._account.minKeysRequired as number;
346
+ if (signature.length < minKeysRequired) {
347
+ verified = false;
348
+ } else {
349
+ // Getting an array which marks the keys signing the message with 1, while marking 0 for the keys not being used.
350
+ const bits = Array.from(bitmap).flatMap((n) =>
351
+ Array.from({ length: 8 }).map((_, i) => (n >> i) & 1)
352
+ );
353
+ // Filter out indexes of the keys we need
354
+ const index = bits.map((_, i) => i).filter((i) => bits[i]);
355
+
356
+ const publicKeys = this._account.publicKey as string[];
357
+ const matchedPublicKeys = publicKeys.filter(
358
+ (_: string, i: number) => index.includes(i)
359
+ );
360
+
361
+ verified = true;
362
+ for (let i = 0; i < signature.length; i++) {
363
+ const isSigVerified = nacl.sign.detached.verify(
364
+ Buffer.from(fullMessage),
365
+ Buffer.from(signature[i], "hex"),
366
+ Buffer.from(matchedPublicKeys[i], "hex")
367
+ ); // `isSigVerified` should be `true` for every signature
368
+
369
+ if (!isSigVerified) {
370
+ verified = false;
371
+ break;
372
+ }
373
+ }
374
+ }
375
+ } else {
376
+ throw new WalletSignMessageAndVerifyError("Failed to get a bitmap")
377
+ .message;
378
+ }
333
379
  } else {
334
380
  // single sig wallets
335
381
  // support for when address doesnt have hex prefix (0x)
@@ -338,7 +384,7 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
338
384
  );
339
385
  // support for when address doesnt have hex prefix (0x)
340
386
  const signature = new HexString(response.signature);
341
- verified = sign.detached.verify(
387
+ verified = nacl.sign.detached.verify(
342
388
  Buffer.from(response.fullMessage),
343
389
  Buffer.from(signature.noPrefix(), "hex"),
344
390
  Buffer.from(currentAccountPublicKey.noPrefix(), "hex")
package/src/types.ts CHANGED
@@ -50,6 +50,7 @@ export interface AdapterPluginProps<Name extends string = string> {
50
50
  name: WalletName<Name>;
51
51
  url: string;
52
52
  icon: `data:image/${"svg+xml" | "webp" | "png" | "gif"};base64,${string}`;
53
+ providerName?: string
53
54
  provider: any;
54
55
  connect(): Promise<any>;
55
56
  disconnect: () => Promise<any>;