@bounded-sh/client 0.0.118-openapps.0 → 0.0.119

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/providers/email-auth-provider.d.ts +2 -1
  2. package/dist/auth/providers/offchain-auth-provider.d.ts +2 -1
  3. package/dist/auth/providers/transaction-utils.d.ts +5 -3
  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-C5bYKzpN.mjs → email-auth-provider-DHq5_wtn.mjs} +7 -2
  7. package/dist/email-auth-provider-DHq5_wtn.mjs.map +1 -0
  8. package/dist/{email-auth-provider-C-SGTRZe.mjs → email-auth-provider-DOI-4lPC.mjs} +7 -2
  9. package/dist/email-auth-provider-DOI-4lPC.mjs.map +1 -0
  10. package/dist/{email-auth-provider-CjbJ8wK1.js → email-auth-provider-DyzhiN9Y.js} +7 -2
  11. package/dist/email-auth-provider-DyzhiN9Y.js.map +1 -0
  12. package/dist/{email-auth-provider-3tuw_aDK.js → email-auth-provider-wOISnCic.js} +7 -2
  13. package/dist/email-auth-provider-wOISnCic.js.map +1 -0
  14. package/dist/{guest-auth-provider-ClCOa69H.js → guest-auth-provider-Br3iM3O3.js} +2 -2
  15. package/dist/{guest-auth-provider-ClCOa69H.js.map → guest-auth-provider-Br3iM3O3.js.map} +1 -1
  16. package/dist/{guest-auth-provider-BwEXKnNK.mjs → guest-auth-provider-DyP5UUg6.mjs} +2 -2
  17. package/dist/{guest-auth-provider-CsM_SuGH.mjs.map → guest-auth-provider-DyP5UUg6.mjs.map} +1 -1
  18. package/dist/{guest-auth-provider-CsM_SuGH.mjs → guest-auth-provider-ZOBNFoeC.mjs} +2 -2
  19. package/dist/{guest-auth-provider-BwEXKnNK.mjs.map → guest-auth-provider-ZOBNFoeC.mjs.map} +1 -1
  20. package/dist/{guest-auth-provider-_jdqZKUo.js → guest-auth-provider-xap-VQBP.js} +2 -2
  21. package/dist/{guest-auth-provider-_jdqZKUo.js.map → guest-auth-provider-xap-VQBP.js.map} +1 -1
  22. package/dist/{index-B2HWEA13.js → index-B4_eKphx.js} +125 -59
  23. package/dist/index-B4_eKphx.js.map +1 -0
  24. package/dist/{index-q9BHoxbM.mjs → index-BaXUWG8Q.mjs} +126 -61
  25. package/dist/index-BaXUWG8Q.mjs.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-CMNMw3Pe.js → index.native-B-pjNetI.js} +142 -60
  31. package/dist/index.native-B-pjNetI.js.map +1 -0
  32. package/dist/{index.native-DfDVa7MG.mjs → index.native-B4yI0BqT.mjs} +143 -62
  33. package/dist/index.native-B4yI0BqT.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-AXc7Lmzk.mjs → injected-evm-wallet-provider-B4Kr6lnK.mjs} +2 -2
  37. package/dist/{injected-evm-wallet-provider-AXc7Lmzk.mjs.map → injected-evm-wallet-provider-B4Kr6lnK.mjs.map} +1 -1
  38. package/dist/{injected-evm-wallet-provider-qB_GQ9ih.js → injected-evm-wallet-provider-CKAv4Qxh.js} +2 -2
  39. package/dist/{injected-evm-wallet-provider-qB_GQ9ih.js.map → injected-evm-wallet-provider-CKAv4Qxh.js.map} +1 -1
  40. package/dist/{injected-evm-wallet-provider-CUNTCT-a.js → injected-evm-wallet-provider-DQMYqPus.js} +2 -2
  41. package/dist/{injected-evm-wallet-provider-CUNTCT-a.js.map → injected-evm-wallet-provider-DQMYqPus.js.map} +1 -1
  42. package/dist/{injected-evm-wallet-provider-E7eCpvLr.mjs → injected-evm-wallet-provider-Vw-Puwxh.mjs} +2 -2
  43. package/dist/{injected-evm-wallet-provider-E7eCpvLr.mjs.map → injected-evm-wallet-provider-Vw-Puwxh.mjs.map} +1 -1
  44. package/dist/{injected-wallet-provider-BEaDBzcd.js → injected-wallet-provider-B8QTPxf6.js} +14 -5
  45. package/dist/{injected-wallet-provider-BEaDBzcd.js.map → injected-wallet-provider-B8QTPxf6.js.map} +1 -1
  46. package/dist/{injected-wallet-provider-BqYJQDGu.js → injected-wallet-provider-BsTfBAD4.js} +14 -5
  47. package/dist/{injected-wallet-provider-BqYJQDGu.js.map → injected-wallet-provider-BsTfBAD4.js.map} +1 -1
  48. package/dist/{injected-wallet-provider-BoRoxrEl.mjs → injected-wallet-provider-CQxGVYja.mjs} +14 -5
  49. package/dist/{injected-wallet-provider-BoRoxrEl.mjs.map → injected-wallet-provider-CQxGVYja.mjs.map} +1 -1
  50. package/dist/{injected-wallet-provider-gmGZ254w.mjs → injected-wallet-provider-jj9dqm2Z.mjs} +14 -5
  51. package/dist/{injected-wallet-provider-gmGZ254w.mjs.map → injected-wallet-provider-jj9dqm2Z.mjs.map} +1 -1
  52. package/package.json +2 -2
  53. package/dist/email-auth-provider-3tuw_aDK.js.map +0 -1
  54. package/dist/email-auth-provider-C-SGTRZe.mjs.map +0 -1
  55. package/dist/email-auth-provider-C5bYKzpN.mjs.map +0 -1
  56. package/dist/email-auth-provider-CjbJ8wK1.js.map +0 -1
  57. package/dist/index-B2HWEA13.js.map +0 -1
  58. package/dist/index-q9BHoxbM.mjs.map +0 -1
  59. package/dist/index.native-CMNMw3Pe.js.map +0 -1
  60. package/dist/index.native-DfDVa7MG.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { getConfig, getActiveSessionManager, WebSessionManager, ReactNativeSessionManager, revokeSession, reconnectWithNewAuth, deriveUserIdentityFromIdToken, init as init$2, onSessionCleared, onSessionChange, subscribe, getFreshAuthToken, getSessionGeneration, getIdToken as getIdToken$1, getConfiguredAppId, setWithVenueGrant, writeNotAppliedPhase, waitForSetResult, reconcileSetResult, resolveVenueRpcUrl, genAuthNonce, genSolanaMessage, createSessionWithSignature } from '@bounded-sh/core';
