@phantom/browser-sdk 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +105 -36
- package/dist/index.mjs +88 -19
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -985,6 +985,46 @@ function toggleDebug(enabled: boolean) {
|
|
|
985
985
|
}
|
|
986
986
|
```
|
|
987
987
|
|
|
988
|
+
## Dapp-Sponsored Transactions (presignTransaction)
|
|
989
|
+
|
|
990
|
+
Pass `presignTransaction` directly to `signAndSendTransaction` for calls that need co-signing. Calls without it proceed normally — it is never applied globally.
|
|
991
|
+
|
|
992
|
+
> **Important:** Phantom embedded wallets do not accept pre-signed transactions. If your use case requires a second signer (e.g. your app as the fee payer), that signing must happen via this option, after Phantom has constructed and validated the transaction. This restriction does not apply to injected providers (e.g. the Phantom browser extension).
|
|
993
|
+
|
|
994
|
+
> **Note:** `presignTransaction` only fires for Solana transactions via the embedded provider. EVM transactions and injected providers are unaffected.
|
|
995
|
+
|
|
996
|
+
### Transaction format
|
|
997
|
+
|
|
998
|
+
The `transaction` string is **base64url-encoded** (URL-safe base64 without `=` padding, using `-` and `_` instead of `+` and `/`).
|
|
999
|
+
|
|
1000
|
+
The SDK exports `base64urlDecode` and `base64urlEncode` utilities:
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
import { base64urlDecode, base64urlEncode } from "@phantom/browser-sdk";
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
### Example: Dapp fee payer
|
|
1007
|
+
|
|
1008
|
+
```ts
|
|
1009
|
+
import { base64urlDecode, base64urlEncode } from "@phantom/browser-sdk";
|
|
1010
|
+
import { Keypair, VersionedTransaction } from "@solana/web3.js";
|
|
1011
|
+
|
|
1012
|
+
const feePayerKeypair = Keypair.fromSecretKey(/* your fee payer secret key */);
|
|
1013
|
+
|
|
1014
|
+
// This call co-signs as fee payer
|
|
1015
|
+
const result = await sdk.solana.signAndSendTransaction(transaction, {
|
|
1016
|
+
presignTransaction: async (tx, context) => {
|
|
1017
|
+
const txBytes = base64urlDecode(tx);
|
|
1018
|
+
const versionedTx = VersionedTransaction.deserialize(txBytes);
|
|
1019
|
+
versionedTx.sign([feePayerKeypair]);
|
|
1020
|
+
return base64urlEncode(versionedTx.serialize());
|
|
1021
|
+
},
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
// This call has no co-signer
|
|
1025
|
+
const result2 = await sdk.solana.signAndSendTransaction(otherTransaction);
|
|
1026
|
+
```
|
|
1027
|
+
|
|
988
1028
|
## Transaction Examples
|
|
989
1029
|
|
|
990
1030
|
### Solana Transactions
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { EmbeddedProviderConfig, EmbeddedProviderAuthType, ConnectResult as ConnectResult$1, WalletAddress, EmbeddedProviderEvent, EventCallback } from '@phantom/embedded-provider-core';
|
|
2
2
|
export { ConnectErrorEventData, ConnectEventData, ConnectStartEventData, DisconnectEventData, EmbeddedProviderEvent, EmbeddedProviderEventMap, EventCallback, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
|
|
3
3
|
import { IEthereumChain, ISolanaChain } from '@phantom/chain-interfaces';
|
|
4
|
-
export { EthTransactionRequest, IEthereumChain, ISolanaChain } from '@phantom/chain-interfaces';
|
|
4
|
+
export { EthTransactionRequest, IEthereumChain, ISolanaChain, SignAndSendTransactionOptions } from '@phantom/chain-interfaces';
|
|
5
5
|
import { AddressType } from '@phantom/client';
|
|
6
|
-
export { AddressType } from '@phantom/client';
|
|
6
|
+
export { AddressType, PresignTransactionContext } from '@phantom/client';
|
|
7
7
|
import { AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult } from '@phantom/browser-injected-sdk/auto-confirm';
|
|
8
8
|
export { AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult } from '@phantom/browser-injected-sdk/auto-confirm';
|
|
9
9
|
export { NetworkId, PHANTOM_ICON } from '@phantom/constants';
|
|
10
|
+
export { base64urlDecode, base64urlEncode } from '@phantom/base64url';
|
|
10
11
|
|
|
11
12
|
declare enum DebugLevel {
|
|
12
13
|
ERROR = 0,
|
package/dist/index.js
CHANGED
|
@@ -34,8 +34,10 @@ __export(src_exports, {
|
|
|
34
34
|
BrowserSDK: () => BrowserSDK,
|
|
35
35
|
DebugCategory: () => DebugCategory,
|
|
36
36
|
DebugLevel: () => DebugLevel,
|
|
37
|
-
NetworkId: () =>
|
|
38
|
-
PHANTOM_ICON: () =>
|
|
37
|
+
NetworkId: () => import_constants8.NetworkId,
|
|
38
|
+
PHANTOM_ICON: () => import_constants9.PHANTOM_ICON,
|
|
39
|
+
base64urlDecode: () => import_base64url2.base64urlDecode,
|
|
40
|
+
base64urlEncode: () => import_base64url2.base64urlEncode,
|
|
39
41
|
debug: () => debug,
|
|
40
42
|
detectBrowser: () => detectBrowser,
|
|
41
43
|
getBrowserDisplayName: () => getBrowserDisplayName,
|
|
@@ -2764,7 +2766,7 @@ var BrowserAuthProvider = class {
|
|
|
2764
2766
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
2765
2767
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
2766
2768
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
2767
|
-
sdk_version: "1.0.
|
|
2769
|
+
sdk_version: "1.0.7",
|
|
2768
2770
|
sdk_type: "browser",
|
|
2769
2771
|
platform: detectBrowser().name,
|
|
2770
2772
|
algorithm: phantomOptions.algorithm || import_constants3.DEFAULT_AUTHENTICATOR_ALGORITHM
|
|
@@ -2965,14 +2967,14 @@ var Auth2AuthProvider = class {
|
|
|
2965
2967
|
const description = this.urlParamsAccessor.getParam("error_description");
|
|
2966
2968
|
throw new Error(`Auth2 callback error: ${description ?? error}`);
|
|
2967
2969
|
}
|
|
2968
|
-
const { idToken, bearerToken, authUserId, expiresInMs } = await (0, import_auth2.exchangeAuthCode)({
|
|
2970
|
+
const { idToken, bearerToken, authUserId, expiresInMs, refreshToken } = await (0, import_auth2.exchangeAuthCode)({
|
|
2969
2971
|
authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
|
|
2970
2972
|
clientId: this.auth2ProviderOptions.clientId,
|
|
2971
2973
|
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2972
2974
|
code,
|
|
2973
2975
|
codeVerifier
|
|
2974
2976
|
});
|
|
2975
|
-
await this.stamper.
|
|
2977
|
+
await this.stamper.setTokens({ idToken, bearerToken, refreshToken, expiresInMs });
|
|
2976
2978
|
await this.storage.saveSession({
|
|
2977
2979
|
...session,
|
|
2978
2980
|
status: "completed",
|
|
@@ -2999,19 +3001,27 @@ var Auth2AuthProvider = class {
|
|
|
2999
3001
|
var import_bs582 = __toESM(require("bs58"));
|
|
3000
3002
|
var import_base64url = require("@phantom/base64url");
|
|
3001
3003
|
var import_sdk_types = require("@phantom/sdk-types");
|
|
3004
|
+
var import_auth22 = require("@phantom/auth2");
|
|
3005
|
+
var import_constants4 = require("@phantom/constants");
|
|
3002
3006
|
var STORE_NAME = "crypto-keys";
|
|
3003
3007
|
var ACTIVE_KEY = "auth2-p256-signing-key";
|
|
3004
3008
|
var Auth2Stamper = class {
|
|
3005
3009
|
/**
|
|
3006
3010
|
* @param dbName - IndexedDB database name (use a unique name per app to
|
|
3007
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.
|
|
3008
3014
|
*/
|
|
3009
|
-
constructor(dbName) {
|
|
3015
|
+
constructor(dbName, refreshConfig) {
|
|
3010
3016
|
this.dbName = dbName;
|
|
3017
|
+
this.refreshConfig = refreshConfig;
|
|
3011
3018
|
this.db = null;
|
|
3012
3019
|
this._keyPair = null;
|
|
3013
3020
|
this._keyInfo = null;
|
|
3014
3021
|
this._idToken = null;
|
|
3022
|
+
this._bearerToken = null;
|
|
3023
|
+
this._refreshToken = null;
|
|
3024
|
+
this._tokenExpiresAt = null;
|
|
3015
3025
|
this.algorithm = import_sdk_types.Algorithm.secp256r1;
|
|
3016
3026
|
this.type = "OIDC";
|
|
3017
3027
|
}
|
|
@@ -3024,6 +3034,15 @@ var Auth2Stamper = class {
|
|
|
3024
3034
|
if (stored.idToken) {
|
|
3025
3035
|
this._idToken = stored.idToken;
|
|
3026
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
|
+
}
|
|
3027
3046
|
return this._keyInfo;
|
|
3028
3047
|
}
|
|
3029
3048
|
return this.generateAndStore();
|
|
@@ -3035,19 +3054,61 @@ var Auth2Stamper = class {
|
|
|
3035
3054
|
return this._keyPair;
|
|
3036
3055
|
}
|
|
3037
3056
|
/**
|
|
3038
|
-
*
|
|
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.
|
|
3039
3084
|
*
|
|
3040
|
-
*
|
|
3041
|
-
*
|
|
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.
|
|
3042
3089
|
*/
|
|
3043
|
-
async
|
|
3090
|
+
async setTokens({
|
|
3091
|
+
idToken,
|
|
3092
|
+
bearerToken,
|
|
3093
|
+
refreshToken,
|
|
3094
|
+
expiresInMs
|
|
3095
|
+
}) {
|
|
3044
3096
|
if (!this.db) {
|
|
3045
3097
|
await this.openDB();
|
|
3046
3098
|
}
|
|
3047
3099
|
this._idToken = idToken;
|
|
3100
|
+
this._bearerToken = bearerToken;
|
|
3101
|
+
this._refreshToken = refreshToken ?? null;
|
|
3102
|
+
this._tokenExpiresAt = expiresInMs != null ? Date.now() + expiresInMs : null;
|
|
3048
3103
|
const existing = await this.loadRecord();
|
|
3049
3104
|
if (existing) {
|
|
3050
|
-
await this.storeRecord({
|
|
3105
|
+
await this.storeRecord({
|
|
3106
|
+
...existing,
|
|
3107
|
+
idToken,
|
|
3108
|
+
bearerToken,
|
|
3109
|
+
refreshToken,
|
|
3110
|
+
tokenExpiresAt: this._tokenExpiresAt ?? void 0
|
|
3111
|
+
});
|
|
3051
3112
|
}
|
|
3052
3113
|
}
|
|
3053
3114
|
async stamp(params) {
|
|
@@ -3080,6 +3141,9 @@ var Auth2Stamper = class {
|
|
|
3080
3141
|
this._keyPair = null;
|
|
3081
3142
|
this._keyInfo = null;
|
|
3082
3143
|
this._idToken = null;
|
|
3144
|
+
this._bearerToken = null;
|
|
3145
|
+
this._refreshToken = null;
|
|
3146
|
+
this._tokenExpiresAt = null;
|
|
3083
3147
|
}
|
|
3084
3148
|
// Auth2 doesn't use key rotation; provide minimal no-op implementations.
|
|
3085
3149
|
async rotateKeyPair() {
|
|
@@ -3276,28 +3340,32 @@ var BrowserPhantomAppProvider = class {
|
|
|
3276
3340
|
|
|
3277
3341
|
// src/providers/embedded/adapters/logger.ts
|
|
3278
3342
|
var BrowserLogger = class {
|
|
3279
|
-
info(
|
|
3280
|
-
debug.info(
|
|
3343
|
+
info(message, ...args) {
|
|
3344
|
+
debug.info(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3281
3345
|
}
|
|
3282
|
-
warn(
|
|
3283
|
-
debug.warn(
|
|
3346
|
+
warn(message, ...args) {
|
|
3347
|
+
debug.warn(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3284
3348
|
}
|
|
3285
|
-
error(
|
|
3286
|
-
debug.error(
|
|
3349
|
+
error(message, ...args) {
|
|
3350
|
+
debug.error(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3287
3351
|
}
|
|
3288
|
-
|
|
3289
|
-
debug.log(
|
|
3352
|
+
debug(message, ...args) {
|
|
3353
|
+
debug.log(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3290
3354
|
}
|
|
3291
3355
|
};
|
|
3292
3356
|
|
|
3293
3357
|
// src/providers/embedded/index.ts
|
|
3294
|
-
var
|
|
3358
|
+
var import_constants5 = require("@phantom/constants");
|
|
3295
3359
|
var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
|
|
3296
3360
|
constructor(config) {
|
|
3297
3361
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
3298
3362
|
const urlParamsAccessor = new BrowserURLParamsAccessor();
|
|
3299
3363
|
const storage = new BrowserStorage();
|
|
3300
|
-
const stamper = config.unstable__auth2Options ? new Auth2Stamper(`phantom-auth2-${config.appId}
|
|
3364
|
+
const stamper = config.unstable__auth2Options ? new Auth2Stamper(`phantom-auth2-${config.appId}`, {
|
|
3365
|
+
authApiBaseUrl: config.unstable__auth2Options.authApiBaseUrl,
|
|
3366
|
+
clientId: config.unstable__auth2Options.clientId,
|
|
3367
|
+
redirectUri: config.authOptions?.redirectUrl ?? ""
|
|
3368
|
+
}) : new import_indexed_db_stamper.IndexedDbStamper({
|
|
3301
3369
|
dbName: `phantom-embedded-sdk-${config.appId}`,
|
|
3302
3370
|
storeName: "crypto-keys",
|
|
3303
3371
|
keyName: "signing-key"
|
|
@@ -3328,13 +3396,13 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
3328
3396
|
name: platformName,
|
|
3329
3397
|
// Use detected browser name and version for identification
|
|
3330
3398
|
analyticsHeaders: {
|
|
3331
|
-
[
|
|
3332
|
-
[
|
|
3333
|
-
[
|
|
3334
|
-
[
|
|
3335
|
-
[
|
|
3336
|
-
[
|
|
3337
|
-
[
|
|
3399
|
+
[import_constants5.ANALYTICS_HEADERS.SDK_TYPE]: "browser",
|
|
3400
|
+
[import_constants5.ANALYTICS_HEADERS.PLATFORM]: "ext-sdk",
|
|
3401
|
+
[import_constants5.ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
|
|
3402
|
+
[import_constants5.ANALYTICS_HEADERS.CLIENT]: browserName,
|
|
3403
|
+
[import_constants5.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
3404
|
+
[import_constants5.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
3405
|
+
[import_constants5.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.7"
|
|
3338
3406
|
// Replaced at build time
|
|
3339
3407
|
}
|
|
3340
3408
|
};
|
|
@@ -3351,7 +3419,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
3351
3419
|
|
|
3352
3420
|
// src/ProviderManager.ts
|
|
3353
3421
|
var import_embedded_provider_core2 = require("@phantom/embedded-provider-core");
|
|
3354
|
-
var
|
|
3422
|
+
var import_constants6 = require("@phantom/constants");
|
|
3355
3423
|
|
|
3356
3424
|
// src/utils/auth-callback.ts
|
|
3357
3425
|
function isAuthFailureCallback(searchParams) {
|
|
@@ -3742,8 +3810,8 @@ var ProviderManager = class {
|
|
|
3742
3810
|
if (!this.config.appId) {
|
|
3743
3811
|
throw new Error("appId is required for embedded provider");
|
|
3744
3812
|
}
|
|
3745
|
-
const apiBaseUrl = this.config.apiBaseUrl ||
|
|
3746
|
-
const authUrl = this.config.authOptions?.authUrl ||
|
|
3813
|
+
const apiBaseUrl = this.config.apiBaseUrl || import_constants6.DEFAULT_WALLET_API_URL;
|
|
3814
|
+
const authUrl = this.config.authOptions?.authUrl || import_constants6.DEFAULT_AUTH_URL;
|
|
3747
3815
|
provider = new EmbeddedProvider({
|
|
3748
3816
|
apiBaseUrl,
|
|
3749
3817
|
appId: this.config.appId,
|
|
@@ -3753,7 +3821,7 @@ var ProviderManager = class {
|
|
|
3753
3821
|
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
|
|
3754
3822
|
},
|
|
3755
3823
|
unstable__auth2Options: this.config.unstable__auth2Options,
|
|
3756
|
-
embeddedWalletType: embeddedWalletType ||
|
|
3824
|
+
embeddedWalletType: embeddedWalletType || import_constants6.DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
3757
3825
|
addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
|
|
3758
3826
|
});
|
|
3759
3827
|
} else {
|
|
@@ -3789,7 +3857,7 @@ var ProviderManager = class {
|
|
|
3789
3857
|
|
|
3790
3858
|
// src/BrowserSDK.ts
|
|
3791
3859
|
var import_embedded_provider_core3 = require("@phantom/embedded-provider-core");
|
|
3792
|
-
var
|
|
3860
|
+
var import_constants7 = require("@phantom/constants");
|
|
3793
3861
|
var BROWSER_SDK_PROVIDER_TYPES = [
|
|
3794
3862
|
...import_embedded_provider_core3.EMBEDDED_PROVIDER_AUTH_TYPES,
|
|
3795
3863
|
"injected",
|
|
@@ -3825,7 +3893,7 @@ var BrowserSDK = class {
|
|
|
3825
3893
|
});
|
|
3826
3894
|
throw new Error("appId is required when using embedded providers (google, apple, phantom, etc.)");
|
|
3827
3895
|
}
|
|
3828
|
-
const embeddedWalletType = config.embeddedWalletType ||
|
|
3896
|
+
const embeddedWalletType = config.embeddedWalletType || import_constants7.DEFAULT_EMBEDDED_WALLET_TYPE;
|
|
3829
3897
|
if (!["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
|
|
3830
3898
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
|
|
3831
3899
|
embeddedWalletType: config.embeddedWalletType
|
|
@@ -4100,6 +4168,7 @@ var BrowserSDK = class {
|
|
|
4100
4168
|
};
|
|
4101
4169
|
|
|
4102
4170
|
// src/index.ts
|
|
4103
|
-
var import_constants7 = require("@phantom/constants");
|
|
4104
|
-
var import_client5 = require("@phantom/client");
|
|
4105
4171
|
var import_constants8 = require("@phantom/constants");
|
|
4172
|
+
var import_client5 = require("@phantom/client");
|
|
4173
|
+
var import_base64url2 = require("@phantom/base64url");
|
|
4174
|
+
var import_constants9 = require("@phantom/constants");
|
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.
|
|
2717
|
+
sdk_version: "1.0.7",
|
|
2718
2718
|
sdk_type: "browser",
|
|
2719
2719
|
platform: detectBrowser().name,
|
|
2720
2720
|
algorithm: phantomOptions.algorithm || DEFAULT_AUTHENTICATOR_ALGORITHM
|
|
@@ -2920,14 +2920,14 @@ var Auth2AuthProvider = class {
|
|
|
2920
2920
|
const description = this.urlParamsAccessor.getParam("error_description");
|
|
2921
2921
|
throw new Error(`Auth2 callback error: ${description ?? error}`);
|
|
2922
2922
|
}
|
|
2923
|
-
const { idToken, bearerToken, authUserId, expiresInMs } = await exchangeAuthCode({
|
|
2923
|
+
const { idToken, bearerToken, authUserId, expiresInMs, refreshToken } = await exchangeAuthCode({
|
|
2924
2924
|
authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
|
|
2925
2925
|
clientId: this.auth2ProviderOptions.clientId,
|
|
2926
2926
|
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2927
2927
|
code,
|
|
2928
2928
|
codeVerifier
|
|
2929
2929
|
});
|
|
2930
|
-
await this.stamper.
|
|
2930
|
+
await this.stamper.setTokens({ idToken, bearerToken, refreshToken, expiresInMs });
|
|
2931
2931
|
await this.storage.saveSession({
|
|
2932
2932
|
...session,
|
|
2933
2933
|
status: "completed",
|
|
@@ -2954,19 +2954,27 @@ var Auth2AuthProvider = class {
|
|
|
2954
2954
|
import bs582 from "bs58";
|
|
2955
2955
|
import { base64urlEncode } from "@phantom/base64url";
|
|
2956
2956
|
import { Algorithm } from "@phantom/sdk-types";
|
|
2957
|
+
import { refreshToken as refreshTokenRequest } from "@phantom/auth2";
|
|
2958
|
+
import { TOKEN_REFRESH_BUFFER_MS } from "@phantom/constants";
|
|
2957
2959
|
var STORE_NAME = "crypto-keys";
|
|
2958
2960
|
var ACTIVE_KEY = "auth2-p256-signing-key";
|
|
2959
2961
|
var Auth2Stamper = class {
|
|
2960
2962
|
/**
|
|
2961
2963
|
* @param dbName - IndexedDB database name (use a unique name per app to
|
|
2962
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.
|
|
2963
2967
|
*/
|
|
2964
|
-
constructor(dbName) {
|
|
2968
|
+
constructor(dbName, refreshConfig) {
|
|
2965
2969
|
this.dbName = dbName;
|
|
2970
|
+
this.refreshConfig = refreshConfig;
|
|
2966
2971
|
this.db = null;
|
|
2967
2972
|
this._keyPair = null;
|
|
2968
2973
|
this._keyInfo = null;
|
|
2969
2974
|
this._idToken = null;
|
|
2975
|
+
this._bearerToken = null;
|
|
2976
|
+
this._refreshToken = null;
|
|
2977
|
+
this._tokenExpiresAt = null;
|
|
2970
2978
|
this.algorithm = Algorithm.secp256r1;
|
|
2971
2979
|
this.type = "OIDC";
|
|
2972
2980
|
}
|
|
@@ -2979,6 +2987,15 @@ var Auth2Stamper = class {
|
|
|
2979
2987
|
if (stored.idToken) {
|
|
2980
2988
|
this._idToken = stored.idToken;
|
|
2981
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
|
+
}
|
|
2982
2999
|
return this._keyInfo;
|
|
2983
3000
|
}
|
|
2984
3001
|
return this.generateAndStore();
|
|
@@ -2990,19 +3007,61 @@ var Auth2Stamper = class {
|
|
|
2990
3007
|
return this._keyPair;
|
|
2991
3008
|
}
|
|
2992
3009
|
/**
|
|
2993
|
-
*
|
|
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.
|
|
2994
3034
|
*
|
|
2995
|
-
* Persists the
|
|
2996
|
-
* auto-connect can restore
|
|
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.
|
|
2997
3042
|
*/
|
|
2998
|
-
async
|
|
3043
|
+
async setTokens({
|
|
3044
|
+
idToken,
|
|
3045
|
+
bearerToken,
|
|
3046
|
+
refreshToken,
|
|
3047
|
+
expiresInMs
|
|
3048
|
+
}) {
|
|
2999
3049
|
if (!this.db) {
|
|
3000
3050
|
await this.openDB();
|
|
3001
3051
|
}
|
|
3002
3052
|
this._idToken = idToken;
|
|
3053
|
+
this._bearerToken = bearerToken;
|
|
3054
|
+
this._refreshToken = refreshToken ?? null;
|
|
3055
|
+
this._tokenExpiresAt = expiresInMs != null ? Date.now() + expiresInMs : null;
|
|
3003
3056
|
const existing = await this.loadRecord();
|
|
3004
3057
|
if (existing) {
|
|
3005
|
-
await this.storeRecord({
|
|
3058
|
+
await this.storeRecord({
|
|
3059
|
+
...existing,
|
|
3060
|
+
idToken,
|
|
3061
|
+
bearerToken,
|
|
3062
|
+
refreshToken,
|
|
3063
|
+
tokenExpiresAt: this._tokenExpiresAt ?? void 0
|
|
3064
|
+
});
|
|
3006
3065
|
}
|
|
3007
3066
|
}
|
|
3008
3067
|
async stamp(params) {
|
|
@@ -3035,6 +3094,9 @@ var Auth2Stamper = class {
|
|
|
3035
3094
|
this._keyPair = null;
|
|
3036
3095
|
this._keyInfo = null;
|
|
3037
3096
|
this._idToken = null;
|
|
3097
|
+
this._bearerToken = null;
|
|
3098
|
+
this._refreshToken = null;
|
|
3099
|
+
this._tokenExpiresAt = null;
|
|
3038
3100
|
}
|
|
3039
3101
|
// Auth2 doesn't use key rotation; provide minimal no-op implementations.
|
|
3040
3102
|
async rotateKeyPair() {
|
|
@@ -3231,17 +3293,17 @@ var BrowserPhantomAppProvider = class {
|
|
|
3231
3293
|
|
|
3232
3294
|
// src/providers/embedded/adapters/logger.ts
|
|
3233
3295
|
var BrowserLogger = class {
|
|
3234
|
-
info(
|
|
3235
|
-
debug.info(
|
|
3296
|
+
info(message, ...args) {
|
|
3297
|
+
debug.info(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3236
3298
|
}
|
|
3237
|
-
warn(
|
|
3238
|
-
debug.warn(
|
|
3299
|
+
warn(message, ...args) {
|
|
3300
|
+
debug.warn(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3239
3301
|
}
|
|
3240
|
-
error(
|
|
3241
|
-
debug.error(
|
|
3302
|
+
error(message, ...args) {
|
|
3303
|
+
debug.error(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3242
3304
|
}
|
|
3243
|
-
|
|
3244
|
-
debug.log(
|
|
3305
|
+
debug(message, ...args) {
|
|
3306
|
+
debug.log(message, args.length > 0 ? String(args[0]) : "", args[1]);
|
|
3245
3307
|
}
|
|
3246
3308
|
};
|
|
3247
3309
|
|
|
@@ -3252,7 +3314,11 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
3252
3314
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
3253
3315
|
const urlParamsAccessor = new BrowserURLParamsAccessor();
|
|
3254
3316
|
const storage = new BrowserStorage();
|
|
3255
|
-
const stamper = config.unstable__auth2Options ? new Auth2Stamper(`phantom-auth2-${config.appId}
|
|
3317
|
+
const stamper = config.unstable__auth2Options ? new Auth2Stamper(`phantom-auth2-${config.appId}`, {
|
|
3318
|
+
authApiBaseUrl: config.unstable__auth2Options.authApiBaseUrl,
|
|
3319
|
+
clientId: config.unstable__auth2Options.clientId,
|
|
3320
|
+
redirectUri: config.authOptions?.redirectUrl ?? ""
|
|
3321
|
+
}) : new IndexedDbStamper({
|
|
3256
3322
|
dbName: `phantom-embedded-sdk-${config.appId}`,
|
|
3257
3323
|
storeName: "crypto-keys",
|
|
3258
3324
|
keyName: "signing-key"
|
|
@@ -3289,7 +3355,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
3289
3355
|
[ANALYTICS_HEADERS.CLIENT]: browserName,
|
|
3290
3356
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
3291
3357
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
3292
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.
|
|
3358
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.7"
|
|
3293
3359
|
// Replaced at build time
|
|
3294
3360
|
}
|
|
3295
3361
|
};
|
|
@@ -4059,6 +4125,7 @@ var BrowserSDK = class {
|
|
|
4059
4125
|
// src/index.ts
|
|
4060
4126
|
import { NetworkId } from "@phantom/constants";
|
|
4061
4127
|
import { AddressType as AddressType4 } from "@phantom/client";
|
|
4128
|
+
import { base64urlEncode as base64urlEncode2, base64urlDecode } from "@phantom/base64url";
|
|
4062
4129
|
import { PHANTOM_ICON as PHANTOM_ICON3 } from "@phantom/constants";
|
|
4063
4130
|
export {
|
|
4064
4131
|
AddressType4 as AddressType,
|
|
@@ -4067,6 +4134,8 @@ export {
|
|
|
4067
4134
|
DebugLevel,
|
|
4068
4135
|
NetworkId,
|
|
4069
4136
|
PHANTOM_ICON3 as PHANTOM_ICON,
|
|
4137
|
+
base64urlDecode,
|
|
4138
|
+
base64urlEncode2 as base64urlEncode,
|
|
4070
4139
|
debug,
|
|
4071
4140
|
detectBrowser,
|
|
4072
4141
|
getBrowserDisplayName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/browser-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
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.
|
|
37
|
-
"@phantom/base64url": "^1.0.
|
|
38
|
-
"@phantom/browser-injected-sdk": "^1.0.
|
|
39
|
-
"@phantom/chain-interfaces": "^1.0.
|
|
40
|
-
"@phantom/client": "^1.0.
|
|
41
|
-
"@phantom/constants": "^1.0.
|
|
42
|
-
"@phantom/embedded-provider-core": "^1.0.
|
|
43
|
-
"@phantom/indexed-db-stamper": "^1.0.
|
|
44
|
-
"@phantom/parsers": "^1.0.
|
|
45
|
-
"@phantom/sdk-types": "^1.0.
|
|
36
|
+
"@phantom/auth2": "^1.0.2",
|
|
37
|
+
"@phantom/base64url": "^1.0.7",
|
|
38
|
+
"@phantom/browser-injected-sdk": "^1.0.7",
|
|
39
|
+
"@phantom/chain-interfaces": "^1.0.7",
|
|
40
|
+
"@phantom/client": "^1.0.7",
|
|
41
|
+
"@phantom/constants": "^1.0.7",
|
|
42
|
+
"@phantom/embedded-provider-core": "^1.0.7",
|
|
43
|
+
"@phantom/indexed-db-stamper": "^1.0.7",
|
|
44
|
+
"@phantom/parsers": "^1.0.7",
|
|
45
|
+
"@phantom/sdk-types": "^1.0.7",
|
|
46
46
|
"axios": "^1.10.0",
|
|
47
47
|
"bs58": "^6.0.0",
|
|
48
48
|
"buffer": "^6.0.3",
|