⚙️ Engineering deep-dive

The engine behind Prune

A transparent look at how every component in the system connects — from browser to blockchain.

How the pieces fit together

The platform is split into two layers: the admin stack that users interact with, and isolated bot containers that execute on-chain autonomously.

Admin layer — handles all user-facing requests
🌐
Browser
HTML / JS
──HTTPS──▶
🔁
Nginx
Reverse proxy + static
──HTTP──▶
FastAPI Admin
Python asyncio
──TCP──▶
🔀
PgBouncer
Connection pooler
──TCP──▶
🗄️
PostgreSQL
Primary database
Docker Socket API
Bot layer — runs autonomously in isolated containers
burnbot_1_WAGMI_01
burnbot_1_PEPE_02
+ up to N bots
JSON-RPC
HTTPS
HTTPS
Solana RPC
Balance · TX submit
🪐
Jupiter API
Swap quotes · routing
💧
Raydium / PumpSwap
Liquidity pools

What happens each cycle

Each bot runs a continuous asyncio loop. Here is exactly what happens on every iteration.

01
Check SOL balance via RPC

The bot calls getBalance on its treasury wallet. If balance is below the configured reserve + fee buffer, the cycle is skipped and the bot sleeps.

solana.rpc.async_api
02
Calculate spendable amount

Spendable = balance − sol_reserve − fee_buffer. Then multiplied by the configured buyback_percent (1–100%). This prevents the wallet from running dry.

in-memory arithmetic
03
Get Jupiter swap quote

Requests a quote from Jupiter Aggregator (lite-api.jup.ag) for SOL → TOKEN. Jupiter routes through all DEXes to find the best price with minimal slippage.

GET /swap/v1/quote
04
Build and sign swap transaction

Jupiter returns a serialized VersionedTransaction. The bot signs it with the treasury keypair (decrypted in-memory, never written to disk) and submits via Solana RPC.

solders · VersionedTransaction
05
Mode-specific action

Buyback & Burn: calls the SPL Token burn instruction on the received tokens.
Buyback Only: tokens stay in treasury.
Add Liquidity: pairs SOL + tokens into the Raydium or PumpSwap pool.

spl.token.instructions · Raydium SDK
06
Persist stats & notify

Stats (SOL spent, tokens burned/bought, cycle count) are written to a JSON file on the data volume, readable by the admin service. A Telegram message is sent if enabled.

json · aiohttp · Telegram Bot API
07
Sleep until next cycle

asyncio.sleep(INTERVAL_SECONDS) — configurable from 60 s to several hours. The bot uses almost zero CPU while sleeping.

asyncio.sleep
bot_loop.py (simplified)
async def bot_loop(): while True: # 01 — check balance balance = await get_sol_balance(client, owner) spendable = balance - SOL_RESERVE - FEE_BUFFER if spendable < MIN_BUYBACK: await sleep(INTERVAL_SECONDS) continue # 02 — apply buyback percent amount = int(spendable * BUYBACK_PERCENT / 100) # 03 — Jupiter quote quote = await jupiter_quote( session, SOL_MINT, TOKEN_MINT, amount, SLIPPAGE_BPS ) # 04 — sign & send swap tx_bytes = await jupiter_swap_tx(session, quote, owner) sig = await send_versioned_tx(client, tx_bytes, keypair) tokens_bought = int(quote["outAmount"]) # 05 — mode-specific action if BOT_MODE == "BUYBACK_AND_BURN": await burn_tokens(client, keypair, TOKEN_MINT, tokens_bought) elif BOT_MODE == "ADD_LIQUIDITY": await add_to_pool(pool_id, amount // 2, tokens_bought) # 06 — persist & notify stats["sol_spent_total"] += amount _save_stats() await telegram_notify(sig, amount, tokens_bought) # 07 — sleep await asyncio.sleep(INTERVAL_SECONDS)

How secrets are protected

Private keys are sensitive. Here is every layer of protection applied to keypairs and API credentials.

🔐
AES-256-GCM keypair encryption

Every treasury and creator wallet is encrypted with AES-256-GCM before being written to the database. The encryption key is never stored alongside the ciphertext — it lives only in the server environment.

key = ENCRYPT_KEY (env, 32 bytes)
iv = os.urandom(12) # unique per key
cipher = AES-256-GCM(key, iv)
stored = iv + tag + ciphertext

plaintext only in memory during bot run
🪪
JWT Bearer authentication

All admin API endpoints require a signed JWT token. Tokens are issued on login/register and expire after 30 days. The signing secret is a configurable environment variable — never hardcoded.

algorithm : HS256
expiry : 30 days
secret : SECRET_KEY (env)

public endpoints (bot stats) require
X-API-Key header instead — SHA-256 hashed
🐳
Docker process isolation

Each bot runs in a dedicated Docker container with its own filesystem, process namespace, and network stack. A crash or compromise in one bot cannot affect any other bot or the admin service.

restart : unless-stopped
network : separate bridge network
no shared volumes between bots

container name:
burnbot_{user}_{TOKEN}_{id}

Technologies powering Prune

Every component chosen for reliability, performance, and Solana ecosystem fit.

Solana
Blockchain

All buybacks, burns, and liquidity operations are on-chain Solana transactions — finalised in ~400 ms with sub-cent fees.

Jupiter Aggregator
DEX routing

Jupiter routes every swap across all major Solana DEXes to find best price. Bots use the lite API (no Metis dependency) for lower latency.

Raydium / PumpSwap
AMM liquidity pools

Add Liquidity mode deposits into the pool that graduated pump.fun tokens live on — PumpSwap or Raydium AMM V4, auto-detected at startup.

FastAPI
Admin API · Python

Async Python web framework with Pydantic validation. Handles auth, bot management, stats, avatar uploads, and the public API — all in a single process.

PgBouncer
Connection pooler

Sits between FastAPI and PostgreSQL in transaction pooling mode. Caps actual DB connections to ~20 regardless of concurrent API requests or future bot count.

PostgreSQL 16
Primary database

Stores users, bots, API keys (SHA-256 hashed), bot stats, and encrypted keypairs. SQLAlchemy async ORM with asyncpg driver.

Docker
Container runtime

The admin service manages bot containers via the Docker socket API at runtime. Each bot is an independent container with its own lifecycle and logs.

Nginx
Reverse proxy · static

Serves all static HTML/CSS/JS files directly (no FastAPI overhead) and proxies only API calls. Handles uploads with 7-day browser caching headers.

AES-256-GCM
Keypair encryption

Python's cryptography library encrypts every private key before DB write. A unique 12-byte IV per key and a 16-byte authentication tag prevent tampering.