Skip to content

Manuel-dev01/pulseGrid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PulseGrid

Real-time DePIN telemetry and verifiable settlement on BOT Chain.

Devices stream signed telemetry that is anchored on-chain every interval. An autonomous Settlement Agent then pays or slashes each operator per interval in stablecoin, automatically, continuously, and gaslessly for the devices. On-chain policy is the sole authority: an operator cannot be paid for data they did not deliver, and the agent cannot stiff an honest operator. Built for the BOT Chain Builder Challenge #1 (DePIN / Real World track, AI-Agent cross-eligible).

▶ Demo video: https://www.youtube.com/watch?v=zK4Gjhi_khY · Live app: https://pulsegrid-nine.vercel.app

Status: live on BOT Chain testnet (chainId 968). Gasless blob-anchored telemetry, on-chain per-epoch pay/slash, an autonomous Go agent, and a Next.js operator app wired to real chain and agent data. Every headline number below is a live chain read with an explorer link.

Seamless, no local setup. A tester connects a wallet, deploys a node, and clicks Go live to stream signed telemetry directly from the browser tab (gaslessly, the device key never leaves the client). The agent then pays it every satisfied interval and slashes it if the tab closes, all on-chain. The registry is permissionless, so anyone is an operator of the nodes they deploy. An optional DeepSeek layer adds advisory device-health narratives, kept strictly non-authoritative.

Reading the dashboard. It is always live against chain state, so it is never blank: the settlement ledger, its full settled history, and every proof transaction render immediately. BOT Chain has a gas floor, so the streaming fleet runs in short funded windows (for a recording or a judging session), not 24/7. When it is not streaming, devices honestly read "idle, not streaming" or "awaiting telemetry". That is truthful live state, not mock data. See What you'll see to bring it fully live.


The guarantee

Bilateral machine-trustlessness. SettlementVault.settleEpoch(deviceId, epoch) takes only (deviceId, epoch). The pay/slash verdict and the amount are re-derived on-chain from the device-signed anchor count and the SLA. A buggy or malicious agent cannot overpay, wrongly slash, pay an un-anchored epoch, or double-settle. This is proven by an adversarial Foundry suite (test_Adversarial_*), part of 68 passing tests.

Why BOT Chain (native integrations)

Native primitive How PulseGrid uses it
Sub-second blocks (0.74s, measured) per-interval real-time settlement driven by an autonomous agent
Near-zero fees (base fee 0, measured) continuous micro-settlement is economically viable
EOA Paymaster / gasless devices sign EIP-712 telemetry and spend zero gas (plain EOAs, no 4337) via a self-hosted MegaFuel-shaped sponsor relayer
Blob API (EIP-4844) raw telemetry rides in type-3 blobs; a compact blobhash(0) anchor is committed to state
On-chain policy authority the agent only drives; the vault re-derives every verdict

Autonomous + advisory AI (AI-Agent track). The Settlement Agent is an autonomous Go service that drives settlement each epoch; the contract decides. An optional DeepSeek layer reads the on-chain facts and the statistical reputation to produce advisory device-health analysis for the dashboard. It is display-only: there is no code path from any AI output to settleEpoch, so the guarantee is untouched, and the app runs identically without a key.

See docs/ARCHITECTURE.md for the design and docs/WRITEUP.md for the submission narrative.

Architecture

device (EOA, 0 gas) --EIP-712 signed telemetry--> sponsor relayer --type-3 blob tx--> TelemetryAnchor
                                                                                        | (anchorsInEpoch)
autonomous Settlement Agent --settleEpoch(deviceId, epoch)--> SettlementVault <-- PolicyModule (re-derives)
   (Go; predicts, never decides)                             dual escrow: funder payEscrow -> operator (PAY)
                                                                          operator bond -> treasury (SLASH)
Next.js app --viem server routes (reads)--> contracts        + reputation.json (agent intelligence layer)
            --wagmi wallet txs (writes)---> contracts
  • contracts/ Foundry: DeviceRegistry, TelemetryAnchor (epoch buckets), ServiceContract (versioned SLA), PolicyModule (pure verdict library), SettlementVault (dual escrow), MockUSD.
  • agent/ Go: settler (autonomous agent), paymaster (sponsor relayer), devicesim (gasless fleet), internal/{telemetry,chain,policy,reputation,ai} (ai = optional DeepSeek advisory layer). Container/host config in agent/Dockerfile + agent/railway.json.
  • web/ Next.js (App Router, wagmi/viem): landing plus the operator app, live-wired. A deployed node can stream from the browser tab (same EIP-712 signing) through the hosted relayer, no install.

