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

@orangecheck/pledge-core

v1.0.0

Published

OC Pledge canonical messages, envelope format, create/verify, state machine, bond verification. Reference SDK for the OC Pledge v0.1 spec.

Readme

@orangecheck/pledge-core

Reference TypeScript SDK for the OC Pledge protocol.

OC Pledge is a Bitcoin-anchored, custody-free commitment primitive: a swearer signs a forward-looking proposition (BIP-322), bonds an OrangeCheck attestation to the pledge, and names a pure-function resolution rule that any verifier can evaluate against public state. Outcomes are recorded as separate envelopes; abandonment counts as broken. The protocol never holds the bonded sats — enforcement is by public exposure.

This package implements the load-bearing parts of OC Pledge v1.0:

  • canonical messages for pledge, pledge-outcome, and pledge-abandonment
  • content-addressed ids (sha256(canonical_message))
  • create + verify for all three envelope kinds
  • bond verification algorithm (§8) — caller injects the chain accessor
  • the §4.4 state machine
  • resolution-grammar validation for the seven mechanisms in §3.4
  • RFC 8785 envelope canonicalization
  • byte-identical conformance against every committed test vector in oc-pledge-protocol/test-vectors/

The package does not ship a Bitcoin RPC client, a Nostr relay client, an HTTPS fetch client, or a BIP-322 signing/verification implementation — those are caller-supplied adapters so the SDK works in browsers, Node, mobile, and CLIs without imposing a runtime opinion.

Status: v1.0.0 — Stable. Tracks oc-pledge-protocol v1.0. Cross-impl conformance with orangecheck.pledge (Python) is gated in CI on every PR.

Install

npm install @orangecheck/pledge-core
# or
yarn add @orangecheck/pledge-core

Peer-free except for @noble/hashes (SHA-256).

Quick start — create + verify a pledge

import { createPledge, verifyPledge } from '@orangecheck/pledge-core';

const env = await createPledge({
    swearer: 'bc1qalice000000000000000000000000000000000',
    proposition: 'I will publish a research preprint with content_hash sha256:e3b0c4… before 2026-09-01.',
    resolution: {
        mechanism: 'stamp_published',
        query: 'stamp(content_hash=sha256:e3b0c4…, signer=bc1qalice…)',
    },
    resolves_at: { time: '2026-09-01T00:00:00Z' },
    expires_at: '2026-09-08T00:00:00Z',
    bond: {
        attestation_id: '<64-hex SHA-256 of an OrangeCheck attestation>',
        min_sats: 1_000_000,
        min_days: 90,
    },
    counterparty: null,
    dispute: { mechanism: null, params: null },
    swearerSigner: {
        address: 'bc1qalice000000000000000000000000000000000',
        signMessage: async (msgHex) => {
            // The `msgHex` argument is the lowercase hex-encoded pledge id.
            // Hand it to your wallet adapter of choice (e.g. bip322-js,
            // sparrow, your own).
            return '<base64 BIP-322 sig>';
        },
    },
});

console.log(env.id);  // 64 lowercase hex chars

const result = await verifyPledge({
    envelope: env,
    verifyBip322: async (msg, sigB64, address) => {
        // Wire your BIP-322 verifier of choice here.
        return true;
    },
});

if (result.ok) {
    console.log('verified', result.id);
} else {
    console.error(result.code, result.message);
}

Outcome envelopes

Deterministic outcome (any of the five non-counterparty mechanisms — chain_state, nostr_event_exists, stamp_published, http_get_hash, dns_record, vote_resolves):

import { createOutcome } from '@orangecheck/pledge-core';

const outcome = await createOutcome({
    pledge_id: env.id,
    outcome: 'kept',
    resolved_at: '2026-09-15T00:00:00Z',
    resolved_by: 'deterministic',
    evidence: {
        mechanism: 'stamp_published',
        result: 'true',
        witness: 'nostr_event_id=<64-hex>',
    },
    dispute_window_ends_at: '2026-09-22T00:00:00Z',
});
// outcome.sig === null

Counterparty-signed outcome:

const outcome = await createOutcome({
    pledge_id: env.id,
    outcome: 'kept',
    resolved_at: '2026-06-02T10:00:00Z',
    resolved_by: 'bc1qcounter000…',
    evidence: {
        mechanism: 'counterparty_signs',
        result: 'kept',
        witness: 'counterparty_sig=<base64 BIP-322>',
    },
    dispute_window_ends_at: '2026-06-09T10:00:00Z',
    signer: counterpartySigner,  // .address must equal resolved_by
});

Note (SPEC §4.3 nuance). counterparty_signs outcomes that classify as expired_unresolved are deterministic — anyone observes the deadline pass without a counterparty signature — so resolved_by="deterministic" and sig=null are correct in that case. Test vector v16 pins this. The SDK keys signature requirements off resolved_by, not mechanism.

State machine

import { classifyState } from '@orangecheck/pledge-core';

const state = classifyState({
    pledge: env,
    outcome: outcomeEnvelope,    // or null
    abandonment: null,
    now: new Date().toISOString().replace(/\.\d+Z$/, 'Z'),
    chain: { tip_height: 920100, tip_time: '2026-09-15T00:00:00Z' },
});
// state ∈ { pending | resolvable | kept | broken | disputed | expired_unresolved }

For block-typed resolves_at, supply chain.tip_height and chain.tip_time so the SDK can decide whether the pledge's resolves block has been mined yet. Without chain, block-typed pledges stay pending until expires_at passes.

Bond verification

import { verifyBond } from '@orangecheck/pledge-core';

const r = await verifyBond({
    pledge: env,
    now: new Date().toISOString().replace(/\.\d+Z$/, 'Z'),
    lookup: async (attestationId, nowIso) => {
        // Resolve the OrangeCheck attestation against live chain state.
        // Return null if not found; otherwise the resolved bond record.
        // This is where you wire your preferred Bitcoin RPC / mempool API.
        return {
            address: 'bc1qalice…',
            sats_bonded: 1_500_000,
            days_unspent: 95,
            utxo_spent_at_or_before_now: false,
        };
    },
});

Resolution-grammar validation

import { validateResolutionQuery } from '@orangecheck/pledge-core';

const r = validateResolutionQuery(
    'http_get_hash',
    'GET https://example.com/release.tar.gz body_sha256 == ' + 'a'.repeat(64),
);
// r.ok === true

The validator catches malformed queries and refused mechanisms (self_proof) per SPEC §3.4. It does not evaluate queries against public state — that's the caller's job.

Conformance

pledge-core is conformant with oc-pledge-protocol v1.0 if:

  • canonical messages reconstruct byte-identical from inputs
  • ids equal sha256(canonical_message_bytes) as 64 lowercase hex
  • envelopes round-trip through RFC 8785 canonicalization
  • state-transition fixtures produce the named expected.state
  • bond-verification fixtures produce the named expected.code
  • malformed-input fixtures raise the named SPEC error code

The conformance harness lives in src/test-vectors.test.ts and runs against the 28 vectors committed to oc-pledge-protocol/test-vectors/. Set OC_PLEDGE_VECTORS_DIR to point at the vectors directory in CI, or check out oc-pledge-protocol as a sibling for local dev. As of 1.0.0, all 28 vectors pass on both this SDK and the Python orangecheck.pledge sub-module; cross-impl byte-equality is enforced in oc-packages CI.

License

MIT.