vesant-sdk 1.6.1 → 1.6.3

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 (67) hide show
  1. package/dist/{client-DW1Xiz6a.d.mts → client-BlCxjbY2.d.mts} +6 -0
  2. package/dist/{client-eLbtPRkh.d.ts → client-C_A7QLcB.d.ts} +6 -0
  3. package/dist/compliance/index.d.mts +9 -2
  4. package/dist/compliance/index.d.ts +9 -2
  5. package/dist/compliance/index.js +177 -63
  6. package/dist/compliance/index.js.map +1 -1
  7. package/dist/compliance/index.mjs +177 -63
  8. package/dist/compliance/index.mjs.map +1 -1
  9. package/dist/decisions/index.js +1 -1
  10. package/dist/decisions/index.js.map +1 -1
  11. package/dist/decisions/index.mjs +1 -1
  12. package/dist/decisions/index.mjs.map +1 -1
  13. package/dist/fraud/index.d.mts +80 -0
  14. package/dist/fraud/index.d.ts +80 -0
  15. package/dist/fraud/index.js +606 -0
  16. package/dist/fraud/index.js.map +1 -0
  17. package/dist/fraud/index.mjs +604 -0
  18. package/dist/fraud/index.mjs.map +1 -0
  19. package/dist/geolocation/index.d.mts +2 -2
  20. package/dist/geolocation/index.d.ts +2 -2
  21. package/dist/geolocation/index.js +43 -14
  22. package/dist/geolocation/index.js.map +1 -1
  23. package/dist/geolocation/index.mjs +43 -14
  24. package/dist/geolocation/index.mjs.map +1 -1
  25. package/dist/index-B04H4xfJ.d.mts +320 -0
  26. package/dist/index-CItMPmLL.d.ts +320 -0
  27. package/dist/index.d.mts +9 -109
  28. package/dist/index.d.ts +9 -109
  29. package/dist/index.js +281 -69
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +281 -70
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/kyc/core.d.mts +1 -1
  34. package/dist/kyc/core.d.ts +1 -1
  35. package/dist/kyc/core.js +11 -7
  36. package/dist/kyc/core.js.map +1 -1
  37. package/dist/kyc/core.mjs +11 -7
  38. package/dist/kyc/core.mjs.map +1 -1
  39. package/dist/kyc/index.d.mts +24 -13
  40. package/dist/kyc/index.d.ts +24 -13
  41. package/dist/kyc/index.js +11 -7
  42. package/dist/kyc/index.js.map +1 -1
  43. package/dist/kyc/index.mjs +11 -7
  44. package/dist/kyc/index.mjs.map +1 -1
  45. package/dist/react.d.mts +1 -1
  46. package/dist/react.d.ts +1 -1
  47. package/dist/react.js +1 -1
  48. package/dist/react.js.map +1 -1
  49. package/dist/react.mjs +1 -1
  50. package/dist/react.mjs.map +1 -1
  51. package/dist/risk-profile/index.js +1 -1
  52. package/dist/risk-profile/index.js.map +1 -1
  53. package/dist/risk-profile/index.mjs +1 -1
  54. package/dist/risk-profile/index.mjs.map +1 -1
  55. package/dist/scores/index.js +1 -1
  56. package/dist/scores/index.js.map +1 -1
  57. package/dist/scores/index.mjs +1 -1
  58. package/dist/scores/index.mjs.map +1 -1
  59. package/dist/tax/index.d.mts +36 -2
  60. package/dist/tax/index.d.ts +36 -2
  61. package/dist/tax/index.js +36 -1
  62. package/dist/tax/index.js.map +1 -1
  63. package/dist/tax/index.mjs +36 -1
  64. package/dist/tax/index.mjs.map +1 -1
  65. package/dist/webhooks/index.d.mts +2 -177
  66. package/dist/webhooks/index.d.ts +2 -177
  67. package/package.json +6 -1
package/dist/index.js CHANGED
@@ -242,7 +242,7 @@ var noopLogger = {
242
242
  };
243
243
 
244
244
  // src/core/version.ts
245
- var SDK_VERSION = "1.6.1";
245
+ var SDK_VERSION = "1.6.2";
246
246
 
247
247
  // src/shared/browser-utils.ts
