@bounded-sh/client 0.0.19 → 0.0.21

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 (31) hide show
  1. package/README.md +2 -2
  2. package/dist/auth/providers/offchain-auth-provider.d.ts +2 -4
  3. package/dist/index.d.ts +0 -1
  4. package/dist/index.js +150 -214
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +151 -213
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/{index.native-DI_Xgv-n.js → index.native-DdKzAUjN.js} +154 -218
  9. package/dist/index.native-DdKzAUjN.js.map +1 -0
  10. package/dist/{index.native-DWI_i6-6.mjs → index.native-N3xLU862.mjs} +155 -217
  11. package/dist/index.native-N3xLU862.mjs.map +1 -0
  12. package/dist/index.native.d.ts +0 -1
  13. package/dist/index.native.js +1 -3
  14. package/dist/index.native.js.map +1 -1
  15. package/dist/index.native.mjs +1 -1
  16. package/dist/{phantom-wallet-provider-DDwgNMg_.mjs → phantom-wallet-provider-DcE4A2_e.mjs} +2 -2
  17. package/dist/{phantom-wallet-provider-DDwgNMg_.mjs.map → phantom-wallet-provider-DcE4A2_e.mjs.map} +1 -1
  18. package/dist/{phantom-wallet-provider-fyOrJZP6.js → phantom-wallet-provider-Dz9lQvNv.js} +2 -2
  19. package/dist/{phantom-wallet-provider-fyOrJZP6.js.map → phantom-wallet-provider-Dz9lQvNv.js.map} +1 -1
  20. package/dist/{privy-wallet-provider-BIr9lDS7.js → privy-wallet-provider-DUvjxNXK.js} +3 -3
  21. package/dist/{privy-wallet-provider-BIr9lDS7.js.map → privy-wallet-provider-DUvjxNXK.js.map} +1 -1
  22. package/dist/{privy-wallet-provider-D7VoQCYf.mjs → privy-wallet-provider-oG3o5vko.mjs} +3 -3
  23. package/dist/{privy-wallet-provider-D7VoQCYf.mjs.map → privy-wallet-provider-oG3o5vko.mjs.map} +1 -1
  24. package/dist/{solana-mobile-wallet-provider-Cush-URL.js → solana-mobile-wallet-provider-DdBoG6c2.js} +2 -2
  25. package/dist/{solana-mobile-wallet-provider-Cush-URL.js.map → solana-mobile-wallet-provider-DdBoG6c2.js.map} +1 -1
  26. package/dist/{solana-mobile-wallet-provider-DgcGxDoL.mjs → solana-mobile-wallet-provider-aS60_GZR.mjs} +2 -2
  27. package/dist/{solana-mobile-wallet-provider-DgcGxDoL.mjs.map → solana-mobile-wallet-provider-aS60_GZR.mjs.map} +1 -1
  28. package/package.json +2 -2
  29. package/dist/auth/providers/mock-auth-provider.d.ts +0 -49
  30. package/dist/index.native-DI_Xgv-n.js.map +0 -1
  31. package/dist/index.native-DWI_i6-6.mjs.map +0 -1
package/README.md CHANGED
@@ -66,13 +66,13 @@ yarn add @tarobase/js-sdk
66
66
 
67
67
 
68
68
 
