vesant-sdk 1.0.4
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/README.md +247 -0
- package/dist/client-CA9Wr_qb.d.ts +1108 -0
- package/dist/client-DMNkESa0.d.mts +1108 -0
- package/dist/compliance/index.d.mts +543 -0
- package/dist/compliance/index.d.ts +543 -0
- package/dist/compliance/index.js +2133 -0
- package/dist/compliance/index.js.map +1 -0
- package/dist/compliance/index.mjs +2130 -0
- package/dist/compliance/index.mjs.map +1 -0
- package/dist/geolocation/index.d.mts +73 -0
- package/dist/geolocation/index.d.ts +73 -0
- package/dist/geolocation/index.js +1100 -0
- package/dist/geolocation/index.js.map +1 -0
- package/dist/geolocation/index.mjs +1094 -0
- package/dist/geolocation/index.mjs.map +1 -0
- package/dist/index.d.mts +50 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +2968 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2948 -0
- package/dist/index.mjs.map +1 -0
- package/dist/kyc/core.d.mts +3 -0
- package/dist/kyc/core.d.ts +3 -0
- package/dist/kyc/core.js +773 -0
- package/dist/kyc/core.js.map +1 -0
- package/dist/kyc/core.mjs +771 -0
- package/dist/kyc/core.mjs.map +1 -0
- package/dist/kyc/index.d.mts +734 -0
- package/dist/kyc/index.d.ts +734 -0
- package/dist/kyc/index.js +773 -0
- package/dist/kyc/index.js.map +1 -0
- package/dist/kyc/index.mjs +771 -0
- package/dist/kyc/index.mjs.map +1 -0
- package/dist/react.d.mts +487 -0
- package/dist/react.d.ts +487 -0
- package/dist/react.js +1122 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +1102 -0
- package/dist/react.mjs.map +1 -0
- package/dist/risk-profile/index.d.mts +228 -0
- package/dist/risk-profile/index.d.ts +228 -0
- package/dist/risk-profile/index.js +548 -0
- package/dist/risk-profile/index.js.map +1 -0
- package/dist/risk-profile/index.mjs +546 -0
- package/dist/risk-profile/index.mjs.map +1 -0
- package/dist/types-Bnsnejor.d.mts +150 -0
- package/dist/types-Bnsnejor.d.ts +150 -0
- package/dist/types-CFupjwi8.d.ts +213 -0
- package/dist/types-CqOLbaXk.d.mts +213 -0
- package/package.json +94 -0
package/dist/kyc/core.js
ADDED
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/core/errors.ts
|
|
4
|
+
var CGSError = class _CGSError extends Error {
|
|
5
|
+
constructor(message, code, statusCode, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.details = details;
|
|
10
|
+
this.name = "CGSError";
|
|
11
|
+
Object.setPrototypeOf(this, _CGSError.prototype);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
var NetworkError = class _NetworkError extends CGSError {
|
|
15
|
+
constructor(message, originalError) {
|
|
16
|
+
super(message, "NETWORK_ERROR", void 0, { originalError });
|
|
17
|
+
this.originalError = originalError;
|
|
18
|
+
this.name = "NetworkError";
|
|
19
|
+
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var ServiceUnavailableError = class _ServiceUnavailableError extends CGSError {
|
|
23
|
+
constructor(service) {
|
|
24
|
+
super(`${service} is unavailable`, "SERVICE_UNAVAILABLE", 503, { service });
|
|
25
|
+
this.name = "ServiceUnavailableError";
|
|
26
|
+
Object.setPrototypeOf(this, _ServiceUnavailableError.prototype);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var AuthenticationError = class _AuthenticationError extends CGSError {
|
|
30
|
+
constructor(message = "Authentication failed") {
|
|
31
|
+
super(message, "AUTHENTICATION_ERROR", 401);
|
|
32
|
+
this.name = "AuthenticationError";
|
|
33
|
+
Object.setPrototypeOf(this, _AuthenticationError.prototype);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var RateLimitError = class _RateLimitError extends CGSError {
|
|
37
|
+
constructor(retryAfter) {
|
|
38
|
+
super("Rate limit exceeded", "RATE_LIMIT_EXCEEDED", 429, { retryAfter });
|
|
39
|
+
this.retryAfter = retryAfter;
|
|
40
|
+
this.name = "RateLimitError";
|
|
41
|
+
Object.setPrototypeOf(this, _RateLimitError.prototype);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var TimeoutError = class _TimeoutError extends CGSError {
|
|
45
|
+
constructor(timeout) {
|
|
46
|
+
super(`Request timeout after ${timeout}ms`, "TIMEOUT", 408, { timeout });
|
|
47
|
+
this.timeout = timeout;
|
|
48
|
+
this.name = "TimeoutError";
|
|
49
|
+
Object.setPrototypeOf(this, _TimeoutError.prototype);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// src/core/client.ts
|
|
54
|
+
var BaseClient = class {
|
|
55
|
+
constructor(config) {
|
|
56
|
+
this.config = {
|
|
57
|
+
baseURL: config.baseURL,
|
|
58
|
+
tenantId: config.tenantId,
|
|
59
|
+
apiKey: config.apiKey || "",
|
|
60
|
+
headers: config.headers || {},
|
|
61
|
+
timeout: config.timeout || 1e4,
|
|
62
|
+
retries: config.retries || 3,
|
|
63
|
+
debug: config.debug || false
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Make an HTTP request with timeout and error handling
|
|
68
|
+
*/
|
|
69
|
+
async request(endpoint, options = {}, serviceURL) {
|
|
70
|
+
const url = `${serviceURL || this.config.baseURL}${endpoint}`;
|
|
71
|
+
const headers = {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
"X-Tenant-ID": this.config.tenantId,
|
|
74
|
+
...this.config.headers,
|
|
75
|
+
...options.headers || {}
|
|
76
|
+
};
|
|
77
|
+
if (this.config.apiKey) {
|
|
78
|
+
headers["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
79
|
+
}
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
82
|
+
try {
|
|
83
|
+
if (this.config.debug) {
|
|
84
|
+
console.log(`[CGS SDK] ${options.method || "GET"} ${url}`, {
|
|
85
|
+
headers,
|
|
86
|
+
body: options.body
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const response = await fetch(url, {
|
|
90
|
+
...options,
|
|
91
|
+
headers,
|
|
92
|
+
signal: controller.signal
|
|
93
|
+
});
|
|
94
|
+
clearTimeout(timeoutId);
|
|
95
|
+
const data = await response.json();
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
this.handleErrorResponse(response.status, data);
|
|
98
|
+
}
|
|
99
|
+
if (this.config.debug) {
|
|
100
|
+
console.log(`[CGS SDK] Response:`, data);
|
|
101
|
+
}
|
|
102
|
+
return data;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
clearTimeout(timeoutId);
|
|
105
|
+
if (error instanceof Error) {
|
|
106
|
+
if (error.name === "AbortError") {
|
|
107
|
+
throw new TimeoutError(this.config.timeout);
|
|
108
|
+
}
|
|
109
|
+
if (error instanceof CGSError) {
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
throw new NetworkError("Network request failed", error);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Make an HTTP request with retry logic
|
|
118
|
+
*/
|
|
119
|
+
async requestWithRetry(endpoint, options = {}, serviceURL, retries = this.config.retries) {
|
|
120
|
+
let lastError;
|
|
121
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
122
|
+
try {
|
|
123
|
+
return await this.request(endpoint, options, serviceURL);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
lastError = error instanceof Error ? error : new Error("Unknown error");
|
|
126
|
+
if (lastError instanceof CGSError && lastError.statusCode && lastError.statusCode >= 400 && lastError.statusCode < 500) {
|
|
127
|
+
throw lastError;
|
|
128
|
+
}
|
|
129
|
+
if (attempt === retries) {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
const delay = Math.min(1e3 * Math.pow(2, attempt) + Math.random() * 1e3, 1e4);
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
134
|
+
if (this.config.debug) {
|
|
135
|
+
console.log(`[CGS SDK] Retry attempt ${attempt + 1}/${retries} after ${delay.toFixed(0)}ms`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
throw new NetworkError(`Request failed after ${retries} retries`, lastError);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Handle error responses from API
|
|
143
|
+
*/
|
|
144
|
+
handleErrorResponse(status, data) {
|
|
145
|
+
const message = data.error || data.message || `HTTP ${status}`;
|
|
146
|
+
switch (status) {
|
|
147
|
+
case 400:
|
|
148
|
+
throw new CGSError(message, "BAD_REQUEST", 400, data);
|
|
149
|
+
case 401:
|
|
150
|
+
throw new AuthenticationError(message);
|
|
151
|
+
case 403:
|
|
152
|
+
throw new CGSError(message, "FORBIDDEN", 403, data);
|
|
153
|
+
case 404:
|
|
154
|
+
throw new CGSError(message, "NOT_FOUND", 404, data);
|
|
155
|
+
case 429:
|
|
156
|
+
const retryAfter = data.retry_after || data.retryAfter;
|
|
157
|
+
throw new RateLimitError(retryAfter);
|
|
158
|
+
case 500:
|
|
159
|
+
case 502:
|
|
160
|
+
case 503:
|
|
161
|
+
case 504:
|
|
162
|
+
throw new ServiceUnavailableError(message);
|
|
163
|
+
default:
|
|
164
|
+
throw new CGSError(message, "UNKNOWN_ERROR", status, data);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Build query string from parameters
|
|
169
|
+
*/
|
|
170
|
+
buildQueryString(params) {
|
|
171
|
+
const query = new URLSearchParams();
|
|
172
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
173
|
+
if (value !== void 0 && value !== null) {
|
|
174
|
+
if (Array.isArray(value)) {
|
|
175
|
+
value.forEach((item) => query.append(key, String(item)));
|
|
176
|
+
} else {
|
|
177
|
+
query.append(key, String(value));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
const queryString = query.toString();
|
|
182
|
+
return queryString ? `?${queryString}` : "";
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Update client configuration
|
|
186
|
+
*/
|
|
187
|
+
updateConfig(config) {
|
|
188
|
+
this.config = {
|
|
189
|
+
...this.config,
|
|
190
|
+
...config,
|
|
191
|
+
headers: {
|
|
192
|
+
...this.config.headers,
|
|
193
|
+
...config.headers || {}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Get current configuration (readonly)
|
|
199
|
+
*/
|
|
200
|
+
getConfig() {
|
|
201
|
+
return { ...this.config };
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Health check endpoint
|
|
205
|
+
*/
|
|
206
|
+
async healthCheck() {
|
|
207
|
+
return this.request("/api/v1/health");
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/kyc/client.ts
|
|
212
|
+
function addFilterParam(params, key, value) {
|
|
213
|
+
if (value !== void 0) {
|
|
214
|
+
params[key] = Array.isArray(value) ? value.join(",") : value;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function addSimpleParams(params, source, keys) {
|
|
218
|
+
for (const key of keys) {
|
|
219
|
+
if (source[key] !== void 0) {
|
|
220
|
+
params[key] = source[key];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
var KycClient = class extends BaseClient {
|
|
225
|
+
constructor(config) {
|
|
226
|
+
const baseConfig = {
|
|
227
|
+
baseURL: config.baseURL,
|
|
228
|
+
tenantId: config.tenantId,
|
|
229
|
+
apiKey: config.apiKey,
|
|
230
|
+
headers: config.headers,
|
|
231
|
+
timeout: config.timeout,
|
|
232
|
+
retries: 3,
|
|
233
|
+
// Default retry count for KYC calls
|
|
234
|
+
debug: config.debug
|
|
235
|
+
};
|
|
236
|
+
super(baseConfig);
|
|
237
|
+
this.userId = config.userId;
|
|
238
|
+
this.riskProfileBaseURL = config.riskProfileBaseURL;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Set the user ID for operations requiring user context
|
|
242
|
+
*/
|
|
243
|
+
setUserId(userId) {
|
|
244
|
+
this.userId = userId;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Get current user ID
|
|
248
|
+
*/
|
|
249
|
+
getUserId() {
|
|
250
|
+
return this.userId;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Build headers including user ID if available
|
|
254
|
+
*/
|
|
255
|
+
getUserHeaders() {
|
|
256
|
+
const headers = {};
|
|
257
|
+
if (this.userId) {
|
|
258
|
+
headers["X-User-ID"] = this.userId;
|
|
259
|
+
}
|
|
260
|
+
return headers;
|
|
261
|
+
}
|
|
262
|
+
// ============================================================================
|
|
263
|
+
// Document Verification
|
|
264
|
+
// ============================================================================
|
|
265
|
+
/**
|
|
266
|
+
* Request a KYC submission redirect URL for a user
|
|
267
|
+
*
|
|
268
|
+
* Generates a link that the user can visit to submit their KYC documents.
|
|
269
|
+
*
|
|
270
|
+
* @param request - Request containing the user ID
|
|
271
|
+
* @returns Response containing the redirect link
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* const result = await client.requestKycSubmitLink({
|
|
276
|
+
* user_id: "user_123"
|
|
277
|
+
* });
|
|
278
|
+
*
|
|
279
|
+
* console.log(`Redirect user to: ${result.link}`);
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
async requestKycSubmitLink(request) {
|
|
283
|
+
return this.requestWithRetry("/api/v1/kyc/request", {
|
|
284
|
+
method: "POST",
|
|
285
|
+
body: JSON.stringify(request),
|
|
286
|
+
headers: this.getUserHeaders()
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Check KYC status for a user
|
|
291
|
+
*
|
|
292
|
+
* Returns the current KYC status:
|
|
293
|
+
* - "complete" → KYC verified, show "Continue to Login"
|
|
294
|
+
* - "processing" → Under review, show "Continue to Login"
|
|
295
|
+
* - "failed" / "declined" → Show error + retry option
|
|
296
|
+
* - "pending" / "in_progress" → Keep polling
|
|
297
|
+
*
|
|
298
|
+
* @param request - Request containing user_id and token
|
|
299
|
+
* @returns Response with kyc_status and message (reason)
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```typescript
|
|
303
|
+
* const result = await client.checkKycStatus({
|
|
304
|
+
* user_id: "user_123",
|
|
305
|
+
* token: "auth_token_xyz"
|
|
306
|
+
* });
|
|
307
|
+
*
|
|
308
|
+
* if (result.kyc_status === 'complete') {
|
|
309
|
+
* // Show "Continue to Login"
|
|
310
|
+
* } else if (result.kyc_status === 'failed' || result.kyc_status === 'declined') {
|
|
311
|
+
* // Show error + retry option
|
|
312
|
+
* } else {
|
|
313
|
+
* // Keep polling
|
|
314
|
+
* }
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
async checkKycStatus(request) {
|
|
318
|
+
const params = {
|
|
319
|
+
user_id: request.user_id,
|
|
320
|
+
kyc_id: request.kyc_id
|
|
321
|
+
};
|
|
322
|
+
return this.requestWithRetry(
|
|
323
|
+
`/api/v1/kyc/request/status${this.buildQueryString(params)}`,
|
|
324
|
+
{
|
|
325
|
+
method: "GET",
|
|
326
|
+
headers: this.getUserHeaders()
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Submit a document verification request with OCR
|
|
332
|
+
*
|
|
333
|
+
* Uses requestWithRetry() for automatic retry on transient failures.
|
|
334
|
+
*
|
|
335
|
+
* @param request - Document verification request with documents and customer info
|
|
336
|
+
* @returns Verification response with status and reference
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```typescript
|
|
340
|
+
* const result = await client.submitVerification({
|
|
341
|
+
* reference: "customer_123",
|
|
342
|
+
* email: "customer@example.com",
|
|
343
|
+
* country: "US",
|
|
344
|
+
* document: {
|
|
345
|
+
* proof: base64EncodedImage,
|
|
346
|
+
* selected_type: ["id_card", "passport"],
|
|
347
|
+
* name: { first_name: "John", last_name: "Doe" },
|
|
348
|
+
* dob: "1990-01-15"
|
|
349
|
+
* },
|
|
350
|
+
* face: {
|
|
351
|
+
* proof: base64EncodedSelfie
|
|
352
|
+
* }
|
|
353
|
+
* });
|
|
354
|
+
*
|
|
355
|
+
* console.log(`Verification submitted: ${result.reference}`);
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
async submitVerification(request) {
|
|
359
|
+
return this.requestWithRetry("/api/v1/kyc/submit", {
|
|
360
|
+
method: "POST",
|
|
361
|
+
body: JSON.stringify(request),
|
|
362
|
+
headers: this.getUserHeaders()
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Get a KYC request by ID
|
|
367
|
+
*
|
|
368
|
+
* @param id - KYC request ID
|
|
369
|
+
* @returns KYC request details including proofs and alerts
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```typescript
|
|
373
|
+
* const kyc = await client.getKycRequest("kyc_abc123");
|
|
374
|
+
* console.log(`Status: ${kyc.status}, ID Verified: ${kyc.id_verified}`);
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
async getKycRequest(id) {
|
|
378
|
+
return this.request(`/api/v1/kyc/requests/${id}`);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* List KYC requests with filters and pagination
|
|
382
|
+
*
|
|
383
|
+
* @param filters - Optional filters (status, search, date range)
|
|
384
|
+
* @param pagination - Optional pagination (page, page_size)
|
|
385
|
+
* @returns Paginated list of KYC requests
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```typescript
|
|
389
|
+
* const requests = await client.listKycRequests(
|
|
390
|
+
* { status: "pending", search: "john" },
|
|
391
|
+
* { page: 1, page_size: 20 }
|
|
392
|
+
* );
|
|
393
|
+
* console.log(`Found ${requests.total} pending requests`);
|
|
394
|
+
* ```
|
|
395
|
+
*/
|
|
396
|
+
async listKycRequests(filters, pagination) {
|
|
397
|
+
const params = {};
|
|
398
|
+
if (filters) {
|
|
399
|
+
addFilterParam(params, "status", filters.status);
|
|
400
|
+
addSimpleParams(params, filters, ["search", "fromDate", "toDate", "sortBy", "order"]);
|
|
401
|
+
}
|
|
402
|
+
if (pagination) {
|
|
403
|
+
if (pagination.page) params.page = pagination.page;
|
|
404
|
+
if (pagination.page_size) params.limit = pagination.page_size;
|
|
405
|
+
}
|
|
406
|
+
return this.request(
|
|
407
|
+
`/api/v1/kyc/requests${this.buildQueryString(params)}`,
|
|
408
|
+
{ headers: this.getUserHeaders() }
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Update KYC request status (accept/decline)
|
|
413
|
+
*
|
|
414
|
+
* @param request - Status update request with reference, status, and reason
|
|
415
|
+
*
|
|
416
|
+
* @example
|
|
417
|
+
* ```typescript
|
|
418
|
+
* // Accept a KYC request
|
|
419
|
+
* await client.updateKycStatus({
|
|
420
|
+
* reference: "shufti_ref_123",
|
|
421
|
+
* status: "accepted",
|
|
422
|
+
* reason: "All documents verified successfully"
|
|
423
|
+
* });
|
|
424
|
+
*
|
|
425
|
+
* // Decline a KYC request
|
|
426
|
+
* await client.updateKycStatus({
|
|
427
|
+
* reference: "shufti_ref_456",
|
|
428
|
+
* status: "declined",
|
|
429
|
+
* reason: "Document expired"
|
|
430
|
+
* });
|
|
431
|
+
* ```
|
|
432
|
+
*/
|
|
433
|
+
async updateKycStatus(request) {
|
|
434
|
+
await this.request("/api/v1/kyc/status", {
|
|
435
|
+
method: "PUT",
|
|
436
|
+
body: JSON.stringify(request),
|
|
437
|
+
headers: this.getUserHeaders()
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Request additional documents from customer
|
|
442
|
+
*
|
|
443
|
+
* @param request - Request with KYC ID and document types needed
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* ```typescript
|
|
447
|
+
* await client.requestAdditionalDocuments({
|
|
448
|
+
* id: "kyc_abc123",
|
|
449
|
+
* document_types: ["address", "document_two"],
|
|
450
|
+
* message: "Please provide proof of address and secondary ID"
|
|
451
|
+
* });
|
|
452
|
+
* ```
|
|
453
|
+
*/
|
|
454
|
+
async requestAdditionalDocuments(request) {
|
|
455
|
+
await this.request("/api/v1/kyc/requests", {
|
|
456
|
+
method: "PUT",
|
|
457
|
+
body: JSON.stringify(request),
|
|
458
|
+
headers: this.getUserHeaders()
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Get downloadable URLs for KYC proofs/documents
|
|
463
|
+
*
|
|
464
|
+
* @param kycId - KYC request ID
|
|
465
|
+
* @returns Array of proof download URLs with expiration
|
|
466
|
+
*
|
|
467
|
+
* @example
|
|
468
|
+
* ```typescript
|
|
469
|
+
* const proofs = await client.getProofDownloadURLs("kyc_abc123");
|
|
470
|
+
* proofs.forEach(proof => {
|
|
471
|
+
* console.log(`${proof.type}: ${proof.url} (expires: ${proof.expires_at})`);
|
|
472
|
+
* });
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
475
|
+
async getProofDownloadURLs(kycId) {
|
|
476
|
+
return this.request(
|
|
477
|
+
`/api/v1/kyc/proofs/${kycId}`,
|
|
478
|
+
{ headers: this.getUserHeaders() }
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
// ============================================================================
|
|
482
|
+
// KYC Overview & Statistics
|
|
483
|
+
// ============================================================================
|
|
484
|
+
/**
|
|
485
|
+
* Get KYC overview statistics
|
|
486
|
+
*
|
|
487
|
+
* @param fromDate - Optional start date (ISO 8601)
|
|
488
|
+
* @param toDate - Optional end date (ISO 8601)
|
|
489
|
+
* @returns KYC statistics including counts by status
|
|
490
|
+
*
|
|
491
|
+
* @example
|
|
492
|
+
* ```typescript
|
|
493
|
+
* const overview = await client.getOverview(
|
|
494
|
+
* "2024-01-01T00:00:00Z",
|
|
495
|
+
* "2024-12-31T23:59:59Z"
|
|
496
|
+
* );
|
|
497
|
+
* console.log(`Total: ${overview.total}, Pending: ${overview.pending}`);
|
|
498
|
+
* console.log(`Approved: ${overview.approved}, Rejected: ${overview.rejected}`);
|
|
499
|
+
* ```
|
|
500
|
+
*/
|
|
501
|
+
async getOverview(fromDate, toDate) {
|
|
502
|
+
const params = {};
|
|
503
|
+
if (fromDate) params.fromDate = fromDate;
|
|
504
|
+
if (toDate) params.toDate = toDate;
|
|
505
|
+
return this.request(
|
|
506
|
+
`/api/v1/kyc/overview${this.buildQueryString(params)}`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
// ============================================================================
|
|
510
|
+
// Alert Management
|
|
511
|
+
// ============================================================================
|
|
512
|
+
/**
|
|
513
|
+
* Get a KYC alert by ID
|
|
514
|
+
*
|
|
515
|
+
* @param alertId - Alert ID
|
|
516
|
+
* @returns Alert details
|
|
517
|
+
*/
|
|
518
|
+
async getAlert(alertId) {
|
|
519
|
+
return this.request(`/api/v1/kyc/alerts/${alertId}`);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* List KYC alerts with filters and pagination
|
|
523
|
+
*
|
|
524
|
+
* @param filters - Optional filters (status, risk, alert_type, assigned_for, etc.)
|
|
525
|
+
* @param pagination - Optional pagination (page, page_size)
|
|
526
|
+
* @returns Paginated list of alerts
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* ```typescript
|
|
530
|
+
* const alerts = await client.listAlerts(
|
|
531
|
+
* {
|
|
532
|
+
* status: ["pending", "in_progress"],
|
|
533
|
+
* risk: "critical",
|
|
534
|
+
* alert_type: "kyc"
|
|
535
|
+
* },
|
|
536
|
+
* { page: 1, page_size: 20 }
|
|
537
|
+
* );
|
|
538
|
+
* console.log(`Found ${alerts.total} alerts`);
|
|
539
|
+
* ```
|
|
540
|
+
*/
|
|
541
|
+
async listAlerts(filters, pagination) {
|
|
542
|
+
const params = {};
|
|
543
|
+
if (filters) {
|
|
544
|
+
addFilterParam(params, "kyc_id", filters.kyc_id);
|
|
545
|
+
addFilterParam(params, "alert_type", filters.alert_type);
|
|
546
|
+
addFilterParam(params, "assigned_for", filters.assigned_for);
|
|
547
|
+
addFilterParam(params, "status", filters.status);
|
|
548
|
+
addFilterParam(params, "risk", filters.risk);
|
|
549
|
+
addSimpleParams(params, filters, ["search", "fromDate", "toDate", "sort_by", "order"]);
|
|
550
|
+
}
|
|
551
|
+
if (pagination) {
|
|
552
|
+
if (pagination.page) params.page = pagination.page;
|
|
553
|
+
if (pagination.page_size) params.limit = pagination.page_size;
|
|
554
|
+
}
|
|
555
|
+
return this.request(
|
|
556
|
+
`/api/v1/kyc/alerts${this.buildQueryString(params)}`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Update a KYC alert
|
|
561
|
+
*
|
|
562
|
+
* @param alertId - Alert ID
|
|
563
|
+
* @param update - Fields to update (status, assigned_for, reason, alert_type)
|
|
564
|
+
*
|
|
565
|
+
* @example
|
|
566
|
+
* ```typescript
|
|
567
|
+
* // Assign an alert
|
|
568
|
+
* await client.updateAlert("alert_123", {
|
|
569
|
+
* assigned_for: "analyst_user_id",
|
|
570
|
+
* status: "in_progress"
|
|
571
|
+
* });
|
|
572
|
+
*
|
|
573
|
+
* // Resolve an alert
|
|
574
|
+
* await client.updateAlert("alert_123", {
|
|
575
|
+
* status: "resolved",
|
|
576
|
+
* reason: "Customer verified via phone call"
|
|
577
|
+
* });
|
|
578
|
+
*
|
|
579
|
+
* // Escalate an alert
|
|
580
|
+
* await client.updateAlert("alert_123", {
|
|
581
|
+
* status: "escalated",
|
|
582
|
+
* assigned_for: "manager_user_id",
|
|
583
|
+
* reason: "Requires senior review - suspicious documents"
|
|
584
|
+
* });
|
|
585
|
+
* ```
|
|
586
|
+
*/
|
|
587
|
+
async updateAlert(alertId, update) {
|
|
588
|
+
await this.request(`/api/v1/kyc/alerts/${alertId}`, {
|
|
589
|
+
method: "PUT",
|
|
590
|
+
body: JSON.stringify(update),
|
|
591
|
+
headers: this.getUserHeaders()
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
// ============================================================================
|
|
595
|
+
// KYC Preferences
|
|
596
|
+
// ============================================================================
|
|
597
|
+
/**
|
|
598
|
+
* Get KYC preferences for the tenant
|
|
599
|
+
*
|
|
600
|
+
* @returns KYC preferences configuration
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* const prefs = await client.getPreferences();
|
|
605
|
+
* console.log(`Face verification required: ${prefs.is_face_verification_required}`);
|
|
606
|
+
* console.log(`Required documents: ${prefs.required_document_count}`);
|
|
607
|
+
* ```
|
|
608
|
+
*/
|
|
609
|
+
async getPreferences() {
|
|
610
|
+
return this.request("/api/v1/kyc/preferences");
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Update KYC preferences for the tenant
|
|
614
|
+
*
|
|
615
|
+
* @param update - Fields to update
|
|
616
|
+
* @returns Updated preferences
|
|
617
|
+
*
|
|
618
|
+
* @example
|
|
619
|
+
* ```typescript
|
|
620
|
+
* await client.updatePreferences({
|
|
621
|
+
* is_face_verification_required: true,
|
|
622
|
+
* is_address_verification_required: true,
|
|
623
|
+
* required_document_count: 2,
|
|
624
|
+
* reasons: [
|
|
625
|
+
* "Documents verified",
|
|
626
|
+
* "Identity confirmed",
|
|
627
|
+
* "Address matched"
|
|
628
|
+
* ]
|
|
629
|
+
* });
|
|
630
|
+
* ```
|
|
631
|
+
*/
|
|
632
|
+
async updatePreferences(update) {
|
|
633
|
+
return this.request("/api/v1/kyc/preferences", {
|
|
634
|
+
method: "PUT",
|
|
635
|
+
body: JSON.stringify(update)
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
// ============================================================================
|
|
639
|
+
// Customer Profile Management (Risk Profile Service)
|
|
640
|
+
// ============================================================================
|
|
641
|
+
/**
|
|
642
|
+
* Make a request to the Risk Profile Service
|
|
643
|
+
* Uses riskProfileBaseURL if configured, otherwise falls back to baseURL
|
|
644
|
+
*/
|
|
645
|
+
async riskProfileRequest(path, options = {}) {
|
|
646
|
+
if (!this.riskProfileBaseURL) {
|
|
647
|
+
throw new Error(
|
|
648
|
+
"Risk Profile Service URL not configured. Please provide riskProfileBaseURL in KycClientConfig."
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
const url = `${this.riskProfileBaseURL}${path}`;
|
|
652
|
+
const config = this.getConfig();
|
|
653
|
+
const headers = {
|
|
654
|
+
"Content-Type": "application/json",
|
|
655
|
+
"X-Tenant-ID": config.tenantId,
|
|
656
|
+
...config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {},
|
|
657
|
+
...this.getUserHeaders(),
|
|
658
|
+
...options.headers
|
|
659
|
+
};
|
|
660
|
+
const response = await fetch(url, {
|
|
661
|
+
...options,
|
|
662
|
+
headers
|
|
663
|
+
});
|
|
664
|
+
if (!response.ok) {
|
|
665
|
+
const errorData = await response.json().catch(() => ({}));
|
|
666
|
+
return this.handleErrorResponse(response.status, errorData);
|
|
667
|
+
}
|
|
668
|
+
return response.json();
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* List customer profiles for the tenant
|
|
672
|
+
*
|
|
673
|
+
* @param filters - Optional filters (risk_category, entity_type, status, search, etc.)
|
|
674
|
+
* @param pagination - Optional pagination (limit, offset)
|
|
675
|
+
* @returns Paginated list of customer profiles
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* ```typescript
|
|
679
|
+
* const profiles = await client.listCustomerProfiles(
|
|
680
|
+
* { risk_category: 'high', entity_type: 'individual' },
|
|
681
|
+
* { limit: 20, offset: 0 }
|
|
682
|
+
* );
|
|
683
|
+
* console.log(`Found ${profiles.total} profiles`);
|
|
684
|
+
* profiles.profiles.forEach(p => console.log(p.customer_id, p.full_name));
|
|
685
|
+
* ```
|
|
686
|
+
*/
|
|
687
|
+
async listCustomerProfiles(filters, pagination) {
|
|
688
|
+
const params = {};
|
|
689
|
+
if (filters) {
|
|
690
|
+
if (filters.risk_category) {
|
|
691
|
+
params.risk_category = Array.isArray(filters.risk_category) ? filters.risk_category : [filters.risk_category];
|
|
692
|
+
}
|
|
693
|
+
if (filters.entity_type) {
|
|
694
|
+
params.entity_type = Array.isArray(filters.entity_type) ? filters.entity_type : [filters.entity_type];
|
|
695
|
+
}
|
|
696
|
+
if (filters.status) {
|
|
697
|
+
params.status = Array.isArray(filters.status) ? filters.status : [filters.status];
|
|
698
|
+
}
|
|
699
|
+
addSimpleParams(params, filters, [
|
|
700
|
+
"search",
|
|
701
|
+
"is_pep",
|
|
702
|
+
"has_sanctions",
|
|
703
|
+
"requires_edd",
|
|
704
|
+
"sort_by",
|
|
705
|
+
"sort_order"
|
|
706
|
+
]);
|
|
707
|
+
}
|
|
708
|
+
if (pagination) {
|
|
709
|
+
addSimpleParams(params, pagination, ["limit", "offset"]);
|
|
710
|
+
}
|
|
711
|
+
return this.riskProfileRequest(
|
|
712
|
+
`/api/v1/risk-dashboard/profiles${this.buildQueryString(params)}`
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Get a customer profile by ID
|
|
717
|
+
*
|
|
718
|
+
* @param profileId - The profile UUID
|
|
719
|
+
* @returns Customer profile details
|
|
720
|
+
*
|
|
721
|
+
* @example
|
|
722
|
+
* ```typescript
|
|
723
|
+
* const profile = await client.getCustomerProfile('uuid-here');
|
|
724
|
+
* console.log(`Customer: ${profile.full_name}, Risk: ${profile.risk_category}`);
|
|
725
|
+
* ```
|
|
726
|
+
*/
|
|
727
|
+
async getCustomerProfile(profileId) {
|
|
728
|
+
return this.riskProfileRequest(
|
|
729
|
+
`/api/v1/risk-dashboard/profiles/${profileId}`
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Create a new customer profile
|
|
734
|
+
*
|
|
735
|
+
* A customer profile must exist before submitting KYC verification.
|
|
736
|
+
* The customer_id field will be used as the 'reference' in KYC submissions.
|
|
737
|
+
*
|
|
738
|
+
* @param profile - Customer profile data
|
|
739
|
+
* @returns Created customer profile
|
|
740
|
+
*
|
|
741
|
+
* @example
|
|
742
|
+
* ```typescript
|
|
743
|
+
* const profile = await client.createCustomerProfile({
|
|
744
|
+
* customer_id: 'cust_123',
|
|
745
|
+
* entity_type: 'individual',
|
|
746
|
+
* full_name: 'John Doe',
|
|
747
|
+
* email_address: 'john@example.com',
|
|
748
|
+
* country_of_residence: 'US'
|
|
749
|
+
* });
|
|
750
|
+
* console.log(`Created profile: ${profile.id}`);
|
|
751
|
+
*
|
|
752
|
+
* // Now you can submit KYC using the customer_id as reference
|
|
753
|
+
* await client.submitVerification({
|
|
754
|
+
* reference: profile.customer_id, // 'cust_123'
|
|
755
|
+
* email: 'john@example.com',
|
|
756
|
+
* // ... other fields
|
|
757
|
+
* });
|
|
758
|
+
* ```
|
|
759
|
+
*/
|
|
760
|
+
async createCustomerProfile(profile) {
|
|
761
|
+
return this.riskProfileRequest("/api/v1/profiles", {
|
|
762
|
+
method: "POST",
|
|
763
|
+
body: JSON.stringify(profile)
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
// ============================================================================
|
|
767
|
+
// Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)
|
|
768
|
+
// ============================================================================
|
|
769
|
+
};
|
|
770
|
+
|
|
771
|
+
exports.KycClient = KycClient;
|
|
772
|
+
//# sourceMappingURL=core.js.map
|
|
773
|
+
//# sourceMappingURL=core.js.map
|