<?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>Forem: Mohammed Alsabaawi</title>
    <description>The latest articles on Forem by Mohammed Alsabaawi (@mohammedalabd).</description>
    <link>https://forem.com/mohammedalabd</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%2F464696%2F0bfe2281-6d86-4e4f-b841-b7227119553b.jpeg</url>
      <title>Forem: Mohammed Alsabaawi</title>
      <link>https://forem.com/mohammedalabd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mohammedalabd"/>
    <language>en</language>
    <item>
      <title>Atom transactions using Jito bundles</title>
      <dc:creator>Mohammed Alsabaawi</dc:creator>
      <pubDate>Mon, 02 Dec 2024 11:18:34 +0000</pubDate>
      <link>https://forem.com/mohammedalabd/atom-transactions-using-jito-bundles-1m78</link>
      <guid>https://forem.com/mohammedalabd/atom-transactions-using-jito-bundles-1m78</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this blog, you learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Solana &lt;strong&gt;transaction size limitation&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jito bundles&lt;/strong&gt;, what they are, and why we need them&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;practical example with TS&lt;/strong&gt; on how to build and submit a Jito bundler to the network (&lt;a href="https://github.com/MohammedAlabd/solana-jito-ts-example" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Solana is a fast, cheap, and performant network; it has a very high TPS, the best of all other chains. But we are not living in a perfect world; everything comes with a price. When you make something that good and cheap, tradeoffs are inevitable. One of these tradeoffs is the transaction size limitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solana transaction size limitation
&lt;/h2&gt;

&lt;p&gt;Solana network enforces a &lt;strong&gt;1232-byte&lt;/strong&gt; transaction size limit to ensure each transaction fits into a single network packet. This design choice is deliberate and efficient. Solana network adheres to a maximum transmission unit (MTU) size of 1280 bytes, consistent with the &lt;a href="https://en.wikipedia.org/wiki/IPv6_packet" rel="noopener noreferrer"&gt;IPv6 MTU&lt;/a&gt;, and after accounting for the necessary headers (40 bytes for IPv6 and 8 bytes for the fragment header), 1232 bytes remain available for packet data. &lt;a href="https://solana.com/docs/core/transactions#transaction-size" rel="noopener noreferrer"&gt;You can read more about this here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While &lt;strong&gt;this is sufficient&lt;/strong&gt; for most use cases, &lt;strong&gt;there are times when you might need more&lt;/strong&gt;. And if, for some reason, you want to have two transactions, and you want one of them to get submitted before the other, and you want to make sure that the second transaction never reaches the network if the first one has some issues, &lt;/p&gt;

&lt;p&gt;You can't sign and send both transactions simultaneously because there's no guarantee the first transaction will be submitted first. Instead, you must sign and submit the first transaction, wait for confirmation, then sign and submit the second. This process creates a poor user experience, as users must sign twice for a single action. So, what's the solution? Here comes Jito Bundles&lt;/p&gt;

&lt;h2&gt;
  
  
  Jito
&lt;/h2&gt;

&lt;p&gt;Jito is one of the biggest projects on the Solana network; they do a lot of cool things (&lt;a href="https://www.jito.network/blog/" rel="noopener noreferrer"&gt;check their blog&lt;/a&gt;), but we are now interested in the Jito Bundles feature. &lt;a href="https://docs.jito.wtf/lowlatencytxnsend/#bundles-api-v1-bundles" rel="noopener noreferrer"&gt;Jito Bundles&lt;/a&gt; consist of up to five transactions that execute sequentially and atomically, ensuring an all-or-nothing outcome. &lt;/p&gt;

&lt;p&gt;How do Bundles work?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traders submit bundles to block engines&lt;/li&gt;
&lt;li&gt;Block engines simulate bundles to determine the most profitable combinations&lt;/li&gt;
&lt;li&gt;Winning bundles are sent to validators to include in blocks&lt;/li&gt;
&lt;li&gt;Validators execute bundles atomically and collect tips&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Example
&lt;/h2&gt;

