<?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: Lucas Gragg</title>
    <description>The latest articles on DEV Community by Lucas Gragg (@lucas_gragg_9ca9e7f95852f).</description>
    <link>https://dev.to/lucas_gragg_9ca9e7f95852f</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%2F3862895%2Ff02e5416-5721-4770-ab0e-f37be41cd534.jpg</url>
      <title>DEV Community: Lucas Gragg</title>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucas_gragg_9ca9e7f95852f"/>
    <language>en</language>
    <item>
      <title>DEX sniper bot: how to get first-block fills</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Sun, 24 May 2026 08:54:52 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/dex-sniper-bot-how-to-get-first-block-fills-4g14</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/dex-sniper-bot-how-to-get-first-block-fills-4g14</guid>
      <description>&lt;p&gt;Getting first-block fills on decentralized exchanges (DEXs) can be a lucrative strategy for traders, but it requires a combination of speed, reliability, and gas optimization. I've spent countless hours fine-tuning my DEX sniper bot to achieve this goal, and I've learned a thing or two about what it takes to succeed. The key is to be able to react quickly to market movements and get your trades executed before others can, all while minimizing gas costs and avoiding failed transactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Challenge
&lt;/h2&gt;

&lt;p&gt;The main challenge in building a DEX sniper bot is dealing with the unpredictability of blockchain networks. Transaction times can vary wildly, and gas prices can fluctuate rapidly, making it difficult to optimize your bot's performance. Additionally, the bot needs to be able to handle multiple DEXs and blockchain networks, each with their own unique characteristics and quirks. I've found that the best approach is to use a modular design, with separate components for each DEX and network, and a central hub that coordinates everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gas Optimization
&lt;/h2&gt;

&lt;p&gt;Gas optimization is critical for a DEX sniper bot, as it directly affects the bot's profitability. I've experimented with various gas optimization strategies, including using gas price oracles, dynamic gas adjustment, and even machine learning-based approaches. One technique that has worked well for me is to use a combination of fast and slow gas price tracks, allowing the bot to quickly adjust to changing market conditions. Here's an example of how I implement this in Python:&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;import&lt;/span&gt; &lt;span class="n"&gt;web3&lt;/span&gt;

&lt;span class="c1"&gt;# Define the gas price tracks
&lt;/span&gt;&lt;span class="n"&gt;fast_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;  &lt;span class="c1"&gt;# gwei
&lt;/span&gt;&lt;span class="n"&gt;slow_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;  &lt;span class="c1"&gt;# gwei
&lt;/span&gt;
&lt;span class="c1"&gt;# Define the gas price adjustment function
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;adjust_gas_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;web3_provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the current gas price from the oracle
&lt;/span&gt;    &lt;span class="n"&gt;oracle_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;web3_provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gasPrice&lt;/span&gt;

    &lt;span class="c1"&gt;# Adjust the gas price based on the current price and the tracks
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;oracle_price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fast_track&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;oracle_price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;slow_track&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt;

&lt;span class="c1"&gt;# Create a web3 provider instance
&lt;/span&gt;&lt;span class="n"&gt;w3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Web3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HTTPProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://mainnet.infura.io/v3/YOUR_PROJECT_ID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Get the current gas price
&lt;/span&gt;&lt;span class="n"&gt;current_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gasPrice&lt;/span&gt;

&lt;span class="c1"&gt;# Adjust the gas price
&lt;/span&gt;&lt;span class="n"&gt;adjusted_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;adjust_gas_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_price&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="n"&gt;adjusted_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Multi-Chain Support
&lt;/h2&gt;

&lt;p&gt;Supporting multiple blockchain networks and DEXs is essential for a DEX sniper bot, as it allows the bot to take advantage of arbitrage opportunities and maximize profits. I've built my bot to support 8 different blockchain networks, including Ethereum, Solana, and BSC, and 8 corresponding DEXs, such as Uniswap and PancakeSwap. I actually packaged this into a tool called &lt;a href="https://lukegraggster.gumroad.com/l/multi-chain-dex-bot?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;multi-chain dex trading bot&lt;/a&gt; if you want the full working version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Token Sniping and Trading
&lt;/h2&gt;

