- wrap my head around it
- see what can be done with it
- see if my instincts are right that this can be used as a basic smart contract vehicle
- what is the potential if we combine it with nostr-scrolls or just wasm snippets in general and where they belong
- have autistic discussions about it
All demos have a event/timeline inspector so we can see what's happening under the hood.
Check it out at: https://schlaustronics.com/nsm/
Source: https://github.com/zeSchlausKwab/nsm
Here is a short description for each demo:
#counter — Counter
The smallest possible Nostr state machine: two players, one shared counter, race to 5. Every TICK is a signed kind:7501; a 3rd-party custodian validates it against the SM definition and publishes a signed kind:30078 snapshot. Click TICK out of turn and watch the custodian reject it with NO_TRANSITION — no off-chain coordination, no shared backend.
#rps — Rock-Paper-Scissors
Commit-reveal RPS over Nostr. Both players publish a hash of their move first; only after both commitments land do they reveal the cleartext, so no one can peek and play accordingly. The SM enforces the order: REVEAL inputs are rejected before both commits exist.
#badges — Mint + Transfer
Mint a badge from any image — the asset id is sha256(image_bytes), content-addressable by construction. Transfers run through a shared "Ownership" state machine that requires the validator to cosign before the transfer settles, blocking double-spends. Open the "ownership proof" panel on a transferred badge to see the cryptographic chain you can verify offline.
#scroll-counter — Counter, but the action is a WASM scroll
Same counter, but the increment isn't hardcoded — it's a WebAssembly module published as a kind:1227 event ("a scroll"). Pick plus-one or times-two, the custodian fetches the scroll off the relay and runs it on every TICK. Actions are now content-addressed bytecode anyone can author, publish, and audit.
#bet — Time-driven betting with oracle + payout scrolls
Two parties stake, the match has wall-clock start/end times, and the SM advances itself: the custodian schedules START_MATCH / CANCEL_BET / TIMEOUT inputs from a schedule table. Resolution is two scrolls — an oracle scroll that names the winner, a payout scroll that computes splits. Optionally, the custodian delegates scroll execution to a remote CVM scroll-executor over MCP-over-Nostr (per CEP-15).
#vote — Deadline-driven voting
Open a question with a deadline; voters cast kind:7501 YES/NO/ABSTAIN inputs. The custodian schedules a synthetic FINALIZE input at the deadline, tallies votes against a configurable threshold, and snapshots the result — no one needs to "close the poll" manually. Watch the countdown tick, then watch the SM transition itself.
#negotiator — Two parties agree on a SM, a jukebox spawns it
Alice and Bob exchange kind:7500 proposals over Nostr (machine definition + scroll source) until both sign the same one. The agreed bundle is then handed to a "jukebox" — a CVM/MCP server that spawns + custodians the machine on demand. The whole negotiation is on-relay; the jukebox tool call rides MCP-over-Nostr per CEP-15, encrypted via NIP-44 gift-wraps.
#nested — Parent SM invokes child SMs
A tournament parent SM uses XState's invoke to spawn two child match SMs (counter-style, race to 4). Alice TICKs match A, bob TICKs match B; each child's onDone flips a flag in the parent, and an always transition fires FINISHED once both children complete. The interesting bit: each child's nested state (count, value, etc.) round-trips through kind:30078 verbatim — getPersistedSnapshot().children is what makes it work.
quotingI was recently working with state machines over Nostr for coordination between parties. The result is a distributed, event-driven, consistent state management protocol that can be used to model any process. It is also auditable, making it interesting for scientific and supply chain applications. Additionally, it enables the deployment of *smart contract-like* functionalities without the blockchain buzz or shitcoinery. I would love to hear your thoughts.
nevent1q…hvr9
This project was originally inspired by a talk from Alan (npub1nyx…h9ph) during the last Sovereign Engineering (nprofile…n66j) 5.
It's also my first time using ngit 🔥
https://gitworkshop.dev/npub1gzuushllat7pet0ccv9yuhygvc8ldeyhrgxuwg744dn5khnpk3gs3ea5ds/relay.ngit.dev/nsm
