<?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: Henry Pham</title>
    <description>The latest articles on DEV Community by Henry Pham (@henrypham).</description>
    <link>https://dev.to/henrypham</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1204283%2F8d545e43-e345-4c38-ad00-59c704a1bbd8.jpeg</url>
      <title>DEV Community: Henry Pham</title>
      <link>https://dev.to/henrypham</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/henrypham"/>
    <language>en</language>
    <item>
      <title>How to write NFT Marketplace Algorand</title>
      <dc:creator>Henry Pham</dc:creator>
      <pubDate>Thu, 23 Nov 2023 07:36:12 +0000</pubDate>
      <link>https://dev.to/henrypham/how-to-write-nft-marketplace-algorand-6f2</link>
      <guid>https://dev.to/henrypham/how-to-write-nft-marketplace-algorand-6f2</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;NFT marketplaces are online platforms that allow creators to mint and sell their NFTs to buyers who can purchase them using cryptocurrency. These marketplaces typically provide a user-friendly interface for creating and managing NFTs, including the ability to set prices, royalties, and other terms and conditions. In this article, we will explore how to create an NFT marketplace smart contract on Algorand.&lt;/p&gt;

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

&lt;p&gt;Before diving into the development process, ensure you have the following tools set up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Docker desktop&lt;/li&gt;
&lt;li&gt;  Python and pipx&lt;/li&gt;
&lt;li&gt;  Visual Studio Code&lt;/li&gt;
&lt;li&gt;  Chrome browser&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install Algokit
&lt;/h3&gt;

&lt;p&gt;Algokit simplifies Algorand development. Install it using pipx:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start Localnet
&lt;/h3&gt;

&lt;p&gt;Launch the local Algorand network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;algokit localnet start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5pmUcgLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.viblo.asia/69e4f6b5-9abb-4184-aade-a2a2fa5641c9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5pmUcgLt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.viblo.asia/69e4f6b5-9abb-4184-aade-a2a2fa5641c9.png" alt="" width="734" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Init Project
&lt;/h3&gt;

&lt;p&gt;Create a new project with Algokit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;algokit init 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TsFnjA0V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.viblo.asia/84a98fbc-cea2-461e-a2f4-5a2d202604e5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TsFnjA0V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.viblo.asia/84a98fbc-cea2-461e-a2f4-5a2d202604e5.png" alt="" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose TypeScript as the preferred language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Marketplace Smart Contract
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Defining Struct
&lt;/h3&gt;