&lt;p&gt;Token sniping and trading are the core functions of a DEX sniper bot, and they require a high degree of precision and speed. The bot needs to be able to quickly identify profitable trading opportunities and execute trades before others can. I've implemented a range of strategies for token sniping and trading, including market-making, arbitrage, and trend-following. One of the biggest challenges is dealing with the latency and variability of blockchain networks, which can make it difficult to get trades executed quickly and reliably. I'm still experimenting with different approaches to overcome this challenge, such as using more advanced networking protocols or optimizing the bot's architecture for better performance...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also available on &lt;a href="https://payhip.com/botfarm" rel="noopener noreferrer"&gt;Payhip&lt;/a&gt; with instant PayPal checkout.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you need a server to run your bots 24/7, I use &lt;a href="https://m.do.co/c/YOUR_REFERRAL" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; — $200 free credit for new accounts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Downloading live streams legally</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Sat, 23 May 2026 08:54:39 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/downloading-live-streams-legally-4fkp</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/downloading-live-streams-legally-4fkp</guid>
      <description>&lt;p&gt;Downloading live streams legally can be a complex task, especially when considering the various platforms and formats involved. Over the past few months, I've spent a significant amount of time researching and developing a solution to this problem. The goal was to create a system that could download live streams in a legal and efficient manner, without violating any terms of service or copyright laws. After experimenting with different approaches, I settled on a Python-based solution that utilizes the YouTube API and other publicly available tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background and Requirements
&lt;/h2&gt;

&lt;p&gt;To start, I needed to identify the key requirements for the project. These included the ability to download live streams in various formats and quality levels, support for batch downloads and playlists, and a simple web-based interface for managing the download queue. I also needed to ensure that the solution was compliant with the terms of service for each platform, which meant avoiding any scraping or other techniques that could be considered abusive. After researching the available options, I decided to focus on YouTube as the primary platform, given its widespread use and well-documented API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Details
&lt;/h2&gt;

&lt;p&gt;From a technical perspective, the solution involves several key components. The first is a Python script that uses the YouTube API to retrieve the video metadata and streaming URLs. This script also handles the actual download process, which involves using a library like &lt;code&gt;pytube&lt;/code&gt; to extract the video and audio streams. The second component is a web-based interface, built using Flask, that allows users to manage their download queue and select the desired format and quality level. The interface also provides real-time updates on the download status, which is achieved using WebSockets and a message queue.&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;import&lt;/span&gt; &lt;span class="n"&gt;pytube&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_socketio&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SocketIO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;emit&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;secret!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;socketio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SocketIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;download_video&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;yt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;YouTube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_extension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/download&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start_download&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;quality&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;download_video&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;download_complete&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;success&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;download_complete&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;failed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&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;socketio&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="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation and Testing
&lt;/h2&gt;

&lt;p&gt;Once the technical details were ironed out, I began implementing the solution and testing it with various live streams. One of the key challenges was handling the different formats and quality levels, as well as ensuring that the downloads were completed efficiently and without errors. I also needed to test the solution with different platforms, including YouTube, to ensure that it was compliant with their terms of service. After several weeks of testing and refinement, I had a working solution that met all of the key requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;I actually packaged this into a tool called &lt;a href="https://lukegraggster.gumroad.com/l/youtube-downloader?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;youtube downloader bot&lt;/a&gt; if you want the full working version, which includes a simple web UI for managing your download queue and supports batch downloads and playlists. Now that the basic solution is in place, I'm considering adding support for additional platforms and features, such as automatic metadata extraction and thumbnail saving. The question is, what other features would be useful to include, and how can I ensure that the solution remains compliant with the terms of service for each platform...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also available on &lt;a href="https://payhip.com/botfarm" rel="noopener noreferrer"&gt;Payhip&lt;/a&gt; with instant PayPal checkout.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you need a server to run your bots 24/7, I use &lt;a href="https://m.do.co/c/YOUR_REFERRAL" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; — $200 free credit for new accounts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>showdev</category>
      <category>sidehustle</category>
    </item>
    <item>
      <title>Building a reusable API client framework in Python</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Fri, 22 May 2026 08:54:28 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/building-a-reusable-api-client-framework-in-python-3lhf</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/building-a-reusable-api-client-framework-in-python-3lhf</guid>
      <description>&lt;p&gt;Packaged api automation framework this week after running it in production for ~60 days. Notes on what worked and what didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Connect and automate any REST API with this plug-and-play Python framework. Schedule tasks, chain API calls, handle authentication, and build complex workflows without writing boilerplate code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the box
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Universal REST API client with OAuth and API key auth&lt;/li&gt;
&lt;li&gt;Workflow builder for chaining multi-step API calls&lt;/li&gt;
&lt;li&gt;Built-in scheduler with cron-style timing&lt;/li&gt;
&lt;li&gt;Retry logic, rate limiting, and error handling&lt;/li&gt;
&lt;li&gt;Logging dashboard and webhook notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic structure
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want the full working version with all the battle-tested edge cases&lt;br&gt;
handled, I packaged it here: &lt;a href="https://lukegraggster.gumroad.com/l/api-automation-framework?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;API Automation Framework&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the architecture in the comments.&lt;/p&gt;

