1- module @ minimarket ::minimarket {
1+ module minimarket ::minimarket {
22 use std::signer;
33 use std::vector;
44
5- /// Ошибки
65 const E_ALREADY_INITIALIZED : u64 = 1 ;
76 const E_NOT_INITIALIZED : u64 = 2 ;
87 const E_BAD_FEE_BPS : u64 = 3 ;
@@ -12,31 +11,26 @@ module @minimarket::minimarket {
1211 const E_NOT_LISTED : u64 = 7 ;
1312 const E_PRICE_MISMATCH : u64 = 8 ;
1413
15- /// Простая запись о лоте
1614 struct Item has drop , store {
1715 seller: address ,
1816 price: u64 ,
1917 listed: bool ,
2018 }
2119
22- /// Баланс внутри модуля (псевдо-коины для демо)
2320 struct Balance has drop , store {
2421 owner: address ,
2522 amount: u64 ,
2623 }
2724
28- /// Синглтон маркетплейса, хранится под адресом администратора (инициатора init).
2925 struct Market has key {
3026 admin: address ,
31- fee_bps: u64 , // 0..=10_000
32- fees_accumulated: u64 , // Накопленные комиссии
33- items: vector <Item >, // По индексу = item_id
34- balances: vector <Balance >, // Простая "карта": поиск по адресу линейный
27+ fee_bps: u64 ,
28+ fees_accumulated: u64 ,
29+ items: vector <Item >,
30+ balances: vector <Balance >,
3531 initialized: bool ,
3632 }
3733
38- /// === helpers ===
39-
4034 fun assert_initialized (market_addr: address ) {
4135 assert ! (exists <Market >(market_addr), E_NOT_INITIALIZED );
4236 }
@@ -46,30 +40,24 @@ module @minimarket::minimarket {
4640 }
4741
4842 fun get_mut (market_addr: address ): &mut Market acquires Market {
49- let m = borrow_global_mut <Market >(market_addr);
50- m
43+ borrow_global_mut <Market >(market_addr)
5144 }
5245
5346 fun get (market_addr: address ): &Market acquires Market {
54- let m = borrow_global <Market >(market_addr);
55- m
47+ borrow_global <Market >(market_addr)
5648 }
5749
58- /// Найти индекс баланса по адресу, либо вернуть опционально None.
5950 fun find_balance_index (balances: &vector <Balance >, owner: address ): (bool , u64 ) {
6051 let i = 0 u64 ;
6152 let len = vector ::length (balances);
6253 while (i < len) {
6354 let b = vector ::borrow (balances, i);
64- if (b.owner == owner) {
65- return (true , i)
66- };
55+ if (b.owner == owner) return (true , i);
6756 i = i + 1 ;
6857 };
6958 (false , 0 )
7059 }
7160
72- /// Кредитовать внутренний баланс.
7361 fun credit_balance (balances: &mut vector <Balance >, owner: address , amount: u64 ) {
7462 let (found, idx) = find_balance_index (balances, owner);
7563 if (found) {
@@ -80,9 +68,7 @@ module @minimarket::minimarket {
8068 }
8169 }
8270
83- /// === entry ===
84-
85- /// Инициализация маркетплейса под адресом администратора (signer).
71+ /// init(admin, fee_bps: 0..=10000)
8672 public entry fun init (admin: &signer , fee_bps: u64 ) acquires Market {
8773 let admin_addr = signer ::address_of (admin);
8874 assert ! (!exists <Market >(admin_addr), E_ALREADY_INITIALIZED );
@@ -98,7 +84,7 @@ module @minimarket::minimarket {
9884 });
9985 }
10086
101- /// Размещение лота . Если item_id == len, пушим новый; если меньше len — ячейка должна быть свободна .
87+ /// list(item_id, price) . Если item_id == len(items) — добавляем новый слот .
10288 public entry fun list (seller: &signer , market_addr: address , item_id: u64 , price: u64 ) acquires Market {
10389 assert_initialized (market_addr);
10490 let seller_addr = signer ::address_of (seller);
@@ -110,15 +96,14 @@ module @minimarket::minimarket {
11096 } else {
11197 assert ! (item_id < len, E_BAD_ITEM_ID );
11298 let it = vector ::borrow_mut (&mut m.items, item_id);
113- // Разрешаем перезалистинг только если ячейка свободна
11499 assert ! (!it.listed, E_ALREADY_LISTED );
115100 it.seller = seller_addr;
116101 it.price = price;
117102 it.listed = true ;
118103 }
119104 }
120105
121- /// Покупка лота. Внутренняя «оплата»: увеличиваем баланс продавца, удерживаем комиссию в пуле.
106+ /// buy(item_id, pay_amount == price). Комиссия удерживается в пуле.
122107 public entry fun buy (buyer: &signer , market_addr: address , item_id: u64 , pay_amount: u64 ) acquires Market {
123108 assert_initialized (market_addr);
124109 let m = get_mut (market_addr);
@@ -129,19 +114,16 @@ module @minimarket::minimarket {
129114 assert ! (it.listed, E_NOT_LISTED );
130115 assert ! (pay_amount == it.price, E_PRICE_MISMATCH );
131116
132- // комиссия: (price * fee_bps) / 10000
133117 let fee = (it.price * m.fee_bps) / 10000 ;
134118 let seller_amount = it.price - fee;
135119
136- // начисляем продавцу, накапливаем комиссию
137120 credit_balance (&mut m.balances, it.seller, seller_amount);
138121 m.fees_accumulated = m.fees_accumulated + fee;
139122
140- // снимаем лот
141123 it.listed = false ;
142124 }
143125
144- /// Вывод комиссий админом во внутренний баланс админа
126+ /// withdraw_fees(): админ зачисляет накопленную комиссию на свой внутренний баланс.
145127 public entry fun withdraw_fees (admin: &signer , market_addr: address ) acquires Market {
146128 assert_initialized (market_addr);
147129 let caller = signer ::address_of (admin);
@@ -155,29 +137,19 @@ module @minimarket::minimarket {
155137 }
156138 }
157139
158- /// Просмотр баланса (для тестов/ демо)
140+ /// Просмотр внутреннего баланса (для демо/тестов )
159141 public fun view_balance (market_addr: address , owner: address ): u64 acquires Market {
160142 let m = get (market_addr);
161143 let (found, idx) = find_balance_index (&m.balances, owner);
162144 if (!found) { 0 } else { vector ::borrow (&m.balances, idx).amount }
163145 }
164146
165- /// Демонстрационная процедура (сценарий happy-path)
147+ /// Быстрый сценарий: init(2.5%), list(0,10_000), buy, withdraw_fees.
166148 public entry fun entry_demo (admin: &signer ) acquires Market {
167- // 1) init с 250 bps = 2.5%
168149 init (admin, 250 );
169150 let admin_addr = signer ::address_of (admin);
170-
171- // 2) Продавец = админ для простоты. Листинг item_id=0 по цене 10_000
172151 list (admin, admin_addr, 0 , 10_000 );
173-
174- // 3) Покупка тем же аккаунтом для демо (в реале будет другой signer)
175152 buy (admin, admin_addr, 0 , 10_000 );
176-
177- // 4) Вывод комиссии админом
178153 withdraw_fees (admin, admin_addr);
179- // Теперь у админа во внутреннем балансе 10_000 (от продажи) + 250 (комиссия) не будет,
180- // комиссия не прибавляется к продавцу; продавцу ушло 9_750, комиссия 250 ушла в пул и затем на баланс админа.
181- // Проверки оставляем в юнит-тестах.
182154 }
183155}
0 commit comments