Skip to main content

Architecture

Dispatch has two deployment paths: a managed gateway (centralised routing, good for apps) and a direct consumer SDK (trustless, peer-to-peer).
Consumer (dApp)

   ├── via consumer-sdk (trustless, direct)
   │     signs receipts locally, discovers providers via subgraph

   └── via dispatch-gateway (managed)
         QoS-scored selection, TAP receipt signing

   │  POST /rpc/{chain_id}
   │  TAP-Receipt: { signed EIP-712 receipt }

dispatch-service          ← JSON-RPC proxy, TAP receipt validation,
   │                         receipt persistence

Ethereum client           ← Geth / Erigon / Reth / Nethermind
(full or archive)

Payment flow

Receipts accumulate off-chain and settle on-chain in batches via GraphTally (TAP v2):
receipts (per request)
  → dispatch-service aggregates into RAV (every 60s)
  → RPCDataService.collect() (every hour)
  → GraphTallyCollector
  → PaymentsEscrow
  → GraphPayments
  → GRT to indexer (via paymentsDestination)
valueAggregate in a RAV is cumulative and never resets. The collector tracks previously collected amounts to calculate deltas on each collect() call.

Workspace layout

crates/
├── dispatch-tap/      EIP-712 types, receipt signing (shared by service + gateway)
├── dispatch-service/  Indexer-side JSON-RPC proxy with TAP middleware
├── dispatch-gateway/  Gateway: QoS scoring, provider selection, receipt issuance
└── dispatch-smoke/    End-to-end smoke test against a live provider

contracts/
├── src/RPCDataService.sol   IDataService implementation (Horizon)
└── src/interfaces/

consumer-sdk/   TypeScript SDK — direct provider access without a gateway
indexer-agent/  TypeScript agent — automates provider lifecycle on-chain
subgraph/       The Graph subgraph — indexes RPCDataService events
docker/         Docker Compose full-stack deployment
demo/           Self-contained local demo: full payment loop on Anvil

Horizon integration

Dispatch is a data service in the Horizon framework. Three Horizon layers are in play: HorizonStaking — indexers call provision(serviceProvider, RPCDataService, tokens, maxVerifierCut, thawingPeriod). Minimum 10,000 GRT, 14-day thawing period. GraphPayments + PaymentsEscrow — consumers deposit GRT into escrow keyed by (sender, serviceProvider). Every request carries a TAP receipt; the TAP agent batches these into RAVs redeemed via collect(). DataService frameworkRPCDataService inherits DataService + DataServiceFees + DataServicePausable. The framework handles stake claim linked lists, fee locking at the configured ratio, and pause logic.