@phantom/react-native-sdk 1.0.7 → 2.0.0-beta.0

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/dist/index.js CHANGED
@@ -31,10 +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_constants5.NetworkId,
34
+ NetworkId: () => import_constants2.NetworkId,
35
35
  PhantomProvider: () => PhantomProvider,
36
- base64urlDecode: () => import_base64url3.base64urlDecode,
37
- base64urlEncode: () => import_base64url3.base64urlEncode,
36
+ base64urlDecode: () => import_base64url.base64urlDecode,
37
+ base64urlEncode: () => import_base64url.base64urlEncode,
38
38
  darkTheme: () => import_wallet_sdk_ui6.darkTheme,
39
39
  lightTheme: () => import_wallet_sdk_ui6.lightTheme,
40
40
  useAccounts: () => useAccounts,
@@ -50,7 +50,7 @@ module.exports = __toCommonJS(src_exports);
50
50
  // src/PhantomProvider.tsx
51
51
  var import_react8 = require("react");
52
52
  var import_embedded_provider_core = require("@phantom/embedded-provider-core");
53
- var import_constants4 = require("@phantom/constants");
53
+ var import_constants = require("@phantom/constants");
54
54
  var import_wallet_sdk_ui5 = require("@phantom/wallet-sdk-ui");
55
55
 
56
56
  // src/ModalProvider.tsx
@@ -532,110 +532,8 @@ var ExpoSecureStorage = class {
532
532
  }
533
533
  };
534
534
 
535
- // src/providers/embedded/auth.ts
536
- var WebBrowser = __toESM(require("expo-web-browser"));
537
- var import_react_native5 = require("react-native");
538
- var import_constants = require("@phantom/constants");
539
- var ExpoAuthProvider = class {
540
- async authenticate(options) {
541
- if ("jwtToken" in options) {
542
- return;
543
- }
544
- const phantomOptions = options;
545
- const { authUrl, redirectUrl, publicKey, sessionId, provider, appId } = phantomOptions;
546
- if (!redirectUrl) {
547
- throw new Error("redirectUrl is required for web browser authentication");
548
- }
549
- if (!publicKey || !sessionId || !appId) {
550
- throw new Error("publicKey, sessionId and appId are required for authentication");
551
- }
552
- try {
553
- const baseUrl = authUrl || import_constants.DEFAULT_AUTH_URL;
554
- const params = new URLSearchParams({
555
- public_key: publicKey,
556
- app_id: appId,
557
- redirect_uri: redirectUrl,
558
- session_id: sessionId,
559
- // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
560
- clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
561
- allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
562
- sdk_version: "1.0.7",
563
- sdk_type: "react-native",
564
- platform: import_react_native5.Platform.OS
565
- });
566
- if (provider) {
567
- console.log("[ExpoAuthProvider] Provider specified, will skip selection", { provider });
568
- params.append("provider", provider);
569
- } else {
570
- console.log("[ExpoAuthProvider] No provider specified, defaulting to Google");
571
- params.append("provider", "google");
572
- }
573
- const fullAuthUrl = `${baseUrl}?${params.toString()}`;
574
- console.log("[ExpoAuthProvider] Starting authentication", {
575
- baseUrl,
576
- redirectUrl,
577
- publicKey,
578
- sessionId,
579
- provider
580
- });
581
- await WebBrowser.warmUpAsync();
582
- const result = await WebBrowser.openAuthSessionAsync(fullAuthUrl, redirectUrl, {
583
- // Use system browser on iOS for ASWebAuthenticationSession
584
- preferEphemeralSession: false
585
- });
586
- console.log("[ExpoAuthProvider] Authentication result", {
587
- type: result.type,
588
- url: result.type === "success" && result.url ? result.url.substring(0, 100) + "..." : void 0
589
- });
590
- if (result.type === "success" && result.url) {
591
- const url = new URL(result.url);
592
- const walletId = url.searchParams.get("wallet_id");
593
- const organizationId = url.searchParams.get("organization_id");
594
- const accountDerivationIndex = url.searchParams.get("selected_account_index");
595
- const expiresInMs = url.searchParams.get("expires_in_ms");
596
- const authUserId = url.searchParams.get("auth_user_id");
597
- if (!walletId) {
598
- throw new Error("Authentication failed: no walletId in redirect URL");
599
- }
600
- if (!organizationId) {
601
- console.error("[ExpoAuthProvider] Missing organizationId in redirect URL", { url: result.url });
602
- throw new Error("Authentication failed: no organizationId in redirect URL");
603
- }
604
- console.log("[ExpoAuthProvider] Auth redirect parameters", {
605
- walletId,
606
- organizationId,
607
- provider,
608
- accountDerivationIndex,
609
- expiresInMs,
610
- authUserId
611
- });
612
- return {
613
- walletId,
614
- organizationId,
615
- provider: provider || void 0,
616
- accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
617
- expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
618
- authUserId: authUserId || void 0
619
- };
620
- } else if (result.type === "cancel") {
621
- throw new Error("User cancelled authentication");
622
- } else {
623
- throw new Error("Authentication failed");
624
- }
625
- } catch (error) {
626
- console.error("[ExpoAuthProvider] Authentication error", error);
627
- throw error;
628
- } finally {
629
- await WebBrowser.coolDownAsync();
630
- }
631
- }
632
- isAvailable() {
633
- return Promise.resolve(true);
634
- }
635
- };
636
-
637
535
  // src/providers/embedded/ExpoAuth2AuthProvider.ts
