@bounded-sh/client 0.0.58 → 0.0.59

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 (71) hide show
  1. package/dist/auth/index.d.ts +1 -1
  2. package/dist/{email-auth-provider-BlJI-8w9.js → email-auth-provider-BSw9FRjg.js} +3 -3
  3. package/dist/email-auth-provider-BSw9FRjg.js.map +1 -0
  4. package/dist/{email-auth-provider-CX7foEhA.mjs → email-auth-provider-DhAMOILG.mjs} +3 -3
  5. package/dist/email-auth-provider-DhAMOILG.mjs.map +1 -0
  6. package/dist/{email-auth-provider-BHtR1H_E.js → email-auth-provider-N-dfsNnE.js} +3 -3
  7. package/dist/email-auth-provider-N-dfsNnE.js.map +1 -0
  8. package/dist/{email-auth-provider-CfNSS8Du.mjs → email-auth-provider-deB_ADc5.mjs} +3 -3
  9. package/dist/email-auth-provider-deB_ADc5.mjs.map +1 -0
  10. package/dist/{guest-auth-provider-DJmuReVa.mjs → guest-auth-provider-B78Ugfar.mjs} +7 -7
  11. package/dist/guest-auth-provider-B78Ugfar.mjs.map +1 -0
  12. package/dist/{guest-auth-provider-BPXDJoEQ.js → guest-auth-provider-BFodq9Rc.js} +7 -7
  13. package/dist/guest-auth-provider-BFodq9Rc.js.map +1 -0
  14. package/dist/{guest-auth-provider-BRjJV8Zq.js → guest-auth-provider-Czl48mOP.js} +7 -7
  15. package/dist/guest-auth-provider-Czl48mOP.js.map +1 -0
  16. package/dist/{guest-auth-provider-DxhZ5sWN.mjs → guest-auth-provider-D9wbogwi.mjs} +7 -7
  17. package/dist/guest-auth-provider-D9wbogwi.mjs.map +1 -0
  18. package/dist/{index-DWodlTFG.mjs → index-SHt4VZZV.mjs} +173 -35
  19. package/dist/index-SHt4VZZV.mjs.map +1 -0
  20. package/dist/{index-MKE9tHpl.js → index-uu8hKP-p.js} +172 -33
  21. package/dist/index-uu8hKP-p.js.map +1 -0
  22. package/dist/index.d.ts +2 -0
  23. package/dist/index.js +2 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.mjs +1 -1
  26. package/dist/{index.native-CQiw9baS.mjs → index.native-D-8IAEy-.mjs} +162 -24
  27. package/dist/index.native-D-8IAEy-.mjs.map +1 -0
  28. package/dist/{index.native-hu3o3zXU.js → index.native-D48QQ0-q.js} +161 -22
  29. package/dist/index.native-D48QQ0-q.js.map +1 -0
  30. package/dist/index.native.d.ts +2 -0
  31. package/dist/index.native.js +2 -1
  32. package/dist/index.native.js.map +1 -1
  33. package/dist/index.native.mjs +1 -1
  34. package/dist/{injected-evm-wallet-provider-BOPzdm7E.js → injected-evm-wallet-provider-CItxws1D.js} +4 -4
  35. package/dist/injected-evm-wallet-provider-CItxws1D.js.map +1 -0
  36. package/dist/{injected-evm-wallet-provider-DCGnUedJ.mjs → injected-evm-wallet-provider-CJsLX16m.mjs} +4 -4
  37. package/dist/injected-evm-wallet-provider-CJsLX16m.mjs.map +1 -0
  38. package/dist/{injected-evm-wallet-provider-Xbt2CUPi.js → injected-evm-wallet-provider-HQMOL_mZ.js} +4 -4
  39. package/dist/injected-evm-wallet-provider-HQMOL_mZ.js.map +1 -0
  40. package/dist/{injected-evm-wallet-provider-CnJRLE8P.mjs → injected-evm-wallet-provider-UWvcy-LO.mjs} +4 -4
  41. package/dist/injected-evm-wallet-provider-UWvcy-LO.mjs.map +1 -0
  42. package/dist/{injected-wallet-provider-Dg3MieTq.mjs → injected-wallet-provider-BihII94U.mjs} +3 -3
  43. package/dist/injected-wallet-provider-BihII94U.mjs.map +1 -0
  44. package/dist/{injected-wallet-provider-Bps6a9IP.mjs → injected-wallet-provider-CNYAynIB.mjs} +3 -3
  45. package/dist/injected-wallet-provider-CNYAynIB.mjs.map +1 -0
  46. package/dist/{injected-wallet-provider-BUvN5Y6_.js → injected-wallet-provider-CVeZgfEt.js} +3 -3
  47. package/dist/injected-wallet-provider-CVeZgfEt.js.map +1 -0
  48. package/dist/{injected-wallet-provider-7ep-jcal.js → injected-wallet-provider-CmXqreEE.js} +3 -3
  49. package/dist/injected-wallet-provider-CmXqreEE.js.map +1 -0
  50. package/dist/onramp.d.ts +30 -0
  51. package/package.json +2 -2
  52. package/dist/email-auth-provider-BHtR1H_E.js.map +0 -1
  53. package/dist/email-auth-provider-BlJI-8w9.js.map +0 -1
  54. package/dist/email-auth-provider-CX7foEhA.mjs.map +0 -1
  55. package/dist/email-auth-provider-CfNSS8Du.mjs.map +0 -1
  56. package/dist/guest-auth-provider-BPXDJoEQ.js.map +0 -1
  57. package/dist/guest-auth-provider-BRjJV8Zq.js.map +0 -1
  58. package/dist/guest-auth-provider-DJmuReVa.mjs.map +0 -1
  59. package/dist/guest-auth-provider-DxhZ5sWN.mjs.map +0 -1
  60. package/dist/index-DWodlTFG.mjs.map +0 -1
  61. package/dist/index-MKE9tHpl.js.map +0 -1
  62. package/dist/index.native-CQiw9baS.mjs.map +0 -1
  63. package/dist/index.native-hu3o3zXU.js.map +0 -1
  64. package/dist/injected-evm-wallet-provider-BOPzdm7E.js.map +0 -1
  65. package/dist/injected-evm-wallet-provider-CnJRLE8P.mjs.map +0 -1
  66. package/dist/injected-evm-wallet-provider-DCGnUedJ.mjs.map +0 -1
  67. package/dist/injected-evm-wallet-provider-Xbt2CUPi.js.map +0 -1
  68. package/dist/injected-wallet-provider-7ep-jcal.js.map +0 -1
  69. package/dist/injected-wallet-provider-BUvN5Y6_.js.map +0 -1
  70. package/dist/injected-wallet-provider-Bps6a9IP.mjs.map +0 -1
  71. package/dist/injected-wallet-provider-Dg3MieTq.mjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -30,6 +30,8 @@ export type { TurnkeySignResult, TurnkeyWallet } from "./auth/turnkey-signer-bri