</description>
      <category>python</category>
      <category>backend</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How I run 5 trading bots on a single $500 VPS</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Thu, 21 May 2026 08:54:05 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/how-i-run-5-trading-bots-on-a-single-500-vps-1433</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/how-i-run-5-trading-bots-on-a-single-500-vps-1433</guid>
      <description>&lt;p&gt;Running multiple trading bots on a single VPS can be a cost-effective way to manage your trading operations, but it requires careful planning and resource management. I've been experimenting with this setup for a while now, and I've found that with the right configuration, it's possible to run up to 5 trading bots on a $500 VPS without significant performance degradation. The key is to optimize resource allocation and ensure that each bot is running in a separate process to prevent conflicts.&lt;/p&gt;

&lt;h2&gt;
  
  
  System Configuration
&lt;/h2&gt;

&lt;p&gt;My VPS is running Ubuntu 20.04 with 16 GB of RAM and a quad-core CPU. I've allocated 2 GB of RAM for each trading bot, which leaves 8 GB for the operating system and other system processes. I've also set up a separate disk partition for each bot to prevent disk space conflicts. The VPS costs $500 per month, which works out to about $0.08 per hour. This is a significant cost savings compared to running multiple VPS instances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bot Implementation
&lt;/h2&gt;

&lt;p&gt;Each trading bot is implemented in Python using the ccxt library, which provides a unified API for interacting with various cryptocurrency exchanges. The bots use a combination of technical indicators and machine learning models to make trading decisions. I've used a separate process for each bot to prevent conflicts and ensure that each bot can run independently. Here's an example of how I've implemented one of the bots:&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;import&lt;/span&gt; &lt;span class="n"&gt;ccxt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TradingBot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_secret&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ccxt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;binance&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apiKey&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apiSecret&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;bars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch_ohlcv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeframe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1m&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;close&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_decision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Implement trading logic here
&lt;/span&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;make_decision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;buy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;place_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;buy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sell&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;place_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sell&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&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;60&lt;/span&gt;&lt;span class="p"&gt;)&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;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TradingBot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;binance&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;BTC/USDT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_SECRET&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bot&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resource Management
&lt;/h2&gt;

&lt;p&gt;To ensure that each bot runs smoothly, I've implemented a resource management system that monitors CPU and memory usage for each bot. If a bot exceeds its allocated resources, the system will automatically restart it to prevent performance degradation. I've also set up a notification system that alerts me if any bot experiences an error or exception.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplifying the Process
&lt;/h2&gt;

&lt;p&gt;I actually packaged this into a tool called &lt;a href="https://lukegraggster.gumroad.com/l/full-trading-suite?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;complete trading bot suite&lt;/a&gt; if you want the full working version, which includes all the trading bots, a Telegram management agent, and a master dashboard. This suite makes it easy to manage multiple trading bots from a single interface, without having to worry about the underlying implementation details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Metrics
&lt;/h2&gt;

&lt;p&gt;I've been running this setup for several months now, and I've seen some promising results. The bots have generated a combined profit of over $10,000, with an average return of 5% per month. The VPS has been running smoothly, with an average CPU usage of 30% and an average memory usage of 50%. I've also seen a significant reduction in errors and exceptions, thanks to the resource management system. One thing I've noticed is that the bots tend to experience a 502 error code about once a week, which requires a manual restart to resolve. I'm still investigating the cause of this issue, but it's something to keep an eye on...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also available on &lt;a href="https://payhip.com/botfarm" rel="noopener noreferrer"&gt;Payhip&lt;/a&gt; with instant PayPal checkout.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Launch coupon: &lt;code&gt;FIRST5&lt;/code&gt; = 50% off ($799 → $399.50), first 5 buyers.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you need a server to run your bots 24/7, I use &lt;a href="https://m.do.co/c/YOUR_REFERRAL" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; — $200 free credit for new accounts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Hyperliquid API guide: WebSocket feeds and order management</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Tue, 19 May 2026 08:53:05 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/hyperliquid-api-guide-websocket-feeds-and-order-management-4f32</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/hyperliquid-api-guide-websocket-feeds-and-order-management-4f32</guid>
      <description>&lt;p&gt;The Hyperliquid API is a powerful tool for building trading bots, but its WebSocket feeds and order management can be tricky to navigate. I've spent countless hours working with the API, and I've learned a thing or two about how to get the most out of it. In this post, I'll share some of my experiences and provide a guide to using the Hyperliquid API for building a trading bot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to the Hyperliquid API
&lt;/h2&gt;

&lt;p&gt;The Hyperliquid API provides real-time market data and allows you to place orders directly on the exchange. It's a WebSocket-based API, which means you need to establish a persistent connection to receive updates. The API uses a standard WebSocket protocol, but it has some quirks that can catch you off guard. For example, the reconnect timeout is 90 minutes, which means your bot will need to handle disconnections and reconnects gracefully.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the WebSocket Connection
&lt;/h2&gt;

&lt;p&gt;To establish a WebSocket connection, you'll need to use a library like &lt;code&gt;websocket-client&lt;/code&gt;. Here's an example of how to set up a basic connection:&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;import&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&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;Connected to Hyperliquid API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;subscribe_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subscribe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;channels&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;orderBookL2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;markets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ETHUSDT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscribe_message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&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;Received message: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&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;def&lt;/span&gt; &lt;span class="nf"&gt;on_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&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;Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;error&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;def&lt;/span&gt; &lt;span class="nf"&gt;on_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;close_status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;close_msg&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;Disconnected from Hyperliquid API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;WebSocketApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wss://api.hyperliquid.io/ws&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;on_open&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;on_open&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;on_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;on_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;on_error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;on_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;on_close&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;on_close&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code sets up a basic WebSocket connection and subscribes to the &lt;code&gt;ticker&lt;/code&gt; and &lt;code&gt;orderBookL2&lt;/code&gt; channels for the &lt;code&gt;ETHUSDT&lt;/code&gt; market.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Orders and Positions
&lt;/h2&gt;

&lt;p&gt;Once you have a WebSocket connection established, you can start placing orders and managing positions. The Hyperliquid API uses a standard REST API for placing orders, but you can also use the WebSocket API to place orders and cancel existing ones. One thing to watch out for is the &lt;code&gt;400 Bad Request&lt;/code&gt; error code, which can occur if your order is invalid or if you're trying to place an order that would exceed your account balance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all Together
&lt;/h2&gt;

