@pooflabs/web 0.0.68 → 0.0.69-rc.2

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.
@@ -10757,7 +10757,10 @@ function handleServerMessage(connection, message) {
10757
10757
  }
10758
10758
  function notifyCallbacks(subscription, data) {
10759
10759
  var _a;
10760
- for (const callback of subscription.callbacks) {
10760
+ // Snapshot the callbacks array so that unsubscriptions during
10761
+ // notification don't cause callbacks to be skipped.
10762
+ const callbacks = subscription.callbacks.slice();
10763
+ for (const callback of callbacks) {
10761
10764
  try {
10762
10765
  (_a = callback.onData) === null || _a === void 0 ? void 0 : _a.call(callback, data);
10763
10766
  }
@@ -13543,7 +13546,7 @@ async function loadDependencies() {
13543
13546
  const [reactModule, reactDomModule, phantomModule] = await Promise.all([
13544
13547
  import('react'),
13545
13548
  import('react-dom/client'),
13546
- import('./index-CzcmQ2iE.esm.js')
13549
+ import('./index-BxW0dVxR.esm.js')
13547
13550
  ]);
13548
13551
  // Extract default export from ESM module namespace
13549
13552
  // Dynamic import() returns { default: Module, ...exports }, not the module directly
@@ -13566,6 +13569,8 @@ class PhantomWalletProvider {
13566
13569
  this.initPromise = null;
13567
13570
  /** Callback to swap to a Privy provider when the user clicks "Log in with email" */
13568
13571
  this.onSwitchToPrivy = null;
13572
+ /** Callback to swap to a Mobile Wallet Adapter provider when the user clicks "Connect Mobile Wallet" */
13573
+ this.onSwitchToMWA = null;
13569
13574
  this.networkUrl = networkUrl;
13570
13575
  this.config = config;
13571
13576
  if (typeof window === 'undefined') {
@@ -13655,9 +13660,15 @@ class PhantomWalletProvider {
13655
13660
  this.containerElement.setAttribute('data-phantom-provider', 'true');
13656
13661
  // Keep Phantom UI above host overlays while avoiding global click-capture.
13657
13662
  this.containerElement.style.position = 'fixed';
13658
- this.containerElement.style.inset = '0';
13659
13663
  this.containerElement.style.zIndex = '2147483647';
13660
- this.containerElement.style.pointerEvents = 'none';
13664
+ if (this.config.enablePrivyFallback) {
13665
+ // Full-viewport overlay for custom modal; pointer-events: none lets
13666
+ // clicks pass through to page except where the modal sets 'auto'
13667
+ this.containerElement.style.inset = '0';
13668
+ this.containerElement.style.pointerEvents = 'none';
13669
+ }
13670
+ // When Privy fallback is off, the container just hosts PhantomProvider
13671
+ // without covering the viewport or blocking pointer events
13661
13672
  document.body.appendChild(this.containerElement);
13662
13673
  const that = this;
13663
13674
  const { PhantomProvider: ReactPhantomProvider, usePhantom, useConnect, useDisconnect, useModal, useSolana, useDiscoveredWallets, AddressType, darkTheme, lightTheme } = phantomReactSdk;
@@ -13927,6 +13938,31 @@ class PhantomWalletProvider {
13927
13938
  }
13928
13939
  }
13929
13940
  };
13941
+ const handleMobileWalletClick = async () => {
13942
+ that.loginInProgress = false;
13943
+ walletClickedRef.current = true;
13944
+ setShowWalletModal(false);
13945
+ if (that.onSwitchToMWA) {
13946
+ try {
13947
+ const mwaProvider = await that.onSwitchToMWA();
13948
+ const user = await mwaProvider.login();
13949
+ if (that.pendingLogin && user) {
13950
+ that.pendingLogin.resolve(user);
13951
+ that.pendingLogin = null;
13952
+ }
13953
+ else if (that.pendingLogin) {
13954
+ that.pendingLogin.reject(new Error('User cancelled login'));
13955
+ that.pendingLogin = null;
13956
+ }
13957
+ }
13958
+ catch (error) {
13959
+ if (that.pendingLogin) {
13960
+ that.pendingLogin.reject(error);
13961
+ that.pendingLogin = null;
13962
+ }
13963
+ }
13964
+ }
13965
+ };
13930
13966
  const handleCloseModal = () => {
13931
13967
  setShowWalletModal(false);
13932
13968
  if (that.loginInProgress && that.pendingLogin && !(phantom === null || phantom === void 0 ? void 0 : phantom.isConnected)) {
@@ -14002,6 +14038,37 @@ class PhantomWalletProvider {
14002
14038
  style: { width: '28px', height: '28px', borderRadius: '6px' },
14003
14039
  }), 'Open Phantom app'));
14004
14040
  }
14041
+ // Mobile Wallet Adapter button — shown on Android when MWA callback is available
14042
+ const isAndroid = /Android/i.test(navigator.userAgent);
14043
+ if (isAndroid && that.onSwitchToMWA) {
14044
+ walletButtons.push(React$1.createElement('button', {
14045
+ key: 'mobile-wallet',
14046
+ style: buttonStyle('mobile-wallet'),
14047
+ onClick: handleMobileWalletClick,
14048
+ onMouseEnter: () => setHoveredBtn('mobile-wallet'),
14049
+ onMouseLeave: () => setHoveredBtn(null),
14050
+ },
14051
+ // Mobile wallet icon (phone with wallet)
14052
+ React$1.createElement('svg', {
14053
+ width: '20', height: '20', viewBox: '0 0 24 24', fill: 'none',
14054
+ style: { flexShrink: '0' },
14055
+ },
14056
+ // Phone outline
14057
+ React$1.createElement('rect', {
14058
+ x: '5', y: '2', width: '14', height: '20', rx: '2',
14059
+ stroke: textColor, strokeWidth: '2', fill: 'none',
14060
+ }),
14061
+ // Screen line
14062
+ React$1.createElement('line', {
14063
+ x1: '5', y1: '6', x2: '19', y2: '6',
14064
+ stroke: textColor, strokeWidth: '1.5',
14065
+ }),
14066
+ // Wallet/shield checkmark
14067
+ React$1.createElement('path', {
14068
+ d: 'M9.5 12.5l2 2 3.5-3.5',
14069
+ stroke: textColor, strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', fill: 'none',
14070
+ })), 'Connect Mobile Wallet'));
14071
+ }
14005
14072
  // Email button (always shown in custom modal since enablePrivyFallback is true)
14006
14073
  walletButtons.push(React$1.createElement('button', {
14007
14074
  key: 'email-login',
@@ -34877,6 +34944,508 @@ class OffchainAuthProvider {
34877
34944
  }
34878
34945
  }
34879
34946
 
34947
+ /**
34948
+ * Detects whether the current environment is a mobile browser capable of
34949
+ * Mobile Wallet Adapter (MWA) communication.
34950
+ *
34951
+ * Returns true on Android browsers (Chrome, etc.) where MWA intents work,
34952
+ * or inside a Seeker/Saga in-app browser context.
34953
+ */
34954
+ function isMobileWalletAvailable() {
34955
+ if (typeof window === 'undefined' || typeof navigator === 'undefined')
34956
+ return false;
34957
+ const ua = navigator.userAgent || '';
34958
+ // Android browser — MWA uses Android intents
34959
+ const isAndroid = /Android/i.test(ua);
34960
+ // In-app browser inside a wallet app on Seeker/Saga
34961
+ const isWalletInAppBrowser = /SolanaWallet/i.test(ua) || /SeedVault/i.test(ua);
34962
+ return isAndroid || isWalletInAppBrowser;
34963
+ }
34964
+ // Dynamically imported MWA module
34965
+ let mwaModule = null;
34966
+ let mwaLoadPromise = null;
34967
+ async function loadMwaModule() {
34968
+ if (mwaModule)
34969
+ return;
34970
+ if (typeof window === 'undefined')
34971
+ return;
34972
+ if (mwaLoadPromise)
34973
+ return mwaLoadPromise;
34974
+ mwaLoadPromise = (async () => {
34975
+ try {
34976
+ mwaModule = await import('@solana-mobile/wallet-adapter-mobile');
34977
+ }
34978
+ catch (e) {
34979
+ console.warn('[SolanaMobileWallet] @solana-mobile/wallet-adapter-mobile not installed. Install it to enable Seeker wallet support.');
34980
+ throw new Error('Missing @solana-mobile/wallet-adapter-mobile dependency');
34981
+ }
34982
+ })();
34983
+ return mwaLoadPromise;
34984
+ }
34985
+ /**
34986
+ * Registers Mobile Wallet Adapter as a wallet-standard wallet so it appears
34987
+ * in wallet selection UIs and can be discovered by other wallet-standard consumers.
34988
+ *
34989
+ * Call this once at app startup (in a browser-only / non-SSR context).
34990
+ *
34991
+ * @param config - App identity and optional remote host authority for desktop QR code support
34992
+ */
34993
+ async function registerMobileWalletAdapter(config) {
34994
+ var _a;
34995
+ if (typeof window === 'undefined')
34996
+ return;
34997
+ try {
34998
+ const walletStandardMobile = await import('@solana-mobile/wallet-standard-mobile');
34999
+ const registerMwa = walletStandardMobile.registerMwa || ((_a = walletStandardMobile.default) === null || _a === void 0 ? void 0 : _a.registerMwa);
35000
+ if (!registerMwa) {
35001
+ console.warn('[SolanaMobileWallet] registerMwa not found in @solana-mobile/wallet-standard-mobile');
35002
+ return;
35003
+ }
35004
+ const options = {};
35005
+ if (config === null || config === void 0 ? void 0 : config.appIdentity) {
35006
+ options.appIdentity = config.appIdentity;
35007
+ }
35008
+ if (config === null || config === void 0 ? void 0 : config.chains) {
35009
+ options.chains = config.chains;
35010
+ }
35011
+ if (config === null || config === void 0 ? void 0 : config.remoteHostAuthority) {
35012
+ options.remoteHostAuthority = config.remoteHostAuthority;
35013
+ }
35014
+ // Use the library's default helpers if available
35015
+ if (walletStandardMobile.createDefaultAuthorizationCache) {
35016
+ options.authorizationCache = walletStandardMobile.createDefaultAuthorizationCache();
35017
+ }
35018
+ if (walletStandardMobile.createDefaultChainSelector) {
35019
+ options.chainSelector = walletStandardMobile.createDefaultChainSelector();
35020
+ }
35021
+ if (walletStandardMobile.createDefaultWalletNotFoundHandler) {
35022
+ options.onWalletNotFound = walletStandardMobile.createDefaultWalletNotFoundHandler();
35023
+ }
35024
+ registerMwa(options);
35025
+ }
35026
+ catch (e) {
35027
+ // @solana-mobile/wallet-standard-mobile is an optional dependency
35028
+ // Silently skip if not installed — the provider still works via
35029
+ // @solana-mobile/wallet-adapter-mobile directly
35030
+ console.debug('[SolanaMobileWallet] @solana-mobile/wallet-standard-mobile not available, skipping wallet-standard registration');
35031
+ }
35032
+ }
35033
+ /**
35034
+ * SolanaMobileWalletProvider implements the AuthProvider interface using the
35035
+ * Solana Mobile Wallet Adapter (MWA) protocol.
35036
+ *
35037
+ * This enables TaroBase dApps to work with any MWA-compliant wallet on Solana
35038
+ * mobile devices (Seeker, Saga) — including the native Seed Vault Wallet,
35039
+ * Phantom, Solflare, and any other wallet that implements the MWA protocol.
35040
+ *
35041
+ * The MWA protocol communicates with wallet apps via Android intents (on mobile)
35042
+ * or WebSocket relay (on desktop via QR code), eliminating the need to integrate
35043
+ * with each wallet individually.
35044
+ */
35045
+ class SolanaMobileWalletProvider {
35046
+ constructor(networkUrl = null, config = {}) {
35047
+ this.mwaAdapter = null;
35048
+ this.authorizedPublicKey = null;
35049
+ this.networkUrl = networkUrl;
35050
+ this.config = config;
35051
+ if (typeof window === 'undefined') {
35052
+ throw new Error('SolanaMobileWalletProvider can only be instantiated in a browser environment');
35053
+ }
35054
+ if (SolanaMobileWalletProvider.instance) {
35055
+ return SolanaMobileWalletProvider.instance;
35056
+ }
35057
+ SolanaMobileWalletProvider.instance = this;
35058
+ }
35059
+ static getInstance(networkUrl, config) {
35060
+ if (!SolanaMobileWalletProvider.instance) {
35061
+ new SolanaMobileWalletProvider(networkUrl, config);
35062
+ }
35063
+ return SolanaMobileWalletProvider.instance;
35064
+ }
35065
+ async ensureAdapter() {
35066
+ var _a;
35067
+ if ((_a = this.mwaAdapter) === null || _a === void 0 ? void 0 : _a.connected)
35068
+ return this.mwaAdapter;
35069
+ await loadMwaModule();
35070
+ const { SolanaMobileWalletAdapter, createDefaultAddressSelector, createDefaultAuthorizationResultCache } = mwaModule;
35071
+ if (!this.mwaAdapter) {
35072
+ const cluster = this.config.cluster || 'mainnet-beta';
35073
+ this.mwaAdapter = new SolanaMobileWalletAdapter({
35074
+ addressSelector: createDefaultAddressSelector(),
35075
+ appIdentity: this.config.appIdentity || {
35076
+ name: 'TaroBase App',
35077
+ uri: typeof window !== 'undefined' ? window.location.origin : undefined,
35078
+ },
35079
+ authorizationResultCache: createDefaultAuthorizationResultCache(),
35080
+ cluster,
35081
+ });
35082
+ }
35083
+ return this.mwaAdapter;
35084
+ }
35085
+ async login() {
35086
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
35087
+ setAuthLoading(true);
35088
+ try {
35089
+ const adapter = await this.ensureAdapter();
35090
+ // Connect triggers the MWA authorization flow — this opens the wallet app
35091
+ // via Android intent and asks the user to authorize this dApp
35092
+ await adapter.connect();
35093
+ const publicKey = ((_b = (_a = adapter.publicKey) === null || _a === void 0 ? void 0 : _a.toBase58) === null || _b === void 0 ? void 0 : _b.call(_a)) || ((_d = (_c = adapter.publicKey) === null || _c === void 0 ? void 0 : _c.toString) === null || _d === void 0 ? void 0 : _d.call(_c));
35094
+ if (!publicKey) {
35095
+ throw new Error('No public key returned from wallet');
35096
+ }
35097
+ this.authorizedPublicKey = publicKey;
35098
+ // Check if we already have a valid session
35099
+ const existingSession = await WebSessionManager.getSession();
35100
+ if (existingSession && existingSession.address === publicKey) {
35101
+ const user = { provider: this, address: publicKey };
35102
+ setCurrentUser(user);
35103
+ return user;
35104
+ }
35105
+ // Create new session with signature
35106
+ const nonce = await genAuthNonce();
35107
+ const messageText = await genSolanaMessage(publicKey, nonce);
35108
+ // MWA signMessage expects Uint8Array
35109
+ const messageBytes = new TextEncoder().encode(messageText);
35110
+ const signatureBytes = await adapter.signMessage(messageBytes);
35111
+ const signature = bufferExports.Buffer.from(signatureBytes).toString('base64');
35112
+ const createSessionResult = await createSessionWithSignature(publicKey, messageText, signature);
35113
+ await WebSessionManager.storeSession(publicKey, createSessionResult.accessToken, createSessionResult.idToken, createSessionResult.refreshToken);
35114
+ // Mark auth method
35115
+ try {
35116
+ localStorage.setItem('tarobase_last_auth_method', 'mobile-wallet-adapter');
35117
+ }
35118
+ catch (_k) { }
35119
+ const user = { provider: this, address: publicKey };
35120
+ setCurrentUser(user);
35121
+ return user;
35122
+ }
35123
+ catch (error) {
35124
+ const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
35125
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user rejected')) ||
35126
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user denied')) ||
35127
+ ((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user cancelled')) ||
35128
+ ((_h = error === null || error === void 0 ? void 0 : error.message) === null || _h === void 0 ? void 0 : _h.toLowerCase().includes('user canceled')) ||
35129
+ ((_j = error === null || error === void 0 ? void 0 : error.message) === null || _j === void 0 ? void 0 : _j.toLowerCase().includes('user declined'));
35130
+ if (!isUserRejection) {
35131
+ console.error('[SolanaMobileWallet] Login failed:', error);
35132
+ }
35133
+ throw error;
35134
+ }
35135
+ finally {
35136
+ setAuthLoading(false);
35137
+ }
35138
+ }
35139
+ async restoreSession() {
35140
+ const session = await WebSessionManager.getSession();
35141
+ if (session) {
35142
+ this.authorizedPublicKey = session.address;
35143
+ return { provider: this, address: session.address };
35144
+ }
35145
+ return null;
35146
+ }
35147
+ async logout() {
35148
+ var _a;
35149
+ try {
35150
+ if ((_a = this.mwaAdapter) === null || _a === void 0 ? void 0 : _a.connected) {
35151
+ await this.mwaAdapter.disconnect();
35152
+ }
35153
+ }
35154
+ catch (error) {
35155
+ console.error('[SolanaMobileWallet] Disconnect error:', error);
35156
+ }
35157
+ this.authorizedPublicKey = null;
35158
+ WebSessionManager.clearSession();
35159
+ setCurrentUser(null);
35160
+ }
35161
+ async signMessage(message) {
35162
+ var _a, _b;
35163
+ const adapter = await this.ensureAdapter();
35164
+ if (!adapter.connected) {
35165
+ await adapter.connect();
35166
+ }
35167
+ try {
35168
+ const messageBytes = new TextEncoder().encode(message);
35169
+ const signatureBytes = await adapter.signMessage(messageBytes);
35170
+ return bufferExports.Buffer.from(signatureBytes).toString('base64');
35171
+ }
35172
+ catch (error) {
35173
+ if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('not connected')) || ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not authorized'))) {
35174
+ await this.logout();
35175
+ throw new Error('Wallet connection lost. Please reconnect.');
35176
+ }
35177
+ throw new Error(`Failed to sign message: ${error.message}`);
35178
+ }
35179
+ }
35180
+ async signTransaction(transaction) {
35181
+ var _a, _b;
35182
+ const adapter = await this.ensureAdapter();
35183
+ if (!adapter.connected) {
35184
+ await adapter.connect();
35185
+ }
35186
+ // Ensure blockhash is set
35187
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
35188
+ if (isLegacyTransaction) {
35189
+ const legacyTx = transaction;
35190
+ if (!legacyTx.recentBlockhash) {
35191
+ const rpcUrl = this.getRpcUrl();
35192
+ const connection = new Connection(rpcUrl, 'confirmed');
35193
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
35194
+ legacyTx.recentBlockhash = blockhash;
35195
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
35196
+ }
35197
+ if (!legacyTx.feePayer && adapter.publicKey) {
35198
+ legacyTx.feePayer = adapter.publicKey;
35199
+ }
35200
+ }
35201
+ else {
35202
+ const versionedTx = transaction;
35203
+ if (!versionedTx.message.recentBlockhash) {
35204
+ const rpcUrl = this.getRpcUrl();
35205
+ const connection = new Connection(rpcUrl, 'confirmed');
35206
+ const { blockhash } = await connection.getLatestBlockhash('confirmed');
35207
+ versionedTx.message.recentBlockhash = blockhash;
35208
+ }
35209
+ }
35210
+ try {
35211
+ const signed = await adapter.signTransaction(transaction);
35212
+ return signed;
35213
+ }
35214
+ catch (error) {
35215
+ if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('not connected')) || ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not authorized'))) {
35216
+ await this.logout();
35217
+ throw new Error('Wallet connection lost. Please reconnect.');
35218
+ }
35219
+ throw new Error(`Failed to sign transaction: ${error.message}`);
35220
+ }
35221
+ }
35222
+ async signAndSubmitTransaction(transaction, feePayer) {
35223
+ var _a, _b, _c, _d, _e, _f;
35224
+ const adapter = await this.ensureAdapter();
35225
+ if (!adapter.connected) {
35226
+ await adapter.connect();
35227
+ }
35228
+ const rpcUrl = this.getRpcUrl();
35229
+ const connection = new Connection(rpcUrl, 'confirmed');
35230
+ const isSurfnet = rpcUrl === SURFNET_RPC_URL;
35231
+ try {
35232
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
35233
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
35234
+ if (isLegacyTransaction) {
35235
+ const legacyTx = transaction;
35236
+ legacyTx.recentBlockhash = blockhash;
35237
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
35238
+ if (!legacyTx.feePayer) {
35239
+ if (feePayer) {
35240
+ legacyTx.feePayer = feePayer;
35241
+ }
35242
+ else if (adapter.publicKey) {
35243
+ legacyTx.feePayer = adapter.publicKey;
35244
+ }
35245
+ }
35246
+ }
35247
+ else {
35248
+ const versionedTx = transaction;
35249
+ versionedTx.message.recentBlockhash = blockhash;
35250
+ }
35251
+ // On surfnet, sign then submit manually
35252
+ if (isSurfnet) {
35253
+ const signedTx = await adapter.signTransaction(transaction);
35254
+ const signature = await connection.sendRawTransaction(signedTx.serialize(), {
35255
+ preflightCommitment: 'confirmed'
35256
+ });
35257
+ const confirmation = await connection.confirmTransaction({
35258
+ signature,
35259
+ blockhash,
35260
+ lastValidBlockHeight,
35261
+ }, 'confirmed');
35262
+ if (confirmation.value.err) {
35263
+ throw new Error(`Transaction failed: ${confirmation.value.err.toString()}`);
35264
+ }
35265
+ return signature;
35266
+ }
35267
+ // MWA supports signAndSendTransaction natively — this lets the wallet
35268
+ // app submit the transaction directly, which is more reliable on mobile
35269
+ if (adapter.sendTransaction) {
35270
+ const signature = await adapter.sendTransaction(transaction, connection, {
35271
+ preflightCommitment: 'confirmed',
35272
+ });
35273
+ await confirmAndCheckTransaction(connection, signature);
35274
+ return signature;
35275
+ }
35276
+ // Fallback: sign then submit
35277
+ const signedTx = await adapter.signTransaction(transaction);
35278
+ const signature = await connection.sendRawTransaction(signedTx.serialize(), {
35279
+ preflightCommitment: 'confirmed'
35280
+ });
35281
+ await confirmAndCheckTransaction(connection, signature);
35282
+ return signature;
35283
+ }
35284
+ catch (error) {
35285
+ if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('not connected')) || ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not authorized'))) {
35286
+ await this.logout();
35287
+ throw new Error('Wallet connection lost. Please reconnect.');
35288
+ }
35289
+ const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
35290
+ ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes('user rejected')) ||
35291
+ ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('user denied')) ||
35292
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user cancelled')) ||
35293
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user canceled'));
35294
+ if (!isUserRejection) {
35295
+ console.error('[SolanaMobileWallet] Transaction failed:', error);
35296
+ }
35297
+ throw new Error(`Failed to execute transaction: ${error.message}`);
35298
+ }
35299
+ }
35300
+ async runTransaction(_evmTransactionData, solTransactionData, options) {
35301
+ var _a, _b, _c, _d, _e, _f, _g, _h;
35302
+ if (!solTransactionData) {
35303
+ throw new Error('Solana transaction data is required for mobile wallet');
35304
+ }
35305
+ const adapter = await this.ensureAdapter();
35306
+ if (!adapter.connected) {
35307
+ await this.login();
35308
+ }
35309
+ const rpcUrl = this.getRpcUrl(solTransactionData.network);
35310
+ const connection = new Connection(rpcUrl, 'confirmed');
35311
+ const isSurfnet = rpcUrl === SURFNET_RPC_URL;
35312
+ try {
35313
+ const publicKey = adapter.publicKey;
35314
+ if (!publicKey) {
35315
+ throw new Error('No wallet connected');
35316
+ }
35317
+ const remainingAccounts = convertRemainingAccounts(solTransactionData.txArgs[0].remainingAccounts);
35318
+ let app_id = solTransactionData.appId;
35319
+ if (typeof window !== 'undefined' && window.CUSTOM_TAROBASE_APP_ID_HEADER) {
35320
+ app_id = window.CUSTOM_TAROBASE_APP_ID_HEADER;
35321
+ }
35322
+ if (!app_id) {
35323
+ throw new Error('App ID is required');
35324
+ }
35325
+ // Create wallet adapter interface for Anchor
35326
+ const walletAdapter = {
35327
+ publicKey,
35328
+ signTransaction: async (tx) => {
35329
+ return await adapter.signTransaction(tx);
35330
+ },
35331
+ signAllTransactions: async (txs) => {
35332
+ return await adapter.signAllTransactions(txs);
35333
+ }
35334
+ };
35335
+ const anchorProvider = new anchor.AnchorProvider(connection, walletAdapter, anchor.AnchorProvider.defaultOptions());
35336
+ const finalDeduped = [];
35337
+ for (const acc of remainingAccounts) {
35338
+ const existing = finalDeduped.find((d) => d.pubkey.equals(acc.pubkey));
35339
+ if (existing) {
35340
+ existing.isSigner = existing.isSigner || acc.isSigner;
35341
+ existing.isWritable = existing.isWritable || acc.isWritable;
35342
+ }
35343
+ else {
35344
+ finalDeduped.push(acc);
35345
+ }
35346
+ }
35347
+ const { tx } = await buildSetDocumentsTransaction(connection, solTransactionData.txArgs[0].idl, anchorProvider, publicKey, {
35348
+ app_id,
35349
+ documents: solTransactionData.txArgs[0].setDocumentData,
35350
+ delete_paths: solTransactionData.txArgs[0].deletePaths,
35351
+ txData: solTransactionData.txArgs[0].txData
35352
+ }, finalDeduped, solTransactionData.lutKey, solTransactionData.preInstructions, false);
35353
+ if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
35354
+ const signedTx = await walletAdapter.signTransaction(tx);
35355
+ return {
35356
+ signedTransaction: signedTx,
35357
+ blockNumber: 0,
35358
+ gasUsed: '0',
35359
+ data: ''
35360
+ };
35361
+ }
35362
+ // On surfnet, sign + submit manually
35363
+ if (isSurfnet) {
35364
+ const signedTx = await walletAdapter.signTransaction(tx);
35365
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
35366
+ const signature = await connection.sendRawTransaction(signedTx.serialize(), {
35367
+ preflightCommitment: 'confirmed'
35368
+ });
35369
+ const confirmation = await connection.confirmTransaction({
35370
+ signature,
35371
+ blockhash,
35372
+ lastValidBlockHeight,
35373
+ }, 'confirmed');
35374
+ if (confirmation.value.err) {
35375
+ throw new Error(`Transaction failed: ${confirmation.value.err.toString()}`);
35376
+ }
35377
+ const txInfo = await connection.getParsedTransaction(signature, {
35378
+ maxSupportedTransactionVersion: 0,
35379
+ commitment: 'confirmed'
35380
+ });
35381
+ return {
35382
+ transactionSignature: signature,
35383
+ blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
35384
+ gasUsed: ((_a = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _a === void 0 ? void 0 : _a.fee.toString()) || '0',
35385
+ data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
35386
+ };
35387
+ }
35388
+ // Use MWA's sendTransaction for mobile-optimized submission
35389
+ let signature;
35390
+ if (adapter.sendTransaction) {
35391
+ signature = await adapter.sendTransaction(tx, connection, {
35392
+ preflightCommitment: 'confirmed',
35393
+ });
35394
+ }
35395
+ else {
35396
+ const signedTx = await walletAdapter.signTransaction(tx);
35397
+ signature = await connection.sendRawTransaction(signedTx.serialize(), {
35398
+ preflightCommitment: 'confirmed'
35399
+ });
35400
+ }
35401
+ const txInfo = await confirmAndCheckTransaction(connection, signature);
35402
+ return {
35403
+ transactionSignature: signature,
35404
+ blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
35405
+ gasUsed: ((_b = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _b === void 0 ? void 0 : _b.fee.toString()) || '0',
35406
+ data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
35407
+ };
35408
+ }
35409
+ catch (error) {
35410
+ if (((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('not connected')) || ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.includes('not authorized'))) {
35411
+ await this.logout();
35412
+ throw new Error('Wallet connection lost. Please reconnect.');
35413
+ }
35414
+ const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
35415
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user rejected')) ||
35416
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user denied')) ||
35417
+ ((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user cancelled')) ||
35418
+ ((_h = error === null || error === void 0 ? void 0 : error.message) === null || _h === void 0 ? void 0 : _h.toLowerCase().includes('user canceled'));
35419
+ if (!isUserRejection) {
35420
+ console.error('[SolanaMobileWallet] Transaction failed:', error);
35421
+ }
35422
+ throw new Error(`Failed to execute transaction: ${error.message}`);
35423
+ }
35424
+ }
35425
+ async getNativeMethods() {
35426
+ return this.mwaAdapter;
35427
+ }
35428
+ /* ----------------------------------------------------------- *
35429
+ * Private Helpers
35430
+ * ----------------------------------------------------------- */
35431
+ getRpcUrl(network) {
35432
+ if (this.networkUrl) {
35433
+ return this.networkUrl;
35434
+ }
35435
+ if (network === 'solana_devnet') {
35436
+ return SOLANA_DEVNET_RPC_URL;
35437
+ }
35438
+ else if (network === 'solana_mainnet') {
35439
+ return SOLANA_MAINNET_RPC_URL;
35440
+ }
35441
+ else if (network === 'surfnet') {
35442
+ return SURFNET_RPC_URL;
35443
+ }
35444
+ return SOLANA_MAINNET_RPC_URL;
35445
+ }
35446
+ }
35447
+ SolanaMobileWalletProvider.instance = null;
35448
+
34880
35449
  let currentAuthProvider = null;
34881
35450
  let currentAuthMethod = null;
34882
35451
  let initConfig = null;
@@ -34946,6 +35515,28 @@ async function hotSwapToPrivyProvider(config) {
34946
35515
  setAuthProviderInstance(provider);
34947
35516
  return privyProvider;
34948
35517
  }
35518
+ async function hotSwapToMWAProvider(config) {
35519
+ var _a, _b;
35520
+ const rpcUrl = (_a = config.rpcUrl) !== null && _a !== void 0 ? _a : null;
35521
+ const mwaConfig = (_b = config.mobileWalletConfig) !== null && _b !== void 0 ? _b : {
35522
+ appIdentity: {
35523
+ name: config.name || undefined,
35524
+ uri: typeof window !== 'undefined' ? window.location.origin : undefined,
35525
+ },
35526
+ };
35527
+ const mwaProvider = new SolanaMobileWalletProvider(rpcUrl, mwaConfig);
35528
+ let provider = mwaProvider;
35529
+ if (config.chain === "offchain") {
35530
+ provider = new OffchainAuthProvider(mwaProvider);
35531
+ }
35532
+ currentAuthProvider = provider;
35533
+ currentAuthMethod = 'mobile-wallet-adapter';
35534
+ const coreConfig = await getConfig();
35535
+ coreConfig.authProvider = provider;
35536
+ coreConfig.authMethod = 'mobile-wallet-adapter';
35537
+ setAuthProviderInstance(provider);
35538
+ return provider;
35539
+ }
34949
35540
  const SOLANA_DEVNET_RPC_URL = "https://idelle-8nxsep-fast-devnet.helius-rpc.com";
34950
35541
  const SOLANA_MAINNET_RPC_URL = "https://celestia-cegncv-fast-mainnet.helius-rpc.com";
34951
35542
  const SURFNET_RPC_URL = "https://surfpool.fly.dev";
@@ -34965,7 +35556,7 @@ async function getAuthProvider(config) {
34965
35556
  return currentAuthProvider;
34966
35557
  }
34967
35558
  // If the user previously logged in with a specific method, use that instead
34968
- const validAuthMethods = ['privy', 'phantom', 'wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'none'];
35559
+ const validAuthMethods = ['privy', 'phantom', 'wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'mobile-wallet-adapter', 'none'];
34969
35560
  const storedMethod = getStoredAuthMethod();
34970
35561
  const authMethod = (storedMethod && validAuthMethods.includes(storedMethod))
34971
35562
  ? storedMethod
@@ -34991,8 +35582,13 @@ async function getAuthProvider(config) {
34991
35582
  if ((_d = config.phantomConfig) === null || _d === void 0 ? void 0 : _d.enablePrivyFallback) {
34992
35583
  currentAuthProvider.onSwitchToPrivy =
34993
35584
  () => hotSwapToPrivyProvider(config);
35585
+ currentAuthProvider.onSwitchToMWA =
35586
+ () => hotSwapToMWAProvider(config);
34994
35587
  }
34995
35588
  break;
35589
+ case "mobile-wallet-adapter":
35590
+ currentAuthProvider = new SolanaMobileWalletProvider(rpcUrl, config.mobileWalletConfig);
35591
+ break;
34996
35592
  case "onboard":
34997
35593
  console.warn("Onboard auth is not yet supported.");
34998
35594
  break;
@@ -35208,5 +35804,5 @@ async function getIdToken() {
35208
35804
  return getIdToken$1(false);
35209
35805
  }
35210
35806
 
35211
- export { useAuth as A, getIdToken as B, PrivyWalletProvider as C, DEFAULT_TEST_ADDRESS as D, EventEmitter3 as E, buildSetDocumentsTransaction as F, clearCache as G, closeAllSubscriptions as H, convertRemainingAccounts as I, createSessionWithPrivy as J, createSessionWithSignature as K, genAuthNonce as L, MockAuthProvider as M, genSolanaMessage as N, OffchainAuthProvider as O, PhantomWalletProvider as P, getCachedData as Q, reconnectWithNewAuth as R, ServerSessionManager as S, refreshSession as T, signSessionCreateMessage as U, WebSessionManager as W, bs58 as a, bufferExports as b, onAuthLoadingChanged as c, getAuthLoading as d, logout as e, getConfig as f, getCurrentUser as g, getAuthProvider as h, init as i, get$2 as j, setMany as k, login as l, setFile as m, getFiles as n, onAuthStateChanged as o, runQueryMany as p, runExpression as q, runQuery as r, set$1 as s, runExpressionMany as t, signMessage as u, signTransaction as v, signAndSubmitTransaction as w, count as x, aggregate as y, subscribe as z };
35212
- //# sourceMappingURL=index-DVa7oS4V.esm.js.map
35807
+ export { useAuth as A, getIdToken as B, PrivyWalletProvider as C, DEFAULT_TEST_ADDRESS as D, EventEmitter3 as E, isMobileWalletAvailable as F, registerMobileWalletAdapter as G, ServerSessionManager as H, buildSetDocumentsTransaction as I, clearCache as J, closeAllSubscriptions as K, convertRemainingAccounts as L, MockAuthProvider as M, createSessionWithPrivy as N, OffchainAuthProvider as O, PhantomWalletProvider as P, createSessionWithSignature as Q, genAuthNonce as R, SolanaMobileWalletProvider as S, genSolanaMessage as T, getCachedData as U, reconnectWithNewAuth as V, WebSessionManager as W, refreshSession as X, signSessionCreateMessage as Y, bs58 as a, bufferExports as b, onAuthLoadingChanged as c, getAuthLoading as d, logout as e, getConfig as f, getCurrentUser as g, getAuthProvider as h, init as i, get$2 as j, setMany as k, login as l, setFile as m, getFiles as n, onAuthStateChanged as o, runQueryMany as p, runExpression as q, runQuery as r, set$1 as s, runExpressionMany as t, signMessage as u, signTransaction as v, signAndSubmitTransaction as w, count as x, aggregate as y, subscribe as z };
35808
+ //# sourceMappingURL=index-gZceh3R8.esm.js.map