@bounded-sh/client 0.0.118 → 0.0.120-expo.0

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 (60) hide show
  1. package/dist/auth/oidc-auth.d.ts +2 -1
  2. package/dist/auth/providers/email-auth-provider.d.ts +2 -1
  3. package/dist/auth/providers/offchain-auth-provider.d.ts +2 -1
  4. package/dist/auth/turnkey-signer-bridge.d.ts +16 -0
  5. package/dist/auth/turnkey-wallet-widget.d.ts +4 -0
  6. package/dist/{email-auth-provider-C-qQ46kD.js → email-auth-provider-Bb_0mHJ_.js} +7 -2
  7. package/dist/email-auth-provider-Bb_0mHJ_.js.map +1 -0
  8. package/dist/{email-auth-provider-BYiK3ZCv.js → email-auth-provider-IsiArtx0.js} +7 -2
  9. package/dist/email-auth-provider-IsiArtx0.js.map +1 -0
  10. package/dist/{email-auth-provider-B9cZ-puM.mjs → email-auth-provider-TA2AbU5Y.mjs} +7 -2
  11. package/dist/email-auth-provider-TA2AbU5Y.mjs.map +1 -0
  12. package/dist/{email-auth-provider-DFHalX9c.mjs → email-auth-provider-ao5ce_SN.mjs} +7 -2
  13. package/dist/email-auth-provider-ao5ce_SN.mjs.map +1 -0
  14. package/dist/{guest-auth-provider-g5-T58yA.js → guest-auth-provider-CJUbifdu.js} +2 -2
  15. package/dist/{guest-auth-provider-g5-T58yA.js.map → guest-auth-provider-CJUbifdu.js.map} +1 -1
  16. package/dist/{guest-auth-provider-D1q3C5uC.js → guest-auth-provider-DTEwf7qP.js} +2 -2
  17. package/dist/{guest-auth-provider-D1q3C5uC.js.map → guest-auth-provider-DTEwf7qP.js.map} +1 -1
  18. package/dist/{guest-auth-provider-i8-RL0js.mjs → guest-auth-provider-Dw-bF10B.mjs} +2 -2
  19. package/dist/{guest-auth-provider-BRq3JB0_.mjs.map → guest-auth-provider-Dw-bF10B.mjs.map} +1 -1
  20. package/dist/{guest-auth-provider-BRq3JB0_.mjs → guest-auth-provider-DxQG3JvU.mjs} +2 -2
  21. package/dist/{guest-auth-provider-i8-RL0js.mjs.map → guest-auth-provider-DxQG3JvU.mjs.map} +1 -1
  22. package/dist/{index-xNGb1ROp.mjs → index-BdzGX8fS.mjs} +113 -23
  23. package/dist/index-BdzGX8fS.mjs.map +1 -0
  24. package/dist/{index-eMCWYiRe.js → index-KUBcQdTX.js} +113 -22
  25. package/dist/index-KUBcQdTX.js.map +1 -0
  26. package/dist/index.d.ts +2 -1
  27. package/dist/index.js +5 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +2 -2
  30. package/dist/{index.native-ByI3rRu4.js → index.native-CZSRvIAb.js} +130 -23
  31. package/dist/index.native-CZSRvIAb.js.map +1 -0
  32. package/dist/{index.native-YmmnwqEw.mjs → index.native-N5zxPEYK.mjs} +130 -24
  33. package/dist/index.native-N5zxPEYK.mjs.map +1 -0
  34. package/dist/index.native.js +1 -1
  35. package/dist/index.native.mjs +1 -1
  36. package/dist/{injected-evm-wallet-provider-BIYAL_NZ.js → injected-evm-wallet-provider--XJFh-7d.js} +2 -2
  37. package/dist/{injected-evm-wallet-provider-BIYAL_NZ.js.map → injected-evm-wallet-provider--XJFh-7d.js.map} +1 -1
  38. package/dist/{injected-evm-wallet-provider-BMjQaUiB.js → injected-evm-wallet-provider-4T_-2UQI.js} +2 -2
  39. package/dist/{injected-evm-wallet-provider-BMjQaUiB.js.map → injected-evm-wallet-provider-4T_-2UQI.js.map} +1 -1
  40. package/dist/{injected-evm-wallet-provider--x3yWNps.mjs → injected-evm-wallet-provider-BlSFIzEA.mjs} +2 -2
  41. package/dist/{injected-evm-wallet-provider--x3yWNps.mjs.map → injected-evm-wallet-provider-BlSFIzEA.mjs.map} +1 -1
  42. package/dist/{injected-evm-wallet-provider-BoLGCVqD.mjs → injected-evm-wallet-provider-CtPPhtMh.mjs} +2 -2
  43. package/dist/{injected-evm-wallet-provider-BoLGCVqD.mjs.map → injected-evm-wallet-provider-CtPPhtMh.mjs.map} +1 -1
  44. package/dist/{injected-wallet-provider-DuWTw-fM.mjs → injected-wallet-provider-Bnsfazum.mjs} +2 -2
  45. package/dist/{injected-wallet-provider-DuWTw-fM.mjs.map → injected-wallet-provider-Bnsfazum.mjs.map} +1 -1
  46. package/dist/{injected-wallet-provider-D3fVFadN.js → injected-wallet-provider-CJ0v5Sgn.js} +2 -2
  47. package/dist/{injected-wallet-provider-D3fVFadN.js.map → injected-wallet-provider-CJ0v5Sgn.js.map} +1 -1
  48. package/dist/{injected-wallet-provider-zXw__lyf.js → injected-wallet-provider-Ckljhcbu.js} +2 -2
  49. package/dist/{injected-wallet-provider-zXw__lyf.js.map → injected-wallet-provider-Ckljhcbu.js.map} +1 -1
  50. package/dist/{injected-wallet-provider-DSOjJP3u.mjs → injected-wallet-provider-yyJfuVgv.mjs} +2 -2
  51. package/dist/{injected-wallet-provider-DSOjJP3u.mjs.map → injected-wallet-provider-yyJfuVgv.mjs.map} +1 -1
  52. package/package.json +2 -2
  53. package/dist/email-auth-provider-B9cZ-puM.mjs.map +0 -1
  54. package/dist/email-auth-provider-BYiK3ZCv.js.map +0 -1
  55. package/dist/email-auth-provider-C-qQ46kD.js.map +0 -1
  56. package/dist/email-auth-provider-DFHalX9c.mjs.map +0 -1
  57. package/dist/index-eMCWYiRe.js.map +0 -1
  58. package/dist/index-xNGb1ROp.mjs.map +0 -1
  59. package/dist/index.native-ByI3rRu4.js.map +0 -1
  60. package/dist/index.native-YmmnwqEw.mjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -17,8 +17,9 @@ export type { HostedAuthMethod, OidcLoginOptions, PopupLoginOptions } from "./au
