<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Building Blocks with Abraar]]></title><description><![CDATA[Building Blocks with Abraar]]></description><link>https://blog.a26nine.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1674129539734/FP3kBUNqc.png</url><title>Building Blocks with Abraar</title><link>https://blog.a26nine.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 22 Apr 2026 02:22:20 GMT</lastBuildDate><atom:link href="https://blog.a26nine.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[QuickNode: The Quickest Solana Node Provider]]></title><description><![CDATA[ℹ
This article was officially published by QuickNode on March 14, 2023, and can be accessed here: QuickNode: The Quickest Solana Node Provider.


The Web3 domain is rapidly progressing every day. However, developers and even end-users feel a void bec...]]></description><link>https://blog.a26nine.dev/quicknode-the-quickest-solana-node-provider</link><guid isPermaLink="true">https://blog.a26nine.dev/quicknode-the-quickest-solana-node-provider</guid><category><![CDATA[QuickNode]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Solana]]></category><dc:creator><![CDATA[Abraar Ahmed]]></dc:creator><pubDate>Mon, 13 Mar 2023 20:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1757469525884/1a448451-5752-4aa8-bd13-6964c59af0d8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">This article was officially published by QuickNode on March 14, 2023, and can be accessed here: <a target="_self" href="https://blog.quicknode.com/quicknode-the-quickest-solana-node-provider/">QuickNode: The Quickest Solana Node Provider</a>.</div>
</div>

<p>The <a target="_blank" href="https://ethereum.org/en/web3/?ref=quicknode-blog"><em>Web3</em></a> domain is rapidly progressing every day. However, developers and even end-users feel a void because the underlying blockchain infrastructure is not quick enough to provide an ideal user experience (UX) like that of Web2.</p>
<p>In the previous article, <em>"</em><a target="_blank" href="https://blog.a26nine.dev/justifying-quick-in-quicknode"><em>Justifying Quick in QuickNode: A Response Time Comparison of Blockchain Node Providers</em></a><em>,"</em> we discussed the importance of application performance for Web3 adoption. Additionally, we compared the response times of various blockchain node providers using an ideal model to measure the fastest provider for <em>Ethereum</em> and other EVM-based blockchains (<em>Polygon</em> and <em>BNB Smart Chain</em>). Finally, we concluded that <strong>QuickNode is the quickest and most stable blockchain node provider</strong>.</p>
<p>The <a target="_blank" href="https://ethereum.org/en/web3/?ref=quicknode-blog"><em>Web3</em></a> domain is rapidly progressing every day. However, developers and even end-users feel a void because the underlying blockchain infrastructure is not quick enough to provide an ideal user experience (UX) like that of Web2.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/image-6.png" alt="Ethereum Response Time Overview (Global)" /></p>
<p>That said, not all blockchains are equal. Every chain has a different architecture and, hence, unique requirements. The performance results of <em>Chain A</em> do not hold true for <em>Chain B</em>, and vice versa. While Ethereum and EVM-based blockchains are somewhat similar, a blockchain like <em>Solana</em> is a different ballgame altogether.</p>
<p>In this article, we will compare the performance and data reliability of blockchain node providers to determine who provides the best infrastructure experience for the <a target="_blank" href="https://www.quicknode.com/chains/sol?utm_source=blog&amp;utm_medium=post&amp;utm_content=response-time-comparison-solana">Solana blockchain</a>.</p>
<h3 id="heading-the-rise-of-solana">The Rise of Solana</h3>
<p>Countless blockchains have come and gone, but none have stood the test of time like Ethereum. That's why Ethereum is considered the "gold standard" of programmable blockchains. While every other blockchain yearned to be the "Ethereum killer," Solana, the new kid on the block, took a different approach.</p>
<p>In 2017, Solana's founder, <em>Anatoly Yakovenko</em>, outlined a novel approach for blockchain timekeeping, called <em>Proof of History (PoH)</em>, in his draft (later published as the <a target="_blank" href="https://solana.com/solana-whitepaper.pdf?ref=blog.quicknode.com">Official Whitepaper</a>). Eventually, PoH and other <a target="_blank" href="https://solana.com/news/8-innovations-that-make-solana-the-first-web-scale-blockchain?ref=blog.quicknode.com">vital innovations</a> enabled Solana to achieve <a target="_blank" href="https://www.nansen.ai/research/solana-scalability-through-speed?ref=quicknode-blog">a throughput of 65,000 transactions per second (TPS), with a theoretical throughput of 710,000 TPS in the future</a>.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🚀</div>
<div data-node-type="callout-text"><em>As of writing this article, Solana is processing upwards of 5,000 TPS on its Mainnet and has processed over 150 billion transactions in under three years.</em></div>
</div>

<p>Solana's innovative approach has opened many doors for blockchain scalability, but has also introduced new challenges, such as managing blockchain infrastructure.</p>
<h3 id="heading-node-providers-as-deliverers">Node Providers as Deliverers</h3>
<p>Running a Solana node to communicate with the blockchain is a demanding task. It requires powerful hardware (<a target="_blank" href="https://docs.solana.com/running-validator/validator-reqs?ref=blog.quicknode.com">a minimum of 16 cores CPU with 256 GB RAM</a>) and constant maintenance to keep up with the block time of <a target="_blank" href="https://solana.com/?ref=blog.quicknode.com">400 milliseconds</a>. A small slip can lead to an unreliable local state of the blockchain.</p>
<p>This is where Solana node providers come to the rescue. They run and manage Solana nodes in-house and provide access to developers through an API endpoint.</p>
<h3 id="heading-not-all-providers-are-equal">Not All Providers Are Equal</h3>
<p>As mentioned earlier, Solana is different from other blockchains. Running a node with the validator software and exposing it over an API is not sufficient, as Solana's architecture is sophisticated.</p>
<p>At a minimum, it requires <a target="_blank" href="https://docs.solana.com/running-validator/validator-start?ref=blog.quicknode.com">system optimization</a>, constant monitoring, and management of <a target="_blank" href="https://docs.solana.com/implemented-proposals/rpc-transaction-history?ref=blog.quicknode.com">long-term persistent storage</a>. The first two are straightforward, but managing storage with a <a target="_blank" href="https://github.com/solana-labs/solana-bigtable?ref=blog.quicknode.com"><em>BigTable</em></a> instance is not.</p>
<p>While the Solana Foundation team provides a publicly accessible BigTable, it's not ideal for running self-hosted nodes. So, when running your own BigTable instance, factors such as hardware quality play a crucial role in the overall RPC performance.</p>
<p>As we dig deeper, differences between Solana node providers become more visible due to such factors. Therefore, it's important to compare the performance of these node providers with a realistic model and an unbiased approach to choose the best provider for your needs. In the following sections, we will do just that.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">📄</div>
<div data-node-type="callout-text"><em>Before moving forward, we strongly recommend reading the previous article in this series, "</em><a target="_self" href="https://blog.quicknode.com/justifying-quick-in-quicknode-response-time-comparison-of-various-blockchain-node-providers/"><em>Justifying Quick in QuickNode: A Response Time Comparison of Blockchain Node Providers</em></a><a target="_self" href="https://blog.quicknode.com/justifying-quick-in-quicknode-response-time-comparison-of-various-blockchain-node-providers/"><em>," as it supplements the next sections.</em></a></div>
</div>

