@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 CHANGED
@@ -60,7 +60,6 @@ const config: EmbeddedProviderConfig = {
60
60
  appId: "your-app-id",
61
61
  embeddedWalletType: "user-wallet", // or 'app-wallet'
62
62
  addressTypes: ["solana", "ethereum"],
63
- solanaProvider: "web3js",
64
63
  authOptions: {
65
64
  authUrl: "https://auth.phantom.app",
66
65
  redirectUrl: "https://your-app.com/callback",
@@ -276,7 +275,6 @@ interface EmbeddedProviderConfig {
276
275
  addressTypes: [AddressType, ...AddressType[]]; // Supported blockchain addresses
277
276
 
278
277
  // Optional
279
- solanaProvider?: "web3js" | "kit"; // Solana library preference
280
278
  authOptions?: {
281
279
  authUrl?: string; // Custom auth URL
282
280
  redirectUrl?: string; // OAuth redirect URL
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { StamperWithKeyManagement } from '@phantom/sdk-types';
1
+ import { StamperWithKeyManagement, Transaction, VersionedTransaction } from '@phantom/sdk-types';
2
+ import { ClientSideSdkHeaders, NetworkId } from '@phantom/constants';
2
3
  import { AddressType } from '@phantom/client';
3
- import { NetworkId } from '@phantom/constants';
4
4
  import { ParsedSignatureResult, ParsedTransactionResult } from '@phantom/parsers';
5
5
  import { ISolanaChain, IEthereumChain, EthTransactionRequest } from '@phantom/chains';
6
6
 
@@ -92,6 +92,7 @@ interface PlatformAdapter {
92
92
  authProvider: AuthProvider;
93
93
  urlParamsAccessor: URLParamsAccessor;
94
94
  stamper: StamperWithKeyManagement;
95
+ analyticsHeaders?: Partial<ClientSideSdkHeaders>;
95
96
  }
96
97
  interface DebugLogger {
97
98
  info(category: string, message: string, data?: any): void;
@@ -134,13 +135,12 @@ interface EmbeddedProviderConfig {
134
135
  apiBaseUrl: string;
135
136
  appId: string;
136
137
  organizationId: string;
137
- authOptions?: {
138
- authUrl?: string;
139
- redirectUrl?: string;
138
+ authOptions: {
139
+ authUrl: string;
140
+ redirectUrl: string;
140
141
  };
141
142
  embeddedWalletType: "app-wallet" | "user-wallet" | (string & Record<never, never>);
142
143
  addressTypes: [AddressType, ...AddressType[]];
143
- solanaProvider: "web3js" | "kit" | (string & Record<never, never>);
144
144
  }
145
145
 
146
146
  type EmbeddedProviderEvent = "connect" | "connect_start" | "connect_error" | "disconnect" | "error";
@@ -212,11 +212,14 @@ declare class EmbeddedSolanaChain implements ISolanaChain {
212
212
  signature: Uint8Array;
213
213
  publicKey: string;
214
214
  }>;
215
- signTransaction<T>(transaction: T): Promise<T>;
216
- signAndSendTransaction<T>(transaction: T): Promise<{
215
+ signTransaction(transaction: Transaction | VersionedTransaction): Promise<Transaction | VersionedTransaction>;
216
+ signAndSendTransaction(transaction: Transaction | VersionedTransaction): Promise<{
217
217
  signature: string;
218
218
  }>;
219
- signAllTransactions<T>(transactions: T[]): Promise<T[]>;
219
+ signAllTransactions(transactions: (Transaction | VersionedTransaction)[]): Promise<(Transaction | VersionedTransaction)[]>;
220
+ signAndSendAllTransactions(transactions: (Transaction | VersionedTransaction)[]): Promise<{
221
+ signatures: string[];
222
+ }>;
220
223
  connect(_options?: {
221
224
  onlyIfTrusted?: boolean;
222
225
  }): Promise<{
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { StamperWithKeyManagement } from '@phantom/sdk-types';
1
+ import { StamperWithKeyManagement, Transaction, VersionedTransaction } from '@phantom/sdk-types';
2
+ import { ClientSideSdkHeaders, NetworkId } from '@phantom/constants';
2
3
  import { AddressType } from '@phantom/client';
3
- import { NetworkId } from '@phantom/constants';
4
4
  import { ParsedSignatureResult, ParsedTransactionResult } from '@phantom/parsers';
5
5
  import { ISolanaChain, IEthereumChain, EthTransactionRequest } from '@phantom/chains';
6
6
 
@@ -92,6 +92,7 @@ interface PlatformAdapter {
92
92
  authProvider: AuthProvider;
93
93
  urlParamsAccessor: URLParamsAccessor;
94
94
  stamper: StamperWithKeyManagement;
95
+ analyticsHeaders?: Partial<ClientSideSdkHeaders>;
95
96
  }
96
97
  interface DebugLogger {
97
98
  info(category: string, message: string, data?: any): void;
@@ -134,13 +135,12 @@ interface EmbeddedProviderConfig {
134
135
  apiBaseUrl: string;
135
136
  appId: string;
136
137
  organizationId: string;
137
- authOptions?: {
138
- authUrl?: string;
139
- redirectUrl?: string;
138
+ authOptions: {
139
+ authUrl: string;
140
+ redirectUrl: string;
140
141
  };
141
142
  embeddedWalletType: "app-wallet" | "user-wallet" | (string & Record<never, never>);
142
143
  addressTypes: [AddressType, ...AddressType[]];
143
- solanaProvider: "web3js" | "kit" | (string & Record<never, never>);
144
144
  }
145
145
 
146
146
  type EmbeddedProviderEvent = "connect" | "connect_start" | "connect_error" | "disconnect" | "error";
@@ -212,11 +212,14 @@ declare class EmbeddedSolanaChain implements ISolanaChain {
212
212
  signature: Uint8Array;
213
213
  publicKey: string;
214
214
  }>;
215
- signTransaction<T>(transaction: T): Promise<T>;
216
- signAndSendTransaction<T>(transaction: T): Promise<{
215
+ signTransaction(transaction: Transaction | VersionedTransaction): Promise<Transaction | VersionedTransaction>;
216
+ signAndSendTransaction(transaction: Transaction | VersionedTransaction): Promise<{
217
217
  signature: string;
218
218
  }>;
219
- signAllTransactions<T>(transactions: T[]): Promise<T[]>;
219
+ signAllTransactions(transactions: (Transaction | VersionedTransaction)[]): Promise<(Transaction | VersionedTransaction)[]>;
220
+ signAndSendAllTransactions(transactions: (Transaction | VersionedTransaction)[]): Promise<{
221
+ signatures: string[];
222
+ }>;
220
223
  connect(_options?: {
221
224
  onlyIfTrusted?: boolean;
222
225
  }): Promise<{
package/dist/index.js CHANGED
@@ -43,6 +43,7 @@ module.exports = __toCommonJS(src_exports);
43
43
 
44
44
  // src/embedded-provider.ts
45
45
  var import_client = require("@phantom/client");
46
+ var import_utils = require("@phantom/utils");
46
47
  var import_base64url2 = require("@phantom/base64url");
47
48
  var import_bs582 = __toESM(require("bs58"));
48
49
  var import_parsers2 = require("@phantom/parsers");
@@ -215,8 +216,12 @@ var EmbeddedSolanaChain = class {
215
216
  transaction,
216
217
  networkId: this.currentNetworkId
217
218
  });
218
- const signatureResult = (0, import_parsers.parseSolanaTransactionSignature)(result.rawTransaction);
219
- return signatureResult.signature;
219
+ const signedResult = (0, import_parsers.parseSolanaSignedTransaction)(result.rawTransaction);
220
+ if (signedResult.transaction && !signedResult.fallback) {
221
+ return signedResult.transaction;
222
+ } else {
223
+ throw new Error("Failed to parse signed transaction");
224
+ }
220
225
  }
221
226
  async signAndSendTransaction(transaction) {
222
227
  this.ensureConnected();
@@ -233,6 +238,10 @@ var EmbeddedSolanaChain = class {
233
238
  const results = await Promise.all(transactions.map((tx) => this.signTransaction(tx)));
234
239
  return results;
235
240
  }
241
+ async signAndSendAllTransactions(transactions) {
242
+ const results = await Promise.all(transactions.map((tx) => this.signAndSendTransaction(tx)));
243
+ return { signatures: results.map((result) => result.signature) };
244
+ }
236
245
  connect(_options) {
237
246
  if (!this.provider.isConnected()) {
238
247
  throw new Error("Provider not connected. Call provider connect first.");
@@ -504,6 +513,9 @@ var EmbeddedProvider = class {
504
513
  this.eventListeners = /* @__PURE__ */ new Map();
505
514
  this.logger = logger;
506
515
  this.logger.log("EMBEDDED_PROVIDER", "Initializing EmbeddedProvider", { config });
516
+ if (config.embeddedWalletType === "app-wallet") {
517
+ throw new Error("app-wallet type is not currently supported. Please use 'user-wallet' instead.");
518
+ }
507
519
  this.config = config;
508
520
  this.platform = platform;
509
521
  this.storage = platform.storage;
@@ -511,7 +523,6 @@ var EmbeddedProvider = class {
511
523
  this.urlParamsAccessor = platform.urlParamsAccessor;
512
524
  this.stamper = platform.stamper;
513
525
  this.jwtAuth = new JWTAuth();
514
- config.solanaProvider;
515
526
  this.solana = new EmbeddedSolanaChain(this);
516
527
  this.ethereum = new EmbeddedEthereumChain(this);
517
528
  this.logger.info("EMBEDDED_PROVIDER", "EmbeddedProvider initialized");
@@ -778,21 +789,24 @@ var EmbeddedProvider = class {
778
789
  this.logger.log("EMBEDDED_PROVIDER", "Creating temporary PhantomClient");
779
790
  const tempClient = new import_client.PhantomClient(
780
791
  {
781
- apiBaseUrl: this.config.apiBaseUrl
792
+ apiBaseUrl: this.config.apiBaseUrl,
793
+ headers: {
794
+ ...this.platform.analyticsHeaders || {}
795
+ }
782
796
  },
783
797
  this.stamper
784
798
  );
785
799
  const platformName = this.platform.name || "unknown";
786
800
  const shortPubKey = stamperInfo.publicKey.slice(0, 8);
787
- const organizationName = `${this.config.organizationId}-${platformName}-${shortPubKey}`;
801
+ const organizationName = `${this.config.organizationId.substring(0, 8)}-${platformName}-${shortPubKey}`;
788
802
  this.logger.log("EMBEDDED_PROVIDER", "Creating organization", {
789
803
  organizationName,
790
804
  publicKey: stamperInfo.publicKey,
791
805
  platform: platformName
792
806
  });
793
807
  const base64urlPublicKey = (0, import_base64url2.base64urlEncode)(import_bs582.default.decode(stamperInfo.publicKey));
794
- const expiresAtMs = Date.now() + AUTHENTICATOR_EXPIRATION_TIME_MS;
795
- const username = `user-${shortPubKey}`;
808
+ const expiresInMs = AUTHENTICATOR_EXPIRATION_TIME_MS;
809
+ const username = `user-${(0, import_utils.randomUUID)()}`;
796
810
  const { organizationId } = await tempClient.createOrganization(organizationName, [
797
811
  {
798
812
  username,
@@ -804,13 +818,13 @@ var EmbeddedProvider = class {
804
818
  publicKey: base64urlPublicKey,
805
819
  algorithm: "Ed25519"
806
820
  // Commented for now until KMS supports fully expirable organizations
807
- // expiresAtMs: expiresAtMs,
821
+ // expiresInMs: expiresInMs,
808
822
  }
809
823
  ]
810
824
  }
811
825
  ]);
812
826
  this.logger.info("EMBEDDED_PROVIDER", "Organization created", { organizationId });
813
- return { organizationId, stamperInfo, expiresAtMs, username };
827
+ return { organizationId, stamperInfo, expiresInMs, username };
814
828
  }
815
829
  async connect(authOptions) {
816
830
  try {
@@ -839,8 +853,8 @@ var EmbeddedProvider = class {
839
853
  }
840
854
  this.validateAuthOptions(authOptions);
841
855
  this.logger.info("EMBEDDED_PROVIDER", "No existing connection, creating new auth flow");
842
- const { organizationId, stamperInfo, expiresAtMs, username } = await this.createOrganizationAndStamper();
843
- const session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions, expiresAtMs, username);
856
+ const { organizationId, stamperInfo, expiresInMs, username } = await this.createOrganizationAndStamper();
857
+ const session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions, expiresInMs, username);
844
858
  if (!session) {
845
859
  return {
846
860
  addresses: [],
@@ -1010,13 +1024,13 @@ var EmbeddedProvider = class {
1010
1024
  * It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.
1011
1025
  * Returns null for redirect flows since they don't complete synchronously.
1012
1026
  */
1013
- async handleAuthFlow(organizationId, stamperInfo, authOptions, expiresAtMs, username) {
1027
+ async handleAuthFlow(organizationId, stamperInfo, authOptions, expiresInMs, username) {
1014
1028
  if (this.config.embeddedWalletType === "user-wallet") {
1015
1029
  this.logger.info("EMBEDDED_PROVIDER", "Creating user-wallet, routing authentication", {
1016
1030
  authProvider: authOptions?.provider || "phantom-connect"
1017
1031
  });
1018
1032
  if (authOptions?.provider === "jwt") {
1019
- return await this.handleJWTAuth(organizationId, stamperInfo, authOptions, expiresAtMs, username);
1033
+ return await this.handleJWTAuth(organizationId, stamperInfo, authOptions, expiresInMs, username);
1020
1034
  } else {
1021
1035
  this.logger.info("EMBEDDED_PROVIDER", "Starting redirect-based authentication flow", {
1022
1036
  organizationId,
@@ -1032,7 +1046,10 @@ var EmbeddedProvider = class {
1032
1046
  const tempClient = new import_client.PhantomClient(
1033
1047
  {
1034
1048
  apiBaseUrl: this.config.apiBaseUrl,
1035
- organizationId
1049
+ organizationId,
1050
+ headers: {
1051
+ ...this.platform.analyticsHeaders || {}
1052
+ }
1036
1053
  },
1037
1054
  this.stamper
1038
1055
  );
@@ -1053,7 +1070,7 @@ var EmbeddedProvider = class {
1053
1070
  createdAt: now,
1054
1071
  lastUsed: now,
1055
1072
  authenticatorCreatedAt: now,
1056
- authenticatorExpiresAt: expiresAtMs,
1073
+ authenticatorExpiresAt: Date.now() + expiresInMs,
1057
1074
  lastRenewalAttempt: void 0,
1058
1075
  username
1059
1076
  };
@@ -1066,7 +1083,7 @@ var EmbeddedProvider = class {
1066
1083
  * We use this method to handle JWT-based authentication for user-wallets.
1067
1084
  * It authenticates using the provided JWT token and creates a completed session.
1068
1085
  */
1069
- async handleJWTAuth(organizationId, stamperInfo, authOptions, expiresAtMs, username) {
1086
+ async handleJWTAuth(organizationId, stamperInfo, authOptions, expiresInMs, username) {
1070
1087
  this.logger.info("EMBEDDED_PROVIDER", "Using JWT authentication flow");
1071
1088
  if (!authOptions.jwtToken) {
1072
1089
  this.logger.error("EMBEDDED_PROVIDER", "JWT token missing for JWT authentication");
@@ -1096,7 +1113,7 @@ var EmbeddedProvider = class {
1096
1113
  createdAt: now,
1097
1114
  lastUsed: now,
1098
1115
  authenticatorCreatedAt: now,
1099
- authenticatorExpiresAt: expiresAtMs,
1116
+ authenticatorExpiresAt: Date.now() + expiresInMs,
1100
1117
  lastRenewalAttempt: void 0,
1101
1118
  username
1102
1119
  };
@@ -1112,8 +1129,8 @@ var EmbeddedProvider = class {
1112
1129
  async handleRedirectAuth(organizationId, stamperInfo, authOptions, username) {
1113
1130
  this.logger.info("EMBEDDED_PROVIDER", "Using Phantom Connect authentication flow (redirect-based)", {
1114
1131
  provider: authOptions?.provider,
1115
- hasRedirectUrl: !!this.config.authOptions?.redirectUrl,
1116
- authUrl: this.config.authOptions?.authUrl
1132
+ hasRedirectUrl: !!this.config.authOptions.redirectUrl,
1133
+ authUrl: this.config.authOptions.authUrl
1117
1134
  });
1118
1135
  const now = Date.now();
1119
1136
  const sessionId = generateSessionId();
@@ -1134,7 +1151,7 @@ var EmbeddedProvider = class {
1134
1151
  authenticatorCreatedAt: now,
1135
1152
  authenticatorExpiresAt: now + AUTHENTICATOR_EXPIRATION_TIME_MS,
1136
1153
  lastRenewalAttempt: void 0,
1137
- username: username || `user-${stamperInfo.keyId.substring(0, 8)}`
1154
+ username: username || `user-${(0, import_utils.randomUUID)()}`
1138
1155
  };
1139
1156
  this.logger.log("EMBEDDED_PROVIDER", "Saving temporary session before redirect", {
1140
1157
  sessionId: tempSession.sessionId,
@@ -1147,16 +1164,16 @@ var EmbeddedProvider = class {
1147
1164
  parentOrganizationId: this.config.organizationId,
1148
1165
  appId: this.config.appId,
1149
1166
  provider: authOptions?.provider,
1150
- authUrl: this.config.authOptions?.authUrl
1167
+ authUrl: this.config.authOptions.authUrl
1151
1168
  });
1152
1169
  const authResult = await this.authProvider.authenticate({
1153
1170
  organizationId,
1154
1171
  appId: this.config.appId,
1155
1172
  parentOrganizationId: this.config.organizationId,
1156
1173
  provider: authOptions?.provider,
1157
- redirectUrl: this.config.authOptions?.redirectUrl,
1174
+ redirectUrl: this.config.authOptions.redirectUrl,
1158
1175
  customAuthData: authOptions?.customAuthData,
1159
- authUrl: this.config.authOptions?.authUrl,
1176
+ authUrl: this.config.authOptions.authUrl,
1160
1177
  sessionId
1161
1178
  });
1162
1179
  if (authResult && "walletId" in authResult) {
@@ -1252,7 +1269,7 @@ var EmbeddedProvider = class {
1252
1269
  newPublicKey: newKeyInfo.publicKey
1253
1270
  });
1254
1271
  const base64urlPublicKey = (0, import_base64url2.base64urlEncode)(import_bs582.default.decode(newKeyInfo.publicKey));
1255
- const expiresAtMs = Date.now() + AUTHENTICATOR_EXPIRATION_TIME_MS;
1272
+ const expiresInMs = AUTHENTICATOR_EXPIRATION_TIME_MS;
1256
1273
  let authenticatorResult;
1257
1274
  try {
1258
1275
  authenticatorResult = await this.client.createAuthenticator({
@@ -1265,7 +1282,7 @@ var EmbeddedProvider = class {
1265
1282
  publicKey: base64urlPublicKey,
1266
1283
  algorithm: "Ed25519"
1267
1284
  // Commented for now until KMS supports fully expiring organizations
1268
- // expiresAtMs: expiresAtMs,
1285
+ // expiresInMs: expiresInMs,
1269
1286
  },
1270
1287
  replaceExpirable: true
1271
1288
  });
@@ -1285,12 +1302,12 @@ var EmbeddedProvider = class {
1285
1302
  const now = Date.now();
1286
1303
  session.stamperInfo = newKeyInfo;
1287
1304
  session.authenticatorCreatedAt = now;
1288
- session.authenticatorExpiresAt = expiresAtMs;
1305
+ session.authenticatorExpiresAt = Date.now() + expiresInMs;
1289
1306
  session.lastRenewalAttempt = now;
1290
1307
  await this.storage.saveSession(session);
1291
1308
  this.logger.info("EMBEDDED_PROVIDER", "Authenticator renewal completed successfully", {
1292
1309
  newKeyId: newKeyInfo.keyId,
1293
- expiresAt: new Date(expiresAtMs).toISOString()
1310
+ expiresAt: new Date(Date.now() + expiresInMs).toISOString()
1294
1311
  });
1295
1312
  } catch (error) {
1296
1313
  await this.stamper.rollbackRotation();
@@ -1313,7 +1330,10 @@ var EmbeddedProvider = class {
1313
1330
  this.client = new import_client.PhantomClient(
1314
1331
  {
1315
1332
  apiBaseUrl: this.config.apiBaseUrl,
1316
- organizationId: session.organizationId
1333
+ organizationId: session.organizationId,
1334
+ headers: {
1335
+ ...this.platform.analyticsHeaders || {}
1336
+ }
1317
1337
  },
1318
1338
  this.stamper
1319
1339
  );