Skip to content

0xstonegm/bot

 
 

Repository files navigation

🐱 Nyanbot

Nyanbot is an advanced, modular Solana trading automation and analytics system. It aggregates market data, applies rules for trading decisions, integrates with Telegram, and supports real-time streaming across multiple venues.


🚀 Features

  • 🔁 Real-time data aggregation for:
    • Pump.fun
    • PumpSwap
    • Jupiter
    • Solana-native sources
  • 📈 Computes candles, market cap, TWAP, and USD prices
  • 🧠 Rule engine for automated trading logic
  • 🧵 Highly concurrent indexer using blockstream + slotstream
  • 🤖 Telegram bot interface for user interaction
  • 🐳 Fully containerized with Docker support
  • 🗂 Postgres-backed storage with SQLx migrations

🛠 Build it yourself

docker build . -t nyanbot/nyanbot

✅ Run tests

Some integration tests require a .env file in the root directory with the following values:

TEST_TELEGRAM_TOKEN=*****************
DATABASE_URL=postgres://username:password@localhost:5432/dev
SOLANA_RPC_URL==*****************
WALLET_SECRET==*****************
TEST_SOLANA_KEY_ONE==*****************
TEST_SOLANA_KEY_TWO==*****************
TEST_SOLANA_KEY_THREE==*****************
TEST_SOLANA_KEY_FOUR==*****************
TEST_SOLANA_KEY_FIVE==*****************

where

  • TEST_SOLANA_KEY_ONE - contains balance - used for the happy path tests
  • TEST_SOLANA_KEY_TWO - receives token and native from TEST_SOLANA_KEY_ONE
  • TEST_SOLANA_KEY_THREE - empty wallet - contains ata for 8j51khGE6ELcKvhQNXne448rVcLGMtqWMc5YNAdHpump and wsol
  • TEST_SOLANA_KEY_FOUR - empty wallet
  • TEST_SOLANA_KEY_FIVE - contains native and wsol

Deployment

The latest build is pushed to Docker Hub. You can also build it yourself and run locally by updating credentials accordingly. Run all services using a docker-compose.yml file like the one shown above.

