@phantom/react-native-sdk 1.0.5 → 1.0.7

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.
package/README.md CHANGED
@@ -489,6 +489,42 @@ The SDK automatically handles deep link redirects. Ensure your app's URL scheme
489
489
 
490
490
  **Redirect URL format:** `{scheme}://phantom-auth-callback?wallet_id=...&session_id=...`
491
491
 
492
+ ## Dapp-Sponsored Transactions (presignTransaction)
493
+
494
+ Pass `presignTransaction` directly to `signAndSendTransaction` for calls that need co-signing. Calls without it proceed normally — it is never applied globally.
495
+
496
+ > **Important:** Phantom embedded wallets do not accept pre-signed transactions. If your use case requires a second signer (e.g. your app as the fee payer), that signing must happen via this option, after Phantom has constructed and validated the transaction. This restriction does not apply to injected providers (e.g. the Phantom browser extension).
497
+
498
+ > **Note:** `presignTransaction` only fires for Solana transactions via the embedded provider. EVM transactions are unaffected.
499
+
500
+ ```tsx
501
+ import { useSolana, base64urlDecode, base64urlEncode } from "@phantom/react-native-sdk";
502
+ import { Keypair, VersionedTransaction } from "@solana/web3.js";
503
+
504
+ const feePayerKeypair = Keypair.fromSecretKey(/* your fee payer secret key */);
505
+
506
+ function SendWithFeeSponsor() {
507
+ const { solana } = useSolana();
508
+
509
+ const sendSponsored = async () => {
510
+ // This call co-signs as fee payer
511
+ const result = await solana.signAndSendTransaction(transaction, {
512
+ presignTransaction: async (tx, context) => {
513
+ const txBytes = base64urlDecode(tx);
514
+ const versionedTx = VersionedTransaction.deserialize(txBytes);
515
+ versionedTx.sign([feePayerKeypair]);
516
+ return base64urlEncode(versionedTx.serialize());
517
+ },
518
+ });
519
+ };
520
+
521
+ const sendNormal = async () => {
522
+ // This call has no co-signer
523
+ const result = await solana.signAndSendTransaction(transaction);
524
+ };
525
+ }
526
+ ```
527
+
492
528
  ## Security Features
493
529
 
494
530
  ### Secure Storage