248
248
  function generateUUID() {
@@ -1123,22 +1123,51 @@ var GeolocationClient = class extends BaseClient {
1123
1123
  void 0,
1124
1124
  requestOptions
1125
1125
  );
1126
- const locationResult = await this.verifyIP({
1127
- ip_address: ipAddress,
1128
- user_id: userId,
1129
- event_type: eventType,
1130
- device_fingerprint: cipherTextResult.valid && cipherTextResult.device ? {
1131
- device_id: cipherTextResult.device_uuid,
1132
- user_agent: "",
1133
- platform: cipherTextResult.device.platform,
1134
- browser: cipherTextResult.device.browser,
1135
- os: cipherTextResult.device.os
1136
- } : void 0
1137
- }, requestOptions);
1126
+ const loc = cipherTextResult.location;
1127
+ const risk = cipherTextResult.risk;
1128
+ if (!risk) {
1129
+ const locationResult = await this.verifyIP({
1130
+ ip_address: ipAddress,
1131
+ user_id: userId,
1132
+ event_type: eventType
1133
+ }, requestOptions);
1134
+ return {
1135
+ ciphertext_valid: cipherTextResult.valid,
1136
+ ciphertext_result: cipherTextResult,
1137
+ location: locationResult
1138
+ };
1139
+ }
1140
+ const location = {
1141
+ ip_address: cipherTextResult.ip_address,
1142
+ location: {
1143
+ country: loc?.country ?? "",
1144
+ country_iso: loc?.country_iso ?? "",
1145
+ city: loc?.city ?? "",
1146
+ region: loc?.region ?? "",
1147
+ postal_code: "",
1148
+ latitude: loc?.latitude ?? 0,
1149
+ longitude: loc?.longitude ?? 0,
1150
+ timezone: "",
1151
+ is_vpn: risk.is_vpn ?? false,
1152
+ is_proxy: risk.is_proxy ?? false,
1153
+ is_tor: risk.is_tor ?? false,
1154
+ is_hosting: risk.is_hosting ?? false,
1155
+ is_anonymizer: risk.is_vpn || risk.is_proxy || risk.is_tor
1156
+ },
1157
+ is_compliant: cipherTextResult.is_compliant ?? !risk.is_blocked,
1158
+ is_blocked: risk.is_blocked ?? false,
1159
+ risk_level: risk.level ?? "low",
1160
+ risk_score: risk.score ?? 0,
1161
+ risk_reasons: risk.is_blocked && risk.block_reasons ? risk.block_reasons : risk.factors ?? [],
1162
+ jurisdiction: cipherTextResult.jurisdiction,
1163
+ geofence_evaluation: cipherTextResult.geofence_evaluation,
1164
+ record_id: cipherTextResult.record_id ?? "",
1165
+ gps_required: cipherTextResult.gps_required
1166
+ };
1138
1167
  return {
1139
1168
  ciphertext_valid: cipherTextResult.valid,
1140
1169
  ciphertext_result: cipherTextResult,
1141
- location: locationResult
1170
+ location
1142
1171
  };
1143
1172
  }
1144
1173
  // ============================================================================
@@ -1543,28 +1572,34 @@ var ComplianceClient = class {
1543
1572
  if (this.config.debug) {
1544
1573
  this.logger.debug("Starting registration verification", { customerId: request.customerId });
1545
1574
  }
1546
- const customerData = request.cipherText ? {
1547
- full_name: request.fullName,
1548
- email: request.emailAddress,
1549
- phone: request.phoneNumber,
1550
- date_of_birth: request.dateOfBirth
1551
- } : void 0;
1552
- [cipherTextResult, geoVerification] = await Promise.all([
1553
- this.executeCipherTextValidation(
1575
+ if (request.cipherText) {
1576
+ cipherTextResult = await this.executeCipherTextValidation(
1554
1577
  request.cipherText,
1555
1578
  request.customerId,
1556
1579
  "registration",
1557
1580
  request.ipAddress,
1558
- customerData,
1581
+ {
1582
+ full_name: request.fullName,
1583
+ email: request.emailAddress,
1584
+ phone: request.phoneNumber,
1585
+ date_of_birth: request.dateOfBirth
1586
+ },
1559
1587
  requestOptions
1560
- ),
1561
- this.geoClient.verifyIP({
1588
+ );
1589
+ geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress)) ?? await this.geoClient.verifyIP({
1562
1590
  ip_address: request.ipAddress,
1563
1591
  user_id: request.customerId,
1564
1592
  event_type: "registration",
1565
1593
  device_fingerprint: request.deviceFingerprint
1566
- }, requestOptions)
1567
- ]);
1594
+ }, requestOptions);
1595
+ } else {
1596
+ geoVerification = await this.geoClient.verifyIP({
1597
+ ip_address: request.ipAddress,
1598
+ user_id: request.customerId,
1599
+ event_type: "registration",
1600
+ device_fingerprint: request.deviceFingerprint
1601
+ }, requestOptions);
1602
+ }
1568
1603
  const blockReasons = this.evaluateRegistrationBlock(geoVerification, cipherTextResult);
