Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account locker in manifest summary encountered entities #213

Merged
merged 11 commits into from
Sep 11, 2024
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/sargon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sargon"
version = "1.1.12"
version = "1.1.13"
edition = "2021"
build = "build.rs"

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
CALL_METHOD
Address("locker_tdx_2_1drgp40wpu5cj0zady4s0pec6rld8muge0j2xx9xuwwc474uzlgja6a")
"claim"
Address("account_tdx_2_12xlu6x99ssrwrs8cnafka8476ursxfyfde3kfyk7d4s9c5kdvcs77x")
Address("resource_tdx_2_1nflxr7dvp29hxhjjp53strsdgv2kv9dxlx6ys52lafrgyljrhwkt27")
Decimal("4")
;
TAKE_FROM_WORKTOP
Address("resource_tdx_2_1nflxr7dvp29hxhjjp53strsdgv2kv9dxlx6ys52lafrgyljrhwkt27")
Decimal("4")
Bucket("bucket1")
;
CALL_METHOD
Address("account_tdx_2_12xlu6x99ssrwrs8cnafka8476ursxfyfde3kfyk7d4s9c5kdvcs77x")
"deposit"
Bucket("bucket1")
;
CALL_METHOD
Address("locker_tdx_2_1drgp40wpu5cj0zady4s0pec6rld8muge0j2xx9xuwwc474uzlgja6a")
"claim"
Address("account_tdx_2_12xlu6x99ssrwrs8cnafka8476ursxfyfde3kfyk7d4s9c5kdvcs77x")
Address("resource_tdx_2_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxtfd2jc")
Decimal("30")
;
TAKE_FROM_WORKTOP
Address("resource_tdx_2_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxtfd2jc")
Decimal("30")
Bucket("bucket2")
;
CALL_METHOD
Address("account_tdx_2_12xlu6x99ssrwrs8cnafka8476ursxfyfde3kfyk7d4s9c5kdvcs77x")
"deposit"
Bucket("bucket2")
;
6 changes: 6 additions & 0 deletions crates/sargon/src/core/error/common_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,12 @@ pub enum CommonError {

#[error("No Profile is yet loaded. Current state is: {current_state}")]
ProfileStateNotLoaded { current_state: String } = 10180,

#[error("Failed to create Address from global_address (hex): {global_address_as_hex}, network_id: {network_id}")]
FailedToCreateAddressFromGlobalAddressAndNetworkID {
global_address_as_hex: String,
network_id: NetworkID,
} = 10181,
}

#[uniffi::export]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use crate::prelude::*;

address_union!(
/// A tagged union of all the encountered addresses in the manifest.
/// This is to be primarily used for the "using dApps" section of the wallet's tx review screen.
enum ManifestEncounteredAddress: component, locker
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about the enum name

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you ask Omar if there is any other address which belongs here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I didn't ask, but should we add other types even if we don't need them in the wallets right now? It will be quite easy to add a new address type when required.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not add other types for now, the logic in the Wallet to display the "used dApps" is explicitly for globalGenericComponents + account locker.

At some point, RET had a field called userApplications in summary, meant to point that these potentially have associated dApps. Maybe we can have the field in the execution summary more specific to potential dApps used, rather than generic ManifestEncounteredAddress, which presumably, by the name, should include all addresses

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GhenadieVP do you have an example? I agree, but I still can't think of a better name to reflect what you described, UserApplicationAddress doesn't sound better and it lacks context (as the keyword manifest offers).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it too generic? I mean that we are filtering the original addresses after all

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first, I thought that AddressReferencedInTX is more specific, but now that I think of it all of the addresses referenced in a manifest are referenced in the transaction so I guess you're right and it's better to put emphasis on the fact that the addresses are of components. I'll rename it to ManifestEncounteredComponentAddress.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but it is not component addresses. LockerAddress is not ComponentAddress right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's not a component address, but locker is a component, right? But I see what you're saying and that's why I didn't use component when naming it initially.

Copy link
Contributor Author

@sergiupuhalschi-rdx sergiupuhalschi-rdx Sep 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the component keyword expresses that it's not just encountered addresses, but addresses of components (not resources or other types of addresses there are). I'd leave it as is unless someone has other suggestions that reflect the fact that the addresses were filtered to match this criteria.

);

macro_rules! impl_try_from_for_manifest_encountered_address {
($($variant:ident => $address_type:ty),*) => {
impl TryFrom<(ScryptoGlobalAddress, NetworkID)> for ManifestEncounteredAddress {
type Error = CommonError;

fn try_from(value: (ScryptoGlobalAddress, NetworkID)) -> Result<Self> {
let (global_address, network_id) = value;

$(
if let Ok(address) = <$address_type>::try_from((global_address, network_id)) {
return Ok(ManifestEncounteredAddress::$variant(address));
}
)*

Err(CommonError::FailedToCreateAddressFromGlobalAddressAndNetworkID {
global_address_as_hex: global_address.to_hex(),
network_id,
})
}
}
};
}

