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

insumer-verify

v1.4.3

Published

Client-side verifier for InsumerAPI condition-based access attestations. ECDSA P-256 signatures, condition hashes, block freshness, expiry. Zero dependencies. Used by DJD Agent Score (Coinbase x402).

Downloads

1,971

Readme

insumer-verify

Client-side verifier for InsumerAPI wallet auth attestations. Validates ECDSA P-256 signatures, condition hashes, block freshness, and attestation expiry. Zero runtime dependencies. Web Crypto API. Node.js 18+ and modern browsers.

In production: DJD Agent Score (Coinbase x402 ecosystem) uses insumer-verify for client-side cryptographic verification in their AI agent wallet trust scoring pipeline. Case study.

Part of the InsumerAPI ecosystem: REST API (26 endpoints, 33 chains) | MCP server (npm) | LangChain (PyPI) | ElizaOS (10 actions, npm) | OpenAI GPT (GPT Store)

Install

npm install insumer-verify

Get an API Key

Generate one from your terminal — no browser needed:

curl -s -X POST https://api.insumermodel.com/v1/keys/create \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "appName": "insumer-verify", "tier": "free"}' | jq .

Returns an insr_live_... key with 100 reads/day and 10 verification credits. One free key per email.

Or get one at insumermodel.com/developers.

Usage

Call InsumerAPI, get a signed attestation, verify it:

import { verifyAttestation } from "insumer-verify";

// 1. Call InsumerAPI
const res = await fetch("https://api.insumermodel.com/v1/attest", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": "insr_live_your_key_here",
  },
  body: JSON.stringify({
    wallet: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    conditions: [
      {
        type: "token_balance",
        chainId: 1,
        contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        threshold: 1000,
        decimals: 6,
        label: "USDC >= 1000 on Ethereum",
      },
    ],
  }),
});

const apiResponse = await res.json();

// 2. Verify the attestation (signature, condition hashes, freshness, expiry)
const result = await verifyAttestation(apiResponse, {
  jwksUrl: "https://insumermodel.com/.well-known/jwks.json",
  maxAge: 120,
});

if (result.valid) {
  const { pass, results } = apiResponse.data.attestation;
  console.log(`All conditions ${pass ? "met" : "not met"}`);
  for (const r of results) {
    console.log(`  ${r.label}: ${r.met ? "met" : "not met"}`);
  }
} else {
  console.log("Verification failed:", result.checks);
}

What the API returns

The attestation response you're verifying looks like this:

{
  "ok": true,
  "data": {
    "attestation": {
      "id": "ATST-A7C3E1B2D4F56789",
      "pass": true,
      "results": [
        {
          "condition": 0,
          "met": true,
          "label": "USDC >= 1000 on Ethereum",
          "type": "token_balance",
          "chainId": 1,
          "evaluatedCondition": {
            "chainId": 1,
            "contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            "decimals": 6,
            "operator": "gte",
            "threshold": 1000,
            "type": "token_balance"
          },
          "conditionHash": "0x554251734232c8b43062f1cf2bb51b76650d13268104d74c645f4893e67ef69c",
          "blockNumber": "0x129e3f7",
          "blockTimestamp": "2026-02-28T12:34:56.000Z"
        }
      ],
      "passCount": 1,
      "failCount": 0,
      "attestedAt": "2026-02-28T12:34:57.000Z",
      "expiresAt": "2026-02-28T13:04:57.000Z"
    },
    "sig": "dmNJKqnGZ9f47qpWax9gxgw1DhUKHKHrbLspTop8NWzYhv2fNpVAt1gAuhUfU4xPsgXTCdrmTXI4vEE50dcfEA==",
    "kid": "insumer-attest-v1"
  },
  "meta": { "version": "1.0", "timestamp": "2026-03-26T20:04:34.153Z", "creditsRemaining": 99, "creditsCharged": 1 }
}

No balances. No amounts. Just a signed true/false per condition.

XRPL-specific fields

XRPL attestation results use ledgerIndex (integer) and ledgerHash (string) instead of blockNumber and blockTimestamp:

{
  "condition": 0,
  "met": true,
  "label": "RLUSD >= 100 on XRPL",
  "type": "token_balance",
  "chainId": "xrpl",
  "evaluatedCondition": {
    "type": "token_balance",
    "chainId": "xrpl",
    "contractAddress": "rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De",
    "currency": "524C555344000000000000000000000000000000",
    "operator": "gte",
    "threshold": 100,
    "decimals": 6
  },
  "conditionHash": "0x9f2c...",
  "ledgerIndex": 96482715,
  "ledgerHash": "A1B2C3D4..."
}

Trust line token conditions may also include trustLineState with a frozen boolean indicating whether the trust line is frozen:

"trustLineState": { "frozen": false }

Because XRPL results have no blockTimestamp, the freshness check (maxAge) skips them rather than failing. Condition hash and signature checks work identically across all chains.

Handling rpc_failure errors

If the API cannot reach one or more upstream data sources after retries, it returns ok: false with error code rpc_failure instead of issuing an attestation. No signature, no JWT, no credits charged. This is a retryable error — retry the same request after a short delay (2-5 seconds).

{
  "ok": false,
  "error": {
    "code": "rpc_failure",
    "message": "Unable to verify all conditions — data source unavailable after retries",
    "failedConditions": [
      { "source": "rpc", "chainId": "43114", "message": "Timeout" }
    ]
  },
  "meta": { "version": "1.0", "timestamp": "..." }
}