1
+ import { getConfig, getActiveSessionManager, confirmSignature, WebSessionManager, ReactNativeSessionManager, revokeSession, reconnectWithNewAuth, deriveUserIdentityFromIdToken, init as init$2, onSessionCleared, onSessionChange, subscribe, getFreshAuthToken, getSessionGeneration, getIdToken as getIdToken$1, getConfiguredAppId, setWithVenueGrant, writeNotAppliedPhase, waitForSetResult, reconcileSetResult, resolveVenueRpcUrl, genAuthNonce, genSolanaMessage, createSessionWithSignature } from '@bounded-sh/core';
2
2
  import * as React from 'react';
3
3
 
4
4
  function walletContextFromClaims(claims, baseUrl, expectedAppId, tenantOrigin) {
@@ -274,6 +274,10 @@ class OffchainAuthProvider {
274
274
  async signTransaction(tx) {
275
275
  return this.wrappedProvider.signTransaction(tx);
276
276
  }
277
+ async prepareToSign() {
278
+ var _a, _b, _c;
279
+ return (_c = (await ((_b = (_a = this.wrappedProvider).prepareToSign) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : 'ready';
280
+ }
277
281
  /**
278
282
  * Sign and submit transaction - not supported in poofnet environment.
279
283
  * See the real providers (PhantomWalletProvider, SolanaKeypairProvider)
@@ -4369,7 +4373,7 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4369
4373
  const requestId = String(ex.request.requestId);
4370
4374
  // Serialize: the approve card is modal, and one warm frame handles one request at a time.
4371
4375
  const run = m.chain.then(() => new Promise((resolve, reject) => {
4372
- var _a;
4376
+ var _a, _b;
4373
4377
  let settled = false;
4374
4378
  let usedFallback = false;
4375
4379
  (_a = ex.assertCurrent) === null || _a === void 0 ? void 0 : _a.call(ex);
@@ -4412,16 +4416,20 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4412
4416
  /* frame gone */
4413
4417
  }
4414
4418
  };
4419
+ const dismiss = () => {
4420
+ if (!ex.silent)
4421
+ hideModal(m);
4422
+ };
4415
4423
  const goFallback = () => {
4416
4424
  if (usedFallback || settled)
4417
4425
  return;
4418
4426
  usedFallback = true;
4419
- hideModal(m);
4427
+ dismiss();
4420
4428
  finish(() => popupFallback().then(resolve, reject));
4421
4429
  };
4422
4430
  m.onBackdrop = () => {
4423
4431
  cancelInFrame();
4424
- hideModal(m);
4432
+ dismiss();
4425
4433
  finish(() => reject(new Error("cancelled")));
4426
4434
  };
4427
4435
  m.onIframeMessage = (d) => {
@@ -4436,17 +4444,18 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4436
4444
  if (d.type === "bounded:turnkey:result" && d.requestId === requestId) {
4437
4445
  const outcome = ex.onResult(d);
4438
4446
  if ("error" in outcome) {
4439
- hideModal(m);
4447
+ dismiss();
4440
4448
  finish(() => reject(new Error(outcome.error)));
4441
4449
  return;
4442
4450
  }
4443
4451
  if (outcome.done) {
4444
- hideModal(m);
4452
+ dismiss();
4445
4453
  finish(() => resolve(outcome.value));
4446
4454
  }
4447
4455
  }
4448
4456
  };
4449
- showModal(m);
4457
+ if (!ex.silent)
4458
+ showModal(m);
4450
4459
  if (m.iframeReady)
4451
4460
  send();
4452
4461
  // If the frame never loads, degrade to the popup (best-effort - a post-load
@@ -4459,10 +4468,10 @@ async function runWidget(url, signerOrigin, ex, popupFallback) {
4459
4468
  ceilingTimer = window.setTimeout(() => {
4460
4469
  if (!settled) {
4461
4470
  cancelInFrame();
4462
- hideModal(m);
4471
+ dismiss();
4463
4472
  finish(() => reject(new Error("Wallet approval timed out.")));
4464
4473
  }
4465
- }, 5 * 60 * 1000);
4474
+ }, (_b = ex.ceilingMs) !== null && _b !== void 0 ? _b : 5 * 60 * 1000);
4466
4475
  }));