1569
1604
  if (blockReasons.length > 0) {
1570
1605
  if (this.config.debug) {
@@ -1645,7 +1680,7 @@ var ComplianceClient = class {
1645
1680
  evaluateRegistrationBlock(geoVerification, cipherTextResult) {
1646
1681
  const blockReasons = [];
1647
1682
  if (geoVerification.is_blocked) {
1648
- blockReasons.push(...geoVerification.risk_reasons);
1683
+ blockReasons.push(...geoVerification.risk_reasons ?? []);
1649
1684
  }
1650
1685
  if (!geoVerification.is_compliant) {
1651
1686
  if (!blockReasons.includes("non_compliant_jurisdiction")) {
@@ -1669,7 +1704,7 @@ var ComplianceClient = class {
1669
1704
  }
1670
1705
  }
1671
1706
  if (geoVerification.geofence_evaluation?.blocked) {
1672
- blockReasons.push(...geoVerification.geofence_evaluation.reasons);
1707
+ blockReasons.push(...geoVerification.geofence_evaluation.reasons ?? []);
1673
1708
  }
1674
1709
  if (geoVerification.risk_level === "critical") {
1675
1710
  if (!blockReasons.includes("critical_risk_level")) {
@@ -1820,23 +1855,39 @@ var ComplianceClient = class {
1820
1855
  if (this.config.debug) {
1821
1856
  this.logger.debug("Starting login verification", { customerId: request.customerId });
1822
1857
  }
1823
- const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1824
- this.executeCipherTextValidation(
1825
- request.cipherText,
1826
- request.customerId,
1827
- "login",
1828
- request.ipAddress,
1829
- void 0,
1830
- requestOptions
1831
- ),
1832
- this.geoClient.verifyIP({
1858
+ let cipherTextResult;
1859
+ let geoVerification;
1860
+ let profileResult;
1861
+ if (request.cipherText) {
1862
+ [cipherTextResult, profileResult] = await Promise.all([
1863
+ this.executeCipherTextValidation(
1864
+ request.cipherText,
1865
+ request.customerId,
1866
+ "login",
1867
+ request.ipAddress,
1868
+ void 0,
1869
+ requestOptions
1870
+ ),
1871
+ this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1872
+ ]);
1873
+ geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress)) ?? await this.geoClient.verifyIP({
1833
1874
  ip_address: request.ipAddress,
1834
1875
  user_id: request.customerId,
1835
1876
  event_type: "login",
1836
1877
  device_fingerprint: request.deviceFingerprint
1837
- }, requestOptions),
1838
- this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1839
- ]);
1878
+ }, requestOptions);
1879
+ } else {
1880
+ [, geoVerification, profileResult] = await Promise.all([
1881
+ Promise.resolve(void 0),
1882
+ this.geoClient.verifyIP({
1883
+ ip_address: request.ipAddress,
1884
+ user_id: request.customerId,
1885
+ event_type: "login",
1886
+ device_fingerprint: request.deviceFingerprint
1887
+ }, requestOptions),
1888
+ this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1889
+ ]);
1890
+ }
1840
1891
  const loginBlockReasons = this.getBlockReasons(geoVerification, profileResult, cipherTextResult);
1841
1892
  const isBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1842
1893
  if (isBlocked && !profileResult) {
@@ -1921,23 +1972,39 @@ var ComplianceClient = class {
1921
1972
  currency: request.currency
1922
1973
  });
1923
1974
  }
1924
- const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1925
- this.executeCipherTextValidation(
1926
- request.cipherText,
1927
- request.customerId,
1928
- "transaction",
1929
- request.ipAddress,
1930
- void 0,
1931
- requestOptions
1932
- ),
1933
- this.geoClient.verifyIP({
1975
+ let cipherTextResult;
1976
+ let geoVerification;
1977
+ let profileResult;
1978
+ if (request.cipherText) {
1979
+ [cipherTextResult, profileResult] = await Promise.all([
1980
+ this.executeCipherTextValidation(
1981
+ request.cipherText,
1982
+ request.customerId,
1983
+ "transaction",
1984
+ request.ipAddress,
1985
+ void 0,
1986
+ requestOptions
1987
+ ),
1988
+ this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1989
+ ]);
1990
+ geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress)) ?? await this.geoClient.verifyIP({
1934
1991
  ip_address: request.ipAddress,
1935
1992
  user_id: request.customerId,
1936
1993
  event_type: "transaction",
1937
1994
  device_fingerprint: request.deviceFingerprint
1938
- }, requestOptions),
1939
- this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1940
- ]);
1995
+ }, requestOptions);
1996
+ } else {
1997
+ [, geoVerification, profileResult] = await Promise.all([
1998
+ Promise.resolve(void 0),
1999
+ this.geoClient.verifyIP({
2000
+ ip_address: request.ipAddress,
2001
+ user_id: request.customerId,
2002
+ event_type: "transaction",
2003
+ device_fingerprint: request.deviceFingerprint
2004
+ }, requestOptions),
2005
+ this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
2006
+ ]);
2007
+ }
1941
2008
  const geoBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1942
