feat: @orangecheck/me-client v0.2.0 — IntegratorPriceConfig + computeFees#5
Merged
Conversation
The Packages workflow's build matrix was missing me-client, so PR #3 (me-client v0.1.0) merged green without ever building or testing the new package — and never auto-published to npm. v0.1.0 was published manually via NPM_TOKEN to unblock /integrate code samples. This commit closes that gap so future me-client versions go through the same gate every other package does: - packages.yml: add me-client to the build matrix. - release.yml: add me-client-v* to the tag-trigger list, plus a matching docstring entry. After merge, future releases ship with: yarn version → git tag me-client-v0.X.0 → git push --tags. Packages CI runs build+test on every push, release.yml publishes on tag push. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Fees
Mirror the systemic refactor in oc-me-web. The package now exports the
canonical integrator-configurable pricing types:
- IntegratorPriceConfig — what every integrator declares
- IntegratorEventConfig — per-subtype { enabled, site_pays, user_share_pct }
- SiteFeeShape — { kind: 'fixed_sats' | 'percent_of_amount', ... }
- ComputedFees — the four-way split: gross / platform / user / site_rebate
Plus the platform constants OC inherits to all integrators:
- PLATFORM_FEE_POLICY = { pct: 0.2, min_floor_sats: 1, ratified }
- MIN_INTEGRATOR_PRICE_SATS = 5
- computeFees(cfg, payment_amount?) helper for client-side preview
Type bundle grew 3.79 KB → 4.81 KB.
Already published manually; this commit makes the version bump
auditable in git history. Future versions auto-publish on
me-client-v0.X.0 tags now that PR #4 added me-client to the release
workflow's tag list.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Xaxis
added a commit
that referenced
this pull request
May 6, 2026
First release of @orangecheck/pledge-core — the load-bearing TypeScript
reference implementation of the OC Pledge protocol. Closes the 6th-verb
gap (every other family member already shipped a -core; pledge had none,
which is why the ochk.io homepage status pill was downgraded to "preview"
ahead of this commit).
Implements:
- canonicalPledgeMessage / canonicalOutcomeMessage /
canonicalAbandonmentMessage — byte-exact builders matching SPEC §3.1,
§4.1, §5.1. Domain separators: "oc-pledge/v1" / "oc-pledge-outcome/v1"
/ "oc-pledge-abandonment/v1". LF-separated, no trailing LF.
- computePledgeId / computeOutcomeId / computeAbandonmentId — sha256
over the canonical bytes, lowercase hex, the content-addressed id.
- createPledge / createOutcome / createAbandonment — build, validate,
sign. Caller supplies BIP-322 signer adapter (Bip322Signer interface).
- verifyPledge / verifyOutcome / verifyAbandonment — version + shape +
canonical-message reconstruction + id check + BIP-322 verify (when
a verifier is supplied). skipSignatureVerification path for
test-vector fixtures with placeholder sigs.
- classifyState — pure-function §4.4 state machine over (pledge,
outcome | null, abandonment | null, now, chain?, contradictoryOutcomes?).
Handles block-typed resolves_at, abandonment-trumps-everything (no
honorable exit), bilateral contradiction → disputed.
- verifyBond — §8 algorithm with caller-injected AttestationLookup.
No bundled Bitcoin RPC by design — same shape as
@orangecheck/stamp-core's verifyOtsAnchor adapter.
- validateResolutionQuery — regex-level grammar gates for the seven
§3.4 mechanisms; refuses self_proof per §3.4.8.
- canonicalize / canonicalizePledgeEnvelope (etc) — RFC 8785 JSON
canonicalization shared across all three envelope kinds. Same
encoder as stamp-core (sorted keys, no insignificant whitespace,
\uXXXX-escaped control chars, undefined keys dropped).
- PledgeError class carrying SPEC §10 error codes (E_PLEDGE_*,
E_OUTCOME_*, E_ABANDONMENT_*, E_BOND_*, E_RESOLUTION_*,
E_DELEGATION_*).
- generateNonce — 32-char-hex helper using globalThis.crypto.
Conformance:
- Cross-implementation conformance harness in src/test-vectors.test.ts
loads every committed vector in oc-pledge-protocol/test-vectors/
(28 vectors as of this commit) and asserts:
· canonical_message reconstructs byte-identical
· canonical_message_bytes_len matches
· pledge_id / outcome_id / abandonment_id == sha256(canonical_bytes)
· declared envelope passes verifyX(skipSignatureVerification:true)
· bond-verification fixtures produce the named expected.code
· state-transition fixtures produce the named expected.state
· bilateral consistency / contradiction → kept / disputed
· malformed-input v28 (empty nonce) raises E_PLEDGE_MALFORMED
- All 28 vectors green. Vector locator checks (a) OC_PLEDGE_VECTORS_DIR
env, (b) sibling oc-pledge-protocol checkout, (c) user-home fallback.
Two SPEC nuances surfaced and handled (both pinned by vectors):
- V08 (agent-delegated) has sig.pubkey = swearer.address (the
principal), not agent_address. SPEC §3.6 says sig.pubkey MUST equal
agent_address; SPEC §7.3 step 6 says "verify sig.value under
agent_address" treating sig.pubkey as informational. The vector
follows §7.3. Resolution: relax shape check, use agent_address as
the BIP-322 verification key when via_delegation is present.
- V16 (counterparty_signs + outcome=expired_unresolved) has
resolved_by="deterministic" + sig=null. Discriminator is resolved_by,
not mechanism — outcomeRequiresSignature() now keys off resolved_by.
"expired_unresolved" is a deterministic classification any verifier
can make once the deadline passes without a counterparty signature.
CI:
- .github/workflows/packages.yml gains pledge-core in the build matrix
+ the protocol-vectors checkout step that mirrors vote-core /
agent-core (clones oc-pledge-protocol → exposes via
OC_PLEDGE_VECTORS_DIR).
Tests: 105 passing across 7 files (canonical, pledge, outcome,
abandonment paths, bond, state, resolution, plus the 28-vector harness).
Stack: TypeScript ES2020, tsup CJS+ESM dual build, vitest, @noble/hashes
for sha256. No bundled Bitcoin RPC, no Nostr client, no BIP-322 lib —
all I/O lives in caller-supplied adapters so the SDK runs everywhere.
Status: 0.1.0-alpha tracking oc-pledge-protocol v0.1.0-alpha. v1.0.0
will land alongside protocol stabilization (Tasks #5 cross-impl Python +
#6 dogfood real pledges + #7 SECURITY re-walk + #8 bump).
Xaxis
added a commit
that referenced
this pull request
May 7, 2026
Mirrors @orangecheck/pledge-core@0.1.0 function-for-function so the
"cross-impl, where it counts" claim on ochk.io now applies to OC Pledge
the same way it applies to OC Attest. All 28 committed test vectors in
oc-pledge-protocol/test-vectors/ reproduce byte-identically across the
two SDKs.
Module layout (orangecheck/pledge/):
canonical.py Canonical messages, ids, validators, RFC 8785 envelope
canonicalization. Exports:
canonical_pledge_message / _outcome_ / _abandonment_
compute_pledge_id / _outcome_id / _abandonment_id
validate_pledge_input / _outcome_ / _abandonment_
pledge_input_from_dict / _outcome_ / _abandonment_
canonicalize_envelope, generate_nonce
Frozen dataclasses for inputs (PledgeCanonicalInput,
OutcomeCanonicalInput, AbandonmentCanonicalInput,
ResolvesAtTime / ResolvesAtBlock, PledgeBond /
Resolution / Dispute, OutcomeEvidence).
envelopes.py create_pledge / verify_pledge with the §3.5
hex-id-as-sign-target rule and the §7.3
agent-address-as-verify-key override; create/verify
for outcome and abandonment envelopes; PledgeError
carrying SPEC §10 codes; the Bip322Signer Protocol
and VerifyBip322 Callable typing for caller adapters.
The §4.3 `expired_unresolved` nuance (test vector v16)
is honoured: outcomeRequiresSignature() keys off
resolved_by, not mechanism.
state.py classify_state — pure-function §4.4 transition table.
Pure Python ISO-8601-UTC parsing (regex + civil-from-
days arithmetic) avoids datetime quirks across CPython
versions and is stable on Python 3.9+.
bond.py verify_bond — the §8 algorithm with a sync-callable
attestation lookup. Caller pre-resolves an
AttestationLookupResult and hands it in; mirrors the
TS SDK's verifyBond shape minus the Promise.
resolution.py validate_resolution_query — regex-level grammar gates
for the seven §3.4 mechanisms. Refuses self_proof per
§3.4.8.
Conformance harness (tests/pledge/test_vectors.py):
* Loads vectors via OC_PLEDGE_VECTORS_DIR env, sibling-clone, or a
user-home fallback (same locator pattern as vote-core / agent-core).
* Parameterizes pytest over the 28 committed vectors; fails the named
vector if any of canonical_message / id / state / bond code / error
code drifts.
* As of this commit, all 28 pass:
v01-v10 pledge envelopes (all 7 mechanisms + agent-delegated +
edge cases)
v11-v16 outcome envelopes (kept / broken / disputed /
expired_unresolved across deterministic and
counterparty-signed paths)
v17 abandonment envelope
v18-v20 bond verification (valid / insufficient sats /
bond-draining UTXO spend)
v21-v22 bilateral consistency / contradiction → kept / disputed
v23-v27 state-machine transitions (pending / resolvable / kept /
broken-via-abandonment / expired_unresolved)
v28 empty-nonce rejection → E_PLEDGE_MALFORMED
Test counts (full sdk-py suite):
* Existing OC Attest tests: 52 passing (unchanged)
* New pledge conformance: 28 passing
* Total: 80 passing in 0.22s on Python 3.11
Package shape:
* pyproject.toml: 0.1.3 → 0.2.0 (minor — additive submodule)
* orangecheck/__init__.py: re-exports `from . import pledge as pledge`
so consumers can write `from orangecheck import pledge` or use the
nested attribute path.
* No new runtime dependency. Optional `[verify]` extra (bip322 native
binding) is reused; pledge's BIP-322 hook accepts any verifier
callable matching `(msg, sig_b64, address) -> bool`, including
orangecheck.verify_bip322_signature.
This unblocks Task #5 (extend the conformance CI job in
oc-packages/.github/workflows/packages.yml to clone oc-pledge-protocol
and run both SDKs against its 28 vectors). Closes Task #4.
Xaxis
added a commit
that referenced
this pull request
May 7, 2026
Extends the oc-packages conformance gate so the homepage's "cross-impl,
where it counts" claim now applies to OC Pledge in CI, not just locally.
Two surgical edits to packages.yml:
1. The basic `python` job now also clones oc-pledge-protocol and exposes
it via OC_PLEDGE_VECTORS_DIR. Previously the new pledge tests in
tests/pledge/test_vectors.py would gracefully skip on CI (no vectors
directory present); now they run as part of every PR's CI gate.
Move `working-directory: sdk-py` from `defaults` onto the install/
test step alone so the protocol checkouts can land at the workspace
root rather than under sdk-py/.
2. The `conformance` job gains parallel pledge-side steps:
* Clone oc-pledge-protocol/main alongside oc-attest-protocol.
* Run pledge-core's TS conformance suite against
/tmp/oc-pledge-protocol/test-vectors.
* Run sdk-py's pledge conformance suite against the same dir.
Two SDKs producing byte-identical canonical messages + ids for every
one of the 28 committed vectors IS the gate. Note that pledge has no
in-tree vendoring (both SDKs load at test time), so the "vendored
copy drifted from spec" failure mode is impossible by construction —
only the symmetric drift "TS produced X, Python produced Y" can fail
this job, which is exactly the property "cross-impl tested" claims.
Comment block at the top of the conformance job documents the two-family
gate so future maintainers don't strip the pledge half thinking it's
duplicated work.
Closes Task #5.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Mirrors the systemic refactor in oc-me-web. Adds canonical integrator-configurable pricing types and computeFees() helper. Already published to npm; this commit makes the version bump auditable.
🤖 Generated with Claude Code