<h2 id="heading-comparing-solana-response-times">Comparing Solana Response Times</h2>
<p>We discussed in the previous article that response time is not solely latency, but the sum of the <em>round-trip time (RTT)</em> and the <em>service time</em>. That is, the total time taken for a request to reach the destination, be processed, and sent back to the source as a response.</p>
<p>To measure accurate response time with complete fairness, we will use the same comparison model used earlier with these seven essential points:</p>
<ol>
<li><p>Using paid accounts.</p>
</li>
<li><p>Calling RPC methods that are not easily cacheable.</p>
</li>
<li><p>Using multiple cloud providers.</p>
</li>
<li><p>Testing from multiple locations.</p>
</li>
<li><p>Making concurrent test calls.</p>
</li>
<li><p>Conducting continuous and frequent tests.</p>
</li>
<li><p>Keeping the data untampered.</p>
</li>
</ol>
<h3 id="heading-running-the-response-time-tests">Running The Response Time Tests</h3>
<p>We have an internal comparison framework called <em>QuickLee</em> ("Quickly"), which is built using the above model and is being used to run these tests. It ticks all the boxes:</p>
<ol>
<li><p>We use API endpoints created through paid accounts for the following providers:<br /> a. Alchemy<br /> b. Ankr<br /> c. Chainstack<br /> d. Pokt Network (<em>Registered, not paid, as no self-serve option available</em>)<br /> e. QuickNode</p>
</li>
<li><p>We make test calls using the <a target="_blank" href="https://www.quicknode.com/docs/solana/getBalance?ref=blog.quicknode.com"><em>getBalance</em></a> RPC method to query the balance of a specific wallet address. The wallet address used as a parameter remains the same for all tests.</p>
</li>
<li><p>We use multiple cloud providers where QuickNode doesn't host its own infrastructure <em>(while the others do, which is acceptable to us)</em>:<br /> a. Amazon Web Services (AWS)<br /> b. Digital Ocean (DO)</p>
</li>
<li><p>We set up multiple servers in various geographical locations globally:<br /> a. AWS<br /> i. Ohio (US-E)<br /> ii. Northern California (US-W)<br /> iii. Frankfurt (EU)<br /> iv. Tokyo (AP)<br /> b. DO<br /> i. New York (US-E)<br /> ii. London (EU)<br /> iii. Singapore (AP)</p>
</li>
<li><p>We created a script using <a target="_blank" href="https://go.dev/?ref=quicknode-blog"><em>Go</em></a> that makes concurrent test calls to all providers.</p>
</li>
<li><p>We make test calls every 10 seconds, which means we have 6 data points for each provider every minute.</p>
</li>
<li><p>We pipe the test data without any interference into <a target="_blank" href="https://www.datadoghq.com/?ref=quicknode-blog"><em>DataDog</em></a>. Each test, or call, records the total response time along with other metadata, such as the response status code.</p>
</li>
</ol>
<p>Finally, we create multiple charts in Datadog to answer various questions. The charts reflect the results in the selected timeframe.</p>
<p>We have created an <em>Overview</em> table with multiple columns:</p>
<ul>
<li><p><em>(Provider) Name</em></p>
</li>
<li><p><em>Average Response Time</em> <a target="_blank" href="https://docs.datadoghq.com/dashboards/querying/?ref=quicknode-blog#aggregate-and-rollup">aggregated by Datadog</a> using the response time data points.</p>
</li>
<li><p><em>Total Calls</em></p>
</li>
<li><p><em>Failed Calls</em></p>
</li>
<li><p><em>Availability</em> calculated using <em>Total Calls</em> and <em>Failed Calls</em>: <code>((Total Calls - Failed Calls) / Total Calls) * 100</code></p>
</li>
</ul>
<p>Every region-specific section has:</p>
<ul>
<li><p><a target="_blank" href="https://docs.datadoghq.com/dashboards/widgets/timeseries/?ref=quicknode-blog"><em>Timeseries Graph</em></a> drawn using the average response time. We have applied a 5-point <a target="_blank" href="https://docs.datadoghq.com/dashboards/functions/smoothing/?ref=quicknode-blog#median-5"><em>rolling median</em></a> function to the chart to remove outliers and cleanly visualize the stability.</p>
</li>
<li><p><a target="_blank" href="https://docs.datadoghq.com/dashboards/widgets/top_list/?ref=quicknode-blog#pagetitle"><em>Top List</em></a> populated based on the average response time in the region.</p>
</li>
</ul>
<h3 id="heading-which-solana-node-provider-is-the-fastest">Which Solana Node Provider Is The Fastest?</h3>
<p>For the comparison in the article, we will use data <strong>from Jan 22, 2023, 00:00 UTC to Feb 18, 2023, 00:00 UTC (4 weeks).</strong> We have more than 1 million data points (for each provider) in this timeframe, which is sufficient to make an unbiased and clear comparison.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/CleanShot-2023-03-14-at-12.14.02@2x.png" alt="Overview" /></p>
<p>In terms of availability, all providers were able to hit the 99.9% mark, except for Ankr (99.6%). <strong>Chainstack and QuickNode had the least failed calls, with 14 and 51 calls, respectively.</strong></p>
<p><strong>QuickNode had the fastest global average response time at 104 ms</strong>, followed by Chainstack and Alchemy with 361 ms and 401 ms, respectively. <strong>Overall, QuickNode was almost 3.5x faster than the next best provider.</strong></p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/CleanShot-2023-03-14-at-12.18.58@2x.png" alt="Average Response Time (Global)" /></p>
<p>Moreover, <strong>QuickNode appeared to be the most stable</strong> with minimal fluctuations globally.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/Snap-20230314-143008.gif" alt="Global Stability" /></p>
<p><strong>QuickNode was also the quickest provider across all regions, with an average response time of 115 ms, 54 ms, and 139 ms in the US, EU, and AP, respectively.</strong></p>
<p>In the US, QuickNode and Chainstack were the only providers with a response time under 200ms. In the EU, the difference between QuickNode and the Chainstack (runner-up) was almost 6x, with 54 ms and 300 ms, respectively. In AP, all providers except QuickNode struggled. While QuickNode had an average response time of 139 ms, the next provider in line, Chainstack, had an average response time of 699 ms.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/CleanShot-2023-03-14-at-12.19.36@2x.png" alt="Average Response Time (US)" /></p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/CleanShot-2023-03-14-at-12.19.47@2x.png" alt="Average Response Time (EU)" /></p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/CleanShot-2023-03-14-at-12.19.57@2x.png" alt="Average Response Time (AP)" /></p>
<p><strong>The results above demonstrate that QuickNode is the top-performing provider globally and across all regions.</strong> Chainstack offers decent performance, followed by Alchemy, but they are still far behind.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/solana-node-provider-comparison-table.png" alt="Solana Response Time Overview (Global)" /></p>
<h2 id="heading-verifying-data-reliability">Verifying Data Reliability</h2>
<p>One of the biggest challenges faced by blockchain node providers and developers is data reliability. Even if you receive super-fast response times, stale data can degrade your application's performance. This is especially true for applications that use an extremely fast blockchain like Solana.</p>
<p>For example, Solana checks for the latest <em>blockhash</em> before sending a transaction, and if the data is even a minute old, the transaction won't go through. Thus, data reliability is of utmost significance.</p>
<p>Imagine operating a crypto wallet or running an NFT mint website. An instance of unreliable data can break your product's functionality. And if this happens too often, your customers will start looking for alternatives.</p>
<h3 id="heading-the-data-reliability-verification-model">The Data Reliability Verification Model</h3>
<p>Any data reliability verification model needs to check three essential things:</p>
<ol>
<li><p>Is the data up-to-date?</p>
</li>
<li><p>Is there any lag in receiving the latest data?</p>
</li>
<li><p>Does the data update regularly and frequently?</p>
</li>
</ol>
<p>We created an open-source tool, <a target="_blank" href="https://github.com/a26nine/sol-block-derby?ref=blog.quicknode.com"><em>Solana Block Derby</em></a>, that uses these three key pieces, along with the parts of the framework used for response time comparison. It queries the latest <em>slot</em> number from Solana node providers concurrently, calculates the winner(s), and stores them in a <a target="_blank" href="https://www.postgresql.org/?ref=blog.quicknode.com"><em>PostgreSQL</em></a> database. At any point, you can query the database to find the answer to the above questions.</p>
<h3 id="heading-running-the-data-reliability-test">Running the Data Reliability Test</h3>
<p>We ran Solana Block Derby <strong>from Feb 26, 2023, to March 1, 2023,</strong> with a timeout of 3 seconds and an interval of 5 seconds. The tool was run in parallel from three locations covering the US, EU, and AP. The response data was inserted into a database in real-time, and we collected <a target="_blank" href="https://github.com/a26nine/sol-block-derby/blob/main/sql/data/sol-block-derby.csv?ref=blog.quicknode.com">100,000 entries</a> for each provider by the end of the test.</p>
<h3 id="heading-which-solana-node-provider-is-the-most-reliable">Which Solana Node Provider Is The Most Reliable?</h3>
<p>To accurately measure data reliability, we need to account for all three factors listed above. So, let’s examine each of them one by one.</p>
<p>For the latest available slot data, <strong>QuickNode won the most rounds with 77,845 wins, followed by Chainstack with 56,978 wins, and Pokt Network with 54,508 wins.</strong> This means that out of every 100 calls, QuickNode provides the latest slot data 78 times.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/Latest-available-Data.png" alt="Wins" /></p>
<p>Timeout results were similar, with <strong>Alchemy timing out the least with 67 calls, followed by QuickNode with 70 calls, and Chainstack with 108 calls.</strong> Pokt Network timed out 16,326 calls and Ankr timed out 25,531 calls, meaning they timed out 20-30 times out of every 100 calls, demonstrating substantial lag in sending the latest data.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/Timeouts-1.png" alt="Timeouts" /></p>
<p>As for updated data frequency, <strong>Pokt Network had the lowest duplicate percentage with 12.95%, followed by QuickNode with 15.58%, and Chainstack with 16.29%.</strong> Ankr and Alchemy had the highest duplicate percentages with 23.01% and 23.11%, respectively, indicating that they returned the same value 23 times out of every 100 calls, which suggests stale data.</p>
<p><img src="https://blog.quicknode.com/content/images/2023/03/Stale-Data-1.png" alt="Duplicates Percentage" /></p>
<p>Combining all three factors, <strong>QuickNode had the most wins with negligible timeouts and fewer duplicates compared to the others, exhibiting superior data reliability.</strong> Chainstack loosely followed QuickNode in terms of data reliability with fewer wins, similar timeouts, and duplicate percentages.</p>
<h2 id="heading-quicknode-provides-the-best-solana-infrastructure-experience">QuickNode Provides The Best Solana Infrastructure Experience</h2>
<p>It is easy to conclude that QuickNode provides the quickest response times for Solana globally, as well as the highest data reliability and stability. Achieving this feat requires more than just running the validator software. It takes innovation, similar to Solana, to meet all the requirements and maintain consistency. QuickNode continually develops powerful elements with exceptional capabilities that work alongside regular Solana RPC to provide maximum efficiency for developers. This is how QuickNode excels!</p>
<p>Lastly, the purpose of this ongoing exercise is to set and maintain high standards, ensuring that we are pushing the blockchain ecosystem forward. Being an infrastructure provider and building an ecosystem around it takes time, effort, and experience. Quantifying the quality of a service requires data-driven decision-making, not biased numbers or gimmicky keywords. Ultimately, these insights help us improve the industry and support builders, which is the end goal.</p>
<h2 id="heading-appendix">Appendix</h2>
<ul>
<li><p>Solana Block Derby Data Dump — <a target="_blank" href="https://github.com/a26nine/sol-block-derby?ref=blog.quicknode.com">GitHub Repository</a> | <a target="_blank" href="https://github.com/a26nine/sol-block-derby/blob/main/sql/queries/?ref=blog.quicknode.com">SQL Queries</a> | <a target="_blank" href="https://github.com/a26nine/sol-block-derby/blob/main/sql/data/sol-block-derby.csv?ref=blog.quicknode.com">Data Dump</a> (CSV)</p>
</li>
<li><p><a target="_blank" href="https://blog.a26nine.dev/justifying-quick-in-quicknode">Justifying Quick in QuickNode: A Response Time Comparison of Blockchain Node Providers</a></p>
</li>
</ul>
<h2 id="heading-why-quicknode">Why QuickNode?</h2>
<p><a target="_blank" href="https://www.quicknode.com/signup?utm_source=blog&amp;utm_medium=post&amp;utm_content=response-time-comparison-solana">QuickNode</a> is an affordable, globally-distributed, multi-chain, multi-client, premium Web3 infrastructure provider, powering industry leaders like 1inch, MagicEden, Exodus, and Nansen, to name a few. QuickNode serves more than 7 billion API requests per day <em>(at the time of writing this article)</em>. Here's <a target="_blank" href="https://blog.quicknode.com/why-businesses-choose-quicknode-for-web3-infrastructure/"><em>why businesses choose QuickNode for Web3 infrastructure</em></a><em>!</em></p>
<p>Moreover, QuickNode is not only a blockchain node provider for 18+ chains but also an ecosystem in itself with a full suite of blockchain APIs and products — <a target="_blank" href="https://www.quicknode.com/core-api?ref=blog.quicknode.com">Core API</a>, <a target="_blank" href="https://www.quicknode.com/token-api?ref=blog.quicknode.com">Token API</a>, <a target="_blank" href="https://marketplace.quicknode.com/add-on/token-and-nft-api-v2-bundle?ref=blog.quicknode.com">NFT API</a>, <a target="_blank" href="https://developers.icy.tools/?ref=blog.quicknode.com">GraphQL API</a>, <a target="_blank" href="https://www.quicknode.com/quickalerts?ref=blog.quicknode.com">QuickAlerts</a> — and the first of its kind, blockchain API <a target="_blank" href="https://www.quicknode.com/marketplace?ref=blog.quicknode.com">Marketplace</a>.</p>
<p>We say, "Do your stuff —build — and let us take care of the rest!"</p>
]]></content:encoded></item><item><title><![CDATA[Justifying Quick in QuickNode: A Response Time Comparison of Blockchain Node Providers]]></title><description><![CDATA[ℹ
This article was officially published by QuickNode on December 6, 2022, and can be accessed here: Justifying Quick in QuickNode: A Response Time Comparison of Blockchain Node Providers.


A couple of decades ago, an average Internet user would have...]]></description><link>https://blog.a26nine.dev/justifying-quick-in-quicknode</link><guid isPermaLink="true">https://blog.a26nine.dev/justifying-quick-in-quicknode</guid><category><![CDATA[QuickNode]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Polygon]]></category><category><![CDATA[BSC]]></category><dc:creator><![CDATA[Abraar Ahmed]]></dc:creator><pubDate>Mon, 05 Dec 2022 20:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1757468797725/cdcd9d2b-4b0e-4436-8730-873421724a87.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">This article was officially published by QuickNode on December 6, 2022, and can be accessed here: <a target="_self" href="https://blog.quicknode.com/justifying-quick-in-quicknode-response-time-comparison-of-various-blockchain-node-providers/">Justifying Quick in QuickNode: A Response Time Comparison of Blockchain Node Providers</a>.</div>
</div>

