<?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: Vinay</title>
    <description>The latest articles on DEV Community by Vinay (@blackat).</description>
    <link>https://dev.to/blackat</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png</url>
      <title>DEV Community: Vinay</title>
      <link>https://dev.to/blackat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blackat"/>
    <language>en</language>
    <item>
      <title>Three Token-2022 Mints in One Week: Fees, Yield, and Soul-Bound Tokens on Solana</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Sun, 28 Jun 2026 18:45:00 +0000</pubDate>
      <link>https://dev.to/blackat/three-token-2022-mints-in-one-week-fees-yield-and-soul-bound-tokens-on-solana-19be</link>
      <guid>https://dev.to/blackat/three-token-2022-mints-in-one-week-fees-yield-and-soul-bound-tokens-on-solana-19be</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A Token-2022 mint is not just a number that moves around. It is a number that moves around with rules attached.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have ever worked with Stripe, you know the pattern. You start with a simple charge. Then you add features — subscriptions, transfer fees, metadata. Each feature is a separate API call, and wiring them together is your job.&lt;/p&gt;

&lt;p&gt;Token-2022 (the upgraded SPL Token program at &lt;code&gt;TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb&lt;/code&gt;) flips that. Instead of middleware living next to the asset, the middleware lives inside the asset. You bake rules directly into the mint at creation time, and every wallet, program, and dApp that handles your token automatically respects them.&lt;/p&gt;

&lt;p&gt;Here are three mints I shipped this week, what each extension does, and when you would reach for one.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Transfer Fee Mint — Skim 1% on Every Transfer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mint:&lt;/strong&gt; &lt;code&gt;AXdJwLSxuzh2hjLvwEtjuDSKXMhWeVwvH2ZZkfguTBJP&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Explorer:&lt;/strong&gt; &lt;a href="https://explorer.solana.com/address/AXdJwLSxuzh2hjLvwEtjuDSKXMhWeVwvH2ZZkfguTBJP?cluster=devnet" rel="noopener noreferrer"&gt;https://explorer.solana.com/address/AXdJwLSxuzh2hjLvwEtjuDSKXMhWeVwvH2ZZkfguTBJP?cluster=devnet&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Extension:&lt;/strong&gt; Transfer Fee (100 basis points = 1%, max fee 1,000,000 tokens)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-basis-points&lt;/span&gt; 100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-maximum-fee&lt;/span&gt; 1000000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you transfer this token, the protocol automatically splits the amount: the recipient gets 99%, and 1% goes into a &lt;code&gt;withheld_amount&lt;/code&gt; field on the recipient's account — untouchable by the recipient. The mint authority can sweep those withheld fees at any time with a single &lt;code&gt;withdraw-withheld-tokens&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token transfer &lt;span class="nt"&gt;--expected-fee&lt;/span&gt; 10 &lt;span class="nv"&gt;$MINT&lt;/span&gt; 1000 &lt;span class="nv"&gt;$RECIPIENT&lt;/span&gt; &lt;span class="nt"&gt;--allow-unfunded-recipient&lt;/span&gt;
spl-token withdraw-withheld-tokens &lt;span class="nv"&gt;$MY_TA&lt;/span&gt; &lt;span class="nv"&gt;$RECIPIENT_TA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Creator royalties, protocol fees on a stablecoin, a treasury skim on a community currency. The fee is enforced at the protocol level — no middleware, no webhook, no way to route around it.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Interest-Bearing + Transfer Fee — Yield That Compounds While You Watch
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mint:&lt;/strong&gt; &lt;code&gt;FALRuEMugKuEf4e5sD4SHL5JsXcmZqGmtBgEPWC3BUpQ&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Explorer:&lt;/strong&gt; &lt;a href="https://explorer.solana.com/address/FALRuEMugKuEf4e5sD4SHL5JsXcmZqGmtBgEPWC3BUpQ?cluster=devnet" rel="noopener noreferrer"&gt;https://explorer.solana.com/address/FALRuEMugKuEf4e5sD4SHL5JsXcmZqGmtBgEPWC3BUpQ?cluster=devnet&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Extensions:&lt;/strong&gt; Transfer Fee (100bps) + Interest-Bearing (5000bps = 50% APR)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 6 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-basis-points&lt;/span&gt; 100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-maximum-fee&lt;/span&gt; 1000000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--interest-rate&lt;/span&gt; 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two extensions, one mint, zero conflict. I minted 1,000,000 tokens, and within seconds the displayed balance started growing — no transaction needed. The trick: interest updates the &lt;em&gt;UI amount only&lt;/em&gt;. The raw token balance in your account never changes. The protocol computes the displayed amount on the fly from the mint's rate and the network clock.&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="c"&gt;# Check balance twice with a 30s pause — watch it grow&lt;/span&gt;
spl-token balance &lt;span class="nv"&gt;$MINT&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;30
spl-token balance &lt;span class="nv"&gt;$MINT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The transfer fee still operates on the raw amount, so both extensions compose cleanly. You get a token that charges fees when it moves and yields interest while it sits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Savings accounts, vesting schedules, any token where time should affect value.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Non-Transferable Mint — A Token That Refuses to Move
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mint:&lt;/strong&gt; &lt;code&gt;3oJBDKS7hrnTsjKQVJ9wGXZm3BVt6NnGekBXfbHRyvfP&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Explorer:&lt;/strong&gt; &lt;a href="https://explorer.solana.com/address/3oJBDKS7hrnTsjKQVJ9wGXZm3BVt6NnGekBXfbHRyvfP?cluster=devnet" rel="noopener noreferrer"&gt;https://explorer.solana.com/address/3oJBDKS7hrnTsjKQVJ9wGXZm3BVt6NnGekBXfbHRyvfP?cluster=devnet&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Extension:&lt;/strong&gt; Non-Transferable (soul-bound)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="nt"&gt;--program-2022&lt;/span&gt; &lt;span class="nt"&gt;--enable-non-transferable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I minted one token to myself and tried to send it to a fresh wallet. The runtime rejected me immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: The transfer is disabled because this token is non-transferable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That error is the feature. The non-transferable extension turns a fungible token into a soul-bound badge. Once it lands in your account, it stays there forever — no wallet, marketplace, or dApp can move it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Certificates, credentials, achievement badges, identity attestations — anything where the holder should be the permanent owner.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Surprised Me
&lt;/h2&gt;

&lt;p&gt;The biggest surprise was that none of this required a custom smart contract. In Web2, every new behavior means a new API endpoint, a new database migration, a new cron job. On Solana with Token-2022, you flip a flag at creation time and the runtime does the rest — fees, interest, transfer restrictions, all composed from the same primitive.&lt;/p&gt;

&lt;p&gt;The second surprise was the interest extension. I kept waiting for a "mint" transaction to appear, but there never was one. The balance just... drifted upward. It is the closest thing to a bank savings account I have seen on a blockchain, and it took one flag to enable.&lt;/p&gt;

&lt;p&gt;If I were building a real product, I would reach for the transfer fee extension for a creator-owned token where every trade pays the treasury, and the non-transferable extension for on-chain credentials that prove attendance or completion without the risk of secondary sales.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>100daysofsolana</category>
      <category>solana</category>
    </item>
    <item>
      <title>Solana NFTs Without Metaplex: A Week of Token Extensions</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Sun, 28 Jun 2026 08:26:07 +0000</pubDate>
      <link>https://dev.to/blackat/solana-nfts-without-metaplex-a-week-of-token-extensions-2a6k</link>
      <guid>https://dev.to/blackat/solana-nfts-without-metaplex-a-week-of-token-extensions-2a6k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;An NFT on Solana is just a mint with supply 1, decimals 0, and metadata.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before this week I thought a Solana NFT required Metaplex. Every tutorial pointed at the Metaplex Token Metadata program as the standard way to add a name, image, and collection to a token. It turns out you can mint a full NFT — with on-chain metadata, a verifiable collection membership, and live-updatable fields — using nothing but the Token Extensions program and a handful of CLI commands. No custom smart contract. No framework. Just the protocol.&lt;/p&gt;

&lt;p&gt;Here is what I built across four days and what surprised me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 1 — An NFT with on-chain metadata
&lt;/h2&gt;

&lt;p&gt;The mental model first. An NFT on Solana is a token mint with three properties: supply of 1, zero decimals (so you cannot split it), and metadata that wallets can read. With Token Extensions, the metadata lives directly on the mint account itself — no separate Metaplex account, no PDA derivation, no extra lookups.&lt;/p&gt;

&lt;p&gt;I created a vanity mint address using &lt;code&gt;solana-keygen grind --starts-with nft:1&lt;/code&gt;, then minted the token with the metadata extension enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
  ./nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I stamped it with a name, symbol, and a URI pointing to a JSON file on a GitHub Gist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token initialize-metadata nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"First Light"&lt;/span&gt; &lt;span class="s2"&gt;"LIGHT"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://gist.githubusercontent.com/bl4ck4t/e0899c5a417f0d40cf72fd48201ab11f/raw/metadata.json"&lt;/span&gt;

