<?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: Cherrypick14</title>
    <description>The latest articles on Forem by Cherrypick14 (@cherrypick14).</description>
    <link>https://forem.com/cherrypick14</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%2F532872%2Fa7132ac2-ecbd-4f13-85a8-db09613aa1bd.jpg</url>
      <title>Forem: Cherrypick14</title>
      <link>https://forem.com/cherrypick14</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cherrypick14"/>
    <language>en</language>
    <item>
      <title>Understanding secp256k1 &amp; Multisig Wallets</title>
      <dc:creator>Cherrypick14</dc:creator>
      <pubDate>Thu, 12 Feb 2026 17:11:57 +0000</pubDate>
      <link>https://forem.com/cherrypick14/understanding-secp256k1-multisig-wallets-3ofj</link>
      <guid>https://forem.com/cherrypick14/understanding-secp256k1-multisig-wallets-3ofj</guid>
      <description>&lt;p&gt;A Deep Dive into Elliptic Curve Cryptography with Rust&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What is needed is an electronic payment system based on cryptographic proof instead of trust." — Satoshi Nakamoto&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every day, millions of transactions flow through Bitcoin and Ethereum networks. Yet, surprisingly few developers truly understand the cryptographic foundation that makes it all possible: &lt;strong&gt;secp256k1&lt;/strong&gt;, the elliptic curve that powers both blockchains.&lt;/p&gt;

&lt;p&gt;While building my &lt;a href="https://github.com/Cherrypick14/multisig-rs" rel="noopener noreferrer"&gt;multisig wallet in Rust&lt;/a&gt;, I realized that most developers (including myself initially) treat elliptic curve cryptography as a black box. We import libraries, call functions, and trust that magic happens.&lt;/p&gt;

&lt;p&gt;This article changes that. We're going to demystify &lt;em&gt;secp256k1&lt;/em&gt;, understand how multisig wallets work, and see why Rust is the perfect language for building cryptographic systems.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  &lt;strong&gt;What is secp256k1&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;secp256k1&lt;/strong&gt; is an elliptic curve defined by the equation:&lt;/p&gt;

&lt;p&gt;The secp256k1 Equation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y² = x³ + 7 (over a finite field)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This deceptively simple equation creates a curve with remarkable properties:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Point Addition&lt;/strong&gt;: You can "add" points on the curve to get another point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalar Multiplication&lt;/strong&gt;: Multiplying a point by a number gives you a new point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One-way Function&lt;/strong&gt;: Easy to go from private key → public key, impossible to reverse.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h2&gt;
  
  
  &lt;strong&gt;Why this Curve?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Bitcoin's creator chose secp256k1 for several reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;: The equation y² = x³ + 7 has no 'x²' or 'x' terms, making computations faster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: 256-bit key space = 2²⁵⁶ possible keys (more atoms than in the observable universe).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Non-NSA&lt;/strong&gt;: Unlike some curves (like NIST P-256), secp256k1's constants weren't chosen by government agencies. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Cryptographic Keys Work&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;p&gt;Here's what happens under the hood:&lt;/p&gt;