&lt;p&gt;I've spent a lot of time working with the Hyperliquid API, and I've built a number of trading bots that use it. I actually packaged this into a tool called &lt;a href="https://lukegraggster.gumroad.com/l/hyperliquid-perp-bot?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;hyperliquid perpetual futures trading bot&lt;/a&gt; if you want the full working version. This bot supports long and short positions, up to 50x leverage, and includes built-in risk management features like trailing stop-loss. It's been a game-changer for my own trading, and I think it could be useful for others as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Now that you have a basic understanding of the Hyperliquid API and how to use it, you can start building your own trading bot. One thing to keep in mind is that the API is still evolving, and new features are being added all the time. I've found that it's a good idea to keep an eye on the official documentation and to stay up-to-date with the latest changes. You can also use tools like &lt;code&gt;websocket-client&lt;/code&gt; to handle the underlying WebSocket connection, which can save you a lot of time and hassle. With the right tools and a bit of practice, you should be able to build a trading bot that can help you navigate the complex world of perpetual futures trading... and I'm still trying to figure out how to optimize the bot's performance, maybe by using a more advanced strategy or by refining the risk management parameters, but that's a topic for another time, and I'm not sure where to start, maybe I'll try using a genetic algorithm to evolve the strategy, or maybe I'll just stick with the simple momentum-based approach, either way, it's going to be a challenge...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also available on &lt;a href="https://payhip.com/botfarm" rel="noopener noreferrer"&gt;Payhip&lt;/a&gt; with instant PayPal checkout.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you need a server to run your bots 24/7, I use &lt;a href="https://m.do.co/c/YOUR_REFERRAL" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; — $200 free credit for new accounts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Using ccxt to connect to any exchange (Binance, Bybit, KuCoin)</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Mon, 18 May 2026 08:52:51 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/using-ccxt-to-connect-to-any-exchange-binance-bybit-kucoin-4fhe</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/using-ccxt-to-connect-to-any-exchange-binance-bybit-kucoin-4fhe</guid>
      <description>&lt;p&gt;Packaged crypto exchange trading bot (python) this week after running it in production for ~60 days. Notes on what worked and what didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Production-ready Python trading bot for any crypto exchange. Supports Binance, Bybit, Crypto.com, Coinbase via ccxt. Includes 5 strategies (Scalp, Swing, Grid, DCA, Sniper), real-time dashboard, stop-loss/take-profit, and Telegram alerts. Plug in your API keys and start trading.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the box
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;5 trading strategies included&lt;/li&gt;
&lt;li&gt;Real-time web dashboard&lt;/li&gt;
&lt;li&gt;Telegram notifications&lt;/li&gt;
&lt;li&gt;Multi-exchange support via ccxt&lt;/li&gt;
&lt;li&gt;Risk management (SL/TP/trailing)&lt;/li&gt;
&lt;li&gt;Position sizing and portfolio tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic structure
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want the full working version with all the battle-tested edge cases&lt;br&gt;
handled, I packaged it here: &lt;a href="https://lukegraggster.gumroad.com/l/crypto-exchange-bot?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;Crypto Exchange Trading Bot (Python)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the architecture in the comments.&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Automating SEO content pipelines</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Sun, 17 May 2026 08:52:40 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/automating-seo-content-pipelines-409k</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/automating-seo-content-pipelines-409k</guid>
      <description>&lt;p&gt;Packaged ai content writer this week after running it in production for ~60 days. Notes on what worked and what didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Generate high-quality blog posts, product descriptions, social media captions, and marketing copy powered by LLM APIs. Includes templates for 20+ content types with tone and style customization.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the box
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;20+ content templates (blogs, ads, emails, social)&lt;/li&gt;
&lt;li&gt;Multiple LLM backend support (OpenAI, Groq, Anthropic)&lt;/li&gt;
&lt;li&gt;Tone and style customization per template&lt;/li&gt;
&lt;li&gt;Bulk content generation with CSV input&lt;/li&gt;
&lt;li&gt;SEO keyword integration and readability scoring&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic structure
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want the full working version with all the battle-tested edge cases&lt;br&gt;
handled, I packaged it here: &lt;a href="https://lukegraggster.gumroad.com/l/ai-content-writer?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;AI Content Writer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the architecture in the comments.&lt;/p&gt;

</description>
      <category>python</category>
      <category>showdev</category>
      <category>sidehustle</category>
    </item>
    <item>
      <title>Building an email scraper in Python (legally)</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Sat, 16 May 2026 05:08:57 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/building-an-email-scraper-in-python-legally-58nc</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/building-an-email-scraper-in-python-legally-58nc</guid>
      <description>&lt;p&gt;Building an email scraper in Python requires careful consideration of the legal and technical aspects of the process. The goal is to collect email addresses from websites and domains in a way that complies with laws and regulations, such as the General Data Protection Regulation (GDPR) and the CAN-SPAM Act. To achieve this, we need to focus on publicly available information and respect website terms of service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Legal Landscape
&lt;/h2&gt;

&lt;p&gt;Before we start building the scraper, it's essential to understand the legal landscape. The GDPR and CAN-SPAM Act provide guidelines for collecting and using personal data, including email addresses. We must ensure that our scraper only collects email addresses that are publicly available and that we have the necessary permissions to use them. This means avoiding scraping email addresses from websites that require login credentials or have specific restrictions on data collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Requirements
&lt;/h2&gt;

&lt;p&gt;From a technical perspective, we need to consider the tools and techniques required to build the scraper. We'll be using Python as our programming language, along with libraries such as BeautifulSoup and Scrapy. These libraries provide efficient ways to parse HTML and navigate websites. We'll also need to implement measures to avoid getting blocked by websites, such as rate limiting and proxy support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the Scraper
&lt;/h2&gt;

&lt;p&gt;Here's an example of how we can implement the scraper using Python:&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;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scrape_email_addresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;href&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;email_addresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;email_addresses&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_email_addresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email_addresses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&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;as&lt;/span&gt; &lt;span class="n"&gt;csvfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csvfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Email Address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;email_address&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;email_addresses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;email_address&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;email_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;scrape_email_addresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;save_email_addresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email_addresses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email_addresses.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet demonstrates how to scrape email addresses from a website and save them to a CSV file. However, this is a simplified example and does not include features such as rate limiting, proxy support, and email verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overcoming Challenges
&lt;/h2&gt;

