<?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: David Ekete</title>
    <description>The latest articles on DEV Community by David Ekete (@davidekete).</description>
    <link>https://dev.to/davidekete</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%2F786858%2F109310c8-620c-4b25-b670-07546243d9e1.JPG</url>
      <title>DEV Community: David Ekete</title>
      <link>https://dev.to/davidekete</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidekete"/>
    <language>en</language>
    <item>
      <title>Working with Tokens on Solana using Native Rust</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Wed, 15 Oct 2025 23:01:52 +0000</pubDate>
      <link>https://dev.to/davidekete/working-with-tokens-on-solana-using-native-rust-1cdk</link>
      <guid>https://dev.to/davidekete/working-with-tokens-on-solana-using-native-rust-1cdk</guid>
      <description>&lt;p&gt;Tokens represent money-like assets, utility (governance or access), rewards and points, game items, tickets, and more. Most tokens on Solana follow the &lt;strong&gt;SPL Token&lt;/strong&gt; standard (or &lt;strong&gt;Token-2022&lt;/strong&gt; with extensions), which defines how tokens are created, transferred, and burned.&lt;/p&gt;

&lt;p&gt;This article will cover how tokens work on Solana and how you can use them in your program. The examples in this article are in Native Rust, but the concepts can be applied to any framework/library (Anchor, Pinocchio, Steel).&lt;/p&gt;

&lt;h2&gt;
  
  
  How Tokens Work on Solana
&lt;/h2&gt;

&lt;p&gt;Every token on Solana has a mint account. A mint account defines key information about the token, such as the decimals, authority (who can mint and optionally freeze), total supply, etc. However, the mint account only defines the token; it doesn’t store it.&lt;/p&gt;

&lt;p&gt;Token decimals describe the asset’s fractional precision. If a mint has &lt;code&gt;d&lt;/code&gt; decimals, then &lt;code&gt;1 token = 10^d&lt;/code&gt; base units. Because on-chain programs use &lt;strong&gt;integers only&lt;/strong&gt; to keep consensus deterministic (floating-point can round differently across machines), wallets and dapps convert to/from base units by multiplying or dividing by &lt;code&gt;10^d&lt;/code&gt;. For example, many fiat-like tokens (e.g., USDC) use &lt;strong&gt;6&lt;/strong&gt; decimals, so &lt;code&gt;1 USDC = 1,000,000&lt;/code&gt; base units.&lt;/p&gt;

&lt;p&gt;Tokens can exist as fungible or non-fungible (NFTs). Fungible tokens typically use decimals like &lt;code&gt;6&lt;/code&gt; or &lt;code&gt;9&lt;/code&gt; for divisibility, while NFTs use &lt;code&gt;0&lt;/code&gt; decimals and a supply of 1 (or small editions).&lt;/p&gt;

&lt;p&gt;The token balances live in Associated Token Accounts (ATAs). ATAs are deterministically derived from an &lt;code&gt;(owner, mint, token_program_id)&lt;/code&gt; tuple. Names, symbols, and logos aren’t in the mint or token account. UIs read them from a Metaplex Token Metadata account linked to the mint.&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%2Fjmitw2xqxrlss6xbugqy.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%2Fjmitw2xqxrlss6xbugqy.png" alt="How tokens work on Solana" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most resources on the web currently cover creating tokens on the client side with a CLI or SDK because it’s simpler, cheaper (no CPI), and fits one-off user-issued tokens or NFTs.&lt;/p&gt;

&lt;p&gt;This guide takes the other path, creating mints on-chain inside your program using PDAs and program-controlled authorities. That approach is crucial when the token is core to protocol safety or pricing, e.g., AMM LP shares, vault/receipt tokens, etc., and as such, the examples in this tutorial are helper functions that can be part of a bigger program, not a standalone one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your Development Environment
&lt;/h2&gt;

&lt;p&gt;To follow along with this tutorial, you will need to set up a minimal Native Rust program.&lt;/p&gt;