Prerequisites

Foundry (forge/cast), Go 1.25+, Node 20+.

Reproduce it

A. View the live instance (no keys, read-only, works immediately)

The app defaults to the deployed demo instance, so it runs against real chain state out of the box.

git clone <this repo> && cd pulseGrid
make test                      # Foundry: 68/68 green
cp web/.env.local.example web/.env.local
make web-install
make web                       # http://localhost:3000  (landing) and /app (operator flow)

The dashboard reads the live contracts: the fleet table, the settlement ledger (PAY green / SLASH red, each deep-linked to scan.bohr.life), per-device detail, the on-chain SLA, treasury balances, and the agent's reputation snapshot. No mock data anywhere on the app path.

Connect a wallet on chainId 968 and you can deploy your own node in /app/deploy, then click Go live to stream it straight from the browser (gasless, no local process). It appears under Operators and is settled automatically. /app/operators groups every device by operator wallet with per-operator earnings, slashes, and reputation.

What you'll see (and why devices may read "idle")

The dashboard is always live against chain state, so it is never blank: the settlement ledger, the full settled history, dev-001/003's paid history, and dev-002's slash are permanent on-chain facts and render immediately, each deep-linked to scan.bohr.life. (The ledger is cumulative and grows with every demo window, so read current totals from the live app, not a fixed number here.)

BOT Chain has a gas floor, so gasless anchoring and per-epoch settlement cost real tBOT. We therefore do not run the streaming fleet 24/7; it runs in short funded windows. When it is not in a window, devices honestly read "idle, not streaming" or "awaiting telemetry", and recent intervals read "idle, no telemetry". That is truthful live state, not mock data and not a bug: a device that is not currently delivering is shown as such (and would be slashed for it).

To see it fully live (devices streaming, new PAY/SLASH rows appearing on camera):

  • Fastest, one device: deploy a node in /app/deploy and click Go live to stream it from your browser. Needs the hosted relayer funded (below).
  • Full fleet: fund the relayer and agent keys from the faucet, then start the hosted services (see Host it). A ~10 tBOT budget covers roughly 25 to 45 minutes of live operation; stop the services when done. Every settlement is a real on-chain tx.

Deploy and stream your own node (2 minutes, no install)

This is the seamless product flow: you become an operator and watch your own device get paid, entirely from the browser. It uses two tabs on purpose (explained below).

  1. Connect a wallet on chainId 968 with a little tBOT for gas (faucet above), on the live app or your local one.
  2. Mint + approve. In /app/treasury, click Mint 1,000 mUSD, then Approve vault (a one-time allowance, no visible change is expected).
  3. Deploy in /app/deploy: give it a label, keep minAnchors 3, click 1 Register device, then 2 Bind policy. A device signing key is generated in this tab and never leaves it.
  4. Go live (button appears after step 3). The tab now signs a reading every ~10s and the sponsor relayer anchors it on-chain, gaslessly. You will see anchored ✓ tx ticks within ~10 seconds. Keep this tab open: it is the device; closing it stops the stream and the next interval slashes.
  5. Fund escrow, in a second tab. Your node streams and settles immediately, but each PAY is $0 until its pay-escrow is funded. Open /app/treasury in a new tab (leave the streaming tab running), find your node under Your devices, and Deposit escrow (e.g. 500). Its next PAY is now real mUSD.

Why two tabs? The in-browser device key lives only in the deploy tab's memory. Navigating that tab away (to Treasury, or via a redirect) regenerates the key, i.e. a different device that is no longer the one streaming. So you fund escrow in a separate tab and let the first keep streaming. All in-app links from the Go-live panel open in new tabs for exactly this reason.

Within one or two intervals your node shows online on /app, appears under your wallet on /app/operators, and earns real mUSD, all with no local process. The autonomous agent settles it like any other device; on-chain policy decides.

B. Deploy your own stack and run the full loop

cp .env.example .env           # then set TESTNET_PRIVATE_KEY to a faucet-funded testnet key
                               # faucet: https://faucet.botchain.ai/basic

