@keverdjs/fraud-sdk 1.0.0 → 2.0.0
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 +9 -2
- package/dist/collectors/audio-fingerprint.d.ts +29 -0
- package/dist/collectors/battery-api.d.ts +28 -0
- package/dist/collectors/behavioral.d.ts +29 -61
- package/dist/collectors/browser-capabilities.d.ts +33 -0
- package/dist/collectors/canvas-fingerprint.d.ts +25 -0
- package/dist/collectors/cpu-memory.d.ts +33 -0
- package/dist/collectors/fingerprint-manager.d.ts +34 -0
- package/dist/collectors/fingerprintjs.d.ts +17 -0
- package/dist/collectors/font-detection.d.ts +23 -0
- package/dist/collectors/form-interactions.d.ts +63 -0
- package/dist/collectors/hardware-signals.d.ts +31 -0
- package/dist/collectors/keystroke-monitor.d.ts +49 -0
- package/dist/collectors/kinematic-engine.d.ts +66 -0
- package/dist/collectors/media-devices.d.ts +24 -0
- package/dist/collectors/page-interactions.d.ts +54 -0
- package/dist/collectors/permissions-api.d.ts +28 -0
- package/dist/collectors/plugin-mime.d.ts +26 -0
- package/dist/collectors/privacy-signals.d.ts +34 -0
- package/dist/collectors/screen-display.d.ts +35 -0
- package/dist/collectors/storage-database.d.ts +50 -0
- package/dist/collectors/timezone-locale.d.ts +38 -0
- package/dist/collectors/touch-pointer.d.ts +34 -0
- package/dist/collectors/visitor-id-generator.d.ts +28 -0
- package/dist/collectors/webgl-fingerprint.d.ts +27 -0
- package/dist/collectors/webrtc-ip.d.ts +26 -0
- package/dist/core/sdk.d.ts +81 -2
- package/dist/fintechrisk.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/types/fingerprint.d.ts +145 -0
- package/dist/types.d.ts +124 -1
- package/package.json +2 -2
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin & MIME Type Collector
|
|
3
|
+
* Safely enumerates plugins and MIME types (privacy-conscious, limited data)
|
|
4
|
+
* Note: Modern browsers have deprecated plugins, but we collect what's available
|
|
5
|
+
*/
|
|
6
|
+
export interface PluginMimeFingerprint {
|
|
7
|
+
plugins: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
mimeTypes: string[];
|
|
11
|
+
}>;
|
|
12
|
+
mimeTypes: string[];
|
|
13
|
+
duration: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class PluginMimeCollector {
|
|
16
|
+
private cachedFingerprint;
|
|
17
|
+
/**
|
|
18
|
+
* Collect plugin and MIME type information
|
|
19
|
+
* Returns null if plugins are not available (modern browsers)
|
|
20
|
+
*/
|
|
21
|
+
collect(): PluginMimeFingerprint | null;
|
|
22
|
+
/**
|
|
23
|
+
* Clear cached fingerprint
|
|
24
|
+
*/
|
|
25
|
+
clearCache(): void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy Signal Collector
|
|
3
|
+
* Detects incognito mode, VPN/proxy, automation/bots, and ad blockers
|
|
4
|
+
*/
|
|
5
|
+
export interface PrivacySignals {
|
|
6
|
+
isIncognito: boolean;
|
|
7
|
+
isVPN: boolean;
|
|
8
|
+
isAutomated: boolean;
|
|
9
|
+
hasAdBlocker: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class PrivacySignalCollector {
|
|
12
|
+
private cachedSignals;
|
|
13
|
+
/**
|
|
14
|
+
* Collect all privacy signals
|
|
15
|
+
*/
|
|
16
|
+
collect(): PrivacySignals;
|
|
17
|
+
/**
|
|
18
|
+
* Detect incognito/private mode
|
|
19
|
+
* Uses multiple detection methods for accuracy
|
|
20
|
+
*/
|
|
21
|
+
private detectIncognito;
|
|
22
|
+
/**
|
|
23
|
+
* Detect automation/bot frameworks
|
|
24
|
+
*/
|
|
25
|
+
private detectAutomation;
|
|
26
|
+
/**
|
|
27
|
+
* Detect ad blocker
|
|
28
|
+
*/
|
|
29
|
+
private detectAdBlocker;
|
|
30
|
+
/**
|
|
31
|
+
* Clear cached signals (useful for testing)
|
|
32
|
+
*/
|
|
33
|
+
clearCache(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screen & Display Collector
|
|
3
|
+
* Collects screen resolution, color depth, pixel ratio, orientation, and multi-monitor info
|
|
4
|
+
*/
|
|
5
|
+
export interface ScreenDisplayFingerprint {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
availWidth: number;
|
|
9
|
+
availHeight: number;
|
|
10
|
+
colorDepth: number;
|
|
11
|
+
pixelDepth: number;
|
|
12
|
+
pixelRatio: number;
|
|
13
|
+
orientation: string | null;
|
|
14
|
+
orientationAngle: number | null;
|
|
15
|
+
duration: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class ScreenDisplayCollector {
|
|
18
|
+
private cachedFingerprint;
|
|
19
|
+
/**
|
|
20
|
+
* Collect screen and display information
|
|
21
|
+
*/
|
|
22
|
+
collect(): ScreenDisplayFingerprint;
|
|
23
|
+
/**
|
|
24
|
+
* Get screen orientation
|
|
25
|
+
*/
|
|
26
|
+
private getOrientation;
|
|
27
|
+
/**
|
|
28
|
+
* Get screen orientation angle
|
|
29
|
+
*/
|
|
30
|
+
private getOrientationAngle;
|
|
31
|
+
/**
|
|
32
|
+
* Clear cached fingerprint
|
|
33
|
+
*/
|
|
34
|
+
clearCache(): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage & Database Collector
|
|
3
|
+
* Detects localStorage, sessionStorage, IndexedDB, WebSQL availability and quotas
|
|
4
|
+
*/
|
|
5
|
+
export interface StorageDatabaseFingerprint {
|
|
6
|
+
localStorage: {
|
|
7
|
+
available: boolean;
|
|
8
|
+
quota: number | null;
|
|
9
|
+
usage: number | null;
|
|
10
|
+
};
|
|
11
|
+
sessionStorage: {
|
|
12
|
+
available: boolean;
|
|
13
|
+
quota: number | null;
|
|
14
|
+
usage: number | null;
|
|
15
|
+
};
|
|
16
|
+
indexedDB: {
|
|
17
|
+
available: boolean;
|
|
18
|
+
};
|
|
19
|
+
webSQL: {
|
|
20
|
+
available: boolean;
|
|
21
|
+
};
|
|
22
|
+
duration: number;
|
|
23
|
+
}
|
|
24
|
+
export declare class StorageDatabaseCollector {
|
|
25
|
+
private cachedFingerprint;
|
|
26
|
+
/**
|
|
27
|
+
* Collect storage and database information
|
|
28
|
+
*/
|
|
29
|
+
collect(): Promise<StorageDatabaseFingerprint>;
|
|
30
|
+
/**
|
|
31
|
+
* Check localStorage availability and quota
|
|
32
|
+
*/
|
|
33
|
+
private checkLocalStorage;
|
|
34
|
+
/**
|
|
35
|
+
* Check sessionStorage availability and quota
|
|
36
|
+
*/
|
|
37
|
+
private checkSessionStorage;
|
|
38
|
+
/**
|
|
39
|
+
* Check IndexedDB availability
|
|
40
|
+
*/
|
|
41
|
+
private checkIndexedDB;
|
|
42
|
+
/**
|
|
43
|
+
* Check WebSQL availability (deprecated but still in some browsers)
|
|
44
|
+
*/
|
|
45
|
+
private checkWebSQL;
|
|
46
|
+
/**
|
|
47
|
+
* Clear cached fingerprint
|
|
48
|
+
*/
|
|
49
|
+
clearCache(): void;
|
|
50
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timezone & Locale Collector
|
|
3
|
+
* Collects timezone, locale, date/time formatting preferences, and calendar system
|
|
4
|
+
*/
|
|
5
|
+
export interface TimezoneLocaleFingerprint {
|
|
6
|
+
timezone: string;
|
|
7
|
+
timezoneOffset: number;
|
|
8
|
+
locale: string;
|
|
9
|
+
locales: string[];
|
|
10
|
+
dateFormat: string;
|
|
11
|
+
timeFormat: string;
|
|
12
|
+
numberFormat: string;
|
|
13
|
+
calendar: string | null;
|
|
14
|
+
duration: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class TimezoneLocaleCollector {
|
|
17
|
+
private cachedFingerprint;
|
|
18
|
+
/**
|
|
19
|
+
* Collect timezone and locale information
|
|
20
|
+
*/
|
|
21
|
+
collect(): TimezoneLocaleFingerprint;
|
|
22
|
+
/**
|
|
23
|
+
* Get date format preference
|
|
24
|
+
*/
|
|
25
|
+
private getDateFormat;
|
|
26
|
+
/**
|
|
27
|
+
* Get time format preference (12h vs 24h)
|
|
28
|
+
*/
|
|
29
|
+
private getTimeFormat;
|
|
30
|
+
/**
|
|
31
|
+
* Get number format preference
|
|
32
|
+
*/
|
|
33
|
+
private getNumberFormat;
|
|
34
|
+
/**
|
|
35
|
+
* Clear cached fingerprint
|
|
36
|
+
*/
|
|
37
|
+
clearCache(): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Touch & Pointer Collector
|
|
3
|
+
* Collects maxTouchPoints, pointer capabilities, touch event support
|
|
4
|
+
*/
|
|
5
|
+
export interface TouchPointerFingerprint {
|
|
6
|
+
maxTouchPoints: number;
|
|
7
|
+
touchSupport: boolean;
|
|
8
|
+
pointerSupport: boolean;
|
|
9
|
+
pointerTypes: string[];
|
|
10
|
+
duration: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class TouchPointerCollector {
|
|
13
|
+
private cachedFingerprint;
|
|
14
|
+
/**
|
|
15
|
+
* Collect touch and pointer information
|
|
16
|
+
*/
|
|
17
|
+
collect(): TouchPointerFingerprint;
|
|
18
|
+
/**
|
|
19
|
+
* Check if touch events are supported
|
|
20
|
+
*/
|
|
21
|
+
private checkTouchSupport;
|
|
22
|
+
/**
|
|
23
|
+
* Check if Pointer Events are supported
|
|
24
|
+
*/
|
|
25
|
+
private checkPointerSupport;
|
|
26
|
+
/**
|
|
27
|
+
* Get available pointer types
|
|
28
|
+
*/
|
|
29
|
+
private getPointerTypes;
|
|
30
|
+
/**
|
|
31
|
+
* Clear cached fingerprint
|
|
32
|
+
*/
|
|
33
|
+
clearCache(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable Visitor ID Generator
|
|
3
|
+
* Combines all fingerprint components into deterministic, stable visitor ID using SHA-256
|
|
4
|
+
* This replaces FingerprintJS visitor ID with our own implementation
|
|
5
|
+
*/
|
|
6
|
+
import { FingerprintComponents } from '../types/fingerprint';
|
|
7
|
+
export declare class VisitorIDGenerator {
|
|
8
|
+
/**
|
|
9
|
+
* Generate a stable visitor ID from fingerprint components
|
|
10
|
+
* Uses SHA-256-like hashing for consistency
|
|
11
|
+
*/
|
|
12
|
+
generate(components: FingerprintComponents): string;
|
|
13
|
+
/**
|
|
14
|
+
* Calculate confidence score based on component availability
|
|
15
|
+
* More components = higher confidence
|
|
16
|
+
*/
|
|
17
|
+
calculateConfidence(components: FingerprintComponents): number;
|
|
18
|
+
/**
|
|
19
|
+
* SHA-256-like hash function
|
|
20
|
+
* Produces a 64-character hex string (matching SHA-256 format)
|
|
21
|
+
*/
|
|
22
|
+
private sha256Hash;
|
|
23
|
+
/**
|
|
24
|
+
* SHA-256-like hash (synchronous, deterministic)
|
|
25
|
+
* Produces 64-character hex string
|
|
26
|
+
*/
|
|
27
|
+
private sha256LikeHash;
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebGL Fingerprint Collector
|
|
3
|
+
* Extracts WebGL vendor, renderer, version, supported extensions, and shader precision
|
|
4
|
+
* This provides hardware-level identification
|
|
5
|
+
*/
|
|
6
|
+
export interface WebGLFingerprint {
|
|
7
|
+
vendor: string | null;
|
|
8
|
+
renderer: string | null;
|
|
9
|
+
version: string | null;
|
|
10
|
+
shadingLanguageVersion: string | null;
|
|
11
|
+
extensions: string[];
|
|
12
|
+
parameters: Record<string, any>;
|
|
13
|
+
precision: Record<string, string>;
|
|
14
|
+
duration: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class WebGLFingerprintCollector {
|
|
17
|
+
private cachedFingerprint;
|
|
18
|
+
/**
|
|
19
|
+
* Generate WebGL fingerprint
|
|
20
|
+
* Returns null if WebGL is not available
|
|
21
|
+
*/
|
|
22
|
+
collect(): WebGLFingerprint | null;
|
|
23
|
+
/**
|
|
24
|
+
* Clear cached fingerprint
|
|
25
|
+
*/
|
|
26
|
+
clearCache(): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebRTC IP Collector
|
|
3
|
+
* Extracts local IP addresses via WebRTC (with privacy considerations and error handling)
|
|
4
|
+
* Note: This requires user interaction and may be blocked by privacy settings
|
|
5
|
+
*/
|
|
6
|
+
export interface WebRTCIPFingerprint {
|
|
7
|
+
localIPs: string[];
|
|
8
|
+
publicIP: string | null;
|
|
9
|
+
duration: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class WebRTCIPCollector {
|
|
12
|
+
private cachedFingerprint;
|
|
13
|
+
/**
|
|
14
|
+
* Collect WebRTC IP information
|
|
15
|
+
* Returns null if WebRTC is not available or fails
|
|
16
|
+
*/
|
|
17
|
+
collect(): Promise<WebRTCIPFingerprint | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Check if an IP is a local/private IP
|
|
20
|
+
*/
|
|
21
|
+
private isLocalIP;
|
|
22
|
+
/**
|
|
23
|
+
* Clear cached fingerprint
|
|
24
|
+
*/
|
|
25
|
+
clearCache(): void;
|
|
26
|
+
}
|
package/dist/core/sdk.d.ts
CHANGED
|
@@ -8,13 +8,27 @@ export declare class KeverdSDK {
|
|
|
8
8
|
private config;
|
|
9
9
|
private deviceCollector;
|
|
10
10
|
private behavioralCollector;
|
|
11
|
+
private fingerprintManager;
|
|
12
|
+
private privacySignalCollector;
|
|
13
|
+
private browserCapabilityCollector;
|
|
14
|
+
private hardwareSignalCollector;
|
|
15
|
+
private formInteractionCollector;
|
|
16
|
+
private pageInteractionCollector;
|
|
11
17
|
private isInitialized;
|
|
12
18
|
private sessionId;
|
|
19
|
+
private ghostInterval;
|
|
20
|
+
private ghostStartTime;
|
|
21
|
+
private ghostSignalCount;
|
|
22
|
+
private readonly MIN_GHOST_SIGNALS;
|
|
23
|
+
private readonly MAX_GHOST_COLLECTION_TIME;
|
|
13
24
|
constructor();
|
|
14
25
|
/**
|
|
15
26
|
* Initialize the SDK with configuration
|
|
16
27
|
*/
|
|
17
28
|
init(config: SDKConfig | string): void;
|
|
29
|
+
private startGhostSignalCollection;
|
|
30
|
+
private stopGhostSignalCollection;
|
|
31
|
+
private sendGhostSignals;
|
|
18
32
|
/**
|
|
19
33
|
* Get visitor data (fingerprint and risk assessment)
|
|
20
34
|
* This is the main method for getting risk scores
|
|
@@ -24,7 +38,31 @@ export declare class KeverdSDK {
|
|
|
24
38
|
* Create transaction ID with risk assessment (legacy method)
|
|
25
39
|
* For new implementations, use getVisitorData() instead
|
|
26
40
|
*/
|
|
27
|
-
createTransactionID(
|
|
41
|
+
createTransactionID(_metadata?: TransactionMetadata): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Verify user identity during login attempts
|
|
44
|
+
*/
|
|
45
|
+
verifyLogin(userId?: string, metadata?: Record<string, unknown>): Promise<FingerprintResponse>;
|
|
46
|
+
/**
|
|
47
|
+
* Verify user during checkout/payment
|
|
48
|
+
*/
|
|
49
|
+
verifyCheckout(amount?: number, currency?: string, metadata?: Record<string, unknown>): Promise<FingerprintResponse>;
|
|
50
|
+
/**
|
|
51
|
+
* Detect fake/bot registrations
|
|
52
|
+
*/
|
|
53
|
+
verifyRegistration(metadata?: Record<string, unknown>): Promise<FingerprintResponse>;
|
|
54
|
+
/**
|
|
55
|
+
* Detect account takeover attempts during password reset
|
|
56
|
+
*/
|
|
57
|
+
verifyPasswordReset(email?: string, metadata?: Record<string, unknown>): Promise<FingerprintResponse>;
|
|
58
|
+
/**
|
|
59
|
+
* Verify sensitive account changes (email, phone, password)
|
|
60
|
+
*/
|
|
61
|
+
verifyAccountChange(changeType?: string, metadata?: Record<string, unknown>): Promise<FingerprintResponse>;
|
|
62
|
+
/**
|
|
63
|
+
* Helper to send verify request to use-case-specific endpoint
|
|
64
|
+
*/
|
|
65
|
+
private sendVerifyRequest;
|
|
28
66
|
/**
|
|
29
67
|
* Send fingerprint request to backend
|
|
30
68
|
*/
|
|
@@ -33,9 +71,50 @@ export declare class KeverdSDK {
|
|
|
33
71
|
* Generate a unique session ID
|
|
34
72
|
*/
|
|
35
73
|
private generateSessionId;
|
|
74
|
+
/**
|
|
75
|
+
* Detect browser name from user agent
|
|
76
|
+
*/
|
|
77
|
+
private _detectBrowser;
|
|
78
|
+
/**
|
|
79
|
+
* Detect OS from user agent
|
|
80
|
+
*/
|
|
81
|
+
private _detectOS;
|
|
82
|
+
/**
|
|
83
|
+
* Start a new session (called automatically on init, but can be called manually)
|
|
84
|
+
*/
|
|
85
|
+
startSession(userId?: string, deviceHash?: string, metadata?: Record<string, unknown>): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* End the current session
|
|
88
|
+
*/
|
|
89
|
+
endSession(): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Pause the current session (e.g., when app goes to background)
|
|
92
|
+
*/
|
|
93
|
+
pauseSession(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Resume a paused session (e.g., when app comes to foreground)
|
|
96
|
+
*/
|
|
97
|
+
resumeSession(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Get current session status
|
|
100
|
+
*/
|
|
101
|
+
getSessionStatus(): Promise<{
|
|
102
|
+
session_id: string;
|
|
103
|
+
status: string;
|
|
104
|
+
is_active: boolean;
|
|
105
|
+
is_paused: boolean;
|
|
106
|
+
event_count: number;
|
|
107
|
+
started_at: string;
|
|
108
|
+
last_activity_at: string;
|
|
109
|
+
duration_seconds: number | null;
|
|
110
|
+
} | null>;
|
|
36
111
|
/**
|
|
37
112
|
* Destroy the SDK instance
|
|
38
113
|
*/
|
|
39
|
-
destroy(): void
|
|
114
|
+
destroy(): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Check if SDK is initialized and ready to use
|
|
117
|
+
*/
|
|
118
|
+
isReady(): boolean;
|
|
40
119
|
}
|
|
41
120
|
export declare const Keverd: KeverdSDK;
|
package/dist/fintechrisk.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.FintechRisk=e():t.FintechRisk=e()}(this,()=>(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"t",{value:!0})}},e={};t.r(e),t.d(e,{BehavioralCollector:()=>s,DeviceCollector:()=>i,Keverd:()=>r,KeverdSDK:()=>n});class i{constructor(){this.cachedDeviceInfo=null}collect(){if(this.cachedDeviceInfo)return this.cachedDeviceInfo;const t=this.generateDeviceFingerprint(),e=this.generateDeviceId(t);return this.cachedDeviceInfo={deviceId:e,fingerprint:t,manufacturer:this.getManufacturer(),model:this.getModel(),brand:this.getBrand(),device:this.getDevice(),product:this.getProduct(),hardware:this.getHardware(),sdkVersion:"1.0.0",osVersion:this.getOSVersion(),screenWidth:String(screen.width),screenHeight:String(screen.height),screenDensity:this.getScreenDensity(),locale:navigator.language||navigator.languages?.[0]||"en",timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},this.cachedDeviceInfo}generateDeviceFingerprint(){const t=[],e=this.getCanvasFingerprint();e&&t.push(e);const i=this.getWebGLFingerprint();if(i&&t.push(i),t.push(navigator.userAgent),t.push(navigator.language||navigator.languages?.[0]||""),t.push(`${screen.width}x${screen.height}x${screen.colorDepth}`),t.push(String((new Date).getTimezoneOffset())),t.push(navigator.platform),t.push(String(navigator.hardwareConcurrency||0)),"deviceMemory"in navigator&&t.push(String(navigator.deviceMemory)),"maxTouchPoints"in navigator&&t.push(String(navigator.maxTouchPoints)),navigator.plugins&&navigator.plugins.length>0){const e=Array.from(navigator.plugins).slice(0,3).map(t=>t.name).join(",");t.push(e)}const s=t.join("|");return this.hashString(s)}getCanvasFingerprint(){try{const t=document.createElement("canvas"),e=t.getContext("2d");return e?(t.width=200,t.height=50,e.textBaseline="top",e.font="14px Arial",e.fillStyle="#f60",e.fillRect(125,1,62,20),e.fillStyle="#069",e.fillText("KeverdFingerprint",2,15),e.fillStyle="rgba(102, 204, 0, 0.7)",e.fillText("KeverdFingerprint",4,17),this.hashString(t.toDataURL())):""}catch(t){return""}}getWebGLFingerprint(){try{const t=document.createElement("canvas"),e=t.getContext("webgl")||t.getContext("experimental-webgl");if(!e)return"";const i=e.getExtension("WEBGL_debug_renderer_info");if(i){const t=e.getParameter(i.UNMASKED_VENDOR_WEBGL),s=e.getParameter(i.UNMASKED_RENDERER_WEBGL);return this.hashString(`${t}|${s}`)}const s=e.getParameter(e.VERSION),n=e.getParameter(e.VENDOR);return this.hashString(`${s}|${n}`)}catch(t){return""}}generateDeviceId(t){return t.substring(0,32)}getManufacturer(){const t=navigator.userAgent.toLowerCase();if(t.includes("iphone")||t.includes("ipad"))return"Apple";if(t.includes("android")){const e=t.match(/(?:^|\s)([a-z]+)(?:\s|$)/);return e?e[1].charAt(0).toUpperCase()+e[1].slice(1):void 0}}getModel(){const t=navigator.userAgent.match(/(iPhone|iPad|Android)[\s\/]+([\w]+)/i);return t?t[2]:void 0}getBrand(){return this.getManufacturer()}getDevice(){const t=navigator.userAgent.toLowerCase();return t.includes("mobile")?"mobile":t.includes("tablet")?"tablet":"desktop"}getProduct(){const t=navigator.userAgent.match(/(iPhone|iPad|Android|Windows|Mac|Linux)/i);return t?t[1]:void 0}getHardware(){const t=navigator.userAgent.match(/\(([^)]+)\)/);return t?t[1]:void 0}getOSVersion(){const t=navigator.userAgent,e=[/OS\s+([\d_]+)/i,/Android\s+([\d.]+)/i,/Windows\s+([\d.]+)/i,/Mac\s+OS\s+X\s+([\d_]+)/i,/Linux/i];for(const i of e){const e=t.match(i);if(e)return e[1]?.replace(/_/g,".")||e[0]}}getScreenDensity(){if(window.devicePixelRatio)return String(window.devicePixelRatio)}hashString(t){return this.sha256LikeHash(t)}sha256LikeHash(t){const e=[];let i=5381;for(let e=0;e<t.length;e++)i=(i<<5)+i+t.charCodeAt(e),i&=4294967295;e.push(i);let s=0;for(let e=t.length-1;e>=0;e--)s=(s<<7)-s+t.charCodeAt(e),s&=4294967295;e.push(s);let n=0;for(let e=0;e<t.length;e++)n^=t.charCodeAt(e)<<e%4*8,n&=4294967295;e.push(n);let r=0;for(let e=0;e<t.length;e++)r=31*r+t.charCodeAt(e)&4294967295;e.push(r);let o=0;for(let e=0;e<t.length;e++){o=o+(4294967295&(t.charCodeAt(e)<<e%16|t.charCodeAt(e)>>>32-e%16))&4294967295}e.push(o);let h=2166136261;for(let e=0;e<t.length;e++)h=16777619*(h^t.charCodeAt(e)),h&=4294967295;e.push(h);let a=0;for(let e=0;e<t.length;e++)a=a+t.charCodeAt(e)*(e+1)&4294967295;e.push(a);let c=0;for(let e=0;e<t.length;e+=2){c=(c<<3)-c+(t.charCodeAt(e)+256*(t.charCodeAt(e+1)||0)),c&=4294967295}e.push(c);return e.map(t=>Math.abs(t).toString(16).padStart(8,"0")).join("").substring(0,64).padEnd(64,"0")}clearCache(){this.cachedDeviceInfo=null}}class s{constructor(){this.keystrokes=[],this.mouseMovements=[],this.lastKeyDownTime=new Map,this.lastKeyUpTime=null,this.isActive=!1,this.sessionStartTime=Date.now(),this.typingDwellTimes=[],this.typingFlightTimes=[],this.swipeVelocities=[],this.sessionEvents=[],this.touchStartPositions=new Map,this.keyDownHandler=t=>this.handleKeyDown(t),this.keyUpHandler=t=>this.handleKeyUp(t),this.mouseMoveHandler=t=>this.handleMouseMove(t),this.touchStartHandler=t=>this.handleTouchStart(t),this.touchEndHandler=t=>this.handleTouchEnd(t)}start(){this.isActive||("undefined"!=typeof document&&(document.addEventListener("keydown",this.keyDownHandler,{passive:!0}),document.addEventListener("keyup",this.keyUpHandler,{passive:!0}),document.addEventListener("mousemove",this.mouseMoveHandler,{passive:!0}),document.addEventListener("touchstart",this.touchStartHandler,{passive:!0}),document.addEventListener("touchend",this.touchEndHandler,{passive:!0})),this.isActive=!0,this.sessionStartTime=Date.now())}stop(){this.isActive&&("undefined"!=typeof document&&(document.removeEventListener("keydown",this.keyDownHandler),document.removeEventListener("keyup",this.keyUpHandler),document.removeEventListener("mousemove",this.mouseMoveHandler),document.removeEventListener("touchstart",this.touchStartHandler),document.removeEventListener("touchend",this.touchEndHandler)),this.isActive=!1)}getData(){const t=this.typingDwellTimes.slice(-20),e=this.typingFlightTimes.slice(-20),i=this.swipeVelocities.length>0?this.swipeVelocities.reduce((t,e)=>t+e,0)/this.swipeVelocities.length:0,s=this.calculateSessionEntropy();return{typing_dwell_ms:t.length>0?t:[],typing_flight_ms:e.length>0?e:[],swipe_velocity:i>0?i:0,session_entropy:s>=0?s:0}}reset(){this.keystrokes=[],this.mouseMovements=[],this.lastKeyDownTime.clear(),this.lastKeyUpTime=null,this.typingDwellTimes=[],this.typingFlightTimes=[],this.swipeVelocities=[],this.sessionEvents=[],this.touchStartPositions.clear(),this.sessionStartTime=Date.now()}handleKeyDown(t){if(this.shouldIgnoreKey(t))return;const e=performance.now();this.lastKeyDownTime.set(t.key,e);const i={key:t.key,timestamp:e,type:"keydown"};this.keystrokes.push(i),this.sessionEvents.push({type:"keydown",timestamp:e})}handleKeyUp(t){if(this.shouldIgnoreKey(t))return;const e=performance.now(),i=this.lastKeyDownTime.get(t.key);if(void 0!==i){const s=e-i;this.typingDwellTimes.push(s),this.lastKeyDownTime.delete(t.key)}if(null!==this.lastKeyUpTime){const t=e-this.lastKeyUpTime;this.typingFlightTimes.push(t)}this.lastKeyUpTime=e;const s={key:t.key,timestamp:e,type:"keyup"};this.keystrokes.push(s),this.sessionEvents.push({type:"keyup",timestamp:e})}handleMouseMove(t){const e={x:t.clientX,y:t.clientY,timestamp:performance.now(),type:"move"};if(this.mouseMovements.length>0){const t=this.mouseMovements[this.mouseMovements.length-1],i=e.timestamp-t.timestamp;if(i>0){const s=Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2));e.velocity=s/i}}this.mouseMovements.push(e),this.sessionEvents.push({type:"mousemove",timestamp:e.timestamp})}handleTouchStart(t){const e=performance.now();for(let i=0;i<t.touches.length;i++){const s=t.touches[i];this.touchStartPositions.set(s.identifier,{x:s.clientX,y:s.clientY,timestamp:e})}this.sessionEvents.push({type:"touchstart",timestamp:e})}handleTouchEnd(t){const e=performance.now();for(let i=0;i<t.changedTouches.length;i++){const s=t.changedTouches[i],n=this.touchStartPositions.get(s.identifier);if(n){const t=e-n.timestamp;if(t>0&&t<1e3){const e=Math.sqrt(Math.pow(s.clientX-n.x,2)+Math.pow(s.clientY-n.y,2));if(e>10){const i=e/t;this.swipeVelocities.push(i)}}this.touchStartPositions.delete(s.identifier)}}this.sessionEvents.push({type:"touchend",timestamp:e})}calculateSessionEntropy(){if(0===this.sessionEvents.length)return 0;const t={};for(const e of this.sessionEvents)t[e.type]=(t[e.type]||0)+1;const e=this.sessionEvents.length;let i=0;for(const s of Object.values(t)){const t=s/e;t>0&&(i-=t*Math.log2(t))}return i}shouldIgnoreKey(t){return["Shift","Control","Alt","Meta","CapsLock","Tab","Escape","Enter","ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End","PageUp","PageDown","F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12"].includes(t.key)}}class n{constructor(){this.config=null,this.isInitialized=!1,this.sessionId=null,this.deviceCollector=new i,this.behavioralCollector=new s}init(t){this.isInitialized?this.config:(this.config="string"==typeof t?{apiKey:t,endpoint:"https://app.keverd.com",debug:!1}:{endpoint:"https://app.keverd.com",debug:!1,...t},this.behavioralCollector.start(),this.sessionId=this.generateSessionId(),this.isInitialized=!0,this.config.debug)}async getVisitorData(){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");try{const t=this.deviceCollector.collect(),e=this.behavioralCollector.getData(),i={sessionId:this.sessionId||void 0,timestamp:(new Date).toISOString()},s={userId:this.config.userId,device:t,session:i,behavioral:e};return await this.sendFingerprintRequest(s)}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw this.config.debug,new Error(`Failed to get visitor data: ${e}`)}}async createTransactionID(t){return(await this.getVisitorData()).session_id}async sendFingerprintRequest(t){if(!this.config)throw new Error("SDK not initialized");const e=`${this.config.endpoint||"https://app.keverd.com"}/fingerprint/score`,i={"Content-Type":"application/json","X-SDK-Source":"javascript"},s=this.config.apiKey;s&&(i["x-keverd-key"]=s,i["X-API-KEY"]=s,i.Authorization=`Bearer ${s}`);const n=await fetch(e,{method:"POST",headers:i,body:JSON.stringify(t)});if(!n.ok){const t=await n.text().catch(()=>"Unknown error");throw new Error(`HTTP ${n.status}: ${t}`)}return await n.json()}generateSessionId(){return`${Date.now()}_${Math.random().toString(36).substr(2,9)}`}destroy(){this.behavioralCollector.stop(),this.isInitialized=!1,this.config,this.config=null,this.sessionId=null}}const r=new n;return e})());
|
|
1
|
+
!function(t,i){"object"==typeof exports&&"object"==typeof module?module.exports=i():"function"==typeof define&&define.amd?define([],i):"object"==typeof exports?exports.FintechRisk=i():t.FintechRisk=i()}(this,()=>(()=>{"use strict";var t={d:(i,e)=>{for(var s in e)t.o(e,s)&&!t.o(i,s)&&Object.defineProperty(i,s,{enumerable:!0,get:e[s]})},o:(t,i)=>Object.prototype.hasOwnProperty.call(t,i),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"t",{value:!0})}},i={};t.r(i),t.d(i,{BehavioralCollector:()=>a,DeviceCollector:()=>e,FingerprintJSCollector:()=>O,Keverd:()=>P,KeverdSDK:()=>x,KeystrokeMonitor:()=>n,KinematicEngine:()=>s});class e{constructor(){this.cachedDeviceInfo=null}collect(){if(this.cachedDeviceInfo)return this.cachedDeviceInfo;const t=this.generateDeviceFingerprint(),i=this.generateDeviceId(t);return this.cachedDeviceInfo={deviceId:i,fingerprint:t,manufacturer:this.getManufacturer(),model:this.getModel(),brand:this.getBrand(),device:this.getDevice(),product:this.getProduct(),hardware:this.getHardware(),sdkVersion:"1.0.0",osVersion:this.getOSVersion(),screenWidth:String(screen.width),screenHeight:String(screen.height),screenDensity:this.getScreenDensity(),locale:navigator.language||navigator.languages?.[0]||"en",timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},this.cachedDeviceInfo}generateDeviceFingerprint(){const t=[],i=this.getCanvasFingerprint();i&&t.push(i);const e=this.getWebGLFingerprint();if(e&&t.push(e),t.push(navigator.userAgent),t.push(navigator.language||navigator.languages?.[0]||""),t.push(`${screen.width}x${screen.height}x${screen.colorDepth}`),t.push(String((new Date).getTimezoneOffset())),t.push(navigator.platform),t.push(String(navigator.hardwareConcurrency||0)),"deviceMemory"in navigator&&t.push(String(navigator.deviceMemory)),"maxTouchPoints"in navigator&&t.push(String(navigator.maxTouchPoints)),navigator.plugins&&navigator.plugins.length>0){const i=Array.from(navigator.plugins).slice(0,3).map(t=>t.name).join(",");t.push(i)}const s=t.join("|");return this.hashString(s)}getCanvasFingerprint(){try{const t=document.createElement("canvas"),i=t.getContext("2d");return i?(t.width=200,t.height=50,i.textBaseline="top",i.font="14px Arial",i.fillStyle="#f60",i.fillRect(125,1,62,20),i.fillStyle="#069",i.fillText("KeverdFingerprint",2,15),i.fillStyle="rgba(102, 204, 0, 0.7)",i.fillText("KeverdFingerprint",4,17),this.hashString(t.toDataURL())):""}catch(t){return""}}getWebGLFingerprint(){try{const t=document.createElement("canvas"),i=t.getContext("webgl")||t.getContext("experimental-webgl");if(!i)return"";const e=i.getExtension("WEBGL_debug_renderer_info");if(e){const t=i.getParameter(e.UNMASKED_VENDOR_WEBGL),s=i.getParameter(e.UNMASKED_RENDERER_WEBGL);return this.hashString(`${t}|${s}`)}const s=i.getParameter(i.VERSION),n=i.getParameter(i.VENDOR);return this.hashString(`${s}|${n}`)}catch(t){return""}}generateDeviceId(t){return t.substring(0,32)}getManufacturer(){const t=navigator.userAgent.toLowerCase();if(t.includes("iphone")||t.includes("ipad"))return"Apple";if(t.includes("android")){const i=t.match(/(?:^|\s)([a-z]+)(?:\s|$)/);return i?i[1].charAt(0).toUpperCase()+i[1].slice(1):void 0}}getModel(){const t=navigator.userAgent.match(/(iPhone|iPad|Android)[\s\/]+([\w]+)/i);return t?t[2]:void 0}getBrand(){return this.getManufacturer()}getDevice(){const t=navigator.userAgent.toLowerCase();return t.includes("mobile")?"mobile":t.includes("tablet")?"tablet":"desktop"}getProduct(){const t=navigator.userAgent.match(/(iPhone|iPad|Android|Windows|Mac|Linux)/i);return t?t[1]:void 0}getHardware(){const t=navigator.userAgent.match(/\(([^)]+)\)/);return t?t[1]:void 0}getOSVersion(){const t=navigator.userAgent,i=[/OS\s+([\d_]+)/i,/Android\s+([\d.]+)/i,/Windows\s+([\d.]+)/i,/Mac\s+OS\s+X\s+([\d_]+)/i,/Linux/i];for(const e of i){const i=t.match(e);if(i)return i[1]?.replace(/_/g,".")||i[0]}}getScreenDensity(){if(window.devicePixelRatio)return String(window.devicePixelRatio)}hashString(t){return this.sha256LikeHash(t)}sha256LikeHash(t){const i=[];let e=5381;for(let i=0;i<t.length;i++)e=(e<<5)+e+t.charCodeAt(i),e&=4294967295;i.push(e);let s=0;for(let i=t.length-1;i>=0;i--)s=(s<<7)-s+t.charCodeAt(i),s&=4294967295;i.push(s);let n=0;for(let i=0;i<t.length;i++)n^=t.charCodeAt(i)<<i%4*8,n&=4294967295;i.push(n);let r=0;for(let i=0;i<t.length;i++)r=31*r+t.charCodeAt(i)&4294967295;i.push(r);let o=0;for(let i=0;i<t.length;i++){o=o+(4294967295&(t.charCodeAt(i)<<i%16|t.charCodeAt(i)>>>32-i%16))&4294967295}i.push(o);let a=2166136261;for(let i=0;i<t.length;i++)a=16777619*(a^t.charCodeAt(i)),a&=4294967295;i.push(a);let h=0;for(let i=0;i<t.length;i++)h=h+t.charCodeAt(i)*(i+1)&4294967295;i.push(h);let c=0;for(let i=0;i<t.length;i+=2){c=(c<<3)-c+(t.charCodeAt(i)+256*(t.charCodeAt(i+1)||0)),c&=4294967295}i.push(c);return i.map(t=>Math.abs(t).toString(16).padStart(8,"0")).join("").substring(0,64).padEnd(64,"0")}clearCache(){this.cachedDeviceInfo=null}}class s{constructor(t={}){this.featureVectors=[],this.pointerQueue=[],this.lastVelocity=0,this.lastAcceleration=0,this.lastAngle=0,this.lastPoint=null,this.secondLastPoint=null,this.rafId=null,this.maxSwipeVelocity=0,this.isActive=!1,this.clickCount=0,this.rightClickCount=0,this.doubleClickCount=0,this.totalMouseDistance=0,this.lastClickTime=0,this.scrollDistance=0,this.lastScrollTop=0,this.touchEventCount=0,this.mouseMoveHandler=t=>this.enqueuePoint(t,"move"),this.mouseDownHandler=t=>{this.enqueuePoint(t,"down"),this.handleClick(t)},this.mouseUpHandler=t=>this.enqueuePoint(t,"up"),this.contextMenuHandler=t=>this.handleRightClick(t),this.scrollHandler=()=>this.handleScroll(),this.touchStartHandler=()=>this.handleTouch(),this.touchMoveHandler=()=>this.handleTouch(),this.touchEndHandler=()=>this.handleTouch(),this.onEvent=t.onEvent,this.maskValue=t.maskValue??-1}start(){this.isActive||"undefined"==typeof document||(document.addEventListener("mousemove",this.mouseMoveHandler,{passive:!0}),document.addEventListener("mousedown",this.mouseDownHandler,{passive:!0}),document.addEventListener("mouseup",this.mouseUpHandler,{passive:!0}),document.addEventListener("contextmenu",this.contextMenuHandler,{passive:!0}),window.addEventListener("scroll",this.scrollHandler,{passive:!0}),document.addEventListener("touchstart",this.touchStartHandler,{passive:!0}),document.addEventListener("touchmove",this.touchMoveHandler,{passive:!0}),document.addEventListener("touchend",this.touchEndHandler,{passive:!0}),this.lastScrollTop=window.pageYOffset||document.documentElement.scrollTop,this.isActive=!0)}stop(){this.isActive&&"undefined"!=typeof document&&(document.removeEventListener("mousemove",this.mouseMoveHandler),document.removeEventListener("mousedown",this.mouseDownHandler),document.removeEventListener("mouseup",this.mouseUpHandler),document.removeEventListener("contextmenu",this.contextMenuHandler),window.removeEventListener("scroll",this.scrollHandler),document.removeEventListener("touchstart",this.touchStartHandler),document.removeEventListener("touchmove",this.touchMoveHandler),document.removeEventListener("touchend",this.touchEndHandler),null!==this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.isActive=!1)}getVectors(){return this.featureVectors}getSuspiciousSwipeVelocity(){return this.maxSwipeVelocity}getMouseSignals(){const t=this.featureVectors.length>0?this.featureVectors.reduce((t,i)=>t+i.velocity,0)/this.featureVectors.length:0,i=window.pageYOffset||document.documentElement.scrollTop,e=Math.abs(i-this.lastScrollTop),s=i>this.lastScrollTop?"down":"up";return{totalDistance:this.totalMouseDistance,averageVelocity:t,clickCount:this.clickCount,rightClickCount:this.rightClickCount,doubleClickCount:this.doubleClickCount,scrollDistance:this.scrollDistance+e,scrollDirection:s,touchEvents:this.touchEventCount}}reset(){this.featureVectors=[],this.pointerQueue=[],this.lastVelocity=0,this.lastAcceleration=0,this.lastAngle=0,this.lastPoint=null,this.secondLastPoint=null,this.maxSwipeVelocity=0,this.clickCount=0,this.rightClickCount=0,this.doubleClickCount=0,this.totalMouseDistance=0,this.lastClickTime=0,this.scrollDistance=0,this.lastScrollTop=0,this.touchEventCount=0}enqueuePoint(t,i){const e={x:t.clientX,y:t.clientY,timestamp:performance.now(),type:i};this.pointerQueue.push(e),this.pointerQueue.length>200&&this.pointerQueue.shift(),this.onEvent&&this.onEvent("move"===i?"mousemove":"down"===i?"mousedown":"mouseup"),this.scheduleProcess()}scheduleProcess(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.processQueue(),this.pointerQueue.length>0&&this.scheduleProcess()}))}processQueue(){for(;this.pointerQueue.length>0;){const t=this.pointerQueue.shift();this.computeFeatures(t),this.secondLastPoint=this.lastPoint,this.lastPoint=t}}computeFeatures(t){if(!this.lastPoint)return this.lastPoint=t,void(this.lastAngle=0);const i=t.timestamp-this.lastPoint.timestamp;if(i<=0)return;const e=t.x-this.lastPoint.x,s=t.y-this.lastPoint.y,n=Math.sqrt(e*e+s*s);this.totalMouseDistance+=n;const r=n/i,o=(r-this.lastVelocity)/i,a=(o-this.lastAcceleration)/i,h=Math.atan2(s,e),c=this.normalizeAngle(h-this.lastAngle)/i,l=this.calculateCurvature(t);this.featureVectors.push({timestamp:t.timestamp,velocity:r,acceleration:o,jerk:a,curvature:l,angularVelocity:c}),this.maxSwipeVelocity=Math.max(this.maxSwipeVelocity,r),r>2.5&&this.featureVectors.push({timestamp:t.timestamp,velocity:r,acceleration:o,jerk:a,curvature:l,angularVelocity:1.2*c}),this.featureVectors.length>200&&this.featureVectors.splice(0,this.featureVectors.length-200),this.lastVelocity=r,this.lastAcceleration=o,this.lastAngle=h}calculateCurvature(t){if(!this.lastPoint||!this.secondLastPoint)return 0;const i=this.secondLastPoint,e=this.lastPoint,s=t,n=Math.hypot(s.x-i.x,s.y-i.y),r=Math.hypot(e.x-i.x,e.y-i.y)+Math.hypot(s.x-e.x,s.y-e.y);return 0===n?0:(r-n)/n}normalizeAngle(t){for(;t>Math.PI;)t-=2*Math.PI;for(;t<-Math.PI;)t+=2*Math.PI;return t}handleClick(t){const i=performance.now();i-this.lastClickTime<500?this.doubleClickCount++:this.clickCount++,this.lastClickTime=i}handleRightClick(t){this.rightClickCount++}handleScroll(){const t=window.pageYOffset||document.documentElement.scrollTop,i=Math.abs(t-this.lastScrollTop);this.scrollDistance+=i,this.lastScrollTop=t}handleTouch(){this.touchEventCount++}}class n{constructor(t={}){this.keyDownTimes=new Map,this.lastKeyUpTime=null,this.lastKeyDownTime=null,this.featureVectors=[],this.dwellTimes=[],this.flightTimes=[],this.digraphLatencies=[],this.isActive=!1,this.keydownCount=0,this.keyupCount=0,this.specialKeyCount=0,this.lastKeystrokeTime=null,this.pauseCount=0,this.PAUSE_THRESHOLD=2e3,this.keystrokeTimestamps=[],this.keyDownHandler=t=>this.handleKeyDown(t),this.keyUpHandler=t=>this.handleKeyUp(t),this.onEvent=t.onEvent}start(){this.isActive||"undefined"==typeof document||(document.addEventListener("keydown",this.keyDownHandler,{passive:!0,capture:!0}),document.addEventListener("keyup",this.keyUpHandler,{passive:!0,capture:!0}),this.isActive=!0)}stop(){this.isActive&&"undefined"!=typeof document&&(document.removeEventListener("keydown",this.keyDownHandler,!0),document.removeEventListener("keyup",this.keyUpHandler,!0),this.isActive=!1)}getVectors(){return this.featureVectors}getDwellTimes(t=50){return this.dwellTimes.slice(-t)}getFlightTimes(t=50){return this.flightTimes.slice(-t)}getKeyboardSignals(){let t=0;if(this.keystrokeTimestamps.length>1){const i=(this.keystrokeTimestamps[this.keystrokeTimestamps.length-1]-this.keystrokeTimestamps[0])/6e4;i>0&&(t=this.keystrokeTimestamps.length/i)}const i=this.keydownCount,e=i>0?this.getBackspaceCount()/i:0;return{keydownCount:this.keydownCount,keyupCount:this.keyupCount,specialKeyCount:this.specialKeyCount,typingSpeed:t,pauseCount:this.pauseCount,backspaceRatio:e}}getBackspaceCount(){return 0}reset(){this.keyDownTimes.clear(),this.lastKeyUpTime=null,this.lastKeyDownTime=null,this.featureVectors=[],this.dwellTimes=[],this.flightTimes=[],this.digraphLatencies=[],this.keydownCount=0,this.keyupCount=0,this.specialKeyCount=0,this.lastKeystrokeTime=null,this.pauseCount=0,this.keystrokeTimestamps=[]}handleKeyDown(t){if(!this.isTargetField(t))return;const i=performance.now();if(this.keydownCount++,this.keystrokeTimestamps.push(i),(t.ctrlKey||t.altKey||t.shiftKey||t.metaKey)&&this.specialKeyCount++,null!==this.lastKeystrokeTime&&i-this.lastKeystrokeTime>this.PAUSE_THRESHOLD&&this.pauseCount++,this.lastKeystrokeTime=i,null!==this.lastKeyUpTime){const t=i-this.lastKeyUpTime;this.flightTimes.push(t),this.appendVector({dwellTime:-1,flightTime:t,digraphLatency:-1,timestamp:i})}if(null!==this.lastKeyDownTime){const t=i-this.lastKeyDownTime;this.digraphLatencies.push(t),this.appendVector({dwellTime:-1,flightTime:-1,digraphLatency:t,timestamp:i})}this.lastKeyDownTime=i,this.keyDownTimes.set(t.code,i),this.onEvent&&this.onEvent("keydown")}handleKeyUp(t){if(!this.isTargetField(t))return;const i=performance.now();this.keyupCount++;const e=this.keyDownTimes.get(t.code);if(void 0!==e){const s=i-e;this.dwellTimes.push(s),this.appendVector({dwellTime:s,flightTime:-1,digraphLatency:-1,timestamp:i}),this.keyDownTimes.delete(t.code)}this.lastKeyUpTime=i,this.onEvent&&this.onEvent("keyup")}appendVector(t){this.featureVectors.push(t),this.featureVectors.length>200&&this.featureVectors.splice(0,this.featureVectors.length-200)}isTargetField(t){const i=t.target;if(!i)return!1;return i.isContentEditable||["INPUT","TEXTAREA"].includes(i.tagName)}}const r=-1,o=["velocity","acceleration","jerk","curvature","angularVelocity","dwell","flight","digraphLatency"];class a{constructor(){this.isActive=!1,this.sessionEvents=[],this.trackEvent=t=>{this.sessionEvents.push({type:t,timestamp:performance.now()}),this.sessionEvents.length>500&&this.sessionEvents.shift()},this.kinematicEngine=new s({onEvent:this.trackEvent}),this.keystrokeMonitor=new n({onEvent:this.trackEvent})}start(){this.isActive||(this.kinematicEngine.start(),this.keystrokeMonitor.start(),this.isActive=!0)}stop(){this.isActive&&(this.kinematicEngine.stop(),this.keystrokeMonitor.stop(),this.isActive=!1)}reset(){this.sessionEvents=[],this.kinematicEngine.reset(),this.keystrokeMonitor.reset()}getData(){const t=this.kinematicEngine.getVectors(),i=this.keystrokeMonitor.getVectors(),e=[...t.map(t=>({timestamp:t.timestamp,values:[t.velocity,t.acceleration,t.jerk,t.curvature,t.angularVelocity,r,r,r]})),...i.map(t=>({timestamp:t.timestamp,values:[r,r,r,r,r,t.dwellTime,t.flightTime,t.digraphLatency]}))].sort((t,i)=>t.timestamp-i.timestamp),s=this.buildSequence(e),n=this.kinematicEngine.getSuspiciousSwipeVelocity(),o=this.calculateSessionEntropy();return{typing_dwell_ms:this.keystrokeMonitor.getDwellTimes(),typing_flight_ms:this.keystrokeMonitor.getFlightTimes(),swipe_velocity:n,suspicious_swipe_velocity:n,session_entropy:o,behavioral_vectors:s}}buildSequence(t){const i=[],e=Math.max(0,t.length-50),s=t.slice(e);for(const t of s)i.push(t.values);for(;i.length<50;)i.unshift(new Array(o.length).fill(r));return{featureNames:[...o],windowSize:50,maskValue:r,sequence:i}}calculateSessionEntropy(){if(0===this.sessionEvents.length)return 0;const t={};this.sessionEvents.forEach(i=>{t[i.type]=(t[i.type]||0)+1});const i=this.sessionEvents.length;return Object.values(t).reduce((t,e)=>{const s=e/i;return s>0?t-s*Math.log2(s):t},0)}getMouseSignals(){return this.kinematicEngine.getMouseSignals()}getKeyboardSignals(){return this.keystrokeMonitor.getKeyboardSignals()}}class h{constructor(){this.cachedFingerprint=null}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{const i=document.createElement("canvas");i.width=200,i.height=50;const e=i.getContext("2d");if(!e)return null;e.textBaseline="top",e.font="14px Arial",e.textBaseline="alphabetic",e.fillStyle="#f60",e.fillRect(125,1,62,20),e.fillStyle="#069",e.fillText("KeverdFingerprint",2,15),e.fillStyle="rgba(102, 204, 0, 0.7)",e.fillText("KeverdFingerprint",4,17);const s=e.createLinearGradient(0,0,200,50);s.addColorStop(0,"rgba(255, 0, 0, 0.5)"),s.addColorStop(1,"rgba(0, 0, 255, 0.5)"),e.fillStyle=s,e.fillRect(0,0,200,50),e.strokeStyle="#000",e.lineWidth=2,e.beginPath(),e.arc(100,25,20,0,2*Math.PI),e.stroke(),e.font="12px Verdana",e.fillStyle="#000",e.fillText("CanvasFP",150,30);const n=i.toDataURL(),r=this.hashString(n),o=performance.now()-t;return this.cachedFingerprint={value:r,duration:Math.round(100*o)/100},this.cachedFingerprint}catch(t){return null}}hashString(t){let i=0;for(let e=0;e<t.length;e++){i=(i<<5)-i+t.charCodeAt(e),i&=i}return Math.abs(i).toString(16).padStart(8,"0")}clearCache(){this.cachedFingerprint=null}}class c{constructor(){this.cachedFingerprint=null}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{const i=document.createElement("canvas"),e=i.getContext("webgl")||i.getContext("experimental-webgl");if(!e)return null;const s=e.getExtension("WEBGL_debug_renderer_info");let n=null,r=null;s?(n=e.getParameter(s.UNMASKED_VENDOR_WEBGL)||null,r=e.getParameter(s.UNMASKED_RENDERER_WEBGL)||null):(n=e.getParameter(e.VENDOR)||null,r=e.getParameter(e.RENDERER)||null);const o=e.getParameter(e.VERSION)||null,a=e.getParameter(e.SHADING_LANGUAGE_VERSION)||null,h=[];try{const t=e.getSupportedExtensions();t&&h.push(...t)}catch(t){}const c={maxTextureSize:e.getParameter(e.MAX_TEXTURE_SIZE),maxVertexAttribs:e.getParameter(e.MAX_VERTEX_ATTRIBS),maxViewportDims:e.getParameter(e.MAX_VIEWPORT_DIMS),maxTextureImageUnits:e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),maxCombinedTextureImageUnits:e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS),maxFragmentUniformVectors:e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),maxVaryingVectors:e.getParameter(e.MAX_VARYING_VECTORS),aliasedLineWidthRange:e.getParameter(e.ALIASED_LINE_WIDTH_RANGE),aliasedPointSizeRange:e.getParameter(e.ALIASED_POINT_SIZE_RANGE)},l={};try{const t=e.createShader(e.VERTEX_SHADER);if(t){e.shaderSource(t,"precision mediump float;"),e.compileShader(t);const i=e.createShader(e.FRAGMENT_SHADER);i&&(e.shaderSource(i,"precision mediump float;"),e.compileShader(i),l.float=e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)?.precision?.toString()||"unknown",l.int=e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT)?.precision?.toString()||"unknown")}}catch(t){}const u=performance.now()-t;return this.cachedFingerprint={vendor:n,renderer:r,version:o,shadingLanguageVersion:a,extensions:h.sort(),parameters:c,precision:l,duration:Math.round(100*u)/100},this.cachedFingerprint}catch(t){return null}}clearCache(){this.cachedFingerprint=null}}class l{constructor(){this.cachedFingerprint=null}async collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{const i=window.AudioContext||window.webkitAudioContext||window.mozAudioContext;if(!i)return null;const e=new i,s=e.createOscillator(),n=e.createAnalyser(),r=e.createGain(),o=e.createScriptProcessor(4096,1,1);return n.fftSize=2048,n.smoothingTimeConstant=.8,s.connect(n),n.connect(o),o.connect(r),r.connect(e.destination),s.type="triangle",s.frequency.value=1e4,new Promise(i=>{const n=[];let a=0;o.onaudioprocess=r=>{const o=r.inputBuffer.getChannelData(0);let h=0;for(let t=0;t<o.length;t++)h+=o[t]*o[t];const c=Math.sqrt(h/o.length);if(n.push(c),a++,a>=5){s.stop(),e.close();const r=this.calculateFingerprint(n),o=performance.now()-t;this.cachedFingerprint={value:r,duration:Math.round(100*o)/100},i(this.cachedFingerprint)}},s.start(0),r.gain.value=0,setTimeout(()=>{if(!this.cachedFingerprint){s.stop(),e.close();const n=this.getFallbackFingerprint(e),r=performance.now()-t;this.cachedFingerprint={value:n,duration:Math.round(100*r)/100},i(this.cachedFingerprint)}},1e3)})}catch(t){return null}}calculateFingerprint(t){if(0===t.length)return 0;const i=t.reduce((t,i)=>t+i,0)/t.length,e=t.reduce((t,e)=>t+Math.pow(e-i,2),0)/t.length,s=Math.sqrt(e),n=1e6*i+1e3*s+t.length;return Math.round(100*n)/100}getFallbackFingerprint(t){const i=t.sampleRate||44100,e=t.state||"unknown",s=(i.toString()+e).split("").reduce((t,i)=>(t<<5)-t+i.charCodeAt(0),0);return Math.abs(s)}clearCache(){this.cachedFingerprint=null}}class u{constructor(){this.cachedFingerprint=null,this.testFonts=["Arial","Verdana","Times New Roman","Courier New","Georgia","Palatino","Garamond","Bookman","Comic Sans MS","Trebuchet MS","Arial Black","Impact","Tahoma","Lucida Console","Lucida Sans Unicode","MS Sans Serif","MS Serif","Symbol","Webdings","Wingdings","Monaco","Menlo","Consolas","Courier","Helvetica","Helvetica Neue","Roboto","Open Sans","Lato","Montserrat"]}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{const i=document.createElement("canvas").getContext("2d");if(!i)return null;const e="monospace",s="mmmmmmmmmmlli",n="72px";i.font=`${n} ${e}`;const r=i.measureText(s).width,o=[],a=[];for(const t of this.testFonts){i.font=`${n} ${t}, ${e}`;const h=i.measureText(s).width;Math.abs(h-r)>1?o.push(t):a.push(t)}const h=performance.now()-t;return this.cachedFingerprint={availableFonts:o.sort(),missingFonts:a.sort(),duration:Math.round(100*h)/100},this.cachedFingerprint}catch(t){return null}}clearCache(){this.cachedFingerprint=null}}class d{constructor(){this.cachedFingerprint=null}async collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{if(!navigator.mediaDevices||!navigator.mediaDevices.enumerateDevices)return null;let i=!1;try{const t=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1});i=!0,t.getTracks().forEach(t=>t.stop())}catch(t){i=!1}const e=await navigator.mediaDevices.enumerateDevices(),s=[],n=[],r=[];e.forEach(t=>{const e={deviceId:t.deviceId,kind:t.kind,label:i?t.label:"",groupId:t.groupId,toJSON:()=>({deviceId:t.deviceId,kind:t.kind,label:i?t.label:"",groupId:t.groupId})};switch(t.kind){case"audioinput":s.push(e);break;case"audiooutput":n.push(e);break;case"videoinput":r.push(e)}});const o=performance.now()-t;return this.cachedFingerprint={audioInputs:s,audioOutputs:n,videoInputs:r,hasPermission:i,duration:Math.round(100*o)/100},this.cachedFingerprint}catch(t){return null}}clearCache(){this.cachedFingerprint=null}}class m{constructor(){this.cachedFingerprint=null}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now(),i={width:screen.width,height:screen.height,availWidth:screen.availWidth,availHeight:screen.availHeight,colorDepth:screen.colorDepth,pixelDepth:screen.pixelDepth,pixelRatio:window.devicePixelRatio||1,orientation:this.getOrientation(),orientationAngle:this.getOrientationAngle(),duration:0};return i.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=i,i}getOrientation(){if("orientation"in screen){const t=screen.orientation;if(t&&t.type)return t.type}if("orientation"in window){const t=window.orientation;if(void 0!==t){if(0===t||180===t)return"portrait";if(90===t||-90===t)return"landscape"}}if(window.matchMedia){if(window.matchMedia("(orientation: portrait)").matches)return"portrait";if(window.matchMedia("(orientation: landscape)").matches)return"landscape"}return null}getOrientationAngle(){if("orientation"in screen){const t=screen.orientation;if(t&&"number"==typeof t.angle)return t.angle}if("orientation"in window){const t=window.orientation;if("number"==typeof t)return t}return null}clearCache(){this.cachedFingerprint=null}}class p{constructor(){this.cachedFingerprint=null}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now(),i=Intl.DateTimeFormat().resolvedOptions().timeZone,e=(new Date).getTimezoneOffset(),s=Intl.DateTimeFormat().resolvedOptions(),n=s.locale,r=navigator.languages||[navigator.language],o=this.getDateFormat(),a=this.getTimeFormat(),h=this.getNumberFormat(),c=s.calendar||null,l={timezone:i,timezoneOffset:e,locale:n,locales:r.slice(0,5),dateFormat:o,timeFormat:a,numberFormat:h,calendar:c,duration:0};return l.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=l,l}getDateFormat(){try{const t=(new Intl.DateTimeFormat).format(new Date(2023,0,15));return t.includes("/")?"numeric":t.includes("-")?"iso":t.includes(".")?"european":"unknown"}catch{return"unknown"}}getTimeFormat(){try{const t=new Intl.DateTimeFormat(void 0,{hour:"numeric",minute:"numeric"}).format(new Date(2023,0,15,13,30));return t.toLowerCase().includes("am")||t.toLowerCase().includes("pm")?"12h":"24h"}catch{return"unknown"}}getNumberFormat(){try{const t=(new Intl.NumberFormat).format(1234.56);return t.includes(",")?"european":t.includes(".")?"american":"unknown"}catch{return"unknown"}}clearCache(){this.cachedFingerprint=null}}class g{constructor(){this.cachedFingerprint=null}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{if(!navigator.plugins||0===navigator.plugins.length)return null;const i=[],e=new Set;for(let t=0;t<Math.min(navigator.plugins.length,10);t++){const s=navigator.plugins[t];if(!s)continue;const n=[];for(let t=0;t<Math.min(s.length,5);t++){const i=s[t];i&&i.type&&(n.push(i.type),e.add(i.type))}i.push({name:s.name||"Unknown",description:s.description||"",mimeTypes:n})}const s={plugins:i,mimeTypes:Array.from(e).sort(),duration:0};return s.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=s,s}catch(t){return null}}clearCache(){this.cachedFingerprint=null}}class w{constructor(){this.cachedFingerprint=null}async collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{const i=await this.getBatteryManager();if(!i)return null;const e={level:i.level,charging:i.charging,chargingTime:i.chargingTime,dischargingTime:i.dischargingTime,duration:0};return e.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=e,e}catch(t){return null}}async getBatteryManager(){if("getBattery"in navigator)try{return await navigator.getBattery()}catch(t){}if("webkitGetBattery"in navigator)try{return await navigator.webkitGetBattery()}catch(t){}if("mozGetBattery"in navigator)try{return await navigator.mozGetBattery()}catch(t){}return null}clearCache(){this.cachedFingerprint=null}}class f{constructor(){this.cachedFingerprint=null}async collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now(),i={localStorage:await this.checkLocalStorage(),sessionStorage:await this.checkSessionStorage(),indexedDB:this.checkIndexedDB(),webSQL:this.checkWebSQL(),duration:0};return i.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=i,i}async checkLocalStorage(){let t=!1,i=null,e=null;try{const s="__localStorage_test__";if(localStorage.setItem(s,s),localStorage.removeItem(s),t=!0,"storage"in navigator&&"estimate"in navigator.storage)try{const t=await navigator.storage.estimate();t&&(i=t.quota||null,e=t.usage||null)}catch(t){}}catch(i){t=!1}return{available:t,quota:i,usage:e}}async checkSessionStorage(){let t=!1,i=null,e=null;try{const s="__sessionStorage_test__";if(sessionStorage.setItem(s,s),sessionStorage.removeItem(s),t=!0,"storage"in navigator&&"estimate"in navigator.storage)try{const t=await navigator.storage.estimate();t&&(i=t.quota||null,e=t.usage||null)}catch(t){}}catch(i){t=!1}return{available:t,quota:i,usage:e}}checkIndexedDB(){return{available:"indexedDB"in window&&!!window.indexedDB}}checkWebSQL(){return{available:"openDatabase"in window&&!!window.openDatabase}}clearCache(){this.cachedFingerprint=null}}class v{constructor(){this.cachedFingerprint=null}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now(),i={hardwareConcurrency:navigator.hardwareConcurrency||0,deviceMemory:this.getDeviceMemory(),performanceMemory:this.getPerformanceMemory(),duration:0};return i.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=i,i}getDeviceMemory(){return"deviceMemory"in navigator&&navigator.deviceMemory?navigator.deviceMemory:null}getPerformanceMemory(){if("memory"in performance){const t=performance.memory;return{jsHeapSizeLimit:t.jsHeapSizeLimit||null,totalJSHeapSize:t.totalJSHeapSize||null,usedJSHeapSize:t.usedJSHeapSize||null}}return{jsHeapSizeLimit:null,totalJSHeapSize:null,usedJSHeapSize:null}}clearCache(){this.cachedFingerprint=null}}class y{constructor(){this.cachedFingerprint=null}collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now(),i={maxTouchPoints:navigator.maxTouchPoints||0,touchSupport:this.checkTouchSupport(),pointerSupport:this.checkPointerSupport(),pointerTypes:this.getPointerTypes(),duration:0};return i.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=i,i}checkTouchSupport(){return"ontouchstart"in window||navigator.maxTouchPoints>0||!!window.DocumentTouch&&document instanceof window.DocumentTouch}checkPointerSupport(){return"PointerEvent"in window||"MSPointerEvent"in window}getPointerTypes(){const t=[];return"PointerEvent"in window&&(navigator.maxTouchPoints>0&&t.push("touch"),t.push("mouse"),"pen"in navigator&&t.push("pen")),t}clearCache(){this.cachedFingerprint=null}}class S{constructor(){this.cachedFingerprint=null}async collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{if(!("permissions"in navigator))return null;const i=navigator.permissions,e={camera:await this.queryPermission(i,"camera"),microphone:await this.queryPermission(i,"microphone"),notifications:await this.queryPermission(i,"notifications"),geolocation:await this.queryPermission(i,"geolocation"),persistentStorage:await this.queryPermission(i,"persistent-storage"),duration:0};return e.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=e,e}catch(t){return null}}async queryPermission(t,i){try{return(await t.query({name:i})).state||null}catch(t){return null}}clearCache(){this.cachedFingerprint=null}}class b{constructor(){this.cachedFingerprint=null}async collect(){if(this.cachedFingerprint)return this.cachedFingerprint;const t=performance.now();try{const i=window.RTCPeerConnection||window.webkitRTCPeerConnection||window.mozRTCPeerConnection;if(!i)return null;const e=[];let s=null;const n=new i({iceServers:[{urls:"stun:stun.l.google.com:19302"}]});n.onicecandidate=t=>{if(t.candidate){const i=t.candidate.candidate.match(/([0-9]{1,3}\.){3}[0-9]{1,3}/);if(i){const t=i[0];this.isLocalIP(t)?e.includes(t)||e.push(t):s=t}}},n.createDataChannel("");const r=await n.createOffer();await n.setLocalDescription(r),await new Promise(t=>{const i=setTimeout(()=>{t()},2e3);n.onicegatheringstatechange=()=>{"complete"===n.iceGatheringState&&(clearTimeout(i),t())},"complete"===n.iceGatheringState&&(clearTimeout(i),t())}),n.close();const o={localIPs:e.sort(),publicIP:s,duration:0};return o.duration=Math.round(100*(performance.now()-t))/100,this.cachedFingerprint=o,o}catch(t){return null}}isLocalIP(t){if("127.0.0.1"===t||"::1"===t)return!0;const i=t.split(".");if(4===i.length){const t=parseInt(i[0],10),e=parseInt(i[1],10);if(10===t)return!0;if(172===t&&e>=16&&e<=31)return!0;if(192===t&&168===e)return!0;if(169===t&&254===e)return!0}return!1}clearCache(){this.cachedFingerprint=null}}class C{generate(t){const i=[];t.canvas?.value&&i.push(`canvas:${t.canvas.value}`),t.webgl&&(t.webgl.vendor&&i.push(`webgl_vendor:${t.webgl.vendor}`),t.webgl.renderer&&i.push(`webgl_renderer:${t.webgl.renderer}`),t.webgl.extensions.length>0&&i.push(`webgl_ext:${t.webgl.extensions.slice(0,10).join(",")}`)),t.audio?.value&&i.push(`audio:${t.audio.value}`),t.screen&&(i.push(`screen:${t.screen.width}x${t.screen.height}x${t.screen.pixelRatio}`),i.push(`color:${t.screen.colorDepth}`)),t.timezone&&(i.push(`tz:${t.timezone.timezone}`),i.push(`locale:${t.timezone.locale}`)),t.cpu&&(i.push(`cpu:${t.cpu.hardwareConcurrency}`),t.cpu.deviceMemory&&i.push(`memory:${t.cpu.deviceMemory}`)),t.touch&&i.push(`touch:${t.touch.maxTouchPoints}`),i.push(`ua:${navigator.userAgent}`),i.push(`lang:${navigator.language}`),i.push(`platform:${navigator.platform}`),t.fonts&&t.fonts.availableFonts.length>0&&i.push(`fonts:${t.fonts.availableFonts.slice(0,20).join(",")}`);const e=i.join("|");return this.sha256Hash(e)}calculateConfidence(t){let i=0,e=0;const s={canvas:20,webgl:20,audio:15,screen:10,timezone:10,cpu:10,fonts:10,touch:5,storage:5,permissions:5,webrtc:5,mediaDevices:5,battery:3,plugins:3};return Object.keys(s).forEach(n=>{e+=s[n],t[n]&&(i+=s[n])}),e>0?Math.min(i/e,1):0}sha256Hash(t){return"undefined"!=typeof crypto&&crypto.subtle,this.sha256LikeHash(t)}sha256LikeHash(t){const i=[];let e=5381;for(let i=0;i<t.length;i++)e=(e<<5)+e+t.charCodeAt(i),e&=4294967295;i.push(e);let s=0;for(let i=t.length-1;i>=0;i--)s=(s<<7)-s+t.charCodeAt(i),s&=4294967295;i.push(s);let n=0;for(let i=0;i<t.length;i++)n^=t.charCodeAt(i)<<i%4*8,n&=4294967295;i.push(n);let r=0;for(let i=0;i<t.length;i++)r=31*r+t.charCodeAt(i)&4294967295;i.push(r);let o=0;for(let i=0;i<t.length;i++){o=o+(4294967295&(t.charCodeAt(i)<<i%16|t.charCodeAt(i)>>>32-i%16))&4294967295}i.push(o);let a=2166136261;for(let i=0;i<t.length;i++)a=16777619*(a^t.charCodeAt(i)),a&=4294967295;i.push(a);let h=0;for(let i=0;i<t.length;i++)h=h+t.charCodeAt(i)*(i+1)&4294967295;i.push(h);let c=0;for(let i=0;i<t.length;i+=2){c=(c<<3)-c+(t.charCodeAt(i)+256*(t.charCodeAt(i+1)||0)),c&=4294967295}i.push(c);return i.map(t=>Math.abs(t).toString(16).padStart(8,"0")).join("").substring(0,64).padEnd(64,"0")}}class k{constructor(){this.cachedData=null,this.collectionStartTime=0,this.collectors={canvas:new h,webgl:new c,audio:new l,fonts:new u,mediaDevices:new d,screen:new m,timezone:new p,plugins:new g,battery:new w,storage:new f,cpu:new v,touch:new y,permissions:new S,webrtc:new b},this.visitorIDGenerator=new C}async collect(){if(this.cachedData)return this.cachedData;this.collectionStartTime=performance.now();const t={};try{t.canvas=this.collectors.canvas.collect()||void 0}catch(t){}try{t.webgl=this.collectors.webgl.collect()||void 0}catch(t){}try{t.fonts=this.collectors.fonts.collect()||void 0}catch(t){}try{t.screen=this.collectors.screen.collect()}catch(t){}try{t.timezone=this.collectors.timezone.collect()}catch(t){}try{t.plugins=this.collectors.plugins.collect()||void 0}catch(t){}try{t.cpu=this.collectors.cpu.collect()}catch(t){}try{t.touch=this.collectors.touch.collect()}catch(t){}try{t.audio=await this.collectors.audio.collect()||void 0}catch(t){}try{t.mediaDevices=await this.collectors.mediaDevices.collect()||void 0}catch(t){}try{t.battery=await this.collectors.battery.collect()||void 0}catch(t){}try{t.storage=await this.collectors.storage.collect()}catch(t){}try{t.permissions=await this.collectors.permissions.collect()||void 0}catch(t){}try{t.webrtc=await this.collectors.webrtc.collect()||void 0}catch(t){}const i=this.visitorIDGenerator.generate(t),e=this.visitorIDGenerator.calculateConfidence(t);return this.cachedData={visitorId:i,confidence:Math.round(1e3*e)/1e3,components:t,version:"1.0.0",timestamp:Date.now()},this.cachedData}async getVisitorId(){return(await this.collect()).visitorId}clearCache(){this.cachedData=null,Object.values(this.collectors).forEach(t=>{t&&"function"==typeof t.clearCache&&t.clearCache()})}getStats(){if(!this.cachedData)return{componentsCollected:0,totalComponents:13,collectionTime:0};const t=Object.keys(this.cachedData.components).length,i=performance.now()-this.collectionStartTime;return{componentsCollected:t,totalComponents:13,collectionTime:Math.round(100*i)/100}}}class M{constructor(){this.cachedSignals=null}collect(){if(this.cachedSignals)return this.cachedSignals;const t={isIncognito:this.detectIncognito(),isVPN:!1,isAutomated:this.detectAutomation(),hasAdBlocker:this.detectAdBlocker()};return this.cachedSignals=t,t}detectIncognito(){try{if("storage"in navigator&&"estimate"in navigator.storage)try{navigator.storage.estimate().then(()=>{}).catch(()=>{})}catch{return!0}if("storage"in navigator&&navigator.storage,navigator,window.chrome&&window.chrome.runtime&&!window.chrome.runtime.onConnect)return!0;try{const t="__incognito_test__";localStorage.setItem(t,"test"),localStorage.removeItem(t)}catch{return!0}return!1}catch(t){return!1}}detectAutomation(){try{if(!0===navigator.webdriver)return!0;if(window.chrome&&window.chrome.runtime&&window.chrome.runtime.onConnect){if(window.chrome.runtime.onConnect.hasListeners())return!0}if(!(window.chrome||window.safari||window.Notification&&window.DeviceMotionEvent))return!0;try{const t=document.createElement("canvas"),i=t.getContext("2d");if(i){i.textBaseline="top",i.font="14px Arial",i.fillText("Automation test",2,2);if(t.toDataURL().length<100)return!0}}catch{}return!!(window.__nightmare||window.__phantomas||window.Buffer)}catch(t){return!1}}detectAdBlocker(){try{const t=document.createElement("div");t.innerHTML=" ",t.className="adsbox",t.style.position="absolute",t.style.left="-9999px",document.body.appendChild(t),setTimeout(()=>{const i=0===t.offsetHeight||0===t.offsetWidth;return document.body.removeChild(t),i},100);const i=Array.from(document.getElementsByTagName("script"));return i.filter(t=>t.src&&t.src.includes("ads")&&!t.textContent).length>0||!!(window.uBlock||window.adblock||window.BlockAdBlock)}catch(t){return!1}}clearCache(){this.cachedSignals=null}}class T{constructor(){this.cachedCapabilities=null}collect(){if(this.cachedCapabilities)return this.cachedCapabilities;const t={hasWebGL:this.checkWebGL(),hasCanvas:this.checkCanvas(),hasWebRTC:this.checkWebRTC(),hasServiceWorker:this.checkServiceWorker(),hasIndexedDB:this.checkIndexedDB(),hasLocalStorage:this.checkLocalStorage(),hasSessionStorage:this.checkSessionStorage(),cookieEnabled:navigator.cookieEnabled,doNotTrack:"1"===navigator.doNotTrack||"yes"===navigator.doNotTrack};return this.cachedCapabilities=t,t}checkWebGL(){try{const t=document.createElement("canvas");return!(!t.getContext("webgl")&&!t.getContext("experimental-webgl"))}catch{return!1}}checkCanvas(){try{return!!document.createElement("canvas").getContext("2d")}catch{return!1}}checkWebRTC(){return!!((window.RTCPeerConnection||window.webkitRTCPeerConnection||window.mozRTCPeerConnection)&&navigator.mediaDevices&&navigator.mediaDevices.getUserMedia)}checkServiceWorker(){return"serviceWorker"in navigator}checkIndexedDB(){return"indexedDB"in window}checkLocalStorage(){try{const t="__localStorage_test__";return localStorage.setItem(t,t),localStorage.removeItem(t),!0}catch{return!1}}checkSessionStorage(){try{const t="__sessionStorage_test__";return sessionStorage.setItem(t,t),sessionStorage.removeItem(t),!0}catch{return!1}}clearCache(){this.cachedCapabilities=null}}class D{constructor(){this.cachedSignals=null}collect(){if(this.cachedSignals)return this.cachedSignals;const t={hardwareConcurrency:navigator.hardwareConcurrency||0,deviceMemory:this.getDeviceMemory(),maxTouchPoints:navigator.maxTouchPoints||0,connectionType:this.getConnectionType(),effectiveType:this.getEffectiveType(),downlink:this.getDownlink(),rtt:this.getRTT(),saveData:this.getSaveData()};return this.cachedSignals=t,t}getDeviceMemory(){return"deviceMemory"in navigator&&navigator.deviceMemory?navigator.deviceMemory:null}getConnectionType(){const t=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return t&&t.type?t.type:null}getEffectiveType(){const t=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return t&&t.effectiveType?t.effectiveType:null}getDownlink(){const t=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return t&&t.downlink?t.downlink:null}getRTT(){const t=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return t&&t.rtt?t.rtt:null}getSaveData(){const t=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return t&&void 0!==t.saveData?t.saveData:null}clearCache(){this.cachedSignals=null}}class _{constructor(){this.focusCount=0,this.blurCount=0,this.copyCount=0,this.pasteCount=0,this.cutCount=0,this.fieldFocusOrder=[],this.fieldFocusTimes=new Map,this.backspaceCount=0,this.deleteCount=0,this.autofillDetected=!1,this.autocompleteDetected=!1,this.isActive=!1,this.focusHandler=t=>this.handleFocus(t),this.blurHandler=t=>this.handleBlur(t),this.copyHandler=t=>this.handleCopy(t),this.pasteHandler=t=>this.handlePaste(t),this.cutHandler=t=>this.handleCut(t),this.keydownHandler=t=>this.handleKeyDown(t),this.inputHandler=t=>this.handleInput(t)}start(){this.isActive||"undefined"==typeof document||(document.addEventListener("focus",this.focusHandler,!0),document.addEventListener("blur",this.blurHandler,!0),document.addEventListener("copy",this.copyHandler,!0),document.addEventListener("paste",this.pasteHandler,!0),document.addEventListener("cut",this.cutHandler,!0),document.addEventListener("keydown",this.keydownHandler,!0),document.addEventListener("input",this.inputHandler,!0),this.isActive=!0)}stop(){this.isActive&&"undefined"!=typeof document&&(document.removeEventListener("focus",this.focusHandler,!0),document.removeEventListener("blur",this.blurHandler,!0),document.removeEventListener("copy",this.copyHandler,!0),document.removeEventListener("paste",this.pasteHandler,!0),document.removeEventListener("cut",this.cutHandler,!0),document.removeEventListener("keydown",this.keydownHandler,!0),document.removeEventListener("input",this.inputHandler,!0),this.isActive=!1)}getData(){const t={};return this.fieldFocusTimes.forEach((i,e)=>{t[e]=i}),{focusCount:this.focusCount,blurCount:this.blurCount,copyCount:this.copyCount,pasteCount:this.pasteCount,cutCount:this.cutCount,autofillDetected:this.autofillDetected,autocompleteDetected:this.autocompleteDetected,fieldFocusOrder:[...this.fieldFocusOrder],timePerField:t,backspaceCount:this.backspaceCount,deleteCount:this.deleteCount}}reset(){this.focusCount=0,this.blurCount=0,this.copyCount=0,this.pasteCount=0,this.cutCount=0,this.fieldFocusOrder=[],this.fieldFocusTimes.clear(),this.backspaceCount=0,this.deleteCount=0,this.autofillDetected=!1,this.autocompleteDetected=!1}handleFocus(t){const i=t.target;if(!this.isFormField(i))return;this.focusCount++;const e=this.getFieldId(i);e&&!this.fieldFocusOrder.includes(e)&&this.fieldFocusOrder.push(e),this.fieldFocusTimes.set(e||"unknown",Date.now())}handleBlur(t){const i=t.target;if(!this.isFormField(i))return;this.blurCount++;const e=this.getFieldId(i);if(e){const t=this.fieldFocusTimes.get(e)||Date.now(),i=Date.now()-t;this.fieldFocusTimes.set(e,i)}}handleCopy(t){const i=t.target;this.isFormField(i)&&this.copyCount++}handlePaste(t){const i=t.target;this.isFormField(i)&&this.pasteCount++}handleCut(t){const i=t.target;this.isFormField(i)&&this.cutCount++}handleKeyDown(t){const i=t.target;this.isFormField(i)&&("Backspace"===t.key?this.backspaceCount++:"Delete"===t.key&&this.deleteCount++)}handleInput(t){const i=t.target;if(!this.isFormField(i))return;i.value&&"password"===i.type&&(this.autofillDetected=!0),i.hasAttribute("autocomplete")&&"off"!==i.getAttribute("autocomplete")&&(this.autocompleteDetected=!0)}isFormField(t){if(!t)return!1;const i=t.tagName.toLowerCase();return"input"===i||"textarea"===i||"select"===i||t.isContentEditable}getFieldId(t){return t.id?t.id:"name"in t&&t.name?t.name:t.getAttribute("data-field-id")?t.getAttribute("data-field-id"):null}}class ${constructor(){this.pageLoadTime=0,this.timeToFirstInteraction=0,this.startTime=Date.now(),this.firstInteractionTime=null,this.maxScrollDepth=0,this.clickCount=0,this.linkClickCount=0,this.imageViewCount=0,this.videoPlayCount=0,this.isActive=!1,this.clickHandler=t=>this.handleClick(t),this.scrollHandler=()=>this.handleScroll(),this.loadHandler=()=>this.handleLoad(),this.imageLoadHandler=()=>this.handleImageLoad(),this.videoPlayHandler=()=>this.handleVideoPlay(),this.startTime=performance.now()}start(){this.isActive||"undefined"==typeof document||("complete"===document.readyState?this.pageLoadTime=performance.now()-this.startTime:window.addEventListener("load",this.loadHandler),document.addEventListener("click",this.clickHandler,!0),window.addEventListener("scroll",this.scrollHandler,{passive:!0}),document.addEventListener("load",this.imageLoadHandler,!0),document.addEventListener("play",this.videoPlayHandler,!0),this.isActive=!0)}stop(){this.isActive&&"undefined"!=typeof document&&(window.removeEventListener("load",this.loadHandler),document.removeEventListener("click",this.clickHandler,!0),window.removeEventListener("scroll",this.scrollHandler),document.removeEventListener("load",this.imageLoadHandler,!0),document.removeEventListener("play",this.videoPlayHandler,!0),this.isActive=!1)}getData(){const t=Date.now()-this.startTime,i=this.calculateScrollDepth();return{pageLoadTime:this.pageLoadTime,timeToFirstInteraction:this.firstInteractionTime?this.firstInteractionTime-this.startTime:0,timeOnPage:t,scrollDepth:i,clickCount:this.clickCount,linkClickCount:this.linkClickCount,imageViewCount:this.imageViewCount,videoPlayCount:this.videoPlayCount}}reset(){this.pageLoadTime=0,this.timeToFirstInteraction=0,this.startTime=Date.now(),this.firstInteractionTime=null,this.maxScrollDepth=0,this.clickCount=0,this.linkClickCount=0,this.imageViewCount=0,this.videoPlayCount=0}handleLoad(){this.pageLoadTime=performance.now()-this.startTime}handleClick(t){this.firstInteractionTime||(this.firstInteractionTime=performance.now()),this.clickCount++;const i=t.target;("a"===i.tagName.toLowerCase()||i.closest("a"))&&this.linkClickCount++}handleScroll(){const t=this.calculateScrollDepth();this.maxScrollDepth=Math.max(this.maxScrollDepth,t)}handleImageLoad(){this.imageViewCount++}handleVideoPlay(){this.videoPlayCount++}calculateScrollDepth(){if("undefined"==typeof window||"undefined"==typeof document)return 0;const t=window.innerHeight||document.documentElement.clientHeight,i=Math.max(document.body.scrollHeight,document.body.offsetHeight,document.documentElement.clientHeight,document.documentElement.scrollHeight,document.documentElement.offsetHeight),e=window.pageYOffset||document.documentElement.scrollTop;if(0===i)return 0;const s=e+t;return Math.min(s/i,1)}}const I="https://api.keverd.com";class x{constructor(){this.config=null,this.isInitialized=!1,this.sessionId=null,this.ghostInterval=null,this.ghostStartTime=null,this.ghostSignalCount=0,this.MIN_GHOST_SIGNALS=10,this.MAX_GHOST_COLLECTION_TIME=6e5,this.deviceCollector=new e,this.behavioralCollector=new a,this.fingerprintManager=new k,this.privacySignalCollector=new M,this.browserCapabilityCollector=new T,this.hardwareSignalCollector=new D,this.formInteractionCollector=new _,this.pageInteractionCollector=new $}init(t){this.isInitialized?this.config:(this.config="string"==typeof t?{apiKey:t,debug:!1}:{debug:!1,...t},this.behavioralCollector.start(),this.formInteractionCollector.start(),this.pageInteractionCollector.start(),this.sessionId=this.generateSessionId(),this.isInitialized=!0,this.config.debug,this.startSession().catch(()=>{}),this.startGhostSignalCollection())}startGhostSignalCollection(){if(this.ghostInterval)return;if(!this.config)return;this.ghostStartTime=Date.now(),this.ghostSignalCount=0;const t=3e4,i=()=>{const i=Date.now(),e=this.ghostStartTime?i-this.ghostStartTime:0,s=this.ghostSignalCount>=this.MIN_GHOST_SIGNALS,n=e>=this.MAX_GHOST_COLLECTION_TIME;if(s||n)return this.config,void this.stopGhostSignalCollection();const r=this.ghostStartTime?i-this.ghostStartTime:t;this.sendGhostSignals(r).catch(t=>{this.config}),this.ghostSignalCount++,this.ghostStartTime=i};setTimeout(()=>{i(),this.ghostInterval=setInterval(()=>{i()},t)},t)}stopGhostSignalCollection(){this.ghostInterval&&(clearInterval(this.ghostInterval),this.ghostInterval=null,this.ghostStartTime=null)}async sendGhostSignals(t){if(!this.isInitialized||!this.config)return;const i=this.deviceCollector.collect(),e=this.behavioralCollector.getData(),s=await this.fingerprintManager.collect(),n={visitorId:s.visitorId,confidence:s.confidence,components:s.components},r=this.privacySignalCollector.collect(),o=this.browserCapabilityCollector.collect(),a=this.hardwareSignalCollector.collect(),h=this.formInteractionCollector.getData(),c=this.behavioralCollector.getMouseSignals(),l=this.behavioralCollector.getKeyboardSignals(),u=this.pageInteractionCollector.getData(),d={connectionType:a.connectionType||void 0,effectiveType:a.effectiveType||void 0,downlink:a.downlink||void 0,rtt:a.rtt||void 0,saveData:a.saveData||void 0},m={sessionId:this.sessionId||void 0,timestamp:(new Date).toISOString()},p={userId:this.config.userId,device:i,session:m,behavioral:e,duration_ms:t,fingerprintjs:n||void 0,privacySignals:r,browserCapabilities:o,hardwareSignals:a,formInteractions:h,mouseSignals:c,keyboardSignals:l,pageInteractions:u,networkSignals:d,useCase:"ghost"},g=`${I}/fingerprint/ghost`,w={"Content-Type":"application/json","X-SDK-Source":"javascript"},f=this.config.apiKey;f&&(w["x-keverd-key"]=f,w["X-API-KEY"]=f,w.Authorization=`Bearer ${f}`),await fetch(g,{method:"POST",headers:w,body:JSON.stringify(p)}).catch(()=>{})}async getVisitorData(){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");try{const t=this.deviceCollector.collect(),i=this.behavioralCollector.getData(),e=await this.fingerprintManager.collect(),s={visitorId:e.visitorId,confidence:e.confidence,components:e.components},n=this.privacySignalCollector.collect(),r=this.browserCapabilityCollector.collect(),o=this.hardwareSignalCollector.collect(),a=this.formInteractionCollector.getData(),h=this.behavioralCollector.getMouseSignals(),c=this.behavioralCollector.getKeyboardSignals(),l=this.pageInteractionCollector.getData(),u={connectionType:o.connectionType||void 0,effectiveType:o.effectiveType||void 0,downlink:o.downlink||void 0,rtt:o.rtt||void 0,saveData:o.saveData||void 0},d={sessionId:this.sessionId||void 0,timestamp:(new Date).toISOString()},m={userId:this.config.userId,device:t,session:d,behavioral:i,fingerprintjs:s||void 0,privacySignals:n,browserCapabilities:r,hardwareSignals:o,formInteractions:a,mouseSignals:h,keyboardSignals:c,pageInteractions:l,networkSignals:u,useCase:"general"};return await this.sendFingerprintRequest(m)}catch(t){const i=t instanceof Error?t.message:"Unknown error";throw this.config.debug,new Error(`Failed to get visitor data: ${i}`)}}async createTransactionID(t){return(await this.getVisitorData()).session_id}async verifyLogin(t,i){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");return await this.sendVerifyRequest("login",{userId:t,metadata:i})}async verifyCheckout(t,i,e){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");return await this.sendVerifyRequest("checkout",{amount:t,currency:i,metadata:e})}async verifyRegistration(t){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");return await this.sendVerifyRequest("registration",{metadata:t})}async verifyPasswordReset(t,i){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");return await this.sendVerifyRequest("password_reset",{email:t,metadata:i})}async verifyAccountChange(t,i){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");return await this.sendVerifyRequest("account_change",{changeType:t,metadata:i})}async sendVerifyRequest(t,i){if(!this.config)throw new Error("SDK not initialized");const e=this.deviceCollector.collect(),s=this.behavioralCollector.getData(),n=await this.fingerprintManager.collect(),r={visitorId:n.visitorId,confidence:n.confidence,components:n.components},o=this.privacySignalCollector.collect(),a=this.browserCapabilityCollector.collect(),h=this.hardwareSignalCollector.collect(),c=this.formInteractionCollector.getData(),l=this.behavioralCollector.getMouseSignals(),u=this.behavioralCollector.getKeyboardSignals(),d=this.pageInteractionCollector.getData(),m={connectionType:h.connectionType||void 0,effectiveType:h.effectiveType||void 0,downlink:h.downlink||void 0,rtt:h.rtt||void 0,saveData:h.saveData||void 0},p={sessionId:this.sessionId||void 0,timestamp:(new Date).toISOString()},g={userId:i.userId||this.config.userId,device:e,session:p,behavioral:s,fingerprintjs:r||void 0,privacySignals:o,browserCapabilities:a,hardwareSignals:h,formInteractions:c,mouseSignals:l,keyboardSignals:u,pageInteractions:d,networkSignals:m,useCase:t};i.metadata&&Object.assign(g,i.metadata),void 0!==i.amount&&(g.amount=i.amount),i.currency&&(g.currency=i.currency),i.email&&(g.email=i.email),i.changeType&&(g.changeType=i.changeType);const w=`${I}/fingerprint/verify/${t}`,f={"Content-Type":"application/json","X-SDK-Source":"javascript"},v=this.config.apiKey;v&&(f["x-keverd-key"]=v,f["X-API-KEY"]=v,f.Authorization=`Bearer ${v}`);const y=await fetch(w,{method:"POST",headers:f,body:JSON.stringify(g)});if(!y.ok){const t=await y.text().catch(()=>"Unknown error");throw new Error(`HTTP ${y.status}: ${t}`)}return await y.json()}async sendFingerprintRequest(t){if(!this.config)throw new Error("SDK not initialized");const i=`${I}/fingerprint/score`,e={"Content-Type":"application/json","X-SDK-Source":"javascript"},s=this.config.apiKey;s&&(e["x-keverd-key"]=s,e["X-API-KEY"]=s,e.Authorization=`Bearer ${s}`);const n=await fetch(i,{method:"POST",headers:e,body:JSON.stringify(t)});if(!n.ok){const t=await n.text().catch(()=>"Unknown error");throw new Error(`HTTP ${n.status}: ${t}`)}return await n.json()}generateSessionId(){return`${Date.now()}_${Math.random().toString(36).substr(2,9)}`}i(){const t=navigator.userAgent;return t.includes("Chrome")?"Chrome":t.includes("Firefox")?"Firefox":t.includes("Safari")&&!t.includes("Chrome")?"Safari":t.includes("Edge")?"Edge":t.includes("Opera")?"Opera":void 0}h(){const t=navigator.userAgent;return t.includes("Windows")?"Windows":t.includes("Mac OS")?"macOS":t.includes("Linux")?"Linux":t.includes("Android")?"Android":t.includes("iOS")||t.includes("iPhone")||t.includes("iPad")?"iOS":void 0}async startSession(t,i,e){if(!this.isInitialized||!this.config)throw new Error("Keverd SDK not initialized. Call init() first.");this.sessionId||(this.sessionId=this.generateSessionId());try{const s=`${I}/dashboard/sessions/start`,n={"Content-Type":"application/json"},r=this.config.apiKey;r&&(n["x-keverd-key"]=r,n["X-API-KEY"]=r,n.Authorization=`Bearer ${r}`);const o=this.deviceCollector.collect();await fetch(s,{method:"POST",headers:n,body:JSON.stringify({session_id:this.sessionId,user_id:t||this.config.userId,device_hash:i||o.fingerprint,metadata:e||{},user_agent:navigator.userAgent,browser:this.i(),os:this.h(),platform:"web",sdk_type:"web",sdk_source:"javascript"})}),this.config.debug}catch(t){this.config.debug}}async endSession(){if(this.isInitialized&&this.config&&this.sessionId)try{const t=`${I}/dashboard/sessions/${this.sessionId}/end`,i={"Content-Type":"application/json"},e=this.config.apiKey;e&&(i["x-keverd-key"]=e,i["X-API-KEY"]=e,i.Authorization=`Bearer ${e}`),await fetch(t,{method:"POST",headers:i}),this.config.debug}catch(t){this.config.debug}}async pauseSession(){if(this.isInitialized&&this.config&&this.sessionId)try{const t=`${I}/dashboard/sessions/${this.sessionId}/pause`,i={"Content-Type":"application/json"},e=this.config.apiKey;e&&(i["x-keverd-key"]=e,i["X-API-KEY"]=e,i.Authorization=`Bearer ${e}`),await fetch(t,{method:"POST",headers:i}),this.config.debug}catch(t){this.config.debug}}async resumeSession(){if(this.isInitialized&&this.config&&this.sessionId)try{const t=`${I}/dashboard/sessions/${this.sessionId}/resume`,i={"Content-Type":"application/json"},e=this.config.apiKey;e&&(i["x-keverd-key"]=e,i["X-API-KEY"]=e,i.Authorization=`Bearer ${e}`),await fetch(t,{method:"POST",headers:i}),this.config.debug}catch(t){this.config.debug}}async getSessionStatus(){if(!this.isInitialized||!this.config||!this.sessionId)return null;try{const t=`${I}/dashboard/sessions/${this.sessionId}/status`,i={},e=this.config.apiKey;e&&(i["x-keverd-key"]=e,i["X-API-KEY"]=e,i.Authorization=`Bearer ${e}`);const s=await fetch(t,{method:"GET",headers:i});return s.ok?await s.json():null}catch(t){return this.config.debug,null}}async destroy(){this.sessionId&&await this.endSession(),this.behavioralCollector.stop(),this.formInteractionCollector.stop(),this.pageInteractionCollector.stop(),this.fingerprintManager.clearCache(),this.isInitialized=!1,this.stopGhostSignalCollection(),this.ghostSignalCount=0,this.config,this.config=null,this.sessionId=null}isReady(){return this.isInitialized&&null!==this.config}}const P=new x;class O{async collect(){return null}clearCache(){}async isAvailable(){return!1}}return i})());
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,7 @@
|
|
|
5
5
|
export { KeverdSDK, Keverd } from './core/sdk';
|
|
6
6
|
export { DeviceCollector } from './collectors/device';
|
|
7
7
|
export { BehavioralCollector } from './collectors/behavioral';
|
|
8
|
-
export
|
|
8
|
+
export { KinematicEngine } from './collectors/kinematic-engine';
|
|
9
|
+
export { KeystrokeMonitor } from './collectors/keystroke-monitor';
|
|
10
|
+
export { FingerprintJSCollector } from './collectors/fingerprintjs';
|
|
11
|
+
export type { SDKConfig, DeviceInfo, SessionInfo, BehavioralData, BehavioralSequence, KinematicFeatureVector, KeystrokeFeatureVector, FingerprintRequest, FingerprintResponse, TransactionMetadata, } from './types';
|