@edge-markets/connect-link 1.2.0 → 1.3.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.
- package/dist/index.d.mts +513 -129
- package/dist/index.d.ts +513 -129
- package/dist/index.js +548 -7
- package/dist/index.mjs +543 -2
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { ALL_EDGE_SCOPES, EDGE_SCOPES, EdgeEnvironment, EdgeError, EdgeLinkExit, EdgeLinkSuccess, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, isEdgeError } from '@edge-markets/connect';
|
|
1
|
+
import { EdgeLinkConfigBase, EdgeScope, EdgeLinkSuccess, EdgeLinkExit, PKCEPair } from '@edge-markets/connect';
|
|
2
|
+
export { ALL_EDGE_SCOPES, EDGE_SCOPES, EdgeEnvironment, EdgeError, EdgeLinkEvent, EdgeLinkEventName, EdgeLinkExit, EdgeLinkSuccess, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, PKCEPair, isEdgeError } from '@edge-markets/connect';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* EdgeLink - Popup Authentication for EDGE Connect
|
|
@@ -51,99 +51,7 @@ export { ALL_EDGE_SCOPES, EDGE_SCOPES, EdgeEnvironment, EdgeError, EdgeLinkExit,
|
|
|
51
51
|
* Only `clientId`, `environment`, and `onSuccess` are required.
|
|
52
52
|
* Everything else has sensible defaults.
|
|
53
53
|
*/
|
|
54
|
-
interface EdgeLinkConfig {
|
|
55
|
-
/**
|
|
56
|
-
* Your OAuth client ID from the EdgeBoost partner portal.
|
|
57
|
-
* This is public and safe to include in frontend code.
|
|
58
|
-
*/
|
|
59
|
-
clientId: string;
|
|
60
|
-
/**
|
|
61
|
-
* Environment to connect to.
|
|
62
|
-
* - `'production'` - Live environment with real money
|
|
63
|
-
* - `'staging'` - Test environment for development
|
|
64
|
-
* - `'sandbox'` - Isolated mock environment (coming soon)
|
|
65
|
-
*/
|
|
66
|
-
environment: EdgeEnvironment;
|
|
67
|
-
/**
|
|
68
|
-
* Called when user successfully authenticates and grants consent.
|
|
69
|
-
*
|
|
70
|
-
* Send the `code` and `codeVerifier` to your backend for token exchange.
|
|
71
|
-
* **Never exchange tokens in the frontend** - that would expose your client secret.
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* onSuccess: async (result) => {
|
|
76
|
-
* const response = await fetch('/api/edge/exchange', {
|
|
77
|
-
* method: 'POST',
|
|
78
|
-
* headers: { 'Content-Type': 'application/json' },
|
|
79
|
-
* body: JSON.stringify({
|
|
80
|
-
* code: result.code,
|
|
81
|
-
* codeVerifier: result.codeVerifier,
|
|
82
|
-
* }),
|
|
83
|
-
* })
|
|
84
|
-
* if (response.ok) {
|
|
85
|
-
* showSuccess('EdgeBoost connected!')
|
|
86
|
-
* }
|
|
87
|
-
* }
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
onSuccess: (result: EdgeLinkSuccess) => void;
|
|
91
|
-
/**
|
|
92
|
-
* Called when user exits the Link flow (closes popup, error, etc.).
|
|
93
|
-
*
|
|
94
|
-
* Use this to handle errors and provide user feedback.
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* ```typescript
|
|
98
|
-
* onExit: (metadata) => {
|
|
99
|
-
* switch (metadata.reason) {
|
|
100
|
-
* case 'user_closed':
|
|
101
|
-
* // User closed popup - maybe show "Connect later" option
|
|
102
|
-
* break
|
|
103
|
-
* case 'popup_blocked':
|
|
104
|
-
* showMessage('Please allow popups and try again')
|
|
105
|
-
* break
|
|
106
|
-
* case 'error':
|
|
107
|
-
* showError(metadata.error?.message || 'Something went wrong')
|
|
108
|
-
* break
|
|
109
|
-
* }
|
|
110
|
-
* }
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
|
-
onExit?: (metadata: EdgeLinkExit) => void;
|
|
114
|
-
/**
|
|
115
|
-
* Called for various events during the Link flow.
|
|
116
|
-
* Useful for analytics and debugging.
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* ```typescript
|
|
120
|
-
* onEvent: (event) => {
|
|
121
|
-
* analytics.track('edge_link_event', {
|
|
122
|
-
* eventName: event.eventName,
|
|
123
|
-
* timestamp: event.timestamp,
|
|
124
|
-
* })
|
|
125
|
-
* }
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
onEvent?: (event: EdgeLinkEvent) => void;
|
|
129
|
-
/**
|
|
130
|
-
* OAuth scopes to request.
|
|
131
|
-
* @default All available scopes
|
|
132
|
-
*
|
|
133
|
-
* @example
|
|
134
|
-
* ```typescript
|
|
135
|
-
* // Request only what you need
|
|
136
|
-
* scopes: ['user.read', 'balance.read']
|
|
137
|
-
* ```
|
|
138
|
-
*/
|
|
139
|
-
scopes?: EdgeScope[];
|
|
140
|
-
/**
|
|
141
|
-
* Custom URL for the Link page.
|
|
142
|
-
* Only use for local development.
|
|
143
|
-
*
|
|
144
|
-
* @default Derived from environment config
|
|
145
|
-
*/
|
|
146
|
-
linkUrl?: string;
|
|
54
|
+
interface EdgeLinkConfig extends EdgeLinkConfigBase {
|
|
147
55
|
/**
|
|
148
56
|
* Custom redirect URI after authentication.
|
|
149
57
|
* Must be registered in your OAuth client settings.
|
|
@@ -152,21 +60,6 @@ interface EdgeLinkConfig {
|
|
|
152
60
|
*/
|
|
153
61
|
redirectUri?: string;
|
|
154
62
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Event emitted during the Link flow.
|
|
157
|
-
*/
|
|
158
|
-
interface EdgeLinkEvent {
|
|
159
|
-
/** Name of the event */
|
|
160
|
-
eventName: EdgeLinkEventName;
|
|
161
|
-
/** Unix timestamp when event occurred */
|
|
162
|
-
timestamp: number;
|
|
163
|
-
/** Additional event-specific data */
|
|
164
|
-
metadata?: Record<string, unknown>;
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Possible Link events.
|
|
168
|
-
*/
|
|
169
|
-
type EdgeLinkEventName = 'OPEN' | 'CLOSE' | 'HANDOFF' | 'TRANSITION' | 'ERROR' | 'SUCCESS';
|
|
170
63
|
/**
|
|
171
64
|
* Options for opening Link.
|
|
172
65
|
*/
|
|
@@ -317,6 +210,514 @@ interface UseEdgeLinkReturn {
|
|
|
317
210
|
}
|
|
318
211
|
declare function useEdgeLink(config: UseEdgeLinkConfig): UseEdgeLinkReturn;
|
|
319
212
|
|
|
213
|
+
/**
|
|
214
|
+
* EdgeTransferVerify - Transfer Verification Launcher for EDGE Connect
|
|
215
|
+
*
|
|
216
|
+
* EdgeTransferVerify provides a simple, reliable way to verify transfers
|
|
217
|
+
* using either an embedded iframe or a popup window. It mirrors the EdgeLink
|
|
218
|
+
* ergonomics but is purpose-built for the post-auth transfer verification flow.
|
|
219
|
+
*
|
|
220
|
+
* **Key Features:**
|
|
221
|
+
* - Callback-based API (onSuccess, onError, onCancel, onExpired, onLoaded, onEvent)
|
|
222
|
+
* - Supports both iframe (default) and popup display modes
|
|
223
|
+
* - Cross-origin communication via postMessage with strict origin validation
|
|
224
|
+
* - Nonce correlation to prevent replay attacks
|
|
225
|
+
* - Automatic cleanup on destroy
|
|
226
|
+
*
|
|
227
|
+
* @module @edge-markets/connect-link
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* import { EdgeTransferVerify } from '@edge-markets/connect-link'
|
|
232
|
+
*
|
|
233
|
+
* const verify = new EdgeTransferVerify({
|
|
234
|
+
* verificationUrl: session.verificationUrl,
|
|
235
|
+
* sessionId: session.sessionId,
|
|
236
|
+
* mode: 'iframe',
|
|
237
|
+
* container: document.getElementById('verify-container')!,
|
|
238
|
+
* onSuccess: (event) => {
|
|
239
|
+
* console.log(`Transfer ${event.transferId} verified!`)
|
|
240
|
+
* },
|
|
241
|
+
* onError: (event) => {
|
|
242
|
+
* console.error(`Verification failed: ${event.error}`)
|
|
243
|
+
* },
|
|
244
|
+
* onCancel: (event) => {
|
|
245
|
+
* console.log('User cancelled verification')
|
|
246
|
+
* },
|
|
247
|
+
* })
|
|
248
|
+
*
|
|
249
|
+
* // Launch the verification UI
|
|
250
|
+
* verify.open()
|
|
251
|
+
*
|
|
252
|
+
* // Clean up when done
|
|
253
|
+
* verify.destroy()
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
/**
|
|
257
|
+
* Event types emitted during the transfer verification flow.
|
|
258
|
+
*
|
|
259
|
+
* The verification page posts these message types back to the parent window:
|
|
260
|
+
* - `success` - User completed verification (OTP accepted)
|
|
261
|
+
* - `error` - Verification failed (invalid OTP, server error, etc.)
|
|
262
|
+
* - `cancel` - User cancelled the verification flow
|
|
263
|
+
* - `expired` - Verification session or OTP expired
|
|
264
|
+
* - `loaded` - Verification UI finished loading and is ready
|
|
265
|
+
*/
|
|
266
|
+
type TransferVerifyEventType = 'edge:transfer-verify:success' | 'edge:transfer-verify:error' | 'edge:transfer-verify:cancel' | 'edge:transfer-verify:expired' | 'edge:transfer-verify:loaded';
|
|
267
|
+
/**
|
|
268
|
+
* Event emitted from the transfer verification UI via postMessage.
|
|
269
|
+
*
|
|
270
|
+
* All events include the sessionId, transferId, and nonce for correlation.
|
|
271
|
+
* Error events also include an `error` string with a description.
|
|
272
|
+
*/
|
|
273
|
+
interface TransferVerifyEvent {
|
|
274
|
+
/** The type of verification event */
|
|
275
|
+
type: TransferVerifyEventType;
|
|
276
|
+
/** The verification session ID */
|
|
277
|
+
sessionId: string;
|
|
278
|
+
/** The transfer ID being verified */
|
|
279
|
+
transferId: string;
|
|
280
|
+
/** Nonce for replay protection — must match the value sent at launch */
|
|
281
|
+
nonce: string;
|
|
282
|
+
/** ISO 8601 timestamp of when the event was generated */
|
|
283
|
+
timestamp: string;
|
|
284
|
+
/** Error description (only present on error events) */
|
|
285
|
+
error?: string;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Display mode for the verification UI.
|
|
289
|
+
*
|
|
290
|
+
* - `'iframe'` (default) — Embeds verification inline within a container element.
|
|
291
|
+
* Best for desktop flows where you want the verification to appear seamlessly
|
|
292
|
+
* within your page layout.
|
|
293
|
+
*
|
|
294
|
+
* - `'popup'` — Opens verification in a popup window.
|
|
295
|
+
* Useful when you want a modal-like experience or when there's no suitable
|
|
296
|
+
* container element. Must be called from a user click handler.
|
|
297
|
+
*/
|
|
298
|
+
type TransferVerifyMode = 'iframe' | 'popup';
|
|
299
|
+
/**
|
|
300
|
+
* Configuration for EdgeTransferVerify.
|
|
301
|
+
*
|
|
302
|
+
* `verificationUrl` and `sessionId` are required. Everything else has sensible defaults.
|
|
303
|
+
*/
|
|
304
|
+
interface EdgeTransferVerifyConfig {
|
|
305
|
+
/**
|
|
306
|
+
* The URL for the verification page.
|
|
307
|
+
* Obtained from the `createVerificationSession` API response.
|
|
308
|
+
*/
|
|
309
|
+
verificationUrl: string;
|
|
310
|
+
/**
|
|
311
|
+
* The verification session ID.
|
|
312
|
+
* Obtained from the `createVerificationSession` API response.
|
|
313
|
+
*/
|
|
314
|
+
sessionId: string;
|
|
315
|
+
/**
|
|
316
|
+
* Optional nonce for replay protection.
|
|
317
|
+
* If not provided, a cryptographically random nonce is generated automatically.
|
|
318
|
+
* The nonce is appended to the verification URL and validated on all incoming messages.
|
|
319
|
+
*/
|
|
320
|
+
nonce?: string;
|
|
321
|
+
/**
|
|
322
|
+
* Display mode for the verification UI.
|
|
323
|
+
* @default 'iframe'
|
|
324
|
+
*/
|
|
325
|
+
mode?: TransferVerifyMode;
|
|
326
|
+
/**
|
|
327
|
+
* Container element for iframe mode.
|
|
328
|
+
* **Required** when `mode` is `'iframe'` (or when mode is omitted, since iframe is the default).
|
|
329
|
+
* The iframe will be appended as a child of this element.
|
|
330
|
+
*
|
|
331
|
+
* @example
|
|
332
|
+
* ```typescript
|
|
333
|
+
* container: document.getElementById('verify-container')!
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
container?: HTMLElement;
|
|
337
|
+
/**
|
|
338
|
+
* Called when transfer verification succeeds.
|
|
339
|
+
*
|
|
340
|
+
* The transfer has been verified — you can now poll the transfer status API
|
|
341
|
+
* to confirm completion on your backend.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```typescript
|
|
345
|
+
* onSuccess: (event) => {
|
|
346
|
+
* console.log(`Transfer ${event.transferId} verified at ${event.timestamp}`)
|
|
347
|
+
* pollTransferStatus(event.transferId)
|
|
348
|
+
* }
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
onSuccess?: (event: TransferVerifyEvent) => void;
|
|
352
|
+
/**
|
|
353
|
+
* Called when verification fails.
|
|
354
|
+
*
|
|
355
|
+
* Check `event.error` for the reason (invalid OTP, server error, etc.).
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```typescript
|
|
359
|
+
* onError: (event) => {
|
|
360
|
+
* showError(`Verification failed: ${event.error}`)
|
|
361
|
+
* }
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
onError?: (event: TransferVerifyEvent) => void;
|
|
365
|
+
/**
|
|
366
|
+
* Called when the user cancels the verification flow.
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```typescript
|
|
370
|
+
* onCancel: (event) => {
|
|
371
|
+
* showMessage('Verification was cancelled')
|
|
372
|
+
* }
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
onCancel?: (event: TransferVerifyEvent) => void;
|
|
376
|
+
/**
|
|
377
|
+
* Called when the verification session or OTP expires.
|
|
378
|
+
*
|
|
379
|
+
* You may want to create a new verification session and retry.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```typescript
|
|
383
|
+
* onExpired: (event) => {
|
|
384
|
+
* showMessage('Verification expired — please try again')
|
|
385
|
+
* createNewSession()
|
|
386
|
+
* }
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
onExpired?: (event: TransferVerifyEvent) => void;
|
|
390
|
+
/**
|
|
391
|
+
* Called when the verification UI has finished loading and is ready.
|
|
392
|
+
*
|
|
393
|
+
* Useful for hiding your own loading indicators.
|
|
394
|
+
*
|
|
395
|
+
* @example
|
|
396
|
+
* ```typescript
|
|
397
|
+
* onLoaded: () => {
|
|
398
|
+
* hideSpinner()
|
|
399
|
+
* }
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
onLoaded?: (event: TransferVerifyEvent) => void;
|
|
403
|
+
/**
|
|
404
|
+
* Called for ALL verification events.
|
|
405
|
+
* Useful for analytics, logging, and debugging.
|
|
406
|
+
*
|
|
407
|
+
* This fires in addition to the specific callbacks above.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```typescript
|
|
411
|
+
* onEvent: (event) => {
|
|
412
|
+
* analytics.track('transfer_verify_event', {
|
|
413
|
+
* type: event.type,
|
|
414
|
+
* sessionId: event.sessionId,
|
|
415
|
+
* timestamp: event.timestamp,
|
|
416
|
+
* })
|
|
417
|
+
* }
|
|
418
|
+
* ```
|
|
419
|
+
*/
|
|
420
|
+
onEvent?: (event: TransferVerifyEvent) => void;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* EdgeTransferVerify - Transfer verification launcher for EDGE Connect.
|
|
424
|
+
*
|
|
425
|
+
* Create one instance per verification session. Call `open()` to launch the
|
|
426
|
+
* verification UI. Call `destroy()` when done or when unmounting.
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* ```typescript
|
|
430
|
+
* // Iframe mode (default) — embedded in your page
|
|
431
|
+
* const verify = new EdgeTransferVerify({
|
|
432
|
+
* verificationUrl: session.verificationUrl,
|
|
433
|
+
* sessionId: session.sessionId,
|
|
434
|
+
* container: document.getElementById('verify-container')!,
|
|
435
|
+
* onSuccess: (event) => {
|
|
436
|
+
* console.log(`Transfer ${event.transferId} verified!`)
|
|
437
|
+
* },
|
|
438
|
+
* onError: (event) => {
|
|
439
|
+
* console.error(`Verification failed: ${event.error}`)
|
|
440
|
+
* },
|
|
441
|
+
* })
|
|
442
|
+
*
|
|
443
|
+
* verify.open()
|
|
444
|
+
*
|
|
445
|
+
* // Popup mode — opens in a new window
|
|
446
|
+
* const verify = new EdgeTransferVerify({
|
|
447
|
+
* verificationUrl: session.verificationUrl,
|
|
448
|
+
* sessionId: session.sessionId,
|
|
449
|
+
* mode: 'popup',
|
|
450
|
+
* onSuccess: handleSuccess,
|
|
451
|
+
* })
|
|
452
|
+
*
|
|
453
|
+
* // Must be called from a click handler for popup mode
|
|
454
|
+
* button.onclick = () => verify.open()
|
|
455
|
+
*
|
|
456
|
+
* // Clean up
|
|
457
|
+
* verify.destroy()
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
declare class EdgeTransferVerify {
|
|
461
|
+
private readonly config;
|
|
462
|
+
private readonly nonce;
|
|
463
|
+
private readonly expectedOrigin;
|
|
464
|
+
private readonly mode;
|
|
465
|
+
private popupManager;
|
|
466
|
+
private iframeManager;
|
|
467
|
+
private messageHandler;
|
|
468
|
+
private isDestroyed;
|
|
469
|
+
private isOpened;
|
|
470
|
+
/**
|
|
471
|
+
* Creates a new EdgeTransferVerify instance.
|
|
472
|
+
*
|
|
473
|
+
* @param config - Configuration options
|
|
474
|
+
* @throws Error if required config is missing or invalid
|
|
475
|
+
*/
|
|
476
|
+
constructor(config: EdgeTransferVerifyConfig);
|
|
477
|
+
/**
|
|
478
|
+
* Opens the transfer verification UI.
|
|
479
|
+
*
|
|
480
|
+
* In iframe mode, this mounts the iframe into the configured container.
|
|
481
|
+
* In popup mode, this opens a popup window.
|
|
482
|
+
*
|
|
483
|
+
* **Popup mode MUST be called directly from a user click handler!**
|
|
484
|
+
* Iframe mode can be called from any context.
|
|
485
|
+
*
|
|
486
|
+
* @throws EdgePopupBlockedError if popup mode and popup is blocked
|
|
487
|
+
* @throws Error if the instance has been destroyed or is already open
|
|
488
|
+
*
|
|
489
|
+
* @example
|
|
490
|
+
* ```typescript
|
|
491
|
+
* // Iframe mode — can call anywhere
|
|
492
|
+
* verify.open()
|
|
493
|
+
*
|
|
494
|
+
* // Popup mode — must call from click handler
|
|
495
|
+
* button.onclick = () => verify.open()
|
|
496
|
+
* ```
|
|
497
|
+
*/
|
|
498
|
+
open(): void;
|
|
499
|
+
/**
|
|
500
|
+
* Closes the verification UI.
|
|
501
|
+
*
|
|
502
|
+
* In popup mode, closes the popup window.
|
|
503
|
+
* In iframe mode, removes the iframe from the container.
|
|
504
|
+
* Does not trigger any callbacks.
|
|
505
|
+
*/
|
|
506
|
+
close(): void;
|
|
507
|
+
/**
|
|
508
|
+
* Destroys the EdgeTransferVerify instance.
|
|
509
|
+
*
|
|
510
|
+
* Closes the UI, removes the postMessage listener, and cleans up all resources.
|
|
511
|
+
* After destroy(), the instance cannot be reused.
|
|
512
|
+
*
|
|
513
|
+
* @example
|
|
514
|
+
* ```typescript
|
|
515
|
+
* // React cleanup
|
|
516
|
+
* useEffect(() => {
|
|
517
|
+
* const verify = new EdgeTransferVerify({ ... })
|
|
518
|
+
* verify.open()
|
|
519
|
+
* return () => verify.destroy()
|
|
520
|
+
* }, [])
|
|
521
|
+
* ```
|
|
522
|
+
*/
|
|
523
|
+
destroy(): void;
|
|
524
|
+
/**
|
|
525
|
+
* Checks if the verification UI is currently displayed.
|
|
526
|
+
*/
|
|
527
|
+
isOpen(): boolean;
|
|
528
|
+
/**
|
|
529
|
+
* Returns the nonce being used for this verification session.
|
|
530
|
+
* Useful for debugging and logging.
|
|
531
|
+
*/
|
|
532
|
+
getNonce(): string;
|
|
533
|
+
/**
|
|
534
|
+
* Builds the verification URL with nonce and parent origin parameters.
|
|
535
|
+
*
|
|
536
|
+
* Appends:
|
|
537
|
+
* - `nonce` — for replay protection / message correlation
|
|
538
|
+
* - `origin` — so the verification page knows where to postMessage back to
|
|
539
|
+
*/
|
|
540
|
+
private buildVerificationUrl;
|
|
541
|
+
/**
|
|
542
|
+
* Opens the verification UI in a popup window.
|
|
543
|
+
*
|
|
544
|
+
* Uses PopupManager from the existing EdgeLink infrastructure.
|
|
545
|
+
* The popup opens immediately (preserving user gesture) and navigates
|
|
546
|
+
* to the verification URL.
|
|
547
|
+
*
|
|
548
|
+
* @param url - The verification URL to load
|
|
549
|
+
* @throws EdgePopupBlockedError if the popup is blocked
|
|
550
|
+
*/
|
|
551
|
+
private openPopup;
|
|
552
|
+
/**
|
|
553
|
+
* Opens the verification UI in an iframe.
|
|
554
|
+
*
|
|
555
|
+
* Uses IframeManager to create and mount the iframe into the configured container.
|
|
556
|
+
*
|
|
557
|
+
* @param url - The verification URL to load
|
|
558
|
+
*/
|
|
559
|
+
private openIframe;
|
|
560
|
+
/**
|
|
561
|
+
* Sets up the postMessage listener for receiving events from the verification page.
|
|
562
|
+
*
|
|
563
|
+
* SECURITY: Every incoming message is validated for:
|
|
564
|
+
* 1. Origin matches the expected EDGE verification origin
|
|
565
|
+
* 2. Message schema matches TransferVerifyMessage
|
|
566
|
+
* 3. Nonce matches the nonce we sent
|
|
567
|
+
* 4. SessionId matches the session we opened
|
|
568
|
+
*/
|
|
569
|
+
private setupMessageListener;
|
|
570
|
+
/**
|
|
571
|
+
* Removes the postMessage listener.
|
|
572
|
+
*/
|
|
573
|
+
private removeMessageListener;
|
|
574
|
+
/**
|
|
575
|
+
* Handles a successful verification event.
|
|
576
|
+
*
|
|
577
|
+
* Closes the UI and notifies the consumer.
|
|
578
|
+
*/
|
|
579
|
+
private handleSuccess;
|
|
580
|
+
/**
|
|
581
|
+
* Handles a verification error event.
|
|
582
|
+
*
|
|
583
|
+
* Does NOT close the UI — the verification page may allow retry.
|
|
584
|
+
* The consumer can call close() or destroy() if they want to dismiss.
|
|
585
|
+
*/
|
|
586
|
+
private handleError;
|
|
587
|
+
/**
|
|
588
|
+
* Handles a cancellation event from the user.
|
|
589
|
+
*
|
|
590
|
+
* Closes the UI and notifies the consumer.
|
|
591
|
+
*/
|
|
592
|
+
private handleCancel;
|
|
593
|
+
/**
|
|
594
|
+
* Handles a session/OTP expiration event.
|
|
595
|
+
*
|
|
596
|
+
* Closes the UI and notifies the consumer.
|
|
597
|
+
*/
|
|
598
|
+
private handleExpired;
|
|
599
|
+
/**
|
|
600
|
+
* Handles the loaded event from the verification page.
|
|
601
|
+
*
|
|
602
|
+
* The verification UI is ready for user interaction.
|
|
603
|
+
*/
|
|
604
|
+
private handleLoaded;
|
|
605
|
+
/**
|
|
606
|
+
* Handles user closing the popup manually (popup mode only).
|
|
607
|
+
*
|
|
608
|
+
* Treated as a cancellation — we fire onCancel with a synthetic event.
|
|
609
|
+
*/
|
|
610
|
+
private handleUserClose;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Iframe Manager
|
|
615
|
+
*
|
|
616
|
+
* Manages an embedded iframe for EDGE Connect transfer verification.
|
|
617
|
+
* This is the iframe counterpart to PopupManager — it creates, configures,
|
|
618
|
+
* and cleans up an iframe element within a provided container.
|
|
619
|
+
*
|
|
620
|
+
* **Why iframe for verification?**
|
|
621
|
+
* Unlike authentication (which uses a popup to avoid phishing), transfer
|
|
622
|
+
* verification is a post-auth flow that benefits from inline embedding:
|
|
623
|
+
* - No popup blockers
|
|
624
|
+
* - Better mobile experience
|
|
625
|
+
* - Feels native to the partner's UI
|
|
626
|
+
*
|
|
627
|
+
* @module @edge-markets/connect-link/iframe-manager
|
|
628
|
+
*/
|
|
629
|
+
/**
|
|
630
|
+
* Configuration for the iframe element.
|
|
631
|
+
*/
|
|
632
|
+
interface IframeConfig {
|
|
633
|
+
/** URL to load in the iframe */
|
|
634
|
+
url: string;
|
|
635
|
+
/** Container element to append the iframe to */
|
|
636
|
+
container: HTMLElement;
|
|
637
|
+
/** Width of the iframe (default: '100%') */
|
|
638
|
+
width?: string;
|
|
639
|
+
/** Height of the iframe (default: '100%') */
|
|
640
|
+
height?: string;
|
|
641
|
+
/** Title for accessibility (screen readers) */
|
|
642
|
+
title?: string;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Callbacks for iframe lifecycle events.
|
|
646
|
+
*/
|
|
647
|
+
interface IframeCallbacks {
|
|
648
|
+
/** Called when the iframe finishes loading */
|
|
649
|
+
onLoad?: () => void;
|
|
650
|
+
/** Called if the iframe fails to load */
|
|
651
|
+
onError?: (error: Error) => void;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Manages the EDGE Connect transfer verification iframe.
|
|
655
|
+
*
|
|
656
|
+
* Handles:
|
|
657
|
+
* - Creating and configuring the iframe element
|
|
658
|
+
* - Rendering a loading state while the iframe loads
|
|
659
|
+
* - Clean removal of DOM elements on destroy
|
|
660
|
+
* - Sandbox permissions for security
|
|
661
|
+
*
|
|
662
|
+
* @example
|
|
663
|
+
* ```typescript
|
|
664
|
+
* const manager = new IframeManager()
|
|
665
|
+
*
|
|
666
|
+
* manager.mount({
|
|
667
|
+
* url: verificationUrl,
|
|
668
|
+
* container: document.getElementById('verify-container')!,
|
|
669
|
+
* }, {
|
|
670
|
+
* onLoad: () => console.log('Verification UI ready'),
|
|
671
|
+
* onError: (err) => console.error('Failed to load:', err),
|
|
672
|
+
* })
|
|
673
|
+
*
|
|
674
|
+
* // Later, clean up
|
|
675
|
+
* manager.destroy()
|
|
676
|
+
* ```
|
|
677
|
+
*/
|
|
678
|
+
declare class IframeManager {
|
|
679
|
+
private iframe;
|
|
680
|
+
private loadingEl;
|
|
681
|
+
private container;
|
|
682
|
+
private callbacks;
|
|
683
|
+
/**
|
|
684
|
+
* Creates and mounts the iframe into the provided container.
|
|
685
|
+
*
|
|
686
|
+
* Displays a branded loading state while the iframe loads,
|
|
687
|
+
* then swaps to the iframe once it's ready.
|
|
688
|
+
*
|
|
689
|
+
* @param config - Iframe configuration
|
|
690
|
+
* @param callbacks - Optional lifecycle callbacks
|
|
691
|
+
*/
|
|
692
|
+
mount(config: IframeConfig, callbacks?: IframeCallbacks): void;
|
|
693
|
+
/**
|
|
694
|
+
* Gets the iframe's content window for postMessage communication.
|
|
695
|
+
*
|
|
696
|
+
* @returns The iframe's contentWindow, or null if not mounted
|
|
697
|
+
*/
|
|
698
|
+
getContentWindow(): WindowProxy | null;
|
|
699
|
+
/**
|
|
700
|
+
* Checks if the iframe is currently mounted in the DOM.
|
|
701
|
+
*/
|
|
702
|
+
isMounted(): boolean;
|
|
703
|
+
/**
|
|
704
|
+
* Removes the iframe and loading state from the DOM.
|
|
705
|
+
* Cleans up all references for garbage collection.
|
|
706
|
+
*/
|
|
707
|
+
destroy(): void;
|
|
708
|
+
/**
|
|
709
|
+
* Renders a branded loading state in the container.
|
|
710
|
+
*
|
|
711
|
+
* This displays immediately while the iframe loads the verification URL.
|
|
712
|
+
* Matches the visual style of the PopupManager loading state.
|
|
713
|
+
*/
|
|
714
|
+
private renderLoadingState;
|
|
715
|
+
/**
|
|
716
|
+
* Hides the loading state and shows the iframe.
|
|
717
|
+
*/
|
|
718
|
+
private hideLoadingState;
|
|
719
|
+
}
|
|
720
|
+
|
|
320
721
|
/**
|
|
321
722
|
* PKCE (Proof Key for Code Exchange) Utilities
|
|
322
723
|
*
|
|
@@ -335,24 +736,7 @@ declare function useEdgeLink(config: UseEdgeLinkConfig): UseEdgeLinkReturn;
|
|
|
335
736
|
*
|
|
336
737
|
* @module @edge-markets/connect-link/pkce
|
|
337
738
|
*/
|
|
338
|
-
|
|
339
|
-
* A PKCE code verifier and challenge pair.
|
|
340
|
-
*
|
|
341
|
-
* Keep the `verifier` secret until token exchange.
|
|
342
|
-
* Send the `challenge` in the authorization URL.
|
|
343
|
-
*/
|
|
344
|
-
interface PKCEPair {
|
|
345
|
-
/**
|
|
346
|
-
* High-entropy random string (43-128 characters).
|
|
347
|
-
* Keep this secret - only send during token exchange.
|
|
348
|
-
*/
|
|
349
|
-
verifier: string;
|
|
350
|
-
/**
|
|
351
|
-
* SHA-256 hash of verifier, base64url encoded.
|
|
352
|
-
* This is public - include in authorization URL.
|
|
353
|
-
*/
|
|
354
|
-
challenge: string;
|
|
355
|
-
}
|
|
739
|
+
|
|
356
740
|
/**
|
|
357
741
|
* Generates a PKCE code verifier and challenge pair.
|
|
358
742
|
*
|
|
@@ -418,4 +802,4 @@ declare function generateState(): string;
|
|
|
418
802
|
*/
|
|
419
803
|
declare function assertCryptoAvailable(): void;
|
|
420
804
|
|
|
421
|
-
export { EdgeLink, type EdgeLinkConfig, type
|
|
805
|
+
export { EdgeLink, type EdgeLinkConfig, type EdgeLinkOpenOptions, EdgeTransferVerify, type EdgeTransferVerifyConfig, type IframeCallbacks, type IframeConfig, IframeManager, type TransferVerifyEvent, type TransferVerifyEventType, type TransferVerifyMode, type UseEdgeLinkConfig, type UseEdgeLinkReturn, assertCryptoAvailable, generatePKCE, generateState, useEdgeLink };
|