Skip to content

Jayy4rl/SatoshiPilot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SatoshiPilot

SatoshiPilot is an AI-powered DeFi copilot for the Stacks blockchain. It aggregates live yield data from eight Bitcoin DeFi protocols, exposes a conversational interface where users instruct the AI in natural language, and executes multi-step on-chain strategies — swapping tokens, comparing vaults, and staging signed transactions — through a structured Plan/Execute protocol backed by a Groq LLM with live protocol data injected into every inference call.


Table of Contents


Overview

SatoshiPilot is built around the idea that interacting with Bitcoin DeFi on Stacks should not require a user to understand individual protocol mechanics, contract addresses, or transaction construction. The interface is a chat window backed by a Groq LLM. The user states an intent — yield optimisation, a token swap, a protocol comparison, a portfolio summary — and the AI determines the sequence of operations required, fetches the relevant live data, and guides execution.

The backend injects the full live dataset from all eight integrated protocols into the LLM system prompt on every request. This means APY figures, TVL, lock-up periods, and pool identifiers the AI references are always current, not approximated from training data.

For strategies that require more than a single on-chain action, the AI enters a Plan/Execute flow. It presents a numbered checklist of steps, waits for explicit user confirmation, then executes exactly one step per response with a visible progress tracker. Steps that require a wallet signature — a swap, a deposit, a withdrawal — trigger a pre-filled transaction modal in the browser. The user reviews the parameters and signs in their own wallet. The AI is notified of the outcome via a structured callback and either advances to the next step or handles the failure explicitly.

For direct single-action requests the planning phase is skipped entirely and the modal is staged immediately.

The frontend is a React/TypeScript SPA. The backend is a Node.js ESM API server that owns all SDK credentials, LLM calls, and on-chain reads. No private keys, Groq API keys, or Bitflow SDK calls exist in the client bundle.


Features

AI Copilot with Structured LLM Responses The AI layer uses Groq's llama-3.1-8b-instant model. Every LLM response is enforced as a structured JSON object containing a phase, an ordered plan array, a current_step_index, an action field for modal triggers, params for that action, and a pool_cards array for visual comparison rendering. The model is never permitted to return free-form text — the backend parser extracts the JSON from the raw completion and rejects malformed output gracefully.

Plan/Execute Protocol Complex multi-step strategies (e.g. compare pools across protocols, route a swap, then deposit the output) are handled through a two-phase flow. In the plan phase the AI presents a numbered checklist and sets awaiting_confirmation: true. On confirmation it enters the execute phase, advancing current_step_index by one per response and setting action + params when a step requires a wallet interaction. A StepperBar component in the UI reflects the current state. Simple single-step requests bypass planning entirely and go directly to phase: execute.

Live Protocol Data Injection APY, TVL, lock-up periods, yield assets, and pool identifiers are fetched concurrently from all eight protocol integrations on each /api/protocols request and cached server-side for five minutes. This cache is shared with the AI route, so every LLM inference call receives an up-to-date pool summary injected into the system prompt. The AI is explicitly instructed never to use training-data yield figures.

Bitflow DEX Integration Token swap routing is handled entirely server-side using the @bitflowlabs/core-sdk. The API exposes token discovery, route enumeration, parallel best-route quoting, and contract-call parameter generation as discrete endpoints. The frontend receives ready-to-sign openContractCall parameters and never instantiates the SDK or holds swap routing state.

Modal-Based Transaction Staging Deposits, withdrawals, and swaps are executed through pre-filled modals mounted at the app root. The AI stages a modal by returning an action and params in its response; the frontend handleToolCall bridge maps this to the appropriate Zustand store action which opens the modal. After the user signs or cancels in their Stacks wallet, an outcome callback fires and the result is sent back to the AI as a structured event message to continue or branch the conversation.

Multi-Protocol Vault Browser The Vaults page renders all protocol pools with live APY, TVL, category, lock-up period, and a direct deposit entry point. Pools are filterable by category, asset, and protocol. Any vault can be deposited into independently of the AI flow.

Portfolio Balances STX, locked STX, sBTC, xBTC, and stSTX balances are fetched from the Hiro API via the backend proxy and displayed in real time, refreshing automatically every 30 seconds after wallet connection.

Protocol Comparison Cards When the AI determines a pool comparison is warranted, it populates the pool_cards field in its response with structured pool objects. The frontend renders these as side-by-side cards showing protocol, product, APY, TVL, lock-up period, and a risk classification badge derived from the pool category, with a direct selection action that feeds back into the conversation.


Architecture

Browser (React + TypeScript)
        |
        |  REST (JSON)
        v