30
30
  export { startTurnkeyEmailLogin } from "./auth/turnkey-auth";
31
31
  export type { TurnkeyEmailLoginHandle } from "./auth/turnkey-auth";
32
32
  export { getIdToken } from "./utils";
33
+ export { onramp } from "./onramp";
34
+ export type { OnrampOptions, OnrampResult } from "./onramp";
33
35
  export { setPlatform, getPlatform } from "./platform";
34
36
  export type { PlatformAdapter, StorageAdapter } from "./platform";
35
37
  export { OffchainAuthProvider, OffchainAuthProviderConfig, } from "./auth/providers/offchain-auth-provider";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-MKE9tHpl.js');
3
+ var index = require('./index-uu8hKP-p.js');
4
4
  var core = require('@bounded-sh/core');
5
5
  require('react');
6
6
 
@@ -39,6 +39,7 @@ exports.loginWithWallet = index.loginWithWallet;
39
39
  exports.logout = index.logout;
40
40
  exports.onAuthLoadingChanged = index.onAuthLoadingChanged;
41
41
  exports.onAuthStateChanged = index.onAuthStateChanged;
42
+ exports.onramp = index.onramp;
42
43
  exports.openBoundedWidget = index.openBoundedWidget;
43
44
  exports.requestEip6963Providers = index.requestEip6963Providers;
