ts-client-lib 0.0.7
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 +76 -0
- package/auth/TSJWT.d.ts +29 -0
- package/auth/TSJWT.js +44 -0
- package/auth/TSOAuth.d.ts +132 -0
- package/auth/TSOAuth.js +230 -0
- package/devices/TSCordova.d.ts +5 -0
- package/devices/TSCordova.js +52 -0
- package/entities/TSCountries.d.ts +14 -0
- package/entities/TSCountries.js +1188 -0
- package/entities/TSCurrencies.d.ts +35 -0
- package/entities/TSCurrencies.js +604 -0
- package/entities/TSMobilePhones.d.ts +167 -0
- package/entities/TSMobilePhones.js +206 -0
- package/entities/TSMoney.d.ts +149 -0
- package/entities/TSMoney.js +311 -0
- package/entities/currency-amount.d.ts +13 -0
- package/entities/currency-amount.js +43 -0
- package/finance/TSBonus.d.ts +197 -0
- package/finance/TSBonus.js +530 -0
- package/finance/TSKYC.d.ts +563 -0
- package/finance/TSKYC.js +1066 -0
- package/finance/TSTax.d.ts +49 -0
- package/finance/TSTax.js +106 -0
- package/finance/bonus-money.d.ts +41 -0
- package/finance/bonus-money.js +61 -0
- package/games/TSBetSlip.d.ts +72 -0
- package/games/TSBetSlip.js +179 -0
- package/games/TSBetSystem.d.ts +4 -0
- package/games/TSBetSystem.js +48 -0
- package/games/TSLotto.d.ts +35 -0
- package/games/TSLotto.js +205 -0
- package/games/TSPool.d.ts +28 -0
- package/games/TSPool.js +88 -0
- package/package.json +93 -0
- package/utils/TSArray.d.ts +9 -0
- package/utils/TSArray.js +87 -0
- package/utils/TSBoolean.d.ts +4 -0
- package/utils/TSBoolean.js +24 -0
- package/utils/TSCache.d.ts +167 -0
- package/utils/TSCache.js +531 -0
- package/utils/TSDate.d.ts +8 -0
- package/utils/TSDate.js +67 -0
- package/utils/TSHeuristic.d.ts +20 -0
- package/utils/TSHeuristic.js +197 -0
- package/utils/TSLZS.d.ts +42 -0
- package/utils/TSLZS.js +343 -0
- package/utils/TSLog.d.ts +40 -0
- package/utils/TSLog.js +110 -0
- package/utils/TSNumber.d.ts +6 -0
- package/utils/TSNumber.js +68 -0
- package/utils/TSObject.d.ts +29 -0
- package/utils/TSObject.js +312 -0
- package/utils/TSPagination.d.ts +282 -0
- package/utils/TSPagination.js +425 -0
- package/utils/TSPaginationMulti.d.ts +77 -0
- package/utils/TSPaginationMulti.js +356 -0
- package/utils/TSString.d.ts +10 -0
- package/utils/TSString.js +107 -0
- package/utils/TSValidator.d.ts +16 -0
- package/utils/TSValidator.js +74 -0
- package/utils/TSWorker.d.ts +3 -0
- package/utils/TSWorker.js +32 -0
- package/utils/diacritics-removal-map.d.ts +5 -0
- package/utils/diacritics-removal-map.js +341 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KYCEligibility - Client-Safe KYC Validation & Eligibility Checker
|
|
3
|
+
*
|
|
4
|
+
* A static class for checking KYC eligibility, limits, and requirements on client-side.
|
|
5
|
+
* No database dependencies - pure functions only.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { KYCEligibility } from 'ts-client-lib/finance/TSKyc';
|
|
10
|
+
*
|
|
11
|
+
* // Check if user can make a transaction
|
|
12
|
+
* const result = KYCEligibility.checkTransaction(limits, {
|
|
13
|
+
* currentTier: 'basic',
|
|
14
|
+
* transactionType: 'withdrawal',
|
|
15
|
+
* amount: 5000,
|
|
16
|
+
* currency: 'EUR',
|
|
17
|
+
* usedToday: 1000,
|
|
18
|
+
* usedThisMonth: 10000,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* if (!result.allowed) {
|
|
22
|
+
* console.log(result.reason);
|
|
23
|
+
* console.log(`Remaining: ${result.remaining}`);
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // Get requirements for next tier
|
|
27
|
+
* const requirements = KYCEligibility.getTierRequirements('enhanced');
|
|
28
|
+
*
|
|
29
|
+
* // Check if user can access a feature
|
|
30
|
+
* const canWithdraw = KYCEligibility.canPerformAction('withdrawal', 'basic', 'standard');
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const KYC_VALIDATOR_ERRORS: {
|
|
34
|
+
readonly UnknownKYCTier: "MSKYCUnknownKYCTier";
|
|
35
|
+
readonly FileTooLarge: "MSKYCFileTooLarge";
|
|
36
|
+
readonly FileTypeNotAllowed: "MSKYCFileTypeNotAllowed";
|
|
37
|
+
readonly FileExtensionNotAllowed: "MSKYCFileExtensionNotAllowed";
|
|
38
|
+
/** KYC status is not approved or in-review (e.g. rejected/suspended/expired). */
|
|
39
|
+
readonly KycStatusNotAllowed: "MSKYCStatusNotAllowed";
|
|
40
|
+
/** Stored `expiresAt` is past. Distinct from `KycStatusNotAllowed` so UIs can prompt re-verification. */
|
|
41
|
+
readonly KycExpired: "MSKYCExpired";
|
|
42
|
+
/** Account flagged suspended at the operator/auth layer. */
|
|
43
|
+
readonly AccountSuspended: "MSKYCAccountSuspended";
|
|
44
|
+
/** Self-exclusion window is active. */
|
|
45
|
+
readonly SelfExcluded: "MSKYCSelfExcluded";
|
|
46
|
+
/** Wallet status is not 'active' (suspended/closed). */
|
|
47
|
+
readonly WalletNotActive: "MSKYCWalletNotActive";
|
|
48
|
+
/** Wallet balance < amount on an outflow operation. */
|
|
49
|
+
readonly InsufficientBalance: "MSKYCInsufficientBalance";
|
|
50
|
+
/** Operation type has no limit profile at this tier (e.g. transfer at tier 'none'). */
|
|
51
|
+
readonly TierNotPermitted: "MSKYCTierNotPermitted";
|
|
52
|
+
/** Amount below the per-transaction min. */
|
|
53
|
+
readonly AmountBelowMin: "MSKYCAmountBelowMin";
|
|
54
|
+
/** Amount above the per-transaction max (upgrade may help). */
|
|
55
|
+
readonly AmountAboveMax: "MSKYCAmountAboveMax";
|
|
56
|
+
/** Daily aggregate cap would be exceeded. */
|
|
57
|
+
readonly DailyLimitExceeded: "MSKYCDailyLimitExceeded";
|
|
58
|
+
/** Weekly aggregate cap would be exceeded. */
|
|
59
|
+
readonly WeeklyLimitExceeded: "MSKYCWeeklyLimitExceeded";
|
|
60
|
+
/** Monthly aggregate cap would be exceeded. */
|
|
61
|
+
readonly MonthlyLimitExceeded: "MSKYCMonthlyLimitExceeded";
|
|
62
|
+
/** Per-period transaction-count cap reached. */
|
|
63
|
+
readonly TransactionCountExceeded: "MSKYCTransactionCountExceeded";
|
|
64
|
+
/** Deposit would push wallet balance above the tier's max-balance ceiling. */
|
|
65
|
+
readonly MaxBalanceExceeded: "MSKYCMaxBalanceExceeded";
|
|
66
|
+
};
|
|
67
|
+
export declare const KYC_VALIDATOR_ERROR_CODES: readonly string[];
|
|
68
|
+
export type KYCValidatorErrorCode = (typeof KYC_VALIDATOR_ERRORS)[keyof typeof KYC_VALIDATOR_ERRORS];
|
|
69
|
+
/**
|
|
70
|
+
* KYC verification tiers - ordered from lowest to highest
|
|
71
|
+
*/
|
|
72
|
+
export type KYCTier = 'none' | 'basic' | 'standard' | 'enhanced' | 'full' | 'professional';
|
|
73
|
+
/**
|
|
74
|
+
* KYC verification status
|
|
75
|
+
*/
|
|
76
|
+
export type KYCStatus = 'pending' | 'in_review' | 'approved' | 'rejected' | 'expired' | 'suspended' | 'manual_review';
|
|
77
|
+
/**
|
|
78
|
+
* Risk assessment levels
|
|
79
|
+
*/
|
|
80
|
+
export type KYCRiskLevel = 'low' | 'medium' | 'high' | 'critical';
|
|
81
|
+
/**
|
|
82
|
+
* Document types for verification (platform-neutral: same union in Node services and browser clients).
|
|
83
|
+
* Add new literals here when kyc-service / atkyc / app agree on a shared label — then publish ts-client-lib.
|
|
84
|
+
*/
|
|
85
|
+
export type KYCDocumentType = 'passport' | 'national_id' | 'drivers_license' | 'residence_permit' | 'visa' | 'utility_bill' | 'bank_statement' | 'tax_document' | 'government_letter' | 'rental_agreement' | 'proof_of_income' | 'employment_letter' | 'tax_return' | 'investment_statement' | 'crypto_wallet_proof' | 'company_registration' | 'articles_of_incorporation' | 'shareholder_register' | 'board_resolution' | 'annual_report' | 'beneficial_owner_declaration' | 'selfie' | 'liveness_video' | 'other';
|
|
86
|
+
/**
|
|
87
|
+
* Document categories
|
|
88
|
+
*/
|
|
89
|
+
export type KYCDocumentCategory = 'identity' | 'address' | 'financial' | 'corporate' | 'biometric';
|
|
90
|
+
/**
|
|
91
|
+
* Canonical KYC transaction types — only four, mapped 1:1 to tier-limit profiles.
|
|
92
|
+
*
|
|
93
|
+
* `deposit` — money in (from external rail to user wallet)
|
|
94
|
+
* `withdrawal` — money out (from user wallet to external rail)
|
|
95
|
+
* `transfer` — peer-to-peer / internal value movement
|
|
96
|
+
* `order` — ANY product debit routed through the `wallet.order` event envelope:
|
|
97
|
+
* sports bets, casino spins, lotto tickets, jackpot draws, oscommerce
|
|
98
|
+
* purchases — anything that consumes wallet balance against an order.
|
|
99
|
+
*
|
|
100
|
+
* Product-specific terminology (`'bet'`, `'purchase'`, `'trade'`) is intentionally
|
|
101
|
+
* absent: adding a new product type should NOT require a code/enum/list change.
|
|
102
|
+
* Operators define per-category overrides at the operator config layer (string-keyed
|
|
103
|
+
* `byCategory` record), feeding `event.data.category` into the lookup. Redis aggregate
|
|
104
|
+
* keys accept any string so usage tracking scales the same way without code changes.
|
|
105
|
+
*
|
|
106
|
+
* `order` reuses the `deposit` limit profile by default (see `canonicalLimitKey`).
|
|
107
|
+
* Operators wanting tighter or looser wager limits configure them as a per-category
|
|
108
|
+
* override on the operator side — the lib stays generic.
|
|
109
|
+
*/
|
|
110
|
+
export type KYCTransactionType = 'deposit' | 'withdrawal' | 'transfer' | 'order';
|
|
111
|
+
/**
|
|
112
|
+
* Map operation type → tier-limit profile key. `KYCTierLimits` stores three profiles
|
|
113
|
+
* (deposit / withdrawal / transfer); `order` reuses `deposit`. Anything else is invalid
|
|
114
|
+
* at the type level so this is exhaustive.
|
|
115
|
+
*
|
|
116
|
+
* **PXE-7** — `tierLimits[X]` MUST go through this helper. Raw `tierLimits[type]` returns
|
|
117
|
+
* undefined for `'order'` and silently bypasses tier-limit enforcement.
|
|
118
|
+
* See graphify/pre-execution/cross-product-admission-canonical.md.
|
|
119
|
+
*/
|
|
120
|
+
export declare function canonicalLimitKey(t: KYCTransactionType): 'deposit' | 'withdrawal' | 'transfer';
|
|
121
|
+
/**
|
|
122
|
+
* Limits for a specific operation type
|
|
123
|
+
*/
|
|
124
|
+
export interface KYCOperationLimits {
|
|
125
|
+
minAmount?: number;
|
|
126
|
+
maxAmount: number;
|
|
127
|
+
dailyLimit: number;
|
|
128
|
+
weeklyLimit?: number;
|
|
129
|
+
monthlyLimit: number;
|
|
130
|
+
yearlyLimit?: number;
|
|
131
|
+
maxDailyTransactions?: number;
|
|
132
|
+
maxMonthlyTransactions?: number;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Transaction limits for a tier
|
|
136
|
+
*/
|
|
137
|
+
export interface KYCTierLimits {
|
|
138
|
+
currency: string;
|
|
139
|
+
deposit: KYCOperationLimits;
|
|
140
|
+
withdrawal: KYCOperationLimits;
|
|
141
|
+
transfer?: KYCOperationLimits;
|
|
142
|
+
maxBalance?: number;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Document requirement
|
|
146
|
+
*/
|
|
147
|
+
export interface KYCDocumentRequirement {
|
|
148
|
+
id: string;
|
|
149
|
+
name: string;
|
|
150
|
+
description?: string;
|
|
151
|
+
category: KYCDocumentCategory;
|
|
152
|
+
acceptedTypes: KYCDocumentType[];
|
|
153
|
+
required: boolean;
|
|
154
|
+
minCount?: number;
|
|
155
|
+
maxAgeDays?: number;
|
|
156
|
+
mustNotBeExpired?: boolean;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check requirement (AML, PEP, etc.)
|
|
160
|
+
*/
|
|
161
|
+
export interface KYCCheckRequirement {
|
|
162
|
+
id: string;
|
|
163
|
+
name: string;
|
|
164
|
+
type: 'aml' | 'pep' | 'sanctions' | 'liveness' | 'face_match' | 'address_verification';
|
|
165
|
+
required: boolean;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Information field requirement
|
|
169
|
+
*/
|
|
170
|
+
export interface KYCInfoRequirement {
|
|
171
|
+
id: string;
|
|
172
|
+
fieldPath: string;
|
|
173
|
+
displayName: string;
|
|
174
|
+
required: boolean;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Complete tier requirements
|
|
178
|
+
*/
|
|
179
|
+
export interface KYCTierRequirements {
|
|
180
|
+
tier: KYCTier;
|
|
181
|
+
displayName: string;
|
|
182
|
+
description: string;
|
|
183
|
+
documents: KYCDocumentRequirement[];
|
|
184
|
+
checks: KYCCheckRequirement[];
|
|
185
|
+
information: KYCInfoRequirement[];
|
|
186
|
+
prerequisiteTier?: KYCTier;
|
|
187
|
+
minimumAge?: number;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Context for transaction checking
|
|
191
|
+
*/
|
|
192
|
+
export interface KYCTransactionContext {
|
|
193
|
+
currentTier: KYCTier;
|
|
194
|
+
kycStatus?: KYCStatus;
|
|
195
|
+
transactionType: KYCTransactionType;
|
|
196
|
+
amount: number;
|
|
197
|
+
currency: string;
|
|
198
|
+
usedToday?: number;
|
|
199
|
+
usedThisWeek?: number;
|
|
200
|
+
usedThisMonth?: number;
|
|
201
|
+
usedThisYear?: number;
|
|
202
|
+
transactionsToday?: number;
|
|
203
|
+
transactionsThisMonth?: number;
|
|
204
|
+
currentBalance?: number;
|
|
205
|
+
country?: string;
|
|
206
|
+
userAge?: number;
|
|
207
|
+
accountAgeDays?: number;
|
|
208
|
+
documentsExpireAt?: Date;
|
|
209
|
+
currentDate?: Date;
|
|
210
|
+
/**
|
|
211
|
+
* When set (e.g. jurisdiction from DB + defaults), used to resolve `requiredTier` when a
|
|
212
|
+
* single transaction exceeds `maxAmount` — same tier ladder as server config, not only lib defaults.
|
|
213
|
+
*/
|
|
214
|
+
jurisdictionLimits?: Record<KYCTier, KYCTierLimits>;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Context for general KYC eligibility checking
|
|
218
|
+
*/
|
|
219
|
+
export interface KYCEligibilityContext {
|
|
220
|
+
userId?: string;
|
|
221
|
+
tenantId?: string;
|
|
222
|
+
currentTier: KYCTier;
|
|
223
|
+
kycStatus: KYCStatus;
|
|
224
|
+
country: string;
|
|
225
|
+
riskLevel?: KYCRiskLevel;
|
|
226
|
+
riskScore?: number;
|
|
227
|
+
hasIdentityDoc?: boolean;
|
|
228
|
+
hasAddressDoc?: boolean;
|
|
229
|
+
hasFinancialDoc?: boolean;
|
|
230
|
+
documentsExpireAt?: Date;
|
|
231
|
+
amlCheckPassed?: boolean;
|
|
232
|
+
pepCheckPassed?: boolean;
|
|
233
|
+
sanctionsCheckPassed?: boolean;
|
|
234
|
+
livenessCheckPassed?: boolean;
|
|
235
|
+
userAge?: number;
|
|
236
|
+
accountAgeDays?: number;
|
|
237
|
+
isPEP?: boolean;
|
|
238
|
+
currentDate?: Date;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Transaction check result
|
|
242
|
+
*/
|
|
243
|
+
export interface KYCTransactionResult {
|
|
244
|
+
allowed: boolean;
|
|
245
|
+
reason?: string;
|
|
246
|
+
/** Stable error code for i18n when result is sent to client */
|
|
247
|
+
code?: string;
|
|
248
|
+
/** Extra context for i18n interpolation */
|
|
249
|
+
details?: Record<string, unknown>;
|
|
250
|
+
remaining?: number;
|
|
251
|
+
dailyRemaining?: number;
|
|
252
|
+
monthlyRemaining?: number;
|
|
253
|
+
maxAllowed?: number;
|
|
254
|
+
requiredTier?: KYCTier;
|
|
255
|
+
upgradeMessage?: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Tier eligibility result
|
|
259
|
+
*/
|
|
260
|
+
export interface KYCTierEligibilityResult {
|
|
261
|
+
currentTier: KYCTier;
|
|
262
|
+
targetTier: KYCTier;
|
|
263
|
+
eligible: boolean;
|
|
264
|
+
missingRequirements: string[];
|
|
265
|
+
completedRequirements: string[];
|
|
266
|
+
progress: number;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Action eligibility result
|
|
270
|
+
*/
|
|
271
|
+
export interface KYCActionResult {
|
|
272
|
+
allowed: boolean;
|
|
273
|
+
reason?: string;
|
|
274
|
+
requiredTier?: KYCTier;
|
|
275
|
+
requiredStatus?: KYCStatus;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Jurisdiction rules for validation
|
|
279
|
+
*/
|
|
280
|
+
export interface KYCJurisdictionRules {
|
|
281
|
+
code: string;
|
|
282
|
+
name: string;
|
|
283
|
+
minimumAge: number;
|
|
284
|
+
blockedCountries: string[];
|
|
285
|
+
highRiskCountries: string[];
|
|
286
|
+
restrictedNationalities?: string[];
|
|
287
|
+
requiresLocalResidence?: boolean;
|
|
288
|
+
selfExclusionRequired?: boolean;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Wallet-side input to `prevalidate`. All fields optional; the lib only enforces what's
|
|
292
|
+
* supplied. The client app already has these from the wallet API; servers populate them
|
|
293
|
+
* from their authoritative state. Same shape on both sides.
|
|
294
|
+
*/
|
|
295
|
+
export interface KYCWalletInput {
|
|
296
|
+
/** 'active' | 'suspended' | 'closed' — only 'active' lets transactions proceed. */
|
|
297
|
+
status?: 'active' | 'suspended' | 'closed';
|
|
298
|
+
/**
|
|
299
|
+
* Wallet balance in the currency being transacted. Consulted ONLY for outflow
|
|
300
|
+
* operations (`withdrawal`, `transfer`, `order`) — deposits don't need a balance check.
|
|
301
|
+
*/
|
|
302
|
+
balance?: number;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Account-side input. The auth/identity API surfaces these.
|
|
306
|
+
*/
|
|
307
|
+
export interface KYCAccountInput {
|
|
308
|
+
/** True if the account is administratively suspended (auth layer). */
|
|
309
|
+
suspended?: boolean;
|
|
310
|
+
/**
|
|
311
|
+
* Self-exclusion window. ISO string or Date. If `> now`, transaction is blocked
|
|
312
|
+
* with `SelfExcluded`. Responsible-gambling regulators require this gate on
|
|
313
|
+
* deposits AND wagers; we enforce it generically.
|
|
314
|
+
*/
|
|
315
|
+
selfExcludedUntil?: string | Date | null;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Bulletproof pre-validation input — single object the caller passes containing
|
|
319
|
+
* everything the lib needs to reach the same verdict the server reaches. Pure: no
|
|
320
|
+
* Redis, no HTTP, no DB. Caller supplies data; lib decides.
|
|
321
|
+
*
|
|
322
|
+
* Client usage: disable submit buttons before the user taps, surface inline
|
|
323
|
+
* messages, suggest upgrades. Server usage: same call in pre-transaction middleware
|
|
324
|
+
* or in the wallet.order handler — defence-in-depth using one rule engine.
|
|
325
|
+
*/
|
|
326
|
+
export interface KYCPrevalidationInput {
|
|
327
|
+
currentTier: KYCTier;
|
|
328
|
+
kycStatus: KYCStatus;
|
|
329
|
+
/** ISO string or Date. If past, treated as `KycExpired` even when status is approved. */
|
|
330
|
+
expiresAt?: string | Date | null;
|
|
331
|
+
/**
|
|
332
|
+
* Per-jurisdiction tier ladder (operator config). When provided, the lib walks
|
|
333
|
+
* the ladder to suggest the right `upgradeToTier`; when omitted, the lib uses
|
|
334
|
+
* its built-in defaults.
|
|
335
|
+
*/
|
|
336
|
+
jurisdictionLimits?: Record<KYCTier, KYCTierLimits>;
|
|
337
|
+
operation: KYCTransactionType;
|
|
338
|
+
amount: number;
|
|
339
|
+
currency: string;
|
|
340
|
+
usedToday?: number;
|
|
341
|
+
usedThisWeek?: number;
|
|
342
|
+
usedThisMonth?: number;
|
|
343
|
+
transactionsToday?: number;
|
|
344
|
+
transactionsThisMonth?: number;
|
|
345
|
+
wallet?: KYCWalletInput;
|
|
346
|
+
account?: KYCAccountInput;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Single-shape result the client renders into UI hints and the server returns
|
|
350
|
+
* to the gateway as a structured rejection. `code` is bounded (`KYC_VALIDATOR_ERRORS`)
|
|
351
|
+
* for stable i18n.
|
|
352
|
+
*/
|
|
353
|
+
export interface KYCPrevalidationResult {
|
|
354
|
+
allowed: boolean;
|
|
355
|
+
/** Bounded code from `KYC_VALIDATOR_ERRORS`. Stable across client + server. */
|
|
356
|
+
code?: KYCValidatorErrorCode;
|
|
357
|
+
reason?: string;
|
|
358
|
+
/** Structured details for i18n interpolation (limit values, remaining, etc.). */
|
|
359
|
+
details?: Record<string, unknown>;
|
|
360
|
+
/** Largest amount the user could submit right now (this operation, this currency). */
|
|
361
|
+
maxAllowed?: number;
|
|
362
|
+
/** Remaining daily budget after this transaction (if allowed). */
|
|
363
|
+
dailyRemaining?: number;
|
|
364
|
+
/** Remaining monthly budget after this transaction (if allowed). */
|
|
365
|
+
monthlyRemaining?: number;
|
|
366
|
+
upgradeToTier?: KYCTier;
|
|
367
|
+
upgradeMessage?: string;
|
|
368
|
+
}
|
|
369
|
+
export declare class KYCEligibility {
|
|
370
|
+
/**
|
|
371
|
+
* Get numeric level for a tier (for comparisons)
|
|
372
|
+
*/
|
|
373
|
+
static getTierLevel(tier: KYCTier): number;
|
|
374
|
+
/**
|
|
375
|
+
* Compare two tiers. Returns negative if a < b, 0 if equal, positive if a > b
|
|
376
|
+
*/
|
|
377
|
+
static compareTiers(a: KYCTier, b: KYCTier): number;
|
|
378
|
+
/**
|
|
379
|
+
* Check if tier meets minimum requirement
|
|
380
|
+
*/
|
|
381
|
+
static tierMeetsRequirement(currentTier: KYCTier, requiredTier: KYCTier): boolean;
|
|
382
|
+
/**
|
|
383
|
+
* Get display name for a tier
|
|
384
|
+
*/
|
|
385
|
+
static getTierDisplayName(tier: KYCTier): string;
|
|
386
|
+
/**
|
|
387
|
+
* Get description for a tier
|
|
388
|
+
*/
|
|
389
|
+
static getTierDescription(tier: KYCTier): string;
|
|
390
|
+
/**
|
|
391
|
+
* Get next tier in the hierarchy
|
|
392
|
+
*/
|
|
393
|
+
static getNextTier(currentTier: KYCTier): KYCTier | null;
|
|
394
|
+
/**
|
|
395
|
+
* Get all tiers in order
|
|
396
|
+
*/
|
|
397
|
+
static getAllTiers(): KYCTier[];
|
|
398
|
+
/**
|
|
399
|
+
* Get requirements for a tier
|
|
400
|
+
*/
|
|
401
|
+
static getTierRequirements(tier: KYCTier): KYCTierRequirements;
|
|
402
|
+
/**
|
|
403
|
+
* Get all requirements needed to reach a tier from current tier
|
|
404
|
+
*/
|
|
405
|
+
static getRequirementsToReachTier(currentTier: KYCTier, targetTier: KYCTier): KYCTierRequirements[];
|
|
406
|
+
/**
|
|
407
|
+
* Check eligibility for a target tier
|
|
408
|
+
*/
|
|
409
|
+
static checkTierEligibility(targetTier: KYCTier, context: KYCEligibilityContext): KYCTierEligibilityResult;
|
|
410
|
+
private static collectTierPrerequisite;
|
|
411
|
+
private static collectTierDocuments;
|
|
412
|
+
private static collectTierVerificationChecks;
|
|
413
|
+
private static collectTierMinimumAge;
|
|
414
|
+
/**
|
|
415
|
+
* Run the full admission gate against a single input. Pure — no I/O. Same function
|
|
416
|
+
* intended to run on the client (before submit) and on the server (in pre-transaction
|
|
417
|
+
* middleware or the wallet.order handler) for defence-in-depth.
|
|
418
|
+
*
|
|
419
|
+
* Order of checks (first failure wins; same order on client and server):
|
|
420
|
+
*
|
|
421
|
+
* 1. **Account preconditions** — suspended? self-excluded?
|
|
422
|
+
* 2. **Wallet preconditions** — status === 'active'?
|
|
423
|
+
* 3. **KYC snapshot** — status approved/in_review? expiresAt > now?
|
|
424
|
+
* 4. **Balance** (outflows only) — wallet.balance >= amount?
|
|
425
|
+
* 5. **Tier limits** — delegates to `checkTransaction` (min/max per-tx, daily/monthly
|
|
426
|
+
* aggregate, transaction count, max-balance ceiling). Bounded `code` flows through.
|
|
427
|
+
*
|
|
428
|
+
* The client app supplies `wallet`, `account`, usage, and KYC snapshot from API
|
|
429
|
+
* responses it already has; the server supplies the same fields from its source of
|
|
430
|
+
* truth. Both sides produce identical results.
|
|
431
|
+
*
|
|
432
|
+
* Why this exists alongside `checkTransaction`: that method only handles tier-limit
|
|
433
|
+
* math and assumes a valid KYC snapshot. `prevalidate` is the high-level umbrella —
|
|
434
|
+
* checks account / wallet / status / expiry first, then delegates limits. UI code
|
|
435
|
+
* should always call `prevalidate`, never `checkTransaction` directly.
|
|
436
|
+
*/
|
|
437
|
+
static prevalidate(input: KYCPrevalidationInput): KYCPrevalidationResult;
|
|
438
|
+
private static preRejectAccount;
|
|
439
|
+
private static preRejectWalletStatus;
|
|
440
|
+
private static preRejectKyc;
|
|
441
|
+
private static preRejectInsufficientBalance;
|
|
442
|
+
/**
|
|
443
|
+
* Get limits for a tier
|
|
444
|
+
*/
|
|
445
|
+
static getTierLimits(tier: KYCTier, customLimits?: Record<KYCTier, KYCTierLimits>): KYCTierLimits;
|
|
446
|
+
/**
|
|
447
|
+
* Check if a transaction is allowed
|
|
448
|
+
*/
|
|
449
|
+
static checkTransaction(limits: KYCTierLimits | Record<KYCTier, KYCTierLimits>, context: KYCTransactionContext): KYCTransactionResult;
|
|
450
|
+
private static resolveTransactionTierLimits;
|
|
451
|
+
private static txRejectInvalidKycStatus;
|
|
452
|
+
private static resolveTransactionOpLimits;
|
|
453
|
+
private static txRejectBelowMinAmount;
|
|
454
|
+
private static txRejectAboveMaxPerTransaction;
|
|
455
|
+
private static txRejectExceedsDailyBudget;
|
|
456
|
+
private static txRejectExceedsMonthlyBudget;
|
|
457
|
+
private static txRejectExceedsWeeklyBudget;
|
|
458
|
+
private static txRejectDailyTransactionCount;
|
|
459
|
+
private static txRejectDepositOverMaxBalance;
|
|
460
|
+
private static txBuildAllowedResult;
|
|
461
|
+
/**
|
|
462
|
+
* Get remaining limits for a user
|
|
463
|
+
*/
|
|
464
|
+
static getRemainingLimits(tier: KYCTier, transactionType: KYCTransactionType, usage: {
|
|
465
|
+
daily?: number;
|
|
466
|
+
weekly?: number;
|
|
467
|
+
monthly?: number;
|
|
468
|
+
}, customLimits?: Record<KYCTier, KYCTierLimits>): {
|
|
469
|
+
daily: number;
|
|
470
|
+
weekly?: number;
|
|
471
|
+
monthly: number;
|
|
472
|
+
perTransaction: number;
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Find the minimum tier that allows a specific amount
|
|
476
|
+
*/
|
|
477
|
+
static findTierForAmount(amount: number, transactionType: KYCTransactionType, customLimits?: Record<KYCTier, KYCTierLimits>): KYCTier | null;
|
|
478
|
+
/**
|
|
479
|
+
* Check if user can perform an action based on their tier
|
|
480
|
+
*/
|
|
481
|
+
static canPerformAction(action: string, currentTier: KYCTier, customActionTiers?: Record<string, KYCTier>): KYCActionResult;
|
|
482
|
+
/**
|
|
483
|
+
* Get all actions a tier can perform
|
|
484
|
+
*/
|
|
485
|
+
static getAvailableActions(tier: KYCTier, customActionTiers?: Record<string, KYCTier>): string[];
|
|
486
|
+
/**
|
|
487
|
+
* Get actions that require upgrade
|
|
488
|
+
*/
|
|
489
|
+
static getLockedActions(tier: KYCTier, customActionTiers?: Record<string, KYCTier>): Array<{
|
|
490
|
+
action: string;
|
|
491
|
+
requiredTier: KYCTier;
|
|
492
|
+
}>;
|
|
493
|
+
/**
|
|
494
|
+
* Check if a country is blocked
|
|
495
|
+
*/
|
|
496
|
+
static isCountryBlocked(country: string, rules: KYCJurisdictionRules): boolean;
|
|
497
|
+
/**
|
|
498
|
+
* Check if a country is high risk
|
|
499
|
+
*/
|
|
500
|
+
static isCountryHighRisk(country: string, rules: KYCJurisdictionRules): boolean;
|
|
501
|
+
/**
|
|
502
|
+
* Check age eligibility for a jurisdiction
|
|
503
|
+
*/
|
|
504
|
+
static checkAgeEligibility(userAge: number, rules: KYCJurisdictionRules): {
|
|
505
|
+
eligible: boolean;
|
|
506
|
+
reason?: string;
|
|
507
|
+
};
|
|
508
|
+
/**
|
|
509
|
+
* Check nationality eligibility
|
|
510
|
+
*/
|
|
511
|
+
static checkNationalityEligibility(nationality: string, rules: KYCJurisdictionRules): {
|
|
512
|
+
eligible: boolean;
|
|
513
|
+
reason?: string;
|
|
514
|
+
};
|
|
515
|
+
/**
|
|
516
|
+
* Check if a document is expired
|
|
517
|
+
*/
|
|
518
|
+
static isDocumentExpired(expiryDate: Date, currentDate?: Date): boolean;
|
|
519
|
+
/**
|
|
520
|
+
* Check if a document is too old (e.g., utility bill older than 3 months)
|
|
521
|
+
*/
|
|
522
|
+
static isDocumentTooOld(issuedDate: Date, maxAgeDays: number, currentDate?: Date): boolean;
|
|
523
|
+
/**
|
|
524
|
+
* Validate document file (client-side pre-validation)
|
|
525
|
+
*/
|
|
526
|
+
static validateDocumentFile(file: {
|
|
527
|
+
name: string;
|
|
528
|
+
size: number;
|
|
529
|
+
type: string;
|
|
530
|
+
}, options?: {
|
|
531
|
+
maxSizeMB?: number;
|
|
532
|
+
allowedTypes?: string[];
|
|
533
|
+
allowedExtensions?: string[];
|
|
534
|
+
}): {
|
|
535
|
+
valid: boolean;
|
|
536
|
+
reason?: string;
|
|
537
|
+
code?: string;
|
|
538
|
+
details?: Record<string, unknown>;
|
|
539
|
+
};
|
|
540
|
+
/**
|
|
541
|
+
* Calculate risk level from score
|
|
542
|
+
*/
|
|
543
|
+
static getRiskLevelFromScore(score: number, thresholds?: {
|
|
544
|
+
low: number;
|
|
545
|
+
medium: number;
|
|
546
|
+
high: number;
|
|
547
|
+
}): KYCRiskLevel;
|
|
548
|
+
/**
|
|
549
|
+
* Check if enhanced due diligence is required
|
|
550
|
+
*/
|
|
551
|
+
static requiresEnhancedDueDiligence(context: KYCEligibilityContext): boolean;
|
|
552
|
+
}
|
|
553
|
+
export declare const checkKYCTransaction: typeof KYCEligibility.checkTransaction;
|
|
554
|
+
export declare const getTierRequirements: typeof KYCEligibility.getTierRequirements;
|
|
555
|
+
export declare const checkTierEligibility: typeof KYCEligibility.checkTierEligibility;
|
|
556
|
+
export declare const canPerformAction: typeof KYCEligibility.canPerformAction;
|
|
557
|
+
export declare const tierMeetsRequirement: typeof KYCEligibility.tierMeetsRequirement;
|
|
558
|
+
export declare const getRemainingLimits: typeof KYCEligibility.getRemainingLimits;
|
|
559
|
+
/**
|
|
560
|
+
* Top-level pre-validation helper — see {@link KYCEligibility.prevalidate}.
|
|
561
|
+
* Bulletproof client + server admission control. Pure function; no I/O.
|
|
562
|
+
*/
|
|
563
|
+
export declare const prevalidateKYCTransaction: typeof KYCEligibility.prevalidate;
|