
Nametoll
Agents pay a desk they found by name. TEE gates spend. Hedera bills on HCS.
Demo
About
If an agent needs live lending data today, somebody hands it a URL, an API key, and a monthly bill. There is no name you can pass to another agent. The spend limit sits in a config the buyer can read. And when the payment goes through, there is no receipt a stranger can check. Nametoll is a desk for that job. You find it by a name. A spend rule the desk itself cannot see decides whether the buyer may pay. If they may, they pay only for what came back, in HBAR, and the bill is written where anyone can recompute it. The public origin is https://nametoll.run.place. You paste a parent such as nametoll.eth on /desks, or a child such as desk.nametoll.eth on /app. The happy path does not ship a name. The name resolves to an HTTP origin, who to pay, what it costs, and where the receipt will be written. Two protocols cost two hundred thousand tinybars against a secret cap of one hundred fifty thousand, so the desk refuses and Pay stays locked. One protocol is one hundred thousand, which is allowed. Unpaid traffic is still HTTP 402. After settle you get live rows, and the same numbers show up on HashScan and on HCS topic 0.0.10464309. What you buy is two things on the same meter. A snapshot is priced by how many protocols you asked for: Aave v3 and Compound III, one Messari-shaped query, fail-soft if an indexer is down. A risk score is one unit. You pass a wallet; the desk computes a health factor, distance to liquidation, and the worst market from those same markets. If the indexer has positions it uses them. If not, it builds a deterministic book from live TVL ratios. The wallet never goes into the spend check. Positions on a public chain are not private, and we do not sell them as if they were. The Graph is the data you pay for. We used it. We did not apply for its prize. The name lives on ENS, version two, on Sepolia. nametoll.eth is the parent. desk.nametoll.eth and agent-02.nametoll.eth are children under that UserRegistry, each with its own Permissioned Resolver. Three documented text keys (url, agent-context, agent-endpoint[web]) carry the origin, the Hedera pay-to, the price rule, the HCS topic, and HBAR asset 0.0.0. The operator can edit those keys and cannot transfer the name. /register issues a new child that resells this desk: the label and endpoint vary, price and pay-to stay this origin. Optional expiresIn writes a bounded expiry. gone.nametoll.eth was registered for ninety seconds; on-chain state is now AVAILABLE and /desks marks it unresolved. npm run agent -- nametoll.eth discovers a live child and pays it. The spend rule is a Chainlink confidential workflow, handlerInTee from their official scaffold. Before Blocky402 settles, the desk asks nametoll-brain. getSecret loads SPEND_CAP and, if set, BUYER_ALLOWLIST and RATE_LIMIT inside the enclave. The public reasons are under cap, over cap, buyer not allowlisted, or rate limited. Deny, or a skipped TEE, is HTTP 403: no settle, no snapshot, no bill. Four cre workflow simulate logs in the repo show AWS Nitro in us-west-2 for allow, over-cap deny, allowlist deny, and rate deny. The same handler can emit unsigned join() calldata for the official ChallengeLending contract on Sepolia; that join is already on-chain. Functions and Automation are not used. CRE deploy is still enrollment-only, so the public desk uses attested simulate, caches a good verdict per amount, payer, and hour-count, re-warms the two pinned amounts so a cold click does not sit for nine seconds, and kills a hung simulate at sixty seconds. Missing simulate fails closed. Payment is Hedera. Unpaid GET /desk/snapshot and GET /desk/risk are HTTP 402, x402 v2, exact, tinybars, asset 0.0.0, fee-payer 0.0.7162784 read live from Blocky402 GET /supported. We do not hold a facilitator key. An operator buyer or a guest session (POST /desk/session creates a Hedera ECDSA account and faucets 0.05 HBAR; the key never appears in JSON) completes a real paid request. If an indexer is down we charge only what arrived and refund unused prepaid on a seller TransferTransaction. Those prepaid, owed, and refund amounts sit on the same HCS topic. A stranger GETs the Mirror Node, decodes each message, and checks units times price. TOLL (0.0.10483302) is an HTS token with a custom HBAR fee, and two wait_for_expiry slots have executed and been claimed. Snapshot 402 stays HBAR because Blocky402 does not advertise an HTS asset. The guest faucet closes with HTTP 503 if the seller is under 5 HBAR or sixteen guests are already live. /health shows that runway. Live evidence: TEE-gated settle https://hashscan.io/testnet/tx/0.0.7162784@1789111350.366520040. Remainder refund https://hashscan.io/testnet/tx/0.0.10463755@1789114039.622724528. HCS topic https://hashscan.io/testnet/topic/0.0.10464309. Parent register https://sepolia.etherscan.io/tx/0x28ab9c164cca6f967413f944a3ef1f81ca3ef86f7e1620fdc5b7a57d8d7a8a96. Sibling https://sepolia.etherscan.io/tx/0xd1f6f4faa9f11636fb64673ddfe6d458285e6cbf6ea79631c0d017c528c10454. Expired child https://sepolia.etherscan.io/tx/0x44bbbd33adc88b3fb103eec45e2941ee4ad9eb14d8a0f446f738c7c2ac20d3ac. ChallengeLending join() https://sepolia.etherscan.io/tx/0x980aaffe6d62561964a42675f7831adbca09cf442c7db0cede9255e2ed5e3086. Repo https://github.com/shreyas-sovani/Nametoll
How it's made
Nametoll is one Node and TypeScript Express app, not a collage of demos. Six modules share stable interfaces: Directory (resolve a pasted name, list children, register a constrained child, guest session), Gate (402, Blocky402 verify and settle, refuse a TEE deny), Brain (CRE handlerInTee verdict), Merchandise (live Graph snapshot, desk-side risk score, billable units), Ledger (HCS bill, optional HTS and schedules), Buyer (resolve, ask TEE, pay, print HashScan and topic). Tests assert those observables. CI is .github/workflows/test.yml. The UI is /, /desks, /register, /app, and /docs. Official partner skills, MCP ids, and llms.txt were the only APIs; if a symbol was not in a skill or the live docs it was not invented. Directory is ENSv2 on Sepolia, not mainnet v1. Writes use the official ens-cli ABIs and addresses; ens-cli emits unsigned {to, data, value} and npm run ens:sepolia broadcasts. The owner Permissioned Resolver was deployed before register so the name never sat on a zero resolver. EAC authorizeTextRoles is scoped to the three desk text keys. Catalog prefers the hosted Omnigraph at api.v2-sepolia.ensnode.io. That host currently serves a Railway certificate Node refuses, so resolve falls through to the official Sepolia Universal Resolver (0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe) and listChildNames walks getSubregistry plus LabelRegistered logs on the parent UserRegistry. That fallback is why /desks still lists children when the indexer TLS dies. /register calls the same issueDeskChild path; expiresIn becomes register(..., expires). After expiry, getState is AVAILABLE. Gate never holds a Blocky402 facilitator key. It reads the fee-payer from live GET https://api.testnet.blocky402.com/supported, returns x402 v2 PAYMENT-REQUIRED, then verify plus settle. payTo is a Hedera account id (0.0.10463755), not an EVM address. Amounts are tinybars. @hiero-ledger signs AccountCreate (guest buyer), TransferTransaction (0.05 HBAR faucet and unused-remainder refund), HCS submit, HTS token create, and ScheduleCreate wait_for_expiry. Guest keys stay in process memory; JSON never includes them. POST /desk/pay is rate-limited with /desk/session and /desk/register, optionally gated by DESK_PAY_SECRET, and pinned to PUBLIC_DESK_URL when that is set. Before a guest is funded, the desk reads the seller balance from Mirror Node. Below 5 HBAR, or at 16 live guests, POST /desk/session returns 503 and tells the judge to use operator pay. /health.runway exposes that floor so a human can check before recording. Brain lives in cre/nametoll-brain, scaffolded with cre init -t hello-confidential-workflows-ts. The HTTP trigger runs inside TeeRuntime. Secrets come from runtime.getSecret. HTTP inside the TEE uses HTTPClient only; ConfidentialHTTPClient is not mixed into a TEE handler (that mix is a documented DQ). Live CRE deploy is private beta, so the public desk runs cre workflow simulate against staging-settings and caches a successful verdict per amount plus payer plus hour-count. Failures and timeouts are not cached. Boot warms the 1-unit and 2-unit amounts. A keep-warm interval re-decides those two amounts every half TTL (VERDICT_TTL_MS, default 60s; set 1800000 for judging day) so the cache does not expire while the process lives. cre workflow simulate is mutexed — one child at a time — and killed at 60 seconds so a hung CLI fails closed instead of hanging the desk. Policy evidence is four redacted Nitro us-west-2 logs: simulate-allow.log, simulate-deny.log, simulate-allowlist-deny.log, simulate-rate-deny.log. The same handler accepts { action: join } and returns unsigned join() to official ChallengeLending 0x88574e7Cc0027afd04951daa09B64d4441931ba1 (the live challenge contract; the ETHOnline scrape address is a dead older deploy). npm run join broadcasts that calldata. Selector 0xb688a363; isUser is true. Merchandise is one Messari-shaped lending query across two pinned Studio deployments (Aave v3 Ethereum JCNWRypm7FYwV8fx5HhzZPSFaMxgkPuw4TnR3Gpi81zk and Compound III AwoxEZbiWLvv6e3QdvdMZw4WDURdGbvPfHmZRc8Dpfz9). Schemas were fetched through The Graph Subgraph MCP, not invented. Units billed equal delivered protocols. Fail-soft returns the live rows and lets Ledger refund the rest. The risk SKU reuses those markets: if Account positions exist, score them; if not, build a deterministic book from TVL weights and score that. The wallet never touches Brain, so scoring a second address does not spawn another simulate. Graph stays off the form. Ledger appends JSON to HCS topic 0.0.10464309. Recompute is units times priceTinybarsPerUnit (100000). Remainder fields (prepaidTinybars, refundTinybars, refundTx) follow the Pinout metering shape on one topic, not dual-topic HIP-991. Risk bills carry sku: risk-score. Subscribe and claim are a side rail: TOLL 0.0.10483302 (custom 100000-tinybar HBAR fee) plus two executed wait_for_expiry slots that delivered live Aave and wrote subscribe bills. Snapshot 402 stays asset 0.0.0 because Blocky402 /supported lists Hedera exact with no HTS asset list. Notable and slightly hacky, on purpose. Hosted ENSNode TLS forced the Universal Resolver plus LabelRegistered catalog fallback so discovery did not depend on a broken cert. Unused remainder is a seller CryptoTransfer, not a second 402 scheme, because Blocky402 testnet is exact-only. The public-desk TEE is attested simulate, not a mainnet DON deploy (Confidential Workflows deploy is still enrollment-gated); missing simulate fails closed with HTTP 403. We opened hedera-dev/hedera-harness pull request 59 after in-place init adopt planted Yarn and Next into this npm Express app; Nametoll has no .harness folder. We did not build ERC-8004, HCS-14, A2A, World Selfie Check, or a Graph prize SKILL. Those would have been stickers. The product is the loop a judge can paste, pay, and recompute.