&lt;p&gt;In this example, you will build and submit a bundle to Jito. You can find the example code in this &lt;a href="https://github.com/MohammedAlabd/solana-jito-ts-example" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similar to &lt;a href="https://solana.com/developers/guides/advanced/how-to-use-priority-fees" rel="noopener noreferrer"&gt;Solana's priority&lt;/a&gt; fees, Jito employs a mechanism to prioritize bundles called 'Jito tips.' These user-defined amounts incentivize validators to process bundles ahead of other transactions, ensuring faster execution.&lt;/p&gt;

&lt;p&gt;Tips are simply a SOL transfer instruction to one of the known Jito tip accounts, and this instruction should be present in your bundle either as a part of another transaction or as a stand-alone transaction, we will look at both of them here.&lt;/p&gt;

&lt;p&gt;If you go ahead and clone the &lt;a href="https://github.com/MohammedAlabd/solana-jito-ts-example" rel="noopener noreferrer"&gt;repo&lt;/a&gt;, open the readme file and follow the instructions to install the dependencies (I use a bun, but feel free to use something else) and set up the env variables, then you can find two files inside the &lt;code&gt;src&lt;/code&gt; folder, &lt;code&gt;embedded-tip-ix.ts&lt;/code&gt; and &lt;code&gt;separated-tip-tx.ts,&lt;/code&gt; they are pretty similar, the only change is that we are embedding the tip instruction in one of the bundle's transactions (the last one) in one of them, while we are separating it into a standalone transaction in the other one, you can read more about the best practices of tipping &lt;a href="https://docs.jito.wtf/lowlatencytxnsend/#tips" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://www.quicknode.com/guides/solana-development/transactions/jito-bundles#important-notes-on-tipping" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TL;DR: you should try to have the tipping instruction as the last one in the bundle, and it is better to have it inside a transaction and not a stand-alone transaction, in this case, you will make sure that your tip will not go for wast by a malicious validator or an &lt;a href="https://www.quicknode.com/guides/solana-development/transactions/jito-bundles#important-notes-on-tipping" rel="noopener noreferrer"&gt;uncle block&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's take a look at the file &lt;code&gt;src/embedded-tip-ix.ts&lt;/code&gt; and skip the import part (because it is boring), the first function that you will see there is &lt;code&gt;getRandomeTipAccountAddress&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getRandomeTipAccountAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;searcherClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;searcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SearcherClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;searcherClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTipAccounts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function fetches the tip accounts and selects a random one. Using a random account instead of always selecting the first one increases the chance of landing our bundle, if too many transactions try to tip the same account, that might push some of them to fail.&lt;/p&gt;

&lt;p&gt;The very next thing is the &lt;code&gt;buildMemoTransaction&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MEMO_PROGRAM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buildMemoTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Keypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;recentBlockhash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;tipIx&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;TransactionInstruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;VersionedTransaction&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionInstruction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isSigner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isWritable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;programId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MEMO_PROGRAM_ID&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instructions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ix&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tipIx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tipIx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageV0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;payerKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;recentBlockhash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;recentBlockhash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;compileToV0Message&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VersionedTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageV0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&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="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;txn signature is: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bs58&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just a simple method that will build a memo transaction, which has no use, but it is so cheap and simple, so it is perfect for our example since we are going to do this on the main net, it also takes an optional tip instruction and pushes it in the transaction if provided.&lt;/p&gt;

