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