@learncard/partner-connect 0.2.0

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.
@@ -0,0 +1,383 @@
1
+ /**
2
+ * LearnCard Partner Connect SDK - Type Definitions
3
+ */
4
+ /**
5
+ * Configuration options for initializing the SDK
6
+ */
7
+ interface PartnerConnectOptions {
8
+ /**
9
+ * The origin(s) of the LearnCard host
10
+ *
11
+ * This can be a single string or an array of strings to serve as a whitelist for
12
+ * the `lc_host_override` query parameter.
13
+ *
14
+ * **Origin Configuration Hierarchy:**
15
+ * 1. **Hardcoded Default**: `https://learncard.app` (security anchor)
16
+ * 2. **Query Parameter Override**: `?lc_host_override=https://staging.learncard.app`
17
+ * - Checked against whitelist if `hostOrigin` is provided
18
+ * - Used for staging/testing environments
19
+ * 3. **Configured Origin**: First value in array or single string value
20
+ *
21
+ * **Security Model:**
22
+ * - The SDK enforces STRICT origin validation
23
+ * - Incoming messages must EXACTLY match the active host origin
24
+ * - Prevents origin spoofing: even if malicious query param is added,
25
+ * messages from unauthorized origins are rejected
26
+ *
27
+ * **Examples:**
28
+ *
29
+ * Single origin (production):
30
+ * ```typescript
31
+ * hostOrigin: 'https://learncard.app'
32
+ * // Uses: https://learncard.app
33
+ * // Override: ?lc_host_override=https://staging.learncard.app (not validated)
34
+ * ```
35
+ *
36
+ * Multiple origins (whitelist for staging):
37
+ * ```typescript
38
+ * hostOrigin: ['https://learncard.app', 'https://staging.learncard.app']
39
+ * // Default: https://learncard.app
40
+ * // Override: ?lc_host_override=https://staging.learncard.app (validated)
41
+ * // Invalid: ?lc_host_override=https://evil.com (rejected)
42
+ * ```
43
+ *
44
+ * @default 'https://learncard.app'
45
+ */
46
+ hostOrigin?: string | string[];
47
+ /**
48
+ * Whether to allow native app origins (default: true)
49
+ *
50
+ * @default true
51
+ */
52
+ allowNativeAppOrigins?: boolean;
53
+ /**
54
+ * Protocol identifier (default: 'LEARNCARD_V1')
55
+ */
56
+ protocol?: string;
57
+ /**
58
+ * Request timeout in milliseconds (default: 30000)
59
+ */
60
+ requestTimeout?: number;
61
+ }
62
+ /**
63
+ * Identity information returned from REQUEST_IDENTITY
64
+ */
65
+ interface IdentityResponse {
66
+ token: string;
67
+ user: {
68
+ did: string;
69
+ [key: string]: unknown;
70
+ };
71
+ }
72
+ /**
73
+ * Response from SEND_CREDENTIAL action
74
+ */
75
+ interface SendCredentialResponse {
76
+ credentialId: string;
77
+ [key: string]: unknown;
78
+ }
79
+ /**
80
+ * Verifiable Presentation Request Query types
81
+ */
82
+ type VPRQuery = {
83
+ type: 'QueryByTitle';
84
+ credentialQuery: {
85
+ reason?: string;
86
+ title: string;
87
+ };
88
+ } | {
89
+ type: 'QueryByExample';
90
+ credentialQuery: unknown;
91
+ };
92
+ /**
93
+ * Verifiable Presentation Request structure
94
+ */
95
+ interface VerifiablePresentationRequest {
96
+ query: VPRQuery[];
97
+ challenge: string;
98
+ domain: string;
99
+ }
100
+ /**
101
+ * Response from ASK_CREDENTIAL_SEARCH action
102
+ */
103
+ interface CredentialSearchResponse {
104
+ verifiablePresentation?: {
105
+ verifiableCredential: unknown[];
106
+ [key: string]: unknown;
107
+ };
108
+ }
109
+ /**
110
+ * Response from ASK_CREDENTIAL_SPECIFIC action
111
+ */
112
+ interface CredentialSpecificResponse {
113
+ credential?: unknown;
114
+ }
115
+ /**
116
+ * Response from REQUEST_CONSENT action
117
+ */
118
+ interface ConsentResponse {
119
+ granted: boolean;
120
+ [key: string]: unknown;
121
+ }
122
+ /**
123
+ * Response from INITIATE_TEMPLATE_ISSUE action
124
+ */
125
+ interface TemplateIssueResponse {
126
+ issued: boolean;
127
+ [key: string]: unknown;
128
+ }
129
+ /**
130
+ * Error codes that can be returned by the LearnCard host
131
+ */
132
+ type ErrorCode = 'LC_TIMEOUT' | 'LC_UNAUTHENTICATED' | 'CREDENTIAL_NOT_FOUND' | 'USER_REJECTED' | 'UNAUTHORIZED' | 'TEMPLATE_NOT_FOUND' | string;
133
+ /**
134
+ * Error object returned when a request fails
135
+ */
136
+ interface LearnCardError {
137
+ code: ErrorCode;
138
+ message: string;
139
+ }
140
+ /**
141
+ * Internal message structure sent via postMessage
142
+ */
143
+ interface PostMessageRequest {
144
+ protocol: string;
145
+ action: string;
146
+ requestId: string;
147
+ payload?: unknown;
148
+ }
149
+ /**
150
+ * Internal message structure received via postMessage
151
+ */
152
+ interface PostMessageResponse {
153
+ protocol: string;
154
+ requestId: string;
155
+ type: 'SUCCESS' | 'ERROR';
156
+ data?: unknown;
157
+ error?: LearnCardError;
158
+ }
159
+ /**
160
+ * Pending request tracking structure
161
+ */
162
+ interface PendingRequest {
163
+ resolve: (value: unknown) => void;
164
+ reject: (error: LearnCardError) => void;
165
+ timeoutId: NodeJS.Timeout;
166
+ }
167
+
168
+ /**
169
+ * LearnCard Partner Connect SDK
170
+ *
171
+ * A Promise-based JavaScript utility for managing cross-origin message communication
172
+ * between partner apps and the LearnCard host application.
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * import { createPartnerConnect } from '@learncard/partner-connect';
177
+ *
178
+ * const learnCard = createPartnerConnect({
179
+ * hostOrigin: 'https://learncard.app'
180
+ * });
181
+ *
182
+ * // Request user identity (SSO)
183
+ * const identity = await learnCard.requestIdentity();
184
+ * console.log('User DID:', identity.user.did);
185
+ * ```
186
+ */
187
+
188
+ /**
189
+ * LearnCard Partner Connect SDK class
190
+ */
191
+ declare class PartnerConnect {
192
+ /** Default host origin (security anchor) */
193
+ static readonly DEFAULT_HOST_ORIGIN = "https://learncard.app";
194
+ private hostOrigins;
195
+ private activeHostOrigin;
196
+ private allowNativeAppOrigins;
197
+ private protocol;
198
+ private requestTimeout;
199
+ private pendingRequests;
200
+ private messageListener;
201
+ private isInitialized;
202
+ constructor(options?: PartnerConnectOptions);
203
+ /**
204
+ * Configure the active host origin using the following hierarchy:
205
+ * 1. Check for `lc_host_override` query parameter (for staging/testing)
206
+ * 2. Fall back to first configured origin
207
+ * 3. Fall back to DEFAULT_HOST_ORIGIN
208
+ *
209
+ * This origin will be used for all outgoing messages and incoming message validation.
210
+ */
211
+ private configureActiveOrigin;
212
+ private isOriginNativeApp;
213
+ /**
214
+ * Check if an origin is in the configured whitelist
215
+ */
216
+ private isOriginInWhitelist;
217
+ /**
218
+ * Check if an event origin is valid against the active host origin
219
+ *
220
+ * Security Rule: Incoming messages must exactly match the active host origin.
221
+ * This prevents malicious actors from spoofing origins via query parameters.
222
+ *
223
+ * @param eventOrigin - The origin from the MessageEvent
224
+ * @returns true if the origin is valid
225
+ */
226
+ private isValidOrigin;
227
+ /**
228
+ * Set up the central message listener to handle responses from the LearnCard host
229
+ */
230
+ private setupMessageListener;
231
+ /**
232
+ * Generate a unique request ID
233
+ */
234
+ private generateRequestId;
235
+ /**
236
+ * Send a message to the parent window and return a Promise
237
+ */
238
+ private sendMessage;
239
+ /**
240
+ * Request user identity (Single Sign-On)
241
+ *
242
+ * @returns Promise resolving to user identity including DID and JWT token
243
+ * @throws {LearnCardError} When user is not authenticated or request fails
244
+ *
245
+ * @example
246
+ * ```typescript
247
+ * const identity = await learnCard.requestIdentity();
248
+ * console.log('User DID:', identity.user.did);
249
+ * console.log('JWT Token:', identity.token);
250
+ * ```
251
+ */
252
+ requestIdentity(): Promise<IdentityResponse>;
253
+ /**
254
+ * Send a credential to the user's LearnCard wallet
255
+ *
256
+ * @param credential - The verifiable credential to send
257
+ * @returns Promise resolving to credential ID
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * const response = await learnCard.sendCredential({
262
+ * '@context': ['https://www.w3.org/2018/credentials/v1'],
263
+ * type: ['VerifiableCredential'],
264
+ * credentialSubject: { id: 'did:example:123' }
265
+ * });
266
+ * console.log('Credential ID:', response.credentialId);
267
+ * ```
268
+ */
269
+ sendCredential(credential: unknown): Promise<SendCredentialResponse>;
270
+ /**
271
+ * Launch a feature in the LearnCard host application
272
+ *
273
+ * @param featurePath - Path to the feature (e.g., '/ai/topics')
274
+ * @param initialPrompt - Optional initial prompt or data
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * await learnCard.launchFeature(
279
+ * '/ai/topics?shortCircuitStep=newTopic',
280
+ * 'Help me understand cryptography'
281
+ * );
282
+ * ```
283
+ */
284
+ launchFeature(featurePath: string, initialPrompt?: string): Promise<void>;
285
+ /**
286
+ * Request credentials from the user's wallet using a query
287
+ *
288
+ * @param verifiablePresentationRequest - VPR with query criteria
289
+ * @returns Promise resolving to verifiable presentation
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * const response = await learnCard.askCredentialSearch({
294
+ * query: [{
295
+ * type: 'QueryByTitle',
296
+ * credentialQuery: {
297
+ * reason: 'We need to verify your skills',
298
+ * title: 'JavaScript Expert'
299
+ * }
300
+ * }],
301
+ * challenge: 'challenge-123',
302
+ * domain: window.location.hostname
303
+ * });
304
+ *
305
+ * if (response.verifiablePresentation) {
306
+ * console.log('Received credentials:', response.verifiablePresentation.verifiableCredential);
307
+ * }
308
+ * ```
309
+ */
310
+ askCredentialSearch(verifiablePresentationRequest: VerifiablePresentationRequest): Promise<CredentialSearchResponse>;
311
+ /**
312
+ * Request a specific credential by ID
313
+ *
314
+ * @param credentialId - The ID of the credential to request
315
+ * @returns Promise resolving to the credential
316
+ *
317
+ * @example
318
+ * ```typescript
319
+ * const response = await learnCard.askCredentialSpecific('credential-id-123');
320
+ * if (response.credential) {
321
+ * console.log('Received credential:', response.credential);
322
+ * }
323
+ * ```
324
+ */
325
+ askCredentialSpecific(credentialId: string): Promise<CredentialSpecificResponse>;
326
+ /**
327
+ * Request user consent for permissions
328
+ *
329
+ * @param contractUri - URI of the consent contract
330
+ * @returns Promise resolving to consent response
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * const response = await learnCard.requestConsent('lc:network:network.learncard.com/trpc:contract:abc123');
335
+ * if (response.granted) {
336
+ * console.log('User granted consent');
337
+ * }
338
+ * ```
339
+ */
340
+ requestConsent(contractUri: string): Promise<ConsentResponse>;
341
+ /**
342
+ * Initiate a template-based credential issuance flow
343
+ *
344
+ * @param templateId - ID of the template/boost to issue
345
+ * @param draftRecipients - Optional array of recipient DIDs
346
+ * @returns Promise resolving to template issue response
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * const response = await learnCard.initiateTemplateIssue(
351
+ * 'lc:network:network.learncard.com/trpc:boost:xyz789',
352
+ * ['did:key:abc', 'did:key:def']
353
+ * );
354
+ *
355
+ * if (response.issued) {
356
+ * console.log('Template issued successfully');
357
+ * }
358
+ * ```
359
+ */
360
+ initiateTemplateIssue(templateId: string, draftRecipients?: string[]): Promise<TemplateIssueResponse>;
361
+ /**
362
+ * Clean up the SDK and remove event listeners
363
+ */
364
+ destroy(): void;
365
+ }
366
+ /**
367
+ * Factory function to create a PartnerConnect instance
368
+ *
369
+ * @param options - Configuration options
370
+ * @returns PartnerConnect instance
371
+ *
372
+ * @example
373
+ * ```typescript
374
+ * const learnCard = createPartnerConnect({
375
+ * hostOrigin: 'https://learncard.app',
376
+ * protocol: 'LEARNCARD_V1',
377
+ * requestTimeout: 30000
378
+ * });
379
+ * ```
380
+ */
381
+ declare function createPartnerConnect(options: PartnerConnectOptions): PartnerConnect;
382
+
383
+ export { ConsentResponse, CredentialSearchResponse, CredentialSpecificResponse, ErrorCode, IdentityResponse, LearnCardError, PartnerConnect, PartnerConnectOptions, PendingRequest, PostMessageRequest, PostMessageResponse, SendCredentialResponse, TemplateIssueResponse, VPRQuery, VerifiablePresentationRequest, createPartnerConnect, createPartnerConnect as default };
@@ -0,0 +1,324 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ const _PartnerConnect = class _PartnerConnect {
5
+ constructor(options) {
6
+ __publicField(this, "hostOrigins", ["https://learncard.app"]);
7
+ __publicField(this, "activeHostOrigin", "https://learncard.app");
8
+ __publicField(this, "allowNativeAppOrigins", true);
9
+ __publicField(this, "protocol", "LEARNCARD_V1");
10
+ __publicField(this, "requestTimeout", 3e4);
11
+ __publicField(this, "pendingRequests");
12
+ __publicField(this, "messageListener", null);
13
+ __publicField(this, "isInitialized", false);
14
+ var _a;
15
+ const hostOrigin = (options == null ? void 0 : options.hostOrigin) || _PartnerConnect.DEFAULT_HOST_ORIGIN;
16
+ this.hostOrigins = Array.isArray(hostOrigin) ? hostOrigin : [hostOrigin];
17
+ this.protocol = (options == null ? void 0 : options.protocol) || "LEARNCARD_V1";
18
+ this.requestTimeout = (options == null ? void 0 : options.requestTimeout) || 3e4;
19
+ this.allowNativeAppOrigins = (_a = options == null ? void 0 : options.allowNativeAppOrigins) != null ? _a : true;
20
+ this.pendingRequests = /* @__PURE__ */ new Map();
21
+ this.configureActiveOrigin();
22
+ this.setupMessageListener();
23
+ }
24
+ /**
25
+ * Configure the active host origin using the following hierarchy:
26
+ * 1. Check for `lc_host_override` query parameter (for staging/testing)
27
+ * 2. Fall back to first configured origin
28
+ * 3. Fall back to DEFAULT_HOST_ORIGIN
29
+ *
30
+ * This origin will be used for all outgoing messages and incoming message validation.
31
+ */
32
+ configureActiveOrigin() {
33
+ if (typeof window === "undefined") {
34
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
35
+ return;
36
+ }
37
+ try {
38
+ const urlParams = new URLSearchParams(window.location.search);
39
+ const hostOverride = urlParams.get("lc_host_override");
40
+ if (hostOverride) {
41
+ if (this.hostOrigins.length > 0 && !this.isOriginInWhitelist(hostOverride)) {
42
+ console.warn(
43
+ "[LearnCard SDK] lc_host_override value is not in the configured whitelist:",
44
+ hostOverride,
45
+ "Allowed:",
46
+ this.hostOrigins
47
+ );
48
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
49
+ } else {
50
+ this.activeHostOrigin = hostOverride;
51
+ console.log("[LearnCard SDK] Using lc_host_override:", hostOverride);
52
+ }
53
+ } else {
54
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
55
+ console.log("[LearnCard SDK] Using configured origin:", this.activeHostOrigin);
56
+ }
57
+ } catch (error) {
58
+ console.error("[LearnCard SDK] Error configuring active origin:", error);
59
+ this.activeHostOrigin = this.hostOrigins[0] || _PartnerConnect.DEFAULT_HOST_ORIGIN;
60
+ }
61
+ }
62
+ isOriginNativeApp(origin) {
63
+ return origin.startsWith("capacitor://") || origin.startsWith("ionic://") || origin.startsWith("https://localhost") || origin.startsWith("http://localhost") || origin.startsWith("http://127.0.0.1") || origin.startsWith("http://192.168.1.164");
64
+ }
65
+ /**
66
+ * Check if an origin is in the configured whitelist
67
+ */
68
+ isOriginInWhitelist(origin) {
69
+ return this.hostOrigins.includes(origin) || this.allowNativeAppOrigins && this.isOriginNativeApp(origin);
70
+ }
71
+ /**
72
+ * Check if an event origin is valid against the active host origin
73
+ *
74
+ * Security Rule: Incoming messages must exactly match the active host origin.
75
+ * This prevents malicious actors from spoofing origins via query parameters.
76
+ *
77
+ * @param eventOrigin - The origin from the MessageEvent
78
+ * @returns true if the origin is valid
79
+ */
80
+ isValidOrigin(eventOrigin) {
81
+ return eventOrigin === this.activeHostOrigin;
82
+ }
83
+ /**
84
+ * Set up the central message listener to handle responses from the LearnCard host
85
+ */
86
+ setupMessageListener() {
87
+ if (typeof window === "undefined") {
88
+ throw new Error("PartnerConnect SDK can only be used in a browser environment");
89
+ }
90
+ this.messageListener = (event) => {
91
+ if (!this.isValidOrigin(event.origin)) {
92
+ return;
93
+ }
94
+ const data = event.data;
95
+ if (data.protocol !== this.protocol || !data.requestId) {
96
+ return;
97
+ }
98
+ const pending = this.pendingRequests.get(data.requestId);
99
+ if (!pending) {
100
+ return;
101
+ }
102
+ clearTimeout(pending.timeoutId);
103
+ this.pendingRequests.delete(data.requestId);
104
+ if (data.type === "SUCCESS") {
105
+ pending.resolve(data.data);
106
+ } else if (data.type === "ERROR") {
107
+ pending.reject(data.error || { code: "UNKNOWN_ERROR", message: "An unknown error occurred" });
108
+ }
109
+ };
110
+ window.addEventListener("message", this.messageListener);
111
+ this.isInitialized = true;
112
+ }
113
+ /**
114
+ * Generate a unique request ID
115
+ */
116
+ generateRequestId(action) {
117
+ return `${action}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
118
+ }
119
+ /**
120
+ * Send a message to the parent window and return a Promise
121
+ */
122
+ sendMessage(action, payload) {
123
+ if (!this.isInitialized) {
124
+ return Promise.reject({
125
+ code: "SDK_NOT_INITIALIZED",
126
+ message: "SDK is not initialized"
127
+ });
128
+ }
129
+ return new Promise((resolve, reject) => {
130
+ const requestId = this.generateRequestId(action);
131
+ const timeoutId = setTimeout(() => {
132
+ if (this.pendingRequests.has(requestId)) {
133
+ this.pendingRequests.delete(requestId);
134
+ reject({
135
+ code: "LC_TIMEOUT",
136
+ message: `Request ${action} timed out after ${this.requestTimeout}ms`
137
+ });
138
+ }
139
+ }, this.requestTimeout);
140
+ this.pendingRequests.set(requestId, {
141
+ resolve,
142
+ reject,
143
+ timeoutId
144
+ });
145
+ const message = {
146
+ protocol: this.protocol,
147
+ action,
148
+ requestId,
149
+ payload
150
+ };
151
+ window.parent.postMessage(message, this.activeHostOrigin);
152
+ });
153
+ }
154
+ /**
155
+ * Request user identity (Single Sign-On)
156
+ *
157
+ * @returns Promise resolving to user identity including DID and JWT token
158
+ * @throws {LearnCardError} When user is not authenticated or request fails
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * const identity = await learnCard.requestIdentity();
163
+ * console.log('User DID:', identity.user.did);
164
+ * console.log('JWT Token:', identity.token);
165
+ * ```
166
+ */
167
+ requestIdentity() {
168
+ return this.sendMessage("REQUEST_IDENTITY", { challenge: `${Date.now()}-${Math.random().toString(36).substring(2, 9)}` });
169
+ }
170
+ /**
171
+ * Send a credential to the user's LearnCard wallet
172
+ *
173
+ * @param credential - The verifiable credential to send
174
+ * @returns Promise resolving to credential ID
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * const response = await learnCard.sendCredential({
179
+ * '@context': ['https://www.w3.org/2018/credentials/v1'],
180
+ * type: ['VerifiableCredential'],
181
+ * credentialSubject: { id: 'did:example:123' }
182
+ * });
183
+ * console.log('Credential ID:', response.credentialId);
184
+ * ```
185
+ */
186
+ sendCredential(credential) {
187
+ return this.sendMessage("SEND_CREDENTIAL", { credential });
188
+ }
189
+ /**
190
+ * Launch a feature in the LearnCard host application
191
+ *
192
+ * @param featurePath - Path to the feature (e.g., '/ai/topics')
193
+ * @param initialPrompt - Optional initial prompt or data
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * await learnCard.launchFeature(
198
+ * '/ai/topics?shortCircuitStep=newTopic',
199
+ * 'Help me understand cryptography'
200
+ * );
201
+ * ```
202
+ */
203
+ launchFeature(featurePath, initialPrompt) {
204
+ return this.sendMessage("LAUNCH_FEATURE", { featurePath, initialPrompt });
205
+ }
206
+ /**
207
+ * Request credentials from the user's wallet using a query
208
+ *
209
+ * @param verifiablePresentationRequest - VPR with query criteria
210
+ * @returns Promise resolving to verifiable presentation
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const response = await learnCard.askCredentialSearch({
215
+ * query: [{
216
+ * type: 'QueryByTitle',
217
+ * credentialQuery: {
218
+ * reason: 'We need to verify your skills',
219
+ * title: 'JavaScript Expert'
220
+ * }
221
+ * }],
222
+ * challenge: 'challenge-123',
223
+ * domain: window.location.hostname
224
+ * });
225
+ *
226
+ * if (response.verifiablePresentation) {
227
+ * console.log('Received credentials:', response.verifiablePresentation.verifiableCredential);
228
+ * }
229
+ * ```
230
+ */
231
+ askCredentialSearch(verifiablePresentationRequest) {
232
+ return this.sendMessage("ASK_CREDENTIAL_SEARCH", {
233
+ verifiablePresentationRequest
234
+ });
235
+ }
236
+ /**
237
+ * Request a specific credential by ID
238
+ *
239
+ * @param credentialId - The ID of the credential to request
240
+ * @returns Promise resolving to the credential
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * const response = await learnCard.askCredentialSpecific('credential-id-123');
245
+ * if (response.credential) {
246
+ * console.log('Received credential:', response.credential);
247
+ * }
248
+ * ```
249
+ */
250
+ askCredentialSpecific(credentialId) {
251
+ return this.sendMessage("ASK_CREDENTIAL_SPECIFIC", {
252
+ credentialId
253
+ });
254
+ }
255
+ /**
256
+ * Request user consent for permissions
257
+ *
258
+ * @param contractUri - URI of the consent contract
259
+ * @returns Promise resolving to consent response
260
+ *
261
+ * @example
262
+ * ```typescript
263
+ * const response = await learnCard.requestConsent('lc:network:network.learncard.com/trpc:contract:abc123');
264
+ * if (response.granted) {
265
+ * console.log('User granted consent');
266
+ * }
267
+ * ```
268
+ */
269
+ requestConsent(contractUri) {
270
+ return this.sendMessage("REQUEST_CONSENT", { contractUri });
271
+ }
272
+ /**
273
+ * Initiate a template-based credential issuance flow
274
+ *
275
+ * @param templateId - ID of the template/boost to issue
276
+ * @param draftRecipients - Optional array of recipient DIDs
277
+ * @returns Promise resolving to template issue response
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const response = await learnCard.initiateTemplateIssue(
282
+ * 'lc:network:network.learncard.com/trpc:boost:xyz789',
283
+ * ['did:key:abc', 'did:key:def']
284
+ * );
285
+ *
286
+ * if (response.issued) {
287
+ * console.log('Template issued successfully');
288
+ * }
289
+ * ```
290
+ */
291
+ initiateTemplateIssue(templateId, draftRecipients) {
292
+ return this.sendMessage("INITIATE_TEMPLATE_ISSUE", {
293
+ templateId,
294
+ draftRecipients: draftRecipients || []
295
+ });
296
+ }
297
+ /**
298
+ * Clean up the SDK and remove event listeners
299
+ */
300
+ destroy() {
301
+ if (this.messageListener) {
302
+ window.removeEventListener("message", this.messageListener);
303
+ this.messageListener = null;
304
+ }
305
+ for (const [requestId, pending] of this.pendingRequests.entries()) {
306
+ clearTimeout(pending.timeoutId);
307
+ pending.reject({
308
+ code: "SDK_DESTROYED",
309
+ message: "SDK was destroyed before request completed"
310
+ });
311
+ }
312
+ this.pendingRequests.clear();
313
+ this.isInitialized = false;
314
+ }
315
+ };
316
+ /** Default host origin (security anchor) */
317
+ __publicField(_PartnerConnect, "DEFAULT_HOST_ORIGIN", "https://learncard.app");
318
+ let PartnerConnect = _PartnerConnect;
319
+ function createPartnerConnect(options) {
320
+ return new PartnerConnect(options);
321
+ }
322
+
323
+ export { PartnerConnect, createPartnerConnect, createPartnerConnect as default };
324
+ //# sourceMappingURL=partner-connect.esm.js.map