Migrating from Scrypto v0.6 to v0.7

resim command

Added resim new-simple-badge command

This command creates a non-fungible resource with an initial supply of one and no metadata. This token can be used to setup authorization rules for packages, components and resources. The command outputs the NonFungibleAddress of the token which you will use for the command flag we will see next…​

Added the --owner-badge flag when publishing a package

We added a new flag that you must provide when deploying a package with resim publish. --owner-badge takes the NonFungibleAddress of a non-fungible token. As of v0.7, packages can have metadata. This owner badge must be presented in order to be authorized to add/update/remove package metadata.

Note that it is not required to provide this flagg when updating an existing package (when the --package-address flag is present)

New syntax when passing NonFungibleId to methods

The string representation of NonFungibleIds have been updated with the latest version. The representation depends on the NonFungibleType that was specified when the non-fungible resource was created (more on this below). You now represent them like so:

NonFungibleType

String representation

U32

U32#100

U64

U64#200

String

String#abcde

Bytes

Bytes#23ae33

UUID

UUID#1234567

Scrypto

Updated how external_blueprint! and external_component! work

We changed how you can specify part of the ABI of external blueprint and components using the external_blueprint! and external_component! macros. The first thing you will notice is that with external_blueprint!, you do not define the package address and blueprint name anymore. Similarly, with external_component!, you do not define the component address anymore. The second thing that changed is that you cannot specify methods within external_blueprint! and you cannot specify functions within external_component!. This means that if you need to both access functions and methods you will have to call both external_blueprint! and external_component!.

After defining the available methods and function signatures, you would access a specific blueprint or component like so:

external_blueprint! {
    ExternalBlueprintTarget {
        fn create() -> ComponentAddress;
        fn get_value_via_package_call() -> String;
    }
}

external_component! {
    ExternalComponentTarget {
        fn get_value_via_ref(&self) -> ExtraStruct;
        fn get_value_via_mut_ref(&mut self) -> ExtraEnum;
    }
}

...

// Calling a function on a blueprint:
let external_blueprint = ExternalBlueprintTarget::at(package_address, "<blueprint_name>");
// Call the `create` function
let component_address = external_blueprint.create();

// Call the `get_value_via_mut_ref` method on the new component
let returned_value = ExternalComponentTarget::at(component_address).get_value_via_mut_ref();

Updated how importing external blueprint/component from ABI works

If you prefer to specify the full string ABI (returned from resim export-abi [package_address] [blueprint_name]), you need to know about the following change. After calling the import! macro with the blueprint’s ABI, two variable types will be made available for you. Let’s say you are importing a blueprint called Hello. You will be able to call the instantiate_hello() function on that blueprint with Hello::instantiate_hello(). Now, what changed is the way you refer to components matching this ABI. The second type automatically created will be HelloGlobalComponentRef ([blueprint_name] + "GlobalComponentRef"). This type allows you to store a reference to a component matching this ABI. Here is an example:

let component: HelloGlobalComponentRef = Hello::instantiate_hello();
let bucket = component.free_token();

Updated AccessRules::method() method signature to accept a third parameter

With v0.7, there is a third parameter you must specify when defining the access rules of your component’s method. This third parameter refers to the authority that is allowed to update the method’s access rule. If you don’t want anyone to be able to update it, you can set this third parameter to AccessRule::DenyAll.

Updated AccessRules::default() method signature to accept a second parameter

Similarly to the previous point, you now have to provide an extra parameter when setting the default method authorization rule of your component. This represent the default authority that is able to update the access rule of the methods.

Replaced Mutable([rule]) and LOCKED with just [rule] when defining access/resources rules

When setting authorization rules on resource actions, you used to provide a Mutable([rule]) or LOCKED flag that would specify the authority allowed to update the resource flag after creation. You can now simply provide an AccessRule rather than a variant of the Mutability enum. Here is an example

let resource_admin = ResourceManager::new_fungible().initial_supply(1);

// Before v0.7
let resource = ResourceManager::new_fungible()
  .mintable(rule!(require(resource_admin.resource_address())), MUTABLE(rule!(resource_admin.resource_address())))
  .burnable(rule!(require(resource_admin.resource_address())), LOCKED)
  .no_initial_supply();

// After v0.7 you can omit the `MUTABLE` and `LOCKED` part
let resource = ResourceManager::new_fungible()
  .mintable(rule!(require(resource_admin.resource_address())), rule!(resource_admin.resource_address()))
  .burnable(rule!(require(resource_admin.resource_address())), AccessRule::DenyAll)
  .no_initial_supply();

Updated the way you instantiate a NonFungibleId

Because there is now a fixed set of possible non-fungible id types, the syntax for instantiating NonFungibleId has changed. Here is an example:

