Skip to content

Repository files navigation

Multi-Wallet Command Center

A Telegram bot that drives many Solana wallets at once. Fund every wallet from one tap, paste a token address to get a full breakdown, buy or sell it across every wallet at once β€” and pull everything back to a main wallet when you're done.

Single-operator by design: only the Telegram user IDs in OWNER_IDS are answered at all. Everyone else gets silence, not an error.


What it does

Portfolio

  • SOL + SPL token balances for every wallet, with USD valuation and a grand total
  • Profit and loss per position, in SOL: what went in, what came back, what is still held. Buys record what the batch spent; sell proceeds are measured from the wallets' balances before and after, so the figure is what actually arrived, fees already deducted β€” not a quote taken before the fill
  • A designated main wallet, shown separately at the top
  • Open positions aggregated across all wallets, largest first

Token research β€” paste any contract address

  • Logo, name, price, 1h/24h change
  • Market cap, FDV, liquidity, 24h volume, buy/sell counts
  • Top holder distribution with the bonding curve and your own wallets labelled
  • pump.fun curve progress bar and graduation status
  • Who launched it and what they still hold β€” the pump.fun bonding curve names the creator wallet, so the card shows the dev's remaining stake and warns when it is over 5% of supply
  • Mint and freeze authority, stated either way on every card. An active freeze authority means the deployer can freeze your token account and stop you selling β€” no chart shows that coming. An active mint authority means supply can be created and sold into the pool. Both read straight off the mint account
  • Automatic risk warnings: holder concentration, thin liquidity, brand-new pairs, volume that looks like wash trading
  • Pasting a non-Solana address still returns a research card, labelled with the chain and venue it trades on β€” read-only, since the bot trades Solana
  • Works on tokens minutes old, before any indexer knows them, by reading Metaplex metadata and the bonding curve directly