<p>A couple of decades ago, an average Internet user would have been satisfied with an email delivered to the recipient in a few minutes. However, today, it's a different case — a product would not see the light if it's not fast enough. <em>"</em><a target="_blank" href="https://qz.com/1705375/a-complete-guide-to-the-evolution-of-the-internet?ref=blog.quicknode.com"><em>Speed helped make the internet what it has become.</em></a><em>"</em></p>
<p>Similarly, one of the primary causes hindering the mainstream adoption of <a target="_blank" href="https://ethereum.org/en/web3/?ref=blog.quicknode.com"><em>Web3</em></a> is the overall user experience (UX). The poor UX of Web3 applications can be pinned down to many things, mainly the application performance — speed.</p>
<h3 id="heading-application-performance-in-web3">Application Performance In Web3</h3>
<p>Application performance is a broad term covering many aspects, but we can boil it down to measuring an application's real-world performance and availability. More specifically (maintaining the context of this article), it's how fast the application loads and responds to user interactions. Whether Web2 or Web3, this is a crucial aspect of any application's adoption. While much has been done in the Web2 space to tackle this issue, the Web3 domain is still struggling.</p>
<h3 id="heading-a-case-for-performance-why-does-it-matter">A Case for Performance — Why Does It Matter?</h3>
<p>According to research, <a target="_blank" href="https://neilpatel.com/blog/speed-is-a-killer/?ref=blog.quicknode.com">47 percent of users will leave a website</a> if it does not load in two seconds, and <a target="_blank" href="https://techjury.net/blog/app-usage-statistics/?ref=blog.quicknode.com">70 percent of mobile app users will abandon an app</a> if it takes too long to load. It means the users would jump ship in favor of a competitor due to inadequate performance.</p>
<p>With Web3, this performance stack has an additional layer: continuous interaction with the blockchain. An event doesn't exist if it's not recorded on the blockchain, i.e., there's an always-on blockchain communication layer in any Web3 application.</p>
<p>Imagine running a DeFi / DEX aggregator like <a target="_blank" href="https://app.1inch.io/?ref=blog.quicknode.com">1inch</a>, providing a non-custodial wallet solution like <a target="_blank" href="https://www.exodus.com/?ref=blog.quicknode.com">Exodus</a>, or presenting an NFT marketplace like <a target="_blank" href="https://magiceden.io/?ref=blog.quicknode.com">MagicEden</a>. Could you risk your application performance because of this blockchain communication layer? The answer should be clear.</p>
<h3 id="heading-innovation-of-fast-blockchains">Innovation of Fast Blockchains</h3>
<p>The days of Bitcoin are far behind when one had to wait long for transactions to be processed. After the advent of Ethereum, things changed massively. Additionally, Layer 2 solutions built on Ethereum enhanced its efficiency. And then blockchains like Solana took it a step further by <a target="_blank" href="https://www.nansen.ai/research/solana-scalability-through-speed?ref=blog.quicknode.com">eyeing a throughput of 65,000 transactions per second (TPS), with a theoretical throughput of 710,000 TPS in the future</a>. The blockchain space is advancing rapidly; however, these numbers would become a reality only when the underlying infrastructure is robust enough to support the ambitious goals of these blockchains.</p>
<h3 id="heading-introducing-blockchain-node-providers">Introducing Blockchain Node Providers</h3>
<p>Unlike in earlier days when you could run a node on an ordinary computer, things have changed drastically. Running a node now to support your production-ready application requires ample resources — it can be hectic. You not only require costly hardware with massive specifications to set up and run the node, but you also need a full-proof plan to manage that infrastructure regularly. And, with time, these requirements are set to increase. For example, when writing this article, <a target="_blank" href="https://docs.solana.com/running-validator/validator-reqs?ref=blog.quicknode.com">Solana requires a minimum of 12 cores CPU with 128 GB RAM to run its blockchain client</a>.</p>
<p>Node providers come in to solve this dilemma. They run and manage blockchain nodes in-house and usually provide end-users access over an API endpoint, often utilizing blockchain RPC technology. RPC providers act as a bridge between the application and the blockchain, allowing developers to interact with the blockchain without the need to run a full node themselves. As stated earlier, running and managing nodes takes much work, so most of the industry players, including prominent ones, trust and leverage the services of these node providers to power their applications.</p>
<p>Lately, we have seen many new players emerge in this industry, claiming to be the fastest node provider without any evident data. Hence, it's crucial to quantify the quality of the providers transparently as we move forward. In the following sections, we will define a methodology and then compare and discuss the response times of various blockchain node providers in the Web3 space, taking into account factors such as their infrastructure, API performance, and utilization of blockchain RPC technology.</p>
<h2 id="heading-methodology-for-comparing-response-time-of-blockchain-node-provider-services">Methodology for Comparing Response Time of Blockchain Node Provider Services</h2>
<p>We have seen many tools and discussions pop up in the recent past comparing the response time of blockchain node provider services. However, most of them are flawed at the methodological level — doing one-off tests, using free tier accounts, testing easily cacheable methods, tampering with data as a part of the methodology, etc. Hence, it's essential to have an unbiased and neutral approach to perform this comparison and also build this model realistically.</p>
<h3 id="heading-what-is-response-time">What Is Response Time?</h3>
<p>Before diving into other things, it's essential to understand that response time is not solely latency. It's the summation of the round-trip time (RTT) and the service time, i.e., the total time taken for a request to reach the destination, be processed, and sent back to the source as a response. The response time can be divided into multiple layers — DNS resolution time, TCP connection time, SSL handshake time, time to first byte, and download time. Understanding this is the foundation for building a solid response time comparison methodology for blockchain node provider services.</p>
<h3 id="heading-creating-a-realistic-comparison-model">Creating a Realistic Comparison Model</h3>
<p>We have laid down the critical points required to ensure complete fairness when running the tests and gathering the data, as well as replicating a real-world use case:</p>
<ol>
<li><p><strong>Paid accounts</strong> - Most providers comment that their free tier is not the most performant. Therefore, using a paid account (wherever available) is crucial.</p>
</li>
<li><p><strong>Not easily cacheable blockchain RPC method</strong> - Some blockchain methods are easily cacheable and can be served without putting any stress on the system. So, choosing an RPC method that engages the system and puts some pressure on it would be essential.</p>
</li>
<li><p><strong>Multiple cloud/hosting providers</strong> - Running the tests using a cloud/hosting provider where self-infrastructure is hosted can introduce a considerable bias. Hence, the tests must be run using multiple unrelated cloud/hosting providers.</p>
</li>
<li><p><strong>Multiple locations</strong> - Node performance can differ from region to region due to various factors — what looks good from the US may not look good from the EU, and vice-versa. Hence, the tests must be executed from multiple locations globally.</p>
</li>
<li><p><strong>Concurrent test calls</strong> - The state of blockchains changes every second, so conducting these tests one after another can paint inaccurate response times. Thus, the test calls should be made concurrently for all the providers.</p>
</li>
<li><p><strong>Continuous and frequent tests</strong> - The real-world use of blockchain nodes is persistent and doesn't stop. To replicate this use case, running tests and collecting data frequently for an extended period is vital.</p>
</li>
<li><p><strong>Untampered data</strong> - When critically analyzing data, it's imperative to have unbiased and unmodified data, which means the data should be passed to the next stage without manipulation.</p>
</li>
</ol>
<h3 id="heading-executing-the-proposed-model">Executing the Proposed Model</h3>
<p>Following the above points, we developed an internal tool for this purpose, <em>QuickLee</em>. It ticks all the boxes:</p>
<ol>
<li><p>We created paid accounts/API endpoints for the following services and are using those in the tests:<br /> a. Alchemy<br /> b. Ankr<br /> c. Chainstack<br /> d. GetBlock<br /> e. Infura</p>
</li>
<li><p>We are making test calls using the <a target="_blank" href="https://www.quicknode.com/docs/ethereum/eth_getBalance?ref=blog.quicknode.com"><em>eth_getBalance</em></a> RPC method (for all the EVM-based chains). This method queries the balance of a wallet address at a specific block height (the <em>latest</em> in our case). Also, the wallet address used as the parameter remains the same for all the tests.</p>
</li>
<li><p>We are using multiple cloud/hosting providers for these tests, where QuickNode doesn't host their infrastructure (while the others do, which is acceptable to us):<br /> a. Amazon Web Services (AWS)<br /> b. Digital Ocean (DO)</p>
</li>
<li><p>With multiple cloud/hosting providers, we have also set up multiple servers in various geographical locations globally:<br /> a. AWS<br /> i. Ohio (US-E)<br /> ii. Northern California (US-W)<br /> iii. Frankfurt (EU)<br /> iv. Tokyo (AP)<br /> b. DO<br /> i. New York (US-E)<br /> ii. London (EU)<br /> iii. Singapore (AP)</p>
</li>
<li><p>We have created a script using <a target="_blank" href="https://go.dev/?ref=blog.quicknode.com"><em>Golang</em></a> that makes concurrent test calls to all the providers at a defined interval.</p>
</li>
<li><p>The calls are made once every 10 seconds, which means we have 6 data points for each provider every minute.</p>
</li>
<li><p>The test data is piped (without any interference) into <a target="_blank" href="https://www.datadoghq.com/?ref=blog.quicknode.com"><em>DataDog</em></a>. Each test—call — records the total response time along with other metadata, such as the response status code.</p>
</li>
</ol>
<h2 id="heading-visualizing-the-data">Visualizing the Data</h2>
<p>Using the data received in Datadog, we create multiple charts to answer various questions. These charts reflect the results in the selected timeframe.</p>
<h3 id="heading-whats-the-average-response-time-and-availability-of-each-node-provider">What's the Average Response Time and Availability of Each Node Provider?</h3>
<p>We have created an <em>Overview</em> table with multiple columns — Name, Average Response Time, Total Calls, Failed Calls, and Availability — sorted based on the Average Response Time.</p>
<ul>
<li><p><em>Average Response Time</em> is <a target="_blank" href="https://docs.datadoghq.com/dashboards/querying/?ref=blog.quicknode.com#aggregate-and-rollup">aggregated by Datadog</a> using the response time (data points).</p>
</li>
<li><p><em>Total Calls</em> are the total number of calls made to a provider, and <em>Failed Calls</em> are the number of failed calls for that provider.</p>
</li>
<li><p><em>Availability</em> is a percentage value calculated using <em>Total Calls</em> and <em>Failed Calls</em>: <code>((Total Calls - Failed Calls) / Total Calls) * 100</code></p>
</li>
</ul>
<h3 id="heading-which-node-provider-is-the-fastest-and-most-stable-globally-and-across-various-regions">Which Node Provider Is the Fastest and Most Stable — Globally and Across Various Regions?</h3>
<p>Every region-specific section — Global, US (United States), EU (Europe), AP (Asia-Pacific) — has a <a target="_blank" href="https://docs.datadoghq.com/dashboards/widgets/top_list/?ref=blog.quicknode.com#pagetitle"><em>Top List</em></a> and a <a target="_blank" href="https://docs.datadoghq.com/dashboards/widgets/timeseries/?ref=blog.quicknode.com"><em>Timeseries Graph</em></a>.</p>
<ul>
<li><p>The <em>Top List</em> is populated based on the average response time in the region and is sorted from lowest to highest.</p>
</li>
<li><p>The <em>Timeseries Graph</em> is a line chart drawn using the average response time. We have also applied a 5-point <a target="_blank" href="https://docs.datadoghq.com/dashboards/functions/smoothing/?ref=blog.quicknode.com#median-5"><em>rolling median</em></a> function to the chart to remove the outliers and cleanly visualize the stability. Furthermore, we have used a log scale graph instead of a linear one with the y-axis marker set to <em>750ms</em> to enhance chart readability.</p>
</li>
</ul>
<h2 id="heading-results-and-discussion">Results and Discussion</h2>
<p>Though we are running these tests for multiple chains, we will do a case study on <em>Ethereum</em> in this article <em>(Live dashboards for all the chains are available in the Appendix).</em> To compare and discuss, we will use two weeks of data — <strong>from Nov 9, 2022, 12:00 UTC to Nov 23, 2022, 12:00 UTC.</strong> This timeframe amounts to almost <strong>5 million data points</strong>, sufficient to make a fair comparison with around 600k calls made to each node provider.</p>
<p><img src="https://blog.quicknode.com/content/images/2022/12/node-provider-response-time-overview.png" alt="Overview" /></p>
<p>From an availability perspective, all the providers were able to hit the 99.9% mark except for GetBlock (80.4%) and Chainstack (99.7%). <strong>QuickNode had the least number of failed calls (2), followed by Ankr (3) and Infura (7).</strong></p>
<p>PS: GetBlock <a target="_blank" href="https://getblock.io/blog/getting-back-to-building-november-13-attack-post-mortem/?ref=blog.quicknode.com">reported an attack on their services</a> during this period.</p>
<p><strong>Looking at the global average response time, QuickNode triumphed with 86ms, followed by Ankr and Alchemy with 164ms and 207ms, respectively.</strong> <strong>Overall, QuickNode was almost 2x faster than the following best and 3x faster than the average response time of the rest of the providers, excluding GetBlock (254ms).</strong></p>
<p><img src="https://blog.quicknode.com/content/images/2022/12/global-average-response-time-node-providers-1.png" alt="Global Average Response Time" /></p>
<p>Not just that, <strong>QuickNode seemed to be the most stable with the slightest fluctuations globally.</strong></p>
<p><img src="https://blog.quicknode.com/content/images/2022/12/node-provider-response-time-global-average.gif" alt="Global Average Response Time Stability" /></p>
<p><strong>Regionally, QuickNode led the charge with an average response time of 45ms, 74ms, and 155ms in the US, EU, and AP, respectively.</strong> In the US, QuickNode was followed by Alchemy and Infura, with an average response time of 115ms and 133ms, respectively. In the EU, Chainstack gave tough competition to QuickNode with an average response time of 78ms, followed by Ankr with 154ms. In AP, most providers struggled with high response times — more than 200ms — except QuickNode, and Ankr, with an average response time of 155ms and 193 ms, respectively.</p>
<p><img src="https://blog.quicknode.com/content/images/2022/12/node-provider-response-time-us-average.png" alt="US Average Response Time" /></p>
<p><img src="https://blog.quicknode.com/content/images/2022/12/node-provider-response-time-eu-average.png" alt="EU Average Response Time" /></p>
<p><img src="https://blog.quicknode.com/content/images/2022/12/node-provider-response-time-ap-average.png" alt="AP Average Response Time" /></p>
<p><strong>The results above show that</strong> <a target="_blank" href="https://www.quicknode.com/signup?utm_source=blog&amp;utm_medium=post&amp;utm_content=response-time-comparison"><strong>QuickNode is the top performer</strong></a> <strong>globally across all the regions.</strong> Ankr and Alchemy exhibit decent performance following QuickNode; however, they are still far apart. Infura surprises in the US with an average response time of 133ms, while Chainstack surprises in the EU with an average response time of 78ms which is almost neck-and-neck with QuickNode.</p>
<p><img src="https://blog.quicknode.com/content/images/2022/12/global-average-response-time-overall-ranking.png" alt="Overall Ranking (Global Average Response Time)" /></p>
<h2 id="heading-quicknode-provides-the-fastest-response-times">QuickNode Provides the Fastest Response Times</h2>
<p>For Web3 to gain mass adoption, the UX needs to be pushed to the next level. And that could only happen with highly-performant applications powered by the finest infrastructure and service — nothing short of the best!</p>
<p>As evident through the data, we can conclude that QuickNode is the fastest and most stable node provider (for <em>Ethereum</em> in this case study). In Europe and Asia-Pacific, it gets some competition from Chainstack and Ankr, respectively. However, the overall performance of QuickNode is unmatched, and it outruns the others. The exact test is running for <em>Polygon</em> and <em>BNB Smart Chain</em>, and the results outline the same conclusion <em>(Live dashboards for all the chains are available in the Appendix).</em></p>
<p>Being an infrastructure provider and building an ecosystem around the same takes time, effort, and experience. The process of quantifying the quality of a service can only happen through data-driven decision-making and not by exhibiting biased numbers or throwing gimmicky keywords. Because eventually, these insights help us improve as an industry to support the builders — the end goal.</p>
<p>Lastly, the ultimate purpose here is to push the Web3 ecosystem forward. This exercise attempts to demonstrate a transparent, unbiased, and neutral perspective around the response time comparison of the blockchain node providers. Not only that, one of our objectives is to promote an industry-wide discussion about how we can align and take this forward together — we are all ears!</p>
]]></content:encoded></item><item><title><![CDATA[Build Ethereum Address Explorer using QuickNode]]></title><description><![CDATA[Are you creating a blockchain/Web3 application with a feature that interacts with the wallets on the blockchain? For that, do you have to write custom logic to fetch transactions of specific wallet addresses? It is a tiring process, isn't it? Fetch a...]]></description><link>https://blog.a26nine.dev/build-ethereum-address-explorer-using-quicknode</link><guid isPermaLink="true">https://blog.a26nine.dev/build-ethereum-address-explorer-using-quicknode</guid><category><![CDATA[QuickNode]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Abraar Ahmed]]></dc:creator><pubDate>Sat, 12 Nov 2022 08:00:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668218198982/fE_G3caRJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you creating a blockchain/Web3 application with a feature that interacts with the wallets on the blockchain? For that, do you have to write custom logic to fetch transactions of specific wallet addresses? It is a tiring process, isn't it? Fetch all the blocks; parse all the transactions; filter the wallet address(es).</p>
<p>Good news, <a target="_blank" href="https://www.quicknode.com/">QuickNode</a> has made this process easy for you! Now, you can fetch all the wallet transactions (and filter them) in a single API call with a simple RPC method — <code>qn_getTransactionReceiptsByAddress</code>. Yes, you read that right; one method! 😄</p>
<p>In this guide, we will create a simple Ethereum address explorer to see how the method works. Let's begin!</p>
<h4 id="heading-requirements">Requirements</h4>
<ul>
<li><p><strong>Python Web3 library</strong></p>
<pre><code class="lang-python">  pip3 install web3
</code></pre>
</li>
<li><p><strong>Streamlit</strong><br />  Streamlit is an open-source framework for building UI-based data apps in Python.</p>
<pre><code class="lang-python">  pip3 install streamlit
</code></pre>
</li>
<li><p><strong>QuickNode Endpoint</strong><br />  Register a free account on <a target="_blank" href="https://www.quicknode.com/">QuickNode</a> and verify your email address. Once verified, create an Ethereum-Mainnet endpoint.</p>
</li>
</ul>
<blockquote>
<p>As of Nov 11, 22, this method works with Ethereum-Mainnet and Ethereum-Goerli networks.</p>
</blockquote>
<h3 id="heading-buidl">BUIDL</h3>
<h4 id="heading-fetch-data-from-quicknode-api">Fetch data from QuickNode API</h4>
<ol>
<li><p><strong>Import components of the</strong> <code>web3</code> library</p>
<pre><code class="lang-python"> <span class="hljs-keyword">from</span> web3 <span class="hljs-keyword">import</span> Web3, HTTPProvider
</code></pre>
</li>
<li><p><strong>Create a connection to the endpoint</strong></p>
<pre><code class="lang-python"> w3 = Web3(HTTPProvider(YOUR_QUICKNODE_ENDPOINT_URL))
</code></pre>
</li>
<li><p>Get the wallet address from the user</p>
<pre><code class="lang-python"> address = input(<span class="hljs-string">"Wallet address: "</span>)
</code></pre>
</li>
<li><p><strong>Call the</strong> <code>qn_getTransactionReceiptsByAddress</code> method</p>
<pre><code class="lang-python"> txs = w3.provider.make_request(<span class="hljs-string">'qn_getTransactionReceiptsByAddress'</span>, [
         {
             <span class="hljs-string">"accounts"</span>: [address]
         }
     ])
</code></pre>
</li>
<li><p><strong>Print the response</strong></p>
<pre><code class="lang-python"> print(txs)
</code></pre>
</li>
</ol>
<p>Now, save the file, run it:</p>
<pre><code class="lang-python">python3 YOUR_FILE_NAME.py
</code></pre>
<p>and check the response. Here is what it should look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668232331919/JzCdUIBmp.gif" alt="Screenshot 2022-11-12 at 05.51.11.gif" /></p>
<p>We got the data. Now, it's time to</p>
<h4 id="heading-make-ui">Make UI</h4>
<ol>
<li><p><strong>Import the streamlit framework</strong></p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> streamlit <span class="hljs-keyword">as</span> st
</code></pre>
</li>
<li><p><strong>Redefine the address variable</strong><br /> In #3 <a class="post-section-overview" href="#heading-fetch-data-from-quicknode-api">above</a>, we stored the user input (wallet address) in the <code>address</code> variable. With streamlit, we will do the same but with the streamlit <code>text_input</code> component. So, we will change the <code>address</code> variable definition with the following:</p>
<pre><code class="lang-python"> address = st.text_input(<span class="hljs-string">"Wallet Address"</span>)
</code></pre>
</li>
<li><p><strong>Create the submit button</strong><br /> We will use the streamlit <code>button</code> component to create the submit button.</p>
<pre><code class="lang-python"> submit = st.button(<span class="hljs-string">"Fetch Txs"</span>)
</code></pre>
</li>
<li><p><strong>Call the</strong> <code>qn_getTransactionReceiptsByAddress</code> method<br /> This step and the following step will be part of the logical flow — if the <code>Fetch Txs</code> (submit) button is pressed. So, we will indent them in an <code>if</code> condition:</p>
<pre><code class="lang-python"> <span class="hljs-keyword">if</span> submit:
</code></pre>
</li>
<li><p>Now, we are going to use the same call from #4 <a class="post-section-overview" href="#heading-fetch-data-from-quicknode-api">above</a> (remove from there) and use it here:</p>
<pre><code class="lang-python">     txs = w3.provider.make_request(<span class="hljs-string">'qn_getTransactionReceiptsByAddress'</span>, [
         {
             <span class="hljs-string">"accounts"</span>: [address]
         }
     ])
</code></pre>
</li>
<li><p><strong>Iterate over the response and print the data</strong><br /> We will receive the data as a JSON object from the QuickNode API. So, we will have to access the <code>result</code> key of the object, iterate over the elements and print the data. In the first step, we will create a variable to store the data in a string with Markdown syntax. And in the next step, we will use Streamlit's <code>markdown</code> component to print the data to the UI.</p>
<pre><code class="lang-python">     <span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> txs[<span class="hljs-string">"result"</span>]:
         tx = (
             <span class="hljs-string">f'TxHash: **[<span class="hljs-subst">{r[<span class="hljs-string">"transactionHash"</span>]}</span>](https://etherscan.io/tx/<span class="hljs-subst">{r[<span class="hljs-string">"transactionHash"</span>]}</span>)**  \n From: **<span class="hljs-subst">{r[<span class="hljs-string">"from"</span>]}</span>**  \n To: **<span class="hljs-subst">{r[<span class="hljs-string">"to"</span>]}</span>**'</span>)
         st.markdown(tx)
</code></pre>
</li>
</ol>
<blockquote>
<p>If you notice, we are appending the transaction hash to the Etherscan URL. It is done to make it a clickable link that would open the transaction on Etherscan.</p>
</blockquote>
<p>That's it! Now we can run the script using streamlit: <code>streamlit run YOUR_FILE_NAME.py</code></p>
<p>It will give you a CLI output like this:</p>
<blockquote>
<p>You can now view your Streamlit app in your browser.</p>
<p>Local URL: http://localhost:8501 Network URL: http://192.168.29.35:8501</p>
</blockquote>
<p>Opening the <code>Local URL</code> will take you to the running instance of the (Streamlit) app in your browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668234194168/oP2Uw50w_.png" alt="Screenshot 2022-11-12 at 06.23.02.png" /></p>
<p>🧪 Now, enter the address, click the <code>Fetch Txs</code> button, and see the magic happen! ✨</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668234288915/UViF7OmbI.gif" alt="Screenshot 2022-11-12 at 06.23.31.gif" /></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We witnessed something magical — a logic that took much of your time and resources now takes a single API call. You saw it by creating your own Ethereum address explorer with a few lines of code. What an achievement! QuickNode — Making BUIDLing easy for the developers. 🚀</p>
<p>Lastly, there's more to the <code>qn_getTransactionReceiptsByAddress</code> method:</p>
<ul>
<li><p>Filter block range — From/To block</p>
</li>
<li><p>Filter address — From/To address</p>
</li>
<li><p>Sort transactions</p>
</li>
<li><p>Use pagination</p>
</li>
</ul>
<p>We only covered a small aspect of this method. For more, you can refer to the <a target="_blank" href="https://www.quicknode.com/docs/ethereum/qn_getTransactionReceiptsByAddress">official documentation</a>.</p>
<p>Until next time... 🫡</p>
<h3 id="heading-access">Access</h3>
<h4 id="heading-live-demo">Live Demo</h4>
<blockquote>
<p>⚠️ Please check the notice below.</p>
</blockquote>
<h4 id="heading-full-code">Full Code</h4>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="200734bfa8fdf245f211a5a9746173e7"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/a26nine/200734bfa8fdf245f211a5a9746173e7" class="embed-card">https://gist.github.com/a26nine/200734bfa8fdf245f211a5a9746173e7</a></div><p> </p>
<blockquote>
<p>⚠️ As of Dec 1, 2022, the method <em>qn_getTransactionReceiptsByAddress has been disabled by QuickNode. So, the above code will break. Once the method is reenabled, the code should work.</em></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Address Lookup Tables and Versioned Transactions on Solana]]></title><description><![CDATA[Solana is a high-performant blockchain that is currently doing an average of ~2.5k-3k transactions per second (TPS)1. Solana has a theoretical throughput of ~65k TPS, far from its current state. Hence, it would require tons of effort to scale to that...]]></description><link>https://blog.a26nine.dev/address-lookup-tables-and-versioned-transactions-on-solana</link><guid isPermaLink="true">https://blog.a26nine.dev/address-lookup-tables-and-versioned-transactions-on-solana</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Solana]]></category><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Abraar Ahmed]]></dc:creator><pubDate>Sun, 16 Oct 2022 12:03:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668245139200/0XLGi-PdD.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Solana is a high-performant blockchain that is currently doing an average of ~2.5k-3k transactions per second (TPS)<sup id="1"><a class="post-section-overview" href="#ft1">1</a></sup>. Solana has a theoretical throughput of ~65k TPS, far from its current state. Hence, it would require tons of effort to scale to that level.</p>
<p>To achieve this highly ambitious goal, the Solana Foundation team constantly updates the blockchain with new features, enhancements, and improvements. They can back this claim with data, as we can see that the team has made <a target="_blank" href="https://github.com/solana-labs/solana/commits/master">4349 commits</a> in the past one year<sup id="2"><a class="post-section-overview" href="#ft2">2</a></sup>.</p>
<p>Recently, they released a new feature '<a target="_blank" href="https://edge.docs.solana.com/developing/lookup-tables">Address Lookup Tables</a>'; and furthermore, another feature '<a target="_blank" href="https://edge.docs.solana.com/developing/versioned-transactions">Versioned Transactions</a>' to support the lookup tables.</p>
<p>In this guide, we will</p>
<ul>
<li>Learn about the Address Lookup Tables and the Versioned Transactions, and,</li>
<li>Create an Address Lookup Table and send a Versioned Transaction using it.</li>
</ul>
<h3 id="heading-versioned-transactions">Versioned Transactions</h3>
<p>Versioned Transactions are the new transaction format that provide additional runtime functionality to the transactions on the Solana blockchain. This means new transaction features would be available without changing the on-chain programs.</p>
<p>The first of these Versioned Transactions is a <code>v0</code> or <code>version 0</code> transaction that allows the use of an Address Lookup Table <a target="_blank" href="https://explorer.solana.com/address/AddressLookupTab1e1111111111111111111111111">program</a> in a transaction.</p>
<blockquote>
<p>Note: All the transactions in the old format would now be tagged as <code>legacy</code> version transactions.</p>
</blockquote>
<h3 id="heading-address-lookup-tables">Address Lookup Tables</h3>
<p>The Address Lookup Tables or lookup tables allow the developers to create a collection of related account addresses directly on-chain, empowering them to load more addresses in a single transaction efficiently.</p>
<p>A single account address is a 32-byte of arbitrary data on the Solana blockchain. And, every transaction on the Solana blockchain requires listing all the addresses it has interacted with during that transaction. This means that a single transaction can have a maximum of 35 addresses<sup id="3"><a class="post-section-overview" href="#ft3">3</a></sup> <sup id="4"><a class="post-section-overview" href="#ft4">4</a></sup>.</p>
<p>Using the lookup tables, each address can be referenced as a 1-byte index in the transaction (instead of a full 32-byte address). This method effectively compresses a 32-byte address into a 1-byte index value, allowing the users to store up to 256 addresses in a single transaction — 8x more than the old format!</p>
<p>Well, let us see it live... 👀</p>
<h3 id="heading-requirements">Requirements</h3>
<ul>
<li><p><strong>Node.js / Solana SDK</strong><br />Though you can use the programming language of your choice, we will use <em>Node.js</em> with the <code>@solana/web3.js</code> SDK in this guide.</p>
<ul>
<li>Install <a target="_blank" href="https://nodejs.org/en/download/">Node.js</a> on your local machine.</li>
<li>Install <a target="_blank" href="https://www.npmjs.com/package/@solana/web3.js">@solana/web3.js</a> using the Node Package Manager (NPM):<pre><code>npm i @solana/web3.js
</code></pre></li>
</ul>
</li>
<li><p><strong>RPC API endpoint (QuickNode)</strong><br />We will use <a target="_blank" href="https://www.quicknode.com/">QuickNode</a> as it provides the fastest, most stable, and most reliable RPC API endpoints. </p>
<ul>
<li><a target="_blank" href="https://www.quicknode.com/accounts/new-signup">Register</a> for a free account on QuickNode and verify your email address.</li>
<li>Create a Solana-Devnet endpoint.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665849947982/70EoeI3BF.gif" alt="Screenshot 2022-10-15 at 16.04.45.gif" /></li>
</ul>
</li>
<li><p><strong>Solana wallet (Phantom)</strong><br />You can use any Solana-compatible wallet that grants you access to your private keys. We will use the <a target="_blank" href="https://phantom.app/">Phantom</a> wallet because of its simple UI and smooth UX.</p>
<ul>
<li><a target="_blank" href="https://phantom.app/download">Download</a> the Phantom wallet for your browser.</li>
<li><a target="_blank" href="https://help.phantom.app/hc/en-us/articles/8071074929043-How-to-create-a-new-wallet">Create</a> a new wallet.</li>
<li>Change the Phantom wallet network to Devnet.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665850538576/VH7KAFHX4.gif" alt="Screenshot 2022-10-15 at 16.15.05.gif" /></li>
<li>Export your Private Key and <strong>store it somewhere safe</strong>. ❗️NEVER SHARE YOUR PRIVATE KEY WITH ANYONE ❗️
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665850786543/aCs8wnx35.gif" alt="Screenshot 2022-10-15 at 16.18.25.gif" /></li>
</ul>
</li>
</ul>
<blockquote>
<p>Tip: We can also use Solana's <a target="_blank" href="https://docs.solana.com/wallet-guide/file-system-wallet">File System Wallet</a> to generate a wallet Keypair using CLI without the need for the Phantom wallet.</p>
</blockquote>
<ul>
<li><strong>Solana faucet (QuickNode Faucet)</strong><br />We will require some test funds — SOL — to experiment. Again, QuickNode provides a free <a target="_blank" href="https://faucet.quicknode.com/">multi-chain faucet</a> to help us with this.<ul>
<li>Go to the <a target="_blank" href="https://faucet.quicknode.com/solana/devnet">Faucet webpage</a>.</li>
<li>Connect your (Phantom) wallet.</li>
<li>Select the <code>Solana</code> chain and <code>Devnet</code> network.</li>
<li>Follow the next steps to request your free 1 SOL on the Solana-Devnet.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665853069243/wNPOX-Zh7.gif" alt="Screenshot 2022-10-15 at 16.56.32.gif" /></li>
</ul>
</li>
</ul>
<p>That's all. We are set. 🏃🏻</p>
<h2 id="heading-lets-code">Let's Code!</h2>
<h3 id="heading-define-functions-and-variables">Define functions and variables</h3>
<h4 id="heading-1-import-required-modules">1. Import required modules</h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> solana = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@solana/web3.js'</span>);
<span class="hljs-keyword">const</span> bs58 = <span class="hljs-built_in">require</span>(<span class="hljs-string">'bs58'</span>);
</code></pre>
<p>Along with the <code>@solana/web3.js</code> SDK, we use the <code>bs58</code> module to decode our private key.</p>
<h4 id="heading-2-set-required-variables">2. Set required variables</h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> PRIVATE_KEY = [YOUR_PRIVATE_KEY_FROM_PHANTOM_WALLET];
<span class="hljs-keyword">const</span> ENDPOINT = [YOUR_QUICKNODE_ENDPOINT_URL];
</code></pre>
<p>Set the variable values with the ones you have.</p>
<h4 id="heading-3-add-account-addresses">3. Add account addresses</h4>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> tableEntries = [
  <span class="hljs-comment">// List of account addresses for address lookup table</span>
];
</code></pre>
<p>These account addresses will be added to the lookup table later and can be any valid account address on the Solana blockchain.</p>
<h4 id="heading-4-pause">4. <code>pause()</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pause</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">5000</span>)); <span class="hljs-comment">// Value in ms</span>
}
</code></pre>
<p>We will use this function to pause the app at a few stages to ensure that we are waiting and fetching the updated data from the blockchain.</p>
<h4 id="heading-5-createconn">5. <code>createConn()</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createConn</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> solana.Connection(ENDPOINT, <span class="hljs-string">'confirmed'</span>);
}
</code></pre>
<p> We will use this function to create an active (endpoint) connection to interact with the blockchain.</p>
<h4 id="heading-6-getlatestblockhash">6. <code>getLatestBlockhash()</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getLatestBlockhash = <span class="hljs-function">(<span class="hljs-params">connection</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> connection
        .getLatestBlockhash(<span class="hljs-string">'finalized'</span>)
        .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.blockhash);
};
</code></pre>
<p>We will need the latest blockhash to send the transactions. This function will use the active connection to fetch the latest blockhash from the blockchain.</p>
<h4 id="heading-7-createlookuptable">7. <code>createLookupTable()</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createLookupTable</span>(<span class="hljs-params">connection, payer</span>) </span>{
    <span class="hljs-keyword">const</span> [lookupTableInst, lookupTableAddress] =
        solana.AddressLookupTableProgram.createLookupTable({
            <span class="hljs-attr">authority</span>: payer.publicKey,
            <span class="hljs-attr">payer</span>: payer.publicKey,
            <span class="hljs-attr">recentSlot</span>: <span class="hljs-keyword">await</span> connection.getSlot(),
        });
    <span class="hljs-keyword">return</span> [lookupTableInst, lookupTableAddress];
}
</code></pre>
<p>We will use this function to create the lookup table by passing an active connection and account owner to it. It will return lookup table instructions and address, which we will use to register the lookup table on-chain through a transaction.</p>
<h4 id="heading-8-extendlookuptable">8. <code>extendLookupTable()</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">extendLookupTable</span>(<span class="hljs-params">payer, lookupTableAddress, addressList</span>) </span>{
    <span class="hljs-keyword">const</span> extendInst = solana.AddressLookupTableProgram.extendLookupTable({
        <span class="hljs-attr">addresses</span>: addressList,
        <span class="hljs-attr">authority</span>: payer.publicKey,
        <span class="hljs-attr">lookupTable</span>: lookupTableAddress,
        <span class="hljs-attr">payer</span>: payer.publicKey,
    });
    <span class="hljs-keyword">return</span> extendInst;
}
</code></pre>
<p>We will use this function to extend the lookup table by passing a list of account addresses. It will return lookup table instructions which we will use to update the lookup table on-chain through a transaction.</p>
<h4 id="heading-9-sendtx">9. <code>sendTx()</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendTx</span>(<span class="hljs-params">connection, payer, inst, lookupTable, compareTxSize</span>) </span>{
    <span class="hljs-keyword">let</span> message;

    <span class="hljs-keyword">if</span> (lookupTable) {
        message = <span class="hljs-keyword">new</span> solana.TransactionMessage({
            <span class="hljs-attr">instructions</span>: inst,
            <span class="hljs-attr">payerKey</span>: payer.publicKey,
            <span class="hljs-attr">recentBlockhash</span>: <span class="hljs-keyword">await</span> getLatestBlockhash(connection),
        }).compileToV0Message([lookupTable]);
    } <span class="hljs-keyword">else</span> {
        message = <span class="hljs-keyword">new</span> solana.TransactionMessage({
            <span class="hljs-attr">instructions</span>: inst,
            <span class="hljs-attr">payerKey</span>: payer.publicKey,
            <span class="hljs-attr">recentBlockhash</span>: <span class="hljs-keyword">await</span> getLatestBlockhash(connection),
        }).compileToV0Message();
    }

    <span class="hljs-keyword">const</span> tx = <span class="hljs-keyword">new</span> solana.VersionedTransaction(message);
    tx.sign([payer]);

    <span class="hljs-keyword">if</span> (compareTxSize) {
        <span class="hljs-built_in">console</span>.log(
            lookupTable
                ? <span class="hljs-string">'🟢 [With Address Lookup Table]'</span>
                : <span class="hljs-string">'🔴 [Without Address Lookup Table]'</span>,
            <span class="hljs-string">'Tx Size:'</span>,
            tx.serialize().length,
            <span class="hljs-string">'bytes'</span>
        );
    }

    <span class="hljs-keyword">const</span> txId = <span class="hljs-keyword">await</span> connection.sendTransaction(tx);
    <span class="hljs-keyword">return</span> txId;
}
</code></pre>
<p>We will use this as our primary function to send transactions (register events on the blockchain). It accepts multiple parameters:</p>
<ul>
<li>Active connection</li>
<li>Account owner</li>
<li>Transaction instructions</li>
<li>Lookup table account</li>
<li>Choice to calculate transaction message size  </li>
</ul>
<p>It's a multi-step process — create message; create versioned transaction; sign transaction; send transaction.</p>
<h3 id="heading-define-main-app">Define main app</h3>
<h4 id="heading-10-create-main-app">10. Create main <code>app()</code></h4>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">app</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Everything after this point would be added to this function</span>
}
</code></pre>
<h4 id="heading-11-setup-wallet-keypair">11. Setup wallet Keypair</h4>
<pre><code class="lang-js">  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'👀 Solana - Address Lookup Tables / Versioned Transactions 👀'</span>);

  <span class="hljs-keyword">const</span> privKey = bs58.decode(PRIVATE_KEY);
  <span class="hljs-keyword">const</span> myWallet = solana.Keypair.fromSecretKey(privKey);
