@bounded-sh/client 0.0.48 → 0.0.50

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 (67) hide show
  1. package/README.md +21 -0
  2. package/dist/auth/providers/guest-auth-provider.d.ts +7 -0
  3. package/dist/auth/providers/guest-keystore.d.ts +2 -0
  4. package/dist/builds/apps.d.ts +32 -0
  5. package/dist/builds/client.d.ts +74 -0
  6. package/dist/builds/index.d.ts +20 -0
  7. package/dist/builds/types.d.ts +121 -0
  8. package/dist/builds/watch.d.ts +20 -0
  9. package/dist/{email-auth-provider-GRj8IOg2.mjs → email-auth-provider-B7czfBEU.mjs} +2 -2
  10. package/dist/{email-auth-provider-GRj8IOg2.mjs.map → email-auth-provider-B7czfBEU.mjs.map} +1 -1
  11. package/dist/{email-auth-provider-CmunfauO.js → email-auth-provider-CmYs6Dcm.js} +2 -2
  12. package/dist/{email-auth-provider-CmunfauO.js.map → email-auth-provider-CmYs6Dcm.js.map} +1 -1
  13. package/dist/{email-auth-provider-CTyjwhLb.mjs → email-auth-provider-DIZAETBC.mjs} +2 -2
  14. package/dist/{email-auth-provider-CTyjwhLb.mjs.map → email-auth-provider-DIZAETBC.mjs.map} +1 -1
  15. package/dist/{email-auth-provider-DyxZTpx6.js → email-auth-provider-Dj66AuH0.js} +2 -2
  16. package/dist/{email-auth-provider-DyxZTpx6.js.map → email-auth-provider-Dj66AuH0.js.map} +1 -1
  17. package/dist/global.d.ts +3 -1
  18. package/dist/{guest-auth-provider-D54uHbov.js → guest-auth-provider-B5sgg-q5.js} +98 -14
  19. package/dist/guest-auth-provider-B5sgg-q5.js.map +1 -0
  20. package/dist/{guest-auth-provider-Dk_km5tF.mjs → guest-auth-provider-BR0_YL8z.mjs} +98 -14
  21. package/dist/guest-auth-provider-BR0_YL8z.mjs.map +1 -0
  22. package/dist/{guest-auth-provider-C4BuTNIa.mjs → guest-auth-provider-CCpNvX3j.mjs} +98 -14
  23. package/dist/guest-auth-provider-CCpNvX3j.mjs.map +1 -0
  24. package/dist/{guest-auth-provider-B68XT2lU.js → guest-auth-provider-CxsLCznO.js} +98 -14
  25. package/dist/guest-auth-provider-CxsLCznO.js.map +1 -0
  26. package/dist/hooks/useBuildRun.d.ts +13 -0
  27. package/dist/{index.native-CytJPNQV.mjs → index-BYy1tSkr.mjs} +850 -26
  28. package/dist/index-BYy1tSkr.mjs.map +1 -0
  29. package/dist/{index.native-BZCc0gO-.js → index-m42Be5Oj.js} +861 -24
  30. package/dist/index-m42Be5Oj.js.map +1 -0
  31. package/dist/index.d.ts +5 -0
  32. package/dist/index.js +10 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.mjs +1 -1
  35. package/dist/{index-C0pR5b7j.mjs → index.native-B-ldAbu2.mjs} +668 -146
  36. package/dist/index.native-B-ldAbu2.mjs.map +1 -0
  37. package/dist/{index-JBeYYsGm.js → index.native-BfoLJCZg.js} +675 -148
  38. package/dist/index.native-BfoLJCZg.js.map +1 -0
  39. package/dist/index.native.d.ts +5 -0
  40. package/dist/index.native.js +10 -1
  41. package/dist/index.native.js.map +1 -1
  42. package/dist/index.native.mjs +1 -1
  43. package/dist/{injected-evm-wallet-provider-_eeYB1ww.js → injected-evm-wallet-provider-BLQzWiBP.js} +2 -2
  44. package/dist/{injected-evm-wallet-provider-_eeYB1ww.js.map → injected-evm-wallet-provider-BLQzWiBP.js.map} +1 -1
  45. package/dist/{injected-evm-wallet-provider-T-EF9C3W.js → injected-evm-wallet-provider-BXj1YFaZ.js} +2 -2
  46. package/dist/{injected-evm-wallet-provider-T-EF9C3W.js.map → injected-evm-wallet-provider-BXj1YFaZ.js.map} +1 -1
  47. package/dist/{injected-evm-wallet-provider-CxAiNN7R.mjs → injected-evm-wallet-provider-sBCSkksr.mjs} +2 -2
  48. package/dist/{injected-evm-wallet-provider-CxAiNN7R.mjs.map → injected-evm-wallet-provider-sBCSkksr.mjs.map} +1 -1
  49. package/dist/{injected-evm-wallet-provider-BOMLGGHM.mjs → injected-evm-wallet-provider-ubsHX217.mjs} +2 -2
  50. package/dist/{injected-evm-wallet-provider-BOMLGGHM.mjs.map → injected-evm-wallet-provider-ubsHX217.mjs.map} +1 -1
  51. package/dist/{injected-wallet-provider-B1uq3r4r.mjs → injected-wallet-provider-BfzoheDy.mjs} +2 -2
  52. package/dist/{injected-wallet-provider-B1uq3r4r.mjs.map → injected-wallet-provider-BfzoheDy.mjs.map} +1 -1
  53. package/dist/{injected-wallet-provider-B2T7JEvn.js → injected-wallet-provider-Cml9TkyV.js} +2 -2
  54. package/dist/{injected-wallet-provider-B2T7JEvn.js.map → injected-wallet-provider-Cml9TkyV.js.map} +1 -1
  55. package/dist/{injected-wallet-provider-DCwygA3j.mjs → injected-wallet-provider-DG87X6AQ.mjs} +2 -2
  56. package/dist/{injected-wallet-provider-DCwygA3j.mjs.map → injected-wallet-provider-DG87X6AQ.mjs.map} +1 -1
  57. package/dist/{injected-wallet-provider-BBZym7YQ.js → injected-wallet-provider-PYcvLO2Z.js} +2 -2
  58. package/dist/{injected-wallet-provider-BBZym7YQ.js.map → injected-wallet-provider-PYcvLO2Z.js.map} +1 -1
  59. package/package.json +2 -2
  60. package/dist/guest-auth-provider-B68XT2lU.js.map +0 -1
  61. package/dist/guest-auth-provider-C4BuTNIa.mjs.map +0 -1
  62. package/dist/guest-auth-provider-D54uHbov.js.map +0 -1
  63. package/dist/guest-auth-provider-Dk_km5tF.mjs.map +0 -1
  64. package/dist/index-C0pR5b7j.mjs.map +0 -1
  65. package/dist/index-JBeYYsGm.js.map +0 -1
  66. package/dist/index.native-BZCc0gO-.js.map +0 -1
  67. package/dist/index.native-CytJPNQV.mjs.map +0 -1