17
17
  export { openBoundedWidget } from "./auth/bounded-login-widget";
18
18
  export type { BoundedWidgetOptions } from "./auth/bounded-login-widget";
19
19
  export { ensureSignedIn } from "./auth/ensure-signed-in";
20
- export { get, getMany, docId, set, setMany, setFile, getFiles, search, queryAggregate, runQuery, runQueryMany, runExpression, runExpressionMany, signMessage, signTransaction, signAndSubmitTransaction, count, aggregate, type GetOptions, type SearchOptions, type SetOptions, type CountOptions, type AggregateOptions, type AggregateOperation, type AggregateResult, type AggregateSpec, type AggregateRow, type QueryAggregateOptions, } from "@bounded-sh/core";
20
+ export { get, getMany, docId, set, setMany, setFile, getFiles, search, queryAggregate, runQuery, runQueryMany, runExpression, runExpressionMany, signMessage, signTransaction, signAndSubmitTransaction, prepareToSign, count, aggregate, type GetOptions, type SearchOptions, type SetOptions, type CountOptions, type AggregateOptions, type AggregateOperation, type AggregateResult, type AggregateSpec, type AggregateRow, type QueryAggregateOptions, } from "@bounded-sh/core";
21
21
  export type { GetOptions as BoundedGetOptions } from "@bounded-sh/core";
22
+ export type { SignerReadiness } from "@bounded-sh/core";
22
23
  export { reconcileSetResult, waitForSetResult } from "@bounded-sh/core";
23
24
  export type { SetResult, SetEntry, SetDocuments, MirrorSync, SolanaFence, ChainTag, SolanaChainTag, CommittedSetResult, ConfirmedSetResult, SolanaConfirmedSetResult, SubmittedSetResult, SolanaSubmittedSetResult, SolanaExpiredNotLandedSetResult, SolanaSignedSetResult, TransactionResult, TransactionReconciliation, ReconcileSetResultOptions, WaitForSetResultOptions, FileUploadResult, FileDeleteResult, } from "@bounded-sh/core";
24
25
  export { subscribe } from "@bounded-sh/core";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-eMCWYiRe.js');
3
+ var index = require('./index-KUBcQdTX.js');
4
4
  var core = require('@bounded-sh/core');
5
5
  require('react');
6
6
 
@@ -148,6 +148,10 @@ Object.defineProperty(exports, "getMany", {
148
148
  enumerable: true,
149
149
  get: function () { return core.getMany; }
150
150
  });
