@transfergratis/react-native-sdk 0.1.24 → 0.1.26

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 (182) hide show
  1. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +12 -5
  2. package/android/build/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar +0 -0
  3. package/android/build/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt +0 -0
  4. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  5. package/android/build/intermediates/incremental/debug-mergeJavaRes/merge-state +0 -0
  6. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +61 -59
  7. package/android/build/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-transfergratis-react-native-sdk.jar +0 -0
  8. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +12 -5
  9. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  10. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  11. package/android/build/outputs/aar/transfergratis-react-native-sdk-debug.aar +0 -0
  12. package/android/build/outputs/logs/manifest-merger-debug-report.txt +26 -34
  13. package/android/src/main/AndroidManifest.xml +22 -7
  14. package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
  15. package/build/components/EnhancedCameraView.web.js +76 -21
  16. package/build/components/EnhancedCameraView.web.js.map +1 -1
  17. package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts +12 -0
  18. package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts.map +1 -0
  19. package/build/components/KYCElements/AdditionalDocumentsTemplate.js +283 -0
  20. package/build/components/KYCElements/AdditionalDocumentsTemplate.js.map +1 -0
  21. package/build/components/KYCElements/EmailVerificationTemplate.d.ts +12 -0
  22. package/build/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -0
  23. package/build/components/KYCElements/EmailVerificationTemplate.js +212 -0
  24. package/build/components/KYCElements/EmailVerificationTemplate.js.map +1 -0
  25. package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  26. package/build/components/KYCElements/IDCardCapture.js +216 -14
  27. package/build/components/KYCElements/IDCardCapture.js.map +1 -1
  28. package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -0
  29. package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
  30. package/build/components/KYCElements/OrientationVideoCapture.js +2 -2
  31. package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
  32. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -0
  33. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
  34. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +2 -2
  35. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
  36. package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -0
  37. package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
  38. package/build/components/KYCElements/OrientationVideoCaptureFinal.js +2 -2
  39. package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
  40. package/build/components/KYCElements/PersonalInformationTemplate.d.ts +12 -0
  41. package/build/components/KYCElements/PersonalInformationTemplate.d.ts.map +1 -0
  42. package/build/components/KYCElements/PersonalInformationTemplate.js +120 -0
  43. package/build/components/KYCElements/PersonalInformationTemplate.js.map +1 -0
  44. package/build/components/KYCElements/PhoneVerificationTemplate.d.ts +12 -0
  45. package/build/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -0
  46. package/build/components/KYCElements/PhoneVerificationTemplate.js +185 -0
  47. package/build/components/KYCElements/PhoneVerificationTemplate.js.map +1 -0
  48. package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
  49. package/build/components/KYCElements/SelfieCaptureTemplate.js +7 -3
  50. package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
  51. package/build/components/KYCElements/WelcomeTemplate.js +2 -1
  52. package/build/components/KYCElements/WelcomeTemplate.js.map +1 -1
  53. package/build/components/OverLay/type.d.ts +2 -0
  54. package/build/components/OverLay/type.d.ts.map +1 -1
  55. package/build/components/OverLay/type.js.map +1 -1
  56. package/build/components/TemplateKYCExample.d.ts +10 -0
  57. package/build/components/TemplateKYCExample.d.ts.map +1 -1
  58. package/build/components/TemplateKYCExample.js +7 -30
  59. package/build/components/TemplateKYCExample.js.map +1 -1
  60. package/build/components/TemplateKYCFlowRefactored.d.ts +12 -0
  61. package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  62. package/build/components/TemplateKYCFlowRefactored.js +25 -3
  63. package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
  64. package/build/config/KYCConfig.d.ts +14 -0
  65. package/build/config/KYCConfig.d.ts.map +1 -0
  66. package/build/config/KYCConfig.js +26 -0
  67. package/build/config/KYCConfig.js.map +1 -0
  68. package/build/config/allowedDomains.d.ts.map +1 -1
  69. package/build/config/allowedDomains.js +4 -19
  70. package/build/config/allowedDomains.js.map +1 -1
  71. package/build/hooks/useOrientationVideo.d.ts +2 -1
  72. package/build/hooks/useOrientationVideo.d.ts.map +1 -1
  73. package/build/hooks/useOrientationVideo.js +3 -3
  74. package/build/hooks/useOrientationVideo.js.map +1 -1
  75. package/build/hooks/useTemplateKYCFlow.d.ts +18 -1
  76. package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  77. package/build/hooks/useTemplateKYCFlow.js +410 -56
  78. package/build/hooks/useTemplateKYCFlow.js.map +1 -1
  79. package/build/i18n/en/index.d.ts +42 -0
  80. package/build/i18n/en/index.d.ts.map +1 -1
  81. package/build/i18n/en/index.js +44 -2
  82. package/build/i18n/en/index.js.map +1 -1
  83. package/build/i18n/fr/index.d.ts +28 -0
  84. package/build/i18n/fr/index.d.ts.map +1 -1
  85. package/build/i18n/fr/index.js +30 -2
  86. package/build/i18n/fr/index.js.map +1 -1
  87. package/build/i18n/types.d.ts +2 -0
  88. package/build/i18n/types.d.ts.map +1 -1
  89. package/build/i18n/types.js.map +1 -1
  90. package/build/index.d.ts +1 -0
  91. package/build/index.d.ts.map +1 -1
  92. package/build/index.js +2 -0
  93. package/build/index.js.map +1 -1
  94. package/build/modules/api/CardAuthentification.d.ts +24 -3
  95. package/build/modules/api/CardAuthentification.d.ts.map +1 -1
  96. package/build/modules/api/CardAuthentification.js +90 -12
  97. package/build/modules/api/CardAuthentification.js.map +1 -1
  98. package/build/modules/api/KYCService.d.ts +17 -7
  99. package/build/modules/api/KYCService.d.ts.map +1 -1
  100. package/build/modules/api/KYCService.js +125 -37
  101. package/build/modules/api/KYCService.js.map +1 -1
  102. package/build/modules/api/SelfieVerification.d.ts +3 -1
  103. package/build/modules/api/SelfieVerification.d.ts.map +1 -1
  104. package/build/modules/api/SelfieVerification.js +17 -1
  105. package/build/modules/api/SelfieVerification.js.map +1 -1
  106. package/build/modules/api/TemplateService.d.ts +0 -1
  107. package/build/modules/api/TemplateService.d.ts.map +1 -1
  108. package/build/modules/api/TemplateService.js +3 -3
  109. package/build/modules/api/TemplateService.js.map +1 -1
  110. package/build/modules/camera/VisionCameraModule.web.d.ts.map +1 -1
  111. package/build/modules/camera/VisionCameraModule.web.js +27 -8
  112. package/build/modules/camera/VisionCameraModule.web.js.map +1 -1
  113. package/build/types/KYC.types.d.ts +130 -5
  114. package/build/types/KYC.types.d.ts.map +1 -1
  115. package/build/types/KYC.types.js.map +1 -1
  116. package/build/types/env.types.d.ts +13 -0
  117. package/build/types/env.types.d.ts.map +1 -0
  118. package/build/types/env.types.js +2 -0
  119. package/build/types/env.types.js.map +1 -0
  120. package/build/utils/cropByObb.d.ts +7 -0
  121. package/build/utils/cropByObb.d.ts.map +1 -1
  122. package/build/utils/cropByObb.js +20 -1
  123. package/build/utils/cropByObb.js.map +1 -1
  124. package/build/utils/deviceDetection.d.ts +6 -0
  125. package/build/utils/deviceDetection.d.ts.map +1 -0
  126. package/build/utils/deviceDetection.js +12 -0
  127. package/build/utils/deviceDetection.js.map +1 -0
  128. package/build/utils/platformAlert.d.ts.map +1 -1
  129. package/build/utils/platformAlert.js.map +1 -1
  130. package/build/utils/template-transformer.d.ts.map +1 -1
  131. package/build/utils/template-transformer.js +12 -0
  132. package/build/utils/template-transformer.js.map +1 -1
  133. package/build/web/WebKYCEntry.d.ts.map +1 -1
  134. package/build/web/WebKYCEntry.js +88 -38
  135. package/build/web/WebKYCEntry.js.map +1 -1
  136. package/package.json +1 -1
  137. package/plugin/build/index.d.ts +1 -0
  138. package/plugin/build/index.js +3 -1
  139. package/plugin/build/withRemovePermissions.d.ts +3 -0
  140. package/plugin/build/withRemovePermissions.js +67 -0
  141. package/plugin/build/withVisionCamera.js +3 -4
  142. package/plugin/src/index.ts +2 -1
  143. package/plugin/src/withRemovePermissions.js +85 -0
  144. package/plugin/src/withRemovePermissions.ts +83 -0
  145. package/plugin/src/withVisionCamera.js +3 -4
  146. package/plugin/src/withVisionCamera.ts +3 -4
  147. package/plugin/tsconfig.tsbuildinfo +1 -1
  148. package/plugin.js +6 -1
  149. package/src/components/EnhancedCameraView.web.tsx +76 -21
  150. package/src/components/KYCElements/AdditionalDocumentsTemplate.tsx +346 -0
  151. package/src/components/KYCElements/EmailVerificationTemplate.tsx +278 -0
  152. package/src/components/KYCElements/IDCardCapture.tsx +253 -21
  153. package/src/components/KYCElements/OrientationVideoCapture.tsx +4 -1
  154. package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +4 -1
  155. package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +4 -1
  156. package/src/components/KYCElements/PersonalInformationTemplate.tsx +158 -0
  157. package/src/components/KYCElements/PhoneVerificationTemplate.tsx +253 -0
  158. package/src/components/KYCElements/SelfieCaptureTemplate.tsx +6 -3
  159. package/src/components/KYCElements/WelcomeTemplate.tsx +2 -1
  160. package/src/components/OverLay/type.ts +2 -0
  161. package/src/components/TemplateKYCExample.tsx +35 -46
  162. package/src/components/TemplateKYCFlowRefactored.tsx +46 -2
  163. package/src/config/KYCConfig.ts +34 -0
  164. package/src/config/allowedDomains.ts +7 -26
  165. package/src/hooks/useOrientationVideo.ts +5 -4
  166. package/src/hooks/useTemplateKYCFlow.tsx +443 -56
  167. package/src/i18n/en/index.ts +46 -3
  168. package/src/i18n/fr/index.ts +31 -2
  169. package/src/i18n/types.ts +2 -0
  170. package/src/index.ts +3 -0
  171. package/src/modules/api/CardAuthentification.ts +98 -12
  172. package/src/modules/api/KYCService.ts +158 -37
  173. package/src/modules/api/SelfieVerification.ts +25 -3
  174. package/src/modules/api/TemplateService.ts +4 -4
  175. package/src/modules/camera/VisionCameraModule.web.ts +30 -12
  176. package/src/types/KYC.types.ts +153 -6
  177. package/src/types/env.types.ts +13 -0
  178. package/src/utils/cropByObb.ts +20 -1
  179. package/src/utils/deviceDetection.ts +11 -0
  180. package/src/utils/platformAlert.ts +1 -0
  181. package/src/utils/template-transformer.ts +20 -8
  182. package/src/web/WebKYCEntry.tsx +123 -61