638
- var WebBrowser2 = __toESM(require("expo-web-browser"));
536
+ var WebBrowser = __toESM(require("expo-web-browser"));
639
537
  var import_auth2 = require("@phantom/auth2");
640
538
  var ExpoAuth2AuthProvider = class {
641
539
  constructor(stamper, auth2ProviderOptions, kmsClientOptions) {
@@ -651,246 +549,111 @@ var ExpoAuth2AuthProvider = class {
651
549
  * so the token exchange and KMS calls all happen here before returning AuthResult.
652
550
  */
653
551
  async authenticate(options) {
654
- if (!this.stamper.getKeyInfo()) {
655
- await this.stamper.init();
656
- }
657
- const keyPair = this.stamper.getCryptoKeyPair();
658
- if (!keyPair) {
659
- throw new Error("Stamper key pair not found.");
660
- }
661
- const codeVerifier = (0, import_auth2.createCodeVerifier)();
662
- const url = await (0, import_auth2.createConnectStartUrl)({
663
- keyPair,
664
- connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
665
- clientId: this.auth2ProviderOptions.clientId,
666
- redirectUri: this.auth2ProviderOptions.redirectUri,
552
+ const { url, codeVerifier } = await (0, import_auth2.prepareAuth2Flow)({
553
+ stamper: this.stamper,
554
+ auth2Options: this.auth2ProviderOptions,
667
555
  sessionId: options.sessionId,
668
- provider: options.provider,
669
- codeVerifier,
670
- // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
671
- salt: ""
556
+ provider: options.provider
672
557
  });
673
- await WebBrowser2.warmUpAsync();
558
+ await WebBrowser.warmUpAsync();
674
559
  let result;
675
560
  try {
676
- result = await WebBrowser2.openAuthSessionAsync(url, this.auth2ProviderOptions.redirectUri);
561
+ result = await WebBrowser.openAuthSessionAsync(url, this.auth2ProviderOptions.redirectUri);
677
562
  } finally {
678
- await WebBrowser2.coolDownAsync();
563
+ await WebBrowser.coolDownAsync();
679
564
  }
680
565
  if (!result.url) {
681
566
  throw new Error("Authentication failed");
682
567
  }
683
568
  const callbackUrl = new URL(result.url);
684
- const state = callbackUrl.searchParams.get("state");
685
- if (state && state !== options.sessionId) {
686
- throw new Error("Auth2 state mismatch \u2014 possible CSRF attack.");
687
- }
688
- const error = callbackUrl.searchParams.get("error");
689
- if (error) {
690
- const description = callbackUrl.searchParams.get("error_description");
691
- throw new Error(`Auth2 callback error: ${description ?? error}`);
692
- }
693
- const code = callbackUrl.searchParams.get("code");
694
- if (!code) {
695
- throw new Error("Auth2 callback missing authorization code");
696
- }
697
- const { idToken, bearerToken, authUserId, expiresInMs, refreshToken } = await (0, import_auth2.exchangeAuthCode)({
698
- authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
699
- clientId: this.auth2ProviderOptions.clientId,
700
- redirectUri: this.auth2ProviderOptions.redirectUri,
569
+ const code = (0, import_auth2.validateAuth2Callback)({
570
+ getParam: (key) => callbackUrl.searchParams.get(key),
571
+ expectedSessionId: options.sessionId
572
+ });
573
+ return (0, import_auth2.completeAuth2Exchange)({
574
+ stamper: this.stamper,
575
+ kms: this.kms,
576
+ auth2Options: this.auth2ProviderOptions,
701
577
  code,
702
- codeVerifier
578
+ codeVerifier,
579
+ provider: options.provider
703
580
  });
704
- await this.stamper.setTokens({ idToken, bearerToken, refreshToken, expiresInMs });
705
- const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
706
- return {
707
- walletId,
708
- organizationId,
709
- provider: options.provider,
710
- accountDerivationIndex: 0,
711
- // discoverWalletId uses derivation index of 0.
712
- expiresInMs,
713
- authUserId,
714
- bearerToken
715
- };
716
581
  }
717
582
  };
718
583
 
719
- // src/providers/embedded/ExpoAuth2Stamper.ts
584
+ // src/PhantomProvider.tsx
585
+ var import_auth22 = require("@phantom/auth2");
586
+
587
+ // src/providers/embedded/SecureStoreAuth2StamperStorage.ts
720
588
  var SecureStore2 = __toESM(require("expo-secure-store"));
721
589
  var import_bs58 = __toESM(require("bs58"));
722
590
  var import_buffer = require("buffer");
723
- var import_base64url = require("@phantom/base64url");
724
- var import_sdk_types = require("@phantom/sdk-types");
725
- var import_auth22 = require("@phantom/auth2");
726
- var import_constants2 = require("@phantom/constants");
727
- var ExpoAuth2Stamper = class {
728
- /**
729
- * @param storageKey - expo-secure-store key used to persist the P-256 private key.
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.
733
- */
734
- constructor(storageKey, refreshConfig) {
591
+ var SecureStoreAuth2StamperStorage = class {
592
+ constructor(storageKey) {
735
593
  this.storageKey = storageKey;
736
- this.refreshConfig = refreshConfig;
737
- this._keyPair = null;
738
- this._keyInfo = null;
739
- this._idToken = null;
740
- this._bearerToken = null;
741
- this._refreshToken = null;
742
- this._tokenExpiresAt = null;
743
- this.algorithm = import_sdk_types.Algorithm.secp256r1;
744
- this.type = "OIDC";
594
+ this.requiresExtractableKeys = true;
745
595
  }
746
- async init() {
747
- const stored = await this.loadRecord();
748
- if (stored) {
749
- this._keyPair = {
750
- privateKey: await this.importPrivateKey(stored.privateKeyPkcs8),
751
- publicKey: await this.importPublicKeyFromBase58(stored.keyInfo.publicKey)
752
- };
753
- this._keyInfo = stored.keyInfo;
754
- if (stored.idToken) {
755
- this._idToken = stored.idToken;
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
- }
766
- return this._keyInfo;
596
+ async load() {
597
+ const raw = await SecureStore2.getItemAsync(this.storageKey);
598
+ if (raw === null) {
599
+ return null;
767
600
  }
768
- return this.generateAndStore();
769
- }
770
- getKeyInfo() {
771
- return this._keyInfo;
772
- }
773
- getCryptoKeyPair() {
774
- return this._keyPair;
775
- }
776
- /**
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);
601
+ let record;
602
+ try {
603
+ record = JSON.parse(raw);
604
+ } catch (err) {
605
+ await SecureStore2.deleteItemAsync(this.storageKey);
606
+ throw new Error(`SecureStoreAuth2StamperStorage: corrupt stored record (JSON parse failed): ${err}`);
789
607
  }
790
- if (!this._idToken || !this._bearerToken) {
791
- return null;
608
+ let privateKey;
609
+ let publicKey;
610
+ try {
611
+ privateKey = await this.importPrivateKey(record.privateKeyPkcs8);
612
+ publicKey = await this.importPublicKeyFromBase58(record.keyInfo.publicKey);
613
+ } catch (err) {
614
+ await SecureStore2.deleteItemAsync(this.storageKey);
615
+ throw new Error(`SecureStoreAuth2StamperStorage: corrupt stored record (key import failed): ${err}`);
792
616
  }
793
617
  return {
794
- idToken: this._idToken,
795
- bearerToken: this._bearerToken,
796
- refreshToken: this._refreshToken ?? void 0
618
+ keyPair: { privateKey, publicKey },
619
+ keyInfo: record.keyInfo,
620
+ accessToken: record.accessToken,
621
+ idType: record.idType,
622
+ refreshToken: record.refreshToken,
623
+ tokenExpiresAt: record.tokenExpiresAt
797
624
  };
798
625
  }
799
- /**
800
- * Arms the stamper with the OIDC token data for subsequent KMS stamp() calls.
801
- *
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.
809
- */
810
- async setTokens({
811
- idToken,
812
- bearerToken,
813
- refreshToken,
814
- expiresInMs
815
- }) {
816
- this._idToken = idToken;
817
- this._bearerToken = bearerToken;
818
- this._refreshToken = refreshToken ?? null;
819
- this._tokenExpiresAt = expiresInMs != null ? Date.now() + expiresInMs : null;
820
- const existing = await this.loadRecord();
821
- if (existing) {
822
- await this.storeRecord({
823
- ...existing,
824
- idToken,
825
- bearerToken,
826
- refreshToken,
827
- tokenExpiresAt: this._tokenExpiresAt ?? void 0
828
- });
829
- }
830
- }
831
- async stamp(params) {
832
- if (!this._keyPair || !this._keyInfo || this._idToken === null) {
833
- throw new Error("ExpoAuth2Stamper not initialized. Call init() first.");
834
- }
835
- const signatureRaw = await crypto.subtle.sign(
836
- { name: "ECDSA", hash: "SHA-256" },
837
- this._keyPair.privateKey,
838
- new Uint8Array(params.data)
839
- );
840
- const rawPublicKey = import_bs58.default.decode(this._keyInfo.publicKey);
841
- const stampData = {
842
- kind: this.type,
843
- idToken: this._idToken,
844
- publicKey: (0, import_base64url.base64urlEncode)(rawPublicKey),
845
- algorithm: this.algorithm,
846
- // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
847
- salt: "",
848
- signature: (0, import_base64url.base64urlEncode)(new Uint8Array(signatureRaw))
626
+ async save(record) {
627
+ const pkcs8Buffer = await crypto.subtle.exportKey("pkcs8", record.keyPair.privateKey);
628
+ const privateKeyPkcs8 = import_buffer.Buffer.from(pkcs8Buffer).toString("base64");
629
+ const serialized = {
630
+ privateKeyPkcs8,
631
+ keyInfo: record.keyInfo,
632
+ accessToken: record.accessToken,
633
+ idType: record.idType,
634
+ refreshToken: record.refreshToken,
635
+ tokenExpiresAt: record.tokenExpiresAt
849
636
  };
850
- return (0, import_base64url.base64urlEncode)(new TextEncoder().encode(JSON.stringify(stampData)));
851
- }
852
- async resetKeyPair() {
853
- await this.clear();
854
- return this.generateAndStore();
637
+ await SecureStore2.setItemAsync(this.storageKey, JSON.stringify(serialized), {
638
+ requireAuthentication: false
639
+ });
855
640
  }
856
641
  async clear() {
857
- await this.clearStoredRecord();
858
- this._keyPair = null;
859
- this._keyInfo = null;
860
- this._idToken = null;
861
- this._bearerToken = null;
862
- this._refreshToken = null;
863
- this._tokenExpiresAt = null;
864
- }
865
- // Auth2 doesn't use key rotation; minimal no-op implementations.
866
- async rotateKeyPair() {
867
- return this.init();
868
- }
869
- // eslint-disable-next-line @typescript-eslint/require-await
870
- async commitRotation(authenticatorId) {
871
- if (this._keyInfo) {
872
- this._keyInfo.authenticatorId = authenticatorId;
642
+ try {
643
+ await SecureStore2.deleteItemAsync(this.storageKey);
644
+ } catch {
873
645
  }
874
646
  }
875
- async rollbackRotation() {
876
- }
877
- async generateAndStore() {
878
- const keyPair = await crypto.subtle.generateKey(
647
+ async importPrivateKey(pkcs8Base64) {
648
+ const pkcs8Bytes = import_buffer.Buffer.from(pkcs8Base64, "base64");
649
+ return crypto.subtle.importKey(
650
+ "pkcs8",
651
+ pkcs8Bytes,
879
652
  { name: "ECDSA", namedCurve: "P-256" },
880
- true,
881
- // extractable needed to export PKCS#8 for SecureStore
882
- ["sign", "verify"]
653
+ this.requiresExtractableKeys,
654
+ // extractable so save() can re-export via pkcs8
655
+ ["sign"]
883
656
  );
884
- const rawPublicKey = new Uint8Array(await crypto.subtle.exportKey("raw", keyPair.publicKey));
885
- const publicKeyBase58 = import_bs58.default.encode(rawPublicKey);
886
- const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
887
- const keyId = (0, import_base64url.base64urlEncode)(new Uint8Array(keyIdBuffer)).substring(0, 16);
888
- this._keyPair = keyPair;
889
- this._keyInfo = { keyId, publicKey: publicKeyBase58, createdAt: Date.now() };
890
- const pkcs8Buffer = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
891
- const privateKeyPkcs8 = import_buffer.Buffer.from(pkcs8Buffer).toString("base64");
892
- await this.storeRecord({ privateKeyPkcs8, keyInfo: this._keyInfo });
893
- return this._keyInfo;
894
657
  }
895
658
  async importPublicKeyFromBase58(base58PublicKey) {
896
659
  const rawBytes = import_bs58.default.decode(base58PublicKey);
@@ -903,38 +666,10 @@ var ExpoAuth2Stamper = class {
903
666
  ["verify"]
904
667
  );
905
668
  }
906
- async importPrivateKey(pkcs8Base64) {
907
- const pkcs8Bytes = import_buffer.Buffer.from(pkcs8Base64, "base64");
908
- return crypto.subtle.importKey(
909
- "pkcs8",
910
- pkcs8Bytes,
911
- { name: "ECDSA", namedCurve: "P-256" },
912
- false,
913
- // non-extractable once loaded into memory
914
- ["sign"]
915
- );
916
- }
917
- async loadRecord() {
918
- try {
919
- const raw = await SecureStore2.getItemAsync(this.storageKey);
920
- return raw ? JSON.parse(raw) : null;
921
- } catch {
922
- return null;
923
- }
924
- }
925
- async storeRecord(record) {
926
- await SecureStore2.setItemAsync(this.storageKey, JSON.stringify(record), { requireAuthentication: false });
927
- }
928
- async clearStoredRecord() {
929
- try {
930
- await SecureStore2.deleteItemAsync(this.storageKey);
931
- } catch {
932
- }
933
- }
934
669
  };
935
670
 
936
671
  // src/providers/embedded/url-params.ts
937
- var import_react_native6 = require("react-native");
672
+ var import_react_native5 = require("react-native");
938
673
  var ExpoURLParamsAccessor = class {
939
674
  constructor() {
940
675
  this.listeners = /* @__PURE__ */ new Set();
@@ -946,7 +681,7 @@ var ExpoURLParamsAccessor = class {
946
681
  }
947
682
  async getInitialParams() {
948
683
  try {
949
- const url = await import_react_native6.Linking.getInitialURL();
684
+ const url = await import_react_native5.Linking.getInitialURL();
950
685
  if (!url) {
951
686
  return null;
952
687
  }
@@ -962,7 +697,7 @@ var ExpoURLParamsAccessor = class {
962
697
  if (this.subscription) {
963
698
  return;
964
699
  }
965
- this.subscription = import_react_native6.Linking.addEventListener("url", ({ url }) => {
700
+ this.subscription = import_react_native5.Linking.addEventListener("url", ({ url }) => {
966
701
  const params = this.parseURLParams(url);
967
702
  if (params && Object.keys(params).length > 0) {
968
703
  this.currentParams = { ...this.currentParams, ...params };
@@ -1001,180 +736,6 @@ var ExpoURLParamsAccessor = class {
1001
736
  }
1002
737
  };
1003
738
 
1004
- // src/providers/embedded/stamper.ts
1005
- var SecureStore3 = __toESM(require("expo-secure-store"));
1006
- var import_api_key_stamper = require("@phantom/api-key-stamper");
1007
- var import_constants3 = require("@phantom/constants");
1008
- var import_crypto = require("@phantom/crypto");
1009
- var import_base64url2 = require("@phantom/base64url");
1010
- var ReactNativeStamper = class {
1011
- // Optional for PKI, required for OIDC
1012
- constructor(config = {}) {
1013
- this.activeKeyRecord = null;
1014
- this.pendingKeyRecord = null;
1015
- this.algorithm = import_constants3.DEFAULT_AUTHENTICATOR_ALGORITHM;
1016
- this.type = "PKI";
1017
- this.keyPrefix = config.keyPrefix || "phantom-rn-stamper";
1018
- this.appId = config.appId || "default";
1019
- }
1020
- /**
1021
- * Initialize the stamper and generate/load cryptographic keys
1022
- */
1023
- async init() {
1024
- this.activeKeyRecord = await this.loadActiveKeyRecord();
1025
- if (!this.activeKeyRecord) {
1026
- this.activeKeyRecord = await this.generateAndStoreNewKeyRecord("active");
1027
- }
1028
- this.pendingKeyRecord = await this.loadPendingKeyRecord();
1029
- return this.activeKeyRecord.keyInfo;
1030
- }
1031
- /**
1032
- * Get the current key information
1033
- */
1034
- getKeyInfo() {
1035
- return this.activeKeyRecord?.keyInfo || null;
1036
- }
1037
- /**
1038
- * Generate and store a new key pair, replacing any existing keys
1039
- */
1040
- async resetKeyPair() {
1041
- await this.clear();
1042
- this.activeKeyRecord = await this.generateAndStoreNewKeyRecord("active");
1043
- this.pendingKeyRecord = null;
1044
- return this.activeKeyRecord.keyInfo;
1045
- }
1046
- /**
1047
- * Create X-Phantom-Stamp header value using stored secret key
1048
- * @param params - Parameters object with data to sign and optional override params
1049
- * @returns Complete X-Phantom-Stamp header value
1050
- */
1051
- async stamp(params) {
1052
- if (!this.activeKeyRecord) {
1053
- throw new Error("Stamper not initialized. Call init() first.");
1054
- }
1055
- const apiKeyStamper = new import_api_key_stamper.ApiKeyStamper({ apiSecretKey: this.activeKeyRecord.secretKey });
1056
- return await apiKeyStamper.stamp(params);
1057
- }
1058
- /**
1059
- * Clear all stored keys from SecureStore
1060
- */
1061
- async clear() {
1062
- const activeKey = this.getActiveKeyName();
1063
- const pendingKey = this.getPendingKeyName();
1064
- try {
1065
- await SecureStore3.deleteItemAsync(activeKey);
1066
- } catch (error) {
1067
- }
1068
- try {
1069
- await SecureStore3.deleteItemAsync(pendingKey);
1070
- } catch (error) {
1071
- }
1072
- this.activeKeyRecord = null;
1073
- this.pendingKeyRecord = null;
1074
- }
1075
- /**
1076
- * Generate a new keypair for rotation without making it active
1077
- */
1078
- async rotateKeyPair() {
1079
- this.pendingKeyRecord = await this.generateAndStoreNewKeyRecord("pending");
1080
- return this.pendingKeyRecord.keyInfo;
1081
- }
1082
- /**
1083
- * Switch to the pending keypair, making it active and cleaning up the old one
1084
- */
1085
- async commitRotation(authenticatorId) {
1086
- if (!this.pendingKeyRecord) {
1087
- throw new Error("No pending keypair to commit");
1088
- }
1089
- if (this.activeKeyRecord) {
1090
- try {
1091
- await SecureStore3.deleteItemAsync(this.getActiveKeyName());
1092
- } catch (error) {
1093
- }
1094
- }
1095
- this.pendingKeyRecord.status = "active";
1096
- this.pendingKeyRecord.authenticatorId = authenticatorId;
1097
- this.pendingKeyRecord.keyInfo.authenticatorId = authenticatorId;
1098
- this.activeKeyRecord = this.pendingKeyRecord;
1099
- this.pendingKeyRecord = null;
1100
- await this.storeKeyRecord(this.activeKeyRecord, "active");
1101
- try {
1102
- await SecureStore3.deleteItemAsync(this.getPendingKeyName());
1103
- } catch (error) {
1104
- }
1105
- }
1106
- /**
1107
- * Discard the pending keypair on rotation failure
1108
- */
1109
- async rollbackRotation() {
1110
- if (!this.pendingKeyRecord) {
1111
- return;
1112
- }
1113
- try {
1114
- await SecureStore3.deleteItemAsync(this.getPendingKeyName());
1115
- } catch (error) {
1116
- }
1117
- this.pendingKeyRecord = null;
1118
- }
1119
- async generateAndStoreNewKeyRecord(type) {
1120
- const keypair = (0, import_crypto.generateKeyPair)();
1121
- const keyId = this.createKeyId(keypair.publicKey);
1122
- const now = Date.now();
1123
- const keyInfo = {
1124
- keyId,
1125
- publicKey: keypair.publicKey,
1126
- createdAt: now
1127
- };
1128
- const record = {
1129
- keyInfo,
1130
- secretKey: keypair.secretKey,
1131
- createdAt: now,
1132
- expiresAt: 0,
1133
- // Not used anymore, kept for backward compatibility
1134
- status: type
1135
- };
1136
- await this.storeKeyRecord(record, type);
1137
- return record;
1138
- }
1139
- createKeyId(publicKey) {
1140
- return (0, import_base64url2.base64urlEncode)(new TextEncoder().encode(publicKey)).substring(0, 16);
1141
- }
1142
- async storeKeyRecord(record, type) {
1143
- const keyName = type === "active" ? this.getActiveKeyName() : this.getPendingKeyName();
1144
- await SecureStore3.setItemAsync(keyName, JSON.stringify(record), {
1145
- requireAuthentication: false
1146
- });
1147
- }
1148
- async loadActiveKeyRecord() {
1149
- try {
1150
- const activeKey = this.getActiveKeyName();
1151
- const storedRecord = await SecureStore3.getItemAsync(activeKey);
1152
- if (storedRecord) {
1153
- return JSON.parse(storedRecord);
1154
- }
1155
- } catch (error) {
1156
- }
1157
- return null;
1158
- }
1159
- async loadPendingKeyRecord() {
1160
- try {
1161
- const pendingKey = this.getPendingKeyName();
1162
- const storedRecord = await SecureStore3.getItemAsync(pendingKey);
1163
- if (storedRecord) {
1164
- return JSON.parse(storedRecord);
1165
- }
1166
- } catch (error) {
1167
- }
1168
- return null;
1169
- }
1170
- getActiveKeyName() {
1171
- return `${this.keyPrefix}-${this.appId}-active`;
1172
- }
1173
- getPendingKeyName() {
1174
- return `${this.keyPrefix}-${this.appId}-pending`;
1175
- }
1176
- };
1177
-
1178
739
  // src/providers/embedded/logger.ts
1179
740
  var ExpoLogger = class {
1180
741
  constructor(enabled = false) {
@@ -1217,7 +778,7 @@ var ReactNativePhantomAppProvider = class {
1217
778
  };
1218
779
 
1219
780
  // src/PhantomProvider.tsx
1220
- var import_react_native7 = require("react-native");
781
+ var import_react_native6 = require("react-native");
1221
782
  var import_jsx_runtime6 = require("react/jsx-runtime");
1222
783
  function PhantomProvider({ children, config, debugConfig, theme, appIcon, appName }) {
1223
784
  const [isConnected, setIsConnected] = (0, import_react8.useState)(false);
@@ -1230,12 +791,12 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1230
791
  const redirectUrl = config.authOptions?.redirectUrl || `${config.scheme}://phantom-auth-callback`;
1231
792
  return {
1232
793
  ...config,
1233
- apiBaseUrl: config.apiBaseUrl || import_constants4.DEFAULT_WALLET_API_URL,
1234
- embeddedWalletType: config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE,
794
+ apiBaseUrl: config.apiBaseUrl || import_constants.DEFAULT_WALLET_API_URL,
795
+ embeddedWalletType: config.embeddedWalletType || import_constants.DEFAULT_EMBEDDED_WALLET_TYPE,
1235
796
  authOptions: {
1236
- ...config.authOptions || {},
1237
797
  redirectUrl,
1238
- authUrl: config.authOptions?.authUrl || import_constants4.DEFAULT_AUTH_URL
798
+ authUrl: config.authOptions?.authUrl || import_constants.DEFAULT_AUTH_URL,
799
+ authApiBaseUrl: config.authOptions?.authApiBaseUrl || import_constants.DEFAULT_AUTH_API_BASE_URL
1239
800
  }
1240
801
  };
1241
802
  }, [config]);
@@ -1243,28 +804,25 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1243
804
  const storage = new ExpoSecureStorage();
1244
805
  const urlParamsAccessor = new ExpoURLParamsAccessor();
1245
806
  const logger = new ExpoLogger(debugConfig?.enabled || false);
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({
1251
- keyPrefix: `phantom-rn-${memoizedConfig.appId}`,
1252
- appId: memoizedConfig.appId
807
+ const stamper = new import_auth22.Auth2Stamper(new SecureStoreAuth2StamperStorage(`phantom-auth2-${memoizedConfig.appId}`), {
808
+ authApiBaseUrl: memoizedConfig.authOptions.authApiBaseUrl,
809
+ clientId: memoizedConfig.appId,
810
+ redirectUri: memoizedConfig.authOptions.redirectUrl
1253
811
  });
1254
- const authProvider = config.unstable__auth2Options && config.authOptions?.authUrl && config.authOptions?.redirectUrl && config.apiBaseUrl && stamper instanceof ExpoAuth2Stamper ? new ExpoAuth2AuthProvider(
812
+ const authProvider = new ExpoAuth2AuthProvider(
1255
813
  stamper,
1256
814
  {
1257
- redirectUri: config.authOptions.redirectUrl,
1258
- connectLoginUrl: config.authOptions.authUrl,
1259
- clientId: config.unstable__auth2Options.clientId,
1260
- authApiBaseUrl: config.unstable__auth2Options.authApiBaseUrl
815
+ redirectUri: memoizedConfig.authOptions.redirectUrl,
816
+ connectLoginUrl: memoizedConfig.authOptions.authUrl,
817
+ clientId: memoizedConfig.appId,
818
+ authApiBaseUrl: memoizedConfig.authOptions.authApiBaseUrl
1261
819
  },
1262
820
  {
1263
- apiBaseUrl: config.apiBaseUrl,
1264
- appId: config.appId
821
+ apiBaseUrl: memoizedConfig.apiBaseUrl,
822
+ appId: memoizedConfig.appId
1265
823
  }
1266
- ) : new ExpoAuthProvider();
1267
- const platformName = `${import_react_native7.Platform.OS}-${import_react_native7.Platform.Version}`;
824
+ );
825
+ const platformName = `${import_react_native6.Platform.OS}-${import_react_native6.Platform.Version}`;
1268
826
  const platform = {
1269
827
  storage,
1270
828
  authProvider,
@@ -1273,13 +831,13 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1273
831
  phantomAppProvider: new ReactNativePhantomAppProvider(),
1274
832
  name: platformName,
1275
833
  analyticsHeaders: {
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"
834
+ [import_constants.ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
835
+ [import_constants.ANALYTICS_HEADERS.PLATFORM]: "ext-sdk",
836
+ [import_constants.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${import_react_native6.Platform.Version}`,
837
+ [import_constants.ANALYTICS_HEADERS.CLIENT]: import_react_native6.Platform.OS,
838
+ [import_constants.ANALYTICS_HEADERS.APP_ID]: config.appId,
839
+ [import_constants.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
840
+ [import_constants.ANALYTICS_HEADERS.SDK_VERSION]: "2.0.0-beta.0"
1283
841
  // Replaced at build time
1284
842
  }
1285
843
  };
@@ -1393,8 +951,8 @@ function useEthereum() {
1393
951
 
1394
952
  // src/index.ts
1395
953
  var import_client = require("@phantom/client");
1396
- var import_constants5 = require("@phantom/constants");
1397
- var import_base64url3 = require("@phantom/base64url");
954
+ var import_constants2 = require("@phantom/constants");
955
+ var import_base64url = require("@phantom/base64url");
1398
956
  var import_wallet_sdk_ui6 = require("@phantom/wallet-sdk-ui");
1399
957
  // Annotate the CommonJS export names for ESM import in node:
1400
958
  0 && (module.exports = {