# 1. Deploy the settlement stack (prints the 5 addresses + deploy block)
cd contracts && forge script script/DeploySettlement.s.sol:DeploySettlement \
  --rpc-url bot_testnet --broadcast --legacy --with-gas-price 50000000000 \
  --private-key $TESTNET_PRIVATE_KEY

# 2. Register a device fleet (operator key), then bond + fund escrow + set each SLA
#    (MockUSD.mint is open; setSLA takes an SLA active from a future epoch).
cd ../agent && TESTNET_PRIVATE_KEY=$OPERATOR_KEY go run ./cmd/devicesim -register -n 3 -registry $REGISTRY

# 3. Run the three processes; point web at your addresses via NEXT_PUBLIC_* in web/.env.local
TESTNET_PRIVATE_KEY=$RELAYER go run ./cmd/paymaster -addr :8789 -anchor $ANCHOR      # sponsor (devices pay 0 gas)
go run ./cmd/devicesim -anchor $ANCHOR -relayer http://localhost:8789 \
  -interval 2s -drop dev-002 -drop-after 240s                                        # gasless fleet; drop one to force a SLASH
AGENT_PRIVATE_KEY=$AGENT go run ./cmd/settler -registry $REGISTRY -anchor $ANCHOR \
  -service $SERVICE -vault $VAULT -from-block $DEPLOY_BLOCK -tick 15s -rep-snapshot reputation.json

The agent logs, per epoch, its off-chain predict and then the on-chain settled result: the two always match, because the contract is the authority. A live device is paid; the dropped device, whose epochs anchor below the SLA threshold, is slashed and its bond flows to the treasury.

Host it (self-driving, browser streaming)

To keep the network live and let browser-deployed nodes stream, host the three Go services with the provided agent/Dockerfile + agent/railway.json. It is one image, the role selected by PG_SERVICE=relayer|settler|fleet:

  • relayer (paymaster) - public HTTPS, sponsors gas; needs TESTNET_PRIVATE_KEY, ANCHOR_ADDR. Point the app at it with NEXT_PUBLIC_RELAYER_URL (Vercel env or web/.env.local).
  • settler - needs AGENT_PRIVATE_KEY + the contract addresses; auto-discovers every on-chain device. Serves its reputation at /reputation (set REPUTATION_URL on the app to surface it and the advisory AI). Optional DEEPSEEK_KEY enables the narratives; BACKFILL=N stops a freshly started agent from re-settling a long idle gap.
  • fleet (devicesim) - streams the canonical devices; needs the device keys (FLEET_JSON).

Economics (why funded windows, not 24/7). BOT Chain has a ~50 gwei gas floor, so each gasless blob anchor (~0.04 tBOT) and each settlement (~0.03 tBOT) costs real tBOT. Run the fleet and settler in short funded windows: fund the relayer and agent keys, railway up the services, record or judge, then railway down. A ~10 tBOT budget covers roughly 25 to 45 minutes of live operation. Browser Go live streams a single device and needs only a funded relayer, so it is much cheaper. When nothing is streaming, the app shows honest idle state; the settled ledger stays on-chain permanently.

Deployed demo instance (BOT Chain testnet)

Contract Address
DeviceRegistry 0x8e55fac4f0bdc53662ef6f55cd38e897d6071ed0
TelemetryAnchor 0x2cc5946299f11be57f43933e780f6f39de490bcf
ServiceContract 0x30cc2a56538dd04d4c4c1900f555c4b47aa0f95a
SettlementVault 0x252cf0165dca8d04aae9da184b3836c12144cd40
MockUSD (mUSD, 6dp) 0x975e7990fae4e71f0b40d4a6b990e872d3046607

Deploy block 15371632, 60s settlement epochs (tuned for live-testnet relayer throughput). Look up any address or tx on the explorer below.

Network

  • Testnet (build target): chainId 968, RPC https://rpc.bohr.life, explorer https://scan.bohr.life
  • Faucet: https://faucet.botchain.ai/basic (manual, Turnstile-gated)
  • Note the domain split: testnet infra is on *.bohr.life; product and mainnet links use *.botchain.ai.

About

Real-time DePIN settlement on BOT Chain: devices sign telemetry and anchor it on-chain gaslessly, and an autonomous agent pays or slashes each operator per interval in stablecoin, with on-chain policy as the sole authority.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors