Skip to content

Commit 72b0e52

Browse files
xlcukby1234
andauthored
fungible helpers (#619)
* fungible helpers * implement mutate and transfers (#620) * use asset id as an argument Co-authored-by: Frank Yin <[email protected]>
1 parent 37e4293 commit 72b0e52

File tree

3 files changed

+404
-0
lines changed

3 files changed

+404
-0
lines changed

tokens/src/impls.rs

+243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
use codec::FullCodec;
2+
use frame_support::dispatch::{DispatchError, DispatchResult};
3+
use frame_support::traits::{
4+
fungible, fungibles,
5+
tokens::{DepositConsequence, WithdrawConsequence},
6+
Contains, Get,
7+
};
8+
use sp_runtime::traits::AtLeast32BitUnsigned;
9+
use sp_std::fmt::Debug;
10+
11+
pub struct Combiner<AccountId, TestKey, A, B>(sp_std::marker::PhantomData<(AccountId, TestKey, A, B)>);
12+
13+
impl<AccountId, TestKey, A, B> fungibles::Inspect<AccountId> for Combiner<AccountId, TestKey, A, B>
14+
where
15+
TestKey: Contains<<B as fungibles::Inspect<AccountId>>::AssetId>,
16+
A: fungible::Inspect<AccountId, Balance = <B as fungibles::Inspect<AccountId>>::Balance>,
17+
B: fungibles::Inspect<AccountId>,
18+
{
19+
type AssetId = <B as fungibles::Inspect<AccountId>>::AssetId;
20+
type Balance = <B as fungibles::Inspect<AccountId>>::Balance;
21+
22+
fn total_issuance(asset: Self::AssetId) -> Self::Balance {
23+
if TestKey::contains(&asset) {
24+
A::total_issuance()
25+
} else {
26+
B::total_issuance(asset)
27+
}
28+
}
29+
30+
fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
31+
if TestKey::contains(&asset) {
32+
A::minimum_balance()
33+
} else {
34+
B::minimum_balance(asset)
35+
}
36+
}
37+
38+
fn balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
39+
if TestKey::contains(&asset) {
40+
A::balance(who)
41+
} else {
42+
B::balance(asset, who)
43+
}
44+
}
45+
46+
fn reducible_balance(asset: Self::AssetId, who: &AccountId, keep_alive: bool) -> Self::Balance {
47+
if TestKey::contains(&asset) {
48+
A::reducible_balance(who, keep_alive)
49+
} else {
50+
B::reducible_balance(asset, who, keep_alive)
51+
}
52+
}
53+
54+
fn can_deposit(asset: Self::AssetId, who: &AccountId, amount: Self::Balance) -> DepositConsequence {
55+
if TestKey::contains(&asset) {
56+
A::can_deposit(who, amount)
57+
} else {
58+
B::can_deposit(asset, who, amount)
59+
}
60+
}
61+
62+
fn can_withdraw(
63+
asset: Self::AssetId,
64+
who: &AccountId,
65+
amount: Self::Balance,
66+
) -> WithdrawConsequence<Self::Balance> {
67+
if TestKey::contains(&asset) {
68+
A::can_withdraw(who, amount)
69+
} else {
70+
B::can_withdraw(asset, who, amount)
71+
}
72+
}
73+
}
74+
75+
impl<AccountId, TestKey, A, B> fungibles::Transfer<AccountId> for Combiner<AccountId, TestKey, A, B>
76+
where
77+
TestKey: Contains<<B as fungibles::Inspect<AccountId>>::AssetId>,
78+
A: fungible::Transfer<AccountId, Balance = <B as fungibles::Inspect<AccountId>>::Balance>,
79+
B: fungibles::Transfer<AccountId>,
80+
{
81+
fn transfer(
82+
asset: Self::AssetId,
83+
source: &AccountId,
84+
dest: &AccountId,
85+
amount: Self::Balance,
86+
keep_alive: bool,
87+
) -> Result<Self::Balance, DispatchError> {
88+
if TestKey::contains(&asset) {
89+
A::transfer(source, dest, amount, keep_alive)
90+
} else {
91+
B::transfer(asset, source, dest, amount, keep_alive)
92+
}
93+
}
94+
}
95+
96+
impl<AccountId, TestKey, A, B> fungibles::Mutate<AccountId> for Combiner<AccountId, TestKey, A, B>
97+
where
98+
TestKey: Contains<<B as fungibles::Inspect<AccountId>>::AssetId>,
99+
A: fungible::Mutate<AccountId, Balance = <B as fungibles::Inspect<AccountId>>::Balance>,
100+
B: fungibles::Mutate<AccountId>,
101+
{
102+
fn mint_into(asset: Self::AssetId, dest: &AccountId, amount: Self::Balance) -> DispatchResult {
103+
if TestKey::contains(&asset) {
104+
A::mint_into(dest, amount)
105+
} else {
106+
B::mint_into(asset, dest, amount)
107+
}
108+
}
109+
110+
fn burn_from(
111+
asset: Self::AssetId,
112+
dest: &AccountId,
113+
amount: Self::Balance,
114+
) -> Result<Self::Balance, DispatchError> {
115+
if TestKey::contains(&asset) {
116+
A::burn_from(dest, amount)
117+
} else {
118+
B::burn_from(asset, dest, amount)
119+
}
120+
}
121+
}
122+
123+
pub trait ConvertBalance<A, B> {
124+
type AssetId;
125+
fn convert_balance(amount: A, asset_id: Self::AssetId) -> B;
126+
fn convert_balance_back(amount: B, asset_id: Self::AssetId) -> A;
127+
}
128+
129+
pub struct Mapper<AccountId, T, C, B, GetCurrencyId>(sp_std::marker::PhantomData<(AccountId, T, C, B, GetCurrencyId)>);
130+
impl<AccountId, T, C, B, GetCurrencyId> fungible::Inspect<AccountId> for Mapper<AccountId, T, C, B, GetCurrencyId>
131+
where
132+
T: fungibles::Inspect<AccountId>,
133+
C: ConvertBalance<
134+
<T as fungibles::Inspect<AccountId>>::Balance,
135+
B,
136+
AssetId = <T as fungibles::Inspect<AccountId>>::AssetId,
137+
>,
138+
// TOOD: use trait Balance after https://github.com/paritytech/substrate/pull/9863 is available
139+
B: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug,
140+
GetCurrencyId: Get<<T as fungibles::Inspect<AccountId>>::AssetId>,
141+
{
142+
type Balance = B;
143+
144+
fn total_issuance() -> Self::Balance {
145+
C::convert_balance(T::total_issuance(GetCurrencyId::get()), GetCurrencyId::get())
146+
}
147+
148+
fn minimum_balance() -> Self::Balance {
149+
C::convert_balance(T::minimum_balance(GetCurrencyId::get()), GetCurrencyId::get())
150+
}
151+
152+
fn balance(who: &AccountId) -> Self::Balance {
153+
C::convert_balance(T::balance(GetCurrencyId::get(), who), GetCurrencyId::get())
154+
}
155+
156+
fn reducible_balance(who: &AccountId, keep_alive: bool) -> Self::Balance {
157+
C::convert_balance(
158+
T::reducible_balance(GetCurrencyId::get(), who, keep_alive),
159+
GetCurrencyId::get(),
160+
)
161+
}
162+
163+
fn can_deposit(who: &AccountId, amount: Self::Balance) -> DepositConsequence {
164+
T::can_deposit(
165+
GetCurrencyId::get(),
166+
who,
167+
C::convert_balance_back(amount, GetCurrencyId::get()),
168+
)
169+
}
170+
171+
fn can_withdraw(who: &AccountId, amount: Self::Balance) -> WithdrawConsequence<Self::Balance> {
172+
use WithdrawConsequence::*;
173+
let res = T::can_withdraw(
174+
GetCurrencyId::get(),
175+
who,
176+
C::convert_balance_back(amount, GetCurrencyId::get()),
177+
);
178+
match res {
179+
WithdrawConsequence::ReducedToZero(b) => {
180+
WithdrawConsequence::ReducedToZero(C::convert_balance(b, GetCurrencyId::get()))
181+
}
182+
NoFunds => NoFunds,
183+
WouldDie => WouldDie,
184+
UnknownAsset => UnknownAsset,
185+
Underflow => Underflow,
186+
Overflow => Overflow,
187+
Frozen => Frozen,
188+
Success => Success,
189+
}
190+
}
191+
}
192+
193+
impl<AccountId, T, C, B, GetCurrencyId> fungible::Transfer<AccountId> for Mapper<AccountId, T, C, B, GetCurrencyId>
194+
where
195+
T: fungibles::Transfer<AccountId, Balance = B>,
196+
C: ConvertBalance<
197+
<T as fungibles::Inspect<AccountId>>::Balance,
198+
B,
199+
AssetId = <T as fungibles::Inspect<AccountId>>::AssetId,
200+
>,
201+
// TOOD: use trait Balance after https://github.com/paritytech/substrate/pull/9863 is available
202+
B: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug,
203+
GetCurrencyId: Get<<T as fungibles::Inspect<AccountId>>::AssetId>,
204+
{
205+
fn transfer(source: &AccountId, dest: &AccountId, amount: B, keep_alive: bool) -> Result<B, DispatchError> {
206+
T::transfer(
207+
GetCurrencyId::get(),
208+
source,
209+
dest,
210+
C::convert_balance_back(amount, GetCurrencyId::get()),
211+
keep_alive,
212+
)
213+
}
214+
}
215+
216+
impl<AccountId, T, C, B, GetCurrencyId> fungible::Mutate<AccountId> for Mapper<AccountId, T, C, B, GetCurrencyId>
217+
where
218+
T: fungibles::Mutate<AccountId, Balance = B>,
219+
C: ConvertBalance<
220+
<T as fungibles::Inspect<AccountId>>::Balance,
221+
B,
222+
AssetId = <T as fungibles::Inspect<AccountId>>::AssetId,
223+
>,
224+
// TOOD: use trait Balance after https://github.com/paritytech/substrate/pull/9863 is available
225+
B: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug,
226+
GetCurrencyId: Get<<T as fungibles::Inspect<AccountId>>::AssetId>,
227+
{
228+
fn mint_into(dest: &AccountId, amount: Self::Balance) -> DispatchResult {
229+
T::mint_into(
230+
GetCurrencyId::get(),
231+
dest,
232+
C::convert_balance_back(amount, GetCurrencyId::get()),
233+
)
234+
}
235+
236+
fn burn_from(dest: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
237+
T::burn_from(
238+
GetCurrencyId::get(),
239+
dest,
240+
C::convert_balance_back(amount, GetCurrencyId::get()),
241+
)
242+
}
243+
}

tokens/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ use orml_traits::{
7575
};
7676

7777
mod imbalances;
78+
mod impls;
7879
mod mock;
7980
mod tests;
8081
mod weights;
8182

83+
pub use impls::*;
8284
pub use weights::WeightInfo;
8385

8486
pub struct TransferDust<T, GetAccountId>(marker::PhantomData<(T, GetAccountId)>);

0 commit comments

Comments
 (0)