&lt;p&gt;Start by running the command below to create a new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo init token-mints &lt;span class="nt"&gt;--lib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add the following crates by running the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add borsh@1.5.7 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
cargo add solana-program@2.3.0 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
cargo add solana-system-interface@1.0.0 &lt;span class="nt"&gt;--features&lt;/span&gt; bincode &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
cargo add spl-associated-token-account@7.0.0 &lt;span class="nt"&gt;--features&lt;/span&gt; no-entrypoint &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
cargo add spl-token@7.0.0 &lt;span class="nt"&gt;--features&lt;/span&gt; no-entrypoint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The crates you added above include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;borsh&lt;/strong&gt; – Deterministic binary serialization/deserialization for your program/account data. Commonly used to (de)serialize instruction payloads and account state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;solana-program&lt;/strong&gt;: types like &lt;code&gt;Pubkey&lt;/code&gt;, &lt;code&gt;AccountInfo&lt;/code&gt;, &lt;code&gt;ProgramResult&lt;/code&gt;, entrypoint glue, sysvars, and helpers to build/parse instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;solana-system-interface&lt;/strong&gt; (+ &lt;code&gt;bincode&lt;/code&gt; feature) – Stable interface types/IDL for the System Program (create accounts, transfers, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;spl-associated-token-account&lt;/strong&gt; (&lt;code&gt;no-entrypoint&lt;/code&gt;) – Instruction builders and CPI interface for the Associated Token Account (ATA) Program (create/find ATAs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;spl-token&lt;/strong&gt; (&lt;code&gt;no-entrypoint&lt;/code&gt;) – Instruction builders, state types, and CPI interface for the SPL Token Program (mint, transfer, burn, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Ensure you install the exact versions in the command above, else this may not work as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating and Initializing a Token Mint
&lt;/h2&gt;

&lt;p&gt;In this section, you’ll build a small helper, &lt;code&gt;create_and_init_mint&lt;/code&gt;, that allocates a mint account as a PDA, then initializes it so your program (via a PDA) controls minting. We’ll set the freeze authority to &lt;code&gt;None&lt;/code&gt; to keep the asset non-custodial by default.&lt;/p&gt;

&lt;p&gt;The function will accept the following inputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accounts:

&lt;ul&gt;
&lt;li&gt;Payer (signer, writable)&lt;strong&gt;:&lt;/strong&gt; funds rent and signs the create account instruction.&lt;/li&gt;
&lt;li&gt;Mint (PDA, writable, uninitialized)&lt;strong&gt;:&lt;/strong&gt; the account to become your mint.&lt;/li&gt;
&lt;li&gt;System Program*&lt;em&gt;:&lt;/em&gt;* required by the system &lt;code&gt;create_account&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;program_id&lt;/code&gt;: your program ID.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;token_decimals: u8&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;mint_authority: Pubkey&lt;/code&gt; (recommend a program PDA)&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;mint_seeds: &amp;amp;[&amp;amp;[u8]]&lt;/code&gt; (the PDA seeds/bump for the mint)&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Before you proceed, ensure that you have the following imports at the top of your file:&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;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;account_info&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AccountInfo&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ProgramResult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;program&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;invoke_signed&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;program_error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;program_pack&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Pack&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Pubkey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rent&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Rent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;solana_program&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sysvar&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sysvar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;spl_token&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;spl_token&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;instruction&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;token_instruction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;spl_token&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;state&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;SplAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mint&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;SplMint&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the imports from &lt;code&gt;spl_token&lt;/code&gt; are renamed to avoid conflicts with packages from &lt;code&gt;solana_program&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Token Mint
&lt;/h3&gt;

&lt;p&gt;To create the mint, first, you allocate the mint account as a &lt;strong&gt;program-derived address (PDA)&lt;/strong&gt; and set its owner to the &lt;strong&gt;SPL Token program&lt;/strong&gt;. This ensures that, after creation, only the token program itself can mutate the mint’s data. &lt;/p&gt;

&lt;p&gt;Next, you set the &lt;strong&gt;mint authority&lt;/strong&gt; to a &lt;strong&gt;PDA controlled by your program&lt;/strong&gt;, so any future issuance must come through your on-chain logic (you’ll sign CPIs with &lt;code&gt;invoke_signed&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;You then intentionally leave the &lt;strong&gt;freeze authority&lt;/strong&gt; as &lt;code&gt;None&lt;/code&gt;, avoiding a built-in backdoor that could freeze user accounts. Finally, you choose the &lt;strong&gt;decimals&lt;/strong&gt; explicitly to set the asset’s precision up front (e.g., &lt;strong&gt;6&lt;/strong&gt; for fiat-like tokens, &lt;strong&gt;9&lt;/strong&gt; for Solana-style precision, &lt;strong&gt;0&lt;/strong&gt; for NFTs).&lt;/p&gt;

&lt;p&gt;Like so:&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;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_and_init_mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;program_id&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;Pubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AccountInfo&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;mint_authority&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;Pubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mint_seeds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&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="n"&gt;token_decimals&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="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ProgramResult&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;acc_iter&lt;/span&gt; &lt;span class="o"&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;accounts&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;//payer (signer), mint (writable), system program&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;payer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;token_mint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;system_program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;payer&lt;/span&gt;&lt;span class="py"&gt;.is_signer&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;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MissingRequiredSignature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="py"&gt;.is_writable&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;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidAccountData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Ensure the passed mint is exactly the PDA we expect for these seeds.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Pubkey&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create_program_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mint_seeds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;program_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.map_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="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidSeeds&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;expected&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;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidSeeds&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;space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SplMint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LEN&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&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;lamports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Rent&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.minimum_balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;space&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="nf"&gt;invoke_signed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;solana_system_interface&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create_account&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;payer&lt;/span&gt;&lt;span class="py"&gt;.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;token_mint&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;lamports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;space&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;payer&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;system_program&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mint_seeds&lt;/span&gt;&lt;span class="p"&gt;],&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you have created the token mint; next, you will initialize it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing Token Mints
&lt;/h3&gt;

&lt;p&gt;To initialize the token mint, you need to invoke the &lt;code&gt;initialize_mint2&lt;/code&gt; instruction from the SPL token program. Pass the SPL program ID, the mint account’s public key, the mint_authority, the freeze authority, and the decimals into the instructions and invoke the instruction with the token mint account.&lt;/p&gt;

&lt;p&gt;Like so (this snippet is part of &lt;code&gt;create_and_init_mint&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;initialize_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;token_instruction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;initialize_mint2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;mint_authority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;token_decimals&lt;/span&gt;&lt;span class="p"&gt;,&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="nf"&gt;invoke&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;initialize_ix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="nf"&gt;.clone&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="nf"&gt;Ok&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;There’s an alternative to the &lt;code&gt;initialize_mint2&lt;/code&gt; instruction, which is the &lt;code&gt;initialize_mint&lt;/code&gt; function. Both set the same mint fields (decimals, mint authority, freeze authority). The difference is in the required accounts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initialize_mint2&lt;/code&gt; &lt;strong&gt;does not&lt;/strong&gt; require the Rent sysvar; you pass only the mint account in the CPI account list.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialize_mint&lt;/code&gt; requires the Rent sysvar to be passed and will read it during initialization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After initialization, the mint’s total supply is 0. The SPL Token program does not enforce a cap; your supply policy is up to you. &lt;/p&gt;

&lt;p&gt;You create supply by calling &lt;code&gt;mint_to_checked&lt;/code&gt; from your mint authority (usually a PDA) into a token account (often a treasury ATA). However, if you want a fixed supply, mint the full amount and then revoke the mint authority by setting it to &lt;code&gt;None&lt;/code&gt; (This process is irreversible).&lt;/p&gt;

&lt;p&gt;Here’s an 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="c1"&gt;// Mint initial supply to a treasury ATA, then lock the mint.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;amount_base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ui_amount&lt;/span&gt;
    &lt;span class="nf"&gt;.checked_mul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10u64&lt;/span&gt;&lt;span class="nf"&gt;.pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_decimals&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidArgument&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;token_instruction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;mint_to_checked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;treasury_ata&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mint_authority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// your PDA signs via invoke_signed&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="n"&gt;amount_base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;token_decimals&lt;/span&gt;&lt;span class="p"&gt;,&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="nf"&gt;invoke&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;ix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;treasury_ata&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="cm"&gt;/* + authority account */&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="c1"&gt;// Later, make supply fixed:&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ix_disable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;token_instruction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;set_authority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// new authority = None → revoke&lt;/span&gt;
    &lt;span class="nn"&gt;spl_token&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MintTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mint_authority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[],&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="nf"&gt;invoke&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;ix_disable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="cm"&gt;/* + authority account */&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you have created and initialized the token mint. Next, you will create associated token accounts for the mints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Associated Token Account (ATA)
&lt;/h2&gt;

&lt;p&gt;For any user to hold the token you just minted and initialized, they have to own an ATA for the mint. An ATA is a deterministic address derived from an &lt;strong&gt;(&lt;/strong&gt;&lt;code&gt;owner&lt;/code&gt;, &lt;code&gt;mint&lt;/code&gt;, &lt;code&gt;token_program_id&lt;/code&gt;&lt;strong&gt;)&lt;/strong&gt; tuple, so wallets and programs can compute it and fetch that single account.&lt;/p&gt;

&lt;p&gt;When creating ATAs, decide who pays the rent to initialize the account. You can sponsor creation from your program (great onboarding, but costs scale with users), or require the user to fund it themselves (adds a signature step and a bit of friction, but controls your spend). Anyone may pay the fee; payer and owner do not have to be the same, and the payer gains no control over the account.&lt;/p&gt;

&lt;p&gt;To create an ATA, invoke the &lt;code&gt;create_associated_token_account_idempotent&lt;/code&gt; instruction from the &lt;code&gt;spl_associated_token_account::instruction&lt;/code&gt; crate with the following accounts (in the same order): payer, owner, ATA account, token mint account, token program account, system program account.&lt;/p&gt;

&lt;p&gt;Like so:&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;use&lt;/span&gt; &lt;span class="n"&gt;spl_associated_token_account&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_ata_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AccountInfo&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ProgramResult&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;acc_iter&lt;/span&gt; &lt;span class="o"&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;accounts&lt;/span&gt;&lt;span class="nf"&gt;.iter&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;payer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="c1"&gt;//pays the fees for account creation&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="c1"&gt;//Owner of the ATA&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ata_acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;token_mint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;token_program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;system_program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="c1"&gt;// Derive the expected ATA address and compare&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;expected_ata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get_associated_token_address_with_program_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="py"&gt;.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="nf"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Sanity check: is the passed ATA the one we expect?&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ata_acc&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;expected_ata&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;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidArgument&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Payer must sign&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;payer&lt;/span&gt;&lt;span class="py"&gt;.is_signer&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;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MissingRequiredSignature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Create the ATA (idempotent)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ata_instruction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create_associated_token_account_idempotent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;payer&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="py"&gt;.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="nf"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Invoke the ATA creation instruction&lt;/span&gt;
    &lt;span class="nf"&gt;invoke&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;ata_instruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;payer&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;ata_acc&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;token_mint&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;system_program&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;token_program&lt;/span&gt;&lt;span class="nf"&gt;.clone&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="o"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can create ATAs for your mints. Next, you will learn how to burn tokens from the ATAs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Burning Tokens
&lt;/h2&gt;

&lt;p&gt;Burning destroys tokens from a specific token account and reduces the mint’s total supply by the same amount. The SPL Token program enforces that only the token account owner (or an approved delegate) may burn from that account; you do not need the mint authority.&lt;/p&gt;

&lt;p&gt;To burn tokens, invoke the spl token programs &lt;code&gt;burn_checked&lt;/code&gt; instruction with the following accounts (in the same order): token mint account, ATA owner account, ATA.&lt;/p&gt;

&lt;p&gt;Like so:&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;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;burn_user_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AccountInfo&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;amount_ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ProgramResult&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;acc_iter&lt;/span&gt; &lt;span class="o"&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;accounts&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 0 mint, 1 owner(signer), 2 token_account(ATA), 3 token_program&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mint_account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;owner_account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="c1"&gt;// authority, must sign&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ata_token_acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next_account_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc_iter&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;owner_account&lt;/span&gt;&lt;span class="py"&gt;.is_signer&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;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MissingRequiredSignature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Sanity: token account belongs to owner and matches mint&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;token_account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SplAccount&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;unpack&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;ata_token_acc&lt;/span&gt;&lt;span class="nf"&gt;.try_borrow_data&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="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;token_account&lt;/span&gt;&lt;span class="py"&gt;.mint&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mint_account&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;token_account&lt;/span&gt;&lt;span class="py"&gt;.owner&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;owner_account&lt;/span&gt;&lt;span class="py"&gt;.key&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;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidAccountData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Derive base units using mint decimals&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SplMint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;unpack&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;mint_account&lt;/span&gt;&lt;span class="nf"&gt;.try_borrow_data&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="o"&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;decimals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="py"&gt;.decimals&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;amount_base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amount_ui&lt;/span&gt;
        &lt;span class="nf"&gt;.checked_mul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10u64&lt;/span&gt;&lt;span class="nf"&gt;.pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decimals&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ProgramError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InvalidArgument&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="c1"&gt;// Burn (checked) — accounts: [token_account, mint, authority]&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;burn_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;token_instruction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;burn_checked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;spl_token_id&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;ata_token_acc&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;mint_account&lt;/span&gt;&lt;span class="py"&gt;.key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;owner_account&lt;/span&gt;&lt;span class="py"&gt;.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="p"&gt;[],&lt;/span&gt;
        &lt;span class="n"&gt;amount_base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;,&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="nf"&gt;invoke&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;burn_ix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;ata_token_acc&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;mint_account&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;owner_account&lt;/span&gt;&lt;span class="nf"&gt;.clone&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="o"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;With the core pieces in place, mints that define the assets, ATAs that hold balances, and a burn mechanism to control supply. You’ve learnt how to create a mint as a PDA, initialize it with explicit decimals and authorities, derive and fund ATAs, mint and transfer in base units, and burn safely.&lt;/p&gt;

&lt;p&gt;With these primitives, you can ship payments, points, or NFTs end-to-end in Native Rust.&lt;/p&gt;

&lt;p&gt;You can find the code examples with associated tests in this &lt;a href="https://github.com/davidekete/token-mints" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. This is part one of a two-part series; the next part will cover Token-2022 extensions and hooks. To get notified when it drops, follow me on &lt;a href="//x.com/david_ekete"&gt;X&lt;/a&gt; :).&lt;/p&gt;

</description>
      <category>solana</category>
      <category>rust</category>
      <category>cryptocurrency</category>
      <category>solanadev</category>
    </item>
    <item>
      <title>An Introduction to Remote Procedural Call (RPC) Nodes in Blockchains</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Wed, 08 Oct 2025 23:11:14 +0000</pubDate>
      <link>https://dev.to/davidekete/an-introduction-to-remote-procedural-call-rpc-nodes-in-blockchain-p88</link>
      <guid>https://dev.to/davidekete/an-introduction-to-remote-procedural-call-rpc-nodes-in-blockchain-p88</guid>
      <description>&lt;p&gt;A blockchain is a peer-to-peer network of nodes that maintains a shared ledger. Every node communicates with other nodes in the network using specialized peer-to-peer (P2P) protocols to verify blocks/transactions, store state, and so on.&lt;/p&gt;

&lt;p&gt;If you’re building an app on a blockchain, you need a way to communicate with these nodes to read the current state of the blockchain (balances, contract/account data, logs) and write a new state. &lt;/p&gt;

&lt;p&gt;However, direct P2P communication is impractical because node-to-node communication is optimized for consensus and gossip, not for app developers. This is because they involve a lot of complex processes that browsers and typical backends aren’t designed to handle.&lt;/p&gt;

&lt;p&gt;Remote Procedural Call (RPC) Nodes exist to abstract this complexity and provide a stable HTTP/WebSocket-friendly way to read and write blockchain data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an RPC Node?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Remote_procedure_call" rel="noopener noreferrer"&gt;&lt;strong&gt;RPC&lt;/strong&gt;&lt;/a&gt; is a communication protocol that allows a program on one computer to execute a function on a different computer as if it were a local call. &lt;/p&gt;

&lt;p&gt;On blockchains, this commonly appears as JSON-RPC over HTTP or WebSocket, so you can call methods like &lt;code&gt;getBalance(address)&lt;/code&gt; which returns the balance of an address without handling low-level networking.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;RPC node&lt;/strong&gt; is a blockchain node configured to expose this developer-friendly API. Behind the scenes, it syncs the chain, validates data, and “&lt;a href="https://medium.com/@sudhindra_saxena/understanding-gossip-protocol-how-it-really-works-dddb6b081626" rel="noopener noreferrer"&gt;gossips&lt;/a&gt;” with peers; to you, it presents clear methods (read state, submit &lt;strong&gt;signed&lt;/strong&gt; transactions, subscribe to updates) accessible via an &lt;strong&gt;RPC endpoint&lt;/strong&gt; (the URL of the API).&lt;/p&gt;

&lt;p&gt;For example:&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;-X&lt;/span&gt; POST https://mainnet.infura.io/v3/YOUR_PROJECT_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "jsonrpc": "2.0",
    "method": "eth_getBalance",
    "params": [
      "0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe",
      "latest"
    ],
    "id": 1
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request above fetches the address’s balance (in &lt;strong&gt;Wei&lt;/strong&gt;) using Infura (an &lt;strong&gt;RPC provider&lt;/strong&gt;) via an Ethereum JSON-RPC endpoint. In practice, apps use libraries like &lt;strong&gt;viem&lt;/strong&gt;, &lt;strong&gt;ethers.js&lt;/strong&gt;, or &lt;strong&gt;web3.js&lt;/strong&gt; to talk to RPC endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  How RPC Nodes work
&lt;/h2&gt;

&lt;p&gt;RPC nodes are normal blockchain nodes with an exposed API surface. The node maintains chain state (syncs blocks, executes transactions, stores results). The &lt;strong&gt;RPC layer&lt;/strong&gt; maps your requests to the right internal components (state/execution, &lt;strong&gt;transaction pool&lt;/strong&gt;, or subscription engine).&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%2Fpd16pb5f8cnnj1r8izwj.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%2Fpd16pb5f8cnnj1r8izwj.png" alt="How an RPC Node works" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The mechanisms explained below depict how RPC nodes on the Ethereum mainnet behave. It can vary from blockchain to blockchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blockchain Reads
&lt;/h3&gt;

&lt;p&gt;For a read (e.g., “get balance” or a contract view), the node selects state at the &lt;strong&gt;block tag&lt;/strong&gt; (&lt;code&gt;latest&lt;/code&gt;, &lt;code&gt;pending&lt;/code&gt;, &lt;code&gt;safe&lt;/code&gt;, &lt;code&gt;finalized&lt;/code&gt;) you asked for, or a specific block number.&lt;/p&gt;

&lt;p&gt;If the method requires execution (for example, an &lt;code&gt;eth_call&lt;/code&gt; against a contract), the node runs the call against a sandboxed state at that height, without changing the chain. It then serializes the result and returns it. &lt;/p&gt;

&lt;h3&gt;
  
  
  Blockchain Writes
&lt;/h3&gt;

&lt;p&gt;For a write (submitting a &lt;strong&gt;signed&lt;/strong&gt; transaction), the node validates format and signature (tx type, chainId, nonce, gas limits/fees, optional access list). &lt;/p&gt;

&lt;p&gt;If valid, your request enters the &lt;strong&gt;mempool&lt;/strong&gt; and is “gossiped” to peers. A block producer includes it, and after it has been executed, you can query receipts, logs, and confirmation depth. &lt;/p&gt;

&lt;h3&gt;
  
  
  Subscriptions
&lt;/h3&gt;

&lt;p&gt;Over WebSocket, Ethereum supports &lt;code&gt;eth_subscribe&lt;/code&gt; channels such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;newHeads&lt;/code&gt; (new block headers)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;logs&lt;/code&gt; (filtered by address/topics)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;newPendingTransactions&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The node manages buffers/backpressure; clients should handle reconnects and resume from the last seen block number to stay consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using RPC Nodes
&lt;/h2&gt;

&lt;p&gt;To use an RPC node, you can either run your own private RPC node, use a public RPC node, or use an RPC node provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running your own RPC Node
&lt;/h3&gt;

&lt;p&gt;If you need overall control over your own RPC node, you can install and run blockchain clients like &lt;a href="https://geth.ethereum.org/" rel="noopener noreferrer"&gt;Geth&lt;/a&gt;, &lt;a href="https://www.nethermind.io/nethermind-client" rel="noopener noreferrer"&gt;Nethermind&lt;/a&gt;, or &lt;a href="https://reth.rs/" rel="noopener noreferrer"&gt;Reth&lt;/a&gt; on your own hardware or virtual server and enable RPC on them.&lt;/p&gt;

&lt;p&gt;This method requires a lot of maintenance on your end and is best for teams with special needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a Public RPC Node
&lt;/h3&gt;

&lt;p&gt;Most blockchains provide free public RPC endpoints that allow anybody to use RPC nodes. Due to their easy accessibility, they are usually overloaded and rate-limited, making them ideal for small Dapps and testing. Additionally, they may not offer WebSocket support.&lt;/p&gt;

&lt;p&gt;Examples of Popular Public RPC Nodes include the following:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chain&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;RPC Endpoint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ethereum&lt;/td&gt;
&lt;td&gt;PublicNode&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ethereum-rpc.publicnode.com/" rel="noopener noreferrer"&gt;https://ethereum-rpc.publicnode.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solana (Mainnet-beta)&lt;/td&gt;
&lt;td&gt;Anza (Solana Labs)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://api.mainnet-beta.solana.com/" rel="noopener noreferrer"&gt;https://api.mainnet-beta.solana.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BNB Smart Chain&lt;/td&gt;
&lt;td&gt;BNB Chain (official)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://bsc-dataseed.bnbchain.org/" rel="noopener noreferrer"&gt;https://bsc-dataseed.bnbchain.org&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sui (Mainnet)&lt;/td&gt;
&lt;td&gt;Mysten Labs&lt;/td&gt;
&lt;td&gt;&lt;a href="https://fullnode.mainnet.sui.io/" rel="noopener noreferrer"&gt;https://fullnode.mainnet.sui.io:443&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Using an RPC Node Provider
&lt;/h3&gt;

&lt;p&gt;This is the most popular option for most developers because using RPC node providers is cheaper than running your own RPC node, and you can scale your configuration as your usage increases.&lt;/p&gt;

&lt;p&gt;To use an RPC provider, you simply need to sign up on their platform, choose a plan, and start querying their endpoint. Some popular RPC Node providers include Alchemy &amp;amp; QuickNode.&lt;/p&gt;

&lt;p&gt;Another interesting RPC provider is the &lt;a href="https://cloud.developerdao.com/" rel="noopener noreferrer"&gt;Developer Dao Cloud&lt;/a&gt;, which is built on the POKT Network and gives you access to 60+ chains with unbeatable uptime. You can join the Developer Dao Cloud waitlist &lt;a href="https://devdao.to/rpc-waitlist" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;You can think of RPC nodes as the API layer of the blockchain. They abstract all the complexities associated with P2P communication between a node and a Dapp and expose a friendlier UI. &lt;/p&gt;

&lt;p&gt;You can access an RPC node via paid providers (often with free tiers), community/public endpoints, or by running your own dedicated node. Whichever route you choose, decide based on your needs for reliability, latency, and cost, and data/privacy requirements.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>webdev</category>
      <category>programming</category>
      <category>rpc</category>
    </item>
    <item>
      <title>How to Build Smart Contracts Fast</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Wed, 16 Jul 2025 23:25:01 +0000</pubDate>
      <link>https://dev.to/davidekete/accelerating-smart-contract-development-with-remix-ide-templates-1ilb</link>
      <guid>https://dev.to/davidekete/accelerating-smart-contract-development-with-remix-ide-templates-1ilb</guid>
      <description>&lt;p&gt;Writing smart contracts from scratch is a hurdle; you have to manually initialize your contract with the legal header and pragma line, and copy the OpenZeppelin import statements required by your smart contract.&lt;/p&gt;

&lt;p&gt;If your contract requires ownership, pausing, or ERC‑20 functionality, you have to manually paste the code. This workflow is very time-consuming and is prone to mistakes that could otherwise be avoided if all the boilerplate your project needed were available out of the box.&lt;/p&gt;

&lt;p&gt;Remix templates populate your workspace with a production-ready folder tree and all the boilerplate files you need to get started on your project. For example, the ER20 template contains a .sol file with all the required boilerplate (including OpenZeppelin imports) and deploy scripts for ethers.js and web3.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use Remix IDE templates
&lt;/h2&gt;

&lt;p&gt;Navigate to the &lt;a href="https://remix.ethereum.org" rel="noopener noreferrer"&gt;Remix IDE website&lt;/a&gt;, click the hamburger icon on the top left, and select the “Create Using Template” option.&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%2F66iheff7lzcebjn9r9s5.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%2F66iheff7lzcebjn9r9s5.png" alt="Remix IDE Select Template" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the workspaces page, select a template that suits your project’s needs from the list of available templates. &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%2Fuwkzm3a8uuyyqetpqdwn.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%2Fuwkzm3a8uuyyqetpqdwn.png" alt="Remix IDE Templates" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Available Remix IDE templates
&lt;/h2&gt;

&lt;p&gt;Here’s a list of the currently available templates on the Remix IDE, divided into categories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generic templates
&lt;/h3&gt;

&lt;p&gt;The templates are minimal and contain general starter boilerplates. Under this category, you can find blank templates, default templates, and templates for standards like &lt;strong&gt;EIP 7702&lt;/strong&gt; and &lt;strong&gt;ERC-4337&lt;/strong&gt; (Account Abstraction).&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenZeppelin templates
&lt;/h3&gt;

&lt;p&gt;The OpenZeppelin templates provide boilerplates containing OpenZeppelin audited implementations of some ERC contracts, like ERC-721 (for NFTS), ERC-1155 (Multi-token standard), and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  CookBook.dev templates
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://Cookbook.dev" rel="noopener noreferrer"&gt;Cookbook.dev&lt;/a&gt; templates provide boilerplates for audited and unaudited contracts from various projects in the ecosystem, like &lt;a href="https://aave.com/" rel="noopener noreferrer"&gt;Aave&lt;/a&gt;, &lt;a href="https://tether.to/" rel="noopener noreferrer"&gt;Tether&lt;/a&gt;, etc., curated by Cookbook.dev.&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%2Fo2kiy1de72m7891oq837.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%2Fo2kiy1de72m7891oq837.png" alt="Cookbook dot dev templates" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: To use these templates, you have to install the &lt;a href="https://Cookbook.dev" rel="noopener noreferrer"&gt;Cookbook.dev&lt;/a&gt; plugin in your Remix IDE.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OxProject
&lt;/h3&gt;

&lt;p&gt;A template for a fungible token contract by 0xProject.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gnosis Safe template
&lt;/h3&gt;

&lt;p&gt;A template for deploying or customizing the Gnosis Safe MultiSig Wallet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Circom ZKP templates
&lt;/h3&gt;

&lt;p&gt;Remix ships three templates for zero‑knowledge development with the Circom compiler plugin: Semaphore, Hash Checker, and Rate‑Limiting Nullifier (RLN).&lt;/p&gt;

&lt;p&gt;Each template is a full project with circuits, TypeScript scripts, and a ready‑made Solidity verifier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Noir ZKP template
&lt;/h3&gt;

&lt;p&gt;The Noir ZKP template contains a simple multiplier circuit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generic ZKP templates
&lt;/h3&gt;

&lt;p&gt;This template contains scripts for compiling circuits and generating Zero-Knowledge Proofs remotely using the Sindri API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uniswap V4 templates
&lt;/h3&gt;

&lt;p&gt;Uniswap V4 templates clones the protocol’s official v4 repos (core snapshot, periphery helpers, and a ready‑made Hook template), complete with Foundry tests and deploy scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Solidity CREATE2 templates&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Remix provides two Solidity CREATE2 templates for the Solidity CREATE2 opcode. A factory and a script for deploying a contract using the CREATE2 opcode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contract verification templates
&lt;/h3&gt;

&lt;p&gt;This template provides a script for verifying a Contract in Etherscan.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Actions
&lt;/h3&gt;

&lt;p&gt;For GitHub actions, Remix provides templates for a Mocha Chai Test Workflow in a GitHub CI, a Solidity Test Workflow, and a Slither Workflow.&lt;/p&gt;

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

&lt;p&gt;Remix IDE templates remove the tedious setup work so you can concentrate on business logic and security, not boilerplate. By starting from a curated workspace that already includes proven patterns, trusted dependencies, and ready‑made scripts, you sidestep common pitfalls such as mismatched compiler versions, missing imports, and fragile deployment flows.&lt;/p&gt;

</description>
      <category>remix</category>
      <category>web3</category>
      <category>smartcontract</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>How to Become a Blockchain Validator</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Tue, 10 Jun 2025 13:16:54 +0000</pubDate>
      <link>https://dev.to/davidekete/how-to-become-a-blockchain-validator-4j7j</link>
      <guid>https://dev.to/davidekete/how-to-become-a-blockchain-validator-4j7j</guid>
      <description>&lt;p&gt;A blockchain validator is a participant in a blockchain network who checks that new transactions and blocks follow the network’s rules before those blocks are permanently added to the ledger.&lt;/p&gt;

&lt;p&gt;Blockchains offer incentives in the form of their native tokens to validators, which are usually proportional to their stake in the network. The actual value of these rewards fluctuates based on market conditions, including price, total value locked (TVL), the number of active validators, penalties, commissions, and fee/MEV capture.&lt;/p&gt;

&lt;p&gt;Based on these factors that affect validator rewards, here’s a list of blockchains that provide viable profit opportunities for validators and how you can become one on the chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Ethereum&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To become a validator on the Ethereum network, you need to &lt;a href="https://ethereum.org/en/run-a-node/" rel="noopener noreferrer"&gt;run an Ethereum node&lt;/a&gt; and deposit 32 ETH (~84,000 USD) to activate your validator account. The minimum hardware requirements for running a node include 4-8 GB RAM, 2TB SSD, and a 64-bit x86 processor.&lt;/p&gt;

&lt;p&gt;You can build a hardware rig or use a dedicated cloud server. The estimated cost of purchasing the hardware is around 650-800 USD (source: Amazon.com). Cloud servers would cost around ~ 148 USD/month.&lt;/p&gt;

&lt;p&gt;As a validator, you have to check new blocks and “attest” to them if they are valid, and propose new blocks when you are randomly selected from the validator pool to propose one.&lt;/p&gt;

&lt;p&gt;If you fail to do either of these tasks, you miss out on the ETH rewards associated with that block. Validators can also be tasked with signature aggregation and participating in sync committees.&lt;/p&gt;

&lt;p&gt;Validators on ETH earn about 3.148% APY on their stake on ETH issuance rewards alone; this number can rise to about 5.69% if you add block tips and maximal extractable value (MEV), assuming your node has 100% uptime. If your node does anything malicious, such as proposing multiple blocks for the same slot, your staked ETH can be “slashed” by up to 1 ETH, and you will be removed from the network. You can read more on how rewards and penalties are calculated in &lt;a href="https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/rewards-and-penalties/" rel="noopener noreferrer"&gt;the official Ethereum documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The approximate cost (excluding electricity and internet costs) for setting up an Ethereum validator is 32 ETH + $800, which amounts to approximately ~ 84,800 USD. Assuming 100% uptime, fair MEV rewards, and tips, the average Ethereum validator earns ~ 1.8203 ETH (~4800 USD) yearly from a single node.&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%2Fgl0ul506qvpol0eb2ax4.jpg" 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%2Fgl0ul506qvpol0eb2ax4.jpg" alt="Running an Ethereum Validator" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s the official guide on &lt;a href="https://ethereum.org/en/staking/solo/" rel="noopener noreferrer"&gt;how to become an Ethereum validator&lt;/a&gt;, and here’s a handy tool you can use to estimate validator rewards based on real-time market data: &lt;a href="https://www.blocknative.com/ethereum-staking-calculator?stake=32&amp;amp;currency=USD&amp;amp;priceChangePerMonth=0&amp;amp;initialCosts=0&amp;amp;monthlyCosts=0&amp;amp;stakingFee=0&amp;amp;reinvest=false&amp;amp;mevboost=true&amp;amp;networkStake=14627105&amp;amp;networkOnlineProbability=90&amp;amp;totalStakeMonthlyChange=0" rel="noopener noreferrer"&gt;Ethereum staking calculator&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solana
&lt;/h2&gt;

&lt;p&gt;The minimum hardware requirements for running a Solana validator are a 12-core/24-thread CPU at 2.8 GHz or faster with SHA and AVX2 instruction support, 256 GB of ECC RAM, separate PCIe Gen3×4 NVMe SSDs of roughly 500 GB for accounts, 1 TB for the ledger and 250 GB for snapshots with an optional 500 GB OS drive, plus a symmetric 1 Gbps internet connection. You can find the full hardware recommendations in the &lt;a href="https://docs.anza.xyz/operations/requirements#hardware-recommendations" rel="noopener noreferrer"&gt;Agave documentation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;A physical setup would cost anywhere from ~ 2600 to 5000 USD, excluding internet and electricity costs. Alternatively, cloud solutions cost around 4,500 USD per year; however, they are a better option, as managing the bandwidth and internet required for voting can be difficult.&lt;/p&gt;

&lt;p&gt;The next substantial cost associated with running a Solana validator is the voting fees. Validators are required to send a vote transaction for every slot they agree with, and these transactions can incur up to 1.1 SOL (~ 185 USD) in fees per day.&lt;/p&gt;

&lt;p&gt;There is no strict minimum amount of SOL you need to run a validator, so “theoretically,” you can deposit 1 SOL. However, according to &lt;a href="https://cogentcrypto.io/ValidatorProfitCalculator?server_cost=4500&amp;amp;commission=100&amp;amp;mev_commission=8&amp;amp;delegated_stake=5700&amp;amp;selected_unit=USD" rel="noopener noreferrer"&gt;Cogent Crypto’s validator profit calculator&lt;/a&gt;, the minimum amount of SOL to be profitable is ~5700 SOL (~ 934,000 USD). Since Solana operates a delegated-POS system, you do not need to own all your stake; you can incentivize SOL holders to delegate their tokens to you and charge them a commission ranging between 0 to 100% deducted from their inflation rewards.&lt;/p&gt;

&lt;p&gt;The image below shows the top 14 Solana validators, their commission, active SOL staked, and other parameters.&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%2Frcpjlh3jwekbpr29aqf2.jpg" 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%2Frcpjlh3jwekbpr29aqf2.jpg" alt="Running an Solana Validator" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For earnings, Solana validators earn from inflation/issuance rewards (on their stake), priority fees (tips), and MEV. Most of the rewards come from issuance. However, tips also make up a good portion. According to Blockworks research, $240 million in priority fees/tips flowed to validators in Jan 2025 alone.&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%2F5s0nf1wuunl964dltkg2.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%2F5s0nf1wuunl964dltkg2.png" alt="Solana validator earnings" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The current barrier of entry for a Solana validator is high compared to Ethereum. However, with &lt;a href="https://davidekete.substack.com/p/introducing-alpenglow-solanas-new" rel="noopener noreferrer"&gt;the Alpenglow upgrade&lt;/a&gt;, you can run a Solana validator on &lt;em&gt;an 8- to 16-core CPU&lt;/em&gt; (no PoH grind), &lt;em&gt;128 GB of ECC RAM&lt;/em&gt;, &lt;em&gt;a single 1 TB NVMe drive&lt;/em&gt; for both ledger and accounts, and the same 1 Gbps uplink, eliminating the need for a separate snapshot drive or vote-spam IOPS. &lt;/p&gt;

&lt;p&gt;Alpenglow also removes voting fees, bringing the minimum amount of SOL to be profitable down from ~ 5700 SOL to around ~ 530 SOL. Note that these figures are speculative as the inflation model might be tweaked to balance the removal of the voting fee, thus increasing the minimum amount required to be profitable.&lt;/p&gt;

&lt;p&gt;Here’s the official guide on &lt;a href="https://docs.anza.xyz/operations/setup-a-validator" rel="noopener noreferrer"&gt;how to setup a Solana validator&lt;/a&gt;. To reduce the barrier of entry for validators, the &lt;a href="https://docs.anza.xyz/operations/validator-initiatives" rel="noopener noreferrer"&gt;Solana Foundation has some initiatives to reduce cost&lt;/a&gt;. Here’s a helpful blog post by Helius, whose validator account earns approximately $ 18 million per year, on &lt;a href="https://www.helius.dev/blog/solana-validator-economics-a-primer" rel="noopener noreferrer"&gt;Solana validator economics&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sui
&lt;/h2&gt;

&lt;p&gt;To become a SUI validator, you have to &lt;a href="https://github.com/MystenLabs/sui/blob/main/nre/sui_for_node_operators.md" rel="noopener noreferrer"&gt;run a SUI node&lt;/a&gt; and have a minimum of 30 million SUI (~ 104.7 million USD) in your staking pool (deposited or delegated). The Sui Foundation helps members of their delegation program satisfy the 30 million threshold. However, the application details are very vague, and the only reference to the program is &lt;a href="https://blog.sui.io/token-delegation/" rel="noopener noreferrer"&gt;this blog post from 2022&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you become a validator, your staking pool must maintain a balance of at least 20 million SUI (~ 69.8 million USD) or risk removal after a 7-epoch (1 epoch = 24 hours) grace period. If your pool falls below 15 million SUI, you will be removed as a validator on the next epoch.&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%2F0yvsvqj3072zr2c64db0.jpg" 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%2F0yvsvqj3072zr2c64db0.jpg" alt="Running an Sui Validator" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The minimum hardware requirements for running a Sui node are a server with 24 physical CPU cores (48 vCPUs), 128 GB of RAM, a 4 TB NVMe SSD, and a 1 Gbps network connection. The estimated cost for building a hardware rig that meets these requirements, according to &lt;a href="http://Amazon.com" rel="noopener noreferrer"&gt;Amazon.com&lt;/a&gt; is around 1200 - 1400 USD (refurbished) and 8000 - 9000 USD (new).&lt;/p&gt;

&lt;p&gt;Running a dedicated server that meets the hardware requirements would cost around 500 USD per month, but this can vary greatly depending on the service you choose.&lt;/p&gt;

&lt;p&gt;Sui validators earn an average of 2.34% APY on their stake, which comes from yield on their stake, commission on delegated stake, and an automatic storage-cost rebate. Thus, with the allowable balance of 20 million SUI, validators make ~ 1.63 million USD per year.&lt;/p&gt;

&lt;p&gt;There’s currently a proposal to reduce the barrier of entry for new validators, &lt;a href="https://github.com/sui-foundation/sips/blob/main/sips/sip-39.md" rel="noopener noreferrer"&gt;SIP-39&lt;/a&gt;. This proposal, when fully rolled out, will replace the 30 million SUI requirement with “3 voting power”. A “voting power” is calculated by dividing a validator’s stake by the total stake and multiplying it by the fixed value of 10,000, which is the total available voting power for each epoch.&lt;/p&gt;

&lt;p&gt;Thus, one voting power equals 0.01 % of the total stake. Currently, that value (total stake, May 2025 = 7.49 billion SUI) is 749,000 SUI—making the entry requirement 2.247 million SUI ( ~7.84 million USD).&lt;/p&gt;

&lt;p&gt;Here’s the official guide for &lt;a href="https://docs.sui.io/guides/operator/validator-config" rel="noopener noreferrer"&gt;becoming a validator on Sui&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  BNB Chain (BSC)
&lt;/h2&gt;

&lt;p&gt;To become a validator on the BNB chain, formerly known as the Binance Smart Chain, you need to run a BSC node and stake a minimum of 2000 + 1 BNB (~ 1.3 million USD). 2,000 BNB is your self-stake, and 1 BNB is burned to a dead-address.&lt;/p&gt;

&lt;p&gt;The hardware requirements to run a BNB chain node are 16 CPU cores, 64 GB RAM, NVMe SSD 2-3 TB, ≥ 1 GB symmetrical bandwidth, which will cost about ~ 875 to 1500 USD (Amazon.com) for hardware. If you use a dedicated cloud server, it would cost anywhere from 104 to 455 USD/month.&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%2Fhhdgsgaqwlweupicup54.jpg" 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%2Fhhdgsgaqwlweupicup54.jpg" alt="Running an BSC Validator" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every validator earns a daily base reward of up to approximately 1.92% APY on their deposited stake. If you sit in the top-21 “Cabinet,” (validators with the largest amount of delegated BNB at the end of each UTC-day election cycle) you also keep almost all gas fees and any MEV in the blocks you build, so your real yield rises by a few additional tenths of a percent when traffic is normal and much more during busy periods; on top of that you skim a commission (typically around 10%) from your delegators’ rewards.&lt;/p&gt;

&lt;p&gt;Income falls whenever you miss duties, and serious faults are expensive: double-signing or malicious votes forfeit 200 BNB of your own bond and sideline you for thirty days, while extended downtime costs 10 BNB and a two-day “jail”.&lt;/p&gt;

&lt;p&gt;Thus, the income of a BNB validator, who holds the minimum stake, is ~ 25,000 USD per year. Here’s the official guide on becoming a &lt;a href="https://docs.bnbchain.org/bnb-smart-chain/developers/node_operators/full_node/" rel="noopener noreferrer"&gt;validator on BNB Chain&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cosmos
&lt;/h2&gt;

&lt;p&gt;The hardware requirements for running a validator node on Cosmos are vague, as the docs only mention the RAM and storage requirements: 32 GB of RAM and 500 GB to 2 TB of storage.&lt;/p&gt;

&lt;p&gt;Most consumer-grade PCs that fit those specs can be picked up for roughly 350 – 800 USD on Amazon, or rented for about ****$92 – $148 per month on dedicated cloud server plans. There is no minimum stake required to become a validator; however, certain caveats apply to this rule.&lt;/p&gt;

&lt;p&gt;To become a validator on Cosmos, you have to send a “declare-candidacy” transaction with some required parameters, which include but is not limited to your PubKey, minimum self-bond amount (minimum amount of ATOM you need to have at all times), initial self-bond amount, etc.&lt;/p&gt;

&lt;p&gt;Once you declare candidacy, Atom holders can delegate atoms to your pool, effectively adding stake to this pool. The total stake of an address is the combination of Atoms bonded by delegators and Atoms self-bonded by the entity that designated itself.&lt;/p&gt;

&lt;p&gt;Out of all the candidates that signaled themselves, the 100 with the most stake are the ones who are designated as validators. If a validator’s total stake falls below the top 100, then that validator loses its validator privileges.&lt;/p&gt;

&lt;p&gt;However, the maximum number of validators increases every year and is set to triple within 10 years since launch. Following &lt;a href="https://github.com/cosmos/cosmos/blob/master/VALIDATORS_FAQ.md#:~:text=will%20increase%2C%20according%20to%20a%20predefined%20schedule%3A" rel="noopener noreferrer"&gt;the schedule&lt;/a&gt;, the current maximum number should be 208 (Year 6).&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%2Fx5v99qa9tscxft1imc2e.jpg" 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%2Fx5v99qa9tscxft1imc2e.jpg" alt="Running a Cosmos Validator" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thus, making the minimum stake any number of ATOM that puts you in the top 200 (Year 6). That value currently sits at 2,740 ATOM (~ 11,900 USD), which is the stake of the 198th validator. &lt;/p&gt;

&lt;p&gt;Cosmos stakers and, by extension, validators earn a “base” compounded ~17 – 19 % APY on their self-stake. In addition to that, they earn from commissions and play a significant role in governance, as all their delegators who don’t vote automatically inherit their vote.&lt;/p&gt;

&lt;p&gt;Here’s the official guide to &lt;a href="https://hub.cosmos.network/main/validators/validator-setup" rel="noopener noreferrer"&gt;becoming a validator on Cosmos&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avalanche
&lt;/h2&gt;

&lt;p&gt;To become a validator on Avalanche, you have to run a node and stake a minimum of 2,000 AVAX (~ 41,460 USD). The maximum weight of a validator (their own stake plus the stake delegated to them) is 3 million AVAX. &lt;/p&gt;

&lt;p&gt;One interesting quirk of the Avalanche validators is that the maximum amount of tokens your validator pool can hold is 5 times your staked amount. For example, if you stake 2,000 AVAX to become a validator, only 8,000 AVAX can be delegated to your node, making the total 10,000.&lt;/p&gt;

&lt;p&gt;The hardware requirements for running a node are vague; publicly accessible materials only list the storage and RAM requirements: 200 GB of storage and 8 GB of RAM.&lt;/p&gt;

&lt;p&gt;Most consumer-grade PCs easily satisfy 8 GB of RAM and ~200 GB of SSD storage, and cost anywhere from $ ****120 to $ 260, or roughly $ 8 to $ 27 per month if you rent a VPS or entry-level bare-metal instance.&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%2Fduywl69t0wnr4e5fiknx.jpg" 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%2Fduywl69t0wnr4e5fiknx.jpg" alt="Running an Avax Validator" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The current reward percentage for staking is 8.5 % APY. Additionally, validators may also receive a percentage of the transaction fees generated on the network or additional tokens. Thus, on a 2,000 AVAX stake, you’d receive ~ 3,500 USD per year. Here’s the official guide on &lt;a href="https://www.youtube.com/watch?v=0m23cuKqQLU&amp;amp;t=299s" rel="noopener noreferrer"&gt;becoming a validator on the Avalanche chain&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chain&lt;/th&gt;
&lt;th&gt;Number of active validators(May 2025)&lt;/th&gt;
&lt;th&gt;Average number of DAW (Daily Active Wallets&lt;/th&gt;
&lt;th&gt;Estimated cost of entry (USD)&lt;/th&gt;
&lt;th&gt;Minimum stake to become profitable&lt;/th&gt;
&lt;th&gt;Average APY on Stake (%)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ethereum&lt;/td&gt;
&lt;td&gt;1,054,030&lt;/td&gt;
&lt;td&gt;490k - 529k&lt;/td&gt;
&lt;td&gt;85,776&lt;/td&gt;
&lt;td&gt;32 ETH&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solana&lt;/td&gt;
&lt;td&gt;1,231&lt;/td&gt;
&lt;td&gt;4.4 - 5 million&lt;/td&gt;
&lt;td&gt;938,500&lt;/td&gt;
&lt;td&gt;5740 SOL&lt;/td&gt;
&lt;td&gt;5-6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sui&lt;/td&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;td&gt;286k - 312k&lt;/td&gt;
&lt;td&gt;104,706,000&lt;/td&gt;
&lt;td&gt;30 million SUI&lt;/td&gt;
&lt;td&gt;2.37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BNB Chain&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;1.5 - 1.8 million&lt;/td&gt;
&lt;td&gt;1,305,460&lt;/td&gt;
&lt;td&gt;2,001 BNB&lt;/td&gt;
&lt;td&gt;1.92&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cosmos&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;11k - 16k&lt;/td&gt;
&lt;td&gt;13,776&lt;/td&gt;
&lt;td&gt;3,000 ATOM&lt;/td&gt;
&lt;td&gt;unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avalanche&lt;/td&gt;
&lt;td&gt;1,348&lt;/td&gt;
&lt;td&gt;41k - 100k&lt;/td&gt;
&lt;td&gt;41,784&lt;/td&gt;
&lt;td&gt;2,000 AVAX&lt;/td&gt;
&lt;td&gt;8.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Today’s blockchain ecosystem makes validator roles and privileges inaccessible to retail—this is both a feature and a flaw. The high barrier of entry makes attacks on the blockchain expensive and unfeasible. &lt;/p&gt;

&lt;p&gt;However, it has made the chain more centralized as only a handful of institutions can afford the hardware and initial capital required. The top validator wallets are also controlled by the foundation responsible for the blockchain, which raises a lot of questions.&lt;/p&gt;

&lt;p&gt;Lowering the barrier of entry for validators and offering better incentives would achieve a higher degree of decentralization while maintaining chain security. As crypto gathers more adoption, we cant wait to see what tomorrow holds.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>solana</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>Introducing Alpenglow: Solana’s new consensus protocol</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Sun, 01 Jun 2025 23:33:19 +0000</pubDate>
      <link>https://dev.to/davidekete/introducing-alpenglow-solanas-new-consensus-protocol-37pk</link>
      <guid>https://dev.to/davidekete/introducing-alpenglow-solanas-new-consensus-protocol-37pk</guid>
      <description>&lt;p&gt;Anza Labs (formerly known as Solana Labs) has proposed the most significant update to the Solana blockchain since it went live: Alpenglow.&lt;/p&gt;

&lt;p&gt;Alpenglow replaces TowerBFT and Proof-of-History as the voting and block finalization mechanism with &lt;strong&gt;Votor&lt;/strong&gt; and refines Turbine as the data propagation layer with &lt;strong&gt;Rotor&lt;/strong&gt;. This piece will discuss how these changes affect the Solana ecosystem and what you can expect after Alpenglow’s implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Votor
&lt;/h2&gt;

&lt;p&gt;Until Votor, Solana relied on T**ower Byzantine Fault Tolerance (TBFT) as its consensus algorithm, which is a custom implementation of Practical Byzantine Fault Tolerance (PBFT). You can visualize TBFT as a two-step handshake.&lt;/p&gt;

&lt;p&gt;On the first handshake, known as the &lt;strong&gt;pre-vote&lt;/strong&gt;, every validator signs a short “yes, I saw this block” message. The block can move on only after &lt;strong&gt;at least two-thirds (2/3)&lt;/strong&gt; of all stake have sent this first vote. On the second handshake, known as the &lt;strong&gt;commit&lt;/strong&gt;, once the same super-majority notices that the first round succeeded, they sign a second, “now it’s final” vote.&lt;/p&gt;

&lt;p&gt;This 2-hop pattern (plus occasional view changes when the leader stalls) is mathematically safe as long as &lt;strong&gt;less than one-third of the total stake is actively malicious&lt;/strong&gt;. However, this introduces a lot of latency, as block finality on Solana averages about 12.8 seconds, which is impractical for real-time applications like games.&lt;/p&gt;

&lt;p&gt;Votor keeps the familiar “everyone votes with stake-weighted signatures” idea, but lets the chain &lt;strong&gt;stop early&lt;/strong&gt; if &lt;em&gt;≈ 80 %&lt;/em&gt; of the stake manages to send its first vote before a deadline T₁ ≈ δ (T₁ = first waiting window, δ = network yardstick). If 80% is reached, the block is finalized immediately—no second hop. &lt;/p&gt;

&lt;p&gt;If 80 % isn’t reached in time, the protocol relaxes to 60 % in two hops, which is only slightly stricter than the old ⅔-rule but still maintains safety. With this mechanism, Votor achieves a median latency of 150 ms, comparable to Web2 infrastructure.&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%2F5tws26mjtifzy00eclhe.jpg" 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%2F5tws26mjtifzy00eclhe.jpg" alt="Alpenglow's Votor" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In essence, Votor shaves hundreds of milliseconds off the &lt;em&gt;common&lt;/em&gt; case by trusting that true, coordinated attacks above 20 % stake are rare. The bargain is a slightly narrower safety cushion, tighter uptime requirements for validators, and a protocol that is trickier to reason about and to monitor in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rotor
&lt;/h2&gt;

&lt;p&gt;Originally, the current slot leader was responsible for sending every byte of the block to the rest of the validators, which was a huge bottleneck. To ease the burden, the protocol adopted Turbine, which broke the blocks into shreds, erasure-coded them, and pushed them down a fixed fan-out tree.&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%2Fmvbfgkvacrhvwbhy8k7c.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%2Fmvbfgkvacrhvwbhy8k7c.png" alt="Turbine, anza.xyz" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This helped; however, it left a few pain points. One, every shred still originates on the leader’s network, tens of thousands of transactions passing through a single pipe. Also, the relay work was uneven. Which node relays to whom is hard-coded by slot number, so the same unlucky validator may forward huge chunks of traffic while others forward almost none, and yet everyone earns identical rewards for “voting”. &lt;/p&gt;

&lt;p&gt;This approach was also blind to stake. A validator with a 0.1% stake could end up relaying as much data as one holding 5%, even though the latter has both the resources and the economic incentive to shoulder more load. As throughput crept upward, the leader bottleneck and unfair bandwidth distribution threatened real-time user experience.&lt;/p&gt;

&lt;p&gt;Rotor re-imagines block distribution as a &lt;strong&gt;stake-weighted peer-to-peer CDN&lt;/strong&gt;. The leader seeds just enough shreds to a randomly sampled set of relay nodes, each chosen with probability proportional to its stake. Those relays then spray their own stake-proportional bandwidth outward; any γ out of Γ shreds suffice to reconstruct the block, so a fair chunk of relays can drop offline without harm. &lt;/p&gt;

&lt;p&gt;The result is that the leader’s outbound traffic falls from “block size × fan-out” to roughly “block size × (log N / Γ)”.&lt;/p&gt;

&lt;p&gt;Rotor keeps the idea of “leader seeds a few peers first”, but it&lt;/p&gt;

&lt;p&gt;eliminates the fixed tree, the 32-fold duplication, and the unpaid relay work. The price is a heavier dependency on honest capacity provisioning, steeper hardware requirements for validators, and a significantly more intricate networking layer that must stay honest and measurable at scale.&lt;/p&gt;

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

&lt;p&gt;Alpenglow reframes Solana’s guiding idea, “the world computer should feel like the local computer,” by eliminating the leader pipe as a bottleneck and letting a stake-weighted swarm move blocks and votes at near-network speed. If the upcoming test networks confirm the projected latency and fairness gains, Alpenglow could set a new benchmark for high-performance, open-participation blockchains.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>cryptocurrency</category>
      <category>web3</category>
      <category>solana</category>
    </item>
    <item>
      <title>Revolutionizing the Stablecoin Market with Solayer USD</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Wed, 13 Nov 2024 18:32:45 +0000</pubDate>
      <link>https://dev.to/davidekete/revolutionizing-the-stablecoin-market-with-solayer-usd-20m7</link>
      <guid>https://dev.to/davidekete/revolutionizing-the-stablecoin-market-with-solayer-usd-20m7</guid>
      <description>&lt;p&gt;Traditional fiat-collateralized stablecoins maintain their value by holding reserves in fiat currency or highly liquid, low-risk assets equal to the value of stablecoins in circulation. However, the yield and interest generated from these reserves benefit only the stablecoin issuer, leaving users without a share in the financial returns.&lt;/p&gt;

&lt;p&gt;This mirrors a problem in traditional finance, where individuals don’t fully benefit from the use of their capital, making the system &lt;strong&gt;less equitable&lt;/strong&gt; and reinforcing &lt;strong&gt;financial inequality&lt;/strong&gt;—issues cryptocurrency was designed to solve.&lt;/p&gt;

&lt;p&gt;Solayer USD (sUSD) seeks to bridge this gap by introducing the first yield-bearing stablecoin on Solana. It is pegged to the U.S. dollar and backed by real-world assets (RWAs) like U.S. Treasury Bills, bonds, and gold. Unlike traditional stablecoins, sUSD redistributes the yield generated from these assets directly to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Solayer USD (sUSD)?
&lt;/h2&gt;

&lt;p&gt;sUSD is a yield-bearing stablecoin on Solana that maintains a 1:1 peg with the U.S. dollar through backing from U.S. &lt;a href="https://www.investopedia.com/terms/t/treasurybill.asp" rel="noopener noreferrer"&gt;Treasury Bills&lt;/a&gt;, which is considered one of the safest short-term government debt instruments. &lt;/p&gt;

&lt;p&gt;In addition to maintaining its peg, T-bill backing also &lt;strong&gt;allows it to generate a 4-5% yield&lt;/strong&gt;, which is automatically redistributed to users through a token multiplier mechanism.&lt;/p&gt;

&lt;h3&gt;
  
  
  The sUSD yield-bearing mechanism
&lt;/h3&gt;

&lt;p&gt;The Solana blockchain’s account model makes minting and distributing tokens as yield to user accounts difficult due to rent fees, complex transaction handling, and the need for frequent state updates in a system with many accounts.&lt;/p&gt;

&lt;p&gt;To handle this, sUSD employs &lt;a href="https://spl.solana.com/token-2022" rel="noopener noreferrer"&gt;Solana’s token22 program&lt;/a&gt; and a &lt;strong&gt;token multiplier mechanism&lt;/strong&gt; that works by changing the multiplier of your sUSD holdings with the interest accumulation rather than changing the amount.&lt;/p&gt;

&lt;p&gt;The value of your holdings is then calculated by applying a multiplier to the number of sUSD tokens you’re holding. For example, if you have &lt;strong&gt;1000&lt;/strong&gt; (one thousand) $sSUD tokens, assuming a &lt;strong&gt;5%&lt;/strong&gt; annual yield, the multiplier on your tokens would be &lt;strong&gt;1.05x&lt;/strong&gt; at the end of the year. &lt;/p&gt;

&lt;p&gt;The multiplier is calculated by considering the annual yield and the compounding period, i.e., &lt;strong&gt;&lt;em&gt;Multiplier=1+n/r&lt;/em&gt;&lt;/strong&gt;, where &lt;strong&gt;&lt;em&gt;r&lt;/em&gt;&lt;/strong&gt; is the annual yield (in this case, 5% or 0.05), and &lt;strong&gt;&lt;em&gt;n&lt;/em&gt;&lt;/strong&gt; is the number of compounding periods per year.&lt;/p&gt;

&lt;p&gt;Thus, the actual value of your 1000 $sUSD tokens would be calculated by &lt;strong&gt;Number of Tokens&lt;/strong&gt; * &lt;strong&gt;Multiplier&lt;/strong&gt;, i.e. USD &lt;strong&gt;1000 * 1.05&lt;/strong&gt;, which equals USD &lt;strong&gt;1050&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%2Fsvg60g72iitflc4f5krl.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%2Fsvg60g72iitflc4f5krl.png" alt="Token Multipler Mechanisim" width="800" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allows the value of sUSD in a wallet to increase natively without losing its peg or increasing the number of $sUSD tokens in your wallet.&lt;/p&gt;

&lt;p&gt;In addition to getting yield from holding $sUSD tokens, you can delegate them exogenous Actively Validated Services (exoAVSs) to gain additional yields and further secure the decentralized network. However, this feature is still under development at the time of writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does sUSD work?
&lt;/h2&gt;

&lt;p&gt;sUSD is built upon Solayer’s &lt;strong&gt;Request for Quote (RFQ)&lt;/strong&gt; protocol, which is essentially a marketplace matching engine. The RFQ protocol matches USDC quotes with a liquidity provider that has the most optimized interest rates for the quote. &lt;/p&gt;

&lt;p&gt;This approach distributes risk and maximizes yield opportunities by leveraging the strengths of different liquidity providers. It also plays a crucial role in the sUSD subscription (buying sUSD) and the redemption process (selling sUSD).&lt;/p&gt;

&lt;h3&gt;
  
  
  The sUSD subscription process
&lt;/h3&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%2F6u1jmulr7owfxcxf22kr.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%2F6u1jmulr7owfxcxf22kr.png" alt="sUSD Subscription" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sUSD subscription process involves locking USDC to mint sUSD. To achieve this, you’ll need a Solana wallet like &lt;a href="https://phantom.app/" rel="noopener noreferrer"&gt;Phantom&lt;/a&gt;, some SOL tokens for gas, and USDC.&lt;/p&gt;

&lt;p&gt;Navigate to the Solayer app on &lt;a href="https://app.solayer.org/" rel="noopener noreferrer"&gt;https://app.solayer.org/&lt;/a&gt; and click on sUSD Restaking, as shown in the image 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%2Ffwkak0o7e2ymvyu5r6rf.jpg" 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%2Ffwkak0o7e2ymvyu5r6rf.jpg" alt="sUSD Restaking" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This takes you to the sUSD restaking page, where you can mint sUSD tokens with USDC on a 1:1 basis. On the restaking page, connect your Solana wallet containing your USDC and some SOL for gas, enter the amount of USDC you want to lock for sUSD and click the &lt;strong&gt;Deposit&lt;/strong&gt; button that appears.&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%2Fusldeo2h1001mhnjlaxz.jpg" 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%2Fusldeo2h1001mhnjlaxz.jpg" alt="Lock USDC" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking the &lt;strong&gt;Deposit&lt;/strong&gt; button locks your USDC and automatically creates a quote that specifies the amount of USDC, the expiry time, and the commission rate for the trade. The RFQ system then broadcasts the quote to all qualified liquidity providers who compete to fulfil the order and receive the offered commission.&lt;/p&gt;

&lt;p&gt;The selected liquidity provider fulfils the buy order by transferring the USDC out and sending back a wrapped T-bill (a tokenized representation of a T-bill) as proof. The RFQ protocol then forwards the wrapped T-bill to the sUSD minting program and locks it there.&lt;/p&gt;

&lt;p&gt;Finally, the USD minting program mints sUSD based on the value of the wrapped T-Bill, maintaining a 1:1 price peg with USDC, thus depositing your sUSD tokens in your wallet. This process takes a while to finalize and is usually completed in 1 working day. &lt;/p&gt;

&lt;p&gt;You should see a processing transaction indicator on the restaking page during this wait time, as shown in the image 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%2Fag2oqq419m0p4xomlc7z.jpg" 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%2Fag2oqq419m0p4xomlc7z.jpg" alt="Subscription Indicator" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will receive an equivalent number of sUSD tokens when this process is complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  The sUSD redemption process
&lt;/h3&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%2F9tgxywik3bauyarqw9ov.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%2F9tgxywik3bauyarqw9ov.png" alt="sUSD Redemption" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sUSD redemption process involves converting your sUSD back to USDC. This conversion does not occur on a 1:1 basis with your sUSD, as a multiplier based on your accumulated yield is applied to your token value, giving you more USDC than you initially locked.&lt;/p&gt;

&lt;p&gt;To start your sUSD redemption process, you have to unstake your sUSD tokens (if you staked or used them for collateral) and send them back to the Solayer sUSD program. Then, navigate to the sUSD restaking dashboard, enter the amount you want to withdraw and click the &lt;strong&gt;Withdraw&lt;/strong&gt; button, as shown in the image 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%2Ffdaizrgsqj27z1c3hw03.jpg" 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%2Ffdaizrgsqj27z1c3hw03.jpg" alt="Enter Withdrawal Details" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking the withdraw button will trigger a pop-up modal that provides information about your withdrawal process, such as the fact that it can take up to 2 days to process. Click the &lt;strong&gt;Withdraw&lt;/strong&gt; button on the modal to start your withdrawal process, as shown in the image 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%2Finivqq20hinwd8my40aq.jpg" 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%2Finivqq20hinwd8my40aq.jpg" alt="Withdraw Page" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click the withdrawal button, the program calculates the corresponding amount of wrapped T-Bills that need to be redeemed based on your request and forwards it to the RFQ protocol.&lt;/p&gt;

&lt;p&gt;The RFQ protocol matches the redemption request to a qualified liquidity provider who receives the wrapped T-Bill and fulfils the withdrawal order by transferring out the wrapped T-Bill and sending the equivalent amount of USDC back to the protocol.&lt;/p&gt;

&lt;p&gt;After the liquidity provider fulfils the withdrawal order, the RFQ protocol returns the corresponding amount of USDC to the user, completing the withdrawal process. &lt;/p&gt;

&lt;p&gt;As mentioned in the pop-up modal, this process will take about 2 days. During this wait time, you should see a processing transaction indicator on the restaking page, as shown in the image 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%2Fbxof6uimr3bwx7p42cep.jpg" 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%2Fbxof6uimr3bwx7p42cep.jpg" alt="Withdrawal Wait Time" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use cases for sUSD
&lt;/h2&gt;

&lt;p&gt;Solayer’s stablecoin, sUSD, has multiple use cases aside from being a stable store of value. Some of them are covered below.&lt;/p&gt;

&lt;h3&gt;
  
  
  sUSD as a savings account on Solana
&lt;/h3&gt;

&lt;p&gt;You can use sUSD as a decentralized savings account that offers a higher yield, &lt;strong&gt;4-5%&lt;/strong&gt;, &lt;a href="https://www.usnews.com/banking/savings-accounts" rel="noopener noreferrer"&gt;compared to traditional banks&lt;/a&gt;. It also provides greater transparency, as the entire process is &lt;strong&gt;on-chain.&lt;/strong&gt; You can see how yield is generated, which assets back it, and where funds are held.&lt;/p&gt;

&lt;p&gt;sUSD is also decentralized and permissionless, meaning anyone can participate regardless of geographical restrictions or access to banking services. It also gives you full control over your assets, unlike a traditional savings account, which relies on financial institutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Securing decentralized systems
&lt;/h3&gt;

&lt;p&gt;sUSD not only functions as a stable, yield-generating asset, but it also provides opportunities to contribute to the security of decentralized systems such as Oracles and Bridges by delegating your tokens to them. For example, delegating your sUSD tokens to an exoAVS, which is coming soon to Solayer.&lt;/p&gt;

&lt;p&gt;The exoAVS system utilizes the delegated sUSD as part of its security mechanism, ensuring that operations like data validation, cross-chain communication, or decentralized governance are carried out securely.&lt;/p&gt;

&lt;p&gt;In exchange, the system compensates you with additional yield, providing an extra incentive beyond the base 4-5% interest from T-bills.&lt;/p&gt;

&lt;h3&gt;
  
  
  sUSD as Collateral
&lt;/h3&gt;

&lt;p&gt;sUSD can serve as collateral within decentralized finance (DeFi) ecosystems due to its stable value and yield-bearing characteristics. You can lock your sUSD on DeFi lending platforms to access liquidity without selling your sUSD holdings.&lt;/p&gt;

&lt;p&gt;A unique feature of sUSD as collateral is that it is yield-bearing. This makes it a more efficient form of collateral than standard stablecoins, as you can maintain a healthy collateral ratio more easily because the interest helps increase the effective value of your collateral over time.&lt;/p&gt;

&lt;p&gt;The yield-bearing nature also of sUSD ensures that you continue to benefit from the underlying asset growth even when locked as collateral, providing a buffer against minor market fluctuations.&lt;/p&gt;

&lt;h3&gt;
  
  
  sUSD for Payments
&lt;/h3&gt;

&lt;p&gt;sUSD is an ideal payment solution due to its stability, low fees, and high speed on the Solana network. Additionally, due to its permissionless and decentralized nature, it is an ideal solution for cross-border payments as it eliminates the need for intermediaries like banks, which often delay and add fees to international payments.&lt;/p&gt;

&lt;p&gt;Payments made with sUSD are recorded &lt;strong&gt;on-chain&lt;/strong&gt;, providing full &lt;strong&gt;transparency&lt;/strong&gt;. This can be valuable for businesses that need to maintain an accurate record of transactions or for users who want to track their payment history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Earn yield on your stablecoins with sUSD
&lt;/h2&gt;

&lt;p&gt;Solayer USD (sUSD) marks a significant innovation in the stablecoin landscape by offering a yield-bearing, real-world asset (RWA)-backed model on Solana. Its permissionless design removes barriers to entry, making sUSD accessible to anyone globally, regardless of their location or financial background.&lt;/p&gt;

&lt;p&gt;sUSD shifts the stablecoin model toward prioritizing user yield over centralized profits, contributing to a more decentralized financial ecosystem. &lt;/p&gt;

&lt;p&gt;Want to earn a stable RWA-backed yield on your stablecoin reserves and contribute to a more decentralized financial ecosystem? Mint sUSD tokens on &lt;a href="https://app.solayer.org/" rel="noopener noreferrer"&gt;https://app.solayer.org/&lt;/a&gt; today!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding Data Transfer Objects (DTO) and Data Validation in TypeScript (NestJS)</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Sun, 15 May 2022 23:38:02 +0000</pubDate>
      <link>https://dev.to/davidekete/understanding-data-transfer-objects-dto-and-data-validation-in-typescript-nestjs-1j2b</link>
      <guid>https://dev.to/davidekete/understanding-data-transfer-objects-dto-and-data-validation-in-typescript-nestjs-1j2b</guid>
      <description>&lt;p&gt;Data Transfer Objects (DTOs) are the basis of data validation in NestJS applications. DTOs enable various layers of flexible data validation in NestJS. &lt;/p&gt;

&lt;p&gt;In this publication, you will take a deep dive into data transfer objects, discussing validation mechanisms, authentication models, and everything else you need to know about data transfer objects.&lt;/p&gt;

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

&lt;p&gt;This tutorial is not beginner-themed. If you’re just getting started with NestJS, read this &lt;a href="https://davidekete.hashnode.dev/the-abcs-of-nestjs-a-beginners-guide-with-mongodbmongoose" rel="noopener noreferrer"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You’ll need to meet these requirements to fully understand this article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prior experience creating NestJS apps with MongoDB.&lt;/li&gt;
&lt;li&gt;Competence with PostMan (recommended) or any other API testing tool.&lt;/li&gt;
&lt;li&gt;Basic knowledge of bcrypt or the NodeJS crypto module.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you meet these requirements, we can get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Data Transfer Object?
&lt;/h2&gt;

&lt;p&gt;A data transfer object, commonly called a DTO, is an object used to validate data and define data structure sent into your Nest applications. DTOs are similar to interfaces, but differ from interfaces in the following ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interfaces are used for type-checking and structure definition.&lt;/li&gt;
&lt;li&gt;A DTO is used for type-checking, structure definition, and data validation.&lt;/li&gt;
&lt;li&gt;Interfaces disappear during compilation, as it’s native to TypeScript and doesn't exist in JavaScript.&lt;/li&gt;
&lt;li&gt;DTOs are defined using classes that are supported in native JavaScript. Hence, it remains after compilation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DTOs alone can only do type-checking and structure definition. To run data validations using DTOs, you’ll need to use the NestJS &lt;code&gt;ValidationPipe&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation Mechanisms
&lt;/h2&gt;

&lt;p&gt;Pipes are used to validate data in NestJS. Data passing through a pipe is evaluated, if it passes the validation test, it is returned unmodified; otherwise, an error is thrown. &lt;/p&gt;

&lt;p&gt;NestJS has 8 inbuilt pipes, but you’ll be focusing on the &lt;code&gt;ValidationPipe&lt;/code&gt; which makes use of the &lt;code&gt;class-validator&lt;/code&gt; package, because it abstracts a lot of verbose code and makes it easy to validate data using decorators.&lt;/p&gt;

&lt;h2&gt;
  
  
  DTOs in a Simple User Authentication Model
&lt;/h2&gt;

&lt;p&gt;A user authentication model is a perfect example to demystify DTOs. This is because it requires multiple levels of data validation. Let’s make one and explore DTOs and the &lt;code&gt;ValidationPipe&lt;/code&gt; to validate all forms of data coming into our application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up Development Environment
&lt;/h3&gt;

&lt;p&gt;To set up your development environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate a new project using the Nest CLI,&lt;/li&gt;
&lt;li&gt;Generate your &lt;code&gt;Module&lt;/code&gt;, &lt;code&gt;Service&lt;/code&gt;, and &lt;code&gt;Controller&lt;/code&gt; using the CLI,&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;Mongoose&lt;/code&gt; and connect your application to the database,&lt;/li&gt;
&lt;li&gt;Create your schema folder and define the &lt;code&gt;Schema&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A typical user-auth schema should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createForClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having the &lt;code&gt;fullName&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;password&lt;/code&gt; as required properties.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a folder inside your module and call it &lt;code&gt;dto&lt;/code&gt;. This is where your dto classes will be stored and exported.&lt;/li&gt;
&lt;li&gt;Create a file inside your &lt;code&gt;dto&lt;/code&gt; folder and name it &lt;code&gt;user.dto.ts&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Structure of a DTO
&lt;/h2&gt;

&lt;p&gt;A DTO is a class, so it follows the same syntax a class does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;newUserDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above is the structure of a basic DTO.&lt;/p&gt;

&lt;p&gt;This structure is only useful for type-checking, it has no data validation properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Data Validation
&lt;/h2&gt;

&lt;p&gt;To add validation functions; follow the steps below;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside your &lt;code&gt;main.ts&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;{ValidationPipe}&lt;/code&gt; from &lt;code&gt;'@nestjs/common'&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;bootstrap&lt;/code&gt; function and directly below the &lt;code&gt;app&lt;/code&gt; constant, call the &lt;code&gt;useGlobalPipes&lt;/code&gt; method on &lt;code&gt;app&lt;/code&gt; and pass in &lt;code&gt;new ValidationPipe()&lt;/code&gt; as an argument.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ValidationPipe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&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;bootstrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&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;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useGlobalPipes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ValidationPipe&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will enable auto-validation and ensure that all endpoints are protected from receiving incorrect data. The Validation pipe takes in an options object as an argument, you can find out more about it in the &lt;a href="https://docs.nestjs.com/techniques/validation#overview" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the &lt;code&gt;class-validator&lt;/code&gt; and the &lt;code&gt;class-transformer&lt;/code&gt; package by running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;transformer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;class-transformer&lt;/code&gt; converts JSON objects into an instance of your DTO class and vice-versa.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;class-validator&lt;/code&gt; package has a lot of validation queries, which you can find in their &lt;a href="https://www.npmjs.com/package/class-validator" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, but you’ll be focusing on a few of them related to user data validation. In your &lt;code&gt;user.dto.ts&lt;/code&gt; file, import the following queries from &lt;code&gt;class-validator&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IsNotEmpty&lt;/code&gt;: This validator checks if a given value is empty. It takes in an object of options as an argument.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IsString&lt;/code&gt;: This validator checks if a given value is a real string. It takes in an object of options as an argument.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IsEmail&lt;/code&gt;: This validator checks if a given value is of type email. It takes in an object of options as an argument.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Length&lt;/code&gt;: This Validator takes in 3 arguments. The first is the &lt;code&gt;minLength&lt;/code&gt;, then the &lt;code&gt;maxLength&lt;/code&gt;, and finally an object of options.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above will be used as decorators to validate their respective fields. Implement this in your DTO,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IsNotEmpty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IsEmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IsString&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class-validator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;newUserDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;IsNotEmpty&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please Enter Full Name&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="nd"&gt;IsString&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please Enter Valid Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;IsEmail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please Enter a Valid Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password length Must be between 6 and 50 charcters&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="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The password field has only a &lt;code&gt;Length&lt;/code&gt; validation but in production, you might need to add a few more fields to ensure the password is more secure. &lt;/p&gt;

&lt;p&gt;These new validation fields might include checking if the password contains uppercase, lowercase, and numbers. &lt;/p&gt;

&lt;p&gt;This can be done in several ways, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Padding with more validation decorators, like you did in the &lt;code&gt;fullName&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;Using the &lt;code&gt;@Matches&lt;/code&gt; validator and passing a regular expression that checks for your requirements as an argument.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the cleanest way to do this would be by creating a custom validator to suit your specifications. You can learn more about custom decorators &lt;a href="https://github.com/davidekete/class-validator#custom-validation-decorators" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Post &amp;amp; Put Requests
&lt;/h2&gt;

&lt;p&gt;Test the data validation by making a few &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;PUT&lt;/code&gt; requests to your application. But before that, it’s bad practice to store your passwords in plain text. So hash them first before storing them in the database;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hashing Passwords
&lt;/h3&gt;

&lt;p&gt;You can hash the passwords using a package called &lt;code&gt;bcrypt&lt;/code&gt; or the NodeJS crypto module. This publication covers &lt;code&gt;bcrypt&lt;/code&gt;. To install &lt;code&gt;bcrypt&lt;/code&gt; run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i bcrypt
npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @types/bcrypt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;utils&lt;/code&gt; folder to store files that contain utility functions, like the function you’ll use to hash the passwords.&lt;/p&gt;

&lt;p&gt;To ensure that user passwords are protected, you’ll need to hash them before they are stored in the database. Let’s implement this&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a file in your &lt;code&gt;utils&lt;/code&gt; folder, this will contain your utility functions.&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;*&lt;/code&gt; as &lt;code&gt;bcrypt&lt;/code&gt; from &lt;code&gt;'bcrypt'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a function that takes in the raw password and hashes it using &lt;code&gt;bcrypt&lt;/code&gt; then returns the hashed password. Export the function.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bcrypt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;salt&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;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;genSalt&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&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;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;hash&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;There are different ways to use the &lt;code&gt;bcrypt&lt;/code&gt; package, which you can find &lt;a href="https://www.npmjs.com/package/bcrypt" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that you have a function to hash our passwords, Implement your first &lt;code&gt;POST&lt;/code&gt; request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a New User
&lt;/h3&gt;

&lt;p&gt;To create a new user with valid credentials, you’ll need to import the DTO you created earlier into your service. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Logic&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an &lt;code&gt;async&lt;/code&gt; function &lt;code&gt;newUser&lt;/code&gt; that takes in a parameter &lt;code&gt;user&lt;/code&gt; which should be the data of the new user. Set its type to the DTO created earlier.&lt;/li&gt;
&lt;li&gt;Import the &lt;code&gt;hashPassword&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;async&lt;/code&gt; function, create a constant &lt;code&gt;password&lt;/code&gt;, and assign the return value of awaiting the &lt;code&gt;hashPassword&lt;/code&gt; function with &lt;code&gt;user.password&lt;/code&gt; as an argument.&lt;/li&gt;
&lt;li&gt;Return a new instance of your own version of my &lt;code&gt;userModel&lt;/code&gt; as an argument pass in an object containing a destructured &lt;code&gt;user&lt;/code&gt; and the &lt;code&gt;password&lt;/code&gt;, and call the &lt;code&gt;save()&lt;/code&gt; method on it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InjectModel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UserDocument&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./schemas/user.schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;newUserDto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dto/user.dto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hashPassword&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./utilis/bcrypt.utils&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="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserDocument&lt;/span&gt;&lt;span class="o"&gt;&amp;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;async&lt;/span&gt; &lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newUserDto&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;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;password&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;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DTO and the validators we set up earlier will continuously check if the data is valid before storing the user data in the database. &lt;/p&gt;

&lt;p&gt;Implement the controller logic so that you can test the DTO with some dummy data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controller Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./auth.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;newUserDto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dto/user.dto&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="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&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="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newUserDto&lt;/span&gt;&lt;span class="p"&gt;,&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;newUserDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see in the code block above, the &lt;code&gt;user&lt;/code&gt; parameter has a type of &lt;code&gt;newUserDto&lt;/code&gt;. This ensures that all data coming into the application matches the DTO, else it throws an error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Endpoints
&lt;/h3&gt;

&lt;p&gt;Test the validation with some dummy data by making requests to &lt;code&gt;http://localhost:3000/users/signup&lt;/code&gt; using PostMan or your preferred testing tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fullName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Jon Snow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"snow@housestark.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON data above checks all validation boxes. Hence, you’ll get a &lt;code&gt;201&lt;/code&gt; response with data, with an &lt;code&gt;_id&lt;/code&gt; property and a hashed password. Copy the &lt;code&gt;_id&lt;/code&gt; property, you’ll need it when testing data validation in &lt;code&gt;PUT&lt;/code&gt; requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fullName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Arya Stark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"aryathefaceless@housestark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON data above has an invalid &lt;code&gt;email&lt;/code&gt; property. Hence, you’ll get a &lt;code&gt;400&lt;/code&gt; response with a message that describes the error. Save it to the database by updating the &lt;code&gt;email&lt;/code&gt; property to &lt;code&gt;aryathefaceless@housestark.com&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fullName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Tyrion Lannister"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"tyrion@houselannister.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"house"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Lannister"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON data above has 2 problems, the password is too short (less than 6 characters) and there is an extra field &lt;code&gt;house&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Increase the length of the &lt;code&gt;password&lt;/code&gt; and send the request again. You’ll get a &lt;code&gt;200&lt;/code&gt; request with the processed data, but the &lt;code&gt;house&lt;/code&gt; field isn’t stored in the database because it was filtered when it was passed through the validation pipe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating a User
&lt;/h3&gt;

&lt;p&gt;Implement a &lt;code&gt;PUT&lt;/code&gt; route to update user data when required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newUserDto&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;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByIdAndUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userData&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;&lt;strong&gt;Controller Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;updateuser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newUserDto&lt;/span&gt;&lt;span class="p"&gt;,&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;newUserDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&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;Similar to the &lt;code&gt;POST&lt;/code&gt; request, the &lt;code&gt;user&lt;/code&gt; is given a type of &lt;code&gt;newUserDto&lt;/code&gt;. Hence, all data is checked thoroughly before it is saved in the database.&lt;/p&gt;

&lt;p&gt;Test this endpoint by updating one of the users stored in your database. Recall that you copied the &lt;code&gt;_id&lt;/code&gt; belonging to Jon Snow.&lt;/p&gt;

&lt;p&gt;So make a &lt;code&gt;PUT&lt;/code&gt; request to &lt;code&gt;http://localhost:3000/id&lt;/code&gt; with the following data;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fullName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Jon Snow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"snow@housetargaryen.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The data above checks all validation boxes, so it would return a &lt;code&gt;200&lt;/code&gt; response. If any of the data fields contain invalid data, it would return a &lt;code&gt;400&lt;/code&gt; response and the &lt;code&gt;PUT&lt;/code&gt; request would fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging Users in
&lt;/h3&gt;

&lt;p&gt;A user-authentication model wouldn't be complete if you couldn't log users in. To implement the logic for that;&lt;/p&gt;

&lt;p&gt;Firstly, you’ll need a &lt;code&gt;bcrypt&lt;/code&gt; utility function that will compare the hashed and plain text passwords. Like so,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&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;validatePassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validUser&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;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textPassword&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;validUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you’ll have to create a new DTO for the login data. The DTO is similar to the &lt;code&gt;newUserDto&lt;/code&gt; but without the &lt;code&gt;fullName&lt;/code&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IsEmail&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class-validator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;loginUserDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;IsEmail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please Enter a Valid Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that no validator was added to the &lt;code&gt;password&lt;/code&gt; property. This is because it could pose a security threat in the future, as it exposes the password length range to malicious users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;loginUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loginUserDto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loginData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;valid&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;validatePassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&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;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UnauthorizedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid Credentials&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your service logic should be able to,&lt;/p&gt;

&lt;p&gt;Check if the user exists;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the user exists, validate the passwords&lt;/li&gt;
&lt;li&gt;If the user doesn't exist, throw an exception&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Validate Passwords;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the passwords match, return the user&lt;/li&gt;
&lt;li&gt;If the passwords don’t match, throw an exception&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Controller Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;loginUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;loginData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loginUserDto&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;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loginUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginData&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;Your controller should make the &lt;code&gt;POST&lt;/code&gt; request to &lt;code&gt;http://localhost:3000/users/login&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;You’re finally at the end of this article. Here’s a recap what you’ve covered.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What a DTO is,&lt;/li&gt;
&lt;li&gt;Differences between a DTO and an interface,&lt;/li&gt;
&lt;li&gt;Structure of a DTO,&lt;/li&gt;
&lt;li&gt;NestJS validation mechanism,&lt;/li&gt;
&lt;li&gt;Making a simple user-authentication model with bcrypt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s quite a lot, congratulations on making it this far.&lt;/p&gt;

&lt;p&gt;You can find the code on &lt;a href="https://github.com/davidekete/Data-Transfer-Objects" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>dto</category>
      <category>datavalidation</category>
      <category>classvalidator</category>
    </item>
    <item>
      <title>The ABCs of NestJS: A Beginner’s guide with MongoDB(Mongoose).</title>
      <dc:creator>David Ekete</dc:creator>
      <pubDate>Sun, 08 May 2022 11:36:06 +0000</pubDate>
      <link>https://dev.to/davidekete/the-abcs-of-nestjs-a-beginners-guide-with-mongodbmongoose-2ln</link>
      <guid>https://dev.to/davidekete/the-abcs-of-nestjs-a-beginners-guide-with-mongodbmongoose-2ln</guid>
      <description>&lt;h2&gt;
  
  
  What is NestJS?
&lt;/h2&gt;

&lt;p&gt;NestJS is a modern NodeJS framework that makes use of popular NodeJS frameworks such as Express and Fastify under the hood. NestJS was largely inspired by Angular, and as a result, it employs an Angular-style module system. NestJS is written in TypeScript, although it also supports native JavaScript.&lt;/p&gt;

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

&lt;p&gt;To follow this tutorial, you must meet the following requirements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Competence in PostMan or any other API testing tool.&lt;/li&gt;
&lt;li&gt;Basic Knowledge of NodeJS and Express apps.&lt;/li&gt;
&lt;li&gt;Basic knowledge of TypeScript.&lt;/li&gt;
&lt;li&gt;Competence in MongoDB(Mongoose).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following should be installed on your system &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NodeJS v.14 and above.&lt;/li&gt;
&lt;li&gt;Visual Studio Code(Recommended) or any other IDE.&lt;/li&gt;
&lt;li&gt;PostMan or any other API testing Tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Terminologies used in NestJS;
&lt;/h2&gt;

&lt;p&gt;Here are some of the most regularly used terms in NestJS that you'll encounter a lot in this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interfaces
&lt;/h3&gt;

&lt;p&gt;An interface is a type definition. As a result, it is utilized as a type checker/enforcer in functions, classes, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;humanInterface&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kevin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;humanInterface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Kevin Sunders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;humanInterface&lt;/code&gt; above performs strict type checking on the &lt;code&gt;kevin&lt;/code&gt; object. Typescript would throw an error if you added another field or changed the type of any of the object properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controllers
&lt;/h3&gt;

&lt;p&gt;Controllers are in charge of receiving incoming requests and responding to the client. A controller collaborates with its associated service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Services
&lt;/h3&gt;

&lt;p&gt;A service is a &lt;a href="https://docs.nestjs.com/providers" rel="noopener noreferrer"&gt;provider&lt;/a&gt; that stores and retrieves data and is used with its corresponding controller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decorators
&lt;/h3&gt;

&lt;p&gt;A decorator is a function-returning expression that accepts a &lt;code&gt;target&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, and &lt;code&gt;property descriptor&lt;/code&gt; as optional arguments. Decorators are written as &lt;code&gt;@decorator-name&lt;/code&gt;. They are usually attached to class declarations, methods, and parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAll&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;The &lt;code&gt;@Get&lt;/code&gt; decorator above marks the code block below it as a &lt;code&gt;GET&lt;/code&gt; request. More about that later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Module
&lt;/h3&gt;

&lt;p&gt;A module is a part of a program that handles a particular task. A module in NestJS is marked by annotating a class annotated with the &lt;code&gt;@Module()&lt;/code&gt; decorator. Nest uses the &lt;a href="https://en.wikipedia.org/wiki/Metadata" rel="noopener noreferrer"&gt;metadata&lt;/a&gt; provided by the &lt;code&gt;@Module()&lt;/code&gt; decorator to organize the application structure.&lt;/p&gt;

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

&lt;p&gt;To get started you’ll have to install the NestJS CLI ****with &lt;code&gt;npm&lt;/code&gt;. You can skip this step if you already have the NestJS CLI installed on your system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @nestjs/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code block above will install the nest CLI globally on your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a new project
&lt;/h2&gt;

&lt;p&gt;To generate a new project run &lt;code&gt;nest new&lt;/code&gt; followed by your desired project name. For this article, we’ll be writing a simple blog API with CRUD functionality while adhering to RESTful standards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest new Blog-Api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will prompt you to select a package manager, choose &lt;code&gt;npm&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This will then scaffold the entire project structure with a test API endpoint whose port is set to &lt;code&gt;3000&lt;/code&gt; by default. You can test it at &lt;code&gt;http://localhost:3000&lt;/code&gt; after running the &lt;code&gt;npm run start:dev&lt;/code&gt; command which will start the server in watch mode similar to what nodemon does in express apps.&lt;/p&gt;

&lt;p&gt;After testing the endpoint, you’ll need to delete some of the default files because you won’t be needing them anymore. To do this;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;open the src folder and inside,&lt;/li&gt;
&lt;li&gt;delete &lt;code&gt;app.controller.spec.ts&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;delete &lt;code&gt;app.controller.ts&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;delete &lt;code&gt;app.service.ts&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;app.module.ts&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Remove the reference to &lt;code&gt;AppController&lt;/code&gt; in the &lt;code&gt;controllers&lt;/code&gt; array and the imports,&lt;/li&gt;
&lt;li&gt;Remove the reference to &lt;code&gt;AppService&lt;/code&gt; in the &lt;code&gt;providers&lt;/code&gt; array and the imports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might also need to change the &lt;code&gt;README.md&lt;/code&gt; to meet your specifications.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;app.module.ts&lt;/code&gt; file should look like this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//app.module.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;providers&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;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Environmental Variables
&lt;/h3&gt;

&lt;p&gt;As good practice, some sensitive information in your code shouldn't be made public. For example your &lt;code&gt;PORT&lt;/code&gt; and your &lt;code&gt;MongoDB URI&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's fix this in your code.&lt;/p&gt;

&lt;p&gt;On your terminal run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a &lt;code&gt;.env&lt;/code&gt; file in your directory and add it to your &lt;code&gt;.gitignore&lt;/code&gt; file. Store your &lt;code&gt;PORT&lt;/code&gt; variable, you will also have to store your &lt;code&gt;MongoDB URI&lt;/code&gt; later in the same place. Now replace the exposed &lt;code&gt;PORT&lt;/code&gt; in your &lt;code&gt;main.ts&lt;/code&gt; file. To do this, import the &lt;code&gt;dotenv&lt;/code&gt; package and call the &lt;code&gt;.config()&lt;/code&gt; method on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should be your &lt;code&gt;main.ts&lt;/code&gt; file after you follow the steps above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//main.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./app.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&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;bootstrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&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;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating Modules
&lt;/h2&gt;

&lt;p&gt;To generate a NestJS module using the NestJS CLI run the code snippet below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest generate module blogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a &lt;code&gt;blogs&lt;/code&gt; folder that contains a &lt;code&gt;blogs.module.ts&lt;/code&gt; file and registers &lt;code&gt;BlogsModule&lt;/code&gt; in your &lt;code&gt;app.module.ts&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating Interfaces
&lt;/h2&gt;

&lt;p&gt;Let’s generate an interface using the NestJS CLI to do the type checking for the object that will represent your blog posts. To achieve this you have to first &lt;code&gt;cd&lt;/code&gt; into the &lt;code&gt;blogs&lt;/code&gt; folder because it is recommended that they be stored near the domain objects to which they are associated.&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;src/blogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the code snippet below to generate the interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest generate interface blogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this creates a &lt;code&gt;blogs.interface.ts&lt;/code&gt; file. This is where we will define our interface. we’ll name the interface &lt;code&gt;BlogsInterface&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BlogsInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dateCreated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&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;before running any more commands on your terminal, remember to &lt;code&gt;cd&lt;/code&gt; out of the &lt;code&gt;src&lt;/code&gt; folder and back into your root folder by running&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; ../..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating Services &amp;amp; Controllers
&lt;/h2&gt;

&lt;p&gt;You’ll need to generate a service class to store and retrieve data and handle all the logic and a controller class to handle all incoming requests and outgoing responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service
&lt;/h3&gt;

&lt;p&gt;To generate a service run the command below,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest generate service blogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates two files the &lt;code&gt;blogs.service.spec.ts&lt;/code&gt; and the &lt;code&gt;blogs.service.ts&lt;/code&gt; and registers the service in the &lt;code&gt;providers&lt;/code&gt; array in the &lt;code&gt;blogs.module.ts&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controller
&lt;/h3&gt;

&lt;p&gt;To generate a controller run the command below,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest generate controller blogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates two files the &lt;code&gt;blogs.controller.spec.ts&lt;/code&gt; and the &lt;code&gt;blogs.controller.ts&lt;/code&gt; and registers the controller in the &lt;code&gt;controllers&lt;/code&gt; array in the &lt;code&gt;blogs.module.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With these your blogs structure is almost complete, you just need to make the &lt;code&gt;BlogsService&lt;/code&gt; accessible to other parts of your program. You can achieve this by creating an &lt;code&gt;exports&lt;/code&gt; array in the &lt;code&gt;blogs.module.ts&lt;/code&gt; file and registering the &lt;code&gt;BlogsService&lt;/code&gt; in that array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//blogs.module.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BlogsService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blogs.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BlogsController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blogs.controller&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BlogsService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BlogsController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BlogsService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogsModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MongoDB(Mongoose).
&lt;/h2&gt;

&lt;p&gt;Install mongoose by running,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; @nestjs/mongoose mongoose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the installation, import &lt;code&gt;{MongooseModule}&lt;/code&gt; from &lt;code&gt;'@nestjs/mongoose’&lt;/code&gt; into your &lt;code&gt;app.module.ts&lt;/code&gt; file. Then grab your &lt;code&gt;MongoDB URI&lt;/code&gt; and store it in your &lt;code&gt;.env&lt;/code&gt; file. Repeat the steps to import &lt;code&gt;dotenv&lt;/code&gt; in the &lt;code&gt;app.module.ts&lt;/code&gt; file. Then in the &lt;code&gt;imports&lt;/code&gt; array call the &lt;code&gt;.forRoot()&lt;/code&gt; method which takes your &lt;code&gt;MongoDB URI&lt;/code&gt; as an argument on the &lt;code&gt;MongooseModule&lt;/code&gt;. Similar to the &lt;code&gt;mongoose.connect()&lt;/code&gt; in regular express apps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;BlogsModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MongooseModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MONGODB_URI&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a Schema.
&lt;/h3&gt;

&lt;p&gt;Let’s create a schema to define the shape of the blogs in our collection. To do this,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a folder inside your &lt;code&gt;blogs&lt;/code&gt; folder, name it &lt;code&gt;schemas&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;schemas&lt;/code&gt; folder, create a file and call it &lt;code&gt;blogs.schema.ts&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then,&lt;/p&gt;

&lt;p&gt;Firstly, you’ll have to,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import the &lt;code&gt;prop&lt;/code&gt; decorator, the &lt;code&gt;Schema&lt;/code&gt; decorator, and the &lt;code&gt;SchemaFactory&lt;/code&gt; from &lt;code&gt;@nestjs/mongoose&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Create a class &lt;code&gt;Blog&lt;/code&gt; and export it,&lt;/li&gt;
&lt;li&gt;Turn the class into a Schema by placing the &lt;code&gt;@Schema()&lt;/code&gt; decorator above the class,&lt;/li&gt;
&lt;li&gt;Create a constant &lt;code&gt;BlogSchema&lt;/code&gt;, assign the return value of calling the &lt;code&gt;.createForClass(Blog)&lt;/code&gt; with the name of your class as an argument on &lt;code&gt;SchemaFactory&lt;/code&gt; that you imported earlier.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//blogs.schema.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/mongoose&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="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Blog&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createForClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you’ll need to define the properties of the Schema.&lt;/p&gt;

&lt;p&gt;To define a property in the schema you’ll need to mark each of them with the &lt;code&gt;@prop()&lt;/code&gt; decorator. The &lt;code&gt;@prop&lt;/code&gt; decorator accepts an options object or a complex type declaration. The complex type declarations could be arrays and nested object type declarations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//blogs.schema.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/mongoose&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="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Blog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;dateCreated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createForClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next import &lt;code&gt;{ Document }&lt;/code&gt; from &lt;code&gt;'mongoose'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then create a union type with the Schema class and the imported &lt;code&gt;Document&lt;/code&gt;. Like so,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//blogs.schema.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BlogDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Blog&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your final &lt;code&gt;blogs.schema.ts&lt;/code&gt; file should look like this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BlogDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Blog&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Blog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;dateCreated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BlogSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SchemaFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createForClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Registering Schema
&lt;/h3&gt;

&lt;p&gt;You’ll need to import everything into your &lt;code&gt;blogs.module.ts&lt;/code&gt; file. To achieve this you’ll need to,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import &lt;code&gt;{MongooseModule}&lt;/code&gt; from &lt;code&gt;'@nestjs/mongoose’&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;{Blog, BlogSchema}&lt;/code&gt; from &lt;code&gt;'./schemas/blogs.schema'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create an &lt;code&gt;imports&lt;/code&gt; array inside the &lt;code&gt;@module&lt;/code&gt; decorator&lt;/li&gt;
&lt;li&gt;Call the &lt;code&gt;.forFeature()&lt;/code&gt; method on the &lt;code&gt;MongooseModule&lt;/code&gt;. This takes in an array containing an object that defines a &lt;code&gt;name&lt;/code&gt; and a &lt;code&gt;schema&lt;/code&gt; property which should be set to your &lt;code&gt;Blog.name&lt;/code&gt; and your &lt;code&gt;BlogSchema&lt;/code&gt; respectively.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;MongooseModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forFeature&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogSchema&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;h3&gt;
  
  
  Injecting Model
&lt;/h3&gt;

&lt;p&gt;You’ll need to inject the &lt;code&gt;Blog&lt;/code&gt; model into the &lt;code&gt;blogs.service.ts&lt;/code&gt; using the &lt;code&gt;@InjectModel()&lt;/code&gt; decorator. To achieve this you’ll have to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;import &lt;code&gt;{ Model }&lt;/code&gt; from &lt;code&gt;'mongoose'&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;import &lt;code&gt;{ InjectModel }&lt;/code&gt; from &lt;code&gt;'@nestjs/mongoose'&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;{Blog, BlogDocument}&lt;/code&gt; from &lt;code&gt;'./schemas/blogs.schema’&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;constructor&lt;/code&gt; inside the &lt;code&gt;BlogsService&lt;/code&gt; class,&lt;/li&gt;
&lt;li&gt;Declare a &lt;code&gt;private&lt;/code&gt; variable and call it &lt;code&gt;blogModel&lt;/code&gt; and assign a type of &lt;code&gt;Model&amp;lt;BlogDocument&amp;gt;&lt;/code&gt; to it. All mongoose methods will be called on this variable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recall that, &lt;code&gt;BlogDocument&lt;/code&gt; is the union type of the &lt;code&gt;Blog&lt;/code&gt; class and the Mongoose &lt;code&gt;Model&lt;/code&gt; that you created earlier. It is used as the generic type for your variable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decorate &lt;code&gt;blogModel&lt;/code&gt; with &lt;code&gt;@InjectModel()&lt;/code&gt; and pass &lt;code&gt;Blog.name&lt;/code&gt; as an argument.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;blogModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogDocument&lt;/span&gt;&lt;span class="o"&gt;&amp;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How Routing Works
&lt;/h3&gt;

&lt;p&gt;By now you must have noticed that the  &lt;code&gt;@Controller&lt;/code&gt; decorator has the string &lt;code&gt;'blogs'&lt;/code&gt; passed into it. This means that the controller will send all responses and handle all requests made on &lt;code&gt;http://localhost/3000/blogs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next up you’ll implement the service and controller logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service and Controller Logic.
&lt;/h2&gt;

&lt;p&gt;It's finally time to implement your CRUD functionality.&lt;/p&gt;

&lt;p&gt;Before we get started you’ll need to set up your controller. Start by importing some &lt;code&gt;HTTP&lt;/code&gt; method decorators into your controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//blogs.controller.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you’ll need to import the service and register it so you can be able to access it and import the interface for type-checking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//blogs.controller.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BlogsInterface&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blogs.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BlogsService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blogs.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To register your service create a &lt;code&gt;constructor&lt;/code&gt; inside the &lt;code&gt;BlogsController&lt;/code&gt; class and declare a &lt;code&gt;private readonly&lt;/code&gt; variable &lt;code&gt;service&lt;/code&gt; and set its type to &lt;code&gt;BlogsService&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogsService&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;Now that you’re all set up, let’s get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Service Logic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Import  &lt;code&gt;{ BlogsInterface }&lt;/code&gt; from &lt;code&gt;'./blogs.interface'&lt;/code&gt; and add an &lt;code&gt;async&lt;/code&gt; function to the &lt;code&gt;BlogsService&lt;/code&gt; class called &lt;code&gt;createBlog&lt;/code&gt;, which will take one parameter &lt;code&gt;blog&lt;/code&gt;, with its type as &lt;code&gt;BlogInterface&lt;/code&gt;, and its return type as a &lt;code&gt;Promise&lt;/code&gt; with a generic &lt;code&gt;&amp;lt;Blog&amp;gt;&lt;/code&gt; type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogsInterface&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;Blog&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blogModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;dateCreated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;save&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;&lt;strong&gt;Controller Logic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;BlogsController&lt;/code&gt; class add an &lt;code&gt;async&lt;/code&gt; function to the class. Call it &lt;code&gt;createBlog&lt;/code&gt; and mark it with the &lt;code&gt;@Post&lt;/code&gt; decorator which defines it as a &lt;code&gt;POST&lt;/code&gt; request.&lt;code&gt;createBlog&lt;/code&gt; takes one parameter &lt;code&gt;blog&lt;/code&gt;, with its type as &lt;code&gt;BlogInterface&lt;/code&gt;. Mark the parameter with &lt;code&gt;@Body&lt;/code&gt; decorator which extracts the entire &lt;code&gt;body&lt;/code&gt; object from the &lt;code&gt;req&lt;/code&gt; object and populates the decorated parameter with the value of &lt;code&gt;body&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogsInterface&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;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blog&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;h3&gt;
  
  
  Read
&lt;/h3&gt;

&lt;p&gt;Add two &lt;code&gt;async&lt;/code&gt; methods, One to return a single blog post and the second to return all the blog posts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getAllBlogs&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;Blog&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blogModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;exec&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="nf"&gt;getBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Blog&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blogModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;&lt;strong&gt;Controller Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getAllBlogs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllBlogs&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="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getBlog&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;The &lt;code&gt;async&lt;/code&gt; functions are marked with the &lt;code&gt;@Get&lt;/code&gt; decorator which defines it as a &lt;code&gt;GET&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;The second &lt;code&gt;async&lt;/code&gt; function’s decorator has an argument &lt;code&gt;':id'&lt;/code&gt;. Which is what you’ll pass into the &lt;code&gt;@Param&lt;/code&gt; decorator. The parameter is marked with the &lt;code&gt;@Param('id')&lt;/code&gt; which extracts the &lt;code&gt;params&lt;/code&gt; property from the &lt;code&gt;req&lt;/code&gt; object and populates the decorated parameter with the value of &lt;code&gt;params&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;p&gt;Let’s implement the logic for the &lt;code&gt;PUT&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;updateBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogsInterface&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;Blog&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blogModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByIdAndUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&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;&lt;strong&gt;Controller Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;updateBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogsInterface&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;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blog&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;The &lt;code&gt;async&lt;/code&gt; function’s second parameter is marked with the &lt;code&gt;@Body()&lt;/code&gt; decorator which extracts the entire &lt;code&gt;body&lt;/code&gt; object from the &lt;code&gt;req&lt;/code&gt; object and populates the decorated parameter with the value of &lt;code&gt;body&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;

&lt;p&gt;Let’s implement the logic for &lt;code&gt;delete&lt;/code&gt; requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;deleteBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blogModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByIdAndDelete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;The &lt;code&gt;Promise&lt;/code&gt; generic type is &lt;code&gt;void&lt;/code&gt; because a &lt;code&gt;Delete&lt;/code&gt; request returns an empty promise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controller Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;deleteBlog&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteBlog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;
  
  
  Testing the API
&lt;/h2&gt;

&lt;p&gt;To test this API, you should use an API testing tool. For this article, I’ll be using a popular API testing tool called &lt;a href="https://www.postman.com" rel="noopener noreferrer"&gt;Postman&lt;/a&gt;. I’ll be using random data about popular topics to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create
&lt;/h3&gt;

&lt;p&gt;Make a &lt;code&gt;POST&lt;/code&gt; request to  &lt;code&gt;http://localhost/3000/blogs&lt;/code&gt; with the following JSON objects, this will add all the data to your database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jeen-yuhs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The life of superstar rapper Kanye West is currently streaming on Netflix - and according to our jeen-yuhs review, it's a fascinating watch. -credit:Radio Times"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Music"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Why You Should Always Wash Your Hands"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Germs from unwashed hands can be transferred to other objects, like handrails, tabletops, or toys, and then transferred to another person's hands.-credit cdc.gov"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Health"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Why You Should Follow me on Twitter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Well, Because I asked nicely"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Random"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get a &lt;code&gt;201&lt;/code&gt; response and the created blog with a date and an &lt;code&gt;_id&lt;/code&gt; added.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read
&lt;/h3&gt;

&lt;p&gt;Make a &lt;code&gt;GET&lt;/code&gt; request to  &lt;code&gt;http://localhost/3000/blogs&lt;/code&gt;. This should return a&lt;/p&gt;

&lt;p&gt;&lt;code&gt;200&lt;/code&gt; response with an array of all the data you previously added. Copy the &lt;code&gt;_id&lt;/code&gt;  property of one of the array objects. &lt;/p&gt;

&lt;p&gt;Make another &lt;code&gt;GET&lt;/code&gt; request to  &lt;code&gt;http://localhost/3000/blogs/id&lt;/code&gt; with the previously copied id. This should return a &lt;code&gt;200&lt;/code&gt; response with the data of the object whose id was used to make the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;p&gt;Make a &lt;code&gt;PUT&lt;/code&gt; request to  &lt;code&gt;http://localhost/3000/blogs/id&lt;/code&gt; with the data below. The &lt;code&gt;id&lt;/code&gt;  should be replaced with the one you copied earlier. This should return a &lt;code&gt;200&lt;/code&gt; response and updates the object bearing the &lt;code&gt;id&lt;/code&gt; behind the scenes. if you run another &lt;code&gt;GET&lt;/code&gt; request you should get the updated object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"why you Should Cut your Nails"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"It's important to trim your nails regularly. Nail trimming together with manicures makes your nails look well-groomed, neat, and tidy.- credit:WebMD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Health"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;

&lt;p&gt;Make a &lt;code&gt;DELETE&lt;/code&gt; request to &lt;code&gt;http://localhost/3000/blogs/id&lt;/code&gt;.This should return a &lt;code&gt;200&lt;/code&gt; response and deletes the object bearing the &lt;code&gt;id&lt;/code&gt; behind the scenes. if you run another &lt;code&gt;GET&lt;/code&gt; request you won’t see the deleted object.&lt;/p&gt;

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

&lt;p&gt;So we’re finally at the end of this article. Let’s recap what you’ve covered.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What NestJS is,&lt;/li&gt;
&lt;li&gt;Terminologies in NestJS,&lt;/li&gt;
&lt;li&gt;Creating a NestJS app,&lt;/li&gt;
&lt;li&gt;Integrating MongoDB into a NestJS app,&lt;/li&gt;
&lt;li&gt;Manipulating and NestJS app,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s quite a lot, congratulations on making it this far.&lt;/p&gt;

&lt;p&gt;You can find the code on &lt;a href="https://github.com/davidekete/Blog-API" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck on your NestJS journey!&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>newbie</category>
      <category>mongodb</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