Copy trading

  • Follow any Solana wallet. Three settings per wallet, each one tap:
  • Size β€” a fixed SOL amount per wallet (0.05), or a share of their trade (5%). Percent sizing reads the SOL that actually left their wallet, so a 10 SOL conviction buy and a 0.5 SOL nibble are copied at different sizes instead of being flattened to one number. 5% means the whole batch is 5% of their trade β€” not 5% multiplied by however many wallets you have running, and the per-wallet safety cap still binds
  • Entries β€” first buy only, or follow their DCA up to 3, 5 or 10 entries. A trader scaling in over twenty transactions must not be able to decide how much of your money goes into a token, so following in is always bounded
  • Follow them out β€” mirror the share they sell (they trim 10%, you trim 10%), exit fully on any sell (a trader trimming is often on the way out, and being seconds behind makes a partial follow the worst of both), or ignore their sells entirely
  • Your own exits β€” a take-profit (+20/50/100/200/500%) and a stop-loss (-30/50/70%), armed automatically on every position the wallet opens for you and measured from what you paid. This is the exit that does not depend on their timing: following someone out means selling seconds after they did, at whatever the price has become by then. Take-profit and stop-loss rules both exit 100% of the position
  • A token arriving is not a purchase. Anyone can send tokens to anyone, and dusting a wallet other people copy is a way of making those people buy something worthless β€” the recipient's balance rises exactly as it would after a trade. The SOL that left is the only thing telling the two apart, and the copy only fires when they spent at least 0.01 SOL. That floor is not arbitrary: a receipt costs its holder up to ~0.004 SOL in account rent and fees while buying nothing, measured on chain at wallets gaining nine million tokens for 0.004 SOL. It is also the smallest quick-buy this bot offers β€” if they spent less than the least you would ever choose to spend, it is not a signal worth paying for
  • Every copied buy is screened first. Copy trading is the only buy in this bot with no human in the loop β€” every other one is a deliberate tap on a screen already listing the warnings. Before money moves, a copied token is checked against every limit below, each one adjustable under Copy trading β†’ πŸ›‘ Safety (defaults shown):
    • top 10 wallets hold over 20% of supply. Vesting balances are displayed, but do not reduce concentration: a future stream end does not prove its tokens cannot already be claimed, or that its vault is a counted holder
    • the launch wallet still holds over 1%
    • the mint or freeze authority is still live, or a Token-2022 mint carries a transfer hook, transfer fee, permanent delegate, or live pause authority
    • wallets the index reads as one person (an allocation bundled out at creation) hold over 20%
    • the developer has minted more than 20 tokens, which reads as a factory rather than a launch, or has rugged a previous token before
    • the pool has under $3,000 of liquidity, once it has a pool at all
    • fewer than 5 distinct wallets traded it in the last five minutes
    • under $1,000 of volume in the last hour
    • the first market is older than 72 hours
    • the followed wallets already hold the coin, or copy trading has already put 0.5 SOL into this mint across every follower combined
  • These defaults are strict on purpose, and strict has a cost. Sampled against 14 tokens people were actively trading: 2 passed. Every rejection but one was concentration β€” top 10 at 21%, 25%, 29%, 42%, 51%, 78%. Raising the top-10 limit to 40% is the single tap that changes this most
  • Pasting a contract address gives a verdict, not just readings. The token card is judged against the same limits copy trading enforces, so the card and the gate can never disagree about the same token: it says passes your limits or names every check it fails
  • Token-2022 mints are checked for transfer traps. The two mint authorities are the whole story for a classic SPL token and only half of it here β€” that program lets a deployer attach behaviour to the mint itself. A transfer hook runs arbitrary code on every trade and can refuse yours; a transfer fee is the sell tax people associate with EVM honeypots; a permanent delegate can move tokens out of your wallet. A mint carrying any of these can show both authorities revoked and still be a trap, so they are refused regardless of what the authority setting says
  • A live freeze authority is the Solana honeypot. There is no sell tax or blacklist function here as there is on an EVM chain β€” a deployer who wants to trap holders freezes their token accounts, and a frozen account cannot transfer, so it cannot sell, and no chart shows it coming
  • Unknown counts as unsafe. A holder query the RPC rate-limited returns no concentration figure, and reading that as "concentration is fine" is how an unattended buyer walks into exactly the token the check exists to avoid. A token that could not be read is refused
  • A token is entered once and never again. Not after they sell it, not if they buy back in a week. copiedMints records that this wallet already got you into that token and nothing clears it
  • Following a wallet records where it is and starts from there. Their existing positions are never retroactively bought
  • Followed wallets are watched over the RPC websocket, not polled. Each of their transactions is pushed as it confirms β€” measured at about three seconds behind the chain against a Helius endpoint, against ten on average and twenty at worst when this was an interval timer. It also costs no requests at all: the poll was spending roughly 389,000 calls a month per followed wallet to learn nothing most of the time, which a free-tier key does not have
  • The poll still runs, as reconciliation rather than as the mechanism. A socket can drop, and a dropped socket nobody notices is a copy trader that silently stopped copying β€” so the sweep continues, finds almost everything already claimed, and catches whatever fell through a reconnect. Every path persists a target-scoped receipt before attempting a trade. Unreadable RPC receipts retry; a crash after the durable claim can miss a copy, and the bot favors avoiding repeated spending. Unknown history gaps pause the target
  • A wallet that floods is dropped rather than throttled. Subscribing to a program or an exchange wallet pushes hundreds of transactions a second, and a read per transaction buries the endpoint in rate-limit errors within one β€” measured, on the pump.fun program. Anything transacting faster than a person trades is unfollowed with an explanation, since its entries were never copyable anyway
  • The honest limitation: three seconds is still three seconds. This follows a trader; it does not race one. Sub-50ms needs a Geyser/gRPC stream at $99–499/month, which is a different kind of bot