spl-token mint nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt 1
spl-token authorize nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt mint &lt;span class="nt"&gt;--disable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--enable-metadata&lt;/code&gt; flag reserves space for both the metadata pointer and the metadata fields at creation time. You cannot add this later — the account size is fixed when the mint is born.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnzeat9po2va9149ra6yw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnzeat9po2va9149ra6yw.png" alt="NFT Image" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 2 — Grouping NFTs into an on-chain collection
&lt;/h2&gt;

&lt;p&gt;A collection on Solana is just another mint with a &lt;strong&gt;group extension&lt;/strong&gt;. Individual NFTs link back to it with a &lt;strong&gt;member extension&lt;/strong&gt;. Together they replace what would be a &lt;code&gt;collections&lt;/code&gt; table joined to an &lt;code&gt;nfts&lt;/code&gt; table in Web2.&lt;/p&gt;

&lt;p&gt;Created a collection mint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 0 &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt; &lt;span class="nt"&gt;--enable-group&lt;/span&gt;

spl-token initialize-metadata 2MEg3Vqbaiy1gNRciiy8f33eqVrenLXj26NDjHPbr7kB &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"Solana Sketchbook"&lt;/span&gt; &lt;span class="s2"&gt;"SKTCH"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://gist.githubusercontent.com/janvinsha/b477ebe4dda46b0ef03895c4ea930a46/raw/f29222bcaff0d4979fe7ebb610a00bb97a8418ec/collection.json"&lt;/span&gt;

spl-token initialize-group 2MEg3Vqbaiy1gNRciiy8f33eqVrenLXj26NDjHPbr7kB 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then created two member NFTs that point back to it:&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="c"&gt;# Member #1&lt;/span&gt;
spl-token &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 0 &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt; &lt;span class="nt"&gt;--enable-member&lt;/span&gt;

spl-token initialize-metadata 9QiJaKzNRUuzw1jowpoQzYWW6KuEcgfZrzrpu7DKWMym &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"Sketch #1"&lt;/span&gt; &lt;span class="s2"&gt;"SK1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://gist.githubusercontent.com/janvinsha/3412c5d4e92b6de9a2ed82337ecafc44/raw/99359fc62ffd0480b6a52ee1ad4048ecba4ae61c/nft.json"&lt;/span&gt;
spl-token initialize-member 9QiJaKzNRUuzw1jowpoQzYWW6KuEcgfZrzrpu7DKWMym 2MEg3Vqbaiy1gNRciiy8f33eqVrenLXj26NDjHPbr7kB

&lt;span class="c"&gt;# Member #2&lt;/span&gt;
spl-token &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 0 &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt; &lt;span class="nt"&gt;--enable-member&lt;/span&gt;

spl-token initialize-metadata 32KYgijQ8cQmAko7PDBo63BpCG4nby8XLksGKrehXSsy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"Sketch #2"&lt;/span&gt; &lt;span class="s2"&gt;"SK2"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://gist.githubusercontent.com/janvinsha/3412c5d4e92b6de9a2ed82337ecafc44/raw/99359fc62ffd0480b6a52ee1ad4048ecba4ae61c/nft.json"&lt;/span&gt;
spl-token initialize-member 32KYgijQ8cQmAko7PDBo63BpCG4nby8XLksGKrehXSsy 2MEg3Vqbaiy1gNRciiy8f33eqVrenLXj26NDjHPbr7kB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;initialize-member&lt;/code&gt; command writes the collection address into the member mint's extension data. Wallets and explorers walk that pointer the same way a SQL query follows a foreign key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3 — Auditing everything on chain
&lt;/h2&gt;

&lt;p&gt;After building, I read everything back using &lt;code&gt;spl-token display&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token display nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt
spl-token display 2MEg3Vqbaiy1gNRciiy8f33eqVrenLXj26NDjHPbr7kB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output shows every extension as a separate block — metadata, group, member — all parsed from raw account bytes. No off-chain index required.&lt;/p&gt;

&lt;p&gt;I also confirmed the parent reference. The &lt;code&gt;Group address&lt;/code&gt; field on each member mint matched the collection mint address byte-for-byte. That is what "verifiable provenance" means — two byte arrays comparing equal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 4 — Mutating metadata live on devnet
&lt;/h2&gt;

&lt;p&gt;Since I held the update authority, I renamed the NFT, added a custom field, then removed it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token update-metadata nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt name &lt;span class="s2"&gt;"Field Notes"&lt;/span&gt;
spl-token update-metadata nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt rarity legendary
spl-token update-metadata nftChe7XoDvsFDkQmavkhQhPv1T9n3pfxKm2A48E9dt rarity &lt;span class="nt"&gt;--remove&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcq90nnrl7wxu8s5jh6q4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcq90nnrl7wxu8s5jh6q4.png" alt="Mutated metadata" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each command is a single transaction. The name and URI move instantly on-chain. The image those bytes point at (off-chain) is cached aggressively by wallets — a good lesson in the asymmetry between the two layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What surprised me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extensions are permanent.&lt;/strong&gt; Every extension you want must be declared at mint creation. There is no &lt;code&gt;ALTER TABLE&lt;/code&gt; on Solana. If you forget &lt;code&gt;--enable-metadata&lt;/code&gt;, you start over with a new mint. This feels restrictive coming from Web2, but it guarantees that any wallet can trust the account layout without additional verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rent scales with extensions.&lt;/strong&gt; A simple frozen mint is 171 bytes (~0.002 SOL rent). My multi-extension mint with metadata + group + member was 599 bytes (~0.005 SOL). Features cost bytes, and bytes cost SOL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The update authority is powerful.&lt;/strong&gt; Whoever holds the metadata update authority can rename, re-URI, and rewrite any field at any time. On mainnet, this should be a multisig or a revoked key for immutable NFTs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go deeper
&lt;/h2&gt;

&lt;p&gt;The official documentation covers every extension I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.solana-program.com/docs/token-2022/extensions#extensions" rel="noopener noreferrer"&gt;Token Extensions Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.solana-program.com/docs/token-2022/extensions#metadata-pointer" rel="noopener noreferrer"&gt;Metadata Pointer and Token Metadata reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are coming from Web2 and learning Solana, start by minting a single NFT with metadata. Then add a collection. Then mutate something. Each step builds the mental model that an NFT is not magic — it is just a mint with supply 1, decimals 0, and the right extensions.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>100daysofsolana</category>
      <category>solana</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Soulbound Credentials on Solana: Combining Non-Transferable and Permanent Delegate Extensions</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Sun, 28 Jun 2026 07:48:01 +0000</pubDate>
      <link>https://dev.to/blackat/soulbound-credentials-on-solana-combining-non-transferable-and-permanent-delegate-extensions-33b5</link>
      <guid>https://dev.to/blackat/soulbound-credentials-on-solana-combining-non-transferable-and-permanent-delegate-extensions-33b5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A certification you cannot sell, but an authority can revoke.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Web2, credentials follow a specific lifecycle. A coding bootcamp issues you a certificate of completion. You cannot sell it or give it to someone else — it belongs to you. But the issuing institution retains the right to revoke it if they discover fraud or if the credential expires. Professional licenses, employee badges, verified status markers on social platforms — they all work the same way. They are yours to hold, but someone else controls whether they remain valid.&lt;/p&gt;

&lt;p&gt;Solana's Token Extensions Program lets you encode this exact pattern at the protocol level using two extensions: &lt;strong&gt;non-transferable&lt;/strong&gt; and &lt;strong&gt;permanent delegate&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;non-transferable extension&lt;/strong&gt; locks tokens in place. Once minted to a wallet, they cannot be moved, sold, or traded. The &lt;strong&gt;permanent delegate extension&lt;/strong&gt; gives your authority keypair the ability to burn tokens from any holder's account without their signature. Combined, they create a credential that is soulbound to the holder but revocable by the issuer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building it
&lt;/h2&gt;

&lt;p&gt;Here is the exact sequence I ran:&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="c"&gt;# Step 1: Create the mint with all three extensions&lt;/span&gt;
&lt;span class="c"&gt;# --enable-non-transferable locks tokens in place&lt;/span&gt;
&lt;span class="c"&gt;# --enable-permanent-delegate lets the authority burn from anywhere&lt;/span&gt;
&lt;span class="c"&gt;# --enable-metadata reserves space for the credential name&lt;/span&gt;
spl-token &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-non-transferable&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-permanent-delegate&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt;

&lt;span class="c"&gt;# Step 2: Give the credential a name and symbol&lt;/span&gt;
spl-token initialize-metadata &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"Solana Dev Credential"&lt;/span&gt; &lt;span class="s2"&gt;"CRED"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://example.com/credential.json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

