1use super::*;
26use crate::traits::{
27 fungible::imbalance,
28 tokens::{
29 fungibles, DepositConsequence, Fortitude, Precision, Preservation, Provenance, Restriction,
30 WithdrawConsequence,
31 },
32};
33use frame_support::traits::fungible::hold::DoneSlash;
34use sp_core::Get;
35use sp_runtime::{DispatchError, DispatchResult};
36
37pub struct ItemOf<
40 F: fungibles::Inspect<AccountId>,
41 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
42 AccountId,
43>(core::marker::PhantomData<(F, A, AccountId)>);
44
45impl<
46 F: fungibles::Inspect<AccountId>,
47 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
48 AccountId,
49 > Inspect<AccountId> for ItemOf<F, A, AccountId>
50{
51 type Balance = <F as fungibles::Inspect<AccountId>>::Balance;
52 fn total_issuance() -> Self::Balance {
53 <F as fungibles::Inspect<AccountId>>::total_issuance(A::get())
54 }
55 fn active_issuance() -> Self::Balance {
56 <F as fungibles::Inspect<AccountId>>::active_issuance(A::get())
57 }
58 fn minimum_balance() -> Self::Balance {
59 <F as fungibles::Inspect<AccountId>>::minimum_balance(A::get())
60 }
61 fn balance(who: &AccountId) -> Self::Balance {
62 <F as fungibles::Inspect<AccountId>>::balance(A::get(), who)
63 }
64 fn total_balance(who: &AccountId) -> Self::Balance {
65 <F as fungibles::Inspect<AccountId>>::total_balance(A::get(), who)
66 }
67 fn reducible_balance(
68 who: &AccountId,
69 preservation: Preservation,
70 force: Fortitude,
71 ) -> Self::Balance {
72 <F as fungibles::Inspect<AccountId>>::reducible_balance(A::get(), who, preservation, force)
73 }
74 fn can_deposit(
75 who: &AccountId,
76 amount: Self::Balance,
77 provenance: Provenance,
78 ) -> DepositConsequence {
79 <F as fungibles::Inspect<AccountId>>::can_deposit(A::get(), who, amount, provenance)
80 }
81 fn can_withdraw(who: &AccountId, amount: Self::Balance) -> WithdrawConsequence<Self::Balance> {
82 <F as fungibles::Inspect<AccountId>>::can_withdraw(A::get(), who, amount)
83 }
84}
85
86impl<
87 F: fungibles::InspectHold<AccountId>,
88 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
89 AccountId,
90 > InspectHold<AccountId> for ItemOf<F, A, AccountId>
91{
92 type Reason = F::Reason;
93
94 fn reducible_total_balance_on_hold(who: &AccountId, force: Fortitude) -> Self::Balance {
95 <F as fungibles::InspectHold<AccountId>>::reducible_total_balance_on_hold(
96 A::get(),
97 who,
98 force,
99 )
100 }
101 fn hold_available(reason: &Self::Reason, who: &AccountId) -> bool {
102 <F as fungibles::InspectHold<AccountId>>::hold_available(A::get(), reason, who)
103 }
104 fn total_balance_on_hold(who: &AccountId) -> Self::Balance {
105 <F as fungibles::InspectHold<AccountId>>::total_balance_on_hold(A::get(), who)
106 }
107 fn balance_on_hold(reason: &Self::Reason, who: &AccountId) -> Self::Balance {
108 <F as fungibles::InspectHold<AccountId>>::balance_on_hold(A::get(), reason, who)
109 }
110 fn can_hold(reason: &Self::Reason, who: &AccountId, amount: Self::Balance) -> bool {
111 <F as fungibles::InspectHold<AccountId>>::can_hold(A::get(), reason, who, amount)
112 }
113}
114
115impl<
116 F: fungibles::InspectFreeze<AccountId>,
117 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
118 AccountId,
119 > InspectFreeze<AccountId> for ItemOf<F, A, AccountId>
120{
121 type Id = F::Id;
122 fn balance_frozen(id: &Self::Id, who: &AccountId) -> Self::Balance {
123 <F as fungibles::InspectFreeze<AccountId>>::balance_frozen(A::get(), id, who)
124 }
125 fn balance_freezable(who: &AccountId) -> Self::Balance {
126 <F as fungibles::InspectFreeze<AccountId>>::balance_freezable(A::get(), who)
127 }
128 fn can_freeze(id: &Self::Id, who: &AccountId) -> bool {
129 <F as fungibles::InspectFreeze<AccountId>>::can_freeze(A::get(), id, who)
130 }
131}
132
133impl<
134 F: fungibles::Unbalanced<AccountId>,
135 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
136 AccountId,
137 > Unbalanced<AccountId> for ItemOf<F, A, AccountId>
138{
139 fn handle_dust(dust: regular::Dust<AccountId, Self>)
140 where
141 Self: Sized,
142 {
143 <F as fungibles::Unbalanced<AccountId>>::handle_dust(fungibles::Dust(A::get(), dust.0))
144 }
145 fn write_balance(
146 who: &AccountId,
147 amount: Self::Balance,
148 ) -> Result<Option<Self::Balance>, DispatchError> {
149 <F as fungibles::Unbalanced<AccountId>>::write_balance(A::get(), who, amount)
150 }
151 fn set_total_issuance(amount: Self::Balance) -> () {
152 <F as fungibles::Unbalanced<AccountId>>::set_total_issuance(A::get(), amount)
153 }
154 fn decrease_balance(
155 who: &AccountId,
156 amount: Self::Balance,
157 precision: Precision,
158 preservation: Preservation,
159 force: Fortitude,
160 ) -> Result<Self::Balance, DispatchError> {
161 <F as fungibles::Unbalanced<AccountId>>::decrease_balance(
162 A::get(),
163 who,
164 amount,
165 precision,
166 preservation,
167 force,
168 )
169 }
170 fn increase_balance(
171 who: &AccountId,
172 amount: Self::Balance,
173 precision: Precision,
174 ) -> Result<Self::Balance, DispatchError> {
175 <F as fungibles::Unbalanced<AccountId>>::increase_balance(A::get(), who, amount, precision)
176 }
177}
178
179impl<
180 F: fungibles::UnbalancedHold<AccountId>,
181 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
182 AccountId,
183 > UnbalancedHold<AccountId> for ItemOf<F, A, AccountId>
184{
185 fn set_balance_on_hold(
186 reason: &Self::Reason,
187 who: &AccountId,
188 amount: Self::Balance,
189 ) -> DispatchResult {
190 <F as fungibles::UnbalancedHold<AccountId>>::set_balance_on_hold(
191 A::get(),
192 reason,
193 who,
194 amount,
195 )
196 }
197 fn decrease_balance_on_hold(
198 reason: &Self::Reason,
199 who: &AccountId,
200 amount: Self::Balance,
201 precision: Precision,
202 ) -> Result<Self::Balance, DispatchError> {
203 <F as fungibles::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
204 A::get(),
205 reason,
206 who,
207 amount,
208 precision,
209 )
210 }
211 fn increase_balance_on_hold(
212 reason: &Self::Reason,
213 who: &AccountId,
214 amount: Self::Balance,
215 precision: Precision,
216 ) -> Result<Self::Balance, DispatchError> {
217 <F as fungibles::UnbalancedHold<AccountId>>::increase_balance_on_hold(
218 A::get(),
219 reason,
220 who,
221 amount,
222 precision,
223 )
224 }
225}
226
227impl<
228 F: fungibles::Mutate<AccountId>,
229 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
230 AccountId: Eq,
231 > Mutate<AccountId> for ItemOf<F, A, AccountId>
232{
233 fn mint_into(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
234 <F as fungibles::Mutate<AccountId>>::mint_into(A::get(), who, amount)
235 }
236 fn burn_from(
237 who: &AccountId,
238 amount: Self::Balance,
239 preservation: Preservation,
240 precision: Precision,
241 force: Fortitude,
242 ) -> Result<Self::Balance, DispatchError> {
243 <F as fungibles::Mutate<AccountId>>::burn_from(
244 A::get(),
245 who,
246 amount,
247 preservation,
248 precision,
249 force,
250 )
251 }
252 fn shelve(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
253 <F as fungibles::Mutate<AccountId>>::shelve(A::get(), who, amount)
254 }
255 fn restore(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
256 <F as fungibles::Mutate<AccountId>>::restore(A::get(), who, amount)
257 }
258 fn transfer(
259 source: &AccountId,
260 dest: &AccountId,
261 amount: Self::Balance,
262 preservation: Preservation,
263 ) -> Result<Self::Balance, DispatchError> {
264 <F as fungibles::Mutate<AccountId>>::transfer(A::get(), source, dest, amount, preservation)
265 }
266
267 fn set_balance(who: &AccountId, amount: Self::Balance) -> Self::Balance {
268 <F as fungibles::Mutate<AccountId>>::set_balance(A::get(), who, amount)
269 }
270}
271
272impl<
273 F: fungibles::MutateHold<AccountId>,
274 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
275 AccountId,
276 > MutateHold<AccountId> for ItemOf<F, A, AccountId>
277{
278 fn hold(reason: &Self::Reason, who: &AccountId, amount: Self::Balance) -> DispatchResult {
279 <F as fungibles::MutateHold<AccountId>>::hold(A::get(), reason, who, amount)
280 }
281 fn release(
282 reason: &Self::Reason,
283 who: &AccountId,
284 amount: Self::Balance,
285 precision: Precision,
286 ) -> Result<Self::Balance, DispatchError> {
287 <F as fungibles::MutateHold<AccountId>>::release(A::get(), reason, who, amount, precision)
288 }
289 fn burn_held(
290 reason: &Self::Reason,
291 who: &AccountId,
292 amount: Self::Balance,
293 precision: Precision,
294 force: Fortitude,
295 ) -> Result<Self::Balance, DispatchError> {
296 <F as fungibles::MutateHold<AccountId>>::burn_held(
297 A::get(),
298 reason,
299 who,
300 amount,
301 precision,
302 force,
303 )
304 }
305 fn transfer_on_hold(
306 reason: &Self::Reason,
307 source: &AccountId,
308 dest: &AccountId,
309 amount: Self::Balance,
310 precision: Precision,
311 mode: Restriction,
312 force: Fortitude,
313 ) -> Result<Self::Balance, DispatchError> {
314 <F as fungibles::MutateHold<AccountId>>::transfer_on_hold(
315 A::get(),
316 reason,
317 source,
318 dest,
319 amount,
320 precision,
321 mode,
322 force,
323 )
324 }
325 fn transfer_and_hold(
326 reason: &Self::Reason,
327 source: &AccountId,
328 dest: &AccountId,
329 amount: Self::Balance,
330 precision: Precision,
331 preservation: Preservation,
332 force: Fortitude,
333 ) -> Result<Self::Balance, DispatchError> {
334 <F as fungibles::MutateHold<AccountId>>::transfer_and_hold(
335 A::get(),
336 reason,
337 source,
338 dest,
339 amount,
340 precision,
341 preservation,
342 force,
343 )
344 }
345}
346
347impl<
348 F: fungibles::MutateFreeze<AccountId>,
349 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
350 AccountId,
351 > MutateFreeze<AccountId> for ItemOf<F, A, AccountId>
352{
353 fn set_freeze(id: &Self::Id, who: &AccountId, amount: Self::Balance) -> DispatchResult {
354 <F as fungibles::MutateFreeze<AccountId>>::set_freeze(A::get(), id, who, amount)
355 }
356 fn extend_freeze(id: &Self::Id, who: &AccountId, amount: Self::Balance) -> DispatchResult {
357 <F as fungibles::MutateFreeze<AccountId>>::extend_freeze(A::get(), id, who, amount)
358 }
359 fn thaw(id: &Self::Id, who: &AccountId) -> DispatchResult {
360 <F as fungibles::MutateFreeze<AccountId>>::thaw(A::get(), id, who)
361 }
362}
363
364pub struct ConvertImbalanceDropHandler<AccountId, Balance, AssetIdType, AssetId, Handler>(
365 core::marker::PhantomData<(AccountId, Balance, AssetIdType, AssetId, Handler)>,
366);
367
368impl<
369 AccountId,
370 Balance,
371 AssetIdType,
372 AssetId: Get<AssetIdType>,
373 Handler: crate::traits::fungibles::HandleImbalanceDrop<AssetIdType, Balance>,
374 > HandleImbalanceDrop<Balance>
375 for ConvertImbalanceDropHandler<AccountId, Balance, AssetIdType, AssetId, Handler>
376{
377 fn handle(amount: Balance) {
378 Handler::handle(AssetId::get(), amount)
379 }
380}
381
382impl<
383 F: fungibles::Inspect<AccountId>
384 + fungibles::Unbalanced<AccountId>
385 + fungibles::Balanced<AccountId>,
386 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
387 AccountId,
388 > Balanced<AccountId> for ItemOf<F, A, AccountId>
389{
390 type OnDropDebt =
391 ConvertImbalanceDropHandler<AccountId, Self::Balance, F::AssetId, A, F::OnDropDebt>;
392 type OnDropCredit =
393 ConvertImbalanceDropHandler<AccountId, Self::Balance, F::AssetId, A, F::OnDropCredit>;
394 fn deposit(
395 who: &AccountId,
396 value: Self::Balance,
397 precision: Precision,
398 ) -> Result<Debt<AccountId, Self>, DispatchError> {
399 <F as fungibles::Balanced<AccountId>>::deposit(A::get(), who, value, precision)
400 .map(imbalance::from_fungibles)
401 }
402 fn issue(amount: Self::Balance) -> Credit<AccountId, Self> {
403 let credit = <F as fungibles::Balanced<AccountId>>::issue(A::get(), amount);
404 imbalance::from_fungibles(credit)
405 }
406 fn pair(
407 amount: Self::Balance,
408 ) -> Result<(Debt<AccountId, Self>, Credit<AccountId, Self>), DispatchError> {
409 let (a, b) = <F as fungibles::Balanced<AccountId>>::pair(A::get(), amount)?;
410 Ok((imbalance::from_fungibles(a), imbalance::from_fungibles(b)))
411 }
412 fn rescind(amount: Self::Balance) -> Debt<AccountId, Self> {
413 let debt = <F as fungibles::Balanced<AccountId>>::rescind(A::get(), amount);
414 imbalance::from_fungibles(debt)
415 }
416 fn resolve(
417 who: &AccountId,
418 credit: Credit<AccountId, Self>,
419 ) -> Result<(), Credit<AccountId, Self>> {
420 let credit = fungibles::imbalance::from_fungible(credit, A::get());
421 <F as fungibles::Balanced<AccountId>>::resolve(who, credit)
422 .map_err(imbalance::from_fungibles)
423 }
424 fn settle(
425 who: &AccountId,
426 debt: Debt<AccountId, Self>,
427 preservation: Preservation,
428 ) -> Result<Credit<AccountId, Self>, Debt<AccountId, Self>> {
429 let debt = fungibles::imbalance::from_fungible(debt, A::get());
430 <F as fungibles::Balanced<AccountId>>::settle(who, debt, preservation).map_or_else(
431 |d| Err(imbalance::from_fungibles(d)),
432 |c| Ok(imbalance::from_fungibles(c)),
433 )
434 }
435 fn withdraw(
436 who: &AccountId,
437 value: Self::Balance,
438 precision: Precision,
439 preservation: Preservation,
440 force: Fortitude,
441 ) -> Result<Credit<AccountId, Self>, DispatchError> {
442 <F as fungibles::Balanced<AccountId>>::withdraw(
443 A::get(),
444 who,
445 value,
446 precision,
447 preservation,
448 force,
449 )
450 .map(imbalance::from_fungibles)
451 }
452}
453
454impl<
455 F: fungibles::BalancedHold<AccountId>,
456 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
457 AccountId,
458 > BalancedHold<AccountId> for ItemOf<F, A, AccountId>
459{
460 fn slash(
461 reason: &Self::Reason,
462 who: &AccountId,
463 amount: Self::Balance,
464 ) -> (Credit<AccountId, Self>, Self::Balance) {
465 let (credit, amount) =
466 <F as fungibles::BalancedHold<AccountId>>::slash(A::get(), reason, who, amount);
467 (imbalance::from_fungibles(credit), amount)
468 }
469}
470
471impl<
472 F: fungibles::BalancedHold<AccountId>,
473 A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
474 AccountId,
475 > DoneSlash<F::Reason, AccountId, F::Balance> for ItemOf<F, A, AccountId>
476{
477 fn done_slash(reason: &F::Reason, who: &AccountId, amount: F::Balance) {
478 <F as fungibles::hold::DoneSlash<F::AssetId, F::Reason, AccountId, F::Balance>>::done_slash(
479 A::get(),
480 reason,
481 who,
482 amount,
483 )
484 }
485}
486
487#[test]
488fn test() {}