@pooflabs/web 0.0.86 → 0.0.87

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/dist/auth/providers/solana-mobile-wallet-provider.d.ts +43 -0
  2. package/dist/{index-D-Wbwevj.js → index-B-x9RTF7.js} +2 -2
  3. package/dist/index-B-x9RTF7.js.map +1 -0
  4. package/dist/{index-BHkED2YI.js → index-BKN0IwAx.js} +3054 -300
  5. package/dist/index-BKN0IwAx.js.map +1 -0
  6. package/dist/{index-BQUfNEiY.esm.js → index-BTwX7FYW.esm.js} +417 -74
  7. package/dist/index-BTwX7FYW.esm.js.map +1 -0
  8. package/dist/{index-DUn32Hkh.js → index-DYBdUxnT.js} +3055 -301
  9. package/dist/index-DYBdUxnT.js.map +1 -0
  10. package/dist/{index-hEc5_KoM.js → index-Dj1tZr6X.js} +418 -73
  11. package/dist/index-Dj1tZr6X.js.map +1 -0
  12. package/dist/{index-DK28JaJm.esm.js → index-DofM-ue2.esm.js} +3054 -301
  13. package/dist/index-DofM-ue2.esm.js.map +1 -0
  14. package/dist/index-_k6pjuwx.esm.js +6 -0
  15. package/dist/index-_k6pjuwx.esm.js.map +1 -0
  16. package/dist/{index-Cfp30Jm_.esm.js → index-x7a-wH2l.esm.js} +3055 -300
  17. package/dist/index-x7a-wH2l.esm.js.map +1 -0
  18. package/dist/{index.browser-DQqKPfDA.esm.js → index.browser-Cndx2raY.esm.js} +506 -1876
  19. package/dist/index.browser-Cndx2raY.esm.js.map +1 -0
  20. package/dist/{index.browser-CbawPvh6.js → index.browser-D7-FFk3q.js} +506 -1876
  21. package/dist/index.browser-D7-FFk3q.js.map +1 -0
  22. package/dist/{index.browser-DD8pg_L2.js → index.browser-DlA-NKvf.js} +1223 -2565
  23. package/dist/index.browser-DlA-NKvf.js.map +1 -0
  24. package/dist/{index.browser-C9gHoUen.esm.js → index.browser-nVGFrIHK.esm.js} +1223 -2565
  25. package/dist/index.browser-nVGFrIHK.esm.js.map +1 -0
  26. package/dist/index.esm.js +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/{index.native-BItnSD47.esm.js → index.native-19VsREMJ.esm.js} +43 -62
  29. package/dist/index.native-19VsREMJ.esm.js.map +1 -0
  30. package/dist/{index.native-7hiNiSyC.js → index.native-D8vj3Lbr.js} +44 -61
  31. package/dist/index.native-D8vj3Lbr.js.map +1 -0
  32. package/dist/index.native.esm.js +1 -1
  33. package/dist/index.native.js +1 -1
  34. package/dist/{phantom-wallet-provider-CjvLq_2_.js → phantom-wallet-provider-BlZZa_3s.js} +4 -4
  35. package/dist/{phantom-wallet-provider-CjvLq_2_.js.map → phantom-wallet-provider-BlZZa_3s.js.map} +1 -1
  36. package/dist/{phantom-wallet-provider-DE3vit2Z.esm.js → phantom-wallet-provider-Bz3qEFzX.esm.js} +4 -4
  37. package/dist/{phantom-wallet-provider-DE3vit2Z.esm.js.map → phantom-wallet-provider-Bz3qEFzX.esm.js.map} +1 -1
  38. package/dist/{privy-wallet-provider-DFZaQPss.js → privy-wallet-provider-CqCgq7uT.js} +3 -3
  39. package/dist/privy-wallet-provider-CqCgq7uT.js.map +1 -0
  40. package/dist/{privy-wallet-provider-ip2pqo_U.esm.js → privy-wallet-provider-DgNFzioA.esm.js} +3 -3
  41. package/dist/privy-wallet-provider-DgNFzioA.esm.js.map +1 -0
  42. package/dist/{solana-mobile-wallet-provider-D7BbSpez.esm.js → solana-mobile-wallet-provider-EeQsBTdr.esm.js} +378 -16
  43. package/dist/solana-mobile-wallet-provider-EeQsBTdr.esm.js.map +1 -0
  44. package/dist/{solana-mobile-wallet-provider-DwER68Rz.js → solana-mobile-wallet-provider-VqIGfdMV.js} +378 -16
  45. package/dist/solana-mobile-wallet-provider-VqIGfdMV.js.map +1 -0
  46. package/package.json +1 -1
  47. package/dist/index-BHkED2YI.js.map +0 -1
  48. package/dist/index-BQUfNEiY.esm.js.map +0 -1
  49. package/dist/index-Cfp30Jm_.esm.js.map +0 -1
  50. package/dist/index-D-Wbwevj.js.map +0 -1
  51. package/dist/index-DK28JaJm.esm.js.map +0 -1
  52. package/dist/index-DKyWaxCB.esm.js +0 -6
  53. package/dist/index-DKyWaxCB.esm.js.map +0 -1
  54. package/dist/index-DUn32Hkh.js.map +0 -1
  55. package/dist/index-hEc5_KoM.js.map +0 -1
  56. package/dist/index.browser-C9gHoUen.esm.js.map +0 -1
  57. package/dist/index.browser-CbawPvh6.js.map +0 -1
  58. package/dist/index.browser-DD8pg_L2.js.map +0 -1
  59. package/dist/index.browser-DQqKPfDA.esm.js.map +0 -1
  60. package/dist/index.native-7hiNiSyC.js.map +0 -1
  61. package/dist/index.native-BItnSD47.esm.js.map +0 -1
  62. package/dist/privy-wallet-provider-DFZaQPss.js.map +0 -1
  63. package/dist/privy-wallet-provider-ip2pqo_U.esm.js.map +0 -1
  64. package/dist/solana-mobile-wallet-provider-D7BbSpez.esm.js.map +0 -1
  65. package/dist/solana-mobile-wallet-provider-DwER68Rz.js.map +0 -1
