@bounded-sh/client 0.0.42 → 0.0.44

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.
package/dist/index.js CHANGED
@@ -3655,7 +3655,7 @@ function decodeJwt$2(token) {
3655
3655
  // Pull the embedded-wallet identity out of the active session's id token.
3656
3656
  // Returns null when this session has no wallet (so callers can throw the
3657
3657
  // informative NO_EMBEDDED_WALLET error).
3658
- function walletClaimsFromSession() {
3658
+ function walletClaimsFromSession(chain = 'solana') {
3659
3659
  let idToken = null;
3660
3660
  try {
3661
3661
  idToken = core.getActiveSessionManager().getIdToken();
@@ -3667,14 +3667,17 @@ function walletClaimsFromSession() {
3667
3667
  return null;
3668
3668
  const c = decodeJwt$2(idToken);
3669
3669
  const address = c['custom:walletAddress'];
3670
+ const evmAddress = c['custom:evmWalletAddress'];
3670
3671
  const email = c['email'];
3671
- if (typeof address !== 'string' || !address)
3672
- return null;
3673
3672
  if (typeof email !== 'string' || !email)
3674
3673
  return null;
3674
+ if (chain === 'solana' && (typeof address !== 'string' || !address))
3675
+ return null;
3676
+ if (chain === 'evm' && (typeof evmAddress !== 'string' || !/^0x[0-9a-fA-F]{40}$/.test(evmAddress)))
3677
+ return null;
3675
3678
  const envClaim = c['custom:walletEnvironment'];
3676
3679
  const environment = envClaim === 'staging' || envClaim === 'production' ? envClaim : undefined;
3677
- return { email, address, environment };
3680
+ return Object.assign(Object.assign(Object.assign({ email }, (typeof address === 'string' && address ? { address } : {})), (typeof evmAddress === 'string' ? { evmAddress: evmAddress.toLowerCase() } : {})), { environment });
3678
3681
  }
3679
3682
  async function signerPageUrl() {
3680
3683
  const cfg = await core.getConfig();
@@ -3695,7 +3698,8 @@ async function signViaSignerPopup(action) {
3695
3698
  if (!hasDOM$1()) {
3696
3699
  throw new Error('Embedded-wallet signing is only available in the browser (popup-based).');
3697
3700
  }
3698
- const claims = walletClaimsFromSession();
3701
+ const isEvm = action.kind === 'evmTransaction';
3702
+ const claims = walletClaimsFromSession(isEvm ? 'evm' : 'solana');
3699
3703
  if (!claims)
3700
3704
  throw new Error(NO_EMBEDDED_WALLET);
3701
3705
  const { url, origin: signerOrigin } = await signerPageUrl();
@@ -3713,7 +3717,7 @@ async function signViaSignerPopup(action) {
3713
3717
  requestId,
3714
3718
  environment: claims.environment, // may be undefined → page auto-detects
3715
3719
  email: claims.email,
3716
- address: claims.address,
3720
+ address: isEvm ? claims.evmAddress : claims.address,
3717
3721
  action,
3718
3722
  };
3719
3723
  return await new Promise((resolve, reject) => {
@@ -3738,6 +3742,8 @@ async function signViaSignerPopup(action) {
3738
3742
  const onMsg = (ev) => {
3739
3743
  if (ev.origin !== signerOrigin)
3740
3744
  return; // only trust the signer page origin
3745
+ if (ev.source !== popup)
3746
+ return; // only trust this signer popup window
3741
3747
  const d = ev.data;
3742
3748
  if (!d || typeof d !== 'object')
3743
3749
  return;
@@ -3809,6 +3815,10 @@ function serializeTransaction(transaction) {
3809
3815
  function hasEmbeddedWallet() {
3810
3816
  return walletClaimsFromSession() != null;
3811
3817
  }
3818
+ /** Whether the active email/social session carries an embedded Crossmint EVM wallet. */
3819
+ function hasEmbeddedEvmWallet() {
3820
+ return walletClaimsFromSession('evm') != null;
3821
+ }
3812
3822
  /** signAndSubmitTransaction for embedded wallets: serialize + route through the
3813
3823
  * signer popup, resolve with the on-chain transaction signature/hash. */
3814
3824
  async function embeddedSignAndSubmit(transaction) {
@@ -3819,6 +3829,36 @@ async function embeddedSignAndSubmit(transaction) {
3819
3829
  throw new Error('Signer returned no transaction hash.');
3820
3830
  return hash;
3821
3831
  }
3832
+ /** Submit a validated BoundedRuntime EVM write through the user's email signer. */
3833
+ async function embeddedRunEvmTransaction(transaction) {
3834
+ var _a, _b;
3835
+ if (!transaction.to || !transaction.data || !transaction.chainId)
3836
+ throw new Error('Incomplete embedded EVM transaction');
3837
+ if (!/^0x[0-9a-fA-F]{40}$/.test(transaction.to))
3838
+ throw new Error('Invalid embedded EVM runtime address');
3839
+ core.assertCanonicalBoundedRuntimeWriteCalldata(transaction.data);
3840
+ if (!Number.isSafeInteger(transaction.chainId) || transaction.chainId <= 0)
3841
+ throw new Error('Invalid embedded EVM chain id');
3842
+ if (transaction.nonce !== undefined)
3843
+ throw new Error('Server-supplied EVM nonces are not accepted');
3844
+ try {
3845
+ if (BigInt((_a = transaction.value) !== null && _a !== void 0 ? _a : '0') !== BigInt(0))
3846
+ throw new Error('Bounded EVM writes cannot transfer native value');
3847
+ }
3848
+ catch (error) {
3849
+ if (error instanceof Error && error.message.includes('cannot transfer'))
3850
+ throw error;
3851
+ throw new Error('Invalid embedded EVM transaction value');
3852
+ }
3853
+ const result = await signViaSignerPopup({
3854
+ kind: 'evmTransaction',
3855
+ transaction: { to: transaction.to, data: transaction.data, value: (_b = transaction.value) !== null && _b !== void 0 ? _b : '0', chainId: transaction.chainId },
3856
+ });
3857
+ const hash = result.hash || result.transactionId;
3858
+ if (!hash)
3859
+ throw new Error('Signer returned no EVM transaction hash.');
3860
+ return { transactionSignature: hash, blockNumber: 0, gasUsed: '0', data: result };
3861
+ }
3822
3862
 
3823
3863
  // Web uses localStorage (WebSessionManager); React Native uses the configured
3824
3864
  // ReactNativeSessionManager. getActiveSessionManager() picks the right one by
@@ -3853,7 +3893,10 @@ function userFromIdToken$1(idToken, fallbackEmail) {
3853
3893
  const id = c['custom:userId'] || c.sub || c['custom:walletAddress'] || '';
3854
3894
  const email = (c.email || fallbackEmail || null);
3855
3895
  // Email logins have no wallet — address is null (the User type allows it).
3856
- return { id, address: (c['custom:walletAddress'] || null), email, provider: emailProviderSingleton };
3896
+ const evmAddress = typeof c['custom:evmWalletAddress'] === 'string' && /^0x[0-9a-fA-F]{40}$/.test(c['custom:evmWalletAddress'])
3897
+ ? c['custom:evmWalletAddress'].toLowerCase()
3898
+ : null;
3899
+ return { id, address: (c['custom:walletAddress'] || null), evmAddress, email, provider: emailProviderSingleton };
3857
3900
  }
3858
3901
  // ---------------------------------------------------------------------------
3859
3902
  // provider
@@ -3887,7 +3930,17 @@ class EmailAuthProvider {
3887
3930
  async signMessage(_message) {
3888
3931
  throw new Error(hasEmbeddedWallet() ? EMBEDDED_WALLET_UNSUPPORTED : NO_WALLET);
3889
3932
  }
3890
- async runTransaction(_evm, _sol, _options) { throw new Error(NO_WALLET); }
3933
+ async runTransaction(evm, sol, options) {
3934
+ if (evm && sol)
3935
+ throw new Error('A transaction cannot target EVM and Solana at the same time.');
3936
+ if (!evm)
3937
+ throw new Error(NO_WALLET);
3938
+ if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false)
3939
+ throw new Error('Embedded EVM wallets sign and submit atomically; shouldSubmitTx:false is unsupported.');
3940
+ if (!hasEmbeddedEvmWallet())
3941
+ throw new Error('This login has no embedded EVM wallet. Enable auth.wallets on an app with an EVM collection and sign in again.');
3942
+ return embeddedRunEvmTransaction(evm);
3943
+ }
3891
3944
  async signTransaction(_t) {
3892
3945
  throw new Error(hasEmbeddedWallet() ? EMBEDDED_WALLET_UNSUPPORTED : NO_WALLET);
3893
3946
  }
@@ -3993,31 +4046,45 @@ function defaultInjectedProvider() {
3993
4046
  return null;
3994
4047
  }
3995
4048
 
3996
- const STORED_AUTH_METHOD_KEY$2 = 'bounded_last_auth_method';
4049
+ const STORED_AUTH_METHOD_KEY$3 = 'bounded_last_auth_method';
3997
4050
  const INJECTED_AUTH_METHOD = 'phantom';
3998
- const NO_WALLET_ERR = 'No injected Solana wallet found. Install a wallet like Phantom (phantom.app) and try again, ' +
4051
+ const NO_WALLET_ERR$1 = 'No injected Solana wallet found. Install a wallet like Phantom (phantom.app) and try again, ' +
3999
4052
  'or pass config.injectedWalletConfig.getProvider to point at your wallet.';
4000
4053
  class InjectedWalletProvider {
4001
4054
  constructor(config = {}, networkUrl = null, configuredNetwork = null) {
4002
- var _a, _b;
4055
+ var _a;
4003
4056
  if (typeof window === 'undefined') {
4004
4057
  throw new Error('InjectedWalletProvider can only be instantiated in a browser environment');
4005
4058
  }
4059
+ // `config.rpcUrl` is the legacy wallet-login-local override. Normalize
4060
+ // it before precedence so an empty legacy value cannot shadow the
4061
+ // current top-level config.rpcUrl. Re-initialization must also replace
4062
+ // every singleton field; otherwise a previous app's provider/RPC can
4063
+ // survive getAuthProvider()'s config-key rotation.
4064
+ const resolvedNetworkUrl = (_a = normalizeSolanaRpcUrl(config.rpcUrl)) !== null && _a !== void 0 ? _a : normalizeSolanaRpcUrl(networkUrl);
4065
+ const localNetwork = typeof config.network === 'string' && config.network.trim() !== ''
4066
+ ? config.network.trim()
4067
+ : null;
4068
+ const resolvedConfiguredNetwork = localNetwork !== null && localNetwork !== void 0 ? localNetwork : (typeof configuredNetwork === 'string' && configuredNetwork.trim() !== ''
4069
+ ? configuredNetwork.trim()
4070
+ : null);
4006
4071
  // Singleton so the SDK reuses one instance (mirrors the other providers).
4007
4072
  if (InjectedWalletProvider.instance) {
4008
- InjectedWalletProvider.instance.config = Object.assign(Object.assign({}, InjectedWalletProvider.instance.config), config);
4073
+ InjectedWalletProvider.instance.config = Object.assign({}, config);
4074
+ InjectedWalletProvider.instance.networkUrl = resolvedNetworkUrl;
4075
+ InjectedWalletProvider.instance.configuredNetwork = resolvedConfiguredNetwork;
4009
4076
  return InjectedWalletProvider.instance;
4010
4077
  }
4011
- this.config = config;
4012
- this.networkUrl = (_a = config.rpcUrl) !== null && _a !== void 0 ? _a : networkUrl;
4013
- this.configuredNetwork = (_b = config.network) !== null && _b !== void 0 ? _b : configuredNetwork;
4078
+ this.config = Object.assign({}, config);
4079
+ this.networkUrl = resolvedNetworkUrl;
4080
+ this.configuredNetwork = resolvedConfiguredNetwork;
4014
4081
  InjectedWalletProvider.instance = this;
4015
4082
  }
4016
4083
  resolveProvider() {
4017
4084
  var _a;
4018
4085
  const provider = (_a = (this.config.getProvider ? this.config.getProvider() : null)) !== null && _a !== void 0 ? _a : defaultInjectedProvider();
4019
4086
  if (!provider)
4020
- throw new Error(NO_WALLET_ERR);
4087
+ throw new Error(NO_WALLET_ERR$1);
4021
4088
  return provider;
4022
4089
  }
4023
4090
  /** Connect the injected wallet (if needed) and return its Solana address. */
@@ -4071,7 +4138,7 @@ class InjectedWalletProvider {
4071
4138
  // Mark the auth method so clearIncompatibleSession() doesn't wipe this
4072
4139
  // wallet session on the next init().
4073
4140
  try {
4074
- getPlatform().storage.setItem(STORED_AUTH_METHOD_KEY$2, INJECTED_AUTH_METHOD);
4141
+ getPlatform().storage.setItem(STORED_AUTH_METHOD_KEY$3, INJECTED_AUTH_METHOD);
4075
4142
  }
4076
4143
  catch ( /* no storage */_a) { /* no storage */ }
4077
4144
  }
@@ -4226,6 +4293,406 @@ class InjectedWalletProvider {
4226
4293
  }
4227
4294
  InjectedWalletProvider.instance = null;
4228
4295
 
4296
+ // injected-evm-wallet-types.ts — tiny, dependency-free surface for the EVM
4297
+ // WALLET LOGIN path (BYO wallet via SIWE). The EVM twin of
4298
+ // injected-wallet-types.ts: kept separate from injected-evm-wallet-provider.ts
4299
+ // so the SDK entry can eagerly export the type surface + the provider-discovery
4300
+ // helper WITHOUT dragging the provider class into the default bundle. The
4301
+ // provider is lazy-loaded by getAuthProvider() when an app opts into
4302
+ // authMethod:'evm-wallet'.
4303
+ //
4304
+ // It rides the standard EIP-1193 injected provider a browser wallet exposes
4305
+ // (MetaMask / Rabby / Coinbase Wallet / any window.ethereum), discovered via
4306
+ // EIP-6963 (multi-wallet, collision-free) with a window.ethereum fallback. It
4307
+ // needs NO viem/ethers and NO React — EIP-1193 request() + hex strings suffice.
4308
+ // EIP-6963 is announcement-based: wallets add an `eip6963:requestProvider`
4309
+ // listener and synchronously dispatch `eip6963:announceProvider` in response. We
4310
+ // keep a persistent collector so announcements (including late ones) are
4311
+ // captured, and re-request on demand.
4312
+ const announcedProviders = [];
4313
+ let announceListenerAttached = false;
4314
+ function attachAnnounceListener() {
4315
+ if (announceListenerAttached || typeof window === 'undefined')
4316
+ return;
4317
+ announceListenerAttached = true;
4318
+ window.addEventListener('eip6963:announceProvider', (event) => {
4319
+ const detail = event === null || event === void 0 ? void 0 : event.detail;
4320
+ if (detail &&
4321
+ detail.provider &&
4322
+ typeof detail.provider.request === 'function' &&
4323
+ !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); })) {
4324
+ announcedProviders.push(detail);
4325
+ }
4326
+ });
4327
+ }
4328
+ /**
4329
+ * Request + collect EIP-6963 providers. Dispatches `eip6963:requestProvider`
4330
+ * (synchronous — already-loaded wallets announce in the same tick) and returns
4331
+ * every wallet announced so far. Kept synchronous so it works inside a user
4332
+ * gesture and can be eagerly exported from the SDK entry.
4333
+ */
4334
+ function requestEip6963Providers() {
4335
+ if (typeof window === 'undefined')
4336
+ return [];
4337
+ attachAnnounceListener();
4338
+ try {
4339
+ window.dispatchEvent(new Event('eip6963:requestProvider'));
4340
+ }
4341
+ catch (_a) {
4342
+ /* older browsers without Event constructor — fall through to window.ethereum */
4343
+ }
4344
+ return announcedProviders.slice();
4345
+ }
4346
+ /**
4347
+ * Default EVM provider discovery: EIP-6963 first (multi-wallet, collision-free),
4348
+ * then legacy `window.ethereum`. Returns null when no injected wallet is present.
4349
+ */
4350
+ function defaultInjectedEvmProvider() {
4351
+ if (typeof window === 'undefined')
4352
+ return null;
4353
+ const details = requestEip6963Providers();
4354
+ if (details.length > 0)
4355
+ return details[0].provider;
4356
+ const eth = window.ethereum;
4357
+ if (eth && typeof eth.request === 'function')
4358
+ return eth;
4359
+ return null;
4360
+ }
4361
+
4362
+ const STORED_AUTH_METHOD_KEY$2 = 'bounded_last_auth_method';
4363
+ // Must equal the authMethod the registry (auth/index.ts) sets as currentAuthMethod,
4364
+ // so clearIncompatibleSession() keeps (not wipes) this session on the next init().
4365
+ const INJECTED_EVM_AUTH_METHOD = 'evm-wallet';
4366
+ // The /session issuer's discriminator for the SIWE (EIP-4361 secp256k1) exchange.
4367
+ const SIWE_SESSION_METHOD = 'siwe';
4368
+ const NO_WALLET_ERR = 'No injected EVM wallet found. Install a wallet like MetaMask (metamask.io) or Rabby and try again, ' +
4369
+ 'or pass config.evmWalletConfig.getProvider to point at your wallet.';
4370
+ const NO_SOL_TX_ERR = 'EVM wallet login signs+submits transactions in one step (eth_sendTransaction) and has no Solana ' +
4371
+ 'transaction surface. Use an onchain WRITE (setMany) — the worker returns a pre-built EVM tx that ' +
4372
+ 'runTransaction submits — instead of signTransaction/signAndSubmitTransaction.';
4373
+ // Bounded polling for the tx receipt: ~60s at 2s cadence (L2 blocks are seconds).
4374
+ const RECEIPT_POLL_ATTEMPTS = 30;
4375
+ const RECEIPT_POLL_INTERVAL_MS = 2000;
4376
+ function normalizeConfig(config) {
4377
+ var _a;
4378
+ if (config.chainId !== undefined && (!Number.isSafeInteger(config.chainId) || config.chainId <= 0)) {
4379
+ throw new Error('EVM wallet chainId must be a positive safe integer');
4380
+ }
4381
+ let runtimeAddress;
4382
+ if (config.runtimeAddress !== undefined) {
4383
+ runtimeAddress = (_a = core.normalizeEvmAddress(config.runtimeAddress)) !== null && _a !== void 0 ? _a : undefined;
4384
+ if (!runtimeAddress)
4385
+ throw new Error('EVM wallet runtimeAddress is invalid');
4386
+ if (config.chainId === undefined)
4387
+ throw new Error('EVM wallet runtimeAddress requires an explicit chainId');
4388
+ }
4389
+ let runtimeAddresses;
4390
+ if (config.runtimeAddresses !== undefined) {
4391
+ runtimeAddresses = {};
4392
+ for (const [rawChainId, rawAddress] of Object.entries(config.runtimeAddresses)) {
4393
+ const chainId = Number(rawChainId);
4394
+ const address = core.normalizeEvmAddress(rawAddress);
4395
+ if (!Number.isSafeInteger(chainId) || chainId <= 0 || String(chainId) !== rawChainId || !address) {
4396
+ throw new Error(`Invalid EVM runtime allowlist entry for chain ${rawChainId}`);
4397
+ }
4398
+ runtimeAddresses[rawChainId] = address;
4399
+ }
4400
+ }
4401
+ return Object.assign(Object.assign({}, config), { runtimeAddress, runtimeAddresses });
4402
+ }
4403
+ class InjectedEvmWalletProvider {
4404
+ constructor(config = {}) {
4405
+ this.authenticatedAddress = null;
4406
+ if (typeof window === 'undefined') {
4407
+ throw new Error('InjectedEvmWalletProvider can only be instantiated in a browser environment');
4408
+ }
4409
+ const normalized = normalizeConfig(config);
4410
+ // Singleton so the SDK reuses one instance (mirrors the other providers).
4411
+ if (InjectedEvmWalletProvider.instance) {
4412
+ InjectedEvmWalletProvider.instance.config = normalized;
4413
+ InjectedEvmWalletProvider.instance.authenticatedAddress = null;
4414
+ return InjectedEvmWalletProvider.instance;
4415
+ }
4416
+ this.config = normalized;
4417
+ InjectedEvmWalletProvider.instance = this;
4418
+ }
4419
+ // @user.address (the Solana wallet) is null for an EVM-wallet login. User.address
4420
+ // is typed `string` for legacy reasons — email logins cast the same null the same
4421
+ // way (email-auth-provider.ts) — so the null is cast here in one place.
4422
+ evmUser(address) {
4423
+ return { id: address, address: null, evmAddress: address, provider: this };
4424
+ }
4425
+ resolveProvider() {
4426
+ var _a;
4427
+ const provider = (_a = (this.config.getProvider ? this.config.getProvider() : null)) !== null && _a !== void 0 ? _a : defaultInjectedEvmProvider();
4428
+ if (!provider)
4429
+ throw new Error(NO_WALLET_ERR);
4430
+ return provider;
4431
+ }
4432
+ /** Connect the injected wallet and return its canonical lowercase EVM address. */
4433
+ async connectAddress(provider) {
4434
+ const accounts = await provider.request({ method: 'eth_requestAccounts' });
4435
+ const raw = Array.isArray(accounts) ? accounts[0] : undefined;
4436
+ const address = core.normalizeEvmAddress(raw);
4437
+ if (!address)
4438
+ throw new Error('Wallet did not return a valid EVM address on connect');
4439
+ return address;
4440
+ }
4441
+ /** Current chain id the wallet is connected to (EIP-155 number), or null. */
4442
+ async currentChainId(provider) {
4443
+ try {
4444
+ const hex = await provider.request({ method: 'eth_chainId' });
4445
+ if (typeof hex !== 'string' || !/^0x[0-9a-fA-F]+$/.test(hex))
4446
+ return null;
4447
+ const n = Number(BigInt(hex));
4448
+ return Number.isSafeInteger(n) && n > 0 ? n : null;
4449
+ }
4450
+ catch (_a) {
4451
+ return null;
4452
+ }
4453
+ }
4454
+ async login() {
4455
+ var _a;
4456
+ setAuthLoading(true);
4457
+ try {
4458
+ const provider = this.resolveProvider();
4459
+ const address = await this.connectAddress(provider);
4460
+ // Reuse a still-valid session for THIS wallet.
4461
+ const existing = await core.getActiveSessionManager().getSession();
4462
+ if (existing && existing.address === address) {
4463
+ const user = this.evmUser(address);
4464
+ this.authenticatedAddress = address;
4465
+ setCurrentUser(user);
4466
+ this.markAuthMethod();
4467
+ return user;
4468
+ }
4469
+ // SIWE: nonce -> canonical EIP-4361 prompt -> the wallet personal_sign's it.
4470
+ const nonce = await core.genAuthNonce();
4471
+ const appId = (await core.getConfig()).appId;
4472
+ const chainId = (_a = this.config.chainId) !== null && _a !== void 0 ? _a : await this.currentChainId(provider);
4473
+ if (chainId === null)
4474
+ throw new Error('Could not verify the EVM wallet chain for SIWE login');
4475
+ const message = core.genSiweMessage(address, nonce, appId, this.resolveDomain(), this.resolveUri(), { chainId });
4476
+ // personal_sign(message, address) -> 0x r‖s‖v hex (the shape the
4477
+ // bounded-auth verifier's recoverSiweSigner consumes). The raw UTF-8
4478
+ // message is signed under the EIP-191 envelope the verifier hashes.
4479
+ const signature = await provider.request({
4480
+ method: 'personal_sign',
4481
+ params: [message, address],
4482
+ });
4483
+ const result = await core.createSessionWithSignature(address, message, signature, SIWE_SESSION_METHOD);
4484
+ await core.getActiveSessionManager().storeSession(address, result.accessToken, result.idToken, result.refreshToken);
4485
+ this.markAuthMethod();
4486
+ const user = this.evmUser(address);
4487
+ this.authenticatedAddress = address;
4488
+ setCurrentUser(user);
4489
+ return user;
4490
+ }
4491
+ finally {
4492
+ setAuthLoading(false);
4493
+ }
4494
+ }
4495
+ resolveDomain() {
4496
+ const actual = window.location.host.toLowerCase();
4497
+ if (this.config.domain && this.config.domain.toLowerCase() !== actual) {
4498
+ throw new Error('SIWE domain override must match the current browser origin');
4499
+ }
4500
+ return actual;
4501
+ }
4502
+ resolveUri() {
4503
+ const actual = window.location.origin.toLowerCase();
4504
+ if (this.config.uri) {
4505
+ let configured;
4506
+ try {
4507
+ configured = new URL(this.config.uri).origin.toLowerCase();
4508
+ }
4509
+ catch (_a) {
4510
+ throw new Error('SIWE URI override must be an absolute URL');
4511
+ }
4512
+ if (configured !== actual)
4513
+ throw new Error('SIWE URI override must match the current browser origin');
4514
+ }
4515
+ return actual;
4516
+ }
4517
+ markAuthMethod() {
4518
+ try {
4519
+ getPlatform().storage.setItem(STORED_AUTH_METHOD_KEY$2, INJECTED_EVM_AUTH_METHOD);
4520
+ }
4521
+ catch ( /* no storage */_a) { /* no storage */ }
4522
+ }
4523
+ async restoreSession() {
4524
+ const session = await core.getActiveSessionManager().getSession();
4525
+ if (!session)
4526
+ return null;
4527
+ // An EVM-wallet session stores the EVM address as its address; @user.address
4528
+ // (the Solana wallet) is null for this login.
4529
+ const address = core.normalizeEvmAddress(session.address);
4530
+ if (!address) {
4531
+ core.getActiveSessionManager().clearSession();
4532
+ return null;
4533
+ }
4534
+ this.authenticatedAddress = address;
4535
+ const user = this.evmUser(address);
4536
+ setCurrentUser(user);
4537
+ return user;
4538
+ }
4539
+ async logout() {
4540
+ // EIP-1193 has no standard disconnect; clearing the Bounded session is the
4541
+ // logout. (wallet_revokePermissions is non-standard/opt-in — skip it.)
4542
+ core.getActiveSessionManager().clearSession();
4543
+ this.authenticatedAddress = null;
4544
+ setCurrentUser(null);
4545
+ }
4546
+ // --- Signing surface -------------------------------------------------------
4547
+ /** App-facing message signing: EIP-191 personal_sign, returns 0x r‖s‖v hex. */
4548
+ async signMessage(message) {
4549
+ const provider = this.resolveProvider();
4550
+ const address = await this.connectAddress(provider);
4551
+ if (!this.authenticatedAddress || address !== this.authenticatedAddress) {
4552
+ throw new Error('The connected EVM wallet account changed after login. Sign in again before signing.');
4553
+ }
4554
+ return provider.request({ method: 'personal_sign', params: [message, address] });
4555
+ }
4556
+ // Solana-typed methods are structurally unsupported on an EVM wallet — the
4557
+ // EVM onchain write goes through runTransaction (eth_sendTransaction).
4558
+ async signTransaction(_transaction) {
4559
+ throw new Error(NO_SOL_TX_ERR);
4560
+ }
4561
+ async signAndSubmitTransaction(_transaction, _feePayer) {
4562
+ throw new Error(NO_SOL_TX_ERR);
4563
+ }
4564
+ /**
4565
+ * Onchain write path: submit the worker's PRE-BUILT EIP-1559 tx via
4566
+ * eth_sendTransaction (the injected wallet signs + submits in one step), then
4567
+ * poll for the receipt. The EVM branch of operations.ts's 202 dispatch calls
4568
+ * this with the pre-built payload in the EVM slot and the Solana slot undefined.
4569
+ */
4570
+ async runTransaction(evmTransactionData, solTransactionData, options) {
4571
+ var _a, _b, _c;
4572
+ const evmTx = evmTransactionData;
4573
+ if (evmTx && solTransactionData) {
4574
+ throw new Error('A transaction cannot target EVM and Solana at the same time.');
4575
+ }
4576
+ if (!evmTx || !core.normalizeEvmAddress(evmTx.to) || typeof evmTx.data !== 'string' || !/^0x(?:[0-9a-fA-F]{2})+$/.test(evmTx.data)) {
4577
+ throw new Error('EVM transaction data (pre-built { to, data, chainId }) is required for an EVM onchain write');
4578
+ }
4579
+ // Exact decode, rather than a four-byte prefix check: permits the
4580
+ // ordinary and attested document-write entrypoints while rejecting
4581
+ // malformed/trailing calldata before the wallet sees a signing prompt.
4582
+ core.assertCanonicalBoundedRuntimeWriteCalldata(evmTx.data);
4583
+ if (!Number.isSafeInteger(evmTx.chainId) || evmTx.chainId <= 0) {
4584
+ throw new Error('EVM transaction chainId is required and must be a positive safe integer');
4585
+ }
4586
+ const chainId = evmTx.chainId;
4587
+ const trustedRuntime = (_b = (_a = this.config.runtimeAddresses) === null || _a === void 0 ? void 0 : _a[String(chainId)]) !== null && _b !== void 0 ? _b : (this.config.chainId === chainId ? this.config.runtimeAddress : undefined);
4588
+ if (!trustedRuntime)
4589
+ throw new Error(`No trusted BoundedRuntime address configured for EVM chain ${chainId}`);
4590
+ if (core.normalizeEvmAddress(evmTx.to) !== trustedRuntime) {
4591
+ throw new Error('EVM transaction target is not the configured BoundedRuntime');
4592
+ }
4593
+ if (evmTx.nonce !== undefined) {
4594
+ throw new Error('Server-supplied EVM nonces are not accepted');
4595
+ }
4596
+ try {
4597
+ if (BigInt((_c = evmTx.value) !== null && _c !== void 0 ? _c : '0') !== BigInt(0)) {
4598
+ throw new Error('BoundedRuntime.setDocuments cannot transfer native value');
4599
+ }
4600
+ }
4601
+ catch (error) {
4602
+ if (error instanceof Error && error.message.includes('cannot transfer'))
4603
+ throw error;
4604
+ throw new Error('Invalid EVM transaction value');
4605
+ }
4606
+ if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
4607
+ // Injected EVM wallets sign+submit atomically; eth_signTransaction is not
4608
+ // broadly supported (MetaMask removed it), so we cannot return a signed-
4609
+ // but-unsubmitted tx here. Fail clearly instead of silently submitting.
4610
+ throw new Error('shouldSubmitTx:false is unsupported for injected EVM wallets (they sign and submit atomically).');
4611
+ }
4612
+ const provider = this.resolveProvider();
4613
+ const from = await this.connectAddress(provider);
4614
+ if (!this.authenticatedAddress || from !== this.authenticatedAddress) {
4615
+ throw new Error('The connected EVM wallet account changed after login. Sign in again before submitting this write.');
4616
+ }
4617
+ // Chain-switch guard: the pre-built tx names the chain it MUST execute on.
4618
+ if (typeof evmTx.chainId === 'number') {
4619
+ const current = await this.currentChainId(provider);
4620
+ if (current === null)
4621
+ throw new Error('Could not verify the EVM wallet chain; refusing to submit the transaction.');
4622
+ if (current !== evmTx.chainId) {
4623
+ const targetHex = '0x' + evmTx.chainId.toString(16);
4624
+ try {
4625
+ await provider.request({
4626
+ method: 'wallet_switchEthereumChain',
4627
+ params: [{ chainId: targetHex }],
4628
+ });
4629
+ }
4630
+ catch (err) {
4631
+ throw new Error(`EVM wallet is on chain ${current} but this write targets chain ${evmTx.chainId}, ` +
4632
+ `and the chain switch was rejected or failed${(err === null || err === void 0 ? void 0 : err.message) ? `: ${err.message}` : ''}. ` +
4633
+ `Switch your wallet to chain ${evmTx.chainId} and retry.`);
4634
+ }
4635
+ const switched = await this.currentChainId(provider);
4636
+ if (switched !== evmTx.chainId) {
4637
+ throw new Error(`EVM wallet did not switch to required chain ${evmTx.chainId}; refusing to submit.`);
4638
+ }
4639
+ }
4640
+ }
4641
+ const txParams = { from, to: core.normalizeEvmAddress(evmTx.to), data: evmTx.data.toLowerCase() };
4642
+ txParams.value = '0x0';
4643
+ // Gas, fee and nonce hints come from the server and are not part of the
4644
+ // governed action. Deliberately omit them: the wallet estimates locally,
4645
+ // preventing a compromised response from forcing an abusive fee/nonce.
4646
+ const txHash = await provider.request({
4647
+ method: 'eth_sendTransaction',
4648
+ params: [txParams],
4649
+ });
4650
+ if (typeof txHash !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(txHash)) {
4651
+ throw new Error('EVM wallet returned an invalid transaction hash');
4652
+ }
4653
+ const receipt = await this.waitForReceipt(provider, txHash);
4654
+ if (!receipt || typeof receipt.status !== 'string' || !/^0x[0-9a-fA-F]+$/.test(receipt.status)) {
4655
+ throw new Error(`EVM transaction ${txHash} returned an invalid receipt status`);
4656
+ }
4657
+ if (BigInt(receipt.status) !== BigInt(1)) {
4658
+ throw new Error(`EVM transaction ${txHash} reverted on-chain`);
4659
+ }
4660
+ if (typeof receipt.blockNumber !== 'string' || !/^0x[0-9a-fA-F]+$/.test(receipt.blockNumber)) {
4661
+ throw new Error(`EVM transaction ${txHash} returned an invalid block number`);
4662
+ }
4663
+ const blockNumber = BigInt(receipt.blockNumber);
4664
+ if (blockNumber > BigInt(Number.MAX_SAFE_INTEGER))
4665
+ throw new Error('EVM receipt block number exceeds the SDK safe-integer range');
4666
+ if (typeof receipt.gasUsed !== 'string' || !/^0x[0-9a-fA-F]+$/.test(receipt.gasUsed)) {
4667
+ throw new Error(`EVM transaction ${txHash} returned invalid gas usage`);
4668
+ }
4669
+ return {
4670
+ transactionSignature: txHash,
4671
+ blockNumber: Number(blockNumber),
4672
+ gasUsed: BigInt(receipt.gasUsed).toString(),
4673
+ data: receipt,
4674
+ };
4675
+ }
4676
+ /** Poll eth_getTransactionReceipt until it lands (bounded retries) or throw. */
4677
+ async waitForReceipt(provider, txHash) {
4678
+ for (let attempt = 0; attempt < RECEIPT_POLL_ATTEMPTS; attempt++) {
4679
+ const receipt = await provider.request({
4680
+ method: 'eth_getTransactionReceipt',
4681
+ params: [txHash],
4682
+ });
4683
+ if (receipt)
4684
+ return receipt;
4685
+ await new Promise((r) => setTimeout(r, RECEIPT_POLL_INTERVAL_MS));
4686
+ }
4687
+ throw new Error(`EVM transaction ${txHash} was submitted but no receipt confirmed within ` +
4688
+ `${(RECEIPT_POLL_ATTEMPTS * RECEIPT_POLL_INTERVAL_MS) / 1000}s. It may still land; check the explorer.`);
4689
+ }
4690
+ async getNativeMethods() {
4691
+ return this.resolveProvider();
4692
+ }
4693
+ }
4694
+ InjectedEvmWalletProvider.instance = null;
4695
+
4229
4696
  // Same message the email provider uses when a hosted (OIDC) login has no
4230
4697
  // embedded wallet — enable `auth.wallets` in policy to get one.
4231
4698
  const OIDC_NO_WALLET = 'This login has no embedded wallet. Enable `"auth": { "wallets": true }` in ' +
@@ -4275,6 +4742,17 @@ const oidcProviderSingleton = {
4275
4742
  async signTransaction(_t) {
4276
4743
  throw new Error(hasEmbeddedWallet() ? EMBEDDED_WALLET_UNSUPPORTED : OIDC_NO_WALLET);
4277
4744
  },
4745
+ async runTransaction(evm, sol, options) {
4746
+ if (evm && sol)
4747
+ throw new Error('A transaction cannot target EVM and Solana at the same time.');
4748
+ if (!evm)
4749
+ throw new Error(OIDC_NO_WALLET);
4750
+ if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false)
4751
+ throw new Error('Embedded EVM wallets sign and submit atomically; shouldSubmitTx:false is unsupported.');
4752
+ if (!hasEmbeddedEvmWallet())
4753
+ throw new Error('This login has no embedded EVM wallet. Enable auth.wallets on an app with an EVM collection and sign in again.');
4754
+ return embeddedRunEvmTransaction(evm);
4755
+ },
4278
4756
  async signAndSubmitTransaction(transaction, _feePayer) {
4279
4757
  if (!hasEmbeddedWallet())
4280
4758
  throw new Error(OIDC_NO_WALLET);
@@ -4286,6 +4764,9 @@ function userFromIdToken(idToken) {
4286
4764
  const id = c['custom:userId'] || c.sub || c['custom:walletAddress'] || '';
4287
4765
  return {
4288
4766
  id, address: (c['custom:walletAddress'] || null),
4767
+ evmAddress: typeof c['custom:evmWalletAddress'] === 'string' && /^0x[0-9a-fA-F]{40}$/.test(c['custom:evmWalletAddress'])
4768
+ ? c['custom:evmWalletAddress'].toLowerCase()
4769
+ : null,
4289
4770
  email: (c.email || null), provider: oidcProviderSingleton,
4290
4771
  };
4291
4772
  }
@@ -4530,23 +5011,74 @@ async function completeLoginFromRedirect() {
4530
5011
  async function loginWithPopup(opts) {
4531
5012
  if (!hasDOM())
4532
5013
  throw new Error('loginWithPopup is web-only — on React Native use loginWithRedirect()');
4533
- const { url, pkce } = await buildAuthorize(opts);
4534
- sessionStorage.setItem(PKCE_STORE_KEY, JSON.stringify(pkce));
5014
+ // Open synchronously, before PKCE/config awaits consume the click's user-
5015
+ // activation window. Opening only after buildAuthorize() intermittently
5016
+ // left Chrome with a real named window stranded at about:blank (or blocked
5017
+ // it entirely), while callers waited forever for an OAuth message.
4535
5018
  const w = opts.width || 480, h = opts.height || 720;
4536
5019
  const left = window.screenX + (window.outerWidth - w) / 2;
4537
5020
  const top = window.screenY + (window.outerHeight - h) / 2;
4538
- const popup = window.open(url, 'bounded-oidc', `width=${w},height=${h},left=${left},top=${top}`);
5021
+ const popup = window.open('', 'bounded-oidc', `width=${w},height=${h},left=${left},top=${top}`);
4539
5022
  if (!popup)
4540
5023
  throw new Error('Popup blocked — use loginWithRedirect() instead');
4541
- // Use the RESOLVED redirect_uri (buildAuthorize defaulted it to the current page on web),
4542
- // not opts.redirectUri which may be undefined.
4543
- const expectedOrigin = new URL(pkce.redirectUri).origin;
5024
+ let authorization;
5025
+ try {
5026
+ authorization = await buildAuthorize(opts);
5027
+ }
5028
+ catch (error) {
5029
+ try {
5030
+ popup.close();
5031
+ }
5032
+ catch ( /* ignore */_a) { /* ignore */ }
5033
+ throw error;
5034
+ }
5035
+ const { url, pkce } = authorization;
5036
+ // Validate every remaining synchronous setup step before navigating. Both
5037
+ // URL parsing and sessionStorage can throw (malformed caller input, blocked
5038
+ // storage, quota/privacy mode); because the popup is already open to retain
5039
+ // user activation, close it on either failure instead of orphaning a blank
5040
+ // window with no listener or watchdog attached.
5041
+ let expectedOrigin;
5042
+ try {
5043
+ expectedOrigin = new URL(pkce.redirectUri).origin;
5044
+ sessionStorage.setItem(PKCE_STORE_KEY, JSON.stringify(pkce));
5045
+ }
5046
+ catch (error) {
5047
+ try {
5048
+ popup.close();
5049
+ }
5050
+ catch ( /* ignore */_b) { /* ignore */ }
5051
+ throw error;
5052
+ }
5053
+ try {
5054
+ popup.location.replace(url);
5055
+ }
5056
+ catch (_c) {
5057
+ try {
5058
+ popup.location.href = url;
5059
+ }
5060
+ catch (_d) {
5061
+ try {
5062
+ popup.close();
5063
+ }
5064
+ catch ( /* ignore */_e) { /* ignore */ }
5065
+ throw new Error('Popup failed to navigate — use loginWithRedirect() instead');
5066
+ }
5067
+ }
5068
+ // expectedOrigin came from the RESOLVED redirect_uri (buildAuthorize defaulted it to the
5069
+ // current page on web), not opts.redirectUri which may be undefined.
4544
5070
  setAuthLoading(true); // reflect "signing in…" while the popup is open
4545
5071
  try {
4546
5072
  return await new Promise((resolve, reject) => {
4547
5073
  let settled = false;
4548
5074
  let timer;
4549
- const cleanup = () => { settled = true; clearInterval(timer); window.removeEventListener('message', onMsg); };
5075
+ let navigationTimer;
5076
+ const cleanup = () => {
5077
+ settled = true;
5078
+ clearInterval(timer);
5079
+ clearTimeout(navigationTimer);
5080
+ window.removeEventListener('message', onMsg);
5081
+ };
4550
5082
  const onMsg = async (ev) => {
4551
5083
  if (ev.origin !== expectedOrigin)
4552
5084
  return; // only trust the redirect_uri origin
@@ -4574,6 +5106,27 @@ async function loginWithPopup(opts) {
4574
5106
  }
4575
5107
  };
4576
5108
  window.addEventListener('message', onMsg);
5109
+ // Some browser/extension combinations can return a real popup handle but
5110
+ // strand the window at about:blank instead of navigating to the hosted
5111
+ // authorize URL. The old code then waited forever because the popup was
5112
+ // open and no message could ever arrive. Once the popup becomes
5113
+ // cross-origin, reading location throws — that is positive evidence that
5114
+ // navigation succeeded, so only a still-readable about:blank is rejected.
5115
+ navigationTimer = setTimeout(() => {
5116
+ if (settled || popup.closed)
5117
+ return;
5118
+ try {
5119
+ if (popup.location.href === 'about:blank') {
5120
+ cleanup();
5121
+ try {
5122
+ popup.close();
5123
+ }
5124
+ catch ( /* ignore */_a) { /* ignore */ }
5125
+ reject(new Error('Popup stalled at about:blank — use loginWithRedirect() instead'));
5126
+ }
5127
+ }
5128
+ catch ( /* cross-origin hosted auth loaded normally */_b) { /* cross-origin hosted auth loaded normally */ }
5129
+ }, 4000);
4577
5130
  // The popup posts its code and then closes ITSELF, so a naive "popup.closed -> reject"
4578
5131
  // races the just-posted message and would report a spurious "Login window closed" on a
4579
5132
  // SUCCESSFUL login. When we see it closed, wait a beat for that pending message to settle
@@ -4717,7 +5270,7 @@ function stableConfigValue(value, seen = new WeakSet()) {
4717
5270
  return String(value);
4718
5271
  }
4719
5272
  function authProviderConfigKey(config) {
4720
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
5273
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
4721
5274
  return JSON.stringify({
4722
5275
  authMethod: (_a = config.authMethod) !== null && _a !== void 0 ? _a : null,
4723
5276
  chain: (_b = config.chain) !== null && _b !== void 0 ? _b : null,
@@ -4727,9 +5280,10 @@ function authProviderConfigKey(config) {
4727
5280
  phantomConfig: stableConfigValue((_e = config.phantomConfig) !== null && _e !== void 0 ? _e : null),
4728
5281
  walletLogin: stableConfigValue((_f = config.walletLogin) !== null && _f !== void 0 ? _f : null),
4729
5282
  injectedWalletConfig: stableConfigValue((_g = config.injectedWalletConfig) !== null && _g !== void 0 ? _g : null),
4730
- privyConfig: stableConfigValue((_h = config.privyConfig) !== null && _h !== void 0 ? _h : null),
4731
- mobileWalletConfig: stableConfigValue((_j = config.mobileWalletConfig) !== null && _j !== void 0 ? _j : null),
4732
- privyExpoProvider: objectIdentityKey((_k = config.privyExpoProvider) !== null && _k !== void 0 ? _k : null),
5283
+ evmWalletConfig: stableConfigValue((_h = config.evmWalletConfig) !== null && _h !== void 0 ? _h : null),
5284
+ privyConfig: stableConfigValue((_j = config.privyConfig) !== null && _j !== void 0 ? _j : null),
5285
+ mobileWalletConfig: stableConfigValue((_k = config.mobileWalletConfig) !== null && _k !== void 0 ? _k : null),
5286
+ privyExpoProvider: objectIdentityKey((_l = config.privyExpoProvider) !== null && _l !== void 0 ? _l : null),
4733
5287
  });
4734
5288
  }
4735
5289
  /**
@@ -4810,7 +5364,7 @@ function optionalProviderError(method) {
4810
5364
  `or install/import an explicit wallet-provider entry once your app opts into "${method}".`);
4811
5365
  }
4812
5366
  async function getAuthProvider(config) {
4813
- var _a;
5367
+ var _a, _b;
4814
5368
  const nextProviderConfigKey = config ? authProviderConfigKey(config) : null;
4815
5369
  if (currentAuthProvider && (!config || currentAuthProviderConfigKey === nextProviderConfigKey)) {
4816
5370
  return currentAuthProvider;
@@ -4834,7 +5388,7 @@ async function getAuthProvider(config) {
4834
5388
  // browser environment" deep in init(). The server build (`bounded-sh/server`)
4835
5389
  // never resolves these methods (it signs with a keypair), so this can't fire for
4836
5390
  // it — it only converts the cryptic browser-in-Node crash into a useful message.
4837
- const browserWalletMethods = ['phantom', 'wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'mobile-wallet-adapter', 'privy'];
5391
+ const browserWalletMethods = ['phantom', 'wallet', 'evm-wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'mobile-wallet-adapter', 'privy'];
4838
5392
  if (typeof window === 'undefined' && browserWalletMethods.includes(authMethod)) {
4839
5393
  throw new Error(`bounded-sh: '${authMethod}' auth requires a browser, but no \`window\` was found ` +
4840
5394
  `(you're likely running in Node). In server/Node code, import from 'bounded-sh/server' ` +
@@ -4869,6 +5423,18 @@ async function getAuthProvider(config) {
4869
5423
  currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
4870
5424
  break;
4871
5425
  }
5426
+ case "evm-wallet": {
5427
+ // First-class EVM WALLET LOGIN (BYO Ethereum wallet via SIWE). Slim
5428
+ // path: rides the EIP-1193 injected provider a browser wallet exposes
5429
+ // (MetaMask / Rabby / Coinbase Wallet / any window.ethereum), discovered
5430
+ // via EIP-6963. The user's REAL EVM wallet becomes @user.evmAddress;
5431
+ // login = SIWE (EIP-4361 personal_sign). No viem/ethers and no React.
5432
+ // Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
5433
+ // to point at a specific wallet or set chainId/domain.
5434
+ const evmWalletConfig = ((_b = config.evmWalletConfig) !== null && _b !== void 0 ? _b : {});
5435
+ currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
5436
+ break;
5437
+ }
4872
5438
  case "rainbowkit":
4873
5439
  console.warn("Rainbow Kit auth is not yet supported.");
4874
5440
  break;
@@ -5345,6 +5911,12 @@ function useQuery(path, options) {
5345
5911
  core.subscribe(path, Object.assign(Object.assign({}, options), { onData: (d) => {
5346
5912
  if (!active)
5347
5913
  return;
5914
+ // A reconnect can legitimately surface a transport error before the
5915
+ // socket re-authenticates and sends a new authorized snapshot. That
5916
+ // fresh snapshot is the recovery boundary: keep the error visible
5917
+ // until data arrives, then clear it so React does not remain stuck on
5918
+ // a failure page after realtime has recovered.
5919
+ setError(null);
5348
5920
  setData(d);
5349
5921
  setLoading(false);
5350
5922
  }, onError: (e) => {
@@ -5830,6 +6402,7 @@ exports.OffchainAuthProvider = OffchainAuthProvider;
5830
6402
  exports.PrivyExpoProvider = PrivyExpoProvider;
5831
6403
  exports.completeLoginFromRedirect = completeLoginFromRedirect;
5832
6404
  exports.completeLoginInPopup = completeLoginInPopup;
6405
+ exports.defaultInjectedEvmProvider = defaultInjectedEvmProvider;
5833
6406
  exports.defaultInjectedProvider = defaultInjectedProvider;
5834
6407
  exports.deserializeTransaction = deserializeTransaction;
5835
6408
  exports.getAuthLoading = getAuthLoading;
@@ -5845,6 +6418,7 @@ exports.loginWithRedirect = loginWithRedirect;
5845
6418
  exports.logout = logout;
5846
6419
  exports.onAuthLoadingChanged = onAuthLoadingChanged;
5847
6420
  exports.onAuthStateChanged = onAuthStateChanged;
6421
+ exports.requestEip6963Providers = requestEip6963Providers;
5848
6422
  exports.setPlatform = setPlatform;
5849
6423
  exports.signInAnonymously = signInAnonymously;
5850
6424
  exports.useAuth = useAuth;