@kyciris/core 0.1.0 → 0.1.1
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 +207 -2
- package/dist/index.d.ts +207 -2
- package/dist/index.js +269 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +269 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -21,14 +21,15 @@ var KYCSdkError = class extends Error {
|
|
|
21
21
|
this.statusCode = statusCode;
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
var
|
|
24
|
+
var _KYCCore = class _KYCCore {
|
|
25
25
|
/**
|
|
26
26
|
* Creates a new KYC Core instance
|
|
27
|
-
* @param credentials API credentials (apiKey and
|
|
27
|
+
* @param credentials API credentials (apiKey, baseUrl, and optional storage)
|
|
28
28
|
*/
|
|
29
29
|
constructor(credentials) {
|
|
30
30
|
this.eventCallbacks = [];
|
|
31
31
|
this.credentials = credentials;
|
|
32
|
+
this.storage = credentials.storage;
|
|
32
33
|
this.client = axios__default.default.create({
|
|
33
34
|
baseURL: credentials.baseUrl,
|
|
34
35
|
headers: {
|
|
@@ -41,6 +42,41 @@ var KYCCore = class _KYCCore {
|
|
|
41
42
|
return config;
|
|
42
43
|
});
|
|
43
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Persists the active verification session via the injected storage adapter.
|
|
47
|
+
* No-op when no storage was provided.
|
|
48
|
+
*/
|
|
49
|
+
async saveSession(session) {
|
|
50
|
+
if (!this.storage) return;
|
|
51
|
+
try {
|
|
52
|
+
await this.storage.setItem(_KYCCore.SESSION_KEY, JSON.stringify(session));
|
|
53
|
+
} catch {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Reads the persisted verification session, or null if none exists or no
|
|
58
|
+
* storage adapter was provided.
|
|
59
|
+
*/
|
|
60
|
+
async getSession() {
|
|
61
|
+
if (!this.storage) return null;
|
|
62
|
+
try {
|
|
63
|
+
const raw = await this.storage.getItem(_KYCCore.SESSION_KEY);
|
|
64
|
+
return raw ? JSON.parse(raw) : null;
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Clears the persisted verification session. Call this once a verification is
|
|
71
|
+
* fully complete so the next flow starts fresh.
|
|
72
|
+
*/
|
|
73
|
+
async clearSession() {
|
|
74
|
+
if (!this.storage) return;
|
|
75
|
+
try {
|
|
76
|
+
await this.storage.removeItem(_KYCCore.SESSION_KEY);
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
}
|
|
44
80
|
/**
|
|
45
81
|
* Registers a callback for KYC status events
|
|
46
82
|
* @param callback Function to call when status changes
|
|
@@ -85,6 +121,15 @@ var KYCCore = class _KYCCore {
|
|
|
85
121
|
async startVerification(params) {
|
|
86
122
|
try {
|
|
87
123
|
const response = await this.client.post("/verification/start", params);
|
|
124
|
+
const session = response.data;
|
|
125
|
+
if (session.identityId && session.verificationId) {
|
|
126
|
+
await this.saveSession({
|
|
127
|
+
identityId: session.identityId,
|
|
128
|
+
verificationId: session.verificationId,
|
|
129
|
+
externalId: params.externalId,
|
|
130
|
+
documentType: params.documentType
|
|
131
|
+
});
|
|
132
|
+
}
|
|
88
133
|
this.emitEvent({
|
|
89
134
|
type: "statusChanged",
|
|
90
135
|
status: "PENDING"
|
|
@@ -202,6 +247,225 @@ var KYCCore = class _KYCCore {
|
|
|
202
247
|
throw new KYCSdkError(message, "STATUS_CHECK_FAILED", error.response?.status);
|
|
203
248
|
}
|
|
204
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* Fetches an identity along with all of its verification records.
|
|
252
|
+
* @param identityId The identity ID to fetch
|
|
253
|
+
* @returns The identity, including the verifications array with upload paths
|
|
254
|
+
*/
|
|
255
|
+
async getIdentity(identityId) {
|
|
256
|
+
try {
|
|
257
|
+
const response = await this.client.get(`/identities/${identityId}`);
|
|
258
|
+
return response.data;
|
|
259
|
+
} catch (error) {
|
|
260
|
+
const message = error.response?.data?.message || error.message || "Failed to get identity";
|
|
261
|
+
throw new KYCSdkError(message, "IDENTITY_FETCH_FAILED", error.response?.status);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Returns the required steps for a given document type, in collection order.
|
|
266
|
+
* ID cards require both sides; driving licenses are single-sided.
|
|
267
|
+
*/
|
|
268
|
+
getRequiredSteps(documentType) {
|
|
269
|
+
if (documentType === "DRIVING_LICENSE") {
|
|
270
|
+
return ["document_front", "selfie"];
|
|
271
|
+
}
|
|
272
|
+
return ["document_front", "document_back", "selfie"];
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Computes which steps a user has already completed and which are still missing
|
|
276
|
+
* for a verification, so a paused flow can be resumed without re-uploading.
|
|
277
|
+
*
|
|
278
|
+
* Both arguments are optional: when omitted they fall back to the persisted
|
|
279
|
+
* session (see the storage adapter). Pass a verificationId to target a specific
|
|
280
|
+
* verification; otherwise the most recently updated verification is used.
|
|
281
|
+
*
|
|
282
|
+
* @param identityId Identity ID owning the verification (defaults to the session)
|
|
283
|
+
* @param verificationId Verification ID to target (defaults to the session)
|
|
284
|
+
* @returns Progress describing uploaded steps and the steps still required
|
|
285
|
+
*/
|
|
286
|
+
async getVerificationProgress(identityId, verificationId) {
|
|
287
|
+
const session = identityId && verificationId ? null : await this.getSession();
|
|
288
|
+
const resolvedIdentityId = identityId ?? session?.identityId;
|
|
289
|
+
const resolvedVerificationId = verificationId ?? session?.verificationId;
|
|
290
|
+
if (!resolvedIdentityId) {
|
|
291
|
+
throw new KYCSdkError(
|
|
292
|
+
"No identityId provided and no persisted session found",
|
|
293
|
+
"SESSION_NOT_FOUND",
|
|
294
|
+
404
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
const identity = await this.getIdentity(resolvedIdentityId);
|
|
298
|
+
const verifications = identity.verifications ?? [];
|
|
299
|
+
if (verifications.length === 0) {
|
|
300
|
+
throw new KYCSdkError("No verifications found for identity", "VERIFICATION_NOT_FOUND", 404);
|
|
301
|
+
}
|
|
302
|
+
const verification = resolvedVerificationId ? verifications.find((v) => v.id === resolvedVerificationId) : [...verifications].sort(
|
|
303
|
+
(a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
|
|
304
|
+
)[0];
|
|
305
|
+
if (!verification) {
|
|
306
|
+
throw new KYCSdkError(
|
|
307
|
+
`Verification ${resolvedVerificationId} not found for identity`,
|
|
308
|
+
"VERIFICATION_NOT_FOUND",
|
|
309
|
+
404
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
const selfieUploaded = !!verification.selfiePath;
|
|
313
|
+
const documentFrontUploaded = !!verification.documentFrontPath;
|
|
314
|
+
const documentBackUploaded = !!verification.documentBackPath;
|
|
315
|
+
const uploaded = {
|
|
316
|
+
selfie: selfieUploaded,
|
|
317
|
+
document_front: documentFrontUploaded,
|
|
318
|
+
document_back: documentBackUploaded
|
|
319
|
+
};
|
|
320
|
+
const missingSteps = this.getRequiredSteps(verification.documentType).filter(
|
|
321
|
+
(step) => !uploaded[step]
|
|
322
|
+
);
|
|
323
|
+
return {
|
|
324
|
+
verificationId: verification.id,
|
|
325
|
+
documentType: verification.documentType,
|
|
326
|
+
status: verification.status,
|
|
327
|
+
selfieUploaded,
|
|
328
|
+
documentFrontUploaded,
|
|
329
|
+
documentBackUploaded,
|
|
330
|
+
missingSteps,
|
|
331
|
+
isComplete: missingSteps.length === 0
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Returns whether every required step of a verification has already been
|
|
336
|
+
* uploaded (both document sides where applicable, plus the selfie).
|
|
337
|
+
*
|
|
338
|
+
* This is the reliable way to tell a user who has fully submitted their
|
|
339
|
+
* documents (verification is now processing on the KYC backend) apart from one
|
|
340
|
+
* who paused mid-flow with steps still missing — both look "PENDING" from the
|
|
341
|
+
* outside. Derived purely from the identity's verification records.
|
|
342
|
+
*
|
|
343
|
+
* Returns `false` (rather than throwing) when the identity has no verification
|
|
344
|
+
* records yet, so callers can treat "nothing uploaded" as "documents missing".
|
|
345
|
+
*
|
|
346
|
+
* @param identityId Identity ID owning the verification (defaults to the session)
|
|
347
|
+
* @param verificationId Verification ID to target (defaults to the most recently updated)
|
|
348
|
+
* @returns True when no steps remain to be uploaded
|
|
349
|
+
*/
|
|
350
|
+
async hasAllDocuments(identityId, verificationId) {
|
|
351
|
+
try {
|
|
352
|
+
const progress = await this.getVerificationProgress(identityId, verificationId);
|
|
353
|
+
return progress.isComplete;
|
|
354
|
+
} catch (error) {
|
|
355
|
+
if (error instanceof KYCSdkError && (error.code === "VERIFICATION_NOT_FOUND" || error.code === "SESSION_NOT_FOUND")) {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
throw error;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Uploads a single verification step (selfie, document front, or document back)
|
|
363
|
+
* in a resume-aware way: it resolves the verification from the persisted session
|
|
364
|
+
* when not given, and skips the upload if that step is already complete.
|
|
365
|
+
*
|
|
366
|
+
* @param params The step, image data, and optional verification/identity overrides
|
|
367
|
+
* @returns The upload result; `skipped` is true when the step was already uploaded
|
|
368
|
+
*/
|
|
369
|
+
async uploadStep(params) {
|
|
370
|
+
const session = params.verificationId && params.identityId ? null : await this.getSession();
|
|
371
|
+
const verificationId = params.verificationId ?? session?.verificationId;
|
|
372
|
+
const identityId = params.identityId ?? session?.identityId;
|
|
373
|
+
if (!verificationId) {
|
|
374
|
+
throw new KYCSdkError(
|
|
375
|
+
"No verificationId provided and no persisted session found",
|
|
376
|
+
"SESSION_NOT_FOUND",
|
|
377
|
+
404
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
if (identityId) {
|
|
381
|
+
const progress = await this.getVerificationProgress(identityId, verificationId);
|
|
382
|
+
if (!progress.missingSteps.includes(params.step)) {
|
|
383
|
+
return {
|
|
384
|
+
message: `Step ${params.step} already uploaded`,
|
|
385
|
+
status: progress.status,
|
|
386
|
+
skipped: true
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (params.step === "selfie") {
|
|
391
|
+
return this.uploadSelfie({
|
|
392
|
+
verificationId,
|
|
393
|
+
imageData: params.imageData,
|
|
394
|
+
mimeType: params.mimeType
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
return this.uploadDocument({
|
|
398
|
+
verificationId,
|
|
399
|
+
type: params.step === "document_front" ? "front" : "back",
|
|
400
|
+
imageData: params.imageData,
|
|
401
|
+
mimeType: params.mimeType
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
async faceMatchVerification(params) {
|
|
405
|
+
try {
|
|
406
|
+
const formData = new FormData();
|
|
407
|
+
const mimeType = params.mimeType || "image/jpeg";
|
|
408
|
+
const imageData = params.file;
|
|
409
|
+
if (imageData.startsWith("file://")) {
|
|
410
|
+
formData.append("file", {
|
|
411
|
+
uri: imageData,
|
|
412
|
+
type: mimeType,
|
|
413
|
+
name: `selfie.jpg`
|
|
414
|
+
});
|
|
415
|
+
} else if (imageData.startsWith("data:")) {
|
|
416
|
+
formData.append("file", {
|
|
417
|
+
uri: imageData,
|
|
418
|
+
type: mimeType,
|
|
419
|
+
name: `selfie.jpg`
|
|
420
|
+
});
|
|
421
|
+
} else {
|
|
422
|
+
formData.append("file", {
|
|
423
|
+
uri: `data:${mimeType};base64,${imageData}`,
|
|
424
|
+
type: mimeType,
|
|
425
|
+
name: `selfie.jpg`
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
const response = await this.client.post(
|
|
429
|
+
`identities/${params.identityId}/face-match`,
|
|
430
|
+
formData,
|
|
431
|
+
{
|
|
432
|
+
headers: { "Content-Type": "multipart/form-data" }
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
return response.data;
|
|
436
|
+
} catch (error) {
|
|
437
|
+
console.log("Upload face match error:", error.response?.data || error.message);
|
|
438
|
+
const message = error.response?.data?.message || error.message || "Failed to upload face match";
|
|
439
|
+
throw new KYCSdkError(message, "FACEMATCH_UPLOAD_FAILED", error.response?.status);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
async faceMatchStatus({
|
|
443
|
+
identityId,
|
|
444
|
+
faceCheckId,
|
|
445
|
+
interval = 3e3,
|
|
446
|
+
timeout = 12e4
|
|
447
|
+
}) {
|
|
448
|
+
const startTime = Date.now();
|
|
449
|
+
return new Promise((resolve, reject) => {
|
|
450
|
+
const poll = async () => {
|
|
451
|
+
try {
|
|
452
|
+
const status = (await this.client.get(`identities/${identityId}/face-match/status/${faceCheckId}`)).data;
|
|
453
|
+
if (status.status === "APPROVED" || status.status === "REJECTED") {
|
|
454
|
+
resolve(status);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
if (Date.now() - startTime > timeout) {
|
|
458
|
+
reject(new KYCSdkError("Polling timeout", "POLLING_TIMEOUT"));
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
setTimeout(poll, interval);
|
|
462
|
+
} catch (error) {
|
|
463
|
+
reject(error);
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
poll();
|
|
467
|
+
});
|
|
468
|
+
}
|
|
205
469
|
/**
|
|
206
470
|
* Polls for verification status until completion or timeout
|
|
207
471
|
* @param verificationId The verification ID to check
|
|
@@ -240,6 +504,9 @@ var KYCCore = class _KYCCore {
|
|
|
240
504
|
return new _KYCCore(credentials);
|
|
241
505
|
}
|
|
242
506
|
};
|
|
507
|
+
/** Storage key under which the active verification session is persisted */
|
|
508
|
+
_KYCCore.SESSION_KEY = "kyc:session";
|
|
509
|
+
var KYCCore = _KYCCore;
|
|
243
510
|
function createKYCClient(credentials) {
|
|
244
511
|
return KYCCore.createClient(credentials);
|
|
245
512
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["axios"],"mappings":"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","file":"index.js","sourcesContent":["import axios, { AxiosInstance } from 'axios';\n\n/**\n * Credentials required to initialize the KYC SDK\n */\nexport interface KYCCredentials {\n /** API key for authentication */\n apiKey: string;\n /** Base URL of the KYC API */\n baseUrl: string;\n}\n\n/**\n * Parameters required to start a verification session\n */\nexport interface StartVerificationParams {\n /** Type of document to verify (e.g., IDENTITY_CARD, DRIVING_LICENSE) */\n documentType: 'IDENTITY_CARD' | 'DRIVING_LICENSE';\n /** Country code (e.g., MZ, AO, PT) */\n country: string;\n /** Optional existing identity ID to link verification to */\n identityId?: string;\n /** Optional external reference ID */\n externalId?: string;\n}\n\n/**\n * Response from starting a verification session\n */\nexport interface VerificationSession {\n /** Unique verification ID */\n verificationId: string;\n /** Linked identity ID (if exists) */\n identityId?: string;\n /** Current verification status */\n status: string;\n}\n\n/**\n * Parameters for uploading a selfie image\n */\nexport interface UploadSelfieParams {\n /** Verification ID to attach the selfie to */\n verificationId: string;\n /** Base64 encoded image data, data URI, or file:// URI (React Native) */\n imageData: string;\n /** MIME type of the image (default: image/jpeg) */\n mimeType?: string;\n}\n\n/**\n * Parameters for uploading a document image\n */\nexport interface UploadDocumentParams {\n /** Verification ID to attach the document to */\n verificationId: string;\n /** Type of document (front or back) */\n type: 'front' | 'back';\n /** Base64 encoded image data, data URI, or file:// URI (React Native) */\n imageData: string;\n /** MIME type of the image (default: image/jpeg) */\n mimeType?: string;\n}\n\n/** Result of an upload operation */\nexport interface UploadResult {\n /** Response message */\n message: string;\n /** Current status after upload */\n status: string;\n}\n\n/** Current status of a verification session */\nexport interface VerificationStatus {\n /** Verification ID */\n verificationId: string;\n /** Current status: PENDING, PROCESSING, APPROVED, or REJECTED */\n status: 'PENDING' | 'PROCESSING' | 'APPROVED' | 'REJECTED';\n /** Face match similarity score (0-1) */\n faceMatchScore?: number;\n /** OCR extracted data from document */\n ocrData?: {\n /** Full name extracted from document */\n fullName?: string;\n /** ID number extracted from document */\n idNumber?: string;\n /** Birth date extracted from document */\n birthDate?: string;\n /** Expiry date extracted from document */\n expiryDate?: string;\n /** Additional extracted fields */\n [key: string]: any;\n };\n /** When the verification was created */\n createdAt: string;\n /** When the verification was last updated */\n updatedAt: string;\n}\n\n/** Event emitted when KYC status changes */\nexport interface KYCStatusEvent {\n /** Type of event: statusChanged or error */\n type: 'statusChanged' | 'error';\n /** New status (for statusChanged events) */\n status?: string;\n /** Error message (for error events) */\n error?: string;\n}\n\n/** Callback function for handling KYC status events */\nexport type KYCEventCallback = (event: KYCStatusEvent) => void;\n\n/**\n * Custom error class for KYC SDK errors\n */\nexport class KYCSdkError extends Error {\n /** Error code for programmatic error handling */\n code: string;\n /** HTTP status code if available */\n statusCode?: number;\n\n /**\n * Creates a new KYC SDK error\n * @param message Human-readable error message\n * @param code Error code for handling\n * @param statusCode Optional HTTP status code\n */\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'KYCSdkError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Core KYC SDK client for interacting with the verification API\n */\nexport class KYCCore {\n private client: AxiosInstance;\n private credentials: KYCCredentials;\n private eventCallbacks: KYCEventCallback[] = [];\n\n /**\n * Creates a new KYC Core instance\n * @param credentials API credentials (apiKey and baseUrl)\n */\n constructor(credentials: KYCCredentials) {\n this.credentials = credentials;\n this.client = axios.create({\n baseURL: credentials.baseUrl,\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n });\n\n this.client.interceptors.request.use((config) => {\n config.headers['x-api-key'] = this.credentials.apiKey;\n return config;\n });\n }\n\n /**\n * Registers a callback for KYC status events\n * @param callback Function to call when status changes\n * @returns Unsubscribe function to remove the callback\n */\n onEvent(callback: KYCEventCallback): () => void {\n this.eventCallbacks.push(callback);\n return () => {\n this.eventCallbacks = this.eventCallbacks.filter((cb) => cb !== callback);\n };\n }\n\n /**\n * Emits a status event to all registered callbacks\n * @param event The event to emit\n */\n private emitEvent(event: KYCStatusEvent): void {\n this.eventCallbacks.forEach((callback) => callback(event));\n }\n\n /**\n * Creates a verification token for secure API access\n * @param externalId External reference ID\n * @param expiry Token expiry in hours (default: 3)\n * @returns Object containing the token and its expiration time\n */\n async createVerificationToken(\n externalId: string,\n expiry: string = '3'\n ): Promise<{ token: string; expiresIn: string }> {\n try {\n const response = await this.client.post('/verification/token', {\n externalId,\n expiry,\n });\n\n return response.data;\n } catch (error: any) {\n const message =\n error.response?.data?.message || error.message || 'Failed to create verification token';\n throw new KYCSdkError(message, 'TOKEN_CREATE_FAILED', error.response?.status);\n }\n }\n\n /**\n * Starts a new verification session\n * @param params Parameters including documentType, country, identityId, and externalId\n * @returns Verification session with verificationId and status\n */\n async startVerification(params: StartVerificationParams): Promise<VerificationSession> {\n try {\n const response = await this.client.post('/verification/start', params);\n\n this.emitEvent({\n type: 'statusChanged',\n status: 'PENDING',\n });\n\n return response.data;\n } catch (error: any) {\n const message =\n error.response?.data?.message || error.message || 'Failed to start verification';\n throw new KYCSdkError(message, 'VERIFICATION_START_FAILED', error.response?.status);\n }\n }\n\n /**\n * Uploads a selfie image for face verification\n * @param params Parameters including verificationId, imageData, and optional mimeType\n * @returns Upload result with status\n */\n async uploadSelfie(params: UploadSelfieParams): Promise<UploadResult> {\n try {\n const formData = new FormData();\n formData.append('verificationId', params.verificationId);\n\n const mimeType = params.mimeType || 'image/jpeg';\n const imageData = params.imageData;\n\n if (imageData.startsWith('file://')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: 'selfie.jpg',\n } as any);\n } else if (imageData.startsWith('data:')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: 'selfie.jpg',\n } as any);\n } else {\n formData.append('file', {\n uri: `data:${mimeType};base64,${imageData}`,\n type: mimeType,\n name: 'selfie.jpg',\n } as any);\n }\n\n const response = await this.client.post('/verification/upload/selfie', formData, {\n headers: { 'Content-Type': 'multipart/form-data' },\n });\n\n this.emitEvent({\n type: 'statusChanged',\n status: 'PROCESSING',\n });\n\n return response.data;\n } catch (error: any) {\n console.log('Upload selfie error:', error.response?.data || error.message);\n const message = error.response?.data?.message || error.message || 'Failed to upload selfie';\n throw new KYCSdkError(message, 'SELFIE_UPLOAD_FAILED', error.response?.status);\n }\n }\n\n /**\n * Uploads a document image (front or back)\n * @param params Parameters including verificationId, type, imageData, and optional mimeType\n * @returns Upload result with status\n */\n async uploadDocument(params: UploadDocumentParams): Promise<UploadResult> {\n try {\n const formData = new FormData();\n formData.append('verificationId', params.verificationId);\n formData.append('type', params.type);\n\n const mimeType = params.mimeType || 'image/jpeg';\n const imageData = params.imageData;\n\n if (imageData.startsWith('file://')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: `${params.type}.jpg`,\n } as any);\n } else if (imageData.startsWith('data:')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: `${params.type}.jpg`,\n } as any);\n } else {\n formData.append('file', {\n uri: `data:${mimeType};base64,${imageData}`,\n type: mimeType,\n name: `${params.type}.jpg`,\n } as any);\n }\n\n const response = await this.client.post('/verification/upload/document', formData, {\n headers: { 'Content-Type': 'multipart/form-data' },\n });\n\n this.emitEvent({\n type: 'statusChanged',\n status: 'PROCESSING',\n });\n\n return response.data;\n } catch (error: any) {\n console.log('Upload document error:', error.response?.data || error.message);\n const message = error.response?.data?.message || error.message || 'Failed to upload document';\n throw new KYCSdkError(message, 'DOCUMENT_UPLOAD_FAILED', error.response?.status);\n }\n }\n\n /**\n * Gets the current status of a verification session\n * @param verificationId The verification ID to check\n * @returns Current verification status including OCR data and face match score\n */\n async getStatus(verificationId: string): Promise<VerificationStatus> {\n try {\n const response = await this.client.get(`/verification/status/${verificationId}`);\n\n this.emitEvent({\n type: 'statusChanged',\n status: response.data.status,\n });\n\n return response.data;\n } catch (error: any) {\n const message =\n error.response?.data?.message || error.message || 'Failed to get verification status';\n throw new KYCSdkError(message, 'STATUS_CHECK_FAILED', error.response?.status);\n }\n }\n\n /**\n * Polls for verification status until completion or timeout\n * @param verificationId The verification ID to check\n * @param interval Polling interval in milliseconds (default: 3000)\n * @param timeout Maximum time to wait in milliseconds (default: 120000)\n * @returns Final verification status when approved or rejected\n */\n async pollStatus(\n verificationId: string,\n interval: number = 3000,\n timeout: number = 120000\n ): Promise<VerificationStatus> {\n const startTime = Date.now();\n\n return new Promise((resolve, reject) => {\n const poll = async () => {\n try {\n const status = await this.getStatus(verificationId);\n\n if (status.status === 'APPROVED' || status.status === 'REJECTED') {\n resolve(status);\n return;\n }\n\n if (Date.now() - startTime > timeout) {\n reject(new KYCSdkError('Polling timeout', 'POLLING_TIMEOUT'));\n return;\n }\n\n setTimeout(poll, interval);\n } catch (error) {\n reject(error);\n }\n };\n\n poll();\n });\n }\n\n /**\n * Static factory method to create a KYC client instance\n * @param credentials API credentials (apiKey and baseUrl)\n * @returns Configured KYCCore instance\n */\n static createClient(credentials: KYCCredentials): KYCCore {\n return new KYCCore(credentials);\n }\n}\n\n/**\n * Factory function to create a KYC client instance\n * @param credentials API credentials (apiKey and baseUrl)\n * @returns Configured KYCCore instance\n */\nexport function createKYCClient(credentials: KYCCredentials): KYCCore {\n return KYCCore.createClient(credentials);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["axios"],"mappings":"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","file":"index.js","sourcesContent":["import axios, { AxiosInstance } from 'axios';\n\n/**\n * Pluggable, platform-agnostic key/value storage used to persist the verification\n * session so a paused flow survives the app being closed.\n *\n * Inject a concrete implementation: AsyncStorage on React Native, or an adapter\n * around localStorage on web. Methods may be sync or async; results are awaited.\n */\nexport interface KYCStorage {\n /** Returns the stored value for a key, or null if absent */\n getItem(key: string): string | null | Promise<string | null>;\n /** Persists a value for a key */\n setItem(key: string, value: string): void | Promise<void>;\n /** Removes a stored key */\n removeItem(key: string): void | Promise<void>;\n}\n\n/**\n * The persisted verification session, used to resume an in-flight verification.\n */\nexport interface KYCSession {\n /** Identity ID owning the verification */\n identityId: string;\n /** Verification ID being completed */\n verificationId: string;\n /** External reference ID provided when starting (if any) */\n externalId?: string;\n /** Document type for the verification */\n documentType?: 'IDENTITY_CARD' | 'DRIVING_LICENSE';\n}\n\n/**\n * Credentials required to initialize the KYC SDK\n */\nexport interface KYCCredentials {\n /** API key for authentication */\n apiKey: string;\n /** Base URL of the KYC API */\n baseUrl: string;\n /**\n * Optional storage adapter. When provided, the SDK persists the verification\n * session on startVerification and reads it back to resume a paused flow.\n */\n storage?: KYCStorage;\n}\n\n/**\n * Parameters required to start a verification session\n */\nexport interface StartVerificationParams {\n /** Type of document to verify (e.g., IDENTITY_CARD, DRIVING_LICENSE) */\n documentType: 'IDENTITY_CARD' | 'DRIVING_LICENSE';\n /** Country code (e.g., MZ, AO, PT) */\n country: string;\n /** Optional existing identity ID to link verification to */\n identityId?: string;\n /** Optional external reference ID */\n externalId?: string;\n}\n\nexport interface FaceMatchVerificationParams {\n /** The identity ID to perform face match on */\n identityId: string;\n /** Base64 encoded image data, data URI, or file:// URI */\n file: string;\n /** MIME type of the image (default: image/jpeg) */\n mimeType?: string;\n}\n\nexport interface FaceMatchStatusParams {\n /** The identity ID to check face match status for */\n identityId: string;\n /** The face check ID from the face match verification response */\n faceCheckId: string;\n /** Polling interval in milliseconds (default: 3000) */\n interval?: number;\n /** Maximum time to wait in milliseconds (default: 120000) */\n timeout?: number;\n}\n\n/**\n * Response from starting a verification session\n */\nexport interface VerificationSession {\n /** Unique verification ID */\n verificationId: string;\n /** Linked identity ID (if exists) */\n identityId?: string;\n /** Current verification status */\n status: string;\n}\n\n/**\n * Parameters for uploading a selfie image\n */\nexport interface UploadSelfieParams {\n /** Verification ID to attach the selfie to */\n verificationId: string;\n /** Base64 encoded image data, data URI, or file:// URI (React Native) */\n imageData: string;\n /** MIME type of the image (default: image/jpeg) */\n mimeType?: string;\n}\n\n/**\n * Parameters for uploading a document image\n */\nexport interface UploadDocumentParams {\n /** Verification ID to attach the document to */\n verificationId: string;\n /** Type of document (front or back) */\n type: 'front' | 'back';\n /** Base64 encoded image data, data URI, or file:// URI (React Native) */\n imageData: string;\n /** MIME type of the image (default: image/jpeg) */\n mimeType?: string;\n}\n\n/** Result of an upload operation */\nexport interface UploadResult {\n /** Response message */\n message: string;\n /** Current status after upload */\n status: string;\n /** True when the step was already uploaded and the call was a no-op */\n skipped?: boolean;\n}\n\n/**\n * Parameters for uploading a single verification step in a resume-aware way.\n */\nexport interface UploadStepParams {\n /** The step to upload */\n step: VerificationStep;\n /** Base64 encoded image data, data URI, or file:// URI (React Native) */\n imageData: string;\n /** Verification ID to attach to; falls back to the persisted session */\n verificationId?: string;\n /** Identity ID used to skip already-uploaded steps; falls back to the persisted session */\n identityId?: string;\n /** MIME type of the image (default: image/jpeg) */\n mimeType?: string;\n}\n\n/** Current status of a verification session */\nexport interface VerificationStatus {\n /** Verification ID */\n verificationId: string;\n /** Current status: PENDING, PROCESSING, APPROVED, or REJECTED */\n status: 'PENDING' | 'PROCESSING' | 'APPROVED' | 'REJECTED';\n /** Face match similarity score (0-1) */\n faceMatchScore?: number;\n /** OCR extracted data from document */\n ocrData?: {\n /** Full name extracted from document */\n fullName?: string;\n /** ID number extracted from document */\n idNumber?: string;\n /** Birth date extracted from document */\n birthDate?: string;\n /** Expiry date extracted from document */\n expiryDate?: string;\n /** Additional extracted fields */\n [key: string]: any;\n };\n /** When the verification was created */\n createdAt: string;\n /** When the verification was last updated */\n updatedAt: string;\n}\n\n/** A single verification record as stored under an identity */\nexport interface VerificationRecord {\n /** Verification ID */\n id: string;\n /** Current verification status */\n status: string;\n /** External reference ID (if provided when starting) */\n externalId: string | null;\n /** Type of document being verified */\n documentType: 'IDENTITY_CARD' | 'DRIVING_LICENSE';\n /** Country code */\n country: string;\n /** Face match similarity score (0-1) */\n faceMatchScore: number | null;\n /** OCR extracted data from document */\n ocrData: Record<string, any> | null;\n /** Stored path of the uploaded selfie, or null if not uploaded yet */\n selfiePath: string | null;\n /** Stored path of the uploaded document front, or null if not uploaded yet */\n documentFrontPath: string | null;\n /** Stored path of the uploaded document back, or null if not uploaded yet */\n documentBackPath: string | null;\n /** Stored path of the document face crop, or null if not available */\n documentFacePath: string | null;\n /** Reason for rejection, if rejected */\n rejectionReason: string | null;\n /** Type of rejection, if rejected */\n rejectionType: string | null;\n /** When the verification was created */\n createdAt: string;\n /** When the verification was last updated */\n updatedAt: string;\n}\n\n/** An identity with its associated verifications */\nexport interface Identity {\n /** Unique identity ID */\n id: string;\n /** Verifications linked to this identity */\n verifications: VerificationRecord[];\n /** When the identity was created */\n createdAt: string;\n /** When the identity was last updated */\n updatedAt: string;\n /** Additional OCR / identity fields */\n [key: string]: any;\n}\n\n/** A single step a user must complete in a verification flow */\nexport type VerificationStep = 'selfie' | 'document_front' | 'document_back';\n\n/** Computed progress of an in-flight verification, used to resume a paused flow */\nexport interface VerificationProgress {\n /** Verification ID the progress refers to */\n verificationId: string;\n /** Document type for this verification */\n documentType: 'IDENTITY_CARD' | 'DRIVING_LICENSE';\n /** Current verification status */\n status: string;\n /** Whether the selfie has already been uploaded */\n selfieUploaded: boolean;\n /** Whether the document front has already been uploaded */\n documentFrontUploaded: boolean;\n /** Whether the document back has already been uploaded (always false for single-sided docs) */\n documentBackUploaded: boolean;\n /** Steps still required to finish, in the order they should be collected */\n missingSteps: VerificationStep[];\n /** True when no steps remain to be uploaded */\n isComplete: boolean;\n}\n\n/** Event emitted when KYC status changes */\nexport interface KYCStatusEvent {\n /** Type of event: statusChanged or error */\n type: 'statusChanged' | 'error';\n /** New status (for statusChanged events) */\n status?: string;\n /** Error message (for error events) */\n error?: string;\n}\n\n/** Callback function for handling KYC status events */\nexport type KYCEventCallback = (event: KYCStatusEvent) => void;\n\n/**\n * Custom error class for KYC SDK errors\n */\nexport class KYCSdkError extends Error {\n /** Error code for programmatic error handling */\n code: string;\n /** HTTP status code if available */\n statusCode?: number;\n\n /**\n * Creates a new KYC SDK error\n * @param message Human-readable error message\n * @param code Error code for handling\n * @param statusCode Optional HTTP status code\n */\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'KYCSdkError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Core KYC SDK client for interacting with the verification API\n */\nexport class KYCCore {\n private client: AxiosInstance;\n private credentials: KYCCredentials;\n private eventCallbacks: KYCEventCallback[] = [];\n private storage?: KYCStorage;\n\n /** Storage key under which the active verification session is persisted */\n private static readonly SESSION_KEY = 'kyc:session';\n\n /**\n * Creates a new KYC Core instance\n * @param credentials API credentials (apiKey, baseUrl, and optional storage)\n */\n constructor(credentials: KYCCredentials) {\n this.credentials = credentials;\n this.storage = credentials.storage;\n this.client = axios.create({\n baseURL: credentials.baseUrl,\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n });\n\n this.client.interceptors.request.use((config) => {\n config.headers['x-api-key'] = this.credentials.apiKey;\n return config;\n });\n }\n\n /**\n * Persists the active verification session via the injected storage adapter.\n * No-op when no storage was provided.\n */\n private async saveSession(session: KYCSession): Promise<void> {\n if (!this.storage) return;\n try {\n await this.storage.setItem(KYCCore.SESSION_KEY, JSON.stringify(session));\n } catch {\n // Persistence is best-effort; a storage failure must not break the flow.\n }\n }\n\n /**\n * Reads the persisted verification session, or null if none exists or no\n * storage adapter was provided.\n */\n async getSession(): Promise<KYCSession | null> {\n if (!this.storage) return null;\n try {\n const raw = await this.storage.getItem(KYCCore.SESSION_KEY);\n return raw ? (JSON.parse(raw) as KYCSession) : null;\n } catch {\n return null;\n }\n }\n\n /**\n * Clears the persisted verification session. Call this once a verification is\n * fully complete so the next flow starts fresh.\n */\n async clearSession(): Promise<void> {\n if (!this.storage) return;\n try {\n await this.storage.removeItem(KYCCore.SESSION_KEY);\n } catch {\n // Best-effort.\n }\n }\n\n /**\n * Registers a callback for KYC status events\n * @param callback Function to call when status changes\n * @returns Unsubscribe function to remove the callback\n */\n onEvent(callback: KYCEventCallback): () => void {\n this.eventCallbacks.push(callback);\n return () => {\n this.eventCallbacks = this.eventCallbacks.filter((cb) => cb !== callback);\n };\n }\n\n /**\n * Emits a status event to all registered callbacks\n * @param event The event to emit\n */\n private emitEvent(event: KYCStatusEvent): void {\n this.eventCallbacks.forEach((callback) => callback(event));\n }\n\n /**\n * Creates a verification token for secure API access\n * @param externalId External reference ID\n * @param expiry Token expiry in hours (default: 3)\n * @returns Object containing the token and its expiration time\n */\n async createVerificationToken(\n externalId: string,\n expiry: string = '3'\n ): Promise<{ token: string; expiresIn: string }> {\n try {\n const response = await this.client.post('/verification/token', {\n externalId,\n expiry,\n });\n\n return response.data;\n } catch (error: any) {\n const message =\n error.response?.data?.message || error.message || 'Failed to create verification token';\n throw new KYCSdkError(message, 'TOKEN_CREATE_FAILED', error.response?.status);\n }\n }\n\n /**\n * Starts a new verification session\n * @param params Parameters including documentType, country, identityId, and externalId\n * @returns Verification session with verificationId and status\n */\n async startVerification(params: StartVerificationParams): Promise<VerificationSession> {\n try {\n const response = await this.client.post('/verification/start', params);\n const session: VerificationSession = response.data;\n\n // Persist the session so the flow can be resumed after the app is closed.\n if (session.identityId && session.verificationId) {\n await this.saveSession({\n identityId: session.identityId,\n verificationId: session.verificationId,\n externalId: params.externalId,\n documentType: params.documentType,\n });\n }\n\n this.emitEvent({\n type: 'statusChanged',\n status: 'PENDING',\n });\n\n return response.data;\n } catch (error: any) {\n const message =\n error.response?.data?.message || error.message || 'Failed to start verification';\n throw new KYCSdkError(message, 'VERIFICATION_START_FAILED', error.response?.status);\n }\n }\n\n /**\n * Uploads a selfie image for face verification\n * @param params Parameters including verificationId, imageData, and optional mimeType\n * @returns Upload result with status\n */\n async uploadSelfie(params: UploadSelfieParams): Promise<UploadResult> {\n try {\n const formData = new FormData();\n formData.append('verificationId', params.verificationId);\n\n const mimeType = params.mimeType || 'image/jpeg';\n const imageData = params.imageData;\n\n if (imageData.startsWith('file://')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: 'selfie.jpg',\n } as any);\n } else if (imageData.startsWith('data:')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: 'selfie.jpg',\n } as any);\n } else {\n formData.append('file', {\n uri: `data:${mimeType};base64,${imageData}`,\n type: mimeType,\n name: 'selfie.jpg',\n } as any);\n }\n\n const response = await this.client.post('/verification/upload/selfie', formData, {\n headers: { 'Content-Type': 'multipart/form-data' },\n });\n\n this.emitEvent({\n type: 'statusChanged',\n status: 'PROCESSING',\n });\n\n return response.data;\n } catch (error: any) {\n console.log('Upload selfie error:', error.response?.data || error.message);\n const message = error.response?.data?.message || error.message || 'Failed to upload selfie';\n throw new KYCSdkError(message, 'SELFIE_UPLOAD_FAILED', error.response?.status);\n }\n }\n\n /**\n * Uploads a document image (front or back)\n * @param params Parameters including verificationId, type, imageData, and optional mimeType\n * @returns Upload result with status\n */\n async uploadDocument(params: UploadDocumentParams): Promise<UploadResult> {\n try {\n const formData = new FormData();\n formData.append('verificationId', params.verificationId);\n formData.append('type', params.type);\n\n const mimeType = params.mimeType || 'image/jpeg';\n const imageData = params.imageData;\n\n if (imageData.startsWith('file://')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: `${params.type}.jpg`,\n } as any);\n } else if (imageData.startsWith('data:')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: `${params.type}.jpg`,\n } as any);\n } else {\n formData.append('file', {\n uri: `data:${mimeType};base64,${imageData}`,\n type: mimeType,\n name: `${params.type}.jpg`,\n } as any);\n }\n\n const response = await this.client.post('/verification/upload/document', formData, {\n headers: { 'Content-Type': 'multipart/form-data' },\n });\n\n this.emitEvent({\n type: 'statusChanged',\n status: 'PROCESSING',\n });\n\n return response.data;\n } catch (error: any) {\n console.log('Upload document error:', error.response?.data || error.message);\n const message = error.response?.data?.message || error.message || 'Failed to upload document';\n throw new KYCSdkError(message, 'DOCUMENT_UPLOAD_FAILED', error.response?.status);\n }\n }\n\n /**\n * Gets the current status of a verification session\n * @param verificationId The verification ID to check\n * @returns Current verification status including OCR data and face match score\n */\n async getStatus(verificationId: string): Promise<VerificationStatus> {\n try {\n const response = await this.client.get(`/verification/status/${verificationId}`);\n\n this.emitEvent({\n type: 'statusChanged',\n status: response.data.status,\n });\n\n return response.data;\n } catch (error: any) {\n const message =\n error.response?.data?.message || error.message || 'Failed to get verification status';\n throw new KYCSdkError(message, 'STATUS_CHECK_FAILED', error.response?.status);\n }\n }\n\n /**\n * Fetches an identity along with all of its verification records.\n * @param identityId The identity ID to fetch\n * @returns The identity, including the verifications array with upload paths\n */\n async getIdentity(identityId: string): Promise<Identity> {\n try {\n const response = await this.client.get(`/identities/${identityId}`);\n return response.data;\n } catch (error: any) {\n const message = error.response?.data?.message || error.message || 'Failed to get identity';\n throw new KYCSdkError(message, 'IDENTITY_FETCH_FAILED', error.response?.status);\n }\n }\n\n /**\n * Returns the required steps for a given document type, in collection order.\n * ID cards require both sides; driving licenses are single-sided.\n */\n private getRequiredSteps(documentType: 'IDENTITY_CARD' | 'DRIVING_LICENSE'): VerificationStep[] {\n // Order is the collection order: documents first, selfie last. missingSteps\n // preserves this, so consumers can route to missingSteps[0] as \"the next step\".\n if (documentType === 'DRIVING_LICENSE') {\n return ['document_front', 'selfie'];\n }\n return ['document_front', 'document_back', 'selfie'];\n }\n\n /**\n * Computes which steps a user has already completed and which are still missing\n * for a verification, so a paused flow can be resumed without re-uploading.\n *\n * Both arguments are optional: when omitted they fall back to the persisted\n * session (see the storage adapter). Pass a verificationId to target a specific\n * verification; otherwise the most recently updated verification is used.\n *\n * @param identityId Identity ID owning the verification (defaults to the session)\n * @param verificationId Verification ID to target (defaults to the session)\n * @returns Progress describing uploaded steps and the steps still required\n */\n async getVerificationProgress(\n identityId?: string,\n verificationId?: string\n ): Promise<VerificationProgress> {\n const session = identityId && verificationId ? null : await this.getSession();\n const resolvedIdentityId = identityId ?? session?.identityId;\n const resolvedVerificationId = verificationId ?? session?.verificationId;\n\n if (!resolvedIdentityId) {\n throw new KYCSdkError(\n 'No identityId provided and no persisted session found',\n 'SESSION_NOT_FOUND',\n 404\n );\n }\n\n const identity = await this.getIdentity(resolvedIdentityId);\n const verifications = identity.verifications ?? [];\n\n if (verifications.length === 0) {\n throw new KYCSdkError('No verifications found for identity', 'VERIFICATION_NOT_FOUND', 404);\n }\n\n const verification = resolvedVerificationId\n ? verifications.find((v) => v.id === resolvedVerificationId)\n : [...verifications].sort(\n (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()\n )[0];\n\n if (!verification) {\n throw new KYCSdkError(\n `Verification ${resolvedVerificationId} not found for identity`,\n 'VERIFICATION_NOT_FOUND',\n 404\n );\n }\n\n const selfieUploaded = !!verification.selfiePath;\n const documentFrontUploaded = !!verification.documentFrontPath;\n const documentBackUploaded = !!verification.documentBackPath;\n\n const uploaded: Record<VerificationStep, boolean> = {\n selfie: selfieUploaded,\n document_front: documentFrontUploaded,\n document_back: documentBackUploaded,\n };\n\n const missingSteps = this.getRequiredSteps(verification.documentType).filter(\n (step) => !uploaded[step]\n );\n\n return {\n verificationId: verification.id,\n documentType: verification.documentType,\n status: verification.status,\n selfieUploaded,\n documentFrontUploaded,\n documentBackUploaded,\n missingSteps,\n isComplete: missingSteps.length === 0,\n };\n }\n\n /**\n * Returns whether every required step of a verification has already been\n * uploaded (both document sides where applicable, plus the selfie).\n *\n * This is the reliable way to tell a user who has fully submitted their\n * documents (verification is now processing on the KYC backend) apart from one\n * who paused mid-flow with steps still missing — both look \"PENDING\" from the\n * outside. Derived purely from the identity's verification records.\n *\n * Returns `false` (rather than throwing) when the identity has no verification\n * records yet, so callers can treat \"nothing uploaded\" as \"documents missing\".\n *\n * @param identityId Identity ID owning the verification (defaults to the session)\n * @param verificationId Verification ID to target (defaults to the most recently updated)\n * @returns True when no steps remain to be uploaded\n */\n async hasAllDocuments(identityId?: string, verificationId?: string): Promise<boolean> {\n try {\n const progress = await this.getVerificationProgress(identityId, verificationId);\n return progress.isComplete;\n } catch (error) {\n // No identity / no verifications yet means nothing has been uploaded.\n if (\n error instanceof KYCSdkError &&\n (error.code === 'VERIFICATION_NOT_FOUND' || error.code === 'SESSION_NOT_FOUND')\n ) {\n return false;\n }\n throw error;\n }\n }\n\n /**\n * Uploads a single verification step (selfie, document front, or document back)\n * in a resume-aware way: it resolves the verification from the persisted session\n * when not given, and skips the upload if that step is already complete.\n *\n * @param params The step, image data, and optional verification/identity overrides\n * @returns The upload result; `skipped` is true when the step was already uploaded\n */\n async uploadStep(params: UploadStepParams): Promise<UploadResult> {\n const session = params.verificationId && params.identityId ? null : await this.getSession();\n const verificationId = params.verificationId ?? session?.verificationId;\n const identityId = params.identityId ?? session?.identityId;\n\n if (!verificationId) {\n throw new KYCSdkError(\n 'No verificationId provided and no persisted session found',\n 'SESSION_NOT_FOUND',\n 404\n );\n }\n\n // Skip steps already uploaded so a resumed flow never re-sends data.\n // Requires an identityId (directly or from the session) to check progress.\n if (identityId) {\n const progress = await this.getVerificationProgress(identityId, verificationId);\n if (!progress.missingSteps.includes(params.step)) {\n return {\n message: `Step ${params.step} already uploaded`,\n status: progress.status,\n skipped: true,\n };\n }\n }\n\n if (params.step === 'selfie') {\n return this.uploadSelfie({\n verificationId,\n imageData: params.imageData,\n mimeType: params.mimeType,\n });\n }\n\n return this.uploadDocument({\n verificationId,\n type: params.step === 'document_front' ? 'front' : 'back',\n imageData: params.imageData,\n mimeType: params.mimeType,\n });\n }\n\n async faceMatchVerification(params: FaceMatchVerificationParams) {\n try {\n const formData = new FormData();\n\n const mimeType = params.mimeType || 'image/jpeg';\n const imageData = params.file;\n\n if (imageData.startsWith('file://')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: `selfie.jpg`,\n } as any);\n } else if (imageData.startsWith('data:')) {\n formData.append('file', {\n uri: imageData,\n type: mimeType,\n name: `selfie.jpg`,\n } as any);\n } else {\n formData.append('file', {\n uri: `data:${mimeType};base64,${imageData}`,\n type: mimeType,\n name: `selfie.jpg`,\n } as any);\n }\n\n const response = await this.client.post(\n `identities/${params.identityId}/face-match`,\n formData,\n {\n headers: { 'Content-Type': 'multipart/form-data' },\n }\n );\n return response.data;\n } catch (error: any) {\n console.log('Upload face match error:', error.response?.data || error.message);\n const message =\n error.response?.data?.message || error.message || 'Failed to upload face match';\n throw new KYCSdkError(message, 'FACEMATCH_UPLOAD_FAILED', error.response?.status);\n }\n }\n\n async faceMatchStatus({\n identityId,\n faceCheckId,\n interval = 3000,\n timeout = 120000,\n }: FaceMatchStatusParams): Promise<VerificationStatus> {\n const startTime = Date.now();\n\n return new Promise((resolve, reject) => {\n const poll = async () => {\n try {\n const status = (\n await this.client.get(`identities/${identityId}/face-match/status/${faceCheckId}`)\n ).data;\n\n if (status.status === 'APPROVED' || status.status === 'REJECTED') {\n resolve(status);\n return;\n }\n\n if (Date.now() - startTime > timeout) {\n reject(new KYCSdkError('Polling timeout', 'POLLING_TIMEOUT'));\n return;\n }\n\n setTimeout(poll, interval);\n } catch (error) {\n reject(error);\n }\n };\n\n poll();\n });\n }\n\n /**\n * Polls for verification status until completion or timeout\n * @param verificationId The verification ID to check\n * @param interval Polling interval in milliseconds (default: 3000)\n * @param timeout Maximum time to wait in milliseconds (default: 120000)\n * @returns Final verification status when approved or rejected\n */\n async pollStatus(\n verificationId: string,\n interval: number = 3000,\n timeout: number = 120000\n ): Promise<VerificationStatus> {\n const startTime = Date.now();\n\n return new Promise((resolve, reject) => {\n const poll = async () => {\n try {\n const status = await this.getStatus(verificationId);\n\n if (status.status === 'APPROVED' || status.status === 'REJECTED') {\n resolve(status);\n return;\n }\n\n if (Date.now() - startTime > timeout) {\n reject(new KYCSdkError('Polling timeout', 'POLLING_TIMEOUT'));\n return;\n }\n\n setTimeout(poll, interval);\n } catch (error) {\n reject(error);\n }\n };\n\n poll();\n });\n }\n\n /**\n * Static factory method to create a KYC client instance\n * @param credentials API credentials (apiKey and baseUrl)\n * @returns Configured KYCCore instance\n */\n static createClient(credentials: KYCCredentials): KYCCore {\n return new KYCCore(credentials);\n }\n}\n\n/**\n * Factory function to create a KYC client instance\n * @param credentials API credentials (apiKey and baseUrl)\n * @returns Configured KYCCore instance\n */\nexport function createKYCClient(credentials: KYCCredentials): KYCCore {\n return KYCCore.createClient(credentials);\n}\n"]}
|