@@ -1,10 +1,18 @@
1
- import { b as bufferExports } from './index-DKyWaxCB.esm.js';
2
- import { g as getPlatform, k as setAuthLoading, W as WebSessionManager, s as setCurrentUser, l as genAuthNonce, m as genSolanaMessage, n as createSessionWithSignature, d as base58, e as confirmAndCheckTransaction, c as convertRemainingAccounts, b as buildSetDocumentsTransaction, a as SOLANA_DEVNET_RPC_URL, S as SOLANA_MAINNET_RPC_URL, h as SURFNET_RPC_URL } from './index.native-BItnSD47.esm.js';
1
+ import { b as bufferExports } from './index-_k6pjuwx.esm.js';
2
+ import { g as getPlatform, W as WebSessionManager, m as genAuthNonce, n as genSolanaMessage, s as setCurrentUser, o as createSessionWithSignature, l as setAuthLoading, e as confirmAndCheckTransaction, d as base58, c as convertRemainingAccounts, b as buildSetDocumentsTransaction, a as SOLANA_DEVNET_RPC_URL, S as SOLANA_MAINNET_RPC_URL, h as SURFNET_RPC_URL } from './index.native-19VsREMJ.esm.js';
3
3
  import { PublicKey, Connection, VersionedTransaction, VersionedMessage, Transaction } from '@solana/web3.js';
4
4
  import * as anchor from '@coral-xyz/anchor';
5
5
  import 'axios';
6
6
  import 'react';
7
7
 
