Skip to content

Ubuntu-Technologies/sona

Repository files navigation

SONA

The Next-Gen Wallet built on Solana

Every command deserves a wallet that thinks.

Live Demo Solana TypeScript Rust Bun License: Apache-2.0

sonawallet.xyz · Whitepaper


Introducing our Brainchild

SONA is a walelt with superpowers built on Solana. In simple terms, you describe what you want to do in plain language, SONA reasons about it, confirms your intent, and executes signed transactions autonomously and also allows you to see its actions in real-time.

It pairs a sandboxed Rust signing core with an Artificially Intelligent brain written in Typescript, giving any LLM the ability to observe on-chain state, reason about actions, and execute signed transactions all within constitutional guardrails that can never be overridden.

Key capabilities:

Feature Description
Natural language commands "Swap 0.01 SOL to USDC" or "Transfer 0.005 SOL to my treasury"
Recurring strategies "Swap 0.01 SOL every 10 minutes" — schedules all steps automatically
Live balance from RPC Always fetches real-time balance from Solana devnet, never stale
Constitutional safety Four immutable laws enforced across TypeScript and Rust layers
Three operating modes Standard (observe), Assisted (approve), God (autonomous)
Multi-provider AI Anthropic · Groq · Gemini · OpenAI · Ollama — auto-detected from env
Pyth Hermes oracle Real-time SOL/USD price feed in both agent observe and chat context
On-chain transparency Every tx carries a SONA Memo receipt (Law III: Radical Transparency)
MCP-compatible Any MCP host (Claude Desktop, Cursor) can use SONA as a signing tool
OpenClaw plugin Install as an agent skill: clawhub install sona
Child wallet factory Spawn isolated wallets per strategy — fleet-ready

Architecture

SONA Architecture

View ASCII diagram
╔══════════════════════════════════════════════════════════════════════════════════╗
║                           USER INTERFACE LAYER                                  ║
╠═══════════════════════════╦════════════════════════════════════════════════════ ║
║     CLI  (packages/cli)   ║         Next.js Dashboard  :3000                   ║
║  ─────────────────────    ║  ─────────────────────────────────────────────────  ║
║  sona init                ║  CHAT TAB              MONITOR TAB                 ║
║  sona start               ║  ├─ AI conversation        ├─ WalletState          ║
║  sona logs                ║  │  (SSE streaming)         ├─ ActivityFeed (SSE)  ║
║  sona approve             ║  ├─ Model picker            ├─ SpendLimitsPanel    ║
║  sona status              ║  │  Free · Pro · Local      ├─ PendingActionsPanel ║
║  --mode standard          ║  └─ Quick actions           ├─ PolicyViewer        ║
║        assisted           ║     send · swap · stake     └─ WalletRegistry      ║
║        god                ║                                                     ║
║  --brain rules|ai|hybrid  ║                                                     ║
╚═══════════════════════════╩═══════════════════╦════════════════════════════════╝
                                                │ SSE + REST
                            ╔═══════════════════╩═══════════════════╗
                            ║        Next.js API Routes             ║
                            ║  GET  /api/stream      SSE feed       ║
                            ║  GET  /api/status      agent status   ║
                            ║  GET  /api/policy      YAML policy    ║
                            ║  POST /api/policy      live limits    ║
                            ║  POST /api/mode        mode switch    ║
                            ║  POST /api/chat        AI commands    ║
                            ║  POST /api/actions/approve            ║
                            ╚═══════════════════╦═══════════════════╝
                                                │ reads / writes SQLite (WAL mode)
