SolSniper guide
How to set up, run and control your Solana token bot from Telegram: from creating the Telegram bot, to paper trading, to trading real SOL.
Most new memecoins go to zero. The safety checks catch common scams (tokens you can't sell, liquidity the developer can pull, printable or freezable tokens, hidden taxes, insider-held supply), but they cannot stop a developer or insiders simply selling their own tokens. Paper trade for a while, look at /pnl, and only put money in the bot wallet that you can afford to lose completely.
What it does
SolSniper runs on your server around the clock. It watches for brand-new Solana tokens, checks each one for safety and liquidity, and sends the ones that pass to your Telegram for approval. After you tap Buy, it manages the exit automatically.
Setup checklist
The bot is already installed at ~/projects/solsniper with everything it needs. You only have to do this:
- Create your Telegram bot and put its token and your chat ID in
.env(about 5 minutes) - Optional but recommended: add a free Solana RPC URL and Jupiter API key
- Run a test check to confirm it works
- Install it as a service so it runs 24/7 and restarts itself
- Paper trade for at least a week or two, then decide about going live
All commands below are run in a terminal on the server. Start every session with:
cd ~/projects/solsniper
Step 1 · Set up the Telegram bot
Telegram is how the bot asks permission to buy and tells you what it's doing. You create your own private bot (free, takes a couple of minutes). It will only ever listen to your chat; messages from anyone else are ignored.
Create the bot with BotFather
- In Telegram, search for @BotFather (blue check mark) and open it.
- Send
/newbot. - Give it a display name, e.g.
My SolSniper. - Give it a username ending in
bot, e.g.mattbox_solsniper_bot(must be unique). - BotFather replies with a token that looks like
7412345678:AAH3k...xyz. Copy it. Treat it like a password.
Create your .env file and paste the token
cd ~/projects/solsniper cp .env.example .env chmod 600 .env nano .env
Fill in the line TELEGRAM_BOT_TOKEN= with your token (no spaces, no quotes):
TELEGRAM_BOT_TOKEN=7412345678:AAH3k...xyz
Save with Ctrl+O, Enter, then exit with Ctrl+X.
Get your chat ID
- In Telegram, open your new bot (tap the link BotFather gave you) and press Start or send any message, like
hi. - On the server run:
.venv/bin/python -m solsniper tg-chatid
It prints something like chat id 123456789 (@yourname) -> TELEGRAM_CHAT_ID=123456789. Open .env again and fill it in:
TELEGRAM_CHAT_ID=123456789
Once the bot is running it reads all incoming messages itself, so tg-chatid won't see them anymore. If you need it again later, stop the service first (sudo systemctl stop solsniper).
Optional: add a command menu in Telegram
In BotFather send /setcommands, pick your bot, then paste this so commands show up when you type /:
status - Mode, balance, PnL, open positions positions - Open positions with live multiples pending - Tokens waiting for approval recent - Last 10 evaluated tokens pnl - Profit and loss summary pause - Stop new buys resume - Resume new buys sell - Sell a position: /sell ID PCT check - Safety-check a token: /check MINT get - Show a setting: /get KEY set - Change a setting: /set KEY VALUE unset - Remove an override: /unset KEY help - All commands
Step 2 · Optional API keys (recommended)
The bot works without these, but both are free and make it faster and more reliable. Add them to the same .env file.
| Setting | Where to get it | Why |
|---|---|---|
SOLANA_RPC_URL | Sign up free at helius.dev (or QuickNode / Alchemy), create a Solana mainnet endpoint and copy its URL. | The public Solana endpoint is slow and rate-limited. Strongly recommended before going live. |
JUPITER_API_KEY | Free key at portal.jup.ag. | Jupiter provides all prices and swaps. Without a key you get about 1 request/second, which can slow checks when it's busy. |
SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR-KEY JUPITER_API_KEY=your-jupiter-key
Changes to .env only take effect after a restart: sudo systemctl restart solsniper.
Step 3 · Test it
Run the safety checks on any Solana token to confirm everything is connected. Copy a token address from dexscreener.com/solana and run:
.venv/bin/python -m solsniper check PASTE_TOKEN_ADDRESS_HERE
You'll get a full report: liquidity, market cap, holders, LP lock, RugCheck score, buy/sell activity, and a verdict (PASS, SOFT FAIL, FAIL or NOT READY) with the reasons.
To see the Telegram side working, start the bot in the foreground for a minute:
.venv/bin/python -m solsniper run
Within a few seconds you should get "🚀 solsniper started — mode PAPER, approval manual" in Telegram. Send /status to it. Press Ctrl+C in the terminal to stop.
Step 4 · Run it 24/7
Install it as a system service. It then starts on boot and restarts itself within 10 seconds if it ever crashes.
sudo cp deploy/solsniper.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now solsniper
Everyday service commands
| What | Command |
|---|---|
| Is it running? | systemctl status solsniper |
| Watch the live log | journalctl -u solsniper -f (Ctrl+C to exit) |
| Last 200 log lines | journalctl -u solsniper -n 200 |
Restart (after editing .env) | sudo systemctl restart solsniper |
| Stop completely | sudo systemctl stop solsniper |
| Don't start on boot | sudo systemctl disable solsniper |
If you just want to stop buying, send /pause in Telegram instead. The bot keeps watching and selling your open positions. Only stop the service when you have no open positions you care about.
Using it day to day
1 · You get a candidate alert
When a token passes every check, you get a message like this:
Fjpwy5gu2PLLS7gX85qLgsYSjbq39axox6Zn9VFVpump
💧 Liq $24,301 · MC $112,534 · age 6.2m · pumpswap
👥 1878 holders · top1 8.6% · top10 9.1% · creator 0% · insiders 0%
🔒 LP locked 100% · rugcheck 31/100 · token-2022
📈 5m: vol $3,494 · 1929 buys / 1733 sells · 12.2%
🔁 buy impact 2.44% · round-trip loss 2.5%
DexScreener · RugCheck · Solscan
⏳ expires in 180s
| Line | What it means | What to look for |
|---|---|---|
| 💧 Liq / MC / age | Pool liquidity in USD, market cap, minutes since the pool was created. | More liquidity = easier to exit. Very young + tiny MC = highest risk. |
| 👥 holders | Number of holders and how much the biggest wallets own (pools excluded). | Low top-10 % and 0% creator/insiders is good. |
| 🔒 LP locked | % of the pool's liquidity tokens burned or locked. | 100% means the developer can't pull the liquidity. |
| rugcheck | RugCheck.xyz risk score, 0–100. Lower is safer. | Under ~40 is typical for clean launches. |
| 📈 5m | Last 5 minutes: volume, number of buys vs sells, price change. | More buys than sells and not crashing. |
| 🔁 impact / round-trip | How much your buy moves the price, and how much you'd lose buying then instantly selling. | Round-trip under ~5% is healthy. High = hidden tax or thin pool. |
| ⚠️ warnings | Non-fatal RugCheck notes (e.g. "Mutable metadata"). | Use your judgment. |
Tap the DexScreener link to see the chart before deciding. Then:
- ✅ Buy 0.1 SOL buys your normal size. Buy 0.2 buys double and Buy 0.05 buys half.
- ❌ Skip ignores it. Doing nothing does the same: it expires after 3 minutes.
- Want a custom size? Type
/approve 42 0.3to buy 0.3 SOL of candidate #42.
The bot re-checks the price the moment you tap Buy. If the price has already pumped more than 25% since the alert, it cancels the buy instead of chasing it. It also refuses if you'd exceed your position limits, total exposure, daily loss limit or minimum SOL reserve.
2 · You get a buy confirmation
0.1003 SOL → 412,880 tokens
Note the position number (#7). Those Sell buttons work at any time. From now on the bot checks the price every 10 seconds and sells by your exit rules.
3 · You get sell notices
received 0.1001 SOL · realized so far 0.1001 / cost 0.1003
received 0.1550 SOL · realized so far 0.3551 / cost 0.1003
FINAL PnL +0.2548 SOL (+254%)
💰 = partial sell (position still open). 🏁 = position closed with final profit/loss.
Other messages you may see
| Message | Meaning |
|---|---|
| ✅ passed checks but not bought: … | A token passed, but a limit blocked it (max positions, exposure, low balance, paused). |
| 🚨 NO SELL ROUTE | The bot can't get a sell price for a position. The liquidity may have been pulled. Check the chart immediately. |
| 🛑 Daily loss limit hit | Today's realized losses reached your limit. Buying is paused until you send /resume. |
| ❌ Buy/Sell failed | A trade didn't go through (no route, slippage, network). The reason is included. |
| 📊 daily summary | Sent every day at 00:00 UTC (5 PM MST, your server's time zone; change with /set telegram.daily_summary_utc_hour 15 for 8 AM MST): balance, positions, PnL. |
| 🔄 config reloaded | You (or /set) changed a setting and it's now active. |
Telegram commands
| Command | What it does | Example |
|---|---|---|
/status | Mode, approval setting, paused or running, balance, PnL today and all-time, open positions. | /status |
/positions | Open positions with current multiple, peak, value, cost, realized SOL, age. | /positions |
/pending | Candidates waiting for approval and seconds left. | /pending |
/approve ID [SOL] | Buy a pending candidate, optionally with a custom size. | /approve 42 0.25 |
/skip ID | Reject a pending candidate. | /skip 42 |
/sell POS [PCT] | Sell a percentage of a position (default 100%). | /sell 7 50 |
/pause | Stop new buys and alerts. Exits keep running. | /pause |
/resume | Start looking for buys again. | /resume |
/recent | Last 10 tokens evaluated and why each was rejected. Useful to tune filters. | /recent |
/check MINT | Run the full safety check on any token address. | /check Fjpw…pump |
/pnl | Closed positions: count, win rate, net SOL, best and worst trade. | /pnl |
/get KEY | Show a setting's current value. | /get budget.buy_amount_sol |
/set KEY VALUE | Change any setting instantly. See Changing settings. | /set exits.stop_loss_pct -25 |
/unset KEY | Remove your Telegram change and go back to the value in config.yaml. | /unset exits.stop_loss_pct |
/help | List of commands. | /help |
IDs can be typed with or without #: /sell #7 and /sell 7 are the same.
Changing settings
You can change any setting two ways. Neither needs a restart.
/set KEY VALUE. Saved in data/overrides.yaml and kept across restarts. Invalid values are rejected with an explanation.nano ~/projects/solsniper/config.yaml. The bot picks it up within 5 seconds. Every option is explained in config.example.yaml.Telegram /set values override config.yaml. If an edit to the file seems ignored, you probably set the same key in Telegram earlier. Run /unset KEY to clear it.
Budget & risk
| Key | Default | Meaning |
|---|---|---|
budget.buy_amount_sol | 0.1 | SOL spent per normal buy. |
budget.max_open_positions | 5 | Maximum positions open at once. |
budget.max_total_exposure_sol | 0.5 | Maximum SOL tied up in open positions in total. |
budget.min_sol_reserve | 0.05 | Always keep at least this much SOL for fees. |
budget.daily_loss_limit_sol | 0.3 | Auto-pause buying after this much realized loss in a UTC day. |
approval | manual | manual = you approve each buy. auto = bot buys everything that passes. |
approval_timeout_sec | 180 | How long an alert stays valid. |
max_price_move_since_alert_pct | 25 | Cancel an approved buy if the price rose more than this since the alert. |
execution.slippage_bps | 1500 | Max buy slippage (1500 = 15%). Too low and buys fail on fast tokens. |
execution.sell_slippage_bps | 2000 | Max sell slippage (20%). |
paper.starting_balance_sol | 5.0 | Fake balance for paper mode. |
Exits
| Key | Default | Meaning |
|---|---|---|
exits.take_profit | 2x initial, 4x 50%, 8x 50% | The take-profit ladder. See How selling works. |
exits.stop_loss_pct | -35 | Sell everything at -35% from entry. null disables. |
exits.stop_loss_after_initial_recovered | null | Once your initial is back, move the stop to this multiple (e.g. 1.0 = break-even). |
exits.trailing_stop | activate 1.8x, drop 30% | Once the peak reaches 1.8x, sell everything if the price falls 30% from the peak. |
exits.max_hold_minutes | 360 | Sell whatever is left after 6 hours. null = hold forever. |
exits.auto | true | false = only notify with Sell buttons; you sell manually. |
exits.monitor_interval_sec | 10 | How often prices are checked. |
Example /set commands
/set budget.buy_amount_sol 0.05
/set budget.max_open_positions 3
/set budget.daily_loss_limit_sol 0.2
/set exits.stop_loss_pct -25
/set exits.stop_loss_after_initial_recovered 1.0
/set exits.trailing_stop {activate_at: 2, drawdown_pct: 25}
/set exits.max_hold_minutes 120
/set exits.take_profit [{at: 1.5, sell_pct: 30}, {at: 2, sell: initial}, {at: 5, sell_pct: 100}]
/set filters.min_liquidity_usd 30000
/set filters.max_pair_age_min null
/set sources.dexscreener_boosts true
/set approval_timeout_sec 300Lists and groups use the format shown above: square brackets for a list, curly braces for a group. null turns a check or rule off.
How selling works
Every 10 seconds the bot asks Jupiter, "if I sold my whole remaining position right now, how much SOL would I get?" It compares that to what those tokens cost you. That ratio is the multiple: 1.0x = break-even, 2.0x = doubled, 0.65x = down 35%. Price impact is included, so the multiple is what you'd really get.
The rules, in priority order
- Stop loss: multiple at or below 0.65x (−35%), sell 100%.
- Trailing stop: once the peak has reached 1.8x, if the price drops 30% from that peak, sell 100%.
- Max hold: after 6 hours, sell 100%.
- Take-profit ladder: each step fires once, lowest first.
The take-profit ladder
Each step is either:
{at: 4, sell_pct: 50}: at 4x, sell 50% of what you still hold.{at: 2, sell: initial}: at 2x, sell exactly enough to get your original SOL back. The rest is a "free ride".
Worked example with the defaults (0.1 SOL buy)
| Price | What happens | SOL back so far | Still riding |
|---|---|---|---|
| Buy | Spend 0.1 SOL | 0 | 100% (worth 0.1) |
| 2x | "Recover initial": sells ~50% | 0.10, investment back | 50% (worth 0.1) |
| 4x | Sells 50% of the remainder | 0.20 | 25% (worth 0.1) |
| 8x | Sells 50% of the remainder | 0.30 | 12.5% (worth 0.1) |
| Falls 30% from its peak | Trailing stop sells the rest | ~0.37 | closed |
If instead it dumps straight after you buy, the stop loss sells everything around −35% (≈0.065 SOL back). In a fast crash the actual fill can be worse.
Conservative: /set exits.take_profit [{at: 1.5, sell: initial}, {at: 3, sell_pct: 100}] plus /set exits.stop_loss_pct -20
Moonbag: /set exits.take_profit [{at: 2, sell: initial}] plus /set exits.trailing_stop {activate_at: 3, drawdown_pct: 40}
Protect after recovery: /set exits.stop_loss_after_initial_recovered 1.0. Once your initial is back, the rest is sold if it falls back to break-even.
Safety checks
A token must pass every enabled check before you see it. Hard failures reject a token permanently. Soft failures (things that can improve, like volume) are re-checked every 2 minutes, up to 3 times. Type /recent to see why tokens are being rejected.
| Check | Setting | Default | Protects against |
|---|---|---|---|
| Mint authority revoked | filters.require_mint_authority_revoked | on | Developer printing unlimited tokens |
| Freeze authority revoked | filters.require_freeze_authority_revoked | on | Developer freezing your tokens so you can't sell |
| No dangerous token features | filters.reject_token2022_dangerous_extensions | on | Trap tokens (can take your tokens back, block or pause transfers) |
| Transfer fee | filters.max_transfer_fee_pct | 0 | Hidden tax on every trade |
| RugCheck danger flags / score | filters.max_rugcheck_score_normalised | 60 | Known scam patterns, creators who rugged before |
| LP locked / burned | filters.min_lp_locked_pct | 90% | Developer pulling the liquidity |
| Top holder | filters.max_top1_holder_pct | 10% | One whale dumping |
| Top 10 holders | filters.max_top10_holder_pct | 35% | Concentrated supply |
| Creator holdings | filters.max_creator_holding_pct | 5% | Developer dumping |
| Insider holdings | filters.max_insider_holding_pct | 15% | Linked insider wallets |
| Liquidity | filters.min_liquidity_usd / max_… | $15k – $2M | Can't exit; or too late/too big |
| Market cap | filters.min_market_cap_usd / max_… | $20k – $3M | Defines "early" |
| Pair age | filters.min_pair_age_min / max_… | 1 – 120 min | Defines "early" |
| Holders | filters.min_holders | 150 | No real community |
| 5-min volume / buys | filters.min_volume_m5_usd, min_buys_m5 | $3k, 20 | Dead tokens |
| Buy/sell ratio | filters.min_buy_sell_ratio_m5 | 0.8 | Everyone selling |
| 5-min price drop | filters.max_price_drop_m5_pct | 35% | Already dumping |
| Socials | filters.require_socials | off | No website/Twitter/Telegram |
| Buy price impact | filters.max_buy_price_impact_pct | 5% | Pool too small for your size |
| Round-trip test | filters.max_roundtrip_loss_pct | 12% | Can't sell (honeypot), hidden taxes |
Getting too few alerts? Loosen the market filters first (e.g. /set filters.min_holders 80, /set filters.min_liquidity_usd 10000). Getting junk? Tighten them. Leave the contract checks (authorities, extensions, LP lock, round-trip) on.
Going live (real money)
Paper trade long enough to have 30+ closed trades in /pnl. Paper results are optimistic: real trades compete with professional bots and fill worse, even though paper mode already deducts an extra 3% per trade. If paper isn't profitable, live won't be.
Create a dedicated bot wallet
Never use your main MetaMask/Phantom wallet or seed phrase. Create a fresh wallet just for the bot:
cd ~/projects/solsniper .venv/bin/python -m solsniper keygen
It creates secrets/bot-wallet.json (readable only by you) and prints the wallet's public address. The private key is never shown and never leaves the server.
Copy secrets/bot-wallet.json somewhere safe and offline (e.g. an encrypted USB drive). If the server dies without a backup, any funds in it are gone. Anyone who gets that file controls the funds.
Point the bot at the wallet
Add this line to .env, then restart:
SOLSNIPER_KEYPAIR=/home/mattbox/projects/solsniper/secrets/bot-wallet.json
sudo systemctl restart solsniper
/status in Telegram now shows the wallet address. It's still in paper mode.
Fund it with a small amount
From an exchange or your main wallet, send SOL to the bot's address. Start small, e.g. 0.5–1 SOL with buy_amount_sol at 0.05–0.1. Keep the reserve (0.05 SOL) for fees.
Switch to live
/set mode live confirm
The bot replies with the mode change. Alerts and buys now say [LIVE] and include Solscan transaction links. Paper positions keep being managed separately until they close.
Go back to paper anytime: /set mode paper.
Later: fully automatic buying
Once you trust the filters in live mode:
/set approval auto
The bot then buys every token that passes all checks, within your limits, and sends you a 🤖 AUTO-BUY notice each time. Your position limits, exposure cap and daily loss limit still apply. Switch back with /set approval manual.
Withdrawing profits
The bot wallet is a normal Solana wallet. To move SOL out, import secrets/bot-wallet.json into a wallet app (Phantom and Solflare can import a private key), or ask your assistant for a one-off withdraw command. Send /pause first and wait until no sells are in progress.
Shell commands
Everything you can do in Telegram also works from the server terminal, which is handy if Telegram is down. Run them from ~/projects/solsniper:
.venv/bin/python -m solsniper status .venv/bin/python -m solsniper positions .venv/bin/python -m solsniper pending .venv/bin/python -m solsniper approve 42 0.1 .venv/bin/python -m solsniper skip 42 .venv/bin/python -m solsniper sell 7 50 .venv/bin/python -m solsniper pause .venv/bin/python -m solsniper resume .venv/bin/python -m solsniper recent .venv/bin/python -m solsniper pnl .venv/bin/python -m solsniper check TOKEN_ADDRESS .venv/bin/python -m solsniper get exits.take_profit .venv/bin/python -m solsniper set budget.buy_amount_sol 0.05 .venv/bin/python -m solsniper unset budget.buy_amount_sol
approve, skip, sell, pause and resume are passed to the running bot, so the service must be running.
Tip: make a short alias
Add this to ~/.bashrc, then open a new terminal, and you can just type sniper status:
alias sniper='cd ~/projects/solsniper && .venv/bin/python -m solsniper'
Troubleshooting
I don't get any Telegram messages
- Check the service is running:
systemctl status solsniper. - Check the log for Telegram errors:
journalctl -u solsniper -n 100 | grep -i telegram. - Make sure
TELEGRAM_BOT_TOKENandTELEGRAM_CHAT_IDin.envhave no spaces or quotes, thensudo systemctl restart solsniper. - Make sure you pressed Start in your bot's chat at least once.
The bot runs but never sends candidates
That's normal for stretches of time: most new tokens fail the checks. Send /recent to see the reasons. If one rule rejects nearly everything (e.g. "only 90 holders (< 150)"), loosen that rule with /set.
Buttons say "expired"
Alerts are valid for 3 minutes. Make that longer with /set approval_timeout_sec 300. Remember the bot also cancels if the price pumped more than 25% since the alert.
"jupiter rate limited" in the log
You're on Jupiter's free tier without a key. Add a free JUPITER_API_KEY (Step 2) and restart. The bot retries automatically meanwhile.
Live buy failed / "confirmation timeout"
Fast tokens move; the swap may have exceeded slippage, or the network was congested. Check the Solscan link in the message. If tokens arrived anyway, the bot normally detects them. If a buy confirmed very late, compare /status with the wallet on Solscan. A paid RPC (SOLANA_RPC_URL) makes this much rarer.
The service keeps restarting after I set live mode
The bot refuses to start in live mode without a wallet key. Check that SOLSNIPER_KEYPAIR in .env points to the right file and that the file is readable only by you (chmod 600 secrets/bot-wallet.json). Or switch back: .venv/bin/python -m solsniper set mode paper.
I edited config.yaml but nothing changed
A Telegram /set for the same key overrides the file. Run /unset that.key. Also check the log for "invalid config": a typo in the file makes the bot keep the previous settings.
Start over with fresh paper results
sudo systemctl stop solsniper mv data/solsniper.db data/solsniper-old.db sudo systemctl start solsniper
This resets the paper balance and history. Your settings and wallet aren't touched.
Files & backups
| File | What it is | Back up? |
|---|---|---|
.env | Telegram token, chat ID, API keys, wallet path. | Yes (private) |
secrets/bot-wallet.json | The bot wallet's private key. | Yes, offline and encrypted |
config.yaml | Your settings. | Yes |
config.example.yaml | Every setting with explanations (defaults). | No |
data/overrides.yaml | Changes made with /set. | Optional |
data/solsniper.db | Every token evaluated (with full report), position and trade. | Optional |
README.md | Short technical reference. | No |
Never paste your wallet key or seed phrase into a chat, website or AI. Never share the Telegram bot token. Keep only what you can afford to lose in the bot wallet, and withdraw profits regularly.