@phantom/browser-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/README.md +6 -2
- package/dist/index.d.ts +1 -5
- package/dist/index.js +60 -419
- package/dist/index.mjs +52 -406
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -216,6 +216,7 @@ const sdk = new BrowserSDK({
|
|
|
216
216
|
authOptions: {
|
|
217
217
|
authUrl: "https://connect.phantom.app/login", // optional
|
|
218
218
|
redirectUrl: "https://yourapp.com/callback", // optional, defaults to current page
|
|
219
|
+
authApiBaseUrl: "https://auth.phantom.app", // optional
|
|
219
220
|
},
|
|
220
221
|
autoConnect: true, // optional, auto-connect to existing session (default: true when embedded providers are used)
|
|
221
222
|
});
|
|
@@ -231,8 +232,9 @@ const sdk = new BrowserSDK({
|
|
|
231
232
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
232
233
|
appId: "your-app-id", // Required for deeplink
|
|
233
234
|
authOptions: {
|
|
234
|
-
authUrl: "https://connect.phantom.app/login",
|
|
235
|
+
authUrl: "https://connect.phantom.app/login/start",
|
|
235
236
|
redirectUrl: "https://yourapp.com/callback",
|
|
237
|
+
authApiBaseUrl: "https://auth.phantom.app",
|
|
236
238
|
},
|
|
237
239
|
});
|
|
238
240
|
```
|
|
@@ -325,9 +327,11 @@ interface BrowserSDKConfig {
|
|
|
325
327
|
|
|
326
328
|
// Optional configuration
|
|
327
329
|
apiBaseUrl?: string; // Phantom API base URL (optional, has default)
|
|
330
|
+
|
|
328
331
|
authOptions?: {
|
|
329
|
-
authUrl?: string; // Custom auth URL (optional, defaults to "https://connect.phantom.app/login")
|
|
332
|
+
authUrl?: string; // Custom auth URL (optional, defaults to "https://connect.phantom.app/login/start")
|
|
330
333
|
redirectUrl?: string; // Custom redirect URL after authentication (optional)
|
|
334
|
+
authApiBaseUrl?: string; // Custom OAuth URL (optional, defaults to "https://auth.phantom.app")
|
|
331
335
|
};
|
|
332
336
|
embeddedWalletType?: "user-wallet"; // Wallet type (optional, defaults to "user-wallet")
|
|
333
337
|
autoConnect?: boolean; // Auto-connect to existing session (default: true when embedded providers used)
|
package/dist/index.d.ts
CHANGED
|
@@ -119,11 +119,7 @@ type BrowserSDKConfig = Prettify<Omit<EmbeddedProviderConfig, "authOptions" | "a
|
|
|
119
119
|
authOptions?: {
|
|
120
120
|
authUrl?: string;
|
|
121
121
|
redirectUrl?: string;
|
|
122
|
-
|
|
123
|
-
/** When also provided, the Auth2 PKCE flow is used instead of the legacy Phantom Connect flow. */
|
|
124
|
-
unstable__auth2Options?: {
|
|
125
|
-
authApiBaseUrl: string;
|
|
126
|
-
clientId: string;
|
|
122
|
+
authApiBaseUrl?: string;
|
|
127
123
|
};
|
|
128
124
|
}>;
|
|
129
125
|
type Prettify<T> = {
|
package/dist/index.js
CHANGED
|
@@ -34,10 +34,10 @@ __export(src_exports, {
|
|
|
34
34
|
BrowserSDK: () => BrowserSDK,
|
|
35
35
|
DebugCategory: () => DebugCategory,
|
|
36
36
|
DebugLevel: () => DebugLevel,
|
|
37
|
-
NetworkId: () =>
|
|
38
|
-
PHANTOM_ICON: () =>
|
|
39
|
-
base64urlDecode: () =>
|
|
40
|
-
base64urlEncode: () =>
|
|
37
|
+
NetworkId: () => import_constants7.NetworkId,
|
|
38
|
+
PHANTOM_ICON: () => import_constants8.PHANTOM_ICON,
|
|
39
|
+
base64urlDecode: () => import_base64url.base64urlDecode,
|
|
40
|
+
base64urlEncode: () => import_base64url.base64urlEncode,
|
|
41
41
|
debug: () => debug,
|
|
42
42
|
detectBrowser: () => detectBrowser,
|
|
43
43
|
getBrowserDisplayName: () => getBrowserDisplayName,
|
|
@@ -2457,7 +2457,7 @@ var InjectedProvider = class {
|
|
|
2457
2457
|
|
|
2458
2458
|
// src/providers/embedded/index.ts
|
|
2459
2459
|
var import_embedded_provider_core = require("@phantom/embedded-provider-core");
|
|
2460
|
-
var
|
|
2460
|
+
var import_auth22 = require("@phantom/auth2");
|
|
2461
2461
|
|
|
2462
2462
|
// src/providers/embedded/adapters/storage.ts
|
|
2463
2463
|
var BrowserStorage = class {
|
|
@@ -2732,161 +2732,6 @@ function isMobileDevice() {
|
|
|
2732
2732
|
return isMobileUA || isSmallScreen && isTouchDevice;
|
|
2733
2733
|
}
|
|
2734
2734
|
|
|
2735
|
-
// src/providers/embedded/adapters/auth.ts
|
|
2736
|
-
var BrowserAuthProvider = class {
|
|
2737
|
-
constructor(urlParamsAccessor) {
|
|
2738
|
-
this.urlParamsAccessor = urlParamsAccessor;
|
|
2739
|
-
}
|
|
2740
|
-
getValidatedCurrentUrl() {
|
|
2741
|
-
const currentUrl = window.location.href;
|
|
2742
|
-
if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
|
|
2743
|
-
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
|
|
2744
|
-
}
|
|
2745
|
-
return currentUrl;
|
|
2746
|
-
}
|
|
2747
|
-
authenticate(options) {
|
|
2748
|
-
return new Promise((resolve) => {
|
|
2749
|
-
if ("jwtToken" in options) {
|
|
2750
|
-
throw new Error("JWT authentication should be handled by the core JWTAuth class");
|
|
2751
|
-
}
|
|
2752
|
-
const phantomOptions = options;
|
|
2753
|
-
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
|
|
2754
|
-
publicKey: phantomOptions.publicKey,
|
|
2755
|
-
appId: phantomOptions.appId,
|
|
2756
|
-
provider: phantomOptions.provider,
|
|
2757
|
-
authUrl: phantomOptions.authUrl
|
|
2758
|
-
});
|
|
2759
|
-
const baseUrl = phantomOptions.authUrl || import_constants3.DEFAULT_AUTH_URL;
|
|
2760
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
|
|
2761
|
-
const params = new URLSearchParams({
|
|
2762
|
-
public_key: phantomOptions.publicKey,
|
|
2763
|
-
app_id: phantomOptions.appId,
|
|
2764
|
-
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
|
|
2765
|
-
session_id: phantomOptions.sessionId,
|
|
2766
|
-
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
2767
|
-
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
2768
|
-
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
2769
|
-
sdk_version: "1.0.7",
|
|
2770
|
-
sdk_type: "browser",
|
|
2771
|
-
platform: detectBrowser().name,
|
|
2772
|
-
algorithm: phantomOptions.algorithm || import_constants3.DEFAULT_AUTHENTICATOR_ALGORITHM
|
|
2773
|
-
});
|
|
2774
|
-
if (phantomOptions.provider) {
|
|
2775
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
2776
|
-
provider: phantomOptions.provider
|
|
2777
|
-
});
|
|
2778
|
-
params.append("provider", phantomOptions.provider);
|
|
2779
|
-
} else {
|
|
2780
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "No provider specified, defaulting to Google");
|
|
2781
|
-
params.append("provider", "google");
|
|
2782
|
-
}
|
|
2783
|
-
const authContext = {
|
|
2784
|
-
publicKey: phantomOptions.publicKey,
|
|
2785
|
-
appId: phantomOptions.appId,
|
|
2786
|
-
provider: phantomOptions.provider,
|
|
2787
|
-
sessionId: phantomOptions.sessionId
|
|
2788
|
-
};
|
|
2789
|
-
sessionStorage.setItem("phantom-auth-context", JSON.stringify(authContext));
|
|
2790
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
|
|
2791
|
-
const authUrl = `${baseUrl}?${params.toString()}`;
|
|
2792
|
-
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Redirecting to Phantom Connect", { authUrl });
|
|
2793
|
-
if (!authUrl.startsWith("https:") && !authUrl.startsWith("http://localhost")) {
|
|
2794
|
-
throw new Error("Invalid auth URL - only HTTPS URLs are allowed for authentication");
|
|
2795
|
-
}
|
|
2796
|
-
window.location.href = authUrl;
|
|
2797
|
-
resolve();
|
|
2798
|
-
});
|
|
2799
|
-
}
|
|
2800
|
-
async resumeAuthFromRedirect(provider) {
|
|
2801
|
-
try {
|
|
2802
|
-
const walletId = this.urlParamsAccessor.getParam("wallet_id");
|
|
2803
|
-
const sessionId = this.urlParamsAccessor.getParam("session_id");
|
|
2804
|
-
const accountDerivationIndex = this.urlParamsAccessor.getParam("selected_account_index");
|
|
2805
|
-
const error = this.urlParamsAccessor.getParam("error");
|
|
2806
|
-
const errorDescription = this.urlParamsAccessor.getParam("error_description");
|
|
2807
|
-
if (error) {
|
|
2808
|
-
const errorMsg = errorDescription || error;
|
|
2809
|
-
switch (error) {
|
|
2810
|
-
case "access_denied":
|
|
2811
|
-
throw new Error(`Authentication cancelled: ${errorMsg}`);
|
|
2812
|
-
case "invalid_request":
|
|
2813
|
-
throw new Error(`Invalid authentication request: ${errorMsg}`);
|
|
2814
|
-
case "server_error":
|
|
2815
|
-
throw new Error(`Authentication server error: ${errorMsg}`);
|
|
2816
|
-
case "temporarily_unavailable":
|
|
2817
|
-
throw new Error(`Authentication service temporarily unavailable: ${errorMsg}`);
|
|
2818
|
-
default:
|
|
2819
|
-
throw new Error(`Authentication failed: ${errorMsg}`);
|
|
2820
|
-
}
|
|
2821
|
-
}
|
|
2822
|
-
if (!walletId || !sessionId) {
|
|
2823
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing auth parameters in URL", {
|
|
2824
|
-
hasWalletId: !!walletId,
|
|
2825
|
-
hasSessionId: !!sessionId
|
|
2826
|
-
});
|
|
2827
|
-
return null;
|
|
2828
|
-
}
|
|
2829
|
-
const contextStr = sessionStorage.getItem("phantom-auth-context");
|
|
2830
|
-
let context = {};
|
|
2831
|
-
if (contextStr) {
|
|
2832
|
-
try {
|
|
2833
|
-
context = JSON.parse(contextStr);
|
|
2834
|
-
} catch (parseError) {
|
|
2835
|
-
debug.warn(DebugCategory.PHANTOM_CONNECT_AUTH, "Failed to parse stored auth context", { error: parseError });
|
|
2836
|
-
}
|
|
2837
|
-
}
|
|
2838
|
-
if (context.sessionId && sessionId !== context.sessionId) {
|
|
2839
|
-
debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Session ID mismatch", {
|
|
2840
|
-
urlSessionId: sessionId,
|
|
2841
|
-
storedSessionId: context.sessionId
|
|
2842
|
-
});
|
|
2843
|
-
throw new Error("Session ID mismatch - possible session corruption or replay attack");
|
|
2844
|
-
}
|
|
2845
|
-
sessionStorage.removeItem("phantom-auth-context");
|
|
2846
|
-
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Successfully resumed auth from redirect", {
|
|
2847
|
-
walletId,
|
|
2848
|
-
sessionId,
|
|
2849
|
-
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
|
|
2850
|
-
});
|
|
2851
|
-
const organizationId = this.urlParamsAccessor.getParam("organization_id");
|
|
2852
|
-
const expiresInMs = this.urlParamsAccessor.getParam("expires_in_ms");
|
|
2853
|
-
const authUserId = this.urlParamsAccessor.getParam("auth_user_id");
|
|
2854
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Auth redirect parameters", {
|
|
2855
|
-
walletId,
|
|
2856
|
-
organizationId,
|
|
2857
|
-
sessionId,
|
|
2858
|
-
accountDerivationIndex,
|
|
2859
|
-
expiresInMs,
|
|
2860
|
-
authUserId
|
|
2861
|
-
});
|
|
2862
|
-
if (!organizationId) {
|
|
2863
|
-
debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing organization_id in auth response");
|
|
2864
|
-
throw new Error("Missing organization_id in auth response");
|
|
2865
|
-
}
|
|
2866
|
-
if (organizationId.startsWith("temp-")) {
|
|
2867
|
-
debug.warn(
|
|
2868
|
-
DebugCategory.PHANTOM_CONNECT_AUTH,
|
|
2869
|
-
"Received temporary organization_id, server may not be configured properly",
|
|
2870
|
-
{
|
|
2871
|
-
organizationId
|
|
2872
|
-
}
|
|
2873
|
-
);
|
|
2874
|
-
}
|
|
2875
|
-
return Promise.resolve({
|
|
2876
|
-
walletId,
|
|
2877
|
-
organizationId,
|
|
2878
|
-
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
|
|
2879
|
-
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
|
|
2880
|
-
authUserId: authUserId || void 0,
|
|
2881
|
-
provider
|
|
2882
|
-
});
|
|
2883
|
-
} catch (error) {
|
|
2884
|
-
sessionStorage.removeItem("phantom-auth-context");
|
|
2885
|
-
throw error;
|
|
2886
|
-
}
|
|
2887
|
-
}
|
|
2888
|
-
};
|
|
2889
|
-
|
|
2890
2735
|
// src/providers/embedded/adapters/Auth2AuthProvider.ts
|
|
2891
2736
|
var import_auth2 = require("@phantom/auth2");
|
|
2892
2737
|
var Auth2AuthProvider = class {
|
|
@@ -2910,30 +2755,17 @@ var Auth2AuthProvider = class {
|
|
|
2910
2755
|
* redirect without ever touching sessionStorage.
|
|
2911
2756
|
*/
|
|
2912
2757
|
async authenticate(options) {
|
|
2913
|
-
if (!this.stamper.getKeyInfo()) {
|
|
2914
|
-
await this.stamper.init();
|
|
2915
|
-
}
|
|
2916
|
-
const keyPair = this.stamper.getCryptoKeyPair();
|
|
2917
|
-
if (!keyPair) {
|
|
2918
|
-
throw new Error("Stamper key pair not found.");
|
|
2919
|
-
}
|
|
2920
|
-
const codeVerifier = (0, import_auth2.createCodeVerifier)();
|
|
2921
2758
|
const session = await this.storage.getSession();
|
|
2922
2759
|
if (!session) {
|
|
2923
2760
|
throw new Error("Session not found.");
|
|
2924
2761
|
}
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
|
|
2929
|
-
clientId: this.auth2ProviderOptions.clientId,
|
|
2930
|
-
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2762
|
+
const { url, codeVerifier } = await (0, import_auth2.prepareAuth2Flow)({
|
|
2763
|
+
stamper: this.stamper,
|
|
2764
|
+
auth2Options: this.auth2ProviderOptions,
|
|
2931
2765
|
sessionId: options.sessionId,
|
|
2932
|
-
provider: options.provider
|
|
2933
|
-
codeVerifier,
|
|
2934
|
-
// The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
|
|
2935
|
-
salt: ""
|
|
2766
|
+
provider: options.provider
|
|
2936
2767
|
});
|
|
2768
|
+
await this.storage.saveSession({ ...session, pkceCodeVerifier: codeVerifier });
|
|
2937
2769
|
Auth2AuthProvider.navigate(url);
|
|
2938
2770
|
}
|
|
2939
2771
|
/**
|
|
@@ -2943,8 +2775,7 @@ var Auth2AuthProvider = class {
|
|
|
2943
2775
|
* and wallet via KMS RPC, then returns a completed AuthResult.
|
|
2944
2776
|
*/
|
|
2945
2777
|
async resumeAuthFromRedirect(provider) {
|
|
2946
|
-
|
|
2947
|
-
if (!code) {
|
|
2778
|
+
if (!this.urlParamsAccessor.getParam("code")) {
|
|
2948
2779
|
return null;
|
|
2949
2780
|
}
|
|
2950
2781
|
if (!this.stamper.getKeyInfo()) {
|
|
@@ -2958,226 +2789,39 @@ var Auth2AuthProvider = class {
|
|
|
2958
2789
|
if (!codeVerifier) {
|
|
2959
2790
|
return null;
|
|
2960
2791
|
}
|
|
2961
|
-
const
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
}
|
|
2965
|
-
const
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
}
|
|
2970
|
-
const { idToken, bearerToken, authUserId, expiresInMs, refreshToken } = await (0, import_auth2.exchangeAuthCode)({
|
|
2971
|
-
authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
|
|
2972
|
-
clientId: this.auth2ProviderOptions.clientId,
|
|
2973
|
-
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2792
|
+
const code = (0, import_auth2.validateAuth2Callback)({
|
|
2793
|
+
getParam: (key) => this.urlParamsAccessor.getParam(key),
|
|
2794
|
+
expectedSessionId: session.sessionId
|
|
2795
|
+
});
|
|
2796
|
+
const result = await (0, import_auth2.completeAuth2Exchange)({
|
|
2797
|
+
stamper: this.stamper,
|
|
2798
|
+
kms: this.kms,
|
|
2799
|
+
auth2Options: this.auth2ProviderOptions,
|
|
2974
2800
|
code,
|
|
2975
|
-
codeVerifier
|
|
2801
|
+
codeVerifier,
|
|
2802
|
+
provider
|
|
2976
2803
|
});
|
|
2977
|
-
await this.stamper.setTokens({ idToken, bearerToken, refreshToken, expiresInMs });
|
|
2978
2804
|
await this.storage.saveSession({
|
|
2979
2805
|
...session,
|
|
2980
2806
|
status: "completed",
|
|
2981
|
-
bearerToken,
|
|
2982
|
-
authUserId,
|
|
2807
|
+
bearerToken: result.bearerToken,
|
|
2808
|
+
authUserId: result.authUserId,
|
|
2983
2809
|
pkceCodeVerifier: void 0
|
|
2984
|
-
// no longer needed after code exchange
|
|
2985
2810
|
});
|
|
2986
|
-
|
|
2987
|
-
return {
|
|
2988
|
-
walletId,
|
|
2989
|
-
organizationId,
|
|
2990
|
-
provider,
|
|
2991
|
-
accountDerivationIndex: 0,
|
|
2992
|
-
// discoverWalletId uses derivation index of 0.
|
|
2993
|
-
expiresInMs,
|
|
2994
|
-
authUserId,
|
|
2995
|
-
bearerToken
|
|
2996
|
-
};
|
|
2811
|
+
return result;
|
|
2997
2812
|
}
|
|
2998
2813
|
};
|
|
2999
2814
|
|
|
3000
|
-
// src/providers/embedded/adapters/
|
|
3001
|
-
var import_bs582 = __toESM(require("bs58"));
|
|
3002
|
-
var import_base64url = require("@phantom/base64url");
|
|
3003
|
-
var import_sdk_types = require("@phantom/sdk-types");
|
|
3004
|
-
var import_auth22 = require("@phantom/auth2");
|
|
3005
|
-
var import_constants4 = require("@phantom/constants");
|
|
2815
|
+
// src/providers/embedded/adapters/IndexedDBAuth2StamperStorage.ts
|
|
3006
2816
|
var STORE_NAME = "crypto-keys";
|
|
3007
2817
|
var ACTIVE_KEY = "auth2-p256-signing-key";
|
|
3008
|
-
var
|
|
3009
|
-
|
|
3010
|
-
* @param dbName - IndexedDB database name (use a unique name per app to
|
|
3011
|
-
* avoid key collisions with other stampers, e.g. `phantom-auth2-<appId>`).
|
|
3012
|
-
* @param refreshConfig - When provided, the stamper will automatically refresh
|
|
3013
|
-
* the id_token using the refresh_token before it expires.
|
|
3014
|
-
*/
|
|
3015
|
-
constructor(dbName, refreshConfig) {
|
|
2818
|
+
var IndexedDBAuth2StamperStorage = class {
|
|
2819
|
+
constructor(dbName) {
|
|
3016
2820
|
this.dbName = dbName;
|
|
3017
|
-
this.refreshConfig = refreshConfig;
|
|
3018
2821
|
this.db = null;
|
|
3019
|
-
this.
|
|
3020
|
-
this._keyInfo = null;
|
|
3021
|
-
this._idToken = null;
|
|
3022
|
-
this._bearerToken = null;
|
|
3023
|
-
this._refreshToken = null;
|
|
3024
|
-
this._tokenExpiresAt = null;
|
|
3025
|
-
this.algorithm = import_sdk_types.Algorithm.secp256r1;
|
|
3026
|
-
this.type = "OIDC";
|
|
3027
|
-
}
|
|
3028
|
-
async init() {
|
|
3029
|
-
await this.openDB();
|
|
3030
|
-
const stored = await this.loadRecord();
|
|
3031
|
-
if (stored) {
|
|
3032
|
-
this._keyPair = stored.keyPair;
|
|
3033
|
-
this._keyInfo = stored.keyInfo;
|
|
3034
|
-
if (stored.idToken) {
|
|
3035
|
-
this._idToken = stored.idToken;
|
|
3036
|
-
}
|
|
3037
|
-
if (stored.bearerToken) {
|
|
3038
|
-
this._bearerToken = stored.bearerToken;
|
|
3039
|
-
}
|
|
3040
|
-
if (stored.refreshToken) {
|
|
3041
|
-
this._refreshToken = stored.refreshToken;
|
|
3042
|
-
}
|
|
3043
|
-
if (stored.tokenExpiresAt) {
|
|
3044
|
-
this._tokenExpiresAt = stored.tokenExpiresAt;
|
|
3045
|
-
}
|
|
3046
|
-
return this._keyInfo;
|
|
3047
|
-
}
|
|
3048
|
-
return this.generateAndStore();
|
|
3049
|
-
}
|
|
3050
|
-
getKeyInfo() {
|
|
3051
|
-
return this._keyInfo;
|
|
3052
|
-
}
|
|
3053
|
-
getCryptoKeyPair() {
|
|
3054
|
-
return this._keyPair;
|
|
3055
|
-
}
|
|
3056
|
-
/**
|
|
3057
|
-
* Returns the current token state (refreshing proactively if near expiry),
|
|
3058
|
-
* or null if no token has been set yet.
|
|
3059
|
-
*/
|
|
3060
|
-
async getTokens() {
|
|
3061
|
-
if (this.refreshConfig && this._refreshToken && this._tokenExpiresAt !== null && Date.now() >= this._tokenExpiresAt - import_constants4.TOKEN_REFRESH_BUFFER_MS) {
|
|
3062
|
-
const refreshed = await (0, import_auth22.refreshToken)({
|
|
3063
|
-
authApiBaseUrl: this.refreshConfig.authApiBaseUrl,
|
|
3064
|
-
clientId: this.refreshConfig.clientId,
|
|
3065
|
-
redirectUri: this.refreshConfig.redirectUri,
|
|
3066
|
-
refreshToken: this._refreshToken
|
|
3067
|
-
});
|
|
3068
|
-
await this.setTokens(refreshed);
|
|
3069
|
-
}
|
|
3070
|
-
if (!this._idToken || !this._bearerToken) {
|
|
3071
|
-
return null;
|
|
3072
|
-
}
|
|
3073
|
-
return {
|
|
3074
|
-
idToken: this._idToken,
|
|
3075
|
-
bearerToken: this._bearerToken,
|
|
3076
|
-
refreshToken: this._refreshToken ?? void 0
|
|
3077
|
-
};
|
|
3078
|
-
}
|
|
3079
|
-
/**
|
|
3080
|
-
* Arms the stamper with the OIDC token data for subsequent KMS stamp() calls.
|
|
3081
|
-
*
|
|
3082
|
-
* Persists the tokens to IndexedDB alongside the key pair so that
|
|
3083
|
-
* auto-connect can restore them on the next page load without a new login.
|
|
3084
|
-
*
|
|
3085
|
-
* @param refreshToken - When provided alongside a `refreshConfig`, enables
|
|
3086
|
-
* silent token refresh before the token expires.
|
|
3087
|
-
* @param expiresInMs - Token lifetime in milliseconds (from `expires_in * 1000`).
|
|
3088
|
-
* Used to compute the absolute expiry time for proactive refresh.
|
|
3089
|
-
*/
|
|
3090
|
-
async setTokens({
|
|
3091
|
-
idToken,
|
|
3092
|
-
bearerToken,
|
|
3093
|
-
refreshToken,
|
|
3094
|
-
expiresInMs
|
|
3095
|
-
}) {
|
|
3096
|
-
if (!this.db) {
|
|
3097
|
-
await this.openDB();
|
|
3098
|
-
}
|
|
3099
|
-
this._idToken = idToken;
|
|
3100
|
-
this._bearerToken = bearerToken;
|
|
3101
|
-
this._refreshToken = refreshToken ?? null;
|
|
3102
|
-
this._tokenExpiresAt = expiresInMs != null ? Date.now() + expiresInMs : null;
|
|
3103
|
-
const existing = await this.loadRecord();
|
|
3104
|
-
if (existing) {
|
|
3105
|
-
await this.storeRecord({
|
|
3106
|
-
...existing,
|
|
3107
|
-
idToken,
|
|
3108
|
-
bearerToken,
|
|
3109
|
-
refreshToken,
|
|
3110
|
-
tokenExpiresAt: this._tokenExpiresAt ?? void 0
|
|
3111
|
-
});
|
|
3112
|
-
}
|
|
2822
|
+
this.requiresExtractableKeys = false;
|
|
3113
2823
|
}
|
|
3114
|
-
async
|
|
3115
|
-
if (!this._keyPair || !this._keyInfo || this._idToken === null) {
|
|
3116
|
-
throw new Error("Auth2Stamper not initialized. Call init() first.");
|
|
3117
|
-
}
|
|
3118
|
-
const signatureRaw = await crypto.subtle.sign(
|
|
3119
|
-
{ name: "ECDSA", hash: "SHA-256" },
|
|
3120
|
-
this._keyPair.privateKey,
|
|
3121
|
-
new Uint8Array(params.data)
|
|
3122
|
-
);
|
|
3123
|
-
const rawPublicKey = import_bs582.default.decode(this._keyInfo.publicKey);
|
|
3124
|
-
const stampData = {
|
|
3125
|
-
kind: this.type,
|
|
3126
|
-
idToken: this._idToken,
|
|
3127
|
-
publicKey: (0, import_base64url.base64urlEncode)(rawPublicKey),
|
|
3128
|
-
algorithm: this.algorithm,
|
|
3129
|
-
// The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
|
|
3130
|
-
salt: "",
|
|
3131
|
-
signature: (0, import_base64url.base64urlEncode)(new Uint8Array(signatureRaw))
|
|
3132
|
-
};
|
|
3133
|
-
return (0, import_base64url.base64urlEncode)(new TextEncoder().encode(JSON.stringify(stampData)));
|
|
3134
|
-
}
|
|
3135
|
-
async resetKeyPair() {
|
|
3136
|
-
await this.clear();
|
|
3137
|
-
return this.generateAndStore();
|
|
3138
|
-
}
|
|
3139
|
-
async clear() {
|
|
3140
|
-
await this.clearStoredRecord();
|
|
3141
|
-
this._keyPair = null;
|
|
3142
|
-
this._keyInfo = null;
|
|
3143
|
-
this._idToken = null;
|
|
3144
|
-
this._bearerToken = null;
|
|
3145
|
-
this._refreshToken = null;
|
|
3146
|
-
this._tokenExpiresAt = null;
|
|
3147
|
-
}
|
|
3148
|
-
// Auth2 doesn't use key rotation; provide minimal no-op implementations.
|
|
3149
|
-
async rotateKeyPair() {
|
|
3150
|
-
return this.init();
|
|
3151
|
-
}
|
|
3152
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
3153
|
-
async commitRotation(authenticatorId) {
|
|
3154
|
-
if (this._keyInfo) {
|
|
3155
|
-
this._keyInfo.authenticatorId = authenticatorId;
|
|
3156
|
-
}
|
|
3157
|
-
}
|
|
3158
|
-
async rollbackRotation() {
|
|
3159
|
-
}
|
|
3160
|
-
async generateAndStore() {
|
|
3161
|
-
const keyPair = await crypto.subtle.generateKey(
|
|
3162
|
-
{ name: "ECDSA", namedCurve: "P-256" },
|
|
3163
|
-
false,
|
|
3164
|
-
// non-extractable — private key never leaves Web Crypto
|
|
3165
|
-
["sign", "verify"]
|
|
3166
|
-
);
|
|
3167
|
-
const rawPublicKey = new Uint8Array(await crypto.subtle.exportKey("raw", keyPair.publicKey));
|
|
3168
|
-
const publicKeyBase58 = import_bs582.default.encode(rawPublicKey);
|
|
3169
|
-
const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
|
|
3170
|
-
const keyId = (0, import_base64url.base64urlEncode)(new Uint8Array(keyIdBuffer)).substring(0, 16);
|
|
3171
|
-
this._keyPair = keyPair;
|
|
3172
|
-
this._keyInfo = {
|
|
3173
|
-
keyId,
|
|
3174
|
-
publicKey: publicKeyBase58,
|
|
3175
|
-
createdAt: Date.now()
|
|
3176
|
-
};
|
|
3177
|
-
await this.storeRecord({ keyPair, keyInfo: this._keyInfo });
|
|
3178
|
-
return this._keyInfo;
|
|
3179
|
-
}
|
|
3180
|
-
async openDB() {
|
|
2824
|
+
async open() {
|
|
3181
2825
|
return new Promise((resolve, reject) => {
|
|
3182
2826
|
const request = indexedDB.open(this.dbName, 1);
|
|
3183
2827
|
request.onsuccess = () => {
|
|
@@ -3193,7 +2837,7 @@ var Auth2Stamper = class {
|
|
|
3193
2837
|
};
|
|
3194
2838
|
});
|
|
3195
2839
|
}
|
|
3196
|
-
async
|
|
2840
|
+
async load() {
|
|
3197
2841
|
return new Promise((resolve, reject) => {
|
|
3198
2842
|
if (!this.db) {
|
|
3199
2843
|
throw new Error("Database not initialized");
|
|
@@ -3207,7 +2851,7 @@ var Auth2Stamper = class {
|
|
|
3207
2851
|
};
|
|
3208
2852
|
});
|
|
3209
2853
|
}
|
|
3210
|
-
async
|
|
2854
|
+
async save(record) {
|
|
3211
2855
|
return new Promise((resolve, reject) => {
|
|
3212
2856
|
if (!this.db) {
|
|
3213
2857
|
throw new Error("Database not initialized");
|
|
@@ -3221,7 +2865,7 @@ var Auth2Stamper = class {
|
|
|
3221
2865
|
};
|
|
3222
2866
|
});
|
|
3223
2867
|
}
|
|
3224
|
-
async
|
|
2868
|
+
async clear() {
|
|
3225
2869
|
return new Promise((resolve, reject) => {
|
|
3226
2870
|
if (!this.db) {
|
|
3227
2871
|
throw new Error("Database not initialized");
|
|
@@ -3355,38 +2999,34 @@ var BrowserLogger = class {
|
|
|
3355
2999
|
};
|
|
3356
3000
|
|
|
3357
3001
|
// src/providers/embedded/index.ts
|
|
3358
|
-
var
|
|
3002
|
+
var import_constants4 = require("@phantom/constants");
|
|
3359
3003
|
var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
|
|
3360
3004
|
constructor(config) {
|
|
3361
3005
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
3362
3006
|
const urlParamsAccessor = new BrowserURLParamsAccessor();
|
|
3363
3007
|
const storage = new BrowserStorage();
|
|
3364
|
-
const stamper =
|
|
3365
|
-
authApiBaseUrl: config.
|
|
3366
|
-
clientId: config.
|
|
3367
|
-
redirectUri: config.authOptions
|
|
3368
|
-
}) : new import_indexed_db_stamper.IndexedDbStamper({
|
|
3369
|
-
dbName: `phantom-embedded-sdk-${config.appId}`,
|
|
3370
|
-
storeName: "crypto-keys",
|
|
3371
|
-
keyName: "signing-key"
|
|
3008
|
+
const stamper = new import_auth22.Auth2Stamper(new IndexedDBAuth2StamperStorage(`phantom-auth2-${config.appId}`), {
|
|
3009
|
+
authApiBaseUrl: config.authOptions.authApiBaseUrl,
|
|
3010
|
+
clientId: config.appId,
|
|
3011
|
+
redirectUri: config.authOptions.redirectUrl
|
|
3372
3012
|
});
|
|
3373
3013
|
const platformName = getPlatformName();
|
|
3374
3014
|
const { name: browserName, version } = detectBrowser();
|
|
3375
|
-
const authProvider =
|
|
3015
|
+
const authProvider = new Auth2AuthProvider(
|
|
3376
3016
|
stamper,
|
|
3377
3017
|
storage,
|
|
3378
3018
|
urlParamsAccessor,
|
|
3379
3019
|
{
|
|
3380
3020
|
redirectUri: config.authOptions.redirectUrl,
|
|
3381
3021
|
connectLoginUrl: config.authOptions.authUrl,
|
|
3382
|
-
clientId: config.
|
|
3383
|
-
authApiBaseUrl: config.
|
|
3022
|
+
clientId: config.appId,
|
|
3023
|
+
authApiBaseUrl: config.authOptions.authApiBaseUrl
|
|
3384
3024
|
},
|
|
3385
3025
|
{
|
|
3386
3026
|
apiBaseUrl: config.apiBaseUrl,
|
|
3387
3027
|
appId: config.appId
|
|
3388
3028
|
}
|
|
3389
|
-
)
|
|
3029
|
+
);
|
|
3390
3030
|
const platform = {
|
|
3391
3031
|
storage,
|
|
3392
3032
|
authProvider,
|
|
@@ -3396,13 +3036,13 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
3396
3036
|
name: platformName,
|
|
3397
3037
|
// Use detected browser name and version for identification
|
|
3398
3038
|
analyticsHeaders: {
|
|
3399
|
-
[
|
|
3400
|
-
[
|
|
3401
|
-
[
|
|
3402
|
-
[
|
|
3403
|
-
[
|
|
3404
|
-
[
|
|
3405
|
-
[
|
|
3039
|
+
[import_constants4.ANALYTICS_HEADERS.SDK_TYPE]: "browser",
|
|
3040
|
+
[import_constants4.ANALYTICS_HEADERS.PLATFORM]: "ext-sdk",
|
|
3041
|
+
[import_constants4.ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
|
|
3042
|
+
[import_constants4.ANALYTICS_HEADERS.CLIENT]: browserName,
|
|
3043
|
+
[import_constants4.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
3044
|
+
[import_constants4.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
3045
|
+
[import_constants4.ANALYTICS_HEADERS.SDK_VERSION]: "2.0.0-beta.0"
|
|
3406
3046
|
// Replaced at build time
|
|
3407
3047
|
}
|
|
3408
3048
|
};
|
|
@@ -3419,7 +3059,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
3419
3059
|
|
|
3420
3060
|
// src/ProviderManager.ts
|
|
3421
3061
|
var import_embedded_provider_core2 = require("@phantom/embedded-provider-core");
|
|
3422
|
-
var
|
|
3062
|
+
var import_constants5 = require("@phantom/constants");
|
|
3423
3063
|
|
|
3424
3064
|
// src/utils/auth-callback.ts
|
|
3425
3065
|
function isAuthFailureCallback(searchParams) {
|
|
@@ -3810,18 +3450,19 @@ var ProviderManager = class {
|
|
|
3810
3450
|
if (!this.config.appId) {
|
|
3811
3451
|
throw new Error("appId is required for embedded provider");
|
|
3812
3452
|
}
|
|
3813
|
-
const apiBaseUrl = this.config.apiBaseUrl ||
|
|
3814
|
-
const authUrl = this.config.authOptions?.authUrl ||
|
|
3453
|
+
const apiBaseUrl = this.config.apiBaseUrl || import_constants5.DEFAULT_WALLET_API_URL;
|
|
3454
|
+
const authUrl = this.config.authOptions?.authUrl || import_constants5.DEFAULT_AUTH_URL;
|
|
3455
|
+
const authApiBaseUrl = this.config.authOptions?.authApiBaseUrl || import_constants5.DEFAULT_AUTH_API_BASE_URL;
|
|
3815
3456
|
provider = new EmbeddedProvider({
|
|
3816
3457
|
apiBaseUrl,
|
|
3817
3458
|
appId: this.config.appId,
|
|
3818
3459
|
authOptions: {
|
|
3819
3460
|
...this.config.authOptions || {},
|
|
3820
3461
|
authUrl,
|
|
3821
|
-
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
|
|
3462
|
+
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl(),
|
|
3463
|
+
authApiBaseUrl
|
|
3822
3464
|
},
|
|
3823
|
-
|
|
3824
|
-
embeddedWalletType: embeddedWalletType || import_constants6.DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
3465
|
+
embeddedWalletType: embeddedWalletType || import_constants5.DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
3825
3466
|
addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
|
|
3826
3467
|
});
|
|
3827
3468
|
} else {
|
|
@@ -3857,7 +3498,7 @@ var ProviderManager = class {
|
|
|
3857
3498
|
|
|
3858
3499
|
// src/BrowserSDK.ts
|
|
3859
3500
|
var import_embedded_provider_core3 = require("@phantom/embedded-provider-core");
|
|
3860
|
-
var
|
|
3501
|
+
var import_constants6 = require("@phantom/constants");
|
|
3861
3502
|
var BROWSER_SDK_PROVIDER_TYPES = [
|
|
3862
3503
|
...import_embedded_provider_core3.EMBEDDED_PROVIDER_AUTH_TYPES,
|
|
3863
3504
|
"injected",
|
|
@@ -3893,7 +3534,7 @@ var BrowserSDK = class {
|
|
|
3893
3534
|
});
|
|
3894
3535
|
throw new Error("appId is required when using embedded providers (google, apple, phantom, etc.)");
|
|
3895
3536
|
}
|
|
3896
|
-
const embeddedWalletType = config.embeddedWalletType ||
|
|
3537
|
+
const embeddedWalletType = config.embeddedWalletType || import_constants6.DEFAULT_EMBEDDED_WALLET_TYPE;
|
|
3897
3538
|
if (!["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
|
|
3898
3539
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
|
|
3899
3540
|
embeddedWalletType: config.embeddedWalletType
|
|
@@ -4168,7 +3809,7 @@ var BrowserSDK = class {
|
|
|
4168
3809
|
};
|
|
4169
3810
|
|
|
4170
3811
|
// src/index.ts
|
|
4171
|
-
var
|
|
3812
|
+
var import_constants7 = require("@phantom/constants");
|
|
4172
3813
|
var import_client5 = require("@phantom/client");
|
|
4173
|
-
var
|
|
4174
|
-
var
|
|
3814
|
+
var import_base64url = require("@phantom/base64url");
|
|
3815
|
+
var import_constants8 = require("@phantom/constants");
|
package/dist/index.mjs
CHANGED
|
@@ -2405,7 +2405,7 @@ var InjectedProvider = class {
|
|
|
2405
2405
|
|
|
2406
2406
|
// src/providers/embedded/index.ts
|
|
2407
2407
|
import { EmbeddedProvider as CoreEmbeddedProvider } from "@phantom/embedded-provider-core";
|
|
2408
|
-
import {
|
|
2408
|
+
import { Auth2Stamper } from "@phantom/auth2";
|
|
2409
2409
|
|
|
2410
2410
|
// src/providers/embedded/adapters/storage.ts
|
|
2411
2411
|
var BrowserStorage = class {
|
|
@@ -2680,167 +2680,12 @@ function isMobileDevice() {
|
|
|
2680
2680
|
return isMobileUA || isSmallScreen && isTouchDevice;
|
|
2681
2681
|
}
|
|
2682
2682
|
|
|
2683
|
-
// src/providers/embedded/adapters/auth.ts
|
|
2684
|
-
var BrowserAuthProvider = class {
|
|
2685
|
-
constructor(urlParamsAccessor) {
|
|
2686
|
-
this.urlParamsAccessor = urlParamsAccessor;
|
|
2687
|
-
}
|
|
2688
|
-
getValidatedCurrentUrl() {
|
|
2689
|
-
const currentUrl = window.location.href;
|
|
2690
|
-
if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
|
|
2691
|
-
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
|
|
2692
|
-
}
|
|
2693
|
-
return currentUrl;
|
|
2694
|
-
}
|
|
2695
|
-
authenticate(options) {
|
|
2696
|
-
return new Promise((resolve) => {
|
|
2697
|
-
if ("jwtToken" in options) {
|
|
2698
|
-
throw new Error("JWT authentication should be handled by the core JWTAuth class");
|
|
2699
|
-
}
|
|
2700
|
-
const phantomOptions = options;
|
|
2701
|
-
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
|
|
2702
|
-
publicKey: phantomOptions.publicKey,
|
|
2703
|
-
appId: phantomOptions.appId,
|
|
2704
|
-
provider: phantomOptions.provider,
|
|
2705
|
-
authUrl: phantomOptions.authUrl
|
|
2706
|
-
});
|
|
2707
|
-
const baseUrl = phantomOptions.authUrl || DEFAULT_AUTH_URL;
|
|
2708
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
|
|
2709
|
-
const params = new URLSearchParams({
|
|
2710
|
-
public_key: phantomOptions.publicKey,
|
|
2711
|
-
app_id: phantomOptions.appId,
|
|
2712
|
-
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
|
|
2713
|
-
session_id: phantomOptions.sessionId,
|
|
2714
|
-
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
2715
|
-
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
2716
|
-
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
2717
|
-
sdk_version: "1.0.7",
|
|
2718
|
-
sdk_type: "browser",
|
|
2719
|
-
platform: detectBrowser().name,
|
|
2720
|
-
algorithm: phantomOptions.algorithm || DEFAULT_AUTHENTICATOR_ALGORITHM
|
|
2721
|
-
});
|
|
2722
|
-
if (phantomOptions.provider) {
|
|
2723
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
2724
|
-
provider: phantomOptions.provider
|
|
2725
|
-
});
|
|
2726
|
-
params.append("provider", phantomOptions.provider);
|
|
2727
|
-
} else {
|
|
2728
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "No provider specified, defaulting to Google");
|
|
2729
|
-
params.append("provider", "google");
|
|
2730
|
-
}
|
|
2731
|
-
const authContext = {
|
|
2732
|
-
publicKey: phantomOptions.publicKey,
|
|
2733
|
-
appId: phantomOptions.appId,
|
|
2734
|
-
provider: phantomOptions.provider,
|
|
2735
|
-
sessionId: phantomOptions.sessionId
|
|
2736
|
-
};
|
|
2737
|
-
sessionStorage.setItem("phantom-auth-context", JSON.stringify(authContext));
|
|
2738
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
|
|
2739
|
-
const authUrl = `${baseUrl}?${params.toString()}`;
|
|
2740
|
-
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Redirecting to Phantom Connect", { authUrl });
|
|
2741
|
-
if (!authUrl.startsWith("https:") && !authUrl.startsWith("http://localhost")) {
|
|
2742
|
-
throw new Error("Invalid auth URL - only HTTPS URLs are allowed for authentication");
|
|
2743
|
-
}
|
|
2744
|
-
window.location.href = authUrl;
|
|
2745
|
-
resolve();
|
|
2746
|
-
});
|
|
2747
|
-
}
|
|
2748
|
-
async resumeAuthFromRedirect(provider) {
|
|
2749
|
-
try {
|
|
2750
|
-
const walletId = this.urlParamsAccessor.getParam("wallet_id");
|
|
2751
|
-
const sessionId = this.urlParamsAccessor.getParam("session_id");
|
|
2752
|
-
const accountDerivationIndex = this.urlParamsAccessor.getParam("selected_account_index");
|
|
2753
|
-
const error = this.urlParamsAccessor.getParam("error");
|
|
2754
|
-
const errorDescription = this.urlParamsAccessor.getParam("error_description");
|
|
2755
|
-
if (error) {
|
|
2756
|
-
const errorMsg = errorDescription || error;
|
|
2757
|
-
switch (error) {
|
|
2758
|
-
case "access_denied":
|
|
2759
|
-
throw new Error(`Authentication cancelled: ${errorMsg}`);
|
|
2760
|
-
case "invalid_request":
|
|
2761
|
-
throw new Error(`Invalid authentication request: ${errorMsg}`);
|
|
2762
|
-
case "server_error":
|
|
2763
|
-
throw new Error(`Authentication server error: ${errorMsg}`);
|
|
2764
|
-
case "temporarily_unavailable":
|
|
2765
|
-
throw new Error(`Authentication service temporarily unavailable: ${errorMsg}`);
|
|
2766
|
-
default:
|
|
2767
|
-
throw new Error(`Authentication failed: ${errorMsg}`);
|
|
2768
|
-
}
|
|
2769
|
-
}
|
|
2770
|
-
if (!walletId || !sessionId) {
|
|
2771
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing auth parameters in URL", {
|
|
2772
|
-
hasWalletId: !!walletId,
|
|
2773
|
-
hasSessionId: !!sessionId
|
|
2774
|
-
});
|
|
2775
|
-
return null;
|
|
2776
|
-
}
|
|
2777
|
-
const contextStr = sessionStorage.getItem("phantom-auth-context");
|
|
2778
|
-
let context = {};
|
|
2779
|
-
if (contextStr) {
|
|
2780
|
-
try {
|
|
2781
|
-
context = JSON.parse(contextStr);
|
|
2782
|
-
} catch (parseError) {
|
|
2783
|
-
debug.warn(DebugCategory.PHANTOM_CONNECT_AUTH, "Failed to parse stored auth context", { error: parseError });
|
|
2784
|
-
}
|
|
2785
|
-
}
|
|
2786
|
-
if (context.sessionId && sessionId !== context.sessionId) {
|
|
2787
|
-
debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Session ID mismatch", {
|
|
2788
|
-
urlSessionId: sessionId,
|
|
2789
|
-
storedSessionId: context.sessionId
|
|
2790
|
-
});
|
|
2791
|
-
throw new Error("Session ID mismatch - possible session corruption or replay attack");
|
|
2792
|
-
}
|
|
2793
|
-
sessionStorage.removeItem("phantom-auth-context");
|
|
2794
|
-
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Successfully resumed auth from redirect", {
|
|
2795
|
-
walletId,
|
|
2796
|
-
sessionId,
|
|
2797
|
-
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
|
|
2798
|
-
});
|
|
2799
|
-
const organizationId = this.urlParamsAccessor.getParam("organization_id");
|
|
2800
|
-
const expiresInMs = this.urlParamsAccessor.getParam("expires_in_ms");
|
|
2801
|
-
const authUserId = this.urlParamsAccessor.getParam("auth_user_id");
|
|
2802
|
-
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Auth redirect parameters", {
|
|
2803
|
-
walletId,
|
|
2804
|
-
organizationId,
|
|
2805
|
-
sessionId,
|
|
2806
|
-
accountDerivationIndex,
|
|
2807
|
-
expiresInMs,
|
|
2808
|
-
authUserId
|
|
2809
|
-
});
|
|
2810
|
-
if (!organizationId) {
|
|
2811
|
-
debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing organization_id in auth response");
|
|
2812
|
-
throw new Error("Missing organization_id in auth response");
|
|
2813
|
-
}
|
|
2814
|
-
if (organizationId.startsWith("temp-")) {
|
|
2815
|
-
debug.warn(
|
|
2816
|
-
DebugCategory.PHANTOM_CONNECT_AUTH,
|
|
2817
|
-
"Received temporary organization_id, server may not be configured properly",
|
|
2818
|
-
{
|
|
2819
|
-
organizationId
|
|
2820
|
-
}
|
|
2821
|
-
);
|
|
2822
|
-
}
|
|
2823
|
-
return Promise.resolve({
|
|
2824
|
-
walletId,
|
|
2825
|
-
organizationId,
|
|
2826
|
-
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
|
|
2827
|
-
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
|
|
2828
|
-
authUserId: authUserId || void 0,
|
|
2829
|
-
provider
|
|
2830
|
-
});
|
|
2831
|
-
} catch (error) {
|
|
2832
|
-
sessionStorage.removeItem("phantom-auth-context");
|
|
2833
|
-
throw error;
|
|
2834
|
-
}
|
|
2835
|
-
}
|
|
2836
|
-
};
|
|
2837
|
-
|
|
2838
2683
|
// src/providers/embedded/adapters/Auth2AuthProvider.ts
|
|
2839
2684
|
import {
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2685
|
+
Auth2KmsRpcClient,
|
|
2686
|
+
prepareAuth2Flow,
|
|
2687
|
+
validateAuth2Callback,
|
|
2688
|
+
completeAuth2Exchange
|
|
2844
2689
|
} from "@phantom/auth2";
|
|
2845
2690
|
var Auth2AuthProvider = class {
|
|
2846
2691
|
constructor(stamper, storage, urlParamsAccessor, auth2ProviderOptions, kmsClientOptions) {
|
|
@@ -2863,30 +2708,17 @@ var Auth2AuthProvider = class {
|
|
|
2863
2708
|
* redirect without ever touching sessionStorage.
|
|
2864
2709
|
*/
|
|
2865
2710
|
async authenticate(options) {
|
|
2866
|
-
if (!this.stamper.getKeyInfo()) {
|
|
2867
|
-
await this.stamper.init();
|
|
2868
|
-
}
|
|
2869
|
-
const keyPair = this.stamper.getCryptoKeyPair();
|
|
2870
|
-
if (!keyPair) {
|
|
2871
|
-
throw new Error("Stamper key pair not found.");
|
|
2872
|
-
}
|
|
2873
|
-
const codeVerifier = createCodeVerifier();
|
|
2874
2711
|
const session = await this.storage.getSession();
|
|
2875
2712
|
if (!session) {
|
|
2876
2713
|
throw new Error("Session not found.");
|
|
2877
2714
|
}
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
|
|
2882
|
-
clientId: this.auth2ProviderOptions.clientId,
|
|
2883
|
-
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2715
|
+
const { url, codeVerifier } = await prepareAuth2Flow({
|
|
2716
|
+
stamper: this.stamper,
|
|
2717
|
+
auth2Options: this.auth2ProviderOptions,
|
|
2884
2718
|
sessionId: options.sessionId,
|
|
2885
|
-
provider: options.provider
|
|
2886
|
-
codeVerifier,
|
|
2887
|
-
// The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
|
|
2888
|
-
salt: ""
|
|
2719
|
+
provider: options.provider
|
|
2889
2720
|
});
|
|
2721
|
+
await this.storage.saveSession({ ...session, pkceCodeVerifier: codeVerifier });
|
|
2890
2722
|
Auth2AuthProvider.navigate(url);
|
|
2891
2723
|
}
|
|
2892
2724
|
/**
|
|
@@ -2896,8 +2728,7 @@ var Auth2AuthProvider = class {
|
|
|
2896
2728
|
* and wallet via KMS RPC, then returns a completed AuthResult.
|
|
2897
2729
|
*/
|
|
2898
2730
|
async resumeAuthFromRedirect(provider) {
|
|
2899
|
-
|
|
2900
|
-
if (!code) {
|
|
2731
|
+
if (!this.urlParamsAccessor.getParam("code")) {
|
|
2901
2732
|
return null;
|
|
2902
2733
|
}
|
|
2903
2734
|
if (!this.stamper.getKeyInfo()) {
|
|
@@ -2911,226 +2742,39 @@ var Auth2AuthProvider = class {
|
|
|
2911
2742
|
if (!codeVerifier) {
|
|
2912
2743
|
return null;
|
|
2913
2744
|
}
|
|
2914
|
-
const
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
}
|
|
2918
|
-
const
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
}
|
|
2923
|
-
const { idToken, bearerToken, authUserId, expiresInMs, refreshToken } = await exchangeAuthCode({
|
|
2924
|
-
authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
|
|
2925
|
-
clientId: this.auth2ProviderOptions.clientId,
|
|
2926
|
-
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2745
|
+
const code = validateAuth2Callback({
|
|
2746
|
+
getParam: (key) => this.urlParamsAccessor.getParam(key),
|
|
2747
|
+
expectedSessionId: session.sessionId
|
|
2748
|
+
});
|
|
2749
|
+
const result = await completeAuth2Exchange({
|
|
2750
|
+
stamper: this.stamper,
|
|
2751
|
+
kms: this.kms,
|
|
2752
|
+
auth2Options: this.auth2ProviderOptions,
|
|
2927
2753
|
code,
|
|
2928
|
-
codeVerifier
|
|
2754
|
+
codeVerifier,
|
|
2755
|
+
provider
|
|
2929
2756
|
});
|
|
2930
|
-
await this.stamper.setTokens({ idToken, bearerToken, refreshToken, expiresInMs });
|
|
2931
2757
|
await this.storage.saveSession({
|
|
2932
2758
|
...session,
|
|
2933
2759
|
status: "completed",
|
|
2934
|
-
bearerToken,
|
|
2935
|
-
authUserId,
|
|
2760
|
+
bearerToken: result.bearerToken,
|
|
2761
|
+
authUserId: result.authUserId,
|
|
2936
2762
|
pkceCodeVerifier: void 0
|
|
2937
|
-
// no longer needed after code exchange
|
|
2938
2763
|
});
|
|
2939
|
-
|
|
2940
|
-
return {
|
|
2941
|
-
walletId,
|
|
2942
|
-
organizationId,
|
|
2943
|
-
provider,
|
|
2944
|
-
accountDerivationIndex: 0,
|
|
2945
|
-
// discoverWalletId uses derivation index of 0.
|
|
2946
|
-
expiresInMs,
|
|
2947
|
-
authUserId,
|
|
2948
|
-
bearerToken
|
|
2949
|
-
};
|
|
2764
|
+
return result;
|
|
2950
2765
|
}
|
|
2951
2766
|
};
|
|
2952
2767
|
|
|
2953
|
-
// src/providers/embedded/adapters/
|
|
2954
|
-
import bs582 from "bs58";
|
|
2955
|
-
import { base64urlEncode } from "@phantom/base64url";
|
|
2956
|
-
import { Algorithm } from "@phantom/sdk-types";
|
|
2957
|
-
import { refreshToken as refreshTokenRequest } from "@phantom/auth2";
|
|
2958
|
-
import { TOKEN_REFRESH_BUFFER_MS } from "@phantom/constants";
|
|
2768
|
+
// src/providers/embedded/adapters/IndexedDBAuth2StamperStorage.ts
|
|
2959
2769
|
var STORE_NAME = "crypto-keys";
|
|
2960
2770
|
var ACTIVE_KEY = "auth2-p256-signing-key";
|
|
2961
|
-
var
|
|
2962
|
-
|
|
2963
|
-
* @param dbName - IndexedDB database name (use a unique name per app to
|
|
2964
|
-
* avoid key collisions with other stampers, e.g. `phantom-auth2-<appId>`).
|
|
2965
|
-
* @param refreshConfig - When provided, the stamper will automatically refresh
|
|
2966
|
-
* the id_token using the refresh_token before it expires.
|
|
2967
|
-
*/
|
|
2968
|
-
constructor(dbName, refreshConfig) {
|
|
2771
|
+
var IndexedDBAuth2StamperStorage = class {
|
|
2772
|
+
constructor(dbName) {
|
|
2969
2773
|
this.dbName = dbName;
|
|
2970
|
-
this.refreshConfig = refreshConfig;
|
|
2971
2774
|
this.db = null;
|
|
2972
|
-
this.
|
|
2973
|
-
this._keyInfo = null;
|
|
2974
|
-
this._idToken = null;
|
|
2975
|
-
this._bearerToken = null;
|
|
2976
|
-
this._refreshToken = null;
|
|
2977
|
-
this._tokenExpiresAt = null;
|
|
2978
|
-
this.algorithm = Algorithm.secp256r1;
|
|
2979
|
-
this.type = "OIDC";
|
|
2980
|
-
}
|
|
2981
|
-
async init() {
|
|
2982
|
-
await this.openDB();
|
|
2983
|
-
const stored = await this.loadRecord();
|
|
2984
|
-
if (stored) {
|
|
2985
|
-
this._keyPair = stored.keyPair;
|
|
2986
|
-
this._keyInfo = stored.keyInfo;
|
|
2987
|
-
if (stored.idToken) {
|
|
2988
|
-
this._idToken = stored.idToken;
|
|
2989
|
-
}
|
|
2990
|
-
if (stored.bearerToken) {
|
|
2991
|
-
this._bearerToken = stored.bearerToken;
|
|
2992
|
-
}
|
|
2993
|
-
if (stored.refreshToken) {
|
|
2994
|
-
this._refreshToken = stored.refreshToken;
|
|
2995
|
-
}
|
|
2996
|
-
if (stored.tokenExpiresAt) {
|
|
2997
|
-
this._tokenExpiresAt = stored.tokenExpiresAt;
|
|
2998
|
-
}
|
|
2999
|
-
return this._keyInfo;
|
|
3000
|
-
}
|
|
3001
|
-
return this.generateAndStore();
|
|
3002
|
-
}
|
|
3003
|
-
getKeyInfo() {
|
|
3004
|
-
return this._keyInfo;
|
|
3005
|
-
}
|
|
3006
|
-
getCryptoKeyPair() {
|
|
3007
|
-
return this._keyPair;
|
|
3008
|
-
}
|
|
3009
|
-
/**
|
|
3010
|
-
* Returns the current token state (refreshing proactively if near expiry),
|
|
3011
|
-
* or null if no token has been set yet.
|
|
3012
|
-
*/
|
|
3013
|
-
async getTokens() {
|
|
3014
|
-
if (this.refreshConfig && this._refreshToken && this._tokenExpiresAt !== null && Date.now() >= this._tokenExpiresAt - TOKEN_REFRESH_BUFFER_MS) {
|
|
3015
|
-
const refreshed = await refreshTokenRequest({
|
|
3016
|
-
authApiBaseUrl: this.refreshConfig.authApiBaseUrl,
|
|
3017
|
-
clientId: this.refreshConfig.clientId,
|
|
3018
|
-
redirectUri: this.refreshConfig.redirectUri,
|
|
3019
|
-
refreshToken: this._refreshToken
|
|
3020
|
-
});
|
|
3021
|
-
await this.setTokens(refreshed);
|
|
3022
|
-
}
|
|
3023
|
-
if (!this._idToken || !this._bearerToken) {
|
|
3024
|
-
return null;
|
|
3025
|
-
}
|
|
3026
|
-
return {
|
|
3027
|
-
idToken: this._idToken,
|
|
3028
|
-
bearerToken: this._bearerToken,
|
|
3029
|
-
refreshToken: this._refreshToken ?? void 0
|
|
3030
|
-
};
|
|
3031
|
-
}
|
|
3032
|
-
/**
|
|
3033
|
-
* Arms the stamper with the OIDC token data for subsequent KMS stamp() calls.
|
|
3034
|
-
*
|
|
3035
|
-
* Persists the tokens to IndexedDB alongside the key pair so that
|
|
3036
|
-
* auto-connect can restore them on the next page load without a new login.
|
|
3037
|
-
*
|
|
3038
|
-
* @param refreshToken - When provided alongside a `refreshConfig`, enables
|
|
3039
|
-
* silent token refresh before the token expires.
|
|
3040
|
-
* @param expiresInMs - Token lifetime in milliseconds (from `expires_in * 1000`).
|
|
3041
|
-
* Used to compute the absolute expiry time for proactive refresh.
|
|
3042
|
-
*/
|
|
3043
|
-
async setTokens({
|
|
3044
|
-
idToken,
|
|
3045
|
-
bearerToken,
|
|
3046
|
-
refreshToken,
|
|
3047
|
-
expiresInMs
|
|
3048
|
-
}) {
|
|
3049
|
-
if (!this.db) {
|
|
3050
|
-
await this.openDB();
|
|
3051
|
-
}
|
|
3052
|
-
this._idToken = idToken;
|
|
3053
|
-
this._bearerToken = bearerToken;
|
|
3054
|
-
this._refreshToken = refreshToken ?? null;
|
|
3055
|
-
this._tokenExpiresAt = expiresInMs != null ? Date.now() + expiresInMs : null;
|
|
3056
|
-
const existing = await this.loadRecord();
|
|
3057
|
-
if (existing) {
|
|
3058
|
-
await this.storeRecord({
|
|
3059
|
-
...existing,
|
|
3060
|
-
idToken,
|
|
3061
|
-
bearerToken,
|
|
3062
|
-
refreshToken,
|
|
3063
|
-
tokenExpiresAt: this._tokenExpiresAt ?? void 0
|
|
3064
|
-
});
|
|
3065
|
-
}
|
|
2775
|
+
this.requiresExtractableKeys = false;
|
|
3066
2776
|
}
|
|
3067
|
-
async
|
|
3068
|
-
if (!this._keyPair || !this._keyInfo || this._idToken === null) {
|
|
3069
|
-
throw new Error("Auth2Stamper not initialized. Call init() first.");
|
|
3070
|
-
}
|
|
3071
|
-
const signatureRaw = await crypto.subtle.sign(
|
|
3072
|
-
{ name: "ECDSA", hash: "SHA-256" },
|
|
3073
|
-
this._keyPair.privateKey,
|
|
3074
|
-
new Uint8Array(params.data)
|
|
3075
|
-
);
|
|
3076
|
-
const rawPublicKey = bs582.decode(this._keyInfo.publicKey);
|
|
3077
|
-
const stampData = {
|
|
3078
|
-
kind: this.type,
|
|
3079
|
-
idToken: this._idToken,
|
|
3080
|
-
publicKey: base64urlEncode(rawPublicKey),
|
|
3081
|
-
algorithm: this.algorithm,
|
|
3082
|
-
// The P-256 ephemeral key is unique per wallet, so no additional salt is needed.
|
|
3083
|
-
salt: "",
|
|
3084
|
-
signature: base64urlEncode(new Uint8Array(signatureRaw))
|
|
3085
|
-
};
|
|
3086
|
-
return base64urlEncode(new TextEncoder().encode(JSON.stringify(stampData)));
|
|
3087
|
-
}
|
|
3088
|
-
async resetKeyPair() {
|
|
3089
|
-
await this.clear();
|
|
3090
|
-
return this.generateAndStore();
|
|
3091
|
-
}
|
|
3092
|
-
async clear() {
|
|
3093
|
-
await this.clearStoredRecord();
|
|
3094
|
-
this._keyPair = null;
|
|
3095
|
-
this._keyInfo = null;
|
|
3096
|
-
this._idToken = null;
|
|
3097
|
-
this._bearerToken = null;
|
|
3098
|
-
this._refreshToken = null;
|
|
3099
|
-
this._tokenExpiresAt = null;
|
|
3100
|
-
}
|
|
3101
|
-
// Auth2 doesn't use key rotation; provide minimal no-op implementations.
|
|
3102
|
-
async rotateKeyPair() {
|
|
3103
|
-
return this.init();
|
|
3104
|
-
}
|
|
3105
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
3106
|
-
async commitRotation(authenticatorId) {
|
|
3107
|
-
if (this._keyInfo) {
|
|
3108
|
-
this._keyInfo.authenticatorId = authenticatorId;
|
|
3109
|
-
}
|
|
3110
|
-
}
|
|
3111
|
-
async rollbackRotation() {
|
|
3112
|
-
}
|
|
3113
|
-
async generateAndStore() {
|
|
3114
|
-
const keyPair = await crypto.subtle.generateKey(
|
|
3115
|
-
{ name: "ECDSA", namedCurve: "P-256" },
|
|
3116
|
-
false,
|
|
3117
|
-
// non-extractable — private key never leaves Web Crypto
|
|
3118
|
-
["sign", "verify"]
|
|
3119
|
-
);
|
|
3120
|
-
const rawPublicKey = new Uint8Array(await crypto.subtle.exportKey("raw", keyPair.publicKey));
|
|
3121
|
-
const publicKeyBase58 = bs582.encode(rawPublicKey);
|
|
3122
|
-
const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
|
|
3123
|
-
const keyId = base64urlEncode(new Uint8Array(keyIdBuffer)).substring(0, 16);
|
|
3124
|
-
this._keyPair = keyPair;
|
|
3125
|
-
this._keyInfo = {
|
|
3126
|
-
keyId,
|
|
3127
|
-
publicKey: publicKeyBase58,
|
|
3128
|
-
createdAt: Date.now()
|
|
3129
|
-
};
|
|
3130
|
-
await this.storeRecord({ keyPair, keyInfo: this._keyInfo });
|
|
3131
|
-
return this._keyInfo;
|
|
3132
|
-
}
|
|
3133
|
-
async openDB() {
|
|
2777
|
+
async open() {
|
|
3134
2778
|
return new Promise((resolve, reject) => {
|
|
3135
2779
|
const request = indexedDB.open(this.dbName, 1);
|
|
3136
2780
|
request.onsuccess = () => {
|
|
@@ -3146,7 +2790,7 @@ var Auth2Stamper = class {
|
|
|
3146
2790
|
};
|
|
3147
2791
|
});
|
|
3148
2792
|
}
|
|
3149
|
-
async
|
|
2793
|
+
async load() {
|
|
3150
2794
|
return new Promise((resolve, reject) => {
|
|
3151
2795
|
if (!this.db) {
|
|
3152
2796
|
throw new Error("Database not initialized");
|
|
@@ -3160,7 +2804,7 @@ var Auth2Stamper = class {
|
|
|
3160
2804
|
};
|
|
3161
2805
|
});
|
|
3162
2806
|
}
|
|
3163
|
-
async
|
|
2807
|
+
async save(record) {
|
|
3164
2808
|
return new Promise((resolve, reject) => {
|
|
3165
2809
|
if (!this.db) {
|
|
3166
2810
|
throw new Error("Database not initialized");
|
|
@@ -3174,7 +2818,7 @@ var Auth2Stamper = class {
|
|
|
3174
2818
|
};
|
|
3175
2819
|
});
|
|
3176
2820
|
}
|
|
3177
|
-
async
|
|
2821
|
+
async clear() {
|
|
3178
2822
|
return new Promise((resolve, reject) => {
|
|
3179
2823
|
if (!this.db) {
|
|
3180
2824
|
throw new Error("Database not initialized");
|
|
@@ -3314,32 +2958,28 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
3314
2958
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
3315
2959
|
const urlParamsAccessor = new BrowserURLParamsAccessor();
|
|
3316
2960
|
const storage = new BrowserStorage();
|
|
3317
|
-
const stamper =
|
|
3318
|
-
authApiBaseUrl: config.
|
|
3319
|
-
clientId: config.
|
|
3320
|
-
redirectUri: config.authOptions
|
|
3321
|
-
}) : new IndexedDbStamper({
|
|
3322
|
-
dbName: `phantom-embedded-sdk-${config.appId}`,
|
|
3323
|
-
storeName: "crypto-keys",
|
|
3324
|
-
keyName: "signing-key"
|
|
2961
|
+
const stamper = new Auth2Stamper(new IndexedDBAuth2StamperStorage(`phantom-auth2-${config.appId}`), {
|
|
2962
|
+
authApiBaseUrl: config.authOptions.authApiBaseUrl,
|
|
2963
|
+
clientId: config.appId,
|
|
2964
|
+
redirectUri: config.authOptions.redirectUrl
|
|
3325
2965
|
});
|
|
3326
2966
|
const platformName = getPlatformName();
|
|
3327
2967
|
const { name: browserName, version } = detectBrowser();
|
|
3328
|
-
const authProvider =
|
|
2968
|
+
const authProvider = new Auth2AuthProvider(
|
|
3329
2969
|
stamper,
|
|
3330
2970
|
storage,
|
|
3331
2971
|
urlParamsAccessor,
|
|
3332
2972
|
{
|
|
3333
2973
|
redirectUri: config.authOptions.redirectUrl,
|
|
3334
2974
|
connectLoginUrl: config.authOptions.authUrl,
|
|
3335
|
-
clientId: config.
|
|
3336
|
-
authApiBaseUrl: config.
|
|
2975
|
+
clientId: config.appId,
|
|
2976
|
+
authApiBaseUrl: config.authOptions.authApiBaseUrl
|
|
3337
2977
|
},
|
|
3338
2978
|
{
|
|
3339
2979
|
apiBaseUrl: config.apiBaseUrl,
|
|
3340
2980
|
appId: config.appId
|
|
3341
2981
|
}
|
|
3342
|
-
)
|
|
2982
|
+
);
|
|
3343
2983
|
const platform = {
|
|
3344
2984
|
storage,
|
|
3345
2985
|
authProvider,
|
|
@@ -3355,7 +2995,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
3355
2995
|
[ANALYTICS_HEADERS.CLIENT]: browserName,
|
|
3356
2996
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
3357
2997
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
3358
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "
|
|
2998
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "2.0.0-beta.0"
|
|
3359
2999
|
// Replaced at build time
|
|
3360
3000
|
}
|
|
3361
3001
|
};
|
|
@@ -3374,7 +3014,12 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
3374
3014
|
import {
|
|
3375
3015
|
EMBEDDED_PROVIDER_AUTH_TYPES
|
|
3376
3016
|
} from "@phantom/embedded-provider-core";
|
|
3377
|
-
import {
|
|
3017
|
+
import {
|
|
3018
|
+
DEFAULT_WALLET_API_URL,
|
|
3019
|
+
DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
3020
|
+
DEFAULT_AUTH_URL as DEFAULT_AUTH_URL2,
|
|
3021
|
+
DEFAULT_AUTH_API_BASE_URL
|
|
3022
|
+
} from "@phantom/constants";
|
|
3378
3023
|
|
|
3379
3024
|
// src/utils/auth-callback.ts
|
|
3380
3025
|
function isAuthFailureCallback(searchParams) {
|
|
@@ -3767,15 +3412,16 @@ var ProviderManager = class {
|
|
|
3767
3412
|
}
|
|
3768
3413
|
const apiBaseUrl = this.config.apiBaseUrl || DEFAULT_WALLET_API_URL;
|
|
3769
3414
|
const authUrl = this.config.authOptions?.authUrl || DEFAULT_AUTH_URL2;
|
|
3415
|
+
const authApiBaseUrl = this.config.authOptions?.authApiBaseUrl || DEFAULT_AUTH_API_BASE_URL;
|
|
3770
3416
|
provider = new EmbeddedProvider({
|
|
3771
3417
|
apiBaseUrl,
|
|
3772
3418
|
appId: this.config.appId,
|
|
3773
3419
|
authOptions: {
|
|
3774
3420
|
...this.config.authOptions || {},
|
|
3775
3421
|
authUrl,
|
|
3776
|
-
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
|
|
3422
|
+
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl(),
|
|
3423
|
+
authApiBaseUrl
|
|
3777
3424
|
},
|
|
3778
|
-
unstable__auth2Options: this.config.unstable__auth2Options,
|
|
3779
3425
|
embeddedWalletType: embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
3780
3426
|
addressTypes: this.config.addressTypes || [AddressType.solana]
|
|
3781
3427
|
});
|
|
@@ -4125,7 +3771,7 @@ var BrowserSDK = class {
|
|
|
4125
3771
|
// src/index.ts
|
|
4126
3772
|
import { NetworkId } from "@phantom/constants";
|
|
4127
3773
|
import { AddressType as AddressType4 } from "@phantom/client";
|
|
4128
|
-
import { base64urlEncode
|
|
3774
|
+
import { base64urlEncode, base64urlDecode } from "@phantom/base64url";
|
|
4129
3775
|
import { PHANTOM_ICON as PHANTOM_ICON3 } from "@phantom/constants";
|
|
4130
3776
|
export {
|
|
4131
3777
|
AddressType4 as AddressType,
|
|
@@ -4135,7 +3781,7 @@ export {
|
|
|
4135
3781
|
NetworkId,
|
|
4136
3782
|
PHANTOM_ICON3 as PHANTOM_ICON,
|
|
4137
3783
|
base64urlDecode,
|
|
4138
|
-
|
|
3784
|
+
base64urlEncode,
|
|
4139
3785
|
debug,
|
|
4140
3786
|
detectBrowser,
|
|
4141
3787
|
getBrowserDisplayName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/browser-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
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": "^
|
|
37
|
-
"@phantom/base64url": "^
|
|
38
|
-
"@phantom/browser-injected-sdk": "^
|
|
39
|
-
"@phantom/chain-interfaces": "^
|
|
40
|
-
"@phantom/client": "^
|
|
41
|
-
"@phantom/constants": "^
|
|
42
|
-
"@phantom/embedded-provider-core": "^
|
|
43
|
-
"@phantom/indexed-db-stamper": "^
|
|
44
|
-
"@phantom/parsers": "^
|
|
45
|
-
"@phantom/sdk-types": "^
|
|
36
|
+
"@phantom/auth2": "^2.0.0-beta.0",
|
|
37
|
+
"@phantom/base64url": "^2.0.0-beta.0",
|
|
38
|
+
"@phantom/browser-injected-sdk": "^2.0.0-beta.0",
|
|
39
|
+
"@phantom/chain-interfaces": "^2.0.0-beta.0",
|
|
40
|
+
"@phantom/client": "^2.0.0-beta.0",
|
|
41
|
+
"@phantom/constants": "^2.0.0-beta.0",
|
|
42
|
+
"@phantom/embedded-provider-core": "^2.0.0-beta.0",
|
|
43
|
+
"@phantom/indexed-db-stamper": "^2.0.0-beta.0",
|
|
44
|
+
"@phantom/parsers": "^2.0.0-beta.0",
|
|
45
|
+
"@phantom/sdk-types": "^2.0.0-beta.0",
|
|
46
46
|
"axios": "^1.10.0",
|
|
47
47
|
"bs58": "^6.0.0",
|
|
48
48
|
"buffer": "^6.0.3",
|