@@ -4247,6 +4247,41 @@ function setStoredAuthMethod(method) {
4247
4247
  // storage might not be available
4248
4248
  }
4249
4249
  }
4250
+ function getStoredIdToken() {
4251
+ try {
4252
+ return core.getActiveSessionManager().getIdToken();
4253
+ }
4254
+ catch (_a) {
4255
+ return null;
4256
+ }
4257
+ }
4258
+ function idTokenIsGuest(idToken, expectedAddress) {
4259
+ var _a;
4260
+ try {
4261
+ if (!idToken)
4262
+ return false;
4263
+ let b64 = (_a = idToken.split('.')[1]) === null || _a === void 0 ? void 0 : _a.replace(/-/g, '+').replace(/_/g, '/');
4264
+ if (!b64)
4265
+ return false;
4266
+ const pad = b64.length % 4;
4267
+ if (pad === 2)
4268
+ b64 += '==';
4269
+ else if (pad === 3)
4270
+ b64 += '=';
4271
+ const claims = JSON.parse(getPlatform().atob(b64));
4272
+ if ((claims === null || claims === void 0 ? void 0 : claims.is_anonymous) !== true)
4273
+ return false;
4274
+ if (expectedAddress && (claims === null || claims === void 0 ? void 0 : claims['custom:walletAddress']) !== expectedAddress)
4275
+ return false;
4276
+ return true;
4277
+ }
4278
+ catch (_b) {
4279
+ return false;
4280
+ }
4281
+ }
4282
+ function storedSessionIsGuest() {
4283
+ return idTokenIsGuest(getStoredIdToken());
4284
+ }
4250
4285
  /**
4251
4286
  * Pick the provider used for an ordinary `init({ appId })` restore.
4252
4287
  *
@@ -4257,7 +4292,16 @@ function setStoredAuthMethod(method) {
4257
4292
  function authMethodForInit(config) {
4258
4293
  if (config.authMethod != null)
4259
4294
  return config.authMethod;
4260
- return getStoredAuthMethod() === 'guest' ? 'guest' : 'email';
4295
+ if (getStoredAuthMethod() !== 'guest')
4296
+ return 'email';
4297
+ if (storedSessionIsGuest())
4298
+ return 'guest';
4299
+ // A marker is only a restore hint; the bearer is authoritative. Repair a
4300
+ // stale marker (for example, a crash/failed switch while a human session was
4301
+ // still active) instead of relabelling that human bearer as a guest.
4302
+ const hasSession = !!getStoredIdToken();
4303
+ setStoredAuthMethod(hasSession ? 'email' : null);
4304
+ return 'email';
4261
4305
  }
4262
4306
  function objectIdentityKey(value) {
4263
4307
  if (!value || (typeof value !== 'object' && typeof value !== 'function'))
@@ -4422,7 +4466,7 @@ async function getAuthProvider(config) {
4422
4466
  // manager as legacy email sessions. Human login should be started
4423
4467
  // with loginWithRedirect(); this provider is kept as the restore and
4424
4468
  // logout surface for those sessions.
4425
- currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-DyxZTpx6.js'); })).EmailAuthProvider();
4469
+ currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-CmYs6Dcm.js'); })).EmailAuthProvider();
4426
4470
  break;
4427
4471
  case "wallet":
4428
4472
  case "phantom": {
@@ -4441,7 +4485,7 @@ async function getAuthProvider(config) {
4441
4485
  if (!isWalletLoginEnabled(config)) {
4442
4486
  throw walletLoginNotEnabledError(authMethod);
4443
4487
  }
4444
- const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-B2T7JEvn.js'); });
4488
+ const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-PYcvLO2Z.js'); });
4445
4489
  currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
4446
4490
  break;
4447
4491
  }
@@ -4454,7 +4498,7 @@ async function getAuthProvider(config) {
4454
4498
  // Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
4455
4499
  // to point at a specific wallet or set chainId/domain.
4456
4500
  const evmWalletConfig = ((_a = config.evmWalletConfig) !== null && _a !== void 0 ? _a : {});
4457
- const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-_eeYB1ww.js'); });
4501
+ const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-BXj1YFaZ.js'); });
4458
4502
  currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
4459
4503
  break;
4460
4504
  }
@@ -4482,7 +4526,7 @@ async function getAuthProvider(config) {
4482
4526
  break;
4483
4527
  case "guest":
4484
4528
  // Anonymous auth: a device-local ed25519 keypair signs the challenge.
4485
- currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-D54uHbov.js'); })).GuestAuthProvider();
4529
+ currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-CxsLCznO.js'); })).GuestAuthProvider();
4486
4530
  break;
4487
4531
  }
4488
4532
  if (!currentAuthProvider) {
@@ -4519,19 +4563,108 @@ function assertBrowserAuthEnv(method) {
4519
4563
  * ownership-as-data pattern. `init()` must have run first. Browser/RN only.
4520
4564
  */
