@phantom/embedded-provider-core 0.1.1 → 0.1.3
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/dist/index.d.mts +29 -10
- package/dist/index.d.ts +29 -10
- package/dist/index.js +120 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +117 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -5
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StamperWithKeyManagement } from '@phantom/sdk-types';
|
|
2
|
+
import { AddressType } from '@phantom/client';
|
|
3
|
+
import { NetworkId } from '@phantom/constants';
|
|
4
|
+
import { ParsedSignatureResult, ParsedTransactionResult } from '@phantom/parsers';
|
|
2
5
|
|
|
3
6
|
interface Keypair {
|
|
4
7
|
publicKey: string;
|
|
5
8
|
secretKey: string;
|
|
6
9
|
}
|
|
10
|
+
interface StamperInfo {
|
|
11
|
+
keyId: string;
|
|
12
|
+
publicKey: string;
|
|
13
|
+
}
|
|
7
14
|
interface Session {
|
|
8
15
|
sessionId: string;
|
|
9
16
|
walletId: string;
|
|
10
17
|
organizationId: string;
|
|
11
|
-
|
|
18
|
+
stamperInfo: StamperInfo;
|
|
19
|
+
keypair?: Keypair;
|
|
12
20
|
authProvider?: string;
|
|
13
21
|
userInfo?: Record<string, any>;
|
|
14
22
|
status: "pending" | "completed" | "failed";
|
|
@@ -54,12 +62,16 @@ interface PhantomConnectOptions {
|
|
|
54
62
|
customAuthData?: Record<string, any>;
|
|
55
63
|
authUrl?: string;
|
|
56
64
|
sessionId: string;
|
|
65
|
+
appName?: string;
|
|
66
|
+
appLogo?: string;
|
|
57
67
|
}
|
|
58
68
|
interface JWTAuthOptions {
|
|
59
69
|
organizationId: string;
|
|
60
70
|
parentOrganizationId: string;
|
|
61
71
|
jwtToken: string;
|
|
62
72
|
customAuthData?: Record<string, any>;
|
|
73
|
+
appName?: string;
|
|
74
|
+
appLogo?: string;
|
|
63
75
|
}
|
|
64
76
|
interface AuthProvider {
|
|
65
77
|
authenticate(options: PhantomConnectOptions | JWTAuthOptions): Promise<void | AuthResult>;
|
|
@@ -67,9 +79,11 @@ interface AuthProvider {
|
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
interface PlatformAdapter {
|
|
82
|
+
name: string;
|
|
70
83
|
storage: EmbeddedStorage;
|
|
71
84
|
authProvider: AuthProvider;
|
|
72
85
|
urlParamsAccessor: URLParamsAccessor;
|
|
86
|
+
stamper: StamperWithKeyManagement;
|
|
73
87
|
}
|
|
74
88
|
interface DebugLogger {
|
|
75
89
|
info(category: string, message: string, data?: any): void;
|
|
@@ -91,12 +105,13 @@ interface SignMessageParams {
|
|
|
91
105
|
message: string;
|
|
92
106
|
networkId: NetworkId;
|
|
93
107
|
}
|
|
108
|
+
interface SignMessageResult extends ParsedSignatureResult {
|
|
109
|
+
}
|
|
94
110
|
interface SignAndSendTransactionParams {
|
|
95
111
|
transaction: any;
|
|
96
112
|
networkId: NetworkId;
|
|
97
113
|
}
|
|
98
|
-
interface SignedTransaction {
|
|
99
|
-
rawTransaction: string;
|
|
114
|
+
interface SignedTransaction extends ParsedTransactionResult {
|
|
100
115
|
}
|
|
101
116
|
interface AuthOptions {
|
|
102
117
|
provider?: "google" | "apple" | "jwt";
|
|
@@ -110,16 +125,20 @@ interface EmbeddedProviderConfig {
|
|
|
110
125
|
authUrl?: string;
|
|
111
126
|
redirectUrl?: string;
|
|
112
127
|
};
|
|
113
|
-
embeddedWalletType: "app-wallet" | "user-wallet";
|
|
128
|
+
embeddedWalletType: "app-wallet" | "user-wallet" | (string & Record<never, never>);
|
|
114
129
|
addressTypes: AddressType[];
|
|
115
|
-
solanaProvider: "web3js" | "kit";
|
|
130
|
+
solanaProvider: "web3js" | "kit" | (string & Record<never, never>);
|
|
131
|
+
appName?: string;
|
|
132
|
+
appLogo?: string;
|
|
116
133
|
}
|
|
117
134
|
|
|
118
135
|
declare class EmbeddedProvider {
|
|
119
136
|
private config;
|
|
137
|
+
private platform;
|
|
120
138
|
private storage;
|
|
121
139
|
private authProvider;
|
|
122
140
|
private urlParamsAccessor;
|
|
141
|
+
private stamper;
|
|
123
142
|
private logger;
|
|
124
143
|
private client;
|
|
125
144
|
private walletId;
|
|
@@ -129,11 +148,11 @@ declare class EmbeddedProvider {
|
|
|
129
148
|
private getAndFilterWalletAddresses;
|
|
130
149
|
private validateAndCleanSession;
|
|
131
150
|
private validateAuthOptions;
|
|
132
|
-
private
|
|
151
|
+
private createOrganizationAndStamper;
|
|
133
152
|
connect(authOptions?: AuthOptions): Promise<ConnectResult>;
|
|
134
153
|
disconnect(): Promise<void>;
|
|
135
|
-
signMessage(params: SignMessageParams): Promise<
|
|
136
|
-
signAndSendTransaction(params: SignAndSendTransactionParams): Promise<
|
|
154
|
+
signMessage(params: SignMessageParams): Promise<ParsedSignatureResult>;
|
|
155
|
+
signAndSendTransaction(params: SignAndSendTransactionParams): Promise<ParsedTransactionResult>;
|
|
137
156
|
getAddresses(): WalletAddress[];
|
|
138
157
|
isConnected(): boolean;
|
|
139
158
|
private handleAuthFlow;
|
|
@@ -151,4 +170,4 @@ declare function generateSessionId(): string;
|
|
|
151
170
|
|
|
152
171
|
declare function retryWithBackoff<T>(operation: () => Promise<T>, operationName: string, logger: DebugLogger, maxRetries?: number, baseDelay?: number): Promise<T>;
|
|
153
172
|
|
|
154
|
-
export { AuthOptions, AuthProvider, AuthResult, ConnectResult, DebugLogger, EmbeddedProvider, EmbeddedProviderConfig, EmbeddedStorage, JWTAuth, JWTAuthOptions, Keypair, PhantomConnectOptions, PlatformAdapter, Session, SignAndSendTransactionParams, SignMessageParams, SignedTransaction, URLParamsAccessor, WalletAddress, generateSessionId, retryWithBackoff };
|
|
173
|
+
export { AuthOptions, AuthProvider, AuthResult, ConnectResult, DebugLogger, EmbeddedProvider, EmbeddedProviderConfig, EmbeddedStorage, JWTAuth, JWTAuthOptions, Keypair, PhantomConnectOptions, PlatformAdapter, Session, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, StamperInfo, URLParamsAccessor, WalletAddress, generateSessionId, retryWithBackoff };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StamperWithKeyManagement } from '@phantom/sdk-types';
|
|
2
|
+
import { AddressType } from '@phantom/client';
|
|
3
|
+
import { NetworkId } from '@phantom/constants';
|
|
4
|
+
import { ParsedSignatureResult, ParsedTransactionResult } from '@phantom/parsers';
|
|
2
5
|
|
|
3
6
|
interface Keypair {
|
|
4
7
|
publicKey: string;
|
|
5
8
|
secretKey: string;
|
|
6
9
|
}
|
|
10
|
+
interface StamperInfo {
|
|
11
|
+
keyId: string;
|
|
12
|
+
publicKey: string;
|
|
13
|
+
}
|
|
7
14
|
interface Session {
|
|
8
15
|
sessionId: string;
|
|
9
16
|
walletId: string;
|
|
10
17
|
organizationId: string;
|
|
11
|
-
|
|
18
|
+
stamperInfo: StamperInfo;
|
|
19
|
+
keypair?: Keypair;
|
|
12
20
|
authProvider?: string;
|
|
13
21
|
userInfo?: Record<string, any>;
|
|
14
22
|
status: "pending" | "completed" | "failed";
|
|
@@ -54,12 +62,16 @@ interface PhantomConnectOptions {
|
|
|
54
62
|
customAuthData?: Record<string, any>;
|
|
55
63
|
authUrl?: string;
|
|
56
64
|
sessionId: string;
|
|
65
|
+
appName?: string;
|
|
66
|
+
appLogo?: string;
|
|
57
67
|
}
|
|
58
68
|
interface JWTAuthOptions {
|
|
59
69
|
organizationId: string;
|
|
60
70
|
parentOrganizationId: string;
|
|
61
71
|
jwtToken: string;
|
|
62
72
|
customAuthData?: Record<string, any>;
|
|
73
|
+
appName?: string;
|
|
74
|
+
appLogo?: string;
|
|
63
75
|
}
|
|
64
76
|
interface AuthProvider {
|
|
65
77
|
authenticate(options: PhantomConnectOptions | JWTAuthOptions): Promise<void | AuthResult>;
|
|
@@ -67,9 +79,11 @@ interface AuthProvider {
|
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
interface PlatformAdapter {
|
|
82
|
+
name: string;
|
|
70
83
|
storage: EmbeddedStorage;
|
|
71
84
|
authProvider: AuthProvider;
|
|
72
85
|
urlParamsAccessor: URLParamsAccessor;
|
|
86
|
+
stamper: StamperWithKeyManagement;
|
|
73
87
|
}
|
|
74
88
|
interface DebugLogger {
|
|
75
89
|
info(category: string, message: string, data?: any): void;
|
|
@@ -91,12 +105,13 @@ interface SignMessageParams {
|
|
|
91
105
|
message: string;
|
|
92
106
|
networkId: NetworkId;
|
|
93
107
|
}
|
|
108
|
+
interface SignMessageResult extends ParsedSignatureResult {
|
|
109
|
+
}
|
|
94
110
|
interface SignAndSendTransactionParams {
|
|
95
111
|
transaction: any;
|
|
96
112
|
networkId: NetworkId;
|
|
97
113
|
}
|
|
98
|
-
interface SignedTransaction {
|
|
99
|
-
rawTransaction: string;
|
|
114
|
+
interface SignedTransaction extends ParsedTransactionResult {
|
|
100
115
|
}
|
|
101
116
|
interface AuthOptions {
|
|
102
117
|
provider?: "google" | "apple" | "jwt";
|
|
@@ -110,16 +125,20 @@ interface EmbeddedProviderConfig {
|
|
|
110
125
|
authUrl?: string;
|
|
111
126
|
redirectUrl?: string;
|
|
112
127
|
};
|
|
113
|
-
embeddedWalletType: "app-wallet" | "user-wallet";
|
|
128
|
+
embeddedWalletType: "app-wallet" | "user-wallet" | (string & Record<never, never>);
|
|
114
129
|
addressTypes: AddressType[];
|
|
115
|
-
solanaProvider: "web3js" | "kit";
|
|
130
|
+
solanaProvider: "web3js" | "kit" | (string & Record<never, never>);
|
|
131
|
+
appName?: string;
|
|
132
|
+
appLogo?: string;
|
|
116
133
|
}
|
|
117
134
|
|
|
118
135
|
declare class EmbeddedProvider {
|
|
119
136
|
private config;
|
|
137
|
+
private platform;
|
|
120
138
|
private storage;
|
|
121
139
|
private authProvider;
|
|
122
140
|
private urlParamsAccessor;
|
|
141
|
+
private stamper;
|
|
123
142
|
private logger;
|
|
124
143
|
private client;
|
|
125
144
|
private walletId;
|
|
@@ -129,11 +148,11 @@ declare class EmbeddedProvider {
|
|
|
129
148
|
private getAndFilterWalletAddresses;
|
|
130
149
|
private validateAndCleanSession;
|
|
131
150
|
private validateAuthOptions;
|
|
132
|
-
private
|
|
151
|
+
private createOrganizationAndStamper;
|
|
133
152
|
connect(authOptions?: AuthOptions): Promise<ConnectResult>;
|
|
134
153
|
disconnect(): Promise<void>;
|
|
135
|
-
signMessage(params: SignMessageParams): Promise<
|
|
136
|
-
signAndSendTransaction(params: SignAndSendTransactionParams): Promise<
|
|
154
|
+
signMessage(params: SignMessageParams): Promise<ParsedSignatureResult>;
|
|
155
|
+
signAndSendTransaction(params: SignAndSendTransactionParams): Promise<ParsedTransactionResult>;
|
|
137
156
|
getAddresses(): WalletAddress[];
|
|
138
157
|
isConnected(): boolean;
|
|
139
158
|
private handleAuthFlow;
|
|
@@ -151,4 +170,4 @@ declare function generateSessionId(): string;
|
|
|
151
170
|
|
|
152
171
|
declare function retryWithBackoff<T>(operation: () => Promise<T>, operationName: string, logger: DebugLogger, maxRetries?: number, baseDelay?: number): Promise<T>;
|
|
153
172
|
|
|
154
|
-
export { AuthOptions, AuthProvider, AuthResult, ConnectResult, DebugLogger, EmbeddedProvider, EmbeddedProviderConfig, EmbeddedStorage, JWTAuth, JWTAuthOptions, Keypair, PhantomConnectOptions, PlatformAdapter, Session, SignAndSendTransactionParams, SignMessageParams, SignedTransaction, URLParamsAccessor, WalletAddress, generateSessionId, retryWithBackoff };
|
|
173
|
+
export { AuthOptions, AuthProvider, AuthResult, ConnectResult, DebugLogger, EmbeddedProvider, EmbeddedProviderConfig, EmbeddedStorage, JWTAuth, JWTAuthOptions, Keypair, PhantomConnectOptions, PlatformAdapter, Session, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, StamperInfo, URLParamsAccessor, WalletAddress, generateSessionId, retryWithBackoff };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -29,7 +39,8 @@ module.exports = __toCommonJS(src_exports);
|
|
|
29
39
|
|
|
30
40
|
// src/embedded-provider.ts
|
|
31
41
|
var import_client = require("@phantom/client");
|
|
32
|
-
var
|
|
42
|
+
var import_base64url = require("@phantom/base64url");
|
|
43
|
+
var import_bs58 = __toESM(require("bs58"));
|
|
33
44
|
var import_parsers = require("@phantom/parsers");
|
|
34
45
|
|
|
35
46
|
// src/auth/jwt-auth.ts
|
|
@@ -157,9 +168,11 @@ var EmbeddedProvider = class {
|
|
|
157
168
|
this.logger = logger;
|
|
158
169
|
this.logger.log("EMBEDDED_PROVIDER", "Initializing EmbeddedProvider", { config });
|
|
159
170
|
this.config = config;
|
|
171
|
+
this.platform = platform;
|
|
160
172
|
this.storage = platform.storage;
|
|
161
173
|
this.authProvider = platform.authProvider;
|
|
162
174
|
this.urlParamsAccessor = platform.urlParamsAccessor;
|
|
175
|
+
this.stamper = platform.stamper;
|
|
163
176
|
this.jwtAuth = new JWTAuth();
|
|
164
177
|
config.solanaProvider;
|
|
165
178
|
this.logger.info("EMBEDDED_PROVIDER", "EmbeddedProvider initialized");
|
|
@@ -233,29 +246,48 @@ var EmbeddedProvider = class {
|
|
|
233
246
|
}
|
|
234
247
|
}
|
|
235
248
|
/*
|
|
236
|
-
* We use this method to
|
|
249
|
+
* We use this method to initialize the stamper and create an organization for new sessions.
|
|
237
250
|
* This is the first step when no existing session is found and we need to set up a new wallet.
|
|
238
251
|
*/
|
|
239
|
-
async
|
|
240
|
-
this.logger.log("EMBEDDED_PROVIDER", "
|
|
241
|
-
const
|
|
242
|
-
this.logger.log("EMBEDDED_PROVIDER", "
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
252
|
+
async createOrganizationAndStamper() {
|
|
253
|
+
this.logger.log("EMBEDDED_PROVIDER", "Initializing stamper");
|
|
254
|
+
const stamperInfo = await this.stamper.init();
|
|
255
|
+
this.logger.log("EMBEDDED_PROVIDER", "Stamper initialized", {
|
|
256
|
+
publicKey: stamperInfo.publicKey,
|
|
257
|
+
keyId: stamperInfo.keyId,
|
|
258
|
+
algorithm: this.stamper.algorithm
|
|
246
259
|
});
|
|
260
|
+
this.logger.log("EMBEDDED_PROVIDER", "Creating temporary PhantomClient");
|
|
247
261
|
const tempClient = new import_client.PhantomClient(
|
|
248
262
|
{
|
|
249
263
|
apiBaseUrl: this.config.apiBaseUrl
|
|
250
264
|
},
|
|
251
|
-
stamper
|
|
265
|
+
this.stamper
|
|
266
|
+
);
|
|
267
|
+
const platformName = this.platform.name || "unknown";
|
|
268
|
+
const shortPubKey = stamperInfo.publicKey.slice(0, 8);
|
|
269
|
+
const organizationName = `${this.config.organizationId}-${platformName}-${shortPubKey}`;
|
|
270
|
+
this.logger.log("EMBEDDED_PROVIDER", "Creating organization", {
|
|
271
|
+
organizationName,
|
|
272
|
+
publicKey: stamperInfo.publicKey,
|
|
273
|
+
platform: platformName
|
|
274
|
+
});
|
|
275
|
+
const base64urlPublicKey = (0, import_base64url.base64urlEncode)(import_bs58.default.decode(stamperInfo.publicKey));
|
|
276
|
+
const { organizationId } = await tempClient.createOrganization(
|
|
277
|
+
organizationName,
|
|
278
|
+
[{
|
|
279
|
+
username: `user-${shortPubKey}`,
|
|
280
|
+
role: "admin",
|
|
281
|
+
authenticators: [{
|
|
282
|
+
authenticatorName: `auth-${shortPubKey}`,
|
|
283
|
+
authenticatorKind: "keypair",
|
|
284
|
+
publicKey: base64urlPublicKey,
|
|
285
|
+
algorithm: "Ed25519"
|
|
286
|
+
}]
|
|
287
|
+
}]
|
|
252
288
|
);
|
|
253
|
-
const uid = Date.now();
|
|
254
|
-
const organizationName = `${this.config.organizationId}-${uid}`;
|
|
255
|
-
this.logger.log("EMBEDDED_PROVIDER", "Creating organization", { organizationName });
|
|
256
|
-
const { organizationId } = await tempClient.createOrganization(organizationName, keypair);
|
|
257
289
|
this.logger.info("EMBEDDED_PROVIDER", "Organization created", { organizationId });
|
|
258
|
-
return { organizationId,
|
|
290
|
+
return { organizationId, stamperInfo };
|
|
259
291
|
}
|
|
260
292
|
async connect(authOptions) {
|
|
261
293
|
try {
|
|
@@ -282,8 +314,8 @@ var EmbeddedProvider = class {
|
|
|
282
314
|
this.validateAuthOptions(authOptions);
|
|
283
315
|
if (!session) {
|
|
284
316
|
this.logger.info("EMBEDDED_PROVIDER", "No existing session, creating new one");
|
|
285
|
-
const { organizationId,
|
|
286
|
-
session = await this.handleAuthFlow(organizationId,
|
|
317
|
+
const { organizationId, stamperInfo } = await this.createOrganizationAndStamper();
|
|
318
|
+
session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions);
|
|
287
319
|
}
|
|
288
320
|
if (!session) {
|
|
289
321
|
return {
|
|
@@ -339,28 +371,53 @@ var EmbeddedProvider = class {
|
|
|
339
371
|
this.client = null;
|
|
340
372
|
this.walletId = null;
|
|
341
373
|
this.addresses = [];
|
|
374
|
+
this.logger.info("EMBEDDED_PROVIDER", "Disconnected from embedded wallet");
|
|
342
375
|
}
|
|
343
376
|
async signMessage(params) {
|
|
344
377
|
if (!this.client || !this.walletId) {
|
|
345
378
|
throw new Error("Not connected");
|
|
346
379
|
}
|
|
380
|
+
this.logger.info("EMBEDDED_PROVIDER", "Signing message", {
|
|
381
|
+
walletId: this.walletId,
|
|
382
|
+
message: params.message
|
|
383
|
+
});
|
|
347
384
|
const parsedMessage = (0, import_parsers.parseMessage)(params.message);
|
|
348
|
-
|
|
385
|
+
const rawResponse = await this.client.signMessage({
|
|
349
386
|
walletId: this.walletId,
|
|
350
387
|
message: parsedMessage.base64url,
|
|
351
388
|
networkId: params.networkId
|
|
352
389
|
});
|
|
390
|
+
this.logger.info("EMBEDDED_PROVIDER", "Message signed successfully", {
|
|
391
|
+
walletId: this.walletId,
|
|
392
|
+
message: params.message
|
|
393
|
+
});
|
|
394
|
+
return (0, import_parsers.parseSignMessageResponse)(rawResponse, params.networkId);
|
|
353
395
|
}
|
|
354
396
|
async signAndSendTransaction(params) {
|
|
355
397
|
if (!this.client || !this.walletId) {
|
|
356
398
|
throw new Error("Not connected");
|
|
357
399
|
}
|
|
400
|
+
this.logger.info("EMBEDDED_PROVIDER", "Signing and sending transaction", {
|
|
401
|
+
walletId: this.walletId,
|
|
402
|
+
networkId: params.networkId
|
|
403
|
+
});
|
|
358
404
|
const parsedTransaction = await (0, import_parsers.parseTransaction)(params.transaction, params.networkId);
|
|
359
|
-
|
|
405
|
+
this.logger.log("EMBEDDED_PROVIDER", "Parsed transaction for signing", {
|
|
406
|
+
walletId: this.walletId,
|
|
407
|
+
transaction: parsedTransaction
|
|
408
|
+
});
|
|
409
|
+
const rawResponse = await this.client.signAndSendTransaction({
|
|
360
410
|
walletId: this.walletId,
|
|
361
411
|
transaction: parsedTransaction.base64url,
|
|
362
412
|
networkId: params.networkId
|
|
363
413
|
});
|
|
414
|
+
this.logger.info("EMBEDDED_PROVIDER", "Transaction signed and sent successfully", {
|
|
415
|
+
walletId: this.walletId,
|
|
416
|
+
networkId: params.networkId,
|
|
417
|
+
hash: rawResponse.hash,
|
|
418
|
+
rawTransaction: rawResponse.rawTransaction
|
|
419
|
+
});
|
|
420
|
+
return await (0, import_parsers.parseTransactionResponse)(rawResponse.rawTransaction, params.networkId, rawResponse.hash);
|
|
364
421
|
}
|
|
365
422
|
getAddresses() {
|
|
366
423
|
return this.addresses;
|
|
@@ -373,23 +430,31 @@ var EmbeddedProvider = class {
|
|
|
373
430
|
* It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.
|
|
374
431
|
* Returns null for redirect flows since they don't complete synchronously.
|
|
375
432
|
*/
|
|
376
|
-
async handleAuthFlow(organizationId,
|
|
433
|
+
async handleAuthFlow(organizationId, stamperInfo, authOptions) {
|
|
377
434
|
if (this.config.embeddedWalletType === "user-wallet") {
|
|
378
435
|
this.logger.info("EMBEDDED_PROVIDER", "Creating user-wallet, routing authentication", {
|
|
379
436
|
authProvider: authOptions?.provider || "phantom-connect"
|
|
380
437
|
});
|
|
381
438
|
if (authOptions?.provider === "jwt") {
|
|
382
|
-
return await this.handleJWTAuth(organizationId,
|
|
439
|
+
return await this.handleJWTAuth(organizationId, stamperInfo, authOptions);
|
|
383
440
|
} else {
|
|
384
|
-
|
|
385
|
-
|
|
441
|
+
this.logger.info("EMBEDDED_PROVIDER", "Starting redirect-based authentication flow", {
|
|
442
|
+
organizationId,
|
|
443
|
+
parentOrganizationId: this.config.organizationId,
|
|
444
|
+
provider: authOptions?.provider
|
|
445
|
+
});
|
|
446
|
+
return await this.handleRedirectAuth(organizationId, stamperInfo, authOptions);
|
|
386
447
|
}
|
|
387
448
|
} else {
|
|
449
|
+
this.logger.info("EMBEDDED_PROVIDER", "Creating app-wallet", {
|
|
450
|
+
organizationId
|
|
451
|
+
});
|
|
388
452
|
const tempClient = new import_client.PhantomClient(
|
|
389
453
|
{
|
|
390
|
-
apiBaseUrl: this.config.apiBaseUrl
|
|
454
|
+
apiBaseUrl: this.config.apiBaseUrl,
|
|
455
|
+
organizationId
|
|
391
456
|
},
|
|
392
|
-
|
|
457
|
+
this.stamper
|
|
393
458
|
);
|
|
394
459
|
const wallet = await tempClient.createWallet(`Wallet ${Date.now()}`);
|
|
395
460
|
const walletId = wallet.walletId;
|
|
@@ -397,8 +462,8 @@ var EmbeddedProvider = class {
|
|
|
397
462
|
const session = {
|
|
398
463
|
sessionId: generateSessionId(),
|
|
399
464
|
walletId,
|
|
400
|
-
organizationId
|
|
401
|
-
|
|
465
|
+
organizationId,
|
|
466
|
+
stamperInfo,
|
|
402
467
|
authProvider: "app-wallet",
|
|
403
468
|
userInfo: { embeddedWalletType: this.config.embeddedWalletType },
|
|
404
469
|
status: "completed",
|
|
@@ -406,6 +471,7 @@ var EmbeddedProvider = class {
|
|
|
406
471
|
lastUsed: now
|
|
407
472
|
};
|
|
408
473
|
await this.storage.saveSession(session);
|
|
474
|
+
this.logger.info("EMBEDDED_PROVIDER", "App-wallet created successfully", { walletId, organizationId });
|
|
409
475
|
return session;
|
|
410
476
|
}
|
|
411
477
|
}
|
|
@@ -413,7 +479,7 @@ var EmbeddedProvider = class {
|
|
|
413
479
|
* We use this method to handle JWT-based authentication for user-wallets.
|
|
414
480
|
* It authenticates using the provided JWT token and creates a completed session.
|
|
415
481
|
*/
|
|
416
|
-
async handleJWTAuth(organizationId,
|
|
482
|
+
async handleJWTAuth(organizationId, stamperInfo, authOptions) {
|
|
417
483
|
this.logger.info("EMBEDDED_PROVIDER", "Using JWT authentication flow");
|
|
418
484
|
if (!authOptions.jwtToken) {
|
|
419
485
|
this.logger.error("EMBEDDED_PROVIDER", "JWT token missing for JWT authentication");
|
|
@@ -432,8 +498,8 @@ var EmbeddedProvider = class {
|
|
|
432
498
|
const session = {
|
|
433
499
|
sessionId: generateSessionId(),
|
|
434
500
|
walletId,
|
|
435
|
-
organizationId
|
|
436
|
-
|
|
501
|
+
organizationId,
|
|
502
|
+
stamperInfo,
|
|
437
503
|
authProvider: authResult.provider,
|
|
438
504
|
userInfo: authResult.userInfo,
|
|
439
505
|
status: "completed",
|
|
@@ -449,7 +515,7 @@ var EmbeddedProvider = class {
|
|
|
449
515
|
* It saves a temporary session before redirecting to prevent losing state during the redirect flow.
|
|
450
516
|
* Session timestamp is updated before redirect to prevent race conditions.
|
|
451
517
|
*/
|
|
452
|
-
async handleRedirectAuth(organizationId,
|
|
518
|
+
async handleRedirectAuth(organizationId, stamperInfo, authOptions) {
|
|
453
519
|
this.logger.info("EMBEDDED_PROVIDER", "Using Phantom Connect authentication flow (redirect-based)", {
|
|
454
520
|
provider: authOptions?.provider,
|
|
455
521
|
hasRedirectUrl: !!this.config.authOptions?.redirectUrl,
|
|
@@ -462,7 +528,7 @@ var EmbeddedProvider = class {
|
|
|
462
528
|
walletId: `temp-${now}`,
|
|
463
529
|
// Temporary ID, will be updated after redirect
|
|
464
530
|
organizationId,
|
|
465
|
-
|
|
531
|
+
stamperInfo,
|
|
466
532
|
authProvider: "phantom-connect",
|
|
467
533
|
userInfo: { provider: authOptions?.provider },
|
|
468
534
|
status: "pending",
|
|
@@ -481,15 +547,31 @@ var EmbeddedProvider = class {
|
|
|
481
547
|
provider: authOptions?.provider,
|
|
482
548
|
authUrl: this.config.authOptions?.authUrl
|
|
483
549
|
});
|
|
484
|
-
await this.authProvider.authenticate({
|
|
550
|
+
const authResult = await this.authProvider.authenticate({
|
|
485
551
|
organizationId,
|
|
486
552
|
parentOrganizationId: this.config.organizationId,
|
|
487
553
|
provider: authOptions?.provider,
|
|
488
554
|
redirectUrl: this.config.authOptions?.redirectUrl,
|
|
489
555
|
customAuthData: authOptions?.customAuthData,
|
|
490
556
|
authUrl: this.config.authOptions?.authUrl,
|
|
491
|
-
sessionId
|
|
557
|
+
sessionId,
|
|
558
|
+
appName: this.config.appName,
|
|
559
|
+
appLogo: this.config.appLogo
|
|
492
560
|
});
|
|
561
|
+
if (authResult && "walletId" in authResult) {
|
|
562
|
+
this.logger.info("EMBEDDED_PROVIDER", "Authentication completed after redirect", {
|
|
563
|
+
walletId: authResult.walletId,
|
|
564
|
+
provider: authResult.provider
|
|
565
|
+
});
|
|
566
|
+
tempSession.walletId = authResult.walletId;
|
|
567
|
+
tempSession.authProvider = authResult.provider || tempSession.authProvider;
|
|
568
|
+
tempSession.status = "completed";
|
|
569
|
+
tempSession.lastUsed = Date.now();
|
|
570
|
+
await this.storage.saveSession(tempSession);
|
|
571
|
+
return tempSession;
|
|
572
|
+
}
|
|
573
|
+
this.logger.info("EMBEDDED_PROVIDER", "Redirect authentication initiated, waiting for redirect completion");
|
|
574
|
+
return null;
|
|
493
575
|
}
|
|
494
576
|
async completeAuthConnection(authResult) {
|
|
495
577
|
const session = await this.storage.getSession();
|
|
@@ -498,7 +580,6 @@ var EmbeddedProvider = class {
|
|
|
498
580
|
}
|
|
499
581
|
session.walletId = authResult.walletId;
|
|
500
582
|
session.authProvider = authResult.provider || session.authProvider;
|
|
501
|
-
session.userInfo = { ...session.userInfo, ...authResult.userInfo };
|
|
502
583
|
session.status = "completed";
|
|
503
584
|
session.lastUsed = Date.now();
|
|
504
585
|
await this.storage.saveSession(session);
|
|
@@ -518,15 +599,15 @@ var EmbeddedProvider = class {
|
|
|
518
599
|
organizationId: session.organizationId,
|
|
519
600
|
walletId: session.walletId
|
|
520
601
|
});
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
602
|
+
if (!this.stamper.getKeyInfo()) {
|
|
603
|
+
await this.stamper.init();
|
|
604
|
+
}
|
|
524
605
|
this.client = new import_client.PhantomClient(
|
|
525
606
|
{
|
|
526
607
|
apiBaseUrl: this.config.apiBaseUrl,
|
|
527
608
|
organizationId: session.organizationId
|
|
528
609
|
},
|
|
529
|
-
stamper
|
|
610
|
+
this.stamper
|
|
530
611
|
);
|
|
531
612
|
this.walletId = session.walletId;
|
|
532
613
|
this.addresses = await this.getAndFilterWalletAddresses(session.walletId);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/embedded-provider.ts","../src/auth/jwt-auth.ts","../src/utils/session.ts","../src/utils/retry.ts"],"sourcesContent":["export * from \"./interfaces\";\nexport * from \"./types\";\nexport * from \"./embedded-provider\";\nexport * from \"./auth/jwt-auth\";\nexport * from \"./utils/session\";\nexport * from \"./utils/retry\";\n","import { PhantomClient, generateKeyPair } from \"@phantom/client\";\nimport type { AddressType } from \"@phantom/client\";\nimport { ApiKeyStamper } from \"@phantom/api-key-stamper\";\nimport { parseMessage, parseTransaction } from \"@phantom/parsers\";\n\nimport type {\n PlatformAdapter,\n Session,\n AuthResult,\n DebugLogger,\n EmbeddedStorage,\n AuthProvider,\n URLParamsAccessor,\n} from \"./interfaces\";\nimport type {\n EmbeddedProviderConfig,\n ConnectResult,\n SignMessageParams,\n SignAndSendTransactionParams,\n SignedTransaction,\n WalletAddress,\n AuthOptions,\n} from \"./types\";\nimport { JWTAuth } from \"./auth/jwt-auth\";\nimport { generateSessionId } from \"./utils/session\";\nimport { retryWithBackoff } from \"./utils/retry\";\n\nexport class EmbeddedProvider {\n private config: EmbeddedProviderConfig;\n private storage: EmbeddedStorage;\n private authProvider: AuthProvider;\n private urlParamsAccessor: URLParamsAccessor;\n private logger: DebugLogger;\n private client: PhantomClient | null = null;\n private walletId: string | null = null;\n private addresses: WalletAddress[] = [];\n private jwtAuth: JWTAuth;\n\n constructor(config: EmbeddedProviderConfig, platform: PlatformAdapter, logger: DebugLogger) {\n this.logger = logger;\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing EmbeddedProvider\", { config });\n\n this.config = config;\n this.storage = platform.storage;\n this.authProvider = platform.authProvider;\n this.urlParamsAccessor = platform.urlParamsAccessor;\n this.jwtAuth = new JWTAuth();\n\n // Store solana provider config (unused for now)\n config.solanaProvider;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"EmbeddedProvider initialized\");\n }\n\n private async getAndFilterWalletAddresses(walletId: string): Promise<WalletAddress[]> {\n // Get wallet addresses with retry and auto-disconnect on failure\n const addresses = await retryWithBackoff(\n () => this.client!.getWalletAddresses(walletId),\n \"getWalletAddresses\",\n this.logger,\n ).catch(async error => {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"getWalletAddresses failed after retries, disconnecting\", {\n walletId,\n error: error.message,\n });\n // Clear the session if getWalletAddresses fails after retries\n await this.storage.clearSession();\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n throw error;\n });\n\n // Filter by enabled address types and return formatted addresses\n return addresses\n .filter(addr => this.config.addressTypes.some(type => type === addr.addressType))\n .map(addr => ({\n addressType: addr.addressType as AddressType,\n address: addr.address,\n }));\n }\n\n /*\n * We use this method to make sure the session is not invalid, or there's a different session id in the url.\n * If there's a different one, we delete the current session and start from scratch.\n * This prevents issues where users have stale sessions or URL mismatches after redirects.\n */\n private async validateAndCleanSession(session: Session | null): Promise<Session | null> {\n if (!session) return null;\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Found existing session, validating\", {\n sessionId: session.sessionId,\n status: session.status,\n walletId: session.walletId,\n });\n\n // If session is not completed, check if we're in the right context\n if (session.status !== \"completed\") {\n const urlSessionId = this.urlParamsAccessor.getParam(\"session_id\");\n\n // If we have a pending session but no sessionId in URL, this is a mismatch\n if (session.status === \"pending\" && !urlSessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session mismatch detected - pending session without redirect context\", {\n sessionId: session.sessionId,\n status: session.status,\n });\n // Clear the invalid session and start fresh\n await this.storage.clearSession();\n return null;\n }\n // If sessionId in URL doesn't match stored session, clear invalid session\n else if (urlSessionId && urlSessionId !== session.sessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session ID mismatch detected\", {\n storedSessionId: session.sessionId,\n urlSessionId: urlSessionId,\n });\n await this.storage.clearSession();\n return null;\n }\n }\n\n return session;\n }\n\n /*\n * We use this method to validate authentication options before processing them.\n * This ensures only supported auth providers are used and required tokens are present.\n */\n private validateAuthOptions(authOptions?: AuthOptions): void {\n if (!authOptions) return;\n\n if (authOptions.provider && ![\"google\", \"apple\", \"jwt\"].includes(authOptions.provider)) {\n throw new Error(`Invalid auth provider: ${authOptions.provider}. Must be \"google\", \"apple\", or \"jwt\"`);\n }\n\n if (authOptions.provider === \"jwt\" && !authOptions.jwtToken) {\n throw new Error(\"JWT token is required when using JWT authentication\");\n }\n }\n\n /*\n * We use this method to generate a new keypair and create an organization for new sessions.\n * This is the first step when no existing session is found and we need to set up a new wallet.\n */\n private async createOrganizationAndKeypair(): Promise<{ organizationId: string; keypair: any }> {\n // Generate keypair using PhantomClient\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Generating keypair\");\n const keypair = generateKeyPair();\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Keypair generated\", { publicKey: keypair.publicKey });\n\n // Create a temporary client with the keypair\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating temporary PhantomClient\");\n const stamper = new ApiKeyStamper({\n apiSecretKey: keypair.secretKey,\n });\n\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n },\n stamper,\n );\n\n // Create an organization\n // organization name is a combination of this organizationId and this userId, which will be a unique identifier\n const uid = Date.now(); // for now\n const organizationName = `${this.config.organizationId}-${uid}`;\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating organization\", { organizationName });\n const { organizationId } = await tempClient.createOrganization(organizationName, keypair);\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Organization created\", { organizationId });\n\n return { organizationId, keypair };\n }\n\n async connect(authOptions?: AuthOptions): Promise<ConnectResult> {\n try {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting embedded provider connect\", {\n authOptions: authOptions\n ? {\n provider: authOptions.provider,\n hasJwtToken: !!authOptions.jwtToken,\n }\n : undefined,\n });\n\n // Get and validate existing session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Getting existing session\");\n let session = await this.storage.getSession();\n session = await this.validateAndCleanSession(session);\n\n // First, check if we're resuming from a redirect\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Checking for redirect resume\");\n if (this.authProvider.resumeAuthFromRedirect) {\n const authResult = this.authProvider.resumeAuthFromRedirect();\n if (authResult) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Resuming from redirect\", {\n walletId: authResult.walletId,\n provider: authResult.provider,\n });\n return this.completeAuthConnection(authResult);\n }\n }\n\n // Validate auth options\n this.validateAuthOptions(authOptions);\n\n // If no session exists, create new one\n if (!session) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"No existing session, creating new one\");\n const { organizationId, keypair } = await this.createOrganizationAndKeypair();\n session = await this.handleAuthFlow(organizationId, keypair, authOptions);\n }\n\n // If session is null here, it means we're doing a redirect\n if (!session) {\n // This should not return anything as redirect is happening\n return {\n addresses: [],\n status: \"pending\",\n } as ConnectResult;\n }\n\n // Update session last used timestamp (only for non-redirect flows)\n // For redirect flows, timestamp is updated before redirect to prevent race condition\n if (!authOptions || authOptions.provider === \"jwt\" || this.config.embeddedWalletType === \"app-wallet\") {\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n }\n\n // Initialize client and get addresses\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n } catch (error) {\n // Log the full error details for debugging\n this.logger.error(\"EMBEDDED_PROVIDER\", \"Connect failed with error\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n });\n\n // Enhanced error handling with specific error types\n if (error instanceof Error) {\n // Check for specific error types and provide better error messages\n if (error.message.includes(\"IndexedDB\") || error.message.includes(\"storage\")) {\n throw new Error(\n \"Storage error: Unable to access browser storage. Please ensure storage is available and try again.\",\n );\n }\n\n if (error.message.includes(\"network\") || error.message.includes(\"fetch\")) {\n throw new Error(\n \"Network error: Unable to connect to authentication server. Please check your internet connection and try again.\",\n );\n }\n\n if (error.message.includes(\"JWT\") || error.message.includes(\"jwt\")) {\n throw new Error(`JWT Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"Authentication\") || error.message.includes(\"auth\")) {\n throw new Error(`Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"organization\") || error.message.includes(\"wallet\")) {\n throw new Error(`Wallet creation error: ${error.message}`);\n }\n\n // Re-throw the original error if it's already well-formatted\n throw error;\n }\n\n // Handle unknown error types\n throw new Error(`Embedded wallet connection failed: ${String(error)}`);\n }\n }\n\n async disconnect(): Promise<void> {\n await this.storage.clearSession();\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n }\n\n async signMessage(params: SignMessageParams): Promise<string> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n // Parse message to base64url format for client\n const parsedMessage = parseMessage(params.message);\n\n return await this.client.signMessage({\n walletId: this.walletId,\n message: parsedMessage.base64url,\n networkId: params.networkId,\n });\n }\n\n async signAndSendTransaction(params: SignAndSendTransactionParams): Promise<SignedTransaction> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n // Parse transaction to base64url format for client based on network\n const parsedTransaction = await parseTransaction(params.transaction, params.networkId);\n\n return await this.client.signAndSendTransaction({\n walletId: this.walletId,\n transaction: parsedTransaction.base64url,\n networkId: params.networkId,\n });\n }\n\n getAddresses(): WalletAddress[] {\n return this.addresses;\n }\n\n isConnected(): boolean {\n return this.client !== null && this.walletId !== null;\n }\n\n /*\n * We use this method to route between different authentication flows based on wallet type and auth options.\n * It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.\n * Returns null for redirect flows since they don't complete synchronously.\n */\n private async handleAuthFlow(\n organizationId: string,\n keypair: any,\n authOptions?: AuthOptions,\n ): Promise<Session | null> {\n if (this.config.embeddedWalletType === \"user-wallet\") {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Creating user-wallet, routing authentication\", {\n authProvider: authOptions?.provider || \"phantom-connect\",\n });\n\n // Route to appropriate authentication flow based on authOptions\n if (authOptions?.provider === \"jwt\") {\n return await this.handleJWTAuth(organizationId, keypair, authOptions);\n } else {\n // This will redirect, so we don't return a session\n await this.handleRedirectAuth(organizationId, keypair, authOptions);\n return null;\n }\n } else {\n // Create app-wallet directly\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n },\n new ApiKeyStamper({ apiSecretKey: keypair.secretKey }),\n );\n\n const wallet = await tempClient.createWallet(`Wallet ${Date.now()}`);\n const walletId = wallet.walletId;\n\n // Save session with app-wallet info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: this.config.organizationId,\n keypair,\n authProvider: \"app-wallet\",\n userInfo: { embeddedWalletType: this.config.embeddedWalletType },\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n await this.storage.saveSession(session);\n return session;\n }\n }\n\n /*\n * We use this method to handle JWT-based authentication for user-wallets.\n * It authenticates using the provided JWT token and creates a completed session.\n */\n private async handleJWTAuth(organizationId: string, keypair: any, authOptions: AuthOptions): Promise<Session> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using JWT authentication flow\");\n\n // Use JWT authentication flow\n if (!authOptions.jwtToken) {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"JWT token missing for JWT authentication\");\n throw new Error(\"JWT token is required for JWT authentication\");\n }\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Starting JWT authentication\");\n const authResult = await this.jwtAuth.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n jwtToken: authOptions.jwtToken,\n customAuthData: authOptions.customAuthData,\n });\n const walletId = authResult.walletId;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"JWT authentication completed\", { walletId });\n\n // Save session with auth info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: this.config.organizationId,\n keypair,\n authProvider: authResult.provider,\n userInfo: authResult.userInfo,\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving JWT session\");\n await this.storage.saveSession(session);\n return session;\n }\n\n /*\n * We use this method to handle redirect-based authentication (Google/Apple OAuth).\n * It saves a temporary session before redirecting to prevent losing state during the redirect flow.\n * Session timestamp is updated before redirect to prevent race conditions.\n */\n private async handleRedirectAuth(organizationId: string, keypair: any, authOptions?: AuthOptions): Promise<void> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using Phantom Connect authentication flow (redirect-based)\", {\n provider: authOptions?.provider,\n hasRedirectUrl: !!this.config.authOptions?.redirectUrl,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Use Phantom Connect authentication flow (redirect-based)\n // Store session before redirect so we can restore it after redirect\n const now = Date.now();\n const sessionId = generateSessionId();\n const tempSession = {\n sessionId: sessionId,\n walletId: `temp-${now}`, // Temporary ID, will be updated after redirect\n organizationId: organizationId,\n keypair,\n authProvider: \"phantom-connect\",\n userInfo: { provider: authOptions?.provider },\n status: \"pending\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving temporary session before redirect\", {\n sessionId: tempSession.sessionId,\n tempWalletId: tempSession.walletId,\n });\n\n // Update session timestamp before redirect (prevents race condition)\n tempSession.lastUsed = Date.now();\n await this.storage.saveSession(tempSession);\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting Phantom Connect redirect\", {\n organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Start the authentication flow (this will redirect the user)\n await this.authProvider.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider as \"google\" | \"apple\" | undefined,\n redirectUrl: this.config.authOptions?.redirectUrl,\n customAuthData: authOptions?.customAuthData,\n authUrl: this.config.authOptions?.authUrl,\n sessionId: sessionId,\n });\n }\n\n private async completeAuthConnection(authResult: AuthResult): Promise<ConnectResult> {\n // Check if we have an existing session\n const session = await this.storage.getSession();\n\n if (!session) {\n throw new Error(\"No session found after redirect - session may have expired\");\n }\n\n // Update session with actual wallet ID and auth info from redirect\n session.walletId = authResult.walletId;\n session.authProvider = authResult.provider || session.authProvider;\n session.userInfo = { ...session.userInfo, ...authResult.userInfo };\n session.status = \"completed\";\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n }\n\n /*\n * We use this method to initialize the PhantomClient and fetch wallet addresses from a completed session.\n * This is the final step that sets up the provider's client state and retrieves available addresses.\n */\n private async initializeClientFromSession(session: Session): Promise<void> {\n // Create client from session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing PhantomClient from session\", {\n organizationId: session.organizationId,\n walletId: session.walletId,\n });\n\n const stamper = new ApiKeyStamper({\n apiSecretKey: session.keypair.secretKey,\n });\n\n this.client = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n organizationId: session.organizationId,\n },\n stamper,\n );\n\n this.walletId = session.walletId;\n\n // Get wallet addresses and filter by enabled address types with retry\n this.addresses = await this.getAndFilterWalletAddresses(session.walletId);\n }\n}\n","import type { AuthResult, JWTAuthOptions } from \"../interfaces\";\n\nexport class JWTAuth {\n async authenticate(options: JWTAuthOptions): Promise<AuthResult> {\n // Validate JWT token format\n if (!options.jwtToken || typeof options.jwtToken !== \"string\") {\n throw new Error(\"Invalid JWT token: token must be a non-empty string\");\n }\n\n // Basic JWT format validation (3 parts separated by dots)\n const jwtParts = options.jwtToken.split(\".\");\n if (jwtParts.length !== 3) {\n throw new Error(\"Invalid JWT token format: token must have 3 parts separated by dots\");\n }\n\n // JWT authentication flow - direct API call to create wallet with JWT\n try {\n // This would typically make an API call to your backend\n // which would validate the JWT and create/retrieve the wallet\n const response = await fetch(\"/api/auth/jwt\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.jwtToken}`,\n },\n body: JSON.stringify({\n organizationId: options.organizationId,\n parentOrganizationId: options.parentOrganizationId,\n customAuthData: options.customAuthData,\n }),\n });\n\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.message || errorData.error || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n switch (response.status) {\n case 400:\n throw new Error(`Invalid JWT authentication request: ${errorMessage}`);\n case 401:\n throw new Error(`JWT token is invalid or expired: ${errorMessage}`);\n case 403:\n throw new Error(`JWT authentication forbidden: ${errorMessage}`);\n case 404:\n throw new Error(`JWT authentication endpoint not found: ${errorMessage}`);\n case 429:\n throw new Error(`Too many JWT authentication requests: ${errorMessage}`);\n case 500:\n case 502:\n case 503:\n case 504:\n throw new Error(`JWT authentication server error: ${errorMessage}`);\n default:\n throw new Error(`JWT authentication failed: ${errorMessage}`);\n }\n }\n\n let result;\n try {\n result = await response.json();\n } catch (parseError) {\n throw new Error(\"Invalid response from JWT authentication server: response is not valid JSON\");\n }\n\n if (!result.walletId) {\n throw new Error(\"Invalid JWT authentication response: missing walletId\");\n }\n\n return {\n walletId: result.walletId,\n provider: \"jwt\",\n userInfo: result.userInfo || {},\n };\n } catch (error) {\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n throw new Error(\"JWT authentication failed: network error or invalid endpoint\");\n }\n\n if (error instanceof Error) {\n throw error; // Re-throw known errors\n }\n\n throw new Error(`JWT authentication error: ${String(error)}`);\n }\n }\n}\n","export function generateSessionId(): string {\n return (\n \"session_\" +\n Math.random().toString(36).substring(2, 15) +\n Math.random().toString(36).substring(2, 15) +\n \"_\" +\n Date.now()\n );\n}\n","import type { DebugLogger } from \"../interfaces\";\n\nexport async function retryWithBackoff<T>(\n operation: () => Promise<T>,\n operationName: string,\n logger: DebugLogger,\n maxRetries: number = 3,\n baseDelay: number = 1000,\n): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n logger.log(\"EMBEDDED_PROVIDER\", `Attempting ${operationName}`, {\n attempt,\n maxRetries,\n });\n return await operation();\n } catch (error) {\n lastError = error as Error;\n logger.warn(\"EMBEDDED_PROVIDER\", `${operationName} failed`, {\n attempt,\n maxRetries,\n error: error instanceof Error ? error.message : String(error),\n });\n\n if (attempt === maxRetries) {\n logger.error(\"EMBEDDED_PROVIDER\", `${operationName} failed after ${maxRetries} attempts`, {\n finalError: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Exponential backoff: 1s, 2s, 4s\n const delay = baseDelay * Math.pow(2, attempt - 1);\n logger.log(\"EMBEDDED_PROVIDER\", `Retrying ${operationName} in ${delay}ms`, {\n attempt: attempt + 1,\n delay,\n });\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n\n throw lastError!;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA+C;AAE/C,6BAA8B;AAC9B,qBAA+C;;;ACDxC,IAAM,UAAN,MAAc;AAAA,EACnB,MAAM,aAAa,SAA8C;AAE/D,QAAI,CAAC,QAAQ,YAAY,OAAO,QAAQ,aAAa,UAAU;AAC7D,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AAGA,UAAM,WAAW,QAAQ,SAAS,MAAM,GAAG;AAC3C,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AAGA,QAAI;AAGF,YAAM,WAAW,MAAM,MAAM,iBAAiB;AAAA,QAC5C,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,UAAU,QAAQ,QAAQ;AAAA,QAC3C;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,gBAAgB,QAAQ;AAAA,UACxB,sBAAsB,QAAQ;AAAA,UAC9B,gBAAgB,QAAQ;AAAA,QAC1B,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,YAAI,eAAe,QAAQ,SAAS,MAAM;AAC1C,YAAI;AACF,gBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,yBAAe,UAAU,WAAW,UAAU,SAAS;AAAA,QACzD,QAAQ;AACN,yBAAe,SAAS,cAAc;AAAA,QACxC;AAEA,gBAAQ,SAAS,QAAQ;AAAA,UACvB,KAAK;AACH,kBAAM,IAAI,MAAM,uCAAuC,YAAY,EAAE;AAAA,UACvE,KAAK;AACH,kBAAM,IAAI,MAAM,oCAAoC,YAAY,EAAE;AAAA,UACpE,KAAK;AACH,kBAAM,IAAI,MAAM,iCAAiC,YAAY,EAAE;AAAA,UACjE,KAAK;AACH,kBAAM,IAAI,MAAM,0CAA0C,YAAY,EAAE;AAAA,UAC1E,KAAK;AACH,kBAAM,IAAI,MAAM,yCAAyC,YAAY,EAAE;AAAA,UACzE,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AACH,kBAAM,IAAI,MAAM,oCAAoC,YAAY,EAAE;AAAA,UACpE;AACE,kBAAM,IAAI,MAAM,8BAA8B,YAAY,EAAE;AAAA,QAChE;AAAA,MACF;AAEA,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,SAAS,KAAK;AAAA,MAC/B,SAAS,YAAY;AACnB,cAAM,IAAI,MAAM,6EAA6E;AAAA,MAC/F;AAEA,UAAI,CAAC,OAAO,UAAU;AACpB,cAAM,IAAI,MAAM,uDAAuD;AAAA,MACzE;AAEA,aAAO;AAAA,QACL,UAAU,OAAO;AAAA,QACjB,UAAU;AAAA,QACV,UAAU,OAAO,YAAY,CAAC;AAAA,MAChC;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa,MAAM,QAAQ,SAAS,OAAO,GAAG;AACjE,cAAM,IAAI,MAAM,8DAA8D;AAAA,MAChF;AAEA,UAAI,iBAAiB,OAAO;AAC1B,cAAM;AAAA,MACR;AAEA,YAAM,IAAI,MAAM,6BAA6B,OAAO,KAAK,CAAC,EAAE;AAAA,IAC9D;AAAA,EACF;AACF;;;AC1FO,SAAS,oBAA4B;AAC1C,SACE,aACA,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE,IAC1C,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE,IAC1C,MACA,KAAK,IAAI;AAEb;;;ACNA,eAAsB,iBACpB,WACA,eACA,QACA,aAAqB,GACrB,YAAoB,KACR;AACZ,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,QAAI;AACF,aAAO,IAAI,qBAAqB,cAAc,aAAa,IAAI;AAAA,QAC7D;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,MAAM,UAAU;AAAA,IACzB,SAAS,OAAO;AACd,kBAAY;AACZ,aAAO,KAAK,qBAAqB,GAAG,aAAa,WAAW;AAAA,QAC1D;AAAA,QACA;AAAA,QACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAC;AAED,UAAI,YAAY,YAAY;AAC1B,eAAO,MAAM,qBAAqB,GAAG,aAAa,iBAAiB,UAAU,aAAa;AAAA,UACxF,YAAY,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QACnE,CAAC;AACD;AAAA,MACF;AAGA,YAAM,QAAQ,YAAY,KAAK,IAAI,GAAG,UAAU,CAAC;AACjD,aAAO,IAAI,qBAAqB,YAAY,aAAa,OAAO,KAAK,MAAM;AAAA,QACzE,SAAS,UAAU;AAAA,QACnB;AAAA,MACF,CAAC;AACD,YAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,KAAK,CAAC;AAAA,IACzD;AAAA,EACF;AAEA,QAAM;AACR;;;AHjBO,IAAM,mBAAN,MAAuB;AAAA,EAW5B,YAAY,QAAgC,UAA2B,QAAqB;AAL5F,SAAQ,SAA+B;AACvC,SAAQ,WAA0B;AAClC,SAAQ,YAA6B,CAAC;AAIpC,SAAK,SAAS;AACd,SAAK,OAAO,IAAI,qBAAqB,iCAAiC,EAAE,OAAO,CAAC;AAEhF,SAAK,SAAS;AACd,SAAK,UAAU,SAAS;AACxB,SAAK,eAAe,SAAS;AAC7B,SAAK,oBAAoB,SAAS;AAClC,SAAK,UAAU,IAAI,QAAQ;AAG3B,WAAO;AACP,SAAK,OAAO,KAAK,qBAAqB,8BAA8B;AAAA,EACtE;AAAA,EAEA,MAAc,4BAA4B,UAA4C;AAEpF,UAAM,YAAY,MAAM;AAAA,MACtB,MAAM,KAAK,OAAQ,mBAAmB,QAAQ;AAAA,MAC9C;AAAA,MACA,KAAK;AAAA,IACP,EAAE,MAAM,OAAM,UAAS;AACrB,WAAK,OAAO,MAAM,qBAAqB,0DAA0D;AAAA,QAC/F;AAAA,QACA,OAAO,MAAM;AAAA,MACf,CAAC;AAED,YAAM,KAAK,QAAQ,aAAa;AAChC,WAAK,SAAS;AACd,WAAK,WAAW;AAChB,WAAK,YAAY,CAAC;AAClB,YAAM;AAAA,IACR,CAAC;AAGD,WAAO,UACJ,OAAO,UAAQ,KAAK,OAAO,aAAa,KAAK,UAAQ,SAAS,KAAK,WAAW,CAAC,EAC/E,IAAI,WAAS;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,SAAS,KAAK;AAAA,IAChB,EAAE;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,wBAAwB,SAAkD;AACtF,QAAI,CAAC;AAAS,aAAO;AAErB,SAAK,OAAO,IAAI,qBAAqB,sCAAsC;AAAA,MACzE,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAGD,QAAI,QAAQ,WAAW,aAAa;AAClC,YAAM,eAAe,KAAK,kBAAkB,SAAS,YAAY;AAGjE,UAAI,QAAQ,WAAW,aAAa,CAAC,cAAc;AACjD,aAAK,OAAO,KAAK,qBAAqB,wEAAwE;AAAA,UAC5G,WAAW,QAAQ;AAAA,UACnB,QAAQ,QAAQ;AAAA,QAClB,CAAC;AAED,cAAM,KAAK,QAAQ,aAAa;AAChC,eAAO;AAAA,MACT,WAES,gBAAgB,iBAAiB,QAAQ,WAAW;AAC3D,aAAK,OAAO,KAAK,qBAAqB,gCAAgC;AAAA,UACpE,iBAAiB,QAAQ;AAAA,UACzB;AAAA,QACF,CAAC;AACD,cAAM,KAAK,QAAQ,aAAa;AAChC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAoB,aAAiC;AAC3D,QAAI,CAAC;AAAa;AAElB,QAAI,YAAY,YAAY,CAAC,CAAC,UAAU,SAAS,KAAK,EAAE,SAAS,YAAY,QAAQ,GAAG;AACtF,YAAM,IAAI,MAAM,0BAA0B,YAAY,QAAQ,uCAAuC;AAAA,IACvG;AAEA,QAAI,YAAY,aAAa,SAAS,CAAC,YAAY,UAAU;AAC3D,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,+BAAkF;AAE9F,SAAK,OAAO,IAAI,qBAAqB,oBAAoB;AACzD,UAAM,cAAU,+BAAgB;AAChC,SAAK,OAAO,IAAI,qBAAqB,qBAAqB,EAAE,WAAW,QAAQ,UAAU,CAAC;AAG1F,SAAK,OAAO,IAAI,qBAAqB,kCAAkC;AACvE,UAAM,UAAU,IAAI,qCAAc;AAAA,MAChC,cAAc,QAAQ;AAAA,IACxB,CAAC;AAED,UAAM,aAAa,IAAI;AAAA,MACrB;AAAA,QACE,YAAY,KAAK,OAAO;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAIA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,mBAAmB,GAAG,KAAK,OAAO,cAAc,IAAI,GAAG;AAC7D,SAAK,OAAO,IAAI,qBAAqB,yBAAyB,EAAE,iBAAiB,CAAC;AAClF,UAAM,EAAE,eAAe,IAAI,MAAM,WAAW,mBAAmB,kBAAkB,OAAO;AACxF,SAAK,OAAO,KAAK,qBAAqB,wBAAwB,EAAE,eAAe,CAAC;AAEhF,WAAO,EAAE,gBAAgB,QAAQ;AAAA,EACnC;AAAA,EAEA,MAAM,QAAQ,aAAmD;AAC/D,QAAI;AACF,WAAK,OAAO,KAAK,qBAAqB,sCAAsC;AAAA,QAC1E,aAAa,cACT;AAAA,UACE,UAAU,YAAY;AAAA,UACtB,aAAa,CAAC,CAAC,YAAY;AAAA,QAC7B,IACA;AAAA,MACN,CAAC;AAGD,WAAK,OAAO,IAAI,qBAAqB,0BAA0B;AAC/D,UAAI,UAAU,MAAM,KAAK,QAAQ,WAAW;AAC5C,gBAAU,MAAM,KAAK,wBAAwB,OAAO;AAGpD,WAAK,OAAO,IAAI,qBAAqB,8BAA8B;AACnE,UAAI,KAAK,aAAa,wBAAwB;AAC5C,cAAM,aAAa,KAAK,aAAa,uBAAuB;AAC5D,YAAI,YAAY;AACd,eAAK,OAAO,KAAK,qBAAqB,0BAA0B;AAAA,YAC9D,UAAU,WAAW;AAAA,YACrB,UAAU,WAAW;AAAA,UACvB,CAAC;AACD,iBAAO,KAAK,uBAAuB,UAAU;AAAA,QAC/C;AAAA,MACF;AAGA,WAAK,oBAAoB,WAAW;AAGpC,UAAI,CAAC,SAAS;AACZ,aAAK,OAAO,KAAK,qBAAqB,uCAAuC;AAC7E,cAAM,EAAE,gBAAgB,QAAQ,IAAI,MAAM,KAAK,6BAA6B;AAC5E,kBAAU,MAAM,KAAK,eAAe,gBAAgB,SAAS,WAAW;AAAA,MAC1E;AAGA,UAAI,CAAC,SAAS;AAEZ,eAAO;AAAA,UACL,WAAW,CAAC;AAAA,UACZ,QAAQ;AAAA,QACV;AAAA,MACF;AAIA,UAAI,CAAC,eAAe,YAAY,aAAa,SAAS,KAAK,OAAO,uBAAuB,cAAc;AACrG,gBAAQ,WAAW,KAAK,IAAI;AAC5B,cAAM,KAAK,QAAQ,YAAY,OAAO;AAAA,MACxC;AAGA,YAAM,KAAK,4BAA4B,OAAO;AAE9C,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,WAAW,KAAK;AAAA,QAChB,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,OAAO;AAEd,WAAK,OAAO,MAAM,qBAAqB,6BAA6B;AAAA,QAClE,OACE,iBAAiB,QACb;AAAA,UACE,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,UACf,OAAO,MAAM;AAAA,QACf,IACA;AAAA,MACR,CAAC;AAGD,UAAI,iBAAiB,OAAO;AAE1B,YAAI,MAAM,QAAQ,SAAS,WAAW,KAAK,MAAM,QAAQ,SAAS,SAAS,GAAG;AAC5E,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,MAAM,QAAQ,SAAS,SAAS,KAAK,MAAM,QAAQ,SAAS,OAAO,GAAG;AACxE,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,MAAM,QAAQ,SAAS,KAAK,KAAK,MAAM,QAAQ,SAAS,KAAK,GAAG;AAClE,gBAAM,IAAI,MAAM,6BAA6B,MAAM,OAAO,EAAE;AAAA,QAC9D;AAEA,YAAI,MAAM,QAAQ,SAAS,gBAAgB,KAAK,MAAM,QAAQ,SAAS,MAAM,GAAG;AAC9E,gBAAM,IAAI,MAAM,yBAAyB,MAAM,OAAO,EAAE;AAAA,QAC1D;AAEA,YAAI,MAAM,QAAQ,SAAS,cAAc,KAAK,MAAM,QAAQ,SAAS,QAAQ,GAAG;AAC9E,gBAAM,IAAI,MAAM,0BAA0B,MAAM,OAAO,EAAE;AAAA,QAC3D;AAGA,cAAM;AAAA,MACR;AAGA,YAAM,IAAI,MAAM,sCAAsC,OAAO,KAAK,CAAC,EAAE;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,QAAQ,aAAa;AAChC,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,YAAY,CAAC;AAAA,EACpB;AAAA,EAEA,MAAM,YAAY,QAA4C;AAC5D,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU;AAClC,YAAM,IAAI,MAAM,eAAe;AAAA,IACjC;AAGA,UAAM,oBAAgB,6BAAa,OAAO,OAAO;AAEjD,WAAO,MAAM,KAAK,OAAO,YAAY;AAAA,MACnC,UAAU,KAAK;AAAA,MACf,SAAS,cAAc;AAAA,MACvB,WAAW,OAAO;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,uBAAuB,QAAkE;AAC7F,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU;AAClC,YAAM,IAAI,MAAM,eAAe;AAAA,IACjC;AAGA,UAAM,oBAAoB,UAAM,iCAAiB,OAAO,aAAa,OAAO,SAAS;AAErF,WAAO,MAAM,KAAK,OAAO,uBAAuB;AAAA,MAC9C,UAAU,KAAK;AAAA,MACf,aAAa,kBAAkB;AAAA,MAC/B,WAAW,OAAO;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,eAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,WAAW,QAAQ,KAAK,aAAa;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,eACZ,gBACA,SACA,aACyB;AACzB,QAAI,KAAK,OAAO,uBAAuB,eAAe;AACpD,WAAK,OAAO,KAAK,qBAAqB,gDAAgD;AAAA,QACpF,cAAc,aAAa,YAAY;AAAA,MACzC,CAAC;AAGD,UAAI,aAAa,aAAa,OAAO;AACnC,eAAO,MAAM,KAAK,cAAc,gBAAgB,SAAS,WAAW;AAAA,MACtE,OAAO;AAEL,cAAM,KAAK,mBAAmB,gBAAgB,SAAS,WAAW;AAClE,eAAO;AAAA,MACT;AAAA,IACF,OAAO;AAEL,YAAM,aAAa,IAAI;AAAA,QACrB;AAAA,UACE,YAAY,KAAK,OAAO;AAAA,QAC1B;AAAA,QACA,IAAI,qCAAc,EAAE,cAAc,QAAQ,UAAU,CAAC;AAAA,MACvD;AAEA,YAAM,SAAS,MAAM,WAAW,aAAa,UAAU,KAAK,IAAI,CAAC,EAAE;AACnE,YAAM,WAAW,OAAO;AAGxB,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,UAAU;AAAA,QACd,WAAW,kBAAkB;AAAA,QAC7B;AAAA,QACA,gBAAgB,KAAK,OAAO;AAAA,QAC5B;AAAA,QACA,cAAc;AAAA,QACd,UAAU,EAAE,oBAAoB,KAAK,OAAO,mBAAmB;AAAA,QAC/D,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,UAAU;AAAA,MACZ;AACA,YAAM,KAAK,QAAQ,YAAY,OAAO;AACtC,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,cAAc,gBAAwB,SAAc,aAA4C;AAC5G,SAAK,OAAO,KAAK,qBAAqB,+BAA+B;AAGrE,QAAI,CAAC,YAAY,UAAU;AACzB,WAAK,OAAO,MAAM,qBAAqB,0CAA0C;AACjF,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AAEA,SAAK,OAAO,IAAI,qBAAqB,6BAA6B;AAClE,UAAM,aAAa,MAAM,KAAK,QAAQ,aAAa;AAAA,MACjD;AAAA,MACA,sBAAsB,KAAK,OAAO;AAAA,MAClC,UAAU,YAAY;AAAA,MACtB,gBAAgB,YAAY;AAAA,IAC9B,CAAC;AACD,UAAM,WAAW,WAAW;AAC5B,SAAK,OAAO,KAAK,qBAAqB,gCAAgC,EAAE,SAAS,CAAC;AAGlF,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UAAU;AAAA,MACd,WAAW,kBAAkB;AAAA,MAC7B;AAAA,MACA,gBAAgB,KAAK,OAAO;AAAA,MAC5B;AAAA,MACA,cAAc,WAAW;AAAA,MACzB,UAAU,WAAW;AAAA,MACrB,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AACA,SAAK,OAAO,IAAI,qBAAqB,oBAAoB;AACzD,UAAM,KAAK,QAAQ,YAAY,OAAO;AACtC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,mBAAmB,gBAAwB,SAAc,aAA0C;AAC/G,SAAK,OAAO,KAAK,qBAAqB,8DAA8D;AAAA,MAClG,UAAU,aAAa;AAAA,MACvB,gBAAgB,CAAC,CAAC,KAAK,OAAO,aAAa;AAAA,MAC3C,SAAS,KAAK,OAAO,aAAa;AAAA,IACpC,CAAC;AAID,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,YAAY,kBAAkB;AACpC,UAAM,cAAc;AAAA,MAClB;AAAA,MACA,UAAU,QAAQ,GAAG;AAAA;AAAA,MACrB;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,UAAU,EAAE,UAAU,aAAa,SAAS;AAAA,MAC5C,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AACA,SAAK,OAAO,IAAI,qBAAqB,4CAA4C;AAAA,MAC/E,WAAW,YAAY;AAAA,MACvB,cAAc,YAAY;AAAA,IAC5B,CAAC;AAGD,gBAAY,WAAW,KAAK,IAAI;AAChC,UAAM,KAAK,QAAQ,YAAY,WAAW;AAE1C,SAAK,OAAO,KAAK,qBAAqB,qCAAqC;AAAA,MACzE;AAAA,MACA,sBAAsB,KAAK,OAAO;AAAA,MAClC,UAAU,aAAa;AAAA,MACvB,SAAS,KAAK,OAAO,aAAa;AAAA,IACpC,CAAC;AAGD,UAAM,KAAK,aAAa,aAAa;AAAA,MACnC;AAAA,MACA,sBAAsB,KAAK,OAAO;AAAA,MAClC,UAAU,aAAa;AAAA,MACvB,aAAa,KAAK,OAAO,aAAa;AAAA,MACtC,gBAAgB,aAAa;AAAA,MAC7B,SAAS,KAAK,OAAO,aAAa;AAAA,MAClC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,uBAAuB,YAAgD;AAEnF,UAAM,UAAU,MAAM,KAAK,QAAQ,WAAW;AAE9C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,4DAA4D;AAAA,IAC9E;AAGA,YAAQ,WAAW,WAAW;AAC9B,YAAQ,eAAe,WAAW,YAAY,QAAQ;AACtD,YAAQ,WAAW,EAAE,GAAG,QAAQ,UAAU,GAAG,WAAW,SAAS;AACjE,YAAQ,SAAS;AACjB,YAAQ,WAAW,KAAK,IAAI;AAC5B,UAAM,KAAK,QAAQ,YAAY,OAAO;AAEtC,UAAM,KAAK,4BAA4B,OAAO;AAE9C,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,WAAW,KAAK;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,4BAA4B,SAAiC;AAEzE,SAAK,OAAO,IAAI,qBAAqB,2CAA2C;AAAA,MAC9E,gBAAgB,QAAQ;AAAA,MACxB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAED,UAAM,UAAU,IAAI,qCAAc;AAAA,MAChC,cAAc,QAAQ,QAAQ;AAAA,IAChC,CAAC;AAED,SAAK,SAAS,IAAI;AAAA,MAChB;AAAA,QACE,YAAY,KAAK,OAAO;AAAA,QACxB,gBAAgB,QAAQ;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAEA,SAAK,WAAW,QAAQ;AAGxB,SAAK,YAAY,MAAM,KAAK,4BAA4B,QAAQ,QAAQ;AAAA,EAC1E;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/embedded-provider.ts","../src/auth/jwt-auth.ts","../src/utils/session.ts","../src/utils/retry.ts"],"sourcesContent":["export * from \"./interfaces\";\nexport * from \"./types\";\nexport * from \"./embedded-provider\";\nexport * from \"./auth/jwt-auth\";\nexport * from \"./utils/session\";\nexport * from \"./utils/retry\";\n","import { PhantomClient } from \"@phantom/client\";\nimport type { AddressType } from \"@phantom/client\";\nimport { base64urlEncode } from \"@phantom/base64url\";\nimport bs58 from \"bs58\";\nimport {\n parseMessage,\n parseTransaction,\n parseSignMessageResponse,\n parseTransactionResponse,\n type ParsedTransactionResult,\n type ParsedSignatureResult,\n} from \"@phantom/parsers\";\n\nimport type {\n PlatformAdapter,\n Session,\n AuthResult,\n DebugLogger,\n EmbeddedStorage,\n AuthProvider,\n URLParamsAccessor,\n StamperInfo,\n} from \"./interfaces\";\nimport type {\n EmbeddedProviderConfig,\n ConnectResult,\n SignMessageParams,\n SignAndSendTransactionParams,\n WalletAddress,\n AuthOptions,\n} from \"./types\";\nimport { JWTAuth } from \"./auth/jwt-auth\";\nimport { generateSessionId } from \"./utils/session\";\nimport { retryWithBackoff } from \"./utils/retry\";\nimport type { StamperWithKeyManagement } from \"@phantom/sdk-types\";\nexport class EmbeddedProvider {\n private config: EmbeddedProviderConfig;\n private platform: PlatformAdapter;\n private storage: EmbeddedStorage;\n private authProvider: AuthProvider;\n private urlParamsAccessor: URLParamsAccessor;\n private stamper: StamperWithKeyManagement;\n private logger: DebugLogger;\n private client: PhantomClient | null = null;\n private walletId: string | null = null;\n private addresses: WalletAddress[] = [];\n private jwtAuth: JWTAuth;\n\n constructor(config: EmbeddedProviderConfig, platform: PlatformAdapter, logger: DebugLogger) {\n this.logger = logger;\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing EmbeddedProvider\", { config });\n\n this.config = config;\n this.platform = platform;\n this.storage = platform.storage;\n this.authProvider = platform.authProvider;\n this.urlParamsAccessor = platform.urlParamsAccessor;\n this.stamper = platform.stamper;\n this.jwtAuth = new JWTAuth();\n\n // Store solana provider config (unused for now)\n config.solanaProvider;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"EmbeddedProvider initialized\");\n }\n\n private async getAndFilterWalletAddresses(walletId: string): Promise<WalletAddress[]> {\n // Get wallet addresses with retry and auto-disconnect on failure\n const addresses = await retryWithBackoff(\n () => this.client!.getWalletAddresses(walletId),\n \"getWalletAddresses\",\n this.logger,\n ).catch(async error => {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"getWalletAddresses failed after retries, disconnecting\", {\n walletId,\n error: error.message,\n });\n // Clear the session if getWalletAddresses fails after retries\n await this.storage.clearSession();\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n throw error;\n });\n\n // Filter by enabled address types and return formatted addresses\n return addresses\n .filter(addr => this.config.addressTypes.some(type => type === addr.addressType))\n .map(addr => ({\n addressType: addr.addressType as AddressType,\n address: addr.address,\n }));\n }\n\n /*\n * We use this method to make sure the session is not invalid, or there's a different session id in the url.\n * If there's a different one, we delete the current session and start from scratch.\n * This prevents issues where users have stale sessions or URL mismatches after redirects.\n */\n private async validateAndCleanSession(session: Session | null): Promise<Session | null> {\n if (!session) return null;\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Found existing session, validating\", {\n sessionId: session.sessionId,\n status: session.status,\n walletId: session.walletId,\n });\n\n // If session is not completed, check if we're in the right context\n if (session.status !== \"completed\") {\n const urlSessionId = this.urlParamsAccessor.getParam(\"session_id\");\n\n // If we have a pending session but no sessionId in URL, this is a mismatch\n if (session.status === \"pending\" && !urlSessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session mismatch detected - pending session without redirect context\", {\n sessionId: session.sessionId,\n status: session.status,\n });\n // Clear the invalid session and start fresh\n await this.storage.clearSession();\n return null;\n }\n // If sessionId in URL doesn't match stored session, clear invalid session\n else if (urlSessionId && urlSessionId !== session.sessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session ID mismatch detected\", {\n storedSessionId: session.sessionId,\n urlSessionId: urlSessionId,\n });\n await this.storage.clearSession();\n return null;\n }\n }\n\n return session;\n }\n\n /*\n * We use this method to validate authentication options before processing them.\n * This ensures only supported auth providers are used and required tokens are present.\n */\n private validateAuthOptions(authOptions?: AuthOptions): void {\n if (!authOptions) return;\n\n if (authOptions.provider && ![\"google\", \"apple\", \"jwt\"].includes(authOptions.provider)) {\n throw new Error(`Invalid auth provider: ${authOptions.provider}. Must be \"google\", \"apple\", or \"jwt\"`);\n }\n\n if (authOptions.provider === \"jwt\" && !authOptions.jwtToken) {\n throw new Error(\"JWT token is required when using JWT authentication\");\n }\n }\n\n /*\n * We use this method to initialize the stamper and create an organization for new sessions.\n * This is the first step when no existing session is found and we need to set up a new wallet.\n */\n private async createOrganizationAndStamper(): Promise<{ organizationId: string; stamperInfo: StamperInfo }> {\n // Initialize stamper (generates keypair in IndexedDB)\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing stamper\");\n const stamperInfo = await this.stamper.init();\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Stamper initialized\", {\n publicKey: stamperInfo.publicKey,\n keyId: stamperInfo.keyId,\n algorithm: this.stamper.algorithm,\n });\n\n // Create a temporary client with the stamper\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating temporary PhantomClient\");\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n },\n this.stamper,\n );\n\n // Create an organization\n // organization name is a combination of this organizationId and this userId, which will be a unique identifier\n const platformName = this.platform.name || \"unknown\";\n const shortPubKey = stamperInfo.publicKey.slice(0, 8);\n const organizationName = `${this.config.organizationId}-${platformName}-${shortPubKey}`;\n\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating organization\", {\n organizationName,\n publicKey: stamperInfo.publicKey,\n platform: platformName,\n });\n\n // Convert base58 public key to base64url format as required by the API\n const base64urlPublicKey = base64urlEncode(bs58.decode(stamperInfo.publicKey));\n \n const { organizationId } = await tempClient.createOrganization(\n organizationName,\n [{\n username: `user-${shortPubKey}`,\n role: 'admin',\n authenticators: [{\n authenticatorName: `auth-${shortPubKey}`,\n authenticatorKind: 'keypair',\n publicKey: base64urlPublicKey,\n algorithm: 'Ed25519',\n }]\n }]\n );\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Organization created\", { organizationId });\n\n return { organizationId, stamperInfo };\n }\n\n async connect(authOptions?: AuthOptions): Promise<ConnectResult> {\n try {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting embedded provider connect\", {\n authOptions: authOptions\n ? {\n provider: authOptions.provider,\n hasJwtToken: !!authOptions.jwtToken,\n }\n : undefined,\n });\n\n // Get and validate existing session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Getting existing session\");\n let session = await this.storage.getSession();\n session = await this.validateAndCleanSession(session);\n\n // First, check if we're resuming from a redirect\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Checking for redirect resume\");\n if (this.authProvider.resumeAuthFromRedirect) {\n const authResult = this.authProvider.resumeAuthFromRedirect();\n if (authResult) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Resuming from redirect\", {\n walletId: authResult.walletId,\n provider: authResult.provider,\n });\n return this.completeAuthConnection(authResult);\n }\n }\n\n // Validate auth options\n this.validateAuthOptions(authOptions);\n\n // If no session exists, create new one\n if (!session) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"No existing session, creating new one\");\n const { organizationId, stamperInfo } = await this.createOrganizationAndStamper();\n session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions);\n }\n\n // If session is null here, it means we're doing a redirect\n if (!session) {\n // This should not return anything as redirect is happening\n return {\n addresses: [],\n status: \"pending\",\n } as ConnectResult;\n }\n\n // Update session last used timestamp (only for non-redirect flows)\n // For redirect flows, timestamp is updated before redirect to prevent race condition\n if (!authOptions || authOptions.provider === \"jwt\" || this.config.embeddedWalletType === \"app-wallet\") {\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n }\n\n // Initialize client and get addresses\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n } catch (error) {\n // Log the full error details for debugging\n this.logger.error(\"EMBEDDED_PROVIDER\", \"Connect failed with error\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n });\n\n // Enhanced error handling with specific error types\n if (error instanceof Error) {\n // Check for specific error types and provide better error messages\n if (error.message.includes(\"IndexedDB\") || error.message.includes(\"storage\")) {\n throw new Error(\n \"Storage error: Unable to access browser storage. Please ensure storage is available and try again.\",\n );\n }\n\n if (error.message.includes(\"network\") || error.message.includes(\"fetch\")) {\n throw new Error(\n \"Network error: Unable to connect to authentication server. Please check your internet connection and try again.\",\n );\n }\n\n if (error.message.includes(\"JWT\") || error.message.includes(\"jwt\")) {\n throw new Error(`JWT Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"Authentication\") || error.message.includes(\"auth\")) {\n throw new Error(`Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"organization\") || error.message.includes(\"wallet\")) {\n throw new Error(`Wallet creation error: ${error.message}`);\n }\n\n // Re-throw the original error if it's already well-formatted\n throw error;\n }\n\n // Handle unknown error types\n throw new Error(`Embedded wallet connection failed: ${String(error)}`);\n }\n }\n\n async disconnect(): Promise<void> {\n await this.storage.clearSession();\n\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Disconnected from embedded wallet\");\n }\n\n async signMessage(params: SignMessageParams): Promise<ParsedSignatureResult> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Signing message\", {\n walletId: this.walletId,\n message: params.message,\n });\n\n // Parse message to base64url format for client\n const parsedMessage = parseMessage(params.message);\n\n // Get raw response from client\n const rawResponse = await this.client.signMessage({\n walletId: this.walletId,\n message: parsedMessage.base64url,\n networkId: params.networkId,\n });\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Message signed successfully\", {\n walletId: this.walletId,\n message: params.message,\n });\n\n // Parse the response to get human-readable signature and explorer URL\n return parseSignMessageResponse(rawResponse, params.networkId);\n }\n\n async signAndSendTransaction(params: SignAndSendTransactionParams): Promise<ParsedTransactionResult> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Signing and sending transaction\", {\n walletId: this.walletId,\n networkId: params.networkId,\n });\n\n // Parse transaction to base64url format for client based on network\n const parsedTransaction = await parseTransaction(params.transaction, params.networkId);\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Parsed transaction for signing\", {\n walletId: this.walletId,\n transaction: parsedTransaction,\n });\n\n // Get raw response from client\n const rawResponse = await this.client.signAndSendTransaction({\n walletId: this.walletId,\n transaction: parsedTransaction.base64url,\n networkId: params.networkId,\n });\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Transaction signed and sent successfully\", {\n walletId: this.walletId,\n networkId: params.networkId,\n hash: rawResponse.hash,\n rawTransaction: rawResponse.rawTransaction,\n });\n\n // Parse the response to get transaction hash and explorer URL\n return await parseTransactionResponse(rawResponse.rawTransaction, params.networkId, rawResponse.hash);\n }\n\n getAddresses(): WalletAddress[] {\n return this.addresses;\n }\n\n isConnected(): boolean {\n return this.client !== null && this.walletId !== null;\n }\n\n /*\n * We use this method to route between different authentication flows based on wallet type and auth options.\n * It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.\n * Returns null for redirect flows since they don't complete synchronously.\n */\n private async handleAuthFlow(\n organizationId: string,\n stamperInfo: StamperInfo,\n authOptions?: AuthOptions,\n ): Promise<Session | null> {\n if (this.config.embeddedWalletType === \"user-wallet\") {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Creating user-wallet, routing authentication\", {\n authProvider: authOptions?.provider || \"phantom-connect\",\n });\n\n // Route to appropriate authentication flow based on authOptions\n if (authOptions?.provider === \"jwt\") {\n return await this.handleJWTAuth(organizationId, stamperInfo, authOptions);\n } else {\n // This will redirect in browser, so we don't return a session\n // In react-native this will return an auth result\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting redirect-based authentication flow\", {\n organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider,\n });\n return await this.handleRedirectAuth(organizationId, stamperInfo, authOptions);\n }\n } else {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Creating app-wallet\", {\n organizationId,\n });\n // Create app-wallet directly\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n organizationId: organizationId,\n },\n this.stamper,\n );\n\n const wallet = await tempClient.createWallet(`Wallet ${Date.now()}`);\n const walletId = wallet.walletId;\n\n // Save session with app-wallet info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: organizationId,\n stamperInfo,\n authProvider: \"app-wallet\",\n userInfo: { embeddedWalletType: this.config.embeddedWalletType },\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n\n await this.storage.saveSession(session);\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"App-wallet created successfully\", { walletId, organizationId });\n return session;\n }\n }\n\n /*\n * We use this method to handle JWT-based authentication for user-wallets.\n * It authenticates using the provided JWT token and creates a completed session.\n */\n private async handleJWTAuth(\n organizationId: string,\n stamperInfo: StamperInfo,\n authOptions: AuthOptions,\n ): Promise<Session> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using JWT authentication flow\");\n\n // Use JWT authentication flow\n if (!authOptions.jwtToken) {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"JWT token missing for JWT authentication\");\n throw new Error(\"JWT token is required for JWT authentication\");\n }\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Starting JWT authentication\");\n const authResult = await this.jwtAuth.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n jwtToken: authOptions.jwtToken,\n customAuthData: authOptions.customAuthData,\n });\n const walletId = authResult.walletId;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"JWT authentication completed\", { walletId });\n\n // Save session with auth info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: organizationId,\n stamperInfo,\n authProvider: authResult.provider,\n userInfo: authResult.userInfo,\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving JWT session\");\n await this.storage.saveSession(session);\n return session;\n }\n\n /*\n * We use this method to handle redirect-based authentication (Google/Apple OAuth).\n * It saves a temporary session before redirecting to prevent losing state during the redirect flow.\n * Session timestamp is updated before redirect to prevent race conditions.\n */\n private async handleRedirectAuth(\n organizationId: string,\n stamperInfo: StamperInfo,\n authOptions?: AuthOptions,\n ): Promise<Session | null> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using Phantom Connect authentication flow (redirect-based)\", {\n provider: authOptions?.provider,\n hasRedirectUrl: !!this.config.authOptions?.redirectUrl,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Use Phantom Connect authentication flow (redirect-based)\n // Store session before redirect so we can restore it after redirect\n const now = Date.now();\n const sessionId = generateSessionId();\n const tempSession: Session = {\n sessionId: sessionId,\n walletId: `temp-${now}`, // Temporary ID, will be updated after redirect\n organizationId: organizationId,\n stamperInfo,\n authProvider: \"phantom-connect\",\n userInfo: { provider: authOptions?.provider },\n status: \"pending\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving temporary session before redirect\", {\n sessionId: tempSession.sessionId,\n tempWalletId: tempSession.walletId,\n });\n\n // Update session timestamp before redirect (prevents race condition)\n tempSession.lastUsed = Date.now();\n await this.storage.saveSession(tempSession);\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting Phantom Connect redirect\", {\n organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Start the authentication flow (this will redirect the user in the browser, or handle it in React Native)\n const authResult = await this.authProvider.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider as \"google\" | \"apple\" | undefined,\n redirectUrl: this.config.authOptions?.redirectUrl,\n customAuthData: authOptions?.customAuthData,\n authUrl: this.config.authOptions?.authUrl,\n sessionId: sessionId,\n appName: this.config.appName,\n appLogo: this.config.appLogo,\n });\n\n if (authResult && \"walletId\" in authResult) {\n // If we got an auth result, we need to update the session with actual wallet ID\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Authentication completed after redirect\", {\n walletId: authResult.walletId,\n provider: authResult.provider,\n });\n\n // Update the temporary session with actual wallet ID and auth info\n tempSession.walletId = authResult.walletId;\n tempSession.authProvider = authResult.provider || tempSession.authProvider;\n tempSession.status = \"completed\";\n tempSession.lastUsed = Date.now();\n await this.storage.saveSession(tempSession);\n\n return tempSession; // Return the auth result for further processing\n }\n // If we don't have an auth result, it means we're in a redirect flow\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Redirect authentication initiated, waiting for redirect completion\");\n // In this case, we don't return anything as the redirect will handle the rest\n return null;\n }\n\n private async completeAuthConnection(authResult: AuthResult): Promise<ConnectResult> {\n // Check if we have an existing session\n const session = await this.storage.getSession();\n\n if (!session) {\n throw new Error(\"No session found after redirect - session may have expired\");\n }\n\n // Update session with actual wallet ID and auth info from redirect\n session.walletId = authResult.walletId;\n session.authProvider = authResult.provider || session.authProvider;\n session.status = \"completed\";\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n }\n\n /*\n * We use this method to initialize the PhantomClient and fetch wallet addresses from a completed session.\n * This is the final step that sets up the provider's client state and retrieves available addresses.\n */\n private async initializeClientFromSession(session: Session): Promise<void> {\n // Create client from session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing PhantomClient from session\", {\n organizationId: session.organizationId,\n walletId: session.walletId,\n });\n\n // Ensure stamper is initialized with existing keys\n if (!this.stamper.getKeyInfo()) {\n await this.stamper.init();\n }\n\n this.client = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n organizationId: session.organizationId,\n },\n this.stamper,\n );\n\n this.walletId = session.walletId;\n\n // Get wallet addresses and filter by enabled address types with retry\n this.addresses = await this.getAndFilterWalletAddresses(session.walletId);\n }\n}\n","import type { AuthResult, JWTAuthOptions } from \"../interfaces\";\n\nexport class JWTAuth {\n async authenticate(options: JWTAuthOptions): Promise<AuthResult> {\n // Validate JWT token format\n if (!options.jwtToken || typeof options.jwtToken !== \"string\") {\n throw new Error(\"Invalid JWT token: token must be a non-empty string\");\n }\n\n // Basic JWT format validation (3 parts separated by dots)\n const jwtParts = options.jwtToken.split(\".\");\n if (jwtParts.length !== 3) {\n throw new Error(\"Invalid JWT token format: token must have 3 parts separated by dots\");\n }\n\n // JWT authentication flow - direct API call to create wallet with JWT\n try {\n // This would typically make an API call to your backend\n // which would validate the JWT and create/retrieve the wallet\n const response = await fetch(\"/api/auth/jwt\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.jwtToken}`,\n },\n body: JSON.stringify({\n organizationId: options.organizationId,\n parentOrganizationId: options.parentOrganizationId,\n customAuthData: options.customAuthData,\n }),\n });\n\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.message || errorData.error || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n switch (response.status) {\n case 400:\n throw new Error(`Invalid JWT authentication request: ${errorMessage}`);\n case 401:\n throw new Error(`JWT token is invalid or expired: ${errorMessage}`);\n case 403:\n throw new Error(`JWT authentication forbidden: ${errorMessage}`);\n case 404:\n throw new Error(`JWT authentication endpoint not found: ${errorMessage}`);\n case 429:\n throw new Error(`Too many JWT authentication requests: ${errorMessage}`);\n case 500:\n case 502:\n case 503:\n case 504:\n throw new Error(`JWT authentication server error: ${errorMessage}`);\n default:\n throw new Error(`JWT authentication failed: ${errorMessage}`);\n }\n }\n\n let result;\n try {\n result = await response.json();\n } catch (parseError) {\n throw new Error(\"Invalid response from JWT authentication server: response is not valid JSON\");\n }\n\n if (!result.walletId) {\n throw new Error(\"Invalid JWT authentication response: missing walletId\");\n }\n\n return {\n walletId: result.walletId,\n provider: \"jwt\",\n userInfo: result.userInfo || {},\n };\n } catch (error) {\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n throw new Error(\"JWT authentication failed: network error or invalid endpoint\");\n }\n\n if (error instanceof Error) {\n throw error; // Re-throw known errors\n }\n\n throw new Error(`JWT authentication error: ${String(error)}`);\n }\n }\n}\n","export function generateSessionId(): string {\n return (\n \"session_\" +\n Math.random().toString(36).substring(2, 15) +\n Math.random().toString(36).substring(2, 15) +\n \"_\" +\n Date.now()\n );\n}\n","import type { DebugLogger } from \"../interfaces\";\n\nexport async function retryWithBackoff<T>(\n operation: () => Promise<T>,\n operationName: string,\n logger: DebugLogger,\n maxRetries: number = 3,\n baseDelay: number = 1000,\n): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n logger.log(\"EMBEDDED_PROVIDER\", `Attempting ${operationName}`, {\n attempt,\n maxRetries,\n });\n return await operation();\n } catch (error) {\n lastError = error as Error;\n logger.warn(\"EMBEDDED_PROVIDER\", `${operationName} failed`, {\n attempt,\n maxRetries,\n error: error instanceof Error ? error.message : String(error),\n });\n\n if (attempt === maxRetries) {\n logger.error(\"EMBEDDED_PROVIDER\", `${operationName} failed after ${maxRetries} attempts`, {\n finalError: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Exponential backoff: 1s, 2s, 4s\n const delay = baseDelay * Math.pow(2, attempt - 1);\n logger.log(\"EMBEDDED_PROVIDER\", `Retrying ${operationName} in ${delay}ms`, {\n attempt: attempt + 1,\n delay,\n });\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n\n throw lastError!;\n}\n"],"mappings":"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","names":["bs58"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
// src/embedded-provider.ts
|
|
2
|
-
import { PhantomClient
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
2
|
+
import { PhantomClient } from "@phantom/client";
|
|
3
|
+
import { base64urlEncode } from "@phantom/base64url";
|
|
4
|
+
import bs58 from "bs58";
|
|
5
|
+
import {
|
|
6
|
+
parseMessage,
|
|
7
|
+
parseTransaction,
|
|
8
|
+
parseSignMessageResponse,
|
|
9
|
+
parseTransactionResponse
|
|
10
|
+
} from "@phantom/parsers";
|
|
5
11
|
|
|
6
12
|
// src/auth/jwt-auth.ts
|
|
7
13
|
var JWTAuth = class {
|
|
@@ -128,9 +134,11 @@ var EmbeddedProvider = class {
|
|
|
128
134
|
this.logger = logger;
|
|
129
135
|
this.logger.log("EMBEDDED_PROVIDER", "Initializing EmbeddedProvider", { config });
|
|
130
136
|
this.config = config;
|
|
137
|
+
this.platform = platform;
|
|
131
138
|
this.storage = platform.storage;
|
|
132
139
|
this.authProvider = platform.authProvider;
|
|
133
140
|
this.urlParamsAccessor = platform.urlParamsAccessor;
|
|
141
|
+
this.stamper = platform.stamper;
|
|
134
142
|
this.jwtAuth = new JWTAuth();
|
|
135
143
|
config.solanaProvider;
|
|
136
144
|
this.logger.info("EMBEDDED_PROVIDER", "EmbeddedProvider initialized");
|
|
@@ -204,29 +212,48 @@ var EmbeddedProvider = class {
|
|
|
204
212
|
}
|
|
205
213
|
}
|
|
206
214
|
/*
|
|
207
|
-
* We use this method to
|
|
215
|
+
* We use this method to initialize the stamper and create an organization for new sessions.
|
|
208
216
|
* This is the first step when no existing session is found and we need to set up a new wallet.
|
|
209
217
|
*/
|
|
210
|
-
async
|
|
211
|
-
this.logger.log("EMBEDDED_PROVIDER", "
|
|
212
|
-
const
|
|
213
|
-
this.logger.log("EMBEDDED_PROVIDER", "
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
218
|
+
async createOrganizationAndStamper() {
|
|
219
|
+
this.logger.log("EMBEDDED_PROVIDER", "Initializing stamper");
|
|
220
|
+
const stamperInfo = await this.stamper.init();
|
|
221
|
+
this.logger.log("EMBEDDED_PROVIDER", "Stamper initialized", {
|
|
222
|
+
publicKey: stamperInfo.publicKey,
|
|
223
|
+
keyId: stamperInfo.keyId,
|
|
224
|
+
algorithm: this.stamper.algorithm
|
|
217
225
|
});
|
|
226
|
+
this.logger.log("EMBEDDED_PROVIDER", "Creating temporary PhantomClient");
|
|
218
227
|
const tempClient = new PhantomClient(
|
|
219
228
|
{
|
|
220
229
|
apiBaseUrl: this.config.apiBaseUrl
|
|
221
230
|
},
|
|
222
|
-
stamper
|
|
231
|
+
this.stamper
|
|
232
|
+
);
|
|
233
|
+
const platformName = this.platform.name || "unknown";
|
|
234
|
+
const shortPubKey = stamperInfo.publicKey.slice(0, 8);
|
|
235
|
+
const organizationName = `${this.config.organizationId}-${platformName}-${shortPubKey}`;
|
|
236
|
+
this.logger.log("EMBEDDED_PROVIDER", "Creating organization", {
|
|
237
|
+
organizationName,
|
|
238
|
+
publicKey: stamperInfo.publicKey,
|
|
239
|
+
platform: platformName
|
|
240
|
+
});
|
|
241
|
+
const base64urlPublicKey = base64urlEncode(bs58.decode(stamperInfo.publicKey));
|
|
242
|
+
const { organizationId } = await tempClient.createOrganization(
|
|
243
|
+
organizationName,
|
|
244
|
+
[{
|
|
245
|
+
username: `user-${shortPubKey}`,
|
|
246
|
+
role: "admin",
|
|
247
|
+
authenticators: [{
|
|
248
|
+
authenticatorName: `auth-${shortPubKey}`,
|
|
249
|
+
authenticatorKind: "keypair",
|
|
250
|
+
publicKey: base64urlPublicKey,
|
|
251
|
+
algorithm: "Ed25519"
|
|
252
|
+
}]
|
|
253
|
+
}]
|
|
223
254
|
);
|
|
224
|
-
const uid = Date.now();
|
|
225
|
-
const organizationName = `${this.config.organizationId}-${uid}`;
|
|
226
|
-
this.logger.log("EMBEDDED_PROVIDER", "Creating organization", { organizationName });
|
|
227
|
-
const { organizationId } = await tempClient.createOrganization(organizationName, keypair);
|
|
228
255
|
this.logger.info("EMBEDDED_PROVIDER", "Organization created", { organizationId });
|
|
229
|
-
return { organizationId,
|
|
256
|
+
return { organizationId, stamperInfo };
|
|
230
257
|
}
|
|
231
258
|
async connect(authOptions) {
|
|
232
259
|
try {
|
|
@@ -253,8 +280,8 @@ var EmbeddedProvider = class {
|
|
|
253
280
|
this.validateAuthOptions(authOptions);
|
|
254
281
|
if (!session) {
|
|
255
282
|
this.logger.info("EMBEDDED_PROVIDER", "No existing session, creating new one");
|
|
256
|
-
const { organizationId,
|
|
257
|
-
session = await this.handleAuthFlow(organizationId,
|
|
283
|
+
const { organizationId, stamperInfo } = await this.createOrganizationAndStamper();
|
|
284
|
+
session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions);
|
|
258
285
|
}
|
|
259
286
|
if (!session) {
|
|
260
287
|
return {
|
|
@@ -310,28 +337,53 @@ var EmbeddedProvider = class {
|
|
|
310
337
|
this.client = null;
|
|
311
338
|
this.walletId = null;
|
|
312
339
|
this.addresses = [];
|
|
340
|
+
this.logger.info("EMBEDDED_PROVIDER", "Disconnected from embedded wallet");
|
|
313
341
|
}
|
|
314
342
|
async signMessage(params) {
|
|
315
343
|
if (!this.client || !this.walletId) {
|
|
316
344
|
throw new Error("Not connected");
|
|
317
345
|
}
|
|
346
|
+
this.logger.info("EMBEDDED_PROVIDER", "Signing message", {
|
|
347
|
+
walletId: this.walletId,
|
|
348
|
+
message: params.message
|
|
349
|
+
});
|
|
318
350
|
const parsedMessage = parseMessage(params.message);
|
|
319
|
-
|
|
351
|
+
const rawResponse = await this.client.signMessage({
|
|
320
352
|
walletId: this.walletId,
|
|
321
353
|
message: parsedMessage.base64url,
|
|
322
354
|
networkId: params.networkId
|
|
323
355
|
});
|
|
356
|
+
this.logger.info("EMBEDDED_PROVIDER", "Message signed successfully", {
|
|
357
|
+
walletId: this.walletId,
|
|
358
|
+
message: params.message
|
|
359
|
+
});
|
|
360
|
+
return parseSignMessageResponse(rawResponse, params.networkId);
|
|
324
361
|
}
|
|
325
362
|
async signAndSendTransaction(params) {
|
|
326
363
|
if (!this.client || !this.walletId) {
|
|
327
364
|
throw new Error("Not connected");
|
|
328
365
|
}
|
|
366
|
+
this.logger.info("EMBEDDED_PROVIDER", "Signing and sending transaction", {
|
|
367
|
+
walletId: this.walletId,
|
|
368
|
+
networkId: params.networkId
|
|
369
|
+
});
|
|
329
370
|
const parsedTransaction = await parseTransaction(params.transaction, params.networkId);
|
|
330
|
-
|
|
371
|
+
this.logger.log("EMBEDDED_PROVIDER", "Parsed transaction for signing", {
|
|
372
|
+
walletId: this.walletId,
|
|
373
|
+
transaction: parsedTransaction
|
|
374
|
+
});
|
|
375
|
+
const rawResponse = await this.client.signAndSendTransaction({
|
|
331
376
|
walletId: this.walletId,
|
|
332
377
|
transaction: parsedTransaction.base64url,
|
|
333
378
|
networkId: params.networkId
|
|
334
379
|
});
|
|
380
|
+
this.logger.info("EMBEDDED_PROVIDER", "Transaction signed and sent successfully", {
|
|
381
|
+
walletId: this.walletId,
|
|
382
|
+
networkId: params.networkId,
|
|
383
|
+
hash: rawResponse.hash,
|
|
384
|
+
rawTransaction: rawResponse.rawTransaction
|
|
385
|
+
});
|
|
386
|
+
return await parseTransactionResponse(rawResponse.rawTransaction, params.networkId, rawResponse.hash);
|
|
335
387
|
}
|
|
336
388
|
getAddresses() {
|
|
337
389
|
return this.addresses;
|
|
@@ -344,23 +396,31 @@ var EmbeddedProvider = class {
|
|
|
344
396
|
* It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.
|
|
345
397
|
* Returns null for redirect flows since they don't complete synchronously.
|
|
346
398
|
*/
|
|
347
|
-
async handleAuthFlow(organizationId,
|
|
399
|
+
async handleAuthFlow(organizationId, stamperInfo, authOptions) {
|
|
348
400
|
if (this.config.embeddedWalletType === "user-wallet") {
|
|
349
401
|
this.logger.info("EMBEDDED_PROVIDER", "Creating user-wallet, routing authentication", {
|
|
350
402
|
authProvider: authOptions?.provider || "phantom-connect"
|
|
351
403
|
});
|
|
352
404
|
if (authOptions?.provider === "jwt") {
|
|
353
|
-
return await this.handleJWTAuth(organizationId,
|
|
405
|
+
return await this.handleJWTAuth(organizationId, stamperInfo, authOptions);
|
|
354
406
|
} else {
|
|
355
|
-
|
|
356
|
-
|
|
407
|
+
this.logger.info("EMBEDDED_PROVIDER", "Starting redirect-based authentication flow", {
|
|
408
|
+
organizationId,
|
|
409
|
+
parentOrganizationId: this.config.organizationId,
|
|
410
|
+
provider: authOptions?.provider
|
|
411
|
+
});
|
|
412
|
+
return await this.handleRedirectAuth(organizationId, stamperInfo, authOptions);
|
|
357
413
|
}
|
|
358
414
|
} else {
|
|
415
|
+
this.logger.info("EMBEDDED_PROVIDER", "Creating app-wallet", {
|
|
416
|
+
organizationId
|
|
417
|
+
});
|
|
359
418
|
const tempClient = new PhantomClient(
|
|
360
419
|
{
|
|
361
|
-
apiBaseUrl: this.config.apiBaseUrl
|
|
420
|
+
apiBaseUrl: this.config.apiBaseUrl,
|
|
421
|
+
organizationId
|
|
362
422
|
},
|
|
363
|
-
|
|
423
|
+
this.stamper
|
|
364
424
|
);
|
|
365
425
|
const wallet = await tempClient.createWallet(`Wallet ${Date.now()}`);
|
|
366
426
|
const walletId = wallet.walletId;
|
|
@@ -368,8 +428,8 @@ var EmbeddedProvider = class {
|
|
|
368
428
|
const session = {
|
|
369
429
|
sessionId: generateSessionId(),
|
|
370
430
|
walletId,
|
|
371
|
-
organizationId
|
|
372
|
-
|
|
431
|
+
organizationId,
|
|
432
|
+
stamperInfo,
|
|
373
433
|
authProvider: "app-wallet",
|
|
374
434
|
userInfo: { embeddedWalletType: this.config.embeddedWalletType },
|
|
375
435
|
status: "completed",
|
|
@@ -377,6 +437,7 @@ var EmbeddedProvider = class {
|
|
|
377
437
|
lastUsed: now
|
|
378
438
|
};
|
|
379
439
|
await this.storage.saveSession(session);
|
|
440
|
+
this.logger.info("EMBEDDED_PROVIDER", "App-wallet created successfully", { walletId, organizationId });
|
|
380
441
|
return session;
|
|
381
442
|
}
|
|
382
443
|
}
|
|
@@ -384,7 +445,7 @@ var EmbeddedProvider = class {
|
|
|
384
445
|
* We use this method to handle JWT-based authentication for user-wallets.
|
|
385
446
|
* It authenticates using the provided JWT token and creates a completed session.
|
|
386
447
|
*/
|
|
387
|
-
async handleJWTAuth(organizationId,
|
|
448
|
+
async handleJWTAuth(organizationId, stamperInfo, authOptions) {
|
|
388
449
|
this.logger.info("EMBEDDED_PROVIDER", "Using JWT authentication flow");
|
|
389
450
|
if (!authOptions.jwtToken) {
|
|
390
451
|
this.logger.error("EMBEDDED_PROVIDER", "JWT token missing for JWT authentication");
|
|
@@ -403,8 +464,8 @@ var EmbeddedProvider = class {
|
|
|
403
464
|
const session = {
|
|
404
465
|
sessionId: generateSessionId(),
|
|
405
466
|
walletId,
|
|
406
|
-
organizationId
|
|
407
|
-
|
|
467
|
+
organizationId,
|
|
468
|
+
stamperInfo,
|
|
408
469
|
authProvider: authResult.provider,
|
|
409
470
|
userInfo: authResult.userInfo,
|
|
410
471
|
status: "completed",
|
|
@@ -420,7 +481,7 @@ var EmbeddedProvider = class {
|
|
|
420
481
|
* It saves a temporary session before redirecting to prevent losing state during the redirect flow.
|
|
421
482
|
* Session timestamp is updated before redirect to prevent race conditions.
|
|
422
483
|
*/
|
|
423
|
-
async handleRedirectAuth(organizationId,
|
|
484
|
+
async handleRedirectAuth(organizationId, stamperInfo, authOptions) {
|
|
424
485
|
this.logger.info("EMBEDDED_PROVIDER", "Using Phantom Connect authentication flow (redirect-based)", {
|
|
425
486
|
provider: authOptions?.provider,
|
|
426
487
|
hasRedirectUrl: !!this.config.authOptions?.redirectUrl,
|
|
@@ -433,7 +494,7 @@ var EmbeddedProvider = class {
|
|
|
433
494
|
walletId: `temp-${now}`,
|
|
434
495
|
// Temporary ID, will be updated after redirect
|
|
435
496
|
organizationId,
|
|
436
|
-
|
|
497
|
+
stamperInfo,
|
|
437
498
|
authProvider: "phantom-connect",
|
|
438
499
|
userInfo: { provider: authOptions?.provider },
|
|
439
500
|
status: "pending",
|
|
@@ -452,15 +513,31 @@ var EmbeddedProvider = class {
|
|
|
452
513
|
provider: authOptions?.provider,
|
|
453
514
|
authUrl: this.config.authOptions?.authUrl
|
|
454
515
|
});
|
|
455
|
-
await this.authProvider.authenticate({
|
|
516
|
+
const authResult = await this.authProvider.authenticate({
|
|
456
517
|
organizationId,
|
|
457
518
|
parentOrganizationId: this.config.organizationId,
|
|
458
519
|
provider: authOptions?.provider,
|
|
459
520
|
redirectUrl: this.config.authOptions?.redirectUrl,
|
|
460
521
|
customAuthData: authOptions?.customAuthData,
|
|
461
522
|
authUrl: this.config.authOptions?.authUrl,
|
|
462
|
-
sessionId
|
|
523
|
+
sessionId,
|
|
524
|
+
appName: this.config.appName,
|
|
525
|
+
appLogo: this.config.appLogo
|
|
463
526
|
});
|
|
527
|
+
if (authResult && "walletId" in authResult) {
|
|
528
|
+
this.logger.info("EMBEDDED_PROVIDER", "Authentication completed after redirect", {
|
|
529
|
+
walletId: authResult.walletId,
|
|
530
|
+
provider: authResult.provider
|
|
531
|
+
});
|
|
532
|
+
tempSession.walletId = authResult.walletId;
|
|
533
|
+
tempSession.authProvider = authResult.provider || tempSession.authProvider;
|
|
534
|
+
tempSession.status = "completed";
|
|
535
|
+
tempSession.lastUsed = Date.now();
|
|
536
|
+
await this.storage.saveSession(tempSession);
|
|
537
|
+
return tempSession;
|
|
538
|
+
}
|
|
539
|
+
this.logger.info("EMBEDDED_PROVIDER", "Redirect authentication initiated, waiting for redirect completion");
|
|
540
|
+
return null;
|
|
464
541
|
}
|
|
465
542
|
async completeAuthConnection(authResult) {
|
|
466
543
|
const session = await this.storage.getSession();
|
|
@@ -469,7 +546,6 @@ var EmbeddedProvider = class {
|
|
|
469
546
|
}
|
|
470
547
|
session.walletId = authResult.walletId;
|
|
471
548
|
session.authProvider = authResult.provider || session.authProvider;
|
|
472
|
-
session.userInfo = { ...session.userInfo, ...authResult.userInfo };
|
|
473
549
|
session.status = "completed";
|
|
474
550
|
session.lastUsed = Date.now();
|
|
475
551
|
await this.storage.saveSession(session);
|
|
@@ -489,15 +565,15 @@ var EmbeddedProvider = class {
|
|
|
489
565
|
organizationId: session.organizationId,
|
|
490
566
|
walletId: session.walletId
|
|
491
567
|
});
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
568
|
+
if (!this.stamper.getKeyInfo()) {
|
|
569
|
+
await this.stamper.init();
|
|
570
|
+
}
|
|
495
571
|
this.client = new PhantomClient(
|
|
496
572
|
{
|
|
497
573
|
apiBaseUrl: this.config.apiBaseUrl,
|
|
498
574
|
organizationId: session.organizationId
|
|
499
575
|
},
|
|
500
|
-
stamper
|
|
576
|
+
this.stamper
|
|
501
577
|
);
|
|
502
578
|
this.walletId = session.walletId;
|
|
503
579
|
this.addresses = await this.getAndFilterWalletAddresses(session.walletId);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/embedded-provider.ts","../src/auth/jwt-auth.ts","../src/utils/session.ts","../src/utils/retry.ts"],"sourcesContent":["import { PhantomClient, generateKeyPair } from \"@phantom/client\";\nimport type { AddressType } from \"@phantom/client\";\nimport { ApiKeyStamper } from \"@phantom/api-key-stamper\";\nimport { parseMessage, parseTransaction } from \"@phantom/parsers\";\n\nimport type {\n PlatformAdapter,\n Session,\n AuthResult,\n DebugLogger,\n EmbeddedStorage,\n AuthProvider,\n URLParamsAccessor,\n} from \"./interfaces\";\nimport type {\n EmbeddedProviderConfig,\n ConnectResult,\n SignMessageParams,\n SignAndSendTransactionParams,\n SignedTransaction,\n WalletAddress,\n AuthOptions,\n} from \"./types\";\nimport { JWTAuth } from \"./auth/jwt-auth\";\nimport { generateSessionId } from \"./utils/session\";\nimport { retryWithBackoff } from \"./utils/retry\";\n\nexport class EmbeddedProvider {\n private config: EmbeddedProviderConfig;\n private storage: EmbeddedStorage;\n private authProvider: AuthProvider;\n private urlParamsAccessor: URLParamsAccessor;\n private logger: DebugLogger;\n private client: PhantomClient | null = null;\n private walletId: string | null = null;\n private addresses: WalletAddress[] = [];\n private jwtAuth: JWTAuth;\n\n constructor(config: EmbeddedProviderConfig, platform: PlatformAdapter, logger: DebugLogger) {\n this.logger = logger;\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing EmbeddedProvider\", { config });\n\n this.config = config;\n this.storage = platform.storage;\n this.authProvider = platform.authProvider;\n this.urlParamsAccessor = platform.urlParamsAccessor;\n this.jwtAuth = new JWTAuth();\n\n // Store solana provider config (unused for now)\n config.solanaProvider;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"EmbeddedProvider initialized\");\n }\n\n private async getAndFilterWalletAddresses(walletId: string): Promise<WalletAddress[]> {\n // Get wallet addresses with retry and auto-disconnect on failure\n const addresses = await retryWithBackoff(\n () => this.client!.getWalletAddresses(walletId),\n \"getWalletAddresses\",\n this.logger,\n ).catch(async error => {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"getWalletAddresses failed after retries, disconnecting\", {\n walletId,\n error: error.message,\n });\n // Clear the session if getWalletAddresses fails after retries\n await this.storage.clearSession();\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n throw error;\n });\n\n // Filter by enabled address types and return formatted addresses\n return addresses\n .filter(addr => this.config.addressTypes.some(type => type === addr.addressType))\n .map(addr => ({\n addressType: addr.addressType as AddressType,\n address: addr.address,\n }));\n }\n\n /*\n * We use this method to make sure the session is not invalid, or there's a different session id in the url.\n * If there's a different one, we delete the current session and start from scratch.\n * This prevents issues where users have stale sessions or URL mismatches after redirects.\n */\n private async validateAndCleanSession(session: Session | null): Promise<Session | null> {\n if (!session) return null;\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Found existing session, validating\", {\n sessionId: session.sessionId,\n status: session.status,\n walletId: session.walletId,\n });\n\n // If session is not completed, check if we're in the right context\n if (session.status !== \"completed\") {\n const urlSessionId = this.urlParamsAccessor.getParam(\"session_id\");\n\n // If we have a pending session but no sessionId in URL, this is a mismatch\n if (session.status === \"pending\" && !urlSessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session mismatch detected - pending session without redirect context\", {\n sessionId: session.sessionId,\n status: session.status,\n });\n // Clear the invalid session and start fresh\n await this.storage.clearSession();\n return null;\n }\n // If sessionId in URL doesn't match stored session, clear invalid session\n else if (urlSessionId && urlSessionId !== session.sessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session ID mismatch detected\", {\n storedSessionId: session.sessionId,\n urlSessionId: urlSessionId,\n });\n await this.storage.clearSession();\n return null;\n }\n }\n\n return session;\n }\n\n /*\n * We use this method to validate authentication options before processing them.\n * This ensures only supported auth providers are used and required tokens are present.\n */\n private validateAuthOptions(authOptions?: AuthOptions): void {\n if (!authOptions) return;\n\n if (authOptions.provider && ![\"google\", \"apple\", \"jwt\"].includes(authOptions.provider)) {\n throw new Error(`Invalid auth provider: ${authOptions.provider}. Must be \"google\", \"apple\", or \"jwt\"`);\n }\n\n if (authOptions.provider === \"jwt\" && !authOptions.jwtToken) {\n throw new Error(\"JWT token is required when using JWT authentication\");\n }\n }\n\n /*\n * We use this method to generate a new keypair and create an organization for new sessions.\n * This is the first step when no existing session is found and we need to set up a new wallet.\n */\n private async createOrganizationAndKeypair(): Promise<{ organizationId: string; keypair: any }> {\n // Generate keypair using PhantomClient\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Generating keypair\");\n const keypair = generateKeyPair();\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Keypair generated\", { publicKey: keypair.publicKey });\n\n // Create a temporary client with the keypair\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating temporary PhantomClient\");\n const stamper = new ApiKeyStamper({\n apiSecretKey: keypair.secretKey,\n });\n\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n },\n stamper,\n );\n\n // Create an organization\n // organization name is a combination of this organizationId and this userId, which will be a unique identifier\n const uid = Date.now(); // for now\n const organizationName = `${this.config.organizationId}-${uid}`;\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating organization\", { organizationName });\n const { organizationId } = await tempClient.createOrganization(organizationName, keypair);\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Organization created\", { organizationId });\n\n return { organizationId, keypair };\n }\n\n async connect(authOptions?: AuthOptions): Promise<ConnectResult> {\n try {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting embedded provider connect\", {\n authOptions: authOptions\n ? {\n provider: authOptions.provider,\n hasJwtToken: !!authOptions.jwtToken,\n }\n : undefined,\n });\n\n // Get and validate existing session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Getting existing session\");\n let session = await this.storage.getSession();\n session = await this.validateAndCleanSession(session);\n\n // First, check if we're resuming from a redirect\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Checking for redirect resume\");\n if (this.authProvider.resumeAuthFromRedirect) {\n const authResult = this.authProvider.resumeAuthFromRedirect();\n if (authResult) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Resuming from redirect\", {\n walletId: authResult.walletId,\n provider: authResult.provider,\n });\n return this.completeAuthConnection(authResult);\n }\n }\n\n // Validate auth options\n this.validateAuthOptions(authOptions);\n\n // If no session exists, create new one\n if (!session) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"No existing session, creating new one\");\n const { organizationId, keypair } = await this.createOrganizationAndKeypair();\n session = await this.handleAuthFlow(organizationId, keypair, authOptions);\n }\n\n // If session is null here, it means we're doing a redirect\n if (!session) {\n // This should not return anything as redirect is happening\n return {\n addresses: [],\n status: \"pending\",\n } as ConnectResult;\n }\n\n // Update session last used timestamp (only for non-redirect flows)\n // For redirect flows, timestamp is updated before redirect to prevent race condition\n if (!authOptions || authOptions.provider === \"jwt\" || this.config.embeddedWalletType === \"app-wallet\") {\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n }\n\n // Initialize client and get addresses\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n } catch (error) {\n // Log the full error details for debugging\n this.logger.error(\"EMBEDDED_PROVIDER\", \"Connect failed with error\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n });\n\n // Enhanced error handling with specific error types\n if (error instanceof Error) {\n // Check for specific error types and provide better error messages\n if (error.message.includes(\"IndexedDB\") || error.message.includes(\"storage\")) {\n throw new Error(\n \"Storage error: Unable to access browser storage. Please ensure storage is available and try again.\",\n );\n }\n\n if (error.message.includes(\"network\") || error.message.includes(\"fetch\")) {\n throw new Error(\n \"Network error: Unable to connect to authentication server. Please check your internet connection and try again.\",\n );\n }\n\n if (error.message.includes(\"JWT\") || error.message.includes(\"jwt\")) {\n throw new Error(`JWT Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"Authentication\") || error.message.includes(\"auth\")) {\n throw new Error(`Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"organization\") || error.message.includes(\"wallet\")) {\n throw new Error(`Wallet creation error: ${error.message}`);\n }\n\n // Re-throw the original error if it's already well-formatted\n throw error;\n }\n\n // Handle unknown error types\n throw new Error(`Embedded wallet connection failed: ${String(error)}`);\n }\n }\n\n async disconnect(): Promise<void> {\n await this.storage.clearSession();\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n }\n\n async signMessage(params: SignMessageParams): Promise<string> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n // Parse message to base64url format for client\n const parsedMessage = parseMessage(params.message);\n\n return await this.client.signMessage({\n walletId: this.walletId,\n message: parsedMessage.base64url,\n networkId: params.networkId,\n });\n }\n\n async signAndSendTransaction(params: SignAndSendTransactionParams): Promise<SignedTransaction> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n // Parse transaction to base64url format for client based on network\n const parsedTransaction = await parseTransaction(params.transaction, params.networkId);\n\n return await this.client.signAndSendTransaction({\n walletId: this.walletId,\n transaction: parsedTransaction.base64url,\n networkId: params.networkId,\n });\n }\n\n getAddresses(): WalletAddress[] {\n return this.addresses;\n }\n\n isConnected(): boolean {\n return this.client !== null && this.walletId !== null;\n }\n\n /*\n * We use this method to route between different authentication flows based on wallet type and auth options.\n * It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.\n * Returns null for redirect flows since they don't complete synchronously.\n */\n private async handleAuthFlow(\n organizationId: string,\n keypair: any,\n authOptions?: AuthOptions,\n ): Promise<Session | null> {\n if (this.config.embeddedWalletType === \"user-wallet\") {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Creating user-wallet, routing authentication\", {\n authProvider: authOptions?.provider || \"phantom-connect\",\n });\n\n // Route to appropriate authentication flow based on authOptions\n if (authOptions?.provider === \"jwt\") {\n return await this.handleJWTAuth(organizationId, keypair, authOptions);\n } else {\n // This will redirect, so we don't return a session\n await this.handleRedirectAuth(organizationId, keypair, authOptions);\n return null;\n }\n } else {\n // Create app-wallet directly\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n },\n new ApiKeyStamper({ apiSecretKey: keypair.secretKey }),\n );\n\n const wallet = await tempClient.createWallet(`Wallet ${Date.now()}`);\n const walletId = wallet.walletId;\n\n // Save session with app-wallet info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: this.config.organizationId,\n keypair,\n authProvider: \"app-wallet\",\n userInfo: { embeddedWalletType: this.config.embeddedWalletType },\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n await this.storage.saveSession(session);\n return session;\n }\n }\n\n /*\n * We use this method to handle JWT-based authentication for user-wallets.\n * It authenticates using the provided JWT token and creates a completed session.\n */\n private async handleJWTAuth(organizationId: string, keypair: any, authOptions: AuthOptions): Promise<Session> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using JWT authentication flow\");\n\n // Use JWT authentication flow\n if (!authOptions.jwtToken) {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"JWT token missing for JWT authentication\");\n throw new Error(\"JWT token is required for JWT authentication\");\n }\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Starting JWT authentication\");\n const authResult = await this.jwtAuth.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n jwtToken: authOptions.jwtToken,\n customAuthData: authOptions.customAuthData,\n });\n const walletId = authResult.walletId;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"JWT authentication completed\", { walletId });\n\n // Save session with auth info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: this.config.organizationId,\n keypair,\n authProvider: authResult.provider,\n userInfo: authResult.userInfo,\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving JWT session\");\n await this.storage.saveSession(session);\n return session;\n }\n\n /*\n * We use this method to handle redirect-based authentication (Google/Apple OAuth).\n * It saves a temporary session before redirecting to prevent losing state during the redirect flow.\n * Session timestamp is updated before redirect to prevent race conditions.\n */\n private async handleRedirectAuth(organizationId: string, keypair: any, authOptions?: AuthOptions): Promise<void> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using Phantom Connect authentication flow (redirect-based)\", {\n provider: authOptions?.provider,\n hasRedirectUrl: !!this.config.authOptions?.redirectUrl,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Use Phantom Connect authentication flow (redirect-based)\n // Store session before redirect so we can restore it after redirect\n const now = Date.now();\n const sessionId = generateSessionId();\n const tempSession = {\n sessionId: sessionId,\n walletId: `temp-${now}`, // Temporary ID, will be updated after redirect\n organizationId: organizationId,\n keypair,\n authProvider: \"phantom-connect\",\n userInfo: { provider: authOptions?.provider },\n status: \"pending\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving temporary session before redirect\", {\n sessionId: tempSession.sessionId,\n tempWalletId: tempSession.walletId,\n });\n\n // Update session timestamp before redirect (prevents race condition)\n tempSession.lastUsed = Date.now();\n await this.storage.saveSession(tempSession);\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting Phantom Connect redirect\", {\n organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Start the authentication flow (this will redirect the user)\n await this.authProvider.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider as \"google\" | \"apple\" | undefined,\n redirectUrl: this.config.authOptions?.redirectUrl,\n customAuthData: authOptions?.customAuthData,\n authUrl: this.config.authOptions?.authUrl,\n sessionId: sessionId,\n });\n }\n\n private async completeAuthConnection(authResult: AuthResult): Promise<ConnectResult> {\n // Check if we have an existing session\n const session = await this.storage.getSession();\n\n if (!session) {\n throw new Error(\"No session found after redirect - session may have expired\");\n }\n\n // Update session with actual wallet ID and auth info from redirect\n session.walletId = authResult.walletId;\n session.authProvider = authResult.provider || session.authProvider;\n session.userInfo = { ...session.userInfo, ...authResult.userInfo };\n session.status = \"completed\";\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n }\n\n /*\n * We use this method to initialize the PhantomClient and fetch wallet addresses from a completed session.\n * This is the final step that sets up the provider's client state and retrieves available addresses.\n */\n private async initializeClientFromSession(session: Session): Promise<void> {\n // Create client from session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing PhantomClient from session\", {\n organizationId: session.organizationId,\n walletId: session.walletId,\n });\n\n const stamper = new ApiKeyStamper({\n apiSecretKey: session.keypair.secretKey,\n });\n\n this.client = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n organizationId: session.organizationId,\n },\n stamper,\n );\n\n this.walletId = session.walletId;\n\n // Get wallet addresses and filter by enabled address types with retry\n this.addresses = await this.getAndFilterWalletAddresses(session.walletId);\n }\n}\n","import type { AuthResult, JWTAuthOptions } from \"../interfaces\";\n\nexport class JWTAuth {\n async authenticate(options: JWTAuthOptions): Promise<AuthResult> {\n // Validate JWT token format\n if (!options.jwtToken || typeof options.jwtToken !== \"string\") {\n throw new Error(\"Invalid JWT token: token must be a non-empty string\");\n }\n\n // Basic JWT format validation (3 parts separated by dots)\n const jwtParts = options.jwtToken.split(\".\");\n if (jwtParts.length !== 3) {\n throw new Error(\"Invalid JWT token format: token must have 3 parts separated by dots\");\n }\n\n // JWT authentication flow - direct API call to create wallet with JWT\n try {\n // This would typically make an API call to your backend\n // which would validate the JWT and create/retrieve the wallet\n const response = await fetch(\"/api/auth/jwt\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.jwtToken}`,\n },\n body: JSON.stringify({\n organizationId: options.organizationId,\n parentOrganizationId: options.parentOrganizationId,\n customAuthData: options.customAuthData,\n }),\n });\n\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.message || errorData.error || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n switch (response.status) {\n case 400:\n throw new Error(`Invalid JWT authentication request: ${errorMessage}`);\n case 401:\n throw new Error(`JWT token is invalid or expired: ${errorMessage}`);\n case 403:\n throw new Error(`JWT authentication forbidden: ${errorMessage}`);\n case 404:\n throw new Error(`JWT authentication endpoint not found: ${errorMessage}`);\n case 429:\n throw new Error(`Too many JWT authentication requests: ${errorMessage}`);\n case 500:\n case 502:\n case 503:\n case 504:\n throw new Error(`JWT authentication server error: ${errorMessage}`);\n default:\n throw new Error(`JWT authentication failed: ${errorMessage}`);\n }\n }\n\n let result;\n try {\n result = await response.json();\n } catch (parseError) {\n throw new Error(\"Invalid response from JWT authentication server: response is not valid JSON\");\n }\n\n if (!result.walletId) {\n throw new Error(\"Invalid JWT authentication response: missing walletId\");\n }\n\n return {\n walletId: result.walletId,\n provider: \"jwt\",\n userInfo: result.userInfo || {},\n };\n } catch (error) {\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n throw new Error(\"JWT authentication failed: network error or invalid endpoint\");\n }\n\n if (error instanceof Error) {\n throw error; // Re-throw known errors\n }\n\n throw new Error(`JWT authentication error: ${String(error)}`);\n }\n }\n}\n","export function generateSessionId(): string {\n return (\n \"session_\" +\n Math.random().toString(36).substring(2, 15) +\n Math.random().toString(36).substring(2, 15) +\n \"_\" +\n Date.now()\n );\n}\n","import type { DebugLogger } from \"../interfaces\";\n\nexport async function retryWithBackoff<T>(\n operation: () => Promise<T>,\n operationName: string,\n logger: DebugLogger,\n maxRetries: number = 3,\n baseDelay: number = 1000,\n): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n logger.log(\"EMBEDDED_PROVIDER\", `Attempting ${operationName}`, {\n attempt,\n maxRetries,\n });\n return await operation();\n } catch (error) {\n lastError = error as Error;\n logger.warn(\"EMBEDDED_PROVIDER\", `${operationName} failed`, {\n attempt,\n maxRetries,\n error: error instanceof Error ? error.message : String(error),\n });\n\n if (attempt === maxRetries) {\n logger.error(\"EMBEDDED_PROVIDER\", `${operationName} failed after ${maxRetries} attempts`, {\n finalError: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Exponential backoff: 1s, 2s, 4s\n const delay = baseDelay * Math.pow(2, attempt - 1);\n logger.log(\"EMBEDDED_PROVIDER\", `Retrying ${operationName} in ${delay}ms`, {\n attempt: attempt + 1,\n delay,\n });\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n\n throw lastError!;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/embedded-provider.ts","../src/auth/jwt-auth.ts","../src/utils/session.ts","../src/utils/retry.ts"],"sourcesContent":["import { PhantomClient } from \"@phantom/client\";\nimport type { AddressType } from \"@phantom/client\";\nimport { base64urlEncode } from \"@phantom/base64url\";\nimport bs58 from \"bs58\";\nimport {\n parseMessage,\n parseTransaction,\n parseSignMessageResponse,\n parseTransactionResponse,\n type ParsedTransactionResult,\n type ParsedSignatureResult,\n} from \"@phantom/parsers\";\n\nimport type {\n PlatformAdapter,\n Session,\n AuthResult,\n DebugLogger,\n EmbeddedStorage,\n AuthProvider,\n URLParamsAccessor,\n StamperInfo,\n} from \"./interfaces\";\nimport type {\n EmbeddedProviderConfig,\n ConnectResult,\n SignMessageParams,\n SignAndSendTransactionParams,\n WalletAddress,\n AuthOptions,\n} from \"./types\";\nimport { JWTAuth } from \"./auth/jwt-auth\";\nimport { generateSessionId } from \"./utils/session\";\nimport { retryWithBackoff } from \"./utils/retry\";\nimport type { StamperWithKeyManagement } from \"@phantom/sdk-types\";\nexport class EmbeddedProvider {\n private config: EmbeddedProviderConfig;\n private platform: PlatformAdapter;\n private storage: EmbeddedStorage;\n private authProvider: AuthProvider;\n private urlParamsAccessor: URLParamsAccessor;\n private stamper: StamperWithKeyManagement;\n private logger: DebugLogger;\n private client: PhantomClient | null = null;\n private walletId: string | null = null;\n private addresses: WalletAddress[] = [];\n private jwtAuth: JWTAuth;\n\n constructor(config: EmbeddedProviderConfig, platform: PlatformAdapter, logger: DebugLogger) {\n this.logger = logger;\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing EmbeddedProvider\", { config });\n\n this.config = config;\n this.platform = platform;\n this.storage = platform.storage;\n this.authProvider = platform.authProvider;\n this.urlParamsAccessor = platform.urlParamsAccessor;\n this.stamper = platform.stamper;\n this.jwtAuth = new JWTAuth();\n\n // Store solana provider config (unused for now)\n config.solanaProvider;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"EmbeddedProvider initialized\");\n }\n\n private async getAndFilterWalletAddresses(walletId: string): Promise<WalletAddress[]> {\n // Get wallet addresses with retry and auto-disconnect on failure\n const addresses = await retryWithBackoff(\n () => this.client!.getWalletAddresses(walletId),\n \"getWalletAddresses\",\n this.logger,\n ).catch(async error => {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"getWalletAddresses failed after retries, disconnecting\", {\n walletId,\n error: error.message,\n });\n // Clear the session if getWalletAddresses fails after retries\n await this.storage.clearSession();\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n throw error;\n });\n\n // Filter by enabled address types and return formatted addresses\n return addresses\n .filter(addr => this.config.addressTypes.some(type => type === addr.addressType))\n .map(addr => ({\n addressType: addr.addressType as AddressType,\n address: addr.address,\n }));\n }\n\n /*\n * We use this method to make sure the session is not invalid, or there's a different session id in the url.\n * If there's a different one, we delete the current session and start from scratch.\n * This prevents issues where users have stale sessions or URL mismatches after redirects.\n */\n private async validateAndCleanSession(session: Session | null): Promise<Session | null> {\n if (!session) return null;\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Found existing session, validating\", {\n sessionId: session.sessionId,\n status: session.status,\n walletId: session.walletId,\n });\n\n // If session is not completed, check if we're in the right context\n if (session.status !== \"completed\") {\n const urlSessionId = this.urlParamsAccessor.getParam(\"session_id\");\n\n // If we have a pending session but no sessionId in URL, this is a mismatch\n if (session.status === \"pending\" && !urlSessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session mismatch detected - pending session without redirect context\", {\n sessionId: session.sessionId,\n status: session.status,\n });\n // Clear the invalid session and start fresh\n await this.storage.clearSession();\n return null;\n }\n // If sessionId in URL doesn't match stored session, clear invalid session\n else if (urlSessionId && urlSessionId !== session.sessionId) {\n this.logger.warn(\"EMBEDDED_PROVIDER\", \"Session ID mismatch detected\", {\n storedSessionId: session.sessionId,\n urlSessionId: urlSessionId,\n });\n await this.storage.clearSession();\n return null;\n }\n }\n\n return session;\n }\n\n /*\n * We use this method to validate authentication options before processing them.\n * This ensures only supported auth providers are used and required tokens are present.\n */\n private validateAuthOptions(authOptions?: AuthOptions): void {\n if (!authOptions) return;\n\n if (authOptions.provider && ![\"google\", \"apple\", \"jwt\"].includes(authOptions.provider)) {\n throw new Error(`Invalid auth provider: ${authOptions.provider}. Must be \"google\", \"apple\", or \"jwt\"`);\n }\n\n if (authOptions.provider === \"jwt\" && !authOptions.jwtToken) {\n throw new Error(\"JWT token is required when using JWT authentication\");\n }\n }\n\n /*\n * We use this method to initialize the stamper and create an organization for new sessions.\n * This is the first step when no existing session is found and we need to set up a new wallet.\n */\n private async createOrganizationAndStamper(): Promise<{ organizationId: string; stamperInfo: StamperInfo }> {\n // Initialize stamper (generates keypair in IndexedDB)\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing stamper\");\n const stamperInfo = await this.stamper.init();\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Stamper initialized\", {\n publicKey: stamperInfo.publicKey,\n keyId: stamperInfo.keyId,\n algorithm: this.stamper.algorithm,\n });\n\n // Create a temporary client with the stamper\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating temporary PhantomClient\");\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n },\n this.stamper,\n );\n\n // Create an organization\n // organization name is a combination of this organizationId and this userId, which will be a unique identifier\n const platformName = this.platform.name || \"unknown\";\n const shortPubKey = stamperInfo.publicKey.slice(0, 8);\n const organizationName = `${this.config.organizationId}-${platformName}-${shortPubKey}`;\n\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Creating organization\", {\n organizationName,\n publicKey: stamperInfo.publicKey,\n platform: platformName,\n });\n\n // Convert base58 public key to base64url format as required by the API\n const base64urlPublicKey = base64urlEncode(bs58.decode(stamperInfo.publicKey));\n \n const { organizationId } = await tempClient.createOrganization(\n organizationName,\n [{\n username: `user-${shortPubKey}`,\n role: 'admin',\n authenticators: [{\n authenticatorName: `auth-${shortPubKey}`,\n authenticatorKind: 'keypair',\n publicKey: base64urlPublicKey,\n algorithm: 'Ed25519',\n }]\n }]\n );\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Organization created\", { organizationId });\n\n return { organizationId, stamperInfo };\n }\n\n async connect(authOptions?: AuthOptions): Promise<ConnectResult> {\n try {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting embedded provider connect\", {\n authOptions: authOptions\n ? {\n provider: authOptions.provider,\n hasJwtToken: !!authOptions.jwtToken,\n }\n : undefined,\n });\n\n // Get and validate existing session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Getting existing session\");\n let session = await this.storage.getSession();\n session = await this.validateAndCleanSession(session);\n\n // First, check if we're resuming from a redirect\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Checking for redirect resume\");\n if (this.authProvider.resumeAuthFromRedirect) {\n const authResult = this.authProvider.resumeAuthFromRedirect();\n if (authResult) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Resuming from redirect\", {\n walletId: authResult.walletId,\n provider: authResult.provider,\n });\n return this.completeAuthConnection(authResult);\n }\n }\n\n // Validate auth options\n this.validateAuthOptions(authOptions);\n\n // If no session exists, create new one\n if (!session) {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"No existing session, creating new one\");\n const { organizationId, stamperInfo } = await this.createOrganizationAndStamper();\n session = await this.handleAuthFlow(organizationId, stamperInfo, authOptions);\n }\n\n // If session is null here, it means we're doing a redirect\n if (!session) {\n // This should not return anything as redirect is happening\n return {\n addresses: [],\n status: \"pending\",\n } as ConnectResult;\n }\n\n // Update session last used timestamp (only for non-redirect flows)\n // For redirect flows, timestamp is updated before redirect to prevent race condition\n if (!authOptions || authOptions.provider === \"jwt\" || this.config.embeddedWalletType === \"app-wallet\") {\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n }\n\n // Initialize client and get addresses\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n } catch (error) {\n // Log the full error details for debugging\n this.logger.error(\"EMBEDDED_PROVIDER\", \"Connect failed with error\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n });\n\n // Enhanced error handling with specific error types\n if (error instanceof Error) {\n // Check for specific error types and provide better error messages\n if (error.message.includes(\"IndexedDB\") || error.message.includes(\"storage\")) {\n throw new Error(\n \"Storage error: Unable to access browser storage. Please ensure storage is available and try again.\",\n );\n }\n\n if (error.message.includes(\"network\") || error.message.includes(\"fetch\")) {\n throw new Error(\n \"Network error: Unable to connect to authentication server. Please check your internet connection and try again.\",\n );\n }\n\n if (error.message.includes(\"JWT\") || error.message.includes(\"jwt\")) {\n throw new Error(`JWT Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"Authentication\") || error.message.includes(\"auth\")) {\n throw new Error(`Authentication error: ${error.message}`);\n }\n\n if (error.message.includes(\"organization\") || error.message.includes(\"wallet\")) {\n throw new Error(`Wallet creation error: ${error.message}`);\n }\n\n // Re-throw the original error if it's already well-formatted\n throw error;\n }\n\n // Handle unknown error types\n throw new Error(`Embedded wallet connection failed: ${String(error)}`);\n }\n }\n\n async disconnect(): Promise<void> {\n await this.storage.clearSession();\n\n this.client = null;\n this.walletId = null;\n this.addresses = [];\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Disconnected from embedded wallet\");\n }\n\n async signMessage(params: SignMessageParams): Promise<ParsedSignatureResult> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Signing message\", {\n walletId: this.walletId,\n message: params.message,\n });\n\n // Parse message to base64url format for client\n const parsedMessage = parseMessage(params.message);\n\n // Get raw response from client\n const rawResponse = await this.client.signMessage({\n walletId: this.walletId,\n message: parsedMessage.base64url,\n networkId: params.networkId,\n });\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Message signed successfully\", {\n walletId: this.walletId,\n message: params.message,\n });\n\n // Parse the response to get human-readable signature and explorer URL\n return parseSignMessageResponse(rawResponse, params.networkId);\n }\n\n async signAndSendTransaction(params: SignAndSendTransactionParams): Promise<ParsedTransactionResult> {\n if (!this.client || !this.walletId) {\n throw new Error(\"Not connected\");\n }\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Signing and sending transaction\", {\n walletId: this.walletId,\n networkId: params.networkId,\n });\n\n // Parse transaction to base64url format for client based on network\n const parsedTransaction = await parseTransaction(params.transaction, params.networkId);\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Parsed transaction for signing\", {\n walletId: this.walletId,\n transaction: parsedTransaction,\n });\n\n // Get raw response from client\n const rawResponse = await this.client.signAndSendTransaction({\n walletId: this.walletId,\n transaction: parsedTransaction.base64url,\n networkId: params.networkId,\n });\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Transaction signed and sent successfully\", {\n walletId: this.walletId,\n networkId: params.networkId,\n hash: rawResponse.hash,\n rawTransaction: rawResponse.rawTransaction,\n });\n\n // Parse the response to get transaction hash and explorer URL\n return await parseTransactionResponse(rawResponse.rawTransaction, params.networkId, rawResponse.hash);\n }\n\n getAddresses(): WalletAddress[] {\n return this.addresses;\n }\n\n isConnected(): boolean {\n return this.client !== null && this.walletId !== null;\n }\n\n /*\n * We use this method to route between different authentication flows based on wallet type and auth options.\n * It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.\n * Returns null for redirect flows since they don't complete synchronously.\n */\n private async handleAuthFlow(\n organizationId: string,\n stamperInfo: StamperInfo,\n authOptions?: AuthOptions,\n ): Promise<Session | null> {\n if (this.config.embeddedWalletType === \"user-wallet\") {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Creating user-wallet, routing authentication\", {\n authProvider: authOptions?.provider || \"phantom-connect\",\n });\n\n // Route to appropriate authentication flow based on authOptions\n if (authOptions?.provider === \"jwt\") {\n return await this.handleJWTAuth(organizationId, stamperInfo, authOptions);\n } else {\n // This will redirect in browser, so we don't return a session\n // In react-native this will return an auth result\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting redirect-based authentication flow\", {\n organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider,\n });\n return await this.handleRedirectAuth(organizationId, stamperInfo, authOptions);\n }\n } else {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Creating app-wallet\", {\n organizationId,\n });\n // Create app-wallet directly\n const tempClient = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n organizationId: organizationId,\n },\n this.stamper,\n );\n\n const wallet = await tempClient.createWallet(`Wallet ${Date.now()}`);\n const walletId = wallet.walletId;\n\n // Save session with app-wallet info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: organizationId,\n stamperInfo,\n authProvider: \"app-wallet\",\n userInfo: { embeddedWalletType: this.config.embeddedWalletType },\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n\n await this.storage.saveSession(session);\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"App-wallet created successfully\", { walletId, organizationId });\n return session;\n }\n }\n\n /*\n * We use this method to handle JWT-based authentication for user-wallets.\n * It authenticates using the provided JWT token and creates a completed session.\n */\n private async handleJWTAuth(\n organizationId: string,\n stamperInfo: StamperInfo,\n authOptions: AuthOptions,\n ): Promise<Session> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using JWT authentication flow\");\n\n // Use JWT authentication flow\n if (!authOptions.jwtToken) {\n this.logger.error(\"EMBEDDED_PROVIDER\", \"JWT token missing for JWT authentication\");\n throw new Error(\"JWT token is required for JWT authentication\");\n }\n\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Starting JWT authentication\");\n const authResult = await this.jwtAuth.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n jwtToken: authOptions.jwtToken,\n customAuthData: authOptions.customAuthData,\n });\n const walletId = authResult.walletId;\n this.logger.info(\"EMBEDDED_PROVIDER\", \"JWT authentication completed\", { walletId });\n\n // Save session with auth info\n const now = Date.now();\n const session = {\n sessionId: generateSessionId(),\n walletId: walletId,\n organizationId: organizationId,\n stamperInfo,\n authProvider: authResult.provider,\n userInfo: authResult.userInfo,\n status: \"completed\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving JWT session\");\n await this.storage.saveSession(session);\n return session;\n }\n\n /*\n * We use this method to handle redirect-based authentication (Google/Apple OAuth).\n * It saves a temporary session before redirecting to prevent losing state during the redirect flow.\n * Session timestamp is updated before redirect to prevent race conditions.\n */\n private async handleRedirectAuth(\n organizationId: string,\n stamperInfo: StamperInfo,\n authOptions?: AuthOptions,\n ): Promise<Session | null> {\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Using Phantom Connect authentication flow (redirect-based)\", {\n provider: authOptions?.provider,\n hasRedirectUrl: !!this.config.authOptions?.redirectUrl,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Use Phantom Connect authentication flow (redirect-based)\n // Store session before redirect so we can restore it after redirect\n const now = Date.now();\n const sessionId = generateSessionId();\n const tempSession: Session = {\n sessionId: sessionId,\n walletId: `temp-${now}`, // Temporary ID, will be updated after redirect\n organizationId: organizationId,\n stamperInfo,\n authProvider: \"phantom-connect\",\n userInfo: { provider: authOptions?.provider },\n status: \"pending\" as const,\n createdAt: now,\n lastUsed: now,\n };\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Saving temporary session before redirect\", {\n sessionId: tempSession.sessionId,\n tempWalletId: tempSession.walletId,\n });\n\n // Update session timestamp before redirect (prevents race condition)\n tempSession.lastUsed = Date.now();\n await this.storage.saveSession(tempSession);\n\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Starting Phantom Connect redirect\", {\n organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider,\n authUrl: this.config.authOptions?.authUrl,\n });\n\n // Start the authentication flow (this will redirect the user in the browser, or handle it in React Native)\n const authResult = await this.authProvider.authenticate({\n organizationId: organizationId,\n parentOrganizationId: this.config.organizationId,\n provider: authOptions?.provider as \"google\" | \"apple\" | undefined,\n redirectUrl: this.config.authOptions?.redirectUrl,\n customAuthData: authOptions?.customAuthData,\n authUrl: this.config.authOptions?.authUrl,\n sessionId: sessionId,\n appName: this.config.appName,\n appLogo: this.config.appLogo,\n });\n\n if (authResult && \"walletId\" in authResult) {\n // If we got an auth result, we need to update the session with actual wallet ID\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Authentication completed after redirect\", {\n walletId: authResult.walletId,\n provider: authResult.provider,\n });\n\n // Update the temporary session with actual wallet ID and auth info\n tempSession.walletId = authResult.walletId;\n tempSession.authProvider = authResult.provider || tempSession.authProvider;\n tempSession.status = \"completed\";\n tempSession.lastUsed = Date.now();\n await this.storage.saveSession(tempSession);\n\n return tempSession; // Return the auth result for further processing\n }\n // If we don't have an auth result, it means we're in a redirect flow\n this.logger.info(\"EMBEDDED_PROVIDER\", \"Redirect authentication initiated, waiting for redirect completion\");\n // In this case, we don't return anything as the redirect will handle the rest\n return null;\n }\n\n private async completeAuthConnection(authResult: AuthResult): Promise<ConnectResult> {\n // Check if we have an existing session\n const session = await this.storage.getSession();\n\n if (!session) {\n throw new Error(\"No session found after redirect - session may have expired\");\n }\n\n // Update session with actual wallet ID and auth info from redirect\n session.walletId = authResult.walletId;\n session.authProvider = authResult.provider || session.authProvider;\n session.status = \"completed\";\n session.lastUsed = Date.now();\n await this.storage.saveSession(session);\n\n await this.initializeClientFromSession(session);\n\n return {\n walletId: this.walletId!,\n addresses: this.addresses,\n status: \"completed\",\n };\n }\n\n /*\n * We use this method to initialize the PhantomClient and fetch wallet addresses from a completed session.\n * This is the final step that sets up the provider's client state and retrieves available addresses.\n */\n private async initializeClientFromSession(session: Session): Promise<void> {\n // Create client from session\n this.logger.log(\"EMBEDDED_PROVIDER\", \"Initializing PhantomClient from session\", {\n organizationId: session.organizationId,\n walletId: session.walletId,\n });\n\n // Ensure stamper is initialized with existing keys\n if (!this.stamper.getKeyInfo()) {\n await this.stamper.init();\n }\n\n this.client = new PhantomClient(\n {\n apiBaseUrl: this.config.apiBaseUrl,\n organizationId: session.organizationId,\n },\n this.stamper,\n );\n\n this.walletId = session.walletId;\n\n // Get wallet addresses and filter by enabled address types with retry\n this.addresses = await this.getAndFilterWalletAddresses(session.walletId);\n }\n}\n","import type { AuthResult, JWTAuthOptions } from \"../interfaces\";\n\nexport class JWTAuth {\n async authenticate(options: JWTAuthOptions): Promise<AuthResult> {\n // Validate JWT token format\n if (!options.jwtToken || typeof options.jwtToken !== \"string\") {\n throw new Error(\"Invalid JWT token: token must be a non-empty string\");\n }\n\n // Basic JWT format validation (3 parts separated by dots)\n const jwtParts = options.jwtToken.split(\".\");\n if (jwtParts.length !== 3) {\n throw new Error(\"Invalid JWT token format: token must have 3 parts separated by dots\");\n }\n\n // JWT authentication flow - direct API call to create wallet with JWT\n try {\n // This would typically make an API call to your backend\n // which would validate the JWT and create/retrieve the wallet\n const response = await fetch(\"/api/auth/jwt\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.jwtToken}`,\n },\n body: JSON.stringify({\n organizationId: options.organizationId,\n parentOrganizationId: options.parentOrganizationId,\n customAuthData: options.customAuthData,\n }),\n });\n\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.message || errorData.error || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n\n switch (response.status) {\n case 400:\n throw new Error(`Invalid JWT authentication request: ${errorMessage}`);\n case 401:\n throw new Error(`JWT token is invalid or expired: ${errorMessage}`);\n case 403:\n throw new Error(`JWT authentication forbidden: ${errorMessage}`);\n case 404:\n throw new Error(`JWT authentication endpoint not found: ${errorMessage}`);\n case 429:\n throw new Error(`Too many JWT authentication requests: ${errorMessage}`);\n case 500:\n case 502:\n case 503:\n case 504:\n throw new Error(`JWT authentication server error: ${errorMessage}`);\n default:\n throw new Error(`JWT authentication failed: ${errorMessage}`);\n }\n }\n\n let result;\n try {\n result = await response.json();\n } catch (parseError) {\n throw new Error(\"Invalid response from JWT authentication server: response is not valid JSON\");\n }\n\n if (!result.walletId) {\n throw new Error(\"Invalid JWT authentication response: missing walletId\");\n }\n\n return {\n walletId: result.walletId,\n provider: \"jwt\",\n userInfo: result.userInfo || {},\n };\n } catch (error) {\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n throw new Error(\"JWT authentication failed: network error or invalid endpoint\");\n }\n\n if (error instanceof Error) {\n throw error; // Re-throw known errors\n }\n\n throw new Error(`JWT authentication error: ${String(error)}`);\n }\n }\n}\n","export function generateSessionId(): string {\n return (\n \"session_\" +\n Math.random().toString(36).substring(2, 15) +\n Math.random().toString(36).substring(2, 15) +\n \"_\" +\n Date.now()\n );\n}\n","import type { DebugLogger } from \"../interfaces\";\n\nexport async function retryWithBackoff<T>(\n operation: () => Promise<T>,\n operationName: string,\n logger: DebugLogger,\n maxRetries: number = 3,\n baseDelay: number = 1000,\n): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n logger.log(\"EMBEDDED_PROVIDER\", `Attempting ${operationName}`, {\n attempt,\n maxRetries,\n });\n return await operation();\n } catch (error) {\n lastError = error as Error;\n logger.warn(\"EMBEDDED_PROVIDER\", `${operationName} failed`, {\n attempt,\n maxRetries,\n error: error instanceof Error ? error.message : String(error),\n });\n\n if (attempt === maxRetries) {\n logger.error(\"EMBEDDED_PROVIDER\", `${operationName} failed after ${maxRetries} attempts`, {\n finalError: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Exponential backoff: 1s, 2s, 4s\n const delay = baseDelay * Math.pow(2, attempt - 1);\n logger.log(\"EMBEDDED_PROVIDER\", `Retrying ${operationName} in ${delay}ms`, {\n attempt: attempt + 1,\n delay,\n });\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n\n throw lastError!;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/embedded-provider-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Platform-agnostic embedded provider core logic for Phantom Wallet SDK",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"test": "jest",
|
|
25
25
|
"test:watch": "jest --watch",
|
|
26
26
|
"lint": "tsc --noEmit && eslint --cache . --ext .ts,.tsx",
|
|
27
|
-
"
|
|
27
|
+
"check-types": "tsc --noEmit",
|
|
28
28
|
"prettier": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
29
29
|
},
|
|
30
30
|
"keywords": [
|
|
@@ -39,9 +39,13 @@
|
|
|
39
39
|
"author": "Phantom",
|
|
40
40
|
"license": "MIT",
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@phantom/api-key-stamper": "0.1.
|
|
43
|
-
"@phantom/
|
|
44
|
-
"@phantom/
|
|
42
|
+
"@phantom/api-key-stamper": "^0.1.3",
|
|
43
|
+
"@phantom/base64url": "^0.1.0",
|
|
44
|
+
"@phantom/client": "^0.1.6",
|
|
45
|
+
"@phantom/constants": "^0.0.2",
|
|
46
|
+
"@phantom/parsers": "^0.0.6",
|
|
47
|
+
"@phantom/sdk-types": "^0.1.2",
|
|
48
|
+
"bs58": "^6.0.0"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
47
51
|
"@types/jest": "^29.5.5",
|