package/dist/index.d.ts CHANGED
@@ -6,8 +6,10 @@ export { ConnectErrorEventData, ConnectEventData, ConnectResult, ConnectStartEve
6
6
  import { PhantomTheme } from '@phantom/wallet-sdk-ui';
7
7
  export { PhantomTheme, darkTheme, lightTheme } from '@phantom/wallet-sdk-ui';
8
8
  import { ISolanaChain, IEthereumChain } from '@phantom/chain-interfaces';
9
- export { AddressType } from '@phantom/client';
9
+ export { SignAndSendTransactionOptions } from '@phantom/chain-interfaces';
10
+ export { AddressType, PresignTransactionContext } from '@phantom/client';
10
11
  export { NetworkId } from '@phantom/constants';
12
+ export { base64urlDecode, base64urlEncode } from '@phantom/base64url';
11
13
 
12
14
  interface PhantomDebugConfig {
13
15
  /** Enable debug logging */
package/dist/index.js CHANGED
@@ -31,8 +31,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  AddressType: () => import_client.AddressType,
34
- NetworkId: () => import_constants4.NetworkId,
34
+ NetworkId: () => import_constants5.NetworkId,
35
35
  PhantomProvider: () => PhantomProvider,
36
+ base64urlDecode: () => import_base64url3.base64urlDecode,
37
+ base64urlEncode: () => import_base64url3.base64urlEncode,
36
38
  darkTheme: () => import_wallet_sdk_ui6.darkTheme,
37
39
  lightTheme: () => import_wallet_sdk_ui6.lightTheme,
38
40
  useAccounts: () => useAccounts,
@@ -48,7 +50,7 @@ module.exports = __toCommonJS(src_exports);
48
50
  // src/PhantomProvider.tsx
49
51
  var import_react8 = require("react");
50
52
  var import_embedded_provider_core = require("@phantom/embedded-provider-core");
51
- var import_constants3 = require("@phantom/constants");
53
+ var import_constants4 = require("@phantom/constants");
52
54
  var import_wallet_sdk_ui5 = require("@phantom/wallet-sdk-ui");
53
55
 
54
56
  // src/ModalProvider.tsx
@@ -557,7 +559,7 @@ var ExpoAuthProvider = class {
557
559
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
558
560
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
559
561
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
560
- sdk_version: "1.0.5",
562
+ sdk_version: "1.0.7",
561
563
  sdk_type: "react-native",
562
564
  platform: import_react_native5.Platform.OS
563
565
  });
@@ -692,14 +694,14 @@ var ExpoAuth2AuthProvider = class {
692
694
  if (!code) {
693
695
  throw new Error("Auth2 callback missing authorization code");
694
696
  }
695
- const { idToken, bearerToken, authUserId, expiresInMs } = await (0, import_auth2.exchangeAuthCode)({
697
+ const { idToken, bearerToken, authUserId, expiresInMs, refreshToken } = await (0, import_auth2.exchangeAuthCode)({
696
698
  authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
697
699
  clientId: this.auth2ProviderOptions.clientId,
698
700
  redirectUri: this.auth2ProviderOptions.redirectUri,
699
701
  code,
700
702
  codeVerifier
701
703
  });
702
- await this.stamper.setIdToken(idToken);
704
+ await this.stamper.setTokens({ idToken, bearerToken, refreshToken, expiresInMs });
703
705
  const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
704
706
  return {
705
707
  walletId,
@@ -720,16 +722,24 @@ var import_bs58 = __toESM(require("bs58"));
720
722
  var import_buffer = require("buffer");
721
723
  var import_base64url = require("@phantom/base64url");
722
724
  var import_sdk_types = require("@phantom/sdk-types");
725
+ var import_auth22 = require("@phantom/auth2");
726
+ var import_constants2 = require("@phantom/constants");
723
727
  var ExpoAuth2Stamper = class {
724
728
  /**
725
729
  * @param storageKey - expo-secure-store key used to persist the P-256 private key.
726
730
  * Use a unique key per app, e.g. `phantom-auth2-<appId>`.
731
+ * @param refreshConfig - When provided, the stamper will automatically refresh
732
+ * the id_token using the refresh_token before it expires.
727
733
  */
728
- constructor(storageKey) {
734
+ constructor(storageKey, refreshConfig) {
729
735
  this.storageKey = storageKey;
736
+ this.refreshConfig = refreshConfig;
730
737
  this._keyPair = null;
731
738
  this._keyInfo = null;
732
739
  this._idToken = null;
740
+ this._bearerToken = null;
741
+ this._refreshToken = null;
742
+ this._tokenExpiresAt = null;
733
743
  this.algorithm = import_sdk_types.Algorithm.secp256r1;
734
744
  this.type = "OIDC";
735
745
  }
@@ -744,6 +754,15 @@ var ExpoAuth2Stamper = class {
744
754
  if (stored.idToken) {
745
755
  this._idToken = stored.idToken;
746
756
  }
757
+ if (stored.bearerToken) {
758
+ this._bearerToken = stored.bearerToken;
759
+ }
760
+ if (stored.refreshToken) {
761
+ this._refreshToken = stored.refreshToken;
762
+ }
763
+ if (stored.tokenExpiresAt) {
764
+ this._tokenExpiresAt = stored.tokenExpiresAt;
765
+ }
747
766
  return this._keyInfo;
748
767
  }
749
768
  return this.generateAndStore();
@@ -755,16 +774,58 @@ var ExpoAuth2Stamper = class {
755
774
  return this._keyPair;
756
775
  }
757
776
  /**
758
- * Arms the stamper with the OIDC id token for subsequent KMS stamp() calls.
777
+ * Returns the current token state (refreshing proactively if near expiry),
778
+ * or null if no token has been set yet.
779
+ */
780
+ async getTokens() {
781
+ if (this.refreshConfig && this._refreshToken && this._tokenExpiresAt !== null && Date.now() >= this._tokenExpiresAt - import_constants2.TOKEN_REFRESH_BUFFER_MS) {
782
+ const refreshed = await (0, import_auth22.refreshToken)({
783
+ authApiBaseUrl: this.refreshConfig.authApiBaseUrl,
784
+ clientId: this.refreshConfig.clientId,
785
+ redirectUri: this.refreshConfig.redirectUri,
786
+ refreshToken: this._refreshToken
787
+ });
788
+ await this.setTokens(refreshed);
789
+ }
790
+ if (!this._idToken || !this._bearerToken) {
791
+ return null;
792
+ }
793
+ return {
794
+ idToken: this._idToken,
795
+ bearerToken: this._bearerToken,
796
+ refreshToken: this._refreshToken ?? void 0
797
+ };
798
+ }
799
+ /**
800
+ * Arms the stamper with the OIDC token data for subsequent KMS stamp() calls.
759
801
  *
760
- * Persists the token to SecureStore alongside the key pair so that
761
- * auto-connect can restore it on the next app launch without a new login.
802
+ * Persists the tokens to SecureStore alongside the key pair so that
803
+ * auto-connect can restore them on the next app launch without a new login.
804
+ *
805
+ * @param refreshToken - When provided alongside a `refreshConfig`, enables
806
+ * silent token refresh before the token expires.
807
+ * @param expiresInMs - Token lifetime in milliseconds (from `expires_in * 1000`).
808
+ * Used to compute the absolute expiry time for proactive refresh.
762
809
  */
763
- async setIdToken(idToken) {
810
+ async setTokens({
811
+ idToken,
812
+ bearerToken,
813
+ refreshToken,
814
+ expiresInMs
815
+ }) {
764
816
  this._idToken = idToken;
817
+ this._bearerToken = bearerToken;
818
+ this._refreshToken = refreshToken ?? null;
819
+ this._tokenExpiresAt = expiresInMs != null ? Date.now() + expiresInMs : null;
765
820
  const existing = await this.loadRecord();
766
821
  if (existing) {
767
- await this.storeRecord({ ...existing, idToken });
822
+ await this.storeRecord({
823
+ ...existing,
824
+ idToken,
825
+ bearerToken,
826
+ refreshToken,
827
+ tokenExpiresAt: this._tokenExpiresAt ?? void 0
828
+ });
768
829
  }
769
830
  }
770
831
  async stamp(params) {
@@ -797,6 +858,9 @@ var ExpoAuth2Stamper = class {
797
858
  this._keyPair = null;
798
859
  this._keyInfo = null;
799
860
  this._idToken = null;
861
+ this._bearerToken = null;
862
+ this._refreshToken = null;
863
+ this._tokenExpiresAt = null;
800
864
  }
801
865
  // Auth2 doesn't use key rotation; minimal no-op implementations.
802
866
  async rotateKeyPair() {
@@ -940,7 +1004,7 @@ var ExpoURLParamsAccessor = class {
940
1004
  // src/providers/embedded/stamper.ts
941
1005
  var SecureStore3 = __toESM(require("expo-secure-store"));
942
1006
  var import_api_key_stamper = require("@phantom/api-key-stamper");
943
- var import_constants2 = require("@phantom/constants");
1007
+ var import_constants3 = require("@phantom/constants");
944
1008
  var import_crypto = require("@phantom/crypto");
945
1009
  var import_base64url2 = require("@phantom/base64url");
946
1010
  var ReactNativeStamper = class {
@@ -948,7 +1012,7 @@ var ReactNativeStamper = class {
948
1012
  constructor(config = {}) {
949
1013
  this.activeKeyRecord = null;
950
1014
  this.pendingKeyRecord = null;
951
- this.algorithm = import_constants2.DEFAULT_AUTHENTICATOR_ALGORITHM;
1015
+ this.algorithm = import_constants3.DEFAULT_AUTHENTICATOR_ALGORITHM;
952
1016
  this.type = "PKI";
953
1017
  this.keyPrefix = config.keyPrefix || "phantom-rn-stamper";
954
1018
  this.appId = config.appId || "default";
@@ -1116,24 +1180,24 @@ var ExpoLogger = class {
1116
1180
  constructor(enabled = false) {
1117
1181
  this.enabled = enabled;
1118
1182
  }
1119
- info(category, message, data) {
1183
+ info(message, ...args) {
1120
1184
  if (this.enabled) {
1121
- console.info(`[${category}] ${message}`, data);
1185
+ console.info(`[PHANTOM] ${message}`, ...args);
1122
1186
  }
1123
1187
  }
1124
- warn(category, message, data) {
1188
+ warn(message, ...args) {
1125
1189
  if (this.enabled) {
1126
- console.warn(`[${category}] ${message}`, data);
1190
+ console.warn(`[PHANTOM] ${message}`, ...args);
1127
1191
  }
1128
1192
  }
1129
- error(category, message, data) {
1193
+ error(message, ...args) {
1130
1194
  if (this.enabled) {
1131
- console.error(`[${category}] ${message}`, data);
1195
+ console.error(`[PHANTOM] ${message}`, ...args);
1132
1196
  }
1133
1197
  }
1134
- log(category, message, data) {
1198
+ debug(message, ...args) {
1135
1199
  if (this.enabled) {
1136
- console.log(`[${category}] ${message}`, data);
1200
+ console.log(`[PHANTOM] ${message}`, ...args);
1137
1201
  }
1138
1202
  }
1139
1203
  };
@@ -1166,12 +1230,12 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1166
1230
  const redirectUrl = config.authOptions?.redirectUrl || `${config.scheme}://phantom-auth-callback`;
1167
1231
  return {
1168
1232
  ...config,
1169
- apiBaseUrl: config.apiBaseUrl || import_constants3.DEFAULT_WALLET_API_URL,
1170
- embeddedWalletType: config.embeddedWalletType || import_constants3.DEFAULT_EMBEDDED_WALLET_TYPE,
1233
+ apiBaseUrl: config.apiBaseUrl || import_constants4.DEFAULT_WALLET_API_URL,
1234
+ embeddedWalletType: config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE,
1171
1235
  authOptions: {
1172
1236
  ...config.authOptions || {},
1173
1237
  redirectUrl,
1174
- authUrl: config.authOptions?.authUrl || import_constants3.DEFAULT_AUTH_URL
1238
+ authUrl: config.authOptions?.authUrl || import_constants4.DEFAULT_AUTH_URL
1175
1239
  }
1176
1240
  };
1177
1241
  }, [config]);
@@ -1179,7 +1243,11 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1179
1243
  const storage = new ExpoSecureStorage();
1180
1244
  const urlParamsAccessor = new ExpoURLParamsAccessor();
1181
1245
  const logger = new ExpoLogger(debugConfig?.enabled || false);
1182
- const stamper = config.unstable__auth2Options ? new ExpoAuth2Stamper(`phantom-auth2-${memoizedConfig.appId}`) : new ReactNativeStamper({
1246
+ const stamper = config.unstable__auth2Options && config.authOptions?.redirectUrl ? new ExpoAuth2Stamper(`phantom-auth2-${memoizedConfig.appId}`, {
1247
+ authApiBaseUrl: config.unstable__auth2Options.authApiBaseUrl,
1248
+ clientId: config.unstable__auth2Options.clientId,
1249
+ redirectUri: config.authOptions.redirectUrl
1250
+ }) : new ReactNativeStamper({
1183
1251
  keyPrefix: `phantom-rn-${memoizedConfig.appId}`,
1184
1252
  appId: memoizedConfig.appId
1185
1253
  });
@@ -1205,13 +1273,13 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1205
1273
  phantomAppProvider: new ReactNativePhantomAppProvider(),
1206
1274
  name: platformName,
1207
1275
  analyticsHeaders: {
1208
- [import_constants3.ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
1209
- [import_constants3.ANALYTICS_HEADERS.PLATFORM]: "ext-sdk",
1210
- [import_constants3.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${import_react_native7.Platform.Version}`,
1211
- [import_constants3.ANALYTICS_HEADERS.CLIENT]: import_react_native7.Platform.OS,
1212
- [import_constants3.ANALYTICS_HEADERS.APP_ID]: config.appId,
1213
- [import_constants3.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1214
- [import_constants3.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.5"
1276
+ [import_constants4.ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
1277
+ [import_constants4.ANALYTICS_HEADERS.PLATFORM]: "ext-sdk",
1278
+ [import_constants4.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${import_react_native7.Platform.Version}`,
1279
+ [import_constants4.ANALYTICS_HEADERS.CLIENT]: import_react_native7.Platform.OS,
1280
+ [import_constants4.ANALYTICS_HEADERS.APP_ID]: config.appId,
1281
+ [import_constants4.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1282
+ [import_constants4.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.7"
1215
1283
  // Replaced at build time
1216
1284
  }
1217
1285
  };
@@ -1325,13 +1393,16 @@ function useEthereum() {
1325
1393
 
1326
1394
  // src/index.ts
1327
1395
  var import_client = require("@phantom/client");
1328
- var import_constants4 = require("@phantom/constants");
1396
+ var import_constants5 = require("@phantom/constants");
1397
+ var import_base64url3 = require("@phantom/base64url");
1329
1398
  var import_wallet_sdk_ui6 = require("@phantom/wallet-sdk-ui");
1330
1399
  // Annotate the CommonJS export names for ESM import in node:
1331
1400
  0 && (module.exports = {
1332
1401
  AddressType,
1333
1402
  NetworkId,
1334
1403
  PhantomProvider,
1404
+ base64urlDecode,
1405
+ base64urlEncode,
1335
1406
  darkTheme,
1336
1407
  lightTheme,
1337
1408
  useAccounts,
package/dist/index.mjs CHANGED
@@ -515,7 +515,7 @@ var ExpoAuthProvider = class {
515
515
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
516
516
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
517
517
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
518
- sdk_version: "1.0.5",
518
+ sdk_version: "1.0.7",
519
519
  sdk_type: "react-native",
520
520
  platform: Platform.OS
521
521
  });
@@ -655,14 +655,14 @@ var ExpoAuth2AuthProvider = class {
655
655
  if (!code) {
656
656
  throw new Error("Auth2 callback missing authorization code");
657
657
  }
658
- const { idToken, bearerToken, authUserId, expiresInMs } = await exchangeAuthCode({
658
+ const { idToken, bearerToken, authUserId, expiresInMs, refreshToken } = await exchangeAuthCode({
659
659
  authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
660
660
  clientId: this.auth2ProviderOptions.clientId,
661
661
  redirectUri: this.auth2ProviderOptions.redirectUri,
662
662
  code,
663
663
  codeVerifier
664
664
  });
665
- await this.stamper.setIdToken(idToken);
665
+ await this.stamper.setTokens({ idToken, bearerToken, refreshToken, expiresInMs });
666
666
  const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
667
667
  return {
668
668
  walletId,
@@ -683,16 +683,24 @@ import bs58 from "bs58";
683
683
  import { Buffer } from "buffer";
684
684
  import { base64urlEncode } from "@phantom/base64url";
685
685
  import { Algorithm } from "@phantom/sdk-types";
686
+ import { refreshToken as refreshTokenRequest } from "@phantom/auth2";
687
+ import { TOKEN_REFRESH_BUFFER_MS } from "@phantom/constants";
686
688
  var ExpoAuth2Stamper = class {
687
689
  /**
688
690
  * @param storageKey - expo-secure-store key used to persist the P-256 private key.
689
691
  * Use a unique key per app, e.g. `phantom-auth2-<appId>`.
692
+ * @param refreshConfig - When provided, the stamper will automatically refresh
693
+ * the id_token using the refresh_token before it expires.
690
694
  */
691
- constructor(storageKey) {
695
+ constructor(storageKey, refreshConfig) {
692
696
  this.storageKey = storageKey;
697
+ this.refreshConfig = refreshConfig;
693
698
  this._keyPair = null;
694
699
  this._keyInfo = null;
695
700
  this._idToken = null;
701
+ this._bearerToken = null;
702
+ this._refreshToken = null;
703
+ this._tokenExpiresAt = null;
696
704
  this.algorithm = Algorithm.secp256r1;
697
705
  this.type = "OIDC";
698
706
  }
@@ -707,6 +715,15 @@ var ExpoAuth2Stamper = class {
707
715
  if (stored.idToken) {
708
716
  this._idToken = stored.idToken;
709
717
  }
718
+ if (stored.bearerToken) {
719
+ this._bearerToken = stored.bearerToken;
720
+ }
721
+ if (stored.refreshToken) {
722
+ this._refreshToken = stored.refreshToken;
723
+ }
724
+ if (stored.tokenExpiresAt) {
725
+ this._tokenExpiresAt = stored.tokenExpiresAt;
726
+ }
710
727
  return this._keyInfo;
711
728
  }
712
729
  return this.generateAndStore();
@@ -718,16 +735,58 @@ var ExpoAuth2Stamper = class {
718
735
  return this._keyPair;
719
736
  }
720
737
  /**
721
- * Arms the stamper with the OIDC id token for subsequent KMS stamp() calls.
738
+ * Returns the current token state (refreshing proactively if near expiry),
739
+ * or null if no token has been set yet.
740
+ */
741
+ async getTokens() {
742
+ if (this.refreshConfig && this._refreshToken && this._tokenExpiresAt !== null && Date.now() >= this._tokenExpiresAt - TOKEN_REFRESH_BUFFER_MS) {
743
+ const refreshed = await refreshTokenRequest({
744
+ authApiBaseUrl: this.refreshConfig.authApiBaseUrl,
745
+ clientId: this.refreshConfig.clientId,
746
+ redirectUri: this.refreshConfig.redirectUri,
747
+ refreshToken: this._refreshToken
748
+ });
749
+ await this.setTokens(refreshed);
750
+ }
751
+ if (!this._idToken || !this._bearerToken) {
752
+ return null;
753
+ }
754
+ return {
755
+ idToken: this._idToken,
756
+ bearerToken: this._bearerToken,
757
+ refreshToken: this._refreshToken ?? void 0
758
+ };
759
+ }
760
+ /**
761
+ * Arms the stamper with the OIDC token data for subsequent KMS stamp() calls.
762
+ *
763
+ * Persists the tokens to SecureStore alongside the key pair so that
764
+ * auto-connect can restore them on the next app launch without a new login.
722
765
  *
723
- * Persists the token to SecureStore alongside the key pair so that
724
- * auto-connect can restore it on the next app launch without a new login.
766
+ * @param refreshToken - When provided alongside a `refreshConfig`, enables
767
+ * silent token refresh before the token expires.
768
+ * @param expiresInMs - Token lifetime in milliseconds (from `expires_in * 1000`).
769
+ * Used to compute the absolute expiry time for proactive refresh.
725
770
  */
726
- async setIdToken(idToken) {
771
+ async setTokens({
772
+ idToken,
773
+ bearerToken,
774
+ refreshToken,
775
+ expiresInMs
776
+ }) {
727
777
  this._idToken = idToken;
778
+ this._bearerToken = bearerToken;
779
+ this._refreshToken = refreshToken ?? null;
780
+ this._tokenExpiresAt = expiresInMs != null ? Date.now() + expiresInMs : null;
728
781
  const existing = await this.loadRecord();
729
782
  if (existing) {
730
- await this.storeRecord({ ...existing, idToken });
783
+ await this.storeRecord({
784
+ ...existing,
785
+ idToken,
786
+ bearerToken,
787
+ refreshToken,
788
+ tokenExpiresAt: this._tokenExpiresAt ?? void 0
789
+ });
731
790
  }
732
791
  }
733
792
  async stamp(params) {
@@ -760,6 +819,9 @@ var ExpoAuth2Stamper = class {
760
819
  this._keyPair = null;
761
820
  this._keyInfo = null;
762
821
  this._idToken = null;
822
+ this._bearerToken = null;
823
+ this._refreshToken = null;
824
+ this._tokenExpiresAt = null;
763
825
  }
764
826
  // Auth2 doesn't use key rotation; minimal no-op implementations.
765
827
  async rotateKeyPair() {
@@ -1079,24 +1141,24 @@ var ExpoLogger = class {
1079
1141
  constructor(enabled = false) {
1080
1142
  this.enabled = enabled;
1081
1143
  }
1082
- info(category, message, data) {
1144
+ info(message, ...args) {
1083
1145
  if (this.enabled) {
1084
- console.info(`[${category}] ${message}`, data);
1146
+ console.info(`[PHANTOM] ${message}`, ...args);
1085
1147
  }
1086
1148
  }
1087
- warn(category, message, data) {
1149
+ warn(message, ...args) {
1088
1150
  if (this.enabled) {
1089
- console.warn(`[${category}] ${message}`, data);
1151
+ console.warn(`[PHANTOM] ${message}`, ...args);
1090
1152
  }
1091
1153
  }
1092
- error(category, message, data) {
1154
+ error(message, ...args) {
1093
1155
  if (this.enabled) {
1094
- console.error(`[${category}] ${message}`, data);
1156
+ console.error(`[PHANTOM] ${message}`, ...args);
1095
1157
  }
1096
1158
  }
1097
- log(category, message, data) {
1159
+ debug(message, ...args) {
1098
1160
  if (this.enabled) {
1099
- console.log(`[${category}] ${message}`, data);
1161
+ console.log(`[PHANTOM] ${message}`, ...args);
1100
1162
  }
1101
1163
  }
1102
1164
  };
@@ -1142,7 +1204,11 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1142
1204
  const storage = new ExpoSecureStorage();
1143
1205
  const urlParamsAccessor = new ExpoURLParamsAccessor();
1144
1206
  const logger = new ExpoLogger(debugConfig?.enabled || false);
1145
- const stamper = config.unstable__auth2Options ? new ExpoAuth2Stamper(`phantom-auth2-${memoizedConfig.appId}`) : new ReactNativeStamper({
1207
+ const stamper = config.unstable__auth2Options && config.authOptions?.redirectUrl ? new ExpoAuth2Stamper(`phantom-auth2-${memoizedConfig.appId}`, {
1208
+ authApiBaseUrl: config.unstable__auth2Options.authApiBaseUrl,
1209
+ clientId: config.unstable__auth2Options.clientId,
1210
+ redirectUri: config.authOptions.redirectUrl
1211
+ }) : new ReactNativeStamper({
1146
1212
  keyPrefix: `phantom-rn-${memoizedConfig.appId}`,
1147
1213
  appId: memoizedConfig.appId
1148
1214
  });
@@ -1174,7 +1240,7 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1174
1240
  [ANALYTICS_HEADERS.CLIENT]: Platform2.OS,
1175
1241
  [ANALYTICS_HEADERS.APP_ID]: config.appId,
1176
1242
  [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1177
- [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.5"
1243
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.7"
1178
1244
  // Replaced at build time
1179
1245
  }
1180
1246
  };
@@ -1289,11 +1355,14 @@ function useEthereum() {
1289
1355
  // src/index.ts
1290
1356
  import { AddressType } from "@phantom/client";
1291
1357
  import { NetworkId } from "@phantom/constants";
1358
+ import { base64urlEncode as base64urlEncode3, base64urlDecode } from "@phantom/base64url";
1292
1359
  import { darkTheme as darkTheme2, lightTheme } from "@phantom/wallet-sdk-ui";
1293
1360
  export {
1294
1361
  AddressType,
1295
1362
  NetworkId,
1296
1363
  PhantomProvider,
1364
+ base64urlDecode,
1365
+ base64urlEncode3 as base64urlEncode,
1297
1366
  darkTheme2 as darkTheme,
1298
1367
  lightTheme,
1299
1368
  useAccounts,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-native-sdk",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Phantom Wallet SDK for React Native and Expo applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -45,16 +45,16 @@
45
45
  "directory": "packages/react-native-sdk"
46
46
  },
47
47
  "dependencies": {
48
- "@phantom/api-key-stamper": "^1.0.5",
49
- "@phantom/auth2": "^1.0.1",
50
- "@phantom/base64url": "^1.0.5",
51
- "@phantom/chain-interfaces": "^1.0.5",
52
- "@phantom/client": "^1.0.5",
53
- "@phantom/constants": "^1.0.5",
54
- "@phantom/crypto": "^1.0.5",
55
- "@phantom/embedded-provider-core": "^1.0.5",
56
- "@phantom/sdk-types": "^1.0.5",
57
- "@phantom/wallet-sdk-ui": "^1.0.5",
48
+ "@phantom/api-key-stamper": "^1.0.7",
49
+ "@phantom/auth2": "^1.0.2",
50
+ "@phantom/base64url": "^1.0.7",
51
+ "@phantom/chain-interfaces": "^1.0.7",
52
+ "@phantom/client": "^1.0.7",
53
+ "@phantom/constants": "^1.0.7",
54
+ "@phantom/crypto": "^1.0.7",
55
+ "@phantom/embedded-provider-core": "^1.0.7",
56
+ "@phantom/sdk-types": "^1.0.7",
57
+ "@phantom/wallet-sdk-ui": "^1.0.7",
58
58
  "@types/bs58": "^5.0.0",
59
59
  "bs58": "^6.0.0",
60
60
  "buffer": "^6.0.3"