@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.
@@ -10777,7 +10777,10 @@ function handleServerMessage(connection, message) {
10777
10777
  }
10778
10778
  function notifyCallbacks(subscription, data) {
10779
10779
  var _a;
10780
- for (const callback of subscription.callbacks) {
10780
+ // Snapshot the callbacks array so that unsubscriptions during
10781
+ // notification don't cause callbacks to be skipped.
10782
+ const callbacks = subscription.callbacks.slice();
10783
+ for (const callback of callbacks) {
10781
10784
  try {
10782
10785
  (_a = callback.onData) === null || _a === void 0 ? void 0 : _a.call(callback, data);
10783
10786
  }
@@ -13563,7 +13566,7 @@ async function loadDependencies() {
13563
13566
  const [reactModule, reactDomModule, phantomModule] = await Promise.all([
13564
13567
  import('react'),
13565
13568
  import('react-dom/client'),
13566
- Promise.resolve().then(function () { return require('./index-ChGj4uuO.js'); })
13569
+ Promise.resolve().then(function () { return require('./index-DDHlGslU.js'); })
13567
13570
  ]);
13568
13571
  // Extract default export from ESM module namespace
13569
13572
  // Dynamic import() returns { default: Module, ...exports }, not the module directly
@@ -13586,6 +13589,8 @@ class PhantomWalletProvider {
13586
13589
  this.initPromise = null;
13587
13590
  /** Callback to swap to a Privy provider when the user clicks "Log in with email" */
13588
13591
  this.onSwitchToPrivy = null;
13592
+ /** Callback to swap to a Mobile Wallet Adapter provider when the user clicks "Connect Mobile Wallet" */
13593
+ this.onSwitchToMWA = null;
13589
13594
  this.networkUrl = networkUrl;
13590
13595
  this.config = config;
13591
13596
  if (typeof window === 'undefined') {
@@ -13675,9 +13680,15 @@ class PhantomWalletProvider {
13675
13680
  this.containerElement.setAttribute('data-phantom-provider', 'true');
13676
13681
  // Keep Phantom UI above host overlays while avoiding global click-capture.
13677
13682
  this.containerElement.style.position = 'fixed';
13678
- this.containerElement.style.inset = '0';
13679
13683
  this.containerElement.style.zIndex = '2147483647';
13680
- this.containerElement.style.pointerEvents = 'none';
13684
+ if (this.config.enablePrivyFallback) {
13685
+ // Full-viewport overlay for custom modal; pointer-events: none lets
13686
+ // clicks pass through to page except where the modal sets 'auto'
13687
+ this.containerElement.style.inset = '0';
13688
+ this.containerElement.style.pointerEvents = 'none';
13689
+ }
13690
+ // When Privy fallback is off, the container just hosts PhantomProvider
13691
+ // without covering the viewport or blocking pointer events
13681
13692
  document.body.appendChild(this.containerElement);
13682
13693
  const that = this;
13683
13694
  const { PhantomProvider: ReactPhantomProvider, usePhantom, useConnect, useDisconnect, useModal, useSolana, useDiscoveredWallets, AddressType, darkTheme, lightTheme } = phantomReactSdk;
@@ -13947,6 +13958,31 @@ class PhantomWalletProvider {
13947
13958
  }
13948
13959
  }
13949
13960
  };
13961
+ const handleMobileWalletClick = async () => {
13962
+ that.loginInProgress = false;
13963
+ walletClickedRef.current = true;
13964
+ setShowWalletModal(false);
13965
+ if (that.onSwitchToMWA) {
13966
+ try {
13967
+ const mwaProvider = await that.onSwitchToMWA();
13968
+ const user = await mwaProvider.login();
13969
+ if (that.pendingLogin && user) {
13970
+ that.pendingLogin.resolve(user);
13971
+ that.pendingLogin = null;
13972
+ }
13973
+ else if (that.pendingLogin) {
13974
+ that.pendingLogin.reject(new Error('User cancelled login'));
13975
+ that.pendingLogin = null;
13976
+ }
13977
+ }
13978
+ catch (error) {
13979
+ if (that.pendingLogin) {
13980
+ that.pendingLogin.reject(error);
13981
+ that.pendingLogin = null;
13982
+ }
13983
+ }
13984
+ }
13985
+ };
13950
13986
  const handleCloseModal = () => {
13951
13987
  setShowWalletModal(false);
13952
13988
  if (that.loginInProgress && that.pendingLogin && !(phantom === null || phantom === void 0 ? void 0 : phantom.isConnected)) {
@@ -14022,6 +14058,37 @@ class PhantomWalletProvider {
14022
14058
  style: { width: '28px', height: '28px', borderRadius: '6px' },
14023
14059
  }), 'Open Phantom app'));
14024
14060
  }
14061
+ // Mobile Wallet Adapter button — shown on Android when MWA callback is available
14062
+ const isAndroid = /Android/i.test(navigator.userAgent);
14063
+ if (isAndroid && that.onSwitchToMWA) {
14064
+ walletButtons.push(React$1.createElement('button', {
14065
+ key: 'mobile-wallet',
14066
+ style: buttonStyle('mobile-wallet'),
14067
+ onClick: handleMobileWalletClick,
14068
+ onMouseEnter: () => setHoveredBtn('mobile-wallet'),
14069
+ onMouseLeave: () => setHoveredBtn(null),
14070
+ },
14071
+ // Mobile wallet icon (phone with wallet)
14072
+ React$1.createElement('svg', {
14073
+ width: '20', height: '20', viewBox: '0 0 24 24', fill: 'none',
14074
+ style: { flexShrink: '0' },
14075
+ },
14076
+ // Phone outline
14077
+ React$1.createElement('rect', {
14078
+ x: '5', y: '2', width: '14', height: '20', rx: '2',
14079
+ stroke: textColor, strokeWidth: '2', fill: 'none',
14080
+ }),
14081
+ // Screen line
14082
+ React$1.createElement('line', {
14083
+ x1: '5', y1: '6', x2: '19', y2: '6',
14084
+ stroke: textColor, strokeWidth: '1.5',
14085
+ }),
14086
+ // Wallet/shield checkmark
14087
+ React$1.createElement('path', {
14088
+ d: 'M9.5 12.5l2 2 3.5-3.5',
14089
+ stroke: textColor, strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', fill: 'none',
14090
+ })), 'Connect Mobile Wallet'));
14091
+ }
14025
14092
  // Email button (always shown in custom modal since enablePrivyFallback is true)
14026
14093
  walletButtons.push(React$1.createElement('button', {
14027
14094
  key: 'email-login',
@@ -34897,6 +34964,508 @@ class OffchainAuthProvider {
34897
34964
  }
34898
34965
  }
34899
34966
 
34967
+ /**
34968
+ * Detects whether the current environment is a mobile browser capable of
34969
+ * Mobile Wallet Adapter (MWA) communication.
34970
+ *
34971
+ * Returns true on Android browsers (Chrome, etc.) where MWA intents work,
34972
+ * or inside a Seeker/Saga in-app browser context.
34973
+ */
34974
+ function isMobileWalletAvailable() {
34975
+ if (typeof window === 'undefined' || typeof navigator === 'undefined')
34976
+ return false;
34977
+ const ua = navigator.userAgent || '';
34978
+ // Android browser — MWA uses Android intents
34979
+ const isAndroid = /Android/i.test(ua);
34980
+ // In-app browser inside a wallet app on Seeker/Saga
34981
+ const isWalletInAppBrowser = /SolanaWallet/i.test(ua) || /SeedVault/i.test(ua);
34982
+ return isAndroid || isWalletInAppBrowser;
34983
+ }
34984
+ // Dynamically imported MWA module
34985
+ let mwaModule = null;
34986
+ let mwaLoadPromise = null;
34987
+ async function loadMwaModule() {
34988
+ if (mwaModule)
34989
+ return;
34990
+ if (typeof window === 'undefined')
34991
+ return;
34992
+ if (mwaLoadPromise)
34993
+ return mwaLoadPromise;
34994
+ mwaLoadPromise = (async () => {
34995
+ try {
34996
+ mwaModule = await import('@solana-mobile/wallet-adapter-mobile');
34997
+ }
34998
+ catch (e) {
34999
+ console.warn('[SolanaMobileWallet] @solana-mobile/wallet-adapter-mobile not installed. Install it to enable Seeker wallet support.');
35000
+ throw new Error('Missing @solana-mobile/wallet-adapter-mobile dependency');
35001
+ }
35002
+ })();
35003
+ return mwaLoadPromise;
35004
+ }
35005
+ /**
35006
+ * Registers Mobile Wallet Adapter as a wallet-standard wallet so it appears
35007
+ * in wallet selection UIs and can be discovered by other wallet-standard consumers.
35008
+ *
35009
+ * Call this once at app startup (in a browser-only / non-SSR context).
35010
+ *
35011
+ * @param config - App identity and optional remote host authority for desktop QR code support
35012
+ */
35013
+ async function registerMobileWalletAdapter(config) {
35014
+ var _a;
35015
+ if (typeof window === 'undefined')
35016
+ return;
35017
+ try {
35018
+ const walletStandardMobile = await import('@solana-mobile/wallet-standard-mobile');
35019
+ const registerMwa = walletStandardMobile.registerMwa || ((_a = walletStandardMobile.default) === null || _a === void 0 ? void 0 : _a.registerMwa);
35020
+ if (!registerMwa) {
35021
+ console.warn('[SolanaMobileWallet] registerMwa not found in @solana-mobile/wallet-standard-mobile');
35022
+ return;
35023
+ }
35024
+ const options = {};
35025
+ if (config === null || config === void 0 ? void 0 : config.appIdentity) {
35026
+ options.appIdentity = config.appIdentity;
35027
+ }
35028
+ if (config === null || config === void 0 ? void 0 : config.chains) {
35029
+ options.chains = config.chains;
35030
+ }
35031
+ if (config === null || config === void 0 ? void 0 : config.remoteHostAuthority) {
35032
+ options.remoteHostAuthority = config.remoteHostAuthority;
35033
+ }
35034
+ // Use the library's default helpers if available
35035
+ if (walletStandardMobile.createDefaultAuthorizationCache) {
35036
+ options.authorizationCache = walletStandardMobile.createDefaultAuthorizationCache();
35037
+ }
35038
+ if (walletStandardMobile.createDefaultChainSelector) {
35039
+ options.chainSelector = walletStandardMobile.createDefaultChainSelector();
35040
+ }
35041
+ if (walletStandardMobile.createDefaultWalletNotFoundHandler) {
35042
+ options.onWalletNotFound = walletStandardMobile.createDefaultWalletNotFoundHandler();
35043
+ }
35044
+ registerMwa(options);
35045
+ }
35046
+ catch (e) {
35047
+ // @solana-mobile/wallet-standard-mobile is an optional dependency
35048
+ // Silently skip if not installed — the provider still works via
35049
+ // @solana-mobile/wallet-adapter-mobile directly
35050
+ console.debug('[SolanaMobileWallet] @solana-mobile/wallet-standard-mobile not available, skipping wallet-standard registration');
35051
+ }
35052
+ }
35053
+ /**
35054
+ * SolanaMobileWalletProvider implements the AuthProvider interface using the
35055
+ * Solana Mobile Wallet Adapter (MWA) protocol.
35056
+ *
35057
+ * This enables TaroBase dApps to work with any MWA-compliant wallet on Solana
35058
+ * mobile devices (Seeker, Saga) — including the native Seed Vault Wallet,
35059
+ * Phantom, Solflare, and any other wallet that implements the MWA protocol.
35060
+ *
35061
+ * The MWA protocol communicates with wallet apps via Android intents (on mobile)
35062
+ * or WebSocket relay (on desktop via QR code), eliminating the need to integrate
35063
+ * with each wallet individually.
35064
+ */
35065
+ class SolanaMobileWalletProvider {
35066
+ constructor(networkUrl = null, config = {}) {
35067
+ this.mwaAdapter = null;
35068
+ this.authorizedPublicKey = null;
35069
+ this.networkUrl = networkUrl;
35070
+ this.config = config;
35071
+ if (typeof window === 'undefined') {
35072
+ throw new Error('SolanaMobileWalletProvider can only be instantiated in a browser environment');
35073
+ }
35074
+ if (SolanaMobileWalletProvider.instance) {
35075
+ return SolanaMobileWalletProvider.instance;
35076
+ }
35077
+ SolanaMobileWalletProvider.instance = this;
35078
+ }
35079
+ static getInstance(networkUrl, config) {
35080
+ if (!SolanaMobileWalletProvider.instance) {
35081
+ new SolanaMobileWalletProvider(networkUrl, config);
35082
+ }
35083
+ return SolanaMobileWalletProvider.instance;
35084
+ }
35085
+ async ensureAdapter() {
35086
+ var _a;
35087
+ if ((_a = this.mwaAdapter) === null || _a === void 0 ? void 0 : _a.connected)
35088
+ return this.mwaAdapter;
35089
+ await loadMwaModule();
35090
+ const { SolanaMobileWalletAdapter, createDefaultAddressSelector, createDefaultAuthorizationResultCache } = mwaModule;
35091
+ if (!this.mwaAdapter) {
35092
+ const cluster = this.config.cluster || 'mainnet-beta';
35093
+ this.mwaAdapter = new SolanaMobileWalletAdapter({
35094
+ addressSelector: createDefaultAddressSelector(),
35095
+ appIdentity: this.config.appIdentity || {
35096
+ name: 'TaroBase App',
35097
+ uri: typeof window !== 'undefined' ? window.location.origin : undefined,
35098
+ },
35099
+ authorizationResultCache: createDefaultAuthorizationResultCache(),
35100
+ cluster,
35101
+ });
35102
+ }
35103
+ return this.mwaAdapter;
35104
+ }
35105
+ async login() {
35106
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
35107
+ setAuthLoading(true);
35108
+ try {
35109
+ const adapter = await this.ensureAdapter();
35110
+ // Connect triggers the MWA authorization flow — this opens the wallet app
35111
+ // via Android intent and asks the user to authorize this dApp
35112
+ await adapter.connect();
35113
+ 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));
35114
+ if (!publicKey) {
35115
+ throw new Error('No public key returned from wallet');
35116
+ }
35117
+ this.authorizedPublicKey = publicKey;
35118
+ // Check if we already have a valid session
35119
+ const existingSession = await WebSessionManager.getSession();
35120
+ if (existingSession && existingSession.address === publicKey) {
35121
+ const user = { provider: this, address: publicKey };
35122
+ setCurrentUser(user);
35123
+ return user;
35124
+ }
35125
+ // Create new session with signature
35126
+ const nonce = await genAuthNonce();
35127
+ const messageText = await genSolanaMessage(publicKey, nonce);
35128
+ // MWA signMessage expects Uint8Array
35129
+ const messageBytes = new TextEncoder().encode(messageText);
35130
+ const signatureBytes = await adapter.signMessage(messageBytes);
35131
+ const signature = bufferExports.Buffer.from(signatureBytes).toString('base64');
35132
+ const createSessionResult = await createSessionWithSignature(publicKey, messageText, signature);
35133
+ await WebSessionManager.storeSession(publicKey, createSessionResult.accessToken, createSessionResult.idToken, createSessionResult.refreshToken);
35134
+ // Mark auth method
35135
+ try {
35136
+ localStorage.setItem('tarobase_last_auth_method', 'mobile-wallet-adapter');
35137
+ }
35138
+ catch (_k) { }
35139
+ const user = { provider: this, address: publicKey };
35140
+ setCurrentUser(user);
35141
+ return user;
35142
+ }
35143
+ catch (error) {
35144
+ const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
35145
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user rejected')) ||
35146
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user denied')) ||
35147
+ ((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user cancelled')) ||
35148
+ ((_h = error === null || error === void 0 ? void 0 : error.message) === null || _h === void 0 ? void 0 : _h.toLowerCase().includes('user canceled')) ||
35149
+ ((_j = error === null || error === void 0 ? void 0 : error.message) === null || _j === void 0 ? void 0 : _j.toLowerCase().includes('user declined'));
35150
+ if (!isUserRejection) {
35151
+ console.error('[SolanaMobileWallet] Login failed:', error);
35152
+ }
35153
+ throw error;
35154
+ }
35155
+ finally {
35156
+ setAuthLoading(false);
35157
+ }
35158
+ }
35159
+ async restoreSession() {
35160
+ const session = await WebSessionManager.getSession();
35161
+ if (session) {
35162
+ this.authorizedPublicKey = session.address;
35163
+ return { provider: this, address: session.address };
35164
+ }
35165
+ return null;
35166
+ }
35167
+ async logout() {
35168
+ var _a;
35169
+ try {
35170
+ if ((_a = this.mwaAdapter) === null || _a === void 0 ? void 0 : _a.connected) {
35171
+ await this.mwaAdapter.disconnect();
35172
+ }
35173
+ }
35174
+ catch (error) {
35175
+ console.error('[SolanaMobileWallet] Disconnect error:', error);
35176
+ }
35177
+ this.authorizedPublicKey = null;
35178
+ WebSessionManager.clearSession();
35179
+ setCurrentUser(null);
35180
+ }
35181
+ async signMessage(message) {
35182
+ var _a, _b;
35183
+ const adapter = await this.ensureAdapter();
35184
+ if (!adapter.connected) {
35185
+ await adapter.connect();
35186
+ }
35187
+ try {
35188
+ const messageBytes = new TextEncoder().encode(message);
35189
+ const signatureBytes = await adapter.signMessage(messageBytes);
35190
+ return bufferExports.Buffer.from(signatureBytes).toString('base64');
35191
+ }
35192
+ catch (error) {
35193
+ 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'))) {
35194
+ await this.logout();
35195
+ throw new Error('Wallet connection lost. Please reconnect.');
35196
+ }
35197
+ throw new Error(`Failed to sign message: ${error.message}`);
35198
+ }
35199
+ }
35200
+ async signTransaction(transaction) {
35201
+ var _a, _b;
35202
+ const adapter = await this.ensureAdapter();
35203
+ if (!adapter.connected) {
35204
+ await adapter.connect();
35205
+ }
35206
+ // Ensure blockhash is set
35207
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
35208
+ if (isLegacyTransaction) {
35209
+ const legacyTx = transaction;
35210
+ if (!legacyTx.recentBlockhash) {
35211
+ const rpcUrl = this.getRpcUrl();
35212
+ const connection = new web3_js.Connection(rpcUrl, 'confirmed');
35213
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
35214
+ legacyTx.recentBlockhash = blockhash;
35215
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
35216
+ }
35217
+ if (!legacyTx.feePayer && adapter.publicKey) {
35218
+ legacyTx.feePayer = adapter.publicKey;
35219
+ }
35220
+ }
35221
+ else {
35222
+ const versionedTx = transaction;
35223
+ if (!versionedTx.message.recentBlockhash) {
35224
+ const rpcUrl = this.getRpcUrl();
35225
+ const connection = new web3_js.Connection(rpcUrl, 'confirmed');
35226
+ const { blockhash } = await connection.getLatestBlockhash('confirmed');
35227
+ versionedTx.message.recentBlockhash = blockhash;
35228
+ }
35229
+ }
35230
+ try {
35231
+ const signed = await adapter.signTransaction(transaction);
35232
+ return signed;
35233
+ }
35234
+ catch (error) {
35235
+ 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'))) {
35236
+ await this.logout();
35237
+ throw new Error('Wallet connection lost. Please reconnect.');
35238
+ }
35239
+ throw new Error(`Failed to sign transaction: ${error.message}`);
35240
+ }
35241
+ }
35242
+ async signAndSubmitTransaction(transaction, feePayer) {
35243
+ var _a, _b, _c, _d, _e, _f;
35244
+ const adapter = await this.ensureAdapter();
35245
+ if (!adapter.connected) {
35246
+ await adapter.connect();
35247
+ }
35248
+ const rpcUrl = this.getRpcUrl();
35249
+ const connection = new web3_js.Connection(rpcUrl, 'confirmed');
35250
+ const isSurfnet = rpcUrl === SURFNET_RPC_URL;
35251
+ try {
35252
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
35253
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
35254
+ if (isLegacyTransaction) {
35255
+ const legacyTx = transaction;
35256
+ legacyTx.recentBlockhash = blockhash;
35257
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
35258
+ if (!legacyTx.feePayer) {
35259
+ if (feePayer) {
35260
+ legacyTx.feePayer = feePayer;
35261
+ }
35262
+ else if (adapter.publicKey) {
35263
+ legacyTx.feePayer = adapter.publicKey;
35264
+ }
35265
+ }
35266
+ }
35267
+ else {
35268
+ const versionedTx = transaction;
35269
+ versionedTx.message.recentBlockhash = blockhash;
35270
+ }
35271
+ // On surfnet, sign then submit manually
35272
+ if (isSurfnet) {
35273
+ const signedTx = await adapter.signTransaction(transaction);
35274
+ const signature = await connection.sendRawTransaction(signedTx.serialize(), {
35275
+ preflightCommitment: 'confirmed'
35276
+ });
35277
+ const confirmation = await connection.confirmTransaction({
35278
+ signature,
35279
+ blockhash,
35280
+ lastValidBlockHeight,
35281
+ }, 'confirmed');
35282
+ if (confirmation.value.err) {
35283
+ throw new Error(`Transaction failed: ${confirmation.value.err.toString()}`);
35284
+ }
35285
+ return signature;
35286
+ }
35287
+ // MWA supports signAndSendTransaction natively — this lets the wallet
35288
+ // app submit the transaction directly, which is more reliable on mobile
35289
+ if (adapter.sendTransaction) {
35290
+ const signature = await adapter.sendTransaction(transaction, connection, {
35291
+ preflightCommitment: 'confirmed',
35292
+ });
35293
+ await confirmAndCheckTransaction(connection, signature);
35294
+ return signature;
35295
+ }
35296
+ // Fallback: sign then submit
35297
+ const signedTx = await adapter.signTransaction(transaction);
35298
+ const signature = await connection.sendRawTransaction(signedTx.serialize(), {
35299
+ preflightCommitment: 'confirmed'
35300
+ });
35301
+ await confirmAndCheckTransaction(connection, signature);
35302
+ return signature;
35303
+ }
35304
+ catch (error) {
35305
+ 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'))) {
35306
+ await this.logout();
35307
+ throw new Error('Wallet connection lost. Please reconnect.');
35308
+ }
35309
+ const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
35310
+ ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes('user rejected')) ||
35311
+ ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('user denied')) ||
35312
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user cancelled')) ||
35313
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user canceled'));
35314
+ if (!isUserRejection) {
35315
+ console.error('[SolanaMobileWallet] Transaction failed:', error);
35316
+ }
35317
+ throw new Error(`Failed to execute transaction: ${error.message}`);
35318
+ }
35319
+ }
35320
+ async runTransaction(_evmTransactionData, solTransactionData, options) {
35321
+ var _a, _b, _c, _d, _e, _f, _g, _h;
35322
+ if (!solTransactionData) {
35323
+ throw new Error('Solana transaction data is required for mobile wallet');
35324
+ }
35325
+ const adapter = await this.ensureAdapter();
35326
+ if (!adapter.connected) {
35327
+ await this.login();
35328
+ }
35329
+ const rpcUrl = this.getRpcUrl(solTransactionData.network);
35330
+ const connection = new web3_js.Connection(rpcUrl, 'confirmed');
35331
+ const isSurfnet = rpcUrl === SURFNET_RPC_URL;
35332
+ try {
35333
+ const publicKey = adapter.publicKey;
35334
+ if (!publicKey) {
35335
+ throw new Error('No wallet connected');
35336
+ }
35337
+ const remainingAccounts = convertRemainingAccounts(solTransactionData.txArgs[0].remainingAccounts);
35338
+ let app_id = solTransactionData.appId;
35339
+ if (typeof window !== 'undefined' && window.CUSTOM_TAROBASE_APP_ID_HEADER) {
35340
+ app_id = window.CUSTOM_TAROBASE_APP_ID_HEADER;
35341
+ }
35342
+ if (!app_id) {
35343
+ throw new Error('App ID is required');
35344
+ }
35345
+ // Create wallet adapter interface for Anchor
35346
+ const walletAdapter = {
35347
+ publicKey,
35348
+ signTransaction: async (tx) => {
35349
+ return await adapter.signTransaction(tx);
35350
+ },
35351
+ signAllTransactions: async (txs) => {
35352
+ return await adapter.signAllTransactions(txs);
35353
+ }
35354
+ };
35355
+ const anchorProvider = new anchor__namespace.AnchorProvider(connection, walletAdapter, anchor__namespace.AnchorProvider.defaultOptions());
35356
+ const finalDeduped = [];
35357
+ for (const acc of remainingAccounts) {
35358
+ const existing = finalDeduped.find((d) => d.pubkey.equals(acc.pubkey));
35359
+ if (existing) {
35360
+ existing.isSigner = existing.isSigner || acc.isSigner;
35361
+ existing.isWritable = existing.isWritable || acc.isWritable;
35362
+ }
35363
+ else {
35364
+ finalDeduped.push(acc);
35365
+ }
35366
+ }
35367
+ const { tx } = await buildSetDocumentsTransaction(connection, solTransactionData.txArgs[0].idl, anchorProvider, publicKey, {
35368
+ app_id,
35369
+ documents: solTransactionData.txArgs[0].setDocumentData,
35370
+ delete_paths: solTransactionData.txArgs[0].deletePaths,
35371
+ txData: solTransactionData.txArgs[0].txData
35372
+ }, finalDeduped, solTransactionData.lutKey, solTransactionData.preInstructions, false);
35373
+ if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
35374
+ const signedTx = await walletAdapter.signTransaction(tx);
35375
+ return {
35376
+ signedTransaction: signedTx,
35377
+ blockNumber: 0,
35378
+ gasUsed: '0',
35379
+ data: ''
35380
+ };
35381
+ }
35382
+ // On surfnet, sign + submit manually
35383
+ if (isSurfnet) {
35384
+ const signedTx = await walletAdapter.signTransaction(tx);
35385
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
35386
+ const signature = await connection.sendRawTransaction(signedTx.serialize(), {
35387
+ preflightCommitment: 'confirmed'
35388
+ });
35389
+ const confirmation = await connection.confirmTransaction({
35390
+ signature,
35391
+ blockhash,
35392
+ lastValidBlockHeight,
35393
+ }, 'confirmed');
35394
+ if (confirmation.value.err) {
35395
+ throw new Error(`Transaction failed: ${confirmation.value.err.toString()}`);
35396
+ }
35397
+ const txInfo = await connection.getParsedTransaction(signature, {
35398
+ maxSupportedTransactionVersion: 0,
35399
+ commitment: 'confirmed'
35400
+ });
35401
+ return {
35402
+ transactionSignature: signature,
35403
+ blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
35404
+ gasUsed: ((_a = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _a === void 0 ? void 0 : _a.fee.toString()) || '0',
35405
+ data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
35406
+ };
35407
+ }
35408
+ // Use MWA's sendTransaction for mobile-optimized submission
35409
+ let signature;
35410
+ if (adapter.sendTransaction) {
35411
+ signature = await adapter.sendTransaction(tx, connection, {
35412
+ preflightCommitment: 'confirmed',
35413
+ });
35414
+ }
35415
+ else {
35416
+ const signedTx = await walletAdapter.signTransaction(tx);
35417
+ signature = await connection.sendRawTransaction(signedTx.serialize(), {
35418
+ preflightCommitment: 'confirmed'
35419
+ });
35420
+ }
35421
+ const txInfo = await confirmAndCheckTransaction(connection, signature);
35422
+ return {
35423
+ transactionSignature: signature,
35424
+ blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
35425
+ gasUsed: ((_b = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _b === void 0 ? void 0 : _b.fee.toString()) || '0',
35426
+ data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
35427
+ };
35428
+ }
35429
+ catch (error) {
35430
+ 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'))) {
35431
+ await this.logout();
35432
+ throw new Error('Wallet connection lost. Please reconnect.');
35433
+ }
35434
+ const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
35435
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user rejected')) ||
35436
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user denied')) ||
35437
+ ((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user cancelled')) ||
35438
+ ((_h = error === null || error === void 0 ? void 0 : error.message) === null || _h === void 0 ? void 0 : _h.toLowerCase().includes('user canceled'));
35439
+ if (!isUserRejection) {
35440
+ console.error('[SolanaMobileWallet] Transaction failed:', error);
35441
+ }
35442
+ throw new Error(`Failed to execute transaction: ${error.message}`);
35443
+ }
35444
+ }
35445
+ async getNativeMethods() {
35446
+ return this.mwaAdapter;
35447
+ }
35448
+ /* ----------------------------------------------------------- *
35449
+ * Private Helpers
35450
+ * ----------------------------------------------------------- */
35451
+ getRpcUrl(network) {
35452
+ if (this.networkUrl) {
35453
+ return this.networkUrl;
35454
+ }
35455
+ if (network === 'solana_devnet') {
35456
+ return SOLANA_DEVNET_RPC_URL;
35457
+ }
35458
+ else if (network === 'solana_mainnet') {
35459
+ return SOLANA_MAINNET_RPC_URL;
35460
+ }
35461
+ else if (network === 'surfnet') {
35462
+ return SURFNET_RPC_URL;
35463
+ }
35464
+ return SOLANA_MAINNET_RPC_URL;
35465
+ }
35466
+ }
35467
+ SolanaMobileWalletProvider.instance = null;
35468
+
34900
35469
  let currentAuthProvider = null;
34901
35470
  let currentAuthMethod = null;
34902
35471
  let initConfig = null;
@@ -34966,6 +35535,28 @@ async function hotSwapToPrivyProvider(config) {
34966
35535
  setAuthProviderInstance(provider);
34967
35536
  return privyProvider;
34968
35537
  }
35538
+ async function hotSwapToMWAProvider(config) {
35539
+ var _a, _b;
35540
+ const rpcUrl = (_a = config.rpcUrl) !== null && _a !== void 0 ? _a : null;
35541
+ const mwaConfig = (_b = config.mobileWalletConfig) !== null && _b !== void 0 ? _b : {
35542
+ appIdentity: {
35543
+ name: config.name || undefined,
35544
+ uri: typeof window !== 'undefined' ? window.location.origin : undefined,
35545
+ },
35546
+ };
35547
+ const mwaProvider = new SolanaMobileWalletProvider(rpcUrl, mwaConfig);
35548
+ let provider = mwaProvider;
35549
+ if (config.chain === "offchain") {
35550
+ provider = new OffchainAuthProvider(mwaProvider);
35551
+ }
35552
+ currentAuthProvider = provider;
35553
+ currentAuthMethod = 'mobile-wallet-adapter';
35554
+ const coreConfig = await getConfig();
35555
+ coreConfig.authProvider = provider;
35556
+ coreConfig.authMethod = 'mobile-wallet-adapter';
35557
+ setAuthProviderInstance(provider);
35558
+ return provider;
35559
+ }
34969
35560
  const SOLANA_DEVNET_RPC_URL = "https://idelle-8nxsep-fast-devnet.helius-rpc.com";
34970
35561
  const SOLANA_MAINNET_RPC_URL = "https://celestia-cegncv-fast-mainnet.helius-rpc.com";
34971
35562
  const SURFNET_RPC_URL = "https://surfpool.fly.dev";
@@ -34985,7 +35576,7 @@ async function getAuthProvider(config) {
34985
35576
  return currentAuthProvider;
34986
35577
  }
34987
35578
  // If the user previously logged in with a specific method, use that instead
34988
- const validAuthMethods = ['privy', 'phantom', 'wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'none'];
35579
+ const validAuthMethods = ['privy', 'phantom', 'wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'mobile-wallet-adapter', 'none'];
34989
35580
  const storedMethod = getStoredAuthMethod();
34990
35581
  const authMethod = (storedMethod && validAuthMethods.includes(storedMethod))
34991
35582
  ? storedMethod
@@ -35011,8 +35602,13 @@ async function getAuthProvider(config) {
35011
35602
  if ((_d = config.phantomConfig) === null || _d === void 0 ? void 0 : _d.enablePrivyFallback) {
35012
35603
  currentAuthProvider.onSwitchToPrivy =
35013
35604
  () => hotSwapToPrivyProvider(config);
35605
+ currentAuthProvider.onSwitchToMWA =
35606
+ () => hotSwapToMWAProvider(config);
35014
35607
  }
35015
35608
  break;
35609
+ case "mobile-wallet-adapter":
35610
+ currentAuthProvider = new SolanaMobileWalletProvider(rpcUrl, config.mobileWalletConfig);
35611
+ break;
35016
35612
  case "onboard":
35017
35613
  console.warn("Onboard auth is not yet supported.");
35018
35614
  break;
@@ -35235,6 +35831,7 @@ exports.OffchainAuthProvider = OffchainAuthProvider;
35235
35831
  exports.PhantomWalletProvider = PhantomWalletProvider;
35236
35832
  exports.PrivyWalletProvider = PrivyWalletProvider;
35237
35833
  exports.ServerSessionManager = ServerSessionManager;
35834
+ exports.SolanaMobileWalletProvider = SolanaMobileWalletProvider;
35238
35835
  exports.WebSessionManager = WebSessionManager;
35239
35836
  exports.aggregate = aggregate;
35240
35837
  exports.bs58 = bs58;
@@ -35257,12 +35854,14 @@ exports.getCurrentUser = getCurrentUser;
35257
35854
  exports.getFiles = getFiles;
35258
35855
  exports.getIdToken = getIdToken;
35259
35856
  exports.init = init;
35857
+ exports.isMobileWalletAvailable = isMobileWalletAvailable;
35260
35858
  exports.login = login;
35261
35859
  exports.logout = logout;
35262
35860
  exports.onAuthLoadingChanged = onAuthLoadingChanged;
35263
35861
  exports.onAuthStateChanged = onAuthStateChanged;
35264
35862
  exports.reconnectWithNewAuth = reconnectWithNewAuth;
35265
35863
  exports.refreshSession = refreshSession;
35864
+ exports.registerMobileWalletAdapter = registerMobileWalletAdapter;
35266
35865
  exports.runExpression = runExpression;
35267
35866
  exports.runExpressionMany = runExpressionMany;
35268
35867
  exports.runQuery = runQuery;
@@ -35276,4 +35875,4 @@ exports.signSessionCreateMessage = signSessionCreateMessage;
35276
35875
  exports.signTransaction = signTransaction;
35277
35876
  exports.subscribe = subscribe;
35278
35877
  exports.useAuth = useAuth;
35279
- //# sourceMappingURL=index-YzZ1QavD.js.map
35878
+ //# sourceMappingURL=index-BZpQdkSL.js.map