Protocol · identity
Prove you hold bitcoin, without showing an ID.
Sats as signal. OC Attest is the identity protocol of the orangecheck family. You sign one message with your Bitcoin wallet. Anyone can then check, from public chain data, that your address has kept N sats unspent for N days.
orangecheck
identities:
address: bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq
purpose: portable reputation attestation (non-custodial)
nonce: 0011223344556677889900aabbccddee
issued_at: 2026-04-22T12:00:00Z
ack: I attest control of this address and bind it to my identities.- Open spec, MIT
- No ID asked
- Signing moves nothing
- Checkable without us
The problem
Open apps can’t tell a person from a bot farm.
The usual fixes ask honest people for more: a phone number, an ID scan, a puzzle that breaks every month. A farm gets around them anyway.
Bitcoin left unspent is different. Holding 100,000 sats for 30 days costs a real person almost nothing. Faking it ten thousand times means funding ten thousand wallets and waiting. OC Attest turns that cost into a proof any app can read.
How it works
Sign. Share. Check.
- 01
Sign
Your wallet signs a short, plain-text message that names your address and, if you like, handles you claim (GitHub, Nostr, a domain, X). You read every line before you sign. No transaction is made. - 02
Share
The signed message is a self-contained proof with a fixed id: the SHA-256 of the message. Keep it, attach it to a link, or publish it to Nostr relays so others can find it. - 03
Check
Anyone verifies the signature and reads your address’s unspent coins from the chain. They get two numbers, sats and days, and decide for themselves what is enough.
- The Bitcoin property it depends on
- A BIP-322 signature from a real address, and the value and age of that address’s unspent outputs. A plain keypair has no balance and no age, so the proof would mean nothing without Bitcoin.
Where it stands
Open, stable, and free to use.
The spec is version 1.0, marked stable since 2026-04-25, with 28 conformance vectors. A private form for backing one account with one coin is a 1.1 draft. The tools at attest.ochk.io are free and work today against Bitcoin mainnet. OC Attest asks for no ID and never holds your coins: signing moves nothing. orangecheck as a whole has not launched publicly yet.
Try it
What you can do today.
By id, address or handle. Your search goes to the relays directly.
attest.ochk.io/attest/discover
For developers
Build on it.
Gate anything with one call. @orangecheck/sdk (1.13.0 on npm) finds the latest proof for an address on Nostr, checks the signature, and recomputes sats and days from live chain data.
npm install @orangecheck/sdkGate
@orangecheck/gatemiddleware for Express, Next.js, Fastify and Hono that returns 403 below your bar; 0.3.0
React and Python
@orangecheck/react · orangecheckUI components, 0.2.1 on npm; the Python package, 2.2.0 on PyPI
import { check } from '@orangecheck/sdk';
const r = await check({ addr: 'bc1q...', minSats: 100_000, minDays: 30 });
if (r.ok) {
// r.sats and r.days were read from the chain just now
} else {
console.log(r.reasons); // e.g. ['not_found'] or ['below_min_days']
}Adding sign-in? There are two paths, and they are different things.
- The hosted account
- To sign people in with an orangecheck account, use ochk.app’s sign-in:
@orangecheck/me-clientand a project key. It is free. Start at the quickstart. To let in only accounts backed by a coin, see require backing. - Do it yourself, no account
@orangecheck/sdkhasissueChallengeandverifyChallenge, so your own server can prove a visitor controls an address and start its own session. See sign in with Bitcoin.
Check one
Verify a proof someone sent you.
Paste the share link you were sent, or its id. Share links look like https://attest.ochk.io/attest/<id>. Every published proof also has a checked page on this site, at ochk.io/a/<id>.
The verifier runs in your browser. It checks that:
- the message has the exact fixed lines, in order, and names the same address;
- the id is the SHA-256 of the message, so nothing was changed after signing;
- the address’s network matches (mainnet unless the message says testnet or signet);
- the BIP-322 signature is valid for that address (legacy signatures only for
1…addresses); - the address has confirmed, unspent coins now, and how many sats for how many days. It counts the oldest coins first, so an old speck of dust can’t lend its age to a fresh deposit;
- any expiry or origin the signer set still holds.
A proof passes only when the signature is valid and confirmed coins back it. A valid signature over an empty address is reported as valid but does not pass.
You don’t need us for any of this. With the message, the signature and any Bitcoin node or block explorer, you can run the same checks yourself. @orangecheck/sdk and oc verify run them on your own machine.
What you trust
Every party you rely on, by name.
- Chain data
- The SDK and the verify page read coins from mempool.space, then blockstream.info if that fails. You can point the SDK at your own node’s Esplora instead.
- Relays, for finding proofs
- By default the SDK searches relay.damus.io, nos.lol, relay.snort.social and relay.ochk.io. A relay can hide a proof. It can’t forge one, because verifiers check the signed message, not the relay’s labels.
- Publishing
- attest.ochk.io re-checks your proof, then wraps it in a Nostr event signed with an orangecheck service key and sends it to nine relays. That key is only the envelope. The proof is your Bitcoin signature inside.
- The hosted API
attest.ochk.io/api/checkruns these checks on our servers. It is a convenience, not the authority. A compromised server could lie, so for anything that matters, check it yourself. The Python SDK’scheck()calls this API.- Handles
- A claimed GitHub, Nostr, domain or X handle is self-asserted. Check it the way you check any handle, for example a gist or a DNS record that contains the proof’s id.
- Backing on ochk.app
- There, ochk.io acts as the registry: it sees which coin backs which account and keeps checking it. The apps you sign in to see only “at least N sats, held at least D days”, never the coin.
What it is not
The limits, plainly.
- Not proof of personhood
- One person can hold many addresses. OC Attest raises the cost of fakes. It does not make them impossible.
- Not private
- A published proof shows your address, its balance and its history. Use a fresh address for each context if that matters. Backing an account on ochk.app is the private form.
- Not permanent
- A proof shows what was true when it is checked. Spend the coins and the next check fails.
- Not a reputation score
- Sats and days are the facts. The reference score is advisory, and each app sets its own bar.
Where it is used
Apps that use it.
- ochk.app (opens in a new tab)
- Backing your account uses OC Attest’s one-coin, one-account format. The coin stays in your wallet.
- OC Pledge
- A pledge’s stake is an OC Attest proof, re-checked against the chain whenever the pledge is verified.
- OC Stamp
- A stamp can carry a proof’s id as a stake signal at the moment of signing.
Make your first proof.
The tools are free and need no account. The spec is open to anyone who wants to build their own.
With thanks to Bram Kanstein, whose work on Bitcoin as a sovereignty layer shaped the premise.