<?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: Miles</title>
    <description>The latest articles on DEV Community by Miles (@btcmiles).</description>
    <link>https://dev.to/btcmiles</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3075865%2F24758825-128f-4a6f-b288-069f3ab29a83.jpeg</url>
      <title>DEV Community: Miles</title>
      <link>https://dev.to/btcmiles</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/btcmiles"/>
    <language>en</language>
    <item>
      <title>python异步请求：一开始写的代码是直接加了async，结果两个函数的请求仍是同步的，单个请求耗时0.3s，两个耗时0.7s。后经调研，发现，需要使用aiohttp请求，才可以实现真正的异步。优化后，总耗时0.4-0.5s左右。</title>
      <dc:creator>Miles</dc:creator>
      <pubDate>Tue, 29 Apr 2025 13:33:50 +0000</pubDate>
      <link>https://dev.to/btcmiles/-1670</link>
      <guid>https://dev.to/btcmiles/-1670</guid>
      <description></description>
      <category>python</category>
      <category>asyncio</category>
      <category>performance</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Types of Quantitative Trading on Solana</title>
      <dc:creator>Miles</dc:creator>
      <pubDate>Wed, 23 Apr 2025 15:39:52 +0000</pubDate>
      <link>https://dev.to/btcmiles/types-of-quantitative-trading-on-solana-iah</link>
      <guid>https://dev.to/btcmiles/types-of-quantitative-trading-on-solana-iah</guid>
      <description>&lt;p&gt;Quantitative trading on Solana generally falls into two categories: &lt;strong&gt;Atomic Arbitrage&lt;/strong&gt; and &lt;strong&gt;Looping Arbitrage (Leverage Arbitrage).&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Atomic Arbitrage&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Leverages Solana’s parallel processing and low-latency features to perform both buy and sell operations within a single transaction (typically a transaction bundle).&lt;/li&gt;
&lt;li&gt;Ensures &lt;strong&gt;atomicity&lt;/strong&gt;, meaning the transaction either fully succeeds or fully fails—no partial execution—thus avoiding risks from price fluctuations in between.&lt;/li&gt;
&lt;li&gt;Commonly used for arbitrage between DEXs such as &lt;strong&gt;Orca, Raydium, and Jupiter&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Looping Arbitrage / Leverage Arbitrage&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stake SOL on a protocol for a 12% annual return.&lt;/li&gt;
&lt;li&gt;Use the staking certificate as collateral to borrow USDC at a 10% annual cost.&lt;/li&gt;
&lt;li&gt;Swap the borrowed USDC back into SOL to stake again…&lt;/li&gt;
&lt;li&gt;By repeating this cycle, you effectively &lt;strong&gt;leverage&lt;/strong&gt; your initial capital to amplify the yield spread.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Let's Start with Basic Arbitrage on Solana
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fhzol2ozus46pi1tn7840.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.amazonaws.com%2Fuploads%2Farticles%2Fhzol2ozus46pi1tn7840.png" alt="Image description" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Logic of On-chain Arbitrage
&lt;/h3&gt;

&lt;p&gt;On-chain arbitrage exploits &lt;strong&gt;price differences of the same token across different liquidity pools (LPs).&lt;/strong&gt; For example, if one pool's price fluctuates sharply due to a trade while another lags behind, an arbitrage opportunity arises.&lt;/p&gt;

&lt;p&gt;This often occurs with common tokens like &lt;strong&gt;wSOL, USDC, and USDT&lt;/strong&gt; across various AMMs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Arbitrage Flow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Monitor price changes / arbitrage opportunities.&lt;/li&gt;
&lt;li&gt;Calculate whether a positive profit exists.&lt;/li&gt;
&lt;li&gt;Construct the transaction (usually as an atomic transaction).&lt;/li&gt;
&lt;li&gt;Bundle and execute the transaction on-chain.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Getting the Best Quotes with Jupiter and Jito
&lt;/h3&gt;

