A working PoC of a Tendermint (CometBFT) + EVM sidechain for Bitmark,
with a real two-way BTMK ⇄ wBTMK bridge, a validator bound to a did:nostr
identity, and an on-chain “Marks” gifting contract — all driven from a
no-build, browser-native ESM / JSON-LD dashboard.
Status: proof-of-concept, run against the live Bitmark network with real (and largely worthless 🙂) BTMK. Not production. The peg is a single-operator federation; see caveats below.

The no-build dashboard: bridge in (deposit), give marks by
did:nostr, bridge out (redeem) — the full round-trip in the browser, over a live Bitmark bridge.
→ The design rationale, trust model, and honest limits are in
docs/ARCHITECTURE.md.
The pieces exist separately — Tendermint+Bitcoin (Nomic, Babylon) and EVM+Bitcoin (Rootstock, Botanix) — but Tendermint + EVM + a Bitcoin-family peg together is an under-explored cell. Bitmark is a good host: it isn’t Bitcoin (no tribal politics), it already hardened L1 with multi-algo PoW (MPoW6), and we control the chain. The sidechain adds what L1 can’t do: ~3s deterministic finality and smart contracts.
Bitmark L1 (MPoW6 PoW · ElectrumX: electrum.bitmark.rocks:50002)
│ deposit BTMK ──▶ peg-watcher.js ──▶ wBTMK.pegMint (mint)
│ release BTMK ◀── redeem-watcher.js ◀── wBTMK PegBurn (burn)
▼
Tendermint / EVM sidechain (CometBFT + evmos · chainId 9000 · ~3s final)
├─ wBTMK bridged Bitmark, ERC-20
├─ Marking.sol "a currency for giving" — gift wBTMK with a reason
└─ validator ⇄ did:nostr (consensus key in the DID doc + on-chain
description + a BIP340-signed attestation)
▲
ui/ — no-build ESM dashboard polling /bridge-state.jsonld (JSON-LD)
7613b651…268e12) → 0.8 wBTMK minted, the L1
txid recorded in the PegMint event.a4308960…d3145c),
change returned to the reserve.description.details, and the DID key signed
an attestation over it — all verifiable with scripts/verify-binding.sh.Needs evmosd (evmos v20 prebuilt binary), Node 20+, and Foundry.
# 1. start the single-validator Tendermint/EVM devnet (JSON-RPC :8545)
./scripts/start-chain.sh
# 2. deploy wBTMK + Marking (writes evm/deployment.json, read by everything)
./scripts/deploy.sh
# 3. bridge + UI
npm run watch # peg-in: Bitmark deposits -> wBTMK
npm run redeem # peg-out: wBTMK burns -> Bitmark releases
npm run ui # dashboard at http://localhost:8080
Or, once the contracts are deployed, bring up the whole stack (chain + both watchers + UI) with one command and tear it down with another:
./scripts/demo-up.sh # http://localhost:8080
./scripts/demo-down.sh
In the UI you can connect a Nostr identity (xlogin), bridge in (deposit to your address), give marks (gift wBTMK with a reason, tagged by did:nostr), and bridge out (redeem to Bitmark L1) — the full round-trip, no scripts.
Full details, the exact peg/identity/Marks flows, and the honest trust model are
in evm/README.md.
| Path | What |
|---|---|
scripts/ |
start/stop the single-validator chain; verify-binding.sh |
evm/*.sol |
wBTMK (bridged token) and Marking (gifting) contracts |
evm/electrum.js, btmk.js, btmk-tx.js |
Bitmark L1: ElectrumX client, addresses, tx signer (pure JS) |
evm/peg-watcher.js, redeem-watcher.js |
the two-way bridge |
evm/server.js |
zero-dep server: static UI + live /bridge-state.jsonld |
ui/ |
no-build ESM dashboard (semantic HTML + data-island hydration) |
agent.did.json |
the agent’s did:nostr identity, wired to the validator |
0xE9B1… deployer key in the code is the public, documented
evmos local-test key. Don’t use it anywhere real.start-chain.sh generates a new consensus key.🤖 Built with Claude Code.