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