@phantom/embedded-provider-core 1.0.0-beta.2 → 1.0.0-beta.4
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 +0 -2
- package/dist/index.d.mts +12 -9
- package/dist/index.d.ts +12 -9
- package/dist/index.js +48 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +49 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/embedded-provider.ts
|
|
2
2
|
import { PhantomClient } from "@phantom/client";
|
|
3
|
+
import { randomUUID } from "@phantom/utils";
|
|
3
4
|
import { base64urlEncode } from "@phantom/base64url";
|
|
4
5
|
import bs582 from "bs58";
|
|
5
6
|
import {
|
|
@@ -134,7 +135,7 @@ async function retryWithBackoff(operation, operationName, logger, maxRetries = 3
|
|
|
134
135
|
import { EventEmitter } from "eventemitter3";
|
|
135
136
|
import { NetworkId } from "@phantom/constants";
|
|
136
137
|
import bs58 from "bs58";
|
|
137
|
-
import {
|
|
138
|
+
import { parseSolanaSignedTransaction } from "@phantom/parsers";
|
|
138
139
|
var EmbeddedSolanaChain = class {
|
|
139
140
|
constructor(provider) {
|
|
140
141
|
this.provider = provider;
|
|
@@ -177,8 +178,12 @@ var EmbeddedSolanaChain = class {
|
|
|
177
178
|
transaction,
|
|
178
179
|
networkId: this.currentNetworkId
|
|
179
180
|
});
|
|
180
|
-
const
|
|
181
|
-
|
|
181
|
+
const signedResult = parseSolanaSignedTransaction(result.rawTransaction);
|
|
182
|
+
if (signedResult.transaction && !signedResult.fallback) {
|
|
183
|
+
return signedResult.transaction;
|
|
184
|
+
} else {
|
|
185
|
+
throw new Error("Failed to parse signed transaction");
|
|
186
|
+
}
|
|
182
187
|
}
|
|
183
188
|
async signAndSendTransaction(transaction) {
|
|
184
189
|
this.ensureConnected();
|
|
@@ -195,6 +200,10 @@ var EmbeddedSolanaChain = class {
|
|
|
195
200
|
const results = await Promise.all(transactions.map((tx) => this.signTransaction(tx)));
|
|
196
201
|
return results;
|
|
197
202
|
}
|
|
203
|
+
async signAndSendAllTransactions(transactions) {
|
|
204
|
+
const results = await Promise.all(transactions.map((tx) => this.signAndSendTransaction(tx)));
|
|
205
|
+
return { signatures: results.map((result) => result.signature) };
|
|
206
|
+
}
|
|
198
207
|
connect(_options) {
|
|
199
208
|
if (!this.provider.isConnected()) {
|
|
200
209
|
throw new Error("Provider not connected. Call provider connect first.");
|
|
@@ -466,6 +475,9 @@ var EmbeddedProvider = class {
|
|
|
466
475
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
467
476
|
this.logger = logger;
|
|
468
477
|
this.logger.log("EMBEDDED_PROVIDER", "Initializing EmbeddedProvider", { config });
|
|
478
|
+
if (config.embeddedWalletType === "app-wallet") {
|
|
479
|
+
throw new Error("app-wallet type is not currently supported. Please use 'user-wallet' instead.");
|
|
480
|
+
}
|
|
469
481
|
this.config = config;
|
|
470
482
|
this.platform = platform;
|
|
471
483
|
this.storage = platform.storage;
|
|
@@ -473,7 +485,6 @@ var EmbeddedProvider = class {
|
|
|
473
485
|
this.urlParamsAccessor = platform.urlParamsAccessor;
|
|
474
486
|
this.stamper = platform.stamper;
|
|
475
487
|
this.jwtAuth = new JWTAuth();
|
|
476
|
-
config.solanaProvider;
|
|
477
488
|
this.solana = new EmbeddedSolanaChain(this);
|
|
478
489
|
this.ethereum = new EmbeddedEthereumChain(this);
|
|
479
490
|
this.logger.info("EMBEDDED_PROVIDER", "EmbeddedProvider initialized");
|
|
@@ -740,21 +751,24 @@ var EmbeddedProvider = class {
|
|
|
740
751
|
this.logger.log("EMBEDDED_PROVIDER", "Creating temporary PhantomClient");
|
|
741
752
|
const tempClient = new PhantomClient(
|
|
742
753
|
{
|
|
743
|
-
apiBaseUrl: this.config.apiBaseUrl
|
|
754
|
+
apiBaseUrl: this.config.apiBaseUrl,
|
|
755
|
+
headers: {
|
|
756
|
+
...this.platform.analyticsHeaders || {}
|
|
757
|
+
}
|
|
744
758
|
},
|
|
745
759
|
this.stamper
|
|
746
760
|
);
|
|
747
761
|
const platformName = this.platform.name || "unknown";
|
|
748
762
|
const shortPubKey = stamperInfo.publicKey.slice(0, 8);
|
|
749
|
-
const organizationName = `${this.config.organizationId}-${platformName}-${shortPubKey}`;
|
|
763
|
+
const organizationName = `${this.config.organizationId.substring(0, 8)}-${platformName}-${shortPubKey}`;
|
|
750
764
|
this.logger.log("EMBEDDED_PROVIDER", "Creating organization", {
|
|
751
765
|
organizationName,
|
|
752
766
|
publicKey: stamperInfo.publicKey,
|
|
753
767
|
platform: platformName
|
|
754
768
|
});
|
|
755
769
|
const base64urlPublicKey = base64urlEncode(bs582.decode(stamperInfo.publicKey));
|
|
756
|
-
const
|
|
757
|
-
const username = `user-${
|
|
770
|
+
const expiresInMs = AUTHENTICATOR_EXPIRATION_TIME_MS;
|
|
771
|
+
const username = `user-${randomUUID()}`;
|
|
758
772
|
const { organizationId } = await tempClient.createOrganization(organizationName, [
|
|
759
773
|
{
|
|
760
774
|
username,
|
|
@@ -766,13 +780,13 @@ var EmbeddedProvider = class {
|
|
|
766
780
|
publicKey: base64urlPublicKey,
|
|
767
781
|
algorithm: "Ed25519"
|
|
768
782
|
// Commented for now until KMS supports fully expirable organizations
|
|
769
|
-
//
|
|
783
|
+
// expiresInMs: expiresInMs,
|
|
770
784
|
}
|
|
771
785
|
]
|
|
772
786
|
}
|
|
773
787
|
]);
|
|
774
788
|
this.logger.info("EMBEDDED_PROVIDER", "Organization created", { organizationId });
|
|
775
|
-
return { organizationId, stamperInfo,
|
|
789
|
+
return { organizationId, stamperInfo, expiresInMs, username };
|
|
776
790
|
}
|
|
777
791
|
async connect(authOptions) {
|
|
778
792
|
try {
|
|
@@ -801,8 +815,8 @@ var EmbeddedProvider = class {
|
|
|
801
815
|
}
|
|
802
816
|
this.validateAuthOptions(authOptions);
|
|
803
817
|
this.logger.info("EMBEDDED_PROVIDER", "No existing connection, creating new auth flow");
|
|
804
|
-
const { organizationId, stamperInfo,
|
|
805
|
-
const session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions,
|
|
818
|
+
const { organizationId, stamperInfo, expiresInMs, username } = await this.createOrganizationAndStamper();
|
|
819
|
+
const session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions, expiresInMs, username);
|
|
806
820
|
if (!session) {
|
|
807
821
|
return {
|
|
808
822
|
addresses: [],
|
|
@@ -972,13 +986,13 @@ var EmbeddedProvider = class {
|
|
|
972
986
|
* It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.
|
|
973
987
|
* Returns null for redirect flows since they don't complete synchronously.
|
|
974
988
|
*/
|
|
975
|
-
async handleAuthFlow(organizationId, stamperInfo, authOptions,
|
|
989
|
+
async handleAuthFlow(organizationId, stamperInfo, authOptions, expiresInMs, username) {
|
|
976
990
|
if (this.config.embeddedWalletType === "user-wallet") {
|
|
977
991
|
this.logger.info("EMBEDDED_PROVIDER", "Creating user-wallet, routing authentication", {
|
|
978
992
|
authProvider: authOptions?.provider || "phantom-connect"
|
|
979
993
|
});
|
|
980
994
|
if (authOptions?.provider === "jwt") {
|
|
981
|
-
return await this.handleJWTAuth(organizationId, stamperInfo, authOptions,
|
|
995
|
+
return await this.handleJWTAuth(organizationId, stamperInfo, authOptions, expiresInMs, username);
|
|
982
996
|
} else {
|
|
983
997
|
this.logger.info("EMBEDDED_PROVIDER", "Starting redirect-based authentication flow", {
|
|
984
998
|
organizationId,
|
|
@@ -994,7 +1008,10 @@ var EmbeddedProvider = class {
|
|
|
994
1008
|
const tempClient = new PhantomClient(
|
|
995
1009
|
{
|
|
996
1010
|
apiBaseUrl: this.config.apiBaseUrl,
|
|
997
|
-
organizationId
|
|
1011
|
+
organizationId,
|
|
1012
|
+
headers: {
|
|
1013
|
+
...this.platform.analyticsHeaders || {}
|
|
1014
|
+
}
|
|
998
1015
|
},
|
|
999
1016
|
this.stamper
|
|
1000
1017
|
);
|
|
@@ -1015,7 +1032,7 @@ var EmbeddedProvider = class {
|
|
|
1015
1032
|
createdAt: now,
|
|
1016
1033
|
lastUsed: now,
|
|
1017
1034
|
authenticatorCreatedAt: now,
|
|
1018
|
-
authenticatorExpiresAt:
|
|
1035
|
+
authenticatorExpiresAt: Date.now() + expiresInMs,
|
|
1019
1036
|
lastRenewalAttempt: void 0,
|
|
1020
1037
|
username
|
|
1021
1038
|
};
|
|
@@ -1028,7 +1045,7 @@ var EmbeddedProvider = class {
|
|
|
1028
1045
|
* We use this method to handle JWT-based authentication for user-wallets.
|
|
1029
1046
|
* It authenticates using the provided JWT token and creates a completed session.
|
|
1030
1047
|
*/
|
|
1031
|
-
async handleJWTAuth(organizationId, stamperInfo, authOptions,
|
|
1048
|
+
async handleJWTAuth(organizationId, stamperInfo, authOptions, expiresInMs, username) {
|
|
1032
1049
|
this.logger.info("EMBEDDED_PROVIDER", "Using JWT authentication flow");
|
|
1033
1050
|
if (!authOptions.jwtToken) {
|
|
1034
1051
|
this.logger.error("EMBEDDED_PROVIDER", "JWT token missing for JWT authentication");
|
|
@@ -1058,7 +1075,7 @@ var EmbeddedProvider = class {
|
|
|
1058
1075
|
createdAt: now,
|
|
1059
1076
|
lastUsed: now,
|
|
1060
1077
|
authenticatorCreatedAt: now,
|
|
1061
|
-
authenticatorExpiresAt:
|
|
1078
|
+
authenticatorExpiresAt: Date.now() + expiresInMs,
|
|
1062
1079
|
lastRenewalAttempt: void 0,
|
|
1063
1080
|
username
|
|
1064
1081
|
};
|
|
@@ -1074,8 +1091,8 @@ var EmbeddedProvider = class {
|
|
|
1074
1091
|
async handleRedirectAuth(organizationId, stamperInfo, authOptions, username) {
|
|
1075
1092
|
this.logger.info("EMBEDDED_PROVIDER", "Using Phantom Connect authentication flow (redirect-based)", {
|
|
1076
1093
|
provider: authOptions?.provider,
|
|
1077
|
-
hasRedirectUrl: !!this.config.authOptions
|
|
1078
|
-
authUrl: this.config.authOptions
|
|
1094
|
+
hasRedirectUrl: !!this.config.authOptions.redirectUrl,
|
|
1095
|
+
authUrl: this.config.authOptions.authUrl
|
|
1079
1096
|
});
|
|
1080
1097
|
const now = Date.now();
|
|
1081
1098
|
const sessionId = generateSessionId();
|
|
@@ -1096,7 +1113,7 @@ var EmbeddedProvider = class {
|
|
|
1096
1113
|
authenticatorCreatedAt: now,
|
|
1097
1114
|
authenticatorExpiresAt: now + AUTHENTICATOR_EXPIRATION_TIME_MS,
|
|
1098
1115
|
lastRenewalAttempt: void 0,
|
|
1099
|
-
username: username || `user-${
|
|
1116
|
+
username: username || `user-${randomUUID()}`
|
|
1100
1117
|
};
|
|
1101
1118
|
this.logger.log("EMBEDDED_PROVIDER", "Saving temporary session before redirect", {
|
|
1102
1119
|
sessionId: tempSession.sessionId,
|
|
@@ -1109,16 +1126,16 @@ var EmbeddedProvider = class {
|
|
|
1109
1126
|
parentOrganizationId: this.config.organizationId,
|
|
1110
1127
|
appId: this.config.appId,
|
|
1111
1128
|
provider: authOptions?.provider,
|
|
1112
|
-
authUrl: this.config.authOptions
|
|
1129
|
+
authUrl: this.config.authOptions.authUrl
|
|
1113
1130
|
});
|
|
1114
1131
|
const authResult = await this.authProvider.authenticate({
|
|
1115
1132
|
organizationId,
|
|
1116
1133
|
appId: this.config.appId,
|
|
1117
1134
|
parentOrganizationId: this.config.organizationId,
|
|
1118
1135
|
provider: authOptions?.provider,
|
|
1119
|
-
redirectUrl: this.config.authOptions
|
|
1136
|
+
redirectUrl: this.config.authOptions.redirectUrl,
|
|
1120
1137
|
customAuthData: authOptions?.customAuthData,
|
|
1121
|
-
authUrl: this.config.authOptions
|
|
1138
|
+
authUrl: this.config.authOptions.authUrl,
|
|
1122
1139
|
sessionId
|
|
1123
1140
|
});
|
|
1124
1141
|
if (authResult && "walletId" in authResult) {
|
|
@@ -1214,7 +1231,7 @@ var EmbeddedProvider = class {
|
|
|
1214
1231
|
newPublicKey: newKeyInfo.publicKey
|
|
1215
1232
|
});
|
|
1216
1233
|
const base64urlPublicKey = base64urlEncode(bs582.decode(newKeyInfo.publicKey));
|
|
1217
|
-
const
|
|
1234
|
+
const expiresInMs = AUTHENTICATOR_EXPIRATION_TIME_MS;
|
|
1218
1235
|
let authenticatorResult;
|
|
1219
1236
|
try {
|
|
1220
1237
|
authenticatorResult = await this.client.createAuthenticator({
|
|
@@ -1227,7 +1244,7 @@ var EmbeddedProvider = class {
|
|
|
1227
1244
|
publicKey: base64urlPublicKey,
|
|
1228
1245
|
algorithm: "Ed25519"
|
|
1229
1246
|
// Commented for now until KMS supports fully expiring organizations
|
|
1230
|
-
//
|
|
1247
|
+
// expiresInMs: expiresInMs,
|
|
1231
1248
|
},
|
|
1232
1249
|
replaceExpirable: true
|
|
1233
1250
|
});
|
|
@@ -1247,12 +1264,12 @@ var EmbeddedProvider = class {
|
|
|
1247
1264
|
const now = Date.now();
|
|
1248
1265
|
session.stamperInfo = newKeyInfo;
|
|
1249
1266
|
session.authenticatorCreatedAt = now;
|
|
1250
|
-
session.authenticatorExpiresAt =
|
|
1267
|
+
session.authenticatorExpiresAt = Date.now() + expiresInMs;
|
|
1251
1268
|
session.lastRenewalAttempt = now;
|
|
1252
1269
|
await this.storage.saveSession(session);
|
|
1253
1270
|
this.logger.info("EMBEDDED_PROVIDER", "Authenticator renewal completed successfully", {
|
|
1254
1271
|
newKeyId: newKeyInfo.keyId,
|
|
1255
|
-
expiresAt: new Date(
|
|
1272
|
+
expiresAt: new Date(Date.now() + expiresInMs).toISOString()
|
|
1256
1273
|
});
|
|
1257
1274
|
} catch (error) {
|
|
1258
1275
|
await this.stamper.rollbackRotation();
|
|
@@ -1275,7 +1292,10 @@ var EmbeddedProvider = class {
|
|
|
1275
1292
|
this.client = new PhantomClient(
|
|
1276
1293
|
{
|
|
1277
1294
|
apiBaseUrl: this.config.apiBaseUrl,
|
|
1278
|
-
organizationId: session.organizationId
|
|
1295
|
+
organizationId: session.organizationId,
|
|
1296
|
+
headers: {
|
|
1297
|
+
...this.platform.analyticsHeaders || {}
|
|
1298
|
+
}
|
|
1279
1299
|
},
|
|
1280
1300
|
this.stamper
|
|
1281
1301
|
);
|