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

@proxze/kyc-react-native

v0.1.0

Published

Proxze Enterprise Address KYC SDK for React Native — passive geofence night verification, consent, evidence upload.

Downloads

95

Readme

@proxze/kyc-react-native

Proxze Enterprise Address KYC SDK. Embeds passive geofence-based address verification into a bank's React Native app: NDPR consent, night-presence tracking (12AM–5AM, 3 consecutive nights), utility-bill upload and optional daily video KYC — against proxze-kyc-service's /v2/sdk/* surface.

Install

yarn add @proxze/kyc-react-native
# recommended peers
yarn add react-native-background-geolocation @react-native-async-storage/async-storage

react-native-background-geolocation (licensed, Transistorsoft) powers the default location adapter — Google Play Services fused location + Geofencing API on Android, CoreLocation region monitoring on iOS. It is an optional peer: a bank with its own location stack can implement the LocationAdapter interface instead and skip the dependency entirely.

@react-native-async-storage/async-storage persists the offline event queue. Also optional — without it the queue lives in memory only (events survive connectivity loss but not a process kill).

Security model

The app only ever holds a session token (pst_…) scoped to one verification. The bank's pxz_live_… API key stays on the bank's backend:

  1. Bank backend calls POST /v2/kyc/initiate with its API key.
  2. It hands the returned session_token to the app (its own auth channel).
  3. The app drives this SDK with that token; the token can only report evidence for its own session and dies when the verification completes.

Quickstart

import { useProxzeKyc } from '@proxze/kyc-react-native';

function AddressVerification({ sessionToken }: { sessionToken: string }) {
  const { session, state, loading, kyc } = useProxzeKyc({
    baseUrl: 'https://api.proxze.com',
    sessionToken,
  });

  if (loading || !session) return <Spinner />;

  switch (state) {
    case 'awaiting_consent':
      // NDPR: show your consent copy, then:
      return <ConsentScreen onAccept={() => kyc.grantConsent('1.0.0')} />;

    case 'awaiting_address_pin':
      // The declared address geocoded too coarsely — ask the customer to
      // drop a pin at home (map screen), then:
      return <PinScreen onConfirm={(p) => kyc.confirmAddress(p)} />;

    case 'awaiting_permissions':
      return (
        <ExplainerScreen
          onContinue={async () => {
            const permission = await kyc.startTracking();
            if (permission.grade === 'denied') {
              // Explain why tracking is needed and re-prompt / open settings.
            } else if (!permission.precise) {
              // Approximate location can't confirm a 100m fence —
              // walk the user to settings to enable Precise Location.
            } else if (permission.grade === 'granted_when_in_use') {
              // Warn: overnight confirmation unlikely without "Always allow".
            }
          }}
        />
      );

    case 'tracking':
      return (
        <ProgressScreen
          nights={session.requirements.nights}
          onUploadBill={(file) => kyc.uploadUtilityBill(file, 'electricity_bill')}
        />
      );

    case 'completed':
      return <DoneScreen status={session.status} />;
  }
}

Imperative use without React is the same machine: new ProxzeKycSession({...}).

How night tracking works

The server evaluates nights in hybrid mode and this SDK feeds both models:

  • Geofence transitions (enter/exit/dwell) come from the OS and survive app termination and reboots (stopOnTerminate: false, startOnBoot: true).
  • Pings are sampled on the 30-minute marks inside the 12AM–5AM window (Africa/Lagos), where the OS allows. iOS will not run a 30-minute background timer — that's expected; the transitions plus the morning check (one in-fence sample in the 3 hours after 05:00) satisfy the server's arrived-and-stayed strategy.
  • Everything is queued offline-first and flushed in batches; the server dedupes on clientEventId, so replays are harmless.
  • Android's mock-location flag rides along on every event; spoofed nights are flagged server-side.

Evidence uploads

// Compulsory utility bill (photo or PDF, ≤10MB, ≤3 months old):
await kyc.uploadUtilityBill(
  { uri: photo.uri, name: 'bill.jpg', type: 'image/jpeg' },
  'electricity_bill',
);

// Daily geo-tagged video, only when the integration requires it:
await kyc.uploadVideo(
  { uri: rec.uri, name: 'day1.mp4', type: 'video/mp4' },
  {
    dayNumber: 1,
    durationSec: 22,
    lat, lng, accuracyM,
    recordedAt: new Date().toISOString(),
  },
);

The bill response carries the OCR/match outcome (status, matchStatus, rejectionReason, canRetry) — one re-upload is allowed after a rejection.

Permissions — the full matrix

startTracking() requests permissions and returns what was actually granted ({ grade, precise }); kyc.diagnostics() re-checks at any time. The SDK starts tracking on anything better than an outright denial — degraded signals still feed the server's hybrid evaluator, which routes unclear nights to review instead of failing the customer — but the app should tell the customer what each state means for their verification:

| State | Effect | App should | | --- | --- | --- | | granted_always + precise | Full night tracking | Nothing — happy path | | granted_when_in_use | Fence events only while app foregrounded; nights mostly inconclusive | Prompt to upgrade to "Allow all the time" (Android takes the user to settings for this on 11+) | | precise: false | Approximate fixes are km-wide; a 100m fence can never confirm | Walk the user to settings → enable Precise Location | | denied | No tracking at all | Explain, re-prompt, or offer to cancel the verification |

Platform notes the host app owns:

  • Android 10+: ACCESS_BACKGROUND_LOCATION is a separate grant; on 11+ the system never shows an "always" button in the dialog — the user must pick it in settings. Google Play also requires an in-app prominent disclosure before the permission prompt; the consent screen you show at awaiting_consent is the natural place.
  • Android 12+: users can grant approximate-only — that's the precise: false state above.
  • Android 13+: add POST_NOTIFICATIONS; the background-geolocation foreground-service notification needs it.
  • Battery optimization: aggressive OEMs (Tecno/Infinix/Xiaomi — a large share of Nigerian handsets) kill background services. The Transistorsoft lib ships DeviceSettings helpers to request an exemption; wire them into your "tracking health" screen for best confirmation rates.
  • iOS: "Always" authorization is granted provisionally and can be downgraded silently by the user; re-check with diagnostics() when the app foregrounds. iOS 14+'s Precise Location toggle maps to precise: false.

Android (AndroidManifest.xml):

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

iOS (Info.plist):

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Your bank uses your location at night to confirm you live at your registered address.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your bank uses your location to confirm your address.</string>
<key>UIBackgroundModes</key>
<array><string>location</string></array>

Follow react-native-background-geolocation's own setup guide for its native configuration and license key.

Custom location stack

import { LocationAdapter, ProxzeKycSession } from '@proxze/kyc-react-native';

class MyAdapter implements LocationAdapter { /* ... */ }

const kyc = new ProxzeKycSession({
  baseUrl,
  sessionToken,
  adapter: new MyAdapter(),
});

Build

yarn build   # tsc → dist/
yarn test    # queue + night-window unit tests

License

Proprietary — © Sage Grey Technologies Limited. Use is permitted only for integrating with Proxze services; modification and redistribution are not. See LICENSE.