If PumpPortal goes down

  • PumpPortal builds every transaction this bot sends, so its availability was a single point of failure β€” and the tokens with no fallback were exactly the fresh launches this bot exists to trade
  • Jupiter is now the fallback for everything, including tokens still on their bonding curve. That used to be excluded on the reasoning that a token existing nowhere but its curve has no aggregator behind it; true when written, and no longer β€” Jupiter integrated pump.fun and quotes those with Pump.fun as the route. Verified end to end: a live on-curve mint quoted, built into a 1212-byte swap, and simulated against a funded trader as executing in 135,309 compute units
  • PumpPortal is still tried first. Its transaction is 610 bytes against Jupiter's 1212 and runs in 117,817 compute units against 135,309 β€” the fallback is a fallback, not a preference

Speed

  • Every RPC request is cut off at 12 seconds and a timeout is never retried, so a stalled endpoint produces a readable error instead of a screen that never arrives
  • The holder-concentration query has a tighter 4-second deadline of its own. Providers throttle that index query harder than anything else a token card needs, and it is the one section the card can render without β€” the price, market cap and safety checks should not wait behind it

Fees and rent, so a position can always be closed

  • A wallet is only sent into a buy if it can afford the round trip. The requirement is the trade, its signature and priority fees, the ~0.00204 SOL rent that opening the token account costs, a bundle tip where one applies, and a reserve for the sell β€” two sells' worth, so one failed attempt does not strand the position. A 0.05 SOL buy therefore needs 0.0522 SOL in the wallet
  • A graduated token costs one more rent-exempt account. Past the bonding curve every venue is an SPL pool, so the buy has to wrap SOL: open a WSOL account, fund it, swap, close it again. The close refunds the rent, but the wallet still has to put it up β€” so a buy on PumpSwap or Raydium asks for 0.0543 SOL, not 0.0522
  • This is the mistake the check exists to prevent: fund fifty wallets with exactly 0.05 and buy 0.05, and every one of them either fails outright on the rent or fills and is then left holding a token it has no SOL left to sell
  • The funding screen states the real per-wallet figure, and the buy screen states it again alongside how many wallets fall short

Interface

  • Buttons are coloured, and the colour means one thing consistently: green spends or opens a position, red closes or destroys one, blue only reads. On a screen where buy and sell sit side by side, that is the difference the eye catches before the text
  • Numbers are written to be read at a glance. Market caps as magnitudes ($205.0M, not $205,048,692.00); memecoin prices with the zeros counted in a subscript ($0.0β‚…233, not 2.3300e-6) so the significant digits sit where the eye lands; a percentage move carrying its direction as both a sign and a colour, with a move that rounds to zero showing neither
  • Bars where a ratio is the question. Buy versus sell pressure, holder concentration, curve progress and batch fill rate are all shares of a whole, and a bar answers "which way is this leaning" before the digits do
  • A failed batch groups its failures by reason. Fifty wallets fail the same way; fifty identical error lines is one fact printed fifty times, and it pushes that fact off the screen
  • Screens that show live numbers carry a πŸ”„ Refresh and the time they were read. The clock is not decoration: a refresh landing on unchanged data would otherwise edit a message into itself, which Telegram rejects, making the tap look like a broken button

Positions

  • Every position shows the price you paid, the price now, and the move between them β€” averaged across every buy, so adding to a position blends the entry rather than replacing it
  • The entry price is derived from measured facts: the SOL that left the wallets and the tokens that arrived. A buy whose fill could not be measured reports no entry rather than a guess, because a stop-loss would otherwise fire against an invented number

Automation

  • Take profit, stop loss and trailing stops per position, checked every 20 seconds by a watcher that survives restarts β€” rules live on disk, so a redeploy cannot silently drop the stop you were relying on
  • A trailing stop tracks the high-water mark rather than your entry, so it works on a token you did not buy through the bot
  • Three rules the design turns on: an unreadable price never fires a rule (an RPC hiccup is not a price of zero), a rule fires once (marked before the sell is attempted, so a crash cannot replay it), and a locked vault pauses rather than fails β€” you get one message, not a stream of errors
  • Limit orders β€” buy the dip or sell into strength at a fixed price. Set as a percentage off the current price and stored as an absolute target, so it cannot drift with the market afterwards
  • DCA β€” average in with "0.05 30 6": 0.05 SOL per wallet, every 30 minutes, six rounds. Plans carry their remaining rounds and stop on their own; a failed round advances the schedule rather than bunching the buys together
  • Fresh pump.fun tokens are priced off the bonding curve, not an aggregator, so a stop-loss works from launch rather than from whenever an indexer catches up

