@phantom/react-native-sdk 1.0.4 → 1.0.5

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 (3) hide show
  1. package/dist/index.js +43 -35
  2. package/dist/index.mjs +43 -36
  3. package/package.json +11 -11
package/dist/index.js CHANGED
@@ -557,7 +557,7 @@ var ExpoAuthProvider = class {
557
557
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
558
558
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
559
559
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
560
- sdk_version: "1.0.4",
560
+ sdk_version: "1.0.5",
561
561
  sdk_type: "react-native",
562
562
  platform: import_react_native5.Platform.OS
563
563
  });
@@ -657,7 +657,6 @@ var ExpoAuth2AuthProvider = class {
657
657
  throw new Error("Stamper key pair not found.");
658
658
  }
659
659
  const codeVerifier = (0, import_auth2.createCodeVerifier)();
660
- const salt = (0, import_auth2.createSalt)();
661
660
  const url = await (0, import_auth2.createConnectStartUrl)({
662
661
  keyPair,
663
662
  connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
@@ -666,7 +665,8 @@ var ExpoAuth2AuthProvider = class {
666
665
  sessionId: options.sessionId,
667
666
  provider: options.provider,
668
667
  codeVerifier,
669
- salt
668
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
669
+ salt: ""
670
670
  });
671
671
  await WebBrowser2.warmUpAsync();
672
672
  let result;
@@ -699,8 +699,7 @@ var ExpoAuth2AuthProvider = class {
699
699
  code,
700
700
  codeVerifier
701
701
  });
702
- this.stamper.idToken = idToken;
703
- this.stamper.salt = salt;
702
+ await this.stamper.setIdToken(idToken);
704
703
  const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
