Passing args while creating a canister in rust

I’m trying to create a function that creates an icrc ledger canister when invoked and I’m getting an error.
“Fail to decode argument 0\n\nCaused by:\n Subtyping error: text)”

Here are my type definitions:

use candid::CandidType;

use candid::Nat;
use candid::Principal;
use icrc_ledger_types::icrc::generic_metadata_value::MetadataValue;

use icrc_ledger_types::icrc::generic_value::Value;
use icrc_ledger_types::icrc1::account::{Account, Subaccount};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, CandidType)]

pub struct FeatureFlags {
    pub icrc2: bool,
}

#[derive(Debug, Serialize, Deserialize, CandidType)]
pub struct InitArgs {
    pub minting_account: Account,
    pub fee_collector_account: Option<Account>,
    pub transfer_fee: Value,
    pub decimals: Option<Value>,
    pub max_memo_length: Option<Value>,
    pub token_symbol: Value,
    pub token_name: Value,
    pub metadata: Vec<(String, MetadataValue)>,
    pub initial_balances: Vec<(Account, Value)>,
    pub feature_flags: Option<FeatureFlags>,
    pub maximum_number_of_accounts: Option<Value>,
    pub accounts_overflow_trim_quantity: Option<Value>,
    pub archive_options: ArchiveOptions,
}

#[derive(Debug, Serialize, Deserialize, CandidType)]
pub struct ArchiveOptions {
    pub num_blocks_to_archive: Value,
    pub max_transactions_per_response: Option<Value>,
    pub trigger_threshold: Value,
    pub max_message_size_bytes: Option<Value>,
    pub cycles_for_archive_creation: Option<Value>,
    pub node_max_memory_size_bytes: Option<Value>,
    pub controller_id: Principal,
    pub more_controller_ids: Option<Vec<Principal>>,
}

#[derive(Debug, Serialize, Deserialize, CandidType)]

pub struct UpgradeArgs {}

#[derive(Debug, Serialize, Deserialize, CandidType)]
pub enum LedgerArg {
    Init(InitArgs),
    Upgrade(Option<UpgradeArgs>),
}

I’m then creating my ledger args like below:

 // Create instances of required fields for InitArgs
    let minting_account = Account {
        owner: Principal::from_text(
            "owu57-ix3tx-4pgh7-pmu7n-dzlor-tqljq-wui5j-g5b2g-mtnfa-yklry-mae",
        )
        .unwrap(),
        subaccount: None,
    };

    let fee_collector_account = Some(Account {
        owner: Principal::from_text(
            "owu57-ix3tx-4pgh7-pmu7n-dzlor-tqljq-wui5j-g5b2g-mtnfa-yklry-mae",
        )
        .unwrap(),
        subaccount: None,
    });

    let transfer_fee = Nat64(1000);
    let decimals = Some(Nat64(8));
    let max_memo_length = Some(Nat64(256));
    let token_symbol = Text("REO".to_string());
    let token_name = Text("Reorg".to_string());
    let metadata = vec![(
        "icrc1_name".to_string(),
        MetadataValue::Text("REORG".to_string()),
    )];

    let initial_balances = vec![(
        Account {
            owner: Principal::from_text(
                "owu57-ix3tx-4pgh7-pmu7n-dzlor-tqljq-wui5j-g5b2g-mtnfa-yklry-mae",
            )
            .unwrap(),
            subaccount: None,
            // Initialize the Account fields as needed
        },
        Nat64(1000),
    )];

    let feature_flags = Some(FeatureFlags { icrc2: true });
    let maximum_number_of_accounts = Some(Nat64(1000));
    let accounts_overflow_trim_quantity = Some(Nat64(100));

    let archive_options = ArchiveOptions {
        num_blocks_to_archive: Nat64(500),
        max_transactions_per_response: Some(Nat64(200)),
        trigger_threshold: Nat64(1000),
        max_message_size_bytes: Some(Nat64(1024)),
        cycles_for_archive_creation: Some(Nat64(10)),
        node_max_memory_size_bytes: Some(Nat64(2000)),
        controller_id: Principal::anonymous(),
        more_controller_ids: Some(vec![Principal::anonymous()]),
    };

    let init_args = InitArgs {
        minting_account,
        fee_collector_account,
        transfer_fee,
        decimals,
        max_memo_length,
        token_symbol,
        token_name,
        metadata,
        initial_balances,
        feature_flags,
        maximum_number_of_accounts,
        accounts_overflow_trim_quantity,
        archive_options,
    };

    // Create a new token instance using LedgerArgs with UpgradeArgs as None

    let token = LedgerArg::Init(init_args);
  let serialized_args = Encode!(&token).expect("Serialization failed");

Then passing that like below let install_args = InstallCodeArgument {
canister_id: Principal::from_text(“b77ix-eeaaa-aaaaa-qaada-cai”).unwrap(), //b77ix-eeaaa-aaaaa-qaada-cai
wasm_module,
arg: serialized_args,
mode: ic_cdk::api::management_canister::main::CanisterInstallMode::Install,
};
But I get the error “Fail to decode argument 0\n\nCaused by:\n Subtyping error: text)”. I will appreciate any help

Looks fine at a glance. I would debug-print the serialized_args and put it through didc decode <hex> and see what comes out and how it matches with the expected arg type

It finally worked after using this types,

pub struct InitArgs {
    pub minting_account: Account,
    pub fee_collector_account: Option<Account>,
    pub initial_balances: Vec<(Account, Nat)>,
    pub transfer_fee: Nat,
    pub decimals: Option<u8>,
    pub token_name: String,
    pub token_symbol: String,
    pub metadata: Vec<(String, Value)>,
    pub archive_options: ArchiveOptions,
    pub max_memo_length: Option<u16>,
    pub feature_flags: Option<FeatureFlags>,
    pub maximum_number_of_accounts: Option<u64>,
    pub accounts_overflow_trim_quantity: Option<u64>,
}

#[derive(Serialize, Deserialize, CandidType, Clone, Debug, PartialEq, Eq)]
pub struct ArchiveOptions {
    /// The number of blocks which, when exceeded, will trigger an archiving
    /// operation.
    pub trigger_threshold: usize,
    /// The number of blocks to archive when trigger threshold is exceeded.
    pub num_blocks_to_archive: usize,
    pub node_max_memory_size_bytes: Option<u64>,
    pub max_message_size_bytes: Option<u64>,
    pub controller_id: Principal,
    // More principals to add as controller of the archive.
    #[serde(default)]
    pub more_controller_ids: Option<Vec<Principal>>,
    // cycles to use for the call to create a new archive canister.
    #[serde(default)]
    pub cycles_for_archive_creation: Option<u64>,
    // Max transactions returned by the [get_transactions] endpoint.
    #[serde(default)]
    pub max_transactions_per_response: Option<u64>,
}
1 Like