8
+ /**
9
+ * Storage key for persisting the MWA auth_token across cold starts.
10
+ * Holds JSON `{ token: string, address: string }`. Cleared by
11
+ * `logout()`. Hydrated by the constructor on native so cold-start
12
+ * doesn't force the user back into Phantom's approval flow when the
13
+ * underlying wallet authorization is still valid.
14
+ */
15
+ const MWA_AUTH_TOKEN_STORAGE_KEY = 'tarobase_mwa_auth_token';
8
16
  const ED25519_SIGNATURE_LENGTH = 64;
9
17
  const STORED_AUTH_METHOD_KEY = 'tarobase_last_auth_method';
10
18
  const MWA_AUTH_METHOD = 'mobile-wallet-adapter';
@@ -506,19 +514,66 @@ class SolanaMobileWalletProvider {
506
514
  constructor(networkUrl = null, config = {}) {
507
515
  /** LocalSolanaMobileWalletAdapterWallet, lazy-constructed in ensureWallet(). */
508
516
  this.wallet = null;
517
+ /**
518
+ * Cached MWA auth_token returned by `wallet.authorize()`. Reused by
519
+ * subsequent native transact() calls (signMessage / signTransaction)
520
+ * so the user doesn't get the wallet-pick popup on every operation.
521
+ * Persisted to platform storage and hydrated by the constructor on
522
+ * native; cleared by logout() and on `ERROR_REAUTHORIZE`.
523
+ */
524
+ this.nativeAuthToken = null;
525
+ /** Cached public key string for the connected MWA wallet (native). */
526
+ this.nativeAddress = null;
509
527
  this.networkUrl = networkUrl;
510
528
  this.config = config;
511
- if (typeof window === 'undefined') {
529
+ // Allow construction in true React Native environments: getPlatform().hasDOM
530
+ // is false there even though `typeof window === 'object'` (RN exposes a
531
+ // partial window global). Web/PWA paths still keep their original guard:
532
+ // they need real window+document for wallet-standard-mobile's deep-link
533
+ // mechanism, so missing-window in those builds remains a fail-fast.
534
+ const hasDOM = getPlatform().hasDOM;
535
+ if (!hasDOM && typeof window === 'undefined') {
536
+ throw new Error('SolanaMobileWalletProvider can only be instantiated in a browser or React Native environment');
537
+ }
538
+ if (hasDOM && typeof window === 'undefined') {
512
539
  throw new Error('SolanaMobileWalletProvider can only be instantiated in a browser environment');
513
540
  }
514
541
  if (SolanaMobileWalletProvider.instance) {
515
542
  return SolanaMobileWalletProvider.instance;
516
543
  }
544
+ // `appIdentity.uri` is what Phantom Android (and other MWA wallets)
545
+ // display in their approval modal. On web/PWA this is the page
546
+ // origin; on native there's no `window.location`, so fall back to
547
+ // a stable identifier the user can recognize. Apps can override
548
+ // entirely via `config.appIdentity.uri`.
549
+ const fallbackUri = hasDOM
550
+ ? getPlatform().getLocationOrigin()
551
+ : 'tarobase://app';
517
552
  this.appIdentity = config.appIdentity || {
518
553
  name: 'TaroBase App',
519
- uri: getPlatform().getLocationOrigin(),
554
+ uri: fallbackUri,
520
555
  };
521
556
  this.cluster = config.cluster || 'mainnet-beta';
557
+ // Hydrate cached MWA auth_token from storage on native so we can
558
+ // skip the wallet-pick popup after a cold-start when the underlying
559
+ // wallet authorization is still valid. Sync storage call per the
560
+ // PlatformAdapter contract; safe to swallow read errors (a fresh
561
+ // login() just re-authorizes).
562
+ if (!hasDOM) {
563
+ try {
564
+ const raw = getPlatform().storage.getItem(MWA_AUTH_TOKEN_STORAGE_KEY);
565
+ if (raw) {
566
+ const parsed = JSON.parse(raw);
567
+ if (typeof parsed.token === 'string' && typeof parsed.address === 'string') {
568
+ this.nativeAuthToken = parsed.token;
569
+ this.nativeAddress = parsed.address;
570
+ }
571
+ }
572
+ }
573
+ catch (_a) {
574
+ // Corrupt or unreadable cache — ignore. login() will re-auth.
575
+ }
576
+ }
522
577
  SolanaMobileWalletProvider.instance = this;
523
578
  }
524
579
  static getInstance(networkUrl, config) {
@@ -531,7 +586,7 @@ class SolanaMobileWalletProvider {
531
586
  async ensureWallet() {
532
587
  if (this.wallet)
533
588
  return this.wallet;
534
- const mod = await import('./index.browser-DQqKPfDA.esm.js');
589
+ const mod = await import('./index.browser-Cndx2raY.esm.js');
535
590
  const chain = mapChainToWalletStandard(this.cluster);
536
591
  this.wallet = new mod.LocalSolanaMobileWalletAdapterWallet({
537
592
  appIdentity: this.appIdentity,
@@ -581,6 +636,134 @@ class SolanaMobileWalletProvider {
581
636
  getChain() {
582
637
  return mapChainToWalletStandard(this.cluster);
583
638
  }
639
+ /**
640
+ * Dynamically import and unwrap `transact` from the MWA web3js
641
+ * package. The package is externalized in rollup.config.js so this
642
+ * resolves to `lib/cjs/index.native.js` (TurboModule-backed) on
643
+ * Metro and `lib/esm/index.browser.js` (WebSocket) on webpack/vite
644
+ * per their respective platform conditions. Handles Metro's CJS-to-
645
+ * ESM interop variance (`mod.transact` vs `mod.default?.transact`).
646
+ */
647
+ async loadTransact() {
648
+ var _a;
649
+ const mod = await import('@solana-mobile/mobile-wallet-adapter-protocol-web3js');
650
+ const t = mod.transact || ((_a = mod.default) === null || _a === void 0 ? void 0 : _a.transact);
651
+ if (typeof t !== 'function') {
652
+ throw new Error('MWA transact API not available on this platform');
653
+ }
654
+ return t;
655
+ }
656
+ /**
657
+ * Cache and persist a fresh MWA auth_token + address. Called from
658
+ * `_loginNative` after a successful authorize. Storage failures are
659
+ * non-fatal (next cold-start re-auths).
660
+ */
661
+ persistNativeAuth(token, address) {
662
+ this.nativeAuthToken = token;
663
+ this.nativeAddress = address;
664
+ try {
665
+ getPlatform().storage.setItem(MWA_AUTH_TOKEN_STORAGE_KEY, JSON.stringify({ token, address }));
666
+ }
667
+ catch (_a) {
668
+ // non-fatal — token still in-memory for this process
669
+ }
670
+ }
671
+ /** Clear cached + persisted native auth state. */
672
+ clearNativeAuth() {
673
+ this.nativeAuthToken = null;
674
+ this.nativeAddress = null;
675
+ try {
676
+ getPlatform().storage.removeItem(MWA_AUTH_TOKEN_STORAGE_KEY);
677
+ }
678
+ catch (_a) {
679
+ // ignore
680
+ }
681
+ }
682
+ /**
683
+ * Classify an MWA-native error as a user cancellation. User-cancel
684
+ * shouldn't surface as a red console.error; callers can swallow or
685
+ * show a softer message. MWA spec codes plus the same substring
686
+ * checks the web path uses to catch wallet-specific phrasing.
687
+ */
688
+ isNativeUserCancel(err) {
689
+ var _a;
690
+ if (!err)
691
+ return false;
692
+ const code = err.code;
693
+ if (code === 'ERROR_NOT_SIGNED')
694
+ return true;
695
+ const msg = String((_a = err.message) !== null && _a !== void 0 ? _a : '').toLowerCase();
696
+ return /user (rejected|denied|cancelled|canceled|declined)/.test(msg);
697
+ }
698
+ /**
699
+ * Native MWA login via @solana-mobile/mobile-wallet-adapter-protocol-web3js.
700
+ * Used in true React Native (Expo) environments where wallet-standard-mobile's
701
+ * web universal-link path doesn't apply. Does authorize + signMessage in a
702
+ * single transact() roundtrip — intent-based MWA doesn't need the two-popup
703
+ * dance the web path uses (no Chrome activation-loss concern). Persists the
704
+ * resulting auth_token so cold-start can reauthorize without a fresh popup.
705
+ */
706
+ async _loginNative() {
707
+ const transact = await this.loadTransact();
708
+ const existingSession = await WebSessionManager.getSession();
709
+ const nonce = await genAuthNonce();
710
+ const result = await transact(async (wallet) => {
711
+ const auth = await wallet.authorize({
712
+ chain: this.getChain(),
713
+ identity: this.appIdentity,
714
+ });
715
+ if (!auth.accounts || auth.accounts.length === 0) {
716
+ throw new Error('MWA returned no accounts');
717
+ }
718
+ const account = auth.accounts[0];
719
+ // account.address is base64-encoded per MWA spec; convert to
720
+ // the base58 form Tarobase + the rest of the SDK use.
721
+ const base58Addr = new PublicKey(bufferExports.Buffer.from(account.address, 'base64')).toBase58();
722
+ // Reuse session if already valid for this address — skip the
723
+ // signMessages roundtrip entirely.
724
+ if (existingSession && existingSession.address === base58Addr) {
725
+ return {
726
+ base58Addr,
727
+ authToken: auth.auth_token,
728
+ signatureBase64: null,
729
+ };
730
+ }
731
+ const messageText = await genSolanaMessage(base58Addr, nonce);
732
+ const messageBytes = getPlatform().textEncode(messageText);
733
+ const signatures = await wallet.signMessages({
734
+ addresses: [account.address],
735
+ payloads: [messageBytes],
736
+ });
737
+ if (!signatures || signatures.length === 0) {
738
+ throw new Error('MWA returned no signature');
739
+ }
740
+ // Per spec, signMessages returns Uint8Array[] of signatures
741
+ // (one per payload), not message+signature concatenations.
742
+ const signatureBase64 = bufferExports.Buffer.from(signatures[0]).toString('base64');
743
+ return {
744
+ base58Addr,
745
+ authToken: auth.auth_token,
746
+ signatureBase64,
747
+ messageText,
748
+ };
749
+ });
750
+ this.persistNativeAuth(result.authToken, result.base58Addr);
751
+ // Existing valid session — short-circuit before re-creating server-side.
752
+ if (existingSession && existingSession.address === result.base58Addr) {
753
+ const user = { provider: this, address: result.base58Addr };
754
+ setCurrentUser(user);
755
+ return user;
756
+ }
757
+ // Create Tarobase session on the server.
758
+ if (!result.signatureBase64 || !result.messageText) {
759
+ throw new Error('MWA login completed without signature');
760
+ }
761
+ const createSessionResult = await createSessionWithSignature(result.base58Addr, result.messageText, result.signatureBase64);
762
+ await WebSessionManager.storeSession(result.base58Addr, createSessionResult.accessToken, createSessionResult.idToken, createSessionResult.refreshToken);
763
+ const user = { provider: this, address: result.base58Addr };
764
+ setCurrentUser(user);
765
+ return user;
766
+ }
584
767
  async login() {
585
768
  var _a, _b, _c, _d, _e;
586
769
  setAuthLoading(true);
@@ -591,6 +774,13 @@ class SolanaMobileWalletProvider {
591
774
  const prevAuthMethod = readAuthMethod();
592
775
  writeAuthMethod(MWA_AUTH_METHOD);
593
776
  try {
777
+ // True React Native: skip the wallet-standard-mobile path (which
778
+ // requires window.isSecureContext and a real DOM) and use the raw
779
+ // MWA protocol via Android intents.
780
+ if (!getPlatform().hasDOM) {
781
+ const user = await this._loginNative();
782
+ return user;
783
+ }
594
784
  const wallet = await this.ensureWallet();
595
785
  // Quick-check: wallet may already have authorization (e.g. from a
596
786
  // previous in-page login) and a matching Tarobase session — skip
@@ -692,6 +882,29 @@ class SolanaMobileWalletProvider {
692
882
  return null;
693
883
  }
694
884
  async logout() {
885
+ if (!getPlatform().hasDOM) {
886
+ // Native path: deauthorize the cached MWA auth_token if we have
887
+ // one (failures non-fatal — the wallet app may have been
888
+ // uninstalled or the token already revoked), then clear local
889
+ // and persisted state.
890
+ const token = this.nativeAuthToken;
891
+ if (token) {
892
+ try {
893
+ const transact = await this.loadTransact();
894
+ await transact(async (wallet) => {
895
+ await wallet.deauthorize({ auth_token: token });
896
+ });
897
+ }
898
+ catch (error) {
899
+ console.warn('[SolanaMobileWallet] Native deauthorize error:', error);
900
+ }
901
+ }
902
+ this.clearNativeAuth();
903
+ WebSessionManager.clearSession();
904
+ writeAuthMethod(null);
905
+ setCurrentUser(null);
906
+ return;
907
+ }
695
908
  try {
696
909
  const wallet = await this.ensureWallet();
697
910
  const disconnectFeat = getDisconnectFeature(wallet);
@@ -711,7 +924,42 @@ class SolanaMobileWalletProvider {
711
924
  setCurrentUser(null);
712
925
  }
713
926
  async signMessage(message) {
714
- var _a, _b;
927
+ var _a, _b, _c;
928
+ // Native: reauthorize with cached auth_token, then signMessages inside
929
+ // the same transact() session. No wallet-pick popup if the auth_token
930
+ // is still valid for the user's wallet.
931
+ if (!getPlatform().hasDOM) {
932
+ if (!this.nativeAuthToken || !this.nativeAddress) {
933
+ throw new Error('Wallet not connected. Call login() first.');
934
+ }
935
+ const transact = await this.loadTransact();
936
+ const messageBytes = getPlatform().textEncode(message);
937
+ const addressBase64 = new PublicKey(this.nativeAddress).toBuffer().toString('base64');
938
+ const authToken = this.nativeAuthToken;
939
+ try {
940
+ const signature = await transact(async (wallet) => {
941
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
942
+ const sigs = await wallet.signMessages({
943
+ addresses: [addressBase64],
944
+ payloads: [messageBytes],
945
+ });
946
+ if (!sigs || sigs.length === 0)
947
+ throw new Error('MWA returned no signature');
948
+ return sigs[0];
949
+ });
950
+ return bufferExports.Buffer.from(signature).toString('base64');
951
+ }
952
+ catch (error) {
953
+ if (this.isNativeUserCancel(error)) {
954
+ throw new Error('User declined to sign');
955
+ }
956
+ if ((error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED' || (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_REAUTHORIZE') {
957
+ await this.logout();
958
+ throw new Error('Wallet connection lost. Please reconnect.');
959
+ }
960
+ throw new Error(`Failed to sign message: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
961
+ }
962
+ }
715
963
  const account = await this.ensureAuthorized();
716
964
  const wallet = await this.ensureWallet();
717
965
  try {
@@ -725,7 +973,7 @@ class SolanaMobileWalletProvider {
725
973
  return bufferExports.Buffer.from(sigBytes).toString('base64');
726
974
  }
727
975
  catch (error) {
728
- 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')) ||
976
+ if (((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not connected')) || ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('not authorized')) ||
729
977
  (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED') {
730
978
  await this.logout();
731
979
  throw new Error('Wallet connection lost. Please reconnect.');
@@ -734,7 +982,58 @@ class SolanaMobileWalletProvider {
734
982
  }
735
983
  }
736
984
  async signTransaction(transaction) {
737
- var _a, _b;
985
+ var _a, _b, _c;
986
+ // Native: fill blockhash/feePayer if missing, then signTransactions
987
+ // inside a transact() session keyed by the cached auth_token.
988
+ if (!getPlatform().hasDOM) {
989
+ if (!this.nativeAuthToken || !this.nativeAddress) {
990
+ throw new Error('Wallet not connected. Call login() first.');
991
+ }
992
+ const connectedPubkey = new PublicKey(this.nativeAddress);
993
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
994
+ if (isLegacyTransaction) {
995
+ const legacyTx = transaction;
996
+ if (!legacyTx.recentBlockhash) {
997
+ const conn = new Connection(this.getRpcUrl(), 'confirmed');
998
+ const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash('confirmed');
999
+ legacyTx.recentBlockhash = blockhash;
1000
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
1001
+ }
1002
+ if (!legacyTx.feePayer) {
1003
+ legacyTx.feePayer = connectedPubkey;
1004
+ }
1005
+ }
1006
+ else {
1007
+ const versionedTx = transaction;
1008
+ if (!versionedTx.message.recentBlockhash) {
1009
+ const conn = new Connection(this.getRpcUrl(), 'confirmed');
1010
+ const { blockhash } = await conn.getLatestBlockhash('confirmed');
1011
+ versionedTx.message.recentBlockhash = blockhash;
1012
+ }
1013
+ }
1014
+ const transact = await this.loadTransact();
1015
+ const authToken = this.nativeAuthToken;
1016
+ try {
1017
+ const signed = await transact(async (wallet) => {
1018
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
1019
+ const results = await wallet.signTransactions({ transactions: [transaction] });
1020
+ if (!results || results.length === 0)
1021
+ throw new Error('MWA returned no signed transaction');
1022
+ return results[0];
1023
+ });
1024
+ return signed;
1025
+ }
1026
+ catch (error) {
1027
+ if (this.isNativeUserCancel(error)) {
1028
+ throw new Error('User declined to sign');
1029
+ }
1030
+ if ((error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED' || (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_REAUTHORIZE') {
1031
+ await this.logout();
1032
+ throw new Error('Wallet connection lost. Please reconnect.');
1033
+ }
1034
+ throw new Error(`Failed to sign transaction: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
1035
+ }
1036
+ }
738
1037
  const account = await this.ensureAuthorized();
739
1038
  const connectedPubkey = new PublicKey(account.publicKey);
740
1039
  const wallet = await this.ensureWallet();
@@ -773,7 +1072,7 @@ class SolanaMobileWalletProvider {
773
1072
  return txFromWireBytes(new Uint8Array(signedBytes));
774
1073
  }
775
1074
  catch (error) {
776
- 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')) ||
1075
+ if (((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not connected')) || ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('not authorized')) ||
777
1076
  (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED') {
778
1077
  await this.logout();
779
1078
  throw new Error('Wallet connection lost. Please reconnect.');
@@ -782,7 +1081,70 @@ class SolanaMobileWalletProvider {
782
1081
  }
783
1082
  }
784
1083
  async signAndSubmitTransaction(transaction, feePayer) {
785
- var _a, _b, _c, _d, _e, _f;
1084
+ var _a, _b, _c, _d, _e, _f, _g;
1085
+ // Native: signAndSendTransactions inside a transact() session.
1086
+ // The wallet submits to its own RPC; we then await confirmation on
1087
+ // ours. Surfnet (custom RPC) needs manual submission because the
1088
+ // wallet won't route there — we fall back to sign-only + manual send.
1089
+ if (!getPlatform().hasDOM) {
1090
+ if (!this.nativeAuthToken || !this.nativeAddress) {
1091
+ throw new Error('Wallet not connected. Call login() first.');
1092
+ }
1093
+ const connectedPubkey = new PublicKey(this.nativeAddress);
1094
+ const rpcUrl = this.getRpcUrl();
1095
+ const connection = new Connection(rpcUrl, 'confirmed');
1096
+ const isSurfnet = rpcUrl === SURFNET_RPC_URL;
1097
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
1098
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
1099
+ if (isLegacyTransaction) {
1100
+ const legacyTx = transaction;
1101
+ legacyTx.recentBlockhash = blockhash;
1102
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
1103
+ if (!legacyTx.feePayer)
1104
+ legacyTx.feePayer = feePayer !== null && feePayer !== void 0 ? feePayer : connectedPubkey;
1105
+ }
1106
+ else {
1107
+ const versionedTx = transaction;
1108
+ versionedTx.message.recentBlockhash = blockhash;
1109
+ }
1110
+ const transact = await this.loadTransact();
1111
+ const authToken = this.nativeAuthToken;
1112
+ try {
1113
+ if (isSurfnet) {
1114
+ // Surfnet: sign only, submit manually to Surfnet RPC
1115
+ // (the wallet would route signAndSend to its own RPC).
1116
+ const signed = await transact(async (wallet) => {
1117
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
1118
+ const results = await wallet.signTransactions({ transactions: [transaction] });
1119
+ if (!results || results.length === 0)
1120
+ throw new Error('MWA returned no signed transaction');
1121
+ return results[0];
1122
+ });
1123
+ const sig = await connection.sendRawTransaction(signed.serialize(), { preflightCommitment: 'confirmed' });
1124
+ await confirmAndCheckTransaction(connection, sig);
1125
+ return sig;
1126
+ }
1127
+ const sig = await transact(async (wallet) => {
1128
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
1129
+ const results = await wallet.signAndSendTransactions({ transactions: [transaction] });
1130
+ if (!results || results.length === 0)
1131
+ throw new Error('MWA returned no signature');
1132
+ return results[0];
1133
+ });
1134
+ await confirmAndCheckTransaction(connection, sig);
1135
+ return sig;
1136
+ }
1137
+ catch (error) {
1138
+ if (this.isNativeUserCancel(error)) {
1139
+ throw new Error('User declined to sign');
1140
+ }
1141
+ if ((error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED' || (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_REAUTHORIZE') {
1142
+ await this.logout();
1143
+ throw new Error('Wallet connection lost. Please reconnect.');
1144
+ }
1145
+ throw new Error(`Failed to sign+submit transaction: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
1146
+ }
1147
+ }
786
1148
  const account = await this.ensureAuthorized();
787
1149
  const connectedPubkey = new PublicKey(account.publicKey);
788
1150
  const wallet = await this.ensureWallet();
@@ -849,16 +1211,16 @@ class SolanaMobileWalletProvider {
849
1211
  return signature;
850
1212
  }
851
1213
  catch (error) {
852
- 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')) ||
1214
+ if (((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not connected')) || ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('not authorized')) ||
853
1215
  (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED') {
854
1216
  await this.logout();
855
1217
  throw new Error('Wallet connection lost. Please reconnect.');
856
1218
  }
857
1219
  const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
858
- ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes('user rejected')) ||
859
- ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('user denied')) ||
860
- ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user cancelled')) ||
861
- ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user canceled'));
1220
+ ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('user rejected')) ||
1221
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user denied')) ||
1222
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user cancelled')) ||
1223
+ ((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user canceled'));
862
1224
  if (!isUserRejection) {
863
1225
  console.error('[SolanaMobileWallet] Transaction failed:', error);
864
1226
  }
@@ -1063,4 +1425,4 @@ class SolanaMobileWalletProvider {
1063
1425
  SolanaMobileWalletProvider.instance = null;
1064
1426
 
1065
1427
  export { SolanaMobileWalletProvider };
1066
- //# sourceMappingURL=solana-mobile-wallet-provider-D7BbSpez.esm.js.map
1428
+ //# sourceMappingURL=solana-mobile-wallet-provider-EeQsBTdr.esm.js.map