705
704
  return {
706
705
  walletId,
@@ -728,18 +727,23 @@ var ExpoAuth2Stamper = class {
728
727
  */
729
728
  constructor(storageKey) {
730
729
  this.storageKey = storageKey;
731
- this.privateKey = null;
732
- this.publicKey = null;
730
+ this._keyPair = null;
733
731
  this._keyInfo = null;
732
+ this._idToken = null;
734
733
  this.algorithm = import_sdk_types.Algorithm.secp256r1;
735
734
  this.type = "OIDC";
736
735
  }
737
736
  async init() {
738
737
  const stored = await this.loadRecord();
739
738
  if (stored) {
740
- this.privateKey = await this.importPrivateKey(stored.privateKeyPkcs8);
741
- this.publicKey = await this.importPublicKeyFromBase58(stored.keyInfo.publicKey);
739
+ this._keyPair = {
740
+ privateKey: await this.importPrivateKey(stored.privateKeyPkcs8),
741
+ publicKey: await this.importPublicKeyFromBase58(stored.keyInfo.publicKey)
742
+ };
742
743
  this._keyInfo = stored.keyInfo;
744
+ if (stored.idToken) {
745
+ this._idToken = stored.idToken;
746
+ }
743
747
  return this._keyInfo;
744
748
  }
745
749
  return this.generateAndStore();
@@ -748,45 +752,51 @@ var ExpoAuth2Stamper = class {
748
752
  return this._keyInfo;
749
753
  }
750
754
  getCryptoKeyPair() {
751
- if (!this.privateKey || !this.publicKey)
752
- return null;
753
- return { privateKey: this.privateKey, publicKey: this.publicKey };
755
+ return this._keyPair;
756
+ }
757
+ /**
758
+ * Arms the stamper with the OIDC id token for subsequent KMS stamp() calls.
759
+ *
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.
762
+ */
763
+ async setIdToken(idToken) {
764
+ this._idToken = idToken;
765
+ const existing = await this.loadRecord();
766
+ if (existing) {
767
+ await this.storeRecord({ ...existing, idToken });
768
+ }
754
769
  }
755
770
  async stamp(params) {
756
- if (!this.privateKey || !this._keyInfo) {
771
+ if (!this._keyPair || !this._keyInfo || this._idToken === null) {
757
772
  throw new Error("ExpoAuth2Stamper not initialized. Call init() first.");
758
773
  }
759
774
  const signatureRaw = await crypto.subtle.sign(
760
775
  { name: "ECDSA", hash: "SHA-256" },
761
- this.privateKey,
776
+ this._keyPair.privateKey,
762
777
  new Uint8Array(params.data)
763
778
  );
764
779
  const rawPublicKey = import_bs58.default.decode(this._keyInfo.publicKey);
765
- if (this.idToken === void 0 || this.salt === void 0) {
766
- throw new Error("ExpoAuth2Stamper not initialized with idToken or salt.");
767
- }
768
780
  const stampData = {
769
- kind: "OIDC",
770
- idToken: this.idToken,
781
+ kind: this.type,
782
+ idToken: this._idToken,
771
783
  publicKey: (0, import_base64url.base64urlEncode)(rawPublicKey),
772
- algorithm: "Secp256r1",
773
- salt: this.salt,
784
+ algorithm: this.algorithm,
785
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
786
+ salt: "",
774
787
  signature: (0, import_base64url.base64urlEncode)(new Uint8Array(signatureRaw))
775
788
  };
776
789
  return (0, import_base64url.base64urlEncode)(new TextEncoder().encode(JSON.stringify(stampData)));
777
790
  }
778
791
  async resetKeyPair() {
779
- await this.clearStoredRecord();
780
- this.privateKey = null;
781
- this.publicKey = null;
782
- this._keyInfo = null;
792
+ await this.clear();
783
793
  return this.generateAndStore();
784
794
  }
785
795
  async clear() {
786
796
  await this.clearStoredRecord();
787
- this.privateKey = null;
788
- this.publicKey = null;
797
+ this._keyPair = null;
789
798
  this._keyInfo = null;
799
+ this._idToken = null;
790
800
  }
791
801
  // Auth2 doesn't use key rotation; minimal no-op implementations.
792
802
  async rotateKeyPair() {
@@ -811,16 +821,11 @@ var ExpoAuth2Stamper = class {
811
821
  const publicKeyBase58 = import_bs58.default.encode(rawPublicKey);
812
822
  const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
813
823
  const keyId = (0, import_base64url.base64urlEncode)(new Uint8Array(keyIdBuffer)).substring(0, 16);
824
+ this._keyPair = keyPair;
814
825
  this._keyInfo = { keyId, publicKey: publicKeyBase58, createdAt: Date.now() };
815
826
  const pkcs8Buffer = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
816
827
  const privateKeyPkcs8 = import_buffer.Buffer.from(pkcs8Buffer).toString("base64");
817
- await SecureStore2.setItemAsync(
818
- this.storageKey,
819
- JSON.stringify({ privateKeyPkcs8, keyInfo: this._keyInfo }),
820
- { requireAuthentication: false }
821
- );
822
- this.privateKey = await this.importPrivateKey(privateKeyPkcs8);
823
- this.publicKey = keyPair.publicKey;
828
+ await this.storeRecord({ privateKeyPkcs8, keyInfo: this._keyInfo });
824
829
  return this._keyInfo;
825
830
  }
826
831
  async importPublicKeyFromBase58(base58PublicKey) {
@@ -853,6 +858,9 @@ var ExpoAuth2Stamper = class {
853
858
  return null;
854
859
  }
855
860
  }
861
+ async storeRecord(record) {
862
+ await SecureStore2.setItemAsync(this.storageKey, JSON.stringify(record), { requireAuthentication: false });
863
+ }
856
864
  async clearStoredRecord() {
857
865
  try {
858
866
  await SecureStore2.deleteItemAsync(this.storageKey);
@@ -1203,7 +1211,7 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1203
1211
  [import_constants3.ANALYTICS_HEADERS.CLIENT]: import_react_native7.Platform.OS,
1204
1212
  [import_constants3.ANALYTICS_HEADERS.APP_ID]: config.appId,
1205
1213
  [import_constants3.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1206
- [import_constants3.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.4"
1214
+ [import_constants3.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.5"
1207
1215
  // Replaced at build time
1208
1216
  }
1209
1217
  };
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.4",
518
+ sdk_version: "1.0.5",
519
519
  sdk_type: "react-native",
520
520
  platform: Platform.OS
521
521
  });
@@ -594,7 +594,6 @@ var ExpoAuthProvider = class {
594
594
  import * as WebBrowser2 from "expo-web-browser";
595
595
  import {
596
596
  createCodeVerifier,
597
- createSalt,
598
597
  exchangeAuthCode,
599
598
  Auth2KmsRpcClient,
600
599
  createConnectStartUrl
@@ -621,7 +620,6 @@ var ExpoAuth2AuthProvider = class {
621
620
  throw new Error("Stamper key pair not found.");
622
621
  }
623
622
  const codeVerifier = createCodeVerifier();
624
- const salt = createSalt();
625
623
  const url = await createConnectStartUrl({
626
624
  keyPair,
627
625
  connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
@@ -630,7 +628,8 @@ var ExpoAuth2AuthProvider = class {
630
628
  sessionId: options.sessionId,
631
629
  provider: options.provider,
632
630
  codeVerifier,
633
- salt
631
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
632
+ salt: ""
634
633
  });
635
634
  await WebBrowser2.warmUpAsync();
636
635
  let result;
@@ -663,8 +662,7 @@ var ExpoAuth2AuthProvider = class {
663
662
  code,
664
663
  codeVerifier
665
664
  });
666
- this.stamper.idToken = idToken;
667
- this.stamper.salt = salt;
665
+ await this.stamper.setIdToken(idToken);
668
666
  const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
669
667
  return {
670
668
  walletId,
@@ -692,18 +690,23 @@ var ExpoAuth2Stamper = class {
692
690
  */
693
691
  constructor(storageKey) {
694
692
  this.storageKey = storageKey;
695
- this.privateKey = null;
696
- this.publicKey = null;
693
+ this._keyPair = null;
697
694
  this._keyInfo = null;
695
+ this._idToken = null;
698
696
  this.algorithm = Algorithm.secp256r1;
699
697
  this.type = "OIDC";
700
698
  }
701
699
  async init() {
702
700
  const stored = await this.loadRecord();
703
701
  if (stored) {
704
- this.privateKey = await this.importPrivateKey(stored.privateKeyPkcs8);
705
- this.publicKey = await this.importPublicKeyFromBase58(stored.keyInfo.publicKey);
702
+ this._keyPair = {
703
+ privateKey: await this.importPrivateKey(stored.privateKeyPkcs8),
704
+ publicKey: await this.importPublicKeyFromBase58(stored.keyInfo.publicKey)
705
+ };
706
706
  this._keyInfo = stored.keyInfo;
707
+ if (stored.idToken) {
708
+ this._idToken = stored.idToken;
709
+ }
707
710
  return this._keyInfo;
708
711
  }
709
712
  return this.generateAndStore();
@@ -712,45 +715,51 @@ var ExpoAuth2Stamper = class {
712
715
  return this._keyInfo;
713
716
  }
714
717
  getCryptoKeyPair() {
715
- if (!this.privateKey || !this.publicKey)
716
- return null;
717
- return { privateKey: this.privateKey, publicKey: this.publicKey };
718
+ return this._keyPair;
719
+ }
720
+ /**
721
+ * Arms the stamper with the OIDC id token for subsequent KMS stamp() calls.
722
+ *
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.
725
+ */
726
+ async setIdToken(idToken) {
727
+ this._idToken = idToken;
728
+ const existing = await this.loadRecord();
729
+ if (existing) {
730
+ await this.storeRecord({ ...existing, idToken });
731
+ }
718
732
  }
719
733
  async stamp(params) {
720
- if (!this.privateKey || !this._keyInfo) {
734
+ if (!this._keyPair || !this._keyInfo || this._idToken === null) {
721
735
  throw new Error("ExpoAuth2Stamper not initialized. Call init() first.");
722
736
  }
723
737
  const signatureRaw = await crypto.subtle.sign(
724
738
  { name: "ECDSA", hash: "SHA-256" },
725
- this.privateKey,
739
+ this._keyPair.privateKey,
726
740
  new Uint8Array(params.data)
727
741
  );
728
742
  const rawPublicKey = bs58.decode(this._keyInfo.publicKey);
729
- if (this.idToken === void 0 || this.salt === void 0) {
730
- throw new Error("ExpoAuth2Stamper not initialized with idToken or salt.");
731
- }
732
743
  const stampData = {
733
- kind: "OIDC",
734
- idToken: this.idToken,
744
+ kind: this.type,
745
+ idToken: this._idToken,
735
746
  publicKey: base64urlEncode(rawPublicKey),
736
- algorithm: "Secp256r1",
737
- salt: this.salt,
747
+ algorithm: this.algorithm,
748
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
749
+ salt: "",
738
750
  signature: base64urlEncode(new Uint8Array(signatureRaw))
739
751
  };
740
752
  return base64urlEncode(new TextEncoder().encode(JSON.stringify(stampData)));
741
753
  }
742
754
  async resetKeyPair() {
743
- await this.clearStoredRecord();
744
- this.privateKey = null;
745
- this.publicKey = null;
746
- this._keyInfo = null;
755
+ await this.clear();
747
756
  return this.generateAndStore();
748
757
  }
749
758
  async clear() {
750
759
  await this.clearStoredRecord();
751
- this.privateKey = null;
752
- this.publicKey = null;
760
+ this._keyPair = null;
753
761
  this._keyInfo = null;
762
+ this._idToken = null;
754
763
  }
755
764
  // Auth2 doesn't use key rotation; minimal no-op implementations.
756
765
  async rotateKeyPair() {
@@ -775,16 +784,11 @@ var ExpoAuth2Stamper = class {
775
784
  const publicKeyBase58 = bs58.encode(rawPublicKey);
776
785
  const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
777
786
  const keyId = base64urlEncode(new Uint8Array(keyIdBuffer)).substring(0, 16);
787
+ this._keyPair = keyPair;
778
788
  this._keyInfo = { keyId, publicKey: publicKeyBase58, createdAt: Date.now() };
779
789
  const pkcs8Buffer = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
780
790
  const privateKeyPkcs8 = Buffer.from(pkcs8Buffer).toString("base64");
781
- await SecureStore2.setItemAsync(
782
- this.storageKey,
783
- JSON.stringify({ privateKeyPkcs8, keyInfo: this._keyInfo }),
784
- { requireAuthentication: false }
785
- );
786
- this.privateKey = await this.importPrivateKey(privateKeyPkcs8);
787
- this.publicKey = keyPair.publicKey;
791
+ await this.storeRecord({ privateKeyPkcs8, keyInfo: this._keyInfo });
788
792
  return this._keyInfo;
789
793
  }
790
794
  async importPublicKeyFromBase58(base58PublicKey) {
@@ -817,6 +821,9 @@ var ExpoAuth2Stamper = class {
817
821
  return null;
818
822
  }
819
823
  }
824
+ async storeRecord(record) {
825
+ await SecureStore2.setItemAsync(this.storageKey, JSON.stringify(record), { requireAuthentication: false });
826
+ }
820
827
  async clearStoredRecord() {
821
828
  try {
822
829
  await SecureStore2.deleteItemAsync(this.storageKey);
@@ -1167,7 +1174,7 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
1167
1174
  [ANALYTICS_HEADERS.CLIENT]: Platform2.OS,
1168
1175
  [ANALYTICS_HEADERS.APP_ID]: config.appId,
1169
1176
  [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1170
- [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.4"
1177
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.5"
1171
1178
  // Replaced at build time
1172
1179
  }
1173
1180
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-native-sdk",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
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.4",
49
- "@phantom/auth2": "^1.0.0",
50
- "@phantom/base64url": "^1.0.4",
51
- "@phantom/chain-interfaces": "^1.0.4",
52
- "@phantom/client": "^1.0.4",
53
- "@phantom/constants": "^1.0.4",
54
- "@phantom/crypto": "^1.0.4",
55
- "@phantom/embedded-provider-core": "^1.0.4",
56
- "@phantom/sdk-types": "^1.0.4",
57
- "@phantom/wallet-sdk-ui": "^1.0.4",
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",
58
58
  "@types/bs58": "^5.0.0",
59
59
  "bs58": "^6.0.0",
60
60
  "buffer": "^6.0.3"