&lt;p&gt;Sitting that aside, let's get to the meat of this, the first few lines of the &lt;code&gt;main&lt;/code&gt; function is just to setup few variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blockEngineUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOCK_ENGINE_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BLOCK_ENGINE_URL:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blockEngineUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authKeypairPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_KEYPAIR_PATH&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AUTH_KEYPAIR_PATH:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authKeypairPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decodedKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authKeypairPath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromSecretKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decodedKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bundleTransactionLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BUNDLE_TRANSACTION_LIMIT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we need to create the searcher client, which is what we will use to communicate with the Jito server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Create the searcher client that will interact with Jito&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searcherClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;searcherClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blockEngineUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can subscribe to the &lt;code&gt;onBundleRequest&lt;/code&gt; so we get updates about our bundle once we send it to the network&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Subscribe to the bundle result&lt;/span&gt;
  &lt;span class="nx"&gt;searcherClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onBundleResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;received bundle result:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we will get the tip account and build the tip instruction&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Get a random tip account address&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tipAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getRandomeTipAccountAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searcherClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tip account:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tipAccount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rpcUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RPC_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RPC_URL:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rpcUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// get the latest blockhash&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rpcUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirmed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blockHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLatestBlockhash&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Build a Transfer Instruction&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tipIx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SystemProgram&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="na"&gt;fromPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;toPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tipAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lamports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned earlier, the tip can be included in one of the bundle transactions. Alternatively, it can be a stand-alone transaction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transactions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;buildMemoTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jito test 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blockHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blockhash&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// Include the tip instruction in the second transactions&lt;/span&gt;
    &lt;span class="nf"&gt;buildMemoTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jito test 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blockHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blockhash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tipIx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but we can also have it as a stand-alone transaction like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const tipTx = new VersionedTransaction(
    new TransactionMessage({
      payerKey: keypair.publicKey,
      recentBlockhash: blockHash.blockhash,
      instructions: [tipIx],
    }).compileToV0Message(),
  );
  tipTx.sign([keypair]);

  const transactions = [
    buildMemoTransaction(keypair, "jito test 1", blockHash.blockhash),
    buildMemoTransaction(keypair, "jito test 2", blockHash.blockhash),
  ];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With everything in place, we can now build the bundle using the transactions and submit it to Jito.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jitoBundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tipTx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;bundleTransactionLimit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;searcherClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendBundle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jitoBundle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resp:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error sending bundle:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here is the full file from the example &lt;code&gt;src/embedded-tip-ix.ts&lt;/code&gt; &lt;a href="https://github.com/MohammedAlabd/solana-jito-ts-example/blob/main/src/embedded-tip-ix.ts" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now if you run that file, you should see the transaction signatures and the bundle Id, you can check the transactions in any explorer and you can check the bundle id in &lt;a href="https://explorer.jito.wtf/" rel="noopener noreferrer"&gt;Jito Explorer&lt;/a&gt; (it might take a minute before showing up there)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;txn signature is:  5YQVsedCaaf1bCbTUJgd23vNfte2doB1K3CB6tKxCH7KYY7Y8rDwbmetCcgBufhz8nY1nWDeCRNqhUkWNydnsjeZ
txn signature is:  3mnhGK2X2FVnsada8YL46TYdZc7BfR14GdYTjJWk8mrG2WzBJGXdyN7aLVNP3ZkWGwUBpGypjW7JWFeYGKNRa2vR
resp: 09d2c693a232d48781f69d786276b8af04be9138b0777d313b18251271825b3c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats, you have submitted a bundle&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Jito Bundles provide a powerful solution for handling Solana’s transaction size limitations, ensuring seamless and atomic execution of complex operations. By leveraging tips and smart transaction bundling, developers can optimize the user experience and make the most of Solana’s capabilities. With this guide and the provided example, you now have the tools to integrate Jito Bundles into your Solana projects effectively. Try it out and explore the possibilities!&lt;/p&gt;

</description>
      <category>solana</category>
      <category>web3</category>
      <category>jito</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Solana Safe Transfer (Fat-Finger-proof Transfer)</title>
      <dc:creator>Mohammed Alsabaawi</dc:creator>
      <pubDate>Sat, 02 Nov 2024 14:10:03 +0000</pubDate>
      <link>https://forem.com/mohammedalabd/solana-safe-transfer-fat-finger-proof-transfer-lgf</link>
      <guid>https://forem.com/mohammedalabd/solana-safe-transfer-fat-finger-proof-transfer-lgf</guid>
      <description>&lt;p&gt;Solana is a fast, cheap, and reliable blockchain network. You can transfer assets worth millions of dollars in seconds to another part of the world. And you'll pay only a fraction of a penny in fees!&lt;/p&gt;