4521
4565
  async function signInAnonymously() {
4566
+ var _a;
4522
4567
  assertBrowserAuthEnv('signInAnonymously');
4523
- const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-D54uHbov.js'); })).GuestAuthProvider();
4524
- currentAuthProvider = provider;
4525
- currentAuthMethod = 'guest';
4526
- currentAuthProviderConfigKey = 'direct:guest';
4568
+ // Resolve configuration before taking the transaction snapshot. Although
4569
+ // getConfig is normally already resolved after init(), it is asynchronous;
4570
+ // another login that finishes during that await must be part of the prior
4571
+ // state we preserve, not accidentally split across old/new snapshots.
4527
4572
  const coreConfig = await core.getConfig();
4528
- coreConfig.authProvider = provider;
4529
- coreConfig.authMethod = 'guest';
4530
- setAuthProviderInstance(provider);
4531
- setStoredAuthMethod('guest');
4573
+ const previousAuthProvider = currentAuthProvider;
4574
+ const previousAuthMethod = currentAuthMethod;
4575
+ const previousProviderConfigKey = currentAuthProviderConfigKey;
4576
+ const previousStoredAuthMethod = getStoredAuthMethod();
4577
+ const previousGlobalProvider = getAuthProviderInstance();
4578
+ const previousUser = getCurrentUser();
4579
+ const previousCoreProvider = coreConfig.authProvider;
4580
+ const previousCoreAuthMethod = coreConfig.authMethod;
4581
+ const previousIdToken = getStoredIdToken();
4582
+ // Lazy-load the guest provider so its ed25519/web3 dependencies stay out of
4583
+ // the main bundle for data-only apps. Specifier is a static string literal
4584
+ // so bundle-splitting can see it.
4585
+ const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-CxsLCznO.js'); })).GuestAuthProvider();
4532
4586
  setAuthLoading(true); // reflect "signing in…" while the guest keypair session is minted
4587
+ const commit = (user) => {
4588
+ // No await/interleaving inside this block: provider/method/config/marker
4589
+ // become guest before the user notification fires, so listeners and
4590
+ // concurrent imperative calls can never observe a mixed identity.
4591
+ currentAuthProvider = provider;
4592
+ currentAuthMethod = 'guest';
4593
+ currentAuthProviderConfigKey = 'direct:guest';
4594
+ coreConfig.authProvider = provider;
4595
+ coreConfig.authMethod = 'guest';
4596
+ setAuthProviderInstance(provider);
4597
+ setStoredAuthMethod('guest');
4598
+ setCurrentUser(user);
4599
+ };
4533
4600
  try {
4534
- return await provider.login();
4601
+ // Mint/store first while every shared provider surface remains on the
4602
+ // previous identity. The provider also withholds setCurrentUser here.
4603
+ const user = await provider.loginForProviderSwitch();
4604
+ if (!user)
4605
+ return null;
4606
+ // A human login may have completed after the guest request persisted but
4607
+ // before its promise resumed here. Re-check the live bearer immediately
4608
+ // before commit so a late guest result cannot overwrite that newer user.
4609
+ if (!user.address || !idTokenIsGuest(getStoredIdToken(), user.address)) {
4610
+ throw new Error('Anonymous sign-in was superseded by another session.');
4611
+ }
4612
+ commit(user);
4613
+ return user;
4614
+ }
4615
+ catch (error) {
4616
+ const currentIdToken = getStoredIdToken();
4617
+ if (currentIdToken !== previousIdToken && idTokenIsGuest(currentIdToken)) {
4618
+ // Defensive applied-yet-error reconciliation: if storage contains a
4619
+ // valid guest bearer/key despite the thrown write, commit that truth
4620
+ // instead of restoring a human UI over a guest token.
4621
+ let recovered = null;
4622
+ try {
4623
+ recovered = await provider.restoreSessionForProviderSwitch();
4624
+ }
4625
+ catch (_b) {
4626
+ try {
4627
+ core.getActiveSessionManager().clearSession();
4628
+ }
4629
+ catch ( /* fail closed below */_c) { /* fail closed below */ }
4630
+ }
4631
+ if (recovered) {
4632
+ commit(recovered);
4633
+ return recovered;
4634
+ }
4635
+ // restoreSessionForProviderSwitch fails closed and clears a split
4636
+ // bearer. Do not resurrect a user object that no longer has its token.
4637
+ setCurrentUser(null);
4638
+ }
4639
+ else if (currentIdToken === previousIdToken) {
4640
+ // The staged attempt never changed the bearer; every shared provider
4641
+ // surface stayed untouched, so restore the exact prior user/marker.
4642
+ currentAuthProvider = previousAuthProvider;
4643
+ currentAuthMethod = previousAuthMethod;
4644
+ currentAuthProviderConfigKey = previousProviderConfigKey;
4645
+ coreConfig.authProvider = previousCoreProvider;
4646
+ coreConfig.authMethod = previousCoreAuthMethod;
4647
+ setAuthProviderInstance(previousGlobalProvider);
4648
+ setStoredAuthMethod(previousStoredAuthMethod);
4649
+ if (getCurrentUser() !== previousUser)
4650
+ setCurrentUser(previousUser);
4651
+ }
4652
+ else {
4653
+ // A different non-guest token won while this staged guest mint was in
4654
+ // flight (another tab/popup/login). The guest attempt never mutated
4655
+ // shared provider state, so preserve that winner exactly. Align only
4656
+ // this module's private registry to the provider the winner installed;
4657
+ // never overwrite its core/global provider, marker, or user snapshot.
4658
+ const concurrentProvider = (_a = getAuthProviderInstance()) !== null && _a !== void 0 ? _a : coreConfig.authProvider;
4659
+ if (concurrentProvider)
4660
+ currentAuthProvider = concurrentProvider;
4661
+ const concurrentStoredMethod = getStoredAuthMethod();
4662
+ currentAuthMethod = concurrentStoredMethod && concurrentStoredMethod !== 'guest'
4663
+ ? concurrentStoredMethod
4664
+ : (previousAuthMethod && previousAuthMethod !== 'guest' ? previousAuthMethod : 'email');
4665
+ currentAuthProviderConfigKey = previousProviderConfigKey;
4666
+ }
4667
+ throw error;
4535
4668
  }
4536
4669
  finally {
4537
4670
  setAuthLoading(false);
@@ -4828,6 +4961,10 @@ function setCurrentUser(user) {
4828
4961
  function getCurrentUser() {
4829
4962
  return currentUser;
4830
4963
  }
4964
+ /** @internal Snapshot/restore surface for transactional auth-provider switches. */
4965
+ function getAuthProviderInstance() {
4966
+ return authProviderInstance;
4967
+ }
4831
4968
  function setAuthProviderInstance(provider) {
4832
4969
  authProviderInstance = provider;
4833
4970
  }
@@ -4904,6 +5041,438 @@ function useAuth() {
4904
5041
  };
4905
5042
  }
4906
5043
 
5044
+ // Wrapper for getIdToken - passes isServer=false for client-side usage
5045
+ async function getIdToken() {
5046
+ return core.getIdToken(false);
5047
+ }
5048
+
5049
+ var __rest = (undefined && undefined.__rest) || function (s, e) {
5050
+ var t = {};
5051
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5052
+ t[p] = s[p];
5053
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
5054
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
5055
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
5056
+ t[p[i]] = s[p[i]];
5057
+ }
5058
+ return t;
5059
+ };
5060
+ /** A structured non-2xx response from the developer API. */
5061
+ class BuildsApiError extends Error {
5062
+ constructor(init) {
5063
+ super(init.message);
5064
+ this.name = 'BuildsApiError';
5065
+ this.code = init.code;
5066
+ this.retryable = init.retryable;
5067
+ this.status = init.status;
5068
+ this.details = init.details;
5069
+ this.retryAfterMs = init.retryAfterMs;
5070
+ }
5071
+ }
5072
+ const memoryIdempotencyKeys = new Map();
5073
+ const IDEMPOTENCY_STORAGE_PREFIX = 'bounded:build:idempotency:';
5074
+ function retryAfterMs(response) {
5075
+ var _a, _b;
5076
+ const value = (_b = (_a = response.headers) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(_a, 'Retry-After');
5077
+ if (!value)
5078
+ return undefined;
5079
+ const seconds = Number(value);
5080
+ if (Number.isFinite(seconds) && seconds >= 0)
5081
+ return Math.ceil(seconds * 1000);
5082
+ const at = Date.parse(value);
5083
+ if (!Number.isFinite(at))
5084
+ return undefined;
5085
+ return Math.max(0, at - Date.now());
5086
+ }
5087
+ async function responseBody(response) {
5088
+ const text = await response.text();
5089
+ if (!text)
5090
+ return {};
5091
+ try {
5092
+ return JSON.parse(text);
5093
+ }
5094
+ catch (_a) {
5095
+ return { raw: text };
5096
+ }
5097
+ }
5098
+ function apiError(response, body) {
5099
+ const envelope = body;
5100
+ const nested = (envelope === null || envelope === void 0 ? void 0 : envelope.error) && typeof envelope.error === 'object'
5101
+ ? envelope.error
5102
+ : undefined;
5103
+ const hasNestedDetails = !!nested && Object.prototype.hasOwnProperty.call(nested, 'details');
5104
+ const hasTopLevelDetails = !!body
5105
+ && typeof body === 'object'
5106
+ && Object.prototype.hasOwnProperty.call(body, 'details');
5107
+ const legacyCode = typeof (body === null || body === void 0 ? void 0 : body.error) === 'string' ? body.error : undefined;
5108
+ const code = typeof (nested === null || nested === void 0 ? void 0 : nested.code) === 'string'
5109
+ ? nested.code
5110
+ : legacyCode !== null && legacyCode !== void 0 ? legacyCode : `http_${response.status}`;
5111
+ const message = typeof (nested === null || nested === void 0 ? void 0 : nested.message) === 'string'
5112
+ ? nested.message
5113
+ : typeof (body === null || body === void 0 ? void 0 : body.message) === 'string'
5114
+ ? body.message
5115
+ : `Developer API request failed with HTTP ${response.status}`;
5116
+ const retryable = typeof (nested === null || nested === void 0 ? void 0 : nested.retryable) === 'boolean'
5117
+ ? nested.retryable
5118
+ : response.status === 429 || response.status >= 500;
5119
+ return new BuildsApiError(Object.assign(Object.assign({ code,
5120
+ message,
5121
+ retryable, status: response.status }, (hasNestedDetails
5122
+ ? { details: nested === null || nested === void 0 ? void 0 : nested.details }
5123
+ : hasTopLevelDetails
5124
+ ? { details: body.details }
5125
+ : {})), (response.status === 429 ? { retryAfterMs: retryAfterMs(response) } : {})));
5126
+ }
5127
+ /** @internal Shared authenticated developer-api transport for builds and apps. */
5128
+ async function requestDevApi(path, request = {}) {
5129
+ var _a, _b;
5130
+ const config = await core.getConfig();
5131
+ const base = (_a = config.devApiUrl) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, '');
5132
+ if (!base) {
5133
+ throw new Error('Bounded developer API is not configured. Pass devApiUrl or a Bounded network to init().');
5134
+ }
5135
+ // Reuse the exact accessor exposed publicly as getIdToken().
5136
+ const token = await getIdToken();
5137
+ if (!token) {
5138
+ throw new BuildsApiError({
5139
+ code: 'auth_required',
5140
+ message: 'Sign in before calling the Bounded developer API.',
5141
+ retryable: false,
5142
+ status: 401,
5143
+ });
5144
+ }
5145
+ const hasBody = request.body !== undefined;
5146
+ const response = await fetch(`${base}${path}`, Object.assign({ method: (_b = request.method) !== null && _b !== void 0 ? _b : 'GET', headers: Object.assign({ Authorization: `Bearer ${token}` }, (hasBody ? { 'Content-Type': 'application/json' } : {})) }, (hasBody ? { body: JSON.stringify(request.body) } : {})));
5147
+ const body = await responseBody(response);
5148
+ if (!response.ok)
5149
+ throw apiError(response, body);
5150
+ return body;
5151
+ }
5152
+ function intentStorageKey(intentKey) {
5153
+ return `${IDEMPOTENCY_STORAGE_PREFIX}${intentKey}`;
5154
+ }
5155
+ function isValidIdempotencyKey(value) {
5156
+ return typeof value === 'string' && value.length > 0 && value.length <= 256;
5157
+ }
5158
+ function readPersistedIdempotencyKey(intentKey) {
5159
+ var _a;
5160
+ const storageKey = intentStorageKey(intentKey);
5161
+ try {
5162
+ const stored = (_a = globalThis.sessionStorage) === null || _a === void 0 ? void 0 : _a.getItem(storageKey);
5163
+ if (isValidIdempotencyKey(stored))
5164
+ return stored;
5165
+ }
5166
+ catch (_b) {
5167
+ // Storage can be disabled by browser privacy policy; use module memory.
5168
+ }
5169
+ const inMemory = memoryIdempotencyKeys.get(storageKey);
5170
+ return isValidIdempotencyKey(inMemory) ? inMemory : undefined;
5171
+ }
5172
+ function persistIdempotencyKey(intentKey, idempotencyKey) {
5173
+ var _a;
5174
+ const storageKey = intentStorageKey(intentKey);
5175
+ memoryIdempotencyKeys.set(storageKey, idempotencyKey);
5176
+ try {
5177
+ (_a = globalThis.sessionStorage) === null || _a === void 0 ? void 0 : _a.setItem(storageKey, idempotencyKey);
5178
+ }
5179
+ catch (_b) {
5180
+ // The in-memory write above is the React Native / disabled-storage fallback.
5181
+ }
5182
+ }
5183
+ function randomHex(bytes) {
5184
+ const cryptoObject = globalThis.crypto;
5185
+ if (cryptoObject === null || cryptoObject === void 0 ? void 0 : cryptoObject.getRandomValues) {
5186
+ const values = new Uint8Array(bytes);
5187
+ cryptoObject.getRandomValues(values);
5188
+ return Array.from(values, (value) => value.toString(16).padStart(2, '0')).join('');
5189
+ }
5190
+ let value = '';
5191
+ for (let index = 0; index < bytes; index += 1) {
5192
+ value += Math.floor(Math.random() * 256).toString(16).padStart(2, '0');
5193
+ }
5194
+ return value;
5195
+ }
5196
+ function mintIdempotencyKey() {
5197
+ const cryptoObject = globalThis.crypto;
5198
+ if (typeof (cryptoObject === null || cryptoObject === void 0 ? void 0 : cryptoObject.randomUUID) === 'function') {
5199
+ return `build_${cryptoObject.randomUUID()}`;
5200
+ }
5201
+ return `build_${Date.now().toString(36)}_${randomHex(16)}`;
5202
+ }
5203
+ function actionIdempotencyKey(options, action) {
5204
+ const supplied = options.idempotencyKey;
5205
+ if (supplied !== undefined) {
5206
+ if (!isValidIdempotencyKey(supplied)) {
5207
+ throw new TypeError('idempotencyKey must be between 1 and 256 characters.');
5208
+ }
5209
+ if (options.intentKey)
5210
+ persistIdempotencyKey(options.intentKey, supplied);
5211
+ return supplied;
5212
+ }
5213
+ if (!options.intentKey) {
5214
+ throw new TypeError(`intentKey is required when ${action} auto-mints an idempotency key.`);
5215
+ }
5216
+ const existing = readPersistedIdempotencyKey(options.intentKey);
5217
+ if (existing)
5218
+ return existing;
5219
+ const minted = mintIdempotencyKey();
5220
+ // This is deliberately synchronous and happens before requestDevApi can fetch.
5221
+ persistIdempotencyKey(options.intentKey, minted);
5222
+ return minted;
5223
+ }
5224
+ function appPath(appId) {
5225
+ return `/app/${encodeURIComponent(appId)}/builds`;
5226
+ }
5227
+ async function submit(appId, options) {
5228
+ const idempotencyKey = actionIdempotencyKey(options, 'submit()');
5229
+ const { intentKey: _intentKey, idempotencyKey: _suppliedKey } = options, submission = __rest(options, ["intentKey", "idempotencyKey"]);
5230
+ return requestDevApi(appPath(appId), {
5231
+ method: 'POST',
5232
+ body: Object.assign(Object.assign({}, submission), { idempotencyKey }),
5233
+ });
5234
+ }
5235
+ async function get(appId, runId) {
5236
+ return requestDevApi(`${appPath(appId)}/${encodeURIComponent(runId)}`);
5237
+ }
5238
+ async function events(appId, runId, after = 0) {
5239
+ const cursor = Number.isFinite(after) ? Math.max(0, Math.floor(after)) : 0;
5240
+ return requestDevApi(`${appPath(appId)}/${encodeURIComponent(runId)}/events?after=${cursor}`);
5241
+ }
5242
+ async function cancel(appId, runId) {
5243
+ return requestDevApi(`${appPath(appId)}/${encodeURIComponent(runId)}/cancel`, { method: 'POST' });
5244
+ }
5245
+ async function decideGate(appId, runId, gateId, options) {
5246
+ const idempotencyKey = actionIdempotencyKey(options, 'decideGate()');
5247
+ const { intentKey: _intentKey, idempotencyKey: _suppliedKey } = options, decision = __rest(options, ["intentKey", "idempotencyKey"]);
5248
+ return requestDevApi(`${appPath(appId)}/${encodeURIComponent(runId)}/gates/${encodeURIComponent(gateId)}/decision`, { method: 'POST', body: Object.assign(Object.assign({}, decision), { idempotencyKey }) });
5249
+ }
5250
+ async function topup(appId, runId, options) {
5251
+ return requestDevApi(`${appPath(appId)}/${encodeURIComponent(runId)}/topup`, { method: 'POST', body: options });
5252
+ }
5253
+ async function list$1(appId, limit = 20) {
5254
+ const requestedLimit = Number.isFinite(limit) ? Math.max(1, Math.floor(limit)) : 20;
5255
+ return requestDevApi(`${appPath(appId)}?limit=${requestedLimit}`);
5256
+ }
5257
+
5258
+ // Source of truth for these strings:
5259
+ // packages/cdk/cloudflare/bounded-build/src/types.ts. Keep them string-pinned;
5260
+ // wire:1 remains additive and callers must tolerate unknown response strings.
5261
+ const NON_TERMINAL_STATES = [
5262
+ 'queued',
5263
+ 'admitted',
5264
+ 'executing',
5265
+ 'preview_ready',
5266
+ 'parked',
5267
+ 'resuming',
5268
+ 'promoting',
5269
+ 'quarantined',
5270
+ ];
5271
+ const TERMINAL_STATES = [
5272
+ 'promoted',
5273
+ 'failed',
5274
+ 'canceled',
5275
+ 'rejected',
5276
+ 'expired',
5277
+ 'rebase_required',
5278
+ 'reported',
5279
+ ];
5280
+ const RUN_STATES = [
5281
+ ...NON_TERMINAL_STATES,
5282
+ ...TERMINAL_STATES,
5283
+ ];
5284
+ const PARK_REASONS = ['gate', 'funding'];
5285
+ const FAILURE_REASONS = [
5286
+ 'admission_rejected',
5287
+ 'dispatch_timeout',
5288
+ 'auth_revoked',
5289
+ 'owner_changed',
5290
+ 'policy_changed',
5291
+ 'quarantine_forced',
5292
+ 'bind_failed',
5293
+ 'internal_error',
5294
+ ];
5295
+
5296
+ const NORMAL_POLL_MS = 2000;
5297
+ const PARKED_POLL_MS = 5000;
5298
+ const LONG_RUNNING_POLL_MS = 10000;
5299
+ const TWO_MINUTES_MS = 2 * 60000;
5300
+ const TEN_MINUTES_MS = 10 * 60000;
5301
+ const terminalStates = new Set(TERMINAL_STATES);
5302
+ function pollCadence(state, elapsedMs) {
5303
+ if (elapsedMs >= TEN_MINUTES_MS)
5304
+ return LONG_RUNNING_POLL_MS;
5305
+ if ((state === null || state === void 0 ? void 0 : state.startsWith('parked')) || elapsedMs >= TWO_MINUTES_MS)
5306
+ return PARKED_POLL_MS;
5307
+ return NORMAL_POLL_MS;
5308
+ }
5309
+ function retryCadence(error, state, elapsedMs) {
5310
+ const cadence = pollCadence(state, elapsedMs);
5311
+ if (error instanceof BuildsApiError && error.status === 429 && error.retryAfterMs !== undefined) {
5312
+ return Math.max(cadence, error.retryAfterMs);
5313
+ }
5314
+ return cadence;
5315
+ }
5316
+ function hasRetryAfter(error) {
5317
+ return error instanceof BuildsApiError
5318
+ && error.status === 429
5319
+ && error.retryAfterMs !== undefined;
5320
+ }
5321
+ // A permanent API refusal (expired session, revoked access, unknown run) will
5322
+ // never heal by re-polling; the loop must stop and surface it instead of
5323
+ // retrying forever. 429 stays retryable regardless of the server envelope.
5324
+ function isPermanentError(error) {
5325
+ return error instanceof BuildsApiError
5326
+ && error.status !== 429
5327
+ && error.retryable === false;
5328
+ }
5329
+ function newEvents(rows, lastSeq, seen) {
5330
+ const cursorBeforePoll = lastSeq;
5331
+ const fresh = [];
5332
+ let nextCursor = lastSeq;
5333
+ for (const event of rows) {
5334
+ if (!Number.isFinite(event === null || event === void 0 ? void 0 : event.seq))
5335
+ continue;
5336
+ nextCursor = Math.max(nextCursor, event.seq);
5337
+ if (event.seq <= cursorBeforePoll || seen.has(event.seq))
5338
+ continue;
5339
+ seen.add(event.seq);
5340
+ fresh.push(event);
5341
+ }
5342
+ return { events: fresh, lastSeq: nextCursor };
5343
+ }
5344
+ /**
5345
+ * Poll a build view and its event cursor until stopped or the run reaches a
5346
+ * known terminal state. Unknown state strings remain untouched and nonterminal.
5347
+ */
5348
+ function watch(appId, runId, onUpdate, options = {}) {
5349
+ const startedAt = Date.now();
5350
+ const seenSeqs = new Set();
5351
+ let lastSeq = Number.isFinite(options.after)
5352
+ ? Math.max(0, Math.floor(options.after))
5353
+ : 0;
5354
+ let timer;
5355
+ let active = true;
5356
+ let lastState;
5357
+ const stop = () => {
5358
+ active = false;
5359
+ if (timer !== undefined) {
5360
+ clearTimeout(timer);
5361
+ timer = undefined;
5362
+ }
5363
+ };
5364
+ const schedule = (delayMs) => {
5365
+ if (!active)
5366
+ return;
5367
+ timer = setTimeout(() => {
5368
+ timer = undefined;
5369
+ void poll();
5370
+ }, delayMs);
5371
+ };
5372
+ const reportError = (error) => {
5373
+ var _a;
5374
+ try {
5375
+ (_a = options.onError) === null || _a === void 0 ? void 0 : _a.call(options, error);
5376
+ }
5377
+ catch (_b) {
5378
+ // A consumer error callback must not break the transport loop.
5379
+ }
5380
+ };
5381
+ const publish = (run, events) => {
5382
+ try {
5383
+ onUpdate({ run, events });
5384
+ }
5385
+ catch (_a) {
5386
+ // Polling is transport state; consumer render errors must not strand it.
5387
+ }
5388
+ };
5389
+ const poll = async () => {
5390
+ if (!active)
5391
+ return;
5392
+ let run;
5393
+ try {
5394
+ const view = await get(appId, runId);
5395
+ if (!active)
5396
+ return;
5397
+ run = view.run;
5398
+ lastState = run.state;
5399
+ }
5400
+ catch (error) {
5401
+ if (!active)
5402
+ return;
5403
+ reportError(error);
5404
+ if (isPermanentError(error)) {
5405
+ stop();
5406
+ return;
5407
+ }
5408
+ schedule(retryCadence(error, lastState, Date.now() - startedAt));
5409
+ return;
5410
+ }
5411
+ try {
5412
+ const response = await events(appId, runId, lastSeq);
5413
+ if (!active)
5414
+ return;
5415
+ const deduped = newEvents(Array.isArray(response.events) ? response.events : [], lastSeq, seenSeqs);
5416
+ lastSeq = deduped.lastSeq;
5417
+ publish(run, deduped.events);
5418
+ }
5419
+ catch (error) {
5420
+ if (!active)
5421
+ return;
5422
+ // The view still advances UI state even when event replay is rate-limited.
5423
+ publish(run, []);
5424
+ reportError(error);
5425
+ if (terminalStates.has(run.state)) {
5426
+ // The run itself is done, but a rate-limited final event replay still
5427
+ // owes the caller its unseen seq rows. Honor Retry-After, retry the
5428
+ // piggyback once the limiter permits it, then stop after a successful
5429
+ // replay. Other terminal replay failures stop normally.
5430
+ if (hasRetryAfter(error)) {
5431
+ schedule(retryCadence(error, run.state, Date.now() - startedAt));
5432
+ return;
5433
+ }
5434
+ stop();
5435
+ return;
5436
+ }
5437
+ if (isPermanentError(error)) {
5438
+ stop();
5439
+ return;
5440
+ }
5441
+ schedule(retryCadence(error, run.state, Date.now() - startedAt));
5442
+ return;
5443
+ }
5444
+ if (!active)
5445
+ return;
5446
+ if (terminalStates.has(run.state)) {
5447
+ // Drain the remaining event pages before stopping: a resumed terminal
5448
+ // watch may owe the caller more rows than one page returns. Each page
5449
+ // advances the cursor, so the loop terminates; the cap is a backstop.
5450
+ for (let page = 0; page < 50 && active; page += 1) {
5451
+ let drained;
5452
+ try {
5453
+ const response = await events(appId, runId, lastSeq);
5454
+ if (!active)
5455
+ return;
5456
+ drained = newEvents(Array.isArray(response.events) ? response.events : [], lastSeq, seenSeqs);
5457
+ }
5458
+ catch (error) {
5459
+ reportError(error);
5460
+ break;
5461
+ }
5462
+ if (drained.events.length === 0)
5463
+ break;
5464
+ lastSeq = drained.lastSeq;
5465
+ publish(run, drained.events);
5466
+ }
5467
+ stop();
5468
+ return;
5469
+ }
5470
+ schedule(pollCadence(run.state, Date.now() - startedAt));
5471
+ };
5472
+ void poll();
5473
+ return { stop };
5474
+ }
5475
+
4907
5476
  var _a;
4908
5477
  // SSR guard (mirrors useAuth): no hooks/subscriptions during Node server render.
4909
5478
  // React Native has no `window` but DOES support hooks, so detect Node SSR
@@ -4911,65 +5480,108 @@ var _a;
4911
5480
  const isSSR = typeof window === 'undefined'
4912
5481
  && typeof process !== 'undefined'
4913
5482
  && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
4914
- function useQuery(path, options) {
5483
+ function useBuildRun(appId, runId, options) {
4915
5484
  if (isSSR) {
4916
- return { data: undefined, loading: true, error: null };
5485
+ return { run: null, events: [], loading: true, error: null };
4917
5486
  }
4918
- const [data, setData] = React__namespace.useState(undefined);
5487
+ const [run, setRun] = React__namespace.useState(null);
5488
+ const [events, setEvents] = React__namespace.useState([]);
4919
5489
  const [loading, setLoading] = React__namespace.useState(true);
4920
5490
  const [error, setError] = React__namespace.useState(null);
4921
- // Re-subscribe only when the query actually changes (not on every render).
4922
5491
  const optionsKey = options ? JSON.stringify(options) : '';
4923
5492
  React__namespace.useEffect(() => {
4924
- if (!path) {
4925
- setData(undefined);
5493
+ setRun(null);
5494
+ setEvents([]);
5495
+ setError(null);
5496
+ if (!appId || !runId) {
4926
5497
  setLoading(false);
4927
- setError(null);
4928
5498
  return;
4929
5499
  }
4930
5500
  let active = true;
4931
- let unsubscribe;
4932
5501
  setLoading(true);
4933
- setError(null);
4934
- core.subscribe(path, Object.assign(Object.assign({}, options), { onData: (d) => {
4935
- if (!active)
4936
- return;
4937
- // A reconnect can legitimately surface a transport error before the
4938
- // socket re-authenticates and sends a new authorized snapshot. That
4939
- // fresh snapshot is the recovery boundary: keep the error visible
4940
- // until data arrives, then clear it so React does not remain stuck on
4941
- // a failure page after realtime has recovered.
4942
- setError(null);
4943
- setData(d);
4944
- setLoading(false);
4945
- }, onError: (e) => {
4946
- if (!active)
4947
- return;
4948
- setError(e instanceof Error ? e : new Error(String(e)));
4949
- setLoading(false);
4950
- } }))
4951
- .then((unsub) => {
4952
- if (active)
4953
- unsubscribe = unsub;
4954
- else
4955
- void unsub(); // unmounted before subscribe resolved
4956
- })
4957
- .catch((e) => {
5502
+ const handle = watch(appId, runId, ({ run: nextRun, events: nextEvents }) => {
4958
5503
  if (!active)
4959
5504
  return;
4960
- setError(e instanceof Error ? e : new Error(String(e)));
5505
+ setRun(nextRun);
5506
+ if (nextEvents.length > 0) {
5507
+ setEvents((current) => {
5508
+ const seen = new Set(current.map((event) => event.seq));
5509
+ return [...current, ...nextEvents.filter((event) => !seen.has(event.seq))];
5510
+ });
5511
+ }
5512
+ setError(null);
4961
5513
  setLoading(false);
4962
- });
5514
+ }, Object.assign(Object.assign({}, options), { onError: (value) => {
5515
+ if (!active)
5516
+ return;
5517
+ setError(value instanceof Error ? value : new Error(String(value)));
5518
+ setLoading(false);
5519
+ } }));
4963
5520
  return () => {
4964
5521
  active = false;
4965
- void (unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe());
5522
+ handle.stop();
4966
5523
  };
4967
- // optionsKey captures the option object's contents; path is the other input.
5524
+ // optionsKey captures the option object's contents; ids are the other inputs.
4968
5525
  // eslint-disable-next-line react-hooks/exhaustive-deps
4969
- }, [path, optionsKey]);
4970
- return { data, loading, error };
5526
+ }, [appId, runId, optionsKey]);
5527
+ return { run, events, loading, error };
4971
5528
  }
4972
5529
 
5530
+ /**
5531
+ * Platform first-party surfaces only (bounded.sh, oapps.fun, localhost) —
5532
+ * dev-api CORS blocks calls from generated-app origins. Server-side callers unaffected.
5533
+ */
5534
+ const builds = {
5535
+ submit,
5536
+ get,
5537
+ events,
5538
+ cancel,
5539
+ decideGate,
5540
+ topup,
5541
+ list: list$1,
5542
+ watch,
5543
+ };
5544
+
5545
+ async function create(options = {}) {
5546
+ const body = Object.assign(Object.assign(Object.assign(Object.assign({}, (options.name !== undefined ? { name: options.name } : {})), (options.prompt !== undefined ? { prompt: options.prompt } : {})), (options.clientToken !== undefined ? { clientToken: options.clientToken } : {})), (options.intent !== undefined ? { intent: options.intent } : {}));
5547
+ const app = await requestDevApi('/apps/new', {
5548
+ method: 'POST',
5549
+ body,
5550
+ });
5551
+ return Object.assign(Object.assign({ appId: app.appId }, (typeof app.slug === 'string' && app.slug ? { slug: app.slug } : {})), { url: app.url,
5552
+ // Fail closed against an older server response that omitted this field.
5553
+ policySeeded: app.policySeeded === true });
5554
+ }
5555
+ async function list() {
5556
+ // This legacy-compatible action shape is also used by oapps.fun listMyApps.
5557
+ const response = await requestDevApi('/', {
5558
+ method: 'POST',
5559
+ body: { action: 'listApps' },
5560
+ });
5561
+ const rows = Array.isArray(response.apps) ? response.apps : [];
5562
+ return rows
5563
+ .map((value) => {
5564
+ var _a, _b, _c, _d;
5565
+ const row = value && typeof value === 'object'
5566
+ ? value
5567
+ : {};
5568
+ const appId = String((_c = (_b = (_a = row._id) !== null && _a !== void 0 ? _a : row.id) !== null && _b !== void 0 ? _b : row.appId) !== null && _c !== void 0 ? _c : '');
5569
+ if (!/^[a-f0-9]{24}$/i.test(appId))
5570
+ return null;
5571
+ const name = String((_d = row.name) !== null && _d !== void 0 ? _d : '').trim() || '(unnamed app)';
5572
+ const slug = typeof row.slug === 'string' && row.slug ? row.slug : undefined;
5573
+ const url = typeof row.url === 'string' && row.url.trim() ? row.url.trim() : undefined;
5574
+ return Object.assign(Object.assign({ appId,
5575
+ name }, (slug ? { slug } : {})), (url ? { url } : {}));
5576
+ })
5577
+ .filter((app) => app !== null);
5578
+ }
5579
+ /**
5580
+ * Platform first-party surfaces only (bounded.sh, oapps.fun, localhost) —
5581
+ * dev-api CORS blocks calls from generated-app origins. Server-side callers unaffected.
5582
+ */
5583
+ const apps = { create, list };
5584
+
4973
5585
  async function deserializeTransaction(tx) {
4974
5586
  // Literal specifier so bundlers can code-split the lazy chunk.
4975
5587
  const { Transaction, VersionedTransaction } = await import('@solana/web3.js');
@@ -4982,11 +5594,6 @@ async function deserializeTransaction(tx) {
4982
5594
  }
4983
5595
  }
4984
5596
 
4985
- // Wrapper for getIdToken - passes isServer=false for client-side usage
4986
- async function getIdToken() {
4987
- return core.getIdToken(false);
4988
- }
4989
-
4990
5597
  /**
4991
5598
  * Extracts a human-readable error message from Solana transaction logs.
4992
5599
  */
@@ -5382,102 +5989,23 @@ class PrivyExpoProvider {
5382
5989
  }
5383
5990
  }