</code></pre>
<h4 id="heading-12-establish-connection">12. Establish connection</h4>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> conn = <span class="hljs-keyword">await</span> createConn();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'✅ Endpoint connected!'</span>);
</code></pre>
<h4 id="heading-13-create-lookup-table">13. Create lookup table</h4>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> [lookupTableInst, lookupTableAddress] = <span class="hljs-keyword">await</span> createLookupTable(
        conn,
        myWallet
    );
    <span class="hljs-built_in">console</span>.log(
        <span class="hljs-string">`📝 Address Lookup Table Details --- <span class="hljs-subst">${lookupTableAddress}</span> | https://explorer.solana.com/address/<span class="hljs-subst">${lookupTableAddress.toBase58()}</span>?cluster=devnet`</span>
    );

    <span class="hljs-keyword">await</span> pause();

    <span class="hljs-keyword">const</span> createTableTxId = <span class="hljs-keyword">await</span> sendTx(conn, myWallet, [lookupTableInst]);
    <span class="hljs-built_in">console</span>.log(
        <span class="hljs-string">`✅ Address Lookup Table Created: https://explorer.solana.com/tx/<span class="hljs-subst">${createTableTxId}</span>?cluster=devnet`</span>
    );

    <span class="hljs-keyword">await</span> pause();
