diff --git a/applications/tari_indexer/src/storage_sqlite/models/utxo.rs b/applications/tari_indexer/src/storage_sqlite/models/utxo.rs index 5e5cb1c3a8..10e9ccecf3 100644 --- a/applications/tari_indexer/src/storage_sqlite/models/utxo.rs +++ b/applications/tari_indexer/src/storage_sqlite/models/utxo.rs @@ -3,11 +3,14 @@ use std::str::FromStr; -use tari_engine_types::{Utxo, UtxoAddress, UtxoId, UtxoOutput}; +use tari_engine_types::{Utxo, UtxoOutput}; use tari_ootle_common_types::StateVersion; use tari_ootle_storage::{time::PrimitiveDateTime, StorageError}; use tari_ootle_wallet_sdk::models::{UtxoBurnt, UtxoSpent, UtxoUnspent, WalletUtxoUpdate}; -use tari_template_lib::prelude::{PedersenCommitmentBytes, ResourceAddress}; +use tari_template_lib::{ + models::{UtxoAddress, UtxoId}, + prelude::{PedersenCommitmentBytes, ResourceAddress}, +}; use crate::storage_sqlite::{schema::utxos, serialization::deserialize_bincode}; diff --git a/applications/tari_indexer/src/storage_sqlite/models/utxo_update.rs b/applications/tari_indexer/src/storage_sqlite/models/utxo_update.rs index 022481b93e..c0ee7294d4 100644 --- a/applications/tari_indexer/src/storage_sqlite/models/utxo_update.rs +++ b/applications/tari_indexer/src/storage_sqlite/models/utxo_update.rs @@ -2,8 +2,9 @@ // SPDX-License-Identifier: BSD-3-Clause use tari_bor::{Deserialize, Serialize}; -use tari_engine_types::{UtxoAddress, UtxoOutput}; +use tari_engine_types::UtxoOutput; use tari_ootle_common_types::{shard::Shard, StateVersion}; +use tari_template_lib::models::UtxoAddress; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum UtxoUpdateRecord { diff --git a/applications/tari_indexer/src/storage_sqlite/reader.rs b/applications/tari_indexer/src/storage_sqlite/reader.rs index 3269ca2bfd..916a0471f8 100644 --- a/applications/tari_indexer/src/storage_sqlite/reader.rs +++ b/applications/tari_indexer/src/storage_sqlite/reader.rs @@ -20,7 +20,6 @@ use tari_consensus_types::BlockId; use tari_engine_types::{ substate::{SubstateId, SubstateValue}, Utxo, - UtxoId, }; use tari_indexer_client::types::{ListSubstateItem, NonFungibleSubstate, TransactionEntry}; use tari_ootle_common_types::{shard::Shard, substate_type::SubstateType, Epoch, ShardGroup, StateVersion}; @@ -28,7 +27,7 @@ use tari_ootle_storage::{time::PrimitiveDateTime, StorageError}; use tari_ootle_storage_sqlite::SqliteTransaction; use tari_ootle_wallet_sdk::models::WalletUtxoUpdate; use tari_template_lib::{ - models::ResourceAddress, + models::{ResourceAddress, UtxoId}, prelude::{RistrettoPublicKeyBytes, TemplateAddress}, types::crypto::UtxoTag, }; diff --git a/applications/tari_indexer/src/storage_sqlite/store_factory.rs b/applications/tari_indexer/src/storage_sqlite/store_factory.rs index 614917d086..d2b478deba 100644 --- a/applications/tari_indexer/src/storage_sqlite/store_factory.rs +++ b/applications/tari_indexer/src/storage_sqlite/store_factory.rs @@ -13,7 +13,7 @@ use diesel::{sql_query, Connection, RunQueryDsl, SqliteConnection}; use diesel_migrations::{EmbeddedMigrations, MigrationHarness}; use serde::{de::DeserializeOwned, Serialize}; use tari_consensus_types::BlockId; -use tari_engine_types::{events::Event, substate::SubstateId, Utxo, UtxoId}; +use tari_engine_types::{events::Event, substate::SubstateId, Utxo}; use tari_indexer_client::types::{ListSubstateItem, NonFungibleSubstate, TransactionEntry}; use tari_ootle_common_types::{shard::Shard, substate_type::SubstateType, Epoch, ShardGroup, StateVersion}; use tari_ootle_storage::{ @@ -23,7 +23,7 @@ use tari_ootle_storage::{ use tari_ootle_storage_sqlite::{error::SqliteStorageError, SqliteTransaction}; use tari_ootle_wallet_sdk::models::WalletUtxoUpdate; use tari_template_lib::{ - models::ResourceAddress, + models::{ResourceAddress, UtxoId}, types::{ crypto::{RistrettoPublicKeyBytes, UtxoTag}, TemplateAddress, diff --git a/applications/tari_indexer/src/substate_manager.rs b/applications/tari_indexer/src/substate_manager.rs index c0a1cb7203..ee97b765f8 100644 --- a/applications/tari_indexer/src/substate_manager.rs +++ b/applications/tari_indexer/src/substate_manager.rs @@ -27,7 +27,6 @@ use tari_common_types::types::FixedHash; use tari_engine_types::{ substate::{Substate, SubstateId, SubstateValue}, Utxo, - UtxoId, }; use tari_epoch_manager::service::EpochManagerHandle; use tari_indexer_client::types::{ListSubstateItem, NonFungibleSubstate}; @@ -41,7 +40,7 @@ use tari_ootle_common_types::{ }; use tari_ootle_wallet_sdk::models::WalletUtxoUpdate; use tari_template_lib::{ - models::ResourceAddress, + models::{ResourceAddress, UtxoId}, types::{ crypto::{RistrettoPublicKeyBytes, UtxoTag}, TemplateAddress, diff --git a/clients/javascript/wallet_daemon_client/package.json b/clients/javascript/wallet_daemon_client/package.json index ec0cefe30e..86641a5a7e 100644 --- a/clients/javascript/wallet_daemon_client/package.json +++ b/clients/javascript/wallet_daemon_client/package.json @@ -1,6 +1,6 @@ { "name": "@tari-project/wallet_jrpc_client", - "version": "1.7.2", + "version": "1.8.0", "description": "Tari wallet JSON-RPC client library", "homepage": "https://github.com/tari-project/tari-ootle#readme", "bugs": { diff --git a/clients/tari_indexer_client/src/types.rs b/clients/tari_indexer_client/src/types.rs index d80a5bbb12..2a6b145877 100644 --- a/clients/tari_indexer_client/src/types.rs +++ b/clients/tari_indexer_client/src/types.rs @@ -12,9 +12,8 @@ use tari_consensus_types::Decision; use tari_engine_types::{ commit_result::ExecuteResult, substate::{Substate, SubstateId, SubstateValue}, - template_lib_models::{NonFungibleAddress, ResourceAddress}, + template_lib_models::{NonFungibleAddress, ResourceAddress, UtxoId}, Utxo, - UtxoId, }; use tari_ootle_common_types::{shard::Shard, substate_type::SubstateType, Epoch, StateVersion}; use tari_ootle_storage::time::PrimitiveDateTime; diff --git a/clients/wallet_daemon_client/src/types.rs b/clients/wallet_daemon_client/src/types.rs index 0cf3bdae68..b8560322b3 100644 --- a/clients/wallet_daemon_client/src/types.rs +++ b/clients/wallet_daemon_client/src/types.rs @@ -28,7 +28,6 @@ use tari_engine_types::{ instruction::Instruction, serde_with, substate::{Substate, SubstateId}, - UtxoAddress, ValidatorFeePoolAddress, }; use tari_ootle_address::OotleAddress; @@ -53,7 +52,7 @@ use tari_ootle_wallet_sdk::{ }; use tari_template_abi::{FunctionDef, TemplateDef}; use tari_template_lib::{ - models::{ConfidentialOutputStatement, NonFungibleId, ResourceAddress, VaultId}, + models::{ConfidentialOutputStatement, NonFungibleId, ResourceAddress, UtxoAddress, VaultId}, prelude::{ComponentAddress, ConfidentialWithdrawProof, ResourceType, RistrettoPublicKeyBytes}, types::{ crypto::{CommitmentSignatureBytes, PedersenCommitmentBytes, RangeProofBytes}, diff --git a/crates/engine/src/runtime/error.rs b/crates/engine/src/runtime/error.rs index efb29dfccc..b34b6a6251 100644 --- a/crates/engine/src/runtime/error.rs +++ b/crates/engine/src/runtime/error.rs @@ -86,11 +86,11 @@ pub enum RuntimeError { // To reduce the size of this variant, we box one of the fields requested_owner: Box, }, - #[error("Expected lock {lock_id} to lock {expected_type} but it locks {address}")] + #[error("Expected lock {lock_id} to lock {expected_type} but it locks {id}")] LockSubstateMismatch { lock_id: LockId, expected_type: &'static str, - address: SubstateId, + id: SubstateId, }, #[error("Component {component} referenced an unknown substate {id}")] ComponentReferencedUnknownSubstate { diff --git a/crates/engine/src/runtime/impl.rs b/crates/engine/src/runtime/impl.rs index 3690833c6c..00b87e6afa 100644 --- a/crates/engine/src/runtime/impl.rs +++ b/crates/engine/src/runtime/impl.rs @@ -51,7 +51,6 @@ use tari_engine_types::{ ConvertFromByteType, ResourceAddressRef, Utxo, - UtxoAddress, UtxoOutput, ValidatorFeePoolAddress, }; @@ -95,6 +94,7 @@ use tari_template_lib::{ ResourceGetNonFungibleArg, ResourceRef, ResourceUpdateNonFungibleDataArg, + SetFreezeStealthUtxosArg, StealthTransferResourceArg, VaultAction, VaultCreateProofByFungibleAmountArg, @@ -119,6 +119,7 @@ use tari_template_lib::{ ResourceAddress, ResourceAddressAllocation, StealthTransferStatement, + UtxoAddress, VaultRef, }, prelude::{ResourceType, RistrettoPublicKeyBytes}, @@ -1154,7 +1155,7 @@ impl> RuntimeInte Ok(InvokeResult::unit()) }) }, - ResourceAction::SetFreeze => { + ResourceAction::SetVaultFreeze => { let resource_address = resource_ref .as_resource_address() @@ -1220,6 +1221,68 @@ impl> RuntimeInte &maybe_bucket.map(tari_template_lib::models::Bucket::from_id), )?) }, + ResourceAction::SetStealthUtxosFreeze => { + let resource_address = + resource_ref + .as_resource_address() + .ok_or_else(|| RuntimeError::InvalidArgument { + argument: "resource_ref", + reason: "FreezeStealthUtxo resource action requires a resource address".to_string(), + })?; + let arg: SetFreezeStealthUtxosArg = args.assert_one_arg()?; + + self.tracker.write_with(|state_mut| { + let resource_lock = state_mut.read_lock_substate(&SubstateId::Resource(resource_address))?; + + let resource = state_mut.get_resource(&resource_lock)?; + + if !resource.resource_type().is_stealth() { + return Err(RuntimeError::InvalidArgument { + argument: "resource_ref", + reason: "FreezeStealthUtxo can only be called on stealth resources".to_string(), + }); + } + + if arg.utxos.is_empty() { + return Err(RuntimeError::InvalidArgument { + argument: "SetFreezeStealthUtxosArg", + reason: "Utxos list cannot be empty".to_string(), + }); + } + + state_mut.authorization().check_resource_access_rules( + ResourceAuthAction::Freeze, + resource.as_ownership(), + resource.access_rules(), + )?; + + for utxo in arg.utxos { + let id = SubstateId::Utxo(UtxoAddress::new(resource_address, utxo)); + let locked = state_mut.write_lock_substate(&id)?; + + let utxo = state_mut + .get_locked_substate_mut(&locked)? + .as_utxo_mut() + .ok_or_else(|| RuntimeError::LockSubstateMismatch { + lock_id: locked.lock_id(), + expected_type: "Utxo", + id, + })?; + + // Freeze is idempotent. + if arg.freeze { + utxo.freeze(); + } else { + utxo.unfreeze(); + } + state_mut.unlock_substate(locked)?; + } + + state_mut.unlock_substate(resource_lock)?; + + Ok(InvokeResult::unit()) + }) + }, } } diff --git a/crates/engine/src/runtime/state_store.rs b/crates/engine/src/runtime/state_store.rs index 50e2550b0c..acf51b9815 100644 --- a/crates/engine/src/runtime/state_store.rs +++ b/crates/engine/src/runtime/state_store.rs @@ -10,10 +10,9 @@ use tari_engine_types::{ substate::{Substate, SubstateId, SubstateValue}, vault::Vault, Utxo, - UtxoAddress, }; use tari_ootle_common_types::optional::Optional; -use tari_template_lib::models::{ComponentAddress, VaultId}; +use tari_template_lib::models::{ComponentAddress, UtxoAddress, VaultId}; use crate::{ runtime::{ diff --git a/crates/engine/src/runtime/tracker.rs b/crates/engine/src/runtime/tracker.rs index 90f10f09e5..7a69cd97a2 100644 --- a/crates/engine/src/runtime/tracker.rs +++ b/crates/engine/src/runtime/tracker.rs @@ -35,12 +35,11 @@ use tari_engine_types::{ logs::LogEntry, substate::{SubstateId, SubstateValue}, virtual_substate::VirtualSubstates, - UtxoAddress, }; use tari_ootle_common_types::Epoch; use tari_template_lib::{ auth::{ComponentAccessRules, OwnerRule}, - models::{ComponentAddress, ComponentAddressAllocation, Metadata, UnclaimedConfidentialOutputAddress}, + models::{ComponentAddress, ComponentAddressAllocation, Metadata, UnclaimedConfidentialOutputAddress, UtxoAddress}, prelude::{RistrettoPublicKeyBytes, TemplateAddress}, types::Hash, }; diff --git a/crates/engine/src/runtime/working_state.rs b/crates/engine/src/runtime/working_state.rs index ea0c17c0dd..bf5e2ea249 100644 --- a/crates/engine/src/runtime/working_state.rs +++ b/crates/engine/src/runtime/working_state.rs @@ -35,7 +35,6 @@ use tari_engine_types::{ ResourceAddressRef, ToByteType, Utxo, - UtxoAddress, ValidatorFeePoolAddress, ValidatorFeeWithdrawal, }; @@ -54,6 +53,7 @@ use tari_template_lib::{ StealthInputsStatement, StealthTransferStatement, UnclaimedConfidentialOutputAddress, + UtxoAddress, VaultId, }, prelude::{AuthHookCaller, ResourceAddressAllocation, PUBLIC_IDENTITY_RESOURCE_ADDRESS}, @@ -204,7 +204,7 @@ impl WorkingState { let (address, substate) = self.store.get_locked_substate(locked.lock_id())?; let component = substate.component().ok_or_else(|| RuntimeError::LockSubstateMismatch { lock_id: locked.lock_id(), - address, + id: address, expected_type: "Component", })?; Ok(component) @@ -222,7 +222,7 @@ impl WorkingState { .component_mut() .ok_or_else(|| RuntimeError::LockSubstateMismatch { lock_id: locked.lock_id(), - address: locked.substate_id().clone(), + id: locked.substate_id().clone(), expected_type: "Component", })?; @@ -263,7 +263,7 @@ impl WorkingState { .as_resource() .ok_or_else(|| RuntimeError::LockSubstateMismatch { lock_id: locked.lock_id(), - address: addr, + id: addr, expected_type: "Resource", })?; @@ -300,8 +300,8 @@ impl WorkingState { let non_fungible = value .as_non_fungible() .ok_or_else(|| RuntimeError::LockSubstateMismatch { - lock_id: 0, - address: address.clone(), + lock_id: locked.lock_id(), + id: address.clone(), expected_type: "NonFungible", })?; Ok(non_fungible) @@ -312,8 +312,8 @@ impl WorkingState { let non_fungible = value .as_non_fungible_mut() .ok_or_else(|| RuntimeError::LockSubstateMismatch { - lock_id: 0, - address: address.clone(), + lock_id: locked.lock_id(), + id: address.clone(), expected_type: "NonFungible", })?; Ok(non_fungible) @@ -342,7 +342,7 @@ impl WorkingState { let vault = substate.as_vault().ok_or_else(|| RuntimeError::LockSubstateMismatch { lock_id: locked.lock_id(), - address: addr, + id: addr, expected_type: "Vault", })?; @@ -356,7 +356,7 @@ impl WorkingState { .as_vault_mut() .ok_or_else(|| RuntimeError::LockSubstateMismatch { lock_id: locked.lock_id(), - address: addr, + id: addr, expected_type: "Vault", })?; @@ -370,7 +370,7 @@ impl WorkingState { .as_resource_mut() .ok_or_else(|| RuntimeError::LockSubstateMismatch { lock_id: locked.lock_id(), - address: addr, + id: addr, expected_type: "Resource", })?; @@ -1069,7 +1069,7 @@ impl WorkingState { total_fees_paid: fee_resource .amount() .to_u64_checked() - .expect("FeeState guarantees that the total fee payments fit in a u64"), + .expect("FeeState guarantees that the total fee payments fit in an u64"), total_fee_overcharge, cost_breakdown: self.fee_state.take_fee_charges(), }, @@ -1455,7 +1455,7 @@ impl WorkingState { if !component.contains_substate(address)? { warn!( target: LOG_TARGET, - "Component {} attempted access to {} that is does not own", + "Component {} attempted access to {} that it does not own", component_lock.substate_id(), address ); diff --git a/crates/engine/tests/stealth.rs b/crates/engine/tests/stealth.rs index aedfe02ecf..8abed58d02 100644 --- a/crates/engine/tests/stealth.rs +++ b/crates/engine/tests/stealth.rs @@ -5,9 +5,9 @@ use std::collections::BTreeMap; use rand::rngs::OsRng; use tari_common_types::types::PrivateKey; -use tari_crypto::{keys::PublicKey, ristretto::RistrettoPublicKey}; +use tari_crypto::{commitment::HomomorphicCommitmentFactory, keys::PublicKey, ristretto::RistrettoPublicKey}; use tari_engine_types::{ - crypto::{ElgamalVerifiableBalance, ValueLookupTable}, + crypto::{get_commitment_factory, ElgamalVerifiableBalance, ValueLookupTable}, resource_container::ResourceError, ToByteType, UtxoOutput, @@ -15,7 +15,7 @@ use tari_engine_types::{ use tari_ootle_common_types::substate_type::SubstateType; use tari_template_lib::{ call_args, - models::{ComponentAddress, ResourceAddress}, + models::{ComponentAddress, ResourceAddress, UtxoId}, prelude::{PedersenCommitmentBytes, SchnorrSignatureBytes}, }; use tari_template_test_tooling::{ @@ -458,3 +458,76 @@ fn mint_with_view_key() { try_brute_force_stealth_balance(&utxos, &view_key_secret, 0..=200, &mut AlwaysMissLookupTable).unwrap(); assert_eq!(total_balance, Some(1000)); } + +#[test] +fn freeze_then_attempt_spend() { + let outputs = vec![100u64, 1000, 10000]; + let mint = stealth::generate_mint_statement(outputs.clone(), 0, None); + let (mut test, faucet, faucet_resx) = setup(&mint, None); + + let transfer = stealth::generate_transfer_data( + &[ + MaskAndValue { + mask: mint.output_masks[0].clone(), + value: 100.into(), + }, + MaskAndValue { + mask: mint.output_masks[1].clone(), + value: 1000.into(), + }, + ], + 0, + Some(1100), + 0, + ); + let owner = test.owner_proof(); + let utxos = mint.output_masks + .iter() + .zip(outputs) + .take(2) // Freeze the first two outputs + .map(|(mask, amount)| { + let commitment = get_commitment_factory().commit_value(mask, amount); + UtxoId::from(commitment.to_byte_type()) + }) + .collect::>(); + + test.execute_expect_success( + Transaction::builder() + .call_method(faucet, "freeze_utxos", args![utxos]) + .build_and_seal(test.secret_key()), + vec![owner.clone()], + ); + + // Try and spend a frozen output + let reason = test.execute_expect_failure( + Transaction::builder() + .stealth_transfer(faucet_resx, transfer.statement.clone()) + .build_and_seal(test.secret_key()), + vec![], + ); + + assert_reject_reason(reason, ResourceError::InvalidSpend { details: String::new() }); + + test.execute_expect_success( + Transaction::builder() + .call_method(faucet, "unfreeze_utxos", args![utxos]) + .build_and_seal(test.secret_key()), + vec![owner], + ); + + // Should be able to spend now + let result = test.execute_expect_success( + Transaction::builder() + .stealth_transfer(faucet_resx, transfer.statement) + .build_and_seal(test.secret_key()), + vec![], + ); + + let diff = result.finalize.any_accept().unwrap(); + let utxos = diff + .up_iter() + .filter_map(|(_, substate)| substate.substate_value().as_utxo()) + .collect::>(); + assert_eq!(utxos.len(), 1); + assert!(utxos[0].output().is_some()); +} diff --git a/crates/engine/tests/templates/events/src/lib.rs b/crates/engine/tests/templates/events/src/lib.rs index 67a0e04824..3b451200bf 100644 --- a/crates/engine/tests/templates/events/src/lib.rs +++ b/crates/engine/tests/templates/events/src/lib.rs @@ -33,8 +33,7 @@ mod event { impl EventEmitter { pub fn test_function(topic: String) { println!("Emitting a new event"); - let payload = [("my", "event")]; - emit_event(topic, payload); + emit_event(topic, metadata!("my" => "event")); } } } diff --git a/crates/engine/tests/templates/freeze/src/lib.rs b/crates/engine/tests/templates/freeze/src/lib.rs index 7332556de6..b39f4bc642 100644 --- a/crates/engine/tests/templates/freeze/src/lib.rs +++ b/crates/engine/tests/templates/freeze/src/lib.rs @@ -36,11 +36,11 @@ mod template { } pub fn freeze(&mut self, vault_id: VaultId) { - ResourceManager::get(self.vault.resource_address()).freeze(vault_id); + ResourceManager::get(self.vault.resource_address()).freeze_vault(vault_id); } pub fn unfreeze(&mut self, vault_id: VaultId) { - ResourceManager::get(self.vault.resource_address()).unfreeze(vault_id); + ResourceManager::get(self.vault.resource_address()).unfreeze_vault(vault_id); } } } diff --git a/crates/engine/tests/templates/stealth/src/lib.rs b/crates/engine/tests/templates/stealth/src/lib.rs index 39b04a2e2f..5b03e1a9a8 100644 --- a/crates/engine/tests/templates/stealth/src/lib.rs +++ b/crates/engine/tests/templates/stealth/src/lib.rs @@ -18,8 +18,10 @@ mod template { mint: StealthTransferStatement, view_key: Option, ) -> Component { + let signer = NonFungibleAddress::from_public_key(CallerContext::transaction_signer_public_key()); let bucket = ResourceBuilder::stealth() .mintable(rule!(allow_all)) + .freezable(rule!(non_fungible(signer))) .with_view_key_opt(view_key) .initial_supply(initial_supply); @@ -68,5 +70,13 @@ mod template { let bucket = self.manager.mint_stealth(amount); self.supply_vault.deposit(bucket); } + + pub fn freeze_utxos(&self, utxos: Vec) { + self.manager.freeze_utxos(utxos); + } + + pub fn unfreeze_utxos(&self, utxos: Vec) { + self.manager.unfreeze_utxos(utxos); + } } } diff --git a/crates/engine_types/src/indexed_value.rs b/crates/engine_types/src/indexed_value.rs index 927b741b02..3b6633e9d9 100644 --- a/crates/engine_types/src/indexed_value.rs +++ b/crates/engine_types/src/indexed_value.rs @@ -15,6 +15,8 @@ use tari_template_lib::{ ResourceAddress, ResourceAddressAllocation, UnclaimedConfidentialOutputAddress, + UtxoAddress, + UtxoAddressContents, VaultId, }, prelude::{ComponentAddress, Metadata, NonFungibleAddress}, @@ -26,8 +28,6 @@ use crate::{ serde_with, substate::SubstateId, transaction_receipt::TransactionReceiptAddress, - UtxoAddress, - UtxoAddressContents, ValidatorFeePoolAddress, }; @@ -208,38 +208,38 @@ impl IndexedWellKnownTypes { } /// Checks if a value contains a substate with the given address. This function does not allocate. - pub fn value_contains_substate(value: &tari_bor::Value, address: &SubstateId) -> Result { + pub fn value_contains_substate(value: &tari_bor::Value, id: &SubstateId) -> Result { let mut found = false; tari_bor::walk_all( value, &mut |value: WellKnownTariValue| { match value { WellKnownTariValue::ComponentAddress(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::ResourceAddress(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::TransactionReceiptAddress(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::NonFungibleAddress(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::VaultId(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::UnclaimedConfidentialOutputAddress(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::PublishedTemplateAddress(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::ValidatorNodeFeePool(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::Utxo(addr) => { - found = *address == addr; + found = *id == addr; }, WellKnownTariValue::BucketId(_) | WellKnownTariValue::Metadata(_) | diff --git a/crates/engine_types/src/substate.rs b/crates/engine_types/src/substate.rs index c17e4653a4..352aab83e6 100644 --- a/crates/engine_types/src/substate.rs +++ b/crates/engine_types/src/substate.rs @@ -31,7 +31,14 @@ use serde::{Deserialize, Serialize}; use tari_bor::{decode, decode_exact, encode, BorError}; use tari_common_types::types::FixedHash; use tari_template_lib::{ - models::{ComponentAddress, NonFungibleAddress, ResourceAddress, UnclaimedConfidentialOutputAddress, VaultId}, + models::{ + ComponentAddress, + NonFungibleAddress, + ResourceAddress, + UnclaimedConfidentialOutputAddress, + UtxoAddress, + VaultId, + }, prelude::PUBLIC_IDENTITY_RESOURCE_ADDRESS, types::{Hash, ObjectKey}, }; @@ -46,7 +53,6 @@ use crate::{ transaction_receipt::{TransactionReceipt, TransactionReceiptAddress}, utxo::Utxo, vault::Vault, - UtxoAddress, ValidatorFeePool, ValidatorFeePoolAddress, ValidatorFeeWithdrawal, @@ -758,6 +764,13 @@ impl SubstateValue { } } + pub fn as_utxo_mut(&mut self) -> Option<&mut Utxo> { + match self { + SubstateValue::Utxo(utxo) => Some(utxo), + _ => None, + } + } + pub fn to_bytes(&self) -> Vec { encode(self).unwrap() } diff --git a/crates/engine_types/src/substate_serde.rs b/crates/engine_types/src/substate_serde.rs index 568991f1ec..1485cb3fe1 100644 --- a/crates/engine_types/src/substate_serde.rs +++ b/crates/engine_types/src/substate_serde.rs @@ -237,12 +237,11 @@ impl<'de> serde::Deserialize<'de> for SubstateId { #[cfg(test)] mod tests { use tari_template_lib::{ - models::NonFungibleId, + models::{NonFungibleId, UtxoAddress, UtxoId}, types::{Hash, ObjectKey}, }; use super::*; - use crate::{UtxoAddress, UtxoId}; #[test] fn encoding_and_decoding() { diff --git a/crates/engine_types/src/utxo.rs b/crates/engine_types/src/utxo.rs index 118968533d..c87c5dae0b 100644 --- a/crates/engine_types/src/utxo.rs +++ b/crates/engine_types/src/utxo.rs @@ -1,24 +1,8 @@ // Copyright 2025 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -use std::{ - fmt, - fmt::{Display, Formatter}, - str::FromStr, -}; - -use borsh::{BorshDeserialize, BorshSerialize}; -use tari_bor::{BorTag, Deserialize, Serialize}; -use tari_template_lib::{ - models::{BinaryTag, ResourceAddress}, - types::{ - crypto::{PedersenCommitmentBytes, RistrettoPublicKeyBytes, UtxoTag}, - from_hex, - hex::write_hex_fmt, - serde_helpers, - KeyParseError, - }, -}; +use tari_bor::{Deserialize, Serialize}; +use tari_template_lib::types::crypto::{RistrettoPublicKeyBytes, UtxoTag}; use crate::crypto::PrivateOutput; @@ -63,9 +47,12 @@ impl Utxo { self.is_frozen = true; } + pub fn unfreeze(&mut self) { + self.is_frozen = false; + } + pub fn burn(&mut self) { self.output = None; - self.is_frozen = true; } pub fn is_frozen(&self) -> bool { @@ -81,139 +68,3 @@ impl Utxo { self.output.as_ref().map(|o| o.tag) } } - -const TAG: u64 = BinaryTag::Utxo.as_u64(); - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))] -pub struct UtxoAddress(BorTag); - -impl UtxoAddress { - pub fn new(resource_address: ResourceAddress, id: UtxoId) -> Self { - Self(BorTag::new(UtxoAddressContents { resource_address, id })) - } - - pub fn resource_address(&self) -> &ResourceAddress { - &self.0.inner().resource_address - } - - pub fn id(&self) -> &UtxoId { - &self.0.inner().id - } -} - -impl FromStr for UtxoAddress { - type Err = KeyParseError; - - fn from_str(s: &str) -> Result { - // utxo_{resource}_{id} - let rest = s.strip_prefix("utxo_").unwrap_or(s); - let (resource, id) = rest.split_once('_').ok_or(KeyParseError)?; - let resource_addr = ResourceAddress::from_hex(resource)?; - let id = UtxoId::from_hex(id)?; - Ok(Self::new(resource_addr, id)) - } -} - -impl Display for UtxoAddress { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "utxo_{}_{}", self.resource_address().as_object_key(), self.id()) - } -} - -impl From for UtxoAddress { - fn from(contents: UtxoAddressContents) -> Self { - Self(BorTag::new(contents)) - } -} - -#[derive( - Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize, -)] -#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))] -pub struct UtxoId( - #[cfg_attr(feature = "ts", ts(type = "string"))] - #[serde(with = "serde_helpers::fixed_hex")] - [u8; Self::LENGTH], -); - -impl UtxoId { - pub const LENGTH: usize = 32; - - pub const fn from_array(arr: [u8; 32]) -> Self { - Self(arr) - } - - pub fn from_hex(hex: &str) -> Result { - from_hex(hex).map(Self::from_array) - } - - pub fn into_commitment_bytes(self) -> PedersenCommitmentBytes { - PedersenCommitmentBytes::from_array(self.0) - } - - pub fn to_commitment_hex_string(&self) -> String { - // to_string happens to return the hex encoding of the commitment bytes. If that changes, so will this. - self.to_string() - } -} - -impl From for UtxoId { - fn from(commitment: PedersenCommitmentBytes) -> Self { - Self::from_array(commitment.into_array()) - } -} - -impl From<&PedersenCommitmentBytes> for UtxoId { - fn from(commitment: &PedersenCommitmentBytes) -> Self { - (*commitment).into() - } -} - -impl Display for UtxoId { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write_hex_fmt(f, &self.0) - } -} - -/// A NonFungibleId namespaced by a ResourceAddress. -#[derive( - Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord, BorshSerialize, BorshDeserialize, -)] -#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))] -pub struct UtxoAddressContents { - resource_address: ResourceAddress, - id: UtxoId, -} - -impl borsh::BorshSerialize for UtxoAddress { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - ::borsh::BorshSerialize::serialize(self.0.inner(), writer) - } -} - -impl borsh::BorshDeserialize for UtxoAddress { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - Ok(Self(BorTag::new(borsh::BorshDeserialize::deserialize_reader(reader)?))) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_parses_from_strings() { - let resource_address = - ResourceAddress::from_hex("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef").unwrap(); - let id = UtxoId::from_hex("3210987654321098765432109876543210987654321098765432109876543210").unwrap(); - let utxo_address = UtxoAddress::new(resource_address, id); - let utxo_address_str = utxo_address.to_string(); - assert_eq!( - utxo_address_str, - "utxo_1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef_3210987654321098765432109876543210987654321098765432109876543210" - ); - let parsed_utxo_address = UtxoAddress::from_str(&utxo_address_str).unwrap(); - assert_eq!(parsed_utxo_address, utxo_address); - } -} diff --git a/crates/tari_bor/src/tag.rs b/crates/tari_bor/src/tag.rs index d4f2f41ec2..853227bd58 100644 --- a/crates/tari_bor/src/tag.rs +++ b/crates/tari_bor/src/tag.rs @@ -7,7 +7,6 @@ use ciborium::tag::Required; use serde::{de, ser, Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub struct BorTag(Required); impl BorTag { diff --git a/crates/template_lib/src/args/types.rs b/crates/template_lib/src/args/types.rs index d22b3b8793..7f026c65c3 100644 --- a/crates/template_lib/src/args/types.rs +++ b/crates/template_lib/src/args/types.rs @@ -43,6 +43,7 @@ use crate::{ ResourceAddress, ResourceAddressAllocation, StealthTransferStatement, + UtxoId, VaultId, VaultRef, }, @@ -234,9 +235,11 @@ pub enum ResourceAction { /// Update the access rules of a resource UpdateAccessRules, /// Sets the freeze flags on a vault of a resource. - SetFreeze, + SetVaultFreeze, /// Executes a stealth transfer for the resource StealthTransfer, + /// Un/freezes one or more stealth UTXOs of a resource + SetStealthUtxosFreeze, } /// All the possible minting operation types @@ -710,3 +713,11 @@ pub struct BuiltinTemplateInvokeArg { pub enum BuiltinTemplateAction { GetTemplateAddress { bultin: BuiltinTemplate }, } + +// -------------------------------- UTXOs -------------------------------- // + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct SetFreezeStealthUtxosArg { + pub utxos: Vec, + pub freeze: bool, +} diff --git a/crates/template_lib/src/models/metadata.rs b/crates/template_lib/src/models/metadata.rs index 3daed07e4a..f472e145e0 100644 --- a/crates/template_lib/src/models/metadata.rs +++ b/crates/template_lib/src/models/metadata.rs @@ -131,3 +131,53 @@ impl Display for Metadata { Ok(()) } } + +/// Creates a metadata object +/// +/// # Example +/// +/// ```rust +/// # use tari_template_lib::metadata; +/// metadata!( +/// "name" => "My NFT", +/// "description" => "This is my first NFT", +/// "image" => "https://example.com/my-nft.png" +/// ); +/// ``` +#[macro_export] +macro_rules! metadata { + ($($key:expr => $value:expr),* $(,)?) => { + { + let mut metadata = $crate::models::Metadata::new(); + $( + metadata.insert($key, $value); + )* + metadata + } + }; + () => { + $crate::models::Metadata::new() + }; +} + +#[cfg(test)] +mod tests { + #[test] + fn metadata_macro() { + let i = 123; + let metadata = metadata!( + "name" => "My NFT", + "description" => "This is my first NFT", + "image" => "https://example.com/my-nft.png", + "index" => i.to_string() + ); + + assert_eq!(metadata.get("name"), Some(&"My NFT".to_string())); + assert_eq!(metadata.get("description"), Some(&"This is my first NFT".to_string())); + assert_eq!( + metadata.get("image"), + Some(&"https://example.com/my-nft.png".to_string()) + ); + assert_eq!(metadata.get("index"), Some(&"123".to_string())); + } +} diff --git a/crates/template_lib/src/models/mod.rs b/crates/template_lib/src/models/mod.rs index b9af170750..f80815f85c 100644 --- a/crates/template_lib/src/models/mod.rs +++ b/crates/template_lib/src/models/mod.rs @@ -31,6 +31,7 @@ mod component; mod confidential_proof; mod encrypted_data; mod layer_one_commitment; +#[macro_use] mod metadata; mod non_fungible; mod proof; @@ -39,6 +40,7 @@ mod signature_verifier; mod stealth; mod system; mod unspent_output; +mod utxo; mod vault; mod viewable_balance; @@ -58,5 +60,6 @@ pub use signature_verifier::*; pub use stealth::*; pub use system::*; pub use unspent_output::*; +pub use utxo::*; pub use vault::*; pub use viewable_balance::*; diff --git a/crates/template_lib/src/models/utxo.rs b/crates/template_lib/src/models/utxo.rs new file mode 100644 index 0000000000..98dff770c4 --- /dev/null +++ b/crates/template_lib/src/models/utxo.rs @@ -0,0 +1,170 @@ +// Copyright 2025 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use tari_bor::{BorTag, Deserialize, Serialize}; +use tari_template_abi::rust::{ + fmt, + fmt::{Display, Formatter}, + str::FromStr, +}; +use tari_template_lib_types::{ + crypto::PedersenCommitmentBytes, + from_hex, + hex::write_hex_fmt, + serde_helpers, + KeyParseError, +}; + +use crate::models::{BinaryTag, ResourceAddress}; + +const TAG: u64 = BinaryTag::Utxo.as_u64(); + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))] +pub struct UtxoAddress(BorTag); + +impl UtxoAddress { + pub fn new(resource_address: ResourceAddress, id: UtxoId) -> Self { + Self(BorTag::new(UtxoAddressContents { resource_address, id })) + } + + pub fn resource_address(&self) -> &ResourceAddress { + &self.0.inner().resource_address + } + + pub fn id(&self) -> &UtxoId { + &self.0.inner().id + } +} + +impl FromStr for UtxoAddress { + type Err = KeyParseError; + + fn from_str(s: &str) -> Result { + // utxo_{resource}_{id} + let rest = s.strip_prefix("utxo_").unwrap_or(s); + let (resource, id) = rest.split_once('_').ok_or(KeyParseError)?; + let resource_addr = ResourceAddress::from_hex(resource)?; + let id = UtxoId::from_hex(id)?; + Ok(Self::new(resource_addr, id)) + } +} + +impl Display for UtxoAddress { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "utxo_{}_{}", self.resource_address().as_object_key(), self.id()) + } +} + +impl From for UtxoAddress { + fn from(contents: UtxoAddressContents) -> Self { + Self(BorTag::new(contents)) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))] +pub struct UtxoId( + #[cfg_attr(feature = "ts", ts(type = "string"))] + #[serde(with = "serde_helpers::fixed_hex")] + [u8; Self::LENGTH], +); + +impl UtxoId { + pub const LENGTH: usize = 32; + + pub const fn from_array(arr: [u8; 32]) -> Self { + Self(arr) + } + + pub fn from_hex(hex: &str) -> Result { + from_hex(hex).map(Self::from_array) + } + + pub fn into_commitment_bytes(self) -> PedersenCommitmentBytes { + PedersenCommitmentBytes::from_array(self.0) + } + + pub fn to_commitment_hex_string(&self) -> String { + // to_string happens to return the hex encoding of the commitment bytes. If that changes, so will this. + self.to_string() + } +} + +impl From for UtxoId { + fn from(commitment: PedersenCommitmentBytes) -> Self { + Self::from_array(commitment.into_array()) + } +} + +impl From<&PedersenCommitmentBytes> for UtxoId { + fn from(commitment: &PedersenCommitmentBytes) -> Self { + (*commitment).into() + } +} + +impl Display for UtxoId { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write_hex_fmt(f, &self.0) + } +} + +/// A NonFungibleId namespaced by a ResourceAddress. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] +pub struct UtxoAddressContents { + resource_address: ResourceAddress, + id: UtxoId, +} + +#[cfg(feature = "borsh")] +mod borsh_impls { + use super::*; + + impl borsh::BorshSerialize for UtxoId { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_all(&self.0) + } + } + + impl borsh::BorshDeserialize for UtxoId { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let mut buf = [0u8; UtxoId::LENGTH]; + reader.read_exact(&mut buf)?; + Ok(Self(buf)) + } + } + + impl borsh::BorshSerialize for UtxoAddress { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + ::borsh::BorshSerialize::serialize(self.0.inner(), writer) + } + } + + impl borsh::BorshDeserialize for UtxoAddress { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + Ok(Self(BorTag::new(borsh::BorshDeserialize::deserialize_reader(reader)?))) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_parses_from_strings() { + let resource_address = + ResourceAddress::from_hex("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef").unwrap(); + let id = UtxoId::from_hex("3210987654321098765432109876543210987654321098765432109876543210").unwrap(); + let utxo_address = UtxoAddress::new(resource_address, id); + let utxo_address_str = utxo_address.to_string(); + assert_eq!( + utxo_address_str, + "utxo_1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef_3210987654321098765432109876543210987654321098765432109876543210" + ); + let parsed_utxo_address = UtxoAddress::from_str(&utxo_address_str).unwrap(); + assert_eq!(parsed_utxo_address, utxo_address); + } +} diff --git a/crates/template_lib/src/prelude.rs b/crates/template_lib/src/prelude.rs index 8f751f6d0e..ea478d58c1 100644 --- a/crates/template_lib/src/prelude.rs +++ b/crates/template_lib/src/prelude.rs @@ -58,6 +58,7 @@ pub use crate::{ info, invoke_args, log, + metadata, models::{ Account, Bucket, @@ -78,6 +79,8 @@ pub use crate::{ StealthInputsStatement, StealthOutputsStatement, StealthTransferStatement, + UtxoAddress, + UtxoId, Vault, VaultId, Verifiable, diff --git a/crates/template_lib/src/resource/manager.rs b/crates/template_lib/src/resource/manager.rs index 446f6c0cef..84379ac9b9 100644 --- a/crates/template_lib/src/resource/manager.rs +++ b/crates/template_lib/src/resource/manager.rs @@ -58,6 +58,7 @@ use crate::{ ResourceInvokeArg, ResourceRef, ResourceUpdateNonFungibleDataArg, + SetFreezeStealthUtxosArg, StealthTransferResourceArg, VaultFreezeFlags, }, @@ -72,6 +73,7 @@ use crate::{ ResourceAddress, ResourceAddressAllocation, StealthTransferStatement, + UtxoId, VaultId, }, prelude::{AuthHook, ResourceType}, @@ -888,15 +890,15 @@ impl ResourceManager { } /// Freezes all withdrawals, deposits and burns for the specified vault. - pub fn freeze(&self, vault_id: VaultId) { - self.set_freeze(vault_id, VaultFreezeFlags::all()); + pub fn freeze_vault(&self, vault_id: VaultId) { + self.set_freeze_vault_flags(vault_id, VaultFreezeFlags::all()); } /// Sets the freeze flags for the specified vault. - pub fn set_freeze(&self, vault_id: VaultId, flags: VaultFreezeFlags) { + pub fn set_freeze_vault_flags(&self, vault_id: VaultId, flags: VaultFreezeFlags) { let resp: InvokeResult = call_engine(EngineOp::ResourceInvoke, &ResourceInvokeArg { resource_ref: self.resource_address.into(), - action: ResourceAction::SetFreeze, + action: ResourceAction::SetVaultFreeze, args: invoke_args![FreezeResourceArg { vault_id, flags }], }); @@ -905,8 +907,28 @@ impl ResourceManager { /// Unfreezes all withdrawals, deposits and burns for the specified vault. /// Equivalent to `manager.set_freeze(FreezeFlags::empty())`. - pub fn unfreeze(&self, vault_id: VaultId) { - self.set_freeze(vault_id, VaultFreezeFlags::empty()); + pub fn unfreeze_vault(&self, vault_id: VaultId) { + self.set_freeze_vault_flags(vault_id, VaultFreezeFlags::empty()); + } + + /// Freezes the specified stealth UTXOs, preventing them from being spent/transferred. + pub fn freeze_utxos(&self, utxos: Vec) { + self.set_freeze_utxos(utxos, true); + } + + /// Unfreezes the specified stealth UTXOs, allowing them to be spent/transferred again. + pub fn unfreeze_utxos(&self, utxos: Vec) { + self.set_freeze_utxos(utxos, false); + } + + fn set_freeze_utxos(&self, utxos: Vec, freeze: bool) { + let resp: InvokeResult = call_engine(EngineOp::ResourceInvoke, &ResourceInvokeArg { + resource_ref: self.resource_address.into(), + action: ResourceAction::SetStealthUtxosFreeze, + args: invoke_args![SetFreezeStealthUtxosArg { utxos, freeze }], + }); + + resp.decode().expect("SetFreeze failed") } fn recall_internal(&self, arg: RecallResourceArg) -> Bucket { diff --git a/crates/wallet/sdk/src/apis/stealth_outputs.rs b/crates/wallet/sdk/src/apis/stealth_outputs.rs index 37cc642ba5..dfb871c5d1 100644 --- a/crates/wallet/sdk/src/apis/stealth_outputs.rs +++ b/crates/wallet/sdk/src/apis/stealth_outputs.rs @@ -11,7 +11,6 @@ use tari_engine_types::{ FromByteType, ToByteType, Utxo, - UtxoAddress, UtxoOutput, }; use tari_ootle_common_types::{ @@ -21,7 +20,7 @@ use tari_ootle_common_types::{ use tari_ootle_wallet_crypto::UnblindedStealthInputStatement; use tari_template_builtin::ACCOUNT_TEMPLATE_ADDRESS; use tari_template_lib::{ - models::{ComponentAddress, ResourceAddress, VaultId}, + models::{ComponentAddress, ResourceAddress, UtxoAddress, VaultId}, prelude::PedersenCommitmentBytes, types::Amount, }; diff --git a/crates/wallet/sdk/src/apis/stealth_transfer.rs b/crates/wallet/sdk/src/apis/stealth_transfer.rs index dc72a4eb40..792474b58c 100644 --- a/crates/wallet/sdk/src/apis/stealth_transfer.rs +++ b/crates/wallet/sdk/src/apis/stealth_transfer.rs @@ -6,7 +6,7 @@ use std::cmp; use digest::crypto_common::rand_core::OsRng; use log::*; use tari_crypto::{keys::PublicKey, ristretto::RistrettoPublicKey}; -use tari_engine_types::{substate::SubstateId, ConvertFromByteType, FromByteType, ToByteType, UtxoAddress}; +use tari_engine_types::{substate::SubstateId, ConvertFromByteType, FromByteType, ToByteType}; use tari_ootle_address::{OotleAddress, RistrettoOotleAddress}; use tari_ootle_common_types::{ displayable::Displayable, @@ -22,7 +22,14 @@ use tari_ootle_wallet_crypto::{ }; use tari_template_lib::{ constants::XTR, - models::{Account as BuiltinAccount, ComponentAddress, ResourceAddress, StealthTransferStatement, VaultId}, + models::{ + Account as BuiltinAccount, + ComponentAddress, + ResourceAddress, + StealthTransferStatement, + UtxoAddress, + VaultId, + }, types::Amount, }; use tari_transaction::{args, Transaction}; diff --git a/crates/wallet/sdk/src/models/stealth_output.rs b/crates/wallet/sdk/src/models/stealth_output.rs index 25dea4139f..d5e285158e 100644 --- a/crates/wallet/sdk/src/models/stealth_output.rs +++ b/crates/wallet/sdk/src/models/stealth_output.rs @@ -1,9 +1,8 @@ // Copyright 2025 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -use tari_engine_types::UtxoAddress; use tari_template_lib::{ - models::{ComponentAddress, EncryptedData}, + models::{ComponentAddress, EncryptedData, UtxoAddress}, prelude::{PedersenCommitmentBytes, ResourceAddress, RistrettoPublicKeyBytes}, types::{crypto::UtxoTag, Amount}, }; diff --git a/crates/wallet/sdk/src/models/utxo_update.rs b/crates/wallet/sdk/src/models/utxo_update.rs index 2030e1e84b..ba7d91c879 100644 --- a/crates/wallet/sdk/src/models/utxo_update.rs +++ b/crates/wallet/sdk/src/models/utxo_update.rs @@ -4,9 +4,11 @@ use std::collections::HashMap; use tari_bor::{Deserialize, Serialize}; -use tari_engine_types::UtxoId; use tari_ootle_common_types::{shard::Shard, StateVersion}; -use tari_template_lib::types::crypto::{RistrettoPublicKeyBytes, UtxoTag}; +use tari_template_lib::{ + models::UtxoId, + types::crypto::{RistrettoPublicKeyBytes, UtxoTag}, +}; #[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export))] diff --git a/crates/wallet/sdk/src/network.rs b/crates/wallet/sdk/src/network.rs index f67fd15060..63d02e838c 100644 --- a/crates/wallet/sdk/src/network.rs +++ b/crates/wallet/sdk/src/network.rs @@ -9,12 +9,11 @@ use tari_engine_types::{ commit_result::ExecuteResult, substate::{Substate, SubstateId, SubstateValue}, Utxo, - UtxoId, }; use tari_ootle_common_types::{shard::Shard, StateVersion}; use tari_template_abi::TemplateDef; use tari_template_lib::{ - models::ResourceAddress, + models::{ResourceAddress, UtxoId}, prelude::{RistrettoPublicKeyBytes, TemplateAddress}, types::crypto::UtxoTag, }; diff --git a/crates/wallet/sdk/src/storage.rs b/crates/wallet/sdk/src/storage.rs index 8b7c7558db..06b1ac0457 100644 --- a/crates/wallet/sdk/src/storage.rs +++ b/crates/wallet/sdk/src/storage.rs @@ -6,7 +6,7 @@ use std::{ ops::{Deref, DerefMut}, }; -use tari_engine_types::{resource::Resource, substate::SubstateId, UtxoAddress, UtxoId}; +use tari_engine_types::{resource::Resource, substate::SubstateId}; use tari_ootle_common_types::{ optional::IsNotFoundError, shard::Shard, @@ -15,7 +15,7 @@ use tari_ootle_common_types::{ VersionedSubstateIdRef, }; use tari_template_lib::{ - models::VaultId, + models::{UtxoAddress, UtxoId, VaultId}, prelude::{ ComponentAddress, NonFungibleId, diff --git a/crates/wallet/sdk/tests/support/harness.rs b/crates/wallet/sdk/tests/support/harness.rs index b62ca1d811..0511027870 100644 --- a/crates/wallet/sdk/tests/support/harness.rs +++ b/crates/wallet/sdk/tests/support/harness.rs @@ -9,7 +9,6 @@ use tari_engine_types::{ substate::{Substate, SubstateId}, ToByteType, Utxo, - UtxoId, }; use tari_ootle_common_types::{optional::Optional, shard::Shard, Network, StateVersion}; use tari_ootle_wallet_sdk::{ @@ -23,7 +22,7 @@ use tari_ootle_wallet_storage_sqlite::SqliteWalletStore; use tari_template_abi::TemplateDef; use tari_template_lib::{ constants::STEALTH_TARI_RESOURCE_ADDRESS, - models::{ComponentAddress, EncryptedData, ResourceAddress, VaultId}, + models::{ComponentAddress, EncryptedData, ResourceAddress, UtxoId, VaultId}, prelude::{Amount, PedersenCommitmentBytes, ResourceType, TemplateAddress}, }; use tari_transaction::{Transaction, TransactionId}; diff --git a/crates/wallet/sdk_services/src/indexer_jrpc_impl.rs b/crates/wallet/sdk_services/src/indexer_jrpc_impl.rs index f497e487c0..aaeb7f47e5 100644 --- a/crates/wallet/sdk_services/src/indexer_jrpc_impl.rs +++ b/crates/wallet/sdk_services/src/indexer_jrpc_impl.rs @@ -10,7 +10,6 @@ use reqwest::{IntoUrl, Url}; use tari_engine_types::{ substate::{Substate, SubstateId}, Utxo, - UtxoId, }; use tari_indexer_client::{ error::IndexerClientError, @@ -38,7 +37,7 @@ use tari_ootle_wallet_sdk::{ }, }; use tari_template_lib::{ - models::ResourceAddress, + models::{ResourceAddress, UtxoId}, prelude::RistrettoPublicKeyBytes, types::{crypto::UtxoTag, TemplateAddress}, }; diff --git a/crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs b/crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs index 459690343f..ba2dd17398 100644 --- a/crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs +++ b/crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs @@ -4,7 +4,7 @@ use std::{array, time::Duration}; use log::*; -use tari_engine_types::{UtxoAddress, UtxoId, UtxoOutput}; +use tari_engine_types::UtxoOutput; use tari_ootle_common_types::{ optional::{IsNotFoundError, Optional}, Network, @@ -14,7 +14,7 @@ use tari_ootle_wallet_sdk::{ storage::{WalletStore, WalletStoreReader, WalletStoreWriter}, WalletSdk, }; -use tari_template_lib::models::ResourceAddress; +use tari_template_lib::models::{ResourceAddress, UtxoAddress, UtxoId}; use tokio::sync::watch; use crate::utxo_scanner::StealthScannerApiError; diff --git a/crates/wallet/storage_sqlite/src/writer.rs b/crates/wallet/storage_sqlite/src/writer.rs index 3d25db548d..7452c395b9 100644 --- a/crates/wallet/storage_sqlite/src/writer.rs +++ b/crates/wallet/storage_sqlite/src/writer.rs @@ -21,7 +21,7 @@ use diesel::{ use log::*; use serde::Serialize; use tari_bor::json_encoding::CborValueJsonSerializeWrapper; -use tari_engine_types::{resource::Resource, substate::SubstateId, UtxoAddress, UtxoId}; +use tari_engine_types::{resource::Resource, substate::SubstateId}; use tari_ootle_common_types::{shard::Shard, StateVersion, VersionedSubstateIdRef}; use tari_ootle_wallet_sdk::{ models::{ @@ -42,7 +42,7 @@ use tari_ootle_wallet_sdk::{ storage::{WalletStorageError, WalletStoreReader, WalletStoreWriter}, }; use tari_template_lib::{ - models::{ComponentAddress, EncryptedData, NonFungibleId, ResourceAddress, VaultId}, + models::{ComponentAddress, EncryptedData, NonFungibleId, ResourceAddress, UtxoAddress, UtxoId, VaultId}, types::{ crypto::{PedersenCommitmentBytes, RistrettoPublicKeyBytes, UtxoTag}, Amount,