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

feat: api events #153

Merged
merged 66 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 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
f72b15a
feat: create & set_metadata
Daanvdplas Jul 30, 2024
7739392
feat: rest of asset management
Daanvdplas Jul 30, 2024
d4f7f99
style: pub function docs
Daanvdplas Jul 30, 2024
6f4da18
fix: remove unnecessary api functions
Daanvdplas Jul 30, 2024
5aec185
merge daan/api
Daanvdplas Jul 31, 2024
602b8bf
merge refactor: integration tests error handling
Daanvdplas Jul 31, 2024
51c38cc
refactor: match statement
Daanvdplas Jul 31, 2024
6084f89
feat: burn and mint
Daanvdplas Jul 31, 2024
406063c
Merge branch 'daan/fix-read_state_error_handling' into daan/feat-asse…
Daanvdplas Jul 31, 2024
584b9c6
feat: create asset in constructor
Daanvdplas Jul 31, 2024
772514c
refactor: IT create token in constructor
Daanvdplas Jul 31, 2024
b164998
merge asset management
Daanvdplas Jul 31, 2024
12e1cf9
test: remove commented out test
Daanvdplas Jul 31, 2024
68ec059
fix: test
Daanvdplas Jul 31, 2024
0311d9a
draft api events
Daanvdplas Jul 31, 2024
95bf679
merge daan/api
Daanvdplas Aug 6, 2024
3a777d5
feat: events to all features + tests
Daanvdplas Aug 6, 2024
bc8181c
feat (api): events fungibles
Daanvdplas Aug 6, 2024
6b10f2a
fix: compilation
Daanvdplas Aug 7, 2024
626b3eb
fix: weight increase_allowance
Daanvdplas Aug 7, 2024
7c0b3fd
refactor: remove duplicated events
Daanvdplas Aug 12, 2024
9862e19
refactor: ink topics + docs to contract events
Daanvdplas Aug 12, 2024
28977a0
fix: incompatible event based on standard
Daanvdplas Aug 12, 2024
9ea2488
refactor: optimization pallet fungibles
Daanvdplas Aug 12, 2024
0904910
fix: weight increase_allowance
Daanvdplas Aug 12, 2024
ea2b461
docs: events contracts
Daanvdplas Aug 12, 2024
5093e88
refactor: remove unnecessary event topic
Daanvdplas Aug 13, 2024
24aa42d
Merge branch 'daan/api' into daan/feat-api_events
Daanvdplas Aug 13, 2024
1d283fd
Merge branch 'daan/api' into daan/feat-api_events
Daanvdplas Aug 13, 2024
221f63d
Merge branch 'daan/api' into daan/feat-api_events
Daanvdplas Aug 13, 2024
3848faa
fix: add asset ID to event
Daanvdplas Aug 13, 2024
6a9cd00
feat: add Create event
Daanvdplas Aug 14, 2024
3b3ae9f
refactor: fungible pallet
Daanvdplas Aug 14, 2024
fa7d258
refactor: consistency
Daanvdplas Aug 14, 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
182 changes: 138 additions & 44 deletions pallets/api/src/fungibles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub mod pallet {
/// Configure the pallet by specifying the parameters and types on which it depends.
#[pallet::config]
pub trait Config: frame_system::Config + pallet_assets::Config<Self::AssetsInstance> {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// The instance of pallet assets it is tightly coupled to.
type AssetsInstance;
/// Weight information for dispatchables in this pallet.
Expand All @@ -93,6 +95,43 @@ pub mod pallet {
#[pallet::pallet]
pub struct Pallet<T>(_);

/// The events that can be emitted.
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
Daanvdplas marked this conversation as resolved.
Show resolved Hide resolved
/// Event emitted when allowance by `owner` to `spender` changes.
Approval {
/// The ID of the asset.
id: AssetIdOf<T>,
/// Account providing allowance.
owner: AccountIdOf<T>,
/// Allowance beneficiary.
spender: AccountIdOf<T>,
/// New allowance amount.
value: BalanceOf<T>,
},
/// Event emitted when transfer of tokens occurs.
Transfer {
/// The ID of the asset.
id: AssetIdOf<T>,
/// Transfer sender. `None` in case of minting new tokens.
from: Option<AccountIdOf<T>>,
/// Transfer recipient. `None` in case of burning tokens.
to: Option<AccountIdOf<T>>,
/// Amount of tokens transferred (or minted/burned).
value: BalanceOf<T>,
},
/// Event emitted when a token class is created.
Create {
Daanvdplas marked this conversation as resolved.
Show resolved Hide resolved
/// The ID of the asset.
id: AssetIdOf<T>,
/// Creator of the asset.
creator: AccountIdOf<T>,
/// Admin of the asset.
admin: AccountIdOf<T>,
},
}

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Transfers `value` amount of tokens from the caller's account to account `to`, with additional
Expand All @@ -110,16 +149,23 @@ pub mod pallet {
to: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let to = T::Lookup::unlookup(to);
AssetsOf::<T>::transfer_keep_alive(origin, id.into(), to, value)
AssetsOf::<T>::transfer_keep_alive(
origin.clone(),
id.clone().into(),
T::Lookup::unlookup(to.clone()),
value,
)?;
let from = ensure_signed(origin)?;
Self::deposit_event(Event::Transfer { id, from: Some(from), to: Some(to), value });
Ok(())
}

/// 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.
/// - `from` - 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)]
Expand All @@ -131,9 +177,15 @@ pub mod pallet {
to: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let from = T::Lookup::unlookup(from);
let to = T::Lookup::unlookup(to);
AssetsOf::<T>::transfer_approved(origin, id.into(), from, to, value)
AssetsOf::<T>::transfer_approved(
origin,
id.clone().into(),
T::Lookup::unlookup(from.clone()),
T::Lookup::unlookup(to.clone()),
value,
)?;
Self::deposit_event(Event::Transfer { id, from: Some(from), to: Some(to), value });
Ok(())
}

/// Approves an account to spend a specified number of tokens on behalf of the caller.
Expand All @@ -150,22 +202,20 @@ pub mod pallet {
spender: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin.clone())
let owner = ensure_signed(origin.clone())
.map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?;
let current_allowance = AssetsOf::<T>::allowance(id.clone(), &who, &spender);
let spender = T::Lookup::unlookup(spender);
let id: AssetIdParameterOf<T> = id.into();
let current_allowance = AssetsOf::<T>::allowance(id.clone(), &owner, &spender);

let return_weight = match value.cmp(&current_allowance) {
let 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,
id.clone().into(),
T::Lookup::unlookup(spender.clone()),
value.saturating_sub(current_allowance),
)
.map_err(|e| e.with_weight(Self::weight_approve(1, 0)))?;
Expand All @@ -174,16 +224,24 @@ pub mod pallet {
// 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)))?;
let id_param: AssetIdParameterOf<T> = id.clone().into();
let spender_source = T::Lookup::unlookup(spender.clone());
AssetsOf::<T>::cancel_approval(
origin.clone(),
id_param.clone(),
spender_source.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());
Self::weight_approve(0, 1)
} else {
AssetsOf::<T>::approve_transfer(origin, id_param, spender_source, value)?;
Self::weight_approve(1, 1)
}
AssetsOf::<T>::approve_transfer(origin, id, spender, value)?;
Self::weight_approve(1, 1)
},
};
Ok(Some(return_weight).into())
Self::deposit_event(Event::Approval { id, owner, spender, value });
Ok(Some(weight).into())
}

/// Increases the allowance of a spender.
Expand All @@ -193,15 +251,25 @@ pub mod pallet {
/// - `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())]
#[pallet::weight(<T as Config>::WeightInfo::approve(1, 0))]
pub fn increase_allowance(
origin: OriginFor<T>,
id: AssetIdOf<T>,
spender: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let spender = T::Lookup::unlookup(spender);
AssetsOf::<T>::approve_transfer(origin, id.into(), spender, value)
) -> DispatchResultWithPostInfo {
let owner = ensure_signed(origin.clone())
.map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?;
AssetsOf::<T>::approve_transfer(
origin,
id.clone().into(),
T::Lookup::unlookup(spender.clone()),
value,
)
.map_err(|e| e.with_weight(AssetsWeightInfoOf::<T>::approve_transfer()))?;
let value = AssetsOf::<T>::allowance(id.clone(), &owner, &spender);
Self::deposit_event(Event::Approval { id, owner, spender, value });
Ok(().into())
}

/// Decreases the allowance of a spender.
Expand All @@ -218,24 +286,31 @@ pub mod pallet {
spender: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin.clone())
let owner = ensure_signed(origin.clone())
.map_err(|e| e.with_weight(Self::weight_approve(0, 0)))?;
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());
}
// 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)))?;
let current_allowance = AssetsOf::<T>::allowance(id.clone(), &owner, &spender);
let spender_source = T::Lookup::unlookup(spender.clone());
let id_param: AssetIdParameterOf<T> = id.clone().into();

// Cancel the approval and set the new value if `new_allowance` is more than zero.
AssetsOf::<T>::cancel_approval(
origin.clone(),
id_param.clone(),
spender_source.clone(),
)
.map_err(|e| e.with_weight(Self::weight_approve(0, 1)))?;
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, new_allowance)?;
Ok(().into())
let weight = if new_allowance.is_zero() {
Self::weight_approve(0, 1)
} else {
AssetsOf::<T>::approve_transfer(origin, id_param, spender_source, new_allowance)?;
Self::weight_approve(1, 1)
};
Self::deposit_event(Event::Approval { id, owner, spender, value: new_allowance });
Ok(Some(weight).into())
}

/// Create a new token with a given asset ID.
Expand All @@ -252,8 +327,15 @@ pub mod pallet {
admin: AccountIdOf<T>,
min_balance: BalanceOf<T>,
) -> DispatchResult {
let admin = T::Lookup::unlookup(admin);
AssetsOf::<T>::create(origin, id.into(), admin, min_balance)
let creator = ensure_signed(origin.clone())?;
AssetsOf::<T>::create(
origin,
id.clone().into(),
T::Lookup::unlookup(admin.clone()),
min_balance,
)?;
Self::deposit_event(Event::Create { id, creator, admin });
Ok(())
}

/// Start the process of destroying a token with a given asset ID.
Expand Down Expand Up @@ -297,7 +379,7 @@ pub mod pallet {
AssetsOf::<T>::clear_metadata(origin, id.into())
}

/// Creates `value` amount tokens and assigns them to `account`, increasing the total supply.
/// Creates `value` amount of tokens and assigns them to `account`, increasing the total supply.
///
/// # Parameters
/// - `id` - The ID of the asset.
Expand All @@ -311,11 +393,17 @@ pub mod pallet {
account: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let account = T::Lookup::unlookup(account);
AssetsOf::<T>::mint(origin, id.into(), account, value)
AssetsOf::<T>::mint(
origin,
id.clone().into(),
T::Lookup::unlookup(account.clone()),
value,
)?;
Self::deposit_event(Event::Transfer { id, from: None, to: Some(account), value });
Ok(())
}

/// Destroys `value` amount tokens from `account`, reducing the total supply.
/// Destroys `value` amount of tokens from `account`, reducing the total supply.
///
/// # Parameters
/// - `id` - The ID of the asset.
Expand All @@ -329,8 +417,14 @@ pub mod pallet {
account: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let account = T::Lookup::unlookup(account);
AssetsOf::<T>::burn(origin, id.into(), account, value)
AssetsOf::<T>::burn(
origin,
id.clone().into(),
T::Lookup::unlookup(account.clone()),
value,
)?;
Self::deposit_event(Event::Transfer { id, from: Some(account), to: None, value });
Ok(())
}
}

Expand Down
Loading
Loading