2009
  if (geoBlocked && !profileResult) {
1943
2010
  return {
@@ -2001,22 +2068,31 @@ var ComplianceClient = class {
2001
2068
  async verifyEvent(request, requestOptions) {
2002
2069
  const startTime = Date.now();
2003
2070
  this.validateEventRequest(request);
2004
- const [cipherTextResult, geoVerification] = await Promise.all([
2005
- this.executeCipherTextValidation(
2071
+ let cipherTextResult;
2072
+ let geoVerification;
2073
+ if (request.cipherText) {
2074
+ cipherTextResult = await this.executeCipherTextValidation(
2006
2075
  request.cipherText,
2007
2076
  request.customerId,
2008
2077
  request.eventType,
2009
2078
  request.ipAddress,
2010
2079
  void 0,
2011
2080
  requestOptions
2012
- ),
2013
- this.geoClient.verifyIP({
2081
+ );
2082
+ geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress)) ?? await this.geoClient.verifyIP({
2083
+ ip_address: request.ipAddress,
2084
+ user_id: request.customerId,
2085
+ event_type: request.eventType,
2086
+ device_fingerprint: request.deviceFingerprint
2087
+ }, requestOptions);
2088
+ } else {
2089
+ geoVerification = await this.geoClient.verifyIP({
2014
2090
  ip_address: request.ipAddress,
2015
2091
  user_id: request.customerId,
2016
2092
  event_type: request.eventType,
2017
2093
  device_fingerprint: request.deviceFingerprint
2018
- }, requestOptions)
2019
- ]);
2094
+ }, requestOptions);
2095
+ }
2020
2096
  if (this.config.autoCreateProfiles) {
2021
2097
  try {
2022
2098
  const profile = await this.riskClient.getProfile(request.customerId, requestOptions);
@@ -2030,7 +2106,7 @@ var ComplianceClient = class {
2030
2106
  }
2031
2107
  }
2032
2108
  const cipherTextBlocked = cipherTextResult ? !cipherTextResult.valid || cipherTextResult.risk?.is_blocked === true : false;
2033
- const blockReasons = [...geoVerification.risk_reasons];
2109
+ const blockReasons = [...geoVerification.risk_reasons ?? []];
2034
2110
  if (cipherTextResult) {
2035
2111
  if (!cipherTextResult.valid) {
2036
2112
  blockReasons.push("ciphertext_validation_failed");
@@ -2099,6 +2175,44 @@ var ComplianceClient = class {
2099
2175
  return void 0;
2100
2176
  }
2101
2177
  }
2178
+ /**
2179
+ * Build a LocationVerification from a ValidateCipherTextResponse.
2180
+ * The validate-ciphertext endpoint now returns the full geo-verification data
2181
+ * (is_compliant, jurisdiction, geofence_evaluation, record_id, gps_required),
2182
+ * so a separate verifyIP call is unnecessary.
2183
+ */
2184
+ buildLocationFromCipherText(ct, ipAddress) {
2185
+ const loc = ct.location;
2186
+ const risk = ct.risk;
2187
+ if (!risk) return null;
2188
+ return {
2189
+ ip_address: ct.ip_address || ipAddress,
2190
+ location: {
2191
+ country: loc?.country ?? "",
2192
+ country_iso: loc?.country_iso ?? "",
2193
+ city: loc?.city ?? "",
2194
+ region: loc?.region ?? "",
2195
+ postal_code: "",
2196
+ latitude: loc?.latitude ?? 0,
2197
+ longitude: loc?.longitude ?? 0,
2198
+ timezone: "",
2199
+ is_vpn: risk.is_vpn,
2200
+ is_proxy: risk.is_proxy,
2201
+ is_tor: risk.is_tor,
2202
+ is_hosting: risk.is_hosting ?? false,
2203
+ is_anonymizer: risk.is_vpn || risk.is_proxy || risk.is_tor
2204
+ },
2205
+ is_compliant: ct.is_compliant ?? !risk.is_blocked,
2206
+ is_blocked: risk.is_blocked,
2207
+ risk_level: risk.level,
2208
+ risk_score: risk.score,
2209
+ risk_reasons: risk.is_blocked && risk.block_reasons ? risk.block_reasons : risk.factors ?? [],
2210
+ jurisdiction: ct.jurisdiction,
2211
+ geofence_evaluation: ct.geofence_evaluation,
2212
+ record_id: ct.record_id ?? "",
2213
+ gps_required: ct.gps_required
2214
+ };
2215
+ }
2102
2216
  calculateTransactionRisk(amount, currency, geoVerification, profile, cipherTextResult) {
2103
2217
  if (!this._currencyRatesCustomized && !this._currencyRatesWarned) {
2104
2218
  this._currencyRatesWarned = true;
@@ -2169,7 +2283,7 @@ var ComplianceClient = class {
2169
2283
  getBlockReasons(geoVerification, profile, cipherTextResult) {
2170
2284
  const reasons = [];
2171
2285
  if (geoVerification.is_blocked) {
2172
- reasons.push(...geoVerification.risk_reasons);
2286
+ reasons.push(...geoVerification.risk_reasons ?? []);
2173
2287
  }
2174
2288
  if (profile) {
2175
2289
  if (profile.customer_status === "suspended") {
@@ -2492,19 +2606,23 @@ var KycClient = class extends BaseClient {
2492
2606
  *
2493
2607
  * Generates a link that the user can visit to submit their KYC documents.
2494
2608
  *
2495
- * @param request - Request containing the user ID, optional redirect URL, and optional callback URL (receives POST requests)
2496
- * @returns Response containing the redirect link and KYC ID
2609
+ * @param request - Request containing the user ID, redirect URL, callback URL, and trigger event
2610
+ * @returns Response containing kyc_required, can_skip, and optionally the redirect link and KYC ID
2497
2611
  *
2498
2612
  * @example
2499
2613
  * ```typescript
2500
2614
  * const result = await client.requestKycSubmitLink({
2501
2615
  * user_id: "user_123",
2502
- * redirect_url: "https://merchant.com/kyc-complete", // optional
2503
- * callback_url: "https://merchant.com/api/kyc-webhook" // optional - receives POST requests on status change
2616
+ * redirect_url: "https://merchant.com/kyc-complete",
2617
+ * callback_url: "https://merchant.com/api/kyc-webhook",
2618
+ * trigger_event: "onboarding"
2504
2619
  * });
2505
2620
  *
2506
- * console.log(`Redirect user to: ${result.link}`);
2507
- * console.log(`KYC ID: ${result.kyc_id}`);
2621
+ * if (result.kyc_required && result.link) {
2622
+ * console.log(`Redirect user to: ${result.link}`);
2623
+ * } else if (result.can_skip) {
2624
+ * console.log("KYC not required, user can proceed");
2625
+ * }
2508
2626
  * ```
2509
2627
  */
2510
2628
  async requestKycSubmitLink(request) {
@@ -3081,6 +3199,41 @@ var TaxClient = class extends BaseClient {
3081
3199
  { ...requestOptions, responseType: "arraybuffer" }
3082
3200
  );
3083
3201
  }
3202
+ async runReminders() {
3203
+ return this.request("/api/v1/tax/reminders/run", {
3204
+ method: "POST"
3205
+ });
3206
+ }
3207
+ /**
3208
+ * Update only the reminder configuration (frequency + max count) without
3209
+ * touching any other tax rule settings. Fetches current rules first and
3210
+ * merges the reminder fields before sending the update.
3211
+ *
3212
+ * Requires the caller to be authenticated as a Tenant Super Admin.
3213
+ * Throws VesantError with status 403 if the role requirement is not met.
3214
+ */
3215
+ async updateReminderConfig(input) {
3216
+ const current = await this.getTaxRules();
3217
+ return this.updateTaxRules({
3218
+ trigger_account_creation: current.trigger_account_creation,
3219
+ trigger_first_withdrawal: current.trigger_first_withdrawal,
3220
+ trigger_threshold: current.trigger_threshold,
3221
+ trigger_manual: current.trigger_manual,
3222
+ trigger_tin_invalid: current.trigger_tin_invalid,
3223
+ trigger_w8ben_expiry: current.trigger_w8ben_expiry,
3224
+ trigger_tin_expired: current.trigger_tin_expired,
3225
+ us_withholding_enabled: current.us_withholding_enabled,
3226
+ non_us_withholding_enabled: current.non_us_withholding_enabled,
3227
+ transaction_action: current.transaction_action,
3228
+ w8ben_expiry_warning_days: current.w8ben_expiry_warning_days,
3229
+ tin_verification_due_date: current.tin_verification_due_date,
3230
+ email_sending_method: current.email_sending_method,
3231
+ display_tin_links_on_platform: current.display_tin_links_on_platform,
3232
+ tax_treaty_support: current.tax_treaty_support,
3233
+ reminder_frequency_days: input.reminder_frequency_days,
3234
+ reminder_max_count: input.reminder_max_count
3235
+ });
3236
+ }
3084
3237
  // ==========================================================================
3085
3238
  // P2 — Tenant Tax Rules
3086
3239
  // ==========================================================================
@@ -3189,6 +3342,64 @@ var TransactionClient = class extends BaseClient {
3189
3342
  }
3190
3343
  };
3191
3344
 
3345
+ // src/fraud/client.ts
3346
+ var FraudClient = class extends BaseClient {
3347
+ /**
3348
+ * Submit a single fraud event for scoring.
3349
+ */
3350
+ async scoreEvent(request, requestOptions) {
3351
+ this.validateScoreRequest(request);
3352
+ return this.requestWithRetry(
3353
+ "/api/v1/fraud/score",
3354
+ {
3355
+ method: "POST",
3356
+ body: JSON.stringify(request)
3357
+ },
3358
+ void 0,
3359
+ void 0,
3360
+ requestOptions
3361
+ );
3362
+ }
3363
+ /**
3364
+ * Submit multiple fraud events for scoring.
3365
+ */
3366
+ async scoreEventsBulk(requests, requestOptions) {
3367
+ if (!Array.isArray(requests) || requests.length === 0) {
3368
+ throw new ValidationError(
3369
+ "Invalid bulk score request: at least one score request is required",
3370
+ ["requests"]
3371
+ );
3372
+ }
3373
+ requests.forEach((request, index) => this.validateScoreRequest(request, index));
3374
+ return this.requestWithRetry(
3375
+ "/api/v1/fraud/score/bulk",
3376
+ {
3377
+ method: "POST",
3378
+ body: JSON.stringify(requests)
3379
+ },
3380
+ void 0,
3381
+ void 0,
3382
+ requestOptions
3383
+ );
3384
+ }
3385
+ validateScoreRequest(request, index) {
3386
+ const errors = [];
3387
+ const prefix = index === void 0 ? "" : `requests[${index}].`;
3388
+ if (!request.customer_id?.trim()) {
3389
+ errors.push(`${prefix}customer_id is required`);
3390
+ }
3391
+ if (!request.sift_user_id?.trim()) {
3392
+ errors.push(`${prefix}sift_user_id is required`);
3393
+ }
3394
+ if (!request.event_type?.trim()) {
3395
+ errors.push(`${prefix}event_type is required`);
3396
+ }
3397
+ if (errors.length > 0) {
3398
+ throw new ValidationError(`Invalid fraud score request: ${errors.join(", ")}`, errors);
3399
+ }
3400
+ }
3401
+ };
3402
+
3192
3403
  // src/webhooks/handler.ts
3193
3404
  var WebhookHandler = class {
3194
3405
  constructor(config) {
@@ -3341,6 +3552,7 @@ exports.ComplianceBlockedError = ComplianceBlockedError;
3341
3552
  exports.ComplianceClient = ComplianceClient;
3342
3553
  exports.ComplianceError = ComplianceError;
3343
3554
  exports.DEFAULT_CURRENCY_RATES = DEFAULT_CURRENCY_RATES;
3555
+ exports.FraudClient = FraudClient;
3344
3556
  exports.GeolocationClient = GeolocationClient;
3345
3557
  exports.KycClient = KycClient;
3346
3558
  exports.NetworkError = NetworkError;