╔═══════════════════════════════════════════════╩════════════════════════════════════╗
║                         AGENT CORE  (TypeScript / Bun)                            ║
║                                                                                    ║
║  ┌──────────────────────────────  AGENT LOOP  ───────────────────────────────┐    ║
║  │                                                                            │    ║
║  │   ┌────────────┐    ┌────────────┐    ┌────────────┐    ┌─────────────┐   │    ║
║  │   │  OBSERVE   │───►│   REASON   │───►│   DECIDE   │───►│   EXECUTE   │   │    ║
║  │   │            │    │            │    │            │    │             │   │    ║
║  │   │ · balance  │    │ · rule eval│    │ · execute  │    │ · build tx  │   │    ║
║  │   │ · SOL price│    │ · signal   │    │ · queue    │    │ · simulate  │   │    ║
║  │   │   (Pyth)   │    │   scoring  │    │ · skip     │    │ · sign+send │   │    ║
║  │   └────────────┘    └────────────┘    └────────────┘    └──────┬──────┘   │    ║
║  │                                                                 │          │    ║
║  └─────────────────────────────────────────────────────────────────┼──────────┘    ║
║                                                                     │              ║
║  ┌──────────────────────────────  SKILL REGISTRY  ─────────────────┼──────────┐   ║
║  │  TransferSkill · SwapSkill · IsolatedSwapSkill                  │          │   ║
║  │  StakeSkill (Marinade) · ArbitrageSkill (Orca)  ◄───────────────┘          │   ║
║  └──────────────────────────────────────────────────────────────────────────────┘  ║
║                                                                                    ║
║  AI Brain: rules | ai | hybrid     Chat Commands: scheduled_at queue             ║
║  Webhook alerts (Discord/HTTP)     x402 Pay-for-Service client                   ║
║  Kora paymaster relay              Named contacts (policy.yaml → address)        ║
╚════════════════════════════════════════╦═══════════════════════════════════════════╝
                                         │ IPC (JSON over stdin/stdout)
╔════════════════════════════════════════╩═══════════════════════════════════════════╗
║                    RUST SIGNING CORE  (crates/wallet-core)                        ║
║                                                                                    ║
║  Ed25519 keypair · AES-256-GCM keystore · Law II spend limits                    ║
║  Enforced before every signature — TypeScript layer cannot bypass                 ║
╚════════════════════════════════════════════════════════════════════════════════════╝

Quickstart

Prerequisites

  • Bun 1.3+
  • Rust 1.78+ (only needed to rebuild the signing core)
  • At least one AI API key (Groq is free — console.groq.com). For the live demo, I made use of Gemini's SDK and the Grokq API where the rate limits were exceeded.

1. Clone and install

git clone https://github.com/Ubuntu-Technologies/sona.git
cd sona
bun install

2. Configure environment

cp .env.example .env.local

Edit .env.local — at minimum, set one AI provider key:

# AI provider (pick one — Groq is free)
GROQ_API_KEY=your_groq_key_here

# Or use Anthropic, Gemini, or OpenAI
# ANTHROPIC_API_KEY=...
# GEMINI_API_KEY=...
# OPENAI_API_KEY=...

3. Initialize wallet

bun run sona init

This generates a keypair, encrypts it with your passphrase, and writes SONA_PASSPHRASE to .env.local.

4. Fund your wallet

solana airdrop 1 <your-wallet-address> --url devnet --allow-unfunded

Or use the Solana CLI airdrop from the setup wizard in the dashboard.

5. Start SONA

bun run sona start --mode god --brain hybrid

Open http://localhost:3000 — the dashboard launches automatically.


Operating Modes

Mode Behaviour
Standard Observe only — reads balance and price, no execution
Assisted Queues actions for human approval before signing
God Full autonomy — executes immediately within spend limits

Switch modes live from the dashboard header or via:

bun run sona start --mode assisted

AI Brain

Brain mode Behaviour
rules Pure YAML policy evaluation — no AI, fully deterministic
ai AI decides every cycle based on observed state
hybrid AI is consulted; constitutional laws and policy caps still apply

Supported providers

Auto-detected from env. Priority order: Anthropic → Gemini → Groq → OpenAI → Ollama.

Provider Env var Notes
Anthropic ANTHROPIC_API_KEY claude-opus-4-6 default
Gemini GEMINI_API_KEY gemini-2.5-flash default
Groq GROQ_API_KEY llama-4-maverick default (free tier available)
OpenAI OPENAI_API_KEY gpt-4o-mini default
Ollama OLLAMA_BASE_URL llama3 default — runs locally