44
45
  exports.setPlatform = index.setPlatform;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { $ as BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA, _ as BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA, Z as BUILD_REVIEW_CAPABILITY_SCHEMA, T as BuildsApiError, Y as FAILURE_REASONS, U as NON_TERMINAL_STATES, P as OffchainAuthProvider, X as PARK_REASONS, Q as PrivyExpoProvider, W as RUN_STATES, V as TERMINAL_STATES, I as apps, S as builds, A as completeLoginFromRedirect, C as completeLoginInPopup, k as defaultInjectedEvmProvider, d as defaultInjectedProvider, J as deserializeTransaction, q as getAuthLoading, v as getAuthProvider, m as getCurrentUser, N as getIdToken, L as getOrCreateTurnkeyWallet, g as getPlatform, l as init, t as login, B as loginWithPopup, x as loginWithPrivy, z as loginWithRedirect, y as loginWithWallet, u as logout, p as onAuthLoadingChanged, o as onAuthStateChanged, D as openBoundedWidget, R as requestEip6963Providers, O as setPlatform, w as signInAnonymously, K as signSolanaMessageViaTurnkey, M as startTurnkeyEmailLogin, F as useAuth, H as useBuildRun, G as useQuery } from './index-DWodlTFG.mjs';
1
+ export { a0 as BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA, $ as BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA, _ as BUILD_REVIEW_CAPABILITY_SCHEMA, U as BuildsApiError, Z as FAILURE_REASONS, V as NON_TERMINAL_STATES, Q as OffchainAuthProvider, Y as PARK_REASONS, R as PrivyExpoProvider, X as RUN_STATES, W as TERMINAL_STATES, I as apps, T as builds, A as completeLoginFromRedirect, C as completeLoginInPopup, k as defaultInjectedEvmProvider, d as defaultInjectedProvider, J as deserializeTransaction, q as getAuthLoading, v as getAuthProvider, m as getCurrentUser, N as getIdToken, L as getOrCreateTurnkeyWallet, g as getPlatform, l as init, t as login, B as loginWithPopup, x as loginWithPrivy, z as loginWithRedirect, y as loginWithWallet, u as logout, p as onAuthLoadingChanged, o as onAuthStateChanged, O as onramp, D as openBoundedWidget, S as requestEip6963Providers, P as setPlatform, w as signInAnonymously, K as signSolanaMessageViaTurnkey, M as startTurnkeyEmailLogin, F as useAuth, H as useBuildRun, G as useQuery } from './index-SHt4VZZV.mjs';
2
2
  export * from '@bounded-sh/core';
3
3
  export { BoundedDeclineError, DECLINE_EVENT_NAME, RATE_LIMIT_EVENT_NAME, ScopedClientReadOnlyError, aggregate, count, createClient, deriveDecline, dispatchDeclineEvent, dispatchRateLimitEvent, docId, get, getConfig, getFiles, getMany, queryAggregate, runExpression, runExpressionMany, runQuery, runQueryMany, search, set, setFile, setMany, signAndSubmitTransaction, signMessage, signTransaction, subscribe } from '@bounded-sh/core';
4
4
  import 'react';
@@ -1,4 +1,4 @@
1
- import { assertCanonicalBoundedRuntimeWriteCalldata, getActiveSessionManager, getConfig, WebSessionManager, ReactNativeSessionManager, revokeSession, init as init$1, reconnectWithNewAuth, deriveUserIdentityFromIdToken, subscribe, getIdToken as getIdToken$1, convertRemainingAccounts, buildSetDocumentsTransaction, genAuthNonce, genSolanaMessage, createSessionWithSignature } from '@bounded-sh/core';
1
+ import { assertCanonicalBoundedRuntimeWriteCalldata, getActiveSessionManager, getConfig, WebSessionManager, ReactNativeSessionManager, revokeSession, init as init$1, onSessionCleared, reconnectWithNewAuth, deriveUserIdentityFromIdToken, subscribe, getIdToken as getIdToken$1, convertRemainingAccounts, buildSetDocumentsTransaction, genAuthNonce, genSolanaMessage, createSessionWithSignature } from '@bounded-sh/core';
2
2
  import * as React from 'react';
3
3
 
4
4
  /**
@@ -3454,7 +3454,7 @@ const EMBEDDED_WALLET_UNSUPPORTED = 'Unsupported for embedded smart wallets —
3454
3454
  const NO_EMBEDDED_WALLET = 'This login has no embedded wallet. Enable `"auth": { "wallets": true }` in ' +
3455
3455
  'the app policy so email logins get a non-custodial wallet (@user.address), ' +
3456
3456
  'then sign from a user gesture.';
3457
- function hasDOM$1() {
3457
+ function hasDOM$2() {
3458
3458
  return typeof window !== 'undefined' && typeof document !== 'undefined';
3459
3459
  }
3460
3460
  function decodeJwt$1(token) {
@@ -3514,7 +3514,7 @@ let requestSeq = 0;
3514
3514
  * wallet's owner, and validates that the wallet address matches the account.
3515
3515
  */