Trading

  • Buy a preset or custom SOL amount from every wallet at once
  • Sell 25 / 50 / 75 / 100% from every wallet at once
  • Sell Everything β€” discovers every token held across every wallet and dumps it all
  • Routing is automatic: the bonding curve while it's live, the AMM once graduated, and Jupiter for anything pump.fun can't route at all β€” so a plain SPL token, an airdrop or a Raydium-only coin sells like everything else
  • Wallets holding none of the token are skipped, not failed β€” and neither are wallets that can't cover a buy. The confirmation screen says how many of them there are before you tap, rather than showing you a column of identical failures afterwards
  • Before you confirm a buy, it simulates the wallets buying in sequence and shows the true average fill, how far the batch moves the price, and what the first and last wallet each get for the same spend

Moving funds

  • Fund every wallet from the main wallet β€” send the same amount to each, or top every wallet up to a target and skip the ones already there. Transfers are packed into batched transactions, so 50 wallets cost 4 fees rather than 50
  • Sweep all SOL from every wallet into the main wallet, one tap
  • Sweep any SPL token, closing the emptied token accounts to reclaim their rent

Wallet management

  • Generate, import, or derive HD sets from one seed phrase (Phantom's standard path, so the wallets import cleanly elsewhere)
  • Label wallets, tag them into groups, and point batch operations at one group
  • Buy and sell buttons are editable in Settings, so the amounts on screen are the sizes you actually trade
  • Disable individual wallets to exclude them from batches
  • Export addresses as a file; export individual keys as self-destructing messages

Setup

1. Install

Use Node 22 or 24. The supported minimum for the project's TSX commands is Node 20.18.

npm ci

2. Configure

cp .env.example .env

Fill in three things at minimum:

Variable Where it comes from
BOT_TOKEN @BotFather β†’ /newbot
OWNER_IDS @userinfobot β†’ your numeric ID
SOLANA_RPC_URL Helius, QuickNode, or Triton β€” see the warning below

Jupiter requests use https://api.jup.ag. Optionally set JUPITER_API_KEY from the Jupiter Developer Platform for the keyed allowance. Quotes, swaps, prices and token metadata share one queue: requests start at least 2000 ms apart without a key, or 1000 ms apart with a key by default. Set JUPITER_REQUEST_INTERVAL_MS to match your plan; zero is intended for offline fixtures. Each request's timeout includes queue wait, so busy keyless batches can return unavailable prices or metadata, or fail to obtain a quote. Expired requests leave the queue without sending. JUPITER_API_BASE_URL accepts an HTTPS origin for an intentional gateway proxy; the key is sent only to that origin, and redirects are refused.

3. Run

npm start

4. Open it

Send /start in Telegram. There is nothing to set up: the vault is created on first boot and opens itself on every boot after that.

The RPC endpoint is not optional

Without SOLANA_RPC_URL the bot falls back to api.mainnet-beta.solana.com, and that endpoint does not work for this. It answers getHealth in ~40ms and then never replies at all to getMultipleAccounts β€” the call behind every balance, portfolio and position screen. Measured from a Railway container:

getHealth            41ms   ok
getMultipleAccounts  hangs  (aborted at 15s, three times running)

So the bot guards against it rather than trusting it: RPC requests are cut off at 12 seconds, a timeout is never retried, and the home screen says so in plain text while no private endpoint is set. You get an error you can read instead of a screen that never arrives β€” but you still get no data. Set the variable to a Helius, QuickNode or Triton endpoint; the free tiers are enough to run this.


Deploying to Railway

The bot is a worker, not a web service β€” it long-polls Telegram and never listens on a port. Railway runs it fine, but three settings are not optional.

1. Nothing to configure for the build. package.json sits at the repo root, so Railway detects a Node app and runs npm start on its own. (It previously lived in a tg bot/ subdirectory, which made Railpack fail with "could not determine how to build the app" β€” that is why the layout is flat.)

2. A volume β€” do this before you create any wallets. Container storage is erased on every redeploy. The encrypted vault is the only copy of your private keys, so losing it makes every wallet permanently unspendable.

  • Add a Volume to the service, mount path /data
  • Set DATA_DIR=/data in Variables

The bot checks this at boot and prints a loud warning if the wallet files are sitting on disposable storage, but it cannot recover keys already lost.

3. One replica. Telegram allows a single polling connection per bot token; two replicas fight over it and the bot flaps with 409 errors. railway.json pins numReplicas: 1 β€” leave it there, and leave app sleeping off, since a sleeping bot stops receiving messages.

Variables to set

Variable Value
BOT_TOKEN from @BotFather
OWNER_IDS your numeric ID from @userinfobot
SOLANA_RPC_URL your Helius / QuickNode endpoint
DATA_DIR /data β€” must match the volume mount path

Once deployed, open your bot in Telegram and send /start. Nothing to unlock β€” the vault comes up with the container.


⚠️ Use a private Solana RPC

The public endpoint (api.mainnet-beta.solana.com) rate-limits aggressively. During testing it rejected getTokenLargestAccounts outright, so holder distribution silently disappears β€” the bot flags this as "unknown" rather than implying a token is safe, but you're flying blind. Batch operations across more than a handful of wallets will also fail.

A free Helius or QuickNode key fixes it. This is the single highest-impact thing you can configure.


Security model

Concern How it's handled
Keys at rest AES-256-GCM, one random IV per secret. Tampering fails loudly.
Master key Random 32 bytes in data/vault.key at 0600, held in one closure, zeroed on shutdown
Secrets in chat Private keys and seed phrases are deleted from the chat on receipt; exports self-destruct after 60s
Logs A redaction filter strips anything shaped like a private key before it's written
Access Only owner updates in private chats are accepted; group and channel updates are dropped
Destructive actions Every write operation requires a second confirming tap

What this does not protect against: anyone who can read the data directory. The key that decrypts the wallets sits in it, so a copy of the volume is a copy of the wallets. This is a deliberate trade β€” a passphrase that had to be re-typed after every container restart was worse than useless, and a bot that cannot open its own vault cannot run a stop-loss while you sleep. Encryption at rest here defends a leaked wallets.json, a backup that went somewhere it shouldn't, and nothing beyond that. Run it somewhere you control, and don't put more in these wallets than you are trading.

Back up data/vault.json, data/wallets.json and data/vault.key together. Any one of them is useless without the others, and there is no recovery path if the key file is lost.

Starting over

Settings β†’ 🧨 Factory reset deletes the vault, every private key, the seed phrase, every label and group, and the trade history β€” then drops back to the first-run state so /start builds a new vault from scratch.

Before it does anything it shows you what you are about to destroy, including the live SOL balance held across those wallets, because that is the one fact that should stop a reset that is about to burn real money. Sweep or export first. Confirming means typing RESET EVERYTHING exactly β€” a button is too easy to press by accident.

A reset creates the replacement vault immediately, so the bot is usable again the moment it finishes β€” there is nothing to set up and nothing to remember.

Wallets from the multi-chain version

This bot handled EVM chains before it became Solana-only, and a wallets.json written back then still carries those records. They are kept, not deleted β€” the addresses may still hold funds. Nothing here can sign with one, so they are hidden from every screen except Settings β†’ πŸ“¦ Export legacy keys, which only appears when there are any. From there you can download the private keys as a file, import them wherever they belong, and then delete them for good.

A factory reset takes them too, and says so before it does.


Safety rails

Set in .env:

  • MAX_BUY_SOL_PER_WALLET β€” hard ceiling on any single buy, per wallet. Multiplied across 50 wallets, a fat-fingered amount gets expensive fast.
  • REQUIRE_CONFIRMATION β€” second tap before anything that spends or moves funds.
  • sweepReserveSol (in Settings) β€” SOL left behind in each wallet so it can still pay fees after a sweep. The main wallet keeps the same amount back when funding, so a distribution can't drain it to the point where it cannot pay for its own next transaction.

Funding refuses outright if the main wallet cannot cover the whole plan, rather than half-funding the set and leaving you to work out which wallets missed.


Execution modes

parallel (default) β€” each wallet's transaction is sent independently with bounded concurrency. One wallet failing costs you nothing on the others. Fills land over a few seconds at slightly different prices.

bundle β€” wallets are grouped 5 at a time into Jito bundles. Each group is atomic: all five land in the same block, or none do. Use this when entry price matters. Costs a Jito tip per bundle, and a bundle that doesn't get picked up fails as a unit.

Toggle it in Settings, or set DEFAULT_EXECUTION_MODE.

Priority fees

A fixed priority fee is wrong twice over: too low when the chain is busy, which is exactly when an entry is worth landing, and wasteful when it is quiet.

In auto mode (the default) the bot samples what recent blocks actually paid to touch the pump.fun program and bids the 75th percentile of that, times 1.25. The median gets outbid in the moments that matter; the maximum is one desperate bidder rather than the going rate.

Your configured priorityFeeSol becomes the floor β€” auto mode only ever raises the bid β€” and priorityFeeCeilingSol caps it so a congestion spike cannot run away with the balance. If the fee market cannot be sampled, your configured value stands.

Measured while building this: the network wanted 838,139 microLamports/CU for the pump.fun program, which is 0.00026 SOL β€” over 5Γ— the old fixed default of 0.00005. Trades at the fixed rate were bidding well under the going rate.


A note on batch buying

Buying the same token from many wallets walks the bonding curve. The tenth wallet does not get the first wallet's price.

The bot simulates this before you confirm and shows the real aggregate: 10 wallets Γ— 0.5 SOL into a fresh curve moves the price +35.7%, the average fill lands +17.7% above the price on screen, and the first wallet receives 17.4M tokens where the last receives 13.2M for the identical 0.5 SOL. Those numbers are on the confirmation screen for a reason β€” read them before tapping. Past +25% the screen says so in bold.


Verification

npm run check

Runs offline checks, also enforced on pull requests by GitHub Actions:

  • typecheck β€” full TypeScript strict-mode pass
  • smoke β€” the existing offline suite: vault crypto (round-trip, unique IVs, tamper rejection, dropping a passphrase without losing a key, a key file that is wrong or missing being refused loudly, and a vault that opens itself at boot), wallet derivation, group and main-wallet invariants, bonding curve maths and batch simulation, funding arithmetic (shortfall-only top-ups, transaction packing, refusing a plan the main wallet can't afford, skipping wallets that cannot cover a buy), token account parsing, P&L arithmetic (banked profit, a position worth zero, and no divide-by-zero without a cost basis), factory reset (files removed from disk, fresh setup possible afterwards), legacy wallet records (hidden from trading, preserved across unrelated writes, exportable, deleted only on request), copy-trade sizing and the screens that configure it (driven through a stub context, so a screen that throws while building its text is caught here rather than in Telegram), a check that every button the keyboards emit reaches a route β€” a dead button looks exactly like a slow one β€” address parsing, concurrency helpers, log redaction
  • regressions β€” mocked transaction responses, automation failures, vault migration write failures, private-chat access, expiring and changed-context confirmations, incomplete portfolio reads, copy-event retries and restart receipts, cancellation during a transaction build, partial-sale cost basis, Token-2022 safety, builder message validation, and ambiguous history repair. These tests never contact Telegram or an RPC.

Run npm run check:live to add the network checks, or run them individually:

  • netcheck β€” live read-only checks against Solana RPC, DexScreener, Jupiter, PumpPortal and the pump.fun program, including that Jupiter can still route a token on its bonding curve β€” a fallback nobody verifies is a fallback that fails the first time it is needed
  • batchsim β€” the dry run for the path that spends money. Builds and signs a real trade for N wallets and simulates each against mainnet instead of sending it: routing, instruction layout, account resolution, signing, transaction size against the 1232-byte packet limit, and per-wallet timing. Empty wallets all fail as "account missing", which proves the transaction is well-formed and nothing more β€” so it also builds the same trade for a wallet that has recently traded the token and simulates that, which answers whether it would actually execute. sigVerify: false means no signature is needed and nothing is broadcast; it reads a public balance and asks the chain a hypothetical

netcheck never signs or broadcasts anything. It builds unsigned transactions for a throwaway public key purely to confirm the request shape still matches, and throws them away.

Run netcheck after any upstream outage or unexpected trade failure β€” it will tell you which dependency moved.


Commands

Command Effect
/start Main menu
/portfolio Balances across every wallet
/positions Open positions and P&L
/wallets Wallet management
/copy Copy trading
/funds Fund wallets or sweep back
/settings Slippage, fees, presets
/history Recent batch operations
/help Command list

Every command also appears behind the Menu button beside the message box β€” Telegram builds that from the bot's registered command list.

Everything else is inline buttons. Pasting a token address is the main entry point.


Layout

src/
  config.ts            env parsing, endpoints
  chains/
    solana.ts          balances, transfers, sweeps, confirmation polling
  store/
    vault.ts           scrypt + AES-256-GCM keystore
    wallets.ts         registry, HD derivation, the encryption boundary
    db.ts              atomic JSON persistence
  trade/
    pumpportal.ts      builds pump.fun transactions, signs them locally
    jito.ts            bundle submission and status polling
    curve.ts           bonding curve reads, quotes, batch simulation
    jupiter.ts         aggregator swaps for graduated and general SPL
    fund.ts            distribution: main wallet β†’ every trading wallet
    engine.ts          batch execution across wallets
  services/
    tokeninfo.ts       the token card: market data, holders, warnings
    metadata.ts        Metaplex metadata for un-indexed tokens
    portfolio.ts       cross-wallet, cross-chain aggregation
    prices.ts          cached USD pricing
    pnl.ts             cost basis and profit/loss, denominated in SOL
    price.ts           price in SOL: bonding curve first, aggregator second
    watcher.ts         the loop behind take-profit, stop-loss and trailing stops
    copytrade.ts       mirroring another wallet's entries and exits
    mintauth.ts        mint + freeze authority, the two Solana rug vectors
  bot/                 Telegram layer: routing, screens, session state

On pump.fun execution

Transactions are built by PumpPortal's local API and signed here, with keys that never leave the process. Signing authorizes the entire returned message. Before signing, the bot checks the sole signer and payer, compute fee ceiling, recognized venue envelope, and permitted direct SOL/token setup instructions. Jupiter quotes are also bound to the requested mints, amount, slippage and mode.

These checks do not decode every swap account or CPI debit. PumpPortal currently uses an opaque wrapper with no published IDL found in this review; that program and both builders remain trust dependencies for complete swap intent. Unknown programs and unresolved lookup-table program or direct-debit accounts are refused. See the deeper review for evidence and remaining work.

Quoting is done independently by reading the bonding curve directly, so the price on screen is the real on-chain price rather than whatever an API reports.

License

This project is released under a custom Profit-Sharing License. Commercial use is permitted, but requires paying 1% of net profits generated from the Software to the creator, in SOL, to:

FQ19UgyuQtwq8RE6FCYrJ8BxUTY4B4DkggngxcUB493S

See LICENSE.md for full terms.

About

Single-operator Telegram command center for funding, monitoring, trading, copy-trading, and sweeping across fleets of Solana wallets.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages