Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: api integration tests #133

Merged
merged 38 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
360bb2a
feat: pop api fungibles pallet
Daanvdplas Jul 19, 2024
e097f80
refactor: comments
Daanvdplas Jul 20, 2024
c8d8b2a
refactor: rebase main, refactor extension with enums
evilrobot-01 Jul 20, 2024
c88387d
refactor
Daanvdplas Jul 21, 2024
224390a
refactor 2
Daanvdplas Jul 22, 2024
43ae445
feat: add fungibles pallet functions
Daanvdplas Jul 22, 2024
bbe01a1
tests: remove transfer_from (transfer copy) and add approve
Daanvdplas Jul 22, 2024
68264da
refactor: primitives
Daanvdplas Jul 22, 2024
2481773
fix: pallet api error + missing docs
Daanvdplas Jul 22, 2024
c10a8d4
fix: integration test after removal fungibles feature primitives
Daanvdplas Jul 22, 2024
a8c4bb5
chore: benchmark approve
Daanvdplas Jul 23, 2024
4419bad
refactor: pallet
Daanvdplas Jul 24, 2024
792fa07
refactor: integration-tests
Daanvdplas Jul 24, 2024
96da2f0
refactor: ink api library
Daanvdplas Jul 24, 2024
cb54a57
refactor: devnet runtime
Daanvdplas Jul 24, 2024
9ec2744
chore: benchmark fungibles approve
Daanvdplas Jul 24, 2024
f0fff97
test: ensure Lookup configuration
Daanvdplas Jul 24, 2024
4a476b0
fix: approve benchmark + weights
Daanvdplas Jul 24, 2024
f3cc83a
refactor: primitives
Daanvdplas Jul 25, 2024
bd85489
refactor: bits and pieces
Daanvdplas Jul 25, 2024
0e49f63
fix: test devnet
Daanvdplas Jul 25, 2024
8f6139c
refactor: apply final comments
Daanvdplas Jul 25, 2024
948e144
chore: benchmark approve
Daanvdplas Jul 23, 2024
88577e4
refactor: read state
Daanvdplas Jul 23, 2024
809e192
refactor: add state query filter
Daanvdplas Jul 23, 2024
ac9714c
fix: test UnknownCall
Daanvdplas Jul 23, 2024
77711ec
refactor: read state functions
Daanvdplas Jul 25, 2024
b50830c
refactor: enums
Daanvdplas Jul 25, 2024
2a8800c
refactor: style docs and using constants for errors in chain extension
Daanvdplas Jul 26, 2024
b93f009
refactor: api integration tests
Daanvdplas Jul 26, 2024
b639e8b
refactor: IT better error handling
Daanvdplas Jul 26, 2024
074b8cf
merge daan/api
Daanvdplas Jul 28, 2024
5aec185
merge daan/api
Daanvdplas Jul 31, 2024
51c38cc
refactor: match statement
Daanvdplas Jul 31, 2024
60c744b
refactor: resolve clippy
Daanvdplas Aug 5, 2024
5b78e4c
feat: asset management (#151)
Daanvdplas Aug 6, 2024
9efb839
style: consistency docs
Daanvdplas Aug 6, 2024
e623419
style: explanation test
Daanvdplas Aug 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() {
Daanvdplas marked this conversation as resolved.
Show resolved Hide resolved
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
Loading