<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bader Youssef</title>
    <description>The latest articles on DEV Community by Bader Youssef (@badery).</description>
    <link>https://dev.to/badery</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%2F2936415%2F4dd6efe8-481e-43a0-bea4-4988f6befea3.jpg</url>
      <title>DEV Community: Bader Youssef</title>
      <link>https://dev.to/badery</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/badery"/>
    <language>en</language>
    <item>
      <title>Introduction to Writing RISC-V Contracts in Rust on Polkadot</title>
      <dc:creator>Bader Youssef</dc:creator>
      <pubDate>Thu, 12 Feb 2026 21:17:06 +0000</pubDate>
      <link>https://dev.to/badery/introduction-to-writing-risc-v-contracts-in-rust-on-polkadot-29n7</link>
      <guid>https://dev.to/badery/introduction-to-writing-risc-v-contracts-in-rust-on-polkadot-29n7</guid>
      <description>&lt;p&gt;Smart contracts have long been the primary method for developing applications in Web3.&lt;/p&gt;

&lt;p&gt;However, the underlying technology hasn't changed much over the years. The &lt;a href="https://ethereum.org/developers/docs/evm/" rel="noopener noreferrer"&gt;EVM (Ethereum Virtual Machine)&lt;/a&gt; has long been the default option for smart contract development. It served its purpose well, bootstrapping an entire industry of decentralized applications.&lt;/p&gt;

&lt;p&gt;Today, it is a massive ecosystem that has become the de facto standard for interacting with Web3 infrastructure.&lt;/p&gt;

&lt;p&gt;Here’s the catch, though:&lt;/p&gt;

&lt;p&gt;The EVM is an emulation layer, not an actual machine.&lt;/p&gt;

&lt;p&gt;Compared to the rest of the software world, it is a virtual machine designed for a specific network, which comes with limitations. Although it is general-purpose in a sense, it does not give developers the full capabilities of a typical tech stack or the standard, high-performance tooling that powers the rest of the internet. If we want to create a new standard for Web3 software, it needs to be on par with (or ideally, better than) the status quo.&lt;/p&gt;

&lt;p&gt;This isolation is what holds back the next generation of complex, high-compute applications. We should be able to create and deploy applications the same way we do in the ‘conventional‘ sense on Web3.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Current State of Smart Contracts
&lt;/h2&gt;

&lt;p&gt;Smart contracts today are rather simplistic in terms of developer experience and execution. The developer writes high-level code, compiles it to bytecode, and the EVM executes that bytecode instruction-by-instruction. While effective, it is slow compared to native execution.&lt;/p&gt;

&lt;p&gt;By relying on a custom virtual machine, we lose access to the decades of optimization that have gone into standard hardware architectures like &lt;a href="https://riscv.org/" rel="noopener noreferrer"&gt;RISC-V&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://github.com/paritytech/polkavm" rel="noopener noreferrer"&gt;PolkaVM&lt;/a&gt; comes in.&lt;/p&gt;

&lt;p&gt;PolkaVM is a RISC-V-based virtual machine that allows developers to write smart contracts in Rust, Go, and other languages that can be compiled by &lt;a href="https://llvm.org/" rel="noopener noreferrer"&gt;LLVM&lt;/a&gt;, just like traditional software. It represents a shift to "bare metal" execution.&lt;/p&gt;

&lt;p&gt;It still executes deterministic logic and maintains persistent state, but it grants developers flexibility beyond the typical bounds of a custom, virtual machine sandbox.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Picture: Polkadot &amp;amp; Revive
&lt;/h2&gt;

&lt;p&gt;Taking a step back, it is important to note that Polkadot supports Solidity through &lt;a href="https://github.com/paritytech/revive" rel="noopener noreferrer"&gt;Revive&lt;/a&gt; (&lt;code&gt;pallet-revive&lt;/code&gt;). Revive is a compiler pipeline that targets PolkaVM (RISC-V) while keeping Ethereum tooling compatibility as a first-class goal.&lt;/p&gt;

&lt;p&gt;Think of it as a translation layer. On the node side, you can run an Ethereum JSON-RPC adapter (often referred to as an &lt;code&gt;eth-rpc&lt;/code&gt; adapter) so tools like &lt;a href="https://metamask.io/" rel="noopener noreferrer"&gt;MetaMask&lt;/a&gt;, &lt;a href="https://hardhat.org/" rel="noopener noreferrer"&gt;Hardhat&lt;/a&gt;, or &lt;a href="https://getfoundry.sh/" rel="noopener noreferrer"&gt;Foundry&lt;/a&gt; can speak "normal Ethereum JSON-RPC" while the node translates those calls into the underlying Polkadot runtime and contract environment.&lt;/p&gt;