4467
4476
  m.chain = run.then(() => undefined, () => undefined);
4468
4477
  return run;
@@ -5044,6 +5053,59 @@ async function clearTurnkeySigningSession(idToken) {
5044
5053
  function hasTurnkeyWallet() {
5045
5054
  return activeTurnkeyAddress() !== null;
5046
5055
  }
5056
+ /** The signer frame could not take the exchange: it never loaded, or a page from before the request existed stays silent. */
5057
+ class SignerFrameUnavailable extends Error {
5058
+ constructor() { super('The Bounded signer frame did not answer.'); }
5059
+ }
5060
+ /** How long a silent session probe may wait for the frame before the write goes on without it. */
5061
+ const SESSION_PROBE_MS = 8000;
5062
+ /**
5063
+ * Make the wallet's 24-hour signing session live BEFORE a transaction exists. Without one the
5064
+ * approve card must first collect an emailed code, which takes longer than a transaction's
5065
+ * blockhash lifetime (about 33 seconds on mainnet in late 2026), so a transaction built before
5066
+ * the code is dead by the time it is signed. A live session is found with nothing shown: the
5067
+ * warm frame answers a silent probe, and it holds the session even where the browser blocks its
5068
+ * storage. Only a lapsed session opens the card, which runs the code ceremony and closes without
5069
+ * signing anything. Resolves `'established'` when that ceremony ran, else `'ready'`.
5070
+ *
5071
+ * Both exchanges run in the warm frame only, since it is the frame that signs next and a popup
5072
+ * keeps its session to itself. Where the frame cannot answer (an embedder that blocks it, or a
5073
+ * signer page from before this request existed), the write goes on the way it always did: the
5074
+ * approve card collects the code itself, and an expired build is built again.
5075
+ */
5076
+ async function ensureTurnkeySigningSession() {
5077
+ if (!hasDOM$3())
5078
+ throw new Error('Turnkey embedded-wallet signing is only available in the browser (trusted wallet UI).');
5079
+ const context = await turnkeySignerPage();
5080
+ context.assertCurrent();
5081
+ if (hasWarmSignerFrame(context.key) && walletSessionState(context.key).status === 'ready')
5082
+ return 'ready';
5083
+ const { url, origin } = context;
5084
+ const authorization = await fetchActionAuthorization('createWallet', context);
5085
+ const frameOnly = () => Promise.reject(new SignerFrameUnavailable());
5086
+ const exchange = (probeOnly) => ({
5087
+ context: context.key, assertCurrent: context.assertCurrent,
5088
+ request: Object.assign({ type: 'bounded:turnkey:session', requestId: `tksession_${Date.now()}_${++requestSeq}`, authorization }, (probeOnly ? { probeOnly: true } : {})),
5089
+ onResult: (d) => d.ok ? { done: true, value: d } : { error: String(d.error || 'The signing session could not be established') },
5090
+ });
5091
+ const probed = await runWidget(url, origin, Object.assign(Object.assign({}, exchange(true)), { silent: true, ceilingMs: SESSION_PROBE_MS }), frameOnly)
5092
+ .catch(() => null);
5093
+ if (!probed)
5094
+ return 'ready';
5095
+ let result = probed;
5096
+ if (result.ready !== true) {
5097
+ try {
5098
+ result = await runWidget(url, origin, exchange(false), frameOnly);
5099
+ }
5100
+ catch (error) {
5101
+ if (error instanceof SignerFrameUnavailable)
5102
+ return 'ready';
5103
+ throw error;
5104
+ }
5105
+ }
5106
+ setWalletSessionState(context.key, { status: 'ready', expiresAt: Number(result.signingSessionExpiresAt) });
5107
+ return result.established === true ? 'established' : 'ready';
5108
+ }
5047
5109
  /**
5048
5110
  * Get-or-create the user's non-custodial Turnkey wallet, resolving with its stable
5049
5111
  * Solana address. Creation never prompts: on first use the signer silently provisions
@@ -5232,10 +5294,9 @@ async function signAndSubmitTransactionWithTurnkey(transaction, feePayer) {
5232
5294
  // has signed silently invalidates their signature - signTransactionWithTurnkey only ADDS the
5233
5295
  // Turnkey signature, it never re-signs the others. So only refresh the blockhash while the
5234
5296
  // transaction is still unsigned; once a real signature is present, preserve the caller's message
5235
- // verbatim and confirm against the blockhash it already carries.
5236
- const hasSignature = transactionHasSignature$1(transaction);
5237
- let confirmBlockhash = blockhash;
5238
- if (!hasSignature) {
5297
+ // verbatim. The confirmation is fenced on the lifetime read above either way: for a pre-signed
5298
+ // transaction that is a superset of the one its signers fenced on, never a shorter wait.
5299
+ if (!transactionHasSignature$1(transaction)) {
5239
5300
  if (isLegacy) {
5240
5301
  const legacy = transaction;
5241
5302
  legacy.recentBlockhash = blockhash;
@@ -5251,19 +5312,17 @@ async function signAndSubmitTransactionWithTurnkey(transaction, feePayer) {
5251
5312
  transaction.message.recentBlockhash = blockhash;
5252
5313
  }
5253
5314
  }
5254
- else {
5255
- confirmBlockhash = (isLegacy
5256
- ? transaction.recentBlockhash
5257
- : transaction.message.recentBlockhash) || blockhash;
5258
- }
5259
5315
  const signed = await signTransactionWithTurnkey(transaction);
5260
5316
  const signature = await connection.sendRawTransaction(signed.serialize(), {
5261
5317
  skipPreflight: false,
5262
5318
  maxRetries: 3,
5263
5319
  });
5264
- const confirmation = await connection.confirmTransaction({ signature, blockhash: confirmBlockhash, lastValidBlockHeight }, 'confirmed');
5265
- if (confirmation.value.err) {
5266
- throw new Error(`Turnkey transaction failed: ${JSON.stringify(confirmation.value.err)}`);
5320
+ const confirmation = await confirmSignature(connection, { signature, lastValidBlockHeight });
5321
+ if (!confirmation.landed) {
5322
+ throw new Error(`Turnkey transaction ${signature} was not confirmed: ${confirmation.reason}. Check its status before sending it again.`);
5323
+ }
5324
+ if (confirmation.status.err) {
5325
+ throw new Error(`Turnkey transaction failed: ${JSON.stringify(confirmation.status.err)}`);
5267
5326
  }
5268
5327
  return signature;
5269
5328
  }
@@ -5279,6 +5338,7 @@ async function getTurnkeyWalletRecoveryUrl() {
5279
5338
  var turnkeySignerBridge = /*#__PURE__*/Object.freeze({
5280
5339
  __proto__: null,
5281
5340
  clearTurnkeySigningSession: clearTurnkeySigningSession,
5341
+ ensureTurnkeySigningSession: ensureTurnkeySigningSession,
5282
5342
  getOrCreateTurnkeyWallet: getOrCreateTurnkeyWallet,
5283
5343
  getTurnkeyWalletRecoveryUrl: getTurnkeyWalletRecoveryUrl,
5284
5344
  getTurnkeyWalletSessionState: getTurnkeyWalletSessionState,
@@ -5362,6 +5422,11 @@ const oidcProviderSingleton = {
5362
5422
  throw new Error(OIDC_NO_WALLET);
5363
5423
  return signTransactionV1WithTurnkey(transaction);
5364
5424
  },
5425
+ async prepareToSign() {
5426
+ if (!hasTurnkeyWallet())
5427
+ throw new Error(OIDC_NO_WALLET);
5428
+ return ensureTurnkeySigningSession();
5429
+ },
5365
5430
  supportedTransactionVersions() {
5366
5431
  return hasTurnkeyWallet() ? ['legacy', 0, 1] : ['legacy', 0];
5367
5432
  },
@@ -6475,7 +6540,7 @@ async function getAuthProvider(config, fromStorage = false) {
6475
6540
  // manager as legacy email sessions. Human login should be started
6476
6541
  // with loginWithRedirect(); this provider is kept as the restore and
6477
6542
  // logout surface for those sessions.
6478
- currentAuthProvider = new (await import('./email-auth-provider-C-SGTRZe.mjs')).EmailAuthProvider();
6543
+ currentAuthProvider = new (await import('./email-auth-provider-DHq5_wtn.mjs')).EmailAuthProvider();
6479
6544
  break;
6480
6545
  case "phantom": {
6481
6546
  // First-class Solana WALLET LOGIN (the poof/TaroBase-style "connect
@@ -6517,7 +6582,7 @@ async function getAuthProvider(config, fromStorage = false) {
6517
6582
  // (bounded-login-widget.ts), so registration never counts as
6518
6583
  // evidence the user has a wallet.
6519
6584
  await ensureSolanaMobileWalletRegistered(config, configuredNetwork);
6520
- const { InjectedWalletProvider } = await import('./injected-wallet-provider-gmGZ254w.mjs');
6585
+ const { InjectedWalletProvider } = await import('./injected-wallet-provider-jj9dqm2Z.mjs');
6521
6586
  currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
6522
6587
  break;
6523
6588
  }
@@ -6530,7 +6595,7 @@ async function getAuthProvider(config, fromStorage = false) {
6530
6595
  // Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
6531
6596
  // to point at a specific wallet or set chainId/domain.
6532
6597
  const evmWalletConfig = ((_a = config.evmWalletConfig) !== null && _a !== void 0 ? _a : {});
6533
- const { InjectedEvmWalletProvider } = await import('./injected-evm-wallet-provider-AXc7Lmzk.mjs');
6598
+ const { InjectedEvmWalletProvider } = await import('./injected-evm-wallet-provider-B4Kr6lnK.mjs');
6534
6599
  currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
6535
6600
  break;
6536
6601
  }
@@ -6555,7 +6620,7 @@ async function getAuthProvider(config, fromStorage = false) {
6555
6620
  break;
6556
6621
  case "guest":
6557
6622
  // Anonymous auth: a device-local ed25519 keypair signs the challenge.
6558
- currentAuthProvider = new (await import('./guest-auth-provider-BwEXKnNK.mjs')).GuestAuthProvider();
6623
+ currentAuthProvider = new (await import('./guest-auth-provider-DyP5UUg6.mjs')).GuestAuthProvider();
6559
6624
  break;
6560
6625
  }
6561
6626
  if (!currentAuthProvider) {
@@ -6617,7 +6682,7 @@ async function signInAnonymously() {
6617
6682
  // Lazy-load the guest provider so its ed25519/web3 dependencies stay out of
6618
6683
  // the main bundle for data-only apps. Specifier is a static string literal
6619
6684
  // so bundle-splitting can see it.
6620
- const provider = new (await import('./guest-auth-provider-BwEXKnNK.mjs')).GuestAuthProvider();
6685
+ const provider = new (await import('./guest-auth-provider-DyP5UUg6.mjs')).GuestAuthProvider();
6621
6686
  setAuthLoading(true); // reflect "signing in…" while the guest keypair session is minted
6622
6687
  // adoptSessionProvider awaits only getConfig() (already resolved here) and then
6623
6688
  // runs every write - provider/method/config/marker/user - in one synchronous
@@ -6788,7 +6853,7 @@ function ensureSharedWalletLoginReady() {
6788
6853
  if (!sharedWalletReady) {
6789
6854
  sharedWalletReady = (async () => {
6790
6855
  await getConfig();
6791
- await import('./injected-wallet-provider-gmGZ254w.mjs');
6856
+ await import('./injected-wallet-provider-jj9dqm2Z.mjs');
6792
6857
  })().catch((error) => {
6793
6858
  sharedWalletReady = null;
6794
6859
  throw error;
@@ -6893,7 +6958,7 @@ async function loginWithWallet(options) {
6893
6958
  await ensureSharedWalletLoginReady();
6894
6959
  else
6895
6960
  await ensureWalletLoginReady();
6896
- const { InjectedWalletProvider } = await import('./injected-wallet-provider-gmGZ254w.mjs');
6961
+ const { InjectedWalletProvider } = await import('./injected-wallet-provider-jj9dqm2Z.mjs');
6897
6962
  // Keep the RAW wallet provider: the offchain wrapper forwards only a fixed
6898
6963
  // set of methods, so cleanup below must speak to the provider that actually
6899
6964
  // holds the config rather than to whatever is wrapping it.
@@ -11556,35 +11621,29 @@ async function getParsedTransactionCompat(connection, signature) {
11556
11621
  }
11557
11622
  }
11558
11623
  /**
11559
- * Polls getSignatureStatuses until the transaction is confirmed, then checks for errors.
11560
- * Throws if the transaction failed on-chain. Returns parsed transaction info on success.
11624
+ * Waits for a broadcast signature by HTTPS status polling, fenced on the blockhash
11625
+ * lifetime it was signed against (core's `confirmSignature`), then checks for an
11626
+ * on-chain error. Throws if the transaction failed on-chain or was not seen before
11627
+ * the fence closed. Returns parsed transaction info on success.
11561
11628
  */
11562
- async function confirmAndCheckTransaction(connection, signature) {
11629
+ async function confirmAndCheckTransaction(connection, signature, lastValidBlockHeight) {
11563
11630
  var _a;
11564
- const maxAttempts = 15;
11565
- for (let i = 0; i < maxAttempts; i++) {
11566
- const { value } = await connection.getSignatureStatuses([signature]);
11567
- const status = value[0];
11568
- if (status) {
11569
- if (status.err) {
11570
- let logMessages;
11571
- try {
11572
- const txInfo = await getParsedTransactionCompat(connection, signature);
11573
- logMessages = (_a = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _a === void 0 ? void 0 : _a.logMessages;
11574
- }
11575
- catch (_b) {
11576
- // Log retrieval is diagnostic only; the on-chain error is the verdict.
11577
- }
11578
- const errorMessage = extractTransactionError(status.err, logMessages);
11579
- throw new Error(`Transaction failed: ${errorMessage}`);
11580
- }
11581
- if (status.confirmationStatus === 'confirmed' || status.confirmationStatus === 'finalized') {
11582
- return await getParsedTransactionCompat(connection, signature);
11583
- }
11631
+ const confirmation = await confirmSignature(connection, { signature, lastValidBlockHeight });
11632
+ if (!confirmation.landed) {
11633
+ throw new Error(`Transaction ${signature} was not confirmed: ${confirmation.reason}. Check its status before sending it again.`);
11634
+ }
11635
+ if (confirmation.status.err) {
11636
+ let logMessages;
11637
+ try {
11638
+ const txInfo = await getParsedTransactionCompat(connection, signature);
11639
+ logMessages = (_a = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _a === void 0 ? void 0 : _a.logMessages;
11584
11640
  }
11585
- await new Promise(resolve => setTimeout(resolve, 1000));
11641
+ catch (_b) {
11642
+ // Log retrieval is diagnostic only; the on-chain error is the verdict.
11643
+ }
11644
+ throw new Error(`Transaction failed: ${extractTransactionError(confirmation.status.err, logMessages)}`);
11586
11645
  }
11587
- throw new Error('Transaction confirmation timeout');
11646
+ return getParsedTransactionCompat(connection, signature);
11588
11647
  }
11589
11648
 
11590
11649
  /**
@@ -11754,24 +11813,30 @@ class PrivyExpoProvider {
11754
11813
  // included), so refreshing the blockhash after any signer (sponsor / co-signer)
11755
11814
  // has signed silently invalidates their signature. Only refresh while the
11756
11815
  // transaction is still unsigned; once a real signature is present, submit the
11757
- // caller's transaction verbatim.
11816
+ // caller's transaction verbatim. Either way the confirmation is fenced on a
11817
+ // lifetime read now: for a pre-signed transaction that is a superset of the
11818
+ // one its signers fenced on, never a shorter wait.
11819
+ let lastValidBlockHeight;
11758
11820
  if (!transactionHasSignature(transaction)) {
11821
+ const { blockhash, lastValidBlockHeight: freshLastValid } = await connection.getLatestBlockhash('confirmed');
11822
+ lastValidBlockHeight = freshLastValid;
11759
11823
  const isLegacyTx = 'recentBlockhash' in transaction &&
11760
11824
  !('message' in transaction && 'staticAccountKeys' in transaction.message);
11761
11825
  if (isLegacyTx) {
11762
11826
  const legacyTx = transaction;
11763
- const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
11764
11827
  legacyTx.recentBlockhash = blockhash;
11765
11828
  legacyTx.lastValidBlockHeight = lastValidBlockHeight;
11766
11829
  legacyTx.feePayer = feePayer || new PublicKey(wallet.address);
11767
11830
  }
11768
11831
  else {
11769
11832
  const versionedTx = transaction;
11770
- const { blockhash } = await connection.getLatestBlockhash('confirmed');
11771
11833
  versionedTx.message.recentBlockhash = blockhash;
11772
11834
  }
11773
11835
  }
11774
- const { signature } = await this.signAndSubmitInternal(transaction, wallet, connection);
11836
+ else {
11837
+ ({ lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed'));
11838
+ }
11839
+ const { signature } = await this.signAndSubmitInternal(transaction, wallet, connection, lastValidBlockHeight);
11775
11840
  return signature;
11776
11841
  }
11777
11842
  async restoreSession(beforeCommit) {
@@ -11842,11 +11907,11 @@ class PrivyExpoProvider {
11842
11907
  `Sign in again before ${action}.`);
11843
11908
  }
11844
11909
  }
11845
- async signAndSubmitInternal(transaction, wallet, connection) {
11910
+ async signAndSubmitInternal(transaction, wallet, connection, lastValidBlockHeight) {
11846
11911
  // Use Privy's combined sign+send
11847
11912
  const result = await wallet.signAndSendTransaction(transaction, connection);
11848
11913
  const signature = result.signature;
11849
- const txInfo = await confirmAndCheckTransaction(connection, signature);
11914
+ const txInfo = await confirmAndCheckTransaction(connection, signature, lastValidBlockHeight);
11850
11915
  return { signature, txInfo };
11851
11916
  }
11852
11917
  // The constructor rpcUrl wins, then init()'s rpcUrl, then the platform RPC
@@ -12271,5 +12336,5 @@ function init(config = {}) {
12271
12336
  return init$1(resolved);
12272
12337
  }
12273
12338
 
12274
- export { onramp as $, logout as A, getAuthProvider as B, signInAnonymously as C, loginWithPrivy as D, loginWithWallet as E, ensureWalletLoginReady as F, ensureSharedWalletLoginReady as G, preloadWalletLogin as H, loginWithRedirect as I, completeLoginFromRedirect as J, getLoginReturnError as K, loginWithPopup as L, openBoundedWidget as M, ensureSignedIn as N, useAuth as O, useQuery as P, useBuildRun as Q, apps as R, SELECTED_WALLET_UNAVAILABLE_ERR as S, signSolanaMessageViaTurnkey as T, getOrCreateTurnkeyWallet as U, openTurnkeyKeyExport as V, WalletConfigError as W, getTurnkeyWalletSessionState as X, getTurnkeyWalletRecoveryUrl as Y, startTurnkeyEmailLogin as Z, getIdToken as _, signMessageWithTurnkey as a, onrampQuote as a0, onrampStatus as a1, connect as a2, completeConnection as a3, getConnections as a4, disconnect as a5, ConnectionError as a6, fundVenueEscrow as a7, disputeVenueEscrow as a8, getVenueEscrow as a9, VenueEscrowError as aa, setPlatform as ab, OffchainAuthProvider as ac, PrivyExpoProvider as ad, requestEip6963Providers as ae, connectBroadcast as af, connectServiceSession as ag, builds as ah, BuildsApiError as ai, mediaAgentTools as aj, NON_TERMINAL_STATES as ak, TERMINAL_STATES as al, RUN_STATES as am, PARK_REASONS as an, FAILURE_REASONS as ao, BUILD_REVIEW_CAPABILITY_SCHEMA as ap, BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA as aq, BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA as ar, signTransactionWithTurnkey as b, signTransactionV1WithTurnkey as c, signAndSubmitTransactionWithTurnkey as d, bs58 as e, defaultInjectedProvider as f, getPlatform as g, hasTurnkeyWallet as h, firstStandardWalletProvider as i, setAuthLoading as j, supportsWalletSignIn as k, bufferExports as l, setStoredAuthMethod as m, normalizeSolanaRpcUrl as n, confirmAndCheckTransaction as o, defaultInjectedEvmProvider as p, init as q, resolveSolanaRpcUrl as r, setCurrentUser as s, transactionHasSignature as t, getCurrentUser as u, onAuthStateChanged as v, onAuthLoadingChanged as w, getAuthLoading as x, waitForAuthReady as y, login as z };
12275
- //# sourceMappingURL=index-q9BHoxbM.mjs.map
12339
+ export { getIdToken as $, login as A, logout as B, getAuthProvider as C, signInAnonymously as D, loginWithPrivy as E, loginWithWallet as F, ensureWalletLoginReady as G, ensureSharedWalletLoginReady as H, preloadWalletLogin as I, loginWithRedirect as J, completeLoginFromRedirect as K, getLoginReturnError as L, loginWithPopup as M, openBoundedWidget as N, ensureSignedIn as O, useAuth as P, useQuery as Q, useBuildRun as R, SELECTED_WALLET_UNAVAILABLE_ERR as S, apps as T, signSolanaMessageViaTurnkey as U, getOrCreateTurnkeyWallet as V, WalletConfigError as W, openTurnkeyKeyExport as X, getTurnkeyWalletSessionState as Y, getTurnkeyWalletRecoveryUrl as Z, startTurnkeyEmailLogin as _, signMessageWithTurnkey as a, onramp as a0, onrampQuote as a1, onrampStatus as a2, connect as a3, completeConnection as a4, getConnections as a5, disconnect as a6, ConnectionError as a7, fundVenueEscrow as a8, disputeVenueEscrow as a9, getVenueEscrow as aa, VenueEscrowError as ab, setPlatform as ac, OffchainAuthProvider as ad, PrivyExpoProvider as ae, requestEip6963Providers as af, connectBroadcast as ag, connectServiceSession as ah, builds as ai, BuildsApiError as aj, mediaAgentTools as ak, NON_TERMINAL_STATES as al, TERMINAL_STATES as am, RUN_STATES as an, PARK_REASONS as ao, FAILURE_REASONS as ap, BUILD_REVIEW_CAPABILITY_SCHEMA as aq, BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA as ar, BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA as as, signTransactionWithTurnkey as b, signTransactionV1WithTurnkey as c, signAndSubmitTransactionWithTurnkey as d, ensureTurnkeySigningSession as e, bs58 as f, getPlatform as g, hasTurnkeyWallet as h, defaultInjectedProvider as i, firstStandardWalletProvider as j, setAuthLoading as k, supportsWalletSignIn as l, bufferExports as m, normalizeSolanaRpcUrl as n, setStoredAuthMethod as o, confirmAndCheckTransaction as p, defaultInjectedEvmProvider as q, resolveSolanaRpcUrl as r, setCurrentUser as s, transactionHasSignature as t, init as u, getCurrentUser as v, onAuthStateChanged as w, onAuthLoadingChanged as x, getAuthLoading as y, waitForAuthReady as z };
12340
+ //# sourceMappingURL=index-BaXUWG8Q.mjs.map