</code></pre>
<h4 id="heading-14-extend-lookup-table">14. Extend lookup table</h4>
<pre><code class="lang-js">    <span class="hljs-keyword">let</span> addressList = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>();
    addressList.push(myWallet.publicKey);
    tableEntries.forEach(<span class="hljs-function">(<span class="hljs-params">entry</span>) =&gt;</span> {
        addressList.push(<span class="hljs-keyword">new</span> solana.PublicKey(entry));
    });

    <span class="hljs-keyword">const</span> extendInst = <span class="hljs-keyword">await</span> extendLookupTable(
        myWallet,
        lookupTableAddress,
        addressList
    );

    <span class="hljs-keyword">const</span> ExtTableTxId = <span class="hljs-keyword">await</span> sendTx(conn, myWallet, [extendInst]);
    <span class="hljs-built_in">console</span>.log(
        <span class="hljs-string">`✅ Address Lookup Table Extended: https://explorer.solana.com/tx/<span class="hljs-subst">${ExtTableTxId}</span>?cluster=devnet`</span>
    );

    <span class="hljs-keyword">await</span> pause();
</code></pre>
<h4 id="heading-15-fetch-lookup-table-data">15. Fetch lookup table data</h4>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> lookupTableAccount = <span class="hljs-keyword">await</span> conn
        .getAddressLookupTable(lookupTableAddress)
        .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.value);

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'🧾 Verifying Addresses in the Lookup Table...'</span>);

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; lookupTableAccount.state.addresses.length; i++) {
        <span class="hljs-keyword">const</span> address = lookupTableAccount.state.addresses[i];
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Address'</span>, i + <span class="hljs-number">1</span>, address.toBase58());
    }
