11module smartunity ::nft_kiosk {
2+ use std::type_name::{get, TypeName };
23
3- use sui::object::{Self , ID };
4+ use smartunity::trading;
5+
6+ use sui::balance::{Self , Balance };
7+ use sui::coin::{Self , Coin };
8+ use sui::kiosk::Kiosk ;
9+ use sui::object::{Self , UID , ID };
10+ use sui::transfer::{Self , public_transfer};
411 use sui::tx_context::{TxContext , sender};
5- use sui::transfer::{public_share_object, public_transfer};
6- use sui::kiosk::{Self , Kiosk , KioskOwnerCap , uid_mut};
7- use sui::dynamic_field::{Self as df};
8- use sui::vec_set::{Self , VecSet };
9- use sui::table::{Self };
1012
11- /// Trying to withdraw profits and sender is not owner
12- const ENotOwner :u64 = 1001 ;
13- const ENotAuthorized :u64 = 1002 ;
13+ /// Error code for Not Enough payment
14+ const ENotEnoughFeeToPay : u64 = 1001 ;
15+ /// Error code for Invalid Coin Type when swap
16+ const ETransactionCoinNotInPool : u64 = 1002 ;
17+ /// Error code for Not Enough Coin X
18+ const ENotEnoughCoinX : u64 = 1003 ;
19+ /// Error code for Not Enough Coin Y
20+ const ENotEnoughCoinY : u64 = 1004 ;
21+ /// Error code for Not Enough Coin Z
22+ const ENotEnoughCoinZ : u64 = 1005 ;
23+ /// Error code for Not Enough balance in pool to swap
24+ const ENotEnoughBalanceInPool : u64 = 1006 ;
25+ /// Error code for Invalid Transaction Coin Type to Pay
26+ const EInvalidTrasnactionCoinType : u64 = 1007 ;
27+ /// Kiosk not in Trading Pool
28+ const ECollectionNotInTradingPool : u64 = 1008 ;
1429
15- /// For `Kiosk::id` value `Table<ID, NftRef>`
16- struct NftRefsDfKey has store , copy , drop {}
17- /// Hold the `KioskOwnerCap`
18- struct KioskOwnerCapDfKey has store , copy , drop {}
30+ /// Trading Pool for swap
31+ /// account: the address to receive the fee paied by transaction maker
32+ /// collection: collection holds the NFT items
33+ /// curve_type
34+ /// delta: price delta
35+ /// fee: fee of transactions, transaction maker pays it and send to address
36+ /// coin: transaction coin type
37+ /// init_price: NFT initialize price
38+ /// coin_sui, coin_stable, coin_self: balance of coin X,Y,Z
39+ struct TradePool <phantom X , phantom Y , phantom Z > has key , store {
40+ id: UID ,
41+ account: address ,
42+ collection: ID ,
43+ curve_type: vector <u8 >,
44+ fee: u64 ,
45+ coin: TypeName ,
46+ init_price: u64 ,
47+ coin_sui: Balance <X >,
48+ coin_stable: Balance <Y >,
49+ coin_self: Balance <Z >,
50+ }
1951
20- /// Stored as dynamic field for `NftRefsDfKey`
21- /// Holds NFT's information
22- struct NftRef has store , drop {
23- auths: VecSet <address >,
24- is_excusively_listed: bool ,
52+ /// generate the trading pool after deposit the NFTs
53+ public entry fun create_pair_nft_trade_pool <X , Y , Z , T , NFT : key + store >(
54+ collection: &mut Kiosk ,
55+ curve_type: vector <u8 >,
56+ fee: u64 ,
57+ init_price: u64 ,
58+ nft: NFT ,
59+ ctx: &mut TxContext ,
60+ ): ID {
61+ deposit_nft (collection, nft, ctx);
62+ let new_pool = TradePool <X , Y , Z > {
63+ id: object::new (ctx),
64+ account: sender (ctx),
65+ collection: object::id (collection),
66+ curve_type,
67+ coin: get <T >(),
68+ fee,
69+ init_price,
70+ coin_sui: balance::zero (),
71+ coin_stable: balance::zero (),
72+ coin_self: balance::zero (),
73+ };
74+ let pool_id = object::id (&new_pool);
75+ transfer::share_object (new_pool);
76+ pool_id
2577 }
2678
27- /// Create `Kiosk` for the sender and share it
28- public fun create_kiosk (ctx: &mut TxContext ): ID {
29- let owner = sender (ctx);
30- let (kiosk, kiosk_cap) = kiosk::new (ctx);
31- let kiosk_id = object::id (&kiosk);
32- kiosk::set_owner_custom (&mut kiosk, &kiosk_cap, owner);
33- insert_extension (&mut kiosk, kiosk_cap, ctx);
34- public_share_object (kiosk);
79+ /// Initialize the user's account
80+ public fun initialize_account (ctx: &mut TxContext ): ID {
81+ let kiosk_id = trading::create_kiosk (ctx);
3582 kiosk_id
3683 }
3784
85+ /// Function to deposit the NFT to Kiosk
86+ public fun deposit_nft <NFT : key + store >(kiosk: &mut Kiosk ,
87+ nft: NFT ,
88+ ctx: &mut TxContext ) {
89+ trading::deposit_nft (kiosk, nft, ctx);
90+ }
3891
39- fun insert_extension (
40- self: &mut Kiosk ,
41- kiosk_cap: KioskOwnerCap ,
42- ctx: &mut TxContext ,
43- ) {
44- assert !(kiosk::has_access (self, &kiosk_cap), ENotOwner );
45- let kiosk_ext = uid_mut (self);
46- df::add (kiosk_ext, KioskOwnerCapDfKey {}, kiosk_cap);
47- df::add (kiosk_ext, NftRefsDfKey {}, table::new <ID , NftRef >(ctx));
92+ /// Function to pay the fee
93+ fun pay <T >(payment: Coin <T >, amount: u64 , reciptant: address , ctx: &mut TxContext ) {
94+ assert !(coin::value (&payment) >= amount, ENotEnoughFeeToPay );
95+ public_transfer (coin::split (&mut payment, amount, ctx), reciptant);
96+ public_transfer (payment, sender (ctx));
4897 }
4998
50- public fun is_owner (self: &Kiosk , address : address ): bool {
51- let owner = kiosk::owner (self);
52- owner == address
99+ /// Split the balance of `T` from Pool
100+ /// and send to transaction maker when swap the NFT in
101+ fun split_from_balance <T >(self: &mut Balance <T >, amount: u64 , ctx: &mut TxContext ) {
102+ assert !(balance::value (self) >= amount, ENotEnoughBalanceInPool );
103+ let coin_t = coin::zero <T >(ctx);
104+ coin::join (&mut coin_t, coin::take <T >(self, amount, ctx));
105+ public_transfer (coin_t, sender (ctx));
53106 }
54107
55- public fun deposit_nft <NFT : key + store >(
56- self: &mut Kiosk ,
57- nft: NFT ,
58- _ctx: &mut TxContext ,
108+ /// Add the balance of `T` into pool
109+ /// after swap the NFT out
110+ fun add_to_balance <T >(self: &mut Balance <T >, coin_t: Coin <T >, amount: u64 , ctx: &mut TxContext ) {
111+ let coin_self_in = coin::split (&mut coin_t, amount, ctx);
112+ coin::put (self, coin_self_in);
113+ public_transfer (coin_t, sender (ctx));
114+ }
115+
116+ /// Swap Coin X by NFTs
117+ public entry fun swap_sui_for_nfts <X , Y , Z , T , NFT : key + store >(trade_pool: &mut TradePool <X , Y , Z >,
118+ kiosk: &mut Kiosk ,
119+ nft_id: ID ,
120+ payment: Coin <T >,
121+ coin_sui: Coin <X >,
122+ ctx: &mut TxContext
59123 ) {
60- let nft_id = object::id (&nft);
61- let refs = df::borrow_mut (uid_mut (self), NftRefsDfKey {});
62- table::add (refs, nft_id, NftRef {
63- auths: vec_set::empty (),
64- is_excusively_listed: false ,
65- });
66- let cap = pop_cap (self);
67- kiosk::place (self, &cap, nft);
68- set_cap (self, cap);
124+ assert !(get <T >() == trade_pool.coin, EInvalidTrasnactionCoinType );
125+ assert !(coin::value (&coin_sui) >= trade_pool.init_price, ENotEnoughCoinX );
126+ assert !(object::id (kiosk) == trade_pool.collection, ECollectionNotInTradingPool );
127+ pay (payment, trade_pool.fee, trade_pool.account, ctx);
128+ trading::withdraw_nft <NFT >(kiosk, nft_id, ctx);
129+ add_to_balance <X >(&mut trade_pool.coin_sui, coin_sui, trade_pool.init_price, ctx);
69130 }
70131
132+ /// Swap Coin Y by NFTs
133+ public entry fun swap_stable_coin_for_nfts <X , Y , Z , T , NFT : key + store >(trade_pool: &mut TradePool <X , Y , Z >,
134+ kiosk: &mut Kiosk ,
135+ nft_id: ID ,
136+ payment: Coin <T >,
137+ coin_stable: Coin <Y >,
138+ ctx: &mut TxContext
139+ ) {
140+ assert !(get <T >() == trade_pool.coin, EInvalidTrasnactionCoinType );
141+ assert !(coin::value (&coin_stable) >= trade_pool.init_price, ENotEnoughCoinX );
142+ assert !(object::id (kiosk) == trade_pool.collection, ECollectionNotInTradingPool );
143+ pay (payment, trade_pool.fee, trade_pool.account, ctx);
144+ trading::withdraw_nft <NFT >(kiosk, nft_id, ctx);
145+ add_to_balance <Y >(&mut trade_pool.coin_stable, coin_stable, trade_pool.init_price, ctx);
146+ }
71147
72- public fun withdraw_nft <NFT : key + store >(
73- self: &mut Kiosk ,
74- nft_id: ID ,
75- ctx: &mut TxContext
76- ){
77- let refs = df::borrow_mut (uid_mut (self), NftRefsDfKey {});
78- let _ref: NftRef = table::remove (refs, nft_id);
79- assert !(is_owner (self, sender (ctx)),ENotAuthorized );
80- let cap = pop_cap (self);
81- let nft = kiosk::take <NFT >(self, &cap, nft_id);
82- set_cap (self, cap);
83- public_transfer (nft, sender (ctx));
148+ /// Swap Coin Z by NFTs
149+ public entry fun swap_self_coin_for_nfts <X , Y , Z , T , NFT : key + store >(trade_pool: &mut TradePool <X , Y , Z >,
150+ kiosk: &mut Kiosk ,
151+ nft_id: ID ,
152+ payment: Coin <T >,
153+ coin_self: Coin <Z >,
154+ ctx: &mut TxContext
155+ ) {
156+ assert !(get <T >() == trade_pool.coin, EInvalidTrasnactionCoinType );
157+ assert !(coin::value (&coin_self) >= trade_pool.init_price, ENotEnoughCoinX );
158+ assert !(object::id (kiosk) == trade_pool.collection, ECollectionNotInTradingPool );
159+ pay (payment, trade_pool.fee, trade_pool.account, ctx);
160+ trading::withdraw_nft <NFT >(kiosk, nft_id, ctx);
161+ add_to_balance <Z >(&mut trade_pool.coin_self, coin_self, trade_pool.init_price, ctx);
84162 }
85163
86- /// Pop `KioskOwnerCap` from within the `Kiosk`
87- fun pop_cap (self: &mut Kiosk ): KioskOwnerCap {
88- df::remove (uid_mut (self), KioskOwnerCapDfKey {})
164+ /// Withdraw the NFT by the person who deposited it.
165+ public entry fun withdraw_nft <X , Y , Z , T , NFT : key + store >(trade_pool: &mut TradePool <X , Y , Z >,
166+ kiosk: &mut Kiosk ,
167+ nft_id: ID ,
168+ ctx: &mut TxContext ) {
169+ assert !(object::id (kiosk) == trade_pool.collection, ECollectionNotInTradingPool );
170+ trading::withdraw_nft <NFT >(kiosk, nft_id, ctx);
89171 }
90172
91- /// Return `KioskOwnerCap` to the `Kiosk`
92- fun set_cap (self: &mut Kiosk , cap: KioskOwnerCap ) {
93- df::add (uid_mut (self), KioskOwnerCapDfKey {}, cap);
173+ /// Swap the Coin X, Y, Z by deposit the NFT to pool
174+ public fun withdraw_coin <X , Y , Z , T , TCOIN , NFT : key + store >(trade_pool: &mut TradePool <X , Y , Z >,
175+ kiosk: &mut Kiosk ,
176+ nft: NFT ,
177+ payment: Coin <T >,
178+ ctx: &mut TxContext ) {
179+ assert !(
180+ get <TCOIN >() == get <X >() || get <TCOIN >() == get <Y >() || get <TCOIN >() == get <Z >(),
181+ ETransactionCoinNotInPool
182+ );
183+ assert !(get <T >() == trade_pool.coin, EInvalidTrasnactionCoinType );
184+ assert !(object::id (kiosk) == trade_pool.collection, ECollectionNotInTradingPool );
185+ pay (payment, trade_pool.fee, trade_pool.account, ctx);
186+ deposit_nft <NFT >(kiosk, nft, ctx);
187+ if (get <TCOIN >() == get <X >()) {
188+ split_from_balance <X >(&mut trade_pool.coin_sui, trade_pool.init_price, ctx);
189+ };
190+ if (get <TCOIN >() == get <Y >()) {
191+ split_from_balance <Y >(&mut trade_pool.coin_stable, trade_pool.init_price, ctx);
192+ };
193+ if (get <TCOIN >() == get <Z >()) {
194+ split_from_balance <Z >(&mut trade_pool.coin_self, trade_pool.init_price, ctx);
195+ };
94196 }
95- }
197+ }
0 commit comments