&lt;span class="c"&gt;# Step 3: Create a recipient account and mint 1 credential&lt;/span&gt;
&lt;span class="nv"&gt;RECIPIENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;solana-keygen pubkey ~/recipient-wallet.json&lt;span class="si"&gt;)&lt;/span&gt;
spl-token create-account &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="nt"&gt;--owner&lt;/span&gt; &lt;span class="nv"&gt;$RECIPIENT&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--fee-payer&lt;/span&gt; ~/.config/solana/id.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
spl-token mint &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 1 &lt;span class="nt"&gt;--recipient-owner&lt;/span&gt; &lt;span class="nv"&gt;$RECIPIENT&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

&lt;span class="c"&gt;# Step 4: Try to transfer — this FAILS (soulbound enforced)&lt;/span&gt;
spl-token transfer &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 1 &lt;span class="o"&gt;[&lt;/span&gt;THIRD_PARTY] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--owner&lt;/span&gt; ~/recipient-wallet.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--fee-payer&lt;/span&gt; ~/.config/solana/id.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;span class="c"&gt;# Error: "Transfer is disabled for this mint"&lt;/span&gt;

&lt;span class="c"&gt;# Step 5: Revoke the credential using permanent delegate&lt;/span&gt;
spl-token burn &lt;span class="o"&gt;[&lt;/span&gt;RECIPIENT_TOKEN_ACCOUNT] 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--owner&lt;/span&gt; ~/.config/solana/id.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

&lt;span class="c"&gt;# Step 6: Verify balance is now 0&lt;/span&gt;
spl-token balance &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="nt"&gt;--owner&lt;/span&gt; &lt;span class="nv"&gt;$RECIPIENT&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;span class="c"&gt;# Output: 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The critical moment is Step 4. The CLI returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transfer is disabled for this mint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the non-transferable extension enforcing the soulbound constraint. No smart contract code was written. No custom program was deployed. It is a protocol-level rule that the Solana runtime applies to every transfer involving this mint.&lt;/p&gt;

&lt;p&gt;Then in Step 5, I burned the token from the recipient's account using only my authority signature — not the recipient's. This is the permanent delegate extension in action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspecting the final mint
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token display &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output shows all three extensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Extensions&lt;/span&gt;
  &lt;span class="s"&gt;Permanent delegate&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164&lt;/span&gt;
  &lt;span class="s"&gt;Non-transferable&lt;/span&gt;
  &lt;span class="s"&gt;Metadata Pointer&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;Metadata&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Solana Dev Credential&lt;/span&gt;
    &lt;span class="na"&gt;Symbol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CRED&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What surprised me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The permanent delegate cannot be changed.&lt;/strong&gt; Once you enable it, that authority is locked for the life of the mint. You cannot transfer it to a multisig later, you cannot revoke it, you cannot rotate the key. If the permanent delegate key is compromised, the attacker can burn every token in existence. This is the most dangerous extension in the Token Extensions suite — use it deliberately and secure the key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The combination maps perfectly to real-world credentials.&lt;/strong&gt; The non-transferable extension prevents secondary markets (no selling certifications). The permanent delegate enables revocation (no lifetime credentials). The metadata makes the credential self-describing (anyone can inspect what it represents without an external database).&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to go deeper
&lt;/h2&gt;

&lt;p&gt;This pattern is immediately useful for DAOs issuing membership badges, protocols granting contributor status, or education platforms distributing certificates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.solana-program.com/docs/token-2022/extensions#non-transferable-tokens" rel="noopener noreferrer"&gt;Non-Transferable Extension Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.solana-program.com/docs/token-2022/extensions#permanent-delegate" rel="noopener noreferrer"&gt;Permanent Delegate Extension Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spl.solana.com/token-2022/extensions" rel="noopener noreferrer"&gt;Token Extensions Overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are building a credential system on Solana, this combination of extensions is the closest thing to a "standard" pattern the protocol offers. Use it. But protect that permanent delegate key like a root password.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>100daysofsolana</category>
      <category>solana</category>
    </item>
    <item>
      <title>Three Token Extension Combinations I Tried This Week (and What Each Is Good For)</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Sun, 28 Jun 2026 07:27:57 +0000</pubDate>
      <link>https://dev.to/blackat/three-token-extension-combinations-i-tried-this-week-and-what-each-is-good-for-51kf</link>
      <guid>https://dev.to/blackat/three-token-extension-combinations-i-tried-this-week-and-what-each-is-good-for-51kf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;One bare token, one feature-rich, one compliance-gated — here is what I learned.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Last week I knew how to mint a basic SPL token. This week I learned that Solana's Token Extensions Program lets you build tokens with protocol-level features — transfer fees, interest accrual, metadata, frozen accounts, soulbound restrictions, and revocable credentials — without writing a single line of on-chain code.&lt;/p&gt;

&lt;p&gt;I spent three days building three different tokens, each with a different combination of extensions. Here is what I built, what each combination is good for, and what surprised me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Combination 1: Interest-Bearing Token (Savings Accounts)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extensions used:&lt;/strong&gt; Interest-bearing (500 basis points = 5%)&lt;/p&gt;

&lt;p&gt;The simplest extension: continuous compounding interest stored as a rate and timestamp. No new tokens are minted. Instead, wallets and applications calculate an adjusted display balance based on elapsed time.&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="c"&gt;# Create a token with 5% annual interest&lt;/span&gt;
spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--interest-rate&lt;/span&gt; 500

&lt;span class="c"&gt;# Create an account and mint tokens&lt;/span&gt;
spl-token create-account &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
spl-token mint &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 1000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

&lt;span class="c"&gt;# Inspect the interest-bearing configuration&lt;/span&gt;
spl-token display &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;spl-token display&lt;/code&gt; output shows a &lt;code&gt;Current rate: 500bps&lt;/code&gt; and a &lt;code&gt;Rate authority&lt;/code&gt;. The raw balance stays 1000, but the UI amount ticks upward over time using &lt;code&gt;A = P * e^(rt)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good for:&lt;/strong&gt; Yield-bearing tokens, savings accounts, staking receipts. Any situation where the balance should grow over time without a background job minting every second.&lt;/p&gt;




&lt;h2&gt;
  
  
  Combination 2: Multi-Extension Token (Transfer Fees + Interest + Metadata)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extensions used:&lt;/strong&gt; Transfer fees (100bps, max 5 tokens), Interest-bearing (5bps), Metadata, Metadata Pointer&lt;/p&gt;

&lt;p&gt;This is the Swiss Army knife. One token that charges fees on transfers, displays interest-adjusted balances, and carries its own name and symbol on-chain.&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="c"&gt;# Create the mint with all three extensions&lt;/span&gt;
spl-token &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-basis-points&lt;/span&gt; 100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-maximum-fee&lt;/span&gt; 500 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--interest-rate&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt;

&lt;span class="c"&gt;# Initialize metadata&lt;/span&gt;
spl-token initialize-metadata &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"ArcCoin"&lt;/span&gt; &lt;span class="s2"&gt;"ARC"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/CompressedCoil/metadata.json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

&lt;span class="c"&gt;# Mint and transfer to see the fee&lt;/span&gt;
spl-token create-account &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS]
spl-token mint &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 1000
spl-token transfer &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 100 &lt;span class="o"&gt;[&lt;/span&gt;RECIPIENT] &lt;span class="nt"&gt;--expected-fee&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I transferred 100 tokens, the recipient received 99. The 1-token fee was withheld in a special balance that the mint authority can harvest later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good for:&lt;/strong&gt; Revenue-generating tokens, ecosystem currencies, branded tokens that need on-chain identity. The extension model means all features work independently without conflicting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Combination 3: Compliance-Gated Token (Default Frozen)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extensions used:&lt;/strong&gt; Default Account State (Frozen), Freeze authority&lt;/p&gt;

&lt;p&gt;Every token account starts frozen. No one can send, receive, or burn until the freeze authority explicitly thaws them. This is protocol-level access control — no frontend bug can bypass it.&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="c"&gt;# Create a mint where all accounts start frozen&lt;/span&gt;
spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-freeze&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--default-account-state&lt;/span&gt; frozen

&lt;span class="c"&gt;# Try to mint — this FAILS because the default account is frozen&lt;/span&gt;
spl-token mint &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 100
&lt;span class="c"&gt;# Error: Account is frozen&lt;/span&gt;

&lt;span class="c"&gt;# Thaw the account, then mint succeeds&lt;/span&gt;
spl-token thaw &lt;span class="o"&gt;[&lt;/span&gt;YOUR_TOKEN_ACCOUNT]
spl-token mint &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 100  &lt;span class="c"&gt;# succeeds&lt;/span&gt;

