1use frame_support::traits::{
23 tokens::{
24 fungibles, fungibles::imbalance, AssetId, DepositConsequence, Fortitude, Precision,
25 Preservation, Provenance, Restriction, WithdrawConsequence,
26 },
27 AccountTouch,
28};
29use sp_runtime::{
30 traits::Convert,
31 DispatchError, DispatchResult, Either,
32 Either::{Left, Right},
33};
34
35pub struct UnionOf<Left, Right, Criterion, AssetKind, AccountId>(
44 core::marker::PhantomData<(Left, Right, Criterion, AssetKind, AccountId)>,
45);
46
47impl<
48 Left: fungibles::Inspect<AccountId>,
49 Right: fungibles::Inspect<AccountId, Balance = Left::Balance>,
50 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
51 AssetKind: AssetId,
52 AccountId,
53 > fungibles::Inspect<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
54{
55 type AssetId = AssetKind;
56 type Balance = Left::Balance;
57
58 fn total_issuance(asset: Self::AssetId) -> Self::Balance {
59 match Criterion::convert(asset) {
60 Left(a) => <Left as fungibles::Inspect<AccountId>>::total_issuance(a),
61 Right(a) => <Right as fungibles::Inspect<AccountId>>::total_issuance(a),
62 }
63 }
64 fn active_issuance(asset: Self::AssetId) -> Self::Balance {
65 match Criterion::convert(asset) {
66 Left(a) => <Left as fungibles::Inspect<AccountId>>::active_issuance(a),
67 Right(a) => <Right as fungibles::Inspect<AccountId>>::active_issuance(a),
68 }
69 }
70 fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
71 match Criterion::convert(asset) {
72 Left(a) => <Left as fungibles::Inspect<AccountId>>::minimum_balance(a),
73 Right(a) => <Right as fungibles::Inspect<AccountId>>::minimum_balance(a),
74 }
75 }
76 fn balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
77 match Criterion::convert(asset) {
78 Left(a) => <Left as fungibles::Inspect<AccountId>>::balance(a, who),
79 Right(a) => <Right as fungibles::Inspect<AccountId>>::balance(a, who),
80 }
81 }
82 fn total_balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
83 match Criterion::convert(asset) {
84 Left(a) => <Left as fungibles::Inspect<AccountId>>::total_balance(a, who),
85 Right(a) => <Right as fungibles::Inspect<AccountId>>::total_balance(a, who),
86 }
87 }
88 fn reducible_balance(
89 asset: Self::AssetId,
90 who: &AccountId,
91 preservation: Preservation,
92 force: Fortitude,
93 ) -> Self::Balance {
94 match Criterion::convert(asset) {
95 Left(a) => <Left as fungibles::Inspect<AccountId>>::reducible_balance(
96 a,
97 who,
98 preservation,
99 force,
100 ),
101 Right(a) => <Right as fungibles::Inspect<AccountId>>::reducible_balance(
102 a,
103 who,
104 preservation,
105 force,
106 ),
107 }
108 }
109 fn can_deposit(
110 asset: Self::AssetId,
111 who: &AccountId,
112 amount: Self::Balance,
113 provenance: Provenance,
114 ) -> DepositConsequence {
115 match Criterion::convert(asset) {
116 Left(a) => {
117 <Left as fungibles::Inspect<AccountId>>::can_deposit(a, who, amount, provenance)
118 },
119 Right(a) => {
120 <Right as fungibles::Inspect<AccountId>>::can_deposit(a, who, amount, provenance)
121 },
122 }
123 }
124 fn can_withdraw(
125 asset: Self::AssetId,
126 who: &AccountId,
127 amount: Self::Balance,
128 ) -> WithdrawConsequence<Self::Balance> {
129 match Criterion::convert(asset) {
130 Left(a) => <Left as fungibles::Inspect<AccountId>>::can_withdraw(a, who, amount),
131 Right(a) => <Right as fungibles::Inspect<AccountId>>::can_withdraw(a, who, amount),
132 }
133 }
134 fn asset_exists(asset: Self::AssetId) -> bool {
135 match Criterion::convert(asset) {
136 Left(a) => <Left as fungibles::Inspect<AccountId>>::asset_exists(a),
137 Right(a) => <Right as fungibles::Inspect<AccountId>>::asset_exists(a),
138 }
139 }
140}
141
142impl<
143 Left: fungibles::Inspect<AccountId> + fungibles::metadata::Inspect<AccountId>,
144 Right: fungibles::Inspect<AccountId, Balance = Left::Balance>
145 + fungibles::metadata::Inspect<AccountId>,
146 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
147 AssetKind: AssetId,
148 AccountId,
149 > fungibles::metadata::Inspect<AccountId>
150 for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
151{
152 fn name(asset: Self::AssetId) -> alloc::vec::Vec<u8> {
153 match Criterion::convert(asset) {
154 Left(a) => <Left as fungibles::metadata::Inspect<AccountId>>::name(a),
155 Right(a) => <Right as fungibles::metadata::Inspect<AccountId>>::name(a),
156 }
157 }
158 fn symbol(asset: Self::AssetId) -> alloc::vec::Vec<u8> {
159 match Criterion::convert(asset) {
160 Left(a) => <Left as fungibles::metadata::Inspect<AccountId>>::symbol(a),
161 Right(a) => <Right as fungibles::metadata::Inspect<AccountId>>::symbol(a),
162 }
163 }
164 fn decimals(asset: Self::AssetId) -> u8 {
165 match Criterion::convert(asset) {
166 Left(a) => <Left as fungibles::metadata::Inspect<AccountId>>::decimals(a),
167 Right(a) => <Right as fungibles::metadata::Inspect<AccountId>>::decimals(a),
168 }
169 }
170}
171
172impl<
173 Left: fungibles::Inspect<AccountId> + fungibles::roles::Inspect<AccountId>,
174 Right: fungibles::Inspect<AccountId, Balance = Left::Balance>
175 + fungibles::roles::Inspect<AccountId>,
176 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
177 AssetKind: AssetId,
178 AccountId,
179 > fungibles::roles::Inspect<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
180{
181 fn owner(asset: Self::AssetId) -> Option<AccountId> {
182 match Criterion::convert(asset) {
183 Left(a) => <Left as fungibles::roles::Inspect<AccountId>>::owner(a),
184 Right(a) => <Right as fungibles::roles::Inspect<AccountId>>::owner(a),
185 }
186 }
187 fn issuer(asset: Self::AssetId) -> Option<AccountId> {
188 match Criterion::convert(asset) {
189 Left(a) => <Left as fungibles::roles::Inspect<AccountId>>::issuer(a),
190 Right(a) => <Right as fungibles::roles::Inspect<AccountId>>::issuer(a),
191 }
192 }
193 fn admin(asset: Self::AssetId) -> Option<AccountId> {
194 match Criterion::convert(asset) {
195 Left(a) => <Left as fungibles::roles::Inspect<AccountId>>::admin(a),
196 Right(a) => <Right as fungibles::roles::Inspect<AccountId>>::admin(a),
197 }
198 }
199 fn freezer(asset: Self::AssetId) -> Option<AccountId> {
200 match Criterion::convert(asset) {
201 Left(a) => <Left as fungibles::roles::Inspect<AccountId>>::freezer(a),
202 Right(a) => <Right as fungibles::roles::Inspect<AccountId>>::freezer(a),
203 }
204 }
205}
206
207impl<
208 Left: fungibles::Inspect<AccountId>
209 + fungibles::metadata::Inspect<AccountId>
210 + fungibles::metadata::Mutate<AccountId>,
211 Right: fungibles::Inspect<AccountId, Balance = Left::Balance>
212 + fungibles::metadata::Inspect<AccountId>
213 + fungibles::metadata::Mutate<AccountId>,
214 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
215 AssetKind: AssetId,
216 AccountId,
217 > fungibles::metadata::Mutate<AccountId>
218 for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
219{
220 fn set(
221 asset: Self::AssetId,
222 from: &AccountId,
223 name: alloc::vec::Vec<u8>,
224 symbol: alloc::vec::Vec<u8>,
225 decimals: u8,
226 ) -> DispatchResult {
227 match Criterion::convert(asset) {
228 Left(a) => <Left as fungibles::metadata::Mutate<AccountId>>::set(
229 a, from, name, symbol, decimals,
230 ),
231 Right(a) => <Right as fungibles::metadata::Mutate<AccountId>>::set(
232 a, from, name, symbol, decimals,
233 ),
234 }
235 }
236}
237
238impl<
239 Left: fungibles::InspectHold<AccountId>,
240 Right: fungibles::InspectHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
241 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
242 AssetKind: AssetId,
243 AccountId,
244 > fungibles::InspectHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
245{
246 type Reason = Left::Reason;
247
248 fn reducible_total_balance_on_hold(
249 asset: Self::AssetId,
250 who: &AccountId,
251 force: Fortitude,
252 ) -> Self::Balance {
253 match Criterion::convert(asset) {
254 Left(a) => {
255 <Left as fungibles::InspectHold<AccountId>>::reducible_total_balance_on_hold(
256 a, who, force,
257 )
258 },
259 Right(a) => {
260 <Right as fungibles::InspectHold<AccountId>>::reducible_total_balance_on_hold(
261 a, who, force,
262 )
263 },
264 }
265 }
266 fn hold_available(asset: Self::AssetId, reason: &Self::Reason, who: &AccountId) -> bool {
267 match Criterion::convert(asset) {
268 Left(a) => <Left as fungibles::InspectHold<AccountId>>::hold_available(a, reason, who),
269 Right(a) => {
270 <Right as fungibles::InspectHold<AccountId>>::hold_available(a, reason, who)
271 },
272 }
273 }
274 fn total_balance_on_hold(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
275 match Criterion::convert(asset) {
276 Left(a) => <Left as fungibles::InspectHold<AccountId>>::total_balance_on_hold(a, who),
277 Right(a) => <Right as fungibles::InspectHold<AccountId>>::total_balance_on_hold(a, who),
278 }
279 }
280 fn balance_on_hold(
281 asset: Self::AssetId,
282 reason: &Self::Reason,
283 who: &AccountId,
284 ) -> Self::Balance {
285 match Criterion::convert(asset) {
286 Left(a) => <Left as fungibles::InspectHold<AccountId>>::balance_on_hold(a, reason, who),
287 Right(a) => {
288 <Right as fungibles::InspectHold<AccountId>>::balance_on_hold(a, reason, who)
289 },
290 }
291 }
292 fn can_hold(
293 asset: Self::AssetId,
294 reason: &Self::Reason,
295 who: &AccountId,
296 amount: Self::Balance,
297 ) -> bool {
298 match Criterion::convert(asset) {
299 Left(a) => {
300 <Left as fungibles::InspectHold<AccountId>>::can_hold(a, reason, who, amount)
301 },
302 Right(a) => {
303 <Right as fungibles::InspectHold<AccountId>>::can_hold(a, reason, who, amount)
304 },
305 }
306 }
307}
308
309impl<
310 Left: fungibles::InspectFreeze<AccountId>,
311 Right: fungibles::InspectFreeze<AccountId, Balance = Left::Balance, Id = Left::Id>,
312 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
313 AssetKind: AssetId,
314 AccountId,
315 > fungibles::InspectFreeze<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
316{
317 type Id = Left::Id;
318 fn balance_frozen(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> Self::Balance {
319 match Criterion::convert(asset) {
320 Left(a) => <Left as fungibles::InspectFreeze<AccountId>>::balance_frozen(a, id, who),
321 Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::balance_frozen(a, id, who),
322 }
323 }
324 fn balance_freezable(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
325 match Criterion::convert(asset) {
326 Left(a) => <Left as fungibles::InspectFreeze<AccountId>>::balance_freezable(a, who),
327 Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::balance_freezable(a, who),
328 }
329 }
330 fn can_freeze(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> bool {
331 match Criterion::convert(asset) {
332 Left(a) => <Left as fungibles::InspectFreeze<AccountId>>::can_freeze(a, id, who),
333 Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::can_freeze(a, id, who),
334 }
335 }
336}
337
338impl<
339 Left: fungibles::Unbalanced<AccountId>,
340 Right: fungibles::Unbalanced<AccountId, Balance = Left::Balance>,
341 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
342 AssetKind: AssetId,
343 AccountId,
344 > fungibles::Unbalanced<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
345{
346 fn handle_dust(dust: fungibles::Dust<AccountId, Self>)
347 where
348 Self: Sized,
349 {
350 match Criterion::convert(dust.0) {
351 Left(a) => {
352 <Left as fungibles::Unbalanced<AccountId>>::handle_dust(fungibles::Dust(a, dust.1))
353 },
354 Right(a) => {
355 <Right as fungibles::Unbalanced<AccountId>>::handle_dust(fungibles::Dust(a, dust.1))
356 },
357 }
358 }
359 fn write_balance(
360 asset: Self::AssetId,
361 who: &AccountId,
362 amount: Self::Balance,
363 ) -> Result<Option<Self::Balance>, DispatchError> {
364 match Criterion::convert(asset) {
365 Left(a) => <Left as fungibles::Unbalanced<AccountId>>::write_balance(a, who, amount),
366 Right(a) => <Right as fungibles::Unbalanced<AccountId>>::write_balance(a, who, amount),
367 }
368 }
369 fn set_total_issuance(asset: Self::AssetId, amount: Self::Balance) -> () {
370 match Criterion::convert(asset) {
371 Left(a) => <Left as fungibles::Unbalanced<AccountId>>::set_total_issuance(a, amount),
372 Right(a) => <Right as fungibles::Unbalanced<AccountId>>::set_total_issuance(a, amount),
373 }
374 }
375 fn decrease_balance(
376 asset: Self::AssetId,
377 who: &AccountId,
378 amount: Self::Balance,
379 precision: Precision,
380 preservation: Preservation,
381 force: Fortitude,
382 ) -> Result<Self::Balance, DispatchError> {
383 match Criterion::convert(asset) {
384 Left(a) => <Left as fungibles::Unbalanced<AccountId>>::decrease_balance(
385 a,
386 who,
387 amount,
388 precision,
389 preservation,
390 force,
391 ),
392 Right(a) => <Right as fungibles::Unbalanced<AccountId>>::decrease_balance(
393 a,
394 who,
395 amount,
396 precision,
397 preservation,
398 force,
399 ),
400 }
401 }
402 fn increase_balance(
403 asset: Self::AssetId,
404 who: &AccountId,
405 amount: Self::Balance,
406 precision: Precision,
407 ) -> Result<Self::Balance, DispatchError> {
408 match Criterion::convert(asset) {
409 Left(a) => <Left as fungibles::Unbalanced<AccountId>>::increase_balance(
410 a, who, amount, precision,
411 ),
412 Right(a) => <Right as fungibles::Unbalanced<AccountId>>::increase_balance(
413 a, who, amount, precision,
414 ),
415 }
416 }
417}
418
419impl<
420 Left: fungibles::UnbalancedHold<AccountId>,
421 Right: fungibles::UnbalancedHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
422 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
423 AssetKind: AssetId,
424 AccountId,
425 > fungibles::UnbalancedHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
426{
427 fn set_balance_on_hold(
428 asset: Self::AssetId,
429 reason: &Self::Reason,
430 who: &AccountId,
431 amount: Self::Balance,
432 ) -> DispatchResult {
433 match Criterion::convert(asset) {
434 Left(a) => <Left as fungibles::UnbalancedHold<AccountId>>::set_balance_on_hold(
435 a, reason, who, amount,
436 ),
437 Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::set_balance_on_hold(
438 a, reason, who, amount,
439 ),
440 }
441 }
442 fn decrease_balance_on_hold(
443 asset: Self::AssetId,
444 reason: &Self::Reason,
445 who: &AccountId,
446 amount: Self::Balance,
447 precision: Precision,
448 ) -> Result<Self::Balance, DispatchError> {
449 match Criterion::convert(asset) {
450 Left(a) => <Left as fungibles::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
451 a, reason, who, amount, precision,
452 ),
453 Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
454 a, reason, who, amount, precision,
455 ),
456 }
457 }
458 fn increase_balance_on_hold(
459 asset: Self::AssetId,
460 reason: &Self::Reason,
461 who: &AccountId,
462 amount: Self::Balance,
463 precision: Precision,
464 ) -> Result<Self::Balance, DispatchError> {
465 match Criterion::convert(asset) {
466 Left(a) => <Left as fungibles::UnbalancedHold<AccountId>>::increase_balance_on_hold(
467 a, reason, who, amount, precision,
468 ),
469 Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::increase_balance_on_hold(
470 a, reason, who, amount, precision,
471 ),
472 }
473 }
474}
475
476impl<
477 Left: fungibles::Mutate<AccountId>,
478 Right: fungibles::Mutate<AccountId, Balance = Left::Balance>,
479 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
480 AssetKind: AssetId,
481 AccountId: Eq,
482 > fungibles::Mutate<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
483{
484 fn mint_into(
485 asset: Self::AssetId,
486 who: &AccountId,
487 amount: Self::Balance,
488 ) -> Result<Self::Balance, DispatchError> {
489 match Criterion::convert(asset) {
490 Left(a) => <Left as fungibles::Mutate<AccountId>>::mint_into(a, who, amount),
491 Right(a) => <Right as fungibles::Mutate<AccountId>>::mint_into(a, who, amount),
492 }
493 }
494 fn burn_from(
495 asset: Self::AssetId,
496 who: &AccountId,
497 amount: Self::Balance,
498 preservation: Preservation,
499 precision: Precision,
500 force: Fortitude,
501 ) -> Result<Self::Balance, DispatchError> {
502 match Criterion::convert(asset) {
503 Left(a) => <Left as fungibles::Mutate<AccountId>>::burn_from(
504 a,
505 who,
506 amount,
507 preservation,
508 precision,
509 force,
510 ),
511 Right(a) => <Right as fungibles::Mutate<AccountId>>::burn_from(
512 a,
513 who,
514 amount,
515 preservation,
516 precision,
517 force,
518 ),
519 }
520 }
521 fn shelve(
522 asset: Self::AssetId,
523 who: &AccountId,
524 amount: Self::Balance,
525 ) -> Result<Self::Balance, DispatchError> {
526 match Criterion::convert(asset) {
527 Left(a) => <Left as fungibles::Mutate<AccountId>>::shelve(a, who, amount),
528 Right(a) => <Right as fungibles::Mutate<AccountId>>::shelve(a, who, amount),
529 }
530 }
531 fn restore(
532 asset: Self::AssetId,
533 who: &AccountId,
534 amount: Self::Balance,
535 ) -> Result<Self::Balance, DispatchError> {
536 match Criterion::convert(asset) {
537 Left(a) => <Left as fungibles::Mutate<AccountId>>::restore(a, who, amount),
538 Right(a) => <Right as fungibles::Mutate<AccountId>>::restore(a, who, amount),
539 }
540 }
541 fn transfer(
542 asset: Self::AssetId,
543 source: &AccountId,
544 dest: &AccountId,
545 amount: Self::Balance,
546 preservation: Preservation,
547 ) -> Result<Self::Balance, DispatchError> {
548 match Criterion::convert(asset) {
549 Left(a) => <Left as fungibles::Mutate<AccountId>>::transfer(
550 a,
551 source,
552 dest,
553 amount,
554 preservation,
555 ),
556 Right(a) => <Right as fungibles::Mutate<AccountId>>::transfer(
557 a,
558 source,
559 dest,
560 amount,
561 preservation,
562 ),
563 }
564 }
565
566 fn set_balance(asset: Self::AssetId, who: &AccountId, amount: Self::Balance) -> Self::Balance {
567 match Criterion::convert(asset) {
568 Left(a) => <Left as fungibles::Mutate<AccountId>>::set_balance(a, who, amount),
569 Right(a) => <Right as fungibles::Mutate<AccountId>>::set_balance(a, who, amount),
570 }
571 }
572}
573
574impl<
575 Left: fungibles::MutateHold<AccountId>,
576 Right: fungibles::MutateHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
577 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
578 AssetKind: AssetId,
579 AccountId,
580 > fungibles::MutateHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
581{
582 fn hold(
583 asset: Self::AssetId,
584 reason: &Self::Reason,
585 who: &AccountId,
586 amount: Self::Balance,
587 ) -> DispatchResult {
588 match Criterion::convert(asset) {
589 Left(a) => <Left as fungibles::MutateHold<AccountId>>::hold(a, reason, who, amount),
590 Right(a) => <Right as fungibles::MutateHold<AccountId>>::hold(a, reason, who, amount),
591 }
592 }
593 fn release(
594 asset: Self::AssetId,
595 reason: &Self::Reason,
596 who: &AccountId,
597 amount: Self::Balance,
598 precision: Precision,
599 ) -> Result<Self::Balance, DispatchError> {
600 match Criterion::convert(asset) {
601 Left(a) => <Left as fungibles::MutateHold<AccountId>>::release(
602 a, reason, who, amount, precision,
603 ),
604 Right(a) => <Right as fungibles::MutateHold<AccountId>>::release(
605 a, reason, who, amount, precision,
606 ),
607 }
608 }
609 fn burn_held(
610 asset: Self::AssetId,
611 reason: &Self::Reason,
612 who: &AccountId,
613 amount: Self::Balance,
614 precision: Precision,
615 force: Fortitude,
616 ) -> Result<Self::Balance, DispatchError> {
617 match Criterion::convert(asset) {
618 Left(a) => <Left as fungibles::MutateHold<AccountId>>::burn_held(
619 a, reason, who, amount, precision, force,
620 ),
621 Right(a) => <Right as fungibles::MutateHold<AccountId>>::burn_held(
622 a, reason, who, amount, precision, force,
623 ),
624 }
625 }
626 fn transfer_on_hold(
627 asset: Self::AssetId,
628 reason: &Self::Reason,
629 source: &AccountId,
630 dest: &AccountId,
631 amount: Self::Balance,
632 precision: Precision,
633 mode: Restriction,
634 force: Fortitude,
635 ) -> Result<Self::Balance, DispatchError> {
636 match Criterion::convert(asset) {
637 Left(a) => <Left as fungibles::MutateHold<AccountId>>::transfer_on_hold(
638 a, reason, source, dest, amount, precision, mode, force,
639 ),
640 Right(a) => <Right as fungibles::MutateHold<AccountId>>::transfer_on_hold(
641 a, reason, source, dest, amount, precision, mode, force,
642 ),
643 }
644 }
645 fn transfer_and_hold(
646 asset: Self::AssetId,
647 reason: &Self::Reason,
648 source: &AccountId,
649 dest: &AccountId,
650 amount: Self::Balance,
651 precision: Precision,
652 preservation: Preservation,
653 force: Fortitude,
654 ) -> Result<Self::Balance, DispatchError> {
655 match Criterion::convert(asset) {
656 Left(a) => <Left as fungibles::MutateHold<AccountId>>::transfer_and_hold(
657 a,
658 reason,
659 source,
660 dest,
661 amount,
662 precision,
663 preservation,
664 force,
665 ),
666 Right(a) => <Right as fungibles::MutateHold<AccountId>>::transfer_and_hold(
667 a,
668 reason,
669 source,
670 dest,
671 amount,
672 precision,
673 preservation,
674 force,
675 ),
676 }
677 }
678}
679
680impl<
681 Left: fungibles::MutateFreeze<AccountId>,
682 Right: fungibles::MutateFreeze<AccountId, Balance = Left::Balance, Id = Left::Id>,
683 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
684 AssetKind: AssetId,
685 AccountId,
686 > fungibles::MutateFreeze<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
687{
688 fn set_freeze(
689 asset: Self::AssetId,
690 id: &Self::Id,
691 who: &AccountId,
692 amount: Self::Balance,
693 ) -> DispatchResult {
694 match Criterion::convert(asset) {
695 Left(a) => <Left as fungibles::MutateFreeze<AccountId>>::set_freeze(a, id, who, amount),
696 Right(a) => {
697 <Right as fungibles::MutateFreeze<AccountId>>::set_freeze(a, id, who, amount)
698 },
699 }
700 }
701 fn extend_freeze(
702 asset: Self::AssetId,
703 id: &Self::Id,
704 who: &AccountId,
705 amount: Self::Balance,
706 ) -> DispatchResult {
707 match Criterion::convert(asset) {
708 Left(a) => {
709 <Left as fungibles::MutateFreeze<AccountId>>::extend_freeze(a, id, who, amount)
710 },
711 Right(a) => {
712 <Right as fungibles::MutateFreeze<AccountId>>::extend_freeze(a, id, who, amount)
713 },
714 }
715 }
716 fn thaw(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> DispatchResult {
717 match Criterion::convert(asset) {
718 Left(a) => <Left as fungibles::MutateFreeze<AccountId>>::thaw(a, id, who),
719 Right(a) => <Right as fungibles::MutateFreeze<AccountId>>::thaw(a, id, who),
720 }
721 }
722}
723
724pub struct ConvertImbalanceDropHandler<
725 Left,
726 Right,
727 LeftAssetId,
728 RightAssetId,
729 Criterion,
730 AssetKind,
731 Balance,
732 AccountId,
733>(
734 core::marker::PhantomData<(
735 Left,
736 Right,
737 LeftAssetId,
738 RightAssetId,
739 Criterion,
740 AssetKind,
741 Balance,
742 AccountId,
743 )>,
744);
745
746impl<
747 Left: fungibles::HandleImbalanceDrop<LeftAssetId, Balance>,
748 Right: fungibles::HandleImbalanceDrop<RightAssetId, Balance>,
749 LeftAssetId,
750 RightAssetId,
751 Criterion: Convert<AssetKind, Either<LeftAssetId, RightAssetId>>,
752 AssetKind,
753 Balance,
754 AccountId,
755 > fungibles::HandleImbalanceDrop<AssetKind, Balance>
756 for ConvertImbalanceDropHandler<
757 Left,
758 Right,
759 LeftAssetId,
760 RightAssetId,
761 Criterion,
762 AssetKind,
763 Balance,
764 AccountId,
765 >
766{
767 fn handle(asset: AssetKind, amount: Balance) {
768 match Criterion::convert(asset) {
769 Left(a) => Left::handle(a, amount),
770 Right(a) => Right::handle(a, amount),
771 }
772 }
773}
774
775impl<
776 Left: fungibles::Balanced<AccountId>,
777 Right: fungibles::Balanced<AccountId, Balance = Left::Balance>,
778 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
779 AssetKind: AssetId,
780 AccountId,
781 > fungibles::Balanced<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
782{
783 type OnDropDebt = ConvertImbalanceDropHandler<
784 Left::OnDropDebt,
785 Right::OnDropDebt,
786 Left::AssetId,
787 Right::AssetId,
788 Criterion,
789 AssetKind,
790 Left::Balance,
791 AccountId,
792 >;
793 type OnDropCredit = ConvertImbalanceDropHandler<
794 Left::OnDropCredit,
795 Right::OnDropCredit,
796 Left::AssetId,
797 Right::AssetId,
798 Criterion,
799 AssetKind,
800 Left::Balance,
801 AccountId,
802 >;
803
804 fn deposit(
805 asset: Self::AssetId,
806 who: &AccountId,
807 value: Self::Balance,
808 precision: Precision,
809 ) -> Result<fungibles::Debt<AccountId, Self>, DispatchError> {
810 match Criterion::convert(asset.clone()) {
811 Left(a) => <Left as fungibles::Balanced<AccountId>>::deposit(a, who, value, precision)
812 .map(|debt| imbalance::from_fungibles(debt, asset)),
813 Right(a) => {
814 <Right as fungibles::Balanced<AccountId>>::deposit(a, who, value, precision)
815 .map(|debt| imbalance::from_fungibles(debt, asset))
816 },
817 }
818 }
819 fn issue(asset: Self::AssetId, amount: Self::Balance) -> fungibles::Credit<AccountId, Self> {
820 match Criterion::convert(asset.clone()) {
821 Left(a) => {
822 let credit = <Left as fungibles::Balanced<AccountId>>::issue(a, amount);
823 imbalance::from_fungibles(credit, asset)
824 },
825 Right(a) => {
826 let credit = <Right as fungibles::Balanced<AccountId>>::issue(a, amount);
827 imbalance::from_fungibles(credit, asset)
828 },
829 }
830 }
831 fn pair(
832 asset: Self::AssetId,
833 amount: Self::Balance,
834 ) -> Result<(fungibles::Debt<AccountId, Self>, fungibles::Credit<AccountId, Self>), DispatchError>
835 {
836 match Criterion::convert(asset.clone()) {
837 Left(a) => {
838 let (a, b) = <Left as fungibles::Balanced<AccountId>>::pair(a, amount)?;
839 Ok((
840 imbalance::from_fungibles(a, asset.clone()),
841 imbalance::from_fungibles(b, asset),
842 ))
843 },
844 Right(a) => {
845 let (a, b) = <Right as fungibles::Balanced<AccountId>>::pair(a, amount)?;
846 Ok((
847 imbalance::from_fungibles(a, asset.clone()),
848 imbalance::from_fungibles(b, asset),
849 ))
850 },
851 }
852 }
853 fn rescind(asset: Self::AssetId, amount: Self::Balance) -> fungibles::Debt<AccountId, Self> {
854 match Criterion::convert(asset.clone()) {
855 Left(a) => {
856 let debt = <Left as fungibles::Balanced<AccountId>>::rescind(a, amount);
857 imbalance::from_fungibles(debt, asset)
858 },
859 Right(a) => {
860 let debt = <Right as fungibles::Balanced<AccountId>>::rescind(a, amount);
861 imbalance::from_fungibles(debt, asset)
862 },
863 }
864 }
865 fn resolve(
866 who: &AccountId,
867 credit: fungibles::Credit<AccountId, Self>,
868 ) -> Result<(), fungibles::Credit<AccountId, Self>> {
869 let asset = credit.asset();
870 match Criterion::convert(asset.clone()) {
871 Left(a) => {
872 let credit = imbalance::from_fungibles(credit, a);
873 <Left as fungibles::Balanced<AccountId>>::resolve(who, credit)
874 .map_err(|credit| imbalance::from_fungibles(credit, asset))
875 },
876 Right(a) => {
877 let credit = imbalance::from_fungibles(credit, a);
878 <Right as fungibles::Balanced<AccountId>>::resolve(who, credit)
879 .map_err(|credit| imbalance::from_fungibles(credit, asset))
880 },
881 }
882 }
883 fn settle(
884 who: &AccountId,
885 debt: fungibles::Debt<AccountId, Self>,
886 preservation: Preservation,
887 ) -> Result<fungibles::Credit<AccountId, Self>, fungibles::Debt<AccountId, Self>> {
888 let asset = debt.asset();
889 match Criterion::convert(asset.clone()) {
890 Left(a) => {
891 let debt = imbalance::from_fungibles(debt, a);
892 match <Left as fungibles::Balanced<AccountId>>::settle(who, debt, preservation) {
893 Ok(credit) => Ok(imbalance::from_fungibles(credit, asset)),
894 Err(debt) => Err(imbalance::from_fungibles(debt, asset)),
895 }
896 },
897 Right(a) => {
898 let debt = imbalance::from_fungibles(debt, a);
899 match <Right as fungibles::Balanced<AccountId>>::settle(who, debt, preservation) {
900 Ok(credit) => Ok(imbalance::from_fungibles(credit, asset)),
901 Err(debt) => Err(imbalance::from_fungibles(debt, asset)),
902 }
903 },
904 }
905 }
906 fn withdraw(
907 asset: Self::AssetId,
908 who: &AccountId,
909 value: Self::Balance,
910 precision: Precision,
911 preservation: Preservation,
912 force: Fortitude,
913 ) -> Result<fungibles::Credit<AccountId, Self>, DispatchError> {
914 match Criterion::convert(asset.clone()) {
915 Left(a) => <Left as fungibles::Balanced<AccountId>>::withdraw(
916 a,
917 who,
918 value,
919 precision,
920 preservation,
921 force,
922 )
923 .map(|credit| imbalance::from_fungibles(credit, asset)),
924 Right(a) => <Right as fungibles::Balanced<AccountId>>::withdraw(
925 a,
926 who,
927 value,
928 precision,
929 preservation,
930 force,
931 )
932 .map(|credit| imbalance::from_fungibles(credit, asset)),
933 }
934 }
935}
936
937impl<
938 Left: fungibles::BalancedHold<AccountId>
939 + fungibles::hold::DoneSlash<Self::AssetId, Self::Reason, AccountId, Self::Balance>,
940 Right: fungibles::BalancedHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>
941 + fungibles::hold::DoneSlash<Self::AssetId, Self::Reason, AccountId, Self::Balance>,
942 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
943 AssetKind: AssetId,
944 AccountId,
945 > fungibles::BalancedHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
946{
947 fn slash(
948 asset: Self::AssetId,
949 reason: &Self::Reason,
950 who: &AccountId,
951 amount: Self::Balance,
952 ) -> (fungibles::Credit<AccountId, Self>, Self::Balance) {
953 match Criterion::convert(asset.clone()) {
954 Left(a) => {
955 let (credit, amount) =
956 <Left as fungibles::BalancedHold<AccountId>>::slash(a, reason, who, amount);
957 (imbalance::from_fungibles(credit, asset), amount)
958 },
959 Right(a) => {
960 let (credit, amount) =
961 <Right as fungibles::BalancedHold<AccountId>>::slash(a, reason, who, amount);
962 (imbalance::from_fungibles(credit, asset), amount)
963 },
964 }
965 }
966}
967
968impl<
969 Reason,
970 Balance,
971 Left: fungibles::Inspect<AccountId>
972 + fungibles::hold::DoneSlash<Left::AssetId, Reason, AccountId, Balance>,
973 Right: fungibles::Inspect<AccountId>
974 + fungibles::hold::DoneSlash<Right::AssetId, Reason, AccountId, Balance>,
975 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
976 AssetKind: AssetId,
977 AccountId,
978 > fungibles::hold::DoneSlash<AssetKind, Reason, AccountId, Balance>
979 for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
980{
981 fn done_slash(asset: AssetKind, reason: &Reason, who: &AccountId, amount: Balance) {
982 match Criterion::convert(asset.clone()) {
983 Left(a) => {
984 Left::done_slash(a, reason, who, amount);
985 },
986 Right(a) => {
987 Right::done_slash(a, reason, who, amount);
988 },
989 }
990 }
991}
992
993impl<
994 Left: fungibles::Inspect<AccountId> + fungibles::Create<AccountId>,
995 Right: fungibles::Inspect<AccountId, Balance = Left::Balance> + fungibles::Create<AccountId>,
996 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
997 AssetKind: AssetId,
998 AccountId,
999 > fungibles::Create<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
1000{
1001 fn create(
1002 asset: AssetKind,
1003 admin: AccountId,
1004 is_sufficient: bool,
1005 min_balance: Self::Balance,
1006 ) -> DispatchResult {
1007 match Criterion::convert(asset) {
1008 Left(a) => {
1009 <Left as fungibles::Create<AccountId>>::create(a, admin, is_sufficient, min_balance)
1010 },
1011 Right(a) => <Right as fungibles::Create<AccountId>>::create(
1012 a,
1013 admin,
1014 is_sufficient,
1015 min_balance,
1016 ),
1017 }
1018 }
1019}
1020
1021impl<
1022 Left: fungibles::Inspect<AccountId> + AccountTouch<Left::AssetId, AccountId>,
1023 Right: fungibles::Inspect<AccountId>
1024 + AccountTouch<
1025 Right::AssetId,
1026 AccountId,
1027 Balance = <Left as AccountTouch<Left::AssetId, AccountId>>::Balance,
1028 >,
1029 Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
1030 AssetKind: AssetId,
1031 AccountId,
1032 > AccountTouch<AssetKind, AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
1033{
1034 type Balance = <Left as AccountTouch<Left::AssetId, AccountId>>::Balance;
1035
1036 fn deposit_required(asset: AssetKind) -> Self::Balance {
1037 match Criterion::convert(asset) {
1038 Left(a) => <Left as AccountTouch<Left::AssetId, AccountId>>::deposit_required(a),
1039 Right(a) => <Right as AccountTouch<Right::AssetId, AccountId>>::deposit_required(a),
1040 }
1041 }
1042
1043 fn should_touch(asset: AssetKind, who: &AccountId) -> bool {
1044 match Criterion::convert(asset) {
1045 Left(a) => <Left as AccountTouch<Left::AssetId, AccountId>>::should_touch(a, who),
1046 Right(a) => <Right as AccountTouch<Right::AssetId, AccountId>>::should_touch(a, who),
1047 }
1048 }
1049
1050 fn touch(asset: AssetKind, who: &AccountId, depositor: &AccountId) -> DispatchResult {
1051 match Criterion::convert(asset) {
1052 Left(a) => <Left as AccountTouch<Left::AssetId, AccountId>>::touch(a, who, depositor),
1053 Right(a) => {
1054 <Right as AccountTouch<Right::AssetId, AccountId>>::touch(a, who, depositor)
1055 },
1056 }
1057 }
1058}
1059
1060impl<
1061 Left: fungibles::Inspect<AccountId> + fungibles::Refund<AccountId>,
1062 Right: fungibles::Inspect<AccountId>
1063 + fungibles::Refund<AccountId, Balance = <Left as fungibles::Refund<AccountId>>::Balance>,
1064 Criterion: Convert<
1065 AssetKind,
1066 Either<
1067 <Left as fungibles::Refund<AccountId>>::AssetId,
1068 <Right as fungibles::Refund<AccountId>>::AssetId,
1069 >,
1070 >,
1071 AssetKind: AssetId,
1072 AccountId,
1073 > fungibles::Refund<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
1074{
1075 type AssetId = AssetKind;
1076 type Balance = <Left as fungibles::Refund<AccountId>>::Balance;
1077
1078 fn deposit_held(asset: AssetKind, who: AccountId) -> Option<(AccountId, Self::Balance)> {
1079 match Criterion::convert(asset) {
1080 Left(a) => <Left as fungibles::Refund<AccountId>>::deposit_held(a, who),
1081 Right(a) => <Right as fungibles::Refund<AccountId>>::deposit_held(a, who),
1082 }
1083 }
1084 fn refund(asset: AssetKind, who: AccountId) -> DispatchResult {
1085 match Criterion::convert(asset) {
1086 Left(a) => <Left as fungibles::Refund<AccountId>>::refund(a, who),
1087 Right(a) => <Right as fungibles::Refund<AccountId>>::refund(a, who),
1088 }
1089 }
1090}