services:
  postgres:
    image: postgres:17-alpine
    container_name: postgres
    restart: always
    environment:
      - POSTGRES_USER=************
      - POSTGRES_PASSWORD=*********
    ports:
      - "127.0.0.1:5432:5432"
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    command: [ "postgres", "-c", "max_locks_per_transaction=1024", "-c", "max_wal_size=8192000" ]

  agg-jup-candle:
    image: nyanbot/nyanbot
    container_name: agg-jup-candle
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "JUPITER_CANDLE_ACTIVE=true"
      - "JUPITER_CANDLE_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "JUPITER_CANDLE_POSTGRES_POOL_MAX=4"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-jup-mcap:
    image: nyanbot/nyanbot
    container_name: agg-jup-mcap
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "JUPITER_MCAP_ACTIVE=true"
      - "JUPITER_MCAP_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "JUPITER_MCAP_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-jup-twap:
    image: nyanbot/nyanbot
    container_name: agg-jup-twap
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "JUPITER_TWAP_ACTIVE=true"
      - "JUPITER_TWAP_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "JUPITER_TWAP_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-jup-usd:
    image: nyanbot/nyanbot
    container_name: agg-jup-usd
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "JUPITER_USD_ACTIVE=true"
      - "JUPITER_USD_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "JUPITER_USD_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-pf-candle:
    image: nyanbot/nyanbot
    container_name: agg-pf-candle
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPFUN_CANDLE_ACTIVE=true"
      - "PUMPFUN_CANDLE_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPFUN_CANDLE_POSTGRES_POOL_MAX=4"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-pf-mcap:
    image: nyanbot/nyanbot
    container_name: agg-pf-mcap
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPFUN_MCAP_ACTIVE=true"
      - "PUMPFUN_MCAP_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPFUN_MCAP_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-pf-progress:
    image: nyanbot/nyanbot
    container_name: agg-pf-progress
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPFUN_PROGRESS_ACTIVE=true"
      - "PUMPFUN_PROGRESS_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPFUN_PROGRESS_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-pf-summary:
    image: nyanbot/nyanbot
    container_name: agg-pf-summary
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPFUN_SUMMARY_ACTIVE=true"
      - "PUMPFUN_SUMMARY_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPFUN_SUMMARY_POSTGRES_POOL_MAX=8"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-pf-twap:
    image: nyanbot/nyanbot
    container_name: agg-pf-twap
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPFUN_TWAP_ACTIVE=true"
      - "PUMPFUN_TWAP_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPFUN_TWAP_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-pf-usd:
    image: nyanbot/nyanbot
    container_name: agg-pf-usd
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPFUN_USD_ACTIVE=true"
      - "PUMPFUN_USD_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPFUN_USD_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-ps-candle:
    image: nyanbot/nyanbot
    container_name: agg-ps-candle
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPSWAP_CANDLE_ACTIVE=true"
      - "PUMPSWAP_CANDLE_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPSWAP_CANDLE_POSTGRES_POOL_MAX=4"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-ps-mcap:
    image: nyanbot/nyanbot
    container_name: agg-ps-mcap
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPSWAP_MCAP_ACTIVE=true"
      - "PUMPSWAP_MCAP_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPSWAP_MCAP_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-ps-summary:
    image: nyanbot/nyanbot
    container_name: agg-ps-summary
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPSWAP_SUMMARY_ACTIVE=true"
      - "PUMPSWAP_SUMMARY_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPSWAP_SUMMARY_POSTGRES_POOL_MAX=8"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-ps-twap:
    image: nyanbot/nyanbot
    container_name: agg-ps-twap
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPSWAP_TWAP_ACTIVE=true"
      - "PUMPSWAP_TWAP_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPSWAP_TWAP_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-ps-usd:
    image: nyanbot/nyanbot
    container_name: agg-ps-usd
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "PUMPSWAP_USD_ACTIVE=true"
      - "PUMPSWAP_USD_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "PUMPSWAP_USD_POSTGRES_POOL_MAX=2"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]


  agg-sol-sol:
    image: nyanbot/nyanbot
    container_name: agg-sol-sol
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "SOLANA_SOL_ACTIVE=true"
      - "SOLANA_SOL_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  agg-leaderboard:
    image: nyanbot/nyanbot
    container_name: agg-leaderboard
    restart: always
    environment:
      - "TOKIO_THREADS=1"
      - "LEADERBOARD_ACTIVE=true"
      - "LEADERBOARD_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
    command: /app/aggregator/aggregator /app/aggregator/config.toml
    depends_on: [ postgres ]

  api:
    image: nyanbot/nyanbot
    container_name: api
    restart: always
    environment:
      - "WALLET_SECRET=d****************************************************************a"
      - "POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "TELEGRAM_TOKEN=******************:***********************************"
    ports:
      - "127.0.0.1:8080:8080"
    command: /app/api/api /app/api/config.toml
    depends_on: [ postgres ]

  engine-handle:
    image: nyanbot/nyanbot
    container_name: engine-handle
    restart: always
    environment:
      - "HANDLE_ACTIVE=true"
      - "HANDLE_MODE=LIVE"
      - "HANDLE_RPC_URL=https://rpc.shyft.to?api_key=*********"
      - "HANDLE_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "WALLET_SECRET=d****************************************************************a"
    command: /app/engine/engine /app/engine/config.toml
    depends_on: [ postgres ]

  engine-rule-pf:
    image: nyanbot/nyanbot
    container_name: engine-rule-pf
    restart: always
    environment:
      - "RULE_PUMPFUN_ACTIVE=true"
      - "RULE_POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
    command: /app/engine/engine /app/engine/config.toml
    depends_on: [ postgres ]

  indexer:
    image: nyanbot/nyanbot
    container_name: indexer
    restart: always
    environment:
      - "TOKIO_THREADS=8"
      - "RAYON_THREADS=4"
      - "POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "BLOCKSTREAM_CONCURRENCY=30"
      - "BLOCKSTREAM_RPC_URL=https://rpc.shyft.to?api_key=*********"
      - "SLOTSTREAM_WS_URL=wss://rpc.shyft.to?api_key=*********"
      - "SLOTSTREAM_DELAY=10"
      - "RPC_URL=https://rpc.shyft.to?api_key=*********"
    command: /app/indexer/indexer /app/indexer/config.toml
    depends_on: [ postgres ]


  telegram:
    image: nyanbot/nyanbot
    container_name: telegram
    restart: always
    environment:
      - "WALLET_SECRET=d****************************************************************a"
      - "POSTGRES_CONNECTION_STRING=postgres://username:password@postgres:5432/db"
      - "TELEGRAM_TOKEN=******************************"
      - "WEBAPP_URL=https://telegram.nyan.bot"
    command: /app/telegram/telegram /app/telegram/config.toml
    depends_on: [ postgres ]

Run database migrations:

sqlx migrate run

🚨 Disclaimer 🚨

This project is in its prototyping phase – speed, clean code, and best practices have been intentionally ignored for now. Do NOT use in dbuction unless you enjoy debugging at 3 AM.

⚠️ Open Source, But No Direct Code Contributions ⚠️

Yes, the code is open source, but we are not accepting PRs at this point in time. However, we highly appreciate feedback, bug reports, and ideas to make Nyanbot even better!

If you want to point out a bug or suggest an improvement, feel free to open an issue. If you include example code to illustrate your point, that’s great! But note that we will rewrite any submitted code ourselves before merging, in a similar fashion to how SQLite operates.

🐾 Your insights matter, and we value your input! Just don’t expect a merge button. 😼

📜 License

This project is licensed under the AGPL-3.0. If you use or modify the code and deploy it publicly, you must also share your changes. Sharing is caring! 😼


About

Your favorite cat-themed automated investing companion!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 88.0%
  • TypeScript 8.5%
  • PLpgSQL 3.4%
  • JavaScript 0.1%
  • Dockerfile 0.0%
  • CSS 0.0%