Override at runtime from the dashboard model picker (Chat tab → Model selector).


Constitutional Laws

These four laws are enforced across both the TypeScript agent and the Rust signing core. No AI response, chat command, or external call can override them.

Law Name Description
I Owner Supremacy Your YAML policy overrides all AI reasoning with no exceptions
II Bounded Expenditure 0.05 SOL/action, 0.5 SOL/session is enforced at the Rust signing layer
III Radical Transparency Every executed transaction includes an on-chain SONA Memo receipt
IV Fail-Safe Halting All transactions are simulated before signing

Policy YAML DSL

SONA reads config/policy.yaml on startup. Rules fire when their trigger condition is met each cycle.

version: 1
agent_name: sona-alpha
mode: god           # standard | assisted | god
brain: hybrid       # rules | ai | hybrid
cycle_interval_seconds: 30

spend_limits:
  max_per_action_sol: 0.05
  max_per_session_sol: 0.5

contacts:
  treasury: "7xKX..."   # named address — use in action_params.destination

rules:
  - id: dip_buy
    priority: 10
    trigger:
      type: price_below
      threshold: 140        # SOL/USD
    action_type: transfer
    action_params:
      destination: treasury
      amount_sol: 0.01

  - id: rebalance
    priority: 5
    trigger:
      type: balance_above
      threshold: 500000000  # 0.5 SOL in lamports
    action_type: swap
    action_params:
      input_mint: So11111111111111111111111111111111111111112
      output_mint: BRjpCHtyQLNCo8gqRUr8jtdAj5AjPYQaoqbvcZiHok1k
      amount_sol: 0.02
      slippage_bps: 50

CLI Reference

sona init               Generate keypair, encrypt keystore, write passphrase to .env.local
sona start              Start the agent loop (--mode, --brain flags)
sona status             Show live wallet balance and last cycle summary
sona logs               Tail the audit DB — recent cycles, observations, decisions
sona approve <id>       Approve a queued action (assisted mode)
sona policy             Print the active policy rules

Environment Variables

Variable Default Description
SONA_PASSPHRASE Keystore decryption passphrase (written by sona init)
SONA_WALLET_CORE_BIN bin/wallet-core Path to Rust signing binary
SONA_KEYSTORE_PATH ~/.sona/keystore.json Encrypted keypair location
SONA_DB_PATH ~/.sona/audit.db SQLite audit database
SONA_POLICY_PATH config/policy.yaml YAML policy rules
SONA_DATA_DIR ~/.sona Data directory root
SONA_RPC_URL https://api.devnet.solana.com Solana RPC endpoint
SONA_AGENT_MODE god Default operating mode
SONA_BRAIN hybrid Default brain mode
ANTHROPIC_API_KEY Anthropic API key
GEMINI_API_KEY Gemini API key
GROQ_API_KEY Groq API key (free tier at console.groq.com)
GROQ_MODEL llama-3.3-70b-versatile Groq model override
OPENAI_API_KEY OpenAI API key
OPENAI_MODEL gpt-4o-mini OpenAI model override
OLLAMA_BASE_URL http://localhost:11434/v1 Ollama base URL
KORA_URL Kora paymaster relay URL (optional)
SONA_WEBHOOK_URL Webhook URL for cycle alerts (Discord or HTTP POST)

Dashboard

The Next.js dashboard runs on :3000 and provides:

  • Chat tab — natural language commands with streaming AI responses. Ask SONA to transfer SOL, swap tokens, or describe a recurring strategy. It confirms intent and executes.
  • Monitor tab — live agent telemetry via SSE: cycle status, balance, price, decisions, executions, spend limits, policy rules, child wallets, pending actions.
  • Mode switcher — switch Standard / Assisted / God live without restarting.
  • Setup wizard — first-run flow: register → initialize wallet → configure mode → start agent.

