use crate::internal_prelude::*;
use radix_engine_interface::api::ModuleId;
use radix_engine_interface::blueprints::access_controller::*;
use radix_engine_interface::blueprints::account::*;
use radix_engine_interface::blueprints::consensus_manager::*;
use radix_engine_interface::blueprints::identity::*;
use radix_engine_interface::blueprints::package::*;
use radix_engine_interface::blueprints::resource::*;
use radix_engine_interface::object_modules::metadata::*;
use radix_engine_interface::object_modules::role_assignment::*;
use radix_engine_interface::object_modules::royalty::*;
use radix_engine_interface::object_modules::ModuleConfig;
pub struct ManifestBuilder<M: BuildableManifest = TransactionManifestV1> {
registrar: ManifestNameRegistrar,
manifest: M,
}
pub struct NewSymbols {
pub new_bucket: Option<ManifestBucket>,
pub new_proof: Option<ManifestProof>,
pub new_address_reservation: Option<ManifestAddressReservation>,
pub new_address_id: Option<ManifestNamedAddress>,
}
pub type TransactionManifestV1Builder = ManifestBuilder<TransactionManifestV1>;
pub type TransactionManifestV2Builder = ManifestBuilder<TransactionManifestV2>;
pub type SubintentManifestV2Builder = ManifestBuilder<SubintentManifestV2>;
pub type SystemManifestV1Builder = ManifestBuilder<SystemTransactionManifestV1>;
impl TransactionManifestV1Builder {
pub fn new() -> Self {
Self::new_typed()
}
pub fn new_v1() -> Self {
Self::new_typed()
}
}
impl TransactionManifestV2Builder {
pub fn new_v2() -> Self {
Self::new_typed()
}
}
impl SubintentManifestV2Builder {
pub fn new_subintent_v2() -> Self {
Self::new_typed()
}
}
impl SystemManifestV1Builder {
pub fn new_system_v1() -> Self {
Self::new_typed()
}
pub fn use_preallocated_address(
&mut self,
fixed_address: impl Into<GlobalAddress>,
package_address: impl Into<PackageAddress>,
blueprint_name: impl Into<String>,
) -> ManifestAddressReservation {
let existing_preallocation_count = self.manifest.preallocated_addresses.len();
let name = format!("preallocation_{existing_preallocation_count}");
let reservation = self.registrar.new_address_reservation(&name);
self.preallocate_address_internal(
reservation,
fixed_address,
package_address,
blueprint_name,
);
self.name_lookup().address_reservation(name)
}
}
impl<M: BuildableManifestSupportingPreallocatedAddresses> ManifestBuilder<M> {
pub fn preallocate_address(
mut self,
reservation: impl NewManifestAddressReservation,
fixed_address: impl Into<GlobalAddress>,
package_address: impl Into<PackageAddress>,
blueprint_name: impl Into<String>,
) -> Self {
self.preallocate_address_internal(
reservation,
fixed_address,
package_address,
blueprint_name,
);
self
}
pub fn preallocate_address_internal(
&mut self,
reservation: impl NewManifestAddressReservation,
fixed_address: impl Into<GlobalAddress>,
package_address: impl Into<PackageAddress>,
blueprint_name: impl Into<String>,
) {
if self
.registrar
.object_names()
.address_reservation_names
.len()
> self.manifest.preallocation_count()
{
panic!("You cannot call preallocate_address after you've allocated any addresses in the manifest");
}
self.manifest
.add_preallocated_address(PreAllocatedAddress {
blueprint_id: BlueprintId {
package_address: package_address.into(),
blueprint_name: blueprint_name.into(),
},
address: fixed_address.into(),
})
.expect("Expected manifest to support adding preallocated address");
reservation.register(&self.registrar);
}
}
impl<M: BuildableManifest> ManifestBuilder<M> {
pub fn new_typed() -> Self {
Self {
registrar: ManifestNameRegistrar::new(),
manifest: M::default(),
}
}
pub fn name_lookup(&self) -> ManifestNameLookup {
self.registrar.name_lookup()
}
pub fn then(self, next: impl FnOnce(Self) -> Self) -> Self {
next(self)
}
pub fn with_name_lookup(self, next: impl FnOnce(Self, ManifestNameLookup) -> Self) -> Self {
let lookup = self.name_lookup();
next(self, lookup)
}
pub fn with_bucket(
self,
bucket: impl LabelledResolve<ManifestBucket>,
next: impl FnOnce(Self, ManifestBucket) -> Self,
) -> Self {
let bucket = bucket.labelled_resolve(&self.registrar);
next(self, bucket)
}
pub fn bucket(&self, name: impl AsRef<str>) -> ManifestBucket {
self.name_lookup().bucket(name)
}
pub fn proof(&self, name: impl AsRef<str>) -> ManifestProof {
self.name_lookup().proof(name)
}
pub fn named_address(&self, name: impl AsRef<str>) -> ManifestNamedAddress {
self.name_lookup().named_address(name)
}
pub fn address(&self, name: impl AsRef<str>) -> ManifestAddress {
ManifestAddress::Named(self.named_address(name))
}
pub fn address_reservation(&self, name: impl AsRef<str>) -> ManifestAddressReservation {
self.name_lookup().address_reservation(name)
}
pub fn generate_bucket_name(&self, prefix: impl Into<String>) -> String {
self.registrar.new_collision_free_bucket_name(prefix)
}
pub fn generate_proof_name(&self, prefix: impl Into<String>) -> String {
self.registrar.new_collision_free_proof_name(prefix)
}
pub fn generate_address_reservation_name(&self, prefix: impl Into<String>) -> String {
self.registrar
.new_collision_free_address_reservation_name(prefix)
}
pub fn generate_address_name(&self, prefix: impl Into<String>) -> String {
self.registrar
.new_collision_free_address_reservation_name(prefix)
}
pub fn object_names(&self) -> KnownManifestObjectNames {
self.registrar.object_names()
}
pub fn add_blob(&mut self, blob_content: Vec<u8>) -> ManifestBlobRef {
let hash = hash(&blob_content);
self.manifest.add_blob(hash, blob_content);
ManifestBlobRef(hash.0)
}
fn add_instruction(mut self, instruction: impl Into<M::Instruction>) -> Self {
self.manifest.add_instruction(instruction.into());
self
}
#[cfg(test)]
pub fn add_raw_instruction_ignoring_all_side_effects(
self,
instruction: impl Into<M::Instruction>,
) -> Self {
self.add_instruction(instruction)
}
pub fn add_instruction_advanced(
self,
instruction: impl Into<M::Instruction>,
) -> (Self, NewSymbols) {
self.add_instruction_advanced_internal(instruction.into())
}
fn add_instruction_advanced_internal(self, instruction: M::Instruction) -> (Self, NewSymbols) {
let mut new_bucket = None;
let mut new_proof = None;
let mut new_address_reservation = None;
let mut new_address_id = None;
let registrar = &self.registrar;
let lookup = self.name_lookup();
match instruction.effect() {
ManifestInstructionEffect::CreateBucket { .. } => {
let bucket_name = registrar.new_collision_free_bucket_name("bucket");
registrar.register_bucket(registrar.new_bucket(&bucket_name));
new_bucket = Some(lookup.bucket(bucket_name));
}
ManifestInstructionEffect::CreateProof { .. }
| ManifestInstructionEffect::CloneProof { .. } => {
let proof_name = registrar.new_collision_free_proof_name("proof");
registrar.register_proof(registrar.new_proof(&proof_name));
new_proof = Some(lookup.proof(proof_name));
}
ManifestInstructionEffect::CreateAddressAndReservation { .. } => {
let reservation_name =
registrar.new_collision_free_address_reservation_name("reservation");
registrar.register_address_reservation(
registrar.new_address_reservation(&reservation_name),
);
let address_name = registrar.new_collision_free_address_name("address");
registrar.register_named_address(registrar.new_named_address(&address_name));
new_address_reservation = Some(lookup.address_reservation(reservation_name));
new_address_id = Some(lookup.named_address(address_name));
}
ManifestInstructionEffect::ConsumeBucket {
consumed_bucket: bucket,
..
} => {
registrar.consume_bucket(bucket);
}
ManifestInstructionEffect::ConsumeProof {
consumed_proof: proof,
..
} => {
registrar.consume_proof(proof);
}
ManifestInstructionEffect::DropManyProofs {
drop_all_named_proofs,
..
} => {
if drop_all_named_proofs {
registrar.consume_all_proofs()
}
}
ManifestInstructionEffect::Invocation { .. } => {}
ManifestInstructionEffect::ResourceAssertion { .. } => {}
ManifestInstructionEffect::Verification { .. } => {}
};
(
self.add_instruction(instruction),
NewSymbols {
new_bucket,
new_proof,
new_address_reservation,
new_address_id,
},
)
}
pub fn build(self) -> M {
let manifest = self.build_no_validate();
manifest
.validate(ValidationRuleset::all())
.expect("Manifest should be valid");
manifest
}
pub fn build_no_validate(mut self) -> M {
self.manifest.set_names(self.object_names());
#[cfg(feature = "dump_manifest_to_file")]
{
let bytes = manifest_encode(&self.manifest).unwrap();
let manifest_hash = hash(&bytes);
let path = format!("manifest_{:?}.raw", manifest_hash);
std::fs::write(&path, bytes).unwrap();
println!("manifest dumped to file {}", &path);
}
self.manifest
}
}
impl<M: BuildableManifest> ManifestBuilder<M>
where
M::Instruction: From<InstructionV1>,
{
fn add_v1_instruction(self, instruction: impl Into<InstructionV1>) -> Self {
self.add_instruction(instruction.into())
}
pub fn take_all_from_worktop(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
new_bucket: impl NewManifestBucket,
) -> Self {
let resource_address = resource_address.resolve_static();
new_bucket.register(&self.registrar);
self.add_v1_instruction(TakeAllFromWorktop { resource_address })
}
pub fn take_from_worktop(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
amount: impl Resolve<Decimal>,
new_bucket: impl NewManifestBucket,
) -> Self {
let resource_address = resource_address.resolve_static();
let amount = amount.resolve();
new_bucket.register(&self.registrar);
self.add_v1_instruction(TakeFromWorktop {
amount,
resource_address,
})
}
pub fn take_non_fungibles_from_worktop(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
ids: impl IntoIterator<Item = NonFungibleLocalId>,
new_bucket: impl NewManifestBucket,
) -> Self {
let resource_address = resource_address.resolve_static();
new_bucket.register(&self.registrar);
self.add_v1_instruction(TakeNonFungiblesFromWorktop {
ids: ids.into_iter().collect(),
resource_address,
})
}
pub fn return_to_worktop(self, bucket: impl ConsumedManifestBucket) -> Self {
let bucket = bucket.mark_consumed(&self.registrar);
self.add_v1_instruction(ReturnToWorktop { bucket_id: bucket })
}
pub fn assert_worktop_contains(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let resource_address = resource_address.resolve_static();
let amount = amount.resolve();
self.add_v1_instruction(AssertWorktopContains {
amount,
resource_address,
})
}
pub fn assert_worktop_contains_any(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
) -> Self {
let resource_address = resource_address.resolve_static();
self.add_v1_instruction(AssertWorktopContainsAny { resource_address })
}
pub fn assert_worktop_contains_non_fungibles(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
ids: impl IntoIterator<Item = NonFungibleLocalId>,
) -> Self {
let resource_address = resource_address.resolve_static();
self.add_v1_instruction(AssertWorktopContainsNonFungibles {
ids: ids.into_iter().collect(),
resource_address,
})
}
pub fn pop_from_auth_zone(self, new_proof: impl NewManifestProof) -> Self {
new_proof.register(&self.registrar);
self.add_v1_instruction(PopFromAuthZone)
}
pub fn push_to_auth_zone(self, proof: impl ConsumedManifestProof) -> Self {
let proof = proof.mark_consumed(&self.registrar);
self.add_v1_instruction(PushToAuthZone { proof_id: proof })
}
pub fn create_proof_from_auth_zone_of_amount(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
amount: impl Resolve<Decimal>,
new_proof: impl NewManifestProof,
) -> Self {
let resource_address = resource_address.resolve_static();
let amount = amount.resolve();
new_proof.register(&self.registrar);
self.add_v1_instruction(CreateProofFromAuthZoneOfAmount {
amount,
resource_address,
})
}
pub fn create_proof_from_auth_zone_of_non_fungibles(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
ids: impl IntoIterator<Item = NonFungibleLocalId>,
new_proof: impl NewManifestProof,
) -> Self {
let resource_address = resource_address.resolve_static();
new_proof.register(&self.registrar);
self.add_v1_instruction(CreateProofFromAuthZoneOfNonFungibles {
ids: ids.into_iter().collect(),
resource_address,
})
}
pub fn create_proof_from_auth_zone_of_all(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
new_proof: impl NewManifestProof,
) -> Self {
let resource_address = resource_address.resolve_static();
new_proof.register(&self.registrar);
self.add_v1_instruction(CreateProofFromAuthZoneOfAll { resource_address })
}
pub fn create_proof_from_bucket_of_amount(
self,
bucket: impl ReferencedManifestBucket,
amount: impl Resolve<Decimal>,
new_proof: impl NewManifestProof,
) -> Self {
let bucket = bucket.resolve_referenced(&self.registrar);
let amount = amount.resolve();
new_proof.register(&self.registrar);
self.add_v1_instruction(CreateProofFromBucketOfAmount {
bucket_id: bucket,
amount,
})
}
pub fn create_proof_from_bucket_of_non_fungibles(
self,
bucket: impl ReferencedManifestBucket,
ids: impl IntoIterator<Item = NonFungibleLocalId>,
new_proof: impl NewManifestProof,
) -> Self {
let bucket = bucket.resolve_referenced(&self.registrar);
new_proof.register(&self.registrar);
self.add_v1_instruction(CreateProofFromBucketOfNonFungibles {
bucket_id: bucket,
ids: ids.into_iter().collect(),
})
}
pub fn create_proof_from_bucket_of_all(
self,
bucket: impl ReferencedManifestBucket,
new_proof: impl NewManifestProof,
) -> Self {
let bucket = bucket.resolve_referenced(&self.registrar);
new_proof.register(&self.registrar);
self.add_v1_instruction(CreateProofFromBucketOfAll { bucket_id: bucket })
}
pub fn clone_proof(
self,
proof: impl ReferencedManifestProof,
new_proof: impl NewManifestProof,
) -> Self {
let proof = proof.resolve_referenced(&self.registrar);
new_proof.register(&self.registrar);
self.add_v1_instruction(CloneProof { proof_id: proof })
}
pub fn allocate_global_address(
self,
package_address: impl ResolvableStaticManifestPackageAddress,
blueprint_name: impl Into<String>,
new_address_reservation: impl NewManifestAddressReservation,
new_address_name: impl NewNamedManifestAddress,
) -> Self {
let package_address = package_address.resolve_static();
let blueprint_name = blueprint_name.into();
new_address_reservation.register(&self.registrar);
new_address_name.register(&self.registrar);
self.add_v1_instruction(AllocateGlobalAddress {
package_address,
blueprint_name,
})
}
pub fn drop_proof(self, proof: impl ConsumedManifestProof) -> Self {
let proof = proof.mark_consumed(&self.registrar);
self.add_v1_instruction(DropProof { proof_id: proof })
}
pub fn drop_all_proofs(self) -> Self {
self.registrar.consume_all_proofs();
self.add_v1_instruction(DropAllProofs)
}
pub fn drop_named_proofs(self) -> Self {
self.registrar.consume_all_proofs();
self.add_v1_instruction(DropNamedProofs)
}
pub fn drop_auth_zone_signature_proofs(self) -> Self {
self.add_v1_instruction(DropAuthZoneSignatureProofs)
}
pub fn drop_auth_zone_regular_proofs(self) -> Self {
self.add_v1_instruction(DropAuthZoneRegularProofs)
}
pub fn drop_auth_zone_proofs(self) -> Self {
self.add_v1_instruction(DropAuthZoneProofs)
}
pub fn create_fungible_resource(
self,
owner_role: OwnerRole,
track_total_supply: bool,
divisibility: u8,
resource_roles: FungibleResourceRoles,
metadata: ModuleConfig<MetadataInit>,
initial_supply: Option<Decimal>,
) -> Self {
let instruction = if let Some(initial_supply) = initial_supply {
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: owner_role.into(),
divisibility,
track_total_supply,
metadata: metadata.into(),
resource_roles: resource_roles.into(),
initial_supply,
address_reservation: None,
}
),
}
} else {
CallFunction {
package_address: RESOURCE_PACKAGE.into(),
blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&FungibleResourceManagerCreateManifestInput {
owner_role: owner_role.into(),
divisibility,
track_total_supply,
metadata: metadata.into(),
resource_roles: resource_roles.into(),
address_reservation: None,
}),
}
};
self.add_v1_instruction(instruction)
}
pub fn create_non_fungible_resource<T, V>(
self,
owner_role: OwnerRole,
id_type: NonFungibleIdType,
track_total_supply: bool,
resource_roles: NonFungibleResourceRoles,
metadata: ModuleConfig<MetadataInit>,
initial_supply: Option<T>,
) -> Self
where
T: IntoIterator<Item = (NonFungibleLocalId, V)>,
V: ManifestEncode + NonFungibleData,
{
let instruction = if let Some(initial_supply) = initial_supply {
let entries = initial_supply
.into_iter()
.map(|(id, e)| (id, (to_manifest_value_and_unwrap!(&e),)))
.collect();
CallFunction {
package_address: RESOURCE_PACKAGE.into(),
blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
.to_string(),
args: to_manifest_value_and_unwrap!(
&NonFungibleResourceManagerCreateWithInitialSupplyManifestInput {
owner_role: owner_role.into(),
id_type,
track_total_supply,
non_fungible_schema:
NonFungibleDataSchema::new_local_without_self_package_replacement::<V>(),
entries,
resource_roles: resource_roles.into(),
metadata: metadata.into(),
address_reservation: None,
}
),
}
} else {
CallFunction {
package_address: RESOURCE_PACKAGE.into(),
blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(
&NonFungibleResourceManagerCreateManifestInput {
owner_role: owner_role.into(),
id_type,
track_total_supply,
non_fungible_schema:
NonFungibleDataSchema::new_local_without_self_package_replacement::<V>(),
resource_roles: resource_roles.into(),
metadata: metadata.into(),
address_reservation: None,
}
),
}
};
self.add_v1_instruction(instruction)
}
pub fn create_ruid_non_fungible_resource<T, V>(
self,
owner_role: OwnerRole,
track_total_supply: bool,
metadata: ModuleConfig<MetadataInit>,
resource_roles: NonFungibleResourceRoles,
initial_supply: Option<T>,
) -> Self
where
T: IntoIterator<Item = V>,
V: ManifestEncode + NonFungibleData,
{
let instruction = if let Some(initial_supply) = initial_supply {
let entries = initial_supply
.into_iter()
.map(|e| (to_manifest_value_and_unwrap!(&e),))
.collect();
CallFunction {
package_address: RESOURCE_PACKAGE.into(),
blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_RUID_WITH_INITIAL_SUPPLY_IDENT
.to_string(),
args: to_manifest_value_and_unwrap!(
&NonFungibleResourceManagerCreateRuidWithInitialSupplyManifestInput {
owner_role: owner_role.into(),
track_total_supply,
non_fungible_schema:
NonFungibleDataSchema::new_local_without_self_package_replacement::<V>(),
resource_roles: resource_roles.into(),
metadata: metadata.into(),
entries,
address_reservation: None,
}
),
}
} else {
CallFunction {
package_address: RESOURCE_PACKAGE.into(),
blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_RUID_WITH_INITIAL_SUPPLY_IDENT
.to_string(),
args: to_manifest_value_and_unwrap!(
&NonFungibleResourceManagerCreateRuidWithInitialSupplyManifestInput {
owner_role: owner_role.into(),
track_total_supply,
non_fungible_schema:
NonFungibleDataSchema::new_local_without_self_package_replacement::<V>(),
resource_roles: resource_roles.into(),
metadata: metadata.into(),
entries: vec![],
address_reservation: None,
}
),
}
};
self.add_v1_instruction(instruction)
}
pub fn update_non_fungible_data(
self,
resource_address: impl ReferencedManifestResourceAddress,
id: NonFungibleLocalId,
field_name: impl Into<String>,
data: impl ManifestEncode,
) -> Self {
let address = resource_address.resolve_referenced(&self.registrar);
let data = manifest_decode(&manifest_encode(&data).unwrap()).unwrap();
self.call_method(
address,
NON_FUNGIBLE_RESOURCE_MANAGER_UPDATE_DATA_IDENT,
NonFungibleResourceManagerUpdateDataManifestInput {
id,
field_name: field_name.into(),
data,
},
)
}
pub fn create_identity_advanced(self, owner_role: OwnerRole) -> Self {
self.add_v1_instruction(CallFunction {
package_address: IDENTITY_PACKAGE.into(),
blueprint_name: IDENTITY_BLUEPRINT.to_string(),
function_name: IDENTITY_CREATE_ADVANCED_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&IdentityCreateAdvancedManifestInput {
owner_role: owner_role.into()
}),
})
}
pub fn create_identity(self) -> Self {
self.add_v1_instruction(CallFunction {
package_address: IDENTITY_PACKAGE.into(),
blueprint_name: IDENTITY_BLUEPRINT.to_string(),
function_name: IDENTITY_CREATE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&IdentityCreateInput {}),
})
}
pub fn create_validator(
self,
key: Secp256k1PublicKey,
fee_factor: impl Resolve<Decimal>,
xrd_payment: impl ConsumedManifestBucket,
) -> Self {
let fee_factor = fee_factor.resolve();
let xrd_payment = xrd_payment.mark_consumed(&self.registrar);
self.call_method(
CONSENSUS_MANAGER,
CONSENSUS_MANAGER_CREATE_VALIDATOR_IDENT,
(key, fee_factor, xrd_payment),
)
}
pub fn register_validator(
self,
validator_address: impl ReferencedManifestComponentAddress,
) -> Self {
let address = validator_address.resolve_referenced(&self.registrar);
self.call_method(address, VALIDATOR_REGISTER_IDENT, ())
}
pub fn unregister_validator(
self,
validator_address: impl ReferencedManifestComponentAddress,
) -> Self {
let address = validator_address.resolve_referenced(&self.registrar);
self.call_method(address, VALIDATOR_UNREGISTER_IDENT, ())
}
pub fn signal_protocol_update_readiness(
self,
validator_address: impl ReferencedManifestComponentAddress,
protocol_version_name: &str,
) -> Self {
let address = validator_address.resolve_referenced(&self.registrar);
self.call_method(
address,
VALIDATOR_SIGNAL_PROTOCOL_UPDATE_READINESS_IDENT,
(protocol_version_name.to_string(),),
)
}
pub fn stake_validator_as_owner(
self,
validator_address: impl ReferencedManifestComponentAddress,
bucket: impl ConsumedManifestBucket,
) -> Self {
let address = validator_address.resolve_referenced(&self.registrar);
let bucket: ManifestBucket = bucket.mark_consumed(&self.registrar);
self.call_method(address, VALIDATOR_STAKE_AS_OWNER_IDENT, (bucket,))
}
pub fn stake_validator(
self,
validator_address: impl ReferencedManifestComponentAddress,
bucket: impl ConsumedManifestBucket,
) -> Self {
let address = validator_address.resolve_referenced(&self.registrar);
let bucket = bucket.mark_consumed(&self.registrar);
self.call_method(address, VALIDATOR_STAKE_IDENT, (bucket,))
}
pub fn unstake_validator(
self,
validator_address: impl ReferencedManifestComponentAddress,
bucket: impl ConsumedManifestBucket,
) -> Self {
let address = validator_address.resolve_referenced(&self.registrar);
let bucket = bucket.mark_consumed(&self.registrar);
self.call_method(address, VALIDATOR_UNSTAKE_IDENT, (bucket,))
}
pub fn claim_xrd(
self,
validator_address: impl ReferencedManifestComponentAddress,
bucket: impl ConsumedManifestBucket,
) -> Self {
let address = validator_address.resolve_referenced(&self.registrar);
let bucket = bucket.mark_consumed(&self.registrar);
self.call_method(address, VALIDATOR_CLAIM_XRD_IDENT, (bucket,))
}
pub fn call_function(
self,
package_address: impl ReferencedManifestPackageAddress,
blueprint_name: impl Into<String>,
function_name: impl Into<String>,
arguments: impl ResolvableArguments,
) -> Self {
let package_address = package_address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallFunction {
package_address,
blueprint_name: blueprint_name.into(),
function_name: function_name.into(),
args: arguments.resolve(),
})
}
pub fn call_function_raw(
self,
package_address: impl ReferencedManifestPackageAddress,
blueprint_name: impl Into<String>,
function_name: impl Into<String>,
arguments: ManifestValue,
) -> Self {
let package_address = package_address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallFunction {
package_address,
blueprint_name: blueprint_name.into(),
function_name: function_name.into(),
args: arguments,
})
}
pub fn call_function_with_name_lookup<T: ResolvableArguments>(
self,
package_address: impl ReferencedManifestPackageAddress,
blueprint_name: impl Into<String>,
function_name: impl Into<String>,
arguments_creator: impl FnOnce(&ManifestNameLookup) -> T,
) -> Self {
let package_address = package_address.resolve_referenced(&self.registrar);
let args = arguments_creator(&self.name_lookup()).resolve();
self.add_v1_instruction(CallFunction {
package_address,
blueprint_name: blueprint_name.into(),
function_name: function_name.into(),
args,
})
}
pub fn call_method(
self,
address: impl ReferencedManifestGlobalAddress,
method_name: impl Into<String>,
arguments: impl ResolvableArguments,
) -> Self {
self.call_module_method(address, ModuleId::Main, method_name, arguments)
}
pub fn call_metadata_method(
self,
address: impl ReferencedManifestGlobalAddress,
method_name: impl Into<String>,
arguments: impl ResolvableArguments,
) -> Self {
self.call_module_method(address, ModuleId::Metadata, method_name, arguments)
}
pub fn call_royalty_method(
self,
address: impl ReferencedManifestGlobalAddress,
method_name: impl Into<String>,
arguments: impl ResolvableArguments,
) -> Self {
self.call_module_method(address, ModuleId::Royalty, method_name, arguments)
}
pub fn call_direct_access_method(
self,
address: InternalAddress,
method_name: impl Into<String>,
arguments: impl ResolvableArguments,
) -> Self {
self.add_v1_instruction(CallDirectVaultMethod {
address,
method_name: method_name.into(),
args: arguments.resolve(),
})
}
pub fn set_owner_role(
self,
address: impl ReferencedManifestGlobalAddress,
rule: impl Into<AccessRule>,
) -> Self {
self.call_module_method(
address,
ModuleId::RoleAssignment,
ROLE_ASSIGNMENT_SET_OWNER_IDENT,
RoleAssignmentSetOwnerManifestInput {
rule: rule.into().into(),
},
)
}
pub fn lock_owner_role(self, address: impl ReferencedManifestGlobalAddress) -> Self {
self.call_module_method(
address,
ModuleId::RoleAssignment,
ROLE_ASSIGNMENT_LOCK_OWNER_IDENT,
RoleAssignmentLockOwnerInput {},
)
}
pub fn set_main_role(
self,
address: impl ReferencedManifestGlobalAddress,
role_key: impl Into<RoleKey>,
rule: impl Into<AccessRule>,
) -> Self {
self.set_role(address, ModuleId::Main, role_key, rule)
}
pub fn set_role(
self,
address: impl ReferencedManifestGlobalAddress,
role_module: ModuleId,
role_key: impl Into<RoleKey>,
rule: impl Into<AccessRule>,
) -> Self {
self.call_module_method(
address,
ModuleId::RoleAssignment,
ROLE_ASSIGNMENT_SET_IDENT,
RoleAssignmentSetManifestInput {
module: role_module,
role_key: role_key.into(),
rule: rule.into().into(),
},
)
}
pub fn get_role(
self,
address: impl ReferencedManifestGlobalAddress,
role_module: ModuleId,
role_key: RoleKey,
) -> Self {
self.call_module_method(
address,
ModuleId::RoleAssignment,
ROLE_ASSIGNMENT_GET_IDENT,
RoleAssignmentGetInput {
module: role_module,
role_key,
},
)
}
pub fn call_role_assignment_method(
self,
address: impl ReferencedManifestGlobalAddress,
method_name: impl Into<String>,
arguments: impl ResolvableArguments,
) -> Self {
self.call_module_method(address, ModuleId::RoleAssignment, method_name, arguments)
}
pub fn call_module_method(
self,
address: impl ReferencedManifestGlobalAddress,
module_id: ModuleId,
method_name: impl Into<String>,
arguments: impl ResolvableArguments,
) -> Self {
let address = address.resolve_referenced(&self.registrar);
match module_id {
ModuleId::Main => self.add_v1_instruction(CallMethod {
address,
method_name: method_name.into(),
args: arguments.resolve(),
}),
ModuleId::Metadata => self.add_v1_instruction(CallMetadataMethod {
address,
method_name: method_name.into(),
args: arguments.resolve(),
}),
ModuleId::Royalty => self.add_v1_instruction(CallRoyaltyMethod {
address,
method_name: method_name.into(),
args: arguments.resolve(),
}),
ModuleId::RoleAssignment => self.add_v1_instruction(CallRoleAssignmentMethod {
address,
method_name: method_name.into(),
args: arguments.resolve(),
}),
}
}
pub fn call_method_raw(
self,
address: impl ReferencedManifestGlobalAddress,
method_name: impl Into<String>,
arguments: ManifestValue,
) -> Self {
let address = address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallMethod {
address,
method_name: method_name.into(),
args: arguments,
})
}
pub fn call_method_with_name_lookup<T: ResolvableArguments>(
self,
address: impl ReferencedManifestGlobalAddress,
method_name: impl Into<String>,
arguments_creator: impl FnOnce(&ManifestNameLookup) -> T,
) -> Self {
let address = address.resolve_referenced(&self.registrar);
let args = arguments_creator(&self.name_lookup()).resolve();
self.add_v1_instruction(CallMethod {
address,
method_name: method_name.into(),
args,
})
}
pub fn claim_package_royalties(
self,
package_address: impl ReferencedManifestPackageAddress,
) -> Self {
let address = package_address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: PACKAGE_CLAIM_ROYALTIES_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&PackageClaimRoyaltiesInput {}),
})
}
pub fn set_component_royalty(
self,
component_address: impl ReferencedManifestComponentAddress,
method: impl Into<String>,
amount: RoyaltyAmount,
) -> Self {
let address = component_address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallRoyaltyMethod {
address: address.into(),
method_name: COMPONENT_ROYALTY_SET_ROYALTY_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&ComponentRoyaltySetInput {
method: method.into(),
amount,
}),
})
}
pub fn lock_component_royalty(
self,
component_address: impl ReferencedManifestComponentAddress,
method: impl Into<String>,
) -> Self {
let address = component_address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallRoyaltyMethod {
address: address.into(),
method_name: COMPONENT_ROYALTY_LOCK_ROYALTY_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&ComponentRoyaltyLockInput {
method: method.into(),
}),
})
}
pub fn claim_component_royalties(
self,
component_address: impl ReferencedManifestComponentAddress,
) -> Self {
let address = component_address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallRoyaltyMethod {
address: address.into(),
method_name: COMPONENT_ROYALTY_CLAIM_ROYALTIES_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&ComponentClaimRoyaltiesInput {}),
})
}
pub fn set_metadata(
self,
address: impl ReferencedManifestGlobalAddress,
key: impl Into<String>,
value: impl ToMetadataEntry,
) -> Self {
let address = address.resolve_referenced(&self.registrar);
match value.to_metadata_entry() {
Some(value) => self.add_v1_instruction(CallMetadataMethod {
address,
method_name: METADATA_SET_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&MetadataSetInput {
key: key.into(),
value
}),
}),
None => self.add_v1_instruction(CallMetadataMethod {
address,
method_name: METADATA_REMOVE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&MetadataRemoveInput { key: key.into() }),
}),
}
}
pub fn lock_metadata(
self,
address: impl ReferencedManifestGlobalAddress,
key: impl Into<String>,
) -> Self {
let address = address.resolve_referenced(&self.registrar);
let key = key.into();
self.add_v1_instruction(CallMetadataMethod {
address,
method_name: METADATA_LOCK_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&MetadataLockInput { key }),
})
}
pub fn freeze_metadata(
self,
address: impl ReferencedManifestGlobalAddress,
key: impl Into<String>,
) -> Self {
let address = address.resolve_referenced(&self.registrar);
self.add_v1_instruction(CallMetadataMethod {
address,
method_name: METADATA_LOCK_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&MetadataLockInput { key: key.into() }),
})
}
pub fn publish_package_advanced(
mut self,
address_reservation: impl ConsumedOptionalManifestAddressReservation,
code: Vec<u8>,
definition: PackageDefinition,
metadata: impl Into<ManifestMetadataInit>,
owner_role: OwnerRole,
) -> Self {
let address_reservation = address_reservation.mark_consumed(&self.registrar);
let code_blob_ref = self.add_blob(code);
self.add_v1_instruction(CallFunction {
package_address: PACKAGE_PACKAGE.into(),
blueprint_name: PACKAGE_BLUEPRINT.to_string(),
function_name: PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&PackagePublishWasmAdvancedManifestInput {
code: code_blob_ref,
definition: definition.into(),
metadata: metadata.into(),
package_address: address_reservation,
owner_role: owner_role.into(),
}),
})
}
pub fn publish_package(mut self, code: Vec<u8>, definition: PackageDefinition) -> Self {
let code_blob_ref = self.add_blob(code);
self.add_v1_instruction(CallFunction {
package_address: PACKAGE_PACKAGE.into(),
blueprint_name: PACKAGE_BLUEPRINT.to_string(),
function_name: PACKAGE_PUBLISH_WASM_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&PackagePublishWasmManifestInput {
code: code_blob_ref,
definition: definition.into(),
metadata: metadata_init!().into(),
}),
})
}
pub fn publish_package_with_owner(
mut self,
code: Vec<u8>,
definition: PackageDefinition,
owner_badge: NonFungibleGlobalId,
) -> Self {
let code_blob_ref = self.add_blob(code);
self.add_v1_instruction(CallFunction {
package_address: PACKAGE_PACKAGE.into(),
blueprint_name: PACKAGE_BLUEPRINT.to_string(),
function_name: PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&PackagePublishWasmAdvancedManifestInput {
package_address: None,
code: code_blob_ref,
definition: definition.into(),
metadata: metadata_init!().into(),
owner_role: OwnerRole::Fixed(rule!(require(owner_badge))).into(),
}),
})
}
pub fn new_token_mutable(
self,
metadata: ModuleConfig<MetadataInit>,
owner_role: AccessRule,
) -> Self {
self.create_fungible_resource(
OwnerRole::Fixed(owner_role),
true,
18,
FungibleResourceRoles {
mint_roles: mint_roles! {
minter => OWNER;
minter_updater => OWNER;
},
burn_roles: burn_roles! {
burner => OWNER;
burner_updater => OWNER;
},
..Default::default()
},
metadata,
None,
)
}
pub fn new_token_fixed(
self,
owner_role: OwnerRole,
metadata: ModuleConfig<MetadataInit>,
initial_supply: impl Resolve<Decimal>,
) -> Self {
let initial_supply = initial_supply.resolve();
self.create_fungible_resource(
owner_role,
true,
18,
FungibleResourceRoles::default(),
metadata,
Some(initial_supply),
)
}
pub fn new_badge_mutable(
self,
metadata: ModuleConfig<MetadataInit>,
owner_role: AccessRule,
) -> Self {
self.create_fungible_resource(
OwnerRole::Fixed(owner_role),
false,
0,
FungibleResourceRoles {
mint_roles: mint_roles! {
minter => OWNER;
minter_updater => OWNER;
},
burn_roles: burn_roles! {
burner => OWNER;
burner_updater => OWNER;
},
..Default::default()
},
metadata,
None,
)
}
pub fn new_badge_fixed(
self,
owner_role: OwnerRole,
metadata: ModuleConfig<MetadataInit>,
initial_supply: impl Resolve<Decimal>,
) -> Self {
let initial_supply = initial_supply.resolve();
self.create_fungible_resource(
owner_role,
false,
0,
FungibleResourceRoles::default(),
metadata,
Some(initial_supply),
)
}
pub fn burn_resource(self, bucket: impl ConsumedManifestBucket) -> Self {
let bucket = bucket.mark_consumed(&self.registrar);
self.add_v1_instruction(BurnResource { bucket_id: bucket })
}
pub fn burn_from_worktop(
self,
amount: impl Resolve<Decimal>,
resource_address: impl ResolvableStaticManifestResourceAddress,
) -> Self {
let amount = amount.resolve();
let resource_address = resource_address.resolve_static();
let bucket = self.generate_bucket_name("to_burn");
self.take_from_worktop(resource_address, amount, &bucket)
.burn_resource(bucket)
}
pub fn burn_all_from_worktop(
self,
resource_address: impl ResolvableStaticManifestResourceAddress,
) -> Self {
let resource_address = resource_address.resolve_static();
let bucket = self.generate_bucket_name("to_burn");
self.take_all_from_worktop(resource_address, &bucket)
.burn_resource(bucket)
}
pub fn burn_non_fungible_from_worktop(
self,
non_fungible_global_id: NonFungibleGlobalId,
) -> Self {
let (resource_address, local_id) = non_fungible_global_id.into_parts();
let bucket = self.generate_bucket_name("to_burn");
self.take_non_fungibles_from_worktop(resource_address, [local_id], &bucket)
.burn_resource(bucket)
}
pub fn mint_fungible(
self,
resource_address: impl ReferencedManifestResourceAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let address = resource_address.resolve_referenced(&self.registrar);
let amount = amount.resolve();
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&FungibleResourceManagerMintInput { amount }),
})
}
pub fn mint_non_fungible<T: IntoIterator<Item = (NonFungibleLocalId, V)>, V: ManifestEncode>(
self,
resource_address: impl ReferencedManifestResourceAddress,
entries: T,
) -> Self {
let address = resource_address.resolve_referenced(&self.registrar);
let entries = entries
.into_iter()
.map(|(id, e)| (id, (to_manifest_value_and_unwrap!(&e),)))
.collect();
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&NonFungibleResourceManagerMintManifestInput {
entries
}),
})
}
pub fn mint_ruid_non_fungible<T: IntoIterator<Item = V>, V: ManifestEncode>(
self,
resource_address: impl ReferencedManifestResourceAddress,
entries: T,
) -> Self {
let address = resource_address.resolve_referenced(&self.registrar);
let entries = entries
.into_iter()
.map(|e| (to_manifest_value_and_unwrap!(&e),))
.collect();
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_RUID_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&NonFungibleResourceManagerMintRuidManifestInput {
entries
}),
})
}
pub fn recall(self, vault_address: InternalAddress, amount: impl Resolve<Decimal>) -> Self {
let amount = amount.resolve();
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_address,
method_name: VAULT_RECALL_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&VaultRecallInput { amount }),
})
}
pub fn recall_non_fungibles(
self,
vault_address: InternalAddress,
non_fungible_local_ids: impl IntoIterator<Item = NonFungibleLocalId>,
) -> Self {
let args = to_manifest_value_and_unwrap!(&NonFungibleVaultRecallNonFungiblesInput {
non_fungible_local_ids: non_fungible_local_ids.into_iter().collect(),
});
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_address,
method_name: NON_FUNGIBLE_VAULT_RECALL_NON_FUNGIBLES_IDENT.to_string(),
args,
})
}
pub fn freeze_withdraw(self, vault_id: InternalAddress) -> Self {
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_id,
method_name: VAULT_FREEZE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&VaultFreezeInput {
to_freeze: VaultFreezeFlags::WITHDRAW,
}),
})
}
pub fn unfreeze_withdraw(self, vault_id: InternalAddress) -> Self {
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_id,
method_name: VAULT_UNFREEZE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&VaultUnfreezeInput {
to_unfreeze: VaultFreezeFlags::WITHDRAW,
}),
})
}
pub fn freeze_deposit(self, vault_id: InternalAddress) -> Self {
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_id,
method_name: VAULT_FREEZE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&VaultFreezeInput {
to_freeze: VaultFreezeFlags::DEPOSIT,
}),
})
}
pub fn unfreeze_deposit(self, vault_id: InternalAddress) -> Self {
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_id,
method_name: VAULT_UNFREEZE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&VaultUnfreezeInput {
to_unfreeze: VaultFreezeFlags::DEPOSIT,
}),
})
}
pub fn freeze_burn(self, vault_id: InternalAddress) -> Self {
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_id,
method_name: VAULT_FREEZE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&VaultFreezeInput {
to_freeze: VaultFreezeFlags::BURN,
}),
})
}
pub fn unfreeze_burn(self, vault_id: InternalAddress) -> Self {
self.add_v1_instruction(CallDirectVaultMethod {
address: vault_id,
method_name: VAULT_UNFREEZE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&VaultUnfreezeInput {
to_unfreeze: VaultFreezeFlags::BURN,
}),
})
}
pub fn new_account_advanced(
self,
owner_role: OwnerRole,
address_reservation: impl ConsumedOptionalManifestAddressReservation,
) -> Self {
let address_reservation = address_reservation.mark_consumed(&self.registrar);
self.add_v1_instruction(CallFunction {
package_address: ACCOUNT_PACKAGE.into(),
blueprint_name: ACCOUNT_BLUEPRINT.to_string(),
function_name: ACCOUNT_CREATE_ADVANCED_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&AccountCreateAdvancedManifestInput {
owner_role: owner_role.into(),
address_reservation
}),
})
}
pub fn new_account(self) -> Self {
self.add_v1_instruction(CallFunction {
package_address: ACCOUNT_PACKAGE.into(),
blueprint_name: ACCOUNT_BLUEPRINT.to_string(),
function_name: ACCOUNT_CREATE_IDENT.to_string(),
args: to_manifest_value_and_unwrap!(&AccountCreateInput {}),
})
}
pub fn lock_fee_and_withdraw(
self,
account_address: impl ReferencedManifestComponentAddress,
amount_to_lock: impl Resolve<Decimal>,
resource_address: impl ResolvableStaticManifestResourceAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let amount_to_lock = amount_to_lock.resolve();
let resource_address = resource_address.resolve_static();
let amount = amount.resolve();
let args = to_manifest_value_and_unwrap!(&AccountLockFeeAndWithdrawInput {
resource_address,
amount,
amount_to_lock,
});
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_LOCK_FEE_AND_WITHDRAW_IDENT.to_string(),
args,
})
}
pub fn lock_fee_and_withdraw_non_fungibles(
self,
account_address: impl ReferencedManifestComponentAddress,
amount_to_lock: impl Resolve<Decimal>,
resource_address: impl ResolvableStaticManifestResourceAddress,
ids: impl IntoIterator<Item = NonFungibleLocalId>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let amount_to_lock = amount_to_lock.resolve();
let resource_address = resource_address.resolve_static();
let args = to_manifest_value_and_unwrap!(&AccountLockFeeAndWithdrawNonFungiblesInput {
amount_to_lock,
resource_address,
ids: ids.into_iter().collect(),
});
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_LOCK_FEE_AND_WITHDRAW_NON_FUNGIBLES_IDENT.to_string(),
args,
})
}
pub fn lock_fee_from_faucet(self) -> Self {
self.lock_standard_test_fee(FAUCET)
}
pub fn lock_standard_test_fee(
self,
account_address: impl ReferencedManifestComponentAddress,
) -> Self {
self.lock_fee(account_address, 5000)
}
pub fn lock_fee(
self,
account_address: impl ReferencedManifestComponentAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let amount = amount.resolve();
let args = to_manifest_value_and_unwrap!(&AccountLockFeeInput { amount });
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_LOCK_FEE_IDENT.to_string(),
args,
})
}
pub fn lock_contingent_fee(
self,
account_address: impl ReferencedManifestComponentAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let amount = amount.resolve();
let args = to_manifest_value_and_unwrap!(&AccountLockContingentFeeInput { amount });
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_LOCK_CONTINGENT_FEE_IDENT.to_string(),
args,
})
}
pub fn get_free_xrd_from_faucet(self) -> Self {
self.call_method(FAUCET, "free", ())
}
pub fn withdraw_from_account(
self,
account_address: impl ReferencedManifestComponentAddress,
resource_address: impl ResolvableStaticManifestResourceAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let resource_address = resource_address.resolve_static();
let amount = amount.resolve();
let args = to_manifest_value_and_unwrap!(&AccountWithdrawInput {
resource_address,
amount,
});
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_WITHDRAW_IDENT.to_string(),
args,
})
}
pub fn withdraw_non_fungible_from_account(
self,
account_address: impl ReferencedManifestComponentAddress,
non_fungible_global_id: NonFungibleGlobalId,
) -> Self {
let (resource_address, local_id) = non_fungible_global_id.into_parts();
self.withdraw_non_fungibles_from_account(account_address, resource_address, [local_id])
}
pub fn withdraw_non_fungibles_from_account(
self,
account_address: impl ReferencedManifestComponentAddress,
resource_address: impl ResolvableStaticManifestResourceAddress,
ids: impl IntoIterator<Item = NonFungibleLocalId>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let resource_address = resource_address.resolve_static();
let args = to_manifest_value_and_unwrap!(&AccountWithdrawNonFungiblesInput {
ids: ids.into_iter().collect(),
resource_address,
});
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_WITHDRAW_NON_FUNGIBLES_IDENT.to_string(),
args,
})
}
pub fn burn_in_account(
self,
account_address: impl ReferencedManifestComponentAddress,
resource_address: impl ResolvableStaticManifestResourceAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let resource_address = resource_address.resolve_static();
let amount = amount.resolve();
let args = to_manifest_value_and_unwrap!(&AccountBurnInput {
resource_address,
amount
});
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_BURN_IDENT.to_string(),
args,
})
}
pub fn burn_non_fungible_in_account(
self,
account_address: impl ReferencedManifestComponentAddress,
non_fungible_global_id: NonFungibleGlobalId,
) -> Self {
let (resource_address, local_id) = non_fungible_global_id.into_parts();
self.burn_non_fungibles_in_account(account_address, resource_address, [local_id])
}
pub fn burn_non_fungibles_in_account(
self,
account_address: impl ReferencedManifestComponentAddress,
resource_address: impl ResolvableStaticManifestResourceAddress,
local_ids: impl IntoIterator<Item = NonFungibleLocalId>,
) -> Self {
let account_address = account_address.resolve_referenced(&self.registrar);
let resource_address = resource_address.resolve_static();
self.call_method(
account_address,
ACCOUNT_BURN_NON_FUNGIBLES_IDENT,
AccountBurnNonFungiblesInput {
resource_address,
ids: local_ids.into_iter().collect(),
},
)
}
pub fn create_proof_from_account_of_amount(
self,
account_address: impl ReferencedManifestComponentAddress,
resource_address: impl ResolvableStaticManifestResourceAddress,
amount: impl Resolve<Decimal>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let resource_address = resource_address.resolve_static();
let amount = amount.resolve();
let args = to_manifest_value_and_unwrap!(&AccountCreateProofOfAmountInput {
resource_address,
amount,
});
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_CREATE_PROOF_OF_AMOUNT_IDENT.to_string(),
args,
})
}
pub fn create_proof_from_account_of_non_fungible(
self,
account_address: impl ReferencedManifestComponentAddress,
non_fungible_global_id: NonFungibleGlobalId,
) -> Self {
let (resource_address, local_id) = non_fungible_global_id.into_parts();
self.create_proof_from_account_of_non_fungibles(
account_address,
resource_address,
[local_id],
)
}
pub fn create_proof_from_account_of_non_fungibles(
self,
account_address: impl ReferencedManifestComponentAddress,
resource_address: impl ResolvableStaticManifestResourceAddress,
local_ids: impl IntoIterator<Item = NonFungibleLocalId>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let resource_address = resource_address.resolve_static();
let args = to_manifest_value_and_unwrap!(&AccountCreateProofOfNonFungiblesInput {
resource_address,
ids: local_ids.into_iter().collect(),
});
self.add_v1_instruction(CallMethod {
address: address.into(),
method_name: ACCOUNT_CREATE_PROOF_OF_NON_FUNGIBLES_IDENT.to_string(),
args,
})
}
pub fn deposit(
self,
account_address: impl ReferencedManifestComponentAddress,
bucket: impl ConsumedManifestBucket,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let bucket = bucket.mark_consumed(&self.registrar);
self.call_method(address, ACCOUNT_DEPOSIT_IDENT, manifest_args!(bucket))
}
pub fn deposit_batch(
self,
account_address: impl ReferencedManifestComponentAddress,
batch: impl ConsumedBucketBatch,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let buckets = batch.resolve_and_consume(&self.registrar);
self.call_method(
address,
ACCOUNT_DEPOSIT_BATCH_IDENT,
AccountDepositBatchManifestInput { buckets },
)
}
pub fn deposit_entire_worktop(
self,
account_address: impl ReferencedManifestComponentAddress,
) -> Self {
self.deposit_batch(account_address, ManifestExpression::EntireWorktop)
}
pub fn try_deposit_or_abort(
self,
account_address: impl ReferencedManifestComponentAddress,
authorized_depositor_badge: Option<ResourceOrNonFungible>,
bucket: impl ConsumedManifestBucket,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let bucket = bucket.mark_consumed(&self.registrar);
self.call_method(
address,
ACCOUNT_TRY_DEPOSIT_OR_ABORT_IDENT,
manifest_args!(
bucket,
authorized_depositor_badge.map(ManifestResourceOrNonFungible::from)
),
)
}
pub fn try_deposit_batch_or_abort(
self,
account_address: impl ReferencedManifestComponentAddress,
batch: impl ConsumedBucketBatch,
authorized_depositor_badge: Option<ResourceOrNonFungible>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let buckets = batch.resolve_and_consume(&self.registrar);
self.call_method(
address,
ACCOUNT_TRY_DEPOSIT_BATCH_OR_ABORT_IDENT,
AccountTryDepositBatchOrAbortManifestInput {
buckets,
authorized_depositor_badge: authorized_depositor_badge.map(Into::into),
},
)
}
pub fn try_deposit_entire_worktop_or_abort(
self,
account_address: impl ReferencedManifestComponentAddress,
authorized_depositor_badge: Option<ResourceOrNonFungible>,
) -> Self {
self.try_deposit_batch_or_abort(
account_address,
ManifestExpression::EntireWorktop,
authorized_depositor_badge,
)
}
pub fn try_deposit_or_refund(
self,
account_address: impl ReferencedManifestComponentAddress,
authorized_depositor_badge: Option<ResourceOrNonFungible>,
bucket: impl ConsumedManifestBucket,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let bucket = bucket.mark_consumed(&self.registrar);
self.call_method(
address,
ACCOUNT_TRY_DEPOSIT_OR_REFUND_IDENT,
manifest_args!(
bucket,
authorized_depositor_badge.map(ManifestResourceOrNonFungible::from)
),
)
}
pub fn try_deposit_batch_or_refund(
self,
account_address: impl ReferencedManifestComponentAddress,
batch: impl ConsumedBucketBatch,
authorized_depositor_badge: Option<ResourceOrNonFungible>,
) -> Self {
let address = account_address.resolve_referenced(&self.registrar);
let buckets = batch.resolve_and_consume(&self.registrar);
self.call_method(
address,
ACCOUNT_TRY_DEPOSIT_BATCH_OR_REFUND_IDENT,
AccountTryDepositBatchOrAbortManifestInput {
buckets,
authorized_depositor_badge: authorized_depositor_badge.map(Into::into),
},
)
}
pub fn try_deposit_entire_worktop_or_refund(
self,
account_address: impl ReferencedManifestComponentAddress,
authorized_depositor_badge: Option<ResourceOrNonFungible>,
) -> Self {
self.try_deposit_batch_or_refund(
account_address,
ManifestExpression::EntireWorktop,
authorized_depositor_badge,
)
}
pub fn create_account_with_owner(
self,
address_reservation: impl ConsumedOptionalManifestAddressReservation,
owner_role: OwnerRole,
) -> Self {
let address_reservation = address_reservation.mark_consumed(&self.registrar);
self.call_function(
ACCOUNT_PACKAGE,
ACCOUNT_BLUEPRINT,
ACCOUNT_CREATE_ADVANCED_IDENT,
AccountCreateAdvancedManifestInput {
address_reservation,
owner_role: owner_role.into(),
},
)
}
pub fn create_access_controller(
self,
controlled_asset: impl ConsumedManifestBucket,
primary_role: AccessRule,
recovery_role: AccessRule,
confirmation_role: AccessRule,
timed_recovery_delay_in_minutes: Option<u32>,
) -> Self {
let controlled_asset = controlled_asset.mark_consumed(&self.registrar);
self.call_function(
ACCESS_CONTROLLER_PACKAGE,
ACCESS_CONTROLLER_BLUEPRINT,
ACCESS_CONTROLLER_CREATE_IDENT,
(
controlled_asset,
ManifestRuleSet {
primary_role: primary_role.into(),
recovery_role: recovery_role.into(),
confirmation_role: confirmation_role.into(),
},
timed_recovery_delay_in_minutes,
Option::<()>::None,
),
)
}
}
impl<M: BuildableManifest> ManifestBuilder<M>
where
M::Instruction: From<InstructionV2>,
{
fn add_v2_instruction(self, instruction: impl Into<InstructionV2>) -> Self {
self.add_instruction(instruction.into())
}
pub fn assert_worktop_is_empty(self) -> Self {
self.add_v2_instruction(AssertWorktopResourcesOnly {
constraints: Default::default(),
})
}
pub fn assert_worktop_resources_only(self, constraints: ManifestResourceConstraints) -> Self {
self.add_v2_instruction(AssertWorktopResourcesOnly { constraints })
}
pub fn assert_worktop_resources_include(
self,
constraints: ManifestResourceConstraints,
) -> Self {
self.add_v2_instruction(AssertWorktopResourcesInclude { constraints })
}
pub fn assert_next_call_returns_no_resources(self) -> Self {
self.add_v2_instruction(AssertNextCallReturnsOnly {
constraints: Default::default(),
})
}
pub fn assert_next_call_returns_only(self, constraints: ManifestResourceConstraints) -> Self {
self.add_v2_instruction(AssertNextCallReturnsOnly { constraints })
}
pub fn assert_next_call_returns_include(
self,
constraints: ManifestResourceConstraints,
) -> Self {
self.add_v2_instruction(AssertNextCallReturnsInclude { constraints })
}
pub fn assert_bucket_contents(
self,
bucket: impl ReferencedManifestBucket,
constraint: ManifestResourceConstraint,
) -> Self {
let bucket_id = bucket.resolve_referenced(&self.registrar);
self.add_v2_instruction(AssertBucketContents {
bucket_id,
constraint,
})
}
}
impl<M: BuildableManifestSupportingChildren> ManifestBuilder<M>
where
M::Instruction: From<InstructionV2>,
{
pub fn use_child(
mut self,
child_name: impl NewManifestIntent,
subintent_hash: SubintentHash,
) -> Self {
child_name.register(&self.registrar);
self.manifest.add_child_subintent(subintent_hash).unwrap();
self
}
pub fn yield_to_child(
self,
child_manifest_intent: impl ReferencedManifestIntent,
arguments: impl ResolvableArguments,
) -> Self {
let intent = child_manifest_intent.resolve_referenced(&self.registrar);
self.add_v2_instruction(YieldToChild {
child_index: ManifestNamedIntentIndex(intent.0),
args: arguments.resolve(),
})
}
pub fn yield_to_child_with_name_lookup<T: ResolvableArguments>(
self,
child_manifest_intent: impl ReferencedManifestIntent,
arguments_creator: impl FnOnce(&ManifestNameLookup) -> T,
) -> Self {
let intent = child_manifest_intent.resolve_referenced(&self.registrar);
let args = arguments_creator(&self.name_lookup()).resolve();
self.add_v2_instruction(YieldToChild {
child_index: ManifestNamedIntentIndex(intent.0),
args,
})
}
}
impl<M: BuildableManifestWithParent> ManifestBuilder<M>
where
M::Instruction: From<InstructionV2>,
{
pub fn yield_to_parent(self, arguments: impl ResolvableArguments) -> Self {
self.add_v2_instruction(YieldToParent {
args: arguments.resolve(),
})
}
pub fn yield_to_parent_with_name_lookup<T: ResolvableArguments>(
self,
arguments_creator: impl FnOnce(&ManifestNameLookup) -> T,
) -> Self {
let args = arguments_creator(&self.name_lookup()).resolve();
self.add_v2_instruction(YieldToParent { args })
}
pub fn verify_parent(self, access_rule: AccessRule) -> Self {
self.add_v2_instruction(VerifyParent { access_rule })
}
}
impl Default for ManifestBuilder<TransactionManifestV1> {
fn default() -> Self {
ManifestBuilder::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn get_builder_and_bucket_and_proof() -> (ManifestBuilder, ManifestBucket, ManifestProof) {
let builder = ManifestBuilder::new()
.take_from_worktop(XRD, dec!(100), "bucket")
.create_proof_from_bucket_of_amount("bucket", dec!(5), "proof");
let lookup = builder.name_lookup();
let proof_id = lookup.proof("proof");
let bucket_id = lookup.bucket("bucket");
(builder, bucket_id, proof_id)
}
#[test]
fn test_manifest_builder_add_instruction_advanced_proof() {
let (builder, _, proof_id) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(CloneProof { proof_id });
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(PopFromAuthZone);
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(CreateProofFromAuthZoneOfAmount {
resource_address: XRD,
amount: dec!(1),
});
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(CreateProofFromAuthZoneOfNonFungibles {
resource_address: XRD,
ids: vec![],
});
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(CreateProofFromAuthZoneOfAll {
resource_address: XRD,
});
let (builder, bucket_id, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(CreateProofFromBucketOfAmount {
bucket_id,
amount: dec!(1),
});
let (builder, bucket_id, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(CreateProofFromBucketOfNonFungibles {
bucket_id,
ids: vec![],
});
let (builder, bucket_id, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(CreateProofFromBucketOfAll { bucket_id });
}
#[test]
fn test_manifest_builder_add_instruction_advanced_worktop() {
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(TakeFromWorktop {
resource_address: XRD,
amount: dec!(1),
});
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(TakeAllFromWorktop {
resource_address: XRD,
});
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(TakeNonFungiblesFromWorktop {
resource_address: XRD,
ids: vec![],
});
}
#[test]
fn test_manifest_builder_add_instruction_advanced_global_address() {
let (builder, _, _) = get_builder_and_bucket_and_proof();
builder.add_instruction_advanced(AllocateGlobalAddress {
package_address: PACKAGE_PACKAGE,
blueprint_name: PACKAGE_BLUEPRINT.to_string(),
});
}
#[test]
fn test_manifest_builder_complex_deposit_batch_build_process_works() {
let account = GENESIS_HELPER; ManifestBuilder::new()
.get_free_xrd_from_faucet()
.take_from_worktop(XRD, dec!(1000), "bucket_1")
.try_deposit_entire_worktop_or_abort(account, None)
.try_deposit_batch_or_abort(account, ["bucket_1"], None)
.build();
}
}