Crowdfunding en Sway

El ultimo año desarrolle un crowdfunding en sway, una dapp bastante sencilla la cual puedes empezar a implementar con conocimientos básicos del lenguaje.

¿Que hace este contrato?

En este contrato hemos desarrollado una dapp para recaudar fondos mediante cantidades que sean relativamente pequeñas pero con un gran números de contribuyentes.

Empecemos

Lo primero que haremos es crear una librería que contendrá la abi con todas las estructuras de datos y funciones que necesitemos.

Definamos la libreria con su nombre e importemos todas las funciones que usaremos de la libreria STD.

library crowdfunding_library;

use core::ops::Eq;

use std::{
    identity::Identity,
    contract_id::ContractId,
};

Luego definimos el abi con las funciones que usaremos en el contrato.

abi CrowdFunding {
    // Initliaze Campaign
    #[storage(read, write)]
    fn initialize(
      token: ContractId
    );

    // See if campaign is initalize or not.
    #[storage(read)]
    fn is_initialized() -> bool;

    // Create campaign
    #[storage(read, write)]
    fn create_campaign(
        beneficiary: Identity, 
        goal_amount: u64, 
        minimumcontribution: u64
    ) -> u64;

    // Pledge an amount to a campaign
    #[storage(read, write)]
    fn minimum_contribution(
      campaign_id: u64
    );

    // Completes a campaign and sends the total amount pledged to the campaign beneficiary
    #[storage(read, write)]
    fn complete_campaign(
      campaign_id: u64
    );
}

Implementamos la función del estado de la campaña.

// function status
pub enum State {
    NotInitialized: (),
    Initialized: (),
}

impl Eq for State {
    fn eq(self, other: Self) -> bool {
        match(self, other) {
            (State::Initialized, State::Initialized) => true,
            (State::NotInitialized, State::NotInitialized) => true,
            _ => false, 
        }
    }
}

Y por ultimo y no menos importante definimos la estructura de la campaña

// Campaing Struct.
pub struct Campaign {
    current_amount: u64,
    is_active: bool,
    author: Identity,
    beneficiary: Identity,
    goal_amount: u64
}

Ahora bien, ya que tenemos la librería completa podemos pasar al desarrollo del contrato principal.

Empezamos llamando la librería que desarrollamos y también la librería std con las funciones que usaremos.

contract;

dep crowdfunding_library;

use crowdfunding_library::*;

use std::{
    identity::Identity,
    contract_id::ContractId,
    assert::assert,
    storage::StorageMap,
    chain::auth::{AuthError, msg_sender},
    result::*,
    context::{call_frames::msg_asset_id, msg_amount, this_balance},
    token::transfer,
    revert::revert,
};

Ahora definimos todas las variables de storage.

storage {
    // Tells us if it is already initialized or not
    state: State = State::NotInitialized,

    // Contract id of the accepted asset
    asset: ContractId = ContractId {
        value: 0x0000000000000000000000000000000000000000000000000000000000000000,
    },

    // The current total number of campaigns
    next_campaign_id: u64 = 0,

    // All campaigns
    campaigns: StorageMap<u64, Campaign> = StorageMap {},
}

Y por ultimo implementamos todas las funciones que desarrollamos en el abi de la libreria crowdfunding_library.sw

impl CrowdFunding for Contract {
    #[storage(read, write)]
    fn initialize(asset: ContractId) {
        // Storage state 
        assert(storage.state == State::NotInitialized);
        // Asset 
        assert(storage.asset == asset::ContractId);   
    }

    // is initialize 
    #[storage(read)]
    fn is_initialized() -> bool {
        match storage.state {
            State::Initialized => true,
            State::NotInitialized => false,
        }
    }

    // Create a new campaign
    #[storage(read, write)]
    fn create_campaign(beneficiary: Identity, goal_amount: u64, minimumcontribution: u64) -> u64 {
        assert(storage.state == State::Initial);

        let author = msg_sender().unwrap();
        let campaign = Campaign {
            current_amount: 0,
            is_active: true,
            author,
            beneficiary,
            goal_amount
        };

        let campaign_id = storage.next_campaign_id;
        storage.campaigns.insert(campaign_id, campaign);
        storage.next_campaign_id += 1;
        campaign_id

    }


    // Minimum Amount for the Contribution
    #[storage(read, write)]
    fn minimum_contribution(campaign_id: u64) {
        assert(storage.state == State::Initialized);
        assert(campaign_id < storage.next_campaign_id);
        assert(storage.asset == msg_asset_id());

        let mut campaign = storage.campaigns.get(campaign_id);
        let minimum_contribution_amount = msg_amount();

        assert(campaign.is_active);
        assert(minimum_contribution_amount > 0);

        campaign.current_amount += minimum_contribution_amount;
        storage.campaigns.insert(campaign_id, campaign);
    }

    // crowfunding completed
    #[storage(read, write)]
    fn complete_campaign(campaign_id: u64) {
        assert(storage.state == State::Initialized);
        assert(campaign_id < storage.next_campaign_id);

        let mut campaign = storage.campaigns.get(campaign_id);

        assert(campaign.is_active);
        assert(campaign.current_amount >= campaign.goal_amount);
        campaign.is_active = false;
    }
}

Y esto es todo, acabamos de desarrollar una dapp para recaudar fondos! Espero que te haya servido este pequeño tutorial.

Subscribe to andrw
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.