3516
3516
  async function signViaSignerPopup(action) {
3517
- if (!hasDOM$1()) {
3517
+ if (!hasDOM$2()) {
3518
3518
  throw new Error('Embedded-wallet signing is only available in the browser (popup-based).');
3519
3519
  }
3520
3520
  const isEvm = action.kind === 'evmTransaction';
@@ -3690,7 +3690,7 @@ const STORED_AUTH_METHOD_KEY$1 = 'bounded_last_auth_method';
3690
3690
  // not by `typeof window` (truthy on RN). OIDC redirect/popup is web-only, but the
3691
3691
  // session it mints is read back through this same selector everywhere.
3692
3692
  const sessionManager = getActiveSessionManager;
3693
- function hasDOM() {
3693
+ function hasDOM$1() {
3694
3694
  return typeof window !== 'undefined' && typeof document !== 'undefined';
3695
3695
  }
3696
3696
  function decodeJwt(token) {
@@ -3721,7 +3721,7 @@ const oidcProviderSingleton = {
3721
3721
  const idToken = sessionManager().getIdToken();
3722
3722
  return idToken ? userFromIdToken(idToken) : null;
3723
3723
  },
3724
- async logout() { sessionManager().clearSession(); },
3724
+ async logout() { await sessionManager().clearSession(); },
3725
3725
  async signMessage(_message) {
3726
3726
  throw new Error(hasEmbeddedWallet() ? EMBEDDED_WALLET_UNSUPPORTED : OIDC_NO_WALLET);
3727
3727
  },
@@ -3830,7 +3830,7 @@ async function buildAuthorize(opts) {
3830
3830
  throw new Error('appId is not configured (init the SDK with your appId)');
3831
3831
  // Web: default to the current page so callers don't have to pass redirectUri. Native has no
3832
3832
  // window — it MUST pass an https universal link (the system auth session needs a real URL).
3833
- const redirectUri = opts.redirectUri || (hasDOM() ? window.location.origin + window.location.pathname : undefined);
3833
+ const redirectUri = opts.redirectUri || (hasDOM$1() ? window.location.origin + window.location.pathname : undefined);
3834
3834
  if (!redirectUri)
3835
3835
  throw new Error('redirectUri is required on React Native — pass the https universal link the app owner registered.');
3836
3836
  const { verifier, challenge } = await makePkce();
@@ -3938,7 +3938,7 @@ async function runNativeLogin(opts) {
3938
3938
  async function loginWithRedirect(opts) {
3939
3939
  if (isNative())
3940
3940
  return runNativeLogin(opts);
3941
- if (!hasDOM())
3941
+ if (!hasDOM$1())
3942
3942
  throw new Error('loginWithRedirect requires a browser or a configured React Native platform');
3943
3943
  const { url, pkce } = await buildAuthorize(opts);
3944
3944
  // Stash the verifier + state so the redirect_uri page can finish the exchange. sessionStorage
@@ -3954,7 +3954,7 @@ async function loginWithRedirect(opts) {
3954
3954
  * loginWithRedirect() (which resolves with the User), so there is no separate redirect
3955
3955
  * page to finish from. Calling it on RN is harmless. */
3956
3956
  async function completeLoginFromRedirect() {
3957
- if (!hasDOM())
3957
+ if (!hasDOM$1())
3958
3958
  return null;
3959
3959
  const url = new URL(window.location.href);
3960
3960
  const code = url.searchParams.get('code');
@@ -4000,7 +4000,7 @@ async function completeLoginFromRedirect() {
4000
4000
  * redirect_uri page posts the code back. The redirect_uri page just calls the usual
4001
4001
  * completeLoginFromRedirect() (which auto-detects the popup) — no separate call needed. */
4002
4002
  async function loginWithPopup(opts) {
4003
- if (!hasDOM())
4003
+ if (!hasDOM$1())
4004
4004
  throw new Error('loginWithPopup is web-only — on React Native use loginWithRedirect()');
4005
4005
  // Open synchronously, before PKCE/config awaits consume the click's user-
4006
4006
  // activation window. Opening only after buildAuthorize() intermittently
@@ -4140,7 +4140,7 @@ async function loginWithPopup(opts) {
4140
4140
  /** Call this on the redirect_uri page when login was opened via loginWithPopup(): posts the
4141
4141
  * code back to the opener and closes. (For the redirect variant use completeLoginFromRedirect.) */
4142
4142
  function completeLoginInPopup(openerOrigin) {
4143
- if (!hasDOM() || !window.opener)
4143
+ if (!hasDOM$1() || !window.opener)
4144
4144
  return;
4145
4145
  const url = new URL(window.location.href);
4146
4146
  const code = url.searchParams.get('code');
@@ -4341,15 +4341,20 @@ function authProviderConfigKey(config) {
4341
4341
  * so both web (WebSessionManager) and RN (ReactNativeSessionManager) sessions
4342
4342
  * are properly cleared.
4343
4343
  */
4344
- function clearIncompatibleSession() {
4344
+ async function clearIncompatibleSession() {
4345
4345
  if (getStoredAuthMethod() === currentAuthMethod) {
4346
4346
  return false;
4347
4347
  }
4348
4348
  // Clear both managers: on web the RN manager is a no-op (not configured),
4349
4349
  // and on RN the web manager is a no-op (no localStorage).
4350
- WebSessionManager.clearSession();
4350
+ //
4351
+ // AWAITED. Session removal is serialized through a cross-tab lock now, so a
4352
+ // fire-and-forget call would let init() reach setCurrentUser while the old
4353
+ // credential was still readable — and a request issued in that gap would
4354
+ // authenticate as the session we are in the middle of discarding.
4355
+ await WebSessionManager.clearSession();
4351
4356
  try {
4352
- ReactNativeSessionManager.clearSession();
4357
+ await ReactNativeSessionManager.clearSession();
4353
4358
  }
4354
4359
  catch ( /* not configured on web */_a) { /* not configured on web */ }
4355
4360
  setStoredAuthMethod(null);
@@ -4448,7 +4453,7 @@ async function getAuthProvider(config) {
4448
4453
  // manager as legacy email sessions. Human login should be started
4449
4454
  // with loginWithRedirect(); this provider is kept as the restore and
4450
4455
  // logout surface for those sessions.
4451
- currentAuthProvider = new (await import('./email-auth-provider-CfNSS8Du.mjs')).EmailAuthProvider();
4456
+ currentAuthProvider = new (await import('./email-auth-provider-deB_ADc5.mjs')).EmailAuthProvider();
4452
4457
  break;
4453
4458
  case "wallet":
4454
4459
  case "phantom": {
@@ -4467,7 +4472,7 @@ async function getAuthProvider(config) {
4467
4472
  if (!isWalletLoginEnabled(config)) {
4468
4473
  throw walletLoginNotEnabledError(authMethod);
4469
4474
  }
4470
- const { InjectedWalletProvider } = await import('./injected-wallet-provider-Bps6a9IP.mjs');
4475
+ const { InjectedWalletProvider } = await import('./injected-wallet-provider-CNYAynIB.mjs');
4471
4476
  currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
4472
4477
  break;
4473
4478
  }
@@ -4480,7 +4485,7 @@ async function getAuthProvider(config) {
4480
4485
  // Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
4481
4486
  // to point at a specific wallet or set chainId/domain.
4482
4487
  const evmWalletConfig = ((_a = config.evmWalletConfig) !== null && _a !== void 0 ? _a : {});
4483
- const { InjectedEvmWalletProvider } = await import('./injected-evm-wallet-provider-DCGnUedJ.mjs');
4488
+ const { InjectedEvmWalletProvider } = await import('./injected-evm-wallet-provider-CJsLX16m.mjs');
4484
4489
  currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
4485
4490
  break;
4486
4491
  }
@@ -4508,7 +4513,7 @@ async function getAuthProvider(config) {
4508
4513
  break;
4509
4514
  case "guest":
4510
4515
  // Anonymous auth: a device-local ed25519 keypair signs the challenge.
4511
- currentAuthProvider = new (await import('./guest-auth-provider-DxhZ5sWN.mjs')).GuestAuthProvider();
4516
+ currentAuthProvider = new (await import('./guest-auth-provider-D9wbogwi.mjs')).GuestAuthProvider();
4512
4517
  break;
4513
4518
  }
4514
4519
  if (!currentAuthProvider) {
@@ -4564,7 +4569,7 @@ async function signInAnonymously() {
4564
4569
  // Lazy-load the guest provider so its ed25519/web3 dependencies stay out of
4565
4570
  // the main bundle for data-only apps. Specifier is a static string literal
4566
4571
  // so bundle-splitting can see it.
4567
- const provider = new (await import('./guest-auth-provider-DxhZ5sWN.mjs')).GuestAuthProvider();
4572
+ const provider = new (await import('./guest-auth-provider-D9wbogwi.mjs')).GuestAuthProvider();
4568
4573
  setAuthLoading(true); // reflect "signing in…" while the guest keypair session is minted
4569
4574
  const commit = (user) => {
4570
4575
  // No await/interleaving inside this block: provider/method/config/marker
@@ -4606,7 +4611,7 @@ async function signInAnonymously() {
4606
4611
  }
4607
4612
  catch (_b) {
4608
4613
  try {
4609
- getActiveSessionManager().clearSession();
4614
+ await getActiveSessionManager().clearSession();
4610
4615
  }
4611
4616
  catch ( /* fail closed below */_c) { /* fail closed below */ }
4612
4617
  }
@@ -4830,6 +4835,22 @@ async function logout$1(options) {
4830
4835
  }
4831
4836
  }
4832
4837
 
4838
+ /**
4839
+ * Subscribed once per process, not per init(): re-registering on every init would
4840
+ * stack duplicate handlers on repeated initialization.
4841
+ */
4842
+ let sessionClearedBridgeRegistered = false;
4843
+ function registerSessionClearedBridge() {
4844
+ if (sessionClearedBridgeRegistered)
4845
+ return;
4846
+ sessionClearedBridgeRegistered = true;
4847
+ onSessionCleared(() => {
4848
+ // Core fires this only when storage was ACTUALLY cleared, never on a
4849
+ // transient refresh failure that preserved the session — so this cannot
4850
+ // sign anyone out over a network blip.
4851
+ setCurrentUser(null);
4852
+ });
4853
+ }
4833
4854
  /**
4834
4855
  * Read the active session's idToken synchronously from whichever store is live
4835
4856
  * for this runtime (WebSessionManager on web, ReactNativeSessionManager on RN —
@@ -4887,6 +4908,15 @@ async function init(newConfig) {
4887
4908
  // setting it here makes "no flash" the SDK's default behavior for every consumer.
4888
4909
  setAuthLoading(true);
4889
4910
  try {
4911
+ // Bridge core's "the stored session is gone" signal into SDK auth state.
4912
+ //
4913
+ // Core cannot import this package, and a session can die deep inside a
4914
+ // session manager (dead refresh token, rejected refresh, app-id mismatch).
4915
+ // Before this, setCurrentUser(null) was only ever called by logout() and
4916
+ // init(), so storage could be wiped while `currentUser` stayed populated —
4917
+ // onAuthStateChanged never fired, and every consumer UI went on showing a
4918
+ // connected wallet for a session the server no longer knew about.
4919
+ registerSessionClearedBridge();
4890
4920
  // Get auth provider first
4891
4921
  authProviderInstance = await getAuthProvider(newConfig);
4892
4922
  // Initialize config with auth provider
@@ -4903,7 +4933,12 @@ async function init(newConfig) {
4903
4933
  let user = await authProviderInstance.restoreSession();
4904
4934
  // If a session exists but was created before auth method tracking (legacy session),
4905
4935
  // clear it to avoid mismatches when the app switches auth methods (e.g. email → phantom)
4906
- if (user && clearIncompatibleSession()) {
4936
+ //
4937
+ // AWAITED: the clear is serialized through a cross-tab lock now, and an
4938
+ // unawaited call would return a Promise (always truthy) — nulling the user
4939
+ // unconditionally AND letting setCurrentUser run while the old credential
4940
+ // was still in storage.
4941
+ if (user && await clearIncompatibleSession()) {
4907
4942
  user = null;
4908
4943
  }
4909
4944
  setCurrentUser(user);
@@ -5766,6 +5801,109 @@ async function deserializeTransaction(tx) {
5766
5801
  }
5767
5802
  }
5768
5803
 
5804
+ // bounded.onramp() - fund the signed-in user's wallet with Coinbase Onramp.
5805
+ //
5806
+ // Web-only. Opens Coinbase's hosted checkout (pay.coinbase.com) in a popup
5807
+ // (new-tab fallback) using a single-use session token minted by the Bounded
5808
+ // platform at POST <origin>/__bounded/onramp/session on the app's own origin.
5809
+ // The platform holds the Coinbase credential; the app never sees it. The
5810
+ // session is bound server-side to the caller's verified Bounded JWT, and the
5811
+ // destination defaults to that user's embedded wallet.
5812
+ //
5813
+ // Works on Bounded-served origins (<app>.bounded.page / custom domains). On a
5814
+ // local dev origin the session endpoint does not exist; we fail with a clear
5815
+ // error rather than guessing a host.
5816
+ function hasDOM() {
5817
+ return typeof window !== 'undefined' && typeof document !== 'undefined';
5818
+ }
5819
+ /**
5820
+ * Open Coinbase Onramp for the signed-in user. Resolves when the popup closes.
5821
+ * Call from a click handler - popup blockers require user activation.
5822
+ */
5823
+ async function onramp(options = {}) {
5824
+ var _a, _b, _c;
5825
+ if (!hasDOM())
5826
+ throw new Error('onramp() is web-only');
5827
+ const user = getCurrentUser();
5828
+ const address = (_b = (_a = options.address) !== null && _a !== void 0 ? _a : user === null || user === void 0 ? void 0 : user.address) !== null && _b !== void 0 ? _b : undefined;
5829
+ if (!address) {
5830
+ throw new Error(user
5831
+ ? 'onramp(): the signed-in account has no wallet address - pass { address } explicitly'
5832
+ : 'onramp(): no signed-in user - call login() first or pass { address }');
5833
+ }
5834
+ const idToken = await getIdToken();
5835
+ if (!idToken)
5836
+ throw new Error('onramp(): no active session - call login() first');
5837
+ // Open the window synchronously so the click's user-activation window is not
5838
+ // consumed by the fetch below (same hard-won pattern as loginWithPopup).
5839
+ let popup = null;
5840
+ if (!options.newTab) {
5841
+ const w = options.width || 460;
5842
+ const h = options.height || 720;
5843
+ const left = window.screenX + (window.outerWidth - w) / 2;
5844
+ const top = window.screenY + (window.outerHeight - h) / 2;
5845
+ popup = window.open('', 'bounded-onramp', `width=${w},height=${h},left=${left},top=${top}`);
5846
+ }
5847
+ let session;
5848
+ try {
5849
+ const res = await fetch(`${window.location.origin}/__bounded/onramp/session`, {
5850
+ method: 'POST',
5851
+ headers: { Authorization: `Bearer ${idToken}`, 'content-type': 'application/json' },
5852
+ body: JSON.stringify(Object.assign(Object.assign(Object.assign({}, (options.asset ? { asset: options.asset } : {})), (options.address ? { address: options.address } : {})), (options.amountUsd !== undefined ? { amountUsd: options.amountUsd } : {}))),
5853
+ });
5854
+ if (!res.ok) {
5855
+ let detail = '';
5856
+ try {
5857
+ detail = (_c = (await res.json()).error) !== null && _c !== void 0 ? _c : '';
5858
+ }
5859
+ catch ( /* keep status only */_d) { /* keep status only */ }
5860
+ if (res.status === 404) {
5861
+ throw new Error('onramp(): session endpoint not found - onramp works on Bounded-served origins (your deployed app URL), not local dev servers');
5862
+ }
5863
+ throw new Error(`onramp(): session mint failed (${res.status}${detail ? `: ${detail}` : ''})`);
5864
+ }
5865
+ session = (await res.json());
5866
+ }
5867
+ catch (error) {
5868
+ try {
5869
+ popup === null || popup === void 0 ? void 0 : popup.close();
5870
+ }
5871
+ catch ( /* ignore */_e) { /* ignore */ }
5872
+ throw error;
5873
+ }
5874
+ if (popup) {
5875
+ try {
5876
+ popup.location.replace(session.url);
5877
+ }
5878
+ catch (_f) {
5879
+ try {
5880
+ popup.location.href = session.url;
5881
+ }
5882
+ catch (_g) {
5883
+ try {
5884
+ popup.close();
5885
+ }
5886
+ catch ( /* ignore */_h) { /* ignore */ }
5887
+ throw new Error('onramp(): popup failed to navigate - retry with { newTab: true }');
5888
+ }
5889
+ }
5890
+ return await new Promise((resolve) => {
5891
+ const timer = setInterval(() => {
5892
+ if (popup.closed) {
5893
+ clearInterval(timer);
5894
+ resolve({ status: 'closed', address: session.address, asset: session.asset });
5895
+ }
5896
+ }, 500);
5897
+ });
5898
+ }
5899
+ // New-tab path (popup was blocked or explicitly requested): cross-origin tab
5900
+ // close is not observable, so resolve immediately.
5901
+ const tab = window.open(session.url, '_blank');
5902
+ if (!tab)
5903
+ throw new Error('onramp(): window.open was blocked - call onramp() from a click handler');
5904
+ return { status: 'opened', address: session.address, asset: session.asset };
5905
+ }
5906
+
5769
5907
  /**
5770
5908
  * Extracts a human-readable error message from Solana transaction logs.
5771
5909
  */
@@ -5895,7 +6033,7 @@ class PrivyExpoProvider {
5895
6033
  return { provider: this, address: session.address };
5896
6034
  }
5897
6035
  // Stale session — clear and continue to fresh login flow
5898
- getActiveSessionManager().clearSession();
6036
+ await getActiveSessionManager().clearSession();
5899
6037
  }
5900
6038
  // Trigger Privy login
5901
6039
  const privyUser = await this.privyMethods.login();
@@ -6076,7 +6214,7 @@ class PrivyExpoProvider {
6076
6214
  if ((_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.isAuthenticated) {
6077
6215
  await this.privyMethods.logout();
6078
6216
  }
6079
- getActiveSessionManager().clearSession();
6217
+ await getActiveSessionManager().clearSession();
6080
6218
  }
6081
6219
  async getNativeMethods() {
6082
6220
  return this.privyMethods;
@@ -6149,5 +6287,5 @@ class PrivyExpoProvider {
6149
6287
  }
6150
6288
  }
6151
6289
 
6152
- export { useAuth as A, useQuery as B, useBuildRun as C, apps as D, EMBEDDED_WALLET_UNSUPPORTED as E, deserializeTransaction as F, getIdToken as G, setPlatform as H, builds as I, BuildsApiError as J, PARK_REASONS as K, FAILURE_REASONS as L, BUILD_REVIEW_CAPABILITY_SCHEMA as M, NON_TERMINAL_STATES as N, OffchainAuthProvider as O, PrivyExpoProvider as P, BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA as Q, RUN_STATES as R, BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA as S, TERMINAL_STATES as T, hasEmbeddedEvmWallet as a, embeddedSignAndSubmit as b, setAuthLoading as c, bufferExports as d, embeddedRunEvmTransaction as e, bs58 as f, getPlatform as g, hasEmbeddedWallet as h, confirmAndCheckTransaction as i, init as j, getCurrentUser as k, onAuthLoadingChanged as l, getAuthLoading as m, normalizeSolanaRpcUrl as n, onAuthStateChanged as o, login as p, logout as q, resolveSolanaRpcUrl as r, setCurrentUser as s, getAuthProvider as t, signInAnonymously as u, loginWithPrivy as v, loginWithRedirect as w, completeLoginFromRedirect as x, loginWithPopup as y, completeLoginInPopup as z };
6153
- //# sourceMappingURL=index.native-CQiw9baS.mjs.map
6290
+ export { useAuth as A, useQuery as B, useBuildRun as C, apps as D, EMBEDDED_WALLET_UNSUPPORTED as E, deserializeTransaction as F, getIdToken as G, onramp as H, setPlatform as I, builds as J, BuildsApiError as K, PARK_REASONS as L, FAILURE_REASONS as M, NON_TERMINAL_STATES as N, OffchainAuthProvider as O, PrivyExpoProvider as P, BUILD_REVIEW_CAPABILITY_SCHEMA as Q, RUN_STATES as R, BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA as S, TERMINAL_STATES as T, BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA as U, hasEmbeddedEvmWallet as a, embeddedSignAndSubmit as b, setAuthLoading as c, bufferExports as d, embeddedRunEvmTransaction as e, bs58 as f, getPlatform as g, hasEmbeddedWallet as h, confirmAndCheckTransaction as i, init as j, getCurrentUser as k, onAuthLoadingChanged as l, getAuthLoading as m, normalizeSolanaRpcUrl as n, onAuthStateChanged as o, login as p, logout as q, resolveSolanaRpcUrl as r, setCurrentUser as s, getAuthProvider as t, signInAnonymously as u, loginWithPrivy as v, loginWithRedirect as w, completeLoginFromRedirect as x, loginWithPopup as y, completeLoginInPopup as z };
6291
+ //# sourceMappingURL=index.native-D-8IAEy-.mjs.map