impl_try_from_for_manifest_encountered_address!(
Component => ComponentAddress,
Locker => LockerAddress
);

#[cfg(test)]
mod tests {
use super::*;

#[allow(clippy::upper_case_acronyms)]
type SUT = ManifestEncounteredAddress;

#[test]
fn sample_values_count() {
let mut set = HashSet::<SUT>::new();
set.extend(SUT::sample_values_all());
// Duplicates should be removed
set.extend(SUT::sample_values_all());

assert_eq!(set.len(), 8);
}

#[test]
fn try_from_failure() {
let global_address = ScryptoGlobalAddress::new_or_panic(
ResourceAddress::sample_stokenet()
.scrypto()
.into_node_id()
.0,
);
let network_id = NetworkID::Stokenet;

let result = SUT::try_from((global_address, network_id));
assert_eq!(
result.unwrap_err(),
CommonError::FailedToCreateAddressFromGlobalAddressAndNetworkID {
global_address_as_hex: global_address.to_hex(),
network_id,
}
);
}

macro_rules! generate_try_from_tests {
($($variant:ident => $address_type:ty),*) => {
$(
#[test]
fn $variant() {
let global_address = ScryptoGlobalAddress::new_or_panic(
<$address_type>::sample_stokenet().scrypto().into_node_id().0
);
let network_id = NetworkID::Stokenet;

let result = SUT::try_from((global_address, network_id));
assert!(result.is_ok());
}
)*
};
}

generate_try_from_tests!(
component => ComponentAddress,
locker => LockerAddress
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod account_locker;
mod address_of_account_or_persona;
mod assets_transfers;
mod build_information;
mod manifest_encountered_address;
mod stake_claim;
mod stake_claim_uniffi_fn;
mod transaction_guarantee;
Expand All @@ -20,3 +21,4 @@ pub use stake_claim_uniffi_fn::*;
pub use transaction_guarantee::*;

pub use account_locker::*;
pub use manifest_encountered_address::*;
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ pub struct ExecutionSummary {
/// The list of the resources of proofs that were presented in the manifest.
pub presented_proofs: Vec<ResourceSpecifier>,

/// The set of all the encountered `ComponentAddress`es` in the manifest. This is
/// The set of all the encountered `ManifestEncounteredAddress`es` in the manifest. This is
/// to be primarily used for the "using dApps" section of the wallet's tx
/// review screen.
pub encountered_component_addresses: Vec<ComponentAddress>,
pub encountered_addresses: Vec<ManifestEncounteredAddress>,

/// Information on how much fees were contingent and how much were not.
pub fee_locks: FeeLocks,
Expand All @@ -71,7 +71,7 @@ impl ExecutionSummary {
newly_created_non_fungibles: impl IntoIterator<Item = NonFungibleGlobalId>,
reserved_instructions: impl IntoIterator<Item = ReservedInstruction>,
presented_proofs: impl IntoIterator<Item = ResourceSpecifier>,
encountered_component_addresses: impl IntoIterator<Item = ComponentAddress>,
encountered_addresses: impl IntoIterator<Item = ManifestEncounteredAddress>,
detailed_classification: impl IntoIterator<Item = DetailedManifestClass>,
fee_locks: impl Into<FeeLocks>,
fee_summary: impl Into<FeeSummary>,
Expand All @@ -95,7 +95,7 @@ impl ExecutionSummary {
.into_iter()
.collect_vec(),
presented_proofs: presented_proofs.into_iter().collect_vec(),
encountered_component_addresses: encountered_component_addresses
encountered_addresses: encountered_addresses
.into_iter()
.collect_vec(),
detailed_classification: detailed_classification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ mod tests {
["resource_tdx_2_1ng88qk08hrgmad30rzdxpyx779yuta4cwcjc3gstk60jhachsv94g9:<Member_44>".parse::<NonFungibleGlobalId>().unwrap()], // newly_created_non_fungibles
[], // reserved_instructions
[], // presented_proofs
["component_tdx_2_1czg6rq9vms7t402fedtpzkjah25hh7snyu3ysgxk3pwlz4d3tugm7j".parse::<ComponentAddress>().unwrap()], // encountered_component_addresses
["component_tdx_2_1czg6rq9vms7t402fedtpzkjah25hh7snyu3ysgxk3pwlz4d3tugm7j".parse::<ManifestEncounteredAddress>().unwrap()], // encountered_component_addresses
[
DetailedManifestClass::General
],
Expand Down Expand Up @@ -546,7 +546,7 @@ mod tests {
[], // newly_created_non_fungibles
[], // reserved_instructions
[ResourceSpecifier::non_fungible("resource_tdx_2_1ng88qk08hrgmad30rzdxpyx779yuta4cwcjc3gstk60jhachsv94g9", vec!["<Member_44>".parse().unwrap()])], // presented_proofs
["component_tdx_2_1crje3en7zsrna9t5vyywn3z3t9ht34l9udxjcpjvdhpcw9v6vlzru8".parse::<ComponentAddress>().unwrap()], // encountered_component_addresses
["component_tdx_2_1crje3en7zsrna9t5vyywn3z3t9ht34l9udxjcpjvdhpcw9v6vlzru8".parse::<ManifestEncounteredAddress>().unwrap()], // encountered_component_addresses
[
DetailedManifestClass::General
],
Expand Down Expand Up @@ -1089,4 +1089,71 @@ mod tests {
)
);
}

#[test]
fn account_locker_claim_fungibles_and_non_fungibles() {
let encoded_receipt_hex = include_str!(concat!(
env!("FIXTURES_TX"),
"account_locker_claim_fungibles_and_non_fungibles.dat"
));
let instructions_string = include_str!(concat!(
env!("FIXTURES_TX"),
"account_locker_claim_fungibles_and_non_fungibles.rtm"
));

let transaction_manifest = TransactionManifest::new(
instructions_string,
NetworkID::Stokenet,
Blobs::default(),
)
.unwrap();

let sut = transaction_manifest
.execution_summary(
BagOfBytes::from_hex(encoded_receipt_hex).unwrap(),
)
.unwrap();

let acc: AccountAddress = "account_tdx_2_12xlu6x99ssrwrs8cnafka8476ursxfyfde3kfyk7d4s9c5kdvcs77x".into();
let fungible_address: ResourceAddress = "resource_tdx_2_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxtfd2jc".into();
let non_fungible_address: ResourceAddress = "resource_tdx_2_1nflxr7dvp29hxhjjp53strsdgv2kv9dxlx6ys52lafrgyljrhwkt27".into();

pretty_assertions::assert_eq!(
sut,
SUT::new(
[],
[(
acc,
vec![
ResourceIndicator::non_fungible(
non_fungible_address,
NonFungibleResourceIndicator::by_amount(4, PredictedNonFungibleLocalIds::new(
[
NonFungibleLocalId::integer(3),
NonFungibleLocalId::integer(5),
NonFungibleLocalId::integer(4),
NonFungibleLocalId::integer(6)
],
1
))
),
ResourceIndicator::fungible(
fungible_address,
FungibleResourceIndicator::guaranteed(30)
),
]
)],
vec!["account_tdx_2_12xlu6x99ssrwrs8cnafka8476ursxfyfde3kfyk7d4s9c5kdvcs77x".into()], // addresses_of_accounts_requiring_auth
[], // addresses_of_identities_requiring_auth
[], // newly_created_non_fungibles
[], // reserved_instructions
[], // presented_proofs
["locker_tdx_2_1drgp40wpu5cj0zady4s0pec6rld8muge0j2xx9xuwwc474uzlgja6a".parse::<ManifestEncounteredAddress>().unwrap()],
[DetailedManifestClass::General],
FeeLocks::default(),
FeeSummary::new("0.2674585", "0.07226045", "0.19378661776", 0,),
NewEntities::default()
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -615,15 +615,15 @@ class TransactionManifestTest : SampleTestable<TransactionManifest> {
),
AccountLockerClaimableResource.NonFungible(
resourceAddress = ResourceAddress.init("resource_rdx1nfyg2f68jw7hfdlg5hzvd8ylsa7e0kjl68t5t62v3ttamtejc9wlxa"),
ids = listOf(NonFungibleLocalId.intId(1.toULong()))
numberOfItems = 10.toULong()
),
AccountLockerClaimableResource.Fungible(
resourceAddress = ResourceAddress.init("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"),
amount = 1500.toDecimal192()
),
AccountLockerClaimableResource.NonFungible(
resourceAddress = ResourceAddress.init("resource_rdx1n2ekdd2m0jsxjt9wasmu3p49twy2yfalpaa6wf08md46sk8dfmldnd"),
ids = listOf(NonFungibleLocalId.stringId("foobar"))
numberOfItems = 1.toULong()
)
)
)
Expand All @@ -632,7 +632,6 @@ class TransactionManifestTest : SampleTestable<TransactionManifest> {

with(actualManifest.instructionsString) {
assertTrue(contains("claim"))
assertTrue(contains("claim_non_fungibles"))
assertTrue(contains("account_rdx128y6j78mt0aqv6372evz28hrxp8mn06ccddkr7xppc88hyvynvjdwr"))
}

Expand Down
Loading