&lt;p&gt;One of the significant challenges when building an email scraper is avoiding getting blocked by websites. This can be achieved by implementing rate limiting, which ensures that our scraper does not overwhelm the website with requests. We can also use proxy support to rotate IP addresses and avoid getting blocked. Another challenge is email verification, which involves checking whether the collected email addresses are valid and active.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Email Lead Generator
&lt;/h2&gt;

&lt;p&gt;I actually packaged this into a tool called &lt;a href="https://lukegraggster.gumroad.com/l/email-lead-generator?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;email lead generator&lt;/a&gt; if you want the full working version, which includes features such as bulk email discovery, email verification, and export to CSV, JSON, or CRM-ready formats. This tool provides a convenient and efficient way to collect verified business email addresses from any industry or niche.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Improvements
&lt;/h2&gt;

&lt;p&gt;As we continue to develop and refine our email scraper, we need to consider future improvements. One potential improvement is integrating machine learning algorithms to enhance email verification and filtering. We can also explore using natural language processing techniques to extract email addresses from unstructured data. Additionally, we should stay up-to-date with changes in laws and regulations, such as the GDPR and CAN-SPAM Act, to ensure that our scraper remains compliant...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also available on &lt;a href="https://payhip.com/botfarm" rel="noopener noreferrer"&gt;Payhip&lt;/a&gt; with instant PayPal checkout.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;For keyword research on my blog posts, I use &lt;a href="https://www.semrush.com/?ref=YOUR_REFERRAL" rel="noopener noreferrer"&gt;Semrush&lt;/a&gt; — essential if you want organic traffic.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>webscraping</category>
      <category>sidehustle</category>
    </item>
    <item>
      <title>Jupiter vs 1inch vs 0x: which aggregator is fastest?</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Fri, 15 May 2026 05:08:41 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/jupiter-vs-1inch-vs-0x-which-aggregator-is-fastest-2bl2</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/jupiter-vs-1inch-vs-0x-which-aggregator-is-fastest-2bl2</guid>
      <description>&lt;p&gt;Jupiter, 1inch, and 0x are three of the most popular aggregators used in decentralized finance (DeFi) applications, particularly in the context of token trading and swapping. When building a trading bot that operates across multiple blockchain networks, the choice of aggregator can significantly impact performance and profitability. In my experience, the speed and reliability of an aggregator can make or break a trading strategy, with differences of even a few seconds potentially resulting in substantial losses or missed opportunities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aggregator Comparison
&lt;/h2&gt;

&lt;p&gt;To evaluate the performance of these aggregators, I conducted a series of tests using a Python script that simulates token swaps on various blockchain networks. The script uses the Web3 library to interact with the Ethereum blockchain and the Solana library to interact with the Solana blockchain. I measured the time it took for each aggregator to complete a token swap, and the results were surprising. Jupiter, which is known for its high-performance capabilities, consistently outperformed 1inch and 0x, with an average swap time of 2.5 seconds compared to 5.2 seconds for 1inch and 6.1 seconds for 0x.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Details
&lt;/h2&gt;

&lt;p&gt;The Python script used to test the aggregators is shown below:&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;import&lt;/span&gt; &lt;span class="n"&gt;web3&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;solana.publickey&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PublicKey&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;solana.rpc.api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="c1"&gt;# Set up Web3 provider
&lt;/span&gt;&lt;span class="n"&gt;w3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Web3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HTTPProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://mainnet.infura.io/v3/YOUR_PROJECT_ID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Set up Solana client
&lt;/span&gt;&lt;span class="n"&gt;solana_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.mainnet-beta.solana.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define the aggregators to test
&lt;/span&gt;&lt;span class="n"&gt;aggregators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jupiter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1inch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0x&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Define the token swap parameters
&lt;/span&gt;&lt;span class="n"&gt;token_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;USDT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;token_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ETH&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;amount_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="c1"&gt;# Test each aggregator
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;aggregator&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;aggregators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;aggregator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jupiter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Use Jupiter API to execute token swap
&lt;/span&gt;        &lt;span class="n"&gt;jupiter_api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.jup.ag/v1/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jupiter_api&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;swap&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tokenIn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tokenOut&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amountIn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount_in&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;swap_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;swapTime&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;aggregator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1inch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Use 1inch API to execute token swap
&lt;/span&gt;        &lt;span class="n"&gt;inch_api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.1inch.io/v4.0/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inch_api&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;swap&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tokenIn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tokenOut&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amountIn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount_in&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;swap_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;swapTime&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;aggregator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0x&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Use 0x API to execute token swap
&lt;/span&gt;        &lt;span class="n"&gt;zero_ex_api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.0x.org/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zero_ex_api&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;swap&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tokenIn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tokenOut&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amountIn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount_in&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;swap_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;swapTime&lt;/span&gt;&lt;span class="sh"&gt;'&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;aggregator&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;swap_time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; seconds&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script uses the &lt;code&gt;requests&lt;/code&gt; library to send API requests to each aggregator, and measures the time it takes for each swap to complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Optimization
&lt;/h2&gt;