151
+ Object.defineProperty(exports, "prepareToSign", {
152
+ enumerable: true,
153
+ get: function () { return core.prepareToSign; }
154
+ });
151
155
  Object.defineProperty(exports, "queryAggregate", {
152
156
  enumerable: true,
153
157
  get: function () { return core.queryAggregate; }
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,5 +1,5 @@
1
- export { ar as BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA, aq as BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA, ap as BUILD_REVIEW_CAPABILITY_SCHEMA, ai as BuildsApiError, a6 as ConnectionError, ao as FAILURE_REASONS, ak as NON_TERMINAL_STATES, ac as OffchainAuthProvider, an as PARK_REASONS, ad as PrivyExpoProvider, am as RUN_STATES, al as TERMINAL_STATES, aa as VenueEscrowError, W as WalletConfigError, R as apps, ah as builds, a3 as completeConnection, J as completeLoginFromRedirect, a2 as connect, af as connectBroadcast, ag as connectServiceSession, p as defaultInjectedEvmProvider, f as defaultInjectedProvider, a5 as disconnect, a8 as disputeVenueEscrow, G as ensureSharedWalletLoginReady, N as ensureSignedIn, F as ensureWalletLoginReady, a7 as fundVenueEscrow, x as getAuthLoading, B as getAuthProvider, a4 as getConnections, u as getCurrentUser, _ as getIdToken, K as getLoginReturnError, U as getOrCreateTurnkeyWallet, g as getPlatform, Y as getTurnkeyWalletRecoveryUrl, X as getTurnkeyWalletSessionState, a9 as getVenueEscrow, q as init, z as login, L as loginWithPopup, D as loginWithPrivy, I as loginWithRedirect, E as loginWithWallet, A as logout, aj as mediaAgentTools, w as onAuthLoadingChanged, v as onAuthStateChanged, $ as onramp, a0 as onrampQuote, a1 as onrampStatus, M as openBoundedWidget, V as openTurnkeyKeyExport, H as preloadWalletLogin, ae as requestEip6963Providers, ab as setPlatform, C as signInAnonymously, T as signSolanaMessageViaTurnkey, Z as startTurnkeyEmailLogin, k as supportsWalletSignIn, O as useAuth, Q as useBuildRun, P as useQuery, y as waitForAuthReady } from './index-xNGb1ROp.mjs';
1
+ export { as as BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA, ar as BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA, aq as BUILD_REVIEW_CAPABILITY_SCHEMA, aj as BuildsApiError, a7 as ConnectionError, ap as FAILURE_REASONS, al as NON_TERMINAL_STATES, ad as OffchainAuthProvider, ao as PARK_REASONS, ae as PrivyExpoProvider, an as RUN_STATES, am as TERMINAL_STATES, ab as VenueEscrowError, W as WalletConfigError, T as apps, ai as builds, a4 as completeConnection, K as completeLoginFromRedirect, a3 as connect, ag as connectBroadcast, ah as connectServiceSession, q as defaultInjectedEvmProvider, i as defaultInjectedProvider, a6 as disconnect, a9 as disputeVenueEscrow, H as ensureSharedWalletLoginReady, O as ensureSignedIn, G as ensureWalletLoginReady, a8 as fundVenueEscrow, y as getAuthLoading, C as getAuthProvider, a5 as getConnections, v as getCurrentUser, $ as getIdToken, L as getLoginReturnError, V as getOrCreateTurnkeyWallet, g as getPlatform, Z as getTurnkeyWalletRecoveryUrl, Y as getTurnkeyWalletSessionState, aa as getVenueEscrow, u as init, A as login, M as loginWithPopup, E as loginWithPrivy, J as loginWithRedirect, F as loginWithWallet, B as logout, ak as mediaAgentTools, x as onAuthLoadingChanged, w as onAuthStateChanged, a0 as onramp, a1 as onrampQuote, a2 as onrampStatus, N as openBoundedWidget, X as openTurnkeyKeyExport, I as preloadWalletLogin, af as requestEip6963Providers, ac as setPlatform, D as signInAnonymously, U as signSolanaMessageViaTurnkey, _ as startTurnkeyEmailLogin, l as supportsWalletSignIn, P as useAuth, R as useBuildRun, Q as useQuery, z as waitForAuthReady } from './index-BdzGX8fS.mjs';
2
2
  export * from '@bounded-sh/core';
3
- export { AppTokenExchangeError, BoundedDeclineError, DECLINE_EVENT_NAME, RATE_LIMIT_EVENT_NAME, ScopedClientReadOnlyError, aggregate, clearAppTokenCache, count, createAppTokenAuthHeaders, createClient, deriveDecline, dispatchDeclineEvent, dispatchRateLimitEvent, docId, exchangeAppToken, get, getConfig, getFiles, getMany, queryAggregate, reconcileSetResult, runExpression, runExpressionMany, runQuery, runQueryMany, search, set, setFile, setMany, signAndSubmitTransaction, signMessage, signTransaction, subscribe, waitForSetResult } from '@bounded-sh/core';
3
+ export { AppTokenExchangeError, BoundedDeclineError, DECLINE_EVENT_NAME, RATE_LIMIT_EVENT_NAME, ScopedClientReadOnlyError, aggregate, clearAppTokenCache, count, createAppTokenAuthHeaders, createClient, deriveDecline, dispatchDeclineEvent, dispatchRateLimitEvent, docId, exchangeAppToken, get, getConfig, getFiles, getMany, prepareToSign, queryAggregate, reconcileSetResult, runExpression, runExpressionMany, runQuery, runQueryMany, search, set, setFile, setMany, signAndSubmitTransaction, signMessage, signTransaction, subscribe, waitForSetResult } from '@bounded-sh/core';
4
4
  import 'react';
5
5
  //# sourceMappingURL=index.mjs.map
@@ -56,7 +56,18 @@ function walletOperationGuard() {
56
56
  throw new Error('wallet_session_changed');
57
57
  };
58
58
  }
59
- function setWalletSessionState(key, state) { }
59
+ // This realm owns one active SDK session and one retained signer frame.
60
+ let activeWalletState;
61
+ function setWalletSessionState(key, state) { activeWalletState = { key, state }; }
62
+ function walletSessionState(key) {
63
+ if ((activeWalletState === null || activeWalletState === void 0 ? void 0 : activeWalletState.key) !== key)
64
+ return { status: 'verification-required' };
65
+ const state = activeWalletState.state;
66
+ if (state.status === 'ready' && (!Number.isFinite(state.expiresAt) || state.expiresAt <= Date.now())) {
67
+ return { status: 'verification-required', reason: 'wallet_session_expired' };
68
+ }
69
+ return state;
70
+ }
60
71
 
61
72
  /**
62
73
  * Platform abstraction layer for React Native compatibility.
@@ -140,8 +151,17 @@ function createWebPlatform() {
140
151
  // bundlers do not externalize or preload a Node-only module in the
141
152
  // email/guest graph; this branch is unreachable when WebCrypto is
142
153
  // available (all supported browsers and current Node releases).
154
+ // The try makes it an optional dependency for Metro, whose production
155
+ // constant folding turns the specifier back into a literal: a React Native
156
+ // app with no node:crypto mapping still bundles (it passes setPlatform({ sha256 })).
143
157
  const nodeCryptoSpecifier = 'node:crypto';
144
- const { createHash } = await import(/* @vite-ignore */ nodeCryptoSpecifier);
158
+ let createHash;
159
+ try {
160
+ ({ createHash } = await import(/* @vite-ignore */ nodeCryptoSpecifier));
161
+ }
162
+ catch (_b) {
163
+ throw new Error('SHA-256 needs WebCrypto here: pass setPlatform({ sha256 }) (e.g. expo-crypto digest).');
164
+ }
145
165
  const hash = createHash('sha256').update(data).digest();