Chat examples

"What's my balance?"
"Transfer 0.005 SOL to 7xKX..."
"Swap 0.01 SOL to USDC"
"Buy the dip — swap 0.02 SOL to USDC every time price drops below $140, 5 times"
"Show my recent transactions"

Skills

SONA ships six built-in execution skills, registered in packages/agent/src/skills/index.ts:

Skill Trigger Description
TransferSkill action_type: transfer SOL and SPL token transfers with SONA Memo
SwapSkill action_type: swap Orca Whirlpools DEX swap
IsolatedSwapSkill action_type: swap_isolated Swap in a child wallet, sweep back to parent
StakeSkill action_type: stake Marinade Finance liquid staking
ArbitrageSkill action_type: arbitrage Triangular SOL→USDC→SOL via Orca (2 legs)

See SKILLS.md for full parameter reference and how to write custom skills.


MCP Server

SONA exposes an MCP server at packages/mcp-server/ which means you can connect any MCP-compatible host (Claude Desktop, Cursor, VS Code) to use SONA as a signing tool.

# Start the MCP server
bun run packages/mcp-server/src/index.ts

Available MCP tools: get_address, check_limits, sign_transaction, get_policy.


OpenClaw Plugin

SONA ships as an installable OpenClaw skill — plug it into any OpenClaw-compatible agent to control your wallet via natural language.

clawhub install sona

Or load directly:

import register from "@sona/openclaw/plugin.ts"

register({
  registerTool(tool) {
    console.log("registered:", tool.name)
  },
})

Available tools: get_wallet_status, get_sol_price, get_agent_status, set_mode, get_policy, transfer_sol, get_pending_actions, approve_action, chat, get_activity.

Set SONA_API_URL and SONA_TOKEN to point at your running SONA instance.


Multi-Agent & Child Wallets

SONA's WalletFactory lets the agent spawn isolated child wallets for per-strategy risk isolation:

# In policy.yaml
rules:
  - id: isolated_arb
    action_type: swap_isolated   # creates child wallet, executes, sweeps back
    action_params:
      amount_sol: 0.03

Child wallet lifecycle: create → fund → execute → sweep → close. The parent wallet retains all funds between strategies.


Advanced Integrations

Kora Paymaster Relay

Route all transactions through a Kora relay for gasless UX:

KORA_URL=https://your-kora-instance.com

Webhook Alerts

Send a Discord embed or HTTP POST on every agent cycle:

SONA_WEBHOOK_URL=https://discord.com/api/webhooks/...

x402 Pay-for-Service

SONA includes an X402Client that auto-pays HTTP 402 responses using Solana. The PPC is capped at 0.001 SOL/call. Demo endpoint available at /api/x402-demo.


Deployment

Deploy to Railway (one command)

# Install Railway CLI
npm i -g @railway/cli

# Login and link
railway login
railway link

# Deploy
railway up

Set the following Railway environment variables:

GROQ_API_KEY          your Groq key (free at console.groq.com)
SONA_AGENT_MODE       god
SONA_BRAIN            hybrid

SONA auto-detects $PORT from Railway. The dashboard, agent API, and agent loop all run in a single container. Persistent data (keystore, DB) lives on a Railway Volume mounted at /data.

After deploying, visit your Railway URL and complete the setup wizard (register → init wallet → start agent).

Docker

# Build
docker build -t sona .

# Run (mount a volume for persistent data)
docker run -p 3000:3000 \
  -v sona-data:/data \
  -e GROQ_API_KEY=your_key \
  sona

Project Structure