&lt;p&gt;To ensure the optimal arbitrage path and maximum profit, most strategies combine &lt;strong&gt;Jupiter&lt;/strong&gt; (Jup) and &lt;strong&gt;Jito&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  How it works:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Use Jupiter to get quotes for two reverse trades (e.g., A → B → A).&lt;/li&gt;
&lt;li&gt;Calculate potential profit based on the price difference.&lt;/li&gt;
&lt;li&gt;Merge both trades into a single atomic transaction and simulate it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Jito&lt;/strong&gt; allows you to submit bundled transactions and simulate them before sending on-chain. Failed simulations incur no cost.&lt;/p&gt;

&lt;p&gt;⚠️ Note: &lt;strong&gt;Frequent API calls to Jito can trigger rate-limiting (like DDoS protection).&lt;/strong&gt; In quantitative deployment, it's crucial to design a rate control strategy—which we’ll cover later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Optimization Strategies
&lt;/h2&gt;

&lt;p&gt;To increase the success rate and profitability of arbitrage, consider optimizing in these areas:&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Flash Loans
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Amplify returns with borrowed capital.&lt;/li&gt;
&lt;li&gt;Because of atomicity, borrowing and repaying happen within a single transaction—&lt;strong&gt;no risk or cost if the transaction fails.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Optimize Compute Unit (CU) Usage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Solana limits CU per transaction.&lt;/li&gt;
&lt;li&gt;Lower CU consumption increases the chance of successful execution—especially in high-concurrency environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Custom Quote &amp;amp; Routing Logic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Jupiter API requests can be slow.&lt;/li&gt;
&lt;li&gt;Implementing your own quoting algorithm and pathfinding logic can dramatically improve speed and increase arbitrage success.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Faster RPC Node Responses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use high-performance RPC nodes (e.g., private or optimized nodes) to avoid frontrunning and reduce latency.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Top Arbitrageurs Don't Use Jupiter
&lt;/h2&gt;

&lt;p&gt;Many users rely on &lt;strong&gt;Jupiter Aggregator&lt;/strong&gt; for optimal swap paths across DEXs, but &lt;strong&gt;serious atomic arbitrageurs avoid it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Atomic arbitrage involves executing all operations within a single atomic transaction, which demands high speed and priority. Professionals typically build their own paths and custom transaction bundles to achieve &lt;strong&gt;higher frequency and lower latency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, &lt;strong&gt;Wintermute&lt;/strong&gt;, a leading market maker, sends hundreds of arbitrage transactions per minute. Jupiter isn’t fast or flexible enough for this kind of high-frequency trading.&lt;/p&gt;

&lt;p&gt;However, Solana has some randomness—like congestion, dropped requests, and competition in transaction ordering—so even Wintermute doesn’t always win.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;This randomness creates opportunities for individual developers&lt;/strong&gt;: with smart strategy design, fast bundling, and high-performance RPC nodes, it's still possible to win arbitrage opportunities.&lt;/p&gt;




&lt;h2&gt;
  
  
  On-chain Speedups
&lt;/h2&gt;

&lt;p&gt;Refer to the &lt;a href="https://docs.solanamevbot.com/home/jupiter-bot/bot-configurations#spam" rel="noopener noreferrer"&gt;Mevbot Docs&lt;/a&gt; for mainstream on-chain providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bloxroute.com/" rel="noopener noreferrer"&gt;Bloxroute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://temporal.io/" rel="noopener noreferrer"&gt;Temporal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pros &amp;amp; Cons of Using Jito
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Supports atomic bundles&lt;/strong&gt;: Ensures either full success or failure; even failed transactions cost nothing—ideal for arbitrage and high-frequency strategies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High validator coverage&lt;/strong&gt;: Jito is widely adopted, meaning submitted transactions have higher chances of inclusion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strict TPS Limits&lt;/strong&gt;: Officially supports 5 TPS per IP, but real-world rates may drop to 1 TPS/IP under heavy load. Each IP is limited to 50 requests/minute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signer throttling&lt;/strong&gt;: TPS limits also apply to the &lt;strong&gt;wallet address&lt;/strong&gt;, so changing IPs alone doesn’t help.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Occasional outages&lt;/strong&gt;: Jito, acting as a middle layer, can sometimes go down—crippling bundle submissions and arbitrage strategies.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Multi-path Transaction Optimization
&lt;/h2&gt;