&lt;span class="c"&gt;# Try to send to a frozen account — FAILS&lt;/span&gt;
spl-token transfer &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] 50 &lt;span class="o"&gt;[&lt;/span&gt;FROZEN_ACCOUNT]
&lt;span class="c"&gt;# Error: destination account is frozen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the sender and the recipient must be thawed. This creates a fully permissioned system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good for:&lt;/strong&gt; Regulated assets, stablecoins with compliance requirements, security tokens, loyalty programs where accounts need approval before activation.&lt;/p&gt;




&lt;h2&gt;
  
  
  What surprised me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extensions cost real SOL.&lt;/strong&gt; Each extension adds bytes to the mint account. My interest-bearing mint was 222 bytes (0.002436 SOL rent). The multi-extension mint was 599 bytes (0.005060 SOL). The simple frozen mint was 171 bytes (0.002081 SOL). The difference between the simplest and the most complex was 2.4x in rent cost. When designing a token, every extension is a deliberate tradeoff between features and cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You cannot add extensions after minting.&lt;/strong&gt; This was the hardest mental shift from Web2. In Stripe, you can add a new product feature anytime. On Solana, the account size is fixed at creation. If you forgot to enable metadata, you cannot add it later — you have to create a new mint and migrate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go deeper
&lt;/h2&gt;

&lt;p&gt;The official documentation covers every extension with implementation details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://spl.solana.com/token-2022/extensions" rel="noopener noreferrer"&gt;Token Extensions Overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try combining extensions that fit your use case. The most powerful pattern I found was frozen-by-default + transfer fees + metadata — a token that enforces compliance, generates revenue, and identifies itself, all without a single line of smart contract code.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>100daysofsolana</category>
      <category>solana</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Reading a Token Mint: How I Learned to Inspect On-Chain Configuration</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Sun, 28 Jun 2026 07:06:49 +0000</pubDate>
      <link>https://dev.to/blackat/reading-a-token-mint-how-i-learned-to-inspect-on-chain-configuration-11fi</link>
      <guid>https://dev.to/blackat/reading-a-token-mint-how-i-learned-to-inspect-on-chain-configuration-11fi</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In Web2 you read config files. On Solana you read accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you join a new team in Web2, your first task is reading configuration files. You open &lt;code&gt;package.json&lt;/code&gt;, environment variables, database schemas. You do not start changing things until you understand what is already there. Reading and interpreting existing configuration is a core skill that separates developers who break things from developers who improve things.&lt;/p&gt;

&lt;p&gt;On Solana, that same skill applies to on-chain accounts. Every token mint stores its configuration as public account data. The &lt;code&gt;spl-token display&lt;/code&gt; command is your &lt;code&gt;cat package.json&lt;/code&gt; — it decodes raw bytes into human-readable configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The command
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token display &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb&lt;/code&gt; flag tells the CLI to read from the Token Extensions program (Token-2022), not the original SPL Token program.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the output tells you
&lt;/h2&gt;

&lt;p&gt;Here is the output from an interest-bearing mint I created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SPL Token Mint
  Address: 7CjQNSGCiXuYAZu6UNn2xGXPEa5wxc1oxLQoj198jFdy
  Program: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
  Supply: 0
  Decimals: 9
  Mint authority: 2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164
Extensions
  Interest-bearing:
    Current rate: 500bps
    Average rate: 500bps
    Rate authority: 2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each extension occupies its own block. The Interest-bearing block tells me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current rate is 500 basis points (5%)&lt;/li&gt;
&lt;li&gt;The rate authority is a specific wallet address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the output from a multi-extension mint (transfer fees + interest + metadata):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Extensions&lt;/span&gt;
  &lt;span class="s"&gt;Interest-bearing&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Current rate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5bps&lt;/span&gt;
    &lt;span class="na"&gt;Rate authority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164&lt;/span&gt;
  &lt;span class="na"&gt;Transfer fees&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Current fee&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100bps&lt;/span&gt;
    &lt;span class="na"&gt;Current maximum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50000&lt;/span&gt;
    &lt;span class="na"&gt;Config authority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164&lt;/span&gt;
    &lt;span class="na"&gt;Withdrawal authority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164&lt;/span&gt;
  &lt;span class="na"&gt;Metadata Pointer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Authority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Cd1SqwosBfgoo8UrxBDBFquZRTt11Cmh1bcPDemn164&lt;/span&gt;
  &lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ArcCoin&lt;/span&gt;
    &lt;span class="na"&gt;Symbol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ARC&lt;/span&gt;
    &lt;span class="na"&gt;URI&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://raw.githubusercontent.com/...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How to compare account sizes
&lt;/h2&gt;

&lt;p&gt;Extensions are not free. Each one adds bytes to the account. You can measure this directly:&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="c"&gt;# Get the data size of any mint&lt;/span&gt;
solana account &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="nt"&gt;--output&lt;/span&gt; json | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'"space":[ ]*[0-9]*'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'[0-9]*$'&lt;/span&gt;

&lt;span class="c"&gt;# Calculate the rent cost&lt;/span&gt;
solana rent &lt;span class="o"&gt;[&lt;/span&gt;DATA_SIZE]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I compared three mints and got this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mint Type&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Rent Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default-frozen (1 extension)&lt;/td&gt;
&lt;td&gt;171 bytes&lt;/td&gt;
&lt;td&gt;0.002081 SOL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interest-bearing (1 extension)&lt;/td&gt;
&lt;td&gt;222 bytes&lt;/td&gt;
&lt;td&gt;0.002436 SOL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-extension (3 extensions)&lt;/td&gt;
&lt;td&gt;599 bytes&lt;/td&gt;
&lt;td&gt;0.005060 SOL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The multi-extension mint costs more than double the rent of the simplest. This is not a bug — it is a design tradeoff. More features mean more data, and more data means more SOL to keep the account rent-exempt.&lt;/p&gt;




&lt;h2&gt;
  
  
  What surprised me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You can see every authority.&lt;/strong&gt; The display command shows who controls what — mint authority, freeze authority, rate authority, transfer fee config authority, metadata update authority. Some of these cannot be changed after creation. Reading the configuration before deploying to mainnet is how you avoid painting yourself into a corner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extensions are stored sequentially as TLV entries.&lt;/strong&gt; Each extension uses a type-length-value format. The CLI parses them one by one and displays them as blocks. The order in the output matches the order in the raw account data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go deeper
&lt;/h2&gt;

&lt;p&gt;Being able to read on-chain state is as important as being able to create it. The official docs explain the data model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://spl.solana.com/token-2022" rel="noopener noreferrer"&gt;Token-2022 Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next time you encounter an unfamiliar token on devnet, run &lt;code&gt;spl-token display&lt;/code&gt; on it. You will learn more from reading one real configuration than from ten tutorials.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>100daysofsolana</category>
      <category>solana</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>What Token Extensions Are and Why a Web2 Developer Should Care</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Fri, 26 Jun 2026 06:43:28 +0000</pubDate>
      <link>https://dev.to/blackat/what-token-extensions-are-and-why-a-web2-developer-should-care-996</link>
      <guid>https://dev.to/blackat/what-token-extensions-are-and-why-a-web2-developer-should-care-996</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;You already understand tokens. Extensions are just middleware for your money.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have ever worked with Stripe, you know the pattern. You start with a simple charge: send money from point A to point B. Then you add features — subscriptions, transfer fees, metadata on invoices, compliance checks. Each feature is a separate Stripe product or API call, and wiring them together is your job.&lt;/p&gt;

&lt;p&gt;Solana's Token Extensions Program is the same idea, but at the blockchain protocol level. Instead of bolting features on top of a basic token after creation (which Solana does not allow), you declare every capability upfront, and the runtime enforces it automatically. No smart contract to write. No backend service to maintain. Just configuration flags at creation time.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a token extension?
&lt;/h2&gt;

&lt;p&gt;A token extension is an optional feature you enable when you create a token mint. Under the hood, each extension reserves extra bytes in the mint's on-chain account. Those bytes store configuration — an interest rate, a fee percentage, a metadata URI — and the Solana runtime reads them during every transaction.&lt;/p&gt;

&lt;p&gt;The original SPL Token Program is simple. It stores supply, decimals, and authorities. The Token Extensions Program (&lt;code&gt;TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb&lt;/code&gt;) is a superset. It stores everything the original does, plus additional data for each extension you enable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extensions map directly to Web2 concepts
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Extension&lt;/th&gt;
&lt;th&gt;Web2 Analogy&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Transfer Fees&lt;/td&gt;
&lt;td&gt;Payment processor fee&lt;/td&gt;
&lt;td&gt;Deducts a % on every transfer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interest-Bearing&lt;/td&gt;
&lt;td&gt;Savings account APY&lt;/td&gt;
&lt;td&gt;Displays time-adjusted balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metadata&lt;/td&gt;
&lt;td&gt;Product catalog entry&lt;/td&gt;
&lt;td&gt;Stores name, symbol, URI on-chain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default Account State&lt;/td&gt;
&lt;td&gt;KYC gating&lt;/td&gt;
&lt;td&gt;All accounts start frozen; you thaw approved users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-Transferable&lt;/td&gt;
&lt;td&gt;Professional license&lt;/td&gt;
&lt;td&gt;Tokens cannot be sold or transferred&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permanent Delegate&lt;/td&gt;
&lt;td&gt;Admin revoke power&lt;/td&gt;
&lt;td&gt;Issuer can burn tokens from any holder&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  A concrete example
&lt;/h2&gt;

