diff --git a/maths/Cargo.toml b/maths/Cargo.toml index 87cbc1b..f5d561a 100644 --- a/maths/Cargo.toml +++ b/maths/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "decimal-maths" -version = "0.0.1" +version = "0.2.1" license = "MIT" edition = "2021" [dependencies] -radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine-common = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } +radix-common = "1.2.0" +radix-common-derive = "1.2.0" [lib] diff --git a/maths/src/exponential.rs b/maths/src/exponential.rs index be50a08..5613acc 100644 --- a/maths/src/exponential.rs +++ b/maths/src/exponential.rs @@ -1,4 +1,4 @@ -use radix_engine::types::{Decimal, I192, I256}; +use crate::internal_prelude::*; pub const SMALLEST_NON_ZERO: Decimal = Decimal(I192::from_digits([ 13893700547235832536, @@ -41,8 +41,9 @@ impl Exponential for Decimal { #[cfg(test)] mod test_exp { use crate::exponential::{Exponential, SMALLEST_NON_ZERO}; + use crate::internal_prelude::*; use crate::RELATIVE_PRECISION; - use radix_engine::types::{dec, Decimal, I192}; + use radix_common_derive::dec; #[test] fn test_zero() { diff --git a/maths/src/internal_prelude.rs b/maths/src/internal_prelude.rs new file mode 100644 index 0000000..8fe3bfe --- /dev/null +++ b/maths/src/internal_prelude.rs @@ -0,0 +1 @@ +pub use radix_common::prelude::{Decimal, I192, I256, U192}; diff --git a/maths/src/lib.rs b/maths/src/lib.rs index e2c2b2a..2dc7cf0 100644 --- a/maths/src/lib.rs +++ b/maths/src/lib.rs @@ -1,6 +1,6 @@ -use radix_engine::types::{Decimal, I192}; - +use internal_prelude::*; pub mod exponential; +pub(crate) mod internal_prelude; pub mod logarithm; pub mod power; diff --git a/maths/src/logarithm.rs b/maths/src/logarithm.rs index b90aae4..c14e1d0 100644 --- a/maths/src/logarithm.rs +++ b/maths/src/logarithm.rs @@ -1,5 +1,5 @@ use crate::exponential::Exponential; -use radix_engine::types::{Decimal, I192, U192}; +use crate::internal_prelude::*; pub const LN_2: Decimal = Decimal(I192::from_digits([693147180559945309, 0, 0])); pub const LN_10: Decimal = Decimal(I192::from_digits([2302585092994045684, 0, 0])); @@ -77,9 +77,10 @@ impl Logarithm for Decimal { #[cfg(test)] mod test_ln { use crate::exponential::Exponential; + use crate::internal_prelude::*; use crate::logarithm::{Logarithm, LN_2}; use crate::RELATIVE_PRECISION; - use radix_engine::types::{dec, Decimal, I192}; + use radix_common_derive::dec; #[test] #[should_panic] diff --git a/maths/src/power.rs b/maths/src/power.rs index 0384b60..ede79e7 100644 --- a/maths/src/power.rs +++ b/maths/src/power.rs @@ -1,6 +1,6 @@ use crate::exponential::Exponential; +use crate::internal_prelude::*; use crate::logarithm::Logarithm; -use radix_engine::types::Decimal; pub trait Power { fn pow(self, exp: Self) -> Self; diff --git a/test-engine/Cargo.toml b/test-engine/Cargo.toml index 3c978da..6877aaa 100644 --- a/test-engine/Cargo.toml +++ b/test-engine/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "test-engine" -version = "0.2.0" +version = "0.2.1" license = "MIT" edition = "2021" [dependencies] -radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine-stores = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -transaction = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto-unit = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine-common = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } +radix-common = "1.2.0" +radix-engine = "1.2.0" +radix-engine-interface = "1.2.0" +radix-transactions = "1.2.0" +scrypto-test = "1.2.0" +radix-substate-store-impls = "1.2.0" lazy_static = "1.4.0" +indexmap = "2.2.6" [lib] diff --git a/test-engine/README.md b/test-engine/README.md index da0b268..3e3743a 100644 --- a/test-engine/README.md +++ b/test-engine/README.md @@ -15,7 +15,7 @@ test-engine = { git = "https://github.com/BeakerTools/scrypto-toolkit", branch = - [Basics](tutorials/1.Basics.md) - [Packages and blueprints](tutorials/2.Packages_and_Blueprints.md) -- [Calling methods](tutorials/3.Method_Calls.md) +- [Calling methods](tutorials/3.Methods_Calls) # Examples diff --git a/test-engine/src/account.rs b/test-engine/src/account.rs index 7f93700..6c83eb6 100644 --- a/test-engine/src/account.rs +++ b/test-engine/src/account.rs @@ -1,10 +1,5 @@ -use radix_engine::types::Secp256k1PublicKey; -use radix_engine_common::crypto::PublicKey; -use radix_engine_interface::blueprints::resource::FromPublicKey; -use radix_engine_interface::prelude::NonFungibleGlobalId; -use radix_engine_interface::types::ComponentAddress; - use crate::engine_interface::EngineInterface; +use crate::internal_prelude::*; #[derive(Debug, Clone)] pub struct Account { diff --git a/test-engine/src/call_builder.rs b/test-engine/src/call_builder.rs index 606cbae..cef8fae 100644 --- a/test-engine/src/call_builder.rs +++ b/test-engine/src/call_builder.rs @@ -1,24 +1,13 @@ use std::collections::BTreeSet; use std::vec::Vec; -use radix_engine::transaction::{TransactionReceipt, TransactionResult}; -use radix_engine::types::{ - manifest_decode, ComponentAddress, Decimal, Encoder, ManifestArgs, ManifestEncoder, - ManifestExpression, ManifestValueKind, NonFungibleLocalId, PackageAddress, ResourceAddress, - FAUCET, MANIFEST_SBOR_V1_MAX_DEPTH, MANIFEST_SBOR_V1_PAYLOAD_PREFIX, -}; - -use transaction::builder::{ManifestBuilder, ResolvableGlobalAddress}; -use transaction::manifest::decompiler::ManifestObjectNames; -use transaction::manifest::dumper::dump_manifest_to_file_system; -use transaction::prelude::{dec, DynamicGlobalAddress, ResolvableArguments, TransactionManifestV1}; - use crate::account::Account; -use crate::environment::{Environment, EnvironmentEncode}; -use crate::manifest_args; +use crate::environment::{EnvironmentEncode, Fungible, NonFungible}; +use crate::internal_prelude::*; use crate::method_call::SimpleMethodCaller; use crate::references::{ComponentReference, GlobalReference, ReferenceName, ResourceReference}; use crate::test_engine::TestEngine; +use crate::to_id::ToId; struct TransactionManifestData { transaction_manifest: TransactionManifestV1, @@ -150,7 +139,11 @@ impl<'a> CallBuilder<'a> { /// * `recipient`: resources to transfer to. /// * `resource`: reference name of the resource to transfer. /// * `amount`: amount to transfer. - pub fn transfer>( + pub fn transfer< + E: ReferenceName, + R: ReferenceName + Clone + 'static, + D: TryInto + Clone + 'static, + >( self, recipient: E, resource: R, @@ -163,10 +156,7 @@ impl<'a> CallBuilder<'a> { recipient, "try_deposit_or_abort", vec![ - Box::new(Environment::FungibleBucket( - resource.clone(), - amount.try_into().unwrap(), - )), + Box::new(Fungible::Bucket(resource.clone(), amount)), Box::new(None::), ], ) @@ -178,17 +168,20 @@ impl<'a> CallBuilder<'a> { /// * `recipient`: resources to transfer to. /// * `resource`: reference name of the resource to transfer. /// * `ids`: ids to transfer. - pub fn transfer_non_fungibles( + pub fn transfer_non_fungibles( self, recipient: E, resource: R, - ids: Vec, + ids: Vec, ) -> Self { self.call_from_component( recipient, "try_deposit_or_abort", vec![ - Box::new(Environment::NonFungibleBucket(resource, ids)), + Box::new(NonFungible::Bucket( + resource, + ids.into_iter().map(|id| id.to_id()).collect(), + )), Box::new(None::), ], ) @@ -351,7 +344,7 @@ impl<'a> CallBuilder<'a> { manifest.instructions.insert( 0, - transaction::model::InstructionV1::CallMethod { + InstructionV1::CallMethod { address: DynamicGlobalAddress::from(self.fee_payer), method_name: "lock_fee".to_string(), args: manifest_args!(self.fee_locked).resolve(), @@ -362,22 +355,19 @@ impl<'a> CallBuilder<'a> { fn write_deposit(&mut self) { let manifest = &mut self.manifest_data.as_mut().unwrap().transaction_manifest; - manifest - .instructions - .push(transaction::model::InstructionV1::CallMethod { - address: DynamicGlobalAddress::from(*self.caller.address()), - method_name: "deposit_batch".to_string(), - args: manifest_args!(ManifestExpression::EntireWorktop).resolve(), - }); + manifest.instructions.push(InstructionV1::CallMethod { + address: DynamicGlobalAddress::from(*self.caller.address()), + method_name: "deposit_batch".to_string(), + args: manifest_args!(ManifestExpression::EntireWorktop).resolve(), + }); } fn write_badge(&mut self) { let manifest = &mut self.manifest_data.as_mut().unwrap().transaction_manifest; - for (badge, opt_ids) in &self.admin_badge { if badge.is_fungible() { manifest.instructions.insert( 1, - transaction::model::InstructionV1::CallMethod { + InstructionV1::CallMethod { address: DynamicGlobalAddress::from(*self.caller.address()), method_name: "create_proof_of_amount".to_string(), args: manifest_args!(badge, Decimal::one()).resolve(), @@ -386,7 +376,7 @@ impl<'a> CallBuilder<'a> { } else { manifest.instructions.insert( 1, - transaction::model::InstructionV1::CallMethod { + InstructionV1::CallMethod { address: DynamicGlobalAddress::from(*self.caller.address()), method_name: "create_proof_of_non_fungibles".to_string(), args: manifest_args!(badge, opt_ids.clone().unwrap()).resolve(), diff --git a/test-engine/src/engine_interface.rs b/test-engine/src/engine_interface.rs index 0bc5373..febaf37 100644 --- a/test-engine/src/engine_interface.rs +++ b/test-engine/src/engine_interface.rs @@ -1,58 +1,30 @@ use std::collections::BTreeMap; use std::path::Path; -use radix_engine::prelude::btreeset; -use radix_engine::transaction::{CostingParameters, ExecutionConfig, TransactionReceipt}; -use radix_engine::types::{ - ComponentAddress, Decimal, Encoder, Epoch, GlobalAddress, NonFungibleLocalId, ResourceAddress, - Secp256k1PublicKey, -}; -use radix_engine_common::network::NetworkDefinition; -use radix_engine_common::prelude::{ - AddressBech32Decoder, ManifestAddressReservation, ManifestExpression, Own, ScryptoDecode, - ScryptoEncode, RESOURCE_PACKAGE, -}; -use radix_engine_common::to_manifest_value_and_unwrap; -use radix_engine_common::types::Round; -use radix_engine_interface::blueprints::consensus_manager::TimePrecisionV2; -use radix_engine_interface::blueprints::package::PackageDefinition; -use radix_engine_interface::prelude::{ - BlueprintId, FromPublicKey, FungibleResourceManagerCreateWithInitialSupplyManifestInput, - FungibleResourceRoles, MetadataValue, NonFungibleData, NonFungibleGlobalId, OwnerRole, - FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT, - FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT, -}; -use scrypto_unit::{CustomGenesis, DefaultTestRunner, TestRunnerBuilder}; -use transaction::builder::ManifestBuilder; -use transaction::model::{InstructionV1, TransactionManifestV1}; -use transaction::prelude::{ - DynamicGlobalAddress, PreAllocatedAddress, Secp256k1PrivateKey, TestTransaction, -}; - use crate::account::Account; -use crate::manifest_args; +use crate::internal_prelude::*; pub struct EngineInterface { - test_runner: DefaultTestRunner, + simulator: DefaultLedgerSimulator, } impl EngineInterface { pub fn new() -> Self { - let test_runner_builder = TestRunnerBuilder::new() + let test_runner_builder = LedgerSimulatorBuilder::new() .with_custom_genesis(CustomGenesis::default( Epoch::of(1), CustomGenesis::default_consensus_manager_config(), )) - .without_trace() + .without_kernel_trace() .build(); Self { - test_runner: test_runner_builder, + simulator: test_runner_builder, } } pub fn publish_package>(&mut self, package_dir: P) -> TransactionReceipt { - self.test_runner.try_publish_package(package_dir.as_ref()) + self.simulator.try_publish_package(package_dir.as_ref()) } pub fn publish_compiled_package( @@ -65,11 +37,11 @@ impl EngineInterface { .publish_package_advanced(None, code, definition, BTreeMap::new(), OwnerRole::None) .build(); - self.test_runner.execute_manifest(manifest, vec![]) + self.simulator.execute_manifest(manifest, vec![]) } pub fn new_account(&mut self) -> (Secp256k1PublicKey, Secp256k1PrivateKey, ComponentAddress) { - self.test_runner.new_account(false) + self.simulator.new_account(false) } pub fn execute_manifest( @@ -78,21 +50,20 @@ impl EngineInterface { with_trace: bool, initial_proofs: Vec, ) -> TransactionReceipt { - let nonce = self.test_runner.next_transaction_nonce(); + let nonce = self.simulator.next_transaction_nonce(); let exec_config = ExecutionConfig::for_test_transaction().with_kernel_trace(with_trace); - self.test_runner.execute_transaction( + self.simulator.execute_transaction( TestTransaction::new_from_nonce(manifest, nonce) .prepare() .expect("expected transaction to be preparable") .get_executable(initial_proofs.into_iter().collect()), - CostingParameters::default(), exec_config, ) } pub fn get_metadata(&mut self, address: GlobalAddress, key: &str) -> Option { - self.test_runner.get_metadata(address, key) + self.simulator.get_metadata(address, key) } pub fn nft_ids( @@ -101,11 +72,11 @@ impl EngineInterface { resource_address: ResourceAddress, ) -> Vec { let account_vault = self - .test_runner + .simulator .get_component_vaults(account, resource_address); let account_vault = account_vault.first(); account_vault.map_or(vec![], |vault_id| { - match self.test_runner.inspect_non_fungible_vault(*vault_id) { + match self.simulator.inspect_non_fungible_vault(*vault_id) { None => vec![], Some((_amount, ids)) => ids.collect(), } @@ -113,7 +84,7 @@ impl EngineInterface { } pub fn balance(&mut self, account: ComponentAddress, resource: ResourceAddress) -> Decimal { - self.test_runner.get_component_balance(account, resource) + self.simulator.get_component_balance(account, resource) } pub fn new_fungible( @@ -121,25 +92,25 @@ impl EngineInterface { account: ComponentAddress, initial_amount: Decimal, ) -> ResourceAddress { - self.test_runner + self.simulator .create_fungible_resource(initial_amount, 18, account) } pub fn set_epoch(&mut self, epoch: Epoch) { - self.test_runner.set_current_epoch(epoch); + self.simulator.set_current_epoch(epoch); } pub fn get_epoch(&mut self) -> Epoch { - self.test_runner.get_current_epoch() + self.simulator.get_current_epoch() } pub fn advance_time(&mut self, time: u64) { let current_time = self - .test_runner + .simulator .get_current_time(TimePrecisionV2::Second) .seconds_since_unix_epoch; - self.test_runner + self.simulator .advance_to_round_at_timestamp(Round::of(1), (current_time + (time as i64)) * 1000); } @@ -166,46 +137,44 @@ impl EngineInterface { .into(), ); - let receipt = self - .test_runner - .execute_system_transaction_with_preallocated_addresses( - vec![ - InstructionV1::CallFunction { - package_address: RESOURCE_PACKAGE.into(), - blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(), - function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT - .to_string(), - args: to_manifest_value_and_unwrap!( - &FungibleResourceManagerCreateWithInitialSupplyManifestInput { - owner_role: OwnerRole::None, - divisibility: 18, - track_total_supply: false, - metadata: Default::default(), - resource_roles: FungibleResourceRoles::default(), - initial_supply, - address_reservation: Some(ManifestAddressReservation(0)), - } - ), - }, - InstructionV1::CallMethod { - address: DynamicGlobalAddress::Static(GlobalAddress::new_or_panic( - (*default_account.address()).into(), - )), - method_name: "deposit_batch".to_string(), - args: manifest_args!(ManifestExpression::EntireWorktop).into(), - }, - ], - pre_allocated_addresses, - btreeset!(NonFungibleGlobalId::from_public_key( - &default_account.public_key() - )), - ); + let receipt = self.simulator.execute_system_transaction( + vec![ + InstructionV1::CallFunction { + package_address: RESOURCE_PACKAGE.into(), + blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(), + function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT + .to_string(), + args: to_manifest_value_and_unwrap!( + &FungibleResourceManagerCreateWithInitialSupplyManifestInput { + owner_role: OwnerRole::None, + divisibility: 18, + track_total_supply: false, + metadata: Default::default(), + resource_roles: FungibleResourceRoles::default(), + initial_supply, + address_reservation: Some(ManifestAddressReservation(0)), + } + ), + }, + InstructionV1::CallMethod { + address: DynamicGlobalAddress::Static(GlobalAddress::new_or_panic( + (*default_account.address()).into(), + )), + method_name: "deposit_batch".to_string(), + args: manifest_args!(ManifestExpression::EntireWorktop).into(), + }, + ], + btreeset!(NonFungibleGlobalId::from_public_key( + &default_account.public_key() + )), + pre_allocated_addresses, + ); receipt.expect_commit(true).new_resource_addresses()[0] } pub fn get_state(&self, component_address: ComponentAddress) -> T { - self.test_runner.component_state(component_address) + self.simulator.component_state(component_address) } pub fn get_kvs_entry( @@ -213,7 +182,7 @@ impl EngineInterface { kv_store_id: Own, key: &K, ) -> Option { - self.test_runner.get_kv_store_entry(kv_store_id, key) + self.simulator.get_kv_store_entry(kv_store_id, key) } pub fn get_non_fungible_data( @@ -221,6 +190,6 @@ impl EngineInterface { resource_address: ResourceAddress, id: NonFungibleLocalId, ) -> T { - self.test_runner.get_non_fungible_data(resource_address, id) + self.simulator.get_non_fungible_data(resource_address, id) } } diff --git a/test-engine/src/environment.rs b/test-engine/src/environment.rs index 0f60851..4ec8e1d 100644 --- a/test-engine/src/environment.rs +++ b/test-engine/src/environment.rs @@ -1,19 +1,23 @@ -use radix_engine::prelude::ValueKind; -use radix_engine::types::{ComponentAddress, Decimal, NonFungibleLocalId}; -use radix_engine::types::{Encode, ManifestCustomValueKind}; -use radix_engine::types::{Encoder, ManifestEncoder}; -use radix_engine_interface::count; -use transaction::builder::ManifestBuilder; -use transaction::model::InstructionV1; - -use crate::manifest_args; -use crate::references::ReferenceName; +use crate::internal_prelude::*; +use crate::references::{ReferenceName, ResourceReference}; use crate::test_engine::TestEngine; +pub trait ToEncode { + fn to_encode<'a>( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + caller: ComponentAddress, + ) -> ( + ManifestBuilder, + Box>>, + ); +} + pub trait EnvironmentEncode { fn encode( &self, - test_engine: &TestEngine, + test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, encoder: &mut ManifestEncoder, caller: ComponentAddress, @@ -24,23 +28,15 @@ pub enum Environment { Account(N), Component(N), Package(N), - WorkTopFungibleBucket(N, Decimal), - FungibleBucket(N, Decimal), - WorktopNonFungibleBucket(N, Vec), - NonFungibleBucket(N, Vec), - AuthZoneFungibleProof(N, Decimal), - FungibleProof(N, Decimal), - AuthZoneNonFungibleProof(N, Vec), - NonFungibleProof(N, Vec), Resource(N), } -impl Environment { +impl ToEncode for Environment { fn to_encode<'a>( &self, - test_engine: &TestEngine, + test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, - caller: ComponentAddress, + _caller: ComponentAddress, ) -> ( ManifestBuilder, Box>>, @@ -62,41 +58,205 @@ impl Environment { let package = test_engine.get_package(address.clone()); (manifest_builder, Box::new(package)) } - Environment::WorkTopFungibleBucket(resource, amount) => { - let resource_address = test_engine.get_resource(resource.clone()); + } + } +} + +impl EnvironmentEncode for Environment { + fn encode( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + encoder: &mut ManifestEncoder, + caller: ComponentAddress, + ) -> ManifestBuilder { + let (manifest_builder, encoded) = self.to_encode(test_engine, manifest_builder, caller); + encoder.encode(encoded.as_ref()).expect("Could not encode"); + manifest_builder + } +} + +pub enum Fungible + Clone> +where + >::Error: std::fmt::Debug, +{ + Bucket(R, D), + BucketFromWorkTop(R, D), + Proof(R, D), + ProofFromAuthZone(R, D), +} + +impl + Clone> ToEncode for Fungible +where + >::Error: std::fmt::Debug, +{ + fn to_encode<'a>( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + caller: ComponentAddress, + ) -> ( + ManifestBuilder, + Box>>, + ) { + match self { + Fungible::Bucket(resource, amount) => { + let resource_address = resource.address(test_engine); + let amount = amount.clone().try_into().unwrap(); + + let manifest_builder = manifest_builder.call_method( + caller, + "withdraw", + manifest_args!(resource_address, amount), + ); let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced(InstructionV1::TakeFromWorktop { resource_address, - amount: *amount, + amount, }); (manifest_builder, Box::new(bucket.new_bucket.unwrap())) } - Environment::FungibleBucket(resource, amount) => { - let resource_address = test_engine.get_resource(resource.clone()); + Fungible::BucketFromWorkTop(resource, amount) => { + let resource_address = resource.address(test_engine); + let amount = amount.clone().try_into().unwrap(); + + let (manifest_builder, bucket) = + manifest_builder.add_instruction_advanced(InstructionV1::TakeFromWorktop { + resource_address, + amount, + }); + (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + } + Fungible::Proof(resource, amount) => { + let resource_address = resource.address(test_engine); + let amount = amount.clone().try_into().unwrap(); + let manifest_builder = manifest_builder.call_method( caller, - "withdraw", + "create_proof_of_amount", manifest_args!(resource_address, amount), ); + let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( + InstructionV1::CreateProofFromAuthZoneOfAmount { + amount, + resource_address, + }, + ); + (manifest_builder, Box::new(proof.new_proof.unwrap())) + } + Fungible::ProofFromAuthZone(resource, amount) => { + let resource_address = resource.address(test_engine); + let amount = amount.clone().try_into().unwrap(); + + let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( + InstructionV1::CreateProofFromAuthZoneOfAmount { + amount, + resource_address, + }, + ); + (manifest_builder, Box::new(proof.new_proof.unwrap())) + } + } + } +} + +impl + Clone> EnvironmentEncode for Fungible +where + >::Error: std::fmt::Debug, +{ + fn encode( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + encoder: &mut ManifestEncoder, + caller: ComponentAddress, + ) -> ManifestBuilder { + let (manifest_builder, encoded) = self.to_encode(test_engine, manifest_builder, caller); + encoder.encode(encoded.as_ref()).expect("Could not encode"); + manifest_builder + } +} + +pub enum FungibleAll { + FromAccount(R), + FromWorktop(R), +} + +impl ToEncode for FungibleAll { + fn to_encode<'a>( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + caller: ComponentAddress, + ) -> ( + ManifestBuilder, + Box>>, + ) { + match self { + FungibleAll::FromAccount(resource) => { + let amount_owned = test_engine.current_balance(resource.clone()); + let resource_address = resource.address(test_engine); + + let manifest_builder = manifest_builder.call_method( + caller, + "withdraw", + manifest_args!(resource_address, amount_owned), + ); let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced(InstructionV1::TakeFromWorktop { resource_address, - amount: *amount, + amount: amount_owned, }); (manifest_builder, Box::new(bucket.new_bucket.unwrap())) } - Environment::WorktopNonFungibleBucket(resource, ids) => { - let resource_address = test_engine.get_resource(resource.clone()); - let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced( - InstructionV1::TakeNonFungiblesFromWorktop { + FungibleAll::FromWorktop(resource) => { + let resource_address = resource.address(test_engine); + + let (manifest_builder, bucket) = + manifest_builder.add_instruction_advanced(InstructionV1::TakeAllFromWorktop { resource_address, - ids: ids.clone(), - }, - ); + }); (manifest_builder, Box::new(bucket.new_bucket.unwrap())) } - Environment::NonFungibleBucket(resource, ids) => { - let resource_address = test_engine.get_resource(resource.clone()); + } + } +} + +impl EnvironmentEncode for FungibleAll { + fn encode( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + encoder: &mut ManifestEncoder, + caller: ComponentAddress, + ) -> ManifestBuilder { + let (manifest_builder, encoded) = self.to_encode(test_engine, manifest_builder, caller); + encoder.encode(encoded.as_ref()).expect("Could not encode"); + manifest_builder + } +} + +pub enum NonFungible { + Bucket(R, Vec), + BucketFromWorktop(R, Vec), + Proof(R, Vec), + ProofFromAuthZone(R, Vec), +} + +impl ToEncode for NonFungible { + fn to_encode<'a>( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + caller: ComponentAddress, + ) -> ( + ManifestBuilder, + Box>>, + ) { + match self { + NonFungible::Bucket(resource, ids) => { + let resource_address = resource.address(test_engine); + let manifest_builder = manifest_builder.call_method( caller, "withdraw_non_fungibles", @@ -110,34 +270,23 @@ impl Environment { ); (manifest_builder, Box::new(bucket.new_bucket.unwrap())) } - Environment::AuthZoneFungibleProof(resource, amount) => { - let resource_address = test_engine.get_resource(resource.clone()); - - let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( - InstructionV1::CreateProofFromAuthZoneOfAmount { - amount: *amount, + NonFungible::BucketFromWorktop(resource, ids) => { + let resource_address = resource.address(test_engine); + let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced( + InstructionV1::TakeNonFungiblesFromWorktop { resource_address, + ids: ids.clone(), }, ); - (manifest_builder, Box::new(proof.new_proof.unwrap())) + (manifest_builder, Box::new(bucket.new_bucket.unwrap())) } - Environment::FungibleProof(resource, amount) => { - let resource_address = test_engine.get_resource(resource.clone()); + NonFungible::Proof(resource, ids) => { + let resource_address = resource.address(test_engine); let manifest_builder = manifest_builder.call_method( caller, - "create_proof_of_amount", - manifest_args!(resource_address, amount), - ); - let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( - InstructionV1::CreateProofFromAuthZoneOfAmount { - amount: *amount, - resource_address, - }, + "create_proof_of_non_fungibles", + manifest_args!(resource_address, ids.clone()), ); - (manifest_builder, Box::new(proof.new_proof.unwrap())) - } - Environment::AuthZoneNonFungibleProof(resource, ids) => { - let resource_address = test_engine.get_resource(resource.clone()); let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( InstructionV1::CreateProofFromAuthZoneOfNonFungibles { resource_address, @@ -146,13 +295,8 @@ impl Environment { ); (manifest_builder, Box::new(proof.new_proof.unwrap())) } - Environment::NonFungibleProof(resource, ids) => { - let resource_address = test_engine.get_resource(resource.clone()); - let manifest_builder = manifest_builder.call_method( - caller, - "create_proof_of_non_fungibles", - manifest_args!(resource_address, ids.clone()), - ); + NonFungible::ProofFromAuthZone(resource, ids) => { + let resource_address = resource.address(test_engine); let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( InstructionV1::CreateProofFromAuthZoneOfNonFungibles { resource_address, @@ -165,10 +309,10 @@ impl Environment { } } -impl EnvironmentEncode for Environment { +impl EnvironmentEncode for NonFungible { fn encode( &self, - test_engine: &TestEngine, + test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, encoder: &mut ManifestEncoder, caller: ComponentAddress, @@ -179,20 +323,66 @@ impl EnvironmentEncode for Environment { } } -pub struct EnvVec { - elements: Vec>, +pub enum NonFungibleAll { + FromAccount(R), + FromWorktop(R), +} + +impl ToEncode for NonFungibleAll { + fn to_encode<'a>( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + caller: ComponentAddress, + ) -> ( + ManifestBuilder, + Box>>, + ) { + match self { + NonFungibleAll::FromAccount(resource) => { + let ids_owned = test_engine.current_ids_balance(resource.clone()); + let resource_address = resource.address(test_engine); + + let manifest_builder = manifest_builder.call_method( + caller, + "withdraw_non_fungibles", + manifest_args!(resource_address, ids_owned.clone()), + ); + let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced( + InstructionV1::TakeNonFungiblesFromWorktop { + resource_address, + ids: ids_owned, + }, + ); + (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + } + NonFungibleAll::FromWorktop(resource) => { + let resource_address = resource.address(test_engine); + + let (manifest_builder, bucket) = + manifest_builder.add_instruction_advanced(InstructionV1::TakeAllFromWorktop { + resource_address, + }); + (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + } + } + } +} + +pub struct EnvVec { + elements: Vec>, } -impl EnvVec { - pub fn from_vec(elements: Vec>) -> Self { +impl EnvVec { + pub fn from_vec(elements: Vec>) -> Self { Self { elements } } } -impl EnvironmentEncode for EnvVec { +impl EnvironmentEncode for EnvVec { fn encode( &self, - test_engine: &TestEngine, + test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, encoder: &mut ManifestEncoder, caller: ComponentAddress, @@ -232,7 +422,7 @@ impl EnvironmentEncode for EnvVec { impl Encode>> EnvironmentEncode for T { fn encode( &self, - _test_engine: &TestEngine, + _test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, encoder: &mut ManifestEncoder, _caller: ComponentAddress, diff --git a/test-engine/src/from_instruction.rs b/test-engine/src/from_instruction.rs index 4a644b2..8b607de 100644 --- a/test-engine/src/from_instruction.rs +++ b/test-engine/src/from_instruction.rs @@ -1,6 +1,4 @@ -use radix_engine_interface::blueprints::transaction_processor::InstructionOutput; -use radix_engine_interface::data::scrypto::scrypto_decode; -use radix_engine_interface::data::scrypto::ScryptoDecode; +use crate::internal_prelude::*; pub trait FromInstruction { fn from(instructions: Vec) -> Self; diff --git a/test-engine/src/internal_prelude.rs b/test-engine/src/internal_prelude.rs new file mode 100644 index 0000000..6e3d18c --- /dev/null +++ b/test-engine/src/internal_prelude.rs @@ -0,0 +1,8 @@ +pub use radix_common::prelude::*; +pub use radix_engine::transaction::*; +pub use radix_engine_interface::prelude::*; +pub use radix_transactions::manifest::decompiler::ManifestObjectNames; +pub use radix_transactions::manifest::dumper::dump_manifest_to_file_system; +pub use radix_transactions::model::InstructionV1; +pub use radix_transactions::prelude::*; +pub use scrypto_test::prelude::*; diff --git a/test-engine/src/lib.rs b/test-engine/src/lib.rs index ea0df42..059298b 100644 --- a/test-engine/src/lib.rs +++ b/test-engine/src/lib.rs @@ -1,13 +1,14 @@ mod account; mod engine_interface; mod from_instruction; -mod private_macros; mod references; -pub mod call_builder; -pub mod environment; -pub mod macros; +mod call_builder; +mod environment; +mod internal_prelude; +mod macros; mod method_call; pub mod prelude; -pub mod receipt_traits; -pub mod test_engine; +pub(crate) mod receipt_traits; +mod test_engine; +mod to_id; diff --git a/test-engine/src/macros.rs b/test-engine/src/macros.rs index f2910ed..dd0406b 100644 --- a/test-engine/src/macros.rs +++ b/test-engine/src/macros.rs @@ -5,7 +5,8 @@ macro_rules! env_args { ); ($( $x:expr ),*) => {{ - use test_engine::environment::EnvironmentEncode; + use test_engine::prelude::*; + let mut temp_vec: Vec> = vec![]; $( temp_vec.push(Box::new($x)); @@ -21,8 +22,13 @@ macro_rules! env_vec { ); ($( $x:expr ),*) => {{ - use test_engine::environment::EnvVec; - EnvVec::from_vec(vec![$($x,)*]) + use test_engine::prelude::*; + + let mut temp_vec: Vec> = vec![]; + $( + temp_vec.push(Box::new($x)); + )* + EnvVec::from_vec(temp_vec) }}; } @@ -37,3 +43,27 @@ macro_rules! global_package { } }; } + +#[macro_export] +macro_rules! nf_ids { + () => ( + vec![] + ); + + ($( $x:expr ),*) => {{ + use test_engine::prelude::*; + + let mut temp_vec: Vec = vec![]; + $( + temp_vec.push($x.to_id()); + )* + temp_vec + }}; +} + +#[macro_export] +macro_rules! none { + () => { + None:: + }; +} diff --git a/test-engine/src/method_call.rs b/test-engine/src/method_call.rs index 48abb44..c7c7b1b 100644 --- a/test-engine/src/method_call.rs +++ b/test-engine/src/method_call.rs @@ -1,7 +1,7 @@ use crate::call_builder::CallBuilder; use crate::environment::EnvironmentEncode; +use crate::internal_prelude::*; use crate::references::{GlobalReference, ResourceReference}; -use radix_engine::transaction::TransactionReceipt; pub trait SimpleMethodCaller { /// Makes a simple call to a method of the current component. diff --git a/test-engine/src/prelude.rs b/test-engine/src/prelude.rs index 9c8f5ff..9f48215 100644 --- a/test-engine/src/prelude.rs +++ b/test-engine/src/prelude.rs @@ -1,5 +1,14 @@ -pub use crate::method_call::ComplexMethodCaller; -pub use crate::method_call::SimpleMethodCaller; +// Macros needed pub use lazy_static::lazy_static; -pub use radix_engine_interface::blueprints::package::PackageDefinition; -pub use scrypto_unit::PackagePublishingSource; + +// Radix types +pub use crate::internal_prelude::*; + +// This crate's types +pub use crate::call_builder::*; +pub use crate::environment::*; +pub use crate::method_call::*; +pub use crate::receipt_traits::*; +pub use crate::test_engine::*; +pub use crate::to_id::ToId; +pub use crate::{env_args, env_vec, global_package, nf_ids, none}; diff --git a/test-engine/src/private_macros.rs b/test-engine/src/private_macros.rs deleted file mode 100644 index c193422..0000000 --- a/test-engine/src/private_macros.rs +++ /dev/null @@ -1,21 +0,0 @@ -#[macro_export] -macro_rules! manifest_args { - ($($args: expr),*) => {{ - use radix_engine_interface::count; - use radix_engine::types::{ MANIFEST_SBOR_V1_MAX_DEPTH, MANIFEST_SBOR_V1_PAYLOAD_PREFIX, - ManifestArgs, ManifestEncoder, manifest_decode, ManifestValueKind}; - - let mut buf = Vec::new(); - let mut encoder = ManifestEncoder::new(&mut buf, MANIFEST_SBOR_V1_MAX_DEPTH); - encoder.write_payload_prefix(MANIFEST_SBOR_V1_PAYLOAD_PREFIX).unwrap(); - encoder.write_value_kind(ManifestValueKind::Tuple).unwrap(); - // Hack: stringify to skip ownership move semantics - encoder.write_size(count!($(stringify!($args)),*)).unwrap(); - $( - let arg = $args; - encoder.encode(&arg).unwrap(); - )* - let value = manifest_decode(&buf).unwrap(); - ManifestArgs::new_from_tuple_or_panic(value) - }}; -} diff --git a/test-engine/src/receipt_traits.rs b/test-engine/src/receipt_traits.rs index c98bd0a..c8e3458 100644 --- a/test-engine/src/receipt_traits.rs +++ b/test-engine/src/receipt_traits.rs @@ -1,6 +1,5 @@ -use radix_engine::transaction::{TransactionOutcome, TransactionReceipt, TransactionResult}; - use crate::from_instruction::FromInstruction; +use crate::internal_prelude::*; pub trait Outcome { fn assert_is_success(self) -> Self; diff --git a/test-engine/src/references.rs b/test-engine/src/references.rs index cbc7f30..ff763c8 100644 --- a/test-engine/src/references.rs +++ b/test-engine/src/references.rs @@ -1,6 +1,5 @@ +use crate::internal_prelude::*; use crate::test_engine::TestEngine; -use radix_engine_common::prelude::ResourceAddress; -use radix_engine_common::types::{ComponentAddress, GlobalAddress}; /// pub trait ReferenceName { diff --git a/test-engine/src/test_engine.rs b/test-engine/src/test_engine.rs index 6a33c91..70b8e68 100644 --- a/test-engine/src/test_engine.rs +++ b/test-engine/src/test_engine.rs @@ -1,25 +1,15 @@ use std::collections::hash_map::Entry; use std::path::Path; -use radix_engine::transaction::{CommitResult, TransactionReceipt, TransactionResult}; -use radix_engine::types::{ - dec, ComponentAddress, Decimal, GlobalAddress, HashMap, NonFungibleLocalId, PackageAddress, - ResourceAddress, FAUCET, XRD, -}; -use radix_engine_common::prelude::{Own, ScryptoDecode, ScryptoEncode}; -use radix_engine_interface::blueprints::package::PackageDefinition; -use radix_engine_interface::prelude::{MetadataValue, NonFungibleGlobalId}; -use radix_engine_interface::types::NonFungibleData; -use transaction::model::TransactionManifestV1; -use transaction::prelude::NetworkDefinition; - use crate::account::Account; use crate::call_builder::CallBuilder; use crate::engine_interface::EngineInterface; use crate::environment::EnvironmentEncode; +use crate::internal_prelude::*; use crate::method_call::{ComplexMethodCaller, SimpleMethodCaller}; use crate::receipt_traits::Outcome; use crate::references::{ComponentReference, GlobalReference, ReferenceName, ResourceReference}; +use crate::to_id::ToId; pub struct TestEngine { engine_interface: EngineInterface, @@ -204,7 +194,11 @@ impl TestEngine { /// * `recipient`: resources to transfer to. /// * `resource`: reference name of the resource to transfer. /// * `amount`: amount of resources to transfer. - pub fn transfer>( + pub fn transfer< + E: ReferenceName, + R: ReferenceName + Clone + 'static, + D: TryInto + Clone + 'static, + >( &mut self, recipient: E, resource: R, @@ -224,11 +218,11 @@ impl TestEngine { /// * `recipient`: resources to transfer to. /// * `resource`: reference name of the resource to transfer. /// * `ids`: ids to transfer. - pub fn transfer_non_fungibles( + pub fn transfer_non_fungibles( &mut self, recipient: E, resource: R, - ids: Vec, + ids: Vec, ) -> TransactionReceipt { CallBuilder::new(self) .transfer_non_fungibles(recipient, resource, ids) @@ -405,13 +399,13 @@ impl TestEngine { /// # Arguments /// * `resource`: reference name or address of the resource of the NFT. /// * `id`: local id of the NFT. - pub fn get_non_fungible_data( + pub fn get_non_fungible_data( &mut self, resource: R, - id: NonFungibleLocalId, - ) -> T { + id: T, + ) -> D { self.engine_interface - .get_non_fungible_data(resource.address(self), id) + .get_non_fungible_data(resource.address(self), id.to_id()) } /// Updates a field of an NFT's non-fungible data. @@ -422,17 +416,17 @@ impl TestEngine { /// * `field_name`: name of the field to update. /// * `data`: new data for this field. /// * `badge`: reference name or address of the badge needed to make the update. - pub fn update_non_fungible_data( + pub fn update_non_fungible_data( &mut self, resource: R1, - id: NonFungibleLocalId, + id: T, field_name: &str, mut data: Vec>, badge: R2, ) -> TransactionReceipt { let resource = resource.address(self); let mut args: Vec> = - vec![Box::new(id), Box::new(field_name.to_string())]; + vec![Box::new(id.to_id()), Box::new(field_name.to_string())]; args.append(&mut data); CallBuilder::new(self) .call_from_component(resource, "update_non_fungible_data", args) diff --git a/test-engine/src/to_id.rs b/test-engine/src/to_id.rs new file mode 100644 index 0000000..b4a6de2 --- /dev/null +++ b/test-engine/src/to_id.rs @@ -0,0 +1,184 @@ +use crate::internal_prelude::*; + +pub trait ToId { + fn to_id(self) -> NonFungibleLocalId; +} + +impl ToId for NonFungibleLocalId { + fn to_id(self) -> NonFungibleLocalId { + self + } +} + +impl ToId for u64 { + fn to_id(self) -> NonFungibleLocalId { + NonFungibleLocalId::integer(self) + } +} + +impl ToId for Vec { + fn to_id(self) -> NonFungibleLocalId { + NonFungibleLocalId::bytes(self).unwrap() + } +} + +impl ToId for [u8; 32] { + fn to_id(self) -> NonFungibleLocalId { + NonFungibleLocalId::ruid(self) + } +} + +impl ToId for String { + fn to_id(self) -> NonFungibleLocalId { + // Transform the String into a vec of chars + let mut chars: Vec = self.chars().collect(); + + // Check if it starts by '<', '#', '{' or '[' + if let Some(first) = chars.first() { + match first { + '<' => { + chars.remove(0); + let last_char = chars.pop().unwrap(); + if last_char == '>' && !chars.is_empty() { + // Then it is an integer nf id and we skip at the end + } else { + chars.push(last_char); + } + } + '#' => { + chars.remove(0); + let last_char = chars.pop().unwrap(); + if last_char == '#' && !chars.is_empty() { + // Then it is an integer nf id + + let char_str: String = chars.into_iter().collect(); + let id: u64 = char_str.parse().unwrap(); + return id.to_id(); + } else { + chars.push(last_char); + } + } + '[' => { + chars.remove(0); + let last_char = chars.pop().unwrap(); + if last_char == ']' && !chars.is_empty() { + // Then it is a bytes nf id + + let hex_string: String = chars.into_iter().collect(); + let hex = hex_string.as_str(); + let bytes: Vec = (0..hex.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap()) + .collect(); + return bytes.to_id(); + } else { + chars.push(last_char); + } + } + '{' => { + chars.remove(0); + let last_char = chars.pop().unwrap(); + if last_char == '}' && !chars.is_empty() { + // Then it is a ruid nf id + + let hex_string: String = + chars.into_iter().collect::().replace('-', ""); + let hex_cleaned = hex_string.as_str(); + let mut bytes = [0u8; 32]; + for i in 0..32 { + bytes[i] = + u8::from_str_radix(&hex_cleaned[i * 2..i * 2 + 2], 16).unwrap(); + } + + return bytes.to_id(); + } else { + chars.push(last_char); + } + } + _ => { // Else do nothing } + } + } + } + // In other cases we consider that it is a String non-fungible id + let char_str: String = chars.into_iter().collect(); + NonFungibleLocalId::string(char_str).unwrap() + } +} + +macro_rules! integer_types_impl { + ($type_name: ident) => { + impl ToId for $type_name { + fn to_id(self) -> NonFungibleLocalId { + NonFungibleLocalId::integer(u64::try_from(self).unwrap()) + } + } + }; +} + +impl ToId for &str { + fn to_id(self) -> NonFungibleLocalId { + String::from(self).to_id() + } +} + +integer_types_impl!(u8); +integer_types_impl!(u16); +integer_types_impl!(u32); +integer_types_impl!(u128); +integer_types_impl!(i8); +integer_types_impl!(i16); +integer_types_impl!(i32); +integer_types_impl!(i64); +integer_types_impl!(i128); + +macro_rules! subtypes_impl { + ($type_name: ident, $subtype_name: ident) => { + impl ToId for $type_name { + fn to_id(self) -> NonFungibleLocalId { + NonFungibleLocalId::$subtype_name(self) + } + } + }; +} + +subtypes_impl!(BytesNonFungibleLocalId, Bytes); +subtypes_impl!(IntegerNonFungibleLocalId, Integer); +subtypes_impl!(RUIDNonFungibleLocalId, RUID); +subtypes_impl!(StringNonFungibleLocalId, String); + +#[cfg(test)] +mod test_to_ids { + use crate::prelude::*; + + macro_rules! integer_test { + ($type_name: ident) => { + let test = 12 as $type_name; + assert_eq!(test.to_id(), NonFungibleLocalId::integer(12 as u64)) + }; + } + + #[test] + fn test_nf_ids_int() { + integer_test!(u8); + integer_test!(u16); + integer_test!(u32); + integer_test!(u64); + integer_test!(u128); + integer_test!(i8); + integer_test!(i16); + integer_test!(i32); + integer_test!(i64); + integer_test!(i128); + } + + #[test] + fn test_nf_ids_from_string() { + let str_1 = "#1#"; + let str_2 = ""; + let str_3 = "blabla"; + + assert_eq!(str_1.to_id(), NonFungibleLocalId::integer(1u64)); + assert_eq!(str_2.to_id(), NonFungibleLocalId::string("SomeId").unwrap()); + assert_eq!(str_3.to_id(), NonFungibleLocalId::string("blabla").unwrap()) + } +} diff --git a/test-engine/tests/general/mod.rs b/test-engine/tests/general/mod.rs index a1871b1..74f7c15 100644 --- a/test-engine/tests/general/mod.rs +++ b/test-engine/tests/general/mod.rs @@ -1,8 +1,4 @@ -use radix_engine::types::dec; -use radix_engine_common::network::NetworkDefinition; -use radix_engine_common::prelude::ResourceAddress; -use test_engine::receipt_traits::Outcome; -use test_engine::test_engine::TestEngine; +use test_engine::prelude::*; #[test] fn test_pre_allocated_token() { diff --git a/test-engine/tests/gumball_machine/package/Cargo.toml b/test-engine/tests/gumball_machine/package/Cargo.toml index 123ce28..3be0091 100644 --- a/test-engine/tests/gumball_machine/package/Cargo.toml +++ b/test-engine/tests/gumball_machine/package/Cargo.toml @@ -4,13 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -sbor = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } - -[dev-dependencies] -transaction = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto-unit = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } +sbor = "1.2.0" +scrypto = "1.2.0" [profile.release] opt-level = 'z' # Optimize for size. diff --git a/test-engine/tests/gumball_machine/unit_tests.rs b/test-engine/tests/gumball_machine/unit_tests.rs index 927bbe2..851ae59 100644 --- a/test-engine/tests/gumball_machine/unit_tests.rs +++ b/test-engine/tests/gumball_machine/unit_tests.rs @@ -1,9 +1,5 @@ mod gumball_machine_tests { - use radix_engine::types::{dec, Decimal}; - use test_engine::environment::Environment; - use test_engine::receipt_traits::{GetReturn, Outcome}; - use test_engine::test_engine::TestEngine; - use test_engine::{env_args, global_package}; + use test_engine::prelude::*; global_package!(GUMBALL_PACKAGE, "tests/gumball_machine/package"); @@ -21,10 +17,8 @@ mod gumball_machine_tests { #[test] fn test_buy_gumball_success() { let mut test_engine = instantiate_gumball(); - let receipt = test_engine.call_method( - "buy_gumball", - env_args!(Environment::FungibleBucket("XRD", dec!(10))), - ); + let receipt = + test_engine.call_method("buy_gumball", env_args!(Fungible::Bucket("XRD", 10))); receipt.assert_is_success(); let amount_owned = test_engine.current_balance("GUM"); assert_eq!(amount_owned, Decimal::one()) @@ -34,10 +28,7 @@ mod gumball_machine_tests { fn test_buy_gumball_fail() { let mut test_engine = instantiate_gumball(); test_engine - .call_method( - "buy_gumball", - env_args!(Environment::FungibleBucket("XRD", Decimal::one())), - ) + .call_method("buy_gumball", env_args!(Fungible::Bucket("XRD", 1))) .assert_failed_with(""); let amount_owned = test_engine.current_balance("GUM"); assert_eq!(amount_owned, Decimal::zero()) diff --git a/test-engine/tests/hello_world/package/Cargo.toml b/test-engine/tests/hello_world/package/Cargo.toml index de74a06..359e377 100644 --- a/test-engine/tests/hello_world/package/Cargo.toml +++ b/test-engine/tests/hello_world/package/Cargo.toml @@ -4,13 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -sbor = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } - -[dev-dependencies] -transaction = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto-unit = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } +sbor = "1.2.0" +scrypto = "1.2.0" [profile.release] opt-level = 'z' # Optimize for size. diff --git a/test-engine/tests/hello_world/unit_tests.rs b/test-engine/tests/hello_world/unit_tests.rs index c1ce413..31a7f34 100644 --- a/test-engine/tests/hello_world/unit_tests.rs +++ b/test-engine/tests/hello_world/unit_tests.rs @@ -1,20 +1,12 @@ mod hello_word_tests { - use radix_engine::types::Decimal; - use test_engine::env_args; - use test_engine::prelude::SimpleMethodCaller; - use test_engine::receipt_traits::Outcome; - use test_engine::test_engine::TestEngine; + use test_engine::prelude::*; #[test] fn test_free_token() { let mut test_engine = TestEngine::new(); - println!("1"); test_engine.new_package("hello world", "tests/hello_world/package"); - println!("2"); test_engine.new_component("hello_comp", "Hello", "instantiate_hello", env_args!()); - println!("3"); let receipt = test_engine.call_method("free_token", env_args!()); - println!("4"); receipt.assert_is_success(); let amount_owned = test_engine.current_balance("Hello Token"); assert_eq!(amount_owned, Decimal::one()) diff --git a/test-engine/tests/nft_marketplace/package/Cargo.toml b/test-engine/tests/nft_marketplace/package/Cargo.toml index e0b06d6..8fe127e 100644 --- a/test-engine/tests/nft_marketplace/package/Cargo.toml +++ b/test-engine/tests/nft_marketplace/package/Cargo.toml @@ -4,13 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -sbor = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } - -[dev-dependencies] -transaction = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto-unit = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } +sbor = "1.2.0" +scrypto = "1.2.0" [profile.release] opt-level = 'z' # Optimize for size. diff --git a/test-engine/tests/nft_marketplace/unit_tests.rs b/test-engine/tests/nft_marketplace/unit_tests.rs index 33e5586..16a8e7e 100644 --- a/test-engine/tests/nft_marketplace/unit_tests.rs +++ b/test-engine/tests/nft_marketplace/unit_tests.rs @@ -1,10 +1,5 @@ mod nft_marketplace_tests { - use radix_engine_interface::dec; - - use test_engine::environment::Environment; - use test_engine::receipt_traits::Outcome; - use test_engine::test_engine::TestEngine; - use test_engine::{env_args, env_vec, global_package}; + use test_engine::prelude::*; global_package!(NFT_MARKETPLACE_PACKAGE, "tests/nft_marketplace/package"); @@ -33,10 +28,7 @@ mod nft_marketplace_tests { "DutchAuction", "instantiate_dutch_auction", env_args![ - env_vec![Environment::NonFungibleBucket( - "cars nft", - vec![car_id.unwrap()] - )], + env_vec![NonFungible::Bucket("cars nft", vec![car_id.unwrap()])], Environment::Resource("xrd"), dec!(10), dec!(5), @@ -65,10 +57,7 @@ mod nft_marketplace_tests { new_buyer(&mut test_engine, "buyer"); let amount_owned_before = test_engine.current_balance("xrd"); test_engine - .call_method( - "buy", - env_args![Environment::FungibleBucket("xrd", dec!(10))], - ) + .call_method("buy", env_args![Fungible::Bucket("xrd", 10)]) .assert_is_success(); let amount_owned_after = test_engine.current_balance("radix"); assert_eq!(amount_owned_before - amount_owned_after, dec!(10)); @@ -82,10 +71,7 @@ mod nft_marketplace_tests { test_engine.jump_epochs(5); let amount_owned_before = test_engine.current_balance("xrd"); test_engine - .call_method_builder( - "buy", - env_args![Environment::FungibleBucket("xrd", dec!(10))], - ) + .call_method_builder("buy", env_args![Fungible::Bucket("xrd", 10)]) .output("tests/nft_marketplace/package/manifests/", "buy") .execute(); let amount_owned_after = test_engine.current_balance("radix"); @@ -99,7 +85,7 @@ mod nft_marketplace_tests { new_buyer(&mut test_engine, "buyer"); test_engine.jump_epochs(3); test_engine.call_method("buy", env_args![ - Environment::FungibleBucket("xrd", dec!(5)) + Fungible::Bucket("xrd", 5) ]).assert_failed_with("[Buy]: Invalid quantity was provided. This sale can only go through when 8.5 tokens are provided."); } diff --git a/test-engine/tests/radiswap/package/Cargo.toml b/test-engine/tests/radiswap/package/Cargo.toml index 9c1e1d4..76604f7 100644 --- a/test-engine/tests/radiswap/package/Cargo.toml +++ b/test-engine/tests/radiswap/package/Cargo.toml @@ -4,15 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -sbor = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } - -[dev-dependencies] -radiswap = { path = ".", features = ["test"] } -transaction = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto-unit = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } -scrypto-test = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "v1.1.1" } +sbor = "1.2.0" +scrypto = "1.2.0" [features] default = [] diff --git a/test-engine/tests/radiswap/unit_tests.rs b/test-engine/tests/radiswap/unit_tests.rs index 81dfc4b..04c586d 100644 --- a/test-engine/tests/radiswap/unit_tests.rs +++ b/test-engine/tests/radiswap/unit_tests.rs @@ -1,9 +1,5 @@ mod radiswap_tests { - use radix_engine::types::dec; - use radix_engine_interface::blueprints::resource::OwnerRole; - use test_engine::environment::Environment; - use test_engine::test_engine::TestEngine; - use test_engine::{env_args, global_package}; + use test_engine::prelude::*; global_package!(RADISWAP_PACKAGE, "tests/radiswap/package"); @@ -30,8 +26,8 @@ mod radiswap_tests { test_engine.call_method( "add_liquidity", env_args!( - Environment::FungibleBucket("usd", dec!(1000)), - Environment::FungibleBucket("btc", dec!(1)) + Fungible::Bucket("usd", dec!(1000)), + Fungible::Bucket("btc", dec!(1)) ), ); let usd_amount = test_engine.current_balance("usd"); @@ -46,14 +42,11 @@ mod radiswap_tests { test_engine.call_method( "add_liquidity", env_args!( - Environment::FungibleBucket("usd", dec!(1000)), - Environment::FungibleBucket("btc", dec!(1)) + Fungible::Bucket("usd", dec!(1000)), + Fungible::Bucket("btc", dec!(1)) ), ); - test_engine.call_method( - "swap", - env_args!(Environment::FungibleBucket("usd", dec!(1000))), - ); + test_engine.call_method("swap", env_args!(Fungible::Bucket("usd", dec!(1000)))); let usd_amount = test_engine.current_balance("usd"); let btc_amount = test_engine.current_balance("btc"); assert_eq!(usd_amount, dec!(98000)); diff --git a/test-engine/tutorials/2.Packages_and_Blueprints.md b/test-engine/tutorials/2.Packages_and_Blueprints.md index a298bc8..9657540 100644 --- a/test-engine/tutorials/2.Packages_and_Blueprints.md +++ b/test-engine/tutorials/2.Packages_and_Blueprints.md @@ -73,37 +73,63 @@ test_engine.set_current_component(component_ref); In the previous examples, we used the `env_args!` macro. This enables us to easily deal with arguments using `ReferenceName`. In the `env_args!` macro, every usual Scrypto types such as `ComponentAddress` or `ResourceAddress` can -be used. Additionally, any variant of the `Environment` enum can be used: +be used. +There are 5 different enums that can be used to create arguments. The first one deals with references used in the +environment. ```Rust pub enum Environment { Account(N), Component(N), Package(N), - WorkTopFungibleBucket(N, Decimal), - FungibleBucket(N, Decimal), - WorktopNonFungibleBucket(N, Vec), - NonFungibleBucket(N, Vec), - AuthZoneFungibleProof(N, Decimal), - FungibleProof(N, Decimal), - AuthZoneNonFungibleProof(N, Vec), - NonFungibleProof(N, Vec), Resource(N), } ``` -where `N` is a `ReferenceName` of the given entity. This enum combined with the `env_args!` macro enables us to only -care -about the arguments of our tests without having to create the Buckets/Proofs manually. For example, if a component takes -a xrd bucket as its single argument to instantiate, we can write: +where `N` is a `ReferenceName` of the given entity. + +To create buckets and proofs, one can use the 4 following enums based on what they want to do: + +```Rust +pub enum Fungible + Clone> + where + >::Error: std::fmt::Debug, +{ + Bucket(R, D), + BucketFromWorkTop(R, D), + Proof(R, D), + ProofFromAuthZone(R, D), +} + +pub enum FungibleAll { + FromAccount(R), + FromWorktop(R), +} + +pub enum NonFungible { + Bucket(R, Vec), + BucketFromWorktop(R, Vec), + Proof(R, Vec), + ProofFromAuthZone(R, Vec), +} + +pub enum NonFungibleAll { + FromAccount(R), + FromWorktop(R), +} +``` + +where `D` is any type that can be casted to a Decimal. +These enum combined with the `env_args!` macro enables us to only +care about the arguments of our tests without having to create the Buckets/Proofs manually. For example, if a component +takes a xrd bucket as its single argument to instantiate, we can write: ```Rust test_engine.new_component( "my component", "MyComponent", "instantiate_with_bucket", -env_args!(Environment::FungibleBucket("xrd", dec!5)) -) +env_args!(Fungible::Bucket("xrd", 5)) ``` A more complex [example](tests/nft_marketplace/unit_tests.rs) @@ -115,7 +141,7 @@ test_engine.new_component( "DutchAuction", "instantiate_dutch_auction", env_args![ - env_vec![Environment::NonFungibleBucket( + env_vec![NonFungible::Bucket( "cars nft", vec![car_id.unwrap()] )], @@ -138,4 +164,31 @@ pub struct SomeType { some_fields: FieldsType } +``` + +## Other quality of life features + +### Non Fungible Ids + +When dealing with non-fungible arguments, constructing `NonFungibleLocalId` can be quite annoying. +Instead of constructing them manually, one can use the underlying non-fungible type as argument or the SBOR string +representation. For example, when using the `update_non_fungible_data()` method the following calls are equivalent: + +```Rust +// For integer non fungible ids +test_engine.update_non_fungible_data("MyNFT", NonFungibleLocalId::integer(1), "field", env_args!(), "admin badge"); +test_engine.update_non_fungible_data("MyNFT", 1, "field", env_args!(), "admin badge"); +test_engine.update_non_fungible_data("MyNFT", "#1#", "field", env_args!(), "admin badge"); + +// For string non fungible ids +test_engine.update_non_fungible_data("MyNFT", NonFungibleLocalId::string(""), "field", env_args!(), "admin badge"); +test_engine.update_non_fungible_data("MyNFT", "SomeId", "field", env_args!(), "admin badge"); +test_engine.update_non_fungible_data("MyNFT", "", "field", env_args!(), "admin badge"); +``` + +Additionally, for non fungible buckets and proofs where a `Vec` the macro `nf_ids!()` can be used as +follows: + +```Rust + let ids = nf_ids![1, 2, 3, 4, 5, 6]; ``` \ No newline at end of file diff --git a/test-engine/tutorials/3.Method_Calls.md b/test-engine/tutorials/3.Methods_Calls.md similarity index 91% rename from test-engine/tutorials/3.Method_Calls.md rename to test-engine/tutorials/3.Methods_Calls.md index bbad825..3a27d4d 100644 --- a/test-engine/tutorials/3.Method_Calls.md +++ b/test-engine/tutorials/3.Methods_Calls.md @@ -5,7 +5,7 @@ Now that we have instantiated a component, we can make calls on it by using the ```Rust test_engine.call_method( "buy_gumball", // Name of the method to call -env_args!(Environment::FungibleBucket("XRD", dec!(10))), // Arguments +env_args!(Fungible::Bucket("XRD", dec!(10))), // Arguments ); ``` @@ -50,7 +50,7 @@ can change this by making calls with the `custom_method_call` method: ```Rust test_engine.call_methode_builder( "buy_gumball", -env_args!(Environment::FungibleBucket("XRD", dec!(10)))) +env_args!(Fungible::Bucket("XRD", dec!(10)))) .lock_fee("default", 20) // The second argument is of any type that can be casted to a Decimal .deposit_batch("User 2") .execute() @@ -61,7 +61,7 @@ env_args!(Environment::FungibleBucket("XRD", dec!(10)))) ```Rust test_engine.call_methode_builder( "buy_gumball", -env_args!(Environment::FungibleBucket("XRD", dec!(10)))) +env_args!(Fungible::Bucket("XRD", dec!(10)))) .deposit_batch("d Ef A ult") .output(output_path, file_name) .execute() @@ -83,7 +83,7 @@ This library implements other ways to interact with the receipt. First, we can c ```Rust test_engine.call_method( "buy_gumball", -env_args!(Environment::FungibleBucket("XRD", dec!(10))), +env_args!(Fungible::Bucket("XRD", dec!(10))), ).assert_is_success(); ``` @@ -91,7 +91,7 @@ We can also check that a `panic!` has successfully been triggered with the corre ```Rust test_engine.call_method("buy", env_args![ - Environment::FungibleBucket("xrd", dec!(5)) + Fungible::Bucket("xrd", dec!(5)) ]).assert_failed_with("[Buy]: Invalid quantity was provided. This sale can only go through when 8.5 tokens are provided."); ```