&lt;p&gt;To maximize transaction success, bots often &lt;strong&gt;broadcast the same transaction to multiple relayers&lt;/strong&gt; (e.g., Jito and non-Jito validators). This strategy is known as &lt;strong&gt;multi-relay submission&lt;/strong&gt; or &lt;strong&gt;multi-path broadcasting&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It helps prevent failures due to single-path congestion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Role of Nonce Accounts
&lt;/h2&gt;

&lt;p&gt;Solana uses recent_blockhash and nonce to prevent replay attacks.&lt;/p&gt;

&lt;p&gt;If you send &lt;strong&gt;identical transactions&lt;/strong&gt; to different relayers, the network may reject them as duplicates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution: Use a &lt;strong&gt;Nonce Account&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With deterministic nonce accounts, even if transaction contents differ slightly (e.g., different tips), the system will accept them as distinct transactions with the &lt;strong&gt;same nonce sequence&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Jupiter's "Both" Mode (Advanced Users)
&lt;/h2&gt;

&lt;p&gt;Jupiter's advanced setting "Both" mode allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simultaneous submission to &lt;strong&gt;Jito Relay&lt;/strong&gt; and &lt;strong&gt;standard validators&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Jupiter auto-generates multiple versions (e.g., Jito tip + regular tip)&lt;/li&gt;
&lt;li&gt;Users sign multiple versions (usually 2) for simultaneous submission&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Full Process:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create and initialize a Nonce Account.&lt;/li&gt;
&lt;li&gt;Build transaction logic (e.g., SOL → USDC swap).&lt;/li&gt;
&lt;li&gt;Generate two versions using the same nonce.&lt;/li&gt;
&lt;li&gt;Sign and send them to Jito and standard relayers.&lt;/li&gt;
&lt;li&gt;Only one will succeed; the other auto-invalidates due to nonce usage.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Strategic Advice:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use Nonce Account to manage atomic multi-path transactions.&lt;/li&gt;
&lt;li&gt;Set appropriate &lt;strong&gt;priority fees and tips&lt;/strong&gt; for each provider.&lt;/li&gt;
&lt;li&gt;Monitor slot/status to stop broadcasting after confirmation.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;high-performance RPC nodes&lt;/strong&gt; and &lt;strong&gt;multi-IP dispatching&lt;/strong&gt; to improve performance and reliability.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Reducing CU Consumption
&lt;/h2&gt;

&lt;p&gt;On Solana, if a transaction's CU cost is very low (e.g., a simple transfer = 300 CU), it can often be included &lt;strong&gt;without tips&lt;/strong&gt;, thanks to the &lt;strong&gt;block "backpack algorithm"&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solana fills each block with high-priority, low-CU transactions first.&lt;/li&gt;
&lt;li&gt;If your CU is tiny, it’s more likely to be included quickly "as a bonus".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The smaller your CU, the faster your transaction gets in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Role of Smart Contracts in Arbitrage
&lt;/h2&gt;

&lt;p&gt;To win the PVP arbitrage race, writing your own smart contract is essential.&lt;/p&gt;

&lt;p&gt;On Solana, bypassing aggregators like Jupiter requires &lt;strong&gt;custom smart contracts&lt;/strong&gt; to handle the entire arbitrage logic.&lt;/p&gt;

&lt;p&gt;Key roles of smart contracts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Profit Checking and Execution Filtering&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Check token balances before/after execution.&lt;/li&gt;
&lt;li&gt;Calculate profits and determine if they exceed a threshold.&lt;/li&gt;
&lt;li&gt;Revert the entire transaction if not profitable—enforcing the "don’t execute unless profitable" rule.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Multi-hop Arbitrage Execution&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example:&lt;br&gt;&lt;br&gt;
   &lt;code&gt;SOL → LAYER → BONK → SOL&lt;/code&gt; (3-hop path)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each step depends on the previous swap’s output.&lt;/li&gt;
&lt;li&gt;Smart contracts can encode these steps as &lt;strong&gt;multiple instructions&lt;/strong&gt; in one transaction.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  2. Multi-Hop Execution (Multi-Hop, Multi-Instructions)
&lt;/h3&gt;

&lt;p&gt;For example, to perform an arbitrage round:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SOL → LAYER → BONK → SOL&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is a 3-hop arbitrage path, where each step depends on the swap output from the previous one.&lt;/p&gt;

&lt;p&gt;In a smart contract, you can write each swap as a separate &lt;em&gt;instruction&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
This requires executing multiple swap instructions &lt;em&gt;sequentially&lt;/em&gt; within a single transaction.&lt;br&gt;&lt;br&gt;
The key challenge: each step needs to read the output from the previous swap (e.g., the amount of tokens received).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction content:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instruction 1: Swap SOL for LAYER (e.g., using Orca)
&lt;/li&gt;
&lt;li&gt;Instruction 2: Swap LAYER back to SOL (e.g., using Raydium)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In-contract flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After Instruction 1, the contract reads the change in LAYER balance (e.g., receives 500 LAYER)
&lt;/li&gt;
&lt;li&gt;Instruction 2 depends on the &lt;em&gt;actual&lt;/em&gt; amount of 500 LAYER before proceeding
&lt;/li&gt;
&lt;li&gt;Finally, compare the resulting SOL with the initial input + target profit
&lt;/li&gt;
&lt;li&gt;If the profit goal isn't met, the whole transaction is reverted to maintain atomicity&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Popular Solana Smart Contract Frameworks and Their Characteristics
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1️⃣ Anchor – The Go-To for Ecosystem Standardization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comes with built-in IDL (Interface Definition Language) and Events, making frontend integration easier
&lt;/li&gt;
&lt;li&gt;Great compatibility with ecosystem projects like Jupiter, Jito, and Meteora
&lt;/li&gt;
&lt;li&gt;Development experience is similar to Ethereum's Hardhat/Foundry, making it beginner-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compiled contracts are larger, with higher CU and rent costs
&lt;/li&gt;
&lt;li&gt;Not suitable for performance-critical arbitrage contracts&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  2️⃣ Native &lt;code&gt;solana-program&lt;/code&gt; (Rust SDK)
&lt;/h3&gt;

&lt;p&gt;The most mainstream choice in the community and officially supported&lt;br&gt;&lt;br&gt;
Offers fine-grained control over accounts, compute units (CU), and execution logic&lt;br&gt;&lt;br&gt;
Doesn’t heavily rely on macros or runtime, making it ideal for &lt;strong&gt;lightweight, high-frequency arbitrage contracts&lt;/strong&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  3️⃣ &lt;code&gt;cavemanloverboy/solana-nostd-entrypoint&lt;/code&gt; – Maximum Optimization
&lt;/h3&gt;

&lt;p&gt;Created by core Temporal members (Jito/ITO providers)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses Rust’s &lt;code&gt;#![no_std]&lt;/code&gt; mode to fully control memory and logic without the standard library
&lt;/li&gt;
&lt;li&gt;No heap allocator or logs; extremely efficient execution
&lt;/li&gt;
&lt;li&gt;Minimal CU usage – perfect for arbitrage contracts targeting the smallest possible block size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very steep learning curve
&lt;/li&gt;
&lt;li&gt;Requires embedded development experience (e.g., using &lt;code&gt;unsafe&lt;/code&gt;, C-style thinking)
&lt;/li&gt;
&lt;li&gt;High debugging costs and much worse dev experience compared to Anchor&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  4️⃣ Pinocchio – Official &lt;code&gt;no_std&lt;/code&gt; Contract Framework
&lt;/h3&gt;

&lt;p&gt;Repo: &lt;code&gt;anza-xyz/pinocchio&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Developed by &lt;strong&gt;Agave&lt;/strong&gt; (a new company from Solana Labs)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write Solana contracts in &lt;strong&gt;C&lt;/strong&gt; to avoid Rust’s compile-time overhead
&lt;/li&gt;
&lt;li&gt;Huge room for optimization
&lt;/li&gt;
&lt;li&gt;Official goal: ultra-small, highly-efficient contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;no_std&lt;/code&gt; and ultra-minimalist
&lt;/li&gt;
&lt;li&gt;Closer to system-level contract style
&lt;/li&gt;
&lt;li&gt;Still lacks detailed documentation and has a steep learning curve&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Code Example: Reading Token Balance Changes in Contracts
&lt;/h3&gt;

