如果你按照之前的步骤正确操作,你的 main.sw
市场合约应该如下所示:
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();
}
}
以下是精简后的说明:
要格式化你的合约,请执行以下命令:
forc fmt
要编译你的合约,请转到合约文件夹并运行:
forc build
恭喜!你已成功用 Sway 编写了一个完整的合约!
编译后,系统将自动生成 abi.json
、storage_slots.json
和 contract.bin
。你可以在以下目录找到这些文件:
contract/out/debug/*
有关部署此合约的详细步骤,请参阅官方 Fuel 开发人员计数器 DApp 指南: 部署合约
要部署,请使用以下命令,如果你已经设置了 forc-wallet 并且在你的账户中有测试网资金。如果没有,请按照上面的说明进行操作。
forc deploy --testnet
部署后,你将能够在 contract/out/deployments
文件夹中找到你的合约 ID。你将需要这个 ID 进行前端集成。