&lt;p&gt;Structs organize and store essential data within the smart contract. Start by defining the &lt;code&gt;collection&lt;/code&gt; struct to contain pertinent collection information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type collectionData = {
  name: string;
  owner: Address;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, define the &lt;code&gt;nftData&lt;/code&gt; struct to link NFTs with their respective collections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type nftData = {
  collectionId: number,
  nftAsset: Asset,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, create the &lt;code&gt;orderData&lt;/code&gt; type to manage order details within the marketplace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type orderData = {
  owner: Address,
  price: uint64,
  nft: Asset,
  status: uint64; // 0 false 1 true
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These structured definitions lay the foundation for organizing collection, NFT, and order-related information within the Algorand smart contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create Collection Function
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;collectionIndex&lt;/code&gt; is a global state key that maintains the index for collections.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;collection&lt;/code&gt; is a box map that stores collection data based on their respective indexes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;collectionIndex = GlobalStateKey&amp;lt;uint64&amp;gt;();
collection = BoxMap&amp;lt;uint64, collectionData&amp;gt;({});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create Collection Function:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  This function creates a new collection within the smart contract.&lt;/li&gt;
&lt;li&gt;  It takes the name of the collection as a parameter and assigns the creator's address as the owner.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createCollection(name: string): void {
    const temp: collectionData = {
      name: name,
      owner: this.txn.sender,
    };

    this.collection(this.collectionIndex.value).value = temp;
    this.collectionIndex.value = this.collectionIndex.value + 1;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;temp&lt;/code&gt; stores the data for the new collection, including its &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;owner&lt;/code&gt; (the address of the sender).&lt;/li&gt;
&lt;li&gt;  The new collection is added to the &lt;code&gt;collection&lt;/code&gt; box map at the index specified by &lt;code&gt;collectionIndex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Increment &lt;code&gt;collectionIndex&lt;/code&gt; to prepare for the next collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Mint NFT Function
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;nft&lt;/code&gt; is a global state key that represents the NFT asset.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nft  =  GlobalStateKey&amp;lt;Asset&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mint NFT Function:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  This function facilitates the creation of a new NFT.&lt;/li&gt;
&lt;li&gt;  It takes the name and URL of the NFT as parameters and returns the minted NFT asset.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mintNFT(name: string, url: string): Asset {
    const nftTicket = sendAssetCreation({
      configAssetTotal: 1,
      configAssetName: name,
      configAssetURL: url,
    });
    return nftTicket;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;nftTicket&lt;/code&gt; holds the newly minted NFT asset.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;sendAssetCreation&lt;/code&gt; function creates an NFT with the specified &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  It configures the NFT asset with a total supply of 1 and associates the provided metadata (name and URL) with the NFT.&lt;/li&gt;
&lt;li&gt;  Finally, the minted NFT asset is returned.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Mapping NFT Data
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;nftIndex&lt;/code&gt; is a global state key used to maintain the index for NFTs.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;nftDataMap&lt;/code&gt; is a box map that stores NFT data mapped to their respective indexes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nftIndex  =  GlobalStateKey&amp;lt;uint64&amp;gt;();
nftDataMap  =  BoxMap&amp;lt;uint64, nftData&amp;gt;({ prefix:  'n' });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Map NFT data function:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  This function maps an NFT to its associated collection.&lt;/li&gt;
&lt;li&gt;  It takes the NFT asset and the ID of the collection as parameters.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mapNFTdata(nft: Asset, collectionId: uint64): void {
    const temp: nftData = {
      collectionId: collectionId,
      nftAsset: nft,
    };

    this.nftDataMap(this.nftIndex.value).value = temp;
    this.nftIndex.value = this.nftIndex.value + 1;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;temp&lt;/code&gt; holds the data associating the NFT with its collection ID.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;nftDataMap&lt;/code&gt; box map stores this data at the index specified by &lt;code&gt;nftIndex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;nftIndex&lt;/code&gt; is incremented to prepare for the next NFT mapping.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Listing NFT to Marketplace
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;orderIndex&lt;/code&gt; is a global state key that maintains the index for orders in the marketplace.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;order&lt;/code&gt; is a box map that stores order data, representing the listing details of NFTs.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;orderIndex  =  GlobalStateKey&amp;lt;uint64&amp;gt;();
order  =  BoxMap&amp;lt;uint64, orderData&amp;gt;({ prefix:  'o' });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Listing NFT Function:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  This function enables the listing of an NFT for sale in the marketplace.&lt;/li&gt;
&lt;li&gt;  It takes the NFT asset, sale price, and the transaction details as parameters.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;listingNFT(nft: Asset, price: number, axfer: AssetTransferTxn): void {
    // verfiy Txn
    verifyTxn(axfer, { assetReceiver: this.app.address });

    // create order
    const temp: orderData = {
      owner: this.txn.sender,
      price: price,
      nft: nft,
      status: 0,
    };

    this.order(this.orderIndex.value).value = temp;
    this.orderIndex.value = this.orderIndex.value + 1;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Verification is performed to ensure that the transfer transaction involves the marketplace contract as the receiver, securing the listing process.&lt;/li&gt;
&lt;li&gt;  The function creates an order for the listed NFT, capturing details such as the owner's address (&lt;code&gt;this.txn.sender&lt;/code&gt;), the sale &lt;code&gt;price&lt;/code&gt;, the &lt;code&gt;nft&lt;/code&gt; being listed, and its status set as &lt;code&gt;0&lt;/code&gt; indicating it's listed for sale.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 6: Unlisting NFT from Marketplace*
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  This function facilitates the removal of a listed NFT from the marketplace.&lt;/li&gt;
&lt;li&gt;  It takes the &lt;code&gt;orderId&lt;/code&gt; of the listing and the NFT asset as parameters.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unListingNFT(orderId: number, nft: Asset): void {
    // verify owner
    assert(this.txn.sender === this.order(orderId).value.owner);

    // check Status of NFT
    assert(this.order(orderId).value.status === 1);

    this.order(orderId).value.status = 1;

    // Transfer NFT to owner
    sendAssetTransfer({
      xferAsset: nft,
      assetReceiver: this.txn.sender,
      assetAmount: 1,
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  The function ensures that only the owner of the NFT can unlist it from the marketplace (&lt;code&gt;assert(this.txn.sender === this.order(orderId).value.owner)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  It verifies that the NFT is currently listed for sale (&lt;code&gt;this.order(orderId).value.status === 0&lt;/code&gt;) before proceeding with unlisting.&lt;/li&gt;
&lt;li&gt;  If conditions are met, the status of the NFT listing is updated to indicate it's no longer available (&lt;code&gt;this.order(orderId).value.status = 1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Additionally, the function transfers the NFT asset back to its owner.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 7: Buy NFT Function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  This function enables the purchase of an NFT listed in the marketplace.&lt;/li&gt;
&lt;li&gt;  It takes the &lt;code&gt;orderId&lt;/code&gt; of the listing, payment transaction details (&lt;code&gt;payment&lt;/code&gt;), and the NFT asset as parameters.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;buyNFTFromMarketplace(orderId: number, payment: PayTxn, nft: Asset): void {
    // Check order status
    assert(this.order(orderId).value.status === 0);
    // Check enough money to buy
    verifyTxn(payment, {
      sender: this.txn.sender,
      amount: { greaterThan: this.order(orderId).value.price },
      receiver: this.order(orderId).value.owner,
    });

    // Transfer Asset
    sendAssetTransfer({
      xferAsset: nft,
      assetReceiver: this.txn.sender,
      assetAmount: 1,
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  The function verifies that the NFT is listed and available for purchase (&lt;code&gt;assert(this.order(orderId).value.status === 0)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  It verifies the buyer's payment transaction details, ensuring the correct payment amount and receiver (&lt;code&gt;verifyTxn(payment, {...})&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Upon successful verification, the NFT is transferred to the buyer's address (&lt;code&gt;sendAssetTransfer&lt;/code&gt;) and the order status is updated to indicate it's sold.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 8: Write some Get Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  getCollectionName(eventId: number): string {
    return this.collection(eventId).value.name;
  }

  getCollectionByNFT(nftIndex: number): number {
    return this.nftDataMap(nftIndex).value.collectionId;
  }

  getNFTAsset(nftIndex: number): Asset {
    return this.nftDataMap(nftIndex).value.nftAsset;
  }

  getOrderOwner(orderId: number): Address {
    return this.order(orderId).value.owner;
  }

  getOrderNFT(orderId: number): Asset {
    return this.order(orderId).value.nft;
  }

  getOrderPrice(orderId: number): number {
    return this.order(orderId).value.price;
  }

  getOrderStatus(orderId: number): number {
    return this.order(orderId).value.status;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These functions retrieve specific details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;getCollectionName&lt;/code&gt;: Retrieves the name of a collection based on its ID.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;getCollectionByNFT&lt;/code&gt;: Retrieves the ID of the collection associated with an NFT.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;getNFTAsset&lt;/code&gt;: Retrieves the NFT asset based on its index.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;getOrderOwner&lt;/code&gt;: Retrieves the owner's address of a specific order.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;getOrderNFT&lt;/code&gt;: Retrieves the NFT asset associated with an order.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;getOrderPrice&lt;/code&gt;: Retrieves the price of an NFT listed in an order.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;getOrderStatus&lt;/code&gt;: Retrieves the status (listed or sold) of an order.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In this guide, we've detailed the step-by-step process of creating an NFT marketplace smart contract on Algorand. From defining data structures to implementing essential functionalities, such as minting NFTs, listing them for sale, and enabling purchases, we've laid the groundwork for a functional NFT marketplace within the Algorand blockchain ecosystem.&lt;/p&gt;

&lt;p&gt;Explore the entire codebase at &lt;a href="https://github.com/cuongpo/Algorand-NFT-Marketplace"&gt;https://github.com/cuongpo/Algorand-NFT-Marketplace&lt;/a&gt; for a deeper dive into the implementation details.&lt;/p&gt;

&lt;p&gt;In the next article, we'll delve into the crucial aspect of testing this smart contract. Thank you for taking the time to read!&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>tutorial</category>
      <category>algorand</category>
      <category>tealscript</category>
    </item>
    <item>
      <title>Build a DAO Smart Contract in Algorand using Beaker #1</title>
      <dc:creator>Henry Pham</dc:creator>
      <pubDate>Tue, 07 Nov 2023 14:58:24 +0000</pubDate>
      <link>https://dev.to/henrypham/build-a-dao-smart-contract-in-algorand-using-beaker-1-3bm</link>
      <guid>https://dev.to/henrypham/build-a-dao-smart-contract-in-algorand-using-beaker-1-3bm</guid>
      <description>&lt;p&gt;Decentralized Autonomous Organizations (DAOs) have gained significant attention in the blockchain space for their ability to facilitate decentralized decision-making and governance. Algorand, a blockchain platform known for its speed and security, offers a powerful environment for creating smart contracts, including DAOs. In this article, we'll walk through a sample DAO smart contract written in PyTeal, the smart contract language for Algorand. We'll explain each part of the contract and how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Declare Variables and Initialize the Application
&lt;/h2&gt;

&lt;p&gt;In this first section, we declare the necessary variables and initialize the application state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from beaker import *
from pyteal import *

from beaker.lib.storage import BoxMapping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define a data structure for a proposal
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class proposalStruct(abi.NamedTuple):
description: abi.Field[abi.String]
vote_yes: abi.Field[abi.Uint64]
vote_no: abi.Field[abi.Uint64]
status: abi.Field[abi.String]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define the smart contract's application state
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class AppStateValue:
    memberCount = GlobalStateValue(
        stack_type=TealType.uint64,
        default=Int(0),
        descr="Number Member of DAO",
    )

    proposalCount = GlobalStateValue(
        stack_type=TealType.uint64,
        default=Int(0),
        descr="Number of Proposals"
    )

    memberDAO = LocalStateValue(
        stack_type=TealType.uint64,
        default=Int(0),
        descr="Member DAO or not",
    )

    check_voted = ReservedLocalStateValue(
        stack_type=TealType.uint64,
        max_keys=8,
        descr=("Check if a user voted in a proposal"),
    )

    proposals = BoxMapping(abi.Uint64, proposalStruct)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create an Algorand application called "Simple DAO" with the defined state
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app = (
    Application("Simple DAO", state=AppStateValue())
    .apply(unconditional_create_approval, initialize_global_state=True)
    .apply(unconditional_opt_in_approval, initialize_local_state=True)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  We declare a data structure &lt;code&gt;proposalStruct&lt;/code&gt; to represent a proposal, which includes a description, vote counts (yes and no), and a status field.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;AppStateValue&lt;/code&gt; class defines the global and local state variables required for the DAO. It includes the number of members, the number of proposals, member status, a reserved local state value to check if a user voted, and a mapping to store proposals.&lt;/li&gt;
&lt;li&gt;  We create an Algorand application named "Simple DAO" with the defined state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Join and Leave the DAO
&lt;/h2&gt;

&lt;p&gt;Next, we define functions for joining and leaving the DAO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check member DAO status
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def check_member_dao(*, output: abi.Uint64) -&amp;gt; Expr:
    return output.set(app.state.memberDAO[Txn.sender()])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Join the DAO
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def join_dao() -&amp;gt; Expr:
    return Seq(
        app.state.memberDAO[Txn.sender()].set(Int(1)),
        app.state.memberCount.increment(),
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Leave the DAO
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def leave_dao() -&amp;gt; Expr:
    return Seq(
        app.state.memberDAO[Txn.sender()].set(Int(0)),
        app.state.memberCount.decrement(),
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;check_member_dao&lt;/code&gt;: This function checks if the sender is a member of the DAO. If they are, it sets the output to &lt;code&gt;1&lt;/code&gt;; otherwise, it sets it to &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;join_dao&lt;/code&gt;: This function allows a user to join the DAO. It sets their DAO membership status to &lt;code&gt;1&lt;/code&gt; and increments the member count.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;leave_dao&lt;/code&gt;: This function lets a user leave the DAO. It sets their DAO membership status to &lt;code&gt;0&lt;/code&gt; and decrements the member count.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Create Proposals
&lt;/h2&gt;

&lt;p&gt;We define a function to create proposals in the DAO.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def create_proposal(descr: abi.String, *, output: proposalStruct) -&amp;gt; Expr:
    proposal_tuple = proposalStruct()
    proposalId = abi.Uint64()
    vote_yes = abi.Uint64()
    vote_no = abi.Uint64()
    status = abi.String()
    return Seq(
        vote_yes.set(Int(0)),
        vote_no.set(Int(0)),
        status.set("In Progress"),
        proposal_tuple.set(descr, vote_yes, vote_no, status),
        proposalId.set(app.state.proposalCount.get()),
        app.state.proposals[proposalId].set(proposal_tuple),
        app.state.proposalCount.increment(),
        app.state.proposals[proposalId].store_into(output),
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  The &lt;code&gt;create_proposal&lt;/code&gt; function allows a user to create a new proposal. It initializes vote counts, sets the status to "In Progress," and stores the proposal in the contract's state. The proposal's details and status are stored in the &lt;code&gt;output&lt;/code&gt; variable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Check and End Proposals
&lt;/h2&gt;

&lt;p&gt;We define functions to check the status of proposals and end proposals when certain conditions are met.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check Proposal
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def check_proposal(proposalId: abi.Uint64, *, output: proposalStruct) -&amp;gt; Expr:
    return app.state.proposals[proposalId].store_into(output)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  End Proposal when total vote &amp;gt; 1/2 member Count
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def end_proposal(proposalId: abi.Uint64, *, output: abi.String) -&amp;gt; Expr:
    proposal = proposalStruct()
    description = abi.String()
    vote_yes = abi.Uint64()
    vote_no = abi.Uint64()
    status = abi.String()
    new_status = abi.String()

    total_dao_member = app.state.memberCount.get()
    app.state.proposals[proposalId].store_into(proposal)
    description.set(proposal.description)
    vote_yes.set(proposal.vote_yes)
    vote_no.set(proposal.vote_no)
    status.set(proposal.status)

    if status != "In Progress":
        return output.set("Proposal Ended")

    if 2 * (vote_yes + vote_no) &amp;lt; total_dao_member:
        return output.set("Not enough votes")

    if vote_yes &amp;lt; vote_no:
        return Seq(
            output.set("Proposal failed"),
            new_status.set("Proposal failed"),
            proposal.set(description, vote_yes, vote_no, new_status),
            app.state.proposals[proposalId].set(proposal),
        )

    return Seq(
        output.set("Proposal succeeded"),
        new_status.set("Proposal succeeded"),
        proposal.set(description, vote_yes, vote_no, new_status),
        app.state.proposals[proposalId].set(proposal),
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;check_proposal&lt;/code&gt;: This function allows users to check the details of a specific proposal.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;end_proposal&lt;/code&gt;: Users can end a proposal using this function if it has received enough votes. The function checks the vote counts and the total number of DAO members to determine if a proposal passes or fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Check Voted and Vote on Proposals
&lt;/h2&gt;

&lt;p&gt;We define functions to check if a user has voted and to cast votes on proposals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def check_voted(proposalId: abi.Uint64, *, output: abi.Uint64) -&amp;gt; Expr:
    return output.set(app.state.check_voted[proposalId])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vote Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.external
def vote(proposalId: abi.Uint64, vote_choice: abi.Uint8, *, output: abi.String) -&amp;gt; Expr:
    proposal = proposalStruct()
    description = abi.String()
    vote_yes = abi.Uint64()
    vote_no = abi.Uint64()
    status = abi.String()
    return Seq(
        proposal.decode(app.state.proposals[proposalId].get()),
        description.set(proposal.description),
        status.set(proposal.status),
        vote_yes.set(proposal.vote_yes),
        vote_no.set(proposal.vote_no),
        If(vote_choice.get() == Int(1))
        .Then(
            vote_yes.set(vote_yes.get() + Int(1)),
        )
        .Else(
            vote_no.set(vote_no.get() + Int(1)),
        ),
        proposal.set(description, vote_yes, vote_no, status),
        app.state.proposals[proposalId].set(proposal),
        output.set("Vote Successfully"),
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;check_voted&lt;/code&gt;: This function allows users to check if they have already voted on a specific proposal.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;vote&lt;/code&gt;: Users can cast their votes on proposals using this function. It increments the vote counts accordingly and updates the proposal's status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, you have a complete step-by-step guide to building and interacting with the DAO smart contract on Algorand. You can opt-in to the contract, join the DAO, create and vote on proposals, check the status of proposals, and more, based on your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check only users who have joined the DAO can create proposals and vote.&lt;/li&gt;
&lt;li&gt;Check that users can only vote once.&lt;/li&gt;
&lt;li&gt;How to deploy and interact with dAppflow.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>algorand</category>
      <category>blockchain</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