5384
5991
 
5385
- /**
5386
- * Default provider discovery: Phantom-first, then any Wallet-Standard
5387
- * `window.solana`. Kept tiny + synchronous (no heavy imports) so it works inside
5388
- * a user gesture and can be eagerly exported from the SDK entry.
5389
- */
5390
- function defaultInjectedProvider() {
5391
- var _a;
5392
- if (typeof window === 'undefined')
5393
- return null;
5394
- const w = window;
5395
- const phantom = (_a = w === null || w === void 0 ? void 0 : w.phantom) === null || _a === void 0 ? void 0 : _a.solana;
5396
- if (phantom && typeof phantom.signMessage === 'function')
5397
- return phantom;
5398
- const generic = w === null || w === void 0 ? void 0 : w.solana;
5399
- if (generic && typeof generic.signMessage === 'function')
5400
- return generic;
5401
- return null;
5402
- }
5403
-
5404
- // injected-evm-wallet-types.ts — tiny, dependency-free surface for the EVM
5405
- // WALLET LOGIN path (BYO wallet via SIWE). The EVM twin of
5406
- // injected-wallet-types.ts: kept separate from injected-evm-wallet-provider.ts
5407
- // so the SDK entry can eagerly export the type surface + the provider-discovery
5408
- // helper WITHOUT dragging the provider class into the default bundle. The
5409
- // provider is lazy-loaded by getAuthProvider() when an app opts into
5410
- // authMethod:'evm-wallet'.
5411
- //
5412
- // It rides the standard EIP-1193 injected provider a browser wallet exposes
5413
- // (MetaMask / Rabby / Coinbase Wallet / any window.ethereum), discovered via
5414
- // EIP-6963 (multi-wallet, collision-free) with a window.ethereum fallback. It
5415
- // needs NO viem/ethers and NO React — EIP-1193 request() + hex strings suffice.
5416
- // EIP-6963 is announcement-based: wallets add an `eip6963:requestProvider`
5417
- // listener and synchronously dispatch `eip6963:announceProvider` in response. We
5418
- // keep a persistent collector so announcements (including late ones) are
5419
- // captured, and re-request on demand.
5420
- const announcedProviders = [];
5421
- let announceListenerAttached = false;
5422
- function attachAnnounceListener() {
5423
- if (announceListenerAttached || typeof window === 'undefined')
5424
- return;
5425
- announceListenerAttached = true;
5426
- window.addEventListener('eip6963:announceProvider', (event) => {
5427
- const detail = event === null || event === void 0 ? void 0 : event.detail;
5428
- if (detail &&
5429
- detail.provider &&
5430
- typeof detail.provider.request === 'function' &&
5431
- !announcedProviders.some((d) => { var _a, _b; return ((_a = d.info) === null || _a === void 0 ? void 0 : _a.uuid) === ((_b = detail.info) === null || _b === void 0 ? void 0 : _b.uuid); })) {
5432
- announcedProviders.push(detail);
5433
- }
5434
- });
5435
- }
5436
- /**
5437
- * Request + collect EIP-6963 providers. Dispatches `eip6963:requestProvider`
5438
- * (synchronous — already-loaded wallets announce in the same tick) and returns
5439
- * every wallet announced so far. Kept synchronous so it works inside a user
5440
- * gesture and can be eagerly exported from the SDK entry.
5441
- */
5442
- function requestEip6963Providers() {
5443
- if (typeof window === 'undefined')
5444
- return [];
5445
- attachAnnounceListener();
5446
- try {
5447
- window.dispatchEvent(new Event('eip6963:requestProvider'));
5448
- }
5449
- catch (_a) {
5450
- /* older browsers without Event constructor — fall through to window.ethereum */
5451
- }
5452
- return announcedProviders.slice();
5453
- }
5454
- /**
5455
- * Default EVM provider discovery: EIP-6963 first (multi-wallet, collision-free),
5456
- * then legacy `window.ethereum`. Returns null when no injected wallet is present.
5457
- */
5458
- function defaultInjectedEvmProvider() {
5459
- if (typeof window === 'undefined')
5460
- return null;
5461
- const details = requestEip6963Providers();
5462
- if (details.length > 0)
5463
- return details[0].provider;
5464
- const eth = window.ethereum;
5465
- if (eth && typeof eth.request === 'function')
5466
- return eth;
5467
- return null;
5468
- }
5469
-
5992
+ exports.BuildsApiError = BuildsApiError;
5470
5993
  exports.EMBEDDED_WALLET_UNSUPPORTED = EMBEDDED_WALLET_UNSUPPORTED;
5994
+ exports.FAILURE_REASONS = FAILURE_REASONS;
5995
+ exports.NON_TERMINAL_STATES = NON_TERMINAL_STATES;
5471
5996
  exports.OffchainAuthProvider = OffchainAuthProvider;
5997
+ exports.PARK_REASONS = PARK_REASONS;
5472
5998
  exports.PrivyExpoProvider = PrivyExpoProvider;
5999
+ exports.RUN_STATES = RUN_STATES;
5473
6000
  exports.SURFNET_RPC_URL = SURFNET_RPC_URL;
6001
+ exports.TERMINAL_STATES = TERMINAL_STATES;
6002
+ exports.apps = apps;
5474
6003
  exports.bs58 = bs58;
5475
6004
  exports.bufferExports = bufferExports;
6005
+ exports.builds = builds;
5476
6006
  exports.completeLoginFromRedirect = completeLoginFromRedirect;
5477
6007
  exports.completeLoginInPopup = completeLoginInPopup;
5478
6008
  exports.confirmAndCheckTransaction = confirmAndCheckTransaction;
5479
- exports.defaultInjectedEvmProvider = defaultInjectedEvmProvider;
5480
- exports.defaultInjectedProvider = defaultInjectedProvider;
5481
6009
  exports.deserializeTransaction = deserializeTransaction;
5482
6010
  exports.embeddedRunEvmTransaction = embeddedRunEvmTransaction;
5483
6011
  exports.embeddedSignAndSubmit = embeddedSignAndSubmit;
@@ -5497,12 +6025,11 @@ exports.logout = logout;
5497
6025
  exports.normalizeSolanaRpcUrl = normalizeSolanaRpcUrl;
5498
6026
  exports.onAuthLoadingChanged = onAuthLoadingChanged;
5499
6027
  exports.onAuthStateChanged = onAuthStateChanged;
5500
- exports.requestEip6963Providers = requestEip6963Providers;
5501
6028
  exports.resolveSolanaRpcUrl = resolveSolanaRpcUrl;
5502
6029
  exports.setAuthLoading = setAuthLoading;
5503
6030
  exports.setCurrentUser = setCurrentUser;
5504
6031
  exports.setPlatform = setPlatform;
5505
6032
  exports.signInAnonymously = signInAnonymously;
5506
6033
  exports.useAuth = useAuth;
5507
- exports.useQuery = useQuery;
5508
- //# sourceMappingURL=index-JBeYYsGm.js.map
6034
+ exports.useBuildRun = useBuildRun;
6035
+ //# sourceMappingURL=index.native-BfoLJCZg.js.map