npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@unbraided/kenal-ekyc-rn

v0.1.10

Published

Kenal eKYC SDK for React Native — document verification and face liveness

Downloads

778

Readme

@unbraided/kenal-ekyc-rn

React Native SDK for Kenal eKYC identity verification. Provides document scanning with on-device ML, face liveness detection, and a fully managed verification flow.

Features

  • On-device document detection and auto-capture (ONNX Runtime)
  • Automatic document type classification (MyKad, MyPR, MyTentera, Passport)
  • MRZ detection and recognition for passports
  • Face liveness verification (AWS Rekognition)
  • Configurable theme, text strings, and custom screens
  • Both imperative and component APIs

Installation

npm install @unbraided/kenal-ekyc-rn

Peer Dependencies

Install the required peer dependencies:

npm install \
  react-native-safe-area-context \
  @react-navigation/native \
  @react-navigation/stack \
  react-native-gesture-handler \
  react-native-reanimated \
  react-native-screens \
  react-native-svg \
  react-native-fs

| Package | Required | Tested with | |---|---|---| | react-native | >=0.76.0 | 0.83.1 | | react-native-safe-area-context | >=4.0.0 | 5.6.2 | | @react-navigation/native | >=7.0.0 | 7.1.28 | | @react-navigation/stack | >=7.0.0 | 7.7.1 | | react-native-gesture-handler | >=2.0.0 | 2.30.0 | | react-native-reanimated | >=3.0.0 | 4.2.1 | | react-native-screens | >=4.0.0 | 4.22.0 | | react-native-svg | >=13.0.0 | 15.15.2 | | react-native-fs | >=2.20.0 | 2.20.0 |

React Native 0.76–0.80: pin react-native-reanimated to v3, as Reanimated 4 requires RN 0.81+:

npm install react-native-reanimated@^3.0.0

Reanimated v4+ (RN 0.81+): also requires react-native-worklets — install it alongside Reanimated:

Add the Reanimated Babel plugin to your babel.config.js:

module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: ['react-native-reanimated/plugin'],
};

iOS Setup

  1. Install pods:

    cd ios && pod install
  2. Add modular headers for ONNX Runtime in your Podfile:

    pod 'onnxruntime-objc', :modular_headers => true
  3. Add camera permission to Info.plist:

    <key>NSCameraUsageDescription</key>
    <string>Camera access is required for identity verification.</string>
  4. Minimum deployment target: iOS 14.0 (required by AWS Amplify FaceLiveness SwiftUI components)

Android Setup

  1. Add camera permission to AndroidManifest.xml:

    <uses-permission android:name="android.permission.CAMERA" />
  2. Enable core library desugaring in app/build.gradle (required by AWS Amplify Liveness):

    android {
        compileOptions {
            coreLibraryDesugaringEnabled true
        }
    }
    dependencies {
        coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
    }
  3. Ensure Gradle configuration:

    • minSdk: 24+
    • compileSdk: 35+

What's Included

The SDK ships native modules and ML models — no additional native code or manual file setup needed.

  • Native modules (KenalCameraModule, KenalLivenessModule) are bundled and auto-linked. The liveness module uses AWS Amplify, which the SDK configures lazily and safely (no conflict if your app already uses Amplify).
  • ONNX model files (~113 MB) for document detection, classification, and MRZ reading are bundled in the npm package and automatically included in your iOS/Android build via the podspec and Gradle config.

Quick Start

import { useState } from 'react';
import { Button, View } from 'react-native';
import { KenalEkyc, KenalEKYCView } from '@unbraided/kenal-ekyc-rn';

function App() {
  const [showEkyc, setShowEkyc] = useState(false);

  const startVerification = () => {
    KenalEkyc.start({
      apiKey: 'your-api-key',
      environment: 'production',
      refId: 'your-user-or-transaction-id', // your internal ID — returned via callback so you can link the result
      name: 'John Doe',
      idNumber: '901234-56-7890',
      docIssueCountry: 'MYS', // ISO 3166-1 alpha-3; required for passport workflows; must match the MRZ issuing state
    });
    setShowEkyc(true);
  };

  if (showEkyc) {
    return (
      <KenalEKYCView
        onCompleted={(result) => {
          console.log('Verification:', result.verificationStatus); // 'Success' | 'Fail' | 'In Review'
          console.log('Steps:', result.executions);
          setShowEkyc(false);
        }}
        onCancelled={() => setShowEkyc(false)}
        onError={(error) => {
          if (error.isRetryable) {
            console.warn(`Retryable error [${error.code}]: ${error.message}`);
          } else {
            console.error(`Fatal error [${error.code}]: ${error.message}`);
          }
          setShowEkyc(false);
        }}
        onExpired={() => setShowEkyc(false)}
      />
    );
  }

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Button title="Start Verification" onPress={startVerification} />
    </View>
  );
}

Querying Status

You can query the status of any eKYC session at any time (even after the session has expired):

const status = await KenalEkyc.getStatus('validation-id', 'your-api-key', 'production');
console.log(status.verificationStatus); // 'Success' | 'Fail' | 'In Progress' | 'In Review'
console.log(status.executions);         // [{ componentType: 'MyKad', result: 'Pass' }, ...]
console.log(status.reasons);            // ['Customer Name Mismatch', ...] (empty if passed)

