TRACK C · DePIN T0 / T1 CUSTODY ZERO KEYS HELD wasm32-wasip2 CHANNEL-AGNOSTIC

The machine that earns, acts,
and proves it.

Three ZeroClaw plugins implement a non-custodial Solana payment rail: create a charge, verify it at finalized commitment, authenticate device heartbeats, and build unsigned hash-chained records. The AI never touches a key; the external order driver, relay adapter, and attestation signer are still integration work.

View the code View the target flow ↓
0repository tests green
0KB offline component
3bounded plugins
0keys the agent holds
Target flow

The intended sale — implemented rail, explicit integration boundaries

Payment truth comes from the chain and the watcher emits a structured verdict. The animation continues through the desired external-driver, relay, and signer steps so their contracts are easy to understand; those steps are not shipped as an autonomous loop.

This animation is an explainer, not the demo. It is a scripted illustration of the target flow — no agent, chain, signer, or hardware is running on this page. Only a separately linked video should be treated as demo evidence. Exact pinned ZeroClaw headless cron does not self-dispatch ordinary plugin steps; an external driver is required.

@DrinkKioskBot — any ZeroClaw channel
raspberry pi 4 · zeroclaw host
kiosk-watch
idle
trusted driver gate
waiting: paid + exclusive claim
🔒
RELAY · GPIO17 · closed
kiosk-attest
01customer orders in chat
02kiosk-charge builds Pay URL + reference
03QR / tap link shown
04customer's own wallet signs
05kiosk-watch verifies on-chain
06target driver claims order, then calls safe relay
07kiosk-attest builds unsigned receipt
08external signer submits + finalizes
Three tools, one substrate

Small plugins. One job each. No god-tool.

Standalone [workspace] crates matching the canonical redact-text layout: pure host-testable core, thin wasm shim, structured logging, minimal permissions. All three share kiosk-core — hand-rolled base58, shortvec, Solana Pay, mockable JSON-RPC. No solana-sdk.

T1

kiosk-charge

✓ shipped · 19 tests

"Charge 1.5 USDC for a cold drink" → versioned JSON, Solana Pay URL, unique reference, and a PKPAY1 reference/item memo. Recipient, mint, prices and caps come from operator config — the model cannot touch them.

permissions = ["config_read"] — zero network, zero secrets. The component imports no wasi:http at all.
T0

kiosk-watch

✓ shipped · 76 tests

Asks the chain whether the expected payment truly landed — recipient, mint, amount, reference/item memo, and finality all verified. Its heartbeat mode authenticates authority, device account, and device id before reporting liveness.

permissions = ["http_client", "config_read"] — read-only. It emits routeable JSON; an external driver must consume it.
T1

kiosk-attest

✓ builder · 38 tests

Hash-chained unsigned messages for sensor readings, sale receipts, and uptime. A durable nonce lets one pending artifact survive approval; the driver must finalize it before building the next. A transfer is not expressible; signing, submission, and finality are external.

permissions = ["http_client", "config_read"] — memo-only transactions, seq recovered from chain.
No hardware? No problem

Three rungs — the Pi is the upgrade, not the gate

Every plugin is useful standalone from a laptop. Hardware unlocks the flagship, it never gatekeeps the product.

The daily driver — zero hardware

The exact pinned, plugin-enabled ZeroClaw host plus any configured channel. The charge and watcher work without physical hardware; a localnet harness lands and validates a reference-bearing test-token transfer.

  • Charge anyone in USDC from a chat window — freelancer invoices, small shop sales
  • "Did invoice #412 get paid?" — answered by the watcher when invoked
  • Build a bounded unsigned attestation for an external signer

Who lives here

Freelancers invoicing in stablecoins, sellers on Telegram/Discord, anyone waiting on a payment, anyone who needs "prove this happened later."

setup: ~10 min · hardware: none · cost: $0

Provable conditions

