@vesant-sdk/fraud 0.1.1-next.f2f4e87 → 0.1.2-next.02b7e78
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 +303 -15
- package/dist/index.d.mts +249 -14
- package/dist/index.d.ts +249 -14
- package/dist/index.js +635 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +623 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -119,8 +119,321 @@ var TransactionStatus = {
|
|
|
119
119
|
Failure: "$failure",
|
|
120
120
|
Pending: "$pending"
|
|
121
121
|
};
|
|
122
|
+
var SiftPaymentTypeValues = [
|
|
123
|
+
"$cash",
|
|
124
|
+
"$check",
|
|
125
|
+
"$credit_card",
|
|
126
|
+
"$crypto_currency",
|
|
127
|
+
"$debit_card",
|
|
128
|
+
"$digital_wallet",
|
|
129
|
+
"$electronic_fund_transfer",
|
|
130
|
+
"$financing",
|
|
131
|
+
"$gift_card",
|
|
132
|
+
"$invoice",
|
|
133
|
+
"$in_app_purchase",
|
|
134
|
+
"$money_order",
|
|
135
|
+
"$points",
|
|
136
|
+
"$prepaid_card",
|
|
137
|
+
"$store_credit",
|
|
138
|
+
"$third_party_processor",
|
|
139
|
+
"$voucher",
|
|
140
|
+
"$sepa_credit",
|
|
141
|
+
"$sepa_instant_credit",
|
|
142
|
+
"$sepa_direct_debit",
|
|
143
|
+
"$ach_credit",
|
|
144
|
+
"$ach_debit",
|
|
145
|
+
"$wire_credit",
|
|
146
|
+
"$wire_debit"
|
|
147
|
+
];
|
|
148
|
+
var PaymentType = {
|
|
149
|
+
Cash: "$cash",
|
|
150
|
+
Check: "$check",
|
|
151
|
+
CreditCard: "$credit_card",
|
|
152
|
+
CryptoCurrency: "$crypto_currency",
|
|
153
|
+
DebitCard: "$debit_card",
|
|
154
|
+
DigitalWallet: "$digital_wallet",
|
|
155
|
+
ElectronicFundTransfer: "$electronic_fund_transfer",
|
|
156
|
+
Financing: "$financing",
|
|
157
|
+
GiftCard: "$gift_card",
|
|
158
|
+
Invoice: "$invoice",
|
|
159
|
+
InAppPurchase: "$in_app_purchase",
|
|
160
|
+
MoneyOrder: "$money_order",
|
|
161
|
+
Points: "$points",
|
|
162
|
+
PrepaidCard: "$prepaid_card",
|
|
163
|
+
StoreCredit: "$store_credit",
|
|
164
|
+
ThirdPartyProcessor: "$third_party_processor",
|
|
165
|
+
Voucher: "$voucher",
|
|
166
|
+
SepaCredit: "$sepa_credit",
|
|
167
|
+
SepaInstantCredit: "$sepa_instant_credit",
|
|
168
|
+
SepaDirectDebit: "$sepa_direct_debit",
|
|
169
|
+
AchCredit: "$ach_credit",
|
|
170
|
+
AchDebit: "$ach_debit",
|
|
171
|
+
WireCredit: "$wire_credit",
|
|
172
|
+
WireDebit: "$wire_debit"
|
|
173
|
+
};
|
|
174
|
+
var SiftWalletTypeValues = ["$crypto", "$digital", "$fiat"];
|
|
175
|
+
var WalletType = {
|
|
176
|
+
Crypto: "$crypto",
|
|
177
|
+
Digital: "$digital",
|
|
178
|
+
Fiat: "$fiat"
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/types/rule-signals.ts
|
|
182
|
+
var LOGIN_RULE_SIGNAL_KEYS = ["ip_country_mismatch"];
|
|
183
|
+
var UPDATE_ACCOUNT_RULE_SIGNAL_KEYS = [
|
|
184
|
+
"two_fa_enabled",
|
|
185
|
+
"two_fa_disabled",
|
|
186
|
+
"two_fa_method_changed"
|
|
187
|
+
];
|
|
188
|
+
var TRANSACTION_RULE_SIGNAL_KEYS = [
|
|
189
|
+
"payment_method",
|
|
190
|
+
"is_first_deposit",
|
|
191
|
+
"cumulative_deposit_amount",
|
|
192
|
+
"deposit_count",
|
|
193
|
+
"failed_deposit_count",
|
|
194
|
+
"is_first_withdrawal",
|
|
195
|
+
"withdrawal_method_differs",
|
|
196
|
+
"cumulative_withdrawal_amount",
|
|
197
|
+
"withdrawal_count",
|
|
198
|
+
"hours_since_last_deposit",
|
|
199
|
+
"days_since_last_activity",
|
|
200
|
+
"hours_since_account_creation"
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
// src/normalization/payment-methods.ts
|
|
204
|
+
var PAYMENT_TYPE_ALIASES = {
|
|
205
|
+
bank_account: "$electronic_fund_transfer",
|
|
206
|
+
electronic_fund_transfer: "$electronic_fund_transfer",
|
|
207
|
+
credit_card: "$credit_card",
|
|
208
|
+
crypto_currency: "$crypto_currency",
|
|
209
|
+
debit_card: "$debit_card",
|
|
210
|
+
digital_wallet: "$digital_wallet",
|
|
211
|
+
cash: "$cash",
|
|
212
|
+
check: "$check",
|
|
213
|
+
financing: "$financing",
|
|
214
|
+
gift_card: "$gift_card",
|
|
215
|
+
invoice: "$invoice",
|
|
216
|
+
in_app_purchase: "$in_app_purchase",
|
|
217
|
+
money_order: "$money_order",
|
|
218
|
+
points: "$points",
|
|
219
|
+
prepaid_card: "$prepaid_card",
|
|
220
|
+
store_credit: "$store_credit",
|
|
221
|
+
third_party_processor: "$third_party_processor",
|
|
222
|
+
voucher: "$voucher",
|
|
223
|
+
sepa_credit: "$sepa_credit",
|
|
224
|
+
sepa_instant_credit: "$sepa_instant_credit",
|
|
225
|
+
sepa_direct_debit: "$sepa_direct_debit",
|
|
226
|
+
ach_credit: "$ach_credit",
|
|
227
|
+
ach_debit: "$ach_debit",
|
|
228
|
+
wire_credit: "$wire_credit",
|
|
229
|
+
wire_debit: "$wire_debit"
|
|
230
|
+
};
|
|
231
|
+
var SIFT_PAYMENT_METHOD_WHITELIST = /* @__PURE__ */ new Set([
|
|
232
|
+
"payment_type",
|
|
233
|
+
"payment_gateway",
|
|
234
|
+
"card_bin",
|
|
235
|
+
"card_last4",
|
|
236
|
+
"avs_result_code",
|
|
237
|
+
"cvv_result_code",
|
|
238
|
+
"verification_status",
|
|
239
|
+
"routing_number",
|
|
240
|
+
"account_holder_name",
|
|
241
|
+
"account_number_last5",
|
|
242
|
+
"bank_name",
|
|
243
|
+
"bank_country",
|
|
244
|
+
"wallet_address",
|
|
245
|
+
"wallet_type",
|
|
246
|
+
"paypal_payer_id",
|
|
247
|
+
"paypal_payer_email"
|
|
248
|
+
]);
|
|
249
|
+
var DEPRECATED_PAYMENT_METHOD_KEYS = [
|
|
250
|
+
"account_number_last4",
|
|
251
|
+
"account_id",
|
|
252
|
+
"wallet_address_last4",
|
|
253
|
+
"crypto_currency",
|
|
254
|
+
"network"
|
|
255
|
+
];
|
|
256
|
+
var METADATA_STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
257
|
+
"account_id",
|
|
258
|
+
"wallet_address_last4",
|
|
259
|
+
"crypto_currency",
|
|
260
|
+
"network"
|
|
261
|
+
]);
|
|
262
|
+
function isDevEnvironment() {
|
|
263
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
264
|
+
}
|
|
265
|
+
function warnDeprecatedKey(key) {
|
|
266
|
+
if (!isDevEnvironment()) return;
|
|
267
|
+
const messages = {
|
|
268
|
+
account_number_last4: "[vesant-sdk/fraud] account_number_last4 is not a Sift field; use account_number_last5",
|
|
269
|
+
account_id: "[vesant-sdk/fraud] account_id is not a Sift field; moved to metadata",
|
|
270
|
+
wallet_address_last4: "[vesant-sdk/fraud] wallet_address_last4 is not a Sift field; moved to metadata",
|
|
271
|
+
crypto_currency: "[vesant-sdk/fraud] crypto_currency is not a Sift field on payment_method; moved to metadata",
|
|
272
|
+
network: "[vesant-sdk/fraud] network is not a Sift field on payment_method; moved to metadata"
|
|
273
|
+
};
|
|
274
|
+
const message = messages[key];
|
|
275
|
+
if (message) {
|
|
276
|
+
console.warn(message);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
function normalizeSiftPaymentType(value) {
|
|
280
|
+
if (value === void 0 || value === null) return void 0;
|
|
281
|
+
const trimmed = String(value).trim();
|
|
282
|
+
if (trimmed === "") return void 0;
|
|
283
|
+
const normalized = trimmed.startsWith("$") ? trimmed.slice(1) : trimmed;
|
|
284
|
+
const alias = PAYMENT_TYPE_ALIASES[normalized.toLowerCase()];
|
|
285
|
+
if (alias) return alias;
|
|
286
|
+
const withPrefix = `$${normalized}`;
|
|
287
|
+
if (SiftPaymentTypeValues.includes(withPrefix)) {
|
|
288
|
+
return withPrefix;
|
|
289
|
+
}
|
|
290
|
+
return void 0;
|
|
291
|
+
}
|
|
292
|
+
function toSiftAccountNumberLast5(value) {
|
|
293
|
+
if (value === void 0 || value === null) return void 0;
|
|
294
|
+
const digits = String(value).replace(/\D/g, "");
|
|
295
|
+
if (digits.length === 0) return void 0;
|
|
296
|
+
if (digits.length >= 5) return digits.slice(-5);
|
|
297
|
+
return digits.padStart(5, "0");
|
|
298
|
+
}
|
|
299
|
+
function collectMetadataExtra(metadataExtras, key, value) {
|
|
300
|
+
if (value === void 0) return;
|
|
301
|
+
metadataExtras[key] = value;
|
|
302
|
+
}
|
|
303
|
+
function normalizeSiftPaymentMethod(raw) {
|
|
304
|
+
const metadataExtras = {};
|
|
305
|
+
const method = {};
|
|
306
|
+
const rawPaymentType = raw.payment_type !== void 0 ? String(raw.payment_type) : raw.$payment_type !== void 0 ? String(raw.$payment_type) : void 0;
|
|
307
|
+
const normalizedType = normalizeSiftPaymentType(rawPaymentType);
|
|
308
|
+
if (rawPaymentType !== void 0 && normalizedType === void 0) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
if (normalizedType !== void 0) {
|
|
312
|
+
method.payment_type = normalizedType;
|
|
313
|
+
}
|
|
314
|
+
for (const key of DEPRECATED_PAYMENT_METHOD_KEYS) {
|
|
315
|
+
if (key in raw) warnDeprecatedKey(key);
|
|
316
|
+
}
|
|
317
|
+
const accountLast4 = raw.account_number_last4 ?? raw.$account_number_last4;
|
|
318
|
+
const accountLast5 = raw.account_number_last5 ?? raw.$account_number_last5;
|
|
319
|
+
const resolvedLast5 = toSiftAccountNumberLast5(accountLast5 ?? accountLast4);
|
|
320
|
+
if (resolvedLast5 !== void 0) {
|
|
321
|
+
method.account_number_last5 = resolvedLast5;
|
|
322
|
+
}
|
|
323
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
324
|
+
if (key === "payment_type" || key === "$payment_type") continue;
|
|
325
|
+
if (key === "account_number_last4" || key === "$account_number_last4") continue;
|
|
326
|
+
if (key === "account_number_last5" || key === "$account_number_last5") continue;
|
|
327
|
+
const plainKey = key.startsWith("$") ? key.slice(1) : key;
|
|
328
|
+
if (METADATA_STRIP_KEYS.has(plainKey)) {
|
|
329
|
+
if (plainKey === "account_id") {
|
|
330
|
+
collectMetadataExtra(metadataExtras, "linkmoney_account_id", String(value));
|
|
331
|
+
} else {
|
|
332
|
+
collectMetadataExtra(metadataExtras, plainKey, value);
|
|
333
|
+
}
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if (!SIFT_PAYMENT_METHOD_WHITELIST.has(plainKey)) {
|
|
337
|
+
collectMetadataExtra(metadataExtras, `payment_method_${plainKey}`, value);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
if (plainKey === "payment_type") {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
method[plainKey] = value;
|
|
344
|
+
}
|
|
345
|
+
const hasMetadata = Object.keys(metadataExtras).length > 0;
|
|
346
|
+
return {
|
|
347
|
+
method,
|
|
348
|
+
...hasMetadata ? { metadataExtras } : {}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function mergeAccountIds(target, accountId) {
|
|
352
|
+
const existing = target.linkmoney_account_ids;
|
|
353
|
+
if (Array.isArray(existing)) {
|
|
354
|
+
existing.push(accountId);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (typeof target.linkmoney_account_id === "string") {
|
|
358
|
+
target.linkmoney_account_ids = [target.linkmoney_account_id, accountId];
|
|
359
|
+
delete target.linkmoney_account_id;
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
target.linkmoney_account_id = accountId;
|
|
363
|
+
}
|
|
364
|
+
function normalizeSiftPaymentMethods(methods) {
|
|
365
|
+
if (methods === void 0) return {};
|
|
366
|
+
const normalized = [];
|
|
367
|
+
const metadata = {};
|
|
368
|
+
for (const raw of methods) {
|
|
369
|
+
const result = normalizeSiftPaymentMethod(raw);
|
|
370
|
+
if (result === null) continue;
|
|
371
|
+
normalized.push(result.method);
|
|
372
|
+
if (result.metadataExtras) {
|
|
373
|
+
for (const [key, value] of Object.entries(result.metadataExtras)) {
|
|
374
|
+
if (key === "linkmoney_account_id" && typeof value === "string") {
|
|
375
|
+
mergeAccountIds(metadata, value);
|
|
376
|
+
} else if (key in metadata && Array.isArray(metadata[key]) && Array.isArray(value)) {
|
|
377
|
+
metadata[key] = [...metadata[key], ...value];
|
|
378
|
+
} else if (!(key in metadata)) {
|
|
379
|
+
metadata[key] = value;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const hasMetadata = Object.keys(metadata).length > 0;
|
|
385
|
+
return {
|
|
386
|
+
payment_methods: normalized,
|
|
387
|
+
...hasMetadata ? { metadata } : {}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/normalization/sift-keys.ts
|
|
392
|
+
function siftKey(key) {
|
|
393
|
+
return key.startsWith("$") ? key : `$${key}`;
|
|
394
|
+
}
|
|
395
|
+
function toSiftKeyedObject(value) {
|
|
396
|
+
if (value === null || value === void 0) {
|
|
397
|
+
return value;
|
|
398
|
+
}
|
|
399
|
+
if (Array.isArray(value)) {
|
|
400
|
+
return value.map((item) => toSiftKeyedObject(item));
|
|
401
|
+
}
|
|
402
|
+
if (typeof value === "object") {
|
|
403
|
+
const out = {};
|
|
404
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
405
|
+
out[siftKey(key)] = toSiftKeyedObject(nested);
|
|
406
|
+
}
|
|
407
|
+
return out;
|
|
408
|
+
}
|
|
409
|
+
return value;
|
|
410
|
+
}
|
|
122
411
|
|
|
123
412
|
// src/normalization/normalize.ts
|
|
413
|
+
var BASE_SIFT_FIELD_KEYS = [
|
|
414
|
+
"session_id",
|
|
415
|
+
"user_email",
|
|
416
|
+
"name",
|
|
417
|
+
"phone",
|
|
418
|
+
"sift_payment_method",
|
|
419
|
+
"payment_methods",
|
|
420
|
+
"billing_address",
|
|
421
|
+
"shipping_address",
|
|
422
|
+
"app",
|
|
423
|
+
"browser",
|
|
424
|
+
"verification_phone_number",
|
|
425
|
+
"order_id",
|
|
426
|
+
"exchange_rate",
|
|
427
|
+
"expedited_shipping",
|
|
428
|
+
"shipping_method",
|
|
429
|
+
"shipping_carrier",
|
|
430
|
+
"shipping_tracking_numbers",
|
|
431
|
+
"brand_name",
|
|
432
|
+
"site_country",
|
|
433
|
+
"site_domain",
|
|
434
|
+
"ip",
|
|
435
|
+
"skip_payment_method_normalization"
|
|
436
|
+
];
|
|
124
437
|
function mergeMetadata(base, extras) {
|
|
125
438
|
return { ...base, ...extras };
|
|
126
439
|
}
|
|
@@ -143,17 +456,152 @@ function applySiftMetadata(body, metadata, siftMetadata, onlyWhenNonEmpty = fals
|
|
|
143
456
|
}
|
|
144
457
|
return body;
|
|
145
458
|
}
|
|
459
|
+
function collectRuleSignals(request, keys) {
|
|
460
|
+
const signals = {};
|
|
461
|
+
for (const key of keys) {
|
|
462
|
+
const value = request[key];
|
|
463
|
+
if (value !== void 0) {
|
|
464
|
+
signals[key] = value;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return signals;
|
|
468
|
+
}
|
|
469
|
+
function buildBaseSiftMetadata(body) {
|
|
470
|
+
const {
|
|
471
|
+
event_type,
|
|
472
|
+
session_id,
|
|
473
|
+
user_email,
|
|
474
|
+
name,
|
|
475
|
+
phone,
|
|
476
|
+
sift_payment_method,
|
|
477
|
+
payment_methods,
|
|
478
|
+
billing_address,
|
|
479
|
+
shipping_address,
|
|
480
|
+
app,
|
|
481
|
+
browser,
|
|
482
|
+
verification_phone_number,
|
|
483
|
+
order_id,
|
|
484
|
+
amount,
|
|
485
|
+
currency_code,
|
|
486
|
+
exchange_rate,
|
|
487
|
+
expedited_shipping,
|
|
488
|
+
shipping_method,
|
|
489
|
+
shipping_carrier,
|
|
490
|
+
shipping_tracking_numbers,
|
|
491
|
+
brand_name,
|
|
492
|
+
site_country,
|
|
493
|
+
site_domain,
|
|
494
|
+
ip,
|
|
495
|
+
metadata,
|
|
496
|
+
skip_payment_method_normalization
|
|
497
|
+
} = body;
|
|
498
|
+
const siftMetadata = {
|
|
499
|
+
...metadata ?? {}
|
|
500
|
+
};
|
|
501
|
+
if (session_id !== void 0) siftMetadata.$session_id = session_id;
|
|
502
|
+
if (user_email !== void 0) siftMetadata.$user_email = user_email;
|
|
503
|
+
if (name !== void 0) siftMetadata.$name = name;
|
|
504
|
+
if (phone !== void 0) siftMetadata.$phone = phone;
|
|
505
|
+
if (sift_payment_method !== void 0) {
|
|
506
|
+
if (skip_payment_method_normalization) {
|
|
507
|
+
siftMetadata.$payment_method = toSiftKeyedObject(sift_payment_method);
|
|
508
|
+
} else {
|
|
509
|
+
const result = normalizeSiftPaymentMethod(
|
|
510
|
+
sift_payment_method
|
|
511
|
+
);
|
|
512
|
+
if (result !== null) {
|
|
513
|
+
siftMetadata.$payment_method = toSiftKeyedObject(result.method);
|
|
514
|
+
if (result.metadataExtras) {
|
|
515
|
+
Object.assign(siftMetadata, result.metadataExtras);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if (payment_methods !== void 0) {
|
|
521
|
+
if (skip_payment_method_normalization) {
|
|
522
|
+
siftMetadata.$payment_methods = toSiftKeyedObject(payment_methods);
|
|
523
|
+
} else {
|
|
524
|
+
const { payment_methods: normalized, metadata: pmMetadata } = normalizeSiftPaymentMethods(
|
|
525
|
+
payment_methods
|
|
526
|
+
);
|
|
527
|
+
if (normalized !== void 0) {
|
|
528
|
+
siftMetadata.$payment_methods = toSiftKeyedObject(normalized);
|
|
529
|
+
}
|
|
530
|
+
if (pmMetadata) {
|
|
531
|
+
Object.assign(siftMetadata, pmMetadata);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (billing_address !== void 0) {
|
|
536
|
+
siftMetadata.$billing_address = toSiftKeyedObject(billing_address);
|
|
537
|
+
}
|
|
538
|
+
if (shipping_address !== void 0) {
|
|
539
|
+
siftMetadata.$shipping_address = toSiftKeyedObject(shipping_address);
|
|
540
|
+
}
|
|
541
|
+
if (app !== void 0) siftMetadata.$app = toSiftKeyedObject(app);
|
|
542
|
+
if (browser !== void 0) {
|
|
543
|
+
siftMetadata.$browser = toSiftKeyedObject(browser);
|
|
544
|
+
}
|
|
545
|
+
if (event_type === "$create_order" || event_type === "$update_account") {
|
|
546
|
+
if (verification_phone_number !== void 0) {
|
|
547
|
+
siftMetadata.$verification_phone_number = verification_phone_number;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if (event_type === "$create_order") {
|
|
551
|
+
if (order_id !== void 0) siftMetadata.$order_id = order_id;
|
|
552
|
+
if (amount !== void 0) siftMetadata.$amount = amount;
|
|
553
|
+
if (currency_code !== void 0) siftMetadata.$currency_code = currency_code;
|
|
554
|
+
if (exchange_rate !== void 0) {
|
|
555
|
+
siftMetadata.$exchange_rate = toSiftKeyedObject(exchange_rate);
|
|
556
|
+
}
|
|
557
|
+
if (expedited_shipping !== void 0) siftMetadata.$expedited_shipping = expedited_shipping;
|
|
558
|
+
if (shipping_method !== void 0) siftMetadata.$shipping_method = shipping_method;
|
|
559
|
+
if (shipping_carrier !== void 0) siftMetadata.$shipping_carrier = shipping_carrier;
|
|
560
|
+
if (shipping_tracking_numbers !== void 0) {
|
|
561
|
+
siftMetadata.$shipping_tracking_numbers = shipping_tracking_numbers;
|
|
562
|
+
}
|
|
563
|
+
if (brand_name !== void 0) siftMetadata.$brand_name = brand_name;
|
|
564
|
+
if (site_country !== void 0) siftMetadata.$site_country = site_country;
|
|
565
|
+
if (site_domain !== void 0) siftMetadata.$site_domain = site_domain;
|
|
566
|
+
if (ip !== void 0) siftMetadata.$ip = ip;
|
|
567
|
+
}
|
|
568
|
+
return siftMetadata;
|
|
569
|
+
}
|
|
570
|
+
function normalizeBaseSiftFields(body) {
|
|
571
|
+
const siftMetadata = buildBaseSiftMetadata(body);
|
|
572
|
+
const stripped = stripSdkOnlyFields(body, [...BASE_SIFT_FIELD_KEYS]);
|
|
573
|
+
if (Object.keys(siftMetadata).length > 0) {
|
|
574
|
+
stripped.metadata = siftMetadata;
|
|
575
|
+
}
|
|
576
|
+
return stripped;
|
|
577
|
+
}
|
|
578
|
+
function applyRuleSignals(body, request, keys, stripKeys) {
|
|
579
|
+
const ruleSignals = collectRuleSignals(request, keys);
|
|
580
|
+
const stripped = stripSdkOnlyFields(body, [...stripKeys]);
|
|
581
|
+
if (Object.keys(ruleSignals).length > 0) {
|
|
582
|
+
stripped.metadata = mergeMetadata(
|
|
583
|
+
stripped.metadata,
|
|
584
|
+
ruleSignals
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
return stripped;
|
|
588
|
+
}
|
|
146
589
|
function normalizeUpdatePassword(request) {
|
|
147
590
|
const { password_reason, password_status, metadata, ...rest } = request;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
591
|
+
let body = createStrippedBody(rest, metadata, [
|
|
592
|
+
"password_reason",
|
|
593
|
+
"password_status"
|
|
594
|
+
]);
|
|
595
|
+
const siftMetadata = {
|
|
596
|
+
$reason: password_reason ?? PasswordUpdateReason.UserUpdate,
|
|
597
|
+
$status: password_status ?? PasswordUpdateStatus.Success
|
|
598
|
+
};
|
|
599
|
+
body = applySiftMetadata(body, metadata, siftMetadata);
|
|
600
|
+
return normalizeBaseSiftFields(body);
|
|
153
601
|
}
|
|
154
602
|
function normalizeWager(request) {
|
|
155
603
|
const { wager_type, wager_status, wager_event_type, wager_event_name, wager_event_id, metadata, ...rest } = request;
|
|
156
|
-
|
|
604
|
+
let body = createStrippedBody(rest, metadata, [
|
|
157
605
|
"wager_type",
|
|
158
606
|
"wager_status",
|
|
159
607
|
"wager_event_type",
|
|
@@ -164,17 +612,19 @@ function normalizeWager(request) {
|
|
|
164
612
|
$wager_type: wager_type,
|
|
165
613
|
$wager_status: wager_status
|
|
166
614
|
};
|
|
167
|
-
if (wager_event_type) siftMetadata
|
|
168
|
-
if (wager_event_name) siftMetadata
|
|
169
|
-
if (wager_event_id) siftMetadata
|
|
170
|
-
|
|
615
|
+
if (wager_event_type) siftMetadata.$wager_event_type = wager_event_type;
|
|
616
|
+
if (wager_event_name) siftMetadata.$wager_event_name = wager_event_name;
|
|
617
|
+
if (wager_event_id) siftMetadata.$wager_event_id = wager_event_id;
|
|
618
|
+
body = applySiftMetadata(body, metadata, siftMetadata);
|
|
619
|
+
return normalizeBaseSiftFields(body);
|
|
171
620
|
}
|
|
172
621
|
function normalizeLogin(request) {
|
|
173
622
|
const { login_status, login_failure_reason, metadata, ...rest } = request;
|
|
174
623
|
const effectiveStatus = login_status ?? LoginStatus.Success;
|
|
175
|
-
|
|
624
|
+
let body = createStrippedBody(rest, metadata, [
|
|
176
625
|
"login_status",
|
|
177
|
-
"login_failure_reason"
|
|
626
|
+
"login_failure_reason",
|
|
627
|
+
...LOGIN_RULE_SIGNAL_KEYS
|
|
178
628
|
]);
|
|
179
629
|
const siftMetadata = {
|
|
180
630
|
$login_status: effectiveStatus
|
|
@@ -182,14 +632,22 @@ function normalizeLogin(request) {
|
|
|
182
632
|
if (effectiveStatus === LoginStatus.Failure && login_failure_reason) {
|
|
183
633
|
siftMetadata.$failure_reason = login_failure_reason;
|
|
184
634
|
}
|
|
185
|
-
|
|
635
|
+
body = applySiftMetadata(body, metadata, siftMetadata);
|
|
636
|
+
body = applyRuleSignals(
|
|
637
|
+
body,
|
|
638
|
+
request,
|
|
639
|
+
LOGIN_RULE_SIGNAL_KEYS,
|
|
640
|
+
[]
|
|
641
|
+
);
|
|
642
|
+
return normalizeBaseSiftFields(body);
|
|
186
643
|
}
|
|
187
644
|
function normalizeTransaction(request) {
|
|
188
645
|
const { transaction_status, decline_category, transfer_recipient_user_id, metadata, ...rest } = request;
|
|
189
|
-
|
|
646
|
+
let body = createStrippedBody(rest, metadata, [
|
|
190
647
|
"transaction_status",
|
|
191
648
|
"decline_category",
|
|
192
|
-
"transfer_recipient_user_id"
|
|
649
|
+
"transfer_recipient_user_id",
|
|
650
|
+
...TRANSACTION_RULE_SIGNAL_KEYS
|
|
193
651
|
]);
|
|
194
652
|
const siftMetadata = {};
|
|
195
653
|
if (transaction_status) siftMetadata.$transaction_status = transaction_status;
|
|
@@ -197,7 +655,43 @@ function normalizeTransaction(request) {
|
|
|
197
655
|
if (transfer_recipient_user_id) {
|
|
198
656
|
siftMetadata.$transfer_recipient_user_id = transfer_recipient_user_id;
|
|
199
657
|
}
|
|
200
|
-
|
|
658
|
+
body = applySiftMetadata(body, metadata, siftMetadata, true);
|
|
659
|
+
body = applyRuleSignals(
|
|
660
|
+
body,
|
|
661
|
+
request,
|
|
662
|
+
TRANSACTION_RULE_SIGNAL_KEYS,
|
|
663
|
+
[]
|
|
664
|
+
);
|
|
665
|
+
return normalizeBaseSiftFields(body);
|
|
666
|
+
}
|
|
667
|
+
function normalizeUpdateAccount(request) {
|
|
668
|
+
const { metadata, ...rest } = request;
|
|
669
|
+
let body = createStrippedBody(rest, metadata, [
|
|
670
|
+
...UPDATE_ACCOUNT_RULE_SIGNAL_KEYS
|
|
671
|
+
]);
|
|
672
|
+
body = applyRuleSignals(
|
|
673
|
+
body,
|
|
674
|
+
request,
|
|
675
|
+
UPDATE_ACCOUNT_RULE_SIGNAL_KEYS,
|
|
676
|
+
[]
|
|
677
|
+
);
|
|
678
|
+
return normalizeBaseSiftFields(body);
|
|
679
|
+
}
|
|
680
|
+
function normalizeCreateOrder(request) {
|
|
681
|
+
const { amount, currency_code, metadata, ...rest } = request;
|
|
682
|
+
let body = createStrippedBody(rest, metadata, [
|
|
683
|
+
"amount",
|
|
684
|
+
"currency_code"
|
|
685
|
+
]);
|
|
686
|
+
const siftMetadata = {
|
|
687
|
+
$amount: amount,
|
|
688
|
+
$currency_code: currency_code
|
|
689
|
+
};
|
|
690
|
+
body = applySiftMetadata(body, metadata, siftMetadata);
|
|
691
|
+
return normalizeBaseSiftFields(body);
|
|
692
|
+
}
|
|
693
|
+
function normalizeDefault(request) {
|
|
694
|
+
return normalizeBaseSiftFields({ ...request });
|
|
201
695
|
}
|
|
202
696
|
function normalizeScoreRequestForApi(request) {
|
|
203
697
|
switch (request.event_type) {
|
|
@@ -209,8 +703,12 @@ function normalizeScoreRequestForApi(request) {
|
|
|
209
703
|
return normalizeLogin(request);
|
|
210
704
|
case "$transaction":
|
|
211
705
|
return normalizeTransaction(request);
|
|
706
|
+
case "$update_account":
|
|
707
|
+
return normalizeUpdateAccount(request);
|
|
708
|
+
case "$create_order":
|
|
709
|
+
return normalizeCreateOrder(request);
|
|
212
710
|
default:
|
|
213
|
-
return
|
|
711
|
+
return normalizeDefault(request);
|
|
214
712
|
}
|
|
215
713
|
}
|
|
216
714
|
|
|
@@ -222,6 +720,7 @@ function buildScoreRequestPreview(request) {
|
|
|
222
720
|
// src/types/events.ts
|
|
223
721
|
var SCORED_FRAUD_EVENT_TYPES = [
|
|
224
722
|
"$create_account",
|
|
723
|
+
"$create_order",
|
|
225
724
|
"$login",
|
|
226
725
|
"$logout",
|
|
227
726
|
"$update_account",
|
|
@@ -238,7 +737,6 @@ var PLANNED_FRAUD_EVENT_TYPES = [
|
|
|
238
737
|
"$verification",
|
|
239
738
|
"$link_session_to_user",
|
|
240
739
|
"$security_notification",
|
|
241
|
-
"$create_order",
|
|
242
740
|
"$update_order",
|
|
243
741
|
"$order_status",
|
|
244
742
|
"$add_promotion"
|
|
@@ -251,10 +749,33 @@ function isSupportedFraudEventType(eventType) {
|
|
|
251
749
|
}
|
|
252
750
|
|
|
253
751
|
// src/types/metadata.ts
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
752
|
+
var TYPED_SIFT_METADATA_KEYS = {
|
|
753
|
+
session_id: "$session_id",
|
|
754
|
+
user_email: "$user_email",
|
|
755
|
+
name: "$name",
|
|
756
|
+
phone: "$phone",
|
|
757
|
+
sift_payment_method: "$payment_method",
|
|
758
|
+
billing_address: "$billing_address",
|
|
759
|
+
payment_methods: "$payment_methods",
|
|
760
|
+
app: "$app",
|
|
761
|
+
verification_phone_number: "$verification_phone_number",
|
|
762
|
+
order_id: "$order_id",
|
|
763
|
+
exchange_rate: "$exchange_rate",
|
|
764
|
+
shipping_address: "$shipping_address",
|
|
765
|
+
expedited_shipping: "$expedited_shipping",
|
|
766
|
+
shipping_method: "$shipping_method",
|
|
767
|
+
shipping_carrier: "$shipping_carrier",
|
|
768
|
+
shipping_tracking_numbers: "$shipping_tracking_numbers",
|
|
769
|
+
browser: "$browser",
|
|
770
|
+
brand_name: "$brand_name",
|
|
771
|
+
site_country: "$site_country",
|
|
772
|
+
site_domain: "$site_domain",
|
|
773
|
+
ip: "$ip"
|
|
774
|
+
};
|
|
775
|
+
function findMetadataConflictWithTypedFields(metadata, request) {
|
|
776
|
+
for (const [field, metaKey] of Object.entries(TYPED_SIFT_METADATA_KEYS)) {
|
|
777
|
+
if (request[field] !== void 0 && metadata[metaKey] !== void 0) {
|
|
778
|
+
return metaKey;
|
|
258
779
|
}
|
|
259
780
|
}
|
|
260
781
|
return void 0;
|
|
@@ -280,22 +801,63 @@ function assertPositiveAmount(amount, field, errors, prefix) {
|
|
|
280
801
|
errors.push(`${prefix}${field} must be greater than 0`);
|
|
281
802
|
}
|
|
282
803
|
}
|
|
283
|
-
function validateMetadata(metadata, errors, prefix) {
|
|
804
|
+
function validateMetadata(metadata, request, errors, prefix) {
|
|
284
805
|
if (!metadata) return;
|
|
285
|
-
const
|
|
286
|
-
|
|
806
|
+
const conflictKey = findMetadataConflictWithTypedFields(
|
|
807
|
+
metadata,
|
|
808
|
+
request
|
|
809
|
+
);
|
|
810
|
+
if (conflictKey) {
|
|
287
811
|
errors.push(
|
|
288
|
-
`${prefix}metadata
|
|
812
|
+
`${prefix}metadata.${conflictKey} conflicts with a typed request field that maps to the same key; omit metadata.${conflictKey} or remove the typed field`
|
|
289
813
|
);
|
|
290
814
|
}
|
|
291
815
|
}
|
|
292
816
|
|
|
293
817
|
// src/validation/rules.ts
|
|
818
|
+
var E164_PHONE_PATTERN = /^\+[1-9]\d{7,14}$/;
|
|
819
|
+
function validatePaymentMethods(request, errors, prefix) {
|
|
820
|
+
const { payment_methods, skip_payment_method_normalization: skipNormalization } = request;
|
|
821
|
+
if (payment_methods === void 0) return;
|
|
822
|
+
if (payment_methods.length === 0) {
|
|
823
|
+
errors.push(`${prefix}payment_methods must include at least one item when provided`);
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
payment_methods.forEach((method, index) => {
|
|
827
|
+
const raw = method;
|
|
828
|
+
if (skipNormalization) {
|
|
829
|
+
for (const key of Object.keys(raw)) {
|
|
830
|
+
const plainKey = key.startsWith("$") ? key.slice(1) : key;
|
|
831
|
+
if (!SIFT_PAYMENT_METHOD_WHITELIST.has(plainKey)) {
|
|
832
|
+
errors.push(
|
|
833
|
+
`${prefix}payment_methods[${index}].${plainKey} is not a valid Sift payment method field`
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
const rawType2 = raw.payment_type !== void 0 ? String(raw.payment_type) : void 0;
|
|
838
|
+
if (rawType2 !== void 0 && normalizeSiftPaymentType(rawType2) === void 0) {
|
|
839
|
+
errors.push(
|
|
840
|
+
`${prefix}payment_methods[${index}].payment_type is not a valid Sift payment type`
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const rawType = raw.payment_type !== void 0 ? String(raw.payment_type) : raw.$payment_type !== void 0 ? String(raw.$payment_type) : void 0;
|
|
846
|
+
if (rawType !== void 0) {
|
|
847
|
+
const result = normalizeSiftPaymentMethod(raw);
|
|
848
|
+
if (result === null) {
|
|
849
|
+
errors.push(
|
|
850
|
+
`${prefix}payment_methods[${index}].payment_type is not a valid Sift payment type`
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
}
|
|
294
856
|
function validateBase(request, errors, prefix) {
|
|
295
857
|
assertNonEmpty(request.customer_id, "customer_id", errors, prefix);
|
|
296
858
|
assertNonEmpty(request.sift_user_id, "sift_user_id", errors, prefix);
|
|
297
859
|
assertNonEmpty(request.event_type, "event_type", errors, prefix);
|
|
298
|
-
validateMetadata(request.metadata, errors, prefix);
|
|
860
|
+
validateMetadata(request.metadata, request, errors, prefix);
|
|
299
861
|
}
|
|
300
862
|
function validateLogin(request, errors, prefix) {
|
|
301
863
|
assertEnum(request.login_status, SiftLoginStatusValues, "login_status", errors, prefix);
|
|
@@ -321,9 +883,6 @@ function validateUpdatePassword(request, errors, prefix) {
|
|
|
321
883
|
errors,
|
|
322
884
|
prefix
|
|
323
885
|
);
|
|
324
|
-
if (!request.password_reason) {
|
|
325
|
-
errors.push(`${prefix}password_reason is required`);
|
|
326
|
-
}
|
|
327
886
|
assertEnum(
|
|
328
887
|
request.password_status,
|
|
329
888
|
SiftPasswordUpdateStatusValues,
|
|
@@ -331,9 +890,6 @@ function validateUpdatePassword(request, errors, prefix) {
|
|
|
331
890
|
errors,
|
|
332
891
|
prefix
|
|
333
892
|
);
|
|
334
|
-
if (!request.password_status) {
|
|
335
|
-
errors.push(`${prefix}password_status is required`);
|
|
336
|
-
}
|
|
337
893
|
}
|
|
338
894
|
function validateTransaction(request, errors, prefix) {
|
|
339
895
|
assertPositiveAmount(request.amount, "amount", errors, prefix);
|
|
@@ -367,6 +923,28 @@ function validateWager(request, errors, prefix) {
|
|
|
367
923
|
assertPositiveAmount(request.amount, "amount", errors, prefix);
|
|
368
924
|
assertNonEmpty(request.currency, "currency", errors, prefix);
|
|
369
925
|
}
|
|
926
|
+
function validateCreateAccount(request, errors, prefix) {
|
|
927
|
+
validatePaymentMethods(request, errors, prefix);
|
|
928
|
+
}
|
|
929
|
+
function validateUpdateAccount(request, errors, prefix) {
|
|
930
|
+
validatePaymentMethods(request, errors, prefix);
|
|
931
|
+
if (request.verification_phone_number !== void 0) {
|
|
932
|
+
if (!E164_PHONE_PATTERN.test(request.verification_phone_number.trim())) {
|
|
933
|
+
errors.push(`${prefix}verification_phone_number must be E.164 (e.g. +14155550123)`);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
function validateCreateOrder(request, errors, prefix) {
|
|
938
|
+
assertPositiveAmount(request.amount, "amount", errors, prefix);
|
|
939
|
+
assertNonEmpty(request.currency_code, "currency_code", errors, prefix);
|
|
940
|
+
validatePaymentMethods(request, errors, prefix);
|
|
941
|
+
if (request.shipping_tracking_numbers !== void 0) {
|
|
942
|
+
const hasEmpty = request.shipping_tracking_numbers.some((n) => n.trim() === "");
|
|
943
|
+
if (hasEmpty) {
|
|
944
|
+
errors.push(`${prefix}shipping_tracking_numbers cannot contain empty values`);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
370
948
|
function validateChargeback(request, errors, prefix) {
|
|
371
949
|
const hasTransactionId = !!request.transaction_id?.trim();
|
|
372
950
|
const hasOrderId = !!request.order_id?.trim();
|
|
@@ -401,9 +979,20 @@ function validateByEventType(request, errors, prefix) {
|
|
|
401
979
|
case "$wager":
|
|
402
980
|
validateWager(request, errors, prefix);
|
|
403
981
|
break;
|
|
982
|
+
case "$create_order":
|
|
983
|
+
validateCreateOrder(request, errors, prefix);
|
|
984
|
+
break;
|
|
404
985
|
case "$chargeback":
|
|
405
986
|
validateChargeback(request, errors, prefix);
|
|
406
987
|
break;
|
|
988
|
+
case "$create_account":
|
|
989
|
+
validateCreateAccount(request, errors, prefix);
|
|
990
|
+
break;
|
|
991
|
+
case "$logout":
|
|
992
|
+
break;
|
|
993
|
+
case "$update_account":
|
|
994
|
+
validateUpdateAccount(request, errors, prefix);
|
|
995
|
+
break;
|
|
407
996
|
}
|
|
408
997
|
}
|
|
409
998
|
function validateScoreRequest(request, index) {
|
|
@@ -466,6 +1055,6 @@ var FraudClient = class extends BaseClient {
|
|
|
466
1055
|
}
|
|
467
1056
|
};
|
|
468
1057
|
|
|
469
|
-
export { CHARGEBACK_FRAUD_EVENT_TYPE, ChargebackReason, ChargebackState, FraudClient, LoginStatus, PLANNED_FRAUD_EVENT_TYPES, PasswordUpdateReason, PasswordUpdateStatus, SCORED_FRAUD_EVENT_TYPES, SUPPORTED_FRAUD_EVENT_TYPES, SiftChargebackReasonValues, SiftChargebackStateValues, SiftLoginFailureReasonValues, SiftLoginStatusValues, SiftPasswordUpdateReasonValues, SiftPasswordUpdateStatusValues, SiftTransactionStatusValues, SiftTransactionTypeValues, SiftWagerStatusValues, TransactionStatus, TransactionType, WagerStatus, buildScoreRequestPreview,
|
|
1058
|
+
export { CHARGEBACK_FRAUD_EVENT_TYPE, ChargebackReason, ChargebackState, FraudClient, LOGIN_RULE_SIGNAL_KEYS, LoginStatus, PLANNED_FRAUD_EVENT_TYPES, PasswordUpdateReason, PasswordUpdateStatus, PaymentType, SCORED_FRAUD_EVENT_TYPES, SUPPORTED_FRAUD_EVENT_TYPES, SiftChargebackReasonValues, SiftChargebackStateValues, SiftLoginFailureReasonValues, SiftLoginStatusValues, SiftPasswordUpdateReasonValues, SiftPasswordUpdateStatusValues, SiftPaymentTypeValues, SiftTransactionStatusValues, SiftTransactionTypeValues, SiftWagerStatusValues, SiftWalletTypeValues, TRANSACTION_RULE_SIGNAL_KEYS, TYPED_SIFT_METADATA_KEYS, TransactionStatus, TransactionType, UPDATE_ACCOUNT_RULE_SIGNAL_KEYS, WagerStatus, WalletType, buildScoreRequestPreview, findMetadataConflictWithTypedFields, isPlannedFraudEventType, isSupportedFraudEventType, normalizeScoreRequestForApi, normalizeSiftPaymentMethod, normalizeSiftPaymentMethods, normalizeSiftPaymentType, toSiftAccountNumberLast5, validateScoreRequest };
|
|
470
1059
|
//# sourceMappingURL=index.mjs.map
|
|
471
1060
|
//# sourceMappingURL=index.mjs.map
|