Skip to content
Back to Home
Syntax Studios Visit ↗

Splat

SvelteKit Elysia (Bun) Rust + Yellowstone gRPC Anchor / Solana Hyperliquid EIP-712 Turnkey sub-orgs PostgreSQL + Diesel Redis (ioredis, Lua) Socket.io

Splat is a Hyperliquid + Solana trading terminal with a $SPLAT staking program that feeds back into trading fees and on-chain rewards. It's live at app.asksplat.com. I built it as five separable services so a hot path on one (orderbook fan-out, indexer ingestion) never starves the others.

The Solana indexer is a Rust service built on the Carbon framework with the yellowstone-grpc client. It subscribes to confirmed transactions filtered to the Jupiter v6 swap program, decodes swaps with Carbon's Jupiter decoder, and walks inner CPI events to capture the full route. Multi-hop routes get folded into a single trade row by summing across the path, so a four-hop swap shows as one logical trade. USD pricing comes from a Jupiter price endpoint cross-referenced with on-chain mint decimals. Limit orders take a different path: events go into an in-memory map and a tokio interval drains them to Postgres via Diesel + r2d2, with a tracked-wallets set hot-loaded at boot deciding which signatures persist. Reorg recovery rides on Yellowstone's confirmed commitment plus a slot-checkpoint table.

The trading backend is Elysia on Bun. Hyperliquid orders are signed as EIP-712 typed data under a fixed Exchange domain, while user-signed actions like withdrawals or USD class transfers sign on Arbitrum mainnet. Every perp order embeds a builder hook so platform fees route through Hyperliquid's native builder-codes flow rather than a wrapped fee contract. Wallets are non-custodial via Turnkey sub-orgs: the SvelteKit client uses an IndexedDB session and OAuth login, and server-built Solana txs sign through a Turnkey signer with consensus-needed handling so policy-gated approvals don't crash the flow.

The on-chain $SPLAT staking program is Anchor. PDAs are scoped per-user, and rewards use a reward-per-token accumulator in fixed-point math:

pending = (stake.amount * rewardPerToken) - stake.rewardDebt

Claims and stakes update both the per-user debt and the global accumulator. The interesting bit is the off-chain auto-compounder: when a position's pending rewards clear a USD floor, the service pulls a Jupiter quote for SOL -> SPLAT, deserializes the swap into account metas, and CPIs into the program's compound instruction as a v0 transaction with looked-up address tables. Users keep growing their stake without manual claims.

The market server is Express + Socket.io + ioredis, with Pyth, Binance, and Hyperliquid websocket clients feeding it. Candles are kept in Redis as per-token rolling OHLCV, with a Lua script atomically rolling closed buckets and trimming to a bounded ring. PubSub batches events per setImmediate tick to keep the event loop responsive, then re-emits to per-room subscribers over Socket.io. The SvelteKit terminal hooks a custom TradingView UDF datafeed into that socket so the chart streams the same candles the backend writes.

Demo 1

Demo 2

Demo 3

Demo 4

Demo 5

Demo 6