Skip to content

Commit

Permalink
feat: convenience constructor functions
Browse files Browse the repository at this point in the history
  • Loading branch information
encody committed May 8, 2024
1 parent 831b9af commit 3a74539
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 87 deletions.
9 changes: 4 additions & 5 deletions src/standard/nep141/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ impl<C: Nep141Controller + Nep141ControllerInternal> Hook<C, Nep145ForceUnregist

let balance = contract.balance_of(&args.account_id);
contract
.burn(&Nep141Burn {
amount: balance,
owner_id: args.account_id.clone(),
memo: Some("storage forced unregistration".into()),
})
.burn(
&Nep141Burn::new(balance, args.account_id.clone())
.memo("storage forced unregistration"),
)
.unwrap_or_else(|e| {
near_sdk::env::panic_str(&format!(
"Failed to burn tokens during forced unregistration: {e}",
Expand Down
70 changes: 70 additions & 0 deletions src/standard/nep141/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,38 @@ pub struct Nep141Transfer<'a> {
}

impl<'a> Nep141Transfer<'a> {
/// Create a new transfer action.
pub fn new(
amount: u128,
sender_id: impl Into<Cow<'a, AccountIdRef>>,
receiver_id: impl Into<Cow<'a, AccountIdRef>>,
) -> Self {
Self {
sender_id: sender_id.into(),
receiver_id: receiver_id.into(),
amount,
memo: None,
msg: None,
revert: false,
}
}

/// Add a memo string.
pub fn memo(self, memo: impl Into<Cow<'a, str>>) -> Self {
Self {
memo: Some(memo.into()),
..self
}
}

/// Add a message string.
pub fn msg(self, msg: impl Into<Cow<'a, str>>) -> Self {
Self {
msg: Some(msg.into()),
..self
}
}

/// Returns `true` if this transfer comes from a `ft_transfer_call`
/// call, `false` otherwise.
pub fn is_transfer_call(&self) -> bool {
Expand All @@ -72,6 +104,25 @@ pub struct Nep141Mint<'a> {
pub memo: Option<Cow<'a, str>>,
}

impl<'a> Nep141Mint<'a> {
/// Create a new mint action.
pub fn new(amount: u128, receiver_id: impl Into<Cow<'a, AccountIdRef>>) -> Self {
Self {
amount,
receiver_id: receiver_id.into(),
memo: None,
}
}

/// Add a memo string.
pub fn memo(self, memo: impl Into<Cow<'a, str>>) -> Self {
Self {
memo: Some(memo.into()),
..self
}
}
}

/// Describes a burn operation.
#[derive(Clone, Debug, PartialEq, Eq)]
#[near]
Expand All @@ -84,6 +135,25 @@ pub struct Nep141Burn<'a> {
pub memo: Option<Cow<'a, str>>,
}

impl<'a> Nep141Burn<'a> {
/// Create a new burn action.
pub fn new(amount: u128, owner_id: impl Into<Cow<'a, AccountIdRef>>) -> Self {
Self {
amount,
owner_id: owner_id.into(),
memo: None,
}
}

/// Add a memo string.
pub fn memo(self, memo: impl Into<Cow<'a, str>>) -> Self {
Self {
memo: Some(memo.into()),
..self
}
}
}

/// Internal functions for [`Nep141Controller`]. Using these methods may result in unexpected behavior.
pub trait Nep141ControllerInternal {
/// Hook for mint operations.
Expand Down
74 changes: 74 additions & 0 deletions src/standard/nep171/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ pub struct Nep171Mint<'a> {
pub memo: Option<Cow<'a, str>>,
}

impl<'a> Nep171Mint<'a> {
/// Create a new mint action.
pub fn new(token_ids: Vec<TokenId>, receiver_id: impl Into<Cow<'a, AccountIdRef>>) -> Self {
Self {
token_ids,
receiver_id: receiver_id.into(),
memo: None,
}
}

/// Add a memo string.
pub fn memo(self, memo: impl Into<Cow<'a, str>>) -> Self {
Self {
memo: Some(memo.into()),
..self
}
}
}

/// NEP-171 burn action.
#[derive(Clone, Debug, PartialEq, Eq)]
#[near]
Expand All @@ -31,6 +50,25 @@ pub struct Nep171Burn<'a> {
pub memo: Option<Cow<'a, str>>,
}

impl<'a> Nep171Burn<'a> {
/// Create a new burn action.
pub fn new(token_ids: Vec<TokenId>, owner_id: impl Into<Cow<'a, AccountIdRef>>) -> Self {
Self {
token_ids,
owner_id: owner_id.into(),
memo: None,
}
}

/// Add a memo string.
pub fn memo(self, memo: impl Into<Cow<'a, str>>) -> Self {
Self {
memo: Some(memo.into()),
..self
}
}
}

/// Transfer metadata generic over both types of transfer (`nft_transfer` and
/// `nft_transfer_call`).
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
Expand All @@ -51,3 +89,39 @@ pub struct Nep171Transfer<'a> {
/// `true` if the transfer is a revert for a `nft_transfer_call`.
pub revert: bool,
}

impl<'a> Nep171Transfer<'a> {
/// Create a new transfer action.
pub fn new(
token_id: TokenId,
sender_id: impl Into<Cow<'a, AccountIdRef>>,
receiver_id: impl Into<Cow<'a, AccountIdRef>>,
authorization: Nep171TransferAuthorization,
) -> Self {
Self {
authorization,
sender_id: sender_id.into(),
receiver_id: receiver_id.into(),
token_id,
memo: None,
msg: None,
revert: false,
}
}

/// Add a memo string.
pub fn memo(self, memo: impl Into<Cow<'a, str>>) -> Self {
Self {
memo: Some(memo.into()),
..self
}
}

/// Add a message string.
pub fn msg(self, msg: impl Into<Cow<'a, str>>) -> Self {
Self {
msg: Some(msg.into()),
..self
}
}
}
9 changes: 4 additions & 5 deletions src/standard/nep171/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ where
contract.with_tokens_for_owner(&action.account_id, |t| t.iter().collect::<Vec<_>>());

contract
.burn(&Nep171Burn {
token_ids,
owner_id: action.account_id.clone(),
memo: Some("storage forced unregistration".into()),
})
.burn(
&Nep171Burn::new(token_ids, action.account_id.clone())
.memo("storage forced unregistration"),
)
.unwrap_or_else(|e| {
near_sdk::env::panic_str(&format!(
"Failed to burn tokens during forced unregistration: {e}",
Expand Down
12 changes: 2 additions & 10 deletions src/standard/nep177.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,7 @@ impl<T: Nep177ControllerInternal + Nep171Controller> Nep177Controller for T {
owner_id: &AccountIdRef,
metadata: &TokenMetadata,
) -> Result<(), Nep171MintError> {
self.mint(&Nep171Mint {
token_ids: vec![token_id.clone()],
receiver_id: owner_id.into(),
memo: None,
})?;
self.mint(&Nep171Mint::new(vec![token_id.clone()], owner_id))?;
self.set_token_metadata_unchecked(token_id, Some(metadata));
Ok(())
}
Expand All @@ -316,11 +312,7 @@ impl<T: Nep177ControllerInternal + Nep171Controller> Nep177Controller for T {
token_id: &TokenId,
owner_id: &AccountId,
) -> Result<(), Nep171BurnError> {
self.burn(&Nep171Burn {
token_ids: vec![token_id.clone()],
owner_id: owner_id.into(),
memo: None,
})?;
self.burn(&Nep171Burn::new(vec![token_id.clone()], owner_id))?;
self.set_token_metadata_unchecked(token_id, None);
Ok(())
}
Expand Down
6 changes: 1 addition & 5 deletions tests/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,11 +528,7 @@ mod owned_fungible_token {
pub fn mint(&mut self, amount: U128) {
Nep141Controller::mint(
self,
&Nep141Mint {
amount: amount.into(),
receiver_id: env::predecessor_account_id().into(),
memo: None,
},
&Nep141Mint::new(amount.0, env::predecessor_account_id()),
)
.unwrap();
}
Expand Down
16 changes: 3 additions & 13 deletions tests/macros/standard/nep141.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,14 @@ fn nep141_transfer() {

assert_eq!(
ft.transfers.pop(),
Some(
borsh::to_vec(&Nep141Transfer {
sender_id: alice.clone().into(),
receiver_id: bob.clone().into(),
amount: 50,
memo: None,
msg: None,
revert: false,
})
.unwrap()
)
Some(borsh::to_vec(&Nep141Transfer::new(50, alice.clone(), bob.clone())).unwrap())
);

let expected_hook_execution_order = vec!["before_transfer", "after_transfer"];
let actual_hook_execution_order = ft.hooks.to_vec();
assert_eq!(expected_hook_execution_order, actual_hook_execution_order);

assert_eq!(ft.ft_balance_of(alice.clone()).0, 50);
assert_eq!(ft.ft_balance_of(bob.clone()).0, 70);
assert_eq!(ft.ft_balance_of(alice).0, 50);
assert_eq!(ft.ft_balance_of(bob).0, 70);
assert_eq!(ft.ft_total_supply().0, 120);
}
13 changes: 5 additions & 8 deletions tests/macros/standard/nep171/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,11 @@ impl NonFungibleToken {
}

pub fn mint(&mut self, token_id: TokenId, receiver_id: AccountId) {
let action = Nep171Mint {
token_ids: vec![token_id],
receiver_id: receiver_id.into(),
memo: None,
};
Nep171Controller::mint(self, &action).unwrap_or_else(|e| {
env::panic_str(&format!("Mint failed: {e:?}"));
});
Nep171Controller::mint(self, &Nep171Mint::new(vec![token_id], receiver_id)).unwrap_or_else(
|e| {
env::panic_str(&format!("Mint failed: {e:?}"));
},
);
}
}

Expand Down
12 changes: 5 additions & 7 deletions tests/macros/standard/nep171/no_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ impl Contract {
let token_id = format!("token_{}", self.next_token_id);
self.next_token_id += 1;

let action = Nep171Mint {
token_ids: vec![token_id.clone()],
receiver_id: env::predecessor_account_id().into(),
memo: None,
};
Nep171Controller::mint(self, &action)
.unwrap_or_else(|e| env::panic_str(&format!("Minting failed: {e}")));
Nep171Controller::mint(
self,
&Nep171Mint::new(vec![token_id.clone()], env::predecessor_account_id()),
)
.unwrap_or_else(|e| env::panic_str(&format!("Minting failed: {e}")));

token_id
}
Expand Down
6 changes: 1 addition & 5 deletions workspaces-tests/src/bin/fungible_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ impl Contract {
pub fn mint(&mut self, amount: U128) {
Nep141Controller::mint(
self,
&Nep141Mint {
amount: amount.into(),
receiver_id: env::predecessor_account_id().into(),
memo: None,
},
&Nep141Mint::new(amount.0, env::predecessor_account_id()),
)
.unwrap();
}
Expand Down
14 changes: 6 additions & 8 deletions workspaces-tests/src/bin/non_fungible_token_nep171.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
workspaces_tests::predicate!();

use near_sdk::{env, log, near, PanicOnDefault};
use near_sdk_contract_tools::{hook::Hook, standard::nep171::*, Nep171};
use near_sdk_contract_tools::{hook::Hook, nft::Nep171Mint, standard::nep171::*, Nep171};

#[derive(Nep171, PanicOnDefault)]
#[nep171(transfer_hook = "Self")]
Expand Down Expand Up @@ -29,12 +29,10 @@ impl Contract {
}

pub fn mint(&mut self, token_ids: Vec<TokenId>) {
let action = action::Nep171Mint {
token_ids,
receiver_id: env::predecessor_account_id().into(),
memo: None,
};
Nep171Controller::mint(self, &action)
.unwrap_or_else(|e| env::panic_str(&format!("Failed to mint: {:#?}", e)));
Nep171Controller::mint(
self,
&Nep171Mint::new(token_ids, env::predecessor_account_id()),
)
.unwrap_or_else(|e| env::panic_str(&format!("Failed to mint: {:#?}", e)));
}
}
Loading

0 comments on commit 3a74539

Please sign in to comment.