&lt;p&gt;Here is the exact command I ran to create a token with transfer fees, interest-bearing, and metadata — all in one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-basis-points&lt;/span&gt; 100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-maximum-fee&lt;/span&gt; 500 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--interest-rate&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single command does what would take three separate services in Web2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transfer fees&lt;/strong&gt; (like Stripe taking 1%): 100 basis points = 1%, capped at 5 tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interest-bearing&lt;/strong&gt; (like a savings account): 5% continuous compounding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata&lt;/strong&gt; (like a product database entry): space reserved for name, symbol, and URI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After creating the mint, I added the metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token initialize-metadata &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"ArcCoin"&lt;/span&gt; &lt;span class="s2"&gt;"ARC"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://example.com/metadata.json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I inspected everything with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token display &lt;span class="o"&gt;[&lt;/span&gt;MINT_ADDRESS] &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output showed each extension as a separate block — TransferFeeConfig, Interest-bearing, Metadata Pointer, Metadata — all living in the same on-chain account.&lt;/p&gt;




&lt;h2&gt;
  
  
  What surprised me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extensions are additive in cost.&lt;/strong&gt; Each one adds bytes to the mint account, and bytes require SOL for rent-exempt status. My bare mint (default-frozen only) was 171 bytes. Adding interest-bearing bumped it to 222 bytes. The multi-extension mint with transfer fees + metadata + interest was 599 bytes — costing over 2x the rent.&lt;/p&gt;

&lt;p&gt;In Web2 terms: extensions are like choosing between a lightweight microservice and a feature-rich monolith. Both have their place, but you should make the choice deliberately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to go deeper
&lt;/h2&gt;

&lt;p&gt;The official Solana documentation covers every extension in detail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://spl.solana.com/token-2022/extensions" rel="noopener noreferrer"&gt;Token Extensions Overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are a Web2 developer curious about Solana, start with the extensions that map to problems you already solve — transfer fees, metadata, access control. You will recognize every one of them.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>100daysofsolana</category>
      <category>solana</category>
    </item>
    <item>
      <title>Transfer Fees, Metadata, and Soulbound Tokens: A Tour of Solana Token Extensions</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Sun, 24 May 2026 13:48:00 +0000</pubDate>
      <link>https://dev.to/blackat/transfer-fees-metadata-and-soulbound-tokens-a-tour-of-solana-token-extensions-41mp</link>
      <guid>https://dev.to/blackat/transfer-fees-metadata-and-soulbound-tokens-a-tour-of-solana-token-extensions-41mp</guid>
      <description>&lt;p&gt;If you are a Web2 developer and the phrase "on-chain token" sounds like something you need a PhD to build, this post is for you. I went from zero to creating tokens with metadata, transfer fees, and non-transferable locks using nothing more than CLI commands. Here is exactly how I did it and what surprised me along the way.&lt;/p&gt;

&lt;p&gt;Before starting this challenge, I had never created a token on any blockchain. I understood the basics of Solana — sending SOL, reading balances, using the CLI — but the idea of creating my own digital asset felt like advanced territory. The goal was simple: learn what Solana tokens can do by building them, one step at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Create a Basic Mint
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a Mint account — the on-chain definition of your token. It stores supply, decimals, and authority. The mint holds no tokens by itself. To hold a balance you need a token account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-account YOUR_MINT_ADDRESS
spl-token mint YOUR_MINT_ADDRESS 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mint is the global token definition. Each token account is a wallet's balance for that specific token. In Web2 terms, the mint is your currency definition and each token account is a user's balance row. The SPL Token Program handles all the hard parts for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Add On-Chain Metadata
&lt;/h2&gt;

&lt;p&gt;A mint address with no name is just a string. The original SPL Token Program does not support on-chain metadata. The Token Extensions Program (&lt;code&gt;TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb&lt;/code&gt;) stores metadata — name, symbol, URI — directly on the mint account, so everything is in one place instead of requiring a separate lookup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 6

spl-token initialize-metadata YOUR_MINT_ADDRESS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"100DaysCoin"&lt;/span&gt; &lt;span class="s2"&gt;"HUNDO"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--enable-metadata&lt;/code&gt; flag activates the metadata extension at mint creation. The &lt;code&gt;initialize-metadata&lt;/code&gt; command writes the name, symbol, and URI. The URI points to a JSON file with additional details like description and image.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Attach a Transfer Fee
&lt;/h2&gt;

&lt;p&gt;Instead of building middleware to collect fees on every transfer, the transfer fee extension enforces collection at the program level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-basis-points&lt;/span&gt; 100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-maximum-fee&lt;/span&gt; 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;100 basis points = 1%. Every transfer of this token automatically withholds 1% in the recipient's token account. The recipient cannot spend withheld tokens. Only the withdraw withheld authority (the wallet that created the mint) can collect them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token transfer YOUR_MINT_ADDRESS 100 RECIPIENT &lt;span class="nt"&gt;--expected-fee&lt;/span&gt; 1
spl-token withdraw-withheld-tokens YOUR_ACCOUNT RECIPIENT_ACCOUNT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--expected-fee&lt;/code&gt; flag is a safety check — the transfer only succeeds if the calculated fee matches what you specified. The withheld tokens accumulate in the recipient's account until the authority sweeps them out.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Full Lifecycle in One Session
&lt;/h2&gt;

&lt;p&gt;Combining multiple extensions on a single mint works in one flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-basis-points&lt;/span&gt; 200 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transfer-fee-maximum-fee&lt;/span&gt; 5000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-metadata&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--decimals&lt;/span&gt; 9

spl-token initialize-metadata YOUR_MINT_ADDRESS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"ReinforceCoin"&lt;/span&gt; &lt;span class="s2"&gt;"RFC"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/CompressedCoil/metadata.json"&lt;/span&gt;

spl-token create-account YOUR_MINT_ADDRESS
spl-token mint YOUR_MINT_ADDRESS 1000
spl-token transfer &lt;span class="nt"&gt;--fund-recipient&lt;/span&gt; YOUR_MINT_ADDRESS 100 RECIPIENT &lt;span class="nt"&gt;--expected-fee&lt;/span&gt; 2 &lt;span class="nt"&gt;--allow-unfunded-recipient&lt;/span&gt;
spl-token withdraw-withheld-tokens YOUR_ACCOUNT RECIPIENT_ACCOUNT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two extensions (metadata + transfer fee) configured on the same mint. No smart contract needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Create a Non-Transferable (Soulbound) Token
&lt;/h2&gt;

&lt;p&gt;Some tokens should never be transferred — verified badges, course certificates, KYC credentials. The non-transferable extension blocks all transfers at the protocol level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token create-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-non-transferable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After minting, attempting a transfer returns an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token transfer YOUR_MINT_ADDRESS 5 RECIPIENT &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unfunded-recipient&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Program log: Transfer is disabled for this mint
Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb failed: custom program error: 0x25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The token program itself rejects the instruction. No client or program can override it. Burning still works — the holder can destroy tokens they own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spl-token burn YOUR_TOKEN_ACCOUNT 3 &lt;span class="nt"&gt;--program-id&lt;/span&gt; TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Non-transferable does not mean non-destructible. The holder controls their own account but cannot move tokens to another wallet.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Surprised Me
&lt;/h2&gt;

&lt;p&gt;Two things did not work the way I expected.&lt;/p&gt;

&lt;p&gt;First, extensions must be configured when the mint is first created. You cannot add a transfer fee or metadata extension later. You have to decide how your token behaves before it exists, which is the opposite of how I would approach it in Web2.&lt;/p&gt;

&lt;p&gt;Second, the non-transferable failure was more satisfying than I expected. I ran the transfer command fully expecting tokens to move. Instead, the blockchain returned &lt;code&gt;Transfer is disabled for this mint&lt;/code&gt;. The error was clear and no flag or workaround could bypass it. That is when it clicked: this is a protocol-level lock, not a convention.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I plan to build a token with real utility — combining metadata and transfer fees into something that could serve as a community reward token. If you are following the #100DaysOfSolana challenge or exploring Solana tokens on your own, start with the basic mint, then add one extension at a time. The CLI makes it easy to experiment without writing any smart contract code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://solana.com/docs/core/tokens" rel="noopener noreferrer"&gt;Tokens on Solana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spl.solana.com/token-2022/extensions" rel="noopener noreferrer"&gt;Token &amp;amp; Transfer Fee Extensions Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://solana.com/developers/guides/token-extensions/non-transferable" rel="noopener noreferrer"&gt;Non-Transferable Tokens Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://solana.com/developers/guides/token-extensions/getting-started" rel="noopener noreferrer"&gt;SPL Token Basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>solana</category>
      <category>100daysofsolana</category>
    </item>
    <item>
      <title>🗄️Solana Accounts Are Just Files — and Programs Are Just People Who Can Read Them</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Tue, 19 May 2026 11:43:48 +0000</pubDate>
      <link>https://dev.to/blackat/solana-accounts-are-just-files-and-programs-are-just-people-who-can-read-them-phc</link>
      <guid>https://dev.to/blackat/solana-accounts-are-just-files-and-programs-are-just-people-who-can-read-them-phc</guid>
      <description>&lt;h3&gt;
  
  
  The analogy that rewired my brain - The Filing Cabinet