&lt;p&gt;This technology is revolutionary, and finance is not the only thing you can do on it with such efficiency. People are doing lots of cool stuff on this network, like running DAOs or building games with experiences different from what we had before blockchain.&lt;/p&gt;

&lt;p&gt;When it comes to finance and money, one of the key differences between traditional banking systems and blockchain (Solana in particular) is speed. Traditional banking systems are slow if you want to send money overseas, and if it's a large sum, you’ll have to pay high fees. The trade-off is security because the bank will double-check the transfer details before sending it. If you make a mistake, like entering the wrong account number, and that number doesn’t belong to anyone, the bank won’t process the transfer, and the money will return to your account.&lt;/p&gt;

&lt;p&gt;Using Solana, on the other hand, is much faster and cheaper. You can send assets worth thousands of dollars in seconds—literally seconds—but there’s a catch: once you sign the transaction and send it to the network, there's no way to reverse it. No one can undo it, ever! This is good for network security, but if you accidentally enter the wrong address, it’s a problem for you.&lt;/p&gt;

&lt;p&gt;If you change even one letter in the address (which is around 32-44 characters long), you could lose access to those assets forever. There’s a chance that the funds might end up in an account that no one owns—and probably never will. That’s why people are often hesitant to send large amounts of assets over the network.&lt;/p&gt;

&lt;p&gt;This is where my program, &lt;em&gt;Solana Safe Transfer&lt;/em&gt;, comes into play. It requires you to enter the recipient's address as well as a unique confirmation code associated with that address. If there are any mistakes in either of these strings, the transfer will fail, and your assets will remain in your account.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Get a Confirmation Code
&lt;/h3&gt;

&lt;p&gt;To get a confirmation code that you can share with others for sending you money, go to the &lt;a href="https://solana-safe-transfer-web.vercel.app/" rel="noopener noreferrer"&gt;Program website&lt;/a&gt;. There, click the &lt;strong&gt;Get a Confirmation Code&lt;/strong&gt; button, and sign a light transaction that will create a confirmation account for you and generate a random code for the wallet you're using. After that, you can copy the code and share it with anyone who wants to transfer funds to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transferring Assets
&lt;/h3&gt;

&lt;p&gt;To send assets, visit the same &lt;a href="https://solana-safe-transfer-web.vercel.app/" rel="noopener noreferrer"&gt;Program website&lt;/a&gt;. From there, you can enter the amount of SOL you want to send, provide the recipient's address, and their confirmation code, then hit send. Right now, the program supports sending SOL, but I’ll be adding support for other SPL tokens as well as NFTs soon.&lt;/p&gt;




&lt;p&gt;Feel free to share any feedback you have, or let me know what features you’d like me to work on next. If you want to get involved and help, please be my guest—&lt;a href="https://github.com/MohammedAlabd/solana-safe-transfer" rel="noopener noreferrer"&gt;here is the repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>solana</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>My Experience at Nas Academy Solana Course: A Journey into the World of Web3</title>
      <dc:creator>Mohammed Alsabaawi</dc:creator>
      <pubDate>Thu, 08 Jun 2023 10:21:11 +0000</pubDate>
      <link>https://forem.com/mohammedalabd/my-experience-at-nas-academy-solana-course-a-journey-into-the-world-of-web3-1el4</link>
      <guid>https://forem.com/mohammedalabd/my-experience-at-nas-academy-solana-course-a-journey-into-the-world-of-web3-1el4</guid>
      <description>&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;p&gt;Recently, I had the incredible opportunity to participate in the &lt;a href="https://nas.io/"&gt;Nas Academy&lt;/a&gt; Solana Course, a bootcamp designed to explore the modern web technology known as Web3. As a full-stack software engineer with a keen interest in the latest advancements, I was eager to delve into this new world and evaluate its potential. In this blog post, I will share my background, discuss my experience throughout the course, highlight the valuable knowledge gained, and provide insights on what could be improved.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background and Motivation:
