@bounded-sh/client 0.0.1

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 (65) hide show
  1. package/README.md +298 -0
  2. package/dist/auth/hooks/useAuth.d.ts +8 -0
  3. package/dist/auth/index.d.ts +73 -0
  4. package/dist/auth/oidc-auth.d.ts +27 -0
  5. package/dist/auth/providers/email-auth-provider.d.ts +38 -0
  6. package/dist/auth/providers/guest-auth-provider.d.ts +14 -0
  7. package/dist/auth/providers/guest-keystore.d.ts +12 -0
  8. package/dist/auth/providers/mock-auth-provider.d.ts +49 -0
  9. package/dist/auth/providers/offchain-auth-provider.d.ts +56 -0
  10. package/dist/auth/providers/phantom-wallet-provider.d.ts +117 -0
  11. package/dist/auth/providers/privy-expo-provider.d.ts +115 -0
  12. package/dist/auth/providers/privy-wallet-provider.d.ts +80 -0
  13. package/dist/auth/providers/sol/sol-utils.d.ts +2 -0
  14. package/dist/auth/providers/solana-mobile-wallet-provider.d.ts +155 -0
  15. package/dist/auth/providers/transaction-utils.d.ts +10 -0
  16. package/dist/global.d.ts +13 -0
  17. package/dist/index-BHTfW8CV.esm.js +16091 -0
  18. package/dist/index-BHTfW8CV.esm.js.map +1 -0
  19. package/dist/index-C1VOdmRN.js +16130 -0
  20. package/dist/index-C1VOdmRN.js.map +1 -0
  21. package/dist/index-CT2j1oic.esm.js +16089 -0
  22. package/dist/index-CT2j1oic.esm.js.map +1 -0
  23. package/dist/index-VGx-869x.js +23572 -0
  24. package/dist/index-VGx-869x.js.map +1 -0
  25. package/dist/index-o5Hv9pfS.esm.js +23456 -0
  26. package/dist/index-o5Hv9pfS.esm.js.map +1 -0
  27. package/dist/index-sKqrgk0t.js +16132 -0
  28. package/dist/index-sKqrgk0t.js.map +1 -0
  29. package/dist/index.browser-BJZ7fYwv.js +5081 -0
  30. package/dist/index.browser-BJZ7fYwv.js.map +1 -0
  31. package/dist/index.browser-DaNhOhkQ.esm.js +4220 -0
  32. package/dist/index.browser-DaNhOhkQ.esm.js.map +1 -0
  33. package/dist/index.browser-DhAcjdpV.esm.js +5071 -0
  34. package/dist/index.browser-DhAcjdpV.esm.js.map +1 -0
  35. package/dist/index.browser-utVKQsEC.js +4225 -0
  36. package/dist/index.browser-utVKQsEC.js.map +1 -0
  37. package/dist/index.d.ts +21 -0
  38. package/dist/index.esm.js +8 -0
  39. package/dist/index.esm.js.map +1 -0
  40. package/dist/index.js +105 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/index.native-B5IBOdv_.js +19684 -0
  43. package/dist/index.native-B5IBOdv_.js.map +1 -0
  44. package/dist/index.native-JPUkdHJj.esm.js +19565 -0
  45. package/dist/index.native-JPUkdHJj.esm.js.map +1 -0
  46. package/dist/index.native.d.ts +26 -0
  47. package/dist/index.native.esm.js +6 -0
  48. package/dist/index.native.esm.js.map +1 -0
  49. package/dist/index.native.js +98 -0
  50. package/dist/index.native.js.map +1 -0
  51. package/dist/phantom-wallet-provider-CDLyxrih.js +1466 -0
  52. package/dist/phantom-wallet-provider-CDLyxrih.js.map +1 -0
  53. package/dist/phantom-wallet-provider-DMlaSrAl.esm.js +1445 -0
  54. package/dist/phantom-wallet-provider-DMlaSrAl.esm.js.map +1 -0
  55. package/dist/platform.d.ts +81 -0
  56. package/dist/privy-wallet-provider-DiHHTDbZ.js +956 -0
  57. package/dist/privy-wallet-provider-DiHHTDbZ.js.map +1 -0
  58. package/dist/privy-wallet-provider-nR52lXzI.esm.js +933 -0
  59. package/dist/privy-wallet-provider-nR52lXzI.esm.js.map +1 -0
  60. package/dist/solana-mobile-wallet-provider-B4CeMMQd.esm.js +1460 -0
  61. package/dist/solana-mobile-wallet-provider-B4CeMMQd.esm.js.map +1 -0
  62. package/dist/solana-mobile-wallet-provider-BYMfFjZb.js +1481 -0
  63. package/dist/solana-mobile-wallet-provider-BYMfFjZb.js.map +1 -0
  64. package/dist/utils.d.ts +1 -0
  65. package/package.json +100 -0