</code></pre>
<h4 id="heading-16-create-transaction-instructions">16. Create transaction instructions</h4>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> txInst = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>();
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; lookupTableAccount.state.addresses.length; i++) {
        <span class="hljs-keyword">const</span> address = lookupTableAccount.state.addresses[i];
        txInst.push(
            solana.SystemProgram.transfer({
                <span class="hljs-attr">fromPubkey</span>: myWallet.publicKey,
                <span class="hljs-attr">toPubkey</span>: address,
                <span class="hljs-attr">lamports</span>: <span class="hljs-number">0.0001</span> * solana.LAMPORTS_PER_SOL, <span class="hljs-comment">// 0.0001 SOL</span>
            })
        );
    }
</code></pre>
<h4 id="heading-17-send-transactions">17. Send transactions</h4>
<pre><code class="lang-js">    <span class="hljs-comment">// Tx with lookup table</span>
    <span class="hljs-keyword">const</span> sendNewTx1 = <span class="hljs-keyword">await</span> sendTx(
        conn,
        myWallet,
        txInst,
        lookupTableAccount,
        <span class="hljs-literal">true</span>
    );

    <span class="hljs-comment">// Tx without lookup table</span>
    <span class="hljs-keyword">const</span> sendNewTx2 = <span class="hljs-keyword">await</span> sendTx(conn, myWallet, txInst, <span class="hljs-literal">null</span>, <span class="hljs-literal">true</span>);

    <span class="hljs-built_in">console</span>.log(
        <span class="hljs-string">`🚀 Versioned Transaction with the Address Lookup Table: https://explorer.solana.com/tx/<span class="hljs-subst">${sendNewTx1}</span>?cluster=devnet`</span>
    );
