@vesant-sdk/fraud 0.1.1-dev.0d9ee60 → 0.1.1-dev.7d59b3e
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 +196 -14
- package/dist/index.d.mts +123 -11
- package/dist/index.d.ts +123 -11
- package/dist/index.js +197 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +193 -33
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -122,7 +122,60 @@ var TransactionStatus = {
|
|
|
122
122
|
Pending: "$pending"
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
+
// src/types/rule-signals.ts
|
|
126
|
+
var LOGIN_RULE_SIGNAL_KEYS = ["ip_country_mismatch"];
|
|
127
|
+
var UPDATE_ACCOUNT_RULE_SIGNAL_KEYS = [
|
|
128
|
+
"two_fa_enabled",
|
|
129
|
+
"two_fa_disabled",
|
|
130
|
+
"two_fa_method_changed"
|
|
131
|
+
];
|
|
132
|
+
var TRANSACTION_RULE_SIGNAL_KEYS = [
|
|
133
|
+
"payment_method",
|
|
134
|
+
"is_first_deposit",
|
|
135
|
+
"cumulative_deposit_amount",
|
|
136
|
+
"deposit_count",
|
|
137
|
+
"failed_deposit_count",
|
|
138
|
+
"is_first_withdrawal",
|
|
139
|
+
"withdrawal_method_differs",
|
|
140
|
+
"cumulative_withdrawal_amount",
|
|
141
|
+
"withdrawal_count",
|
|
142
|
+
"hours_since_last_deposit",
|
|
143
|
+
"days_since_last_activity",
|
|
144
|
+
"hours_since_account_creation"
|
|
145
|
+
];
|
|
146
|
+
|
|
147
|
+
// src/normalization/sift-keys.ts
|
|
148
|
+
function siftKey(key) {
|
|
149
|
+
return key.startsWith("$") ? key : `$${key}`;
|
|
150
|
+
}
|
|
151
|
+
function toSiftKeyedObject(value) {
|
|
152
|
+
if (value === null || value === void 0) {
|
|
153
|
+
return value;
|
|
154
|
+
}
|
|
155
|
+
if (Array.isArray(value)) {
|
|
156
|
+
return value.map((item) => toSiftKeyedObject(item));
|
|
157
|
+
}
|
|
158
|
+
if (typeof value === "object") {
|
|
159
|
+
const out = {};
|
|
160
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
161
|
+
out[siftKey(key)] = toSiftKeyedObject(nested);
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
return value;
|
|
166
|
+
}
|
|
167
|
+
|
|
125
168
|
// src/normalization/normalize.ts
|
|
169
|
+
var BASE_SIFT_FIELD_KEYS = [
|
|
170
|
+
"session_id",
|
|
171
|
+
"user_email",
|
|
172
|
+
"name",
|
|
173
|
+
"phone",
|
|
174
|
+
"sift_payment_method",
|
|
175
|
+
"payment_methods",
|
|
176
|
+
"billing_address",
|
|
177
|
+
"app"
|
|
178
|
+
];
|
|
126
179
|
function mergeMetadata(base, extras) {
|
|
127
180
|
return { ...base, ...extras };
|
|
128
181
|
}
|
|
@@ -145,17 +198,82 @@ function applySiftMetadata(body, metadata, siftMetadata, onlyWhenNonEmpty = fals
|
|
|
145
198
|
}
|
|
146
199
|
return body;
|
|
147
200
|
}
|
|
201
|
+
function collectRuleSignals(request, keys) {
|
|
202
|
+
const signals = {};
|
|
203
|
+
for (const key of keys) {
|
|
204
|
+
const value = request[key];
|
|
205
|
+
if (value !== void 0) {
|
|
206
|
+
signals[key] = value;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return signals;
|
|
210
|
+
}
|
|
211
|
+
function buildBaseSiftMetadata(body) {
|
|
212
|
+
const {
|
|
213
|
+
session_id,
|
|
214
|
+
user_email,
|
|
215
|
+
name,
|
|
216
|
+
phone,
|
|
217
|
+
sift_payment_method,
|
|
218
|
+
payment_methods,
|
|
219
|
+
billing_address,
|
|
220
|
+
app,
|
|
221
|
+
metadata
|
|
222
|
+
} = body;
|
|
223
|
+
const siftMetadata = {
|
|
224
|
+
...metadata ?? {}
|
|
225
|
+
};
|
|
226
|
+
if (session_id !== void 0) siftMetadata.$session_id = session_id;
|
|
227
|
+
if (user_email !== void 0) siftMetadata.$user_email = user_email;
|
|
228
|
+
if (name !== void 0) siftMetadata.$name = name;
|
|
229
|
+
if (phone !== void 0) siftMetadata.$phone = phone;
|
|
230
|
+
if (sift_payment_method !== void 0) {
|
|
231
|
+
siftMetadata.$payment_method = toSiftKeyedObject(sift_payment_method);
|
|
232
|
+
}
|
|
233
|
+
if (payment_methods !== void 0) {
|
|
234
|
+
siftMetadata.$payment_methods = toSiftKeyedObject(payment_methods);
|
|
235
|
+
}
|
|
236
|
+
if (billing_address !== void 0) {
|
|
237
|
+
siftMetadata.$billing_address = toSiftKeyedObject(billing_address);
|
|
238
|
+
}
|
|
239
|
+
if (app !== void 0) siftMetadata.$app = toSiftKeyedObject(app);
|
|
240
|
+
return siftMetadata;
|
|
241
|
+
}
|
|
242
|
+
function normalizeBaseSiftFields(body) {
|
|
243
|
+
const siftMetadata = buildBaseSiftMetadata(body);
|
|
244
|
+
const stripped = stripSdkOnlyFields(body, [...BASE_SIFT_FIELD_KEYS]);
|
|
245
|
+
if (Object.keys(siftMetadata).length > 0) {
|
|
246
|
+
stripped.metadata = siftMetadata;
|
|
247
|
+
}
|
|
248
|
+
return stripped;
|
|
249
|
+
}
|
|
250
|
+
function applyRuleSignals(body, request, keys, stripKeys) {
|
|
251
|
+
const ruleSignals = collectRuleSignals(request, keys);
|
|
252
|
+
const stripped = stripSdkOnlyFields(body, [...stripKeys]);
|
|
253
|
+
if (Object.keys(ruleSignals).length > 0) {
|
|
254
|
+
stripped.metadata = mergeMetadata(
|
|
255
|
+
stripped.metadata,
|
|
256
|
+
ruleSignals
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
return stripped;
|
|
260
|
+
}
|
|
148
261
|
function normalizeUpdatePassword(request) {
|
|
149
262
|
const { password_reason, password_status, metadata, ...rest } = request;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
263
|
+
let body = createStrippedBody(rest, metadata, [
|
|
264
|
+
"password_reason",
|
|
265
|
+
"password_status"
|
|
266
|
+
]);
|
|
267
|
+
const siftMetadata = {
|
|
268
|
+
$reason: password_reason ?? PasswordUpdateReason.UserUpdate,
|
|
269
|
+
$status: password_status ?? PasswordUpdateStatus.Success
|
|
270
|
+
};
|
|
271
|
+
body = applySiftMetadata(body, metadata, siftMetadata);
|
|
272
|
+
return normalizeBaseSiftFields(body);
|
|
155
273
|
}
|
|
156
274
|
function normalizeWager(request) {
|
|
157
275
|
const { wager_type, wager_status, wager_event_type, wager_event_name, wager_event_id, metadata, ...rest } = request;
|
|
158
|
-
|
|
276
|
+
let body = createStrippedBody(rest, metadata, [
|
|
159
277
|
"wager_type",
|
|
160
278
|
"wager_status",
|
|
161
279
|
"wager_event_type",
|
|
@@ -166,17 +284,19 @@ function normalizeWager(request) {
|
|
|
166
284
|
$wager_type: wager_type,
|
|
167
285
|
$wager_status: wager_status
|
|
168
286
|
};
|
|
169
|
-
if (wager_event_type) siftMetadata
|
|
170
|
-
if (wager_event_name) siftMetadata
|
|
171
|
-
if (wager_event_id) siftMetadata
|
|
172
|
-
|
|
287
|
+
if (wager_event_type) siftMetadata.$wager_event_type = wager_event_type;
|
|
288
|
+
if (wager_event_name) siftMetadata.$wager_event_name = wager_event_name;
|
|
289
|
+
if (wager_event_id) siftMetadata.$wager_event_id = wager_event_id;
|
|
290
|
+
body = applySiftMetadata(body, metadata, siftMetadata);
|
|
291
|
+
return normalizeBaseSiftFields(body);
|
|
173
292
|
}
|
|
174
293
|
function normalizeLogin(request) {
|
|
175
294
|
const { login_status, login_failure_reason, metadata, ...rest } = request;
|
|
176
295
|
const effectiveStatus = login_status ?? LoginStatus.Success;
|
|
177
|
-
|
|
296
|
+
let body = createStrippedBody(rest, metadata, [
|
|
178
297
|
"login_status",
|
|
179
|
-
"login_failure_reason"
|
|
298
|
+
"login_failure_reason",
|
|
299
|
+
...LOGIN_RULE_SIGNAL_KEYS
|
|
180
300
|
]);
|
|
181
301
|
const siftMetadata = {
|
|
182
302
|
$login_status: effectiveStatus
|
|
@@ -184,14 +304,22 @@ function normalizeLogin(request) {
|
|
|
184
304
|
if (effectiveStatus === LoginStatus.Failure && login_failure_reason) {
|
|
185
305
|
siftMetadata.$failure_reason = login_failure_reason;
|
|
186
306
|
}
|
|
187
|
-
|
|
307
|
+
body = applySiftMetadata(body, metadata, siftMetadata);
|
|
308
|
+
body = applyRuleSignals(
|
|
309
|
+
body,
|
|
310
|
+
request,
|
|
311
|
+
LOGIN_RULE_SIGNAL_KEYS,
|
|
312
|
+
[]
|
|
313
|
+
);
|
|
314
|
+
return normalizeBaseSiftFields(body);
|
|
188
315
|
}
|
|
189
316
|
function normalizeTransaction(request) {
|
|
190
317
|
const { transaction_status, decline_category, transfer_recipient_user_id, metadata, ...rest } = request;
|
|
191
|
-
|
|
318
|
+
let body = createStrippedBody(rest, metadata, [
|
|
192
319
|
"transaction_status",
|
|
193
320
|
"decline_category",
|
|
194
|
-
"transfer_recipient_user_id"
|
|
321
|
+
"transfer_recipient_user_id",
|
|
322
|
+
...TRANSACTION_RULE_SIGNAL_KEYS
|
|
195
323
|
]);
|
|
196
324
|
const siftMetadata = {};
|
|
197
325
|
if (transaction_status) siftMetadata.$transaction_status = transaction_status;
|
|
@@ -199,7 +327,30 @@ function normalizeTransaction(request) {
|
|
|
199
327
|
if (transfer_recipient_user_id) {
|
|
200
328
|
siftMetadata.$transfer_recipient_user_id = transfer_recipient_user_id;
|
|
201
329
|
}
|
|
202
|
-
|
|
330
|
+
body = applySiftMetadata(body, metadata, siftMetadata, true);
|
|
331
|
+
body = applyRuleSignals(
|
|
332
|
+
body,
|
|
333
|
+
request,
|
|
334
|
+
TRANSACTION_RULE_SIGNAL_KEYS,
|
|
335
|
+
[]
|
|
336
|
+
);
|
|
337
|
+
return normalizeBaseSiftFields(body);
|
|
338
|
+
}
|
|
339
|
+
function normalizeUpdateAccount(request) {
|
|
340
|
+
const { metadata, ...rest } = request;
|
|
341
|
+
let body = createStrippedBody(rest, metadata, [
|
|
342
|
+
...UPDATE_ACCOUNT_RULE_SIGNAL_KEYS
|
|
343
|
+
]);
|
|
344
|
+
body = applyRuleSignals(
|
|
345
|
+
body,
|
|
346
|
+
request,
|
|
347
|
+
UPDATE_ACCOUNT_RULE_SIGNAL_KEYS,
|
|
348
|
+
[]
|
|
349
|
+
);
|
|
350
|
+
return normalizeBaseSiftFields(body);
|
|
351
|
+
}
|
|
352
|
+
function normalizeDefault(request) {
|
|
353
|
+
return normalizeBaseSiftFields({ ...request });
|
|
203
354
|
}
|
|
204
355
|
function normalizeScoreRequestForApi(request) {
|
|
205
356
|
switch (request.event_type) {
|
|
@@ -211,8 +362,10 @@ function normalizeScoreRequestForApi(request) {
|
|
|
211
362
|
return normalizeLogin(request);
|
|
212
363
|
case "$transaction":
|
|
213
364
|
return normalizeTransaction(request);
|
|
365
|
+
case "$update_account":
|
|
366
|
+
return normalizeUpdateAccount(request);
|
|
214
367
|
default:
|
|
215
|
-
return
|
|
368
|
+
return normalizeDefault(request);
|
|
216
369
|
}
|
|
217
370
|
}
|
|
218
371
|
|
|
@@ -253,10 +406,20 @@ function isSupportedFraudEventType(eventType) {
|
|
|
253
406
|
}
|
|
254
407
|
|
|
255
408
|
// src/types/metadata.ts
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
409
|
+
var TYPED_SIFT_METADATA_KEYS = {
|
|
410
|
+
session_id: "$session_id",
|
|
411
|
+
user_email: "$user_email",
|
|
412
|
+
name: "$name",
|
|
413
|
+
phone: "$phone",
|
|
414
|
+
sift_payment_method: "$payment_method",
|
|
415
|
+
billing_address: "$billing_address",
|
|
416
|
+
payment_methods: "$payment_methods",
|
|
417
|
+
app: "$app"
|
|
418
|
+
};
|
|
419
|
+
function findMetadataConflictWithTypedFields(metadata, request) {
|
|
420
|
+
for (const [field, metaKey] of Object.entries(TYPED_SIFT_METADATA_KEYS)) {
|
|
421
|
+
if (request[field] !== void 0 && metadata[metaKey] !== void 0) {
|
|
422
|
+
return metaKey;
|
|
260
423
|
}
|
|
261
424
|
}
|
|
262
425
|
return void 0;
|
|
@@ -282,12 +445,15 @@ function assertPositiveAmount(amount, field, errors, prefix) {
|
|
|
282
445
|
errors.push(`${prefix}${field} must be greater than 0`);
|
|
283
446
|
}
|
|
284
447
|
}
|
|
285
|
-
function validateMetadata(metadata, errors, prefix) {
|
|
448
|
+
function validateMetadata(metadata, request, errors, prefix) {
|
|
286
449
|
if (!metadata) return;
|
|
287
|
-
const
|
|
288
|
-
|
|
450
|
+
const conflictKey = findMetadataConflictWithTypedFields(
|
|
451
|
+
metadata,
|
|
452
|
+
request
|
|
453
|
+
);
|
|
454
|
+
if (conflictKey) {
|
|
289
455
|
errors.push(
|
|
290
|
-
`${prefix}metadata
|
|
456
|
+
`${prefix}metadata.${conflictKey} conflicts with a typed request field that maps to the same key; omit metadata.${conflictKey} or remove the typed field`
|
|
291
457
|
);
|
|
292
458
|
}
|
|
293
459
|
}
|
|
@@ -297,7 +463,7 @@ function validateBase(request, errors, prefix) {
|
|
|
297
463
|
assertNonEmpty(request.customer_id, "customer_id", errors, prefix);
|
|
298
464
|
assertNonEmpty(request.sift_user_id, "sift_user_id", errors, prefix);
|
|
299
465
|
assertNonEmpty(request.event_type, "event_type", errors, prefix);
|
|
300
|
-
validateMetadata(request.metadata, errors, prefix);
|
|
466
|
+
validateMetadata(request.metadata, request, errors, prefix);
|
|
301
467
|
}
|
|
302
468
|
function validateLogin(request, errors, prefix) {
|
|
303
469
|
assertEnum(request.login_status, SiftLoginStatusValues, "login_status", errors, prefix);
|
|
@@ -323,9 +489,6 @@ function validateUpdatePassword(request, errors, prefix) {
|
|
|
323
489
|
errors,
|
|
324
490
|
prefix
|
|
325
491
|
);
|
|
326
|
-
if (!request.password_reason) {
|
|
327
|
-
errors.push(`${prefix}password_reason is required`);
|
|
328
|
-
}
|
|
329
492
|
assertEnum(
|
|
330
493
|
request.password_status,
|
|
331
494
|
SiftPasswordUpdateStatusValues,
|
|
@@ -333,9 +496,6 @@ function validateUpdatePassword(request, errors, prefix) {
|
|
|
333
496
|
errors,
|
|
334
497
|
prefix
|
|
335
498
|
);
|
|
336
|
-
if (!request.password_status) {
|
|
337
|
-
errors.push(`${prefix}password_status is required`);
|
|
338
|
-
}
|
|
339
499
|
}
|
|
340
500
|
function validateTransaction(request, errors, prefix) {
|
|
341
501
|
assertPositiveAmount(request.amount, "amount", errors, prefix);
|
|
@@ -472,6 +632,7 @@ exports.CHARGEBACK_FRAUD_EVENT_TYPE = CHARGEBACK_FRAUD_EVENT_TYPE;
|
|
|
472
632
|
exports.ChargebackReason = ChargebackReason;
|
|
473
633
|
exports.ChargebackState = ChargebackState;
|
|
474
634
|
exports.FraudClient = FraudClient;
|
|
635
|
+
exports.LOGIN_RULE_SIGNAL_KEYS = LOGIN_RULE_SIGNAL_KEYS;
|
|
475
636
|
exports.LoginStatus = LoginStatus;
|
|
476
637
|
exports.PLANNED_FRAUD_EVENT_TYPES = PLANNED_FRAUD_EVENT_TYPES;
|
|
477
638
|
exports.PasswordUpdateReason = PasswordUpdateReason;
|
|
@@ -487,11 +648,14 @@ exports.SiftPasswordUpdateStatusValues = SiftPasswordUpdateStatusValues;
|
|
|
487
648
|
exports.SiftTransactionStatusValues = SiftTransactionStatusValues;
|
|
488
649
|
exports.SiftTransactionTypeValues = SiftTransactionTypeValues;
|
|
489
650
|
exports.SiftWagerStatusValues = SiftWagerStatusValues;
|
|
651
|
+
exports.TRANSACTION_RULE_SIGNAL_KEYS = TRANSACTION_RULE_SIGNAL_KEYS;
|
|
652
|
+
exports.TYPED_SIFT_METADATA_KEYS = TYPED_SIFT_METADATA_KEYS;
|
|
490
653
|
exports.TransactionStatus = TransactionStatus;
|
|
491
654
|
exports.TransactionType = TransactionType;
|
|
655
|
+
exports.UPDATE_ACCOUNT_RULE_SIGNAL_KEYS = UPDATE_ACCOUNT_RULE_SIGNAL_KEYS;
|
|
492
656
|
exports.WagerStatus = WagerStatus;
|
|
493
657
|
exports.buildScoreRequestPreview = buildScoreRequestPreview;
|
|
494
|
-
exports.
|
|
658
|
+
exports.findMetadataConflictWithTypedFields = findMetadataConflictWithTypedFields;
|
|
495
659
|
exports.isPlannedFraudEventType = isPlannedFraudEventType;
|
|
496
660
|
exports.isSupportedFraudEventType = isSupportedFraudEventType;
|
|
497
661
|
exports.normalizeScoreRequestForApi = normalizeScoreRequestForApi;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/enums.ts","../src/normalization/normalize.ts","../src/normalization/preview.ts","../src/types/events.ts","../src/types/metadata.ts","../src/validation/helpers.ts","../src/validation/rules.ts","../src/client.ts"],"names":["ValidationError","BaseClient"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Sift-aligned enum types and const objects for fraud scoring requests.\n */\n\nexport type SiftTransactionType =\n | '$sale'\n | '$authorize'\n | '$capture'\n | '$void'\n | '$refund'\n | '$deposit'\n | '$withdrawal'\n | '$transfer'\n | '$buy'\n | '$sell'\n | '$send'\n | '$receive';\n\nexport const SiftTransactionTypeValues = [\n '$sale',\n '$authorize',\n '$capture',\n '$void',\n '$refund',\n '$deposit',\n '$withdrawal',\n '$transfer',\n '$buy',\n '$sell',\n '$send',\n '$receive',\n] as const satisfies readonly SiftTransactionType[];\n\nexport const TransactionType = {\n Sale: '$sale',\n Authorize: '$authorize',\n Capture: '$capture',\n Void: '$void',\n Refund: '$refund',\n Deposit: '$deposit',\n Withdrawal: '$withdrawal',\n Transfer: '$transfer',\n Buy: '$buy',\n Sell: '$sell',\n Send: '$send',\n Receive: '$receive',\n} as const satisfies Record<string, SiftTransactionType>;\n\nexport type SiftChargebackState =\n | '$received'\n | '$accepted'\n | '$disputed'\n | '$won'\n | '$lost';\n\nexport const SiftChargebackStateValues = [\n '$received',\n '$accepted',\n '$disputed',\n '$won',\n '$lost',\n] as const satisfies readonly SiftChargebackState[];\n\nexport const ChargebackState = {\n Received: '$received',\n Accepted: '$accepted',\n Disputed: '$disputed',\n Won: '$won',\n Lost: '$lost',\n} as const satisfies Record<string, SiftChargebackState>;\n\nexport type SiftChargebackReason =\n | '$fraud'\n | '$duplicate'\n | '$product_not_received'\n | '$product_unacceptable'\n | '$authorization'\n | '$consumer_disputes'\n | '$processing_errors'\n | '$cancel_subscription'\n | '$friendly_fraud'\n | '$ach_return'\n | '$ach_reversal'\n | '$other';\n\nexport const SiftChargebackReasonValues = [\n '$fraud',\n '$duplicate',\n '$product_not_received',\n '$product_unacceptable',\n '$authorization',\n '$consumer_disputes',\n '$processing_errors',\n '$cancel_subscription',\n '$friendly_fraud',\n '$ach_return',\n '$ach_reversal',\n '$other',\n] as const satisfies readonly SiftChargebackReason[];\n\nexport const ChargebackReason = {\n Fraud: '$fraud',\n Duplicate: '$duplicate',\n ProductNotReceived: '$product_not_received',\n ProductUnacceptable: '$product_unacceptable',\n Authorization: '$authorization',\n ConsumerDisputes: '$consumer_disputes',\n ProcessingErrors: '$processing_errors',\n CancelSubscription: '$cancel_subscription',\n FriendlyFraud: '$friendly_fraud',\n AchReturn: '$ach_return',\n AchReversal: '$ach_reversal',\n Other: '$other',\n} as const satisfies Record<string, SiftChargebackReason>;\n\nexport type SiftLoginStatus = '$success' | '$failure';\n\nexport const SiftLoginStatusValues = ['$success', '$failure'] as const satisfies readonly SiftLoginStatus[];\n\nexport const LoginStatus = {\n Success: '$success',\n Failure: '$failure',\n} as const satisfies Record<string, SiftLoginStatus>;\n\nexport type SiftLoginFailureReason =\n | '$account_unknown'\n | '$account_suspended'\n | '$account_disabled'\n | '$wrong_password';\n\nexport const SiftLoginFailureReasonValues = [\n '$account_unknown',\n '$account_suspended',\n '$account_disabled',\n '$wrong_password',\n] as const satisfies readonly SiftLoginFailureReason[];\n\nexport type SiftPasswordUpdateReason =\n | '$user_update'\n | '$forgot_password'\n | '$forced_reset';\n\nexport const SiftPasswordUpdateReasonValues = [\n '$user_update',\n '$forgot_password',\n '$forced_reset',\n] as const satisfies readonly SiftPasswordUpdateReason[];\n\nexport const PasswordUpdateReason = {\n UserUpdate: SiftPasswordUpdateReasonValues[0],\n ForgotPassword: SiftPasswordUpdateReasonValues[1],\n ForcedReset: SiftPasswordUpdateReasonValues[2],\n} as const satisfies Record<string, SiftPasswordUpdateReason>;\n\nexport type SiftPasswordUpdateStatus = '$pending' | '$success' | '$failure';\n\nexport const SiftPasswordUpdateStatusValues = [\n '$pending',\n '$success',\n '$failure',\n] as const satisfies readonly SiftPasswordUpdateStatus[];\n\nexport const PasswordUpdateStatus = {\n Pending: '$pending',\n Success: '$success',\n Failure: '$failure',\n} as const satisfies Record<string, SiftPasswordUpdateStatus>;\n\nexport type SiftWagerStatus = '$accept' | '$cancel';\n\nexport const SiftWagerStatusValues = ['$accept', '$cancel'] as const satisfies readonly SiftWagerStatus[];\n\nexport const WagerStatus = {\n Accept: '$accept',\n Cancel: '$cancel',\n} as const satisfies Record<string, SiftWagerStatus>;\n\nexport type SiftTransactionStatus = '$success' | '$failure' | '$pending';\n\nexport const SiftTransactionStatusValues = [\n '$success',\n '$failure',\n '$pending',\n] as const satisfies readonly SiftTransactionStatus[];\n\nexport const TransactionStatus = {\n Success: '$success',\n Failure: '$failure',\n Pending: '$pending',\n} as const satisfies Record<string, SiftTransactionStatus>;\n\nexport type FraudRiskLevel = 'low' | 'medium' | 'high' | 'critical';\n","import { LoginStatus } from '../types/enums';\nimport type { FraudScoreRequest } from '../types/requests';\nimport type { FraudCustomMetadata } from '../types/metadata';\n\nfunction mergeMetadata(\n base: FraudCustomMetadata | undefined,\n extras: FraudCustomMetadata\n): FraudCustomMetadata {\n return { ...base, ...extras };\n}\n\nfunction stripSdkOnlyFields(\n request: Record<string, unknown>,\n keys: string[]\n): Record<string, unknown> {\n const body = { ...request };\n for (const key of keys) {\n delete body[key];\n }\n return body;\n}\n\nfunction createStrippedBody(\n rest: Record<string, unknown>,\n metadata: FraudCustomMetadata | undefined,\n stripKeys: string[]\n): Record<string, unknown> {\n return stripSdkOnlyFields(\n { ...rest, metadata: mergeMetadata(metadata, {}) },\n stripKeys\n );\n}\n\nfunction applySiftMetadata(\n body: Record<string, unknown>,\n metadata: FraudCustomMetadata | undefined,\n siftMetadata: FraudCustomMetadata,\n onlyWhenNonEmpty = false\n): Record<string, unknown> {\n if (!onlyWhenNonEmpty || Object.keys(siftMetadata).length > 0) {\n body.metadata = mergeMetadata(metadata, siftMetadata);\n }\n return body;\n}\n\nfunction normalizeUpdatePassword(\n request: Extract<FraudScoreRequest, { event_type: '$update_password' }>\n): Record<string, unknown> {\n const { password_reason, password_status, metadata, ...rest } = request;\n const body = createStrippedBody(rest, metadata, []);\n const siftMetadata: FraudCustomMetadata = {};\n if (password_reason) siftMetadata.$reason = password_reason;\n if (password_status) siftMetadata.$status = password_status;\n return applySiftMetadata(body, metadata, siftMetadata);\n}\n\nfunction normalizeWager(\n request: Extract<FraudScoreRequest, { event_type: '$wager' }>\n): Record<string, unknown> {\n const { wager_type, wager_status, wager_event_type, wager_event_name, wager_event_id, metadata, ...rest } =\n request;\n const body = createStrippedBody(rest, metadata, [\n 'wager_type',\n 'wager_status',\n 'wager_event_type',\n 'wager_event_name',\n 'wager_event_id',\n ]);\n const siftMetadata: FraudCustomMetadata = {\n $wager_type: wager_type,\n $wager_status: wager_status,\n };\n if (wager_event_type) siftMetadata.wager_event_type = wager_event_type;\n if (wager_event_name) siftMetadata.wager_event_name = wager_event_name;\n if (wager_event_id) siftMetadata.wager_event_id = wager_event_id;\n return applySiftMetadata(body, metadata, siftMetadata);\n}\n\nfunction normalizeLogin(\n request: Extract<FraudScoreRequest, { event_type: '$login' }>\n): Record<string, unknown> {\n const { login_status, login_failure_reason, metadata, ...rest } = request;\n const effectiveStatus = login_status ?? LoginStatus.Success;\n const body = createStrippedBody(rest, metadata, [\n 'login_status',\n 'login_failure_reason',\n ]);\n const siftMetadata: FraudCustomMetadata = {\n $login_status: effectiveStatus,\n };\n if (effectiveStatus === LoginStatus.Failure && login_failure_reason) {\n siftMetadata.$failure_reason = login_failure_reason;\n }\n return applySiftMetadata(body, metadata, siftMetadata);\n}\n\nfunction normalizeTransaction(\n request: Extract<FraudScoreRequest, { event_type: '$transaction' }>\n): Record<string, unknown> {\n const { transaction_status, decline_category, transfer_recipient_user_id, metadata, ...rest } =\n request;\n const body = createStrippedBody(rest, metadata, [\n 'transaction_status',\n 'decline_category',\n 'transfer_recipient_user_id',\n ]);\n const siftMetadata: FraudCustomMetadata = {};\n if (transaction_status) siftMetadata.$transaction_status = transaction_status;\n if (decline_category) siftMetadata.$decline_category = decline_category;\n if (transfer_recipient_user_id) {\n siftMetadata.$transfer_recipient_user_id = transfer_recipient_user_id;\n }\n return applySiftMetadata(body, metadata, siftMetadata, true);\n}\n\nexport function normalizeScoreRequestForApi(request: FraudScoreRequest): Record<string, unknown> {\n switch (request.event_type) {\n case '$update_password':\n return normalizeUpdatePassword(request);\n case '$wager':\n return normalizeWager(request);\n case '$login':\n return normalizeLogin(request);\n case '$transaction':\n return normalizeTransaction(request);\n default:\n return { ...request };\n }\n}\n","import type { FraudScoreRequest } from '../types/requests';\nimport { normalizeScoreRequestForApi } from './normalize';\n\n/**\n * Returns the JSON body that would be sent to POST /api/v1/fraud/score after normalization.\n * Useful for debugging without calling the API.\n */\nexport function buildScoreRequestPreview(request: FraudScoreRequest): Record<string, unknown> {\n return normalizeScoreRequestForApi(request);\n}\n","/**\n * Fraud event type unions aligned with fraud-service support matrix.\n */\n\n/** Events that run Sift scoring + rule engine */\nexport type ScoredFraudEventType =\n | '$create_account'\n | '$login'\n | '$logout'\n | '$update_account'\n | '$update_password'\n | '$transaction'\n | '$wager';\n\n/** Feedback-only; no meaningful fraud score in response */\nexport type ChargebackFraudEventType = '$chargeback';\n\n/** Union accepted by scoreEvent / scoreEventsBulk */\nexport type SupportedFraudEventType = ScoredFraudEventType | ChargebackFraudEventType;\n\nexport const SCORED_FRAUD_EVENT_TYPES: readonly ScoredFraudEventType[] = [\n '$create_account',\n '$login',\n '$logout',\n '$update_account',\n '$update_password',\n '$transaction',\n '$wager',\n] as const;\n\nexport const CHARGEBACK_FRAUD_EVENT_TYPE = '$chargeback' as const;\n\nexport const SUPPORTED_FRAUD_EVENT_TYPES: readonly SupportedFraudEventType[] = [\n ...SCORED_FRAUD_EVENT_TYPES,\n CHARGEBACK_FRAUD_EVENT_TYPE,\n] as const;\n\nexport const PLANNED_FRAUD_EVENT_TYPES = [\n '$verification',\n '$link_session_to_user',\n '$security_notification',\n '$create_order',\n '$update_order',\n '$order_status',\n '$add_promotion',\n] as const;\n\n/**\n * Listed in Vesant dashboard / future API — NOT valid for scoreEvent today.\n * @deprecated Not supported by POST /api/v1/fraud/score\n */\nexport type PlannedFraudEventType = (typeof PLANNED_FRAUD_EVENT_TYPES)[number];\n\n/**\n * @deprecated Use SupportedFraudEventType; kept for migration\n */\nexport type FraudEventType = SupportedFraudEventType | (typeof PLANNED_FRAUD_EVENT_TYPES)[number];\n\nexport function isPlannedFraudEventType(\n eventType: string\n): eventType is (typeof PLANNED_FRAUD_EVENT_TYPES)[number] {\n return (PLANNED_FRAUD_EVENT_TYPES as readonly string[]).includes(eventType);\n}\n\nexport function isSupportedFraudEventType(\n eventType: string\n): eventType is SupportedFraudEventType {\n return (SUPPORTED_FRAUD_EVENT_TYPES as readonly string[]).includes(eventType);\n}\n","/**\n * Custom metadata for fraud score requests (non-Sift reserved keys).\n */\n\nexport type FraudCustomMetadata = Record<string, unknown>;\n\nexport function hasReservedMetadataKey(metadata: FraudCustomMetadata): string | undefined {\n for (const key of Object.keys(metadata)) {\n if (key.startsWith('$')) {\n return key;\n }\n }\n return undefined;\n}\n","import { hasReservedMetadataKey } from '../types/metadata';\nimport type { FraudCustomMetadata } from '../types/metadata';\n\nexport function fieldPrefix(index?: number): string {\n return index === undefined ? '' : `requests[${index}].`;\n}\n\nexport function assertNonEmpty(\n value: string | undefined,\n field: string,\n errors: string[],\n prefix: string\n): void {\n if (!value?.trim()) {\n errors.push(`${prefix}${field} is required`);\n }\n}\n\nexport function assertEnum<T extends string>(\n value: string | undefined,\n allowed: readonly T[],\n field: string,\n errors: string[],\n prefix: string\n): void {\n if (value === undefined) return;\n if (!(allowed as readonly string[]).includes(value)) {\n errors.push(`${prefix}${field} must be one of: ${allowed.join(', ')}`);\n }\n}\n\nexport function assertPositiveAmount(\n amount: number | undefined,\n field: string,\n errors: string[],\n prefix: string\n): void {\n if (amount === undefined || amount <= 0) {\n errors.push(`${prefix}${field} must be greater than 0`);\n }\n}\n\nexport function validateMetadata(\n metadata: FraudCustomMetadata | undefined,\n errors: string[],\n prefix: string\n): void {\n if (!metadata) return;\n const reservedKey = hasReservedMetadataKey(metadata);\n if (reservedKey) {\n errors.push(\n `${prefix}metadata keys must not start with '$' (found '${reservedKey}'). Use typed request fields instead.`\n );\n }\n}\n","import { ValidationError } from '@vesant-sdk/core';\nimport {\n SiftChargebackReasonValues,\n SiftChargebackStateValues,\n SiftLoginFailureReasonValues,\n SiftLoginStatusValues,\n SiftPasswordUpdateReasonValues,\n SiftPasswordUpdateStatusValues,\n SiftTransactionStatusValues,\n SiftTransactionTypeValues,\n SiftWagerStatusValues,\n TransactionType,\n} from '../types/enums';\nimport {\n isPlannedFraudEventType,\n isSupportedFraudEventType,\n SUPPORTED_FRAUD_EVENT_TYPES,\n} from '../types/events';\nimport type { FraudScoreRequest } from '../types/requests';\nimport {\n assertEnum,\n assertNonEmpty,\n assertPositiveAmount,\n fieldPrefix,\n validateMetadata,\n} from './helpers';\n\nfunction validateBase(\n request: FraudScoreRequest,\n errors: string[],\n prefix: string\n): void {\n assertNonEmpty(request.customer_id, 'customer_id', errors, prefix);\n assertNonEmpty(request.sift_user_id, 'sift_user_id', errors, prefix);\n assertNonEmpty(request.event_type, 'event_type', errors, prefix);\n validateMetadata(request.metadata, errors, prefix);\n}\n\nfunction validateLogin(\n request: Extract<FraudScoreRequest, { event_type: '$login' }>,\n errors: string[],\n prefix: string\n): void {\n assertEnum(request.login_status, SiftLoginStatusValues, 'login_status', errors, prefix);\n if (request.login_failure_reason !== undefined) {\n if (request.login_status === '$failure') {\n assertEnum(\n request.login_failure_reason,\n SiftLoginFailureReasonValues,\n 'login_failure_reason',\n errors,\n prefix\n );\n } else {\n errors.push(`${prefix}login_failure_reason is only allowed when login_status is '$failure'`);\n }\n }\n}\n\nfunction validateUpdatePassword(\n request: Extract<FraudScoreRequest, { event_type: '$update_password' }>,\n errors: string[],\n prefix: string\n): void {\n assertEnum(\n request.password_reason,\n SiftPasswordUpdateReasonValues,\n 'password_reason',\n errors,\n prefix\n );\n if (!request.password_reason) {\n errors.push(`${prefix}password_reason is required`);\n }\n assertEnum(\n request.password_status,\n SiftPasswordUpdateStatusValues,\n 'password_status',\n errors,\n prefix\n );\n if (!request.password_status) {\n errors.push(`${prefix}password_status is required`);\n }\n}\n\nfunction validateTransaction(\n request: Extract<FraudScoreRequest, { event_type: '$transaction' }>,\n errors: string[],\n prefix: string\n): void {\n assertPositiveAmount(request.amount, 'amount', errors, prefix);\n assertNonEmpty(request.currency, 'currency', errors, prefix);\n assertEnum(request.transaction_type, SiftTransactionTypeValues, 'transaction_type', errors, prefix);\n assertEnum(\n request.transaction_status,\n SiftTransactionStatusValues,\n 'transaction_status',\n errors,\n prefix\n );\n\n if (request.decline_category !== undefined && request.transaction_status !== '$failure') {\n errors.push(\n `${prefix}decline_category is only allowed when transaction_status is '$failure'`\n );\n }\n\n if (\n request.transfer_recipient_user_id !== undefined &&\n request.transaction_type !== TransactionType.Transfer\n ) {\n errors.push(\n `${prefix}transfer_recipient_user_id is only allowed when transaction_type is '$transfer'`\n );\n }\n}\n\nfunction validateWager(\n request: Extract<FraudScoreRequest, { event_type: '$wager' }>,\n errors: string[],\n prefix: string\n): void {\n assertNonEmpty(request.transaction_id, 'transaction_id', errors, prefix);\n assertNonEmpty(request.wager_type, 'wager_type', errors, prefix);\n assertEnum(request.wager_status, SiftWagerStatusValues, 'wager_status', errors, prefix);\n if (!request.wager_status) {\n errors.push(`${prefix}wager_status is required`);\n }\n assertPositiveAmount(request.amount, 'amount', errors, prefix);\n assertNonEmpty(request.currency, 'currency', errors, prefix);\n}\n\nfunction validateChargeback(\n request: Extract<FraudScoreRequest, { event_type: '$chargeback' }>,\n errors: string[],\n prefix: string\n): void {\n const hasTransactionId = !!request.transaction_id?.trim();\n const hasOrderId = !!request.order_id?.trim();\n if (!hasTransactionId && !hasOrderId) {\n errors.push(`${prefix}transaction_id or order_id is required`);\n }\n assertEnum(request.chargeback_state, SiftChargebackStateValues, 'chargeback_state', errors, prefix);\n assertEnum(\n request.chargeback_reason,\n SiftChargebackReasonValues,\n 'chargeback_reason',\n errors,\n prefix\n );\n if (request.ach_return_code !== undefined && request.ach_return_code.trim() !== '') {\n if (!/^R\\d{2}$/i.test(request.ach_return_code.trim())) {\n errors.push(`${prefix}ach_return_code must match NACHA R## pattern (e.g. R01)`);\n }\n }\n}\n\nfunction validateByEventType(request: FraudScoreRequest, errors: string[], prefix: string): void {\n switch (request.event_type) {\n case '$login':\n validateLogin(request, errors, prefix);\n break;\n case '$update_password':\n validateUpdatePassword(request, errors, prefix);\n break;\n case '$transaction':\n validateTransaction(request, errors, prefix);\n break;\n case '$wager':\n validateWager(request, errors, prefix);\n break;\n case '$chargeback':\n validateChargeback(request, errors, prefix);\n break;\n case '$create_account':\n case '$logout':\n case '$update_account':\n break;\n default:\n break;\n }\n}\n\nexport function validateScoreRequest(request: FraudScoreRequest, index?: number): void {\n const errors: string[] = [];\n const prefix = fieldPrefix(index);\n\n validateBase(request, errors, prefix);\n\n if (request.event_type && isPlannedFraudEventType(request.event_type)) {\n errors.push(\n `${prefix}event_type ${request.event_type} is not supported by POST /api/v1/fraud/score. Supported: ${SUPPORTED_FRAUD_EVENT_TYPES.join(', ')}`\n );\n } else if (request.event_type && !isSupportedFraudEventType(request.event_type)) {\n errors.push(\n `${prefix}event_type must be one of: ${SUPPORTED_FRAUD_EVENT_TYPES.join(', ')}`\n );\n } else if (isSupportedFraudEventType(request.event_type)) {\n validateByEventType(request, errors, prefix);\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid fraud score request: ${errors.join(', ')}`, errors);\n }\n}\n","/**\n * Fraud scoring API client.\n */\n\nimport { BaseClient } from '@vesant-sdk/core';\nimport type { RequestOptions } from '@vesant-sdk/core';\nimport { ValidationError } from '@vesant-sdk/core';\nimport { normalizeScoreRequestForApi } from './normalization';\nimport type {\n FraudScoreRequest,\n FraudScoreResponseData,\n FraudScoreResponseEnvelope,\n} from './types';\nimport { validateScoreRequest } from './validation/rules';\n\nexport class FraudClient extends BaseClient {\n async scoreEvent(\n request: FraudScoreRequest,\n requestOptions?: RequestOptions\n ): Promise<FraudScoreResponseEnvelope<FraudScoreResponseData>> {\n validateScoreRequest(request);\n const body = normalizeScoreRequestForApi(request);\n\n return this.requestWithRetry<FraudScoreResponseEnvelope<FraudScoreResponseData>>(\n '/api/v1/fraud/score',\n {\n method: 'POST',\n body: JSON.stringify(body),\n },\n undefined,\n undefined,\n requestOptions\n );\n }\n\n async scoreEventsBulk(\n requests: FraudScoreRequest[],\n requestOptions?: RequestOptions\n ): Promise<FraudScoreResponseEnvelope<FraudScoreResponseData[]>> {\n if (!Array.isArray(requests) || requests.length === 0) {\n throw new ValidationError(\n 'Invalid bulk score request: at least one score request is required',\n ['requests']\n );\n }\n\n const bodies = requests.map((request, index) => {\n validateScoreRequest(request, index);\n return normalizeScoreRequestForApi(request);\n });\n\n return this.requestWithRetry<FraudScoreResponseEnvelope<FraudScoreResponseData[]>>(\n '/api/v1/fraud/score/bulk',\n {\n method: 'POST',\n body: JSON.stringify(bodies),\n },\n undefined,\n undefined,\n requestOptions\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/enums.ts","../src/types/rule-signals.ts","../src/normalization/sift-keys.ts","../src/normalization/normalize.ts","../src/normalization/preview.ts","../src/types/events.ts","../src/types/metadata.ts","../src/validation/helpers.ts","../src/validation/rules.ts","../src/client.ts"],"names":["ValidationError","BaseClient"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Sift-aligned enum types and const objects for fraud scoring requests.\n */\n\nexport type SiftTransactionType =\n | '$sale'\n | '$authorize'\n | '$capture'\n | '$void'\n | '$refund'\n | '$deposit'\n | '$withdrawal'\n | '$transfer'\n | '$buy'\n | '$sell'\n | '$send'\n | '$receive';\n\nexport const SiftTransactionTypeValues = [\n '$sale',\n '$authorize',\n '$capture',\n '$void',\n '$refund',\n '$deposit',\n '$withdrawal',\n '$transfer',\n '$buy',\n '$sell',\n '$send',\n '$receive',\n] as const satisfies readonly SiftTransactionType[];\n\nexport const TransactionType = {\n Sale: '$sale',\n Authorize: '$authorize',\n Capture: '$capture',\n Void: '$void',\n Refund: '$refund',\n Deposit: '$deposit',\n Withdrawal: '$withdrawal',\n Transfer: '$transfer',\n Buy: '$buy',\n Sell: '$sell',\n Send: '$send',\n Receive: '$receive',\n} as const satisfies Record<string, SiftTransactionType>;\n\nexport type SiftChargebackState =\n | '$received'\n | '$accepted'\n | '$disputed'\n | '$won'\n | '$lost';\n\nexport const SiftChargebackStateValues = [\n '$received',\n '$accepted',\n '$disputed',\n '$won',\n '$lost',\n] as const satisfies readonly SiftChargebackState[];\n\nexport const ChargebackState = {\n Received: '$received',\n Accepted: '$accepted',\n Disputed: '$disputed',\n Won: '$won',\n Lost: '$lost',\n} as const satisfies Record<string, SiftChargebackState>;\n\nexport type SiftChargebackReason =\n | '$fraud'\n | '$duplicate'\n | '$product_not_received'\n | '$product_unacceptable'\n | '$authorization'\n | '$consumer_disputes'\n | '$processing_errors'\n | '$cancel_subscription'\n | '$friendly_fraud'\n | '$ach_return'\n | '$ach_reversal'\n | '$other';\n\nexport const SiftChargebackReasonValues = [\n '$fraud',\n '$duplicate',\n '$product_not_received',\n '$product_unacceptable',\n '$authorization',\n '$consumer_disputes',\n '$processing_errors',\n '$cancel_subscription',\n '$friendly_fraud',\n '$ach_return',\n '$ach_reversal',\n '$other',\n] as const satisfies readonly SiftChargebackReason[];\n\nexport const ChargebackReason = {\n Fraud: '$fraud',\n Duplicate: '$duplicate',\n ProductNotReceived: '$product_not_received',\n ProductUnacceptable: '$product_unacceptable',\n Authorization: '$authorization',\n ConsumerDisputes: '$consumer_disputes',\n ProcessingErrors: '$processing_errors',\n CancelSubscription: '$cancel_subscription',\n FriendlyFraud: '$friendly_fraud',\n AchReturn: '$ach_return',\n AchReversal: '$ach_reversal',\n Other: '$other',\n} as const satisfies Record<string, SiftChargebackReason>;\n\nexport type SiftLoginStatus = '$success' | '$failure';\n\nexport const SiftLoginStatusValues = ['$success', '$failure'] as const satisfies readonly SiftLoginStatus[];\n\nexport const LoginStatus = {\n Success: '$success',\n Failure: '$failure',\n} as const satisfies Record<string, SiftLoginStatus>;\n\nexport type SiftLoginFailureReason =\n | '$account_unknown'\n | '$account_suspended'\n | '$account_disabled'\n | '$wrong_password';\n\nexport const SiftLoginFailureReasonValues = [\n '$account_unknown',\n '$account_suspended',\n '$account_disabled',\n '$wrong_password',\n] as const satisfies readonly SiftLoginFailureReason[];\n\nexport type SiftPasswordUpdateReason =\n | '$user_update'\n | '$forgot_password'\n | '$forced_reset';\n\nexport const SiftPasswordUpdateReasonValues = [\n '$user_update',\n '$forgot_password',\n '$forced_reset',\n] as const satisfies readonly SiftPasswordUpdateReason[];\n\nexport const PasswordUpdateReason = {\n UserUpdate: SiftPasswordUpdateReasonValues[0],\n ForgotPassword: SiftPasswordUpdateReasonValues[1],\n ForcedReset: SiftPasswordUpdateReasonValues[2],\n} as const satisfies Record<string, SiftPasswordUpdateReason>;\n\nexport type SiftPasswordUpdateStatus = '$pending' | '$success' | '$failure';\n\nexport const SiftPasswordUpdateStatusValues = [\n '$pending',\n '$success',\n '$failure',\n] as const satisfies readonly SiftPasswordUpdateStatus[];\n\nexport const PasswordUpdateStatus = {\n Pending: '$pending',\n Success: '$success',\n Failure: '$failure',\n} as const satisfies Record<string, SiftPasswordUpdateStatus>;\n\nexport type SiftWagerStatus = '$accept' | '$cancel';\n\nexport const SiftWagerStatusValues = ['$accept', '$cancel'] as const satisfies readonly SiftWagerStatus[];\n\nexport const WagerStatus = {\n Accept: '$accept',\n Cancel: '$cancel',\n} as const satisfies Record<string, SiftWagerStatus>;\n\nexport type SiftTransactionStatus = '$success' | '$failure' | '$pending';\n\nexport const SiftTransactionStatusValues = [\n '$success',\n '$failure',\n '$pending',\n] as const satisfies readonly SiftTransactionStatus[];\n\nexport const TransactionStatus = {\n Success: '$success',\n Failure: '$failure',\n Pending: '$pending',\n} as const satisfies Record<string, SiftTransactionStatus>;\n\nexport type FraudRiskLevel = 'low' | 'medium' | 'high' | 'critical';\n","/**\n * Optional top-level rule-signal fields copied into plain metadata on the wire.\n */\n\nexport interface LoginRuleSignals {\n ip_country_mismatch?: boolean;\n}\n\nexport interface UpdateAccountRuleSignals {\n two_fa_enabled?: boolean;\n two_fa_disabled?: boolean;\n two_fa_method_changed?: boolean;\n}\n\nexport interface TransactionRuleSignals {\n payment_method?: string;\n is_first_deposit?: boolean;\n cumulative_deposit_amount?: number;\n deposit_count?: number;\n failed_deposit_count?: number;\n is_first_withdrawal?: boolean;\n withdrawal_method_differs?: boolean;\n cumulative_withdrawal_amount?: number;\n withdrawal_count?: number;\n hours_since_last_deposit?: number;\n days_since_last_activity?: number;\n hours_since_account_creation?: number;\n}\n\nexport const LOGIN_RULE_SIGNAL_KEYS = ['ip_country_mismatch'] as const;\n\nexport const UPDATE_ACCOUNT_RULE_SIGNAL_KEYS = [\n 'two_fa_enabled',\n 'two_fa_disabled',\n 'two_fa_method_changed',\n] as const;\n\nexport const TRANSACTION_RULE_SIGNAL_KEYS = [\n 'payment_method',\n 'is_first_deposit',\n 'cumulative_deposit_amount',\n 'deposit_count',\n 'failed_deposit_count',\n 'is_first_withdrawal',\n 'withdrawal_method_differs',\n 'cumulative_withdrawal_amount',\n 'withdrawal_count',\n 'hours_since_last_deposit',\n 'days_since_last_activity',\n 'hours_since_account_creation',\n] as const;\n","function siftKey(key: string): string {\n return key.startsWith('$') ? key : `$${key}`;\n}\n\n/**\n * Recursively prefix object keys with $ for Sift wire format (no double-prefix).\n */\nexport function toSiftKeyedObject(value: unknown): unknown {\n if (value === null || value === undefined) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map((item) => toSiftKeyedObject(item));\n }\n if (typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, nested] of Object.entries(value as Record<string, unknown>)) {\n out[siftKey(key)] = toSiftKeyedObject(nested);\n }\n return out;\n }\n return value;\n}\n","import { LoginStatus, PasswordUpdateReason, PasswordUpdateStatus } from '../types/enums';\nimport type { FraudCustomMetadata } from '../types/metadata';\nimport type { FraudScoreRequest } from '../types/requests';\nimport {\n LOGIN_RULE_SIGNAL_KEYS,\n TRANSACTION_RULE_SIGNAL_KEYS,\n UPDATE_ACCOUNT_RULE_SIGNAL_KEYS,\n} from '../types/rule-signals';\nimport { toSiftKeyedObject } from './sift-keys';\n\nconst BASE_SIFT_FIELD_KEYS = [\n 'session_id',\n 'user_email',\n 'name',\n 'phone',\n 'sift_payment_method',\n 'payment_methods',\n 'billing_address',\n 'app',\n] as const;\n\nfunction mergeMetadata(\n base: FraudCustomMetadata | undefined,\n extras: FraudCustomMetadata\n): FraudCustomMetadata {\n return { ...base, ...extras };\n}\n\nfunction stripSdkOnlyFields(\n request: Record<string, unknown>,\n keys: string[]\n): Record<string, unknown> {\n const body = { ...request };\n for (const key of keys) {\n delete body[key];\n }\n return body;\n}\n\nfunction createStrippedBody(\n rest: Record<string, unknown>,\n metadata: FraudCustomMetadata | undefined,\n stripKeys: string[]\n): Record<string, unknown> {\n return stripSdkOnlyFields(\n { ...rest, metadata: mergeMetadata(metadata, {}) },\n stripKeys\n );\n}\n\nfunction applySiftMetadata(\n body: Record<string, unknown>,\n metadata: FraudCustomMetadata | undefined,\n siftMetadata: FraudCustomMetadata,\n onlyWhenNonEmpty = false\n): Record<string, unknown> {\n if (!onlyWhenNonEmpty || Object.keys(siftMetadata).length > 0) {\n body.metadata = mergeMetadata(metadata, siftMetadata);\n }\n return body;\n}\n\nfunction collectRuleSignals(\n request: Record<string, unknown>,\n keys: readonly string[]\n): FraudCustomMetadata {\n const signals: FraudCustomMetadata = {};\n for (const key of keys) {\n const value = request[key];\n if (value !== undefined) {\n signals[key] = value;\n }\n }\n return signals;\n}\n\nfunction buildBaseSiftMetadata(body: Record<string, unknown>): FraudCustomMetadata {\n const {\n session_id,\n user_email,\n name,\n phone,\n sift_payment_method,\n payment_methods,\n billing_address,\n app,\n metadata,\n } = body;\n\n const siftMetadata: FraudCustomMetadata = {\n ...((metadata as FraudCustomMetadata | undefined) ?? {}),\n };\n\n if (session_id !== undefined) siftMetadata.$session_id = session_id;\n if (user_email !== undefined) siftMetadata.$user_email = user_email;\n if (name !== undefined) siftMetadata.$name = name;\n if (phone !== undefined) siftMetadata.$phone = phone;\n if (sift_payment_method !== undefined) {\n siftMetadata.$payment_method = toSiftKeyedObject(sift_payment_method) as FraudCustomMetadata[string];\n }\n if (payment_methods !== undefined) {\n siftMetadata.$payment_methods = toSiftKeyedObject(payment_methods) as FraudCustomMetadata[string];\n }\n if (billing_address !== undefined) {\n siftMetadata.$billing_address = toSiftKeyedObject(billing_address) as FraudCustomMetadata[string];\n }\n if (app !== undefined) siftMetadata.$app = toSiftKeyedObject(app) as FraudCustomMetadata[string];\n\n return siftMetadata;\n}\n\nfunction normalizeBaseSiftFields(body: Record<string, unknown>): Record<string, unknown> {\n const siftMetadata = buildBaseSiftMetadata(body);\n const stripped = stripSdkOnlyFields(body, [...BASE_SIFT_FIELD_KEYS]);\n\n if (Object.keys(siftMetadata).length > 0) {\n stripped.metadata = siftMetadata;\n }\n\n return stripped;\n}\n\nfunction applyRuleSignals(\n body: Record<string, unknown>,\n request: Record<string, unknown>,\n keys: readonly string[],\n stripKeys: readonly string[]\n): Record<string, unknown> {\n const ruleSignals = collectRuleSignals(request, keys);\n const stripped = stripSdkOnlyFields(body, [...stripKeys]);\n if (Object.keys(ruleSignals).length > 0) {\n stripped.metadata = mergeMetadata(\n stripped.metadata as FraudCustomMetadata | undefined,\n ruleSignals\n );\n }\n return stripped;\n}\n\nfunction normalizeUpdatePassword(\n request: Extract<FraudScoreRequest, { event_type: '$update_password' }>\n): Record<string, unknown> {\n const { password_reason, password_status, metadata, ...rest } = request;\n let body = createStrippedBody(rest as Record<string, unknown>, metadata, [\n 'password_reason',\n 'password_status',\n ]);\n const siftMetadata: FraudCustomMetadata = {\n $reason: password_reason ?? PasswordUpdateReason.UserUpdate,\n $status: password_status ?? PasswordUpdateStatus.Success,\n };\n body = applySiftMetadata(body, metadata, siftMetadata);\n return normalizeBaseSiftFields(body);\n}\n\nfunction normalizeWager(\n request: Extract<FraudScoreRequest, { event_type: '$wager' }>\n): Record<string, unknown> {\n const { wager_type, wager_status, wager_event_type, wager_event_name, wager_event_id, metadata, ...rest } =\n request;\n let body = createStrippedBody(rest as Record<string, unknown>, metadata, [\n 'wager_type',\n 'wager_status',\n 'wager_event_type',\n 'wager_event_name',\n 'wager_event_id',\n ]);\n const siftMetadata: FraudCustomMetadata = {\n $wager_type: wager_type,\n $wager_status: wager_status,\n };\n if (wager_event_type) siftMetadata.$wager_event_type = wager_event_type;\n if (wager_event_name) siftMetadata.$wager_event_name = wager_event_name;\n if (wager_event_id) siftMetadata.$wager_event_id = wager_event_id;\n body = applySiftMetadata(body, metadata, siftMetadata);\n return normalizeBaseSiftFields(body);\n}\n\nfunction normalizeLogin(\n request: Extract<FraudScoreRequest, { event_type: '$login' }>\n): Record<string, unknown> {\n const { login_status, login_failure_reason, metadata, ...rest } = request;\n const effectiveStatus = login_status ?? LoginStatus.Success;\n let body = createStrippedBody(rest as Record<string, unknown>, metadata, [\n 'login_status',\n 'login_failure_reason',\n ...LOGIN_RULE_SIGNAL_KEYS,\n ]);\n const siftMetadata: FraudCustomMetadata = {\n $login_status: effectiveStatus,\n };\n if (effectiveStatus === LoginStatus.Failure && login_failure_reason) {\n siftMetadata.$failure_reason = login_failure_reason;\n }\n body = applySiftMetadata(body, metadata, siftMetadata);\n body = applyRuleSignals(\n body,\n request as unknown as Record<string, unknown>,\n LOGIN_RULE_SIGNAL_KEYS,\n []\n );\n return normalizeBaseSiftFields(body);\n}\n\nfunction normalizeTransaction(\n request: Extract<FraudScoreRequest, { event_type: '$transaction' }>\n): Record<string, unknown> {\n const { transaction_status, decline_category, transfer_recipient_user_id, metadata, ...rest } =\n request;\n let body = createStrippedBody(rest as Record<string, unknown>, metadata, [\n 'transaction_status',\n 'decline_category',\n 'transfer_recipient_user_id',\n ...TRANSACTION_RULE_SIGNAL_KEYS,\n ]);\n const siftMetadata: FraudCustomMetadata = {};\n if (transaction_status) siftMetadata.$transaction_status = transaction_status;\n if (decline_category) siftMetadata.$decline_category = decline_category;\n if (transfer_recipient_user_id) {\n siftMetadata.$transfer_recipient_user_id = transfer_recipient_user_id;\n }\n body = applySiftMetadata(body, metadata, siftMetadata, true);\n body = applyRuleSignals(\n body,\n request as unknown as Record<string, unknown>,\n TRANSACTION_RULE_SIGNAL_KEYS,\n []\n );\n return normalizeBaseSiftFields(body);\n}\n\nfunction normalizeUpdateAccount(\n request: Extract<FraudScoreRequest, { event_type: '$update_account' }>\n): Record<string, unknown> {\n const { metadata, ...rest } = request;\n let body = createStrippedBody(rest as Record<string, unknown>, metadata, [\n ...UPDATE_ACCOUNT_RULE_SIGNAL_KEYS,\n ]);\n body = applyRuleSignals(\n body,\n request as unknown as Record<string, unknown>,\n UPDATE_ACCOUNT_RULE_SIGNAL_KEYS,\n []\n );\n return normalizeBaseSiftFields(body);\n}\n\nfunction normalizeDefault(request: FraudScoreRequest): Record<string, unknown> {\n return normalizeBaseSiftFields({ ...request } as Record<string, unknown>);\n}\n\nexport function normalizeScoreRequestForApi(request: FraudScoreRequest): Record<string, unknown> {\n switch (request.event_type) {\n case '$update_password':\n return normalizeUpdatePassword(request);\n case '$wager':\n return normalizeWager(request);\n case '$login':\n return normalizeLogin(request);\n case '$transaction':\n return normalizeTransaction(request);\n case '$update_account':\n return normalizeUpdateAccount(request);\n default:\n return normalizeDefault(request);\n }\n}\n","import type { FraudScoreRequest } from '../types/requests';\nimport { normalizeScoreRequestForApi } from './normalize';\n\n/**\n * Returns the JSON body that would be sent to POST /api/v1/fraud/score after normalization.\n * Useful for debugging without calling the API.\n */\nexport function buildScoreRequestPreview(request: FraudScoreRequest): Record<string, unknown> {\n return normalizeScoreRequestForApi(request);\n}\n","/**\n * Fraud event type unions aligned with fraud-service support matrix.\n */\n\n/** Events that run Sift scoring + rule engine */\nexport type ScoredFraudEventType =\n | '$create_account'\n | '$login'\n | '$logout'\n | '$update_account'\n | '$update_password'\n | '$transaction'\n | '$wager';\n\n/** Feedback-only; no meaningful fraud score in response */\nexport type ChargebackFraudEventType = '$chargeback';\n\n/** Union accepted by scoreEvent / scoreEventsBulk */\nexport type SupportedFraudEventType = ScoredFraudEventType | ChargebackFraudEventType;\n\nexport const SCORED_FRAUD_EVENT_TYPES: readonly ScoredFraudEventType[] = [\n '$create_account',\n '$login',\n '$logout',\n '$update_account',\n '$update_password',\n '$transaction',\n '$wager',\n] as const;\n\nexport const CHARGEBACK_FRAUD_EVENT_TYPE = '$chargeback' as const;\n\nexport const SUPPORTED_FRAUD_EVENT_TYPES: readonly SupportedFraudEventType[] = [\n ...SCORED_FRAUD_EVENT_TYPES,\n CHARGEBACK_FRAUD_EVENT_TYPE,\n] as const;\n\nexport const PLANNED_FRAUD_EVENT_TYPES = [\n '$verification',\n '$link_session_to_user',\n '$security_notification',\n '$create_order',\n '$update_order',\n '$order_status',\n '$add_promotion',\n] as const;\n\n/**\n * Listed in Vesant dashboard / future API — NOT valid for scoreEvent today.\n * @deprecated Not supported by POST /api/v1/fraud/score\n */\nexport type PlannedFraudEventType = (typeof PLANNED_FRAUD_EVENT_TYPES)[number];\n\n/**\n * @deprecated Use SupportedFraudEventType; kept for migration\n */\nexport type FraudEventType = SupportedFraudEventType | (typeof PLANNED_FRAUD_EVENT_TYPES)[number];\n\nexport function isPlannedFraudEventType(\n eventType: string\n): eventType is (typeof PLANNED_FRAUD_EVENT_TYPES)[number] {\n return (PLANNED_FRAUD_EVENT_TYPES as readonly string[]).includes(eventType);\n}\n\nexport function isSupportedFraudEventType(\n eventType: string\n): eventType is SupportedFraudEventType {\n return (SUPPORTED_FRAUD_EVENT_TYPES as readonly string[]).includes(eventType);\n}\n","/**\n * Metadata for fraud score requests.\n * Plain keys are Vesant rule signals; $-prefixed keys are Sift pass-through (or set via typed fields).\n */\n\nexport interface FraudRuleSignalMetadata {\n /** Rule signal payment method (e.g. \"$credit_card\"), not Sift $payment_method object */\n payment_method?: string;\n country?: string;\n two_fa_enabled?: boolean;\n two_fa_disabled?: boolean;\n two_fa_method_changed?: boolean;\n ip_country_mismatch?: boolean;\n is_first_deposit?: boolean;\n cumulative_deposit_amount?: number;\n deposit_count?: number;\n failed_deposit_count?: number;\n is_first_withdrawal?: boolean;\n withdrawal_method_differs?: boolean;\n cumulative_withdrawal_amount?: number;\n withdrawal_count?: number;\n hours_since_last_deposit?: number;\n days_since_last_activity?: number;\n hours_since_account_creation?: number;\n}\n\n/** Extra Sift fields forwarded verbatim in metadata (e.g. $referrer_user_id, $promotions). */\nexport type SiftPassThroughMetadata = Record<`$${string}`, unknown>;\n\nexport type FraudCustomMetadata = FraudRuleSignalMetadata &\n SiftPassThroughMetadata &\n Record<string, unknown>;\n\n/** Maps typed request fields to metadata keys they populate (typed values win on normalize). */\nexport const TYPED_SIFT_METADATA_KEYS: Readonly<Record<string, string>> = {\n session_id: '$session_id',\n user_email: '$user_email',\n name: '$name',\n phone: '$phone',\n sift_payment_method: '$payment_method',\n billing_address: '$billing_address',\n payment_methods: '$payment_methods',\n app: '$app',\n};\n\nexport function findMetadataConflictWithTypedFields(\n metadata: FraudCustomMetadata,\n request: Record<string, unknown>\n): string | undefined {\n for (const [field, metaKey] of Object.entries(TYPED_SIFT_METADATA_KEYS)) {\n if (request[field] !== undefined && metadata[metaKey] !== undefined) {\n return metaKey;\n }\n }\n return undefined;\n}\n","import { findMetadataConflictWithTypedFields } from '../types/metadata';\nimport type { FraudCustomMetadata } from '../types/metadata';\nimport type { FraudScoreRequestBase } from '../types/requests';\n\nexport function fieldPrefix(index?: number): string {\n return index === undefined ? '' : `requests[${index}].`;\n}\n\nexport function assertNonEmpty(\n value: string | undefined,\n field: string,\n errors: string[],\n prefix: string\n): void {\n if (!value?.trim()) {\n errors.push(`${prefix}${field} is required`);\n }\n}\n\nexport function assertEnum<T extends string>(\n value: string | undefined,\n allowed: readonly T[],\n field: string,\n errors: string[],\n prefix: string\n): void {\n if (value === undefined) return;\n if (!(allowed as readonly string[]).includes(value)) {\n errors.push(`${prefix}${field} must be one of: ${allowed.join(', ')}`);\n }\n}\n\nexport function assertPositiveAmount(\n amount: number | undefined,\n field: string,\n errors: string[],\n prefix: string\n): void {\n if (amount === undefined || amount <= 0) {\n errors.push(`${prefix}${field} must be greater than 0`);\n }\n}\n\nexport function validateMetadata(\n metadata: FraudCustomMetadata | undefined,\n request: FraudScoreRequestBase,\n errors: string[],\n prefix: string\n): void {\n if (!metadata) return;\n const conflictKey = findMetadataConflictWithTypedFields(\n metadata,\n request as unknown as Record<string, unknown>\n );\n if (conflictKey) {\n errors.push(\n `${prefix}metadata.${conflictKey} conflicts with a typed request field that maps to the same key; omit metadata.${conflictKey} or remove the typed field`\n );\n }\n}\n","import { ValidationError } from '@vesant-sdk/core';\nimport {\n SiftChargebackReasonValues,\n SiftChargebackStateValues,\n SiftLoginFailureReasonValues,\n SiftLoginStatusValues,\n SiftPasswordUpdateReasonValues,\n SiftPasswordUpdateStatusValues,\n SiftTransactionStatusValues,\n SiftTransactionTypeValues,\n SiftWagerStatusValues,\n TransactionType,\n} from '../types/enums';\nimport {\n isPlannedFraudEventType,\n isSupportedFraudEventType,\n SUPPORTED_FRAUD_EVENT_TYPES,\n} from '../types/events';\nimport type { FraudScoreRequest } from '../types/requests';\nimport {\n assertEnum,\n assertNonEmpty,\n assertPositiveAmount,\n fieldPrefix,\n validateMetadata,\n} from './helpers';\n\nfunction validateBase(\n request: FraudScoreRequest,\n errors: string[],\n prefix: string\n): void {\n assertNonEmpty(request.customer_id, 'customer_id', errors, prefix);\n assertNonEmpty(request.sift_user_id, 'sift_user_id', errors, prefix);\n assertNonEmpty(request.event_type, 'event_type', errors, prefix);\n validateMetadata(request.metadata, request, errors, prefix);\n}\n\nfunction validateLogin(\n request: Extract<FraudScoreRequest, { event_type: '$login' }>,\n errors: string[],\n prefix: string\n): void {\n assertEnum(request.login_status, SiftLoginStatusValues, 'login_status', errors, prefix);\n if (request.login_failure_reason !== undefined) {\n if (request.login_status === '$failure') {\n assertEnum(\n request.login_failure_reason,\n SiftLoginFailureReasonValues,\n 'login_failure_reason',\n errors,\n prefix\n );\n } else {\n errors.push(`${prefix}login_failure_reason is only allowed when login_status is '$failure'`);\n }\n }\n}\n\nfunction validateUpdatePassword(\n request: Extract<FraudScoreRequest, { event_type: '$update_password' }>,\n errors: string[],\n prefix: string\n): void {\n assertEnum(\n request.password_reason,\n SiftPasswordUpdateReasonValues,\n 'password_reason',\n errors,\n prefix\n );\n assertEnum(\n request.password_status,\n SiftPasswordUpdateStatusValues,\n 'password_status',\n errors,\n prefix\n );\n}\n\nfunction validateTransaction(\n request: Extract<FraudScoreRequest, { event_type: '$transaction' }>,\n errors: string[],\n prefix: string\n): void {\n assertPositiveAmount(request.amount, 'amount', errors, prefix);\n assertNonEmpty(request.currency, 'currency', errors, prefix);\n assertEnum(request.transaction_type, SiftTransactionTypeValues, 'transaction_type', errors, prefix);\n assertEnum(\n request.transaction_status,\n SiftTransactionStatusValues,\n 'transaction_status',\n errors,\n prefix\n );\n\n if (request.decline_category !== undefined && request.transaction_status !== '$failure') {\n errors.push(\n `${prefix}decline_category is only allowed when transaction_status is '$failure'`\n );\n }\n\n if (\n request.transfer_recipient_user_id !== undefined &&\n request.transaction_type !== TransactionType.Transfer\n ) {\n errors.push(\n `${prefix}transfer_recipient_user_id is only allowed when transaction_type is '$transfer'`\n );\n }\n}\n\nfunction validateWager(\n request: Extract<FraudScoreRequest, { event_type: '$wager' }>,\n errors: string[],\n prefix: string\n): void {\n assertNonEmpty(request.transaction_id, 'transaction_id', errors, prefix);\n assertNonEmpty(request.wager_type, 'wager_type', errors, prefix);\n assertEnum(request.wager_status, SiftWagerStatusValues, 'wager_status', errors, prefix);\n if (!request.wager_status) {\n errors.push(`${prefix}wager_status is required`);\n }\n assertPositiveAmount(request.amount, 'amount', errors, prefix);\n assertNonEmpty(request.currency, 'currency', errors, prefix);\n}\n\nfunction validateChargeback(\n request: Extract<FraudScoreRequest, { event_type: '$chargeback' }>,\n errors: string[],\n prefix: string\n): void {\n const hasTransactionId = !!request.transaction_id?.trim();\n const hasOrderId = !!request.order_id?.trim();\n if (!hasTransactionId && !hasOrderId) {\n errors.push(`${prefix}transaction_id or order_id is required`);\n }\n assertEnum(request.chargeback_state, SiftChargebackStateValues, 'chargeback_state', errors, prefix);\n assertEnum(\n request.chargeback_reason,\n SiftChargebackReasonValues,\n 'chargeback_reason',\n errors,\n prefix\n );\n if (request.ach_return_code !== undefined && request.ach_return_code.trim() !== '') {\n if (!/^R\\d{2}$/i.test(request.ach_return_code.trim())) {\n errors.push(`${prefix}ach_return_code must match NACHA R## pattern (e.g. R01)`);\n }\n }\n}\n\nfunction validateByEventType(request: FraudScoreRequest, errors: string[], prefix: string): void {\n switch (request.event_type) {\n case '$login':\n validateLogin(request, errors, prefix);\n break;\n case '$update_password':\n validateUpdatePassword(request, errors, prefix);\n break;\n case '$transaction':\n validateTransaction(request, errors, prefix);\n break;\n case '$wager':\n validateWager(request, errors, prefix);\n break;\n case '$chargeback':\n validateChargeback(request, errors, prefix);\n break;\n case '$create_account':\n case '$logout':\n case '$update_account':\n break;\n default:\n break;\n }\n}\n\nexport function validateScoreRequest(request: FraudScoreRequest, index?: number): void {\n const errors: string[] = [];\n const prefix = fieldPrefix(index);\n\n validateBase(request, errors, prefix);\n\n if (request.event_type && isPlannedFraudEventType(request.event_type)) {\n errors.push(\n `${prefix}event_type ${request.event_type} is not supported by POST /api/v1/fraud/score. Supported: ${SUPPORTED_FRAUD_EVENT_TYPES.join(', ')}`\n );\n } else if (request.event_type && !isSupportedFraudEventType(request.event_type)) {\n errors.push(\n `${prefix}event_type must be one of: ${SUPPORTED_FRAUD_EVENT_TYPES.join(', ')}`\n );\n } else if (isSupportedFraudEventType(request.event_type)) {\n validateByEventType(request, errors, prefix);\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid fraud score request: ${errors.join(', ')}`, errors);\n }\n}\n","/**\n * Fraud scoring API client.\n */\n\nimport { BaseClient } from '@vesant-sdk/core';\nimport type { RequestOptions } from '@vesant-sdk/core';\nimport { ValidationError } from '@vesant-sdk/core';\nimport { normalizeScoreRequestForApi } from './normalization';\nimport type {\n FraudScoreRequest,\n FraudScoreResponseData,\n FraudScoreResponseEnvelope,\n} from './types';\nimport { validateScoreRequest } from './validation/rules';\n\nexport class FraudClient extends BaseClient {\n async scoreEvent(\n request: FraudScoreRequest,\n requestOptions?: RequestOptions\n ): Promise<FraudScoreResponseEnvelope<FraudScoreResponseData>> {\n validateScoreRequest(request);\n const body = normalizeScoreRequestForApi(request);\n\n return this.requestWithRetry<FraudScoreResponseEnvelope<FraudScoreResponseData>>(\n '/api/v1/fraud/score',\n {\n method: 'POST',\n body: JSON.stringify(body),\n },\n undefined,\n undefined,\n requestOptions\n );\n }\n\n async scoreEventsBulk(\n requests: FraudScoreRequest[],\n requestOptions?: RequestOptions\n ): Promise<FraudScoreResponseEnvelope<FraudScoreResponseData[]>> {\n if (!Array.isArray(requests) || requests.length === 0) {\n throw new ValidationError(\n 'Invalid bulk score request: at least one score request is required',\n ['requests']\n );\n }\n\n const bodies = requests.map((request, index) => {\n validateScoreRequest(request, index);\n return normalizeScoreRequestForApi(request);\n });\n\n return this.requestWithRetry<FraudScoreResponseEnvelope<FraudScoreResponseData[]>>(\n '/api/v1/fraud/score/bulk',\n {\n method: 'POST',\n body: JSON.stringify(bodies),\n },\n undefined,\n undefined,\n requestOptions\n );\n }\n}\n"]}
|