vesant-sdk 1.5.2 → 1.6.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.
Files changed (65) hide show
  1. package/dist/{client-BZxzOidG.d.mts → client-DW1Xiz6a.d.mts} +4 -2
  2. package/dist/{client-B8pFrXx_.d.ts → client-eLbtPRkh.d.ts} +4 -2
  3. package/dist/{client-CIon-bGS.d.mts → client-ePzhQKp9.d.mts} +2 -0
  4. package/dist/{client-CIon-bGS.d.ts → client-ePzhQKp9.d.ts} +2 -0
  5. package/dist/compliance/index.d.mts +18 -5
  6. package/dist/compliance/index.d.ts +18 -5
  7. package/dist/compliance/index.js +222 -42
  8. package/dist/compliance/index.js.map +1 -1
  9. package/dist/compliance/index.mjs +222 -42
  10. package/dist/compliance/index.mjs.map +1 -1
  11. package/dist/decisions/index.d.mts +1 -1
  12. package/dist/decisions/index.d.ts +1 -1
  13. package/dist/decisions/index.js +14 -1
  14. package/dist/decisions/index.js.map +1 -1
  15. package/dist/decisions/index.mjs +14 -1
  16. package/dist/decisions/index.mjs.map +1 -1
  17. package/dist/geolocation/index.d.mts +3 -3
  18. package/dist/geolocation/index.d.ts +3 -3
  19. package/dist/geolocation/index.js +14 -1
  20. package/dist/geolocation/index.js.map +1 -1
  21. package/dist/geolocation/index.mjs +14 -1
  22. package/dist/geolocation/index.mjs.map +1 -1
  23. package/dist/index.d.mts +6 -376
  24. package/dist/index.d.ts +6 -376
  25. package/dist/index.js +289 -251
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +289 -251
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/kyc/core.d.mts +1 -1
  30. package/dist/kyc/core.d.ts +1 -1
  31. package/dist/kyc/core.js +14 -1
  32. package/dist/kyc/core.js.map +1 -1
  33. package/dist/kyc/core.mjs +14 -1
  34. package/dist/kyc/core.mjs.map +1 -1
  35. package/dist/kyc/index.d.mts +1 -1
  36. package/dist/kyc/index.d.ts +1 -1
  37. package/dist/kyc/index.js +14 -1
  38. package/dist/kyc/index.js.map +1 -1
  39. package/dist/kyc/index.mjs +14 -1
  40. package/dist/kyc/index.mjs.map +1 -1
  41. package/dist/react.d.mts +2 -2
  42. package/dist/react.d.ts +2 -2
  43. package/dist/react.js +1 -1
  44. package/dist/react.js.map +1 -1
  45. package/dist/react.mjs +1 -1
  46. package/dist/react.mjs.map +1 -1
  47. package/dist/risk-profile/index.d.mts +1 -1
  48. package/dist/risk-profile/index.d.ts +1 -1
  49. package/dist/risk-profile/index.js +14 -1
  50. package/dist/risk-profile/index.js.map +1 -1
  51. package/dist/risk-profile/index.mjs +14 -1
  52. package/dist/risk-profile/index.mjs.map +1 -1
  53. package/dist/scores/index.d.mts +1 -1
  54. package/dist/scores/index.d.ts +1 -1
  55. package/dist/scores/index.js +14 -1
  56. package/dist/scores/index.js.map +1 -1
  57. package/dist/scores/index.mjs +14 -1
  58. package/dist/scores/index.mjs.map +1 -1
  59. package/dist/tax/index.d.mts +256 -0
  60. package/dist/tax/index.d.ts +256 -0
  61. package/dist/tax/index.js +652 -0
  62. package/dist/tax/index.js.map +1 -0
  63. package/dist/tax/index.mjs +650 -0
  64. package/dist/tax/index.mjs.map +1 -0
  65. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -240,7 +240,7 @@ var noopLogger = {
240
240
  };
241
241
 
242
242
  // src/core/version.ts
243
- var SDK_VERSION = "1.5.2";
243
+ var SDK_VERSION = "1.6.1";
244
244
 
245
245
  // src/shared/browser-utils.ts
