<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel </title>
    <description>The latest articles on DEV Community by Daniel  (@alphar).</description>
    <link>https://dev.to/alphar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4006312%2F8e0dd674-4ff5-4b8d-9b20-0d8b86edd489.jpg</url>
      <title>DEV Community: Daniel </title>
      <link>https://dev.to/alphar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alphar"/>
    <language>en</language>
    <item>
      <title>I let an AI price my Solana bundle tips, and it stopped me overpaying on every pump dot fun snipe</title>
      <dc:creator>Daniel </dc:creator>
      <pubDate>Mon, 29 Jun 2026 10:33:43 +0000</pubDate>
      <link>https://dev.to/alphar/i-let-an-ai-price-my-solana-bundle-tips-and-it-stopped-me-overpaying-on-every-pump-dot-fun-snipe-4e90</link>
      <guid>https://dev.to/alphar/i-let-an-ai-price-my-solana-bundle-tips-and-it-stopped-me-overpaying-on-every-pump-dot-fun-snipe-4e90</guid>
      <description>&lt;p&gt;A token goes live on pump dot fun. You have one block, maybe two, before your price is gone. Everyone is racing into the same slot, and being first to click is not how you win.&lt;/p&gt;

&lt;p&gt;On Solana you land a transaction one of two ways. A priority fee jumps you up the line inside a block. A Jito bundle enters a sealed-bid auction where the validator picks the winners. Either way, the number that decides it is your tip.&lt;/p&gt;

&lt;p&gt;So you pick a tip. And here is the uncomfortable part. You are guessing.&lt;/p&gt;

&lt;p&gt;I learned it the hard way. My tip was a constant I copied from some tool months earlier, "usually enough" lamports, and a constant behaves badly in a market that is anything but. On quiet launches it torched SOL I never needed to spend. On a hot one, where a launch floods the queue and the clearing price jumps tenfold inside a single slot, "usually enough" was not. My bundle got skipped. I watched my entry fill at a worse price while my transaction sat there meaning nothing.&lt;/p&gt;

&lt;p&gt;That is the whole problem in a sentence. A snipe is a sealed-bid auction where the clearing price can move 10x in 400 milliseconds, and most of us bid a number we hardcoded and forgot.&lt;/p&gt;

&lt;p&gt;So I built Styx, a Rust SDK that watches the live auction, hands the evidence to an AI agent, and prices every bundle from what the market is doing right now. It tracks the full transaction lifecycle, retries on its own when a bundle drops, and explains every decision in plain English.&lt;/p&gt;

&lt;p&gt;Here is the short version of what it taught me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9st44q5vsp8tyc7dnx3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9st44q5vsp8tyc7dnx3d.png" alt="Arch. Diagram" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;IMAGE 1: Styx high-level architecture&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop reading summaries. Watch the auction.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Jito publishes tip percentiles over a REST endpoint, and most tools poll it and bid with these percentiles. It feels principled. It is not. That endpoint averages across recent slots, so it smooths out the exact spike you care about. By the time you read a percentile and build your submission, the slot has already turned over. You are acting on a market that no longer exists.&lt;/p&gt;

&lt;p&gt;My fix was simple: watch the auction directly. Every tip on Jito has to land in one of eight known accounts, so those eight accounts are basically the cash register of the whole auction. The trick is to watch them live. Yellowstone is a gRPC firehose that streams account changes off a validator the instant they happen, so if we subscribe to all eight through a Yellowstone account filter we might get something interesting: every balance increase is a real tip that just cleared, seen live instead of read back to us seconds late.&lt;/p&gt;

