1
1
module smartunity ::nft_kiosk {
2
+ use std::type_name::{get, TypeName };
2
3
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};
4
11
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 };
10
12
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 ;
14
29
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
+ }
19
51
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
25
77
}
26
78
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);
35
82
kiosk_id
36
83
}
37
84
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
+ }
38
91
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));
48
97
}
49
98
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));
53
106
}
54
107
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
59
123
) {
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);
69
130
}
70
131
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
+ }
71
147
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);
84
162
}
85
163
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);
89
171
}
90
172
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
+ };
94
196
}
95
- }
197
+ }
0 commit comments