@phantom/embedded-provider-core 1.0.0-beta.21 → 1.0.0-beta.24
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 +3 -3
- package/dist/index.d.mts +56 -69
- package/dist/index.d.ts +56 -69
- package/dist/index.js +37 -159
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -158
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -9
package/dist/index.js
CHANGED
|
@@ -32,10 +32,10 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
AUTHENTICATOR_EXPIRATION_TIME_MS: () => AUTHENTICATOR_EXPIRATION_TIME_MS,
|
|
34
34
|
AUTHENTICATOR_RENEWAL_WINDOW_MS: () => AUTHENTICATOR_RENEWAL_WINDOW_MS,
|
|
35
|
+
EMBEDDED_PROVIDER_AUTH_TYPES: () => EMBEDDED_PROVIDER_AUTH_TYPES,
|
|
35
36
|
EmbeddedEthereumChain: () => EmbeddedEthereumChain,
|
|
36
37
|
EmbeddedProvider: () => EmbeddedProvider,
|
|
37
38
|
EmbeddedSolanaChain: () => EmbeddedSolanaChain,
|
|
38
|
-
JWTAuth: () => JWTAuth,
|
|
39
39
|
generateSessionId: () => generateSessionId,
|
|
40
40
|
retryWithBackoff: () => retryWithBackoff
|
|
41
41
|
});
|
|
@@ -52,91 +52,7 @@ var import_bs582 = __toESM(require("bs58"));
|
|
|
52
52
|
// src/constants.ts
|
|
53
53
|
var AUTHENTICATOR_EXPIRATION_TIME_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
54
54
|
var AUTHENTICATOR_RENEWAL_WINDOW_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
55
|
-
|
|
56
|
-
// src/auth/jwt-auth.ts
|
|
57
|
-
var JWTAuth = class {
|
|
58
|
-
async authenticate(options) {
|
|
59
|
-
if (!options.jwtToken || typeof options.jwtToken !== "string") {
|
|
60
|
-
throw new Error("Invalid JWT token: token must be a non-empty string");
|
|
61
|
-
}
|
|
62
|
-
const jwtParts = options.jwtToken.split(".");
|
|
63
|
-
if (jwtParts.length !== 3) {
|
|
64
|
-
throw new Error("Invalid JWT token format: token must have 3 parts separated by dots");
|
|
65
|
-
}
|
|
66
|
-
try {
|
|
67
|
-
const response = await fetch("/api/auth/jwt", {
|
|
68
|
-
method: "POST",
|
|
69
|
-
headers: {
|
|
70
|
-
"Content-Type": "application/json",
|
|
71
|
-
Authorization: `Bearer ${options.jwtToken}`,
|
|
72
|
-
"X-PHANTOM-APPID": options.appId
|
|
73
|
-
},
|
|
74
|
-
body: JSON.stringify({
|
|
75
|
-
appId: options.appId,
|
|
76
|
-
publicKey: options.publicKey
|
|
77
|
-
})
|
|
78
|
-
});
|
|
79
|
-
if (!response.ok) {
|
|
80
|
-
let errorMessage = `HTTP ${response.status}`;
|
|
81
|
-
try {
|
|
82
|
-
const errorData = await response.json();
|
|
83
|
-
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
84
|
-
} catch {
|
|
85
|
-
errorMessage = response.statusText || errorMessage;
|
|
86
|
-
}
|
|
87
|
-
switch (response.status) {
|
|
88
|
-
case 400:
|
|
89
|
-
throw new Error(`Invalid JWT authentication request: ${errorMessage}`);
|
|
90
|
-
case 401:
|
|
91
|
-
throw new Error(`JWT token is invalid or expired: ${errorMessage}`);
|
|
92
|
-
case 403:
|
|
93
|
-
throw new Error(`JWT authentication forbidden: ${errorMessage}`);
|
|
94
|
-
case 404:
|
|
95
|
-
throw new Error(`JWT authentication endpoint not found: ${errorMessage}`);
|
|
96
|
-
case 429:
|
|
97
|
-
throw new Error(`Too many JWT authentication requests: ${errorMessage}`);
|
|
98
|
-
case 500:
|
|
99
|
-
case 502:
|
|
100
|
-
case 503:
|
|
101
|
-
case 504:
|
|
102
|
-
throw new Error(`JWT authentication server error: ${errorMessage}`);
|
|
103
|
-
default:
|
|
104
|
-
throw new Error(`JWT authentication failed: ${errorMessage}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
let result;
|
|
108
|
-
try {
|
|
109
|
-
result = await response.json();
|
|
110
|
-
} catch (parseError) {
|
|
111
|
-
throw new Error("Invalid response from JWT authentication server: response is not valid JSON");
|
|
112
|
-
}
|
|
113
|
-
if (!result.walletId) {
|
|
114
|
-
throw new Error("Invalid JWT authentication response: missing walletId");
|
|
115
|
-
}
|
|
116
|
-
if (!result.organizationId) {
|
|
117
|
-
throw new Error("Invalid JWT authentication response: missing organizationId");
|
|
118
|
-
}
|
|
119
|
-
if (!result.expiresInMs) {
|
|
120
|
-
throw new Error("Invalid JWT authentication response: missing expiresInMs");
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
walletId: result.walletId,
|
|
124
|
-
organizationId: result.organizationId,
|
|
125
|
-
provider: "jwt",
|
|
126
|
-
expiresInMs: result.expiresInMs,
|
|
127
|
-
accountDerivationIndex: result.accountDerivationIndex || 0
|
|
128
|
-
};
|
|
129
|
-
} catch (error) {
|
|
130
|
-
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
131
|
-
throw new Error("JWT authentication failed: network error or invalid endpoint");
|
|
132
|
-
}
|
|
133
|
-
if (error instanceof Error) {
|
|
134
|
-
throw error;
|
|
135
|
-
}
|
|
136
|
-
throw new Error(`JWT authentication error: ${String(error)}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
};
|
|
55
|
+
var EMBEDDED_PROVIDER_AUTH_TYPES = ["google", "apple", "x", "phantom", "tiktok"];
|
|
140
56
|
|
|
141
57
|
// src/chains/SolanaChain.ts
|
|
142
58
|
var import_eventemitter3 = require("eventemitter3");
|
|
@@ -536,7 +452,6 @@ var EmbeddedProvider = class {
|
|
|
536
452
|
this.phantomAppProvider = platform.phantomAppProvider;
|
|
537
453
|
this.urlParamsAccessor = platform.urlParamsAccessor;
|
|
538
454
|
this.stamper = platform.stamper;
|
|
539
|
-
this.jwtAuth = new JWTAuth();
|
|
540
455
|
this.solana = new EmbeddedSolanaChain(this);
|
|
541
456
|
this.ethereum = new EmbeddedEthereumChain(this);
|
|
542
457
|
this.logger.info("EMBEDDED_PROVIDER", "EmbeddedProvider initialized");
|
|
@@ -677,7 +592,11 @@ var EmbeddedProvider = class {
|
|
|
677
592
|
this.logger.log("EMBEDDED_PROVIDER", "Getting existing session");
|
|
678
593
|
let session = await this.storage.getSession();
|
|
679
594
|
session = await this.validateAndCleanSession(session);
|
|
680
|
-
if (session
|
|
595
|
+
if (!session) {
|
|
596
|
+
this.logger.log("EMBEDDED_PROVIDER", "No existing session found");
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
if (session.status === "completed") {
|
|
681
600
|
this.logger.info("EMBEDDED_PROVIDER", "Using existing completed session", {
|
|
682
601
|
sessionId: session.sessionId,
|
|
683
602
|
walletId: session.walletId
|
|
@@ -694,8 +613,8 @@ var EmbeddedProvider = class {
|
|
|
694
613
|
walletId: this.walletId,
|
|
695
614
|
addresses: this.addresses,
|
|
696
615
|
status: "completed",
|
|
697
|
-
|
|
698
|
-
|
|
616
|
+
authUserId: session.authUserId,
|
|
617
|
+
authProvider: session.authProvider
|
|
699
618
|
};
|
|
700
619
|
this.emit("connect", {
|
|
701
620
|
...result,
|
|
@@ -705,7 +624,7 @@ var EmbeddedProvider = class {
|
|
|
705
624
|
}
|
|
706
625
|
this.logger.log("EMBEDDED_PROVIDER", "No completed session found, checking for redirect resume");
|
|
707
626
|
if (this.authProvider.resumeAuthFromRedirect) {
|
|
708
|
-
const authResult = this.authProvider.resumeAuthFromRedirect();
|
|
627
|
+
const authResult = this.authProvider.resumeAuthFromRedirect(session.authProvider);
|
|
709
628
|
if (authResult) {
|
|
710
629
|
this.logger.info("EMBEDDED_PROVIDER", "Resuming from redirect", {
|
|
711
630
|
walletId: authResult.walletId,
|
|
@@ -737,11 +656,10 @@ var EmbeddedProvider = class {
|
|
|
737
656
|
* This ensures only supported auth providers are used and required tokens are present.
|
|
738
657
|
*/
|
|
739
658
|
validateAuthOptions(authOptions) {
|
|
740
|
-
if (!
|
|
741
|
-
throw new Error(
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
throw new Error("JWT token is required when using JWT authentication");
|
|
659
|
+
if (!EMBEDDED_PROVIDER_AUTH_TYPES.includes(authOptions.provider)) {
|
|
660
|
+
throw new Error(
|
|
661
|
+
`Invalid auth provider: ${authOptions.provider}. Must be "google", "apple", "phantom", "tiktok", or "x"`
|
|
662
|
+
);
|
|
745
663
|
}
|
|
746
664
|
}
|
|
747
665
|
/*
|
|
@@ -881,8 +799,7 @@ var EmbeddedProvider = class {
|
|
|
881
799
|
try {
|
|
882
800
|
this.logger.info("EMBEDDED_PROVIDER", "Starting embedded provider connect", {
|
|
883
801
|
authOptions: {
|
|
884
|
-
provider: authOptions.provider
|
|
885
|
-
hasJwtToken: !!authOptions.jwtToken
|
|
802
|
+
provider: authOptions.provider
|
|
886
803
|
}
|
|
887
804
|
});
|
|
888
805
|
this.emit("connect_start", {
|
|
@@ -912,10 +829,10 @@ var EmbeddedProvider = class {
|
|
|
912
829
|
return {
|
|
913
830
|
addresses: [],
|
|
914
831
|
status: "pending",
|
|
915
|
-
|
|
832
|
+
authProvider: authOptions.provider
|
|
916
833
|
};
|
|
917
834
|
}
|
|
918
|
-
if (
|
|
835
|
+
if (this.config.embeddedWalletType === "app-wallet") {
|
|
919
836
|
session.lastUsed = Date.now();
|
|
920
837
|
await this.storage.saveSession(session);
|
|
921
838
|
}
|
|
@@ -925,8 +842,8 @@ var EmbeddedProvider = class {
|
|
|
925
842
|
walletId: this.walletId,
|
|
926
843
|
addresses: this.addresses,
|
|
927
844
|
status: "completed",
|
|
928
|
-
|
|
929
|
-
|
|
845
|
+
authUserId: session?.authUserId,
|
|
846
|
+
authProvider: session?.authProvider
|
|
930
847
|
};
|
|
931
848
|
this.emit("connect", {
|
|
932
849
|
...result,
|
|
@@ -994,12 +911,11 @@ var EmbeddedProvider = class {
|
|
|
994
911
|
walletId: this.walletId,
|
|
995
912
|
message: params.message
|
|
996
913
|
});
|
|
997
|
-
const base64UrlMessage = (0, import_base64url.stringToBase64url)(params.message);
|
|
998
914
|
const session = await this.storage.getSession();
|
|
999
915
|
const derivationIndex = session?.accountDerivationIndex ?? 0;
|
|
1000
|
-
const rawResponse = await this.client.
|
|
916
|
+
const rawResponse = await this.client.signUtf8Message({
|
|
1001
917
|
walletId: this.walletId,
|
|
1002
|
-
message:
|
|
918
|
+
message: params.message,
|
|
1003
919
|
networkId: params.networkId,
|
|
1004
920
|
derivationIndex
|
|
1005
921
|
});
|
|
@@ -1085,12 +1001,16 @@ var EmbeddedProvider = class {
|
|
|
1085
1001
|
if (!transactionPayload) {
|
|
1086
1002
|
throw new Error("Failed to parse transaction: no valid encoding found");
|
|
1087
1003
|
}
|
|
1004
|
+
const account = this.getAddressForNetwork(params.networkId);
|
|
1005
|
+
if (!account) {
|
|
1006
|
+
throw new Error(`No address found for network ${params.networkId}`);
|
|
1007
|
+
}
|
|
1088
1008
|
const rawResponse = await this.client.signTransaction({
|
|
1089
1009
|
walletId: this.walletId,
|
|
1090
1010
|
transaction: transactionPayload,
|
|
1091
1011
|
networkId: params.networkId,
|
|
1092
1012
|
derivationIndex,
|
|
1093
|
-
account
|
|
1013
|
+
account
|
|
1094
1014
|
});
|
|
1095
1015
|
this.logger.info("EMBEDDED_PROVIDER", "Transaction signed successfully", {
|
|
1096
1016
|
walletId: this.walletId,
|
|
@@ -1120,12 +1040,16 @@ var EmbeddedProvider = class {
|
|
|
1120
1040
|
if (!transactionPayload) {
|
|
1121
1041
|
throw new Error("Failed to parse transaction: no valid encoding found");
|
|
1122
1042
|
}
|
|
1043
|
+
const account = this.getAddressForNetwork(params.networkId);
|
|
1044
|
+
if (!account) {
|
|
1045
|
+
throw new Error(`No address found for network ${params.networkId}`);
|
|
1046
|
+
}
|
|
1123
1047
|
const rawResponse = await this.client.signAndSendTransaction({
|
|
1124
1048
|
walletId: this.walletId,
|
|
1125
1049
|
transaction: transactionPayload,
|
|
1126
1050
|
networkId: params.networkId,
|
|
1127
1051
|
derivationIndex,
|
|
1128
|
-
account
|
|
1052
|
+
account
|
|
1129
1053
|
});
|
|
1130
1054
|
this.logger.info("EMBEDDED_PROVIDER", "Transaction signed and sent successfully", {
|
|
1131
1055
|
walletId: this.walletId,
|
|
@@ -1151,9 +1075,7 @@ var EmbeddedProvider = class {
|
|
|
1151
1075
|
this.logger.info("EMBEDDED_PROVIDER", "Creating user-wallet, routing authentication", {
|
|
1152
1076
|
authProvider: authOptions.provider
|
|
1153
1077
|
});
|
|
1154
|
-
if (authOptions.provider === "
|
|
1155
|
-
return await this.handleJWTAuth(publicKey, stamperInfo, authOptions, expiresInMs);
|
|
1156
|
-
} else if (authOptions.provider === "phantom") {
|
|
1078
|
+
if (authOptions.provider === "phantom") {
|
|
1157
1079
|
return await this.handlePhantomAuth(publicKey, stamperInfo, expiresInMs);
|
|
1158
1080
|
} else {
|
|
1159
1081
|
this.logger.info("EMBEDDED_PROVIDER", "Starting redirect-based authentication flow", {
|
|
@@ -1186,7 +1108,8 @@ var EmbeddedProvider = class {
|
|
|
1186
1108
|
organizationId,
|
|
1187
1109
|
appId: this.config.appId,
|
|
1188
1110
|
stamperInfo,
|
|
1189
|
-
authProvider: "
|
|
1111
|
+
authProvider: "device",
|
|
1112
|
+
// For now app wallets have no auth provider.
|
|
1190
1113
|
accountDerivationIndex: 0,
|
|
1191
1114
|
// App wallets default to index 0
|
|
1192
1115
|
status: "completed",
|
|
@@ -1201,51 +1124,6 @@ var EmbeddedProvider = class {
|
|
|
1201
1124
|
return session;
|
|
1202
1125
|
}
|
|
1203
1126
|
}
|
|
1204
|
-
/*
|
|
1205
|
-
* We use this method to handle JWT-based authentication for user-wallets.
|
|
1206
|
-
* It authenticates using the provided JWT token and creates a completed session.
|
|
1207
|
-
*/
|
|
1208
|
-
async handleJWTAuth(publicKey, stamperInfo, authOptions, localExpiresInMs) {
|
|
1209
|
-
this.logger.info("EMBEDDED_PROVIDER", "Using JWT authentication flow");
|
|
1210
|
-
if (!authOptions.jwtToken) {
|
|
1211
|
-
this.logger.error("EMBEDDED_PROVIDER", "JWT token missing for JWT authentication");
|
|
1212
|
-
throw new Error("JWT token is required for JWT authentication");
|
|
1213
|
-
}
|
|
1214
|
-
this.logger.log("EMBEDDED_PROVIDER", "Starting JWT authentication");
|
|
1215
|
-
const authResult = await this.jwtAuth.authenticate({
|
|
1216
|
-
publicKey,
|
|
1217
|
-
appId: this.config.appId,
|
|
1218
|
-
jwtToken: authOptions.jwtToken
|
|
1219
|
-
});
|
|
1220
|
-
const walletId = authResult.walletId;
|
|
1221
|
-
const organizationId = authResult.organizationId;
|
|
1222
|
-
const expiresInMs = authResult.expiresInMs > 0 ? authResult.expiresInMs : localExpiresInMs;
|
|
1223
|
-
this.logger.info("EMBEDDED_PROVIDER", "JWT authentication completed", {
|
|
1224
|
-
walletId,
|
|
1225
|
-
organizationId,
|
|
1226
|
-
expiresInMs,
|
|
1227
|
-
source: authResult.expiresInMs ? "server" : "local"
|
|
1228
|
-
});
|
|
1229
|
-
const now = Date.now();
|
|
1230
|
-
const session = {
|
|
1231
|
-
sessionId: generateSessionId(),
|
|
1232
|
-
walletId,
|
|
1233
|
-
organizationId,
|
|
1234
|
-
appId: this.config.appId,
|
|
1235
|
-
stamperInfo,
|
|
1236
|
-
authProvider: authResult.provider,
|
|
1237
|
-
accountDerivationIndex: authResult.accountDerivationIndex,
|
|
1238
|
-
status: "completed",
|
|
1239
|
-
createdAt: now,
|
|
1240
|
-
lastUsed: now,
|
|
1241
|
-
authenticatorCreatedAt: now,
|
|
1242
|
-
authenticatorExpiresAt: Date.now() + expiresInMs,
|
|
1243
|
-
lastRenewalAttempt: void 0
|
|
1244
|
-
};
|
|
1245
|
-
this.logger.log("EMBEDDED_PROVIDER", "Saving JWT session");
|
|
1246
|
-
await this.storage.saveSession(session);
|
|
1247
|
-
return session;
|
|
1248
|
-
}
|
|
1249
1127
|
/*
|
|
1250
1128
|
* We use this method to handle Phantom app-based authentication for user-wallets.
|
|
1251
1129
|
* This method uses the PhantomAppProvider to authenticate via the browser extension or mobile app.
|
|
@@ -1419,8 +1297,8 @@ var EmbeddedProvider = class {
|
|
|
1419
1297
|
walletId: this.walletId,
|
|
1420
1298
|
addresses: this.addresses,
|
|
1421
1299
|
status: "completed",
|
|
1422
|
-
|
|
1423
|
-
|
|
1300
|
+
authUserId: session.authUserId,
|
|
1301
|
+
authProvider: session.authProvider
|
|
1424
1302
|
};
|
|
1425
1303
|
}
|
|
1426
1304
|
/*
|
|
@@ -1480,10 +1358,10 @@ var EmbeddedProvider = class {
|
|
|
1480
1358
|
0 && (module.exports = {
|
|
1481
1359
|
AUTHENTICATOR_EXPIRATION_TIME_MS,
|
|
1482
1360
|
AUTHENTICATOR_RENEWAL_WINDOW_MS,
|
|
1361
|
+
EMBEDDED_PROVIDER_AUTH_TYPES,
|
|
1483
1362
|
EmbeddedEthereumChain,
|
|
1484
1363
|
EmbeddedProvider,
|
|
1485
1364
|
EmbeddedSolanaChain,
|
|
1486
|
-
JWTAuth,
|
|
1487
1365
|
generateSessionId,
|
|
1488
1366
|
retryWithBackoff
|
|
1489
1367
|
});
|