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