Icon Link检查点

Icon LinkSway 合约检查点

如果你按照之前的步骤正确操作,你的 main.sw 市场合约应该如下所示:

Icon LinkCheckpoint

Icon LinkSway Contract Checkpoint

If you have followed the previous steps correctly your main.sw marketplace contract should look like this:

contract;
 
use std::{
    auth::msg_sender,
    call_frames::msg_asset_id,
    context::{
        msg_amount,
        this_balance,
    },
    asset::transfer,
    hash::Hash,
};
 
struct Item {
    id: u64,
    price: u64,
    owner: Identity,
    metadata: str[20],
    total_bought: u64,
}
 
abi SwayStore {
    // a function to list an item for sale
    // takes the price and metadata as args
    #[storage(read, write)]
    fn list_item(price: u64, metadata: str[20]);
 
    // a function to buy an item
    // takes the item id as the arg
    #[storage(read, write), payable]
    fn buy_item(item_id: u64);
 
    // a function to get a certain item
    #[storage(read)]
    fn get_item(item_id: u64) -> Item;
 
    // a function to set the contract owner
    #[storage(read, write)]
    fn initialize_owner() -> Identity;
 
    // a function to withdraw contract funds
    #[storage(read)]
    fn withdraw_funds();
 
    // return the number of items listed
    #[storage(read)]
    fn get_count() -> u64;
}
 
storage {
    // counter for total items listed
    item_counter: u64 = 0,
 
    // map of item IDs to Items
    item_map: StorageMap<u64, Item> = StorageMap {},
 
    // owner of the contract
    owner: Option<Identity> = Option::None,
}
 
enum InvalidError {
    IncorrectAssetId: AssetId,
    NotEnoughTokens: u64,
    OnlyOwner: Identity,
}
 
impl SwayStore for Contract {
    #[storage(read, write)]
    fn list_item(price: u64, metadata: str[20]) {
        
        // increment the item counter
        storage.item_counter.write(storage.item_counter.try_read().unwrap() + 1);
        
        // get the message sender
        let sender = msg_sender().unwrap();
        
        // configure the item
        let new_item: Item = Item {
            id: storage.item_counter.try_read().unwrap(),
            price: price,
            owner: sender,
            metadata: metadata,
            total_bought: 0,
        };
 
        // save the new item to storage using the counter value
        storage.item_map.insert(storage.item_counter.try_read().unwrap(), new_item);
    }
 
    #[storage(read, write), payable]
    fn buy_item(item_id: u64) {
        // get the asset id for the asset sent
        let asset_id = msg_asset_id();
 
        // require that the correct asset was sent
        require(asset_id == AssetId::base(), InvalidError::IncorrectAssetId(asset_id));
 
        // get the amount of coins sent
        let amount = msg_amount();
 
        // get the item to buy
        let mut item = storage.item_map.get(item_id).try_read().unwrap();
 
        // require that the amount is at least the price of the item
        require(amount >= item.price, InvalidError::NotEnoughTokens(amount));
 
        // update the total amount bought
        item.total_bought += 1;
 
        // update the item in the storage map
        storage.item_map.insert(item_id, item);
 
        // only charge commission if price is more than 0.1 ETH
        if amount > 100_000_000 {
            // keep a 5% commission
            let commission = amount / 20;
            let new_amount = amount - commission;
            // send the payout minus commission to the seller
            transfer(item.owner, asset_id, new_amount);
        } else {
            // send the full payout to the seller
            transfer(item.owner, asset_id, amount);
        }
    }
 
    #[storage(read)]
    fn get_item(item_id: u64) -> Item {
        // returns the item for the given item_id
        return storage.item_map.get(item_id).try_read().unwrap();
    }
 
    #[storage(read, write)]
    fn initialize_owner() -> Identity {
        let owner = storage.owner.try_read().unwrap();
        
        // make sure the owner has NOT already been initialized
        require(owner.is_none(), "owner already initialized");
        
        // get the identity of the sender        
        let sender = msg_sender().unwrap(); 
 
        // set the owner to the sender's identity
        storage.owner.write(Option::Some(sender));
        
        // return the owner
        return sender;
    }
 
    #[storage(read)]
    fn withdraw_funds() {
        let owner = storage.owner.try_read().unwrap();
 
        // make sure the owner has been initialized
        require(owner.is_some(), "owner not initialized");
        
        let sender = msg_sender().unwrap(); 
 
        // require the sender to be the owner
        require(sender == owner.unwrap(), InvalidError::OnlyOwner(sender));
        
        // get the current balance of this contract for the base asset
        let amount = this_balance(AssetId::base());
 
        // require the contract balance to be more than 0
        require(amount > 0, InvalidError::NotEnoughTokens(amount));
        
        // send the amount to the owner
        transfer(owner.unwrap(), AssetId::base(), amount);
    }
 
    #[storage(read)]
    fn get_count() -> u64 {
        return storage.item_counter.try_read().unwrap();
    }
}

Icon Link构建合约

以下是精简后的说明:

要格式化你的合约,请执行以下命令:

forc fmt

要编译你的合约,请转到合约文件夹并运行:

forc build

恭喜!你已成功用 Sway 编写了一个完整的合约!

编译后,系统将自动生成 abi.jsonstorage_slots.jsoncontract.bin。你可以在以下目录找到这些文件:

contract/out/debug/*

Icon Link部署合约

有关部署此合约的详细步骤,请参阅官方 Fuel 开发人员计数器 DApp 指南: 部署合约

要部署,请使用以下命令,如果你已经设置了 forc-wallet 并且在你的账户中有测试网资金。如果没有,请按照上面的说明进行操作。

forc deploy --testnet

部署后,你将能够在 contract/out/deployments 文件夹中找到你的合约 ID。你将需要这个 ID 进行前端集成。