&lt;/h3&gt;

&lt;p&gt;With over three years of experience as a software engineer working on web2 projects, I was eager to expand my horizons and dive into the realm of Web3. The opportunity to learn from the best in the field motivated me to join the Nas Academy Solana Course. Having witnessed the impressive work produced by Nas Academy, I was confident that this bootcamp would provide an enriching experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experience at Nas Academy:
&lt;/h3&gt;

&lt;p&gt;My journey at Nas Academy began with an engaging speaker session before the start of my cohort. There, I had the pleasure of meeting the enthusiastic and knowledgeable Nas crew. Their vibrant energy and passion for the subject instantly captivated me, setting the stage for an exciting learning experience. The course itself was led by &lt;a href="https://www.linkedin.com/in/jamesrpacheco"&gt;James&lt;/a&gt;, an exceptional teacher and engineer who provided valuable insights into Solana development. Through his guidance, I learned not only about Solana but also about debugging techniques and other essential skills.&lt;/p&gt;

&lt;p&gt;Furthermore, the presence of &lt;a href="https://www.linkedin.com/in/giorgio-grillo-8b0350155/"&gt;Giorgio&lt;/a&gt;, an amazing support system for the students, with his infectious energy, was a dedicated support system throughout the course. Always available to help students when they encountered challenges, he played a pivotal role in creating a supportive and collaborative learning environment. Her commitment to ensuring everyone's success was truly commendable.&lt;/p&gt;

&lt;p&gt;and A.J. though not directly involved in technical aspects, contributed significantly to the smooth functioning of the course. She was responsible for organizing the sessions, managing logistics, and uploading the session recordings. Her efforts behind the scenes ensured that everything ran seamlessly, allowing participants to focus on the learning experience without any distractions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways:
&lt;/h3&gt;

&lt;p&gt;Throughout the Nas Academy Solana Course, I acquired a comprehensive understanding of Solana and its potential applications. From developing front-end applications that interacted with existing Solana programs, to creating fungible tokens, NFTs, and candy machines, I gained hands-on experience in building decentralized applications. Moreover, I learned how to write my own programs using vanilla Rust and the Anchor framework, and successfully deployed them on the Solana blockchain. The course also enlightened me about the fundamental concepts of Web3 and reinforced my belief that it represents the future of the internet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Favorite Aspects of the Course:
&lt;/h3&gt;

&lt;p&gt;One of the standout features of the Nas Academy Solana Course was its exceptional organization and professionalism. The sessions were conducted punctually, with a perfect balance between pace and interactivity. I appreciated that there was ample time to ask questions and learn from the best in the field. Additionally, the &lt;a href="https://buildspace.so/p/solana-core"&gt;offline course material&lt;/a&gt; provided was incredibly informative, enriching the overall learning experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Suggestions for Improvement:
&lt;/h3&gt;

&lt;p&gt;While the course offered a well-rounded learning experience, one aspect that I would have appreciated is the inclusion of code reviews. As someone who greatly values feedback on my code, I believe that incorporating a few additional weeks at the end of the course for a capstone project, where participants can receive expert reviews on their code, would have been a valuable addition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion:
&lt;/h3&gt;

