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