146
166
  return hash.buffer.slice(hash.byteOffset, hash.byteOffset + hash.byteLength);
147
167
  },
@@ -247,6 +267,10 @@ class OffchainAuthProvider {
247
267
  async signTransaction(tx) {
248
268
  return this.wrappedProvider.signTransaction(tx);
249
269
  }
270
+ async prepareToSign() {
271
+ var _a, _b, _c;
272
+ return (_c = (await ((_b = (_a = this.wrappedProvider).prepareToSign) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : 'ready';
273
+ }
250
274
  /**
251
275
  * Sign and submit transaction - not supported in poofnet environment.
252
276
  * See the real providers (PhantomWalletProvider, SolanaKeypairProvider)
@@ -4164,6 +4188,11 @@ function detachWarmSignerIframe(origin) {
4164
4188
  detachIframe(modal);
4165
4189
  return true;
4166
4190
  }
4191
+ /** A removed frame cannot still supply its in-memory signing session. */
4192
+ function hasWarmSignerFrame(context) {
4193
+ var _a;
4194
+ return Boolean(((_a = modal === null || modal === void 0 ? void 0 : modal.iframe) === null || _a === void 0 ? void 0 : _a.isConnected) && modal.iframeContext === context);
4195
+ }
4167
4196
  function detachIframe(m) {
4168
4197
  if (m.iframe) {
4169
4198
  try {
@@ -4205,7 +4234,7 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4205
4234
  const requestId = String(ex.request.requestId);
4206
4235
  // Serialize: the approve card is modal, and one warm frame handles one request at a time.
4207
4236
  const run = m.chain.then(() => new Promise((resolve, reject) => {
4208
- var _a;
4237
+ var _a, _b;
4209
4238
  let settled = false;
4210
4239
  let usedFallback = false;
4211
4240
  (_a = ex.assertCurrent) === null || _a === void 0 ? void 0 : _a.call(ex);
@@ -4248,16 +4277,20 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4248
4277
  /* frame gone */
4249
4278
  }
4250
4279
  };
4280
+ const dismiss = () => {
4281
+ if (!ex.silent)
4282
+ hideModal(m);
4283
+ };
4251
4284
  const goFallback = () => {
4252
4285
  if (usedFallback || settled)
4253
4286
  return;
4254
4287
  usedFallback = true;
4255
- hideModal(m);
4288
+ dismiss();
4256
4289
  finish(() => popupFallback().then(resolve, reject));
4257
4290
  };
4258
4291
  m.onBackdrop = () => {
4259
4292
  cancelInFrame();
4260
- hideModal(m);
4293
+ dismiss();
4261
4294
  finish(() => reject(new Error("cancelled")));
4262
4295
  };
4263
4296
  m.onIframeMessage = (d) => {
@@ -4272,17 +4305,18 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4272
4305
  if (d.type === "bounded:turnkey:result" && d.requestId === requestId) {
4273
4306
  const outcome = ex.onResult(d);
4274
4307
  if ("error" in outcome) {
4275
- hideModal(m);
4308
+ dismiss();
4276
4309
  finish(() => reject(new Error(outcome.error)));
4277
4310
  return;
4278
4311
  }
4279
4312
  if (outcome.done) {
4280
- hideModal(m);
4313
+ dismiss();
4281
4314
  finish(() => resolve(outcome.value));
4282
4315
  }
4283
4316
  }
4284
4317
  };
4285
- showModal(m);
4318
+ if (!ex.silent)
4319
+ showModal(m);
4286
4320
  if (m.iframeReady)
4287
4321
  send();
4288
4322
  // If the frame never loads, degrade to the popup (best-effort - a post-load
@@ -4295,10 +4329,10 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4295
4329
  ceilingTimer = window.setTimeout(() => {
4296
4330
  if (!settled) {
4297
4331
  cancelInFrame();
4298
- hideModal(m);
4332
+ dismiss();
4299
4333
  finish(() => reject(new Error("Wallet approval timed out.")));
4300
4334
  }
4301
- }, 5 * 60 * 1000);
4335
+ }, (_b = ex.ceilingMs) !== null && _b !== void 0 ? _b : 5 * 60 * 1000);
4302
4336
  }));
4303
4337
  m.chain = run.then(() => undefined, () => undefined);
4304
4338
  return run;
@@ -4800,6 +4834,59 @@ async function clearTurnkeySigningSession(idToken) {
4800
4834
  function hasTurnkeyWallet() {
4801
4835
  return activeTurnkeyAddress() !== null;
4802
4836
  }
4837
+ /** The signer frame could not take the exchange: it never loaded, or a page from before the request existed stays silent. */
4838
+ class SignerFrameUnavailable extends Error {
4839
+ constructor() { super('The Bounded signer frame did not answer.'); }
4840
+ }
4841
+ /** How long a silent session probe may wait for the frame before the write goes on without it. */
4842
+ const SESSION_PROBE_MS = 8000;
4843
+ /**
4844
+ * Make the wallet's 24-hour signing session live BEFORE a transaction exists. Without one the
4845
+ * approve card must first collect an emailed code, which takes longer than a transaction's
4846
+ * blockhash lifetime (about 33 seconds on mainnet in late 2026), so a transaction built before
4847
+ * the code is dead by the time it is signed. A live session is found with nothing shown: the
4848
+ * warm frame answers a silent probe, and it holds the session even where the browser blocks its
4849
+ * storage. Only a lapsed session opens the card, which runs the code ceremony and closes without
4850
+ * signing anything. Resolves `'established'` when that ceremony ran, else `'ready'`.
4851
+ *
4852
+ * Both exchanges run in the warm frame only, since it is the frame that signs next and a popup
4853
+ * keeps its session to itself. Where the frame cannot answer (an embedder that blocks it, or a
4854
+ * signer page from before this request existed), the write goes on the way it always did: the
4855
+ * approve card collects the code itself, and an expired build is built again.
4856
+ */
4857
+ async function ensureTurnkeySigningSession() {
4858
+ if (!hasDOM$2())
4859
+ throw new Error('Turnkey embedded-wallet signing is only available in the browser (trusted wallet UI).');
4860
+ const context = await turnkeySignerPage();
4861
+ context.assertCurrent();
4862
+ if (hasWarmSignerFrame(context.key) && walletSessionState(context.key).status === 'ready')
4863
+ return 'ready';
4864
+ const { url, origin } = context;
4865
+ const authorization = await fetchActionAuthorization('createWallet', context);
4866
+ const frameOnly = () => Promise.reject(new SignerFrameUnavailable());
4867
+ const exchange = (probeOnly) => ({
4868
+ context: context.key, assertCurrent: context.assertCurrent,
4869
+ request: Object.assign({ type: 'bounded:turnkey:session', requestId: `tksession_${Date.now()}_${++requestSeq}`, authorization }, (probeOnly ? { probeOnly: true } : {})),
4870
+ onResult: (d) => d.ok ? { done: true, value: d } : { error: String(d.error || 'The signing session could not be established') },
4871
+ });
4872
+ const probed = await runWidget(url, origin, Object.assign(Object.assign({}, exchange(true)), { silent: true, ceilingMs: SESSION_PROBE_MS }), frameOnly)
4873
+ .catch(() => null);
4874
+ if (!probed)
4875
+ return 'ready';
4876
+ let result = probed;
4877
+ if (result.ready !== true) {
4878
+ try {
4879
+ result = await runWidget(url, origin, exchange(false), frameOnly);
4880
+ }
4881
+ catch (error) {
4882
+ if (error instanceof SignerFrameUnavailable)
4883
+ return 'ready';
4884
+ throw error;
4885
+ }
4886
+ }
4887
+ setWalletSessionState(context.key, { status: 'ready', expiresAt: Number(result.signingSessionExpiresAt) });
4888
+ return result.established === true ? 'established' : 'ready';
4889
+ }
4803
4890
  /**
4804
4891
  * Open the Bounded Turnkey approval card and sign `message` (raw bytes) with the
4805
4892
  * user's Turnkey wallet, resolving with the ed25519 signature and wallet address.
@@ -4836,7 +4923,7 @@ async function signSolanaMessageViaTurnkey(message) {
4836
4923
  // A top-level popup keeps its signing session in the signer origin's own storage, which the
4837
4924
  // warm in-app frame (a partitioned context) cannot see, so it says nothing about that frame.
4838
4925
  if (transport !== 'popup')
4839
- setWalletSessionState(context.key, { expiresAt: Number(d.signingSessionExpiresAt) });
4926
+ setWalletSessionState(context.key, { status: 'ready', expiresAt: Number(d.signingSessionExpiresAt) });
4840
4927
  return { done: true, value: { signature: fromHex(d.signatureHex), address: d.address, subOrgId: String(d.subOrgId || '') } };
4841
4928
  }
4842
4929
  // The hosted signer refuses a cross-app signature inside a frame. Never retry it from here:
@@ -4952,6 +5039,7 @@ async function signAndSubmitTransactionWithTurnkey(transaction, feePayer) {
4952
5039
  var turnkeySignerBridge = /*#__PURE__*/Object.freeze({
4953
5040
  __proto__: null,
4954
5041
  clearTurnkeySigningSession: clearTurnkeySigningSession,
5042
+ ensureTurnkeySigningSession: ensureTurnkeySigningSession,
4955
5043
  hasTurnkeyWallet: hasTurnkeyWallet,
4956
5044
  signAndSubmitTransactionWithTurnkey: signAndSubmitTransactionWithTurnkey,
4957
5045
  signMessageWithTurnkey: signMessageWithTurnkey,
@@ -5031,6 +5119,11 @@ const oidcProviderSingleton = {
5031
5119
  throw new Error(OIDC_NO_WALLET);
5032
5120
  return signTransactionV1WithTurnkey(transaction);
5033
5121
  },
5122
+ async prepareToSign() {
5123
+ if (!hasTurnkeyWallet())
5124
+ throw new Error(OIDC_NO_WALLET);
5125
+ return ensureTurnkeySigningSession();
5126
+ },
5034
5127
  supportedTransactionVersions() {
5035
5128
  return hasTurnkeyWallet() ? ['legacy', 0, 1] : ['legacy', 0];
5036
5129
  },
@@ -5105,6 +5198,14 @@ function cleanCallbackUrl(url) {
5105
5198
  clean.searchParams.delete(key);
5106
5199
  return clean;
5107
5200
  }
5201
+ // The address a code returned to, without the fragment. The issuer never sets one
5202
+ // (redirectUri may not carry one), but a browser can keep one across the redirect
5203
+ // chain: iOS lands a Google sign-in on `<redirectUri>?code=...#`.
5204
+ function returnAddress(url) {
5205
+ const clean = cleanCallbackUrl(url);
5206
+ clean.hash = '';
5207
+ return clean.href;
5208
+ }
5108
5209
  async function validateAttempt(pkce, callback) {
5109
5210
  const cfg = await core.getConfig();
5110
5211
  if (!pkce || typeof pkce.verifier !== 'string' || !pkce.verifier ||
@@ -5114,7 +5215,7 @@ async function validateAttempt(pkce, callback) {
5114
5215
  if (!Number.isFinite(pkce.createdAt) || Date.now() - pkce.createdAt > LOGIN_TIMEOUT_MS || pkce.createdAt > Date.now()) {
5115
5216
  throw new Error('Login expired. Start sign-in again.');
5116
5217
  }
5117
- if (callback && (cleanCallbackUrl(callback).href !== cleanCallbackUrl(new URL(pkce.redirectUri)).href ||
5218
+ if (callback && (returnAddress(callback) !== returnAddress(new URL(pkce.redirectUri)) ||
5118
5219
  (callback.searchParams.has('iss') && callback.searchParams.get('iss') !== pkce.issuer))) {
5119
5220
  throw new Error('Login returned to a different address or from a different auth server. Start sign-in again.');
5120
5221
  }
@@ -5367,7 +5468,7 @@ function parseCallbackParams(callbackUrl) {
5367
5468
  // universal-link callback, verify state, and run the SAME PKCE code→token exchange
5368
5469
  // as web. Returns the signed-in User inline; web redirects complete on the next init().
5369
5470
  async function runNativeLogin(opts) {
5370
- var _a, _b;
5471
+ var _a, _b, _c, _d;
5371
5472
  const { url, pkce } = await buildAuthorize(opts);
5372
5473
  const WebBrowser = await loadExpoWebBrowser();
5373
5474
  const openAuthSession = WebBrowser.openAuthSessionAsync || ((_a = WebBrowser.default) === null || _a === void 0 ? void 0 : _a.openAuthSessionAsync);
@@ -5379,12 +5480,16 @@ async function runNativeLogin(opts) {
5379
5480
  // openAuthSessionAsync keeps JS alive while the system browser is shown, then
5380
5481
  // resolves with the callback URL once the universal link fires — so `pkce`
5381
5482
  // stays in scope and never needs to be persisted.
5382
- const result = await openAuthSession(url, opts.redirectUri);
5483
+ // iOS (17.4+) only returns an https callback to the app when asked to; without it the
5484
+ // sheet treats "https" as a custom scheme and never completes. A custom scheme callback
5485
+ // (an Expo Go preview's exps://) is caught by its scheme either way.
5486
+ const preferUniversalLinks = (_c = (_b = opts.redirectUri) === null || _b === void 0 ? void 0 : _b.startsWith('https:')) !== null && _c !== void 0 ? _c : false;
5487
+ const result = await openAuthSession(url, opts.redirectUri, { preferUniversalLinks });
5383
5488
  if (!result || result.type === 'cancel' || result.type === 'dismiss') {
5384
5489
  throw new Error('Login cancelled');
5385
5490
  }
5386
5491
  if (result.type !== 'success' || typeof result.url !== 'string') {
5387
- throw new Error(`Hosted login did not complete (result: ${(_b = result === null || result === void 0 ? void 0 : result.type) !== null && _b !== void 0 ? _b : 'unknown'})`);
5492
+ throw new Error(`Hosted login did not complete (result: ${(_d = result === null || result === void 0 ? void 0 : result.type) !== null && _d !== void 0 ? _d : 'unknown'})`);
5388
5493
  }
5389
5494
  const { code, state: returnedState } = parseCallbackParams(result.url);
5390
5495
  if (!code)
@@ -5407,7 +5512,8 @@ async function runNativeLogin(opts) {
5407
5512
  * callback, runs the PKCE exchange INLINE, and resolves with the signed-in User. No
5408
5513
  * completeLoginFromRedirect() call is needed on native. Requires `redirectUri` to be an
5409
5514
  * https UNIVERSAL LINK whose origin the app owner registered in the app's allowedOrigins
5410
- * (custom `myapp://` schemes are rejected by the issuer). Needs the optional peer deps
5515
+ * (custom `myapp://` schemes are rejected by the issuer; an app preview opened in Expo Go
5516
+ * uses `exps://<preview host>/--/<path>`). Needs the optional peer deps
5411
5517
  * expo-web-browser + (expo-crypto or react-native-get-random-values). */
5412
5518
  async function loginWithRedirect(opts) {
5413
5519
  if (isNative())
@@ -6086,7 +6192,7 @@ async function getAuthProvider(config, fromStorage = false) {
6086
6192
  // manager as legacy email sessions. Human login should be started
6087
6193
  // with loginWithRedirect(); this provider is kept as the restore and
6088
6194
  // logout surface for those sessions.
6089
- currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-C-qQ46kD.js'); })).EmailAuthProvider();
6195
+ currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-Bb_0mHJ_.js'); })).EmailAuthProvider();
6090
6196
  break;
6091
6197
  case "phantom": {
6092
6198
  // First-class Solana WALLET LOGIN (the poof/TaroBase-style "connect
@@ -6128,7 +6234,7 @@ async function getAuthProvider(config, fromStorage = false) {
6128
6234
  // (bounded-login-widget.ts), so registration never counts as
6129
6235
  // evidence the user has a wallet.
6130
6236
  await ensureSolanaMobileWalletRegistered(config, configuredNetwork);
6131
- const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-zXw__lyf.js'); });
6237
+ const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-Ckljhcbu.js'); });
6132
6238
  currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
6133
6239
  break;
6134
6240
  }
@@ -6141,7 +6247,7 @@ async function getAuthProvider(config, fromStorage = false) {
6141
6247
  // Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
6142
6248
  // to point at a specific wallet or set chainId/domain.
6143
6249
  const evmWalletConfig = ((_a = config.evmWalletConfig) !== null && _a !== void 0 ? _a : {});
6144
- const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-BMjQaUiB.js'); });
6250
+ const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-4T_-2UQI.js'); });
6145
6251
  currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
6146
6252
  break;
6147
6253
  }
@@ -6166,7 +6272,7 @@ async function getAuthProvider(config, fromStorage = false) {
6166
6272
  break;
6167
6273
  case "guest":
6168
6274
  // Anonymous auth: a device-local ed25519 keypair signs the challenge.
6169
- currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-g5-T58yA.js'); })).GuestAuthProvider();
6275
+ currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-CJUbifdu.js'); })).GuestAuthProvider();
6170
6276
  break;
6171
6277
  }
6172
6278
  if (!currentAuthProvider) {
@@ -6228,7 +6334,7 @@ async function signInAnonymously() {
6228
6334
  // Lazy-load the guest provider so its ed25519/web3 dependencies stay out of
6229
6335
  // the main bundle for data-only apps. Specifier is a static string literal
6230
6336
  // so bundle-splitting can see it.
6231
- const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-g5-T58yA.js'); })).GuestAuthProvider();
6337
+ const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-CJUbifdu.js'); })).GuestAuthProvider();
6232
6338
  setAuthLoading(true); // reflect "signing in…" while the guest keypair session is minted
6233
6339
  // adoptSessionProvider awaits only getConfig() (already resolved here) and then
6234
6340
  // runs every write - provider/method/config/marker/user - in one synchronous
@@ -6399,7 +6505,7 @@ function ensureSharedWalletLoginReady() {
6399
6505
  if (!sharedWalletReady) {
6400
6506
  sharedWalletReady = (async () => {
6401
6507
  await core.getConfig();
6402
- await Promise.resolve().then(function () { return require('./injected-wallet-provider-zXw__lyf.js'); });
6508
+ await Promise.resolve().then(function () { return require('./injected-wallet-provider-Ckljhcbu.js'); });
6403
6509
  })().catch((error) => {
6404
6510
  sharedWalletReady = null;
6405
6511
  throw error;
@@ -8922,6 +9028,7 @@ exports.bufferExports = bufferExports;
8922
9028
  exports.builds = builds;
8923
9029
  exports.completeLoginFromRedirect = completeLoginFromRedirect;
8924
9030
  exports.confirmAndCheckTransaction = confirmAndCheckTransaction;
9031
+ exports.ensureTurnkeySigningSession = ensureTurnkeySigningSession;
8925
9032
  exports.getAuthLoading = getAuthLoading;
8926
9033
  exports.getAuthProvider = getAuthProvider;
8927
9034
  exports.getCurrentUser = getCurrentUser;
@@ -8963,4 +9070,4 @@ exports.useBuildRun = useBuildRun;
8963
9070
  exports.useQuery = useQuery;
8964
9071
  exports.waitForAuthReady = waitForAuthReady;
8965
9072
  exports.walletStandardFeatureName = walletStandardFeatureName;
8966
- //# sourceMappingURL=index.native-ByI3rRu4.js.map
9073
+ //# sourceMappingURL=index.native-CZSRvIAb.js.map