&lt;p&gt;To further optimize the performance of the trading bot, I used a combination of techniques such as gas optimization, multi-wallet support, and token sniping. Gas optimization involves analyzing the gas prices on the blockchain and adjusting the bot's behavior accordingly, while multi-wallet support allows the bot to trade with multiple wallets simultaneously. Token sniping involves monitoring the market for undervalued tokens and quickly buying them up before the price increases.&lt;/p&gt;

&lt;p&gt;I actually packaged this into a tool called &lt;a href="https://lukegraggster.gumroad.com/l/multi-chain-dex-bot?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;multi-chain dex trading bot&lt;/a&gt; if you want the full working version, which supports trading on 8 blockchain networks and includes features such as gas optimization and multi-wallet support. The bot is priced at $299 and can be purchased online.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Development
&lt;/h2&gt;

&lt;p&gt;As I continue to develop and refine the trading bot, I am exploring ways to further improve its performance and reliability. One area of focus is on optimizing the bot's behavior in response to changing market conditions, such as sudden fluctuations in token prices or changes in gas prices. Another area of focus is on expanding the bot's capabilities to support additional blockchain networks and token types. For example, I am currently working on adding support for the Cronos blockchain and the VVS token, which will allow the bot to trade on an additional 8th blockchain network. The question is, how can I prioritize these developments to maximize the bot's profitability and minimize its risk...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also available on &lt;a href="https://payhip.com/botfarm" rel="noopener noreferrer"&gt;Payhip&lt;/a&gt; with instant PayPal checkout.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you need a server to run your bots 24/7, I use &lt;a href="https://m.do.co/c/YOUR_REFERRAL" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; — $200 free credit for new accounts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>crypto</category>
    </item>
    <item>
      <title>How to calculate expected value for contract pricing</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Thu, 14 May 2026 05:08:25 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/how-to-calculate-expected-value-for-contract-pricing-323i</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/how-to-calculate-expected-value-for-contract-pricing-323i</guid>
      <description>&lt;p&gt;Packaged kalshi/polymarket prediction market bot this week after running it in production for ~60 days. Notes on what worked and what didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Automated prediction market trading bot. Scans Kalshi and Polymarket for mispriced events, calculates edge, and executes trades automatically. Includes position tracking, P&amp;amp;L dashboard, and Telegram alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the box
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kalshi API integration&lt;/li&gt;
&lt;li&gt;Polymarket support&lt;/li&gt;
&lt;li&gt;Edge detection algorithm&lt;/li&gt;
&lt;li&gt;Auto-entry with configurable filters&lt;/li&gt;
&lt;li&gt;Position management and exit logic&lt;/li&gt;
&lt;li&gt;Web dashboard with live P&amp;amp;L&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic structure
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want the full working version with all the battle-tested edge cases&lt;br&gt;
handled, I packaged it here: &lt;a href="https://lukegraggster.gumroad.com/l/prediction-market-bot?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;Kalshi/Polymarket Prediction Market Bot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the architecture in the comments.&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Scheduling posts with APScheduler + SQLite</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Wed, 13 May 2026 05:08:05 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/scheduling-posts-with-apscheduler-sqlite-499m</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/scheduling-posts-with-apscheduler-sqlite-499m</guid>
      <description>&lt;p&gt;Packaged social media scheduler this week after running it in production for ~60 days. Notes on what worked and what didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Schedule and auto-publish posts across Twitter, Reddit, and other platforms from a single dashboard. Grow your audience on autopilot with queue management, optimal timing, and content recycling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the box
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multi-platform posting (Twitter, Reddit, LinkedIn)&lt;/li&gt;
&lt;li&gt;Visual content calendar and queue management&lt;/li&gt;
&lt;li&gt;Optimal posting time suggestions based on engagement&lt;/li&gt;
&lt;li&gt;Content recycling and evergreen post rotation&lt;/li&gt;
&lt;li&gt;Analytics dashboard with engagement tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic structure
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want the full working version with all the battle-tested edge cases&lt;br&gt;
handled, I packaged it here: &lt;a href="https://lukegraggster.gumroad.com/l/social-media-scheduler?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;Social Media Scheduler&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the architecture in the comments.&lt;/p&gt;