&lt;p&gt;Private Key (&lt;strong&gt;256-bit random number&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Public Key (&lt;strong&gt;Point on the curve&lt;/strong&gt;) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apply point multiplication: PublicKey = PrivateKey × G
Where G is the generator point (a fixed point on secp256k1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Address :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hash the public key with SHA256 + RIPEMD160, add checksums → Your wallet address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Multisig Wallets: Shared Ownership&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we understand single-key cryptography, let's level up to &lt;strong&gt;multisignature (multisig) wallets&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a Multisig Wallet?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A wallet that requires &lt;strong&gt;M out of N&lt;/strong&gt; signatures to authorize a transaction.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. &lt;strong&gt;2-of-3&lt;/strong&gt;: Company wallet (CEO, CFO, CTO — any 2 can approve).&lt;/li&gt;
&lt;li&gt;2. &lt;strong&gt;3-of-5&lt;/strong&gt;: DAO treasury (requires majority approval).&lt;/li&gt;
&lt;li&gt;3. &lt;strong&gt;1-of-2&lt;/strong&gt;: Personal backup (main key + recovery key).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Why Multisig Matters&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: No single point of failure. Lose one key? Still safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance&lt;/strong&gt;: Requires consensus for major decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust Minimization&lt;/strong&gt;: No need to trust a single party.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recovery&lt;/strong&gt;: Built-in key recovery mechanisms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Building It in Rust: Why?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Rust isn't just a trendy language — it's perfect for cryptography:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Rust's type system prevents common crypto bugs
pub struct PrivateKey([u8; 32]);  // Exactly 32 bytes, no more, no less

impl PrivateKey {
    // Ownership system ensures keys aren't accidentally copied
    pub fn sign(&amp;amp;self, message: &amp;amp;[u8]) -&amp;gt; Signature {
        // Compile-time guarantee of memory safety
        // No buffer overflows, no use-after-free
    }
}

// Error handling forces you to handle failures
match wallet.verify_signature(&amp;amp;tx, &amp;amp;sig) {
    Ok(valid) =&amp;gt; { /* proceed */ },
    Err(e) =&amp;gt; { /* must handle error */ },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Rust advantages for cryptography:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory Safety&lt;/strong&gt;: No buffer overflows that could leak keys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-cost Abstractions&lt;/strong&gt;: High-level code compiles to fast assembly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit Error Handling&lt;/strong&gt;: Cryptographic failures can't be ignored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Garbage Collection&lt;/strong&gt;: Predictable performance, no unexpected pauses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Building in Rust: Core Architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here's a typical structure for a multisig wallet in Rust. This demonstrates the key concepts — the actual implementation in my &lt;a href="https://github.com/Cherrypick14/multisig-rs" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; includes additional features like transaction queuing, enhanced serialization, and more robust error handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Core data structures
pub struct MultisigWallet {
    pub threshold: usize,           // M in M-of-N
    pub signers: Vec&amp;lt;PublicKey&amp;gt;,    // N public keys
    pub nonce: u64,                 // Prevent replay attacks
}

pub struct Transaction {
    pub to: Address,
    pub amount: u64,
    pub nonce: u64,
}

// The critical signing and verification functions
impl MultisigWallet {
    pub fn create_signature(
        &amp;amp;self,
        tx: &amp;amp;Transaction,
        private_key: &amp;amp;PrivateKey,
    ) -&amp;gt; Result&amp;lt;Signature, Error&amp;gt; {
        // Hash the transaction
        let msg_hash = hash_transaction(tx);

        // Sign with secp256k1
        sign_ecdsa(&amp;amp;msg_hash, private_key)
    }

    pub fn verify_and_execute(
        &amp;amp;mut self,
        tx: &amp;amp;Transaction,
        signatures: Vec&amp;lt;Signature&amp;gt;,
    ) -&amp;gt; Result&amp;lt;(), Error&amp;gt; {
        // Verify we have enough signatures
        if signatures.len() &amp;lt; self.threshold {
            return Err(Error::InsufficientSignatures);
        }

        // Verify each signature is from a valid signer
        let msg_hash = hash_transaction(tx);

        for sig in signatures.iter().take(self.threshold) {
            let pub_key = recover_public_key(&amp;amp;msg_hash, sig)?;

            if !self.signers.contains(&amp;amp;pub_key) {
                return Err(Error::UnauthorizedSigner);
            }
        }

        // Execute transaction
        self.execute_transaction(tx)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;The Challenges I Faced&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Signature Verification Edge Cases&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Challenge&lt;/strong&gt;: What if the same key signs twice? What if signatures are in wrong order?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Recover the public key from each signature and check against the signer list. Use HashSets to prevent duplicate signatures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Transaction Replay Attacks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Challenge&lt;/strong&gt;: Without nonces, an attacker could replay old valid transactions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Include a nonce that increments with each transaction. Old transactions become invalid.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Key Serialization&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Challenge&lt;/strong&gt;: Public keys can be compressed (&lt;em&gt;33 bytes&lt;/em&gt;) or uncompressed (&lt;em&gt;65 bytes&lt;/em&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Always use compressed format for consistency. Rust's type system helps enforce this.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What I Learned&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cryptography is unforgiving&lt;/strong&gt;: One byte wrong = complete failure. Rust's strictness is a feature, not a bug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing is critical&lt;/strong&gt;: Test with known test vectors, fuzz testing, property-based testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understanding beats memorization&lt;/strong&gt;: Knowing why secp256k1 works makes debugging infinitely easier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error handling&lt;/strong&gt; is security: Every &lt;em&gt;Result&lt;/em&gt; is a potential vulnerability if mishandled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Takeaways&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  &lt;strong&gt;Try It Yourself&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The complete implementation is open source and documented. Here's what you'll find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full secp256k1 signature creation and verification.&lt;/li&gt;
&lt;li&gt;M-of-N multisig wallet implementation.&lt;/li&gt;
&lt;li&gt;Transaction serialization and hashing.&lt;/li&gt;
&lt;li&gt;Comprehensive error handling.&lt;/li&gt;
&lt;li&gt;Test suite with known test vectors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you found this helpful , leave a comment or feedback. Any Questions? Found a bug? Want to contribute?&lt;/p&gt;

&lt;p&gt;Open an issue or PR - let's build secure crypto systems together! 🦀&lt;/p&gt;

</description>
      <category>rust</category>
      <category>blockchain</category>
      <category>wallets</category>
    </item>
    <item>
      <title>How to Build a Real-Time Blockchain Dashboard with PAPI</title>
      <dc:creator>Cherrypick14</dc:creator>
      <pubDate>Mon, 13 Oct 2025 15:18:09 +0000</pubDate>
      <link>https://forem.com/cherrypick14/how-to-build-a-real-time-blockchain-dashboard-with-papi-44d3</link>
      <guid>https://forem.com/cherrypick14/how-to-build-a-real-time-blockchain-dashboard-with-papi-44d3</guid>
      <description>&lt;p&gt;Blockchain developers have long struggled with the complexity of connecting to and querying blockchain networks. Traditional APIs often require extensive boilerplate code, lack type safety, and make real-time data subscriptions cumbersome. Enter &lt;strong&gt;Polkadot API (PAPI)&lt;/strong&gt; - a modern, TypeScript-first API that revolutionizes how we interact with Polkadot and its parachains.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk you through building &lt;strong&gt;Polkadot Network Pulse&lt;/strong&gt;, a real-time blockchain monitoring dashboard that showcases PAPI's powerful features. By the end, you'll understand how to leverage PAPI's reactive subscriptions, WebSocket connections, and type-safe queries to build production-ready blockchain applications.&lt;/p&gt;

&lt;p&gt;🔗 Live Demo: &lt;a href="https://polkadot-network-pulse.vercel.app/" rel="noopener noreferrer"&gt;https://polkadot-network-pulse.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📦 Source Code: &lt;a href="https://github.com/Cherrypick14/polkadot-network-pulse" rel="noopener noreferrer"&gt;https://github.com/Cherrypick14/polkadot-network-pulse&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is PAPI?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Polkadot API (PAPI) is the next-generation JavaScript/TypeScript library for interacting with Polkadot and Substrate-based chains. It's a complete rewrite of the legacy &lt;code&gt;@polkadot/api&lt;/code&gt; with several key improvements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why PAPI Over Legacy &lt;a class="mentioned-user" href="https://dev.to/polkadot"&gt;@polkadot&lt;/a&gt;/api?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5ep53tag61mfyixpe2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5ep53tag61mfyixpe2w.png" alt="Diagram comparing PAPI vs legacy Polkadot API, highlighting TypeScript-first design, observables for real-time updates, and improved developer ergonomics." width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project Overview: Polkadot Network Pulse&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polkadot Network Pulse&lt;/strong&gt; is a real-time dashboard that monitors the Polkadot blockchain, displaying:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Latest block updates (streaming in real-time)&lt;/li&gt;
&lt;li&gt;Finalized block numbers&lt;/li&gt;
&lt;li&gt;Average block time calculations&lt;/li&gt;
&lt;li&gt;Live block feed with animations&lt;/li&gt;
&lt;li&gt;Connection status monitoring&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is to demonstrate PAPI's core strengths: &lt;strong&gt;reactive subscriptions&lt;/strong&gt; and &lt;strong&gt;WebSocket-based real-time data streaming&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technical Architecture&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Tech Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Frontend: React 19 with TypeScript&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Blockchain API: Polkadot API (PAPI) v1.20+&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Styling: Tailwind CSS v4&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Build Tool: Vite&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Icons: Lucide React&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Architecture Diagram&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x8bw2k7cbgudkgvs7iq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x8bw2k7cbgudkgvs7iq.png" alt="Diagram showing the technical architecture of the Polkadot Network Pulse app, including the frontend React interface, PAPI connection to the Polkadot mainnet, and real-time block data flow." width="262" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation Deep Dive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Setting Up PAPI&lt;/strong&gt;&lt;br&gt;
First, install the required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install polkadot-api
npm install @polkadot-api/descriptors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Creating the PAPI Client&lt;/strong&gt;&lt;br&gt;
The foundation of any PAPI application is the client creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createClient } from "polkadot-api";
import { getWsProvider } from "polkadot-api/ws-provider/web";

// Create WebSocket provider
const provider = getWsProvider("wss://rpc.polkadot.io");

// Initialize PAPI client
const client = createClient(provider);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Insight&lt;/strong&gt;: Unlike the legacy API, PAPI uses a &lt;strong&gt;provider pattern&lt;/strong&gt; that separates connection management from client logic. This makes testing and switching between networks trivial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Real-Time Block Subscriptions&lt;/strong&gt;&lt;br&gt;
This is where PAPI truly shines. Instead of polling for new blocks, we subscribe to observables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Subscribe to best (latest) blocks
client.bestBlocks$.subscribe((blocks) =&amp;gt; {
  for (const block of blocks) {
    const blockInfo = {
      number: block.number,
      hash: block.hash,
      timestamp: Date.now(),
    };

    setLatestBlock(blockInfo);

    // Update block feed
    setRecentBlocks((prev) =&amp;gt; [blockInfo, ...prev].slice(0, 15));
  }
});

// Subscribe to finalized blocks
client.finalizedBlock$.subscribe((block) =&amp;gt; {
  setFinalizedBlock(block.number);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Observables?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reactive: Automatically updates when new data arrives.&lt;/li&gt;
&lt;li&gt;Memory Efficient: Unsubscribe when component unmounts.&lt;/li&gt;
&lt;li&gt;Composable: Easy to combine multiple data streams.&lt;/li&gt;
&lt;li&gt;Error Handling: Built-in error propagation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;4. Calculating Block Time&lt;/strong&gt; &lt;br&gt;
One interesting metric is the average block time. We calculate this by comparing timestamps of recent blocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const calculateBlockTime = () =&amp;gt; {
  if (recentBlocks.length &amp;lt; 2) return null;

  const timeDiff = recentBlocks[0].timestamp - 
                   recentBlocks[recentBlocks.length - 1].timestamp;
  const blockDiff = recentBlocks[0].number - 
                    recentBlocks[recentBlocks.length - 1].number;

  return (timeDiff / blockDiff / 1000).toFixed(2); // in seconds
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us a &lt;strong&gt;live, measured block time&lt;/strong&gt; rather than relying on hardcoded values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Managing Connection State&lt;/strong&gt;&lt;br&gt;
Proper connection management is crucial for production apps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [isConnected, setIsConnected] = useState(false);
const [error, setError] = useState&amp;lt;string | null&amp;gt;(null);
const [loading, setLoading] = useState(false);

const connectToPolkadot = async () =&amp;gt; {
  try {
    setLoading(true);
    setError(null);

    const provider = getWsProvider("wss://rpc.polkadot.io");
    const client = createClient(provider);

    setIsConnected(true);
    // ... set up subscriptions
  } catch (err) {
    setError(err instanceof Error ? err.message : "Connection failed");
    setIsConnected(false);
  } finally {
    setLoading(false);
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key PAPI Concepts Explained&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Observables vs. Promises&lt;/strong&gt;&lt;br&gt;
Traditional APIs use promises for async operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Legacy approach (promise)
const block = await api.rpc.chain.getBlock();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PAPI uses observables for continuous data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// PAPI approach (observable)
client.bestBlocks$.subscribe(blocks =&amp;gt; {
  // Automatically receives updates
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;No need to repeatedly poll&lt;/li&gt;
&lt;li&gt;Lower network overhead&lt;/li&gt;
&lt;li&gt;Real-time updates&lt;/li&gt;
&lt;li&gt;Automatic cleanup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. WebSocket Provider&lt;/strong&gt;&lt;br&gt;
PAPI's WebSocket provider maintains a persistent connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const provider = getWsProvider("wss://rpc.polkadot.io");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Automatic reconnection on disconnect&lt;/li&gt;
&lt;li&gt;Connection pooling&lt;/li&gt;
&lt;li&gt;Request queuing&lt;/li&gt;
&lt;li&gt;Error recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Type Safety&lt;/strong&gt;&lt;br&gt;
One of PAPI's biggest advantages is full TypeScript support. While we didn't use typed APIs extensively in this project (focusing on subscriptions), here's how they work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Get typed API with chain-specific types
const typedApi = client.getTypedApi(chainSpec);

// TypeScript knows all available queries
const validators = await typedApi.query.Session.Validators.getValue();
// validators is properly typed!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Challenges &amp;amp; Solutions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 1: PAPI API Changes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: PAPI is actively developed, and APIs change between versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Focused on stable core features (subscriptions) rather than experimental typed queries. Always check the official docs - &lt;a href="https://papi.how" rel="noopener noreferrer"&gt;https://papi.how&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 2: Handling Reconnections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: WebSocket connections can drop unexpectedly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: PAPI's provider handles this automatically. We just need to show connection state to users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{isConnected &amp;amp;&amp;amp; (
  &amp;lt;div className="flex items-center gap-2"&amp;gt;
    &amp;lt;div className="w-3 h-3 bg-green-500 rounded-full animate-pulse" /&amp;gt;
    &amp;lt;span&amp;gt;Live Connected&amp;lt;/span&amp;gt;
  &amp;lt;/div&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Challenge 3: Performance with Rapid Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: New blocks every ~6 seconds can cause performance issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Limit the block feed to 15 most recent blocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setRecentBlocks((prev) =&amp;gt; [blockInfo, ...prev].slice(0, 15));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Performance Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Bundle Size&lt;/strong&gt;&lt;br&gt;
PAPI significantly reduces bundle size compared to legacy API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Legacy &lt;a class="mentioned-user" href="https://dev.to/polkadot"&gt;@polkadot&lt;/a&gt;/api: ~500KB+ .&lt;/li&gt;
&lt;li&gt;PAPI: ~100KB base + only what you use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Memory Management&lt;/strong&gt;&lt;br&gt;
Always unsubscribe from observables when components unmount:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  const subscription = client.bestBlocks$.subscribe(/* ... */);

  return () =&amp;gt; {
    subscription.unsubscribe(); // Cleanup
  };
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Connection Pooling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PAPI automatically manages connection pooling, so multiple subscriptions share the same WebSocket connection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build for Production&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vercel (Preference):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push code to GitHub&lt;/li&gt;
&lt;li&gt;Import project in Vercel&lt;/li&gt;
&lt;li&gt;Deploy automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note: Alternative Deployment When Vercel UI Fails&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I first tried deploying through the Vercel dashboard, I ran into this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sh: line 1: vite: command not found
Error: Command "vite build" exited with 127
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens sometimes when the build environment can’t find your local dev dependencies (like Vite).&lt;/p&gt;

&lt;p&gt;Instead of getting stuck, I used a different approach that worked perfectly — deploying through &lt;strong&gt;Vercel CLI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s what I did:&lt;/p&gt;

&lt;p&gt;Just for more flexibility and if you want more control, the CLI route is smooth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g vercel
vercel login
vercel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the build command to &lt;code&gt;npm run build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Output directory: &lt;code&gt;dist&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Confirm project name or leave defaults&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Within seconds, your PAPI app will be live with a URL like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-app-name.vercel.app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Pro tip&lt;/strong&gt;: The CLI often works better than the UI if you’re using a custom front-end tool-chain or need to debug build errors locally before deployment.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;npm run build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Drag &lt;code&gt;dist&lt;/code&gt;/ folder to Netlify Drop&lt;/li&gt;
&lt;li&gt;Done!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Environment Variables:&lt;/p&gt;

&lt;p&gt;If using different RPC endpoints, add &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_RPC_ENDPOINT=wss://rpc.polkadot.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. PAPI is Production-Ready&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Despite being newer than the legacy API, PAPI is stable and performant. The developer experience is significantly better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Observables Are Powerful&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RxJS observables might seem complex at first, but they're perfect for blockchain data that updates continuously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Type Safety Catches Bugs Early&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TypeScript integration means fewer runtime errors and better IDE autocomplete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Start Simple&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Focus on core features (subscriptions) before diving into complex queries. PAPI's strength is real-time data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Potential enhancements for this project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Historical Data&lt;/strong&gt;: Query past blocks and create charts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Monitoring&lt;/strong&gt;: Subscribe to extrinsics in real-time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Chain Support&lt;/strong&gt;: Connect to parachains (Kusama, Acala, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account Tracking&lt;/strong&gt;: Monitor specific account balances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance Dashboard&lt;/strong&gt;: Track referendums and votes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Metrics&lt;/strong&gt;: Add more network statistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Useful Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;📚 - PAPI Official Documentation - &lt;a href="https://papi.how" rel="noopener noreferrer"&gt;https://papi.how&lt;/a&gt;&lt;br&gt;
🔧 - PAPI Github - &lt;a href="https://github.com/polkadot-api/polkadot-api" rel="noopener noreferrer"&gt;https://github.com/polkadot-api/polkadot-api&lt;/a&gt;&lt;br&gt;
🌐 - Polkadot Network - &lt;a href="https://polkadot.network" rel="noopener noreferrer"&gt;https://polkadot.network&lt;/a&gt;&lt;br&gt;
💬 - Polkadot Discord - &lt;a href="https://discord.gg/polkadot" rel="noopener noreferrer"&gt;https://discord.gg/polkadot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building &lt;strong&gt;Polkadot Network Pulse&lt;/strong&gt; demonstrated that PAPI is a significant leap forward for Polkadot development. The combination of TypeScript support, reactive subscriptions, and a clean API makes it the ideal choice for modern blockchain applications.&lt;/p&gt;

&lt;p&gt;Whether you're building a &lt;strong&gt;block explorer&lt;/strong&gt;, &lt;strong&gt;DeFi dashboard&lt;/strong&gt;, or &lt;strong&gt;governance tool&lt;/strong&gt;, PAPI provides the tools you need to create responsive, type-safe applications with minimal boilerplate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PAPI simplifies real-time blockchain data subscriptions&lt;/li&gt;
&lt;li&gt;Observables provide elegant solutions for continuous data streams&lt;/li&gt;
&lt;li&gt;TypeScript integration catches errors at compile-time&lt;/li&gt;
&lt;li&gt;WebSocket providers handle connection management automatically&lt;/li&gt;
&lt;li&gt;Smaller bundle sizes improve application performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready to build with PAPI? Start with the official documentation -&lt;a href="https://papi.how" rel="noopener noreferrer"&gt;https://papi.how&lt;/a&gt; and experiment with subscriptions. The future of Polkadot development is here!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About Me:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hey folks 👋 I’m Cheryl, a Full-Stack and Blockchain Developer. I enjoy turning complex technical concepts into clear, easy-to-grasp content through technical writing. &lt;/p&gt;

&lt;p&gt;Let's connect here:&lt;br&gt;
My github: &lt;a href="https://github.com/Cherrypick14" rel="noopener noreferrer"&gt;https://github.com/Cherrypick14&lt;/a&gt;&lt;br&gt;
X(Twitter) : &lt;a href="https://x.com/OwalaCheryl" rel="noopener noreferrer"&gt;https://x.com/OwalaCheryl&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Found this helpful? Drop a ❤️ and follow for more blockchain development content!&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🦀 5 Rust Concepts You Must Understand When Building on Polkadot</title>
      <dc:creator>Cherrypick14</dc:creator>
      <pubDate>Fri, 04 Jul 2025 20:30:06 +0000</pubDate>
      <link>https://forem.com/cherrypick14/5-rust-concepts-you-must-understand-when-building-on-polkadot-2f4o</link>
      <guid>https://forem.com/cherrypick14/5-rust-concepts-you-must-understand-when-building-on-polkadot-2f4o</guid>
      <description>&lt;p&gt;&lt;em&gt;No Jargon. No Headaches. Just the Good Stuff.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, you want to build on Polkadot? Nice. But let’s be honest, &lt;strong&gt;jumping into smart contract development without understanding Rust is like showing up to a Formula 1 race on a bicycle&lt;/strong&gt;.&lt;br&gt;
You need the right engine.&lt;/p&gt;

&lt;p&gt;But don’t worry, I’m not here to drown you in complex theory. I’m here to break down the five Rust concepts you really need to survive and thrive when building ink! smart contracts on Polkadot.&lt;/p&gt;

&lt;p&gt;Let’s ride 🚴‍♂️💨.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1.  &lt;strong&gt;Ownership and Borrowing&lt;/strong&gt; – &lt;em&gt;&lt;strong&gt;The VIP Pass to Rustland&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rust is picky about &lt;strong&gt;who owns what&lt;/strong&gt; and honestly, it’s for your &lt;strong&gt;own safety&lt;/strong&gt;.&lt;br&gt;
Ownership in Rust is like having a house key. If you give it away, you can’t get back in unless you borrow it politely.&lt;/p&gt;

&lt;p&gt;In smart contracts, this isn’t just theory ~ if you mess this up, you can cause storage errors, panics, or inefficient memory usage that &lt;strong&gt;cost you gas (the blockchain’s version of real money)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And trust me, Polkadot’s runtime isn’t going to hold your hand.&lt;br&gt;
👉 You’ll need to carefully decide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Should I move this data?&lt;/li&gt;
&lt;li&gt;Should I just borrow it?&lt;/li&gt;
&lt;li&gt;Should I clone it? (But wait ~ cloning is like copying an entire building instead of sharing the keys. Choose wisely.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Bottom line&lt;/strong&gt;:&lt;br&gt;
Understanding ownership and borrowing isn’t optional ~ it’s literally how you keep your contract from falling apart.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2.  &lt;strong&gt;no_std&lt;/strong&gt; – &lt;em&gt;&lt;strong&gt;The Stripped-Down, No-Nonsense Rust&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you write regular Rust, you have access to the full toolbox: file systems, threads, fancy libraries ~ you name it.&lt;/p&gt;

&lt;p&gt;But when you build smart contracts on Polkadot, &lt;strong&gt;you get the ‘camping edition’ of Rust&lt;/strong&gt;.&lt;br&gt;
No kitchen, no electricity. You’re out here with a tent and a flashlight. Welcome to&lt;code&gt;no_std&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In simple terms:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The standard library &lt;code&gt;(std)&lt;/code&gt; is gone.&lt;/li&gt;
&lt;li&gt;No file storage. &lt;/li&gt;
&lt;li&gt;No threading. &lt;/li&gt;
&lt;li&gt;No OS support.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 You’ll only work with what fits in the lightweight, super-restricted &lt;strong&gt;WebAssembly (Wasm)&lt;/strong&gt; world.&lt;/p&gt;

&lt;p&gt;It’s kind of like trying to cook a five-star meal with a camping stove.&lt;br&gt;
Possible? Yes.&lt;br&gt;
But you better know what you’re doing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3. &lt;strong&gt;Traits&lt;/strong&gt; – &lt;em&gt;&lt;strong&gt;The Smart Contract’s Secret Handshake&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Rust, &lt;strong&gt;traits are like contracts for your contracts&lt;/strong&gt;.&lt;br&gt;
They say, “&lt;em&gt;Hey, if you implement this trait, you promise to provide these methods&lt;/em&gt;.”&lt;/p&gt;

&lt;p&gt;In Polkadot smart contracts, &lt;strong&gt;traits help you define what your contract can do and how other contracts can talk to you&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of traits like this:&lt;br&gt;
👉 If your smart contract was a restaurant, the trait is your menu. It tells everyone exactly what they can order.&lt;br&gt;
👉 No trait? No service.&lt;/p&gt;

&lt;p&gt;If you plan to do &lt;strong&gt;cross-contract communication&lt;/strong&gt; (basically, smart contracts calling each other like besties), traits will keep your project from turning into a spaghetti mess.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn how to cook with traits early. Your future self will thank you.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4. &lt;strong&gt;Error Handling&lt;/strong&gt; – &lt;strong&gt;&lt;em&gt;Unwrap Carefully, It’s Hot!&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Look, in Rust, we all get tempted to use &lt;code&gt;unwrap&lt;/code&gt; or &lt;code&gt;expect&lt;/code&gt; to quickly get results out of&lt;code&gt;Option&lt;/code&gt; or &lt;code&gt;Result&lt;/code&gt;.&lt;br&gt;
But in smart contracts?&lt;br&gt;
&lt;strong&gt;That’s like defusing a bomb with your eyes closed. One wrong unwrap, and boom ~ your transaction is gone, and you’ve wasted gas.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Polkadot smart contracts, panicking can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;💸 Waste the caller’s gas. &lt;/li&gt;
&lt;li&gt;🚫 Revert the entire transaction. &lt;/li&gt;
&lt;li&gt;😬 Break user trust.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So instead of forcing results, handle errors gracefully.&lt;br&gt;
👉 Always use &lt;code&gt;Result&lt;/code&gt; or &lt;code&gt;Option&lt;/code&gt; properly.&lt;br&gt;
👉 Return helpful errors instead of setting traps.&lt;/p&gt;

&lt;p&gt;Smart contracts are like public playgrounds. Don’t leave loose wires sticking out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5. &lt;strong&gt;Storage&lt;/strong&gt; – &lt;strong&gt;&lt;em&gt;Where Every Byte Has Rent&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On Polkadot, storage isn’t free. It’s not like your 500GB hard drive at home.&lt;br&gt;
Each piece of data your contract stores costs gas and the bigger your storage, the more expensive your contract gets.&lt;/p&gt;

&lt;p&gt;👉 In Rust, you can use all kinds of fancy data structures.&lt;br&gt;
👉 In ink!, you need to be &lt;strong&gt;smart and lean&lt;/strong&gt;.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Mapping&lt;/code&gt; instead of heavy &lt;code&gt;HashMap&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compact, storage-friendly types. &lt;/li&gt;
&lt;li&gt;Careful cloning (remember, copying big stuff is like duplicating a skyscraper it’s expensive.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The storage you design is like renting space in a premium apartment don’t hoard junk you don’t need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building on Polkadot is exciting, but it’s a different playground.&lt;br&gt;
&lt;strong&gt;If you master these five Rust concepts, you’ll be a few steps ahead of most people stumbling through smart contract development&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 You don’t need to be a Rust wizard.&lt;br&gt;
👉 You just need to know what matters.&lt;/p&gt;

&lt;p&gt;So go ahead build, test, break things, and fix them. And remember,&lt;br&gt;
&lt;strong&gt;Smart contracts don’t need to be smart to everyone. They just need to work&lt;/strong&gt;. &lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The Rust concepts that challenge you the most are usually the ones that will grow you the fastest&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;If you found this article interesting, what else would you add? Let me know in the comments.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/book/" rel="noopener noreferrer"&gt;The Rust Programming Language Book (Official)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/reference/items/modules.html#non-standard-library-attributes" rel="noopener noreferrer"&gt;Rust Reference - Non-standard Library Attributes (no_std)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://use.ink/" rel="noopener noreferrer"&gt;ink! Smart Contract Documentation (Official)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/core/" rel="noopener noreferrer"&gt;Rust core and alloc Libraries&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ownership</category>
      <category>traits</category>
      <category>errors</category>
      <category>rust</category>
    </item>
    <item>
      <title>Strategies for Debugging Immutable Code</title>
      <dc:creator>Cherrypick14</dc:creator>
      <pubDate>Sun, 09 Jun 2024 21:10:54 +0000</pubDate>
      <link>https://forem.com/cherrypick14/strategies-for-debugging-immutable-code-1a8b</link>
      <guid>https://forem.com/cherrypick14/strategies-for-debugging-immutable-code-1a8b</guid>
      <description>&lt;p&gt;As any seasoned developer can attest, debugging code can often feel like a never-ending battle against an ever-multiplying army of bugs – a relentless game of whack-a-mole where squashing one issue only seems to spawn two more in its place. In the world of Go programming, immutability is a powerful ally that can make your code more reliable and easier to maintain, but even this helpful tool has its own unique challenges when it comes to debugging.&lt;/p&gt;

&lt;p&gt;In Go, you'll find two types of data structures: &lt;strong&gt;immutable (value) types&lt;/strong&gt; and &lt;strong&gt;mutable (reference) types&lt;/strong&gt;. Immutable types, like &lt;strong&gt;int, float, bool, string,&lt;/strong&gt; and good ol' &lt;strong&gt;structs&lt;/strong&gt; without any fancy reference types, are set in stone – they cannot be modified after creation, much like a developer's love for a good cup of coffee. On the other hand, &lt;strong&gt;mutable types&lt;/strong&gt;, such as &lt;strong&gt;slices, maps,&lt;/strong&gt; and &lt;strong&gt;channels,&lt;/strong&gt; can be changed, even though their elements might be immutable or mutable depending on their types, making them as unpredictable as a rubber duck's mood.&lt;/p&gt;

&lt;p&gt;Working with immutable data structures can simplify how you think about your program's state and reduce the risk of unintended changes causing bugs. However, even with these benefits, debugging immutable code can present its own unique challenges, like trying to navigate a maze while wearing a blindfold – frustrating, but not impossible with the right strategies.&lt;/p&gt;

&lt;p&gt;Immutable data structures, by their very nature, cannot be modified once created, which can make it tricky to observe and manipulate data during the debugging process. It's like trying to catch a glimpse of a shooting star – blink, and you might miss it. Additionally, immutability can introduce new kinds of bugs, such as &lt;em&gt;accidentally creating new copies of data&lt;/em&gt; when you intended to modify existing ones, leaving you scratching your head like a confused monkey.&lt;/p&gt;

&lt;p&gt;This article aims to equip you with practical strategies and techniques for effectively debugging immutable code in Go. Whether you're working with built-in immutable types or creating your own custom immutable data structures, these strategies will help you identify and resolve issues more efficiently, allowing you to fully harness the power of immutability in your Go projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Leveraging Logging and Tracing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One of the most powerful tools for debugging immutable code is effective logging and tracing. By logging relevant information at strategic points in your code, you can gain valuable insights into the state of your program and the flow of data through your immutable data structures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func processData(data []byte) (result []byte, err error) {
    log.Printf("Processing data: %v", data)
    // ... data processing logic ...
    log.Printf("Result: %v", result)
    return result, nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we log the input data and the final result, providing a clear trail of information that can aid in debugging. Additionally, you can employ more advanced logging techniques, such as structured logging or using third-party logging libraries like logrus or zap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Leverage Debuggers and Profilers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While immutable data structures can simplify debugging by reducing the number of potential sources of mutation, they can also make it more challenging to observe and manipulate data during the debugging process. Fortunately, Go's built-in debugger (dlv) and profiling tools can be invaluable allies in these situations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main() {
    data := []byte("hello, world")
    result, err := processData(data)
    if err != nil {
        log.Fatalf("Error processing data: %v", err)
    }
    fmt.Println(string(result))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By setting breakpoints and inspecting variables at different points in your code, you can gain insights into the state of your immutable data structures and identify potential issues. Additionally, profiling tools like pprof can help you detect performance bottlenecks, memory leaks, or other issues that may be related to your immutable data structures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Embrace Pure Functions and Immutable Transformations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Functional programming techniques, such as pure functions and immutable data transformations, can greatly simplify debugging by reducing side effects and making code more predictable. In Go, you can leverage these techniques to work with immutable data structures more effectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func transformData(data []byte) []byte {
    // Perform some transformation on the data
    // ...
    return result
}

func processData(data []byte) ([]byte, error) {
    transformed := transformData(data)
    // ... further processing ...
    return result, nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, transformData is a pure function that takes an immutable slice of bytes as input and returns a new, transformed slice without modifying the original data. &lt;code&gt;transformData&lt;/code&gt; is likely a pure function because it consistently returns the same result for the same input and has no side effects while &lt;code&gt;processData&lt;/code&gt; is less likely to be a pure function due to error handling and potential side effects from additional processing.By separating your data transformations into pure functions, you can more easily reason about their behavior and identify potential issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Leverage Third-Party Libraries and Tools&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While Go's standard library provides some immutable data structures (e.g., &lt;em&gt;bytes.Buffer&lt;/em&gt;, &lt;em&gt;strings.Builder&lt;/em&gt;), there are also several third-party libraries and tools available that can aid in working with immutable data structures and debugging immutable code.&lt;/p&gt;

&lt;p&gt;For example, the &lt;em&gt;immutable package&lt;/em&gt; (&lt;a href="https://github.com/benbjohnson/immutable" rel="noopener noreferrer"&gt;https://github.com/benbjohnson/immutable&lt;/a&gt;) provides a collection of immutable data structures, including &lt;em&gt;lists&lt;/em&gt;, &lt;em&gt;maps&lt;/em&gt;, and &lt;em&gt;sets&lt;/em&gt;. Using these data structures can simplify your code and provide additional debugging benefits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Debugging immutable code in Go requires a combination of effective &lt;em&gt;logging and tracing&lt;/em&gt;, &lt;em&gt;leveraging debuggers&lt;/em&gt; and &lt;em&gt;profilers&lt;/em&gt;, embracing &lt;em&gt;pure functions&lt;/em&gt; and &lt;em&gt;immutable transformations&lt;/em&gt;, and taking advantage of &lt;em&gt;third-party libraries and tools&lt;/em&gt;. By applying these strategies, you can unlock the full potential of immutability in Go, writing more robust and maintainable code while simplifying the debugging process.&lt;/p&gt;

&lt;p&gt;Remember, immutability is a powerful tool for reducing bugs and improving code quality, and mastering the art of debugging immutable code can be a game-changer for your Go development workflow. While the strategies discussed in this article can greatly aid in debugging immutable code, it's essential to continually learn and adapt as new techniques and tools emerge.&lt;/p&gt;

</description>
      <category>go</category>
      <category>immutablecode</category>
      <category>debuggingtechniques</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Demystifying Regex in Go</title>
      <dc:creator>Cherrypick14</dc:creator>
      <pubDate>Sun, 19 May 2024 22:54:19 +0000</pubDate>
      <link>https://forem.com/cherrypick14/demystifying-regex-in-go-4clf</link>
      <guid>https://forem.com/cherrypick14/demystifying-regex-in-go-4clf</guid>
      <description>&lt;p&gt;Certainly! Regular expressions (regex) in Go can be a powerful tool for pattern matching and text manipulation, but they should be used judiciously and in appropriate scenarios. Here are some points to consider:&lt;/p&gt;

&lt;p&gt;When &lt;strong&gt;TO&lt;/strong&gt; use regex in Go:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validating user input&lt;/strong&gt;: Regex can be used to validate input strings against specific patterns, such as email addresses, phone numbers, or URLs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parsing and extracting data&lt;/strong&gt;: Regex can help extract specific parts of a string, such as extracting dates, IDs, or keywords from larger texts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Text manipulation&lt;/strong&gt;: Regex can be used to perform operations like replacing, splitting, or cleaning text based on patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Log analysis&lt;/strong&gt;: Regex is useful for parsing and analyzing log files, where patterns need to be identified and extracted.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitrat28xe39fw1b5a5f8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitrat28xe39fw1b5a5f8.png" alt="Log analysis using regular expressions " width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The example provided falls under the category of "Log analysis": Regex is useful for parsing and analyzing log files, where patterns need to be identified and extracted.&lt;/p&gt;

&lt;p&gt;In the given example, we are using a regular expression pattern to parse and extract relevant information (timestamp, severity level, and message) from log entries. This is a typical use case for log analysis, where log files often contain semi-structured or unstructured data that needs to be parsed and processed.&lt;/p&gt;

&lt;p&gt;In the above example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We define a regular expression pattern &lt;code&gt;^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(\w+)\] (.*)&lt;/code&gt; that captures the &lt;em&gt;timestamp&lt;/em&gt;, &lt;em&gt;severity level&lt;/em&gt;, and &lt;em&gt;message&lt;/em&gt; from the log entry.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;regexp.MustCompile&lt;/strong&gt; function compiles the regular &lt;br&gt;
expression &lt;em&gt;pattern&lt;/em&gt; into a regular expression &lt;em&gt;object&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;FindStringSubmatch&lt;/strong&gt; method is used to match the &lt;em&gt;pattern&lt;/em&gt; against the &lt;em&gt;log entry&lt;/em&gt; string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a match is found, the captured groups are extracted from the &lt;strong&gt;match&lt;/strong&gt; slice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The extracted timestamp, severity, and message are printed to the console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you run this code with the log entry &lt;strong&gt;"2023-05-18 12:35:12 [ERROR] Failed to connect to the database."&lt;/strong&gt;, the output will be:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7rjbs0ua4lqh8g7w97s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7rjbs0ua4lqh8g7w97s.png" alt="regex output for the log entry" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This example demonstrates how regular expressions can be used to parse and extract specific pieces of information from semi-structured text data, such as log entries. By defining a suitable pattern, you can capture the desired parts of the text and process them further as needed.&lt;/p&gt;

&lt;p&gt;Regular expressions are particularly useful in scenarios where the data format is not strictly defined or follows a loosely structured pattern, making it difficult to use traditional parsing techniques or libraries.&lt;/p&gt;

&lt;p&gt;An explanation of the different parts of the regex pattern above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(\w+)\] (.*)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})&lt;/code&gt;: This part captures the timestamp in the format "YYYY-MM-DD HH:MM:SS". The parentheses &lt;code&gt;()&lt;/code&gt; create a capturing group, which means the matched text will be stored in the result array for later use. The &lt;code&gt;^&lt;/code&gt; symbol asserts that the match must start at the beginning of the string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;\[(\w+)\]&lt;/code&gt;: This part captures the severity level enclosed within square brackets &lt;code&gt;[]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;\[&lt;/code&gt; and &lt;code&gt;\]&lt;/code&gt; are used to match the literal square bracket characters &lt;code&gt;[&lt;/code&gt; and &lt;code&gt;]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;(\w+)&lt;/code&gt; is a capturing group that matches one or more word characters (&lt;code&gt;\w&lt;/code&gt; matches letters, digits, or underscores).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;(.*)&lt;/code&gt;: This part captures the remaining text after the severity level, which is the log message itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;(.*)&lt;/code&gt; is a capturing group that matches any character (except newline) zero or more times using the &lt;code&gt;.*&lt;/code&gt; pattern.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, when you break it down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;\[(\w+)\]&lt;/code&gt; captures the severity level (e.g., "INFO", "WARNING", "ERROR") inside the square brackets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;(.*)&lt;/code&gt; captures the log message that comes after the severity level.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the example log entry &lt;code&gt;"2023-05-18 12:35:12 [ERROR] Failed to connect to the database."&lt;/code&gt;, the regular expression pattern will match as follows:&lt;/p&gt;

&lt;p&gt;The first capturing group&lt;code&gt;(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})&lt;/code&gt; will capture &lt;code&gt;"2023-05-18 12:35:12"&lt;/code&gt; (the timestamp).&lt;/p&gt;

&lt;p&gt;The second capturing group &lt;code&gt;(\w+)&lt;/code&gt; inside &lt;code&gt;\[(\w+)\]&lt;/code&gt;  will capture "ERROR" (the severity level).&lt;/p&gt;

&lt;p&gt;The third capturing group &lt;code&gt;(.*)&lt;/code&gt; will capture &lt;code&gt;"Failed to connect to the database."&lt;/code&gt; (the log message).&lt;/p&gt;

&lt;p&gt;These captured groups are stored in the &lt;code&gt;match&lt;/code&gt; slice, which you can then access and use in your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;match := re.FindStringSubmatch(logEntry)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By defining a suitable regular expression pattern, we can identify and extract specific components of the log entries, such as the timestamp, severity level, and message. This allows us to analyze and process the log data more effectively, as we can separate and handle each component individually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log analysis&lt;/strong&gt; is one of the most common and robust use cases for regular expressions because log files frequently exhibit varying formats and patterns, making it challenging to use traditional parsing techniques or libraries. Regular expressions provide the flexibility and power to handle these diverse log formats and extract the desired information.&lt;/p&gt;

&lt;p&gt;When &lt;strong&gt;NOT&lt;/strong&gt; to use regex in Go:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When the pattern is &lt;strong&gt;simple&lt;/strong&gt;: For basic string operations like checking if a string starts or ends with a specific substring, using built-in string functions like &lt;code&gt;strings.HasPrefix&lt;/code&gt; or &lt;code&gt;strings.HasSuffix&lt;/code&gt; is more efficient and readable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the pattern is &lt;strong&gt;complex&lt;/strong&gt;: While regex can handle complex patterns, it can become difficult to read and maintain. In such cases, it's better to use dedicated parsing libraries or write custom parsing logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When performance is &lt;strong&gt;critical&lt;/strong&gt;: Regex operations can be computationally expensive, especially for complex patterns or large input strings. If performance is a concern, consider alternative approaches or optimize the regex pattern.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Potential alternatives to regex in Go:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;String manipulation functions: Go's standard library provides various string functions (strings package) that can handle basic operations without the need for regex.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dedicated parsing libraries: For specific domains or formats, there may be dedicated parsing libraries that offer a more robust and efficient solution than regex. For example, the &lt;strong&gt;net/url package&lt;/strong&gt; for &lt;strong&gt;parsing URLs&lt;/strong&gt;, or the &lt;strong&gt;encoding/json package&lt;/strong&gt; for &lt;strong&gt;parsing JSON data&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Custom parsing logic: Depending on the complexity of the problem, writing custom parsing logic using &lt;strong&gt;string operations&lt;/strong&gt; and &lt;strong&gt;control flow statements&lt;/strong&gt; can be more readable and efficient than regex in some cases.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Tools&lt;/strong&gt; and &lt;strong&gt;utilities&lt;/strong&gt; for working with regex in Go:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;regexp package: Go's standard library includes the regexp package, which provides functionality for working with regular expressions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Online regex testers and debuggers: Tools like (&lt;a href="https://regex101.com/" rel="noopener noreferrer"&gt;https://regex101.com/&lt;/a&gt;) or (&lt;a href="https://regexr.com/" rel="noopener noreferrer"&gt;https://regexr.com/&lt;/a&gt;) can help you test and debug your regular expressions before integrating them into your Go code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Regex playground: The Go Playground (&lt;a href="https://go.dev/play/" rel="noopener noreferrer"&gt;https://go.dev/play/&lt;/a&gt;) allows you to experiment with regex patterns and Go code interactively.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When using regex in Go, it's important to follow &lt;strong&gt;Best Practices&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Use named capturing groups and comments to &lt;strong&gt;improve readability&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test&lt;/strong&gt; and &lt;strong&gt;validate&lt;/strong&gt; your regex patterns thoroughly.&lt;br&gt;
Consider performance implications, especially for &lt;strong&gt;complex patterns&lt;/strong&gt; or &lt;strong&gt;large input strings&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prefer &lt;strong&gt;simple string operations&lt;/strong&gt; or dedicated parsing libraries when appropriate, as they can be more &lt;strong&gt;efficient&lt;/strong&gt; and &lt;strong&gt;maintainable&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By carefully considering the scenarios and weighing the trade-offs, one can effectively leverage the power of regex in Go while maintaining code readability, maintainability, and performance.&lt;/p&gt;

</description>
      <category>go</category>
      <category>regex</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Pull from a Remote Repository</title>
      <dc:creator>Cherrypick14</dc:creator>
      <pubDate>Wed, 07 Sep 2022 11:49:49 +0000</pubDate>
      <link>https://forem.com/cherrypick14/how-to-pull-from-a-remote-repository-2g52</link>
      <guid>https://forem.com/cherrypick14/how-to-pull-from-a-remote-repository-2g52</guid>
      <description>&lt;p&gt;Suppose you're working on a project with other developers. The first thing to do is to create a repository where all the workflow will take place. Since y'all are gonna contribute to the repo, you have to understand the git tools. Someone from the team has made some changes to the repo, how do you stay updated..? Instead of &lt;strong&gt;zipping up files&lt;/strong&gt; and creating more confusion, all you need to do is &lt;strong&gt;pull&lt;/strong&gt; their changes into your &lt;strong&gt;local repository&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to pull the changes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to your Git repo folder in your chosen terminal.&lt;/li&gt;
&lt;li&gt;Then run a &lt;strong&gt;git pull&lt;/strong&gt; command.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So git pull is usually a combination of &lt;strong&gt;git fetch&lt;/strong&gt; + &lt;strong&gt;git merge&lt;/strong&gt;&lt;br&gt;
It basically involves fetching &lt;strong&gt;upstream changes&lt;/strong&gt; and syncing them with the &lt;strong&gt;local ones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should I use git pull?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Before you start working ~ to stay updated with the latest changes.&lt;/li&gt;
&lt;li&gt;Before you push anything.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Fetching the Changes:&lt;/strong&gt;&lt;br&gt;
git fetch gets to download the latest remote repo changes.&lt;br&gt;
git merge now merges those changes into your local codebase.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And what if I want to review the changes first and not merge the code immediately..?&lt;/em&gt; ~ Just do a &lt;strong&gt;git fetch&lt;/strong&gt; other than &lt;strong&gt;git pull&lt;/strong&gt;.&lt;br&gt;
You'll get to proceed as per the steps listed in the ~ &lt;strong&gt;How to pull the changes&lt;/strong&gt;. The difference comes in the 2nd part, instead of running a &lt;strong&gt;git pull&lt;/strong&gt; command, run &lt;strong&gt;git fetch&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Serving Your Static Files With Express</title>
      <dc:creator>Cherrypick14</dc:creator>
      <pubDate>Sat, 04 Dec 2021 15:16:44 +0000</pubDate>
      <link>https://forem.com/cherrypick14/serving-your-static-files-with-express-5g00</link>
      <guid>https://forem.com/cherrypick14/serving-your-static-files-with-express-5g00</guid>
      <description>&lt;p&gt;Getting started with Express&lt;/p&gt;

&lt;p&gt;What is Express?&lt;/p&gt;

&lt;p&gt;It's basically a web application framework for Node.&lt;/p&gt;

&lt;p&gt;First things first. Ensure your node.js env is set up. If not and you are a linux user, you can use a tool called Node Version Manager to help install node on your machine. &lt;strong&gt;Note&lt;/strong&gt;: You should have &lt;em&gt;git&lt;/em&gt; and &lt;em&gt;curl&lt;/em&gt; installed. To get started with &lt;em&gt;git&lt;/em&gt; and &lt;em&gt;curl&lt;/em&gt; if at all you don’t have them installed in your system’s package manager. Example on an ubuntu or Debian, one would run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install curl git 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So back to Express. Some of its &lt;strong&gt;merits&lt;/strong&gt; include its &lt;em&gt;flexibility _and _minimality&lt;/em&gt;. To get started using Express, you need to use NPM to install the module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get all dependencies that are needed to run the app, you run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have Express installed and an already existing directory like the one below, you’ll get to see something like this in the package.json file in “dependencies”.&lt;/p&gt;

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

&lt;p&gt;Let's talk about nodemon for a sec:&lt;/p&gt;

&lt;p&gt;From the above snip, you guys can note the nodemon in the devdependencies. It’s actually a tool that  helps node.js based  applications by &lt;strong&gt;automatically restarting&lt;/strong&gt; the node application&lt;br&gt;
when  file changes in the directory are &lt;strong&gt;spotted&lt;/strong&gt;. To install nodemon on your project as dev-dependency, just type;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install nodemon --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So to get started on serving your files with Express, make sure you have all your files &lt;strong&gt;including&lt;/strong&gt; the &lt;em&gt;index.html&lt;/em&gt; in your &lt;strong&gt;public directory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The files can be served as below:&lt;/p&gt;

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

&lt;p&gt;Incase this doesn’t work out for you, you can try using serve-index. Much is explained in this article. Check it out here:&lt;/p&gt;

&lt;p&gt;Opened to any feedback. #Learning never stops&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/swlh/serve-directory-listings-in-an-express-app-with-serve-index-ff54f20c9636" rel="noopener noreferrer"&gt;https://medium.com/swlh/serve-directory-listings-in-an-express-app-with-serve-index-ff54f20c9636&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
