@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
@@ -4,6 +4,21 @@ import * as anchor from '@coral-xyz/anchor';
4
4
  import { Program } from '@coral-xyz/anchor';
5
5
  import * as React$2 from 'react';
6
6
 
7
+ function _mergeNamespaces(n, m) {
8
+ m.forEach(function (e) {
9
+ e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default' && !(k in n)) {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ });
19
+ return Object.freeze(n);
20
+ }
21
+
7
22
  function getDefaultExportFromCjs$1 (x) {
8
23
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
9
24
  }
@@ -6749,28 +6764,6 @@ class WebSessionManager {
6749
6764
  static async storeSession(address, accessToken, idToken, refreshToken) {
6750
6765
  if (typeof window === "undefined")
6751
6766
  return;
6752
- // JWT-wallet binding: refuse to store a session whose idToken is bound
6753
- // to a different wallet than `address`. Prevents races that would otherwise
6754
- // leave localStorage with mismatched address/token state.
6755
- try {
6756
- const payloadB64 = idToken.split(".")[1];
6757
- if (payloadB64) {
6758
- const payload = JSON.parse(this.decodeBase64Url(payloadB64));
6759
- const tokenWallet = payload["custom:walletAddress"];
6760
- if (tokenWallet && tokenWallet !== address) {
6761
- throw new Error(`[WebSessionManager] Refusing to store session: address (${address}) does not match idToken custom:walletAddress (${tokenWallet})`);
6762
- }
6763
- if (!tokenWallet) {
6764
- console.warn("[WebSessionManager] storeSession: idToken has no custom:walletAddress claim — writing without validation");
6765
- }
6766
- }
6767
- }
6768
- catch (err) {
6769
- if (typeof (err === null || err === void 0 ? void 0 : err.message) === "string" && err.message.includes("Refusing to store session")) {
6770
- throw err;
6771
- }
6772
- console.warn("[WebSessionManager] storeSession: failed to decode idToken for validation:", err);
6773
- }
6774
6767
  const config = await getConfig();
6775
6768
  const currentAppId = config.appId;
6776
6769
  localStorage.setItem(this.TAROBASE_SESSION_STORAGE_KEY, JSON.stringify({
@@ -9469,11 +9462,11 @@ function requireSrc$1 () {
9469
9462
  }
9470
9463
 
9471
9464
  var bs58$1;
9472
- var hasRequiredBs58;
9465
+ var hasRequiredBs58$1;
9473
9466
 
9474
- function requireBs58 () {
9475
- if (hasRequiredBs58) return bs58$1;
9476
- hasRequiredBs58 = 1;
9467
+ function requireBs58$1 () {
9468
+ if (hasRequiredBs58$1) return bs58$1;
9469
+ hasRequiredBs58$1 = 1;
9477
9470
  var basex = requireSrc$1();
9478
9471
  var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
9479
9472
 
@@ -9481,8 +9474,8 @@ function requireBs58 () {
9481
9474
  return bs58$1;
9482
9475
  }
9483
9476
 
9484
- var bs58Exports = requireBs58();
9485
- var bs58 = /*@__PURE__*/getDefaultExportFromCjs(bs58Exports);
9477
+ var bs58Exports$1 = requireBs58$1();
9478
+ var bs58$2 = /*@__PURE__*/getDefaultExportFromCjs(bs58Exports$1);
9486
9479
 
9487
9480
  // ─────────────────────────────────────────────────────────────
9488
9481
  // Local implementation of getSimulationComputeUnits
@@ -9744,7 +9737,7 @@ function loadKeypairFromEnv() {
9744
9737
  try {
9745
9738
  const secretKey = secret.trim().startsWith("[")
9746
9739
  ? Uint8Array.from(JSON.parse(secret))
9747
- : bs58.decode(secret.trim());
9740
+ : bs58$2.decode(secret.trim());
9748
9741
  return Keypair.fromSecretKey(secretKey);
9749
9742
  }
9750
9743
  catch (err) {
@@ -11689,28 +11682,6 @@ class ReactNativeSessionManager {
11689
11682
  /* STORE */
11690
11683
  /* ------------------------------------------------------------------ */
11691
11684
  static async storeSession(address, accessToken, idToken, refreshToken) {
11692
- // JWT-wallet binding: refuse to store a session whose idToken is bound
11693
- // to a different wallet than `address`. Prevents races that would otherwise
11694
- // leave storage with mismatched address/token state.
11695
- try {
11696
- const payloadB64 = idToken.split(".")[1];
11697
- if (payloadB64) {
11698
- const payload = JSON.parse(this.decodeBase64Url(payloadB64));
11699
- const tokenWallet = payload["custom:walletAddress"];
11700
- if (tokenWallet && tokenWallet !== address) {
11701
- throw new Error(`[ReactNativeSessionManager] Refusing to store session: address (${address}) does not match idToken custom:walletAddress (${tokenWallet})`);
11702
- }
11703
- if (!tokenWallet) {
11704
- console.warn("[ReactNativeSessionManager] storeSession: idToken has no custom:walletAddress claim — writing without validation");
11705
- }
11706
- }
11707
- }
11708
- catch (err) {
11709
- if (typeof (err === null || err === void 0 ? void 0 : err.message) === "string" && err.message.includes("Refusing to store session")) {
11710
- throw err;
11711
- }
11712
- console.warn("[ReactNativeSessionManager] storeSession: failed to decode idToken for validation:", err);
11713
- }
11714
11685
  const config = await getConfig();
11715
11686
  const currentAppId = config.appId;
11716
11687
  this.getStorage().setItem(this.TAROBASE_SESSION_STORAGE_KEY, JSON.stringify({
@@ -15709,7 +15680,7 @@ async function loadDependencies() {
15709
15680
  const [reactModule, reactDomModule, phantomModule] = await Promise.all([
15710
15681
  import('react'),
15711
15682
  import('react-dom/client'),
15712
- import('./index-Cfp30Jm_.esm.js')
15683
+ import('./index-DofM-ue2.esm.js')
15713
15684
  ]);
15714
15685
  // Extract default export from ESM module namespace
15715
15686
  // Dynamic import() returns { default: Module, ...exports }, not the module directly
@@ -20367,16 +20338,26 @@ function requireSrc () {
20367
20338
  return src;
20368
20339
  }
20369
20340
 
20370
- var srcExports = requireSrc();
20371
- var basex = /*@__PURE__*/getDefaultExportFromCjs$1(srcExports);
20341
+ var bs58;
20342
+ var hasRequiredBs58;
20343
+
20344
+ function requireBs58 () {
20345
+ if (hasRequiredBs58) return bs58;
20346
+ hasRequiredBs58 = 1;
20347
+ var basex = requireSrc();
20348
+ var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
20349
+
20350
+ bs58 = basex(ALPHABET);
20351
+ return bs58;
20352
+ }
20372
20353
 
20373
- var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
20374
- var base58 = basex(ALPHABET);
20354
+ var bs58Exports = requireBs58();
20355
+ var base58 = /*@__PURE__*/getDefaultExportFromCjs$1(bs58Exports);
20375
20356
 
20376
- var index = /*#__PURE__*/Object.freeze({
20357
+ var index = /*#__PURE__*/_mergeNamespaces({
20377
20358
  __proto__: null,
20378
20359
  default: base58
20379
- });
20360
+ }, [bs58Exports]);
20380
20361
 
20381
20362
  const SURFNET_RPC_URL$1 = "https://surfpool.fly.dev";
20382
20363
  let React;
@@ -21265,6 +21246,14 @@ var privyWalletProvider = /*#__PURE__*/Object.freeze({
21265
21246
  PrivyWalletProvider: PrivyWalletProvider
21266
21247
  });
21267
21248
 
21249
+ /**
21250
+ * Storage key for persisting the MWA auth_token across cold starts.
21251
+ * Holds JSON `{ token: string, address: string }`. Cleared by
21252
+ * `logout()`. Hydrated by the constructor on native so cold-start
21253
+ * doesn't force the user back into Phantom's approval flow when the
21254
+ * underlying wallet authorization is still valid.
21255
+ */
21256
+ const MWA_AUTH_TOKEN_STORAGE_KEY = 'tarobase_mwa_auth_token';
21268
21257
  /**
21269
21258
  * Detects whether the current environment is a mobile browser capable of
21270
21259
  * Mobile Wallet Adapter (MWA) communication.
@@ -21759,7 +21748,7 @@ async function registerMobileWalletAdapter(config) {
21759
21748
  if (typeof window === 'undefined')
21760
21749
  return;
21761
21750
  try {
21762
- const walletStandardMobile = await import('./index.browser-C9gHoUen.esm.js');
21751
+ const walletStandardMobile = await import('./index.browser-nVGFrIHK.esm.js');
21763
21752
  const registerMwa = walletStandardMobile.registerMwa || ((_a = walletStandardMobile.default) === null || _a === void 0 ? void 0 : _a.registerMwa);
21764
21753
  if (!registerMwa) {
21765
21754
  console.warn('[SolanaMobileWallet] registerMwa not found in @solana-mobile/wallet-standard-mobile');
@@ -21826,19 +21815,66 @@ class SolanaMobileWalletProvider {
21826
21815
  constructor(networkUrl = null, config = {}) {
21827
21816
  /** LocalSolanaMobileWalletAdapterWallet, lazy-constructed in ensureWallet(). */
21828
21817
  this.wallet = null;
21818
+ /**
21819
+ * Cached MWA auth_token returned by `wallet.authorize()`. Reused by
21820
+ * subsequent native transact() calls (signMessage / signTransaction)
21821
+ * so the user doesn't get the wallet-pick popup on every operation.
21822
+ * Persisted to platform storage and hydrated by the constructor on
21823
+ * native; cleared by logout() and on `ERROR_REAUTHORIZE`.
21824
+ */
21825
+ this.nativeAuthToken = null;
21826
+ /** Cached public key string for the connected MWA wallet (native). */
21827
+ this.nativeAddress = null;
21829
21828
  this.networkUrl = networkUrl;
21830
21829
  this.config = config;
21831
- if (typeof window === 'undefined') {
21830
+ // Allow construction in true React Native environments: getPlatform().hasDOM
21831
+ // is false there even though `typeof window === 'object'` (RN exposes a
21832
+ // partial window global). Web/PWA paths still keep their original guard:
21833
+ // they need real window+document for wallet-standard-mobile's deep-link
21834
+ // mechanism, so missing-window in those builds remains a fail-fast.
21835
+ const hasDOM = getPlatform().hasDOM;
21836
+ if (!hasDOM && typeof window === 'undefined') {
21837
+ throw new Error('SolanaMobileWalletProvider can only be instantiated in a browser or React Native environment');
21838
+ }
21839
+ if (hasDOM && typeof window === 'undefined') {
21832
21840
  throw new Error('SolanaMobileWalletProvider can only be instantiated in a browser environment');
21833
21841
  }
21834
21842
  if (SolanaMobileWalletProvider.instance) {
21835
21843
  return SolanaMobileWalletProvider.instance;
21836
21844
  }
21845
+ // `appIdentity.uri` is what Phantom Android (and other MWA wallets)
21846
+ // display in their approval modal. On web/PWA this is the page
21847
+ // origin; on native there's no `window.location`, so fall back to
21848
+ // a stable identifier the user can recognize. Apps can override
21849
+ // entirely via `config.appIdentity.uri`.
21850
+ const fallbackUri = hasDOM
21851
+ ? getPlatform().getLocationOrigin()
21852
+ : 'tarobase://app';
21837
21853
  this.appIdentity = config.appIdentity || {
21838
21854
  name: 'TaroBase App',
21839
- uri: getPlatform().getLocationOrigin(),
21855
+ uri: fallbackUri,
21840
21856
  };
21841
21857
  this.cluster = config.cluster || 'mainnet-beta';
21858
+ // Hydrate cached MWA auth_token from storage on native so we can
21859
+ // skip the wallet-pick popup after a cold-start when the underlying
21860
+ // wallet authorization is still valid. Sync storage call per the
21861
+ // PlatformAdapter contract; safe to swallow read errors (a fresh
21862
+ // login() just re-authorizes).
21863
+ if (!hasDOM) {
21864
+ try {
21865
+ const raw = getPlatform().storage.getItem(MWA_AUTH_TOKEN_STORAGE_KEY);
21866
+ if (raw) {
21867
+ const parsed = JSON.parse(raw);
21868
+ if (typeof parsed.token === 'string' && typeof parsed.address === 'string') {
21869
+ this.nativeAuthToken = parsed.token;
21870
+ this.nativeAddress = parsed.address;
21871
+ }
21872
+ }
21873
+ }
21874
+ catch (_a) {
21875
+ // Corrupt or unreadable cache — ignore. login() will re-auth.
21876
+ }
21877
+ }
21842
21878
  SolanaMobileWalletProvider.instance = this;
21843
21879
  }
21844
21880
  static getInstance(networkUrl, config) {
@@ -21851,7 +21887,7 @@ class SolanaMobileWalletProvider {
21851
21887
  async ensureWallet() {
21852
21888
  if (this.wallet)
21853
21889
  return this.wallet;
21854
- const mod = await import('./index.browser-C9gHoUen.esm.js');
21890
+ const mod = await import('./index.browser-nVGFrIHK.esm.js');
21855
21891
  const chain = mapChainToWalletStandard(this.cluster);
21856
21892
  this.wallet = new mod.LocalSolanaMobileWalletAdapterWallet({
21857
21893
  appIdentity: this.appIdentity,
@@ -21901,6 +21937,134 @@ class SolanaMobileWalletProvider {
21901
21937
  getChain() {
21902
21938
  return mapChainToWalletStandard(this.cluster);
21903
21939
  }
21940
+ /**
21941
+ * Dynamically import and unwrap `transact` from the MWA web3js
21942
+ * package. The package is externalized in rollup.config.js so this
21943
+ * resolves to `lib/cjs/index.native.js` (TurboModule-backed) on
21944
+ * Metro and `lib/esm/index.browser.js` (WebSocket) on webpack/vite
21945
+ * per their respective platform conditions. Handles Metro's CJS-to-
21946
+ * ESM interop variance (`mod.transact` vs `mod.default?.transact`).
21947
+ */
21948
+ async loadTransact() {
21949
+ var _a;
21950
+ const mod = await import('@solana-mobile/mobile-wallet-adapter-protocol-web3js');
21951
+ const t = mod.transact || ((_a = mod.default) === null || _a === void 0 ? void 0 : _a.transact);
21952
+ if (typeof t !== 'function') {
21953
+ throw new Error('MWA transact API not available on this platform');
21954
+ }
21955
+ return t;
21956
+ }
21957
+ /**
21958
+ * Cache and persist a fresh MWA auth_token + address. Called from
21959
+ * `_loginNative` after a successful authorize. Storage failures are
21960
+ * non-fatal (next cold-start re-auths).
21961
+ */
21962
+ persistNativeAuth(token, address) {
21963
+ this.nativeAuthToken = token;
21964
+ this.nativeAddress = address;
21965
+ try {
21966
+ getPlatform().storage.setItem(MWA_AUTH_TOKEN_STORAGE_KEY, JSON.stringify({ token, address }));
21967
+ }
21968
+ catch (_a) {
21969
+ // non-fatal — token still in-memory for this process
21970
+ }
21971
+ }
21972
+ /** Clear cached + persisted native auth state. */
21973
+ clearNativeAuth() {
21974
+ this.nativeAuthToken = null;
21975
+ this.nativeAddress = null;
21976
+ try {
21977
+ getPlatform().storage.removeItem(MWA_AUTH_TOKEN_STORAGE_KEY);
21978
+ }
21979
+ catch (_a) {
21980
+ // ignore
21981
+ }
21982
+ }
21983
+ /**
21984
+ * Classify an MWA-native error as a user cancellation. User-cancel
21985
+ * shouldn't surface as a red console.error; callers can swallow or
21986
+ * show a softer message. MWA spec codes plus the same substring
21987
+ * checks the web path uses to catch wallet-specific phrasing.
21988
+ */
21989
+ isNativeUserCancel(err) {
21990
+ var _a;
21991
+ if (!err)
21992
+ return false;
21993
+ const code = err.code;
21994
+ if (code === 'ERROR_NOT_SIGNED')
21995
+ return true;
21996
+ const msg = String((_a = err.message) !== null && _a !== void 0 ? _a : '').toLowerCase();
21997
+ return /user (rejected|denied|cancelled|canceled|declined)/.test(msg);
21998
+ }
21999
+ /**
22000
+ * Native MWA login via @solana-mobile/mobile-wallet-adapter-protocol-web3js.
22001
+ * Used in true React Native (Expo) environments where wallet-standard-mobile's
22002
+ * web universal-link path doesn't apply. Does authorize + signMessage in a
22003
+ * single transact() roundtrip — intent-based MWA doesn't need the two-popup
22004
+ * dance the web path uses (no Chrome activation-loss concern). Persists the
22005
+ * resulting auth_token so cold-start can reauthorize without a fresh popup.
22006
+ */
22007
+ async _loginNative() {
22008
+ const transact = await this.loadTransact();
22009
+ const existingSession = await WebSessionManager.getSession();
22010
+ const nonce = await genAuthNonce();
22011
+ const result = await transact(async (wallet) => {
22012
+ const auth = await wallet.authorize({
22013
+ chain: this.getChain(),
22014
+ identity: this.appIdentity,
22015
+ });
22016
+ if (!auth.accounts || auth.accounts.length === 0) {
22017
+ throw new Error('MWA returned no accounts');
22018
+ }
22019
+ const account = auth.accounts[0];
22020
+ // account.address is base64-encoded per MWA spec; convert to
22021
+ // the base58 form Tarobase + the rest of the SDK use.
22022
+ const base58Addr = new PublicKey(bufferExports.Buffer.from(account.address, 'base64')).toBase58();
22023
+ // Reuse session if already valid for this address — skip the
22024
+ // signMessages roundtrip entirely.
22025
+ if (existingSession && existingSession.address === base58Addr) {
22026
+ return {
22027
+ base58Addr,
22028
+ authToken: auth.auth_token,
22029
+ signatureBase64: null,
22030
+ };
22031
+ }
22032
+ const messageText = await genSolanaMessage(base58Addr, nonce);
22033
+ const messageBytes = getPlatform().textEncode(messageText);
22034
+ const signatures = await wallet.signMessages({
22035
+ addresses: [account.address],
22036
+ payloads: [messageBytes],
22037
+ });
22038
+ if (!signatures || signatures.length === 0) {
22039
+ throw new Error('MWA returned no signature');
22040
+ }
22041
+ // Per spec, signMessages returns Uint8Array[] of signatures
22042
+ // (one per payload), not message+signature concatenations.
22043
+ const signatureBase64 = bufferExports.Buffer.from(signatures[0]).toString('base64');
22044
+ return {
22045
+ base58Addr,
22046
+ authToken: auth.auth_token,
22047
+ signatureBase64,
22048
+ messageText,
22049
+ };
22050
+ });
22051
+ this.persistNativeAuth(result.authToken, result.base58Addr);
22052
+ // Existing valid session — short-circuit before re-creating server-side.
22053
+ if (existingSession && existingSession.address === result.base58Addr) {
22054
+ const user = { provider: this, address: result.base58Addr };
22055
+ setCurrentUser(user);
22056
+ return user;
22057
+ }
22058
+ // Create Tarobase session on the server.
22059
+ if (!result.signatureBase64 || !result.messageText) {
22060
+ throw new Error('MWA login completed without signature');
22061
+ }
22062
+ const createSessionResult = await createSessionWithSignature(result.base58Addr, result.messageText, result.signatureBase64);
22063
+ await WebSessionManager.storeSession(result.base58Addr, createSessionResult.accessToken, createSessionResult.idToken, createSessionResult.refreshToken);
22064
+ const user = { provider: this, address: result.base58Addr };
22065
+ setCurrentUser(user);
22066
+ return user;
22067
+ }
21904
22068
  async login() {
21905
22069
  var _a, _b, _c, _d, _e;
21906
22070
  setAuthLoading(true);
@@ -21911,6 +22075,13 @@ class SolanaMobileWalletProvider {
21911
22075
  const prevAuthMethod = readAuthMethod();
21912
22076
  writeAuthMethod(MWA_AUTH_METHOD);
21913
22077
  try {
22078
+ // True React Native: skip the wallet-standard-mobile path (which
22079
+ // requires window.isSecureContext and a real DOM) and use the raw
22080
+ // MWA protocol via Android intents.
22081
+ if (!getPlatform().hasDOM) {
22082
+ const user = await this._loginNative();
22083
+ return user;
22084
+ }
21914
22085
  const wallet = await this.ensureWallet();
21915
22086
  // Quick-check: wallet may already have authorization (e.g. from a
21916
22087
  // previous in-page login) and a matching Tarobase session — skip
@@ -22012,6 +22183,29 @@ class SolanaMobileWalletProvider {
22012
22183
  return null;
22013
22184
  }
22014
22185
  async logout() {
22186
+ if (!getPlatform().hasDOM) {
22187
+ // Native path: deauthorize the cached MWA auth_token if we have
22188
+ // one (failures non-fatal — the wallet app may have been
22189
+ // uninstalled or the token already revoked), then clear local
22190
+ // and persisted state.
22191
+ const token = this.nativeAuthToken;
22192
+ if (token) {
22193
+ try {
22194
+ const transact = await this.loadTransact();
22195
+ await transact(async (wallet) => {
22196
+ await wallet.deauthorize({ auth_token: token });
22197
+ });
22198
+ }
22199
+ catch (error) {
22200
+ console.warn('[SolanaMobileWallet] Native deauthorize error:', error);
22201
+ }
22202
+ }
22203
+ this.clearNativeAuth();
22204
+ WebSessionManager.clearSession();
22205
+ writeAuthMethod(null);
22206
+ setCurrentUser(null);
22207
+ return;
22208
+ }
22015
22209
  try {
22016
22210
  const wallet = await this.ensureWallet();
22017
22211
  const disconnectFeat = getDisconnectFeature(wallet);
@@ -22031,7 +22225,42 @@ class SolanaMobileWalletProvider {
22031
22225
  setCurrentUser(null);
22032
22226
  }
22033
22227
  async signMessage(message) {
22034
- var _a, _b;
22228
+ var _a, _b, _c;
22229
+ // Native: reauthorize with cached auth_token, then signMessages inside
22230
+ // the same transact() session. No wallet-pick popup if the auth_token
22231
+ // is still valid for the user's wallet.
22232
+ if (!getPlatform().hasDOM) {
22233
+ if (!this.nativeAuthToken || !this.nativeAddress) {
22234
+ throw new Error('Wallet not connected. Call login() first.');
22235
+ }
22236
+ const transact = await this.loadTransact();
22237
+ const messageBytes = getPlatform().textEncode(message);
22238
+ const addressBase64 = new PublicKey(this.nativeAddress).toBuffer().toString('base64');
22239
+ const authToken = this.nativeAuthToken;
22240
+ try {
22241
+ const signature = await transact(async (wallet) => {
22242
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
22243
+ const sigs = await wallet.signMessages({
22244
+ addresses: [addressBase64],
22245
+ payloads: [messageBytes],
22246
+ });
22247
+ if (!sigs || sigs.length === 0)
22248
+ throw new Error('MWA returned no signature');
22249
+ return sigs[0];
22250
+ });
22251
+ return bufferExports.Buffer.from(signature).toString('base64');
22252
+ }
22253
+ catch (error) {
22254
+ if (this.isNativeUserCancel(error)) {
22255
+ throw new Error('User declined to sign');
22256
+ }
22257
+ if ((error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED' || (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_REAUTHORIZE') {
22258
+ await this.logout();
22259
+ throw new Error('Wallet connection lost. Please reconnect.');
22260
+ }
22261
+ throw new Error(`Failed to sign message: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
22262
+ }
22263
+ }
22035
22264
  const account = await this.ensureAuthorized();
22036
22265
  const wallet = await this.ensureWallet();
22037
22266
  try {
@@ -22045,7 +22274,7 @@ class SolanaMobileWalletProvider {
22045
22274
  return bufferExports.Buffer.from(sigBytes).toString('base64');
22046
22275
  }
22047
22276
  catch (error) {
22048
- 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')) ||
22277
+ 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')) ||
22049
22278
  (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED') {
22050
22279
  await this.logout();
22051
22280
  throw new Error('Wallet connection lost. Please reconnect.');
@@ -22054,7 +22283,58 @@ class SolanaMobileWalletProvider {
22054
22283
  }
22055
22284
  }
22056
22285
  async signTransaction(transaction) {
22057
- var _a, _b;
22286
+ var _a, _b, _c;
22287
+ // Native: fill blockhash/feePayer if missing, then signTransactions
22288
+ // inside a transact() session keyed by the cached auth_token.
22289
+ if (!getPlatform().hasDOM) {
22290
+ if (!this.nativeAuthToken || !this.nativeAddress) {
22291
+ throw new Error('Wallet not connected. Call login() first.');
22292
+ }
22293
+ const connectedPubkey = new PublicKey(this.nativeAddress);
22294
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
22295
+ if (isLegacyTransaction) {
22296
+ const legacyTx = transaction;
22297
+ if (!legacyTx.recentBlockhash) {
22298
+ const conn = new Connection(this.getRpcUrl(), 'confirmed');
22299
+ const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash('confirmed');
22300
+ legacyTx.recentBlockhash = blockhash;
22301
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
22302
+ }
22303
+ if (!legacyTx.feePayer) {
22304
+ legacyTx.feePayer = connectedPubkey;
22305
+ }
22306
+ }
22307
+ else {
22308
+ const versionedTx = transaction;
22309
+ if (!versionedTx.message.recentBlockhash) {
22310
+ const conn = new Connection(this.getRpcUrl(), 'confirmed');
22311
+ const { blockhash } = await conn.getLatestBlockhash('confirmed');
22312
+ versionedTx.message.recentBlockhash = blockhash;
22313
+ }
22314
+ }
22315
+ const transact = await this.loadTransact();
22316
+ const authToken = this.nativeAuthToken;
22317
+ try {
22318
+ const signed = await transact(async (wallet) => {
22319
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
22320
+ const results = await wallet.signTransactions({ transactions: [transaction] });
22321
+ if (!results || results.length === 0)
22322
+ throw new Error('MWA returned no signed transaction');
22323
+ return results[0];
22324
+ });
22325
+ return signed;
22326
+ }
22327
+ catch (error) {
22328
+ if (this.isNativeUserCancel(error)) {
22329
+ throw new Error('User declined to sign');
22330
+ }
22331
+ if ((error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED' || (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_REAUTHORIZE') {
22332
+ await this.logout();
22333
+ throw new Error('Wallet connection lost. Please reconnect.');
22334
+ }
22335
+ throw new Error(`Failed to sign transaction: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
22336
+ }
22337
+ }
22058
22338
  const account = await this.ensureAuthorized();
22059
22339
  const connectedPubkey = new PublicKey(account.publicKey);
22060
22340
  const wallet = await this.ensureWallet();
@@ -22093,7 +22373,7 @@ class SolanaMobileWalletProvider {
22093
22373
  return txFromWireBytes(new Uint8Array(signedBytes));
22094
22374
  }
22095
22375
  catch (error) {
22096
- 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')) ||
22376
+ 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')) ||
22097
22377
  (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED') {
22098
22378
  await this.logout();
22099
22379
  throw new Error('Wallet connection lost. Please reconnect.');
@@ -22102,7 +22382,70 @@ class SolanaMobileWalletProvider {
22102
22382
  }
22103
22383
  }
22104
22384
  async signAndSubmitTransaction(transaction, feePayer) {
22105
- var _a, _b, _c, _d, _e, _f;
22385
+ var _a, _b, _c, _d, _e, _f, _g;
22386
+ // Native: signAndSendTransactions inside a transact() session.
22387
+ // The wallet submits to its own RPC; we then await confirmation on
22388
+ // ours. Surfnet (custom RPC) needs manual submission because the
22389
+ // wallet won't route there — we fall back to sign-only + manual send.
22390
+ if (!getPlatform().hasDOM) {
22391
+ if (!this.nativeAuthToken || !this.nativeAddress) {
22392
+ throw new Error('Wallet not connected. Call login() first.');
22393
+ }
22394
+ const connectedPubkey = new PublicKey(this.nativeAddress);
22395
+ const rpcUrl = this.getRpcUrl();
22396
+ const connection = new Connection(rpcUrl, 'confirmed');
22397
+ const isSurfnet = rpcUrl === SURFNET_RPC_URL$2;
22398
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
22399
+ const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
22400
+ if (isLegacyTransaction) {
22401
+ const legacyTx = transaction;
22402
+ legacyTx.recentBlockhash = blockhash;
22403
+ legacyTx.lastValidBlockHeight = lastValidBlockHeight;
22404
+ if (!legacyTx.feePayer)
22405
+ legacyTx.feePayer = feePayer !== null && feePayer !== void 0 ? feePayer : connectedPubkey;
22406
+ }
22407
+ else {
22408
+ const versionedTx = transaction;
22409
+ versionedTx.message.recentBlockhash = blockhash;
22410
+ }
22411
+ const transact = await this.loadTransact();
22412
+ const authToken = this.nativeAuthToken;
22413
+ try {
22414
+ if (isSurfnet) {
22415
+ // Surfnet: sign only, submit manually to Surfnet RPC
22416
+ // (the wallet would route signAndSend to its own RPC).
22417
+ const signed = await transact(async (wallet) => {
22418
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
22419
+ const results = await wallet.signTransactions({ transactions: [transaction] });
22420
+ if (!results || results.length === 0)
22421
+ throw new Error('MWA returned no signed transaction');
22422
+ return results[0];
22423
+ });
22424
+ const sig = await connection.sendRawTransaction(signed.serialize(), { preflightCommitment: 'confirmed' });
22425
+ await confirmAndCheckTransaction(connection, sig);
22426
+ return sig;
22427
+ }
22428
+ const sig = await transact(async (wallet) => {
22429
+ await wallet.reauthorize({ auth_token: authToken, identity: this.appIdentity });
22430
+ const results = await wallet.signAndSendTransactions({ transactions: [transaction] });
22431
+ if (!results || results.length === 0)
22432
+ throw new Error('MWA returned no signature');
22433
+ return results[0];
22434
+ });
22435
+ await confirmAndCheckTransaction(connection, sig);
22436
+ return sig;
22437
+ }
22438
+ catch (error) {
22439
+ if (this.isNativeUserCancel(error)) {
22440
+ throw new Error('User declined to sign');
22441
+ }
22442
+ if ((error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED' || (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_REAUTHORIZE') {
22443
+ await this.logout();
22444
+ throw new Error('Wallet connection lost. Please reconnect.');
22445
+ }
22446
+ throw new Error(`Failed to sign+submit transaction: ${(_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error}`);
22447
+ }
22448
+ }
22106
22449
  const account = await this.ensureAuthorized();
22107
22450
  const connectedPubkey = new PublicKey(account.publicKey);
22108
22451
  const wallet = await this.ensureWallet();
@@ -22169,16 +22512,16 @@ class SolanaMobileWalletProvider {
22169
22512
  return signature;
22170
22513
  }
22171
22514
  catch (error) {
22172
- 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')) ||
22515
+ 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')) ||
22173
22516
  (error === null || error === void 0 ? void 0 : error.code) === 'ERROR_AUTHORIZATION_FAILED') {
22174
22517
  await this.logout();
22175
22518
  throw new Error('Wallet connection lost. Please reconnect.');
22176
22519
  }
22177
22520
  const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
22178
- ((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes('user rejected')) ||
22179
- ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('user denied')) ||
22180
- ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user cancelled')) ||
22181
- ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user canceled'));
22521
+ ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('user rejected')) ||
22522
+ ((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user denied')) ||
22523
+ ((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user cancelled')) ||
22524
+ ((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user canceled'));
22182
22525
  if (!isUserRejection) {
22183
22526
  console.error('[SolanaMobileWallet] Transaction failed:', error);
22184
22527
  }
@@ -22728,5 +23071,5 @@ class PrivyExpoProvider {
22728
23071
  }
22729
23072
  }
22730
23073
 
22731
- export { getCachedData as $, subscribe as A, useAuth as B, deserializeTransaction as C, getIdToken as D, setPlatform as E, getPlatform as F, PrivyWalletProvider as G, DEFAULT_TEST_ADDRESS as H, isMobileWalletAvailable as I, registerMobileWalletAdapter as J, PrivyExpoProvider as K, InsufficientBalanceError as L, MockAuthProvider as M, ServerSessionManager as N, OffchainAuthProvider as O, PhantomWalletProvider as P, buildSetDocumentsTransaction as Q, ReactNativeSessionManager as R, SolanaMobileWalletProvider as S, clearCache as T, closeAllSubscriptions as U, convertRemainingAccounts as V, WebSessionManager as W, createSessionWithPrivy as X, createSessionWithSignature as Y, genAuthNonce as Z, genSolanaMessage as _, base58 as a, getMany as a0, reconnectWithNewAuth as a1, refreshSession as a2, signSessionCreateMessage as a3, bufferExports as b, getCurrentUser as c, onAuthLoadingChanged as d, getAuthLoading as e, logout as f, getDefaultExportFromCjs$1 as g, getConfig as h, init as i, getAuthProvider as j, get as k, login as l, setMany as m, setFile as n, onAuthStateChanged as o, getFiles as p, runQueryMany as q, runQuery as r, set as s, runExpression as t, runExpressionMany as u, signMessage as v, signTransaction as w, signAndSubmitTransaction as x, count as y, aggregate as z };
22732
- //# sourceMappingURL=index-BQUfNEiY.esm.js.map
23074
+ export { genAuthNonce as $, count as A, aggregate as B, subscribe as C, useAuth as D, deserializeTransaction as E, getIdToken as F, setPlatform as G, getPlatform as H, PrivyWalletProvider as I, DEFAULT_TEST_ADDRESS as J, isMobileWalletAvailable as K, registerMobileWalletAdapter as L, MockAuthProvider as M, PrivyExpoProvider as N, OffchainAuthProvider as O, PhantomWalletProvider as P, InsufficientBalanceError as Q, ReactNativeSessionManager as R, SolanaMobileWalletProvider as S, ServerSessionManager as T, buildSetDocumentsTransaction as U, clearCache as V, WebSessionManager as W, closeAllSubscriptions as X, convertRemainingAccounts as Y, createSessionWithPrivy as Z, createSessionWithSignature as _, base58 as a, genSolanaMessage as a0, getCachedData as a1, getMany as a2, reconnectWithNewAuth as a3, refreshSession as a4, signSessionCreateMessage as a5, bufferExports as b, commonjsRequire as c, getCurrentUser as d, onAuthLoadingChanged as e, getAuthLoading as f, getDefaultExportFromCjs$1 as g, logout as h, init as i, getConfig as j, getAuthProvider as k, login as l, get as m, setMany as n, onAuthStateChanged as o, setFile as p, getFiles as q, require$$0 as r, set as s, runQuery as t, runQueryMany as u, runExpression as v, runExpressionMany as w, signMessage as x, signTransaction as y, signAndSubmitTransaction as z };
23075
+ //# sourceMappingURL=index-BTwX7FYW.esm.js.map