&lt;/h3&gt;

&lt;p&gt;Imagine a room filled with filing cabinets. Each drawer has a random label. Inside each drawer is a folder.&lt;/p&gt;

&lt;p&gt;On the front of the folder is written:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Owner&lt;/strong&gt; — who can open and change the contents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Executable&lt;/strong&gt; — is this a set of instructions or just data?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt; — the actual contents (a number, JSON, raw bytes)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyone can walk up to any drawer and read the label. Only the &lt;strong&gt;Owner&lt;/strong&gt; can modify what's inside.&lt;/p&gt;

&lt;p&gt;This room is Solana. The drawers are &lt;strong&gt;accounts&lt;/strong&gt;. The folders are &lt;strong&gt;account data&lt;/strong&gt;. The owners are &lt;strong&gt;programs&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 What This Explains
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;There is no "users table."&lt;/strong&gt; Your wallet is a file owned by the System Program. The data inside is one number — your SOL balance. "Sending SOL" means authorizing the System Program to decrease the number in your file and increase it in someone else's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can't modify every account.&lt;/strong&gt; Only the owning program can. This isn't a restriction — it's the entire security model. If anyone could modify any account, the network would be chaos. The runtime enforces ownership at the validator level, not in application code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Programs are stateless.&lt;/strong&gt; A program is like a person who knows how to read specific file formats. The System Program reads simple balance files. The Token Program reads mint metadata and token balances. Your custom program reads whatever format you define. The program itself stores nothing — state lives in separate accounts it owns. Think of it like a web server (the program) that reads and writes to a database (data accounts) rather than keeping everything in memory.&lt;/p&gt;




&lt;h2&gt;
  
  
  📋 The Four Fields
&lt;/h2&gt;

&lt;p&gt;Every account on Solana has the same structure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lamports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The SOL balance (always in lamports — 1 SOL = 1,000,000,000)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Raw bytes — file contents, whatever the owner program decides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Owner&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The program address that controls this account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Executable&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Is this file a program (code) or just data?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's what they look like in practice:&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="nv"&gt;$ &lt;/span&gt;solana account TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA

Public Key: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Balance: 0.00028296 SOL
Owner: BPFLoaderUpgradeab1e11111111111111111111111
Executable: &lt;span class="nb"&gt;true
&lt;/span&gt;Data: &lt;span class="o"&gt;(&lt;/span&gt;compiled program bytecode&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A wallet, a token program, a sysvar — all use the same four fields. Different values. That's the entire state model.&lt;/p&gt;




&lt;h2&gt;
  
  
  💰 Rent Exemption
&lt;/h2&gt;

&lt;p&gt;Keeping a file on-chain costs storage space. Solana charges rent — a small deposit proportional to your account's data size. Deposit enough (~2 years worth) and your account is "rent-exempt" — it stays forever.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;solana rent 0     &lt;span class="c"&gt;# 0.00089088 SOL (basic account)&lt;/span&gt;
solana rent 100   &lt;span class="c"&gt;# cost for 100 bytes of data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a basic wallet with no extra data, it's roughly 0.00089 SOL. This deposit is refundable when you close the account. Not a bug — it's the price of storing data in a globally replicated system.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 Three Things That Suddenly Make Sense
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Ownership rules.&lt;/strong&gt; Only the owner program can modify an account's data or deduct lamports. Anyone can credit lamports to any writable account. Simple, powerful, enforced by every validator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. PDAs.&lt;/strong&gt; Sometimes a program needs a file it controls but no private key can sign for it. Program-Derived Addresses are deterministic drawer labels — computed from program ID + seeds — that only the program can authorize. Like a combination lock where only the program knows the combination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Composability.&lt;/strong&gt; Every file declares its owner. Anyone can read. Only the owner can write. Programs chain together: Program A reads a Token account to check your balance, then asks the System Program to move SOL. All in one atomic transaction. That's composability.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Why This Matters
&lt;/h2&gt;

&lt;p&gt;Before this analogy clicked, every Solana concept felt like learning a new language from scratch. After it clicked, the documentation became readable. Error messages became decipherable. I stopped asking "what is an account?" and started asking "what kind of file is this, and who owns it?"&lt;/p&gt;

&lt;p&gt;If you're coming from Web2 and struggling with Solana's account model, try the filing cabinet. You'll know it clicked when you stop thinking about tables and start thinking about drawers.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is the final post in a 4-part series on unlearning Web2 mental models for Solana:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://dev.to/blackat/solana-is-a-public-spreadsheet-not-your-private-database-424h"&gt;📊 Solana Is a Public Spreadsheet — Not Your Private Database&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://dev.to/blackat/the-connect-wallet-button-replaced-my-entire-auth-system-330k"&gt;🔌 The "Connect Wallet" Button Replaced My Entire Auth System&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://dev.to/blackat/a-solana-transaction-is-a-signed-check-not-an-api-request-1p8b"&gt;✍️ A Solana Transaction Is a Signed Check — Not an API Request&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;You're reading it.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/100-days-of-solana"&gt;100 Days of Solana Writing Challenge&lt;/a&gt;, running from &lt;strong&gt;15 May to 22 May&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>100daysofsolana</category>
      <category>solana</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>✍️ A Solana Transaction Is a Signed Check — Not an API Request</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Tue, 19 May 2026 11:24:11 +0000</pubDate>
      <link>https://dev.to/blackat/a-solana-transaction-is-a-signed-check-not-an-api-request-1p8b</link>
      <guid>https://dev.to/blackat/a-solana-transaction-is-a-signed-check-not-an-api-request-1p8b</guid>
      <description>&lt;p&gt;&lt;em&gt;When I started writing code that sends SOL, I treated transactions like API calls. Construct a payload, POST it to the network, wait for a 200 OK. That mental model worked — until it didn't.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Then I realized: &lt;strong&gt;a Solana transaction isn't a request. It's a signed check.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 The Analogy
&lt;/h2&gt;

&lt;p&gt;Think of writing a physical check. You fill in who gets paid and how much. You sign it. Someone deposits it. The bank processes it — either the money moves or the check bounces.&lt;/p&gt;

&lt;p&gt;A Solana transaction works the same way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You write the instruction&lt;/strong&gt; — "Pay 0.1 SOL from my account to this address"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You sign it&lt;/strong&gt; — with your private key (like signing the check)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You submit it&lt;/strong&gt; — to the network (like depositing the check)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The network processes it&lt;/strong&gt; — atomically, all or nothing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The check analogy breaks down in one important way though: &lt;strong&gt;in Solana, you pay the processing fee even if the check bounces.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ The Part That Surprised Me
&lt;/h2&gt;

&lt;p&gt;I crafted a transaction sending 500 SOL from a wallet that only had 2. I disabled preflight simulation so it would reach the network. It failed, obviously. But the 5,000 lamport fee was still deducted.&lt;/p&gt;

&lt;p&gt;This is fundamentally different from Web2. A failed HTTP request costs you nothing — the server returns an error and you move on. On Solana, validators executed your instruction, ran your program, determined the outcome, and included the result in a block. That work consumed compute resources, and validators get paid regardless of the outcome.&lt;/p&gt;

&lt;p&gt;I covered the technical details — building a transfer tool with commitment tracking, polling for confirmation, forcing failures — in -&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/blackat/my-deep-dive-into-solana-transactions-shifting-the-web2-perspective-2123" class="crayons-story__hidden-navigation-link"&gt;⚓My Deep Dive into Solana Transactions: Shifting the Web2 Perspective&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/blackat" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" alt="blackat profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/blackat" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Vinay
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Vinay
                
              
              &lt;div id="story-author-preview-content-3645081" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/blackat" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Vinay&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/blackat/my-deep-dive-into-solana-transactions-shifting-the-web2-perspective-2123" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 10&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/blackat/my-deep-dive-into-solana-transactions-shifting-the-web2-perspective-2123" id="article-link-3645081"&gt;
          ⚓My Deep Dive into Solana Transactions: Shifting the Web2 Perspective
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/100daysofsolana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;100daysofsolana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/solana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;solana&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/blackat/my-deep-dive-into-solana-transactions-shifting-the-web2-perspective-2123" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/blackat/my-deep-dive-into-solana-transactions-shifting-the-web2-perspective-2123#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;But the economic lesson is what stuck with me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every transaction is an economic event.&lt;/strong&gt; It consumes network resources. It has a cost. You pay for execution, not just success.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ What This Changes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Simulate before you send.&lt;/strong&gt; The &lt;code&gt;skipPreflight&lt;/code&gt; flag exists for edge cases, not everyday development. Most failures can be caught locally — insufficient balance, wrong account ownership, expired blockhash. Check everything before you submit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failed transactions are learning tools.&lt;/strong&gt; The program logs in a failed tx show you exactly where execution stopped, how much compute was consumed, and what error the program returned. I've learned more from forced failures than from successful transfers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atomicity is built in, not bolted on.&lt;/strong&gt; If a transaction has three instructions and instruction 2 fails, instructions 1 and 3 are rolled back too. The fee is still charged. In Web2, you'd write try/catch blocks and compensation logic. On Solana, the runtime guarantees atomicity — but you pay either way.&lt;/p&gt;




&lt;p&gt;I wrote about the transaction anatomy -&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" class="crayons-story__hidden-navigation-link"&gt;Understanding Solana's transaction anatomy&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/blackat" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" alt="blackat profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/blackat" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Vinay
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Vinay
                
              
              &lt;div id="story-author-preview-content-3620611" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/blackat" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Vinay&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" id="article-link-3620611"&gt;
          Understanding Solana's transaction anatomy
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/100daysofsolana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;100daysofsolana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/solana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;solana&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;br&gt;
 — signatures, blockhashes, account keys, compiled instructions — and walked through a CLI transfer - &lt;br&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" class="crayons-story__hidden-navigation-link"&gt;Sending Your First SOL Transfer (Devnet, via CLI)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/blackat" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" alt="blackat profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/blackat" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Vinay
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Vinay
                
              
              &lt;div id="story-author-preview-content-3620076" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/blackat" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Vinay&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" id="article-link-3620076"&gt;
          Sending Your First SOL Transfer (Devnet, via CLI)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/100daysofsolana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;100daysofsolana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/solana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;solana&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;7&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;step by step in earlier posts. But the mental model upgrade is simpler than any of those details:&lt;/p&gt;

&lt;p&gt;Don't think of a transaction as a request you send. Think of it as a check you sign.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next: &lt;a href="https://dev.to/blackat/solana-accounts-are-just-files-and-programs-are-just-people-who-can-read-them-phc"&gt;The Filing Cabinet — why Solana accounts are just files and programs are just people who can read them.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/100-days-of-solana"&gt;100 Days of Solana Writing Challenge&lt;/a&gt;, running from &lt;strong&gt;15 May to 22 May&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>100daysofsolana</category>
      <category>solana</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>🔌 The "Connect Wallet" Button Replaced My Entire Auth System</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Tue, 19 May 2026 11:13:42 +0000</pubDate>
      <link>https://dev.to/blackat/the-connect-wallet-button-replaced-my-entire-auth-system-330k</link>
      <guid>https://dev.to/blackat/the-connect-wallet-button-replaced-my-entire-auth-system-330k</guid>
      <description>&lt;p&gt;&lt;em&gt;Here's something I didn't expect when I started building on Solana: &lt;strong&gt;I never wrote a signup form.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;No username field. No password validation. No "confirm your email" flow. No "forgot password" page. Every piece of auth infrastructure I'd built dozens of times in Web2 — gone.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In its place: one button. "Connect Wallet."&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 What a Wallet Actually Does
&lt;/h2&gt;

&lt;p&gt;If you're new to Solana, I wrote about the conceptual shift — from usernames to keypairs — in a previous post -&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/blackat/from-usernames-to-keypairs-understanding-identity-on-solana-472p" class="crayons-story__hidden-navigation-link"&gt;🔑 From Usernames to Keypairs: Understanding Identity on Solana&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/blackat" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" alt="blackat profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/blackat" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Vinay
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Vinay
                
              
              &lt;div id="story-author-preview-content-3549409" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/blackat" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Vinay&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/blackat/from-usernames-to-keypairs-understanding-identity-on-solana-472p" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/blackat/from-usernames-to-keypairs-understanding-identity-on-solana-472p" id="article-link-3549409"&gt;
          🔑 From Usernames to Keypairs: Understanding Identity on Solana
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/100daysofsolana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;100daysofsolana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/solana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;solana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/blackat/from-usernames-to-keypairs-understanding-identity-on-solana-472p" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/blackat/from-usernames-to-keypairs-understanding-identity-on-solana-472p#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;br&gt;
The short version: your identity is a cryptographic keypair, not a database row.

&lt;p&gt;But for a developer, the practical implication matters more than the theory. Here's what changes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You don't manage authentication.&lt;/strong&gt; The wallet does. When a user clicks "Connect Wallet," their browser extension (Phantom, Solflare, etc.) pops up a confirmation. They approve. Your app gets their public key. You never see the private key. You never store a password hash. You never issue a session token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You don't build onboarding flows.&lt;/strong&gt; In Web2, every step of signup is a drop-off point. Email entry, email verification, profile setup, terms acceptance. On Solana, the user already has an identity before they visit your app. Your job is just to detect it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Logging in" is just signing a message.&lt;/strong&gt; Your app sends a message, the wallet signs it, you verify the signature on your backend. No session cookie. No JWT. The signature is the proof.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚠️ What You Lose
&lt;/h2&gt;

&lt;p&gt;This isn't strictly better. There are tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No password reset.&lt;/strong&gt; If a user loses their private key, they lose access. There's no admin tool to restore their account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No account recovery.&lt;/strong&gt; In Web2, you can email a reset link. On Solana, the keypair is the only identity. Lose it, and everything associated with that address — tokens, NFTs, program state — is inaccessible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No gradual onboarding.&lt;/strong&gt; In Web2, you can let users browse before requiring login. On Solana, the user's address is their identity from the first interaction. There's no "anonymous session" that converts to a registered account later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I covered the technical details of keypair generation and storage — why &lt;code&gt;extractable: true&lt;/code&gt; matters, how PKCS8 works — in another post -&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/blackat/why-my-solana-wallet-broke-without-extractable-true-and-what-pkcs8-taught-me-about-private-keys-20kp" class="crayons-story__hidden-navigation-link"&gt;Why My Solana Wallet Broke Without "extractable: true" — And What PKCS8 Taught Me About Private Keys&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/blackat" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" alt="blackat profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/blackat" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Vinay
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Vinay
                
              
              &lt;div id="story-author-preview-content-3556539" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/blackat" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Vinay&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/blackat/why-my-solana-wallet-broke-without-extractable-true-and-what-pkcs8-taught-me-about-private-keys-20kp" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 27&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/blackat/why-my-solana-wallet-broke-without-extractable-true-and-what-pkcs8-taught-me-about-private-keys-20kp" id="article-link-3556539"&gt;
          Why My Solana Wallet Broke Without "extractable: true" — And What PKCS8 Taught Me About Private Keys
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/100daysofsolana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;100daysofsolana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/solana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;solana&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/blackat/why-my-solana-wallet-broke-without-extractable-true-and-what-pkcs8-taught-me-about-private-keys-20kp" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/blackat/why-my-solana-wallet-broke-without-extractable-true-and-what-pkcs8-taught-me-about-private-keys-20kp#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;But the developer workflow shift is what I had to actually rebuild in my head.&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 The Code Difference
&lt;/h2&gt;

&lt;p&gt;In Web2, auth looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Signup&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;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;req&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;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&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="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&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;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;passwordHash&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&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;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;// Login&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;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;req&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;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;passwordHash&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&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;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;On Solana, auth looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Connect wallet (browser side)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt; &lt;span class="p"&gt;}&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;wallet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standard:connect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;connect&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;userAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// That's it. The user is now "authenticated."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No password hashing. No session management. No database lookups. The wallet handles the cryptographic proof. Your app just reads the public key.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Why This Matters
&lt;/h2&gt;

&lt;p&gt;The "Connect Wallet" pattern isn't just a UI trend. It represents a fundamental shift in how identity works. In Web2, you build auth into your app. In Solana, auth is infrastructure — it lives in the wallet, not in your codebase.&lt;/p&gt;

&lt;p&gt;That means as a developer, you don't need to worry about password storage, session hijacking, or email verification. But you also can't rely on support tickets or account recovery when something goes wrong.&lt;/p&gt;

&lt;p&gt;Once I understood this tradeoff — less code, more responsibility — the "Connect Wallet" button stopped looking like a simplification and started looking like a completely different approach to identity.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next: &lt;a href="https://dev.to/blackat/a-solana-transaction-is-a-signed-check-not-an-api-request-1p8b"&gt;Transactions aren't HTTP requests. They're signed checks — and failed ones still cost you.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/100-days-of-solana"&gt;100 Days of Solana Writing Challenge&lt;/a&gt;, running from &lt;strong&gt;15 May to 22 May&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>100daysofsolana</category>
      <category>solana</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>📊Solana Is a Public Spreadsheet — Not Your Private Database</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Tue, 19 May 2026 10:56:17 +0000</pubDate>
      <link>https://dev.to/blackat/solana-is-a-public-spreadsheet-not-your-private-database-424h</link>
      <guid>https://dev.to/blackat/solana-is-a-public-spreadsheet-not-your-private-database-424h</guid>
      <description>&lt;p&gt;&lt;em&gt;If you're coming from Web2, here's the first mental model you need to rewrite: &lt;strong&gt;Solana is not a database you control. It's a public spreadsheet that everyone can see and no one fully owns.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 The Analogy
&lt;/h2&gt;

&lt;p&gt;Think of a &lt;strong&gt;Google Sheet&lt;/strong&gt; shared with the entire internet. Anyone can open it and read any cell. But only specific people (programs) have permission to edit specific rows.&lt;/p&gt;

&lt;p&gt;Your wallet is a row in that sheet. The columns are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lamports&lt;/strong&gt; — your SOL balance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt; — any extra info attached to your row&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Owner&lt;/strong&gt; — which program is allowed to edit this row&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyone can look up your row. Only the owner program can change it. And the owner program can only make changes when you prove you're you — by signing with your private key.&lt;/p&gt;

&lt;p&gt;In Web2, your database has a wall around it. Users authenticate with passwords, and your server decides who sees what. On Solana, there's no wall. The security comes from &lt;strong&gt;cryptographic signatures&lt;/strong&gt;, not login gates.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ What This Changes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You can't hide data.&lt;/strong&gt; Every balance, every transaction, every interaction with any program is publicly visible forever. If you're building on Solana, don't store private info in account data. It's not private.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There's no "backend" to build.&lt;/strong&gt; You don't need to design a database schema, set up authentication middleware, or deploy an API server. Solana is the backend. Your program (smart contract) defines the rules, and users interact with it directly through transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ownership is enforced by the network, not your code.&lt;/strong&gt; In Web2, you write &lt;code&gt;if (user.isAdmin)&lt;/code&gt; checks to control access. On Solana, the runtime itself prevents unauthorized writes. If your program doesn't own an account, it simply cannot modify it — no matter what your code tries to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 The Hardest Adjustment
&lt;/h2&gt;

&lt;p&gt;The first time I queried someone else's wallet balance, I felt like I was doing something wrong. Coming from web development, I never once displayed another user's financial data without permission. But on Solana, that's not just allowed — it's the entire point.&lt;/p&gt;

&lt;p&gt;Transparency isn't a design flaw. It's the feature that makes everything else possible. Composability, auditability, trustlessness — all of it starts with the fact that every piece of state is public.&lt;/p&gt;

&lt;p&gt;Once I stopped thinking of Solana as "someone else's database I'm borrowing" and started seeing it as "a shared public spreadsheet," the rest of the model started clicking.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next: &lt;a href="https://dev.to/blackat/the-connect-wallet-button-replaced-my-entire-auth-system-330k"&gt;The "Connect Wallet" button replaced my entire auth system.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/100-days-of-solana"&gt;100 Days of Solana Writing Challenge&lt;/a&gt;, running from &lt;strong&gt;15 May to 22 May&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>100daysofsolana</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>solana</category>
    </item>
    <item>
      <title>⚓My Deep Dive into Solana Transactions: Shifting the Web2 Perspective</title>
      <dc:creator>Vinay</dc:creator>
      <pubDate>Sun, 10 May 2026 15:14:24 +0000</pubDate>
      <link>https://dev.to/blackat/my-deep-dive-into-solana-transactions-shifting-the-web2-perspective-2123</link>
      <guid>https://dev.to/blackat/my-deep-dive-into-solana-transactions-shifting-the-web2-perspective-2123</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Over the last few days, I’ve been learning how Solana transactions actually work. At first, I approached them like I would approach API requests in Web2: you send something to the network, wait for a response, and either it succeeds or fails.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;But after building transfer tools, tracking confirmations, and intentionally forcing failed transactions, I realized Solana transactions are much closer to atomic state transitions in a distributed system than traditional request/response workflows.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;🏗️ The Foundation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before this post, I documented two earlier parts of the journey:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" class="crayons-story__hidden-navigation-link"&gt;Sending Your First SOL Transfer (Devnet, via CLI)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/blackat" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" alt="blackat profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/blackat" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Vinay
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Vinay
                
              
              &lt;div id="story-author-preview-content-3620076" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/blackat" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Vinay&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" id="article-link-3620076"&gt;
          Sending Your First SOL Transfer (Devnet, via CLI)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/100daysofsolana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;100daysofsolana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/solana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;solana&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;7&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/blackat/sending-your-first-sol-transfer-devnet-via-cli-1gdi#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;



&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" class="crayons-story__hidden-navigation-link"&gt;Understanding Solana's transaction anatomy&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/blackat" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" alt="blackat profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/blackat" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Vinay
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Vinay
                
              
              &lt;div id="story-author-preview-content-3620611" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/blackat" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3881968%2Fd6b017fd-5606-40fa-a8ac-fdac3d3bea66.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Vinay&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 6&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" id="article-link-3620611"&gt;
          Understanding Solana's transaction anatomy
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/100daysofsolana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;100daysofsolana&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/web3"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;web3&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/blockchain"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;blockchain&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/solana"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;solana&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/blackat/understanding-solanas-transaction-anatomy-52j0#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Those experiments helped me understand the structure underneath every transaction before I started building tooling around them.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;🔍 Deconstructing the Transaction Anatomy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The first thing that stood out to me was how much information exists inside a transaction. Once I started inspecting transactions in Solana Explorer and using solana confirm -v, I stopped seeing transfers as simple wallet operations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A single transaction includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signatures&lt;/li&gt;
&lt;li&gt;Instructions&lt;/li&gt;
&lt;li&gt;Account keys&lt;/li&gt;
&lt;li&gt;Recent blockhashes&lt;/li&gt;
&lt;li&gt;Fee payer information&lt;/li&gt;
&lt;li&gt;Execution logs&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🧠The Mental Model Shift:&lt;/strong&gt;&lt;br&gt;
A Solana transaction is not just a request. It’s a signed set of instructions that tells the network how on-chain state should change.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;🛠️ Building the Tooling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After getting comfortable with CLI transfers, I built a reusable transfer tool instead of manually typing commands every time.&lt;/p&gt;

&lt;p&gt;The tool eventually handled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recipient and amount validation&lt;/li&gt;
&lt;li&gt;Balance checks before sending&lt;/li&gt;
&lt;li&gt;Explorer link generation&lt;/li&gt;
&lt;li&gt;Confirmation tracking&lt;/li&gt;
&lt;li&gt;Transaction failure handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The balance checks were especially interesting because failed transactions on Solana still cost fees. That’s very different from most backend systems I’m used to. In Web2, failed requests are usually just errors. On Solana, even failed execution still consumes validator compute resources.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;⛓️ Understanding the Lifecycle of Confirmation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the most useful things I learned was how confirmation actually works. At first, I thought transactions were either pending or complete.&lt;/p&gt;

&lt;p&gt;But Solana has multiple commitment levels:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Processed:&lt;/strong&gt; Received by a validator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirmed:&lt;/strong&gt; Voted on by the network supermajority.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finalized:&lt;/strong&gt; Effectively irreversible after additional confirmed blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Watching transactions move through those stages made the network feel much more real. Instead of treating blockchain confirmation like a black box, I could actually observe the lifecycle happening in real time.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;⚠️ Learning Through Failure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most valuable part of the process, though, was intentionally breaking transactions.&lt;/p&gt;

&lt;p&gt;I created empty wallets. I forced failed transfers. I inspected logs and Explorer traces. I compared local CLI validation with actual on-chain failures. That ended up teaching me more than successful transactions did.&lt;/p&gt;

&lt;p&gt;Seeing compute usage, log messages, and failure metadata made the debugging side of Solana feel surprisingly similar to debugging distributed backend systems—except here, every mistake has an economic cost attached to it.&lt;/p&gt;




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

&lt;p&gt;The biggest takeaway from this journey is that understanding transactions is really about understanding how Solana itself thinks.&lt;/p&gt;

&lt;p&gt;Once I stopped comparing transactions directly to REST API calls, concepts like signatures, blockhash expiration, commitment levels, and transaction simulation started making much more sense. Intentionally exploring failed transactions was the point where everything finally clicked for me.&lt;/p&gt;

</description>
      <category>100daysofsolana</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>solana</category>
    </item>
  </channel>
</rss>
