diff --git a/examples/fungible-token/ft/Cargo.toml b/examples/fungible-token/ft/Cargo.toml index 664d923b0..9c861d848 100644 --- a/examples/fungible-token/ft/Cargo.toml +++ b/examples/fungible-token/ft/Cargo.toml @@ -10,3 +10,6 @@ crate-type = ["cdylib"] [dependencies] near-sdk = { path = "../../../near-sdk" } near-contract-standards = { path = "../../../near-contract-standards" } + +[dev-dependencies] +near-contract-standards = { path = "../../../near-contract-standards", default-features = false, features = ["unit-testing"]} \ No newline at end of file diff --git a/examples/fungible-token/ft/src/lib.rs b/examples/fungible-token/ft/src/lib.rs index a6be56935..6fd8f4bc4 100644 --- a/examples/fungible-token/ft/src/lib.rs +++ b/examples/fungible-token/ft/src/lib.rs @@ -199,6 +199,33 @@ mod tests { builder } + #[test] + fn test_fungible_token_core() { + let mut context = get_context(accounts(2)); + testing_env!(context.build()); + let mut contract = Contract::new_default_meta(accounts(2).into(), TOTAL_SUPPLY.into()); + testing_env!(context + .storage_usage(env::storage_usage()) + .attached_deposit(contract.storage_balance_bounds().min.into()) + .predecessor_account_id(accounts(1)) + .build()); + // Paying for account registration, aka storage deposit + contract.storage_deposit(None, None); + + testing_env!(context + .storage_usage(env::storage_usage()) + .attached_deposit(NearToken::from_yoctonear(1)) + .predecessor_account_id(accounts(2)) + .build()); + near_contract_standards::fungible_token::core::tests::test(&mut contract); + } + + #[test] + fn test_fungible_token_metadata() { + let mut contract = Contract::new_default_meta(accounts(2).into(), TOTAL_SUPPLY.into()); + near_contract_standards::fungible_token::metadata::tests::test(&mut contract); + } + #[test] fn test_new() { let mut context = get_context(accounts(1)); diff --git a/near-contract-standards/Cargo.toml b/near-contract-standards/Cargo.toml index 7b7cf8512..7b94137a7 100644 --- a/near-contract-standards/Cargo.toml +++ b/near-contract-standards/Cargo.toml @@ -21,3 +21,4 @@ near-sdk = { path = "../near-sdk", default-features = false, features = ["unit-t [features] default = [] abi = ["near-sdk/abi"] +unit-testing = [] diff --git a/near-contract-standards/src/fungible_token/core.rs b/near-contract-standards/src/fungible_token/core.rs index defe0752c..7d1e4d566 100644 --- a/near-contract-standards/src/fungible_token/core.rs +++ b/near-contract-standards/src/fungible_token/core.rs @@ -100,3 +100,38 @@ pub trait FungibleTokenCore { /// Returns the balance of the account. If the account doesn't exist must returns `"0"`. fn ft_balance_of(&self, account_id: AccountId) -> U128; } + +#[cfg(all(not(target_arch = "wasm32"), feature = "unit-testing"))] +pub mod tests { + + use near_sdk::test_utils::accounts; + + use super::*; + + fn test_transfer_ok(contract: &mut impl FungibleTokenCore) { + assert_eq!(contract.ft_balance_of(accounts(2)), U128(1_000_000_000_000_000)); + assert_eq!(contract.ft_balance_of(accounts(1)), U128(0)); + let amount = contract.ft_total_supply().0 / 4; + contract.ft_transfer(accounts(1), amount.into(), None); + assert_eq!(contract.ft_balance_of(accounts(2)).0, contract.ft_total_supply().0 - amount); + assert_eq!(contract.ft_balance_of(accounts(1)).0, amount); + } + + fn test_transfer_call_ok(contract: &mut impl FungibleTokenCore) { + let amount = contract.ft_total_supply().0 / 4; + let result = contract.ft_transfer_call(accounts(1), amount.into(), None, "".to_string()); + match result { + PromiseOrValue::Promise(_promise) => { + println!("Handle promise here"); + } + _ => panic!("Expected Promise variant"), + } + assert_eq!(contract.ft_balance_of(accounts(2)).0, contract.ft_total_supply().0 / 2); + assert_eq!(contract.ft_balance_of(accounts(1)).0, contract.ft_total_supply().0 / 2); + } + + pub fn test(contract: &mut impl FungibleTokenCore) { + test_transfer_ok(contract); + test_transfer_call_ok(contract); + } +} diff --git a/near-contract-standards/src/fungible_token/metadata.rs b/near-contract-standards/src/fungible_token/metadata.rs index 1eecbbbf9..c976e07b5 100644 --- a/near-contract-standards/src/fungible_token/metadata.rs +++ b/near-contract-standards/src/fungible_token/metadata.rs @@ -29,3 +29,24 @@ impl FungibleTokenMetadata { } } } + +#[cfg(all(not(target_arch = "wasm32"), feature = "unit-testing"))] +pub mod tests { + use super::FungibleTokenMetadataProvider; + use crate::fungible_token::metadata::FT_METADATA_SPEC; + + fn ft_metadata_ok(contract: &mut impl FungibleTokenMetadataProvider) { + let metadata = contract.ft_metadata(); + assert_eq!(metadata.spec, FT_METADATA_SPEC.to_string()); + assert_eq!(metadata.name, "Example NEAR fungible token"); + assert_eq!(metadata.symbol, "EXAMPLE".to_string()); + assert_eq!(metadata.icon, Some("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 288 288'%3E%3Cg id='l' data-name='l'%3E%3Cpath d='M187.58,79.81l-30.1,44.69a3.2,3.2,0,0,0,4.75,4.2L191.86,103a1.2,1.2,0,0,1,2,.91v80.46a1.2,1.2,0,0,1-2.12.77L102.18,77.93A15.35,15.35,0,0,0,90.47,72.5H87.34A15.34,15.34,0,0,0,72,87.84V201.16A15.34,15.34,0,0,0,87.34,216.5h0a15.35,15.35,0,0,0,13.08-7.31l30.1-44.69a3.2,3.2,0,0,0-4.75-4.2L96.14,186a1.2,1.2,0,0,1-2-.91V104.61a1.2,1.2,0,0,1,2.12-.77l89.55,107.23a15.35,15.35,0,0,0,11.71,5.43h3.13A15.34,15.34,0,0,0,216,201.16V87.84A15.34,15.34,0,0,0,200.66,72.5h0A15.35,15.35,0,0,0,187.58,79.81Z'/%3E%3C/g%3E%3C/svg%3E".to_string())); + assert_eq!(metadata.reference, None); + assert_eq!(metadata.reference_hash, None); + assert_eq!(metadata.decimals, 24); + } + + pub fn test(contract: &mut impl FungibleTokenMetadataProvider) { + ft_metadata_ok(contract); + } +}