@diviswap/sdk 1.7.6

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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +510 -0
  3. package/bin/create-diviswap-app.js +25 -0
  4. package/bin/diviswap-sdk.js +4 -0
  5. package/dist/cli/index.js +1888 -0
  6. package/dist/cli/templates/nextjs-app/actions.ts.hbs +259 -0
  7. package/dist/cli/templates/nextjs-app/api-hooks.ts.hbs +439 -0
  8. package/dist/cli/templates/nextjs-app/api-route.ts.hbs +502 -0
  9. package/dist/cli/templates/nextjs-app/auth-context.tsx.hbs +59 -0
  10. package/dist/cli/templates/nextjs-app/client.ts.hbs +116 -0
  11. package/dist/cli/templates/nextjs-app/dashboard-hooks.ts.hbs +180 -0
  12. package/dist/cli/templates/nextjs-app/example-page.tsx.hbs +276 -0
  13. package/dist/cli/templates/nextjs-app/hooks.ts.hbs +252 -0
  14. package/dist/cli/templates/nextjs-app/kyc-hooks.ts.hbs +87 -0
  15. package/dist/cli/templates/nextjs-app/kyc-wizard.css.hbs +433 -0
  16. package/dist/cli/templates/nextjs-app/kyc-wizard.tsx.hbs +711 -0
  17. package/dist/cli/templates/nextjs-app/layout-wrapper.tsx.hbs +13 -0
  18. package/dist/cli/templates/nextjs-app/layout.tsx.hbs +13 -0
  19. package/dist/cli/templates/nextjs-app/middleware.ts.hbs +49 -0
  20. package/dist/cli/templates/nextjs-app/provider-wrapper.tsx.hbs +8 -0
  21. package/dist/cli/templates/nextjs-app/provider.tsx.hbs +408 -0
  22. package/dist/cli/templates/nextjs-app/setup-provider.tsx.hbs +25 -0
  23. package/dist/cli/templates/nextjs-app/types.ts.hbs +159 -0
  24. package/dist/cli/templates/react/api-client-wrapper.ts.hbs +89 -0
  25. package/dist/cli/templates/react/example.tsx.hbs +69 -0
  26. package/dist/cli/templates/react/tanstack-hooks.ts.hbs +185 -0
  27. package/dist/cli/templates/webhooks/nextjs.hbs +98 -0
  28. package/dist/index.d.mts +91 -0
  29. package/dist/index.d.ts +91 -0
  30. package/dist/index.js +2339 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/index.mjs +2313 -0
  33. package/dist/index.mjs.map +1 -0
  34. package/dist/react/index.d.mts +192 -0
  35. package/dist/react/index.d.ts +192 -0
  36. package/dist/react/index.js +1083 -0
  37. package/dist/react/index.js.map +1 -0
  38. package/dist/react/index.mjs +1064 -0
  39. package/dist/react/index.mjs.map +1 -0
  40. package/dist/wallet-BEGvzNtB.d.mts +1614 -0
  41. package/dist/wallet-BEGvzNtB.d.ts +1614 -0
  42. package/package.json +102 -0
  43. package/src/cli/templates/index.ts +65 -0
  44. package/src/cli/templates/nextjs-app/actions.ts.hbs +259 -0
  45. package/src/cli/templates/nextjs-app/api-hooks.ts.hbs +439 -0
  46. package/src/cli/templates/nextjs-app/api-route.ts.hbs +502 -0
  47. package/src/cli/templates/nextjs-app/auth-context.tsx.hbs +59 -0
  48. package/src/cli/templates/nextjs-app/client.ts.hbs +116 -0
  49. package/src/cli/templates/nextjs-app/dashboard-hooks.ts.hbs +180 -0
  50. package/src/cli/templates/nextjs-app/example-page.tsx.hbs +276 -0
  51. package/src/cli/templates/nextjs-app/hooks.ts.hbs +252 -0
  52. package/src/cli/templates/nextjs-app/kyc-hooks.ts.hbs +87 -0
  53. package/src/cli/templates/nextjs-app/kyc-wizard.css.hbs +433 -0
  54. package/src/cli/templates/nextjs-app/kyc-wizard.tsx.hbs +711 -0
  55. package/src/cli/templates/nextjs-app/layout-wrapper.tsx.hbs +13 -0
  56. package/src/cli/templates/nextjs-app/layout.tsx.hbs +13 -0
  57. package/src/cli/templates/nextjs-app/middleware.ts.hbs +49 -0
  58. package/src/cli/templates/nextjs-app/provider-wrapper.tsx.hbs +8 -0
  59. package/src/cli/templates/nextjs-app/provider.tsx.hbs +408 -0
  60. package/src/cli/templates/nextjs-app/setup-provider.tsx.hbs +25 -0
  61. package/src/cli/templates/nextjs-app/types.ts.hbs +159 -0
  62. package/src/cli/templates/react/api-client-wrapper.ts.hbs +89 -0
  63. package/src/cli/templates/react/example.tsx.hbs +69 -0
  64. package/src/cli/templates/react/tanstack-hooks.ts.hbs +185 -0
  65. package/src/cli/templates/shared/client.ts +78 -0
  66. package/src/cli/templates/webhooks/nextjs.hbs +98 -0
