w3wallets 1.0.0-beta.10 → 1.0.0-beta.11

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/dist/index.d.mts CHANGED
@@ -108,6 +108,13 @@ declare class Metamask extends Wallet {
108
108
  */
109
109
  dismissPopups(): Promise<void>;
110
110
  private waitForPopupHidden;
111
+ /**
112
+ * MetaMask's MV3 service worker can fail to come up on cold-start
113
+ * (especially in fresh-extension CI runs), showing an error screen
114
+ * with a "Restart MetaMask" button. Detect and click it so the
115
+ * normal post-unlock flow can proceed.
116
+ */
117
+ private recoverFromStartupError;
111
118
  /**
112
119
  * After unlock, MetaMask may show onboarding screens, queued
113
120
  * notifications, or go straight to the wallet UI. Race all possible
package/dist/index.d.ts CHANGED
@@ -108,6 +108,13 @@ declare class Metamask extends Wallet {
108
108
  */
109
109
  dismissPopups(): Promise<void>;
110
110
  private waitForPopupHidden;
111
+ /**
112
+ * MetaMask's MV3 service worker can fail to come up on cold-start
113
+ * (especially in fresh-extension CI runs), showing an error screen
114
+ * with a "Restart MetaMask" button. Detect and click it so the
115
+ * normal post-unlock flow can proceed.
116
+ */
117
+ private recoverFromStartupError;
111
118
  /**
112
119
  * After unlock, MetaMask may show onboarding screens, queued
113
120
  * notifications, or go straight to the wallet UI. Race all possible
package/dist/index.js CHANGED
@@ -392,11 +392,23 @@ var Metamask = class extends Wallet {
392
392
  await passwordInputs.nth(1).fill(pwd);
393
393
  await this.page.getByRole("checkbox").click({ force: true });
394
394
  await this.page.getByRole("button", { name: "Create password" }).click();
395
+ const passkeyMaybeLater = this.page.getByTestId(
396
+ "passkey-maybe-later-button"
397
+ );
395
398
  const metametricsBtn = this.page.getByTestId("metametrics-i-agree");
396
- await metametricsBtn.click();
397
- const openWalletBtn = this.page.getByRole("button", {
398
- name: /open wallet/i
399
+ const postPasswordState = await Promise.race([
400
+ passkeyMaybeLater.waitFor({ state: "visible", timeout: ONBOARD_VISIBLE_TIMEOUT }).then(() => "passkey"),
401
+ metametricsBtn.waitFor({ state: "visible", timeout: ONBOARD_VISIBLE_TIMEOUT }).then(() => "metametrics")
402
+ ]);
403
+ if (postPasswordState === "passkey") {
404
+ await passkeyMaybeLater.click();
405
+ }
406
+ await metametricsBtn.waitFor({
407
+ state: "visible",
408
+ timeout: ONBOARD_VISIBLE_TIMEOUT
399
409
  });
410
+ await metametricsBtn.click();
411
+ const openWalletBtn = this.page.getByTestId("onboarding-complete-done");
400
412
  await openWalletBtn.click();
401
413
  await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
402
414
  await this.page.goto(
@@ -437,6 +449,26 @@ var Metamask = class extends Wallet {
437
449
  return false;
438
450
  }
439
451
  }
452
+ /**
453
+ * MetaMask's MV3 service worker can fail to come up on cold-start
454
+ * (especially in fresh-extension CI runs), showing an error screen
455
+ * with a "Restart MetaMask" button. Detect and click it so the
456
+ * normal post-unlock flow can proceed.
457
+ */
458
+ async recoverFromStartupError() {
459
+ const restartBtn = this.page.getByRole("button", {
460
+ name: "Restart MetaMask"
461
+ });
462
+ if (!await restartBtn.isVisible({ timeout: POPUP_VISIBILITY_TIMEOUT }).catch(() => false)) {
463
+ return;
464
+ }
465
+ debug("metamask.recoverFromStartupError: clicking Restart MetaMask");
466
+ await restartBtn.click();
467
+ await restartBtn.waitFor({
468
+ state: "hidden",
469
+ timeout: POST_UNLOCK_TIMEOUT
470
+ });
471
+ }
440
472
  /**
441
473
  * After unlock, MetaMask may show onboarding screens, queued
442
474
  * notifications, or go straight to the wallet UI. Race all possible
@@ -444,16 +476,19 @@ var Metamask = class extends Wallet {
444
476
  */
445
477
  async stabilizePostUnlock() {
446
478
  debug("metamask.stabilizePostUnlock: racing post-unlock states");
479
+ await this.recoverFromStartupError();
480
+ const passkeyMaybeLater = this.page.getByTestId(
481
+ "passkey-maybe-later-button"
482
+ );
447
483
  const metametricsBtn = this.page.getByTestId("metametrics-i-agree");
448
- const openWalletBtn = this.page.getByRole("button", {
449
- name: /open wallet/i
450
- });
484
+ const openWalletBtn = this.page.getByTestId("onboarding-complete-done");
451
485
  const readyIndicator = this.page.getByTestId("account-options-menu-button");
452
486
  const rejectAllBtn = this.page.getByText("Reject all");
453
487
  const notificationCancelBtn = this.page.getByTestId(
454
488
  "confirmation-cancel-button"
455
489
  );
456
490
  const state = await Promise.race([
491
+ passkeyMaybeLater.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "passkey"),
457
492
  metametricsBtn.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "metametrics"),
458
493
  openWalletBtn.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "openWallet"),
459
494
  rejectAllBtn.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "rejectAll"),
@@ -463,9 +498,18 @@ var Metamask = class extends Wallet {
463
498
  debug(`metamask.stabilizePostUnlock: state=${state}`);
464
499
  if (state === "timeout") {
465
500
  debug(
466
- `metamask.stabilizePostUnlock: timeout after ${POST_UNLOCK_TIMEOUT}ms. URL: ${this.page.url()}. Checked: metametrics-i-agree, open-wallet button, Reject all, confirmation-cancel-button, account-options-menu-button`
501
+ `metamask.stabilizePostUnlock: timeout after ${POST_UNLOCK_TIMEOUT}ms. URL: ${this.page.url()}. Checked: passkey-maybe-later-button, metametrics-i-agree, onboarding-complete-done, Reject all, confirmation-cancel-button, account-options-menu-button`
467
502
  );
468
503
  }
504
+ if (state === "passkey") {
505
+ await passkeyMaybeLater.click();
506
+ if (await metametricsBtn.isVisible({ timeout: POST_UNLOCK_TIMEOUT }).catch(() => false)) {
507
+ await metametricsBtn.click();
508
+ }
509
+ if (await openWalletBtn.isVisible({ timeout: POPUP_HIDDEN_TIMEOUT }).catch(() => false)) {
510
+ await openWalletBtn.click();
511
+ }
512
+ }
469
513
  if (state === "metametrics") {
470
514
  await metametricsBtn.click();
471
515
  if (await openWalletBtn.isVisible({ timeout: POPUP_HIDDEN_TIMEOUT }).catch(() => false)) {
@@ -493,6 +537,7 @@ var Metamask = class extends Wallet {
493
537
  "confirmation-cancel-button"
494
538
  );
495
539
  await this.page.goto(homeUrl);
540
+ await this.recoverFromStartupError();
496
541
  for (let i = 0; i < 10; i++) {
497
542
  const state = await Promise.race([
498
543
  readyIndicator.waitFor({ state: "visible", timeout: NOTIFICATION_CHECK_TIMEOUT }).then(() => "ready"),
@@ -538,8 +583,8 @@ var Metamask = class extends Wallet {
538
583
  };
539
584
  let routeFound = false;
540
585
  for (let attempt = 0; attempt < MAX_ROUTE_ATTEMPTS; attempt++) {
541
- await this.page.goto(sidepanelUrl);
542
586
  try {
587
+ await this.page.goto(sidepanelUrl, { timeout: ROUTE_RETRY_TIMEOUT });
543
588
  await this.page.waitForURL(confirmRoutePattern, {
544
589
  timeout: ROUTE_RETRY_TIMEOUT
545
590
  });
@@ -610,7 +655,7 @@ var Metamask = class extends Wallet {
610
655
  const menuBtn = this.page.getByTestId("account-options-menu-button");
611
656
  await menuBtn.waitFor({ state: "visible", timeout: MENU_BUTTON_TIMEOUT });
612
657
  await menuBtn.click({ force: true });
613
- await this.page.locator("text=Log out").click();
658
+ await this.page.getByTestId("global-menu-lock").click();
614
659
  }
615
660
  /**
616
661
  * Unlock MetaMask with password.
package/dist/index.mjs CHANGED
@@ -356,11 +356,23 @@ var Metamask = class extends Wallet {
356
356
  await passwordInputs.nth(1).fill(pwd);
357
357
  await this.page.getByRole("checkbox").click({ force: true });
358
358
  await this.page.getByRole("button", { name: "Create password" }).click();
359
+ const passkeyMaybeLater = this.page.getByTestId(
360
+ "passkey-maybe-later-button"
361
+ );
359
362
  const metametricsBtn = this.page.getByTestId("metametrics-i-agree");
360
- await metametricsBtn.click();
361
- const openWalletBtn = this.page.getByRole("button", {
362
- name: /open wallet/i
363
+ const postPasswordState = await Promise.race([
364
+ passkeyMaybeLater.waitFor({ state: "visible", timeout: ONBOARD_VISIBLE_TIMEOUT }).then(() => "passkey"),
365
+ metametricsBtn.waitFor({ state: "visible", timeout: ONBOARD_VISIBLE_TIMEOUT }).then(() => "metametrics")
366
+ ]);
367
+ if (postPasswordState === "passkey") {
368
+ await passkeyMaybeLater.click();
369
+ }
370
+ await metametricsBtn.waitFor({
371
+ state: "visible",
372
+ timeout: ONBOARD_VISIBLE_TIMEOUT
363
373
  });
374
+ await metametricsBtn.click();
375
+ const openWalletBtn = this.page.getByTestId("onboarding-complete-done");
364
376
  await openWalletBtn.click();
365
377
  await this.page.goto(`chrome-extension://${this.extensionId}/home.html`);
366
378
  await this.page.goto(
@@ -401,6 +413,26 @@ var Metamask = class extends Wallet {
401
413
  return false;
402
414
  }
403
415
  }
416
+ /**
417
+ * MetaMask's MV3 service worker can fail to come up on cold-start
418
+ * (especially in fresh-extension CI runs), showing an error screen
419
+ * with a "Restart MetaMask" button. Detect and click it so the
420
+ * normal post-unlock flow can proceed.
421
+ */
422
+ async recoverFromStartupError() {
423
+ const restartBtn = this.page.getByRole("button", {
424
+ name: "Restart MetaMask"
425
+ });
426
+ if (!await restartBtn.isVisible({ timeout: POPUP_VISIBILITY_TIMEOUT }).catch(() => false)) {
427
+ return;
428
+ }
429
+ debug("metamask.recoverFromStartupError: clicking Restart MetaMask");
430
+ await restartBtn.click();
431
+ await restartBtn.waitFor({
432
+ state: "hidden",
433
+ timeout: POST_UNLOCK_TIMEOUT
434
+ });
435
+ }
404
436
  /**
405
437
  * After unlock, MetaMask may show onboarding screens, queued
406
438
  * notifications, or go straight to the wallet UI. Race all possible
@@ -408,16 +440,19 @@ var Metamask = class extends Wallet {
408
440
  */
409
441
  async stabilizePostUnlock() {
410
442
  debug("metamask.stabilizePostUnlock: racing post-unlock states");
443
+ await this.recoverFromStartupError();
444
+ const passkeyMaybeLater = this.page.getByTestId(
445
+ "passkey-maybe-later-button"
446
+ );
411
447
  const metametricsBtn = this.page.getByTestId("metametrics-i-agree");
412
- const openWalletBtn = this.page.getByRole("button", {
413
- name: /open wallet/i
414
- });
448
+ const openWalletBtn = this.page.getByTestId("onboarding-complete-done");
415
449
  const readyIndicator = this.page.getByTestId("account-options-menu-button");
416
450
  const rejectAllBtn = this.page.getByText("Reject all");
417
451
  const notificationCancelBtn = this.page.getByTestId(
418
452
  "confirmation-cancel-button"
419
453
  );
420
454
  const state = await Promise.race([
455
+ passkeyMaybeLater.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "passkey"),
421
456
  metametricsBtn.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "metametrics"),
422
457
  openWalletBtn.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "openWallet"),
423
458
  rejectAllBtn.waitFor({ state: "visible", timeout: POST_UNLOCK_TIMEOUT }).then(() => "rejectAll"),
@@ -427,9 +462,18 @@ var Metamask = class extends Wallet {
427
462
  debug(`metamask.stabilizePostUnlock: state=${state}`);
428
463
  if (state === "timeout") {
429
464
  debug(
430
- `metamask.stabilizePostUnlock: timeout after ${POST_UNLOCK_TIMEOUT}ms. URL: ${this.page.url()}. Checked: metametrics-i-agree, open-wallet button, Reject all, confirmation-cancel-button, account-options-menu-button`
465
+ `metamask.stabilizePostUnlock: timeout after ${POST_UNLOCK_TIMEOUT}ms. URL: ${this.page.url()}. Checked: passkey-maybe-later-button, metametrics-i-agree, onboarding-complete-done, Reject all, confirmation-cancel-button, account-options-menu-button`
431
466
  );
432
467
  }
468
+ if (state === "passkey") {
469
+ await passkeyMaybeLater.click();
470
+ if (await metametricsBtn.isVisible({ timeout: POST_UNLOCK_TIMEOUT }).catch(() => false)) {
471
+ await metametricsBtn.click();
472
+ }
473
+ if (await openWalletBtn.isVisible({ timeout: POPUP_HIDDEN_TIMEOUT }).catch(() => false)) {
474
+ await openWalletBtn.click();
475
+ }
476
+ }
433
477
  if (state === "metametrics") {
434
478
  await metametricsBtn.click();
435
479
  if (await openWalletBtn.isVisible({ timeout: POPUP_HIDDEN_TIMEOUT }).catch(() => false)) {
@@ -457,6 +501,7 @@ var Metamask = class extends Wallet {
457
501
  "confirmation-cancel-button"
458
502
  );
459
503
  await this.page.goto(homeUrl);
504
+ await this.recoverFromStartupError();
460
505
  for (let i = 0; i < 10; i++) {
461
506
  const state = await Promise.race([
462
507
  readyIndicator.waitFor({ state: "visible", timeout: NOTIFICATION_CHECK_TIMEOUT }).then(() => "ready"),
@@ -502,8 +547,8 @@ var Metamask = class extends Wallet {
502
547
  };
503
548
  let routeFound = false;
504
549
  for (let attempt = 0; attempt < MAX_ROUTE_ATTEMPTS; attempt++) {
505
- await this.page.goto(sidepanelUrl);
506
550
  try {
551
+ await this.page.goto(sidepanelUrl, { timeout: ROUTE_RETRY_TIMEOUT });
507
552
  await this.page.waitForURL(confirmRoutePattern, {
508
553
  timeout: ROUTE_RETRY_TIMEOUT
509
554
  });
@@ -574,7 +619,7 @@ var Metamask = class extends Wallet {
574
619
  const menuBtn = this.page.getByTestId("account-options-menu-button");
575
620
  await menuBtn.waitFor({ state: "visible", timeout: MENU_BUTTON_TIMEOUT });
576
621
  await menuBtn.click({ force: true });
577
- await this.page.locator("text=Log out").click();
622
+ await this.page.getByTestId("global-menu-lock").click();
578
623
  }
579
624
  /**
580
625
  * Unlock MetaMask with password.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "w3wallets",
3
3
  "description": "browser wallets for playwright",
4
- "version": "1.0.0-beta.10",
4
+ "version": "1.0.0-beta.11",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "homepage": "https://github.com/Maksandre/w3wallets",