@axiomatic_oracle/proofkit
v1.0.3
Published
Proofkit SDK for building and publishing PoVal p1 notes
Readme
TypeScript/JavaScript SDK for building and publishing p1 Proof-of-Valuation (PoVal) attestations on Algorand for Axiomatic Oracle.
It focuses on:
- Building canonical, deterministic p1 payloads (JCS/ACJ-style JSON).
- Anchoring them on-chain as the note of a 0-ALGO self-transaction.
- Keeping signing and key management fully client-side.
- Remaining interoperable with independent verifiers (Node + Python).
This package is ESM-first and works with Node.js (18+) and modern browsers.
Who is this for?
Use @axiomatic_oracle/proofkit if you:
- Need to issue PoVal attestations on Algorand from Node.js or browser code.
- Build RWA / tokenization / lending platforms that require verifiable valuations.
- Want deterministic, cross-language
p1payloads aligned with the Python SDKs.
If you only need to verify existing attestations, see
@axiomatic_oracle/verifier (Node) or axiomatic_verifier (Python).
Typical use cases
Real estate tokenization
- Compute a fair value
vand intervalufor a property. - Build a
p1attestation via ProofKit. - Publish it as a 0-ALGO self-transaction on Algorand TestNet/MainNet.
- Compute a fair value
On-chain collateral / lending
- Issue PoVal proofs for assets used as collateral.
- Let risk engines consume the on-chain
p1notes and verify them independently.
Back-office & attestations feed
- Run a service that continuously publishes updated valuations.
- Maintain a verifiable trail of model versions, hashes and timestamps.
Installation
npm install @axiomatic_oracle/proofkit algosdkRequirements:
- Node.js 18+ (or a browser with
fetch,TextEncoder,crypto.subtle). algosdkis required by your app (listed as a dependency).
p1 structure
buildP1 returns an object of the form:
export type P1 = {
s: "p1"; // schema marker
a: string; // asset tag (e.g. "re:EUR")
mv: string; // model version
mh: string; // model hash (hex, optional)
ih: string; // input hash (hex, required)
v: number; // point estimate (e.g. value)
u: [number, number]; // uncertainty range [low, high]
ts: number; // unix epoch seconds
};The object is normalized and serialized using a JCS/ACJ-style canonical JSON encoder for stable hashing and cross-language parity.
Quickstart (Node.js): build and publish a p1
Example using a local mnemonic on TestNet (demo only).
import "dotenv/config";
import algosdk from "algosdk";
import {
buildP1,
publishP1,
buildCanonicalInput,
computeInputHash,
} from "@axiomatic_oracle/proofkit";
async function main() {
const mnemonic = process.env.ALGORAND_MNEMONIC || "";
const network = (process.env.ALGORAND_NETWORK || "testnet").trim();
if (!mnemonic) {
throw new Error("Missing ALGORAND_MNEMONIC");
}
const { sk, addr } = algosdk.mnemonicToSecretKey(mnemonic);
const from = addr.toString();
// 1) Optional: derive a canonical input hash from your raw input
const rawInput = {
property_id: "demo-123",
country: "IT",
value_hint: 550000,
};
const allowedKeys = Object.keys(rawInput);
const canonicalInput = buildCanonicalInput(rawInput, allowedKeys);
const inputHashHex = await computeInputHash(canonicalInput, allowedKeys);
// 2) Build a p1 attestation
const p1 = buildP1({
assetTag: "re:EUR",
modelVersion: "v2",
modelHashHex: "",
inputHashHex,
valueEUR: 550000,
uncertaintyLowEUR: 520000,
uncertaintyHighEUR: 580000,
// timestampEpochSec optional (defaults to now)
});
// 3) Signer: you control the keys. ProofKit only passes bytes to sign.
const sign = async (unsignedBytes: Uint8Array): Promise<Uint8Array> => {
const tx = algosdk.decodeUnsignedTransaction(unsignedBytes);
const { blob } = algosdk.signTransaction(tx, sk);
return blob; // msgpack-encoded SignedTransaction
};
// 4) Publish as a 0-ALGO self-transaction with canonical note
const res = await publishP1({
p1,
from,
sign,
network, // "testnet" or "mainnet"
// optional: custom algod via `algod`
// optional: Pera in browser via `pera`
});
console.log("P1 published:", res);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});This will:
- Build a canonical
p1. - Create a 0-ALGO self-payment with the
p1note. - Sign using your function or Pera.
- Submit via Algonode by default.
- Return
{ txid, explorerUrl }.
Publish → verify (end-to-end)
To verify a published p1 attestation from Node, use
@axiomatic_oracle/verifier:
import { verifyTx } from "@axiomatic_oracle/verifier";
const res = await verifyTx({
txid: "YOUR_TXID",
network: "testnet",
maxSkewPastSec: 3600,
maxSkewFutureSec: 300,
});
console.log(res.verified, res.reason);This checks that:
- the note is structurally valid,
- canonicalization and
sha256match, - the timestamp
tsis inside your time window.
API surface
From @axiomatic_oracle/proofkit:
buildP1(options)→P1canonicalNoteBytesP1(p1)→{ bytes, sha256, size }assertNoteSizeOK(p1, maxBytes?)buildCanonicalInput(record, allowedKeys, stripNone?)computeInputHash(record, allowedKeys)→sha256(JCS-style)publishP1(options)→{ txid, explorerUrl }NOTE_MAX_BYTESDEFAULT_ASSET_TAG- Types:
P1,BuildP1Opts,PublishOpts,Network
Signing model
publishP1 is intentionally minimal:
export type PublishOpts = {
p1: P1;
network?: "testnet" | "mainnet";
algod?: any; // custom Algodv2 client (optional)
pera?: any; // PeraWallet instance in browser (optional)
from?: string;
sign?: (unsignedBytes: Uint8Array) => Promise<Uint8Array>;
waitRounds?: number;
};You must provide either:
pera: in-browser signing flow, orsign: a function that receives unsigned tx bytes and returns signed tx bytes.
This keeps all key management under your control.
Relationship with other SDKs
- Use
@axiomatic_oracle/proofkitto build and publishp1attestations. - Use
@axiomatic_oracle/verifier(Node) oraxiomatic_verifier(Python) to independently validate the on-chain note. - Canonicalization and hashing are aligned across all ProofKit / Verifier SDKs.
Security notes
- Keys never leave your environment: ProofKit only builds payloads and tx bytes.
- For production, replace mnemonic-based signing with wallets, custodial services, HSM/KMS, etc.
- Always review your signing and broadcasting pipeline according to your security and compliance requirements.
