Coins pallet (#399)

* initial implementation

* add function to get a balance of an account

* add support for multiple coins

* rename pallet to "coins-pallet"

* replace balances, assets and tokens pallet with coins pallet in runtime

* add total supply info

* update client side for new Coins pallet

* handle fees

* bug fixes

* Update FeeAccount test

* Fmt

* fix pr comments

* remove extraneous Imbalance type

* Minor tweaks

---------

Co-authored-by: Luke Parker <lukeparker5132@gmail.com>
This commit is contained in:
akildemir
2023-10-19 13:22:21 +03:00
committed by GitHub
parent 3255c0ace5
commit fdfce9e207
32 changed files with 535 additions and 445 deletions

View File

@@ -15,7 +15,7 @@ mod other_primitives {
pub use serai_runtime::in_instructions::primitives;
}
pub mod coins {
pub use serai_runtime::tokens::primitives;
pub use serai_runtime::coins::primitives;
}
pub mod validator_sets {
pub use serai_runtime::validator_sets::primitives;

View File

@@ -1,19 +1,17 @@
use sp_core::sr25519::Public;
use serai_runtime::{
primitives::{SeraiAddress, SubstrateAmount, Amount, Coin, Balance},
assets::{AssetDetails, AssetAccount},
tokens, Tokens, Runtime,
coins, Coins, Runtime,
};
pub use tokens::primitives;
use primitives::OutInstruction;
pub use coins::primitives;
use primitives::OutInstructionWithBalance;
use subxt::tx::Payload;
use crate::{TemporalSerai, SeraiError, Composite, scale_value, scale_composite};
const PALLET: &str = "Tokens";
const PALLET: &str = "Coins";
pub type TokensEvent = tokens::Event<Runtime>;
pub type CoinsEvent = coins::Event<Runtime>;
#[derive(Clone, Copy)]
pub struct SeraiCoins<'a>(pub(crate) TemporalSerai<'a>);
@@ -22,37 +20,25 @@ impl<'a> SeraiCoins<'a> {
self.0
}
pub async fn mint_events(&self) -> Result<Vec<TokensEvent>, SeraiError> {
self.0.events::<Tokens, _>(|event| matches!(event, TokensEvent::Mint { .. })).await
pub async fn mint_events(&self) -> Result<Vec<CoinsEvent>, SeraiError> {
self.0.events::<Coins, _>(|event| matches!(event, CoinsEvent::Mint { .. })).await
}
pub async fn burn_events(&self) -> Result<Vec<TokensEvent>, SeraiError> {
self.0.events::<Tokens, _>(|event| matches!(event, TokensEvent::Burn { .. })).await
pub async fn burn_events(&self) -> Result<Vec<CoinsEvent>, SeraiError> {
self.0.events::<Coins, _>(|event| matches!(event, CoinsEvent::Burn { .. })).await
}
pub async fn sri_balance(&self, address: SeraiAddress) -> Result<u64, SeraiError> {
let data: Option<
serai_runtime::system::AccountInfo<u32, serai_runtime::balances::AccountData<u64>>,
> = self.0.storage("System", "Account", Some(vec![scale_value(address)])).await?;
Ok(data.map(|data| data.data.free).unwrap_or(0))
}
pub async fn token_supply(&self, coin: Coin) -> Result<Amount, SeraiError> {
pub async fn coin_supply(&self, coin: Coin) -> Result<Amount, SeraiError> {
Ok(Amount(
self
.0
.storage::<AssetDetails<SubstrateAmount, SeraiAddress, SubstrateAmount>>(
"Assets",
"Asset",
Some(vec![scale_value(coin)]),
)
.storage::<SubstrateAmount>(PALLET, "Supply", Some(vec![scale_value(coin)]))
.await?
.map(|token| token.supply)
.unwrap_or(0),
))
}
pub async fn token_balance(
pub async fn coin_balance(
&self,
coin: Coin,
address: SeraiAddress,
@@ -60,35 +46,25 @@ impl<'a> SeraiCoins<'a> {
Ok(Amount(
self
.0
.storage::<AssetAccount<SubstrateAmount, SubstrateAmount, (), Public>>(
"Assets",
"Account",
Some(vec![scale_value(coin), scale_value(address)]),
.storage::<SubstrateAmount>(
PALLET,
"Balances",
Some(vec![scale_value(address), scale_value(coin)]),
)
.await?
.map(|account| account.balance())
.unwrap_or(0),
))
}
pub fn transfer_sri(to: SeraiAddress, amount: Amount) -> Payload<Composite<()>> {
pub fn transfer(to: SeraiAddress, balance: Balance) -> Payload<Composite<()>> {
Payload::new(
"Balances",
// TODO: Use transfer_allow_death?
// TODO: Replace the Balances pallet with something much simpler
PALLET,
"transfer",
scale_composite(serai_runtime::balances::Call::<Runtime>::transfer {
dest: to,
value: amount.0,
}),
scale_composite(serai_runtime::coins::Call::<Runtime>::transfer { to, balance }),
)
}
pub fn burn(balance: Balance, instruction: OutInstruction) -> Payload<Composite<()>> {
Payload::new(
PALLET,
"burn",
scale_composite(tokens::Call::<Runtime>::burn { balance, instruction }),
)
pub fn burn(instruction: OutInstructionWithBalance) -> Payload<Composite<()>> {
Payload::new(PALLET, "burn", scale_composite(coins::Call::<Runtime>::burn { instruction }))
}
}