&lt;p&gt;When you send a transaction, the adapter and runtime plumbing route it into the PolkaVM execution engine, taking advantage of the performance and security properties of the underlying RISC-V VM.&lt;/p&gt;

&lt;p&gt;If you want a reference point on Ethereum RPC support on Polkadot Hub, see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.polkadot.com/node-infrastructure/run-a-node/polkadot-hub-rpc/" rel="noopener noreferrer"&gt;Polkadot Hub RPC node guide (Ethereum RPC adapter)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/" rel="noopener noreferrer"&gt;Smart contract functionality / Ethereum tooling compatibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also see how smart contracts on Polkadot Hub generally work: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.polkadot.com/smart-contracts/get-started/" rel="noopener noreferrer"&gt;Get Started - Smart Contracts on Polkadot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The "Bare Metal" Environment
&lt;/h2&gt;

&lt;p&gt;Solidity is not our only option. As mentioned previously, we can write contracts in any language that compiles to RISC-V, such as Rust.&lt;/p&gt;

&lt;p&gt;Writing for PolkaVM is similar to writing for an embedded environment. You are operating on "bare metal," without an operating system (OS).&lt;/p&gt;

&lt;p&gt;This is a &lt;code&gt;no_std&lt;/code&gt; environment. The Rust standard library (&lt;code&gt;std&lt;/code&gt;) assumes OS services for things like threads, files, and some allocation plumbing. Since we don't have an OS, we cannot use &lt;code&gt;std&lt;/code&gt; in the usual way.&lt;/p&gt;

&lt;p&gt;However, you can still use &lt;code&gt;core&lt;/code&gt; (always available) and &lt;code&gt;alloc&lt;/code&gt; if you provide a global allocator.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory: Stack vs. Heap
&lt;/h2&gt;

&lt;p&gt;To understand why &lt;code&gt;no_std&lt;/code&gt; is challenging, we need to look at how computers manage memory:&lt;/p&gt;




