Skip to content

Commit

Permalink
refactor: api integration tests (#133)
Browse files Browse the repository at this point in the history
Co-authored-by: Frank Bell <frank@r0gue.io>
  • Loading branch information
2 people authored and chungquantin committed Sep 6, 2024
1 parent 59c3389 commit f2f35ca
Show file tree
Hide file tree
Showing 17 changed files with 1,559 additions and 1,103 deletions.
222 changes: 161 additions & 61 deletions pallets/api/src/fungibles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type BalanceOf<T> = <pallet_assets::Pallet<T, AssetsInstanceOf<T>> as Inspect<
#[frame_support::pallet]
pub mod pallet {
use super::*;
use core::cmp::Ordering::*;
use frame_support::{
dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo},
pallet_prelude::*,
Expand Down Expand Up @@ -75,6 +76,9 @@ pub mod pallet {
/// Token decimals for a given asset ID.
#[codec(index = 10)]
TokenDecimals(AssetIdOf<T>),
/// Check if token with a given asset ID exists.
#[codec(index = 18)]
AssetExists(AssetIdOf<T>),
}

/// Configure the pallet by specifying the parameters and types on which it depends.
Expand All @@ -95,49 +99,49 @@ pub mod pallet {
/// `data` in unspecified format.
///
/// # Parameters
/// * `id` - The ID of the asset.
/// * `to` - The recipient account.
/// * `value` - The number of tokens to transfer.
/// - `id` - The ID of the asset.
/// - `to` - The recipient account.
/// - `value` - The number of tokens to transfer.
#[pallet::call_index(3)]
#[pallet::weight(AssetsWeightInfoOf::<T>::transfer_keep_alive())]
pub fn transfer(
origin: OriginFor<T>,
id: AssetIdOf<T>,
target: AccountIdOf<T>,
amount: BalanceOf<T>,
to: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let target = T::Lookup::unlookup(target);
AssetsOf::<T>::transfer_keep_alive(origin, id.into(), target, amount)
let to = T::Lookup::unlookup(to);
AssetsOf::<T>::transfer_keep_alive(origin, id.into(), to, value)
}

/// Transfers `value` amount of tokens from the delegated account approved by the `owner` to
/// account `to`, with additional `data` in unspecified format.
/// Transfers `value` amount tokens on behalf of `from` to account `to` with additional `data`
/// in unspecified format.
///
/// # Parameters
/// * `id` - The ID of the asset.
/// * `owner` - The account from which the asset balance will be withdrawn.
/// * `to` - The recipient account.
/// * `value` - The number of tokens to transfer.
/// - `id` - The ID of the asset.
/// - `owner` - The account from which the asset balance will be withdrawn.
/// - `to` - The recipient account.
/// - `value` - The number of tokens to transfer.
#[pallet::call_index(4)]
#[pallet::weight(AssetsWeightInfoOf::<T>::transfer_approved())]
pub fn transfer_from(
origin: OriginFor<T>,
id: AssetIdOf<T>,
owner: AccountIdOf<T>,
target: AccountIdOf<T>,
amount: BalanceOf<T>,
from: AccountIdOf<T>,
to: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let owner = T::Lookup::unlookup(owner);
let target = T::Lookup::unlookup(target);
AssetsOf::<T>::transfer_approved(origin, id.into(), owner, target, amount)
let from = T::Lookup::unlookup(from);
let to = T::Lookup::unlookup(to);
AssetsOf::<T>::transfer_approved(origin, id.into(), from, to, value)
}

/// Approves an account to spend a specified number of tokens on behalf of the caller.
///
/// # Parameters
/// * `id` - The ID of the asset.
/// * `spender` - The account that is allowed to spend the tokens.
/// * `value` - The number of tokens to approve.
/// - `id` - The ID of the asset.
/// - `spender` - The account that is allowed to spend the tokens.
/// - `value` - The number of tokens to approve.
#[pallet::call_index(5)]
#[pallet::weight(<T as Config>::WeightInfo::approve(1, 1))]
pub fn approve(
Expand All @@ -152,40 +156,42 @@ pub mod pallet {
let spender = T::Lookup::unlookup(spender);
let id: AssetIdParameterOf<T> = id.into();

// If the new value is equal to the current allowance, do nothing.
let return_weight = if value == current_allowance {
Self::weight_approve(0, 0)
}
// If the new value is greater than the current allowance, approve the difference
// because `approve_transfer` works additively (see `pallet-assets`).
else if value > current_allowance {
AssetsOf::<T>::approve_transfer(
origin,
id,
spender,
value.saturating_sub(current_allowance),
)
.map_err(|e| e.with_weight(Self::weight_approve(1, 0)))?;
Self::weight_approve(1, 0)
} else {
// If the new value is less than the current allowance, cancel the approval and set the new value
AssetsOf::<T>::cancel_approval(origin.clone(), id.clone(), spender.clone())
.map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?;
if value.is_zero() {
return Ok(Some(Self::weight_approve(0, 1)).into());
}
AssetsOf::<T>::approve_transfer(origin, id, spender, value)?;
Self::weight_approve(1, 1)
let return_weight = match value.cmp(&current_allowance) {
// If the new value is equal to the current allowance, do nothing.
Equal => Self::weight_approve(0, 0),
// If the new value is greater than the current allowance, approve the difference
// because `approve_transfer` works additively (see `pallet-assets`).
Greater => {
AssetsOf::<T>::approve_transfer(
origin,
id,
spender,
value.saturating_sub(current_allowance),
)
.map_err(|e| e.with_weight(Self::weight_approve(1, 0)))?;
Self::weight_approve(1, 0)
},
// If the new value is less than the current allowance, cancel the approval and
// set the new value.
Less => {
AssetsOf::<T>::cancel_approval(origin.clone(), id.clone(), spender.clone())
.map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?;
if value.is_zero() {
return Ok(Some(Self::weight_approve(0, 1)).into());
}
AssetsOf::<T>::approve_transfer(origin, id, spender, value)?;
Self::weight_approve(1, 1)
},
};
Ok(Some(return_weight).into())
}

/// Increases the allowance of a spender.
///
/// # Parameters
/// * `id` - The ID of the asset.
/// * `spender` - The account that is allowed to spend the tokens.
/// * `value` - The number of tokens to increase the allowance by.
/// - `id` - The ID of the asset.
/// - `spender` - The account that is allowed to spend the tokens.
/// - `value` - The number of tokens to increase the allowance by.
#[pallet::call_index(6)]
#[pallet::weight(AssetsWeightInfoOf::<T>::approve_transfer())]
pub fn increase_allowance(
Expand All @@ -201,9 +207,9 @@ pub mod pallet {
/// Decreases the allowance of a spender.
///
/// # Parameters
/// * `id` - The ID of the asset.
/// * `spender` - The account that is allowed to spend the tokens.
/// * `value` - The number of tokens to decrease the allowance by.
/// - `id` - The ID of the asset.
/// - `spender` - The account that is allowed to spend the tokens.
/// - `value` - The number of tokens to decrease the allowance by.
#[pallet::call_index(7)]
#[pallet::weight(<T as Config>::WeightInfo::approve(1, 1))]
pub fn decrease_allowance(
Expand All @@ -214,25 +220,118 @@ pub mod pallet {
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin.clone())
.map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?;
let mut current_allowance = AssetsOf::<T>::allowance(id.clone(), &who, &spender);
let current_allowance = AssetsOf::<T>::allowance(id.clone(), &who, &spender);
let spender = T::Lookup::unlookup(spender);
let id: AssetIdParameterOf<T> = id.into();

if value.is_zero() {
return Ok(Some(Self::weight_approve(0, 0)).into());
}

current_allowance.saturating_reduce(value);
// Cancel the aproval and set the new value if `current_allowance` is more than zero.
// Cancel the aproval and set the new value if `new_allowance` is more than zero.
AssetsOf::<T>::cancel_approval(origin.clone(), id.clone(), spender.clone())
.map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?;

if current_allowance.is_zero() {
let new_allowance = current_allowance.saturating_sub(value);
if new_allowance.is_zero() {
return Ok(Some(Self::weight_approve(0, 1)).into());
}
AssetsOf::<T>::approve_transfer(origin, id, spender, current_allowance)?;
AssetsOf::<T>::approve_transfer(origin, id, spender, new_allowance)?;
Ok(().into())
}

/// Create a new token with a given asset ID.
///
/// # Parameters
/// - `id` - The ID of the asset.
/// - `admin` - The account that will administer the asset.
/// - `min_balance` - The minimum balance required for accounts holding this asset.
#[pallet::call_index(11)]
#[pallet::weight(AssetsWeightInfoOf::<T>::create())]
pub fn create(
origin: OriginFor<T>,
id: AssetIdOf<T>,
admin: AccountIdOf<T>,
min_balance: BalanceOf<T>,
) -> DispatchResult {
let admin = T::Lookup::unlookup(admin);
AssetsOf::<T>::create(origin, id.into(), admin, min_balance)
}

/// Start the process of destroying a token with a given asset ID.
///
/// # Parameters
/// - `id` - The ID of the asset.
#[pallet::call_index(12)]
#[pallet::weight(AssetsWeightInfoOf::<T>::start_destroy())]
pub fn start_destroy(origin: OriginFor<T>, id: AssetIdOf<T>) -> DispatchResult {
AssetsOf::<T>::start_destroy(origin, id.into())
}

/// Set the metadata for a token with a given asset ID.
///
/// # Parameters
/// - `id`: The identifier of the asset to update.
/// - `name`: The user friendly name of this asset. Limited in length by
/// `pallet_assets::Config::StringLimit`.
/// - `symbol`: The exchange symbol for this asset. Limited in length by
/// `pallet_assets::Config::StringLimit`.
/// - `decimals`: The number of decimals this asset uses to represent one unit.
#[pallet::call_index(16)]
#[pallet::weight(AssetsWeightInfoOf::<T>::set_metadata(name.len() as u32, symbol.len() as u32))]
pub fn set_metadata(
origin: OriginFor<T>,
id: AssetIdOf<T>,
name: Vec<u8>,
symbol: Vec<u8>,
decimals: u8,
) -> DispatchResult {
AssetsOf::<T>::set_metadata(origin, id.into(), name, symbol, decimals)
}

/// Clear the metadata for a token with a given asset ID.
///
/// # Parameters
/// - `id` - The ID of the asset.
#[pallet::call_index(17)]
#[pallet::weight(AssetsWeightInfoOf::<T>::clear_metadata())]
pub fn clear_metadata(origin: OriginFor<T>, id: AssetIdOf<T>) -> DispatchResult {
AssetsOf::<T>::clear_metadata(origin, id.into())
}

/// Creates `value` amount tokens and assigns them to `account`, increasing the total supply.
///
/// # Parameters
/// - `id` - The ID of the asset.
/// - `account` - The account to be credited with the created tokens.
/// - `value` - The number of tokens to mint.
#[pallet::call_index(19)]
#[pallet::weight(AssetsWeightInfoOf::<T>::mint())]
pub fn mint(
origin: OriginFor<T>,
id: AssetIdOf<T>,
account: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let account = T::Lookup::unlookup(account);
AssetsOf::<T>::mint(origin, id.into(), account, value)
}

/// Destroys `value` amount tokens from `account`, reducing the total supply.
///
/// # Parameters
/// - `id` - The ID of the asset.
/// - `account` - The account from which the tokens will be destroyed.
/// - `value` - The number of tokens to destroy.
#[pallet::call_index(20)]
#[pallet::weight(AssetsWeightInfoOf::<T>::burn())]
pub fn burn(
origin: OriginFor<T>,
id: AssetIdOf<T>,
account: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let account = T::Lookup::unlookup(account);
AssetsOf::<T>::burn(origin, id.into(), account, value)
}
}

impl<T: Config> Pallet<T> {
Expand All @@ -242,8 +341,8 @@ pub mod pallet {
/// encoded result.
///
/// # Parameter
/// * `value` - An instance of `Read<T>`, which specifies the type of state query and
/// the associated parameters.
/// - `value` - An instance of `Read<T>`, which specifies the type of state query and
/// the associated parameters.
pub fn read_state(value: Read<T>) -> Vec<u8> {
use Read::*;

Expand All @@ -262,6 +361,7 @@ pub mod pallet {
TokenDecimals(id) => {
<AssetsOf<T> as MetadataInspect<AccountIdOf<T>>>::decimals(id).encode()
},
AssetExists(id) => AssetsOf::<T>::asset_exists(id).encode(),
}
}

Expand Down
Loading

0 comments on commit f2f35ca

Please sign in to comment.