Search projects, hackathons, sponsors and tech

    ← All projects

    Speakeasy

    Non-custodial 1inch Aqua trading for agents while Ledger holds the keys

    Demo

    About

    Speakeasy is a non-custodial trading backend for AI agents on 1inch Aqua / SwapVM. An agent talks to a local MCP stdio bridge (request_trade, post_trade, and related tools). That bridge handles OAuth and Ledger FIDO2 login, then asks our Bun HTTP API for an immutable five-minute trade preview. The API never receives a private key and never signs with the user’s wallet. Agent, facilitator, keeper, and PASETO material live in a Ledger Key Ring (wallet-cli ring). A secret-broker process decrypts over a Unix socket only when something must be signed. Humans keep hardware custody; the chain stays the source of truth. Settlement is official Aqua plus SwapVM, not a custom AMM. Limit flow uses a pinned five-instruction SwapVM program on LimitSwapVMRouter. Funding uses x402 v2 exact Permit2 on the deployment chain (any standard ERC-20 sell token). Canonical Permit2 and the x402 exact proxy are the usual mainnet addresses. Conditional orders (stops, trailing, OCO, brackets) go through our Foundry contracts: AquaIntentController, vault factory, and BoundedMatcher, which may call at most eight allowlisted target/selector pairs. Off-chain, Postgres plus workers rebuild the book from confirmed Aqua and SwapVM events and poll ERC-20 transfers (no websocket). Keepers can only hit manifest-allowlisted functions. Local demo is Anvil 31337 with fixture aUSD/aETH. Live explorer demo is Ethereum Sepolia (11155111). Physical Ledger (Sync, Ethereum blind signing, Security Key) is the real path; Speculos is for protocol tests only and is not a Secure Element claim. The API is a strict language recognizer: unknown JSON keys and non-canonical amounts are rejected. OpenAPI lives at /docs. Cubane is the first-party EVM stack (no first-party viem/ethers/1inch SDK). Bazantic catalog discovery exists; a public paid Agentify gateway is out of scope until we have HTTPS OpenAPI. Hosted Vercel can serve read/health routes; hardware-bound trades stay on the local MCP bridge.

    How it's made

    We built Speakeasy as one Nix flake so the toolchain is locked: Bun, Aube, Foundry, Postgres, Process Compose, and (on Linux) Speculos plus pinned Ledger Sync / Ethereum / Security Key ELFs. There is no first-party viem, ethers, or 1inch SDK. Cubane + Noble do RPC, ABI, EIP-712, and txs. Zod 4 owns every HTTP body; OpenAPI 3.1 and Swagger are generated from the same routes. Errors are RFC 9457. Amounts are canonical decimal strings turned into bigint with maker-favouring rounding. Custody is the hard split. wallet-cli ring encrypts agent, facilitator, keeper, and PASETO keys (LKRP). apps/secret-broker only decrypts over a Unix socket. The HTTP API never sees plaintext. Physical mode is node-hid, Device Management Kit, and on-device confirmations (quit Ledger Live). Emulated mode is Speculos + AQUA_E2E=1 and a wallet-cli adapter. Those keyrings are not interchangeable: a coworker with a real Nano cannot decrypt Speculos ciphertext, and Sepolia AquaIntentController.operator is immutable, so a new device means a new deploy. The agent path is MCP stdio (apps/mcp-bridge): OAuth 2.1 + PKCE, Ledger FIDO2 (Security Key / CTAP), then request_trade → five-minute preview hash → post_trade. First POST /v1/trades returns x402 v2 PAYMENT-REQUIRED; retry is exact Permit2 on the deployment chain. The local facilitator settles Anvil/Sepolia. Quotes are SwapVM eth_call against pinned 1inch Aqua + LimitSwapVMRouter / AquaSwapVMRouter. Workers poll logs and ERC-20 transfers into Postgres (no websocket). The keeper may only hit manifest-allowlisted selectors on the intent controller, vault factory, and BoundedMatcher (max eight hops). Partner tech: Ledger is the actual KMS and the login authenticator (amr: ["fido2","hwk"] on PASETO v4.public). 1inch Aqua/SwapVM is the matching and limit bytecode, not a wrapper AMM. Uniswap Permit2 and x402 exact (0x402085c2…) are the payment rail. Optional 1inch spot prices are a keyed add-on and are not required to quote. Hacky / notable: Windows had to clone onto WSL ext4 because Anvil Unix sockets and chmod die on /mnt/e. Nix needed filter-syscalls = false. We patched Linux LD_LIBRARY_PATH so node-usb could load libudev/libstdc++ in e2e. Pocket’s Sepolia RPC answered eth_getCode but often returned “method not found” for Foundry EIP-1559 and even eth_sendRawTransaction depending on User-Agent; we signed with cast mktx and broadcast through a second RPC, and skipped genesis-hash checks on pruned nodes. Compose on Mac maps Speculos to host 15000 so it does not steal port 5000. dev/start refuse to serve until the runtime manifest’s code hashes, Aqua bindings, and matcher allowlists verify. Incomplete .data/keyring is never overwritten. Arbitrary Aqua programs are rejected on purpose because SwapVM instruction order is load-bearing.