&lt;h3&gt;
  
  
  The Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mechanism:&lt;/strong&gt; Linear memory, Last-In/First-Out (LIFO). It’s fast because “allocating” is often just moving a pointer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Limitation:&lt;/strong&gt; The compiler needs to know sizes up-front. This makes truly dynamic structures harder.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The Heap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mechanism:&lt;/strong&gt; Dynamic memory for data structures that can grow/shrink at runtime (like &lt;code&gt;Vec&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Cost:&lt;/strong&gt; It needs an allocator to manage free space and fragmentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a standard environment, the allocator is provided for you. In a &lt;code&gt;no_std&lt;/code&gt; environment, you start without one.&lt;/p&gt;

&lt;p&gt;This doesn’t mean "no heap is possible" - it means you don’t get heap allocation for free. If you want dynamic data, you provide an allocator.&lt;/p&gt;




&lt;h2&gt;
  
  
  Entering the Allocator
&lt;/h2&gt;

&lt;p&gt;What if we could have an allocator for the heap, even in a &lt;code&gt;no_std&lt;/code&gt; environment?&lt;/p&gt;

&lt;p&gt;We can. By adding a memory allocator like &lt;a href="https://crates.io/crates/picoalloc" rel="noopener noreferrer"&gt;picoalloc&lt;/a&gt;, we can manage a fixed chunk of memory (typically a statically reserved region) as a heap.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We designate a fixed region of memory for the allocator to manage.&lt;/span&gt;
&lt;span class="nd"&gt;#[global_allocator]&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;ALLOC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;picoalloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This unlocks the standard &lt;a href="https://doc.rust-lang.org/alloc/" rel="noopener noreferrer"&gt;&lt;code&gt;alloc&lt;/code&gt;&lt;/a&gt; crate, allowing you to use useful types like &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; even in a &lt;code&gt;no_std&lt;/code&gt; environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Host Functions &amp;amp; ABI
&lt;/h2&gt;

&lt;p&gt;If the contract runs in an isolated environment, how does it interact with the blockchain?&lt;/p&gt;

&lt;p&gt;It uses a host interface (in Revive’s stack this is commonly accessed via the &lt;code&gt;pallet-revive-uapi&lt;/code&gt; crate). When the contract needs to store data, transfer tokens, emit events, or inspect chain context, it calls host functions.&lt;/p&gt;

&lt;p&gt;Here are representative host functions you’ll see in &lt;code&gt;pallet-revive-uapi&lt;/code&gt; (names match the HostFn surface):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Host Function&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;set_storage&lt;/code&gt; / &lt;code&gt;get_storage&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Write/read contract storage (key/value).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;call&lt;/code&gt; / &lt;code&gt;instantiate&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Call another contract / deploy a new contract instance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deposit_event&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Emit an event (topics + data).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;caller&lt;/code&gt; / &lt;code&gt;origin&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Get the caller and origin addresses.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;call_data_size&lt;/code&gt; / &lt;code&gt;call_data_copy&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Read transaction input (calldata).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;return_value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Return data (and optionally revert) and stop execution.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;balance&lt;/code&gt; / &lt;code&gt;balance_of&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Query balances.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.rs/pallet-revive-uapi/latest/pallet_revive_uapi/" rel="noopener noreferrer"&gt;pallet-revive-uapi docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Data Persistence (Storage)
&lt;/h2&gt;

&lt;p&gt;If you’re writing your PVM contract in Rust, storage is fairly conventional. It is a raw key-value store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keys:&lt;/strong&gt; Fixed-size byte arrays (commonly 32 bytes).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Values:&lt;/strong&gt; Variable-length byte arrays.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;VALUE_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would then be stored using a host function like &lt;code&gt;set_storage&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;set_storage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nn"&gt;StorageFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;VALUE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value_bytes&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The ABI (Application Binary Interface)
&lt;/h2&gt;

&lt;p&gt;The ABI defines how functions are identified within the contract. In Ethereum-style ABIs, a 4-byte selector targets specific functions.&lt;/p&gt;

&lt;p&gt;We identify functions using selectors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take the text signature: &lt;code&gt;"flip()"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Hash it (Keccak-256)&lt;/li&gt;
&lt;li&gt;Take the first 4 bytes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This 4-byte ID acts as the “key” to select a function entry point.&lt;/p&gt;

&lt;p&gt;Our Rust contracts can use a Solidity interface as their ABI. This ensures Ethereum tooling compatibility: tools like Foundry’s &lt;a href="https://getfoundry.sh/reference/cast/cast" rel="noopener noreferrer"&gt;&lt;code&gt;cast&lt;/code&gt;&lt;/a&gt; can talk to your contract through an Ethereum JSON-RPC endpoint.&lt;/p&gt;

&lt;p&gt;This also means other contracts (Rust or Solidity) can call into your contract on-chain using the same ABI expectations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating an Ethereum ABI for a PVM Contract
&lt;/h2&gt;

&lt;p&gt;To define an Ethereum-compatible ABI, you have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an external Solidity file that defines your contract’s ABI.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;sol!&lt;/code&gt; macro in &lt;a href="https://alloy.rs/" rel="noopener noreferrer"&gt;alloy&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s look at how this works using &lt;code&gt;sol!&lt;/code&gt; with an external file. Suppose our Solidity interface contains a public function called &lt;code&gt;flip()&lt;/code&gt;. We import the contract as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;sol!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Flipper.sol"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The macro expands this at compile-time into Rust types with selectors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Generated code (simplified)&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;flipCall&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;SolCall&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;flipCall&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 4-byte selector for flip()&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SELECTOR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"flip()"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type safety:&lt;/strong&gt; Decode into Rust types rather than hand-parsing bytes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard selectors:&lt;/strong&gt; Same selector scheme as the EVM ABI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can then reference the selector like so: &lt;code&gt;Flipper::flipCall::SELECTOR&lt;/code&gt; in our dispatch loop. Once we determine which function the user is trying to call, we invoke the corresponding Rust function to do the work.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Build Pipeline
&lt;/h2&gt;

&lt;p&gt;The PVM build process consists of two stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rust -&amp;gt; ELF:&lt;/strong&gt; The compiler generates a standard ELF binary (&lt;code&gt;riscv64emac-unknown-none-polkavm&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refinement (Polkatool):&lt;/strong&gt; A specialized linker performs "tree shaking" (removing dead code) and optimization to produce the final &lt;code&gt;.polkavm&lt;/code&gt; file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This &lt;code&gt;.polkavm&lt;/code&gt; file is the artifact deployed on-chain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building and Deploying a Flipper Contract in Rust
&lt;/h2&gt;

&lt;p&gt;Enough talk: let's build a flipper contract and deploy it on the Polkadot Testnet. This contract will store a single boolean value and allow anyone to flip it between true and false.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before jumping into the code, we need to ensure your environment is set up with the necessary tools, a wallet, and testnet funds.&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Install Developer Tools
&lt;/h3&gt;

&lt;p&gt;You will need Git, Rust, and Foundry installed on your machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rust:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--proto&lt;/span&gt; &lt;span class="s1"&gt;'=https'&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;-sSf&lt;/span&gt; https://sh.rustup.rs | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Foundry:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://foundry.paradigm.xyz | bash
foundryup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Git:&lt;/strong&gt; If you don't have Git installed, download it from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/install/" rel="noopener noreferrer"&gt;https://git-scm.com/install/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2) Generate a Wallet
&lt;/h3&gt;

&lt;p&gt;We need a private key to sign transactions. We can use Foundry's &lt;code&gt;cast&lt;/code&gt; tool to generate one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cast wallet new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, save the wallet so we can use it for signing later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cast wallet import pvm-account &lt;span class="nt"&gt;--private-key&lt;/span&gt; &amp;lt;your-private-key-from-cast-wallet&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3) Get Testnet Funds
&lt;/h3&gt;

&lt;p&gt;We are deploying to the Polkadot testnet (Paseo / Asset Hub), so we’ll use a faucet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;a href="https://faucet.polkadot.io/" rel="noopener noreferrer"&gt;Polkadot Faucet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Select "Polkadot testnet (Paseo)" from the network list.&lt;/li&gt;
&lt;li&gt;Ensure the chain is on "Assethub".&lt;/li&gt;
&lt;li&gt;Enter the address you generated above.&lt;/li&gt;
&lt;li&gt;Click "Get Funds" (this may take a few minutes).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Scaffold
&lt;/h2&gt;

&lt;p&gt;To get started, clone a prepared template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;-b&lt;/span&gt; template https://github.com/CrackTheCode016/flipper-pvm flipper
&lt;span class="nb"&gt;cd &lt;/span&gt;flipper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: There is a CLI tool under development that can automate project creation and scaffolding (see: &lt;code&gt;cargo-pvm-contract&lt;/code&gt;). For this tutorial, we work manually from the template above.&lt;/p&gt;

&lt;p&gt;The template is already configured with the files we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/flipper.rs&lt;/code&gt; for logic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Flipper.sol&lt;/code&gt; for the ABI interface&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Implement Flipper (&lt;code&gt;src/flipper.rs&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;src/flipper.rs&lt;/code&gt;. The template provides scaffolding (allocator via picoalloc, panic handler, and the Solidity interface definition), but the core logic is missing.&lt;/p&gt;

&lt;p&gt;We need to fill in the &lt;code&gt;todo!()&lt;/code&gt; blocks for storage, event emission, and the dispatch loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Logic &amp;amp; Storage
&lt;/h2&gt;

&lt;p&gt;We’ll store our flipper state in &lt;code&gt;VALUE_KEY&lt;/code&gt;. Locate &lt;code&gt;get_value&lt;/code&gt; and &lt;code&gt;set_value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;fn get_value()&lt;/code&gt;, replace &lt;code&gt;todo!()&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;value_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value_bytes&lt;/span&gt;&lt;span class="nf"&gt;.as_mut_slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get_storage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;StorageFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;VALUE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Check if the last byte is non-zero (Solidity stores bool as uint8)&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Default to false if not set&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;fn set_value(value: bool)&lt;/code&gt;, replace &lt;code&gt;todo!()&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;value_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;value_bytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;set_storage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;StorageFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;VALUE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value_bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Event
&lt;/h2&gt;

&lt;p&gt;Find &lt;code&gt;emit_flipped&lt;/code&gt;. Replace &lt;code&gt;todo!()&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Flipper&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Flipped&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// The signature hash is the first topic (the event ID)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;topics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nn"&gt;Flipper&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Flipped&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SIGNATURE_HASH&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// We manually encode the data (bool as u256/32 bytes)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;deposit_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Entry Point
&lt;/h2&gt;

&lt;p&gt;Implement the &lt;code&gt;call()&lt;/code&gt; function (the main entry point). Replace &lt;code&gt;todo!()&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. INPUT HANDLING&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;call_data_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;call_data_size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;call_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;call_data_len&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;call_data_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;call_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. SELECTOR EXTRACTION&lt;/span&gt;
&lt;span class="c1"&gt;// We expect at least 4 bytes for the function selector&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;call_data&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ReturnFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;REVERT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"Input too short"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;call_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.try_into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 3. DISPATCHING&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;selector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle flip() function call&lt;/span&gt;
    &lt;span class="nn"&gt;Flipper&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;flipCall&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SELECTOR&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;set_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;emit_flipped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Handle get() function call&lt;/span&gt;
    &lt;span class="nn"&gt;Flipper&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;getCall&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SELECTOR&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_value&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// 4. RETURN ENCODING&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;return_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;return_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ReturnFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;return_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Unknown function selector - revert&lt;/span&gt;
        &lt;span class="nn"&gt;api&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ReturnFlags&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;REVERT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"Unknown function"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;

&lt;p&gt;Generate the artifacts for on-chain upload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, you should see &lt;code&gt;flipper.debug.polkavm&lt;/code&gt; within the &lt;code&gt;target&lt;/code&gt; directory.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deploy &amp;amp; Interact
&lt;/h2&gt;

&lt;p&gt;Set your RPC endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ETH_RPC_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://services.polkadothub-rpc.com/testnet"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cast send &lt;span class="nt"&gt;--account&lt;/span&gt; pvm-account &lt;span class="nt"&gt;--create&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xxd &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 99999 target/flipper.debug.polkavm&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, you should see output similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;blockHash             0xf215391078dd412eb90095e5c5ad4454a761299ef51ce9ad44e0dc5178f957ee
blockNumber           2
contractAddress       &amp;lt;YOUR_CONTRACT_ADDRESS&amp;gt;
cumulativeGasUsed     0
effectiveGasPrice     50000000000
from                  0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac
gasUsed               295239...
status                1 (success)...
to                    0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the &lt;code&gt;contractAddress&lt;/code&gt; and set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RUST_ADDRESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;YOUR_CONTRACT_ADDRESS&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Interaction
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check current value (should be false)&lt;/span&gt;
cast call &lt;span class="nv"&gt;$RUST_ADDRESS&lt;/span&gt; &lt;span class="s2"&gt;"get() returns (bool)"&lt;/span&gt;

&lt;span class="c"&gt;# Flip it!&lt;/span&gt;
cast send &lt;span class="nt"&gt;--account&lt;/span&gt; pvm-account &lt;span class="nv"&gt;$RUST_ADDRESS&lt;/span&gt; &lt;span class="s2"&gt;"flip()"&lt;/span&gt;

&lt;span class="c"&gt;# Check again (should be true)&lt;/span&gt;
cast call &lt;span class="nv"&gt;$RUST_ADDRESS&lt;/span&gt; &lt;span class="s2"&gt;"get() returns (bool)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;a href="https://polkadot.testnet.routescan.io/address/0x2044DB81C13954e157Cb9F1E006006a70b7CEA89" rel="noopener noreferrer"&gt;https://polkadot.testnet.routescan.io/address/0x2044DB81C13954e157Cb9F1E006006a70b7CEA89&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;PolkaVM demonstrates a future where web3 applications are not mini-apps, but full-scale programs running on real technology stacks. Building on Web3 should not be having to compromise on design due to technological limitations; rather, it should expand and broaden our horizons while providing a more resilient and robust future for computing.&lt;/p&gt;

&lt;p&gt;Working at this low level of smart contract development opens new avenues for computationally expensive applications, where every byte counts. Other contracts on-chain, whether written in Rust or Solidity, can call these optimized contracts, leveraging their lower costs and more practical execution models.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>rust</category>
      <category>polkadot</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Beginners Guide to Polkadot API (PAPI) - You've Got Mail!</title>
      <dc:creator>Bader Youssef</dc:creator>
      <pubDate>Wed, 12 Mar 2025 17:40:04 +0000</pubDate>
      <link>https://dev.to/badery/beginners-guide-to-polkadot-api-papi-youve-got-mail-mc1</link>
      <guid>https://dev.to/badery/beginners-guide-to-polkadot-api-papi-youve-got-mail-mc1</guid>
      <description>&lt;p&gt;Welcome to the Beginners Guide to Polkadot API series! &lt;/p&gt;

&lt;p&gt;This tutorial will focus on learning how to build and compose decentralized applications (dApps) on the Polkadot network. We will also define what that means exactly and explain how to create your first light client-powered app on Polkadot.&lt;/p&gt;

&lt;p&gt;If you're new to Polkadot (and blockchain development in general), keep reading; otherwise, you can skip to the tutorial below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Introduction: What is Polkadot?
&lt;/h2&gt;

&lt;p&gt;Polkadot's is a protocol that &lt;em&gt;coordinates&lt;/em&gt; and &lt;em&gt;secures&lt;/em&gt; different rollups (often called parachains) allowing for a horizontally scaling, heterogeneously sharded, multi-chain approach to Web3.  One of the keywords here is &lt;em&gt;heterogeneously sharded&lt;/em&gt;, meaning that each shard, or blockchain (or state machine, if you want to get more technical), contains its unique domain-specific logic. Anyone can build a rollup and inherit security from the Polkadot relay chain using the Polkadot SDK.  A rollup can be quite literally anything from a &lt;a href="https://wiki.polkadot.network/docs/learn-hyperbridge" rel="noopener noreferrer"&gt;bridge to Ethereum and other protocols (Hyperbridge)&lt;/a&gt;, &lt;a href="https://origintrail.io/technology/multichain" rel="noopener noreferrer"&gt;a decentralized knowledge graph️ (OriginTrail)&lt;/a&gt;, or even &lt;a href="https://acurast.com/" rel="noopener noreferrer"&gt;a cloud computing and oracle platform that is powered by old smartphones (Acurast)&lt;/a&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%2F08zo03nht5ni6uguovcy.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%2F08zo03nht5ni6uguovcy.png" alt="build-1-706b8858ef80594b1c9d2cd9c4ce0421" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once deployed, rollups can use cross-consensus messaging (&lt;a href="https://docs.polkadot.com/develop/interoperability/intro-to-xcm/" rel="noopener noreferrer"&gt;XCM&lt;/a&gt;) to communicate with one another. This is not limited to just rollups within Polkadot, but even to other protocols, such as Ethereum.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composing Applications Using the Polkadot Stack
&lt;/h2&gt;

&lt;p&gt;As Polkadot has a wide range of different application-specific rollups at our creative disposal, the concept of &lt;em&gt;composing&lt;/em&gt; apps should not be a foreign one. Similar to how a traditional, web2 application may use different services, APIs, and technologies to build a full-stack application, we can utilize the different parts of the Polkadot stack to build a web3 native application. You even go as far as to host your application on a web3 service to bypass the conventional means of deployment completely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Composer - The Polkadot API (PAPI)
&lt;/h2&gt;

&lt;p&gt;Although you can use a number of languages to build apps on Polkadot, such as Rust, Python, or Typescript/Javascript, we'll be using &lt;a href="https://papi.how/" rel="noopener noreferrer"&gt;&lt;strong&gt;Polkadot API&lt;/strong&gt;&lt;/a&gt;, or &lt;strong&gt;PAPI&lt;/strong&gt;, which is a Typescript library for interacting with Polkadot (and its rollups). The main differentiator with PAPI is its light-client-first approach, in which it has native support for communicating to Polkadot via a light client.&lt;/p&gt;

&lt;p&gt;The light client implementation, called &lt;a href="https://github.com/smol-dot/smoldot" rel="noopener noreferrer"&gt;&lt;code&gt;smoldot&lt;/code&gt;&lt;/a&gt;, runs in the background and ensures that we have the latest, verified chain state.  Using PAPI, you can even interact with multiple rollups on Polkadot at once.&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%2Fe81kd4nge31gl8s1ldem.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%2Fe81kd4nge31gl8s1ldem.png" alt="Screenshot 2025-03-11 at 3.38.51 PM" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Are Light Clients Important?
&lt;/h3&gt;

&lt;p&gt;Light clients are one of the two options for connecting to a blockchain, with the other usually depending on a single RPC provider (which often runs on a centralized server). They are typically a more secure, trust-minimized, efficient way of communicating to a blockchain. Light clients verify the state of the blockchain using Merkle proofs, ensuring it has not only the latest but &lt;em&gt;correct&lt;/em&gt; state. As it just verifies the headers of the blocks, it has no need to download the whole state, making it ideal for resource-constrained environments.&lt;/p&gt;

&lt;p&gt;Unlike RPC connections, they do not depend on a single RPC provider and can be embedded in both the browser and natively. &lt;/p&gt;

&lt;h2&gt;
  
  
  "You've Got Mail!" - Polkadot API Boilerplate and Example
&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%2Fvt6j2zao8e2sz3wf407n.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%2Fvt6j2zao8e2sz3wf407n.png" alt="rs_1024x759-161107120558-1024AOL" width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the explanation out of the way, let's get our hands dirty with some code. &lt;/p&gt;

&lt;h3&gt;
  
  
  Project Introduction
&lt;/h3&gt;

&lt;p&gt;Our project will be quite simple - it will be a CLI application that runs in the terminal, which watches the relay chain for a certain &lt;code&gt;extrinsic&lt;/code&gt; (a transaction). This extrinsic will be the &lt;code&gt;system.remarkWithEvent&lt;/code&gt; extrinsic, meaning it is coming from the &lt;code&gt;system&lt;/code&gt; pallet (module) on the Westend test network.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;system.remarkWithEvent&lt;/code&gt; extrinsic allows us to send any arbitrary data on-chain, with the end result being a hash that is the address and the word "email" combined (&lt;code&gt;address+email&lt;/code&gt;). We'll hash this combination and watch for remarks on a chain that are addressed to us. The &lt;code&gt;system.remarkWithEvent&lt;/code&gt; extrinsic emits an event that we can use PAPI to watch the chain for.&lt;/p&gt;

&lt;p&gt;Once we receive a remark addressed to us, we will play the infamous "You've Got Mail!" sound byte.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;You should have the following installed as a prerequisite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm&lt;/code&gt; (or other package manager)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;node&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://polkadot.js.org/extension/" rel="noopener noreferrer"&gt;Polkadot.js Browser Extension (wallet)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will also need an account with Westend tokens. Below you can find guides for both Polkadot.js and the faucet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DNU0p5G0Gqc" rel="noopener noreferrer"&gt;Creating Accounts on Polkadot.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://faucet.polkadot.io/westend" rel="noopener noreferrer"&gt;Westend Faucet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloning the repository
&lt;/h3&gt;

&lt;p&gt;For this tutorial, you can choose to run the example directly by cloning the &lt;a href="https://github.com/CrackTheCode016/polkadot-api-example-cli/tree/main" rel="noopener noreferrer"&gt;main branch of the repository&lt;/a&gt;, or to use a boilerplate/template and follow the tutorial. &lt;/p&gt;

&lt;p&gt;We need to clone the template, which has everything we need to get started with the Polkadot API and Typescript. Be sure you clone the correct branch (&lt;code&gt;empty-cli&lt;/code&gt;) which already provides all dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/CrackTheCode016/polkadot-api-example-cli &lt;span class="nt"&gt;--branch&lt;/span&gt; empty-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once cloned, run the following to ensure &lt;code&gt;npm&lt;/code&gt; dependencies are installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;polkadot-api-example-cli
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exploring the Template (Light Clients!)
&lt;/h3&gt;

&lt;p&gt;When we open the repository, we should see the following code (excluding imports):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withLightClient&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PolkadotClient&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Start the light client&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;smoldot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// The Westend Relay Chain&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;relayChain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;smoldot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addChain&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;chainSpec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;westEndChainSpec&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;getSmProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;relayChain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CLI Code goes here...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The notable function to pay attention to is the &lt;code&gt;withLightClient&lt;/code&gt; function. This function uses the built in light client functionality (powered by &lt;a href="https://github.com/smol-dot/smoldot" rel="noopener noreferrer"&gt;&lt;code&gt;smoldot&lt;/code&gt;&lt;/a&gt;) to actually create a light client that syncs and interacts with Polkadot right there in our application. &lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the CLI
&lt;/h3&gt;

&lt;p&gt;Next, let's create our CLI, which is to be done within the confines of the &lt;code&gt;main&lt;/code&gt; function. We will include an option (&lt;code&gt;-a&lt;/code&gt; / &lt;code&gt;--account&lt;/code&gt;), which will be the account we will watch for our "mail":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;figlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;textSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Web3 Mail Watcher&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Web3 Mail Watcher - A simple CLI tool to watch for remarks on Polkadot network&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-a, --account &amp;lt;account&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Account to watch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// CLI Arguments from commander&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Watching for Remarks
&lt;/h3&gt;

&lt;p&gt;Next, we need to start watching the Westend network for remarks sent to our account. As was done before, all code should be within the &lt;code&gt;main&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// We check for the --account flag, if its not provided we exit&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bgRed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Watching account:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;whiteBright&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="c1"&gt;// We create a light client to connect to the Polkadot (Westend) network&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lightClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;withLightClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// We get the typed API to interact with the network&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dotApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lightClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTypedApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wnd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// We subscribe to the System.Remarked event and watch for remarks from our account&lt;/span&gt;
        &lt;span class="nx"&gt;dotApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Remarked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// We look for a specific hash, indicating that its our address + an email&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="c1"&gt;// We calculate the hash of our account + email&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calculatedHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bytesToHex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;blake2b&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;+email`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dkLen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
            &lt;span class="c1"&gt;// If the hash matches, we play a sound and log the message - You got mail!&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`0x&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;calculatedHash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asHex&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;sound&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;youve-got-mail-sound.mp3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bgRed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`You got mail!`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bgCyan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;From:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;whiteBright&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bgBlue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hash:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;whiteBright&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asHex&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// If the account is not provided, we exit&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Account is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is doing quite a bit, so let's break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we check for the existance of the &lt;code&gt;--account&lt;/code&gt; argument, and log that we are watching that account, else we exit. We are using the &lt;code&gt;chalk&lt;/code&gt; package to add color to our &lt;code&gt;console.log&lt;/code&gt; statements.&lt;/li&gt;
&lt;li&gt;Next, we create our light client.&lt;/li&gt;
&lt;li&gt;We use a light client and the Westend chain specification (&lt;code&gt;wnd&lt;/code&gt;) to access a typed API. &lt;/li&gt;
&lt;li&gt;Once we have our API, we then begin to reactively watch the account for the event that corresponds to the remark. We analyze the payload, looking for a hash which is calculated as follows: 

&lt;ul&gt;
&lt;li&gt;hash of: &lt;code&gt;account_address+email&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;When an event containing this hash is identified, it then plays the "You've Got Mail!" soundbite.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compiling and running
&lt;/h3&gt;

&lt;p&gt;Once we have all of our code in place, we should compile and run the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm start &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--account&lt;/span&gt; &amp;lt;account-address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon running, we should have the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ npm start &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--account&lt;/span&gt; 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; youve-got-mail-web3@1.0.0 start
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; tsc &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; node ./dist/index.js &lt;span class="nt"&gt;--account&lt;/span&gt; 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY

 __        __   _    _____   __  __       _ _  __        __    _       _
 &lt;span class="se"&gt;\ \ &lt;/span&gt;     / /__| |__|___ /  |  &lt;span class="se"&gt;\/&lt;/span&gt;  | __ _&lt;span class="o"&gt;(&lt;/span&gt;_&lt;span class="o"&gt;)&lt;/span&gt; | &lt;span class="se"&gt;\ \ &lt;/span&gt;     / /_ _| |_ ___| |__   ___ _ __
  &lt;span class="se"&gt;\ \ &lt;/span&gt;/&lt;span class="se"&gt;\ &lt;/span&gt;/ / _ &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="s1"&gt;'_ \ |_ \  | |\/| |/ _` | | |  \ \ /\ / / _` | __/ __| '&lt;/span&gt;_ &lt;span class="se"&gt;\ &lt;/span&gt;/ _ &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="s1"&gt;'__|
   \ V  V /  __/ |_) |__) | | |  | | (_| | | |   \ V  V / (_| | || (__| | | |  __/ |
    \_/\_/ \___|_.__/____/  |_|  |_|\__,_|_|_|    \_/\_/ \__,_|\__\___|_| |_|\___|_|

Watching account: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
[smoldot] Smoldot v2.0.34
[smoldot] Chain initialization complete for westend2. Name: "Westend". Genesis hash: 0xe143…423e. Chain specification starting at: 0x10cf…b908 (#23920337)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing the CLI
&lt;/h2&gt;

&lt;p&gt;Now that our application is actively watching for remark events on-chain, we can move to testing to see if it works! &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As mentioned previously, you will need a Westend account with some tokens to pay for fees.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Navigate to the &lt;a href="https://dev.papi.how/extrinsics#networkId=westend&amp;amp;endpoint=light-client" rel="noopener noreferrer"&gt;PAPI Dev Console &amp;gt; Extrinsics&lt;/a&gt;. You then want to select the &lt;code&gt;System&lt;/code&gt; pallet, and the &lt;code&gt;remark_with_event&lt;/code&gt; call:&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%2Fwkljon74xpp6kjvc81zg.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%2Fwkljon74xpp6kjvc81zg.png" alt="Screenshot 2025-03-03 at 4.54.29 PM" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we want to be sure we get the correct input for the text field. We want to be sure we are following the convention we set forth in our application: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;address+email&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If for example, we are watching &lt;code&gt;5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY&lt;/code&gt;, then the field should look like the following: &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%2F750zp2c0igkpbe5pa94d.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%2F750zp2c0igkpbe5pa94d.png" alt="Screenshot 2025-03-03 at 4.58.04 PM" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this input is in place, you may click the &lt;code&gt;Submit extrinsic&lt;/code&gt; button, where you can sign using the Polkadot.js browser wallet: &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%2Fvjbvo4k5ew0jxqfz39ps.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%2Fvjbvo4k5ew0jxqfz39ps.png" alt="Screenshot 2025-03-03 at 5.00.20 PM" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Heading back to our CLI, we should soon see the following, along with the fact that "YOU'VE GOT MAIL!" (as in the sound should play):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; __        __   _    _____   __  __       _ _  __        __    _       _
 \ \      / /__| |__|___ /  |  \/  | __ _(_) | \ \      / /_ _| |_ ___| |__   ___ _ __
  \ \ /\ / / _ \ '_ \ |_ \  | |\/| |/ _` | | |  \ \ /\ / / _` | __/ __| '_ \ / _ \ '__|
   \ V  V /  __/ |_) |__) | | |  | | (_| | | |   \ V  V / (_| | || (__| | | |  __/ |
    \_/\_/ \___|_.__/____/  |_|  |_|\__,_|_|_|    \_/\_/ \__,_|\__\___|_| |_|\___|_|

Watching account: 5Cm8yiG45rqrpyV2zPLrbtr8efksrRuCXcqcB4xj8AejfcTB
You've got mail!
From: 5Cm8yiG45rqrpyV2zPLrbtr8efksrRuCXcqcB4xj8AejfcTB
Hash: 0xb6999c9082f5b1dede08b387404c9eb4eb2deee4781415dfa7edf08b87472050
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This application can be expanded in a number of ways, whether that is by adding a chatroom through remarks, or by using some of the rollups on Polkadot to expand the functionality.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>developer</category>
    </item>
  </channel>
</rss>