</code></pre>
<h4 id="heading-18-initialize-app">18. Initialize <code>app()</code></h4>
<pre><code class="lang-js">app();
</code></pre>
<h3 id="heading-output">Output</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665920461185/v_p54DAKV.gif" alt="Screenshot 2022-10-16 at 11.39.16.gif" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665920417381/RMhnKR0Hd.png" alt="Screenshot 2022-10-16 at 11.39.52@2x.png" /></p>
<pre><code>👀 Solana - Address Lookup Tables / Versioned Transactions 👀
✅ Endpoint connected!
📝 Address Lookup Table Details --- <span class="hljs-number">7</span>x3zgryXe9RSucuV3DriSqTcj4kKPBikZPTEnAWRK8kT | https:<span class="hljs-comment">//explorer.solana.com/address/7x3zgryXe9RSucuV3DriSqTcj4kKPBikZPTEnAWRK8kT?cluster=devnet</span>
✅ Address Lookup Table Created: https:<span class="hljs-comment">//explorer.solana.com/tx/3BcHwivCv2NQjdkZpfbpJwjUMfRQbbjTFhxTTekKsKBCPQGvd6MKKZsfQ7r8A8ZZvkpQVVY1PJvrV1rJBgEtcGZh?cluster=devnet</span>
✅ Address Lookup Table Extended: https:<span class="hljs-comment">//explorer.solana.com/tx/3nqHuPBRxS7rupwninpTwrTxikDwGWBM8F5gGbxjKUbQ1zHEg8fTKoeJbkLaajRv7PbM48HLc43GmLXKmGe8ZLqm?cluster=devnet</span>
🧾 Verifying Addresses <span class="hljs-keyword">in</span> the Lookup Table...
Address <span class="hljs-number">1</span> <span class="hljs-number">5</span>FoZtVFxvSwkyyJWKiadcX4vQrTDdEcHVhwB6179bRgq
Address <span class="hljs-number">2</span> BXBk9wAw424EQEpxMFjaqjs3D3rjfqezuKh8sobbPVy5
Address <span class="hljs-number">3</span> FN69Pe14FDC6iEeQEb1usyy3m5EMZB2xBED6o91YaNU4
Address <span class="hljs-number">4</span> <span class="hljs-number">4</span>PUuD5o6fzjGniqTbsUKaW5cJACoJAVeJQ91JkPmTzyH
🟢 [With Address Lookup Table] Tx Size: <span class="hljs-number">273</span> bytes
🔴 [Without Address Lookup Table] Tx Size: <span class="hljs-number">332</span> bytes
🚀 Versioned Transaction <span class="hljs-keyword">with</span> the Address Lookup Table: https:<span class="hljs-comment">//explorer.solana.com/tx/47ftfMgLVcSxjdCSiGiXbcnLACmsSXHPzQwH953MXC74tdDLkDGtAchfYvQLaj9ADUMEYJvvfthzA2TD2i7d735a?cluster=devnet</span>
</code></pre><h3 id="heading-conclusion">Conclusion</h3>
<p>As you notice, there is a good difference in the size of the transaction message with the Address Lookup Table. The benefit would be more noticeable during transactions with custom programs and a large number of account addresses.</p>
<p>Hopefully, this is the first of many transaction features to come that would make the Solana blockchain more efficient.</p>
<p>Also, if you use RPC methods to fetch the blockchain data, it is essential to note that these changes have also impacted some RPC methods. I have posted a Twitter thread with the details about how this feature activation would affect the developers.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/a26nine/status/1579343395373592577">https://twitter.com/a26nine/status/1579343395373592577</a></div>
<p>I hope you found this guide helpful! Until next time... 🫡</p>
<h3 id="heading-full-code">Full Code</h3>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="874a0046cb3c75362213e1c2ebf9faad"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/a26nine/874a0046cb3c75362213e1c2ebf9faad" class="embed-card">https://gist.github.com/a26nine/874a0046cb3c75362213e1c2ebf9faad</a></div><hr />
<p><strong>Other Resources</strong></p>
<ul>
<li>https://docs.solana.com/developing/programming-model/transactions</li>
<li>https://docs.solana.com/proposals/transactions-v2</li>
<li>https://solana-labs.github.io/solana-web3.js/</li>
</ul>
<hr />
<ol>
<li><p><span id="ft1"></span>At the time of writing this guide. <a class="post-section-overview" href="#1">↩</a></p>
</li>
<li><p><span id="ft2"></span>At the time of writing this guide. <a class="post-section-overview" href="#2">↩</a></p>
</li>
<li><p><span id="ft3"></span>Solana blockchain uses a conservative MTU size of 1280 bytes. After accounting for headers, signatures, and other metadata, the transaction is left with around 1120 bytes. <a class="post-section-overview" href="#3">↩</a></p>
</li>
<li><p><span id="ft4"></span>https://github.com/solana-labs/solana/blob/090e11210aa7222d8295610a6ccac4acda711bb9/sdk/src/packet.rs#L13 <a class="post-section-overview" href="#4">↩</a></p>
</li>
</ol>
<hr />
]]></content:encoded></item><item><title><![CDATA[Build Ethereum Balance Checker in Python]]></title><description><![CDATA[There are ample blockchain explorers online to query Ethereum wallet balance. But have you ever thought of checking the ETH balance directly from your command-line in a couple of steps? Let's create a tool for that with only 6 lines of code! 😎
Requi...]]></description><link>https://blog.a26nine.dev/build-ethereum-balance-checker-in-python</link><guid isPermaLink="true">https://blog.a26nine.dev/build-ethereum-balance-checker-in-python</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Cryptocurrency]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Abraar Ahmed]]></dc:creator><pubDate>Wed, 16 Mar 2022 08:49:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1668244338646/C551KATaG.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are ample blockchain explorers online to query Ethereum wallet balance. But have you ever thought of checking the ETH balance directly from your command-line in a couple of steps? Let's create a tool for that with only 6 lines of code! 😎</p>
<h3 id="heading-requirements">Requirements</h3>
<ul>
<li><strong>Python Web3 Library</strong><br />  Install <a target="_blank" href="https://web3py.readthedocs.io/en/stable/">Python 'Web3.py' Library</a> by executing the following command:</li>
</ul>
<pre><code class="lang-python">pip install web3
</code></pre>
<ul>
<li><p><strong>Ethereum Node API Endpoint</strong><br />  Though there are many Ethereum node service providers available online, we'll use <a target="_blank" href="https://www.pokt.network/">Pocket Network</a> for our project as it is free.</p>
<ol>
<li><p>Signup for an account at <a target="_blank" href="https://mainnet.portal.pokt.network/#/signup">Pokt.network</a> and verify your email address to get access to the endpoints.</p>
</li>
<li><p>Select <em>Apps</em> from the side menu and click <em>Create</em>.</p>
</li>
<li><p>Enter desired <em>App Name</em> and click <em>Launch Application</em>.</p>
</li>
<li><p>Copy the <em>Endpoint</em> provided. (Ensure that <em>Ethereum Mainnet</em> is selected as the Endpoint network!</p>
</li>
</ol>
</li>
</ul>
<p><strong>The web3 library will allow us to interact with the Ethereum blockchain through the API endpoint.</strong></p>
<h3 id="heading-lets-code">Let's Code!</h3>
<ol>
<li>Import required modules</li>
</ol>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> web3 <span class="hljs-keyword">import</span> Web3, HTTPProvider
</code></pre>
<ol>
<li>Save the endpoint URL in a variable</li>
</ol>
<pre><code class="lang-python">endpoint = <span class="hljs-string">'YOUR_ENDPOINT_URL_HERE'</span>
</code></pre>
<ol>
<li>Make a connection to Ethereum blockchain through the endpoint</li>
</ol>
<pre><code class="lang-python">connection = Web3(HTTPProvider(endpoint))
</code></pre>
<ol>
<li>Get the wallet address input from the user</li>
</ol>
<pre><code class="lang-python">address = input(<span class="hljs-string">"Enter ETH wallet address: "</span>)
</code></pre>
<ol>
<li>Fetch the latest ETH balance from the blockchain and convert it to <em>ether</em> denomination.</li>
</ol>
<pre><code class="lang-python">balance = connection.fromWei(connection.eth.getBalance(address, <span class="hljs-string">'latest'</span>), <span class="hljs-string">'ether'</span>)
</code></pre>
<ol>
<li>Display the balance</li>
</ol>
<pre><code class="lang-python">print(<span class="hljs-string">f"Balance: <span class="hljs-subst">{balance}</span> ether"</span>)
</code></pre>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="b0f905e7f1aeae6fa4a7ecfaefcb9042"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/a26nine/b0f905e7f1aeae6fa4a7ecfaefcb9042" class="embed-card">https://gist.github.com/a26nine/b0f905e7f1aeae6fa4a7ecfaefcb9042</a></div><p> </p>
<p>Save the file; run it; enter ETH address and get your balance right in the terminal. That simple!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647420336980/DUphd0nwM.png" alt="Result" /></p>
<p>So, what's your balance? 😁</p>
]]></content:encoded></item></channel></rss>