&lt;p&gt;My time at Nas Academy Solana Course was a remarkable journey into the world of Web3. The course instructors, James, Jorgie, and A.J., provided exceptional guidance and support, making the learning experience enjoyable and enlightening. I gained in-depth knowledge of Solana development, learned essential debugging techniques, and explored the concept of Web3 as the future of the internet. Although I would have appreciated the opportunity for code reviews, I highly recommend this bootcamp to anyone interested in immersing themselves in the exciting world of Web3.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>nasacademy</category>
      <category>solana</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>A Better Way to Deal With Dependencies</title>
      <dc:creator>Mohammed Alsabaawi</dc:creator>
      <pubDate>Mon, 04 Jul 2022 05:57:45 +0000</pubDate>
      <link>https://forem.com/mohammedalabd/a-better-way-to-deal-with-dependencies-2c2a</link>
      <guid>https://forem.com/mohammedalabd/a-better-way-to-deal-with-dependencies-2c2a</guid>
      <description>&lt;p&gt;Dependencies are everywhere right now and are always a necessary part of developing any app; however, occasionally our code can easily become &lt;strong&gt;highly coupled&lt;/strong&gt; with them and this is &lt;strong&gt;extremely risky&lt;/strong&gt;. As a result, our app will eventually go down sooner than we expect when one of the dependencies goes down for any reason, and to make it worse external code is out of our control which makes it much harder to deal with, another thing to consider when using a lot of dependencies is changing one of them, that could be also hell and needs a lot of work unless we plan for it carefully to manage the dependencies in a way that makes it less dangerous to use them.&lt;/p&gt;

&lt;p&gt;There are several approaches to achieve this, including and not limited to &lt;strong&gt;"dependency injection"&lt;/strong&gt; and &lt;strong&gt;"dependency inversion"&lt;/strong&gt;, and in this post, we will discuss a strategy related to dependency inversion&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem:
&lt;/h2&gt;

&lt;p&gt;Assume that we have a nodejs app and we need to use a library that generates a random number; by googling this, we could find quite a few of them, and we decide to use the library &lt;code&gt;x-random-generator&lt;/code&gt; and we need to do this to generate a random number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;xRandomGenerator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;`x-random-generator`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;xRandomGeneration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateRandomNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and let's say that this library generates also random IDs and we will use it like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;xRandomGenerator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;`x-random-generator`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;xRandomGeneration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateRandomId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we went ahead and used this in our code, and we used this library in up to &lt;strong&gt;X number&lt;/strong&gt; of files, and everything is working fine.&lt;/p&gt;

&lt;p&gt;After a while, the app grows a little bit more, and now we have a new feature that needs to use a random username using only a special set of characters. we went back to our library and after reading its documentation, we can see that we can't use it to generate the random username we need because this library uses a set of characters containing this &lt;code&gt;-&lt;/code&gt; and  &lt;code&gt;_&lt;/code&gt;, but those are not allowed in our username so what should we do now?&lt;/p&gt;

&lt;p&gt;we went ahead and found a cool library called &lt;code&gt;y-random-generator&lt;/code&gt; that provides this feature as well as random numbers and random IDs; and because we can't use both of them, so we need to replace the old one with this one, and because we have used it in many places, we will have to touch all the files that used the old library, and this is never a good idea specially if the new library have a different interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution:
&lt;/h2&gt;

&lt;p&gt;to avoid this problem we will have to hide our dependencies, no part of our app should ever know which library this part of code is coming from, only one component should know that, and we should use it abstract only the methods that we need to use out of the large library we use.&lt;br&gt;
this component will look this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;yRandomGenerator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;`x-random-generator`&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;randomNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yRandomGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateRandomNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;randomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yRandomGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateRandomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;randomUsername&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yRandomGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateRandomUsername&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We may use this new component across our entire application, and whenever we wish to switch to a different library —even a one that might even have a very different interface— this component can act as an adopter to ensure that the code still functions properly for our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ZRandomGenerator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;`z-random-generator`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zRandomGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ZRandomGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zRandomUsernameGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ZRandomGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abcdefghijklmnopqrstuvwxyz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;randomNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;zRandomGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;randomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;zRandomGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;randomUsername&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;zRandomUsernameGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  conclusion:
&lt;/h2&gt;

&lt;p&gt;To assist lessen the coupling to our dependents and to give ourself a little more freedom when we wish to update or change one of them, we should always aim to hide our dependencies under a layer of abstraction. and This even supports the "&lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;".&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>api</category>
      <category>patterns</category>
    </item>
  </channel>
</rss>