Error Handling

The onError callback receives a KenalEkycError object:

interface KenalEkycError {
  domain: 'SDK' | 'NETWORK' | 'SERVER'; // where the error originated
  code: string;                          // machine-readable code (see below)
  message: string;                       // human-readable message
  isRetryable: boolean;                  // true → safe to retry; false → fatal
  traceId?: string;                      // backend trace ID for support
}

Common error codes by domain:

| Domain | Code | Retryable | Meaning | |---|---|---|---| | SDK | SDK_CAMERA_PERMISSION_DENIED | No | User denied camera access | | SDK | SDK_MODEL_LOAD_FAILED | No | ONNX model failed to load | | SDK | SDK_LIVENESS_CANCELLED | No | User cancelled the liveness check | | NETWORK | NETWORK_UNREACHABLE | Yes | No internet connection | | NETWORK | NETWORK_REQUEST_FAILED | Yes | Request failed or timed out | | SERVER | SERVER_SESSION_EXPIRED | No | Session expired (also fires onExpired) | | SERVER | SERVER_UPLOAD_FAILED | Yes | Document upload failed | | SERVER | SERVER_UNAUTHORIZED | No | Invalid API key | | SERVER | SERVER_MAX_RETRY_EXCEEDED | No | User exceeded maximum verification attempts |

Use isRetryable to decide whether to restart the flow or show a final error. For the full list of error codes, see Errors and Types.


Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | apiKey | string | required | API key from the Kenal admin portal | | environment | 'sandbox' \| 'production' | 'sandbox' | Backend environment ('sandbox' for dev/testing, 'production' for live) | | refId | string | required | Your application's reference ID for this eKYC session (e.g. a user ID or transaction ID). Passed back to your server via the webhook/callback URL so you can link the eKYC result to the correct record in your own system. | | name | string | required | User's full name (matched against the document during verification — see note below) | | idNumber | string | required | User's ID number, e.g. MyKad number or passport number (matched against the document during verification — see note below) | | docIssueCountry | string | — | Passport issuing country. ISO 3166-1 alpha-3 (e.g. 'MYS', 'GBR', 'USA'). Required for passport workflows — session fails to start if omitted. Must match the MRZ issuing state code (see note below). | | theme | Partial<KenalEkycTheme> | — | Style/theme overrides | | texts | Partial<KenalEkycTexts> | — | Text label overrides for i18n | | enableDebugLogs | boolean | false | Enable verbose debug logging | | showDetectionOverlay | boolean | false | Show polygon detection overlay (debug) | | enableDocumentLiveness | boolean | true | Enable document liveness step |

Why are name and idNumber required?

eKYC verification has two parts: (1) extracting personal information from the document, and (2) cross-checking it against an external source for an additional layer of security. Typically, integrating platforms have already captured their user's personal information — by passing name and idNumber to the SDK, the extracted document data is verified against this trusted source. This ensures the document belongs to the person performing the verification.

In a future release, these fields will become optional to support flows where the integrating platform relies on the SDK to extract the information and performs the cross-check on their own platform.

docIssueCountry — use the MRZ issuing state code, not the country of residence

The value must be the ISO 3166-1 alpha-3 code that appears in the passport's MRZ (Machine Readable Zone). This is the issuing state, not necessarily the holder's country of residence. In most cases they are the same, but there are exceptions — for example, Hong Kong and Macau HKSAR passports are issued under the PRC, so the MRZ issuing state is CHN. Pass 'CHN', not 'HKG' or 'MAC'.

If the value does not match what's in the passport's MRZ, the passport verification step will fail and the user will be rejected.

Customization

Theme

All theme keys are optional — only override what you need.

config={{
  // ...
  theme: {
    primaryColor: '#1a73e8',       // buttons, progress indicators
    backgroundColor: '#ffffff',    // non-camera screen backgrounds
    textColor: '#111827',          // primary text
    textSecondaryColor: '#6b7280', // subtitles, hints
    errorColor: '#dc2626',         // error states
    successColor: '#16a34a',       // success states
    buttonBorderRadius: 12,        // button corner radius (px)
    cardBorderRadius: 16,          // card/container corner radius (px)
    fontFamily: 'Inter',           // optional font override
  },
}}

Text / Localisation

Override any string shown in the SDK UI. All keys are optional.

config={{
  // ...
  texts: {
    // Camera screen
    detectingCard: 'Place your document in the frame',
    holdStill: 'Hold still...',
    captured: 'Captured!',
    flipToBack: 'Now scan the back',

    // Session expired screen
    sessionExpiredTitle: 'Session Expired',
    sessionExpiredMessage: 'Your session has timed out. Please start again.',
    sessionExpiredButton: 'Close',

    // General
    cancelButton: 'Cancel',
  },
}}

For the full list of available text keys, see SDK Reference → KenalEkycTexts.


Documentation

Platform Support

| Platform | Minimum Version | |----------|----------------| | iOS | 14.0+ (arm64) | | Android | API 24+ (Android 7.0) |

License

MIT