246
246
  function generateUUID() {
@@ -414,6 +414,19 @@ var BaseClient = class {
414
414
  if (this.rateLimitTracker) {
415
415
  this.rateLimitTracker.updateFromHeaders(response.headers);
416
416
  }
417
+ if (requestOptions?.responseType === "arraybuffer") {
418
+ if (!response.ok) {
419
+ let errData = {};
420
+ try {
421
+ errData = await response.json();
422
+ } catch {
423
+ }
424
+ this.handleErrorResponse(response.status, errData, requestId);
425
+ }
426
+ this.circuitBreaker?.onSuccess();
427
+ const buffer = await response.arrayBuffer();
428
+ return buffer;
429
+ }
417
430
  let data;
418
431
  try {
419
432
  data = await response.json();
@@ -1523,17 +1536,34 @@ var ComplianceClient = class {
1523
1536
  const startTime = Date.now();
1524
1537
  this.validateRegistrationRequest(request);
1525
1538
  let geoVerification = null;
1539
+ let cipherTextResult;
1526
1540
  try {
1527
1541
  if (this.config.debug) {
1528
1542
  this.logger.debug("Starting registration verification", { customerId: request.customerId });
1529
1543
  }
1530
- geoVerification = await this.geoClient.verifyIP({
1531
- ip_address: request.ipAddress,
1532
- user_id: request.customerId,
1533
- event_type: "registration",
1534
- device_fingerprint: request.deviceFingerprint
1535
- }, requestOptions);
1536
- const blockReasons = this.evaluateRegistrationBlock(geoVerification);
1544
+ const customerData = request.cipherText ? {
1545
+ full_name: request.fullName,
1546
+ email: request.emailAddress,
1547
+ phone: request.phoneNumber,
1548
+ date_of_birth: request.dateOfBirth
1549
+ } : void 0;
1550
+ [cipherTextResult, geoVerification] = await Promise.all([
1551
+ this.executeCipherTextValidation(
1552
+ request.cipherText,
1553
+ request.customerId,
1554
+ "registration",
1555
+ request.ipAddress,
1556
+ customerData,
1557
+ requestOptions
1558
+ ),
1559
+ this.geoClient.verifyIP({
1560
+ ip_address: request.ipAddress,
1561
+ user_id: request.customerId,
1562
+ event_type: "registration",
1563
+ device_fingerprint: request.deviceFingerprint
1564
+ }, requestOptions)
1565
+ ]);
1566
+ const blockReasons = this.evaluateRegistrationBlock(geoVerification, cipherTextResult);
1537
1567
  if (blockReasons.length > 0) {
1538
1568
  if (this.config.debug) {
1539
1569
  this.logger.debug("Registration blocked at geo stage", { blockReasons });
@@ -1545,7 +1575,8 @@ var ComplianceClient = class {
1545
1575
  requiresKYC: false,
1546
1576
  requiresEDD: false,
1547
1577
  blockReasons,
1548
- processingTime: Date.now() - startTime
1578
+ processingTime: Date.now() - startTime,
1579
+ cipherTextValidation: cipherTextResult
1549
1580
  };
1550
1581
  }
1551
1582
  const profile = await this.riskClient.createProfile({
@@ -1580,7 +1611,8 @@ var ComplianceClient = class {
1580
1611
  requiresKYC,
1581
1612
  requiresEDD,
1582
1613
  blockReasons: [],
1583
- processingTime: Date.now() - startTime
1614
+ processingTime: Date.now() - startTime,
1615
+ cipherTextValidation: cipherTextResult
1584
1616
  };
1585
1617
  } catch (error) {
1586
1618
  if (this.config.debug) {
@@ -1608,7 +1640,7 @@ var ComplianceClient = class {
1608
1640
  * @param geoVerification - Geolocation verification result
1609
1641
  * @returns Array of block reasons (empty if allowed)
1610
1642
  */
1611
- evaluateRegistrationBlock(geoVerification) {
1643
+ evaluateRegistrationBlock(geoVerification, cipherTextResult) {
1612
1644
  const blockReasons = [];
1613
1645
  if (geoVerification.is_blocked) {
1614
1646
  blockReasons.push(...geoVerification.risk_reasons);
@@ -1642,6 +1674,20 @@ var ComplianceClient = class {
1642
1674
  blockReasons.push("critical_risk_level");
1643
1675
  }
1644
1676
  }
1677
+ if (cipherTextResult) {
1678
+ if (!cipherTextResult.valid) {
1679
+ blockReasons.push("ciphertext_validation_failed");
1680
+ }
1681
+ if (cipherTextResult.risk?.is_blocked) {
1682
+ blockReasons.push(...cipherTextResult.risk.block_reasons || []);
1683
+ }
1684
+ if (cipherTextResult.risk?.location_mismatch) {
1685
+ blockReasons.push("gps_ip_location_mismatch");
1686
+ }
1687
+ }
1688
+ if (geoVerification.gps_required && !cipherTextResult) {
1689
+ blockReasons.push("gps_verification_required");
1690
+ }
1645
1691
  return [...new Set(blockReasons)];
1646
1692
  }
1647
1693
  /**
@@ -1772,7 +1818,15 @@ var ComplianceClient = class {
1772
1818
  if (this.config.debug) {
1773
1819
  this.logger.debug("Starting login verification", { customerId: request.customerId });
1774
1820
  }
1775
- const [geoVerification, profileResult] = await Promise.all([
1821
+ const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1822
+ this.executeCipherTextValidation(
1823
+ request.cipherText,
1824
+ request.customerId,
1825
+ "login",
1826
+ request.ipAddress,
1827
+ void 0,
1828
+ requestOptions
1829
+ ),
1776
1830
  this.geoClient.verifyIP({
1777
1831
  ip_address: request.ipAddress,
1778
1832
  user_id: request.customerId,
@@ -1781,10 +1835,23 @@ var ComplianceClient = class {
1781
1835
  }, requestOptions),
1782
1836
  this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1783
1837
  ]);
1838
+ const loginBlockReasons = this.getBlockReasons(geoVerification, profileResult, cipherTextResult);
1839
+ const isBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1840
+ if (isBlocked && !profileResult) {
1841
+ return {
1842
+ allowed: false,
1843
+ geolocation: geoVerification,
1844
+ profile: null,
1845
+ requiresStepUp: false,
1846
+ blockReasons: loginBlockReasons,
1847
+ processingTime: Date.now() - startTime,
1848
+ cipherTextValidation: cipherTextResult
1849
+ };
1850
+ }
1784
1851
  let profile;
1785
1852
  if (profileResult) {
1786
1853
  profile = profileResult;
1787
- if (this.shouldUpdateProfile(profile, geoVerification.location.city)) {
1854
+ if (!isBlocked && this.shouldUpdateProfile(profile, geoVerification.location.city)) {
1788
1855
  profile = await this.riskClient.updateProfile(profile.id, {
1789
1856
  last_recorded_activity: (/* @__PURE__ */ new Date()).toISOString(),
1790
1857
  location: `${geoVerification.location.city}, ${geoVerification.location.country}`,
@@ -1797,15 +1864,15 @@ var ComplianceClient = class {
1797
1864
  }
1798
1865
  profile = await this.createProfileFromGeo(request.customerId, geoVerification);
1799
1866
  }
1800
- const isAllowed = geoVerification.is_compliant && !geoVerification.is_blocked && profile.customer_status !== "suspended";
1801
- const requiresStepUp = geoVerification.risk_level === "high" || geoVerification.risk_level === "critical";
1867
+ const requiresStepUp = geoVerification.risk_level === "high" || geoVerification.risk_level === "critical" || cipherTextResult?.risk?.location_mismatch === true;
1802
1868
  return {
1803
- allowed: isAllowed,
1869
+ allowed: !isBlocked && profile.customer_status !== "suspended",
1804
1870
  geolocation: geoVerification,
1805
1871
  profile,
1806
1872
  requiresStepUp,
1807
- blockReasons: this.getBlockReasons(geoVerification, profile),
1808
- processingTime: Date.now() - startTime
1873
+ blockReasons: isBlocked || profile.customer_status === "suspended" ? this.getBlockReasons(geoVerification, profile, cipherTextResult) : [],
1874
+ processingTime: Date.now() - startTime,
1875
+ cipherTextValidation: cipherTextResult
1809
1876
  };
1810
1877
  } catch (error) {
1811
1878
  throw new ComplianceError("Login verification failed", error instanceof Error ? error.message : void 0);
@@ -1852,27 +1919,58 @@ var ComplianceClient = class {
1852
1919
  currency: request.currency
1853
1920
  });
1854
1921
  }
1855
- const [geoVerification, profile] = await Promise.all([
1922
+ const [cipherTextResult, geoVerification, profileResult] = await Promise.all([
1923
+ this.executeCipherTextValidation(
1924
+ request.cipherText,
1925
+ request.customerId,
1926
+ "transaction",
1927
+ request.ipAddress,
1928
+ void 0,
1929
+ requestOptions
1930
+ ),
1856
1931
  this.geoClient.verifyIP({
1857
1932
  ip_address: request.ipAddress,
1858
1933
  user_id: request.customerId,
1859
1934
  event_type: "transaction",
1860
1935
  device_fingerprint: request.deviceFingerprint
1861
1936
  }, requestOptions),
1862
- this.riskClient.getProfile(request.customerId, requestOptions)
1937
+ this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null)
1863
1938
  ]);
1939
+ const geoBlocked = !geoVerification.is_compliant || geoVerification.is_blocked || !!cipherTextResult?.risk?.is_blocked || cipherTextResult?.valid === false || geoVerification.gps_required && !cipherTextResult;
1940
+ if (geoBlocked && !profileResult) {
1941
+ return {
1942
+ allowed: false,
1943
+ geolocation: geoVerification,
1944
+ profile: null,
1945
+ transactionRisk: { score: 0, level: "low", factors: [], allowed: false, requiresManualReview: false },
1946
+ requiresApproval: false,
1947
+ blockReasons: this.getTransactionBlockReasons(
1948
+ geoVerification,
1949
+ { score: 0, level: "low", factors: [], allowed: false, requiresManualReview: false },
1950
+ true,
1951
+ cipherTextResult
1952
+ ),
1953
+ processingTime: Date.now() - startTime,
1954
+ cipherTextValidation: cipherTextResult
1955
+ };
1956
+ }
1957
+ if (!profileResult) {
1958
+ throw new ComplianceError("Customer profile not found", request.customerId);
1959
+ }
1960
+ const profile = profileResult;
1864
1961
  const transactionRisk = this.calculateTransactionRisk(
1865
1962
  request.amount,
1866
1963
  request.currency,
1867
1964
  geoVerification,
1868
- profile
1965
+ profile,
1966
+ cipherTextResult
1869
1967
  );
1870
1968
  const jurisdictionAllowed = this.checkJurisdictionLimits(
1871
1969
  request.amount,
1872
1970
  request.currency,
1873
1971
  geoVerification.jurisdiction
1874
1972
  );
1875
- const isAllowed = geoVerification.is_compliant && !geoVerification.is_blocked && jurisdictionAllowed && transactionRisk.allowed;
1973
+ const isAllowed = !geoBlocked && jurisdictionAllowed && transactionRisk.allowed && profile.customer_status !== "suspended";
1876
1974
  return {
1877
1975
  allowed: isAllowed,
1878
1976
  geolocation: geoVerification,
@@ -1882,9 +1980,11 @@ var ComplianceClient = class {
1882
1980
  blockReasons: this.getTransactionBlockReasons(
1883
1981
  geoVerification,
1884
1982
  transactionRisk,
1885
- jurisdictionAllowed
1983
+ jurisdictionAllowed,
1984
+ cipherTextResult
1886
1985
  ),
1887
- processingTime: Date.now() - startTime
1986
+ processingTime: Date.now() - startTime,
1987
+ cipherTextValidation: cipherTextResult
1888
1988
  };
1889
1989
  } catch (error) {
1890
1990
  throw new ComplianceError("Transaction verification failed", error instanceof Error ? error.message : void 0);
@@ -1899,12 +1999,22 @@ var ComplianceClient = class {
1899
1999
  async verifyEvent(request, requestOptions) {
1900
2000
  const startTime = Date.now();
1901
2001
  this.validateEventRequest(request);
1902
- const geoVerification = await this.geoClient.verifyIP({
1903
- ip_address: request.ipAddress,
1904
- user_id: request.customerId,
1905
- event_type: request.eventType,
1906
- device_fingerprint: request.deviceFingerprint
1907
- }, requestOptions);
2002
+ const [cipherTextResult, geoVerification] = await Promise.all([
2003
+ this.executeCipherTextValidation(
2004
+ request.cipherText,
2005
+ request.customerId,
2006
+ request.eventType,
2007
+ request.ipAddress,
2008
+ void 0,
2009
+ requestOptions
2010
+ ),
2011
+ this.geoClient.verifyIP({
2012
+ ip_address: request.ipAddress,
2013
+ user_id: request.customerId,
2014
+ event_type: request.eventType,
2015
+ device_fingerprint: request.deviceFingerprint
2016
+ }, requestOptions)
2017
+ ]);
1908
2018
  if (this.config.autoCreateProfiles) {
1909
2019
  try {
1910
2020
  const profile = await this.riskClient.getProfile(request.customerId, requestOptions);
@@ -1917,11 +2027,26 @@ var ComplianceClient = class {
1917
2027
  }
1918
2028
  }
1919
2029
  }
2030
+ const cipherTextBlocked = cipherTextResult ? !cipherTextResult.valid || cipherTextResult.risk?.is_blocked === true : false;
2031
+ const blockReasons = [...geoVerification.risk_reasons];
2032
+ if (cipherTextResult) {
2033
+ if (!cipherTextResult.valid) {
2034
+ blockReasons.push("ciphertext_validation_failed");
2035
+ }
2036
+ if (cipherTextResult.risk?.is_blocked) {
2037
+ blockReasons.push(...cipherTextResult.risk.block_reasons || []);
2038
+ }
2039
+ }
2040
+ const gpsBlocked = geoVerification.gps_required && !cipherTextResult;
2041
+ if (gpsBlocked) {
2042
+ blockReasons.push("gps_verification_required");
2043
+ }
1920
2044
  return {
1921
- allowed: geoVerification.is_compliant && !geoVerification.is_blocked,
2045
+ allowed: geoVerification.is_compliant && !geoVerification.is_blocked && !cipherTextBlocked && !gpsBlocked,
1922
2046
  geolocation: geoVerification,
1923
- blockReasons: geoVerification.risk_reasons,
1924
- processingTime: Date.now() - startTime
2047
+ blockReasons: [...new Set(blockReasons)],
2048
+ processingTime: Date.now() - startTime,
2049
+ cipherTextValidation: cipherTextResult
1925
2050
  };
1926
2051
  }
1927
2052
  // ============================================================================
@@ -1950,7 +2075,29 @@ var ComplianceClient = class {
1950
2075
  kyc_status: "pending"
1951
2076
  });
1952
2077
  }
1953
- calculateTransactionRisk(amount, currency, geoVerification, profile) {
2078
+ /**
2079
+ * Execute cipherText validation with graceful degradation.
2080
+ * Returns undefined if cipherText is not provided or validation fails.
2081
+ */
2082
+ async executeCipherTextValidation(cipherText, userId, eventType, ipAddress, customerData, requestOptions) {
2083
+ if (!cipherText) return void 0;
2084
+ try {
2085
+ return await this.geoClient.validateCipherText(
2086
+ cipherText,
2087
+ userId,
2088
+ eventType,
2089
+ ipAddress,
2090
+ customerData,
2091
+ requestOptions
2092
+ );
2093
+ } catch (err) {
2094
+ this.logger.warn("CipherText validation failed, proceeding with IP-only", {
2095
+ error: err instanceof Error ? err.message : "Unknown error"
2096
+ });
2097
+ return void 0;
2098
+ }
2099
+ }
2100
+ calculateTransactionRisk(amount, currency, geoVerification, profile, cipherTextResult) {
1954
2101
  if (!this._currencyRatesCustomized && !this._currencyRatesWarned) {
1955
2102
  this._currencyRatesWarned = true;
1956
2103
  this.logger.warn(
@@ -1983,6 +2130,15 @@ var ComplianceClient = class {
1983
2130
  riskScore += 50;
1984
2131
  factors.push("account_suspended");
1985
2132
  }
2133
+ if (cipherTextResult) {
2134
+ if (cipherTextResult.risk?.location_mismatch) {
2135
+ riskScore += 20;
2136
+ factors.push("gps_ip_location_mismatch");
2137
+ }
2138
+ if (cipherTextResult.risk?.score) {
2139
+ riskScore += cipherTextResult.risk.score * 0.2;
2140
+ }
2141
+ }
1986
2142
  return {
1987
2143
  score: Math.min(riskScore, 100),
1988
2144
  level: this.getRiskLevel(riskScore),
@@ -2008,20 +2164,33 @@ var ComplianceClient = class {
2008
2164
  if (score >= 40) return "medium";
2009
2165
  return "low";
2010
2166
  }
2011
- getBlockReasons(geoVerification, profile) {
2167
+ getBlockReasons(geoVerification, profile, cipherTextResult) {
2012
2168
  const reasons = [];
2013
2169
  if (geoVerification.is_blocked) {
2014
2170
  reasons.push(...geoVerification.risk_reasons);
2015
2171
  }
2016
- if (profile.customer_status === "suspended") {
2017
- reasons.push("account_suspended");
2172
+ if (profile) {
2173
+ if (profile.customer_status === "suspended") {
2174
+ reasons.push("account_suspended");
2175
+ }
2176
+ if (profile.has_sanctions) {
2177
+ reasons.push("sanctions_match");
2178
+ }
2179
+ }
2180
+ if (cipherTextResult) {
2181
+ if (!cipherTextResult.valid) {
2182
+ reasons.push("ciphertext_validation_failed");
2183
+ }
2184
+ if (cipherTextResult.risk?.is_blocked) {
2185
+ reasons.push(...cipherTextResult.risk.block_reasons || []);
2186
+ }
2018
2187
  }
2019
- if (profile.has_sanctions) {
2020
- reasons.push("sanctions_match");
2188
+ if (geoVerification.gps_required && !cipherTextResult) {
2189
+ reasons.push("gps_verification_required");
2021
2190
  }
2022
- return reasons;
2191
+ return [...new Set(reasons)];
2023
2192
  }
2024
- getTransactionBlockReasons(geoVerification, transactionRisk, jurisdictionAllowed) {
2193
+ getTransactionBlockReasons(geoVerification, transactionRisk, jurisdictionAllowed, cipherTextResult) {
2025
2194
  const reasons = [];
2026
2195
  if (!geoVerification.is_compliant) {
2027
2196
  reasons.push("non_compliant_jurisdiction");
@@ -2032,7 +2201,18 @@ var ComplianceClient = class {
2032
2201
  if (!transactionRisk.allowed) {
2033
2202
  reasons.push(...transactionRisk.factors);
2034
2203
  }
2035
- return reasons;
2204
+ if (cipherTextResult) {
2205
+ if (!cipherTextResult.valid) {
2206
+ reasons.push("ciphertext_validation_failed");
2207
+ }
2208
+ if (cipherTextResult.risk?.is_blocked) {
2209
+ reasons.push(...cipherTextResult.risk.block_reasons || []);
2210
+ }
2211
+ }
2212
+ if (geoVerification.gps_required && !cipherTextResult) {
2213
+ reasons.push("gps_verification_required");
2214
+ }
2215
+ return [...new Set(reasons)];
2036
2216
  }
2037
2217
  // ============================================================================
2038
2218
  // Location Request Methods
@@ -2853,235 +3033,93 @@ var TaxClient = class extends BaseClient {
2853
3033
  };
2854
3034
  super(baseConfig);
2855
3035
  }
2856
- // ============================================================================
2857
- // Tax Enable / Disable Configuration
2858
- // ============================================================================
2859
- /**
2860
- * Get the tax enabled/disabled state for the tenant
2861
- *
2862
- * @returns The current tax config (tax_enabled flag)
2863
- *
2864
- * @example
2865
- * ```typescript
2866
- * const config = await client.getTaxConfig();
2867
- * console.log(`Tax enabled: ${config.tax_enabled}`);
2868
- * ```
2869
- */
2870
- async getTaxConfig() {
2871
- const res = await this.request("/api/v1/tax/config");
2872
- return res.tax_config;
3036
+ // ==========================================================================
3037
+ // P1 — Customer Tax Profile (core compliance flow)
3038
+ // ==========================================================================
3039
+ async getCustomerTaxProfileRecord(customerID) {
3040
+ return this.request(
3041
+ `/api/v1/tax/customer-tax-profiles/${customerID}`
3042
+ );
2873
3043
  }
2874
- /**
2875
- * Enable or disable tax compliance features for the tenant
2876
- *
2877
- * @param request - Object with tax_enabled boolean
2878
- * @returns Updated tax config
2879
- *
2880
- * @example
2881
- * ```typescript
2882
- * // Enable tax
2883
- * const config = await client.updateTaxConfig({ tax_enabled: true });
2884
- *
2885
- * // Disable tax
2886
- * const config = await client.updateTaxConfig({ tax_enabled: false });
2887
- * ```
2888
- */
2889
- async updateTaxConfig(request) {
2890
- const res = await this.request("/api/v1/tax/config", {
2891
- method: "PUT",
2892
- body: JSON.stringify({ tax_config: request })
2893
- });
2894
- return res.tax_config;
3044
+ async requestTaxForm(customerID) {
3045
+ return this.request(
3046
+ `/api/v1/tax/customer-tax-profiles/${customerID}/request-form`,
3047
+ { method: "POST" }
3048
+ );
2895
3049
  }
2896
- // ============================================================================
2897
- // Solicitation Trigger Configuration
2898
- // ============================================================================
2899
- /**
2900
- * Get solicitation triggers for the tenant
2901
- *
2902
- * @returns List of solicitation triggers with their enabled state
2903
- *
2904
- * @example
2905
- * ```typescript
2906
- * const triggers = await client.getSolicitationTriggers();
2907
- * triggers.forEach(t => console.log(`${t.label}: ${t.enabled}`));
2908
- * ```
2909
- */
2910
- async getSolicitationTriggers() {
2911
- const res = await this.request(
2912
- "/api/v1/tax/solicitation/config"
3050
+ async checkTINStatus(customerID) {
3051
+ return this.requestWithRetry(
3052
+ `/api/v1/tax/customer-tax-profiles/${customerID}/check-tin`,
3053
+ { method: "POST" }
2913
3054
  );
2914
- return res.solicitation_triggers;
2915
3055
  }
2916
- /**
2917
- * Update solicitation triggers for the tenant
2918
- *
2919
- * @param triggers - Array of triggers with updated enabled/threshold values
2920
- * @returns Updated triggers
2921
- *
2922
- * @example
2923
- * ```typescript
2924
- * const triggers = await client.updateSolicitationTriggers([
2925
- * { type: 'first_withdrawal', enabled: true, label: 'First Withdrawal', description: '...' },
2926
- * { type: 'threshold_based', enabled: true, label: 'Threshold', description: '...', threshold_amount: 600 },
2927
- * ]);
2928
- * ```
2929
- */
2930
- async updateSolicitationTriggers(triggers) {
2931
- const res = await this.request(
2932
- "/api/v1/tax/solicitation/config",
3056
+ async reRequestTaxForm(customerID, input) {
3057
+ return this.request(
3058
+ `/api/v1/tax/customer-tax-profiles/${customerID}/re-request-form`,
2933
3059
  {
2934
- method: "PUT",
2935
- body: JSON.stringify({ solicitation_triggers: triggers })
3060
+ method: "POST",
3061
+ body: JSON.stringify(input)
2936
3062
  }
2937
3063
  );
2938
- return res.solicitation_triggers;
2939
3064
  }
2940
- // ============================================================================
2941
- // Reminder Configuration
2942
- // ============================================================================
2943
- /**
2944
- * Get the reminder configuration for the tenant
2945
- *
2946
- * @returns Reminder config (enabled, max_reminders, frequency_days)
2947
- *
2948
- * @example
2949
- * ```typescript
2950
- * const config = await client.getReminderConfig();
2951
- * console.log(`Reminders enabled: ${config.enabled}, every ${config.frequency_days} days`);
2952
- * ```
2953
- */
2954
- async getReminderConfig() {
2955
- const res = await this.request(
2956
- "/api/v1/tax/solicitation/reminder-config"
2957
- );
2958
- return res.reminder_config;
2959
- }
2960
- /**
2961
- * Update the reminder configuration for the tenant
2962
- *
2963
- * @param config - Reminder configuration to set
2964
- * @returns Updated reminder config
2965
- *
2966
- * @example
2967
- * ```typescript
2968
- * const updated = await client.updateReminderConfig({
2969
- * enabled: true,
2970
- * max_reminders: 3,
2971
- * frequency_days: 7,
2972
- * });
2973
- * ```
2974
- */
2975
- async updateReminderConfig(config) {
2976
- const res = await this.request(
2977
- "/api/v1/tax/solicitation/reminder-config",
3065
+ async enableBackupWithholding(customerID, input) {
3066
+ return this.request(
3067
+ `/api/v1/tax/customer-tax-profiles/${customerID}/enable-withholding`,
2978
3068
  {
2979
- method: "PUT",
2980
- body: JSON.stringify({ reminder_config: config })
3069
+ method: "POST",
3070
+ body: JSON.stringify(input)
2981
3071
  }
2982
3072
  );
2983
- return res.reminder_config;
2984
3073
  }
2985
- // ============================================================================
2986
- // Tax Forms
2987
- // ============================================================================
2988
- /**
2989
- * List tax forms with optional filters and pagination
2990
- *
2991
- * @param filters - Optional filters (customer_id, form_type, form_status, etc.)
2992
- * @returns Paginated list of tax forms
2993
- *
2994
- * @example
2995
- * ```typescript
2996
- * const result = await client.listTaxForms({ form_type: 'W-9', form_status: 'Pending' });
2997
- * console.log(`Found ${result.total} forms`);
2998
- * ```
2999
- */
3000
- async listTaxForms(filters) {
3001
- const params = {};
3002
- if (filters) {
3003
- if (filters.customer_id) params.customer_id = filters.customer_id;
3004
- if (filters.form_type) params.form_type = filters.form_type;
3005
- if (filters.form_status) params.form_status = filters.form_status;
3006
- if (filters.tin_status) params.tin_status = filters.tin_status;
3007
- if (filters.avalara_company_id) params.avalara_company_id = filters.avalara_company_id;
3008
- if (filters.search) params.search = filters.search;
3009
- if (filters.start_date) params.start_date = filters.start_date;
3010
- if (filters.end_date) params.end_date = filters.end_date;
3011
- if (filters.page) params.page = filters.page;
3012
- if (filters.page_size) params.limit = filters.page_size;
3013
- }
3014
- return this.request(`/api/v1/tax/forms${this.buildQueryString(params)}`);
3015
- }
3016
- /**
3017
- * Get a tax form by ID
3018
- *
3019
- * @param formId - Tax form UUID
3020
- * @returns Tax form details
3021
- */
3022
- async getTaxForm(formId) {
3023
- return this.request(`/api/v1/tax/forms/${formId}`);
3024
- }
3025
- /**
3026
- * Get lifecycle events for a tax form
3027
- *
3028
- * @param formId - Tax form UUID
3029
- * @returns List of lifecycle events
3030
- */
3031
- async getTaxFormLifecycleEvents(formId) {
3032
- const res = await this.request(
3033
- `/api/v1/tax/forms/${formId}/lifecycle`
3074
+ async downloadTaxForm(customerID, requestOptions) {
3075
+ return this.request(
3076
+ `/api/v1/tax/customer-tax-profiles/${customerID}/download-form`,
3077
+ { method: "GET" },
3078
+ void 0,
3079
+ { ...requestOptions, responseType: "arraybuffer" }
3034
3080
  );
3035
- return res.lifecycle_events;
3036
3081
  }
3037
- // ============================================================================
3038
- // Customer Tax Profile
3039
- // ============================================================================
3040
- /**
3041
- * Get the full tax profile for a customer (all forms + lifecycle events)
3042
- *
3043
- * @param customerID - Customer ID
3044
- * @returns Customer tax profile with all forms and events
3045
- *
3046
- * @example
3047
- * ```typescript
3048
- * const profile = await client.getCustomerTaxProfile('cust_123');
3049
- * console.log(`Customer has ${profile.tax_forms.length} tax forms`);
3050
- * ```
3051
- */
3052
- async getCustomerTaxProfile(customerID) {
3053
- return this.request(`/api/v1/tax/profile/${customerID}`);
3082
+ // ==========================================================================
3083
+ // P2 — Tenant Tax Rules
3084
+ // ==========================================================================
3085
+ async getTaxRules() {
3086
+ const res = await this.request("/api/v1/tax/rules");
3087
+ return res.rules;
3054
3088
  }
3055
- // ============================================================================
3056
- // Tax Companies
3057
- // ============================================================================
3058
- /**
3059
- * List Avalara tax companies for the tenant
3060
- *
3061
- * @param page - Page number (default: 1)
3062
- * @param pageSize - Items per page (default: 20)
3063
- * @returns Paginated list of tax companies
3064
- */
3065
- async listTaxCompanies(page, pageSize) {
3089
+ async updateTaxRules(input) {
3090
+ const res = await this.request("/api/v1/tax/rules", {
3091
+ method: "PUT",
3092
+ body: JSON.stringify({ rules: input })
3093
+ });
3094
+ return res.version;
3095
+ }
3096
+ async getComplianceStats(filters) {
3066
3097
  const params = {};
3067
- if (page) params.page = page;
3068
- if (pageSize) params.limit = pageSize;
3098
+ if (filters?.time_range) params.time_range = filters.time_range;
3099
+ if (filters?.from_date) params.from_date = filters.from_date;
3100
+ if (filters?.to_date) params.to_date = filters.to_date;
3069
3101
  return this.request(
3070
- `/api/v1/tax/companies${this.buildQueryString(params)}`
3102
+ `/api/v1/tax/tenant/w-form-tenant-stats${this.buildQueryString(params)}`
3071
3103
  );
3072
3104
  }
3073
- /**
3074
- * Get a tax company by ID
3075
- *
3076
- * @param companyId - Tax company UUID
3077
- * @returns Tax company details
3078
- */
3079
- async getTaxCompany(companyId) {
3080
- return this.request(`/api/v1/tax/companies/${companyId}`);
3105
+ // ==========================================================================
3106
+ // P3 Global Tax Rule & Treaty Countries
3107
+ // ==========================================================================
3108
+ async getCurrentGlobalTaxRule() {
3109
+ const res = await this.request(
3110
+ "/api/v1/tm/tenant/global-tax-rules/current"
3111
+ );
3112
+ return res.data;
3113
+ }
3114
+ async listTreatyCountries() {
3115
+ return this.request("/api/v1/tax/treaty-countries");
3116
+ }
3117
+ async getTreatyCountry(code) {
3118
+ const res = await this.request(
3119
+ `/api/v1/tax/treaty-countries/${encodeURIComponent(code)}`
3120
+ );
3121
+ return res.treaty_country;
3081
3122
  }
3082
- // ============================================================================
3083
- // Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)
3084
- // ============================================================================
3085
3123
  };
3086
3124
 
3087
3125
  // src/transaction/client.ts