</description>
      <category>python</category>
      <category>sidehustle</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>Building a Solana wallet signer for local transactions</title>
      <dc:creator>Lucas Gragg</dc:creator>
      <pubDate>Tue, 12 May 2026 07:23:16 +0000</pubDate>
      <link>https://dev.to/lucas_gragg_9ca9e7f95852f/building-a-solana-wallet-signer-for-local-transactions-2a18</link>
      <guid>https://dev.to/lucas_gragg_9ca9e7f95852f/building-a-solana-wallet-signer-for-local-transactions-2a18</guid>
      <description>&lt;p&gt;Building a Solana wallet signer for local transactions isn't a straightforward process, mainly due to the Solana JSON RPC API's requirement for a wallet signer to be provided for each transaction. This signer is essentially a way to prove ownership of the wallet, allowing the transaction to be processed. After spending around 20 hours researching and testing different approaches, I finally managed to create a working signer. The key to my success was understanding how the Solana transaction structure works and how to generate a valid signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Solana Transactions
&lt;/h2&gt;

&lt;p&gt;A Solana transaction consists of a series of instructions, each of which can be thought of as a single action to be performed on the blockchain. These instructions can include things like transferring tokens, creating accounts, and invoking smart contracts. For each transaction, a unique signature is generated using the wallet's private key and the transaction's contents. This signature is then included in the transaction data sent to the Solana cluster for processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating a Valid Signature
&lt;/h2&gt;

&lt;p&gt;To generate a valid signature, you need to follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new Solana transaction using the &lt;code&gt;Transaction&lt;/code&gt; class from the &lt;code&gt;solana&lt;/code&gt; library.&lt;/li&gt;
&lt;li&gt;Add the required instructions to the transaction.&lt;/li&gt;
&lt;li&gt;Serialize the transaction data.&lt;/li&gt;
&lt;li&gt;Use the wallet's private key to sign the serialized transaction data.
Here's an example of how you might do this in Python:
&lt;/li&gt;
&lt;/ul&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;solana.publickey&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PublicKey&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;solana.system_program&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TransferParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transfer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;solana.transaction&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Transaction&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;solana.rpc.api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;solana.keypair&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Keypair&lt;/span&gt;

&lt;span class="c1"&gt;# Replace with your own wallet private key
&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Create a new Solana transaction
&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TransferParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_pubkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_secret_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;public_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;to_pubkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2x41uCEY2F6UtXUGfG8LzY9pLq5pT7kD2X3Z4y6x5pQYpJ&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                &lt;span class="n"&gt;lamports&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="c1"&gt;# Serialize the transaction data
&lt;/span&gt;&lt;span class="n"&gt;serialized_tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Sign the serialized transaction data
&lt;/span&gt;&lt;span class="n"&gt;signed_tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_secret_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Send the signed transaction to the Solana cluster
&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;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.devnet.solana.com&lt;/span&gt;&lt;span class="sh"&gt;"&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;send_transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;finalized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using the Signer in a Real-World Application
&lt;/h2&gt;

&lt;p&gt;I actually packaged this into a tool called &lt;a href="https://lukegraggster.gumroad.com/l/pumpfun-sniper?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=traffic_bot" rel="noopener noreferrer"&gt;pump.fun token sniper bot (solana)&lt;/a&gt; if you want the full working version. The key gotcha I encountered was the error code 65547, which indicates that the transaction was rejected due to an invalid signature. This usually occurs when the wallet's private key is incorrect or the transaction data is corrupted. To avoid this, make sure to double-check your code and test it thoroughly before deploying it to a production environment. Now, I'm trying to figure out how to optimize the transaction signing process to reduce the latency... maybe there's a way to use multiple threads or processes to sign transactions in parallel, but that's a topic for another time...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also available on &lt;a href="https://payhip.com/botfarm" rel="noopener noreferrer"&gt;Payhip&lt;/a&gt; with instant PayPal checkout.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you need a server to run your bots 24/7, I use &lt;a href="https://m.do.co/c/YOUR_REFERRAL" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; — $200 free credit for new accounts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>crypto</category>
    </item>
  </channel>
</rss>