&lt;p&gt;I keep only the biggest tip in each slot, since that is the price the auction actually settled at, and roll the last 20 of them into a window. From that window I read a low, a middle, and a high, plus whether tips are heating up or cooling off. Then I label the mood. I call the buckets Cold, Warm, Hot, and Manic, and each one carries its own safety cushion on top of the bid. That label is all the agent needs to know what kind of room it just walked into.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The agent prices the bid&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agent gets a JSON snapshot of the window plus the last ten outcomes, and returns a multiplier from 0.1 to 10.0 with a written reason.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;tip = clearing_median * regime_safety * forward_multiplier&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is the readable part. The part that keeps you solvent is the cap. The baseline is floored at a minimum tip, and the result is capped by transaction type against a Jupiter quote of what the trade is worth: a snipe may spend up to 80 percent of expected value, an arb 60, a routine swap only 5, a memo is uncapped. So even a wild multiplier in a Manic regime cannot tip more than the trade is worth. Think of the multiplier as the agent's opinion and the cap as the seatbelt. The opinion can be wrong. The seatbelt does not let it cost you the trade.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fatkujoyhdocgfc6ri0y7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fatkujoyhdocgfc6ri0y7.png" alt="UI Image from testing" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three Solana lessons I did not expect&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The processed-to-confirmed gap is a free health check.&lt;/strong&gt;&lt;br&gt;
A transaction lands in two steps. First one validator processes it, then the network confirms it once a supermajority votes the block in. The gap between those two is a pulse reading. Healthy mainnet sits at 200 to 800 milliseconds. Past 1.5 seconds, something is wrong: a fork, slow votes, a slow block. That gap is sitting in your own timestamps, and reading it means your failures stop surprising you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Never fetch a blockhash at finalized commitment.&lt;/strong&gt;&lt;br&gt;
A blockhash is the freshness stamp on a transaction, and it lives about 150 slots, roughly 60 seconds. Solana lets you ask for chain data at different levels of certainty, and the safest one, finalized, lags the chain tip by 31 to 32 slots, about 13 seconds. So a blockhash you grab at that level is born already a fifth dead. Under congestion your retry can be holding a corpse. Use confirmed commitment everywhere time-sensitive, it is one or two slots back and leaves the whole window intact. Styx only touches finalized to stamp the final timestamp in the log.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: &lt;em&gt;A skipped Jito leader gives you nothing. If the scheduled leader skips, your bundle is silently dropped and &lt;code&gt;getBundleStatuses&lt;/code&gt; returns an empty array forever. No error, no code. The only honest detection is a timeout. Styx waits 60 seconds, then the classifier infers a Dropped if the blockhash is still alive but nothing confirmed. The agent reprices from the live window and usually escalates, because every bundle that missed that slot is about to pile into the next one with you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retries that the model actually owns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a bundle fails, the failure is classified first. ExpiredBlockhash, FeeTooLow, and Dropped go to the agent, which decides whether to retry, at what multiplier, and whether to refresh the hash. ComputeExceeded and hard bundle failures are terminal and never retried, since no amount of tip fixes a transaction that is broken on its face. On a FeeTooLow or Dropped retry, the reprice enforces at least the previous tip plus one, so you never resubmit at a number the network already refused. Retries cap at three. If the model says abort, it aborts.&lt;/p&gt;

&lt;p&gt;Lifecycle tracking runs two watchers in a race instead of polling &lt;code&gt;getSignatureStatus&lt;/code&gt;. A Yellowstone payer subscription fires the moment your signed transaction hits a processed slot, with an RPC poller as fallback. First to confirm wins, the other is killed. Yellowstone usually leads by 200 to 500 milliseconds, the exact margin that decides a retry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The stack, and one indulgence&lt;/strong&gt; 😊😊&lt;/p&gt;

&lt;p&gt;I created five crates in a Cargo workspace. &lt;code&gt;ingest&lt;/code&gt; owns the Yellowstone feed, &lt;code&gt;core&lt;/code&gt; owns the auction window and lifecycle and retry logic, &lt;code&gt;agent&lt;/code&gt; owns the LLM client and execution engine, &lt;code&gt;styx&lt;/code&gt; re-exports the public surface, and &lt;code&gt;demo&lt;/code&gt; is an Axum server with a WebSocket relay. Bundles fan out to four Jito regions at once, and Jupiter handles quotes and swaps.&lt;/p&gt;

&lt;p&gt;The choice I will defend forever: the SDK never touches your private key. You hand it a signing closure that takes unsigned transactions and returns signed ones. Key management stays yours alone.&lt;/p&gt;

&lt;p&gt;Then the indulgence. I did the whole UI in Rust, with Leptos, Trunk, and a little Tailwind, compiled to WASM and rendered straight in the browser. No React, no TypeScript, no npm tree the size of a small moon. I had never written a UI in Rust before and mostly wanted to see how far it would carry me before I missed JavaScript. The honest answer is I never did. Snipe engine to dashboard, one language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go break it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The repo has the SDK, the tip formula, the lifecycle stages, and the steps to run the demo and UI yourself. Spin it up, fire a bundle, and watch the agent talk through a live retry while the savings delta against the naive baseline climbs in real time. That is the moment tip pricing stopped feeling like a guess for me.&lt;/p&gt;

&lt;p&gt;Code and setup are on GitHub at &lt;a href="https://github.com/AlphaR2/styx.git" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I actually walked away with&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started this because I was curious of how jito tips works and how to land transactions smarter. What I ended up with was a different way of seeing the chain. The tip auction is not noise, it is a live price you can read. The processed-to-confirmed gap is not plumbing, it is a heartbeat. A silent drop is not a mystery, it is a signal once you know where to look. None of that needed an AI. The AI just turned the reading into a decision, every block, faster than I could.&lt;/p&gt;

&lt;p&gt;If you snipe, clone it, point it at your own wallet, and run a real session. Then tell me what your savings delta looks like against the dumb 2x baseline. That is the number I actually want to see, and it is the one that finally made me trust the thing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rust</category>
      <category>blockchain</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