69
- Before using the SDK, initialize it with your **Application ID**. You can obtain your `appId` by creating an application on the [Tarobase Console](https://console.tarobase.com). The console also allows you to configure your application's policies, including data storage preferences (on-chain or off-chain) and data schemas.
69
+ Before using the SDK, initialize it with your **Application ID** and the one auth method this app intends to use. You can obtain your `appId` by creating an application on the [Tarobase Console](https://console.tarobase.com). The console also allows you to configure your application's policies, including data storage preferences (on-chain or off-chain) and data schemas.
70
70
 
71
71
 
72
72
  ```typescript
73
73
  import { init } from '@tarobase/js-sdk';
74
74
 
75
- init({appId: 'YOUR_APP_ID' });
75
+ init({ appId: 'YOUR_APP_ID', authMethod: 'email' });
76
76
  ```
77
77
 
78
78
  ### Authentication
@@ -9,9 +9,8 @@ export interface OffchainAuthProviderConfig {
9
9
  /**
10
10
  * OffchainAuthProvider wraps a real auth provider (e.g., Phantom) for the poofnet environment.
11
11
  *
12
- * For signMessageMock, this shows a custom confirmation modal and then delegates
13
- * to the wrapped provider for a real detached signature over the exact offchain
14
- * transaction message.
12
+ * signMessage shows a custom confirmation modal and then delegates to the wrapped
13
+ * provider for a real detached signature over the exact offchain transaction message.
15
14
  */
16
15
  export declare class OffchainAuthProvider implements AuthProvider {
17
16
  private wrappedProvider;
@@ -31,7 +30,6 @@ export declare class OffchainAuthProvider implements AuthProvider {
31
30
  signAndSubmitTransaction(_transaction: Transaction | VersionedTransaction, _feePayer?: any): Promise<string>;
32
31
  getNativeMethods(): Promise<any>;
33
32
  signMessage(message: string): Promise<string>;
34
- signMessageMock(message: string): Promise<string>;
35
33
  private showUnsupportedTransactionModal;
36
34
  private showTransactionModal;
37
35
  private closeModal;
package/dist/index.d.ts CHANGED
@@ -16,7 +16,6 @@ export { getIdToken } from "./utils";
16
16
  export { setPlatform, getPlatform } from "./platform";
17
17
  export type { PlatformAdapter, StorageAdapter } from "./platform";
18
18
  export { PhantomWalletProvider, PhantomWalletConfig, PhantomProviderType, } from "./auth/providers/phantom-wallet-provider";
19
- export { MockAuthProvider, DEFAULT_TEST_ADDRESS, } from "./auth/providers/mock-auth-provider";
20
19
  export { OffchainAuthProvider, OffchainAuthProviderConfig, } from "./auth/providers/offchain-auth-provider";
21
20
  export { SolanaMobileWalletProvider, SolanaMobileWalletConfig, isMobileWalletAvailable, registerMobileWalletAdapter, } from "./auth/providers/solana-mobile-wallet-provider";
22
21
  export { PrivyWalletProvider } from "./auth/providers/privy-wallet-provider";
package/dist/index.js CHANGED
@@ -180,142 +180,11 @@ function detectAndroid() {
180
180
  return false;
181
181
  }
182
182
 
183
- // Default test wallet address (Solana devnet address)
184
- const DEFAULT_TEST_ADDRESS = 'HKbZbRR7jWWR5VRN8KFjvTCHEzJQgameYxKQxh2gPoof';
185
- // Session storage key to track if user explicitly called login()
186
- const EXPLICIT_LOGIN_KEY = 'mock-auth-explicit-login';
187
- /**
188
- * MockAuthProvider bypasses real wallet authentication for testing purposes.
189
- * Uses session storage to simulate logged-in user, with fallback to default test address.
190
- *
191
- * This is enabled by passing mockAuth: true to init()
192
- */
193
- class MockAuthProvider {
194
- /**
195
- * Mock login - reads user from session storage or uses default test address
196
- */
197
- async login() {
198
- let address = getPlatform().sessionStorage.getItem('test-user-address');
199
- if (!address) {
200
- address = DEFAULT_TEST_ADDRESS;
201
- // Store default address in session storage so it gets used in API calls
202
- getPlatform().sessionStorage.setItem('test-user-address', DEFAULT_TEST_ADDRESS);
203
- console.log('[MockAuth] Using default test address:', address);
204
- }
205
- // Mark that user explicitly called login() - allows restoreSession on refresh
206
- getPlatform().sessionStorage.setItem(EXPLICIT_LOGIN_KEY, 'true');
207
- console.log('[MockAuth] Mock login successful:', address);
208
- return {
209
- address,
210
- provider: this
211
- };
212
- }
213
- /**
214
- * Mock transaction - returns fake signature without actual blockchain interaction
215
- * The real transaction will be handled by the backend using test headers
216
- */
217
- async runTransaction(evmTransactionData, solTransactionData, options) {
218
- const address = getPlatform().sessionStorage.getItem('test-user-address') || DEFAULT_TEST_ADDRESS;
219
- // Generate a fake transaction signature
220
- const fakeSignature = `mock_tx_${Math.random().toString(36).substring(2, 15)}`;
221
- console.log('[MockAuth] Mock transaction executed:', {
222
- address,
223
- signature: fakeSignature,
224
- evmTx: evmTransactionData,
225
- solTx: solTransactionData
226
- });
227
- return {
228
- transactionSignature: fakeSignature,
229
- signedTransaction: fakeSignature,
230
- blockNumber: 0,
231
- gasUsed: '0'
232
- };
233
- }
234
- /**
235
- * Mock message signing
236
- */
237
- async signMessage(message) {
238
- const address = getPlatform().sessionStorage.getItem('test-user-address') || DEFAULT_TEST_ADDRESS;
239
- // Generate a fake signature
240
- const fakeSignature = `mock_sig_${Math.random().toString(36).substring(2, 15)}`;
241
- console.log('[MockAuth] Mock message signed:', {
242
- address,
243
- message,
244
- signature: fakeSignature
245
- });
246
- return fakeSignature;
247
- }
248
- async signMessageMock(message) {
249
- const address = getPlatform().sessionStorage.getItem('test-user-address') || DEFAULT_TEST_ADDRESS;
250
- const signature = `mock_sig_${Math.random().toString(36).substring(2, 15)}`;
251
- console.log('[MockAuth] Mock message signed:', {
252
- address,
253
- message,
254
- signature
255
- });
256
- return signature;
257
- }
258
- /**
259
- * Mock transaction signing - returns the transaction as-is (no actual signing)
260
- */
261
- async signTransaction(transaction) {
262
- console.log('[MockAuth] Mock transaction signing (no-op)');
263
- return transaction;
264
- }
265
- /**
266
- * Sign and submit transaction - not supported in mock environment.
267
- * See the real providers (PhantomWalletProvider, SolanaKeypairProvider)
268
- * for the full implementation with blockhash handling and feePayer support.
269
- */
270
- async signAndSubmitTransaction(_transaction, _feePayer) {
271
- throw new Error('signAndSubmitTransaction is not supported in the mock environment');
272
- }
273
- /**
274
- * Restore session - only restores if user previously called login() explicitly.
275
- * This prevents auto-login on first page load, but allows session persistence after login.
276
- */
277
- async restoreSession() {
278
- const explicitlyLoggedIn = getPlatform().sessionStorage.getItem(EXPLICIT_LOGIN_KEY);
279
- if (!explicitlyLoggedIn) {
280
- console.log('[MockAuth] No explicit login found. Call login() to authenticate.');
281
- return null;
282
- }
283
- const address = getPlatform().sessionStorage.getItem('test-user-address');
284
- if (!address) {
285
- console.log('[MockAuth] No previous session found');
286
- return null;
287
- }
288
- console.log('[MockAuth] Session restored:', address);
289
- return {
290
- address,
291
- provider: this
292
- };
293
- }
294
- /**
295
- * Mock logout - clears test user from session storage
296
- */
297
- async logout() {
298
- getPlatform().sessionStorage.removeItem('test-user-address');
299
- getPlatform().sessionStorage.removeItem('test-user-id');
300
- getPlatform().sessionStorage.removeItem(EXPLICIT_LOGIN_KEY);
301
- console.log('[MockAuth] Mock logout successful');
302
- }
303
- /**
304
- * Get native wallet methods (not needed for mock auth)
305
- */
306
- async getNativeMethods() {
307
- return {
308
- // Return empty object - no native methods needed for mock auth
309
- };
310
- }
311
- }
312
-
313
183
  /**
314
184
  * OffchainAuthProvider wraps a real auth provider (e.g., Phantom) for the poofnet environment.
315
185
  *
316
- * For signMessageMock, this shows a custom confirmation modal and then delegates
317
- * to the wrapped provider for a real detached signature over the exact offchain
318
- * transaction message.
186
+ * signMessage shows a custom confirmation modal and then delegates to the wrapped
187
+ * provider for a real detached signature over the exact offchain transaction message.
319
188
  */
320
189
  class OffchainAuthProvider {
321
190
  constructor(wrappedProvider, config = {}) {
@@ -366,13 +235,7 @@ class OffchainAuthProvider {
366
235
  }
367
236
  // ============ signMessage delegates to wrapped provider ============
368
237
  async signMessage(message) {
369
- // Delegate to wrapped provider for real wallet signing
370
- return this.wrappedProvider.signMessage(message);
371
- }
372
- // ============ Mock signMessage with Custom Modal for Offchain Transactions ============
373
- async signMessageMock(message) {
374
238
  var _a, _b, _c, _d, _e, _f;
375
- // Callback: signing started
376
239
  (_b = (_a = this.config).onSigningStart) === null || _b === void 0 ? void 0 : _b.call(_a);
377
240
  try {
378
241
  // On RN (no DOM), auto-confirm — there's no modal to show.
@@ -389,7 +252,6 @@ class OffchainAuthProvider {
389
252
  return signature;
390
253
  }
391
254
  catch (error) {
392
- // Callback: signing error
393
255
  (_f = (_e = this.config).onSigningError) === null || _f === void 0 ? void 0 : _f.call(_e, error);
394
256
  throw error;
395
257
  }
@@ -4127,13 +3989,33 @@ function createEmailModalTree() {
4127
3989
  close.type = 'button';
4128
3990
  close.textContent = '×';
4129
3991
  card.appendChild(close);
3992
+ // Brand row — the real Bounded mark (same geometry as bounded.sh) + wordmark.
4130
3993
  const brand = document.createElement('div');
4131
3994
  brand.className = 'ba-brand';
4132
- const dot = document.createElement('span');
4133
- dot.className = 'ba-dot';
4134
- brand.appendChild(dot);
4135
- brand.appendChild(document.createTextNode(' Sign in'));
3995
+ const mark = document.createElement('span');
3996
+ mark.className = 'ba-mark';
3997
+ mark.setAttribute('aria-hidden', 'true');
3998
+ mark.innerHTML =
3999
+ '<svg width="24" height="24" viewBox="0 0 32 32" fill="none">' +
4000
+ '<path class="ba-c ba-c1" d="M16 5 H5 V16"/>' +
4001
+ '<path class="ba-c ba-c2" d="M16 5 H27 V16"/>' +
4002
+ '<path class="ba-c ba-c3" d="M5 16 V27 H16"/>' +
4003
+ '<path class="ba-c ba-c4" d="M27 16 V27 H16"/>' +
4004
+ '</svg>';
4005
+ brand.appendChild(mark);
4006
+ const word = document.createElement('span');
4007
+ word.className = 'ba-word';
4008
+ word.textContent = 'bounded';
4009
+ brand.appendChild(word);
4136
4010
  card.appendChild(brand);
4011
+ const title = document.createElement('h1');
4012
+ title.className = 'ba-title';
4013
+ title.textContent = 'Sign in';
4014
+ card.appendChild(title);
4015
+ const sub = document.createElement('p');
4016
+ sub.className = 'ba-subtitle';
4017
+ sub.textContent = 'Continue with your email — no wallet needed.';
4018
+ card.appendChild(sub);
4137
4019
  const emailStep = document.createElement('div');
4138
4020
  emailStep.id = 'ba-email-step';
4139
4021
  card.appendChild(emailStep);
@@ -4154,7 +4036,7 @@ function createEmailModalTree() {
4154
4036
  emailButton.id = 'ba-email-btn';
4155
4037
  emailButton.className = 'ba-btn';
4156
4038
  emailButton.type = 'button';
4157
- emailButton.textContent = 'Continue';
4039
+ emailButton.textContent = 'Continue with email';
4158
4040
  emailStep.appendChild(emailButton);
4159
4041
  const otpStep = document.createElement('div');
4160
4042
  otpStep.id = 'ba-otp-step';
@@ -4199,37 +4081,67 @@ function createEmailModalTree() {
4199
4081
  card.appendChild(foot);
4200
4082
  return root;
4201
4083
  }
4084
+ // Design language matches the hosted Bounded login (auth.bounded.sh) and bounded.sh:
4085
+ // dark editorial panel, green accent, Schibsted Grotesk / Newsreader / JetBrains Mono,
4086
+ // the Bounded mark drawing itself in. Fonts load best-effort (scoped @import); every
4087
+ // rule has a system fallback so the modal looks right even if Google Fonts is blocked.
4088
+ // All selectors are scoped under #bounded-auth-modal so we never leak into the host page.
4202
4089
  const MODAL_CSS = `
4203
- #bounded-auth-modal .ba-overlay{position:fixed;inset:0;background:rgba(8,10,18,.62);backdrop-filter:blur(4px);
4090
+ @import url('https://fonts.googleapis.com/css2?family=Newsreader:opsz,wght@6..72,400;6..72,500&family=Schibsted+Grotesk:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap');
4091
+ #bounded-auth-modal{--ba-bg:#0a0a0b;--ba-panel:#0e0f11;--ba-inset:#060607;--ba-raise:#131416;
4092
+ --ba-line:rgba(232,230,222,.08);--ba-line-strong:rgba(232,230,222,.16);
4093
+ --ba-text:#e8e6de;--ba-dim:#9b9991;--ba-faint:#85837c;--ba-green:#58c98f;
4094
+ --ba-green-bg:rgba(88,201,143,.09);--ba-green-line:rgba(88,201,143,.28);--ba-red:#ec8488;
4095
+ --ba-body:'Schibsted Grotesk',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
4096
+ --ba-display:'Newsreader','Iowan Old Style',Georgia,serif;
4097
+ --ba-mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;}
4098
+ #bounded-auth-modal .ba-overlay{position:fixed;inset:0;background:rgba(6,6,7,.66);backdrop-filter:blur(4px);
4204
4099
  display:flex;align-items:center;justify-content:center;z-index:2147483000;opacity:1;transition:opacity .16s ease;
4205
- font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;padding:16px;}
4100
+ font-family:var(--ba-body);padding:16px;}
4206
4101
  #bounded-auth-modal .ba-overlay.out{opacity:0;}
4207
- #bounded-auth-modal .ba-card{width:100%;max-width:380px;background:#0f1117;color:#f4f5f7;border:1px solid #232838;
4208
- border-radius:18px;padding:24px 22px 18px;box-shadow:0 24px 70px rgba(0,0,0,.5);position:relative;
4209
- animation:ba-in .18s ease;}
4210
- @keyframes ba-in{from{transform:translateY(10px);opacity:.6}to{transform:translateY(0);opacity:1}}
4211
- #bounded-auth-modal .ba-x{position:absolute;top:12px;right:12px;width:30px;height:30px;border:none;background:#1a1e2b;
4212
- color:#9aa3b2;border-radius:9px;font-size:20px;line-height:1;cursor:pointer;}
4213
- #bounded-auth-modal .ba-x:hover{background:#222838;color:#fff;}
4214
- #bounded-auth-modal .ba-brand{display:flex;align-items:center;gap:8px;font-weight:600;font-size:15px;margin:0 0 18px;}
4215
- #bounded-auth-modal .ba-dot{width:10px;height:10px;border-radius:50%;background:linear-gradient(135deg,#8b5cf6,#22d3ee);}
4216
- #bounded-auth-modal .ba-label{display:block;font-size:13px;color:#aab2c0;margin:0 0 8px;}
4217
- #bounded-auth-modal .ba-em{color:#fff;font-weight:600;}
4218
- #bounded-auth-modal .ba-input{width:100%;box-sizing:border-box;background:#171b26;border:1px solid #2a3040;color:#fff;
4219
- border-radius:11px;padding:13px 14px;font-size:16px;outline:none;transition:border-color .12s;}
4220
- #bounded-auth-modal .ba-input:focus{border-color:#7c5cff;}
4221
- #bounded-auth-modal .ba-code{letter-spacing:8px;text-align:center;font-size:22px;font-variant-numeric:tabular-nums;}
4222
- #bounded-auth-modal .ba-btn{width:100%;margin-top:12px;background:linear-gradient(135deg,#7c5cff,#5b8cff);color:#fff;
4223
- border:none;border-radius:11px;padding:13px;font-size:15px;font-weight:600;cursor:pointer;transition:filter .12s;}
4224
- #bounded-auth-modal .ba-btn:hover{filter:brightness(1.08);}
4225
- #bounded-auth-modal .ba-btn:disabled{opacity:.6;cursor:default;}
4226
- #bounded-auth-modal .ba-link{width:100%;margin-top:10px;background:none;border:none;color:#8aa0c6;font-size:13px;cursor:pointer;}
4227
- #bounded-auth-modal .ba-link:hover{color:#bcd0f0;}
4228
- #bounded-auth-modal .ba-msg{min-height:18px;margin-top:10px;font-size:13px;color:#8aa0c6;text-align:center;}
4229
- #bounded-auth-modal .ba-msg.err{color:#ff8a8a;}
4230
- #bounded-auth-modal .ba-foot{margin-top:14px;text-align:center;font-size:11px;color:#5a6273;}
4102
+ #bounded-auth-modal *{box-sizing:border-box;}
4103
+ #bounded-auth-modal .ba-card{width:100%;max-width:372px;background:var(--ba-panel);color:var(--ba-text);
4104
+ border:1px solid var(--ba-line);border-radius:12px;padding:28px 28px 22px;position:relative;
4105
+ box-shadow:0 1px 0 rgba(232,230,222,.03) inset,0 30px 80px -40px rgba(0,0,0,.8);animation:ba-in .18s ease;}
4106
+ @keyframes ba-in{from{transform:translateY(8px);opacity:.5}to{transform:translateY(0);opacity:1}}
4107
+ #bounded-auth-modal .ba-x{position:absolute;top:14px;right:14px;width:28px;height:28px;border:1px solid var(--ba-line);
4108
+ background:var(--ba-raise);color:var(--ba-faint);border-radius:7px;font-size:18px;line-height:1;cursor:pointer;
4109
+ transition:color .15s,border-color .15s;}
4110
+ #bounded-auth-modal .ba-x:hover{color:var(--ba-text);border-color:var(--ba-faint);}
4111
+ #bounded-auth-modal .ba-brand{display:flex;align-items:center;gap:10px;margin:0 0 24px;}
4112
+ #bounded-auth-modal .ba-mark{display:flex;color:var(--ba-text);}
4113
+ #bounded-auth-modal .ba-mark svg{overflow:visible;display:block;}
4114
+ #bounded-auth-modal .ba-c{stroke:currentColor;stroke-width:2.4;fill:none;}
4115
+ @media (prefers-reduced-motion:no-preference){
4116
+ #bounded-auth-modal .ba-c{stroke-dasharray:23;stroke-dashoffset:23;animation:ba-draw .4s cubic-bezier(.45,0,.2,1) forwards;}
4117
+ #bounded-auth-modal .ba-c1{animation-delay:.1s}#bounded-auth-modal .ba-c2{animation-delay:.38s}
4118
+ #bounded-auth-modal .ba-c3{animation-delay:.66s}#bounded-auth-modal .ba-c4{animation-delay:.94s}}
4119
+ @keyframes ba-draw{to{stroke-dashoffset:0}}
4120
+ #bounded-auth-modal .ba-word{font-family:var(--ba-body);font-weight:500;font-size:15px;letter-spacing:.2px;color:var(--ba-text);}
4121
+ #bounded-auth-modal .ba-title{font-family:var(--ba-display);font-weight:400;font-size:25px;letter-spacing:-.01em;margin:0 0 5px;}
4122
+ #bounded-auth-modal .ba-subtitle{color:var(--ba-dim);font-size:14px;margin:0 0 22px;}
4123
+ #bounded-auth-modal .ba-label{display:block;font-size:12px;color:var(--ba-dim);margin:0 0 7px;}
4124
+ #bounded-auth-modal .ba-em{color:var(--ba-text);font-weight:600;}
4125
+ #bounded-auth-modal .ba-input{width:100%;background:var(--ba-inset);border:1px solid var(--ba-line-strong);color:var(--ba-text);
4126
+ border-radius:6px;padding:11px 13px;font-family:var(--ba-body);font-size:15px;outline:none;transition:border-color .15s,box-shadow .15s;}
4127
+ #bounded-auth-modal .ba-input::placeholder{color:var(--ba-faint);}
4128
+ #bounded-auth-modal .ba-input:focus{border-color:var(--ba-green-line);box-shadow:0 0 0 3px var(--ba-green-bg);}
4129
+ #bounded-auth-modal .ba-code{font-family:var(--ba-mono);letter-spacing:8px;text-align:center;font-size:21px;padding-left:8px;}
4130
+ #bounded-auth-modal .ba-btn{width:100%;margin-top:16px;background:var(--ba-text);color:var(--ba-bg);
4131
+ border:0;border-radius:6px;padding:12px;font-family:var(--ba-body);font-size:14px;font-weight:600;cursor:pointer;
4132
+ transition:opacity .15s,transform .04s;}
4133
+ #bounded-auth-modal .ba-btn:hover{opacity:.9;}
4134
+ #bounded-auth-modal .ba-btn:active{transform:translateY(.5px);}
4135
+ #bounded-auth-modal .ba-btn:disabled{opacity:.45;cursor:default;}
4136
+ #bounded-auth-modal .ba-link{width:100%;margin-top:14px;background:none;border:none;color:var(--ba-dim);
4137
+ font-family:var(--ba-body);font-size:12.5px;cursor:pointer;}
4138
+ #bounded-auth-modal .ba-link:hover{color:var(--ba-text);}
4139
+ #bounded-auth-modal .ba-msg{min-height:16px;margin-top:16px;font-size:12.5px;color:var(--ba-dim);text-align:center;}
4140
+ #bounded-auth-modal .ba-msg.err{color:var(--ba-red);}
4141
+ #bounded-auth-modal .ba-foot{margin-top:26px;padding-top:16px;border-top:1px solid var(--ba-line);
4142
+ text-align:center;font-size:11px;color:var(--ba-faint);}
4231
4143
  #bounded-auth-modal .hidden{display:none;}
4232
- @media (max-width:480px){#bounded-auth-modal .ba-card{max-width:none;border-radius:16px;}}`;
4144
+ @media (max-width:480px){#bounded-auth-modal .ba-card{max-width:none;}}`;
4233
4145
 
4234
4146
  const SURFNET_RPC_URL = "https://surfpool.fly.dev";
4235
4147
  const SUPPORTED_SOLANA_NETWORKS = new Set([
@@ -4276,6 +4188,7 @@ function resolveSolanaRpcUrl(explicitRpcUrl, network, context) {
4276
4188
  }
4277
4189
 
4278
4190
  const PKCE_STORE_KEY = 'bounded.oidc.pkce';
4191
+ const STORED_AUTH_METHOD_KEY$2 = 'bounded_last_auth_method';
4279
4192
  // Active session store (Web on web, RN on React Native) — selected by config,
4280
4193
  // not by `typeof window` (truthy on RN). OIDC redirect/popup is web-only, but the
4281
4194
  // session it mints is read back through this same selector everywhere.
@@ -4570,6 +4483,10 @@ async function exchangeCode(code, verifier, redirectUri) {
4570
4483
  const refreshToken = tokenField(data, 'refresh_token', 'refreshToken');
4571
4484
  const user = userFromIdToken(idToken);
4572
4485
  await sessionManager().storeSession(String(user.address || ''), accessToken, idToken, refreshToken, base);
4486
+ try {
4487
+ getPlatform().storage.setItem(STORED_AUTH_METHOD_KEY$2, 'email');
4488
+ }
4489
+ catch ( /* storage unavailable */_b) { /* storage unavailable */ }
4573
4490
  setCurrentUser(user);
4574
4491
  setAuthProviderInstance(oidcProviderSingleton);
4575
4492
  return user;
@@ -4580,7 +4497,10 @@ async function exchangeCode(code, verifier, redirectUri) {
4580
4497
  // (react-dom) when this module is imported on RN.
4581
4498
  let currentAuthProvider = null;
4582
4499
  let currentAuthMethod = null;
4500
+ let currentAuthProviderConfigKey = null;
4583
4501
  let initConfig = null;
4502
+ const objectIdentityKeys = new WeakMap();
4503
+ let nextObjectIdentityKey = 1;
4584
4504
  // --- localStorage helpers: track which auth method created the active session ---
4585
4505
  const STORED_AUTH_METHOD_KEY$1 = 'bounded_last_auth_method';
4586
4506
  function getStoredAuthMethod() {
@@ -4604,6 +4524,51 @@ function setStoredAuthMethod(method) {
4604
4524
  // storage might not be available
4605
4525
  }
4606
4526
  }
4527
+ function objectIdentityKey(value) {
4528
+ if (!value || (typeof value !== 'object' && typeof value !== 'function'))
4529
+ return null;
4530
+ const obj = value;
4531
+ let id = objectIdentityKeys.get(obj);
4532
+ if (!id) {
4533
+ id = nextObjectIdentityKey++;
4534
+ objectIdentityKeys.set(obj, id);
4535
+ }
4536
+ return `object:${id}`;
4537
+ }
4538
+ function stableConfigValue(value, seen = new WeakSet()) {
4539
+ if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean')
4540
+ return value;
4541
+ if (typeof value === 'function')
4542
+ return '[function]';
4543
+ if (Array.isArray(value))
4544
+ return value.map((item) => stableConfigValue(item, seen));
4545
+ if (typeof value === 'object') {
4546
+ if (seen.has(value))
4547
+ return '[circular]';
4548
+ seen.add(value);
4549
+ const out = {};
4550
+ for (const key of Object.keys(value).sort()) {
4551
+ out[key] = stableConfigValue(value[key], seen);
4552
+ }
4553
+ seen.delete(value);
4554
+ return out;
4555
+ }
4556
+ return String(value);
4557
+ }
4558
+ function authProviderConfigKey(config) {
4559
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4560
+ return JSON.stringify({
4561
+ authMethod: (_a = config.authMethod) !== null && _a !== void 0 ? _a : null,
4562
+ chain: (_b = config.chain) !== null && _b !== void 0 ? _b : null,
4563
+ rpcUrl: normalizeSolanaRpcUrl(config.rpcUrl),
4564
+ name: (_c = config.name) !== null && _c !== void 0 ? _c : null,
4565
+ logoUrl: (_d = config.logoUrl) !== null && _d !== void 0 ? _d : null,
4566
+ phantomConfig: stableConfigValue((_e = config.phantomConfig) !== null && _e !== void 0 ? _e : null),
4567
+ privyConfig: stableConfigValue((_f = config.privyConfig) !== null && _f !== void 0 ? _f : null),
4568
+ mobileWalletConfig: stableConfigValue((_g = config.mobileWalletConfig) !== null && _g !== void 0 ? _g : null),
4569
+ privyExpoProvider: objectIdentityKey((_h = config.privyExpoProvider) !== null && _h !== void 0 ? _h : null),
4570
+ });
4571
+ }
4607
4572
  /**
4608
4573
  * Clears the session if it was created by a different auth method.
4609
4574
  * Returns true if the session was cleared, false if the session is compatible.
@@ -4685,38 +4650,6 @@ function requireMobileWalletConfig(config) {
4685
4650
  }
4686
4651
  return Object.assign(Object.assign({}, ((_c = config.mobileWalletConfig) !== null && _c !== void 0 ? _c : {})), { cluster });
4687
4652
  }
4688
- function isLocalOrTestUrl(value) {
4689
- if (!value)
4690
- return false;
4691
- try {
4692
- const hostname = new URL(value).hostname.toLowerCase();
4693
- return hostname === 'localhost' ||
4694
- hostname === '127.0.0.1' ||
4695
- hostname === '::1' ||
4696
- hostname.endsWith('.localhost') ||
4697
- hostname.endsWith('.test');
4698
- }
4699
- catch (_a) {
4700
- return false;
4701
- }
4702
- }
4703
- function assertMockAuthLocalOnly(config) {
4704
- const requiredEndpoints = [
4705
- config.apiUrl,
4706
- config.wsApiUrl,
4707
- config.authApiUrl,
4708
- ];
4709
- const optionalEndpoints = [
4710
- config.rpcUrl,
4711
- config.humanAuthApiUrl,
4712
- config.functionsUrl,
4713
- ].filter((value) => typeof value === 'string' && value.trim() !== '');
4714
- if (requiredEndpoints.every(isLocalOrTestUrl) && optionalEndpoints.every(isLocalOrTestUrl)) {
4715
- return;
4716
- }
4717
- throw new Error("mockAuth is local/test-only. Pass explicit localhost/.test apiUrl, wsApiUrl, and authApiUrl values; " +
4718
- "mockAuth cannot be used with Bounded production or staging endpoints.");
4719
- }
4720
4653
  async function hotSwapToMWAProvider(config) {
4721
4654
  var _a;
4722
4655
  const rpcUrl = normalizeSolanaRpcUrl(config.rpcUrl);
@@ -4741,6 +4674,7 @@ async function hotSwapToMWAProvider(config) {
4741
4674
  }
4742
4675
  currentAuthProvider = provider;
4743
4676
  currentAuthMethod = 'mobile-wallet-adapter';
4677
+ currentAuthProviderConfigKey = authProviderConfigKey(Object.assign(Object.assign({}, config), { authMethod: 'mobile-wallet-adapter' }));
4744
4678
  const coreConfig = await core.getConfig();
4745
4679
  coreConfig.authProvider = provider;
4746
4680
  // Send 'phantom' as authMethod so the server routes to Solana verification.
@@ -4751,20 +4685,19 @@ async function hotSwapToMWAProvider(config) {
4751
4685
  }
4752
4686
  async function getAuthProvider(config) {
4753
4687
  var _a, _b;
4754
- if (currentAuthProvider) {
4688
+ const nextProviderConfigKey = config ? authProviderConfigKey(config) : null;
4689
+ if (currentAuthProvider && (!config || currentAuthProviderConfigKey === nextProviderConfigKey)) {
4755
4690
  return currentAuthProvider;
4756
4691
  }
4757
4692
  if (!config) {
4758
4693
  throw new Error("Config is required to initialize auth provider");
4759
4694
  }
4760
- initConfig = config;
4761
- // If mockAuth is enabled, use MockAuthProvider regardless of authMethod
4762
- if (config.mockAuth) {
4763
- assertMockAuthLocalOnly(config);
4764
- console.log("[MockAuth] Mock authentication enabled");
4765
- currentAuthProvider = new MockAuthProvider();
4766
- return currentAuthProvider;
4695
+ if (currentAuthProvider && currentAuthProviderConfigKey !== nextProviderConfigKey) {
4696
+ currentAuthProvider = null;
4697
+ currentAuthMethod = null;
4698
+ currentAuthProviderConfigKey = null;
4767
4699
  }
4700
+ initConfig = config;
4768
4701
  const authMethod = config.authMethod;
4769
4702
  if (!authMethod) {
4770
4703
  throw new Error("authMethod is required to initialize auth provider; configure the single intended auth method explicitly.");
@@ -4846,6 +4779,7 @@ async function getAuthProvider(config) {
4846
4779
  console.log("[Offchain] Wrapping auth provider for Poofnet transaction tracking");
4847
4780
  currentAuthProvider = new OffchainAuthProvider(currentAuthProvider);
4848
4781
  }
4782
+ currentAuthProviderConfigKey = nextProviderConfigKey;
4849
4783
  return currentAuthProvider;
4850
4784
  }
4851
4785
  /**
@@ -4875,6 +4809,7 @@ async function signInAnonymously() {
4875
4809
  const provider = new GuestAuthProvider();
4876
4810
  currentAuthProvider = provider;
4877
4811
  currentAuthMethod = 'guest';
4812
+ currentAuthProviderConfigKey = 'direct:guest';
4878
4813
  const coreConfig = await core.getConfig();
4879
4814
  coreConfig.authProvider = provider;
4880
4815
  coreConfig.authMethod = 'guest';
@@ -4919,6 +4854,7 @@ async function loginWithPrivy(options) {
4919
4854
  provider = new OffchainAuthProvider(provider);
4920
4855
  }
4921
4856
  currentAuthProvider = provider;
4857
+ currentAuthProviderConfigKey = authProviderConfigKey(Object.assign(Object.assign({}, coreConfig), { authMethod: currentAuthMethod }));
4922
4858
  coreConfig.authProvider = provider;
4923
4859
  coreConfig.authMethod = currentAuthMethod;
4924
4860
  setAuthProviderInstance(provider);
@@ -4935,6 +4871,7 @@ async function activateEmailProvider() {
4935
4871
  const provider = new EmailAuthProvider();
4936
4872
  currentAuthProvider = provider;
4937
4873
  currentAuthMethod = 'email';
4874
+ currentAuthProviderConfigKey = 'direct:email';
4938
4875
  const coreConfig = await core.getConfig();
4939
4876
  coreConfig.authProvider = provider;
4940
4877
  coreConfig.authMethod = 'email';
@@ -5061,6 +4998,7 @@ async function logout$1() {
5061
4998
  setStoredAuthMethod(null);
5062
4999
  currentAuthProvider = null;
5063
5000
  currentAuthMethod = null;
5001
+ currentAuthProviderConfigKey = null;
5064
5002
  }
5065
5003
 
5066
5004
  /**
@@ -9727,8 +9665,6 @@ Object.defineProperty(exports, "subscribe", {
9727
9665
  enumerable: true,
9728
9666
  get: function () { return core.subscribe; }
9729
9667
  });
9730
- exports.DEFAULT_TEST_ADDRESS = DEFAULT_TEST_ADDRESS;
9731
- exports.MockAuthProvider = MockAuthProvider;
9732
9668
  exports.OffchainAuthProvider = OffchainAuthProvider;
9733
9669
  exports.PhantomWalletProvider = PhantomWalletProvider;
9734
9670
  exports.PrivyExpoProvider = PrivyExpoProvider;