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