@@ -0,0 +1,933 @@
1
+ import { e as SOLANA_MAINNET_RPC_URL, S as SOLANA_DEVNET_RPC_URL, n as getActiveSessionManager, c as convertRemainingAccounts, b as bufferExports, a as buildSetDocumentsTransaction, o as base58, d as confirmAndCheckTransaction, s as setCurrentUser, i as getPlatform, k as genAuthNonce, l as genSolanaMessage, m as createSessionWithSignature } from './index.native-JPUkdHJj.esm.js';
2
+ import { Connection, VersionedTransaction, PublicKey, Transaction } from '@solana/web3.js';
3
+ import * as anchor from '@coral-xyz/anchor';
4
+ import { createSolanaRpcSubscriptions, createSolanaRpc } from '@solana/kit';
5
+ import * as React from 'react';
6
+ import * as ReactDOM from 'react-dom/client';
7
+ import 'axios';
8
+
9
+ const SURFNET_RPC_URL = "https://surfpool.fly.dev";
10
+ // @privy-io/react-auth(/solana) are OPTIONAL peer deps. They are loaded lazily
11
+ // via dynamic import() rather than a static top-level import: a static import
12
+ // would (a) in the ESM bundle still be a bare `import` the consumer resolves —
13
+ // fine — but (b) in the CJS bundle become an eager top-level require() that
14
+ // throws for any consumer who hasn't installed Privy (this module is pulled
15
+ // into the entry via a static re-export). The lazy import keeps the browser
16
+ // ESM bundle free of any runtime `require('@privy-io...')` AND lets a consumer
17
+ // who never uses Privy load the package without it installed. Populated once
18
+ // in `initialize()` (browser-only) before the Privy React tree renders.
19
+ let privyImports;
20
+ let privySolana;
21
+ async function loadPrivyModules() {
22
+ if (privyImports && privySolana)
23
+ return;
24
+ [privyImports, privySolana] = await Promise.all([
25
+ import('@privy-io/react-auth'),
26
+ import('@privy-io/react-auth/solana'),
27
+ ]);
28
+ }
29
+ const getDefaultPrivyConfig = () => ({
30
+ appId: "cm4ve714908o27dk2yurpnfhd",
31
+ config: {
32
+ embeddedWallets: {
33
+ solana: {
34
+ createOnLogin: "users-without-wallets"
35
+ }
36
+ },
37
+ appearance: {
38
+ walletChainType: 'solana-only'
39
+ },
40
+ externalWallets: { solana: { connectors: privySolana.toSolanaWalletConnectors() } }
41
+ }
42
+ });
43
+ class PrivyWalletProvider {
44
+ constructor(appName, appLogoUrl, privyConfig, networkUrl = null) {
45
+ this.containerElement = null;
46
+ this.chainId = 'solana:mainnet';
47
+ this.root = null;
48
+ this.privyMethods = null;
49
+ this.pendingLogin = null;
50
+ // This is used to store the pending transaction until the wallet is connected for workaround for the wallet not being connected after login completion
51
+ this.pendingTransaction = null;
52
+ // This is used to store pending signTransaction calls until the wallet is connected
53
+ this.pendingSignTransaction = null;
54
+ // This is used to store pending signMessage calls until the wallet is connected
55
+ this.pendingSignMessage = null;
56
+ // This is used to store pending signAndSubmitTransaction calls until the wallet is connected
57
+ this.pendingSignAndSubmitTransaction = null;
58
+ this.networkUrl = networkUrl;
59
+ if (typeof window === 'undefined') {
60
+ throw new Error('PrivyWalletProvider can only be instantiated in a browser environment');
61
+ }
62
+ if (PrivyWalletProvider.instance) {
63
+ return PrivyWalletProvider.instance;
64
+ }
65
+ this.containerElement = null;
66
+ this.root = null;
67
+ this.privyMethods = null;
68
+ this.privyConfig = privyConfig !== null && privyConfig !== void 0 ? privyConfig : getDefaultPrivyConfig();
69
+ // Only use the appName and appLogoUrl if no privyConfig is provided
70
+ if (privyConfig == null) {
71
+ if (appName != null && appName != '') {
72
+ this.privyConfig.config.appearance.landingHeader = appName;
73
+ }
74
+ if (appLogoUrl != null && appLogoUrl != '') {
75
+ this.privyConfig.config.appearance.logo = appLogoUrl;
76
+ }
77
+ }
78
+ // (externalWallets connectors are configured in initialize() once the
79
+ // Privy SDK is lazily loaded — see loadPrivyModules.)
80
+ // Add Solana RPC configuration for v3
81
+ let devnetUrl = SOLANA_DEVNET_RPC_URL;
82
+ let mainnetUrl = SOLANA_MAINNET_RPC_URL;
83
+ if (networkUrl != null) {
84
+ if (networkUrl.includes('mainnet')) {
85
+ mainnetUrl = networkUrl;
86
+ this.chainId = 'solana:mainnet';
87
+ }
88
+ else if (networkUrl.includes('devnet')) {
89
+ devnetUrl = networkUrl;
90
+ this.chainId = 'solana:devnet';
91
+ }
92
+ }
93
+ if (!this.privyConfig.config.solana) {
94
+ this.privyConfig.config.solana = {};
95
+ }
96
+ this.privyConfig.config.solana.rpcs = {
97
+ 'solana:devnet': {
98
+ rpc: createSolanaRpc(devnetUrl),
99
+ rpcSubscriptions: createSolanaRpcSubscriptions(devnetUrl.replace('https://', 'wss://'))
100
+ },
101
+ 'solana:mainnet': {
102
+ rpc: createSolanaRpc(mainnetUrl),
103
+ rpcSubscriptions: createSolanaRpcSubscriptions(mainnetUrl.replace('https://', 'wss://'))
104
+ }
105
+ };
106
+ const existingProviders = document.querySelectorAll('[data-privy-provider]');
107
+ existingProviders.forEach(el => el.remove());
108
+ // Fire-and-forget: initialize() lazily loads the Privy SDK then renders
109
+ // the hidden React tree. privyMethods stays null until that render runs,
110
+ // which the login/connect methods already wait for. Surface a clear error
111
+ // if the optional @privy-io/react-auth peer dep isn't installed.
112
+ this.initialize().catch((err) => {
113
+ console.error('PrivyWalletProvider: failed to load @privy-io/react-auth — ensure it is installed to use Privy login.', err);
114
+ });
115
+ // Assign this instance to the static instance property
116
+ PrivyWalletProvider.instance = this;
117
+ }
118
+ // Optional: Provide a static method to get the instance
119
+ static getInstance(appName, appLogoUrl, privyConfig) {
120
+ if (!PrivyWalletProvider.instance) {
121
+ new PrivyWalletProvider(appName, appLogoUrl, privyConfig);
122
+ }
123
+ return PrivyWalletProvider.instance;
124
+ }
125
+ async initialize() {
126
+ // Lazily load the Privy SDK (browser-only) before building the React tree.
127
+ await loadPrivyModules();
128
+ // Ensure externalWallets connectors are always configured — required for
129
+ // useWallets().ready to resolve even when no browser extension is present.
130
+ if (!this.privyConfig.config.externalWallets && privySolana) {
131
+ this.privyConfig.config.externalWallets = {
132
+ solana: { connectors: privySolana.toSolanaWalletConnectors() }
133
+ };
134
+ }
135
+ if (!this.containerElement) {
136
+ this.containerElement = document.createElement('div');
137
+ this.containerElement.setAttribute('data-privy-provider', 'true');
138
+ document.body.appendChild(this.containerElement);
139
+ const that = this;
140
+ const PrivyComponent = () => {
141
+ const privy = privyImports.usePrivy();
142
+ const useOAuthTokens = privyImports.useOAuthTokens();
143
+ const useFundWalletSolana = privySolana.useFundWallet();
144
+ const useSendTransactionSolana = privySolana.useSignAndSendTransaction();
145
+ const { signTransaction } = privySolana.useSignTransaction();
146
+ const { signMessage: signMessageHook } = privySolana.useSignMessage();
147
+ const { ready: walletReady, wallets } = privySolana.useWallets();
148
+ const { createWallet } = privySolana.useCreateWallet();
149
+ const { exportWallet } = privySolana.useExportWallet();
150
+ const useSolanaWallets = { createWallet, exportWallet, ready: walletReady, wallets };
151
+ const useIdentityToken = privyImports.useIdentityToken();
152
+ const { connectWallet } = privyImports.useConnectWallet({
153
+ onSuccess: async ({ wallet }) => {
154
+ await that.createSession(wallet.address, await privy.getAccessToken(), useIdentityToken.identityToken);
155
+ // If there's a pending transaction, execute it now
156
+ if (that.pendingTransaction) {
157
+ const { evmTransactionData, solTransactionData, options, resolve, reject } = that.pendingTransaction;
158
+ try {
159
+ const result = await that.runTransaction(evmTransactionData, solTransactionData, options);
160
+ resolve(result);
161
+ }
162
+ catch (error) {
163
+ reject(error);
164
+ }
165
+ that.pendingTransaction = null;
166
+ }
167
+ // If there's a pending signTransaction, execute it now
168
+ if (that.pendingSignTransaction) {
169
+ const { transaction, resolve, reject } = that.pendingSignTransaction;
170
+ try {
171
+ const result = await that.signTransaction(transaction);
172
+ resolve(result);
173
+ }
174
+ catch (error) {
175
+ reject(error);
176
+ }
177
+ that.pendingSignTransaction = null;
178
+ }
179
+ // If there's a pending signMessage, execute it now
180
+ if (that.pendingSignMessage) {
181
+ const { message, resolve, reject } = that.pendingSignMessage;
182
+ try {
183
+ const result = await that.signMessage(message);
184
+ resolve(result);
185
+ }
186
+ catch (error) {
187
+ reject(error);
188
+ }
189
+ that.pendingSignMessage = null;
190
+ }
191
+ // If there's a pending signAndSubmitTransaction, execute it now
192
+ if (that.pendingSignAndSubmitTransaction) {
193
+ const { transaction, feePayer, resolve, reject } = that.pendingSignAndSubmitTransaction;
194
+ try {
195
+ const result = await that.signAndSubmitTransaction(transaction, feePayer);
196
+ resolve(result);
197
+ }
198
+ catch (error) {
199
+ reject(error);
200
+ }
201
+ that.pendingSignAndSubmitTransaction = null;
202
+ }
203
+ },
204
+ onError: (error) => {
205
+ // Only log errors that aren't user-initiated cancellations
206
+ if (error !== 'exited_auth_flow' && (error === null || error === void 0 ? void 0 : error.message) !== 'exited_auth_flow') {
207
+ console.error('Wallet connection error:', error);
208
+ }
209
+ if (that.pendingTransaction) {
210
+ that.pendingTransaction.reject(error);
211
+ that.pendingTransaction = null;
212
+ }
213
+ if (that.pendingSignTransaction) {
214
+ that.pendingSignTransaction.reject(error);
215
+ that.pendingSignTransaction = null;
216
+ }
217
+ if (that.pendingSignMessage) {
218
+ that.pendingSignMessage.reject(error);
219
+ that.pendingSignMessage = null;
220
+ }
221
+ if (that.pendingSignAndSubmitTransaction) {
222
+ that.pendingSignAndSubmitTransaction.reject(error);
223
+ that.pendingSignAndSubmitTransaction = null;
224
+ }
225
+ }
226
+ });
227
+ const { login } = privyImports.useLogin({
228
+ onComplete: async ({ user }) => {
229
+ var _a;
230
+ // This is a hack to indicate to the app that privy login is not complete
231
+ // @ts-ignore
232
+ window.runningPrivyOnComplete = true;
233
+ if (!user) {
234
+ getActiveSessionManager().clearSession();
235
+ return;
236
+ }
237
+ const solanaLinkedAccounts = user.linkedAccounts.filter((account) => account.chainType === 'solana');
238
+ const sortedLinkedAccounts = solanaLinkedAccounts.sort((a, b) => new Date(b.latestVerifiedAt).getTime() - new Date(a.latestVerifiedAt).getTime());
239
+ let finalAddress = (_a = sortedLinkedAccounts[0]) === null || _a === void 0 ? void 0 : _a.address;
240
+ if (!finalAddress) {
241
+ const solanaWallet = await createWallet();
242
+ finalAddress = solanaWallet.address;
243
+ getActiveSessionManager().clearSession();
244
+ return;
245
+ }
246
+ const session = await getActiveSessionManager().getSession();
247
+ if (!session || finalAddress !== session.address) {
248
+ try {
249
+ const accessToken = await privy.getAccessToken();
250
+ const idToken = useIdentityToken.identityToken;
251
+ await that.createSession(finalAddress, accessToken, idToken);
252
+ }
253
+ catch (error) {
254
+ console.error('Error creating session:', error);
255
+ }
256
+ }
257
+ // @ts-ignore
258
+ window.runningPrivyOnComplete = false;
259
+ setCurrentUser({ address: finalAddress, provider: that });
260
+ if (that.pendingLogin) {
261
+ that.pendingLogin.resolve({ address: finalAddress, provider: that });
262
+ that.pendingLogin = null;
263
+ }
264
+ },
265
+ onError: (error) => {
266
+ // Only log errors that aren't user-initiated cancellations
267
+ if (error !== 'exited_auth_flow' && (error === null || error === void 0 ? void 0 : error.message) !== 'exited_auth_flow') {
268
+ console.error('Login error:', error);
269
+ }
270
+ if (that.pendingLogin) {
271
+ that.pendingLogin.reject(error);
272
+ that.pendingLogin = null;
273
+ }
274
+ }
275
+ });
276
+ const { logout } = privyImports.useLogout({
277
+ onSuccess: () => {
278
+ getActiveSessionManager().clearSession();
279
+ setCurrentUser(null);
280
+ }
281
+ });
282
+ React.useEffect(() => {
283
+ if (privy.ready) {
284
+ that.privyMethods = {
285
+ ready: privy.ready,
286
+ walletReady: walletReady,
287
+ authenticated: privy.authenticated,
288
+ wallets,
289
+ login,
290
+ logout,
291
+ connectWallet,
292
+ getAccessToken: privy.getAccessToken,
293
+ identityToken: useIdentityToken.identityToken,
294
+ usePrivy: privy,
295
+ useOAuthTokens: useOAuthTokens,
296
+ useFundWalletSolana: useFundWalletSolana,
297
+ useSendTransactionSolana: useSendTransactionSolana,
298
+ useSolanaWallets: useSolanaWallets,
299
+ signTransaction: signTransaction,
300
+ signMessage: signMessageHook,
301
+ };
302
+ }
303
+ }, [privy.ready, privy.authenticated, wallets, login, logout, walletReady]);
304
+ return null;
305
+ };
306
+ const FinalPrivyComponent = () => {
307
+ if (typeof window === 'undefined') {
308
+ return null;
309
+ }
310
+ return React.createElement(privyImports.PrivyProvider, {
311
+ appId: this.privyConfig.appId,
312
+ config: this.privyConfig.config,
313
+ children: React.createElement(PrivyComponent)
314
+ });
315
+ };
316
+ this.root = ReactDOM.createRoot(this.containerElement);
317
+ this.root.render(React.createElement(FinalPrivyComponent));
318
+ }
319
+ }
320
+ async login() {
321
+ var _a, _b;
322
+ await this.ensureReady();
323
+ // Check if we have a valid session that matches an authenticated wallet
324
+ const session = await getActiveSessionManager().getSession();
325
+ if (((_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.authenticated) && ((_b = this.privyMethods.wallets) === null || _b === void 0 ? void 0 : _b.length) > 0 && session) {
326
+ // Find the wallet matching the session
327
+ const matchingWallet = this.privyMethods.wallets.find((wallet) => wallet.address === session.address);
328
+ if (matchingWallet) {
329
+ // Valid session with matching wallet, return immediately
330
+ setCurrentUser({ address: matchingWallet.address, provider: this });
331
+ return {
332
+ address: matchingWallet.address,
333
+ provider: this
334
+ };
335
+ }
336
+ // Session exists but doesn't match any connected wallet
337
+ // This can happen after wallet switching - force fresh login
338
+ console.log('Session wallet mismatch detected, forcing fresh login flow');
339
+ }
340
+ // If no valid session or wallet mismatch, force a fresh login flow
341
+ // This ensures the user can select the correct wallet, especially after logout
342
+ if (this.pendingLogin) {
343
+ return new Promise((resolve, reject) => {
344
+ this.pendingLogin.resolve = resolve;
345
+ this.pendingLogin.reject = reject;
346
+ });
347
+ }
348
+ return new Promise((resolve, reject) => {
349
+ this.pendingLogin = { resolve, reject };
350
+ // open Privy modal to let user select/verify wallet
351
+ this.privyMethods.login();
352
+ // safety timeout
353
+ setTimeout(() => {
354
+ if (this.pendingLogin) {
355
+ this.pendingLogin.reject(new Error("Login timed out"));
356
+ this.pendingLogin = null;
357
+ }
358
+ }, 180000);
359
+ });
360
+ }
361
+ async getNativeMethods() {
362
+ var _a;
363
+ await this.ensureReady();
364
+ return (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.usePrivy;
365
+ }
366
+ async logout() {
367
+ await this.ensureReady();
368
+ await this.privyMethods.logout();
369
+ }
370
+ async runTransaction(_evmTransactionData, solTransactionData, options) {
371
+ var _a, _b, _c;
372
+ await this.ensureReady({ waitForWallets: true });
373
+ let session = await getActiveSessionManager().getSession();
374
+ let sessionAddress = session === null || session === void 0 ? void 0 : session.address;
375
+ let privyWallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
376
+ let privyWallet = privyWallets === null || privyWallets === void 0 ? void 0 : privyWallets.find((wallet) => wallet.address === sessionAddress);
377
+ // If wallet not found yet, it may be an embedded wallet (email login) that hasn't
378
+ // appeared in the wallets array due to React state timing. Wait for it before
379
+ // falling back to connectWallet() which shows an unwanted wallet selection modal.
380
+ if (!privyWallets || privyWallets.length === 0 || !privyWallet) {
381
+ if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
382
+ privyWallet = await this.waitForMatchingWallet(sessionAddress);
383
+ }
384
+ }
385
+ if (!privyWallet) {
386
+ // If there's already a pending transaction, throw an error to prevent overlapping calls
387
+ if (this.pendingTransaction) {
388
+ throw new Error("Oops... something went wrong. Please try again.");
389
+ }
390
+ // Create a promise to wait for the transaction result
391
+ return new Promise((resolve, reject) => {
392
+ this.pendingTransaction = {
393
+ resolve,
394
+ reject,
395
+ evmTransactionData: _evmTransactionData,
396
+ solTransactionData,
397
+ options
398
+ };
399
+ this.privyMethods.connectWallet();
400
+ // Set a timeout to reject the promise if connection takes too long
401
+ setTimeout(() => {
402
+ if (this.pendingTransaction) {
403
+ this.pendingTransaction.reject(new Error("Wallet connection timed out"));
404
+ this.pendingTransaction = null;
405
+ }
406
+ }, 30000); // 30 seconds timeout
407
+ });
408
+ }
409
+ // Proceed with the transaction using privyWallet
410
+ const wallet = privyWallet;
411
+ if (solTransactionData == null) {
412
+ throw new Error("Solana transaction data is required");
413
+ }
414
+ const rpcUrl = this.getRpcUrl(solTransactionData.network);
415
+ const connection = new Connection(rpcUrl, "confirmed");
416
+ const remainingAccounts = convertRemainingAccounts(solTransactionData.txArgs[0].remainingAccounts);
417
+ let app_id = solTransactionData.appId;
418
+ if (typeof window !== 'undefined' && window.CUSTOM_TAROBASE_APP_ID_HEADER) {
419
+ const customAppId = window.CUSTOM_TAROBASE_APP_ID_HEADER;
420
+ if (customAppId) {
421
+ app_id = customAppId;
422
+ }
423
+ }
424
+ if (!app_id) {
425
+ throw new Error("App ID is required");
426
+ }
427
+ const anchorProvider = new anchor.AnchorProvider(connection, wallet.provider, anchor.AnchorProvider.defaultOptions());
428
+ const finalDeduped = [];
429
+ for (const acc of remainingAccounts) {
430
+ const existing = finalDeduped.find((d) => d.pubkey.equals(acc.pubkey));
431
+ if (existing) {
432
+ existing.isSigner = existing.isSigner || acc.isSigner;
433
+ existing.isWritable = existing.isWritable || acc.isWritable;
434
+ }
435
+ else {
436
+ finalDeduped.push(acc);
437
+ }
438
+ }
439
+ let tx;
440
+ let blockhash;
441
+ let lastValidBlockHeight;
442
+ if (solTransactionData.signedTransaction) {
443
+ // Server already set the blockhash and co-signed — do NOT overwrite
444
+ // the blockhash or it will invalidate the server's signature.
445
+ tx = VersionedTransaction.deserialize(bufferExports.Buffer.from(solTransactionData.signedTransaction, 'base64'));
446
+ // Extract the blockhash that was baked into the signed message
447
+ blockhash = tx.message.recentBlockhash;
448
+ const latestBlockhash = await connection.getLatestBlockhash('confirmed');
449
+ lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;
450
+ }
451
+ else {
452
+ const result = await buildSetDocumentsTransaction(connection, solTransactionData.txArgs[0].idl, anchorProvider, new PublicKey(wallet.address), { app_id, documents: solTransactionData.txArgs[0].setDocumentData, delete_paths: solTransactionData.txArgs[0].deletePaths, txData: solTransactionData.txArgs[0].txData }, finalDeduped, solTransactionData.lutKey, solTransactionData.preInstructions, false, solTransactionData.additionalLutAddresses);
453
+ tx = result.tx;
454
+ blockhash = result.blockhash;
455
+ lastValidBlockHeight = result.lastValidBlockHeight;
456
+ }
457
+ // Use duck typing instead of instanceof to handle multiple @solana/web3.js versions
458
+ const isLegacyTx = 'recentBlockhash' in tx && !('message' in tx && 'staticAccountKeys' in tx.message);
459
+ if (isLegacyTx) {
460
+ tx.recentBlockhash = blockhash;
461
+ tx.lastValidBlockHeight = lastValidBlockHeight;
462
+ }
463
+ else {
464
+ tx.message.recentBlockhash = blockhash;
465
+ }
466
+ try {
467
+ if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
468
+ // Just sign, don't submit - return raw signed bytes (same as original runTransaction)
469
+ const signedTx = await this.signTransactionRaw(tx, privyWallet);
470
+ return {
471
+ signedTransaction: signedTx, // Raw Uint8Array from Privy
472
+ blockNumber: 0,
473
+ gasUsed: "0",
474
+ data: ""
475
+ };
476
+ }
477
+ // Sign and submit using shared helper
478
+ const { signature, txInfo } = await this.signAndSubmitInternal(tx, privyWallet, rpcUrl, connection);
479
+ return {
480
+ transactionSignature: signature,
481
+ blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
482
+ gasUsed: ((_c = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _c === void 0 ? void 0 : _c.fee.toString()) || '0',
483
+ data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
484
+ };
485
+ }
486
+ catch (err) {
487
+ console.error(err);
488
+ throw err;
489
+ }
490
+ }
491
+ /**
492
+ * Signs a Solana transaction without submitting it.
493
+ *
494
+ * This method handles blockhash automatically if not set - you do NOT need to
495
+ * set recentBlockhash on the transaction before calling this method.
496
+ * The network/RPC URL is derived from the provider's configuration (set during initialization).
497
+ *
498
+ * @param transaction - The transaction to sign (Transaction or VersionedTransaction)
499
+ * @returns The signed transaction
500
+ */
501
+ async signTransaction(transaction) {
502
+ var _a, _b;
503
+ await this.ensureReady({ waitForWallets: true });
504
+ let privyWallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
505
+ let session = await getActiveSessionManager().getSession();
506
+ let sessionAddress = session === null || session === void 0 ? void 0 : session.address;
507
+ let privyWallet = privyWallets === null || privyWallets === void 0 ? void 0 : privyWallets.find((wallet) => wallet.address === sessionAddress);
508
+ // If there's already a pending sign transaction, throw an error to prevent overlapping calls
509
+ if (this.pendingSignTransaction) {
510
+ throw new Error("Oops... something went wrong. Please try again.");
511
+ }
512
+ // If wallet not found yet, it may be an embedded wallet (email login) that hasn't
513
+ // appeared in the wallets array due to React state timing. Wait for it before
514
+ // falling back to connectWallet() which shows an unwanted wallet selection modal.
515
+ if (!privyWallets || privyWallets.length === 0 || !privyWallet) {
516
+ if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
517
+ privyWallet = await this.waitForMatchingWallet(sessionAddress);
518
+ }
519
+ }
520
+ // If still no wallet after waiting, trigger connection and queue the signing
521
+ if (!privyWallet) {
522
+ return new Promise((resolve, reject) => {
523
+ this.pendingSignTransaction = {
524
+ resolve,
525
+ reject,
526
+ transaction
527
+ };
528
+ this.privyMethods.connectWallet();
529
+ // Set a timeout to reject the promise if connection takes too long
530
+ setTimeout(() => {
531
+ if (this.pendingSignTransaction) {
532
+ this.pendingSignTransaction.reject(new Error("Wallet connection timed out"));
533
+ this.pendingSignTransaction = null;
534
+ }
535
+ }, 30000); // 30 seconds timeout
536
+ });
537
+ }
538
+ // Privy requires serialized transaction bytes, which requires a blockhash.
539
+ // If the transaction doesn't have one, get a fresh blockhash and set it.
540
+ // Use duck typing instead of instanceof to handle multiple @solana/web3.js versions
541
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
542
+ if (isLegacyTransaction) {
543
+ const legacyTx = transaction;
544
+ if (!legacyTx.recentBlockhash) {
545
+ const rpcUrl = this.getRpcUrl();
546
+ const connection = new Connection(rpcUrl, 'confirmed');
547
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
548
+ legacyTx.recentBlockhash = blockhash;
549
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
550
+ }
551
+ // Set feePayer if not already set
552
+ if (!legacyTx.feePayer) {
553
+ legacyTx.feePayer = new PublicKey(privyWallet.address);
554
+ }
555
+ }
556
+ else {
557
+ // VersionedTransaction
558
+ const versionedTx = transaction;
559
+ if (!versionedTx.message.recentBlockhash) {
560
+ const rpcUrl = this.getRpcUrl();
561
+ const connection = new Connection(rpcUrl, 'confirmed');
562
+ const { blockhash } = await connection.getLatestBlockhash('confirmed');
563
+ versionedTx.message.recentBlockhash = blockhash;
564
+ }
565
+ }
566
+ // Sign using raw method, then deserialize for the public API
567
+ const signedTxRaw = await this.signTransactionRaw(transaction, privyWallet);
568
+ return this.deserializeSignedTransaction(signedTxRaw);
569
+ }
570
+ /**
571
+ * Signs and submits a Solana transaction to the network.
572
+ *
573
+ * This method handles blockhash and transaction confirmation automatically - you do NOT need to
574
+ * set recentBlockhash or lastValidBlockHeight on the transaction before calling this method.
575
+ * The network/RPC URL is derived from the provider's configuration (set during initialization).
576
+ *
577
+ * @param transaction - The transaction to sign and submit (Transaction or VersionedTransaction)
578
+ * @param feePayer - Optional fee payer public key. If not provided and the transaction doesn't
579
+ * already have a feePayer set, the connected wallet address will be used.
580
+ * Useful for co-signing scenarios where a different account pays the fees.
581
+ * @returns The transaction signature
582
+ */
583
+ async signAndSubmitTransaction(transaction, feePayer) {
584
+ var _a, _b;
585
+ await this.ensureReady({ waitForWallets: true });
586
+ let privyWallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
587
+ let session = await getActiveSessionManager().getSession();
588
+ let sessionAddress = session === null || session === void 0 ? void 0 : session.address;
589
+ let privyWallet = privyWallets === null || privyWallets === void 0 ? void 0 : privyWallets.find((wallet) => wallet.address === sessionAddress);
590
+ // If there's already a pending signAndSubmitTransaction, throw an error to prevent overlapping calls
591
+ if (this.pendingSignAndSubmitTransaction) {
592
+ throw new Error("Oops... something went wrong. Please try again.");
593
+ }
594
+ // If wallet not found yet, it may be an embedded wallet (email login) that hasn't
595
+ // appeared in the wallets array due to React state timing. Wait for it before
596
+ // falling back to connectWallet() which shows an unwanted wallet selection modal.
597
+ if (!privyWallets || privyWallets.length === 0 || !privyWallet) {
598
+ if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
599
+ privyWallet = await this.waitForMatchingWallet(sessionAddress);
600
+ }
601
+ }
602
+ // If still no wallet after waiting, trigger connection and queue the signing
603
+ if (!privyWallet) {
604
+ return new Promise((resolve, reject) => {
605
+ this.pendingSignAndSubmitTransaction = {
606
+ resolve,
607
+ reject,
608
+ transaction,
609
+ feePayer
610
+ };
611
+ this.privyMethods.connectWallet();
612
+ // Set a timeout to reject the promise if connection takes too long
613
+ setTimeout(() => {
614
+ if (this.pendingSignAndSubmitTransaction) {
615
+ this.pendingSignAndSubmitTransaction.reject(new Error("Wallet connection timed out"));
616
+ this.pendingSignAndSubmitTransaction = null;
617
+ }
618
+ }, 30000); // 30 seconds timeout
619
+ });
620
+ }
621
+ // Get RPC URL and create connection
622
+ const rpcUrl = this.getRpcUrl();
623
+ const connection = new Connection(rpcUrl, 'confirmed');
624
+ // Get fresh blockhash and set it on the transaction before signing
625
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
626
+ // Use duck typing instead of instanceof to handle multiple @solana/web3.js versions
627
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
628
+ if (isLegacyTransaction) {
629
+ const legacyTx = transaction;
630
+ legacyTx.recentBlockhash = blockhash;
631
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
632
+ // Set feePayer if not already set
633
+ if (!legacyTx.feePayer) {
634
+ legacyTx.feePayer = feePayer !== null && feePayer !== void 0 ? feePayer : new PublicKey(privyWallet.address);
635
+ }
636
+ }
637
+ else {
638
+ // VersionedTransaction
639
+ const versionedTx = transaction;
640
+ versionedTx.message.recentBlockhash = blockhash;
641
+ // Note: VersionedTransaction feePayer is set in the message at creation time
642
+ // and cannot be modified after creation
643
+ }
644
+ // Use shared sign and submit logic
645
+ const { signature } = await this.signAndSubmitInternal(transaction, privyWallet, rpcUrl, connection);
646
+ return signature;
647
+ }
648
+ // ============ Private Helpers ============
649
+ getRpcUrl(network) {
650
+ if (this.networkUrl) {
651
+ return this.networkUrl;
652
+ }
653
+ if (network === 'solana_devnet') {
654
+ return SOLANA_DEVNET_RPC_URL;
655
+ }
656
+ else if (network === 'solana_mainnet') {
657
+ return SOLANA_MAINNET_RPC_URL;
658
+ }
659
+ else if (network === 'surfnet') {
660
+ return SURFNET_RPC_URL;
661
+ }
662
+ return SOLANA_MAINNET_RPC_URL; // default to mainnet
663
+ }
664
+ /**
665
+ * Internal sign transaction - serializes and signs via Privy
666
+ * Returns the raw result from Privy (Uint8Array)
667
+ * This mirrors exactly what runTransaction was doing
668
+ */
669
+ async signTransactionRaw(transaction, privyWallet) {
670
+ var _a;
671
+ // Serialize the transaction
672
+ // Use duck typing instead of instanceof to handle multiple @solana/web3.js versions
673
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
674
+ let serializedForSign;
675
+ if (isLegacyTransaction) {
676
+ serializedForSign = transaction.serialize({ requireAllSignatures: false, verifySignatures: false });
677
+ }
678
+ else {
679
+ serializedForSign = transaction.serialize();
680
+ }
681
+ // Sign via Privy - returns { signedTransaction: Uint8Array }
682
+ const result = await ((_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.signTransaction({
683
+ transaction: serializedForSign,
684
+ wallet: privyWallet,
685
+ chain: this.chainId
686
+ }));
687
+ // Privy returns { signedTransaction: Uint8Array }, unwrap it
688
+ const signedTx = (result === null || result === void 0 ? void 0 : result.signedTransaction) || result;
689
+ return signedTx;
690
+ }
691
+ /**
692
+ * Deserialize a signed transaction from Uint8Array to Transaction object
693
+ */
694
+ deserializeSignedTransaction(signedTxRaw) {
695
+ // Handle different formats Privy might return
696
+ let signedTx;
697
+ if (signedTxRaw instanceof Uint8Array) {
698
+ signedTx = signedTxRaw;
699
+ }
700
+ else if (Array.isArray(signedTxRaw)) {
701
+ signedTx = new Uint8Array(signedTxRaw);
702
+ }
703
+ else if (signedTxRaw && typeof signedTxRaw === 'object' && 'signedTransaction' in signedTxRaw) {
704
+ // Privy might wrap the result
705
+ signedTx = signedTxRaw.signedTransaction instanceof Uint8Array
706
+ ? signedTxRaw.signedTransaction
707
+ : new Uint8Array(signedTxRaw.signedTransaction);
708
+ }
709
+ else if (bufferExports.Buffer.isBuffer(signedTxRaw)) {
710
+ signedTx = new Uint8Array(signedTxRaw);
711
+ }
712
+ else {
713
+ throw new Error(`Unexpected signed transaction format: ${typeof signedTxRaw}`);
714
+ }
715
+ // Try to deserialize as VersionedTransaction first, fall back to legacy Transaction
716
+ try {
717
+ return VersionedTransaction.deserialize(signedTx);
718
+ }
719
+ catch (_a) {
720
+ return Transaction.from(signedTx);
721
+ }
722
+ }
723
+ /**
724
+ * Internal sign and submit - handles Surfnet vs non-Surfnet logic
725
+ * This is the core submission logic used by both signAndSubmitTransaction and runTransaction
726
+ *
727
+ * For Surfnet: sign with signTransactionRaw, then sendRawTransaction
728
+ * For non-Surfnet: use Privy's signAndSendTransaction (combined operation)
729
+ */
730
+ async signAndSubmitInternal(transaction, privyWallet, rpcUrl, connection) {
731
+ var _a;
732
+ const isSurfnet = rpcUrl === SURFNET_RPC_URL;
733
+ let signature;
734
+ if (isSurfnet) {
735
+ // For Surfnet: sign with signTransactionRaw, then sendRawTransaction
736
+ const signedTx = await this.signTransactionRaw(transaction, privyWallet);
737
+ signature = await connection.sendRawTransaction(signedTx);
738
+ }
739
+ else {
740
+ // For non-Surfnet: use Privy's combined signAndSendTransaction
741
+ // Serialize the transaction for Privy API
742
+ // Use duck typing instead of instanceof to handle multiple @solana/web3.js versions
743
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
744
+ let serializedTx;
745
+ if (isLegacyTransaction) {
746
+ serializedTx = transaction.serialize({ requireAllSignatures: false, verifySignatures: false });
747
+ }
748
+ else {
749
+ serializedTx = transaction.serialize();
750
+ }
751
+ const result = await ((_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.useSendTransactionSolana.signAndSendTransaction({
752
+ transaction: serializedTx,
753
+ wallet: privyWallet,
754
+ chain: this.chainId
755
+ }));
756
+ // Handle case where signature might be bytes instead of string
757
+ const rawSig = result.signature;
758
+ if (rawSig instanceof Uint8Array || Array.isArray(rawSig)) {
759
+ signature = base58.encode(rawSig instanceof Uint8Array ? rawSig : new Uint8Array(rawSig));
760
+ }
761
+ else {
762
+ signature = rawSig;
763
+ }
764
+ }
765
+ const txInfo = await confirmAndCheckTransaction(connection, signature);
766
+ return { signature, txInfo };
767
+ }
768
+ async signMessage(message) {
769
+ var _a, _b, _c;
770
+ await this.ensureReady({ waitForWallets: true });
771
+ const session = await getActiveSessionManager().getSession();
772
+ let sessionAddress = session === null || session === void 0 ? void 0 : session.address;
773
+ // If there's already a pending sign message, throw an error to prevent overlapping calls
774
+ if (this.pendingSignMessage) {
775
+ throw new Error("Oops... something went wrong. Please try again.");
776
+ }
777
+ // If no wallets connected yet, it may be an embedded wallet (email login) that hasn't
778
+ // appeared in the wallets array due to React state timing. Wait for it before
779
+ // falling back to connectWallet() which shows an unwanted wallet selection modal.
780
+ if (!((_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets) || this.privyMethods.wallets.length === 0) {
781
+ if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
782
+ const matchedWallet = await this.waitForMatchingWallet(sessionAddress);
783
+ if (!matchedWallet) {
784
+ return new Promise((resolve, reject) => {
785
+ this.pendingSignMessage = {
786
+ resolve,
787
+ reject,
788
+ message
789
+ };
790
+ this.privyMethods.connectWallet();
791
+ // Set a timeout to reject the promise if connection takes too long
792
+ setTimeout(() => {
793
+ if (this.pendingSignMessage) {
794
+ this.pendingSignMessage.reject(new Error("Wallet connection timed out"));
795
+ this.pendingSignMessage = null;
796
+ }
797
+ }, 30000); // 30 seconds timeout
798
+ });
799
+ }
800
+ }
801
+ else {
802
+ return new Promise((resolve, reject) => {
803
+ this.pendingSignMessage = {
804
+ resolve,
805
+ reject,
806
+ message
807
+ };
808
+ this.privyMethods.connectWallet();
809
+ // Set a timeout to reject the promise if connection takes too long
810
+ setTimeout(() => {
811
+ if (this.pendingSignMessage) {
812
+ this.pendingSignMessage.reject(new Error("Wallet connection timed out"));
813
+ this.pendingSignMessage = null;
814
+ }
815
+ }, 30000); // 30 seconds timeout
816
+ });
817
+ }
818
+ }
819
+ let privyWallet = this.privyMethods.wallets.find((wallet) => wallet.address === sessionAddress);
820
+ if (!privyWallet) {
821
+ // Session address is not a privy wallet, just default to the first wallet
822
+ const accessToken = await this.privyMethods.getAccessToken();
823
+ await this.createSession(this.privyMethods.wallets[0].address, accessToken, this.privyMethods.identityToken);
824
+ setCurrentUser({ address: this.privyMethods.wallets[0].address, provider: this });
825
+ const session = await getActiveSessionManager().getSession();
826
+ sessionAddress = session === null || session === void 0 ? void 0 : session.address;
827
+ if (!sessionAddress) {
828
+ throw new Error('No wallet connected or logged in to sign message');
829
+ }
830
+ privyWallet = this.privyMethods.wallets[0];
831
+ }
832
+ // Use the Privy signMessage hook for Solana wallets
833
+ // The message needs to be passed as a Uint8Array
834
+ const messageBytes = getPlatform().textEncode(message);
835
+ const result = await ((_c = this.privyMethods) === null || _c === void 0 ? void 0 : _c.signMessage({
836
+ message: messageBytes,
837
+ wallet: privyWallet,
838
+ }));
839
+ // The signature is returned as a Uint8Array, encode it as base58 (standard Solana format)
840
+ const signatureBytes = (result === null || result === void 0 ? void 0 : result.signature) || result;
841
+ const bs58 = await import('./index.native-JPUkdHJj.esm.js').then(function (n) { return n.aI; });
842
+ return bs58.default.encode(signatureBytes);
843
+ }
844
+ async restoreSession() {
845
+ const session = await getActiveSessionManager().getSession();
846
+ if (session) {
847
+ return { provider: this, address: session.address };
848
+ }
849
+ else {
850
+ return null;
851
+ }
852
+ }
853
+ // NOTE: accessToken/idToken are accepted for backwards-compat with existing
854
+ // call sites but are no longer used. The session is minted by having the Privy
855
+ // Solana wallet SIGN the canonical SIWS challenge (the same wallet-signature
856
+ // path Phantom/MWA/guest use), so the bounded /session issuer needs no
857
+ // Privy-specific token verification — it arrives as a Solana signature and is
858
+ // recorded server-side as authMethod 'phantom'.
859
+ async createSession(address, _accessToken, _idToken) {
860
+ var _a, _b, _c, _d, _e, _f, _g;
861
+ // Resolve the Privy wallet for this address (fall back to the first wallet).
862
+ const privyWallet = (_c = (_b = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets) === null || _b === void 0 ? void 0 : _b.find((w) => w.address === address)) !== null && _c !== void 0 ? _c : (_e = (_d = this.privyMethods) === null || _d === void 0 ? void 0 : _d.wallets) === null || _e === void 0 ? void 0 : _e[0];
863
+ if (!privyWallet) {
864
+ throw new Error('No Privy Solana wallet available to mint a session.');
865
+ }
866
+ const nonce = await genAuthNonce();
867
+ const message = await genSolanaMessage(address, nonce);
868
+ const messageBytes = getPlatform().textEncode(message);
869
+ // Low-level Privy sign hook — signs WITHOUT touching the session (the public
870
+ // signMessage() bootstraps sessions, which would recurse here).
871
+ const signResult = await ((_f = this.privyMethods) === null || _f === void 0 ? void 0 : _f.signMessage({
872
+ message: messageBytes,
873
+ wallet: privyWallet,
874
+ }));
875
+ const signatureBytes = (_g = signResult === null || signResult === void 0 ? void 0 : signResult.signature) !== null && _g !== void 0 ? _g : signResult;
876
+ // base64-encoded detached signature (matches Phantom + guest providers).
877
+ const signature = bufferExports.Buffer.from(signatureBytes).toString('base64');
878
+ const createSessionResult = await createSessionWithSignature(address, message, signature);
879
+ if (createSessionResult) {
880
+ await getActiveSessionManager().storeSession(address, createSessionResult.accessToken, createSessionResult.idToken, createSessionResult.refreshToken);
881
+ }
882
+ }
883
+ /**
884
+ * Waits for a wallet matching the session address to appear in the wallets array.
885
+ * This handles the timing gap where Privy's embedded wallet (created for email login users)
886
+ * may not yet be in the useWallets() array when signTransaction is called immediately after login.
887
+ */
888
+ async waitForMatchingWallet(sessionAddress, timeoutMs = 10000) {
889
+ var _a;
890
+ const startTime = Date.now();
891
+ while (Date.now() - startTime < timeoutMs) {
892
+ const wallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
893
+ if (wallets && wallets.length > 0) {
894
+ const wallet = wallets.find((w) => w.address === sessionAddress);
895
+ if (wallet)
896
+ return wallet;
897
+ }
898
+ await new Promise(resolve => setTimeout(resolve, 200));
899
+ }
900
+ return null;
901
+ }
902
+ async ensureReady({ waitForWallets = false, timeoutMs = 15000 } = {}) {
903
+ const isReady = () => {
904
+ var _a, _b;
905
+ if (!((_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.ready))
906
+ return false;
907
+ if (waitForWallets && !((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.walletReady))
908
+ return false;
909
+ return true;
910
+ };
911
+ if (isReady())
912
+ return;
913
+ return new Promise((resolve, reject) => {
914
+ const startTime = Date.now();
915
+ const check = () => {
916
+ if (isReady()) {
917
+ resolve();
918
+ }
919
+ else if (Date.now() - startTime > timeoutMs) {
920
+ reject(new Error('Login provider failed to initialize. This can happen in incognito mode or when third-party cookies are blocked. Try using a regular browser window.'));
921
+ }
922
+ else {
923
+ setTimeout(check, 100);
924
+ }
925
+ };
926
+ check();
927
+ });
928
+ }
929
+ }
930
+ PrivyWalletProvider.instance = null;
931
+
932
+ export { PrivyWalletProvider };
933
+ //# sourceMappingURL=privy-wallet-provider-nR52lXzI.esm.js.map