Roadmap integration: any Linux box or Pi + a BME280 on I2C. The checked-in SOP documents the cadence, but pinned headless cron does not execute its ordinary sensor/plugin steps without an external driver.

  • Temperature/humidity history nobody can backdate or edit
  • Hash-chained reading artifacts with operator-configured bounds
  • Target: signer submission and operator alerting after a verified breach

Who lives here

Pharmacy fridges (cold-chain compliance), food storage, greenhouses, server closets, landlord/tenant disputes.

setup: ~30 min · hardware: ₹250–400 · cost: <$1/mo

The full kiosk — the machine acts

Roadmap integration: Pi 4 + relay on GPIO17 wired to a lock, dispenser, or plug. Trusted host-local order persistence and exclusive claiming exist; the driver, bounded relay_pulse adapter, crash-recovery journal, and delivery sensor do not.

  • Target: pay in chat → external driver actuates → signer lands a receipt
  • Vending, paid door access, EV/laundry/3D-printer time
  • Every sale becomes a provable on-chain event

Who lives here

Self-service machines of any kind, after the missing hardware and signer adapters are implemented and evidenced.

status: architecture + wiring guide · hardware run not yet evidenced
Safety & custody — 25% of the score, 100% of the trust

Prompt-inject it. It fails closed. Every row is an executable test.

The rule: the LLM is untrusted wherever money or actuation is concerned. The shipped plugins create and verify bounded artifacts; any future driver must use those structured verdicts and preserve the same boundary. Click each attack.

No component can build a transfer. charge's recipient is config-fixed; attest's transaction is memo-only — a transfer is not expressible in its output.
The paid verdict requires a finalized, exact payment, but explicitly says actuation_authorized=false. A future driver must consume the raw host-direct result, validate persisted order state, and create the exclusive local claim. No GPIO adapter is shipped.
serde deny_unknown_fields plus an explicit raw-key allowlist — deserialization fails before any logic runs. Shipped as a passing test today.
Free text is percent-encoded inert. The test asserts exactly one live amount param and zero recipient params.
Operator-configured metric bounds reject it and raise an alarm. Caps and sequence live in config + chain state, never in memory — the host gives a fresh sandbox every call, and designs that keep counters in memory silently reset. Ours can't.
Secrets never appear in args, outputs, logs, or Debug output (redacted). kiosk-charge holds no secret at all — there is nothing to print.
The field

Seven DePIN rivals build reporters. We build the whole machine.

CapabilityPalinurus#126 suitebest of others ×5ProofKiosk
Attestation + durable nonceyesyessomeyes
Real sensor on real GPIOsimulatednonowiring guide; not evidenced
Payments (Solana Pay)nononoshipped
Physical actuationnononotarget contract; adapter absent
Payment verification loopnouptime onlynoplugins ready; external driver needed
Attestation batching1 tx / reading1 tx / reading1 tx / readingnot shipped
Zero-hardware on-rampyesnonorung 1 of 3
Reproducibility — an evening, not a weekend

Run the payment rail from the exact host pin

operator@laptop
# exact ZeroClaw commit e112ce6… (source 0.8.2) + plugin backend
./scripts/install-pinned-zeroclaw.sh
export PATH="$PWD/.build/zeroclaw-install/bin:$PATH"

# exact host runs valid charge, paid-watch, and unsigned-attest paths
rustup target add wasm32-wasip2
./scripts/host-smoke.sh

# canonical host schema: one natural-key row per plugin
[plugins]
enabled = true
auto_discover = true

[[plugins.entries]]
name = "kiosk-charge"
[plugins.entries.config]
merchant_address = "YOUR_WALLET"
usdc_mint = "YOUR_SPL_MINT"
token_decimals = "6"
price_list = "cold_drink:1.5, snack:0.75"

# local test-token payment: separate customer → merchant, finalized
npm ci
MODE=localnet ./scripts/devnet-setup.sh
source .devnet/payment.env
npm run devnet:pay