let type1 = NonFungibleId::U32(22u32)
let type2 = NonFungibleId::U64(1234u64)
let type3 = NonFungibleId::String("string")
let type4 = NonFungibleId::Bytes(vec![1u8, 5u8, 3u8])
let type5 = NonFungibleId::UUID(123444u128)

Added a parameter to ResourceBuilder::new_non_fungible() for the ID type

Now, the system is making sure all minted NFTs of the same resource manager has the same non-fungible type. This is made possible by having the resource creator being required to provide the non-fungible id type that the minted NFTs will have. Example:

let my_nft = ResourceBuilder::new_non_fungible(NonFungibleIdType::String)
    .no_initial_supply();

Here are the available types:

NonFungibleType

String representation

U32

NonFungibleIdType::U32

U64

NonFungibleIdType::U64

String

NonFungibleIdType::String

Bytes

NonFungibleIdType::Bytes

UUID

NonFungibleIdType::UUID

Updated the string representation of NonFungibleAddresses

With v0.7, it is now easier to work with NonFungibleAddresses as their string representation is now simply the concatenation of the resource address with the string representation of the NonFungibleID (separated with a :). Example: resource_sim1qqswts6ls77yrqrpppds0vp2xz58pl3py3dfw5g07xrs4hgzj3:U32#532 refers to a NFT with the resource address resource_sim1qqswts6ls77yrqrpppds0vp2xz58pl3py3dfw5g07xrs4hgzj3 and with an u32 ID of 532.

Removed ResourceManager::update_metadata(hashmap)

We removed the ResourceManager::update_metadata(<hashmap>) method in favor of the ResourceManager::set_metadata(key, value) method.

Changes to the derive macro when defining custom structs

You now have to use the scrypto macro instead of derive when defining a struct as TypeId, Encode and Decode. You might have to use both derive and scrypto for a single struct:

#[derive(Clone, Describe, Debug, PartialEq, Eq)]
#[scrypto(TypeId, Encode, Decode)]
struct MyStruct {
    ...
}

Renamed ResourceManager::metadata() to ResourceManager::get_metadata()

Added access to real world time

With v0.7, you can now have access to the current time using the following functions:

let instant: Instant = Clock::current_time(TimePrecision::Minute)
let boolean1: bool = Clock::current_time_is_strictly_before(instant, TimePrecision::Minute)
let boolean2: bool = Clock::current_time_is_at_or_before(instant, TimePrecision::Minute)
let boolean3: bool = Clock::current_time_is_strictly_after(instant, TimePrecision::Minute)
let boolean4: bool = Clock::current_time_is_at_or_after(instant, TimePrecision::Minute)

At the moment, only TimePrecision::Minute is available. The Instant type is a Rust struct with a single i64 seconds_since_unix_epoch field.

Added Recallable tokens

More documentation regarding this soon

Added developer royalties

More documentation regarding this soon

Added package/component metadata

More documentation regarding this soon

Renamed the Faucet’s free_xrd() method to just free()

Added three new methods on the Account blueprint

Three new methods were added to the Account blueprint to withdraw tokens and pay for the transaction fee at the same time:

Account::lock_fee_and_withdraw(amount_to_lock, resource_address) -> Bucket
Account::lock_fee_and_withdraw_by_amount(amount_to_lock, amount_to_withdraw, resource_address) -> Bucket
Account::lock_fee_and_withdraw_by_ids(amount_to_lock, ids: BTreeSet<NonFungibleId>, resource_address) -> Bucket

Testing

Renamed TestRunner::new_account() to TestRunner::new_allocated_account()

Updated TestRunner::execute_manifest_ignoring_fee() last argument

Now, to provide the public keys, you create a vector of NonFungibleAddresses like this:

test_runner.execute_manifest_ignoring_fee(manifest1, vec![NonFungibleAddress::from_public_key(&public_key)]);

Transaction Manifest

Renamed Set to Array

Changed Maps to be representeed as Array of tuples

Maps are now represented as arrays of tuples. Example:

CALL_METHOD ComponentAddress("${address}") Array<Tuple>(("key1", "value1"), ("key2", "value2"));

Added PUBLISH_PACKAGE_WITH_OWNER instruction

You can now publish a package with a specific owner NonFungibleAddress as follow:

PUBLISH_PACKAGE_WITH_OWNER Blob("<hex>") Blob("<hex>") NonFungibleAddress("<resource_address>", "<id>");

Added BURN_BUCKET instruction

You can now burn buckets from the transaction manifest like this:

DROP_BUCKET Bucket("my_bucket");

Added CALL_NATIVE_FUNCTION instruction

This instruction allows you to call lower-level system functions.

Added CALL_NATIVE_METHOD instruction

This instruction allows you to call lower-level methods. For example, this is used when recalling tokens from a specific vault or withdrawing the developer royalies (more information on this soon).

Frontend SDK

Take a look at this README file here to find out how to use the frontend wallet SDK.