Untitled

 avatar
user_8098220
plain_text
a year ago
7.4 kB
0
Indexable
Never
module overmind::birthday_bot {
    use aptos_std::table::Table;
    use std::signer;
    use std::error;
    use aptos_framework::account;
    use std::vector;
    use aptos_framework::coin;
    use aptos_framework::aptos_coin::{Self, AptosCoin};
    use aptos_std::table;
    use aptos_framework::timestamp;

    

    //
    // Errors
    //
    const ERROR_DISTRIBUTION_STORE_EXIST: u64 = 0;
    const ERROR_DISTRIBUTION_STORE_DOES_NOT_EXIST: u64 = 1;
    const ERROR_LENGTHS_NOT_EQUAL: u64 = 2;
    const ERROR_BIRTHDAY_GIFT_DOES_NOT_EXIST: u64 = 3;
    const ERROR_BIRTHDAY_TIMESTAMP_SECONDS_HAS_NOT_PASSED: u64 = 4;

    //
    // Data structures
    //
    struct BirthdayGift has drop, store {
        amount: u64,
        birthday_timestamp_seconds: u64,
    }

    struct DistributionStore has key {
        birthday_gifts: Table<address, BirthdayGift>,
        signer_capability: account::SignerCapability,
    }

    //
    // Assert functions
    //
    public fun assert_distribution_store_exists(
        account_address: address,
    ) {
        // TODO: assert that `DistributionStore` exists
        assert!(exists<DistributionStore>(account_address), 1);
    }

    public fun assert_distribution_store_does_not_exist(
        account_address: address,
    ) {
        // TODO: assert that `DistributionStore` does not exist
        assert!(!exists<DistributionStore>(account_address), 0);
    }

    public fun assert_lengths_are_equal(
        addresses: vector<address>,
        amounts: vector<u64>,
        timestamps: vector<u64>
    ) {
        // TODO: assert that the lengths of `addresses`, `amounts`, and `timestamps` are all equal
        let single_vector_len = vector::length<address>(&addresses);
        assert!(vector::length<u64>(&amounts) == single_vector_len, 2);
        assert!(vector::length<u64>(&timestamps) == single_vector_len, 2);
    }

    public fun assert_birthday_gift_exists(
        distribution_address: address,
        address: address,
    ) acquires DistributionStore {
        // TODO: assert that `birthday_gifts` exists
        let distribution_store = borrow_global<DistributionStore>(distribution_address);
        assert!(table::contains(&distribution_store.birthday_gifts, address), 0);
    }

    public fun assert_birthday_timestamp_seconds_has_passed(
        distribution_address: address,
        address: address,
    ) acquires DistributionStore {
        // TODO: assert that the current timestamp is greater than or equal to `birthday_timestamp_seconds`
        let distribution_store = borrow_global<DistributionStore>(distribution_address);
        let birthday_store = table::borrow(&distribution_store.birthday_gifts, address);
        assert!(timestamp::now_seconds() >= birthday_store.birthday_timestamp_seconds, 4);
        // let timestamp: Table<address, BirthdayGift> = table::borrow(&mut distribution_store.birthday_gifts, address);
    }

    //
    // Entry functions
    //
    /**
    * Initializes birthday gift distribution contract
    * @param account - account signer executing the function
    * @param addresses - list of addresses that can claim their birthday gifts
    * @param amounts  - list of amounts for birthday gifts
    * @param birthday_timestamps - list of birthday timestamps in seconds (only claimable after this timestamp has passed)
    **/
    
    public entry fun initialize_distribution(
        account: &signer,
        addresses: vector<address>,
        amounts: vector<u64>,
        birthday_timestamps: vector<u64>
    ) acquires DistributionStore {
        // TODO: check `DistributionStore` does not exist

        assert_distribution_store_does_not_exist(signer::address_of(account));

        // TODO: check all lengths of `addresses`, `amounts`, and `birthday_timestamps` are equal

        assert_lengths_are_equal(addresses, amounts, birthday_timestamps);

        // TODO: create resource account

        let (the_signer, signer_capability) = account::create_resource_account(account, vector::empty<u8>());       

        // TODO: register Aptos coin to resource account
        
        aptos_framework::managed_coin::register<AptosCoin>(&the_signer);

        // TODO: loop through the lists and push items to birthday_gifts table
        let birthday_gift_store = table::new<address, BirthdayGift>();
        let i = 0;
        let sum_of_all_amounts = 0;
        while (i < vector::length(&addresses)) {
            let addr = vector::borrow<address>(&addresses, i);
            let amount = vector::borrow<u64>(&amounts, i);
            let birthday_timestamp_seconds = vector::borrow<u64>(&birthday_timestamps, i);
            let gift = BirthdayGift {
                amount: *amount, birthday_timestamp_seconds: *birthday_timestamp_seconds
            };

            table::upsert(&mut birthday_gift_store, *addr, gift);

            i = i + 1;
            sum_of_all_amounts = sum_of_all_amounts + *amount;
        };

        // TODO: transfer the sum of all items in `amounts` from initiator to resource account
        
        aptos_framework::coin::transfer<AptosCoin>(account, signer::address_of(&the_signer), sum_of_all_amounts);
        // TODO: move_to resource `DistributionStore` to account signer

        move_to(account, DistributionStore {birthday_gifts: birthday_gift_store,signer_capability: signer_capability});
    }

    /**
    * Add birthday gift to `DistributionStore.birthday_gifts`
    * @param account - account signer executing the function
    * @param address - address that can claim the birthday gift
    * @param amount  - amount for the birthday gift
    * @param birthday_timestamp_seconds - birthday timestamp in seconds (only claimable after this timestamp has passed)
    **/
    public entry fun add_birthday_gift(
        account: &signer,
        address: address,
        amount: u64,
        birthday_timestamp_seconds: u64
    ) acquires DistributionStore {
        // TODO: check that the distribution store exists

        // TODO: set new birthday gift to new `amount` and `birthday_timestamp_seconds` (birthday_gift already exists, sum `amounts` and override the `birthday_timestamp_seconds`

        // TODO: transfer the `amount` from initiator to resource account
    }

    /**
    * Remove birthday gift from `DistributionStore.birthday_gifts`
    * @param account - account signer executing the function
    * @param address - `birthday_gifts` address
    **/
    public entry fun remove_birthday_gift(
        account: &signer,
        address: address,
    ) acquires DistributionStore {
        // TODO: check that the distribution store exists

        // TODO: if `birthday_gifts` exists, remove `birthday_gift` from table and transfer `amount` from resource account to initiator
    }

    /**
    * Claim birthday gift from `DistributionStore.birthday_gifts`
    * @param account - account signer executing the function
    * @param distribution_address - distribution contract address
    **/
    public entry fun claim_birthday_gift(
        account: &signer,
        distribution_address: address,
    ) acquires DistributionStore {
        // TODO: check that the distribution store exists

        // TODO: check that the `birthday_gift` exists

        // TODO: check that the `birthday_timestamp_seconds` has passed

        // TODO: remove `birthday_gift` from table and transfer `amount` from resource account to initiator
    }
}