@@ -1,11 +1,33 @@
1
- import kycService, { authentification } from "./KYCService";
1
+ import kycService, { authentification, SelfieVideoResponse } from "./KYCService";
2
2
 
3
- const selfieVerification = async (selfieImage: string) => {
4
- const token = await authentification();
3
+ import { KycEnvironment } from "../../types/env.types";
4
+
5
+ const selfieVerification = async (selfieImage: string, env: KycEnvironment = 'PRODUCTION'): Promise<SelfieVideoResponse[]> => {
6
+ // In SANDBOX mode, skip AI verification and return a mock success response
7
+ if (env === 'SANDBOX') {
8
+ console.log("SANDBOX mode: Skipping AI verification for selfie");
9
+ // Return a mock response that simulates successful verification
10
+ // This allows the flow to continue without actual AI processing
11
+
12
+ const mockResponse: SelfieVideoResponse[] = [{
13
+ orientation_direction: "center",
14
+ turn_score: 1.0,
15
+ bbox: [0, 0, 100, 100],
16
+ capture: true,
17
+ instruction: "SANDBOX: AI verification skipped",
18
+ error: ""
19
+ }];
20
+ return mockResponse;
21
+ }
5
22
 
23
+ // PRODUCTION mode: perform actual AI verification
24
+ const token = await authentification();
6
25
  const response = await kycService.processSelfieOrientationPicture(selfieImage, token);
7
26
  console.log("selfieVerification response", JSON.stringify(response, null, 2));
8
27
  return response;
9
28
  }
10
29
 
30
+
31
+
32
+
11
33
  export default selfieVerification;
@@ -2,9 +2,9 @@ import axios from 'axios';
2
2
  import { BackendKYCTemplate, TemplateAPIResponse } from '../../types/KYC.types';
3
3
  import { logger } from '../../utils/logger';
4
4
  import { errorMessage } from './KYCService';
5
+ import KYCConfig from '../../config/KYCConfig';
5
6
 
6
7
  export class TemplateServiceClass {
7
- private backendServiceURL = 'https://service.sanctumkey.com/api/v1';
8
8
  private cache: Map<string, { template: BackendKYCTemplate; timestamp: number }> = new Map();
9
9
  private cacheTimeout = 5 * 60 * 1000; // 5 minutes
10
10
 
@@ -55,8 +55,8 @@ export class TemplateServiceClass {
55
55
  }
56
56
 
57
57
  try {
58
- const url = `${this.backendServiceURL}/templates/kyc/template/${templateId}/`;
59
- logger.log(`Fetching template from: ${url} with apiKey: ${apiKey} and token: ${token}`,{
58
+ const url = `${KYCConfig.getBackendUrl()}/templates/kyc/template/${templateId}/`;
59
+ logger.log(`Fetching template from: ${url} with apiKey: ${apiKey} and token: ${token}`, {
60
60
  headers: this.getHeaders(apiKey, token)
61
61
  });
62
62
 
@@ -142,7 +142,7 @@ export class TemplateServiceClass {
142
142
  */
143
143
  async fetchTemplateList(apiKey?: string, token?: string): Promise<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>> {
144
144
  try {
145
- const url = `${this.backendServiceURL}/templates/kyc/templates`;
145
+ const url = `${KYCConfig.getBackendUrl()}/templates/kyc/templates`;
146
146
  logger.log(`Fetching template list from: ${url}`);
147
147
 
148
148
  const response = await axios.get<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>>(url, {
@@ -151,17 +151,18 @@ export class VisionCameraModule {
151
151
  return false;
152
152
  }
153
153
 
154
- const stream = await navigator.mediaDevices.getUserMedia({
155
- video: {
154
+ // Use min + ideal so Android Chrome doesn't cache low resolution (e.g. 640x480)
155
+ const stream = await navigator.mediaDevices.getUserMedia({
156
+ video: {
156
157
  facingMode: 'user',
157
- width: { ideal: 1280 },
158
- height: { ideal: 720 }
159
- }
158
+ width: { min: 1280, ideal: 1920 },
159
+ height: { min: 720, ideal: 1080 },
160
+ },
160
161
  });
161
-
162
+
162
163
  // Libérer le stream de test
163
164
  stream.getTracks().forEach(track => track.stop());
164
-
165
+
165
166
  return true;
166
167
  } catch (error) {
167
168
  console.error('Error requesting camera permission:', error);
@@ -330,13 +331,30 @@ export class VisionCameraModule {
330
331
  return;
331
332
  }
332
333
 
333
- this.stream = await navigator.mediaDevices.getUserMedia({
334
+ const constraints: MediaStreamConstraints = {
334
335
  video: {
335
336
  facingMode: 'user',
336
- width: { ideal: 1280 },
337
- height: { ideal: 720 }
337
+ width: { min: 1280, ideal: 1920 },
338
+ height: { min: 720, ideal: 1080 },
339
+ },
340
+ };
341
+
342
+ try {
343
+ this.stream = await navigator.mediaDevices.getUserMedia(constraints);
344
+ } catch (err) {
345
+ const name = err instanceof Error ? err.name : '';
346
+ if (name === 'OverconstrainedError') {
347
+ this.stream = await navigator.mediaDevices.getUserMedia({
348
+ video: {
349
+ facingMode: 'user',
350
+ width: { ideal: 1920 },
351
+ height: { ideal: 1080 },
352
+ },
353
+ });
354
+ } else {
355
+ throw err;
338
356
  }
339
- });
357
+ }
340
358
 
341
359
  if (this.videoElement) {
342
360
  this.videoElement.srcObject = this.stream;
@@ -531,7 +549,7 @@ export class VisionCameraModule {
531
549
  context.drawImage(this.videoElement, 0, 0);
532
550
 
533
551
  // Convertir en base64
534
- const imageDataUrl = this.canvasElement.toDataURL('image/jpeg', 0.8);
552
+ const imageDataUrl = this.canvasElement.toDataURL('image/jpeg', 0.95);
535
553
 
536
554
  // Créer un nom de fichier unique
537
555
  const timestamp = new Date().getTime();
@@ -8,6 +8,7 @@ export interface Document {
8
8
  uploadedAt: Date;
9
9
  validated: boolean;
10
10
  extractedData?: DocumentData;
11
+
11
12
  }
12
13
 
13
14
  export type DocumentType = 'passport' | 'id_card' | 'drivers_license';
@@ -406,12 +407,17 @@ export type ComponentConfig =
406
407
  | FileUploadConfig
407
408
  | LocationConfig
408
409
  | CountrySelectionConfig
409
- | WelcomeConfig;
410
+ | CountrySelectionConfig
411
+ | WelcomeConfig
412
+ | EmailVerificationConfig
413
+ | PhoneVerificationConfig
414
+ | PersonalInformationConfig
415
+ | AdditionalDocumentsConfig;
410
416
 
411
417
  // Nouveau type de composant basé sur le template JSON
412
418
  export interface TemplateComponent {
413
419
  id: number;
414
- type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress' | 'welcome';
420
+ type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress' | 'welcome' | 'email_verification' | 'phone_verification' | 'personal_information' | 'additional_documents';
415
421
  order: number;
416
422
  templateId?: number;
417
423
  labels: LocalizedText | Record<string, LocalizedText>;
@@ -449,6 +455,8 @@ export interface SessionState {
449
455
  isInitialized: boolean;
450
456
  isProcessing: boolean;
451
457
  error: string | null;
458
+ /** True once loadSessionData has run (for resume flow); allows UI to show loading until country/data restored */
459
+ sessionDataRestored?: boolean;
452
460
  }
453
461
 
454
462
  export type VerificationStatus = 'idle' | 'in_progress' | 'success' | 'failed';
@@ -463,11 +471,11 @@ export interface VerificationState {
463
471
  // Actions pour le template KYC
464
472
  export interface TemplateActions {
465
473
  initializeTemplate: (template: KYCTemplate) => void;
466
- nextComponent: () => void;
474
+ nextComponent: (overrideData?: any) => void;
467
475
  previousComponent: () => void;
468
476
  goToComponent: (componentId: number) => void;
469
477
  updateComponentData: (componentId: number, data: any) => void;
470
- validateComponent: (componentId: number) => boolean;
478
+ validateComponent: (componentId: number, dataOverride?: any) => boolean;
471
479
  submitTemplate: () => Promise<void>;
472
480
  resetTemplate: () => void;
473
481
  setLanguage: (language: string) => void;
@@ -476,7 +484,7 @@ export interface TemplateActions {
476
484
  submitVerification: () => Promise<void>;
477
485
  }
478
486
 
479
- // Hook pour le template KYC
487
+ // Hook pour le template KYC (return type of useTemplateKYCFlow)
480
488
  export interface UseTemplateReturn {
481
489
  state: TemplateState;
482
490
  actions: TemplateActions;
@@ -487,6 +495,9 @@ export interface UseTemplateReturn {
487
495
  isComplete: boolean;
488
496
  getLocalizedText: (text: LocalizedText) => string;
489
497
  initializeSession: () => Promise<void>;
498
+ env: 'PRODUCTION' | 'SANDBOX';
499
+ /** Optional API key for backend auth (e.g. email verification endpoints). */
500
+ apiKey?: string;
490
501
  }
491
502
 
492
503
 
@@ -646,7 +657,7 @@ export interface BackendComponentTranslations {
646
657
  // Backend template component
647
658
  export interface BackendTemplateComponent {
648
659
  id: string;
649
- type: 'welcome' | 'location-capture' | 'government-id' | 'selfie-capture' | 'review-submit' | 'verification-progress';
660
+ type: 'welcome' | 'location-capture' | 'government-id' | 'selfie-capture' | 'review-submit' | 'verification-progress' | 'email-verification' | 'phone-verification' | 'personal-information' | 'additional-documents';
650
661
  order: number;
651
662
  config: BackendComponentConfig;
652
663
  required?: boolean;
@@ -671,6 +682,74 @@ export interface BackendKYCTemplate {
671
682
  };
672
683
  }
673
684
 
685
+ // ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====
686
+
687
+ export interface EmailVerificationConfig {
688
+ allowResend: boolean;
689
+ otpSettings: {
690
+ codeLength: number;
691
+ expiryTime: number;
692
+ };
693
+ resendCooldown: number;
694
+ emailValidation: {
695
+ corporateOnly: boolean;
696
+ validateFormat: boolean;
697
+ checkDisposable: boolean;
698
+ checkDeliverability: boolean;
699
+ };
700
+ verificationMethod: string;
701
+ required?: boolean;
702
+ }
703
+
704
+ export interface PhoneVerificationConfig {
705
+ required: boolean;
706
+ codeExpiry: number;
707
+ codeLength: number;
708
+ maxAttempts: number;
709
+ resendDelay: number;
710
+ countryRestrictions: string;
711
+ verificationMethods: string[];
712
+ allowSkipForVerified: boolean;
713
+ }
714
+
715
+ export interface PersonalInfoField {
716
+ id: string;
717
+ type: string;
718
+ label: string;
719
+ required: boolean;
720
+ placeholder?: string;
721
+ autoFillFromId?: boolean;
722
+ minAge?: number;
723
+ verifyAge?: boolean;
724
+ dateFormat?: string;
725
+ }
726
+
727
+ export interface PersonalInformationConfig {
728
+ fields: PersonalInfoField[];
729
+ validationSettings: {
730
+ validateOnBlur: boolean;
731
+ showAllErrorsAtOnce: boolean;
732
+ preventSubmissionWithErrors: boolean;
733
+ };
734
+ required?: boolean;
735
+ }
736
+
737
+ export interface DocumentCategory {
738
+ enabled: boolean;
739
+ category: string;
740
+ documentTypes: string[];
741
+ }
742
+
743
+ export interface AdditionalDocumentsConfig {
744
+ required: boolean;
745
+ maxSizeEach: string;
746
+ maxDocuments: number;
747
+ minDocuments: number;
748
+ documentCategories: DocumentCategory[];
749
+ customDocumentTypes: any[];
750
+ showBasedOnUserProfile: boolean;
751
+ }
752
+
674
753
  // API response for template
675
754
  export interface TemplateAPIResponse {
676
755
  id: string;
@@ -687,4 +766,72 @@ export interface TemplateAPIResponse {
687
766
  fr: string;
688
767
  [key: string]: string;
689
768
  };
769
+ }
770
+
771
+ // ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====
772
+
773
+ export interface EmailVerificationConfig {
774
+ allowResend: boolean;
775
+ otpSettings: {
776
+ codeLength: number;
777
+ expiryTime: number;
778
+ };
779
+ resendCooldown: number;
780
+ emailValidation: {
781
+ corporateOnly: boolean;
782
+ validateFormat: boolean;
783
+ checkDisposable: boolean;
784
+ checkDeliverability: boolean;
785
+ };
786
+ verificationMethod: string;
787
+ required?: boolean;
788
+ }
789
+
790
+ export interface PhoneVerificationConfig {
791
+ required: boolean;
792
+ codeExpiry: number;
793
+ codeLength: number;
794
+ maxAttempts: number;
795
+ resendDelay: number;
796
+ countryRestrictions: string;
797
+ verificationMethods: string[];
798
+ allowSkipForVerified: boolean;
799
+ }
800
+
801
+ export interface PersonalInfoField {
802
+ id: string;
803
+ type: string;
804
+ label: string;
805
+ required: boolean;
806
+ placeholder?: string;
807
+ autoFillFromId?: boolean;
808
+ minAge?: number;
809
+ verifyAge?: boolean;
810
+ dateFormat?: string;
811
+ }
812
+
813
+ export interface PersonalInformationConfig {
814
+ fields: PersonalInfoField[];
815
+ validationSettings: {
816
+ validateOnBlur: boolean;
817
+ showAllErrorsAtOnce: boolean;
818
+ preventSubmissionWithErrors: boolean;
819
+ };
820
+ required?: boolean;
821
+ }
822
+
823
+ export interface DocumentCategory {
824
+ enabled: boolean;
825
+ category: string;
826
+ documentTypes: string[];
827
+ }
828
+
829
+ export interface AdditionalDocumentsConfig {
830
+ required: boolean;
831
+ maxSizeEach: string;
832
+ maxDocuments: number;
833
+ minDocuments: number;
834
+ documentCategories: DocumentCategory[];
835
+ customDocumentTypes: any[];
836
+ showBasedOnUserProfile: boolean;
690
837
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * KYC Environment types
3
+ * PRODUCTION: Full verification with AI checks
4
+ * SANDBOX: Skip AI verification, only save data to backend
5
+ */
6
+ export type KycEnvironment = 'PRODUCTION' | 'SANDBOX';
7
+
8
+ /**
9
+ * Backend Environment types
10
+ * PRODUCTION: Production backend
11
+ * TEST: Test backend
12
+ */
13
+ export type BackendEnvironment = 'PRODUCTION' | 'TEST';
@@ -5,6 +5,21 @@ import { logger } from './logger';
5
5
 
6
6
  type Point = [number, number];
7
7
 
8
+ /** OBB confidence below this = card not fully in frame; don't crop, give user feedback. */
9
+ export const OBB_CONFIDENCE_THRESHOLD = 0.85;
10
+
11
+ /**
12
+ * card_obb format from API: [ [ [p1,p2,p3,p4], confidence ] ]
13
+ * Returns confidence in [0,1] or null if not present.
14
+ */
15
+ export function getObbConfidence(cardObb: any): number | null {
16
+ if (!cardObb || !Array.isArray(cardObb) || cardObb.length === 0) return null;
17
+ const first = cardObb[0];
18
+ if (!Array.isArray(first) || first.length < 2) return null;
19
+ const score = first[1];
20
+ return typeof score === 'number' ? score : null;
21
+ }
22
+
8
23
  // Compute axis-aligned bounding box from oriented quadrilateral
9
24
  function computeAabb(points: Point[]) {
10
25
  const xs = points.map(p => p[0]);
@@ -49,7 +64,11 @@ async function cropWeb(uri: string, points: Point[]): Promise<string> {
49
64
  // Fallback: return original for native (no dependency added); caller can still use bbox to draw overlay
50
65
  export async function cropByObb(uri: string, cardObb: any): Promise<{ base64?: string; bbox?: { minX: number; minY: number; width: number; height: number } }> {
51
66
  try {
52
- // card_obb format: [ [ [p1,p2,p3,p4], score ] ]
67
+ // card_obb format: [ [ [p1,p2,p3,p4], score ] ] — if confidence too low, don't crop (send full image)
68
+ const confidence = getObbConfidence(cardObb);
69
+ if (confidence !== null && confidence < OBB_CONFIDENCE_THRESHOLD) {
70
+ return {};
71
+ }
53
72
  const first = Array.isArray(cardObb) ? cardObb[0] : null;
54
73
  const points = Array.isArray(first?.[0]) ? (first[0] as Point[]) : null;
55
74
  if (!points || points.length !== 4) return {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Checks if the current environment is a mobile web browser based on User Agent.
3
+ * This can be used to distinguish between desktop web and mobile web.
4
+ */
5
+ export const isMobileWeb = (): boolean => {
6
+ if (typeof window === 'undefined' || !window.navigator) {
7
+ return false;
8
+ }
9
+ const userAgent = window.navigator.userAgent;
10
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
11
+ };
@@ -21,6 +21,7 @@ export const showAlert = (
21
21
  const fullMessage = message ? `${title}\n\n${message}` : title;
22
22
 
23
23
  if (buttons && buttons.length > 1) {
24
+
24
25
  // Multiple buttons - use confirm dialog
25
26
  const confirmed = window.confirm(fullMessage);
26
27
 
@@ -42,6 +42,10 @@ const COMPONENT_TYPE_MAPPING: Record<string, TemplateComponent['type']> = {
42
42
  'verification-progress': 'verification_progress',
43
43
  'file-upload': 'file_upload',
44
44
  'country-selection': 'country_selection',
45
+ 'email-verification': 'email_verification',
46
+ 'phone-verification': 'phone_verification',
47
+ 'personal-information': 'personal_information',
48
+ 'additional-documents': 'additional_documents',
45
49
  };
46
50
 
47
51
  /**
@@ -241,6 +245,14 @@ function transformComponentConfig(
241
245
  default_country: backendConfig.default_country || '',
242
246
  required: backendConfig.required !== false,
243
247
  } as CountrySelectionConfig;
248
+ case 'email_verification':
249
+ return backendConfig as any;
250
+ case 'phone_verification':
251
+ return backendConfig as any;
252
+ case 'personal_information':
253
+ return backendConfig as any;
254
+ case 'additional_documents':
255
+ return backendConfig as any;
244
256
  default:
245
257
  return backendConfig as ComponentConfig;
246
258
  }
@@ -328,23 +340,23 @@ export function transformBackendTemplateToSDK(
328
340
  // Auto-create country_selection component before id_card if government-id has selection data
329
341
  // Check if country_selection already exists in backend template
330
342
  const hasCountrySelectionInBackend = sortedComponents.some(c => (c as any).type === 'country-selection');
331
-
343
+
332
344
  if (!hasCountrySelectionInBackend) {
333
345
  // Find the first government-id component with selection data
334
- const govIdWithSelection = sortedComponents.find(backendComp =>
335
- backendComp.type === 'government-id' &&
346
+ const govIdWithSelection = sortedComponents.find(backendComp =>
347
+ backendComp.type === 'government-id' &&
336
348
  backendComp.config && (
337
349
  (backendComp.config as any).selectedCountries ||
338
350
  (backendComp.config as any).documentTypesByCountry
339
351
  )
340
352
  );
341
-
353
+
342
354
  if (govIdWithSelection) {
343
355
  // Find the corresponding transformed id_card component
344
- const transformedIdCard = transformedComponents.find(c =>
356
+ const transformedIdCard = transformedComponents.find(c =>
345
357
  hashStringToNumber(govIdWithSelection.id) === c.id
346
358
  );
347
-
359
+
348
360
  if (transformedIdCard) {
349
361
  // Create a country_selection component before id_card
350
362
  const countrySelectionComponent: TemplateComponent = {
@@ -372,14 +384,14 @@ export function transformBackendTemplateToSDK(
372
384
  required: true,
373
385
  } as CountrySelectionConfig,
374
386
  };
375
-
387
+
376
388
  // Insert country_selection before id_card in transformedComponents
377
389
  const idCardIndex = transformedComponents.indexOf(transformedIdCard);
378
390
  transformedComponents.splice(idCardIndex, 0, countrySelectionComponent);
379
391
  }
380
392
  }
381
393
  }
382
-
394
+
383
395
  // Re-assign order values sequentially after insertion
384
396
  transformedComponents.forEach((comp, index) => {
385
397
  comp.order = index + 1;