Express API Server (Node.js ESM)
        |
        |-- /api/protocols   -- aggregates 8 protocol fetchers concurrently
        |-- /api/balances    -- proxies Hiro blockchain API
        |-- /api/swap/*      -- wraps Bitflow SDK (tokens, routes, quote, params)
        |-- /api/ai/chat     -- Groq LLM inference with live pool data injected
        |
        |-- Groq (llama-3.1-8b-instant)
        |-- Hiro API (balances, contract reads)
        |-- Bitflow SDK (swap routing)
        |-- Protocol APIs / On-chain reads (StackingDAO, ALEX, Zest, ...)

The frontend and backend are completely independent deployments. The frontend is a static Vite build that communicates with the backend exclusively through the REST API. No private keys, API keys, or SDK credentials exist in the frontend bundle.


Project Structure

SatoshiPilot/
|-- package.json              Root scripts (dev:backend, dev:frontend, build)
|-- render.yaml               Render deployment config for both services
|
|-- backend/
|   |-- package.json
|   |-- src/
|       |-- server.js         Express app, CORS, health endpoint
|       |-- routes/
|       |   |-- ai.js         POST /api/ai/chat — Groq inference
|       |   |-- balances.js   GET  /api/balances/:address
|       |   |-- protocols.js  GET  /api/protocols
|       |   |-- swap.js       GET/POST /api/swap/*
|       |-- services/
|       |   |-- protocols/
|       |       |-- index.js        Concurrent aggregator
|       |       |-- alex.js
|       |       |-- arkadiko.js
|       |       |-- bitflow.js
|       |       |-- cycle.js
|       |       |-- granite.js
|       |       |-- hermetica.js
|       |       |-- stackingdao.js
|       |       |-- velar.js
|       |       |-- zest.js
|       |-- lib/
|       |   |-- bitflow/
|       |       |-- client.js       Singleton Bitflow SDK instance
|       |       |-- parallelQuote.js Parallel route quoting
|       |-- utils/
|           |-- cache.js            In-process TTL cache
|           |-- contractRead.js     Hiro API helper
|
|-- frontend/
    |-- index.html
    |-- vite.config.ts
    |-- src/
        |-- App.tsx               Root shell, routing, modal mounts
        |-- main.tsx
        |-- pages/
        |   |-- AIChatPage.tsx    Full-page AI chat with Plan/Execute UI
        |   |-- VaultsPage.tsx    Protocol vault browser with filters
        |   |-- SwapPage.tsx      Token swap interface
        |-- components/
        |   |-- layout/           Header, navigation
        |   |-- modals/           DepositModal, SwapModal
        |   |-- swap/             TokenPicker, token utilities
        |   |-- vaults/           VaultCard, VaultFilters
        |   |-- wallet/           WalletConnectButton, BalanceCard, WalletInfo
        |   |-- ai/               ChatPanel (floating)
        |-- store/
        |   |-- chatStore.ts      Zustand — conversation history, plan state
        |   |-- poolStore.ts      Zustand — deposit modal state + callbacks
        |   |-- swapStore.ts      Zustand — swap modal state + callbacks
        |-- contexts/
        |   |-- WalletContext.tsx  Stacks wallet connection, balance refresh
        |-- lib/
        |   |-- ai/handleToolCall.ts   AI tool -> modal bridge
        |   |-- bitflow/executeSwap.ts Swap transaction builder
        |   |-- stacks/deposit.ts      Deposit transaction builder
        |-- services/
        |   |-- hiroApi.ts        Hiro balance fetching
        |   |-- protocolsApi.ts   Frontend protocols API wrapper
        |-- types/
            |-- pools.ts
            |-- protocol.ts
            |-- wallet.ts

Integrated Protocols

Protocol Category Asset Data Source
StackingDAO Liquid stacking STX On-chain contract
Bitflow DEX liquidity pool STX/stSTX On-chain contract
ALEX AMM DEX STX/sBTC ALEX REST API
Hermetica Synthetic yield sBTC Hermetica REST API
Velar DEX liquidity pool STX Velar REST API
Zest Lending/borrowing sBTC On-chain contract
Arkadiko Lending/stablecoin STX/DIKO On-chain contract
Granite Lending sBTC On-chain contract

Each protocol fetcher is isolated and fault-tolerant. If one fetcher throws, the aggregator returns an error entry for that protocol and continues serving the others.


AI Assistant

The assistant runs on Groq's llama-3.1-8b-instant model. Every response is a structured JSON object — never plain text — with the following fields:

{
  "message": "Plain English shown to the user.",
  "phase": "plan | execute | complete | error",
  "plan": ["Step label 1", "Step label 2"],
  "current_step_index": 0,
  "action": "stage_swap | stage_deposit | stage_withdraw | null",
  "params": {},
  "awaiting_confirmation": true,
  "pool_cards": []
}

Phase behaviour:

  • plan — used only for tasks spanning three or more distinct operations across multiple modals or protocols. The user sees a checklist and Confirm/Cancel buttons before anything executes.
  • execute — one step per reply. A StepperBar above the messages tracks progress. Steps that require wallet interaction set action and params to open the appropriate modal.
  • complete — single-step answers and direct actions. No plan card is shown.
  • error — failure with a clear human-readable description.

Action tools (open modals):

  • stage_deposit — opens the deposit modal for a given pool_id and optional amount
  • stage_swap — opens the swap modal with from_token, to_token, optional amount
  • stage_withdraw — opens the withdrawal modal for a given pool_id

Read-only tools (resolved inline by the AI):

  • get_best_pool — finds the highest-APY pool for a given asset
  • compare_pools — compares a list of pools and populates pool_cards for the UI
  • explain_pool — describes a pool's mechanics
  • get_portfolio_summary — summarises the connected wallet's positions

The backend injects the full live pool dataset into the system prompt on every request, so the AI never falls back on stale training data for APY or TVL figures.


Getting Started

Prerequisites

Environment Variables

backend/.env

GROQ_API_KEY=your_groq_api_key
FRONTEND_URL=http://localhost:5173
HIRO_API_KEY=your_hiro_api_key        # optional
PORT=3001                              # optional, defaults to 3001
PROTOCOLS_CACHE_TTL_MS=300000          # optional, defaults to 5 minutes

frontend/.env

VITE_API_BASE_URL=http://localhost:3001

Leave VITE_API_BASE_URL unset or empty to use a relative URL (useful when frontend and backend are served from the same origin).

Running Locally

Install dependencies and start both services from the root:

# Install all dependencies
npm install --prefix backend
npm install --prefix frontend

# Start backend (port 3001, file-watch enabled)
npm run dev:backend

# Start frontend (port 5173, Vite HMR)
npm run dev:frontend

Or start each service individually from its own directory:

# Backend
cd backend && npm run dev

# Frontend
cd frontend && npm run dev

API Reference

GET /health

Returns { status: "ok" }. Use this to verify the server is running.

GET /api/protocols

Returns the aggregated pool data from all eight protocols.

{
  "protocols": [
    {
      "id": "stackingdao-liquid",
      "protocol": "StackingDAO",
      "product": "Liquid Stacking",
      "category": "liquid-stacking",
      "asset": "STX",
      "yieldAsset": "stSTX",
      "apy": 7.42,
      "tvlUsd": 45200000,
      "lockupDays": 0,
      "url": "https://stackingdao.com"
    }
  ],
  "fetchedAt": "2026-03-13T10:00:00.000Z"
}

GET /api/balances/:address

Proxies Hiro's balance endpoint. Returns STX balance, locked STX, and all fungible token balances for the given Stacks address.

GET /api/swap/tokens

Returns all tokens available for swapping. Pass ?from=<tokenId> to return only tokens reachable from a given token (used to populate the TO-token dropdown after a FROM token is selected).

GET /api/swap/routes

Returns all routes between two tokens. Query params: tokenX, tokenY.

POST /api/swap/quote

Body: { tokenX, tokenY, amount }. Returns the best route and estimated output amount.

POST /api/swap/params

Body: { tokenX, tokenY, amount, route, slippage, senderAddress }. Returns the full contract-call parameters ready to pass to openContractCall.

POST /api/ai/chat

Body:

{
  "messages": [
    { "role": "user", "content": "Swap 10 STX to sBTC" }
  ],
  "userAddress": "SP..."
}

Returns the structured AI response object described in the AI Assistant section.


Frontend Pages

AI Chat (/ai) Full-page conversation interface. Renders plan cards with step checklists and Confirm/Cancel buttons for multi-step plans, a step progress bar during execution, and pool comparison cards when the AI compares protocols.

Portfolio Displays the connected wallet's STX balance, locked STX, sBTC, xBTC, and stSTX holdings. Balances auto-refresh every 30 seconds.

Vaults Browsable list of all protocol pools with live APY, TVL, category, lock-up period, and a deposit button. Filterable by category, asset, and protocol.

Swap Token swap interface powered by Bitflow. Selects FROM and TO tokens via the TokenPicker component, auto-fetches the best quote with a 600 ms debounce, displays the route path, and builds the transaction on confirm.


Deploying to Render

A render.yaml file at the root configures both services for Render's Blueprint deployment.

  1. Push the repository to GitHub.
  2. In the Render dashboard, create a new Blueprint and point it at the repository.
  3. Set the following environment variables in the Render dashboard (they are marked sync: false in the YAML and will not be committed):
Service Variable Value
Backend API GROQ_API_KEY Your Groq API key
Backend API FRONTEND_URL The deployed frontend URL from Render
Backend API HIRO_API_KEY Your Hiro Platform API key (recommended)
Frontend VITE_API_BASE_URL The deployed backend URL from Render

The frontend is deployed as a static site with a catch-all rewrite to index.html for client-side routing.


Tech Stack

Frontend

  • React 19 with TypeScript
  • Vite 7
  • Zustand 5 (state management)
  • @stacks/connect (wallet integration — Xverse, Leather, and all WalletConnect-compatible Stacks wallets)

Backend

  • Node.js 20+ (ESM)
  • Express 5
  • groq-sdk (Groq LLM API)
  • @bitflowlabs/core-sdk (swap routing)
  • @stacks/transactions (Clarity value encoding)

Infrastructure

  • Render (backend: Node web service, frontend: static site)
  • Hiro API (blockchain data)
  • Groq Cloud (LLM inference)

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors