@offline-protocol/pol
v0.1.2
Published
Proof of Location SDK for React and React Native. Verify GPS with operator attestation (location.verify) or commit on-chain only (location.commit).
Downloads
466
Readme
@offline-protocol/pol
Proof of Location for Offline Protocol apps. Submit a GPS claim and obtain an
operator attestation (witness) using your app ID (app_…) and an
Offline ID JWT.
Works in React / Next.js and React Native (same package; Metro uses a
fetch-based client with no native module).
The SDK does not log users in — you supply auth and coordinates (or a
locationProvider at init).
Install
npm install @offline-protocol/polOptional peer: react (>=18, <20) if you use ProofOfLocationProvider.
Prerequisites
- App ID —
app_…from the Offline developer portal. - Auth — Offline ID JWT, e.g. from
@offline-protocol/id-react-native. - Location — pass
claim: { lat, lon }or setlocationProvideron init.
Quick start (verify — recommended)
Verify commits on-chain (when needed) and completes the operator witness round trip. This is the usual PoL flow.
import { ProofOfLocation } from "@offline-protocol/pol";
const pol = ProofOfLocation.init({
appId: "app_xxxxxxxx",
getSessionToken: () => yourJwt,
locationProvider: getGpsFromDevice,
});
const proof = await pol.location.verify({
claim: { lat: 37.77, lon: -122.42 },
});
// proof.attestation — operator signature; proof.transaction, proof.geohash, …With the ID SDK:
import { ProofOfLocation } from "@offline-protocol/pol";
import { useAuth } from "@offline-protocol/id-react-native";
const { token } = useAuth();
const pol = ProofOfLocation.init({
appId: "app_xxxxxxxx",
getSessionToken: () => token,
locationProvider: getGpsFromDevice,
});
await pol.location.verify();Two-step: commit, then verify
If you already committed on-chain and only need the operator witness (for example after a transient WebSocket error), pass the existing commitment:
const commitment = await pol.location.commit({ claim });
const proof = await pol.location.verify({ commitment });Commit only (on-chain, no witness)
Use location.commit when you only need the on-chain location commitment
and not operator attestation:
const commitment = await pol.location.commit({
claim: { lat: 37.77, lon: -122.42 },
});
// commitment.id, commitment.transaction, commitment.commitment, commitment.geohashReact provider
import { ProofOfLocationProvider, useProofOfLocation } from "@offline-protocol/pol";
<ProofOfLocationProvider appId={APP_ID} getSessionToken={() => token} locationProvider={getGps}>
<App />
</ProofOfLocationProvider>;const { location, latestVerification, status, error } = useProofOfLocation();
const proof = await location.verify({ claim: { lat, lon } });
// commit-only when you do not need attestation:
await location.commit({ claim: { lat, lon } });Next.js (optional WASM client)
import { ProofOfLocationWasm } from "@offline-protocol/pol/wasm";
const pol = await ProofOfLocationWasm.init({ appId, getSessionToken: () => token });
await pol.location.verify({ claim: { lat, lon } });Configure your bundler for .wasm from pkg/. The default @offline-protocol/pol
import does not require WASM.
// next.config.js
transpilePackages: ["@offline-protocol/pol"],API summary
| Method | Purpose |
| --- | --- |
| pol.location.verify(opts?) | Recommended — on-chain commit (if needed) + operator WebSocket witness → attestation |
| pol.location.commit(opts?) | On-chain commit only — POST …/location-commitment |
Verify options include commitment (witness only), operatorUrl, witnessDelayMs,
and witnessRetries for operator connectivity.
Backend
| Call | Purpose |
| --- | --- |
| GET /users/me | Resolve username when not set locally |
| POST /profiles/:username/location-commitment | Submit commitment |
| WebSocket on commitment.operators[0] | Witness during verify |
Common errors: 400 (app id), 403 (PoL disabled), 429 (rate limit), 503 (commit service down).
License
MIT — see the repository pol-sdk/LICENSE.
Contributing
Maintainer docs: pol-sdk/CONTRIBUTING.md and pol-sdk/docs/ in the GitHub repo.
