Native collection
Location, device fingerprinting, integrity checks, secure storage, sensors, and network probes run in the SDK's own native code. No additional native peer package is required.
Collect device integrity, fingerprint, network, and location signals, then evaluate geofence and fraud policy through native Swift and Kotlin modules.
The package exports a GeoFenceSDK class, public TypeScript types, and a Permissions namespace. React Native autolinking connects the JavaScript wrapper to the native modules.
Location, device fingerprinting, integrity checks, secure storage, sensors, and network probes run in the SDK's own native code. No additional native peer package is required.
Continuous checks pause when the app backgrounds and resume against the server-provided interval when the app becomes active. Version 0.4.0 does not perform background location checks.
The package is published to the Kade project package registry on GitLab, not the public npm registry. Configure the @videntrix scope and an authorized registry token before installing.
Add this project-level .npmrc. Supply NPM_TOKEN through your local environment or CI secret store; do not commit the token.
@videntrix:registry=https://gitlab.com/api/v4/projects/geofence1%2Freact-native-sdk/packages/npm/
//gitlab.com/api/v4/projects/geofence1%2Freact-native-sdk/packages/npm/:_authToken=${NPM_TOKEN}Use a GitLab personal, project, deploy, or CI job token that can read this project's package registry. A deploy token needs read_package_registry; a personal or project access token commonly uses the api scope.
npm install @videntrix/react-native-geofence-sdk@0.4.0
# Or with Yarn after the same registry configuration
yarn add @videntrix/react-native-geofence-sdk@0.4.0npm install without the scoped registry and a token will attempt the wrong registry or fail authorization.The podspec supports iOS 13 or newer and autolinks both the native core and React Native bridge. Keep the deployment target at 13.0 or higher, add the foreground location usage text, then install pods.
# ios/Podfile
platform :ios, '13.0'
target 'YourApp' do
config = use_native_modules!
use_react_native!(path: config[:reactNativePath])
end<!-- ios/YourApp/Info.plist -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>We verify your location to confirm you are in a licensed region.</string>cd ios
pod install
cd ..The pod uses Swift 5.7. No manual pod 'GeoFenceSdk' entry is needed when React Native autolinking is enabled.
The included React Native configuration points autolinking at the package's bridge class. The library manifest declares:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />You do not need to register the package manually or duplicate these permissions in the app manifest. Before a location-enabled ping() or startContinuousPing(), the wrapper requests runtime location permission and gives Android an opportunity to upgrade coarse access to precise access.
permissionRationale in the constructor to provide Android rationale copy when required by the OS.The bundled config plugin writes the iOS foreground location description and ensures the Android location and network permissions are present.
{
"expo": {
"plugins": [
[
"@videntrix/react-native-geofence-sdk",
{
"locationUsageDescription": "We verify your location to confirm you are in a licensed region."
}
]
]
}
}npx expo prebuild
# Build and install a native development client
eas build --profile developmentexpo prebuild and use a development build, or let EAS Build generate the native projects. Changing plugin options requires regenerating/rebuilding the native app.Create one instance, attach an error observer, initialize it, and run a ping. Public operations initialize the native client automatically, but explicit startup makes initialization failures easier to handle.
import GeoFenceSDK from '@videntrix/react-native-geofence-sdk';
const sdk = new GeoFenceSDK({
apiToken: 'your-api-token',
regionId: 123,
locationAccuracy: 'high',
debug: __DEV__,
permissionRationale: {
title: 'Location access',
message: 'Kade uses your location to confirm your licensed region.',
},
});
sdk.onError((error, context) => {
console.warn(`Kade SDK error in ${context}`, error);
});
await sdk.init();
const response = await sdk.ping({
userId: 'player-123',
source: 'login',
email: 'player@example.com',
});
if (response.blocked) {
handleBlocked(response.code, response.message);
} else {
console.log(response.inside, response.area?.name);
}Omit skipLocation for normal GPS-backed verification. Pass skipLocation: true when the flow intentionally relies on server-side network location and must not request device location.
apiToken is the only required constructor option. serverUrl defaults to https://api.videntrix.com.
| Option | Type | Behavior |
|---|---|---|
apiToken | string | Required API token sent with SDK requests. |
serverUrl | string? | Overrides the default Kade API origin. |
regionId | number? | Default region; a ping-level region overrides it. |
signingSecret | string? | Enables HMAC request signing in the native client. |
locationStrategy | 'race' | 'sequential'? | race runs high- and low-accuracy acquisition in parallel; sequential tries high accuracy first. The default is race. |
locationMaxAge | number? | Maximum cached GPS fix age in milliseconds. Default 120,000. |
locationMaxStalenessRadius | number? | Fallback maximum displacement in metres when speed is unavailable. Default 100. |
locationAccuracy | 'high' | 'balanced' | 'low'? | Native location accuracy tier. Default high. |
permissionRationale | { title, message }? | Android runtime permission rationale copy. |
debug | boolean? | Enables verbose native diagnostics. Lifecycle, warning, and error logs still emit when false. |
Creates an instance and validates that apiToken is present. Native resources are prepared by init() or the first operation that initializes automatically.
Observes JavaScript and native errors handled by the SDK and returns the instance for chaining. Continue to catch rejected method promises; initialization and ping failures can still reject.
Starts the native client, installs event listeners, and prepares SDK state. Repeated calls after initialization are no-ops.
Runs one geofence and risk evaluation. Unless skipLocation is true, it handles runtime location permission before calling the native ping client.
Without a user ID, returns the local device fingerprint result. With a user ID, the native client can send the fingerprint for server-side association and return the enriched server response.
Posts registration identity data to /public/email-check. It returns no verdict to the app; results are operator-only. Network errors are reported through the SDK error path and swallowed so registration is not interrupted.
Starts native recurring checks and reuses the supplied options for every check. Responses and loop errors are delivered to the callback.
Stops the loop and location watcher and clears its callback.
Stops continuous checks, removes native listeners, releases native resources, and allows a later call to initialize again.
await sdk.evaluateEmail({
email: 'new.user@example.com',
firstName: 'New',
lastName: 'User',
userId: 'player-123',
});
// The promise resolves without a client-visible verdict.Import the package-level Permissions namespace when your UI needs to inspect or request location access before a ping.
import {
Permissions,
type PermissionStatus,
} from '@videntrix/react-native-geofence-sdk';
const current: PermissionStatus = await Permissions.getLocationStatus();
if (current !== 'granted') {
const result = await Permissions.requestLocation({
title: 'Location access',
message: 'Location is required to verify your licensed region.',
});
if (result !== 'granted') {
showLocationSettingsHelp(result);
}
}| Helper | Return value | Behavior |
|---|---|---|
Permissions.getLocationStatus() | Promise<PermissionStatus> | Reads granted, denied, restricted, or notDetermined. |
Permissions.requestLocation(rationale?) | Promise<PermissionStatus> | Requests foreground location. Concurrent calls share one in-flight native request; the first rationale wins. |
Normal ping() and startContinuousPing() calls perform this permission flow automatically unless skipLocation: true is set.
The native loop pings immediately, then schedules each subsequent check using the server's response.interval.
await sdk.startContinuousPing(
{
userId: 'player-123',
source: 'gameplay',
regionId: 123,
},
(response, error) => {
if (error) {
console.warn('Continuous ping failed', error);
return;
}
if (response.blocked) {
handleBlocked(response.code);
return;
}
updateLocationState(response.inside, response.distanceToBorder);
},
);
// Await this when the protected flow ends.
await sdk.stopContinuousPing();Timers and the location watcher stop when the app enters the background. Version 0.4.0 is foreground-only and does not request always-on location.
If the last server interval elapsed while paused, the SDK pings immediately. Otherwise it waits only the remaining interval.
The native loop stops after a blocked response or HTTP status 403/451. It also adapts location watching to the server interval and disables the watcher for skipLocation.
interface PingOptions {
userId?: string;
silent?: boolean;
skipLocation?: boolean;
source?: string;
regionId?: number;
email?: string;
firstName?: string;
lastName?: string;
}silent asks the server to process the request without returning the normal verdict payload.skipLocation suppresses the runtime permission request and device GPS collection for that operation.source is a free-form flow tag such as login, deposit, or gameplay.regionId overrides the constructor's region for the ping or entire continuous session.interface PingArea {
id: number;
name: string;
}
interface PingResponse {
inside: boolean;
status: number;
message?: string;
code?: GeoFenceResponseCode;
interval: number;
distanceToBorder: number;
regionId?: number;
area?: PingArea;
blocked?: boolean;
requestLocation?: boolean;
deviceTrustTtl?: number;
}requestLocation lets the server ask the native client to escalate toward GPS on a later ping. deviceTrustTtl is a server-provided millisecond window in which the native client may skip expensive integrity probes.
interface FingerprintResult {
visitorId: string;
}
interface FingerprintServerResponse {
clientId: string;
fingerprintRequestCount: number;
visitorId?: string;
confidence: {
score: number;
comment: string;
};
ip: string;
ja3?: string;
ja4?: string;
device: {
userAgent?: string;
browser?: string;
os?: string;
};
}Branch on blocked === true first. The code union permits future strings, so unknown codes must still be treated as blocked.
| Code | Meaning |
|---|---|
BLOCKED | Generic security or compliance rejection. |
BLACKLISTED | The client was already blacklisted. |
DEV_TOOLS_DETECTED | Debugger-style inspection contributed to the block. |
VPN_DETECTED | VPN, proxy, hosting, datacenter, or related network evidence contributed to the block. |
DEVELOPER_MODE_DETECTED | iOS/Android developer mode, ADB, or an attached debugger contributed to the block. |
EMULATOR_DETECTED | An emulator or simulator contributed to the block. |
LOCATION_PERMISSION_MISSING | Foreground location permission was not granted. |
LOCATION_PERMISSION_PRECISE_REQUIRED | Precise location was required but unavailable. |
LOCATION_SERVICES_DISABLED | Device-level location services are disabled. |
LOCATION_TIMEOUT | The SDK timed out waiting for a usable location fix. |
LOCATION_UNAVAILABLE | The SDK could not obtain a usable location fix. |
estimateLocation(), primeLocation(), and requestLocationPermission(). They are not methods on the React Native GeoFenceSDK class.On React Native, use Permissions.getLocationStatus() and Permissions.requestLocation() for explicit UI flows. For the normal case, call ping() or startContinuousPing() and let the SDK perform automatic foreground permission handling.
Uses native GPS, integrity, sensor, secure-storage, and network probes. It pauses continuous work while the app is backgrounded.
Uses browser APIs and exposes browser-specific location priming and network-estimation methods. Those methods do not transfer to the native package.
Talk to the Kade team about package registry access, native setup, permission UX, configuration, or production rollout.