sona/
├── packages/
│   ├── agent/          TypeScript agent loop, skills, AI brain, Pyth oracle
│   ├── cli/            sona init / start / status / logs / approve
│   ├── dashboard/      Next.js 15 dashboard (Chat + Monitor tabs)
│   ├── mcp-server/     MCP server for Claude Desktop / Cursor integration
│   └── openclaw/       OpenClaw plugin adapter for ClaWHub marketplace
├── crates/
│   └── wallet-core/    Rust signing core — Ed25519, AES-256-GCM, spend limits
├── config/
│   └── policy.yaml     Default policy rules (edit to customize)
├── bin/
│   └── wallet-core     Pre-compiled Rust binary (Linux x86_64)
├── entrypoint.sh       Container startup — dashboard + agent watcher
└── Dockerfile          Single-stage bun:1.3 image

Security Architecture

SONA's security model is built on a hard separation between the intelligence layer and the cryptographic layer. The TypeScript agent (the "shell") handles observation, reasoning, and decision-making but never holds a private key — not in memory, not on disk. The Rust binary (the "core") holds the Ed25519 keypair encrypted at rest with AES-256-GCM and Argon2id KDF, receives unsigned transaction bytes over a subprocess pipe, enforces spend limits before signing, and returns only the 64-byte signature. There is no shared memory between the two layers; the Rust process never makes network calls and cannot be exfiltrated via SSRF.

The IPC protocol uses newline-delimited JSON over stdin/stdout. The TypeScript layer sends a sign_transaction request containing the compiled transaction bytes, the amount in lamports, and the current spend policy. The Rust layer validates the amount against max_per_action_lamports and max_per_session_lamports before the keypair ever touches the transaction. If the amount exceeds policy, the Rust process returns an error — the TypeScript shell cannot bypass this check, even if the AI brain is compromised or hallucinating.

The Rust Signer trait is pluggable: the default LocalSigner uses AES-256-GCM for development, but the same interface supports Phala Network TEE (Intel SGX / AMD SEV enclaves where the key only exists in hardware) and Turnkey MPC (non-custodial multi-party computation with quorum approvals for large treasury moves). No TypeScript code changes are required to swap custody backends.

Threat mitigations:

Threat Mitigation
Prompt injection AI output is a suggestion only — TypeScript constitution checks + Rust spend limits before any signature
Model hallucination (over-spend) Law II: Rust rejects any amount exceeding policy limits before signing
Keystore theft AES-256-GCM + Argon2id: the file is useless without the passphrase
Dependency compromise Private key never in TypeScript heap — compromised npm package cannot exfiltrate it
Replay attack Solana transactions include a recent blockhash (~90s TTL) — replayed transactions are rejected
Simulation bypass Law IV: SONA's own simulation must pass before broadcast; skipPreflight only at the RPC layer after

Operational security:

  • The passphrase never leaves .env.local (mode 0600). It is not logged or transmitted.
  • All API endpoints require JWT session tokens. Login rate-limited to 10 req/min per IP.
  • Passwords require: 12+ chars, uppercase, lowercase, digit, symbol.
  • CORS is locked to SONA_DASHBOARD_ORIGIN. No wildcard on state-changing routes.
  • Every transaction is simulated on devnet before broadcast. Simulation failure = halt.
  • Every executed transaction includes an on-chain SONA Memo for permanent audit.

Troubleshooting

Agent shows OFFLINE in dashboard The agent watcher needs the keystore to exist and SONA_PASSPHRASE to be set in the data volume's .env.local. Complete the setup wizard to initialize.

Cannot find module '@sona/agent/src/...' Rebuild the lockfile: bun install. Ensure you're on Bun 1.3+.

SQLITE_BUSY errors The database uses WAL mode — this should not occur in normal operation. If it does, restart the container.

Gemini quota exceeded Set GROQ_API_KEY in your env and remove GEMINI_API_KEY. Groq has a free tier that works out of the box.

Balance shows 0 but wallet is funded The dashboard fetches live balance from the Solana devnet JSON-RPC on every chat command. If balance is 0, the wallet may not be funded yet — run solana airdrop 1 <address> --url devnet.


License

Apache-2.0 — see LICENSE for details.


Built on Solana · Powered by Pyth · Secured by Rust

sonawallet.xyz

About

SONA is the Next-Gen Solana Wallet built with native Agentic Superpowers

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors