@pooflabs/web 0.0.85-rc1 → 0.0.85-rc3

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.
Files changed (51) hide show
  1. package/dist/auth/providers/solana-mobile-wallet-provider.d.ts +5 -0
  2. package/dist/{index-DlyeWzMk.js → index-B5qYY4YM.js} +2 -2
  3. package/dist/index-B5qYY4YM.js.map +1 -0
  4. package/dist/{index-Buu8v-Oe.esm.js → index-BE-VWSJT.esm.js} +2 -2
  5. package/dist/{index-Buu8v-Oe.esm.js.map → index-BE-VWSJT.esm.js.map} +1 -1
  6. package/dist/{index-BoWQVxMI.js → index-BaKs3A8s.js} +2 -2
  7. package/dist/{index-BoWQVxMI.js.map → index-BaKs3A8s.js.map} +1 -1
  8. package/dist/{index-C2p1Cldz.js → index-BzeiIIwF.js} +3 -3
  9. package/dist/{index-C2p1Cldz.js.map → index-BzeiIIwF.js.map} +1 -1
  10. package/dist/{index-ZKzq5QT_.esm.js → index-C4AnWFs_.esm.js} +421 -13
  11. package/dist/{index-ZKzq5QT_.esm.js.map → index-C4AnWFs_.esm.js.map} +1 -1
  12. package/dist/index-TzHXEf3-.esm.js +6 -0
  13. package/dist/index-TzHXEf3-.esm.js.map +1 -0
  14. package/dist/{index-R7cvXys2.js → index-bEXLwE7_.js} +421 -13
  15. package/dist/{index-R7cvXys2.js.map → index-bEXLwE7_.js.map} +1 -1
  16. package/dist/{index-4TKz3Mn_.esm.js → index-dqqR5q7b.esm.js} +3 -3
  17. package/dist/{index-4TKz3Mn_.esm.js.map → index-dqqR5q7b.esm.js.map} +1 -1
  18. package/dist/{index.browser-BQSN-6X2.js → index.browser-CN6obNQM.js} +2 -118
  19. package/dist/{index.browser-BQSN-6X2.js.map → index.browser-CN6obNQM.js.map} +1 -1
  20. package/dist/{index.browser-DZCNegue.js → index.browser-CZIJCtms.js} +2 -2
  21. package/dist/{index.browser-DZCNegue.js.map → index.browser-CZIJCtms.js.map} +1 -1
  22. package/dist/{index.browser-tPepE5fo.esm.js → index.browser-D8ttddP4.esm.js} +3 -117
  23. package/dist/{index.browser-tPepE5fo.esm.js.map → index.browser-D8ttddP4.esm.js.map} +1 -1
  24. package/dist/{index.browser-zfGYm0ST.esm.js → index.browser-DQIwLToJ.esm.js} +2 -2
  25. package/dist/{index.browser-zfGYm0ST.esm.js.map → index.browser-DQIwLToJ.esm.js.map} +1 -1
  26. package/dist/index.esm.js +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/{index.native-BPQqeP6_.esm.js → index.native-DLziTime.esm.js} +4 -4
  29. package/dist/{index.native-BPQqeP6_.esm.js.map → index.native-DLziTime.esm.js.map} +1 -1
  30. package/dist/{index.native-BGaUOX9f.js → index.native-pG1NTZ0f.js} +4 -4
  31. package/dist/{index.native-BGaUOX9f.js.map → index.native-pG1NTZ0f.js.map} +1 -1
  32. package/dist/index.native.esm.js +1 -1
  33. package/dist/index.native.js +1 -1
  34. package/dist/{phantom-wallet-provider-DheGhOp4.esm.js → phantom-wallet-provider-CP6NXRwG.esm.js} +4 -4
  35. package/dist/{phantom-wallet-provider-DheGhOp4.esm.js.map → phantom-wallet-provider-CP6NXRwG.esm.js.map} +1 -1
  36. package/dist/{phantom-wallet-provider-MFcwrRpJ.js → phantom-wallet-provider-zBp7-uEw.js} +4 -4
  37. package/dist/{phantom-wallet-provider-MFcwrRpJ.js.map → phantom-wallet-provider-zBp7-uEw.js.map} +1 -1
  38. package/dist/{privy-wallet-provider-D15Au3j8.esm.js → privy-wallet-provider-CGYvf3-r.esm.js} +3 -3
  39. package/dist/{privy-wallet-provider-D15Au3j8.esm.js.map → privy-wallet-provider-CGYvf3-r.esm.js.map} +1 -1
  40. package/dist/{privy-wallet-provider-CFw6o7O5.js → privy-wallet-provider-CoyW5Gdg.js} +3 -3
  41. package/dist/{privy-wallet-provider-CFw6o7O5.js.map → privy-wallet-provider-CoyW5Gdg.js.map} +1 -1
  42. package/dist/{solana-mobile-wallet-provider-ChHh-U_p.esm.js → solana-mobile-wallet-provider-B8rHfsPN.esm.js} +414 -9
  43. package/dist/solana-mobile-wallet-provider-B8rHfsPN.esm.js.map +1 -0
  44. package/dist/{solana-mobile-wallet-provider-BM9wdF0m.js → solana-mobile-wallet-provider-CN-D_H4l.js} +414 -9
  45. package/dist/solana-mobile-wallet-provider-CN-D_H4l.js.map +1 -0
  46. package/package.json +1 -1
  47. package/dist/index-COF6zNCs.esm.js +0 -6
  48. package/dist/index-COF6zNCs.esm.js.map +0 -1
  49. package/dist/index-DlyeWzMk.js.map +0 -1
  50. package/dist/solana-mobile-wallet-provider-BM9wdF0m.js.map +0 -1
  51. package/dist/solana-mobile-wallet-provider-ChHh-U_p.esm.js.map +0 -1
@@ -15709,7 +15709,7 @@ async function loadDependencies() {
15709
15709
  const [reactModule, reactDomModule, phantomModule] = await Promise.all([
15710
15710
  import('react'),
15711
15711
  import('react-dom/client'),
15712
- import('./index-Buu8v-Oe.esm.js')
15712
+ import('./index-BE-VWSJT.esm.js')
15713
15713
  ]);
15714
15714
  // Extract default export from ESM module namespace
15715
15715
  // Dynamic import() returns { default: Module, ...exports }, not the module directly
@@ -21280,6 +21280,381 @@ function isMobileWalletAvailable() {
21280
21280
  const ED25519_SIGNATURE_LENGTH = 64;
21281
21281
  const STORED_AUTH_METHOD_KEY = 'tarobase_last_auth_method';
21282
21282
  const MWA_AUTH_METHOD = 'mobile-wallet-adapter';
21283
+ function findMwaError(e, maxDepth = 5) {
21284
+ var _a;
21285
+ let cur = e;
21286
+ let depth = 0;
21287
+ while (cur && depth < maxDepth) {
21288
+ if ((cur === null || cur === void 0 ? void 0 : cur.name) === 'SolanaMobileWalletAdapterError' && typeof (cur === null || cur === void 0 ? void 0 : cur.code) === 'string') {
21289
+ return { code: cur.code, message: String((_a = cur.message) !== null && _a !== void 0 ? _a : '') };
21290
+ }
21291
+ cur = cur === null || cur === void 0 ? void 0 : cur.cause;
21292
+ depth++;
21293
+ }
21294
+ return null;
21295
+ }
21296
+ /**
21297
+ * Returns the matched MwaErrorInfo when the error is from an association
21298
+ * failure that an automatic retry can recover from (i.e. the wallet exists
21299
+ * on-device but the dApp's protocol session didn't complete in time). Returns
21300
+ * null for non-retryable errors (user cancel, unknown wallet errors, etc.).
21301
+ *
21302
+ * Specifically:
21303
+ * - ERROR_WALLET_NOT_FOUND: thrown from the protocol's startScenario when
21304
+ * it gave up waiting for a wallet to respond. On Seeker this races the
21305
+ * first-time-consent UI on the very first authorize.
21306
+ * - ERROR_SESSION_TIMEOUT: similar — the protocol's session-establishment
21307
+ * timer expired.
21308
+ * - ERROR_ASSOCIATION_CANCELLED: shared by user-cancel ("Wallet connection
21309
+ * cancelled by user") AND the 30s wallet-standard WALLET_ASSOCIATION_TIMEOUT
21310
+ * ("Wallet connection timed out"). Discriminate by message — never retry
21311
+ * a user cancel.
21312
+ */
21313
+ function isMwaAssociationRetryable(e) {
21314
+ const info = findMwaError(e);
21315
+ if (!info)
21316
+ return null;
21317
+ if (info.code === 'ERROR_WALLET_NOT_FOUND')
21318
+ return info;
21319
+ if (info.code === 'ERROR_SESSION_TIMEOUT')
21320
+ return info;
21321
+ if (info.code === 'ERROR_ASSOCIATION_CANCELLED' && /timed out/i.test(info.message))
21322
+ return info;
21323
+ return null;
21324
+ }
21325
+ /**
21326
+ * Single-retry wrapper for MWA association failures. Used ONLY for login's
21327
+ * `standard:connect` and `solana:signMessage` calls — never for
21328
+ * `signAndSendTransaction`/`runTransaction` because retry on a path that
21329
+ * may have already submitted a tx can double-send.
21330
+ *
21331
+ * The retry exists for one specific scenario: on first-time MWA usage from a
21332
+ * given origin on Seeker, the protocol's session-establishment timer races
21333
+ * Seeker's first-time consent UI. The user reads the consent sheet, taps
21334
+ * Connect — but by then the protocol has given up and thrown
21335
+ * ERROR_WALLET_NOT_FOUND. The consent itself IS persisted on Seeker though,
21336
+ * so a second attempt skips the consent sheet, jumps straight to
21337
+ * Verify/Approve, and completes inside the timeout.
21338
+ */
21339
+ async function withMwaAssociationRetry(label, fn) {
21340
+ const t0 = Date.now();
21341
+ console.log(`[MWA-DEBUG] ${label} attempt=1 start`);
21342
+ try {
21343
+ const result = await fn();
21344
+ console.log(`[MWA-DEBUG] ${label} attempt=1 ok (${Date.now() - t0}ms)`);
21345
+ return result;
21346
+ }
21347
+ catch (e) {
21348
+ const info = findMwaError(e);
21349
+ console.log(`[MWA-DEBUG] ${label} attempt=1 err (${Date.now() - t0}ms)`, {
21350
+ outer: { name: e === null || e === void 0 ? void 0 : e.name, message: e === null || e === void 0 ? void 0 : e.message },
21351
+ mwa: info,
21352
+ });
21353
+ const retryable = isMwaAssociationRetryable(e);
21354
+ if (!retryable)
21355
+ throw e;
21356
+ // Seeker's consent sheet is a bottom-sheet overlay — Chrome doesn't
21357
+ // reliably flip document.visibilityState to 'hidden' while it's open,
21358
+ // so visibility-based waits fire too early. Use a fixed delay long
21359
+ // enough for Seeker to dismiss its sheet and the OS to release intent
21360
+ // state. 2.5s is empirically safe; tune from device traces if needed.
21361
+ console.log(`[MWA-DEBUG] ${label} retryable (${retryable.code}); waiting 2500ms before retry`);
21362
+ await new Promise(r => setTimeout(r, 2500));
21363
+ const t1 = Date.now();
21364
+ console.log(`[MWA-DEBUG] ${label} attempt=2 start`);
21365
+ try {
21366
+ const result = await fn();
21367
+ console.log(`[MWA-DEBUG] ${label} attempt=2 ok (${Date.now() - t1}ms)`);
21368
+ return result;
21369
+ }
21370
+ catch (e2) {
21371
+ const info2 = findMwaError(e2);
21372
+ console.log(`[MWA-DEBUG] ${label} attempt=2 err (${Date.now() - t1}ms)`, {
21373
+ outer: { name: e2 === null || e2 === void 0 ? void 0 : e2.name, message: e2 === null || e2 === void 0 ? void 0 : e2.message },
21374
+ mwa: info2,
21375
+ });
21376
+ // Only mask the error with the clean Seeker message when the
21377
+ // second failure is also an association-flavored error. If it's
21378
+ // a user cancel, wallet rejection, or unknown error, rethrow
21379
+ // the original so the host app surfaces the real cause.
21380
+ if (isMwaAssociationRetryable(e2)) {
21381
+ throw new Error("Couldn't connect to your Seeker wallet. Please try again.");
21382
+ }
21383
+ throw e2;
21384
+ }
21385
+ }
21386
+ }
21387
+ /**
21388
+ * User-gesture-mediated wallet-standard sign helper.
21389
+ *
21390
+ * Why this exists: login flows that go through wallet-standard call two
21391
+ * separate transacts (standard:connect, then solana:signMessage). Each
21392
+ * transact dispatches its own `solana-wallet:` Android intent navigation
21393
+ * via `window.location.assign(associationUrl)` (see
21394
+ * @solana-mobile/mobile-wallet-adapter-protocol/lib/cjs/index.browser.js
21395
+ * `launchAssociation()` at line 459). Chrome requires **transient user
21396
+ * activation** for each custom-scheme navigation. The first transact
21397
+ * consumes the activation from the user's "Continue to Allow" tap on the
21398
+ * LNA modal; by the time the second transact (signMessage) runs as a JS
21399
+ * continuation, the activation has decayed, Chrome blocks the navigation,
21400
+ * no `blur` event fires, the protocol's `getDetectionPromise` (3000ms
21401
+ * timeout, line 433) rejects, and we get `ERROR_WALLET_NOT_FOUND`.
21402
+ *
21403
+ * Fix: show a Tarobase-controlled modal between the two transacts. When the
21404
+ * user taps the modal's "Sign in" button, that tap IS a fresh user
21405
+ * activation. We invoke the sign function directly inside the click handler
21406
+ * — no `await` between the tap and the call — so the activation propagates
21407
+ * to the protocol's `location.assign`.
21408
+ *
21409
+ * Failure recovery is also user-gesture driven: if the sign function fails
21410
+ * with a retryable association error, we re-enable the button so the user's
21411
+ * next tap is a new activation (a real retry). A timer-based retry would
21412
+ * just hit the same Chrome block. Cap at 3 attempts before giving up.
21413
+ */
21414
+ async function awaitSignInGestureAndSign(label, theme, signFn) {
21415
+ if (typeof document === 'undefined' || typeof window === 'undefined') {
21416
+ // SSR / non-browser: skip the gesture, just call (the activation
21417
+ // model doesn't apply outside the browser).
21418
+ const results = await signFn();
21419
+ if (!results || results.length === 0)
21420
+ throw new Error('MWA returned no signature');
21421
+ return results[0];
21422
+ }
21423
+ return new Promise((resolve, reject) => {
21424
+ const isDark = theme === 'dark'
21425
+ || (theme == null
21426
+ && typeof window.matchMedia === 'function'
21427
+ && window.matchMedia('(prefers-color-scheme: dark)').matches);
21428
+ // Palette
21429
+ const overlayBg = 'rgba(0, 0, 0, 0.62)';
21430
+ const cardBg = isDark ? '#1a1a1f' : '#ffffff';
21431
+ const titleColor = isDark ? '#ffffff' : '#0a0a0a';
21432
+ const subtitleColor = isDark ? '#a1a1aa' : '#52525b';
21433
+ const btnBg = isDark ? '#ffffff' : '#0a0a0a';
21434
+ const btnText = isDark ? '#0a0a0a' : '#ffffff';
21435
+ const btnDisabledBg = isDark ? '#3f3f46' : '#d4d4d8';
21436
+ const btnDisabledText = isDark ? '#71717a' : '#71717a';
21437
+ const errorColor = isDark ? '#fca5a5' : '#dc2626';
21438
+ const closeColor = isDark ? '#71717a' : '#a1a1aa';
21439
+ const fontStack = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
21440
+ const overlay = document.createElement('div');
21441
+ overlay.setAttribute('data-tarobase-mwa-gesture', 'true');
21442
+ overlay.style.cssText = [
21443
+ 'position: fixed',
21444
+ 'inset: 0',
21445
+ 'z-index: 2147483646',
21446
+ `background: ${overlayBg}`,
21447
+ 'display: flex',
21448
+ 'align-items: center',
21449
+ 'justify-content: center',
21450
+ 'padding: 20px',
21451
+ 'box-sizing: border-box',
21452
+ `font-family: ${fontStack}`,
21453
+ ].join('; ');
21454
+ const card = document.createElement('div');
21455
+ card.style.cssText = [
21456
+ `background: ${cardBg}`,
21457
+ 'border-radius: 20px',
21458
+ 'padding: 28px 24px 24px',
21459
+ 'max-width: 340px',
21460
+ 'width: 100%',
21461
+ 'box-shadow: 0 20px 50px rgba(0, 0, 0, 0.28)',
21462
+ 'position: relative',
21463
+ 'box-sizing: border-box',
21464
+ ].join('; ');
21465
+ const closeBtn = document.createElement('button');
21466
+ closeBtn.setAttribute('aria-label', 'Close');
21467
+ closeBtn.innerHTML = '&times;';
21468
+ closeBtn.style.cssText = [
21469
+ 'position: absolute',
21470
+ 'top: 12px',
21471
+ 'right: 12px',
21472
+ 'background: transparent',
21473
+ 'border: none',
21474
+ `color: ${closeColor}`,
21475
+ 'font-size: 24px',
21476
+ 'line-height: 1',
21477
+ 'cursor: pointer',
21478
+ 'padding: 6px 10px',
21479
+ 'border-radius: 8px',
21480
+ ].join('; ');
21481
+ const title = document.createElement('div');
21482
+ title.textContent = 'Almost there';
21483
+ title.style.cssText = [
21484
+ `color: ${titleColor}`,
21485
+ 'font-size: 20px',
21486
+ 'font-weight: 600',
21487
+ 'margin-bottom: 6px',
21488
+ 'text-align: center',
21489
+ ].join('; ');
21490
+ const subtitle = document.createElement('div');
21491
+ subtitle.textContent = 'Tap to sign in with your wallet';
21492
+ subtitle.style.cssText = [
21493
+ `color: ${subtitleColor}`,
21494
+ 'font-size: 14px',
21495
+ 'line-height: 1.4',
21496
+ 'margin-bottom: 22px',
21497
+ 'text-align: center',
21498
+ ].join('; ');
21499
+ const errorRow = document.createElement('div');
21500
+ errorRow.style.cssText = [
21501
+ `color: ${errorColor}`,
21502
+ 'font-size: 13px',
21503
+ 'line-height: 1.4',
21504
+ 'margin-bottom: 14px',
21505
+ 'text-align: center',
21506
+ 'min-height: 0',
21507
+ 'transition: min-height 100ms ease',
21508
+ ].join('; ');
21509
+ const button = document.createElement('button');
21510
+ button.textContent = 'Sign in';
21511
+ const setButtonEnabledStyle = () => {
21512
+ button.style.cssText = [
21513
+ `background: ${btnBg}`,
21514
+ `color: ${btnText}`,
21515
+ 'border: none',
21516
+ 'border-radius: 14px',
21517
+ 'padding: 14px 20px',
21518
+ 'font-size: 16px',
21519
+ 'font-weight: 600',
21520
+ 'width: 100%',
21521
+ 'cursor: pointer',
21522
+ '-webkit-tap-highlight-color: transparent',
21523
+ 'box-sizing: border-box',
21524
+ `font-family: ${fontStack}`,
21525
+ ].join('; ');
21526
+ };
21527
+ const setButtonDisabledStyle = () => {
21528
+ button.style.cssText = [
21529
+ `background: ${btnDisabledBg}`,
21530
+ `color: ${btnDisabledText}`,
21531
+ 'border: none',
21532
+ 'border-radius: 14px',
21533
+ 'padding: 14px 20px',
21534
+ 'font-size: 16px',
21535
+ 'font-weight: 600',
21536
+ 'width: 100%',
21537
+ 'cursor: default',
21538
+ '-webkit-tap-highlight-color: transparent',
21539
+ 'box-sizing: border-box',
21540
+ `font-family: ${fontStack}`,
21541
+ ].join('; ');
21542
+ };
21543
+ setButtonEnabledStyle();
21544
+ card.appendChild(closeBtn);
21545
+ card.appendChild(title);
21546
+ card.appendChild(subtitle);
21547
+ card.appendChild(errorRow);
21548
+ card.appendChild(button);
21549
+ overlay.appendChild(card);
21550
+ document.body.appendChild(overlay);
21551
+ let settled = false;
21552
+ let attemptCount = 0;
21553
+ const MAX_ATTEMPTS = 3;
21554
+ const cleanup = () => {
21555
+ try {
21556
+ overlay.remove();
21557
+ }
21558
+ catch ( /* ignore */_a) { /* ignore */ }
21559
+ document.removeEventListener('keydown', onKeydown);
21560
+ };
21561
+ const finishResolve = (value) => {
21562
+ if (settled)
21563
+ return;
21564
+ settled = true;
21565
+ cleanup();
21566
+ resolve(value);
21567
+ };
21568
+ const finishReject = (err) => {
21569
+ if (settled)
21570
+ return;
21571
+ settled = true;
21572
+ cleanup();
21573
+ reject(err);
21574
+ };
21575
+ const handleCancel = () => {
21576
+ // Phrasing matches login()'s isUserRejection substring check so
21577
+ // the existing catch suppresses error-log noise.
21578
+ finishReject(new Error('User cancelled wallet sign in'));
21579
+ };
21580
+ closeBtn.addEventListener('click', () => {
21581
+ console.log(`[MWA-DEBUG] ${label} gesture: close clicked`);
21582
+ handleCancel();
21583
+ });
21584
+ overlay.addEventListener('click', (e) => {
21585
+ if (e.target === overlay) {
21586
+ console.log(`[MWA-DEBUG] ${label} gesture: overlay clicked (cancel)`);
21587
+ handleCancel();
21588
+ }
21589
+ });
21590
+ const onKeydown = (e) => {
21591
+ if (e.key === 'Escape') {
21592
+ console.log(`[MWA-DEBUG] ${label} gesture: Escape pressed (cancel)`);
21593
+ handleCancel();
21594
+ }
21595
+ };
21596
+ document.addEventListener('keydown', onKeydown);
21597
+ button.addEventListener('click', () => {
21598
+ if (settled)
21599
+ return;
21600
+ attemptCount++;
21601
+ const attempt = attemptCount;
21602
+ console.log(`[MWA-DEBUG] ${label} gesture: button click attempt=${attempt}`);
21603
+ // Disable to prevent double-clicks while the wallet popup is up.
21604
+ button.disabled = true;
21605
+ setButtonDisabledStyle();
21606
+ const originalText = 'Sign in';
21607
+ button.textContent = 'Signing in…';
21608
+ errorRow.textContent = '';
21609
+ errorRow.style.minHeight = '0';
21610
+ // CRITICAL: invoke signFn() synchronously inside the click handler
21611
+ // so Chrome's transient user activation propagates to the
21612
+ // protocol's window.location.assign(associationUrl) inside
21613
+ // launchAssociation(). Do not `await` before calling.
21614
+ const t0 = Date.now();
21615
+ console.log(`[MWA-DEBUG] ${label} gesture: signMessage start (attempt=${attempt})`);
21616
+ signFn().then((results) => {
21617
+ const elapsed = Date.now() - t0;
21618
+ if (!results || results.length === 0) {
21619
+ console.log(`[MWA-DEBUG] ${label} gesture: signMessage returned empty (attempt=${attempt}, ${elapsed}ms)`);
21620
+ finishReject(new Error('MWA returned no signature'));
21621
+ return;
21622
+ }
21623
+ console.log(`[MWA-DEBUG] ${label} gesture: signMessage ok (attempt=${attempt}, ${elapsed}ms)`);
21624
+ finishResolve(results[0]);
21625
+ }).catch((err) => {
21626
+ const elapsed = Date.now() - t0;
21627
+ const info = findMwaError(err);
21628
+ console.log(`[MWA-DEBUG] ${label} gesture: signMessage err (attempt=${attempt}, ${elapsed}ms)`, {
21629
+ outer: { name: err === null || err === void 0 ? void 0 : err.name, message: err === null || err === void 0 ? void 0 : err.message },
21630
+ mwa: info,
21631
+ });
21632
+ const retryable = isMwaAssociationRetryable(err);
21633
+ if (retryable && attempt < MAX_ATTEMPTS) {
21634
+ // Re-enable the button so the user's next tap provides a
21635
+ // fresh user activation. Show inline error text.
21636
+ console.log(`[MWA-DEBUG] ${label} gesture: retryable (${retryable.code}); awaiting user tap to retry (attempt ${attempt}/${MAX_ATTEMPTS})`);
21637
+ button.disabled = false;
21638
+ setButtonEnabledStyle();
21639
+ button.textContent = originalText;
21640
+ errorRow.textContent = "Couldn't connect — tap to try again";
21641
+ errorRow.style.minHeight = '20px';
21642
+ return;
21643
+ }
21644
+ if (retryable) {
21645
+ // Hit the attempt cap with a still-retryable failure.
21646
+ console.log(`[MWA-DEBUG] ${label} gesture: retryable but attempt cap reached (${attempt})`);
21647
+ finishReject(new Error("Couldn't connect to your Seeker wallet. Please try again."));
21648
+ return;
21649
+ }
21650
+ // Non-retryable error (user cancel inside Seeker, wallet
21651
+ // rejected sign, unknown error, etc.) — surface as-is.
21652
+ finishReject(err);
21653
+ });
21654
+ });
21655
+ console.log(`[MWA-DEBUG] ${label} gesture: modal shown`);
21656
+ });
21657
+ }
21283
21658
  /**
21284
21659
  * Normalize a chain string to a wallet-standard Solana chain identifier.
21285
21660
  *
@@ -21417,11 +21792,11 @@ function readAuthMethod() {
21417
21792
  * @param config - App identity and optional remote host authority for desktop QR code support
21418
21793
  */
21419
21794
  async function registerMobileWalletAdapter(config) {
21420
- var _a;
21795
+ var _a, _b;
21421
21796
  if (typeof window === 'undefined')
21422
21797
  return;
21423
21798
  try {
21424
- const walletStandardMobile = await import('./index.browser-zfGYm0ST.esm.js');
21799
+ const walletStandardMobile = await import('./index.browser-DQIwLToJ.esm.js');
21425
21800
  const registerMwa = walletStandardMobile.registerMwa || ((_a = walletStandardMobile.default) === null || _a === void 0 ? void 0 : _a.registerMwa);
21426
21801
  if (!registerMwa) {
21427
21802
  console.warn('[SolanaMobileWallet] registerMwa not found in @solana-mobile/wallet-standard-mobile');
@@ -21444,9 +21819,12 @@ async function registerMobileWalletAdapter(config) {
21444
21819
  if (walletStandardMobile.createDefaultChainSelector) {
21445
21820
  options.chainSelector = walletStandardMobile.createDefaultChainSelector();
21446
21821
  }
21447
- if (walletStandardMobile.createDefaultWalletNotFoundHandler) {
21448
- options.onWalletNotFound = walletStandardMobile.createDefaultWalletNotFoundHandler();
21449
- }
21822
+ // Default: suppress the "We can't find a wallet" modal — see
21823
+ // SolanaMobileWalletProvider.ensureWallet() for why. Consumers that
21824
+ // want their own UX can pass config.onWalletNotFound.
21825
+ options.onWalletNotFound = (_b = config === null || config === void 0 ? void 0 : config.onWalletNotFound) !== null && _b !== void 0 ? _b : (async () => {
21826
+ console.warn('[MWA-DEBUG] registerMobileWalletAdapter onWalletNotFound (suppressed)');
21827
+ });
21450
21828
  registerMwa(options);
21451
21829
  }
21452
21830
  catch (e) {
@@ -21510,14 +21888,22 @@ class SolanaMobileWalletProvider {
21510
21888
  async ensureWallet() {
21511
21889
  if (this.wallet)
21512
21890
  return this.wallet;
21513
- const mod = await import('./index.browser-zfGYm0ST.esm.js');
21891
+ const mod = await import('./index.browser-DQIwLToJ.esm.js');
21514
21892
  const chain = mapChainToWalletStandard(this.cluster);
21515
21893
  this.wallet = new mod.LocalSolanaMobileWalletAdapterWallet({
21516
21894
  appIdentity: this.appIdentity,
21517
21895
  authorizationCache: mod.createDefaultAuthorizationCache(),
21518
21896
  chains: [chain],
21519
21897
  chainSelector: mod.createDefaultChainSelector(),
21520
- onWalletNotFound: mod.createDefaultWalletNotFoundHandler(),
21898
+ // Suppress the default "We can't find a wallet" modal — that
21899
+ // modal is misleading when ERROR_WALLET_NOT_FOUND fires during
21900
+ // a first-time-consent race on Seeker (the wallet IS installed,
21901
+ // the protocol just gave up before the user finished consenting).
21902
+ // login()'s withMwaAssociationRetry handles this case; on second
21903
+ // failure it surfaces a clean error message to the host app.
21904
+ onWalletNotFound: async () => {
21905
+ console.warn('[MWA-DEBUG] ensureWallet onWalletNotFound (suppressed)');
21906
+ },
21521
21907
  });
21522
21908
  return this.wallet;
21523
21909
  }
@@ -21582,8 +21968,15 @@ class SolanaMobileWalletProvider {
21582
21968
  // is where wallet-standard's checkLocalNetworkAccessPermission()
21583
21969
  // fires the three-stage LNA UX (info modal → permission prompt →
21584
21970
  // success modal) before opening the localhost WebSocket.
21971
+ //
21972
+ // Wrap with single-retry: on a Seeker origin's first MWA usage,
21973
+ // the protocol's session-establishment timer often races Seeker's
21974
+ // first-time consent UI and throws ERROR_WALLET_NOT_FOUND before
21975
+ // the user finishes tapping. The retry hits Seeker's cached
21976
+ // consent on the second pass and completes quickly. See
21977
+ // withMwaAssociationRetry for details.
21585
21978
  const connectFeat = getConnectFeature(wallet);
21586
- const { accounts } = await connectFeat.connect();
21979
+ const { accounts } = await withMwaAssociationRetry('login:connect', () => connectFeat.connect());
21587
21980
  if (!accounts || accounts.length === 0) {
21588
21981
  throw new Error('MWA returned no accounts');
21589
21982
  }
@@ -21598,14 +21991,29 @@ class SolanaMobileWalletProvider {
21598
21991
  return user;
21599
21992
  }
21600
21993
  // Wallet popup #2: sign the Tarobase nonce message.
21994
+ //
21995
+ // We cannot call signMessageFeat.signMessage() directly here:
21996
+ // it would run as a JS continuation from the connect() resolve,
21997
+ // with no fresh Chrome transient user activation. The wallet-
21998
+ // standard sign path internally dispatches a new solana-wallet:
21999
+ // Android intent via window.location.assign() (see
22000
+ // @solana-mobile/mobile-wallet-adapter-protocol launchAssociation
22001
+ // at lib/cjs/index.browser.js:459). Chrome blocks the assign
22002
+ // without activation, the blur event never fires, and the
22003
+ // protocol's 3-second getDetectionPromise rejects with
22004
+ // ERROR_WALLET_NOT_FOUND.
22005
+ //
22006
+ // Insert a Tarobase modal: the user's tap on "Sign in" provides a
22007
+ // fresh activation, and signMessage is invoked synchronously
22008
+ // inside the click handler so the activation propagates.
21601
22009
  const messageText = await genSolanaMessage(base58Addr, nonce);
21602
22010
  const messageBytes = getPlatform().textEncode(messageText);
21603
22011
  const signMessageFeat = getSignMessageFeature(wallet);
21604
- const signResults = await signMessageFeat.signMessage({ account, message: messageBytes });
21605
- if (!signResults || signResults.length === 0) {
22012
+ const signResult = await awaitSignInGestureAndSign('login:signMessage', this.config.theme, () => signMessageFeat.signMessage({ account, message: messageBytes }));
22013
+ if (!signResult) {
21606
22014
  throw new Error('MWA returned no signature');
21607
22015
  }
21608
- const { signature: sigBytes } = signResults[0];
22016
+ const { signature: sigBytes } = signResult;
21609
22017
  const signatureBase64 = bufferExports.Buffer.from(sigBytes).toString('base64');
21610
22018
  // Create Tarobase session on the server.
21611
22019
  const createSessionResult = await createSessionWithSignature(base58Addr, messageText, signatureBase64);
@@ -22358,4 +22766,4 @@ class PrivyExpoProvider {
22358
22766
  }
22359
22767
 
22360
22768
  export { getCachedData as $, subscribe as A, useAuth as B, deserializeTransaction as C, getIdToken as D, setPlatform as E, getPlatform as F, PrivyWalletProvider as G, DEFAULT_TEST_ADDRESS as H, isMobileWalletAvailable as I, registerMobileWalletAdapter as J, PrivyExpoProvider as K, InsufficientBalanceError as L, MockAuthProvider as M, ServerSessionManager as N, OffchainAuthProvider as O, PhantomWalletProvider as P, buildSetDocumentsTransaction as Q, ReactNativeSessionManager as R, SolanaMobileWalletProvider as S, clearCache as T, closeAllSubscriptions as U, convertRemainingAccounts as V, WebSessionManager as W, createSessionWithPrivy as X, createSessionWithSignature as Y, genAuthNonce as Z, genSolanaMessage as _, base58 as a, getMany as a0, reconnectWithNewAuth as a1, refreshSession as a2, signSessionCreateMessage as a3, bufferExports as b, getCurrentUser as c, onAuthLoadingChanged as d, getAuthLoading as e, logout as f, getDefaultExportFromCjs$1 as g, getConfig as h, init as i, getAuthProvider as j, get as k, login as l, setMany as m, setFile as n, onAuthStateChanged as o, getFiles as p, runQueryMany as q, runQuery as r, set as s, runExpression as t, runExpressionMany as u, signMessage as v, signTransaction as w, signAndSubmitTransaction as x, count as y, aggregate as z };
22361
- //# sourceMappingURL=index-ZKzq5QT_.esm.js.map
22769
+ //# sourceMappingURL=index-C4AnWFs_.esm.js.map