@abstraxn/warrant-verifier
v0.1.0
Published
KYI Warrant receipt verifier — offline Ed25519 + optional on-chain MandateRegistry / ReceiptLog checks
Readme
@abstraxn/warrant-verifier
Offline verification for KYI Warrant decision receipts. Zero network calls to Warrant — auditors only need the signed receipt JSON and Warrant’s public key.
Related packages:
| Package | Role |
|---------|------|
| @abstraxn/warrant | Server / Node client |
| @abstraxn/warrant-react | MandateForm + Readback |
| @abstraxn/warrant-verifier | Offline receipt verify + CLI |
Installation
npm install @abstraxn/warrant-verifieryarn add @abstraxn/warrant-verifierpnpm add @abstraxn/warrant-verifierPrerequisites
- Node.js >= 18
- Warrant Ed25519 public key (hex file, base64, or JSON
{ "publicKey": "…" })- From KYI:
GET /v1/warrant/keys/receipt(or your deployed key material)
- From KYI:
Library
import {
verifyReceiptJson,
verifyReceiptsJsonl,
canonicalize,
tamperReceiptsJsonl,
} from '@abstraxn/warrant-verifier';
import { readFileSync } from 'node:fs';
function hexToBytes(hex: string): Uint8Array {
const clean = hex.trim().replace(/^0x/i, '');
const out = new Uint8Array(clean.length / 2);
for (let i = 0; i < out.length; i++) {
out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
}
return out;
}
const publicKey = hexToBytes(readFileSync('public.key', 'utf8').trim());
const jsonl = readFileSync('receipts.jsonl', 'utf8');
const rows = await verifyReceiptsJsonl(jsonl, publicKey);
for (const row of rows) {
console.log(row.receipt_id, row.verdict, row.valid ? 'VALID' : row.error);
}Single receipt
const result = await verifyReceiptJson(receiptObjectOrJsonString, publicKey);
// { receipt_id, verdict, reasons, valid, error? }CLI
The package ships a warrant-verify binary:
npx warrant-verify receipts.jsonl --public-key=./public.keyOptions
| Flag | Description |
|------|-------------|
| --public-key=<path> | Path to hex / base64 / JSON public key (default: config/keys/public.key) |
| --tamper | Demo mode: mutate amount on the last receipt, write *.tamper.jsonl, then verify (signature stays intact → fails) |
Exit code 0 if all receipts are valid; 1 otherwise.
Tamper demo
npx warrant-verify receipts.jsonl --public-key=./public.key --tamperShows that changing receipt content without resigning fails verification.
API reference
| Export | Description |
|--------|-------------|
| verifyReceiptJson(lineOrObject, publicKey) | Verify one receipt (JSON string or object) |
| verifyReceiptsJsonl(content, publicKey) | Verify each non-empty JSONL line |
| canonicalize(value) | Deterministic JSON canonicalize used for the signed message |
| tamperReceiptsJsonl(content) | Demo helper — mutates amount on the last receipt |
| verifyMandateOnchain(…) | RPC: MandateRegistry content hash + active |
| verifyReceiptOnchain(…) | RPC: ReceiptLog Merkle inclusion |
| verifyMerkleProof(…) | Offline Merkle inclusion (sorted pairs) |
type VerifyResult = {
receipt_id: string;
verdict: string;
reasons: string;
valid: boolean;
error?: string;
};How verification works
- Strip
signaturefrom the receipt object - Canonicalize the unsigned payload
- Ed25519-verify
signature.sig(hex) against Warrant’s public key
On-chain Merkle / STH checks are planned when MandateRegistry / ReceiptLog contracts are live; this package already verifies cryptographic integrity offline.
On-chain helpers (optional RPC)
Auditors can also check MandateRegistry / ReceiptLog without calling the Warrant API:
import {
verifyMandateOnchain,
verifyReceiptOnchain,
verifyMerkleProof,
receiptLeafBytes32,
canonicalize,
} from '@abstraxn/warrant-verifier';
const mandate = await verifyMandateOnchain({
rpcUrl: process.env.RPC_URL!,
mandateRegistry: '0x9f13744Cd7ca5b7851Aa21C9607617a83904A3b5',
mandateId: 'mnd_sha256:…',
contentHashHex: '…', // mandate.hash
chainId: 80002,
});
// Offline Merkle (no RPC)
const leaf = receiptLeafBytes32(canonicalize(unsignedOrSignedReceipt));
const merkleOk = verifyMerkleProof({ leaf, proof, root });
const receipt = await verifyReceiptOnchain({
rpcUrl: process.env.RPC_URL!,
receiptLog: '0x65eDCae32a92eCCC47b7f0CBa06f2F924ce3A45E',
leaf,
proof,
batchId: '1',
root,
chainId: 80002,
});| Export | Description |
|--------|-------------|
| verifyMandateOnchain(…) | MandateRegistry.verifyMandate + isActive |
| verifyReceiptOnchain(…) | ReceiptLog.verifyReceipt / verifyReceiptAgainstAnyBatch |
| verifyMerkleProof(…) | Offline sorted-pair Merkle inclusion |
| mandateIdBytes32 / contentHashBytes32 / receiptLeafBytes32 | Same encodings as KYI |
License
MIT
