@phantom/browser-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 +51 -37
  2. package/dist/index.mjs +51 -38
  3. package/package.json +11 -11
package/dist/index.js CHANGED
@@ -2764,7 +2764,7 @@ var BrowserAuthProvider = class {
2764
2764
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
2765
2765
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
2766
2766
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
2767
- sdk_version: "1.0.4",
2767
+ sdk_version: "1.0.5",
2768
2768
  sdk_type: "browser",
2769
2769
  platform: detectBrowser().name,
2770
2770
  algorithm: phantomOptions.algorithm || import_constants3.DEFAULT_AUTHENTICATOR_ALGORITHM
@@ -2904,8 +2904,8 @@ var Auth2AuthProvider = class {
2904
2904
  *
2905
2905
  * Called by EmbeddedProvider.handleRedirectAuth() after the stamper has
2906
2906
  * already been initialized and a pending Session has been saved to storage.
2907
- * We store the PKCE code_verifier and salt into that session so they survive
2908
- * the page redirect without ever touching sessionStorage.
2907
+ * We store the PKCE code_verifier into that session so it survives the page
2908
+ * redirect without ever touching sessionStorage.
2909
2909
  */
2910
2910
  async authenticate(options) {
2911
2911
  if (!this.stamper.getKeyInfo()) {
@@ -2916,12 +2916,11 @@ var Auth2AuthProvider = class {
2916
2916
  throw new Error("Stamper key pair not found.");
2917
2917
  }
2918
2918
  const codeVerifier = (0, import_auth2.createCodeVerifier)();
2919
- const salt = (0, import_auth2.createSalt)();
2920
2919
  const session = await this.storage.getSession();
2921
2920
  if (!session) {
2922
2921
  throw new Error("Session not found.");
2923
2922
  }
2924
- await this.storage.saveSession({ ...session, pkceCodeVerifier: codeVerifier, salt });
2923
+ await this.storage.saveSession({ ...session, pkceCodeVerifier: codeVerifier });
2925
2924
  const url = await (0, import_auth2.createConnectStartUrl)({
2926
2925
  keyPair,
2927
2926
  connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
@@ -2930,7 +2929,8 @@ var Auth2AuthProvider = class {
2930
2929
  sessionId: options.sessionId,
2931
2930
  provider: options.provider,
2932
2931
  codeVerifier,
2933
- salt
2932
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
2933
+ salt: ""
2934
2934
  });
2935
2935
  Auth2AuthProvider.navigate(url);
2936
2936
  }
@@ -2972,17 +2972,14 @@ var Auth2AuthProvider = class {
2972
2972
  code,
2973
2973
  codeVerifier
2974
2974
  });
2975
- this.stamper.idToken = idToken;
2976
- this.stamper.salt = session?.salt;
2975
+ await this.stamper.setIdToken(idToken);
2977
2976
  await this.storage.saveSession({
2978
2977
  ...session,
2979
2978
  status: "completed",
2980
2979
  bearerToken,
2981
2980
  authUserId,
2982
- pkceCodeVerifier: void 0,
2981
+ pkceCodeVerifier: void 0
2983
2982
  // no longer needed after code exchange
2984
- salt: void 0
2985
- // no longer needed after nonce binding is complete
2986
2983
  });
2987
2984
  const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
2988
2985
  return {
@@ -3012,17 +3009,21 @@ var Auth2Stamper = class {
3012
3009
  constructor(dbName) {
3013
3010
  this.dbName = dbName;
3014
3011
  this.db = null;
3015
- this.keyPair = null;
3012
+ this._keyPair = null;
3016
3013
  this._keyInfo = null;
3014
+ this._idToken = null;
3017
3015
  this.algorithm = import_sdk_types.Algorithm.secp256r1;
3018
- this.type = "PKI";
3016
+ this.type = "OIDC";
3019
3017
  }
3020
3018
  async init() {
3021
3019
  await this.openDB();
3022
- const stored = await this.loadKeyPair();
3020
+ const stored = await this.loadRecord();
3023
3021
  if (stored) {
3024
- this.keyPair = stored.keyPair;
3022
+ this._keyPair = stored.keyPair;
3025
3023
  this._keyInfo = stored.keyInfo;
3024
+ if (stored.idToken) {
3025
+ this._idToken = stored.idToken;
3026
+ }
3026
3027
  return this._keyInfo;
3027
3028
  }
3028
3029
  return this.generateAndStore();
@@ -3031,41 +3032,54 @@ var Auth2Stamper = class {
3031
3032
  return this._keyInfo;
3032
3033
  }
3033
3034
  getCryptoKeyPair() {
3034
- return this.keyPair;
3035
+ return this._keyPair;
3036
+ }
3037
+ /**
3038
+ * Arms the stamper with the OIDC id token for subsequent KMS stamp() calls.
3039
+ *
3040
+ * Persists the token to IndexedDB alongside the key pair so that
3041
+ * auto-connect can restore it on the next page load without a new login.
3042
+ */
3043
+ async setIdToken(idToken) {
3044
+ if (!this.db) {
3045
+ await this.openDB();
3046
+ }
3047
+ this._idToken = idToken;
3048
+ const existing = await this.loadRecord();
3049
+ if (existing) {
3050
+ await this.storeRecord({ ...existing, idToken });
3051
+ }
3035
3052
  }
3036
3053
  async stamp(params) {
3037
- if (!this.keyPair || !this._keyInfo) {
3054
+ if (!this._keyPair || !this._keyInfo || this._idToken === null) {
3038
3055
  throw new Error("Auth2Stamper not initialized. Call init() first.");
3039
3056
  }
3040
3057
  const signatureRaw = await crypto.subtle.sign(
3041
3058
  { name: "ECDSA", hash: "SHA-256" },
3042
- this.keyPair.privateKey,
3059
+ this._keyPair.privateKey,
3043
3060
  new Uint8Array(params.data)
3044
3061
  );
3045
3062
  const rawPublicKey = import_bs582.default.decode(this._keyInfo.publicKey);
3046
- if (this.idToken === void 0 || this.salt === void 0) {
3047
- throw new Error("Auth2Stamper not initialized with idToken or salt.");
3048
- }
3049
3063
  const stampData = {
3050
- kind: "OIDC",
3051
- idToken: this.idToken,
3064
+ kind: this.type,
3065
+ idToken: this._idToken,
3052
3066
  publicKey: (0, import_base64url.base64urlEncode)(rawPublicKey),
3053
- algorithm: "Secp256r1",
3054
- salt: this.salt,
3067
+ algorithm: this.algorithm,
3068
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
3069
+ salt: "",
3055
3070
  signature: (0, import_base64url.base64urlEncode)(new Uint8Array(signatureRaw))
3056
3071
  };
3057
3072
  return (0, import_base64url.base64urlEncode)(new TextEncoder().encode(JSON.stringify(stampData)));
3058
3073
  }
3059
3074
  async resetKeyPair() {
3060
- await this.clearStoredKey();
3061
- this.keyPair = null;
3062
- this._keyInfo = null;
3075
+ await this.clear();
3063
3076
  return this.generateAndStore();
3064
3077
  }
3065
3078
  async clear() {
3066
- await this.clearStoredKey();
3067
- this.keyPair = null;
3079
+ await this.clearStoredRecord();
3080
+ this._keyPair = null;
3068
3081
  this._keyInfo = null;
3082
+ this._idToken = null;
3069
3083
  }
3070
3084
  // Auth2 doesn't use key rotation; provide minimal no-op implementations.
3071
3085
  async rotateKeyPair() {
@@ -3090,13 +3104,13 @@ var Auth2Stamper = class {
3090
3104
  const publicKeyBase58 = import_bs582.default.encode(rawPublicKey);
3091
3105
  const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
3092
3106
  const keyId = (0, import_base64url.base64urlEncode)(new Uint8Array(keyIdBuffer)).substring(0, 16);
3093
- this.keyPair = keyPair;
3107
+ this._keyPair = keyPair;
3094
3108
  this._keyInfo = {
3095
3109
  keyId,
3096
3110
  publicKey: publicKeyBase58,
3097
3111
  createdAt: Date.now()
3098
3112
  };
3099
- await this.storeKeyPair(keyPair, this._keyInfo);
3113
+ await this.storeRecord({ keyPair, keyInfo: this._keyInfo });
3100
3114
  return this._keyInfo;
3101
3115
  }
3102
3116
  async openDB() {
@@ -3115,7 +3129,7 @@ var Auth2Stamper = class {
3115
3129
  };
3116
3130
  });
3117
3131
  }
3118
- async loadKeyPair() {
3132
+ async loadRecord() {
3119
3133
  return new Promise((resolve, reject) => {
3120
3134
  if (!this.db) {
3121
3135
  throw new Error("Database not initialized");
@@ -3129,12 +3143,12 @@ var Auth2Stamper = class {
3129
3143
  };
3130
3144
  });
3131
3145
  }
3132
- async storeKeyPair(keyPair, keyInfo) {
3146
+ async storeRecord(record) {
3133
3147
  return new Promise((resolve, reject) => {
3134
3148
  if (!this.db) {
3135
3149
  throw new Error("Database not initialized");
3136
3150
  }
3137
- const request = this.db.transaction([STORE_NAME], "readwrite").objectStore(STORE_NAME).put({ keyPair, keyInfo }, ACTIVE_KEY);
3151
+ const request = this.db.transaction([STORE_NAME], "readwrite").objectStore(STORE_NAME).put(record, ACTIVE_KEY);
3138
3152
  request.onsuccess = () => {
3139
3153
  resolve();
3140
3154
  };
@@ -3143,7 +3157,7 @@ var Auth2Stamper = class {
3143
3157
  };
3144
3158
  });
3145
3159
  }
3146
- async clearStoredKey() {
3160
+ async clearStoredRecord() {
3147
3161
  return new Promise((resolve, reject) => {
3148
3162
  if (!this.db) {
3149
3163
  throw new Error("Database not initialized");
@@ -3320,7 +3334,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
3320
3334
  [import_constants4.ANALYTICS_HEADERS.CLIENT]: browserName,
3321
3335
  [import_constants4.ANALYTICS_HEADERS.APP_ID]: config.appId,
3322
3336
  [import_constants4.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
3323
- [import_constants4.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.4"
3337
+ [import_constants4.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.5"
3324
3338
  // Replaced at build time
3325
3339
  }
3326
3340
  };
package/dist/index.mjs CHANGED
@@ -2714,7 +2714,7 @@ var BrowserAuthProvider = class {
2714
2714
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
2715
2715
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
2716
2716
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
2717
- sdk_version: "1.0.4",
2717
+ sdk_version: "1.0.5",
2718
2718
  sdk_type: "browser",
2719
2719
  platform: detectBrowser().name,
2720
2720
  algorithm: phantomOptions.algorithm || DEFAULT_AUTHENTICATOR_ALGORITHM
@@ -2838,7 +2838,6 @@ var BrowserAuthProvider = class {
2838
2838
  // src/providers/embedded/adapters/Auth2AuthProvider.ts
2839
2839
  import {
2840
2840
  createCodeVerifier,
2841
- createSalt,
2842
2841
  createConnectStartUrl,
2843
2842
  exchangeAuthCode,
2844
2843
  Auth2KmsRpcClient
@@ -2860,8 +2859,8 @@ var Auth2AuthProvider = class {
2860
2859
  *
2861
2860
  * Called by EmbeddedProvider.handleRedirectAuth() after the stamper has
2862
2861
  * already been initialized and a pending Session has been saved to storage.
2863
- * We store the PKCE code_verifier and salt into that session so they survive
2864
- * the page redirect without ever touching sessionStorage.
2862
+ * We store the PKCE code_verifier into that session so it survives the page
2863
+ * redirect without ever touching sessionStorage.
2865
2864
  */
2866
2865
  async authenticate(options) {
2867
2866
  if (!this.stamper.getKeyInfo()) {
@@ -2872,12 +2871,11 @@ var Auth2AuthProvider = class {
2872
2871
  throw new Error("Stamper key pair not found.");
2873
2872
  }
2874
2873
  const codeVerifier = createCodeVerifier();
2875
- const salt = createSalt();
2876
2874
  const session = await this.storage.getSession();
2877
2875
  if (!session) {
2878
2876
  throw new Error("Session not found.");
2879
2877
  }
2880
- await this.storage.saveSession({ ...session, pkceCodeVerifier: codeVerifier, salt });
2878
+ await this.storage.saveSession({ ...session, pkceCodeVerifier: codeVerifier });
2881
2879
  const url = await createConnectStartUrl({
2882
2880
  keyPair,
2883
2881
  connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
@@ -2886,7 +2884,8 @@ var Auth2AuthProvider = class {
2886
2884
  sessionId: options.sessionId,
2887
2885
  provider: options.provider,
2888
2886
  codeVerifier,
2889
- salt
2887
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
2888
+ salt: ""
2890
2889
  });
2891
2890
  Auth2AuthProvider.navigate(url);
2892
2891
  }
@@ -2928,17 +2927,14 @@ var Auth2AuthProvider = class {
2928
2927
  code,
2929
2928
  codeVerifier
2930
2929
  });
2931
- this.stamper.idToken = idToken;
2932
- this.stamper.salt = session?.salt;
2930
+ await this.stamper.setIdToken(idToken);
2933
2931
  await this.storage.saveSession({
2934
2932
  ...session,
2935
2933
  status: "completed",
2936
2934
  bearerToken,
2937
2935
  authUserId,
2938
- pkceCodeVerifier: void 0,
2936
+ pkceCodeVerifier: void 0
2939
2937
  // no longer needed after code exchange
2940
- salt: void 0
2941
- // no longer needed after nonce binding is complete
2942
2938
  });
2943
2939
  const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
2944
2940
  return {
@@ -2968,17 +2964,21 @@ var Auth2Stamper = class {
2968
2964
  constructor(dbName) {
2969
2965
  this.dbName = dbName;
2970
2966
  this.db = null;
2971
- this.keyPair = null;
2967
+ this._keyPair = null;
2972
2968
  this._keyInfo = null;
2969
+ this._idToken = null;
2973
2970
  this.algorithm = Algorithm.secp256r1;
2974
- this.type = "PKI";
2971
+ this.type = "OIDC";
2975
2972
  }
2976
2973
  async init() {
2977
2974
  await this.openDB();
2978
- const stored = await this.loadKeyPair();
2975
+ const stored = await this.loadRecord();
2979
2976
  if (stored) {
2980
- this.keyPair = stored.keyPair;
2977
+ this._keyPair = stored.keyPair;
2981
2978
  this._keyInfo = stored.keyInfo;
2979
+ if (stored.idToken) {
2980
+ this._idToken = stored.idToken;
2981
+ }
2982
2982
  return this._keyInfo;
2983
2983
  }
2984
2984
  return this.generateAndStore();
@@ -2987,41 +2987,54 @@ var Auth2Stamper = class {
2987
2987
  return this._keyInfo;
2988
2988
  }
2989
2989
  getCryptoKeyPair() {
2990
- return this.keyPair;
2990
+ return this._keyPair;
2991
+ }
2992
+ /**
2993
+ * Arms the stamper with the OIDC id token for subsequent KMS stamp() calls.
2994
+ *
2995
+ * Persists the token to IndexedDB alongside the key pair so that
2996
+ * auto-connect can restore it on the next page load without a new login.
2997
+ */
2998
+ async setIdToken(idToken) {
2999
+ if (!this.db) {
3000
+ await this.openDB();
3001
+ }
3002
+ this._idToken = idToken;
3003
+ const existing = await this.loadRecord();
3004
+ if (existing) {
3005
+ await this.storeRecord({ ...existing, idToken });
3006
+ }
2991
3007
  }
2992
3008
  async stamp(params) {
2993
- if (!this.keyPair || !this._keyInfo) {
3009
+ if (!this._keyPair || !this._keyInfo || this._idToken === null) {
2994
3010
  throw new Error("Auth2Stamper not initialized. Call init() first.");
2995
3011
  }
2996
3012
  const signatureRaw = await crypto.subtle.sign(
2997
3013
  { name: "ECDSA", hash: "SHA-256" },
2998
- this.keyPair.privateKey,
3014
+ this._keyPair.privateKey,
2999
3015
  new Uint8Array(params.data)
3000
3016
  );
3001
3017
  const rawPublicKey = bs582.decode(this._keyInfo.publicKey);
3002
- if (this.idToken === void 0 || this.salt === void 0) {
3003
- throw new Error("Auth2Stamper not initialized with idToken or salt.");
3004
- }
3005
3018
  const stampData = {
3006
- kind: "OIDC",
3007
- idToken: this.idToken,
3019
+ kind: this.type,
3020
+ idToken: this._idToken,
3008
3021
  publicKey: base64urlEncode(rawPublicKey),
3009
- algorithm: "Secp256r1",
3010
- salt: this.salt,
3022
+ algorithm: this.algorithm,
3023
+ // The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
3024
+ salt: "",
3011
3025
  signature: base64urlEncode(new Uint8Array(signatureRaw))
3012
3026
  };
3013
3027
  return base64urlEncode(new TextEncoder().encode(JSON.stringify(stampData)));
3014
3028
  }
3015
3029
  async resetKeyPair() {
3016
- await this.clearStoredKey();
3017
- this.keyPair = null;
3018
- this._keyInfo = null;
3030
+ await this.clear();
3019
3031
  return this.generateAndStore();
3020
3032
  }
3021
3033
  async clear() {
3022
- await this.clearStoredKey();
3023
- this.keyPair = null;
3034
+ await this.clearStoredRecord();
3035
+ this._keyPair = null;
3024
3036
  this._keyInfo = null;
3037
+ this._idToken = null;
3025
3038
  }
3026
3039
  // Auth2 doesn't use key rotation; provide minimal no-op implementations.
3027
3040
  async rotateKeyPair() {
@@ -3046,13 +3059,13 @@ var Auth2Stamper = class {
3046
3059
  const publicKeyBase58 = bs582.encode(rawPublicKey);
3047
3060
  const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
3048
3061
  const keyId = base64urlEncode(new Uint8Array(keyIdBuffer)).substring(0, 16);
3049
- this.keyPair = keyPair;
3062
+ this._keyPair = keyPair;
3050
3063
  this._keyInfo = {
3051
3064
  keyId,
3052
3065
  publicKey: publicKeyBase58,
3053
3066
  createdAt: Date.now()
3054
3067
  };
3055
- await this.storeKeyPair(keyPair, this._keyInfo);
3068
+ await this.storeRecord({ keyPair, keyInfo: this._keyInfo });
3056
3069
  return this._keyInfo;
3057
3070
  }
3058
3071
  async openDB() {
@@ -3071,7 +3084,7 @@ var Auth2Stamper = class {
3071
3084
  };
3072
3085
  });
3073
3086
  }
3074
- async loadKeyPair() {
3087
+ async loadRecord() {
3075
3088
  return new Promise((resolve, reject) => {
3076
3089
  if (!this.db) {
3077
3090
  throw new Error("Database not initialized");
@@ -3085,12 +3098,12 @@ var Auth2Stamper = class {
3085
3098
  };
3086
3099
  });
3087
3100
  }
3088
- async storeKeyPair(keyPair, keyInfo) {
3101
+ async storeRecord(record) {
3089
3102
  return new Promise((resolve, reject) => {
3090
3103
  if (!this.db) {
3091
3104
  throw new Error("Database not initialized");
3092
3105
  }
3093
- const request = this.db.transaction([STORE_NAME], "readwrite").objectStore(STORE_NAME).put({ keyPair, keyInfo }, ACTIVE_KEY);
3106
+ const request = this.db.transaction([STORE_NAME], "readwrite").objectStore(STORE_NAME).put(record, ACTIVE_KEY);
3094
3107
  request.onsuccess = () => {
3095
3108
  resolve();
3096
3109
  };
@@ -3099,7 +3112,7 @@ var Auth2Stamper = class {
3099
3112
  };
3100
3113
  });
3101
3114
  }
3102
- async clearStoredKey() {
3115
+ async clearStoredRecord() {
3103
3116
  return new Promise((resolve, reject) => {
3104
3117
  if (!this.db) {
3105
3118
  throw new Error("Database not initialized");
@@ -3276,7 +3289,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
3276
3289
  [ANALYTICS_HEADERS.CLIENT]: browserName,
3277
3290
  [ANALYTICS_HEADERS.APP_ID]: config.appId,
3278
3291
  [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
3279
- [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.4"
3292
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.5"
3280
3293
  // Replaced at build time
3281
3294
  }
3282
3295
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/browser-sdk",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Browser SDK for Phantom Wallet",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,16 +33,16 @@
33
33
  "prettier": "prettier --write \"src/**/*.{ts,tsx}\""
34
34
  },
35
35
  "dependencies": {
36
- "@phantom/auth2": "^1.0.0",
37
- "@phantom/base64url": "^1.0.4",
38
- "@phantom/browser-injected-sdk": "^1.0.4",
39
- "@phantom/chain-interfaces": "^1.0.4",
40
- "@phantom/client": "^1.0.4",
41
- "@phantom/constants": "^1.0.4",
42
- "@phantom/embedded-provider-core": "^1.0.4",
43
- "@phantom/indexed-db-stamper": "^1.0.4",
44
- "@phantom/parsers": "^1.0.4",
45
- "@phantom/sdk-types": "^1.0.4",
36
+ "@phantom/auth2": "^1.0.1",
37
+ "@phantom/base64url": "^1.0.5",
38
+ "@phantom/browser-injected-sdk": "^1.0.5",
39
+ "@phantom/chain-interfaces": "^1.0.5",
40
+ "@phantom/client": "^1.0.5",
41
+ "@phantom/constants": "^1.0.5",
42
+ "@phantom/embedded-provider-core": "^1.0.5",
43
+ "@phantom/indexed-db-stamper": "^1.0.5",
44
+ "@phantom/parsers": "^1.0.5",
45
+ "@phantom/sdk-types": "^1.0.5",
46
46
  "axios": "^1.10.0",
47
47
  "bs58": "^6.0.0",
48
48
  "buffer": "^6.0.3",