&lt;p&gt;This snippet is a typical method in Solana smart contracts for manually reading an SPL Token account's balance to determine profit before and after a transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;token_amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_le_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="py"&gt;.data&lt;/span&gt;
        &lt;span class="nf"&gt;.borrow&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;program_error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;line!&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why parse balances manually?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Unlike Ethereum, Solana doesn't provide a built-in "balanceOf" style function. You must manually extract the balance field from an account’s binary &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In SPL Token accounts, the balance starts at &lt;strong&gt;byte offset 64&lt;/strong&gt;, stored as a little-endian &lt;code&gt;u64&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;account.data[64..72]&lt;/code&gt; = balance field (8 bytes)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Code Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;accounts[0].data.borrow()&lt;/code&gt; → borrow the account's data buffer
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[64..72]&lt;/code&gt; → locate the balance bytes
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.try_into()&lt;/code&gt; → convert 8 bytes to &lt;code&gt;[u8; 8]&lt;/code&gt; for parsing
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;u64::from_le_bytes(...)&lt;/code&gt; → interpret as a u64 little-endian value&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Tool Recommendation: Anchor 8byte Database
&lt;/h3&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/666pulse/solana-discriminator" rel="noopener noreferrer"&gt;https://github.com/666pulse/solana-discriminator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is 8byte?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
In Anchor, each function call is routed using an 8-byte selector.&lt;br&gt;&lt;br&gt;
In EVM (Ethereum), this is similar to the 4-byte function selector (e.g., &lt;code&gt;0xa9059cbb&lt;/code&gt; = &lt;code&gt;transfer(address,uint256)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does the 8byte database do?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It allows reverse-engineering of function signatures from bytecode to identify whether a contract matches known open-source projects.&lt;/p&gt;

&lt;p&gt;This is especially useful when a contract isn’t verified on explorers—just analyze its 8-byte selectors.&lt;/p&gt;


&lt;h3&gt;
  
  
  Meteora – LP Market Making Arbitrage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lower Protocol Fees = Higher LP Yields&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Compared to other DEXs, Meteora charges lower protocol fees for LPs, resulting in higher actual returns for the same liquidity strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Airdrop Incentives = Additional Expected Yield&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Meteora offers a long-term points system: providing LP, trading, or mining earns points that are expected to be used for future airdrops.&lt;br&gt;&lt;br&gt;
Even with thin arbitrage margins, these points can boost your total yield.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer-Friendly Contracts with Anchor&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Built with Anchor: standardized IDL, clear function calls, standardized events&lt;br&gt;&lt;br&gt;
Perfect for LP strategy or arbitrage bot developers—low integration cost, easy debugging, and well-documented&lt;/p&gt;


&lt;h3&gt;
  
  
  Useful RPC Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;getTokenLargestAccounts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Purpose:&lt;/em&gt; View the top 20 largest holders of a given SPL Token  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;getLeaderSchedule&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Purpose:&lt;/em&gt; Query the block production schedule for validators in a specific epoch  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;getProgramAccounts&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Purpose:&lt;/em&gt; Query all accounts related to a program (e.g., pools, LP positions, reward accounts)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Querying Your LP Position via &lt;code&gt;getProgramAccounts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To find your LP position in a specific pool, use &lt;code&gt;memcmp&lt;/code&gt; filters. Solana contract data is serialized with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;discriminator (8 bytes) + pool address + user address&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Example Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;my_position_bytes_prefix&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_position_bytes_prefix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;PositionV2Discriminator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_position_bytes_prefix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;pool_addr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_position_bytes_prefix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;40&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;72&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;myaddr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;my_positions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;helius&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetProgramAccountsWithOpts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DImmProgram&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetProgramAccountsOpts&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Commitment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommitmentConfirmed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Filters&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RPCFilter&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Memcmp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RPCFilterMemcmp&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;my_position_bytes_prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query all your LP positions across multiple pools
&lt;/li&gt;
&lt;li&gt;Display staking/mining positions on frontend
&lt;/li&gt;
&lt;li&gt;Identify unclaimed rewards for automated arbitrage&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Real-Time Pool Trade Tracking via gRPC: Overbought/Oversold Analysis
&lt;/h3&gt;

&lt;p&gt;Use gRPC to subscribe to DEX pool trades and evaluate market sentiment in real-time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calculate Overbought/Oversold Indicators&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Similar to RSI, OBV, or MACD in traditional finance.&lt;/p&gt;

&lt;p&gt;Example (within 1 minute):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Side&lt;/th&gt;
&lt;th&gt;Amount (USDC)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;12:00:01&lt;/td&gt;
&lt;td&gt;swap&lt;/td&gt;
&lt;td&gt;buy&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12:00:02&lt;/td&gt;
&lt;td&gt;swap&lt;/td&gt;
&lt;td&gt;buy&lt;/td&gt;
&lt;td&gt;8,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12:00:03&lt;/td&gt;
&lt;td&gt;swap&lt;/td&gt;
&lt;td&gt;buy&lt;/td&gt;
&lt;td&gt;12,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;→ Total buy = 30,000 USDC, Total sell = 5,000 USDC → Overbought → Possible short/arbitrage signal&lt;/p&gt;




&lt;h3&gt;
  
  
  Liquidity Beneath the Surface
&lt;/h3&gt;

&lt;p&gt;Many liquidity pools are not publicly listed like on Jupiter—they may be used privately and lack a website or Twitter presence. Tapping into these pools can also yield arbitrage profits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Wintermute OTC/RFQ SolFi&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Analyze One-Sided Liquidity Risk with OKX DEX Tools
&lt;/h3&gt;

&lt;p&gt;Open OKX DEX or a Solana DEX dashboard and find a token (e.g., &lt;code&gt;$ABC&lt;/code&gt;) showing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Liquidity: $1M&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But when you inspect the pool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$ABC&lt;/code&gt;: 980,000 tokens (~$980,000)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SOL&lt;/code&gt;: 20 tokens (~$2,000)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates the illusion of $1M liquidity, but only 20 SOL is actually redeemable—indicating serious one-sided risk.&lt;/p&gt;




&lt;h3&gt;
  
  
  Lending Platform Arbitrage / Looping Arbitrage (Using Kamino as an Example)
&lt;/h3&gt;

&lt;p&gt;On Kamino, the utilization rate of some stablecoins (such as USDC) is often above 82%, indicating a supply shortage—deposited funds are fully utilized for lending, which results in higher deposit interest rates.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Asset&lt;/th&gt;
&lt;th&gt;Supply APR&lt;/th&gt;
&lt;th&gt;Borrow APR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;USDC&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;td&gt;12%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FDUSD/TEA&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;td&gt;12%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In this scenario, the &lt;strong&gt;deposit rate is higher than the borrowing rate&lt;/strong&gt;, which implies that the platform is offering &lt;strong&gt;incentives&lt;/strong&gt; or that there's strong demand for the asset in the current market.&lt;/p&gt;




&lt;h3&gt;
  
  
  Arbitrage Method: Looping
&lt;/h3&gt;

&lt;p&gt;By leveraging the structural interest rate spread where &lt;strong&gt;Supply &amp;gt; Borrow&lt;/strong&gt;, we can engage in a “looping” strategy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deposit USDC to earn interest (e.g., 15%)&lt;/li&gt;
&lt;li&gt;Use the deposited USDC as collateral to borrow a portion (e.g., 70%)&lt;/li&gt;
&lt;li&gt;Re-deposit the borrowed USDC and borrow again…&lt;/li&gt;
&lt;li&gt;Repeat multiple rounds to &lt;strong&gt;amplify your principal&lt;/strong&gt;, thus &lt;strong&gt;amplifying your earnings&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This method is known as a &lt;strong&gt;leveraged yield farming strategy&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Risk Warning: Leverage Amplifies Risk
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Liquidation risk&lt;/strong&gt;: If market volatility causes your collateral value to drop or borrowing interest to rise, liquidation may occur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spread risk&lt;/strong&gt;: If the borrowing rate surpasses the deposit rate, the arbitrage model becomes invalid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol parameter risks&lt;/strong&gt;: Changes like reduced LTV, lowered incentives, or updated interest rate models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-chain execution cost&lt;/strong&gt;: Looping requires multiple steps, which incurs gas fees (though Solana is cheap, it can still become congested).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  APY ≠ APR, and APR &amp;lt; APY
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;APR (Annual Percentage Rate)&lt;/strong&gt; is a &lt;strong&gt;simple annual interest rate&lt;/strong&gt;, not considering compounding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APY (Annual Percentage Yield)&lt;/strong&gt; is the &lt;strong&gt;actual annual return including compound interest&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Why is APR &amp;lt; APY?
&lt;/h4&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;APR&lt;/strong&gt; is calculated as a straight percentage over time without reinvestment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APY&lt;/strong&gt; assumes reinvestment of interest, where compounding boosts returns over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
If a platform offers an &lt;strong&gt;APR of 12%&lt;/strong&gt; and interest is &lt;strong&gt;compounded monthly&lt;/strong&gt;, then your actual APY becomes:&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.amazonaws.com%2Fuploads%2Farticles%2Felo8h11bkzq78apn8f6x.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.amazonaws.com%2Fuploads%2Farticles%2Felo8h11bkzq78apn8f6x.png" alt="Image description" width="340" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, even though the stated APR is 12%, the actual &lt;strong&gt;annualized yield (APY)&lt;/strong&gt; is 12.68%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When doing DeFi arbitrage or yield strategies, it’s better to look at APY&lt;/strong&gt;, especially for compounding-based strategies.&lt;/p&gt;




&lt;h3&gt;
  
  
  Atomic Arbitrage / Looping Arbitrage Reflections
&lt;/h3&gt;

&lt;p&gt;On Solana, atomic or looping arbitrage is typically done using &lt;strong&gt;Jupiter aggregator&lt;/strong&gt;, which is developer-friendly but has some critical downsides:&lt;/p&gt;

&lt;h4&gt;
  
  
  Issues with Jupiter:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Polling mechanism&lt;/strong&gt;: Based on REST API polling for market quotes—slower response compared to gRPC trade subscriptions, making it hard to catch arbitrage opportunities promptly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High CPU load&lt;/strong&gt;: Constant polling and frequent path calculations strain device resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low chance of Jito Bundle inclusion&lt;/strong&gt;: While atomic execution is supported, &lt;strong&gt;Jito nodes are scarce&lt;/strong&gt;, and &lt;strong&gt;rate limits are strict&lt;/strong&gt;, making real arbitrage success rates low.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expensive SPAM strategy&lt;/strong&gt;: Without Jito, some rely on “broadcast spamming” RPCs—hundreds of transactions might fail, but one success is a win; however, gas costs are extremely high.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Optimization Direction:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Custom Aggregator + Smart Contracts&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a &lt;strong&gt;custom-built DEX aggregator&lt;/strong&gt; for &lt;strong&gt;path control and reactive matching&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Combine with &lt;strong&gt;efficient smart contract frameworks&lt;/strong&gt; (e.g., &lt;code&gt;no_std&lt;/code&gt;), which consume &lt;strong&gt;far less CU&lt;/strong&gt; than Jupiter, greatly improving arbitrage execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity assurance&lt;/strong&gt;: Multi-hop transactions executed within the contract ensure either all succeed or all fail—risk is managed.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Instead of relying on Jupiter's high-overhead and low-control approach, it’s better to &lt;strong&gt;build your own strategy with lightweight contract logic&lt;/strong&gt;, precisely controlling execution paths and on-chain processes. This increases both the &lt;strong&gt;success rate&lt;/strong&gt; and &lt;strong&gt;profit margin&lt;/strong&gt; of arbitrage strategies.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🧠 Troubleshooting and Resolving Telegram Bot Disconnection Issues: A Practical Pitfall Sharing</title>
      <dc:creator>Miles</dc:creator>
      <pubDate>Tue, 22 Apr 2025 16:19:19 +0000</pubDate>
      <link>https://dev.to/btcmiles/troubleshooting-and-resolving-telegram-bot-disconnection-issues-a-practical-pitfall-sharing-527g</link>
      <guid>https://dev.to/btcmiles/troubleshooting-and-resolving-telegram-bot-disconnection-issues-a-practical-pitfall-sharing-527g</guid>
      <description>&lt;p&gt;During the development of a Telegram bot for listening to messages from a specific channel, I encountered a strange issue:&lt;/p&gt;

&lt;p&gt;After the program ran for a while, it suddenly stopped receiving new messages from the channel, without any obvious error messages.&lt;br&gt;
This left me quite puzzled and delayed the real-time monitoring tasks. In this article, I will go over the troubleshooting process and how I solved it by implementing a "keep-alive" mechanism and an "auto-reconnect" mechanism. I hope this can help those of you who are also developing TG bots.&lt;/p&gt;
&lt;h3&gt;
  
  
  🚩 &lt;strong&gt;Issue Reproduction: Listening Stops Without Errors&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;At first, I was using a very simple Telethon script to listen to the channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;telethon&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TelegramClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TelegramClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TG_APPID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TG_APPHASH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@client.on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NewMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chats&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CHANNEL_ID&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;message_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New message received:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_until_disconnected&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything worked fine, but after a few hours, the messages suddenly stopped printing. The key issue—no errors! The program was still running but seemed to have "lost connection."&lt;/p&gt;

&lt;h3&gt;
  
  
  🔍 &lt;strong&gt;Initial Troubleshooting: Blocking? Deadlock? Exception?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I suspected that the issue might have been caused by an exception in the &lt;code&gt;message_handler&lt;/code&gt; function, so I added a try-except block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@client.on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NewMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chats&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CHANNEL_ID&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;message_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a few hours, I finally captured the following error message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ConnectionError: Timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This indicated that the problem lay in the connection between the client and Telegram's servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  📡 &lt;strong&gt;In-depth Analysis: Why the Timeout?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By consulting the documentation, I discovered that Telegram uses its proprietary MTProto protocol for communication, supporting TCP, HTTPS, and other transmission methods. The client and server typically establish a long-term connection via TCP and rely on periodic heartbeat packets to maintain the connection.&lt;/p&gt;

&lt;p&gt;However, if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client doesn't send requests for a long time&lt;/li&gt;
&lt;li&gt;There are no active tasks (such as message uploads or downloads)&lt;/li&gt;
&lt;li&gt;Network fluctuations or device sleep&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server might classify the connection as "inactive" and close it.&lt;br&gt;
Reference: Telegram Protocol Documentation, Shunix's Weblog&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;Solution: Keep-Alive + Auto-Reconnect&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To maintain the connection with Telegram, we can employ two strategies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Send Heartbeats Periodically (Keep-Alive)&lt;/strong&gt;&lt;br&gt;
Call a method like &lt;code&gt;client.get_me()&lt;/code&gt; at regular intervals to show the client is still active.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auto-Reconnect Mechanism&lt;/strong&gt;&lt;br&gt;
If the connection is lost, restart the connection using a &lt;code&gt;while True&lt;/code&gt; loop and exception handling.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  💻 &lt;strong&gt;Final Code Implementation (Simplified)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;keep_alive&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_me&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Heartbeat
&lt;/span&gt;        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[Keep-Alive Failed]: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Execute every 5 minutes
&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;keep_alive&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Start keep-alive
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_until_disconnected&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[Reconnection Failed]: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Wait 5 seconds before reconnecting
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔚 &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Although the process of solving this issue was somewhat "tedious," it taught me several valuable lessons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Communication with Telegram requires connection maintenance.&lt;/li&gt;
&lt;li&gt;Exception handling is important and can help identify hidden issues.&lt;/li&gt;
&lt;li&gt;Long-running bots need self-recovery capabilities (like keep-alive and auto-reconnect).&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
