見出し画像

【Sui直コンバトル】1st - コントラクトとコード

コントラクト

https://suivision.xyz/package/0x0a5c57a8b67f78a9186276d06aada84029d9dd362dd56eb4d6deb41bbda4c407

コード

module onigiri::chokucon_battle_first {

    // === Imports ===

    use std::string::{utf8, String};

    use sui::sui::{SUI};
    use sui::balance::{Self, Balance};
    use sui::coin::{Self, Coin};
    use sui::display::{Self, Display};
    use sui::package::{Self};
    use sui::table::{Self, Table};

    // === Errors ===

    const EDirectorIsPaused: u64 = 100;
    const ENotWhitelisted: u64 = 101;
    const EAlreadyMinted: u64 = 102;
    const EAlreadyRewarded: u64 = 103;

    // === Constants ===

    const MINT_SUCCESS_REWARD_SUI: u64 = 5_000_000_000; // 5 SUI

    // === Structs ===

    public struct CHOKUCON_BATTLE_FIRST has drop {}

    public struct AdminCap has store, key {
        id: UID,
    }

    public struct Director has key, store {
        id: UID,
        paused: bool,
        participants: Table<address, bool>,
        minted: Table<address, bool>,
        rewarded: Table<address, bool>,
        mint_success_reward: Balance<SUI>,
    }

    public struct ChallengerNFT has key, store {
        id: UID,
    }

    public struct MasterNFT has key, store {
        id: UID,
    }

    public struct Reward<phantom T> has key {
        id: UID,
        balance: Balance<T>,
    }

    // === Initialization ===

    fun init(otw: CHOKUCON_BATTLE_FIRST,  ctx: &mut TxContext) {
        let challenger_keys = vector[
            utf8(b"name"),
            utf8(b"image_url")
        ];

        let challenger_values = vector[
            utf8(b"Chokucon Battle 1st Challenger NFT"),
            utf8(b"https://yefpkulasxjrieeyvjzj.supabase.co/storage/v1/object/public/images/Chokucon_Battle_1st_Challenger_NFT.png"),
        ];

        let master_keys = vector[
            utf8(b"name"),
            utf8(b"image_url")
        ];

        let master_values = vector[
            utf8(b"Chokucon Battle 1st Master NFT"),
            utf8(b"https://yefpkulasxjrieeyvjzj.supabase.co/storage/v1/object/public/images/Chokucon_Battle_1st_Master_NFT.png"),
        ];

        let publisher = package::claim(otw, ctx);

        let mut challenger_display = display::new_with_fields<ChallengerNFT>(&publisher, challenger_keys, challenger_values, ctx);
        display::update_version(&mut challenger_display);

        let mut master_display = display::new_with_fields<MasterNFT>(&publisher, master_keys, master_values, ctx);
        display::update_version(&mut master_display);

        transfer::public_transfer(challenger_display, ctx.sender());
        transfer::public_transfer(master_display, ctx.sender());

        transfer::public_transfer(publisher, ctx.sender());

        transfer::transfer(AdminCap {
            id: object::new(ctx),
        }, ctx.sender());

        transfer::share_object(Director {
            id: object::new(ctx),
            paused: true,
            participants: table::new<address, bool>(ctx),
            minted: table::new<address, bool>(ctx),
            rewarded: table::new<address, bool>(ctx),
            mint_success_reward: balance::zero(),
        });
    }

    // === Public Functions ===

    entry public fun mint(director: &mut Director, ctx: &mut TxContext) {
        assert!(director.paused == false, EDirectorIsPaused);
        assert!(table::contains(&director.participants, ctx.sender()) == true, ENotWhitelisted);
        assert!(table::contains(&director.minted, ctx.sender()) == false, EAlreadyMinted);

        let reward_balance = director.mint_success_reward.split(MINT_SUCCESS_REWARD_SUI);
        transfer::public_transfer(coin::from_balance(reward_balance, ctx), ctx.sender());

        table::add(&mut director.minted, ctx.sender(), true);

        transfer::transfer(ChallengerNFT { id: object::new(ctx) }, ctx.sender());
    }

    entry public fun get_reward<T>(_: &ChallengerNFT, director: &mut Director, reward: &mut Reward<T>, ctx: &mut TxContext) {
        assert!(director.paused == false, EDirectorIsPaused);
        assert!(table::contains(&director.participants, ctx.sender()) == true, ENotWhitelisted);
        assert!(table::contains(&director.rewarded, ctx.sender()) == false, EAlreadyRewarded);


        let balance = reward.balance.withdraw_all();
        transfer::public_transfer(coin::from_balance(balance, ctx), ctx.sender());

        table::add(&mut director.rewarded, ctx.sender(), true);

        transfer::transfer(MasterNFT { id: object::new(ctx) }, ctx.sender());
    }

    entry public fun add_reward<T>(c: Coin<T>, ctx: &mut TxContext) {
        transfer::share_object(Reward {
            id: object::new(ctx),
            balance: c.into_balance(),
        });
    }

    entry public fun add_mint_success_reward(director: &mut Director, c: Coin<SUI>) {
        director.mint_success_reward.join(c.into_balance());
    }

    // === Admin functions ===

    public fun admin_pause(_: &AdminCap, director: &mut Director) {
        director.paused = true;
    }

    public fun admin_resume(_: &AdminCap, director: &mut Director) {
        director.paused = false;
    }

    public fun admin_add_participants(_: &AdminCap, director: &mut Director, mut participants: vector<address>) {
        let mut i = participants.length();
        while (i > 0) {
            let p = participants.pop_back();
            if (table::contains(&director.participants, p) == false) {
                table::add(&mut director.participants, p, true);
            };
            i = i - 1;
        };
    }

    public fun admin_update_image_url(_: &AdminCap, display: &mut Display<ChallengerNFT>, image_url: String) {
        display.edit(utf8(b"image_url"), image_url);
        display::update_version(display);
    }

    entry public fun admin_withdraw_reward<T>(_: &AdminCap, reward: &mut Reward<T>, ctx: &mut TxContext) {
        let balance = reward.balance.withdraw_all();
        transfer::public_transfer(coin::from_balance(balance, ctx), ctx.sender());
    }

    entry public fun admin_withdraw_mint_reward(_: &AdminCap, director: &mut Director, ctx: &mut TxContext) {
        let balance = director.mint_success_reward.withdraw_all();
        transfer::public_transfer(coin::from_balance(balance, ctx), ctx.sender());
    }
}

この記事が気に入ったらサポートをしてみませんか?