Cross-blueprint Calls

A cross-blueprint call happens when a function/method invokes a function/method defined in different blueprint. This allows a developer to create complex systems by composing various blueprints and components together.

Calling with Blueprint ABI

To export the ABI of a blueprint, use the following command:

resim export-abi <PACKAGE_ADDRESS> <BLUEPRINT_NAME>

After obtaining the blueprint ABI, you can use the import macro to generate a stub, e.g.,

import! { r#"
{
    "package": "01bda8686d6c2fa45dce04fac71a09b54efbc8028c23aac74bc00e",
    "name": "Airdrop",
    "functions": [
        {
            "name": "new",
            "inputs": [],
            "output": {
                "type": "Custom",
                "name": "scrypto::core::Component",
                "generics": []
            }
        }
    ],
    "methods": [
        {
            "name": "free_token",
            "mutability": "Immutable",
            "inputs": [],
            "output": {
                "type": "Custom",
                "name": "scrypto::resource::Bucket",
                "generics": []
            }
        }
    ]
}
"# }

r#"<STRING_LITERAL>"# is a Rust syntax to define a string literal that may span multiple lines.

Once the blueprint is imported, you can then call any of its functions. For example,

let airdrop: Component = Airdrop::new();

To invoke a method, you will need the component address first and then convert it into a component. After that, you can call any of the methods.

let address: Address = "022cf5de8153aaf56ee81c032fb06c7fde0a1dc2389040d651dfc2".parse().unwrap();
let airdrop: Airdrop = Airdrop::from(address);
let tokens: Bucket = airdrop.free_token();

Calling without Blueprint ABI

In cases where the blueprint ABI is not available or not ready, you can also dynamically call a function or method using Scrypto APIs.

To call a function, construct a Blueprint and then make a call:

let blueprint: Blueprint = (package_address, blueprint_name).into();
let return_value: ReturnType = blueprint.call(
    function_name,
    args!(arg1, arg2, arg3)
);

To call a method, construct a Component and then make a call:

let component: Component = component_address.into();
let return_value: ReturnType = component.call(
    method_name,
    args!(arg1, arg2, arg3)
);

If no return data is expected, use () for ReturnType.