drt_sc_modules/bonding_curve/utils/
user_endpoints.rs1drt_sc::imports!();
2drt_sc::derive_imports!();
3
4use drt_sc::contract_base::ManagedSerializer;
5
6use crate::bonding_curve::{
7 curves::curve_function::CurveFunction,
8 utils::{events, storage, structs::BondingCurve},
9};
10
11#[drt_sc::module]
12pub trait UserEndpointsModule: storage::StorageModule + events::EventsModule {
13 fn sell_token<T>(&self)
14 where
15 T: CurveFunction<Self::Api>
16 + TopEncode
17 + TopDecode
18 + NestedEncode
19 + NestedDecode
20 + TypeAbi
21 + PartialEq
22 + Default,
23 {
24 let (offered_token, nonce, sell_amount) = self.call_value().single_dcdt().into_tuple();
25 let _ = self.check_owned_return_payment_token::<T>(&offered_token, &sell_amount);
26
27 let (calculated_price, payment_token) =
28 self.bonding_curve(&offered_token).update(|buffer| {
29 let serializer = ManagedSerializer::new();
30
31 let mut bonding_curve: BondingCurve<Self::Api, T> =
32 serializer.top_decode_from_managed_buffer(buffer);
33
34 require!(
35 bonding_curve.sell_availability,
36 "Selling is not available on this token"
37 );
38 let price = self.compute_sell_price::<T>(&offered_token, &sell_amount);
39 bonding_curve.payment.amount -= &price;
40 bonding_curve.arguments.balance += &sell_amount;
41 let payment_token = bonding_curve.payment_token();
42 *buffer = serializer.top_encode_to_managed_buffer(&bonding_curve);
43 (price, payment_token)
44 });
45
46 let caller = self.blockchain().get_caller();
47
48 self.nonce_amount(&offered_token, nonce)
49 .update(|val| *val += sell_amount);
50
51 self.tx()
52 .to(&caller)
53 .rewa_or_single_dcdt(&payment_token, 0u64, &calculated_price)
54 .transfer();
55
56 self.token_details(&offered_token)
57 .update(|details| details.add_nonce(nonce));
58
59 self.sell_token_event(&caller, &calculated_price);
60 }
61
62 fn buy_token<T>(
63 &self,
64 requested_amount: BigUint,
65 requested_token: TokenIdentifier,
66 requested_nonce: OptionalValue<u64>,
67 ) where
68 T: CurveFunction<Self::Api>
69 + TopEncode
70 + TopDecode
71 + NestedEncode
72 + NestedDecode
73 + TypeAbi
74 + PartialEq
75 + Default,
76 {
77 let (offered_token, payment) = self.call_value().rewa_or_single_fungible_dcdt();
78 let payment_token =
79 self.check_owned_return_payment_token::<T>(&requested_token, &requested_amount);
80 self.check_given_token(&payment_token, &offered_token);
81
82 let calculated_price = self.bonding_curve(&requested_token).update(|buffer| {
83 let serializer = ManagedSerializer::new();
84
85 let mut bonding_curve: BondingCurve<Self::Api, T> =
86 serializer.top_decode_from_managed_buffer(buffer);
87
88 let price = self.compute_buy_price::<T>(&requested_token, &requested_amount);
89 require!(
90 price <= payment,
91 "The payment provided is not enough for the transaction"
92 );
93 bonding_curve.payment.amount += &price;
94 bonding_curve.arguments.balance -= &requested_amount;
95 *buffer = serializer.top_encode_to_managed_buffer(&bonding_curve);
96
97 price
98 });
99
100 let caller = self.blockchain().get_caller();
101
102 match requested_nonce {
103 OptionalValue::Some(nonce) => {
104 self.tx()
105 .to(&caller)
106 .single_dcdt(&requested_token, nonce, &requested_amount)
107 .transfer();
108 if self.nonce_amount(&requested_token, nonce).get() - requested_amount.clone() > 0 {
109 self.nonce_amount(&requested_token, nonce)
110 .update(|val| *val -= requested_amount.clone());
111 } else {
112 self.nonce_amount(&requested_token, nonce).clear();
113 self.token_details(&requested_token)
114 .update(|details| details.remove_nonce(nonce));
115 }
116 },
117 OptionalValue::None => {
118 self.send_next_available_tokens(&caller, requested_token, requested_amount);
119 },
120 };
121
122 self.tx()
123 .to(&caller)
124 .rewa_or_single_dcdt(&offered_token, 0u64, &(&payment - &calculated_price))
125 .transfer();
126
127 self.buy_token_event(&caller, &calculated_price);
128 }
129
130 fn send_next_available_tokens(
131 &self,
132 caller: &ManagedAddress,
133 token: TokenIdentifier,
134 amount: BigUint,
135 ) {
136 let mut nonces = self.token_details(&token).get().token_nonces;
137 let mut total_amount = amount;
138 let mut tokens_to_send = ManagedVec::<Self::Api, DcdtTokenPayment<Self::Api>>::new();
139 loop {
140 require!(!nonces.is_empty(), "Insufficient balance");
141 let nonce = nonces.get(0);
142 let available_amount = self.nonce_amount(&token, nonce).get();
143
144 let amount_to_send: BigUint;
145 if available_amount <= total_amount {
146 amount_to_send = available_amount.clone();
147 total_amount -= amount_to_send.clone();
148 self.nonce_amount(&token, nonce).clear();
149 nonces.remove(0);
150 } else {
151 self.nonce_amount(&token, nonce)
152 .update(|val| *val -= total_amount.clone());
153 amount_to_send = total_amount.clone();
154 total_amount = BigUint::zero();
155 }
156 tokens_to_send.push(DcdtTokenPayment::new(token.clone(), nonce, amount_to_send));
157 if total_amount == BigUint::zero() {
158 break;
159 }
160 }
161
162 self.tx().to(caller).multi_dcdt(tokens_to_send).transfer();
163
164 self.token_details(&token)
165 .update(|token_ownership| token_ownership.token_nonces = nonces);
166 }
167
168 fn get_buy_price<T>(&self, amount: BigUint, identifier: TokenIdentifier) -> BigUint
169 where
170 T: CurveFunction<Self::Api>
171 + TopEncode
172 + TopDecode
173 + NestedEncode
174 + NestedDecode
175 + TypeAbi
176 + PartialEq
177 + Default,
178 {
179 self.check_token_exists(&identifier);
180 self.compute_buy_price::<T>(&identifier, &amount)
181 }
182
183 fn get_sell_price<T>(&self, amount: BigUint, identifier: TokenIdentifier) -> BigUint
184 where
185 T: CurveFunction<Self::Api>
186 + TopEncode
187 + TopDecode
188 + NestedEncode
189 + NestedDecode
190 + TypeAbi
191 + PartialEq
192 + Default,
193 {
194 self.check_token_exists(&identifier);
195 self.compute_sell_price::<T>(&identifier, &amount)
196 }
197
198 fn check_token_exists(&self, issued_token: &TokenIdentifier) {
199 require!(
200 !self.bonding_curve(issued_token).is_empty(),
201 "Token is not issued yet!"
202 );
203 }
204
205 #[view(getTokenAvailability)]
206 fn get_token_availability(
207 &self,
208 identifier: TokenIdentifier,
209 ) -> MultiValueEncoded<MultiValue2<u64, BigUint>> {
210 let token_nonces = self.token_details(&identifier).get().token_nonces;
211 let mut availability = MultiValueEncoded::new();
212
213 for current_check_nonce in &token_nonces {
214 availability.push(MultiValue2((
215 current_check_nonce,
216 self.nonce_amount(&identifier, current_check_nonce).get(),
217 )));
218 }
219 availability
220 }
221
222 fn check_owned_return_payment_token<T>(
223 &self,
224 issued_token: &TokenIdentifier,
225 amount: &BigUint,
226 ) -> RewaOrDcdtTokenIdentifier
227 where
228 T: CurveFunction<Self::Api>
229 + TopEncode
230 + TopDecode
231 + NestedEncode
232 + NestedDecode
233 + TypeAbi
234 + PartialEq
235 + Default,
236 {
237 self.check_token_exists(issued_token);
238
239 let serializer = ManagedSerializer::new();
240 let bonding_curve: BondingCurve<Self::Api, T> =
241 serializer.top_decode_from_managed_buffer(&self.bonding_curve(issued_token).get());
242
243 require!(
244 bonding_curve.curve != T::default(),
245 "The token price was not set yet!"
246 );
247 require!(amount > &BigUint::zero(), "Must pay more than 0 tokens!");
248 bonding_curve.payment_token()
249 }
250
251 fn check_given_token(
252 &self,
253 accepted_token: &RewaOrDcdtTokenIdentifier,
254 given_token: &RewaOrDcdtTokenIdentifier,
255 ) {
256 require!(
257 given_token == accepted_token,
258 "Only {} tokens accepted",
259 accepted_token
260 );
261 }
262
263 fn compute_buy_price<T>(&self, identifier: &TokenIdentifier, amount: &BigUint) -> BigUint
264 where
265 T: CurveFunction<Self::Api>
266 + TopEncode
267 + TopDecode
268 + NestedEncode
269 + NestedDecode
270 + TypeAbi
271 + PartialEq
272 + Default,
273 {
274 let serializer = ManagedSerializer::new();
275 let bonding_curve: BondingCurve<Self::Api, T> =
276 serializer.top_decode_from_managed_buffer(&self.bonding_curve(identifier).get());
277
278 let arguments = &bonding_curve.arguments;
279 let function_selector = &bonding_curve.curve;
280
281 let token_start = &arguments.first_token_available();
282 function_selector.calculate_price(token_start, amount, arguments)
283 }
284
285 fn compute_sell_price<T>(&self, identifier: &TokenIdentifier, amount: &BigUint) -> BigUint
286 where
287 T: CurveFunction<Self::Api>
288 + TopEncode
289 + TopDecode
290 + NestedEncode
291 + NestedDecode
292 + TypeAbi
293 + PartialEq
294 + Default,
295 {
296 let serializer = ManagedSerializer::new();
297 let bonding_curve: BondingCurve<Self::Api, T> =
298 serializer.top_decode_from_managed_buffer(&self.bonding_curve(identifier).get());
299
300 let arguments = &bonding_curve.arguments;
301 let function_selector = &bonding_curve.curve;
302
303 let token_start = arguments.first_token_available() - amount;
304 function_selector.calculate_price(&token_start, amount, arguments)
305 }
306}