Hello again my fellow SuiMove travellers. I am trying to build my first Kiosk app. My script is as below:
#[allow(unused)]
module try::kiosk;
use std::string::{Self, String};
use sui::coin::{Self, Coin};
use sui::sui::SUI;
use sui::package::{Self, Publisher};
use sui::transfer_policy::{Self, TransferPolicy, TransferPolicyCap, TransferRequest};
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
const EIncorrectArgument: u64 = 0;
const EInsufficientAmount: u64 = 1;
const MAX_BPS: u16 = 10_000;
// Item for trade
public struct Item has key, store {
id: UID,
name: String,
}
// One-time-witness for publisher
public struct KIOSK has drop {}
// Rule for policy
public struct Rule has drop {}
// Config for rule
public struct Config has store, drop {
amount_bp: u16,
min_amount: u64,
}
// Init publisher
fun init(otw: KIOSK, ctx: &mut TxContext) {
let publisher = package::claim(otw, ctx);
transfer::public_transfer(publisher, tx_context::sender(ctx));
}
// Create kiosk
public entry fun new_kiosk(ctx: &mut TxContext) {
let (kiosk, kiosk_owner_cap) = kiosk::new(ctx);
transfer::public_share_object(kiosk);
transfer::public_transfer(kiosk_owner_cap, tx_context::sender(ctx));
}
// Create item
public entry fun new_item(name: vector<u8>, ctx: &mut TxContext) {
transfer::transfer(Item {
id: object::new(ctx),
name: string::utf8(name),
}, tx_context::sender(ctx));
}
// Place item in kiosk
public entry fun place_item(
kiosk: &mut Kiosk,
kiosk_cap: &KioskOwnerCap,
item: Item) {
kiosk::place(kiosk, kiosk_cap, item);
}
// List item for sale
public entry fun list_item(
kiosk: &mut Kiosk,
kiosk_cap: &KioskOwnerCap,
item_id: ID,
price: u64) {
kiosk::list<Item>(kiosk, kiosk_cap, item_id, price);
}
// Create TransferPolicy & TransferPolicyCap
#[allow(lint(share_owned, self_transfer))]
public entry fun new_policy(publisher: &Publisher, ctx: &mut TxContext) {
let (policy, policy_cap) = transfer_policy::new<Item>(publisher, ctx);
transfer::public_share_object(policy);
transfer::public_transfer(policy_cap, tx_context::sender(ctx));
}
// Add rule to policy
public entry fun add_rule(
policy: &mut TransferPolicy<Item>,
policy_cap: &TransferPolicyCap<Item>,
amount_bp: u16,
min_amount: u64) {
assert!(amount_bp <= MAX_BPS, EIncorrectArgument);
transfer_policy::add_rule(Rule {}, policy, policy_cap, Config { amount_bp, min_amount });
}
// Pay the royalty fee
public fun pay_fee(
policy: &mut TransferPolicy<Item>,
request: &mut TransferRequest<Item>,
payment: Coin<SUI>) {
let paid = transfer_policy::paid(request);
let amount = fee_amount(policy, paid);
assert!(coin::value(&payment) == amount, EInsufficientAmount);
transfer_policy::add_to_balance(Rule {}, policy, payment);
transfer_policy::add_receipt(Rule {}, request);
}
// Calculate the royalty fee
public fun fee_amount(policy: &TransferPolicy<Item>, paid: u64): u64 {
let config: &Config = transfer_policy::get_rule(Rule {}, policy);
let mut amount = (((paid as u128) * (config.amount_bp as u128) / 10_000) as u64);
if (amount < config.min_amount) {
amount = config.min_amount
};
amount
}
// Purchase item from kiosk - IS THIS WHERE ALL GOES HAYWIRE ????
public entry fun buy_item(
kiosk: &mut Kiosk,
item_id: ID,
payment: Coin<SUI>,
policy: &TransferPolicy<Item>,
buyer: address) {
let (item, request) = kiosk::purchase(kiosk, item_id, payment);
pay_fee(policy, &mut request, payment);
transfer_policy::confirm_request<Item>(policy, request);
transfer::public_transfer(item, buyer);
}
When I compile it I get the following error msg:
error[E04006]: invalid subtype
โโ ./sources/try.move:138:9
โ
107 โ policy: &mut TransferPolicy<Item>,
โ ------------------------- Expected: '&mut sui::transfer_policy::TransferPolicy<try::kiosk::Item>'
ยท
135 โ policy: &TransferPolicy<Item>,
โ --------------------- Given: '&sui::transfer_policy::TransferPolicy<try::kiosk::Item>'
ยท
138 โ pay_fee(policy, &mut request, payment);
โ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Invalid call of 'try::kiosk::pay_fee'. Invalid argument for parameter 'policy'
Failed to build Move modules: Compilation error.
If I comment out the last entry function buy_item the code compiles. It runs succesfully on the SUI Client CLI (Sui Explorer is a bit whimsical at times and I have yet to tame SUI PTB).
I realize that the flow of purchasing from Kiosk should be:
Buyer โ kiosk::purchase() โ Item + TransferRequest โ Subsequent calls to fulfill TransferRequest โ transfer_policy::confirm_request() โ Transfer Item under ownership
I confess that I am unable to implement that in code. Any help would be dearly appreciated.
I thank you in advance.
Theodoros