@@ -0,0 +1,711 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect } from "react";
4
+ import { ArrowRight, ArrowLeft, CheckCircle, AlertCircle, Loader2 } from 'lucide-react';
5
+
6
+ // Types
7
+ type KYCStep = 'intro' | 'personal' | 'identification' | 'address' | 'review' | 'success';
8
+
9
+ interface KycFormData {
10
+ firstName: string;
11
+ lastName: string;
12
+ email: string;
13
+ dobDay: string;
14
+ dobMonth: string;
15
+ dobYear: string;
16
+ idType: 'ssn' | 'tin' | 'passport';
17
+ idNumber: string;
18
+ addressLine1: string;
19
+ addressLine2?: string;
20
+ city: string;
21
+ state: string;
22
+ postalCode: string;
23
+ country: string;
24
+ }
25
+
26
+ interface LiberexKYCProps {
27
+ onSuccess?: (status: any) => void;
28
+ onError?: (error: Error) => void;
29
+ onClose?: () => void;
30
+ theme?: 'light' | 'dark' | {
31
+ primaryColor?: string;
32
+ backgroundColor?: string;
33
+ textColor?: string;
34
+ borderRadius?: string;
35
+ };
36
+ steps?: KYCStep[];
37
+ autoClose?: boolean;
38
+ className?: string;
39
+ }
40
+
41
+ export function LiberexKYC({
42
+ onSuccess,
43
+ onError,
44
+ onClose,
45
+ theme = 'light',
46
+ steps = ['intro', 'personal', 'identification', 'address', 'review', 'success'],
47
+ autoClose = false,
48
+ className = ''
49
+ }: LiberexKYCProps) {
50
+ const [currentStep, setCurrentStep] = useState<KYCStep>(steps[0]);
51
+ const [isSubmitting, setIsSubmitting] = useState(false);
52
+ const [formData, setFormData] = useState<KycFormData>({
53
+ firstName: '',
54
+ lastName: '',
55
+ email: '',
56
+ dobDay: '',
57
+ dobMonth: '',
58
+ dobYear: '',
59
+ idType: 'ssn',
60
+ idNumber: '',
61
+ addressLine1: '',
62
+ addressLine2: '',
63
+ city: '',
64
+ state: '',
65
+ postalCode: '',
66
+ country: 'US'
67
+ });
68
+
69
+ // Theme configuration
70
+ const themeConfig = typeof theme === 'string' ? {
71
+ primaryColor: theme === 'dark' ? '#6366f1' : '#4f46e5',
72
+ backgroundColor: theme === 'dark' ? '#1f2937' : '#ffffff',
73
+ textColor: theme === 'dark' ? '#f9fafb' : '#1f2937',
74
+ borderRadius: '8px'
75
+ } : theme;
76
+
77
+ const stepIndex = steps.indexOf(currentStep);
78
+ const totalSteps = steps.filter(s => s !== 'intro' && s !== 'success').length;
79
+ const progressPercentage = stepIndex === 0 ? 0 : ((stepIndex - 1) / (totalSteps - 1)) * 100;
80
+
81
+ const submitKYC = async () => {
82
+ setIsSubmitting(true);
83
+ try {
84
+ // Format date of birth
85
+ const dateOfBirth = `${formData.dobYear}-${formData.dobMonth.padStart(2, '0')}-${formData.dobDay.padStart(2, '0')}`;
86
+
87
+ // Prepare KYC data
88
+ const kycData = {
89
+ personalInfo: {
90
+ firstName: formData.firstName,
91
+ lastName: formData.lastName,
92
+ email: formData.email,
93
+ dateOfBirth,
94
+ ssn: formData.idType === 'ssn' ? formData.idNumber.replace(/-/g, '') : undefined,
95
+ tin: formData.idType === 'tin' ? formData.idNumber : undefined,
96
+ passport: formData.idType === 'passport' ? formData.idNumber : undefined,
97
+ },
98
+ address: {
99
+ addressLine1: formData.addressLine1,
100
+ addressLine2: formData.addressLine2,
101
+ city: formData.city,
102
+ state: formData.state,
103
+ postalCode: formData.postalCode,
104
+ country: formData.country,
105
+ }
106
+ };
107
+
108
+ // Call your KYC submission API
109
+ const response = await fetch('/api/diviswap', {
110
+ method: 'POST',
111
+ headers: { 'Content-Type': 'application/json' },
112
+ body: JSON.stringify({
113
+ action: 'submitKYC',
114
+ ...kycData
115
+ }),
116
+ });
117
+
118
+ if (!response.ok) {
119
+ const error = await response.json();
120
+ throw new Error(error.error || 'KYC submission failed');
121
+ }
122
+
123
+ const result = await response.json();
124
+
125
+ if (steps.includes('success')) {
126
+ setCurrentStep('success');
127
+ }
128
+
129
+ onSuccess?.(result);
130
+
131
+ if (autoClose) {
132
+ setTimeout(() => onClose?.(), 2000);
133
+ }
134
+
135
+ } catch (error: any) {
136
+ console.error('KYC submission error:', error);
137
+ onError?.(error);
138
+ } finally {
139
+ setIsSubmitting(false);
140
+ }
141
+ };
142
+
143
+ const nextStep = () => {
144
+ const currentIndex = steps.indexOf(currentStep);
145
+ if (currentIndex < steps.length - 1) {
146
+ setCurrentStep(steps[currentIndex + 1]);
147
+ }
148
+ };
149
+
150
+ const prevStep = () => {
151
+ const currentIndex = steps.indexOf(currentStep);
152
+ if (currentIndex > 0) {
153
+ setCurrentStep(steps[currentIndex - 1]);
154
+ }
155
+ };
156
+
157
+ const updateFormData = (updates: Partial<KycFormData>) => {
158
+ setFormData(prev => ({ ...prev, ...updates }));
159
+ };
160
+
161
+ const containerStyle = {
162
+ backgroundColor: themeConfig.backgroundColor,
163
+ color: themeConfig.textColor,
164
+ borderRadius: themeConfig.borderRadius
165
+ };
166
+
167
+ const primaryButtonStyle = {
168
+ backgroundColor: themeConfig.primaryColor,
169
+ borderRadius: themeConfig.borderRadius
170
+ };
171
+
172
+ return (
173
+ <div className={`diviswap-kyc-container ${className}`} style={containerStyle}>
174
+ {/* Progress Bar */}
175
+ {currentStep !== 'intro' && currentStep !== 'success' && (
176
+ <div className="progress-container">
177
+ <div className="progress-bar">
178
+ <div
179
+ className="progress-fill"
180
+ style={{
181
+ width: `${progressPercentage}%`,
182
+ backgroundColor: themeConfig.primaryColor
183
+ }}
184
+ />
185
+ </div>
186
+ <div className="progress-text">
187
+ Step {Math.max(stepIndex, 1)} of {totalSteps}
188
+ </div>
189
+ </div>
190
+ )}
191
+
192
+ {/* Step Content */}
193
+ {currentStep === 'intro' && (
194
+ <IntroStep
195
+ onNext={nextStep}
196
+ onClose={onClose}
197
+ theme={themeConfig}
198
+ />
199
+ )}
200
+
201
+ {currentStep === 'personal' && (
202
+ <PersonalInfoStep
203
+ formData={formData}
204
+ updateFormData={updateFormData}
205
+ onNext={nextStep}
206
+ onPrev={prevStep}
207
+ theme={themeConfig}
208
+ />
209
+ )}
210
+
211
+ {currentStep === 'identification' && (
212
+ <IdentificationStep
213
+ formData={formData}
214
+ updateFormData={updateFormData}
215
+ onNext={nextStep}
216
+ onPrev={prevStep}
217
+ theme={themeConfig}
218
+ />
219
+ )}
220
+
221
+ {currentStep === 'address' && (
222
+ <AddressStep
223
+ formData={formData}
224
+ updateFormData={updateFormData}
225
+ onNext={nextStep}
226
+ onPrev={prevStep}
227
+ theme={themeConfig}
228
+ />
229
+ )}
230
+
231
+ {currentStep === 'review' && (
232
+ <ReviewStep
233
+ formData={formData}
234
+ onSubmit={submitKYC}
235
+ onPrev={prevStep}
236
+ isSubmitting={isSubmitting}
237
+ theme={themeConfig}
238
+ />
239
+ )}
240
+
241
+ {currentStep === 'success' && (
242
+ <SuccessStep
243
+ onClose={onClose}
244
+ theme={themeConfig}
245
+ />
246
+ )}
247
+ </div>
248
+ );
249
+ }
250
+
251
+ // Step Components
252
+ function IntroStep({ onNext, onClose, theme }: any) {
253
+ return (
254
+ <div className="kyc-step intro-step">
255
+ <div className="step-header">
256
+ <CheckCircle className="step-icon" style={{ color: theme.primaryColor }} />
257
+ <h2>Identity Verification</h2>
258
+ <p>We need to verify your identity to comply with financial regulations. This process takes about 3 minutes.</p>
259
+ </div>
260
+
261
+ <div className="verification-info">
262
+ <div className="info-item">
263
+ <span className="info-number">1</span>
264
+ <div>
265
+ <h4>Personal Information</h4>
266
+ <p>Basic details like name and date of birth</p>
267
+ </div>
268
+ </div>
269
+ <div className="info-item">
270
+ <span className="info-number">2</span>
271
+ <div>
272
+ <h4>Identification</h4>
273
+ <p>Government-issued ID verification</p>
274
+ </div>
275
+ </div>
276
+ <div className="info-item">
277
+ <span className="info-number">3</span>
278
+ <div>
279
+ <h4>Address</h4>
280
+ <p>Current residential address</p>
281
+ </div>
282
+ </div>
283
+ </div>
284
+
285
+ <div className="step-actions">
286
+ <button
287
+ onClick={onNext}
288
+ className="btn-primary"
289
+ style={{ backgroundColor: theme.primaryColor }}
290
+ >
291
+ Start Verification
292
+ <ArrowRight className="btn-icon" />
293
+ </button>
294
+ {onClose && (
295
+ <button onClick={onClose} className="btn-secondary">
296
+ Not Now
297
+ </button>
298
+ )}
299
+ </div>
300
+ </div>
301
+ );
302
+ }
303
+
304
+ function PersonalInfoStep({ formData, updateFormData, onNext, onPrev, theme }: any) {
305
+ const isValid = formData.firstName && formData.lastName && formData.email &&
306
+ formData.dobDay && formData.dobMonth && formData.dobYear;
307
+
308
+ return (
309
+ <div className="kyc-step personal-step">
310
+ <div className="step-header">
311
+ <h2>Personal Information</h2>
312
+ <p>Please enter your legal name as it appears on your government-issued ID.</p>
313
+ </div>
314
+
315
+ <form className="step-form">
316
+ <div className="form-row">
317
+ <div className="form-field">
318
+ <label>First Name</label>
319
+ <input
320
+ type="text"
321
+ value={formData.firstName}
322
+ onChange={(e) => updateFormData({ firstName: e.target.value })}
323
+ placeholder="John"
324
+ required
325
+ />
326
+ </div>
327
+ <div className="form-field">
328
+ <label>Last Name</label>
329
+ <input
330
+ type="text"
331
+ value={formData.lastName}
332
+ onChange={(e) => updateFormData({ lastName: e.target.value })}
333
+ placeholder="Doe"
334
+ required
335
+ />
336
+ </div>
337
+ </div>
338
+
339
+ <div className="form-field">
340
+ <label>Email Address</label>
341
+ <input
342
+ type="email"
343
+ value={formData.email}
344
+ onChange={(e) => updateFormData({ email: e.target.value })}
345
+ placeholder="john@example.com"
346
+ required
347
+ />
348
+ </div>
349
+
350
+ <div className="form-field">
351
+ <label>Date of Birth</label>
352
+ <div className="date-inputs">
353
+ <select
354
+ value={formData.dobMonth}
355
+ onChange={(e) => updateFormData({ dobMonth: e.target.value })}
356
+ required
357
+ >
358
+ <option value="">Month</option>
359
+ {Array.from({ length: 12 }, (_, i) => (
360
+ <option key={i + 1} value={String(i + 1)}>
361
+ {new Date(0, i).toLocaleString('en', { month: 'long' })}
362
+ </option>
363
+ ))}
364
+ </select>
365
+ <select
366
+ value={formData.dobDay}
367
+ onChange={(e) => updateFormData({ dobDay: e.target.value })}
368
+ required
369
+ >
370
+ <option value="">Day</option>
371
+ {Array.from({ length: 31 }, (_, i) => (
372
+ <option key={i + 1} value={String(i + 1)}>
373
+ {i + 1}
374
+ </option>
375
+ ))}
376
+ </select>
377
+ <select
378
+ value={formData.dobYear}
379
+ onChange={(e) => updateFormData({ dobYear: e.target.value })}
380
+ required
381
+ >
382
+ <option value="">Year</option>
383
+ {Array.from({ length: 100 }, (_, i) => {
384
+ const year = new Date().getFullYear() - 18 - i;
385
+ return (
386
+ <option key={year} value={String(year)}>
387
+ {year}
388
+ </option>
389
+ );
390
+ })}
391
+ </select>
392
+ </div>
393
+ </div>
394
+ </form>
395
+
396
+ <div className="step-actions">
397
+ <button onClick={onPrev} className="btn-secondary">
398
+ <ArrowLeft className="btn-icon" />
399
+ Back
400
+ </button>
401
+ <button
402
+ onClick={onNext}
403
+ disabled={!isValid}
404
+ className="btn-primary"
405
+ style={{ backgroundColor: theme.primaryColor }}
406
+ >
407
+ Continue
408
+ <ArrowRight className="btn-icon" />
409
+ </button>
410
+ </div>
411
+ </div>
412
+ );
413
+ }
414
+
415
+ function IdentificationStep({ formData, updateFormData, onNext, onPrev, theme }: any) {
416
+ const isValid = formData.idType && formData.idNumber;
417
+
418
+ return (
419
+ <div className="kyc-step identification-step">
420
+ <div className="step-header">
421
+ <h2>Government ID</h2>
422
+ <p>We need to verify your government-issued identification.</p>
423
+ </div>
424
+
425
+ <form className="step-form">
426
+ <div className="form-field">
427
+ <label>ID Type</label>
428
+ <select
429
+ value={formData.idType}
430
+ onChange={(e) => updateFormData({ idType: e.target.value as 'ssn' | 'tin' | 'passport' })}
431
+ required
432
+ >
433
+ <option value="ssn">Social Security Number (SSN)</option>
434
+ <option value="tin">Taxpayer Identification Number (TIN)</option>
435
+ <option value="passport">Passport Number</option>
436
+ </select>
437
+ </div>
438
+
439
+ <div className="form-field">
440
+ <label>
441
+ {formData.idType === 'ssn' && 'Social Security Number'}
442
+ {formData.idType === 'tin' && 'Taxpayer Identification Number'}
443
+ {formData.idType === 'passport' && 'Passport Number'}
444
+ </label>
445
+ <input
446
+ type="text"
447
+ value={formData.idNumber}
448
+ onChange={(e) => updateFormData({ idNumber: e.target.value })}
449
+ placeholder={
450
+ formData.idType === 'ssn' ? '123-45-6789' :
451
+ formData.idType === 'tin' ? '12-3456789' :
452
+ 'A12345678'
453
+ }
454
+ required
455
+ />
456
+ </div>
457
+ </form>
458
+
459
+ <div className="step-actions">
460
+ <button onClick={onPrev} className="btn-secondary">
461
+ <ArrowLeft className="btn-icon" />
462
+ Back
463
+ </button>
464
+ <button
465
+ onClick={onNext}
466
+ disabled={!isValid}
467
+ className="btn-primary"
468
+ style={{ backgroundColor: theme.primaryColor }}
469
+ >
470
+ Continue
471
+ <ArrowRight className="btn-icon" />
472
+ </button>
473
+ </div>
474
+ </div>
475
+ );
476
+ }
477
+
478
+ function AddressStep({ formData, updateFormData, onNext, onPrev, theme }: any) {
479
+ const isValid = formData.addressLine1 && formData.city && formData.state &&
480
+ formData.postalCode && formData.country;
481
+
482
+ return (
483
+ <div className="kyc-step address-step">
484
+ <div className="step-header">
485
+ <h2>Address Information</h2>
486
+ <p>Please provide your current residential address.</p>
487
+ </div>
488
+
489
+ <form className="step-form">
490
+ <div className="form-field">
491
+ <label>Address Line 1</label>
492
+ <input
493
+ type="text"
494
+ value={formData.addressLine1}
495
+ onChange={(e) => updateFormData({ addressLine1: e.target.value })}
496
+ placeholder="123 Main Street"
497
+ required
498
+ />
499
+ </div>
500
+
501
+ <div className="form-field">
502
+ <label>Address Line 2 (Optional)</label>
503
+ <input
504
+ type="text"
505
+ value={formData.addressLine2}
506
+ onChange={(e) => updateFormData({ addressLine2: e.target.value })}
507
+ placeholder="Apt 4B"
508
+ />
509
+ </div>
510
+
511
+ <div className="form-row">
512
+ <div className="form-field">
513
+ <label>City</label>
514
+ <input
515
+ type="text"
516
+ value={formData.city}
517
+ onChange={(e) => updateFormData({ city: e.target.value })}
518
+ placeholder="New York"
519
+ required
520
+ />
521
+ </div>
522
+ <div className="form-field">
523
+ <label>State</label>
524
+ <input
525
+ type="text"
526
+ value={formData.state}
527
+ onChange={(e) => updateFormData({ state: e.target.value })}
528
+ placeholder="NY"
529
+ required
530
+ />
531
+ </div>
532
+ </div>
533
+
534
+ <div className="form-row">
535
+ <div className="form-field">
536
+ <label>Postal Code</label>
537
+ <input
538
+ type="text"
539
+ value={formData.postalCode}
540
+ onChange={(e) => updateFormData({ postalCode: e.target.value })}
541
+ placeholder="10001"
542
+ required
543
+ />
544
+ </div>
545
+ <div className="form-field">
546
+ <label>Country</label>
547
+ <select
548
+ value={formData.country}
549
+ onChange={(e) => updateFormData({ country: e.target.value })}
550
+ required
551
+ >
552
+ <option value="US">United States</option>
553
+ <option value="CA">Canada</option>
554
+ <option value="UK">United Kingdom</option>
555
+ {/* Add more countries as needed */}
556
+ </select>
557
+ </div>
558
+ </div>
559
+ </form>
560
+
561
+ <div className="step-actions">
562
+ <button onClick={onPrev} className="btn-secondary">
563
+ <ArrowLeft className="btn-icon" />
564
+ Back
565
+ </button>
566
+ <button
567
+ onClick={onNext}
568
+ disabled={!isValid}
569
+ className="btn-primary"
570
+ style={{ backgroundColor: theme.primaryColor }}
571
+ >
572
+ Continue
573
+ <ArrowRight className="btn-icon" />
574
+ </button>
575
+ </div>
576
+ </div>
577
+ );
578
+ }
579
+
580
+ function ReviewStep({ formData, onSubmit, onPrev, isSubmitting, theme }: any) {
581
+ return (
582
+ <div className="kyc-step review-step">
583
+ <div className="step-header">
584
+ <h2>Review Your Information</h2>
585
+ <p>Please review your information before submitting.</p>
586
+ </div>
587
+
588
+ <div className="review-sections">
589
+ <div className="review-section">
590
+ <h3>Personal Information</h3>
591
+ <div className="review-item">
592
+ <span>Name:</span>
593
+ <span>{formData.firstName} {formData.lastName}</span>
594
+ </div>
595
+ <div className="review-item">
596
+ <span>Email:</span>
597
+ <span>{formData.email}</span>
598
+ </div>
599
+ <div className="review-item">
600
+ <span>Date of Birth:</span>
601
+ <span>{formData.dobMonth}/{formData.dobDay}/{formData.dobYear}</span>
602
+ </div>
603
+ </div>
604
+
605
+ <div className="review-section">
606
+ <h3>Identification</h3>
607
+ <div className="review-item">
608
+ <span>ID Type:</span>
609
+ <span>{formData.idType.toUpperCase()}</span>
610
+ </div>
611
+ <div className="review-item">
612
+ <span>ID Number:</span>
613
+ <span>***-**-{formData.idNumber.slice(-4)}</span>
614
+ </div>
615
+ </div>
616
+
617
+ <div className="review-section">
618
+ <h3>Address</h3>
619
+ <div className="review-item">
620
+ <span>Address:</span>
621
+ <span>
622
+ {formData.addressLine1}
623
+ {formData.addressLine2 && `, ${formData.addressLine2}`}
624
+ </span>
625
+ </div>
626
+ <div className="review-item">
627
+ <span>City, State:</span>
628
+ <span>{formData.city}, {formData.state} {formData.postalCode}</span>
629
+ </div>
630
+ <div className="review-item">
631
+ <span>Country:</span>
632
+ <span>{formData.country}</span>
633
+ </div>
634
+ </div>
635
+ </div>
636
+
637
+ <div className="step-actions">
638
+ <button onClick={onPrev} className="btn-secondary" disabled={isSubmitting}>
639
+ <ArrowLeft className="btn-icon" />
640
+ Back
641
+ </button>
642
+ <button
643
+ onClick={onSubmit}
644
+ disabled={isSubmitting}
645
+ className="btn-primary"
646
+ style={{ backgroundColor: theme.primaryColor }}
647
+ >
648
+ {isSubmitting ? (
649
+ <>
650
+ <Loader2 className="btn-icon animate-spin" />
651
+ Submitting...
652
+ </>
653
+ ) : (
654
+ <>
655
+ Submit Verification
656
+ <ArrowRight className="btn-icon" />
657
+ </>
658
+ )}
659
+ </button>
660
+ </div>
661
+ </div>
662
+ );
663
+ }
664
+
665
+ function SuccessStep({ onClose, theme }: any) {
666
+ return (
667
+ <div className="kyc-step success-step">
668
+ <div className="step-header">
669
+ <CheckCircle className="step-icon success-icon" style={{ color: theme.primaryColor }} />
670
+ <h2>Verification Submitted!</h2>
671
+ <p>Your identity verification has been submitted successfully. We'll review your information and notify you of the results.</p>
672
+ </div>
673
+
674
+ <div className="success-info">
675
+ <div className="info-box">
676
+ <h4>What happens next?</h4>
677
+ <ul>
678
+ <li>We'll review your information within 24-48 hours</li>
679
+ <li>You'll receive an email with the verification results</li>
680
+ <li>Once approved, you can access all platform features</li>
681
+ </ul>
682
+ </div>
683
+ </div>
684
+
685
+ {onClose && (
686
+ <div className="step-actions">
687
+ <button
688
+ onClick={onClose}
689
+ className="btn-primary"
690
+ style={{ backgroundColor: theme.primaryColor }}
691
+ >
692
+ Continue
693
+ </button>
694
+ </div>
695
+ )}
696
+ </div>
697
+ );
698
+ }
699
+
700
+ // Export modal version
701
+ export function LiberexKYCModal({ isOpen, onClose, ...props }: LiberexKYCProps & { isOpen: boolean }) {
702
+ if (!isOpen) return null;
703
+
704
+ return (
705
+ <div className="diviswap-kyc-modal-overlay">
706
+ <div className="diviswap-kyc-modal">
707
+ <LiberexKYC {...props} onClose={onClose} />
708
+ </div>
709
+ </div>
710
+ );
711
+ }