Important: rpc_failure is NOT a verification failure. It means the API could not check the condition at all. Do not treat it as pass: false. Check for ok: false with error.code === "rpc_failure" and retry:

const res = await fetch("https://api.insumermodel.com/v1/attest", { ... });
const data = await res.json();

if (!data.ok && data.error?.code === "rpc_failure") {
  // Retryable — data source temporarily unavailable
  // Wait 2-5 seconds and retry the same request
  console.log("RPC failure, retrying...", data.error.failedConditions);
  return;
}

// Only verify if we got an actual attestation
const result = await verifyAttestation(data, { maxAge: 120 });

Browser

<script type="module">
  import { verifyAttestation } from "https://esm.sh/insumer-verify";

  // apiResponse = attestation from your backend
  const result = await verifyAttestation(apiResponse, {
    jwksUrl: "https://insumermodel.com/.well-known/jwks.json",
  });
  console.log(result.valid, result.checks);
</script>

Freshness check

Pass maxAge (seconds) to reject attestations where block data is too old:

const result = await verifyAttestation(apiResponse, { maxAge: 120 });
// Fails if any blockTimestamp is older than 120 seconds

Results without blockTimestamp (certain EVM chains, Solana, and XRPL) are skipped, not treated as failures. XRPL results use ledgerIndex and ledgerHash instead.

JWKS key discovery

By default, insumer-verify uses the hardcoded InsumerAPI public key. You can opt in to dynamic key discovery via the JWKS endpoint:

const result = await verifyAttestation(apiResponse, {
  jwksUrl: "https://insumermodel.com/.well-known/jwks.json",
});

When jwksUrl is set, the library fetches the JWKS, matches the key by kid from the attestation response, and uses it for signature verification. This enables automatic key rotation without library updates.

API

verifyAttestation(response, options?)

| Parameter | Type | Description | |-----------|------|-------------| | response | unknown | Full InsumerAPI response envelope (must contain data.attestation and data.sig) |

Common mistake: Pass the full API response (await res.json()), not response.data or response.data.attestation. The function expects the outer envelope {ok, data: {attestation, sig, kid}, meta}. Passing the inner data object will throw "Invalid response: missing data object". | options.maxAge | number | Optional max age in seconds for block freshness check | | options.jwksUrl | string | Optional JWKS URL for dynamic key discovery (e.g. https://insumermodel.com/.well-known/jwks.json) |

Returns Promise<VerifyResult>:

interface VerifyResult {
  valid: boolean; // true only if ALL checks pass
  checks: {
    signature: { passed: boolean; reason?: string };
    conditionHashes: { passed: boolean; failures?: number[]; reason?: string };
    freshness: { passed: boolean; reason?: string };
    expiry: { passed: boolean; reason?: string };
  };
}

What gets verified

| Check | What it does | |-------|-------------| | Signature | Verifies the ECDSA P-256 signature over {id, pass, results, attestedAt} using InsumerAPI's public key | | Condition hashes | Recomputes SHA-256 of each evaluatedCondition (canonical sorted-key JSON) and compares to conditionHash | | Freshness | Checks blockTimestamp age against caller-defined maxAge (optional, skipped if not set) | | Expiry | Checks whether the attestation's 30-minute validity window has elapsed |

Condition hash specification

Each attestation result includes an evaluatedCondition object and a conditionHash. The hash is computed as:

  1. Extract all keys from evaluatedCondition and sort them alphabetically
  2. Serialize with JSON.stringify(evaluatedCondition, sortedKeys) (the sorted keys array as the replacer produces canonical key order)
  3. Compute SHA-256 of the UTF-8 encoded string
  4. Format as "0x" + hex

This ensures the condition that was actually evaluated on-chain can be independently verified by any third party.

Examples

The examples/ directory contains runnable scripts covering common patterns:

| Example | What it shows | |---------|--------------| | basic-attest.mjs | Single token balance check + verification | | multi-condition.mjs | Multiple conditions across different chains | | jwt-format.mjs | JWT format for gateway integration (Kong, Nginx, Cloudflare Access) | | verify-manual.mjs | DIY verification with Web Crypto — no library, proving the format is open | | express-gate.mjs | Express middleware: verify attestation before granting access | | xrpl-trustline.mjs | XRPL trust line tokens (RLUSD, USDC) |

INSUMER_API_KEY=insr_live_... node examples/basic-attest.mjs

The attestation format is an open standard — verify-manual.mjs demonstrates full verification using only the Web Crypto API with no dependencies. See the State Attestation Spec for the complete format definition.

Pricing

Tiers: Free (100 reads/day, 10 credits) | Pro $29/mo (1,000 credits/mo, 10,000/day) | Enterprise $99/mo (5,000 credits/mo, 100,000/day)

Volume discounts: $5–$99 = $0.04/call (25 credits/$1) · $100–$499 = $0.03 (33/$1, 25% off) · $500+ = $0.02 (50/$1, 50% off)

Platform wallets:

  • EVM (USDC/USDT): 0xAd982CB19aCCa2923Df8F687C0614a7700255a23
  • Solana (USDC/USDT): 6a1mLjefhvSJX1sEX8PTnionbE9DqoYjU6F6bNkT4Ydr
  • Bitcoin: bc1qg7qnerdhlmdn899zemtez5tcx2a2snc0dt9dt0

Supported payment chains: Ethereum, Base, Polygon, Arbitrum, Optimism, BNB Chain, Avalanche, Solana, Bitcoin. Tokens sent on unsupported chains cannot be recovered. All purchases are final and non-refundable. Full pricing →

License

MIT