Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
* The corresponding environment "ic" is defined implicitly which can be overwritten by user configuration.
* The `--mainnet` and `--ic` flags are removed. Use `-n/--network ic`, `-e/--environment ic` instead.
* feat: Allow overriding the implicit `local` network and environment.
* chore: get rid of `TCYCLES` mentions and replace them with `cycles`
* feat: Add `icp cycles transfer` as replacement for `icp token cycles transfer`
* chore!: remove support for `cycles` in `icp token`. Use `icp cycles` instead
* chore!: Change display format of token and cycles amounts
* feat: Token and cycles amounts now support new formats. Valid examples: `1_000`, `1k`, `1.5m`, `1_234.5b`, `4T`
* feat: Allow installing WASMs that are larger than 2MB
* feat: Add `icp identity account-id` command to display the ICP ledger account identifier
* Supports `--of-principal` flag to convert a specific principal instead of the current identity
Expand Down
7 changes: 5 additions & 2 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ publish = false
anyhow = "1.0.100"
async-dropper = { version = "0.3.0", features = ["tokio", "simple"] }
async-trait = "0.1.88"
bigdecimal = "0.4.8"
bigdecimal = "0.4.10"
bip32 = "0.5.0"
bollard = "0.19.4"
byte-unit = "5.1.6"
Expand Down Expand Up @@ -59,6 +59,9 @@ keyring = { version = "3.6.3", features = ["apple-native", "windows-native", "sy
lazy_static = "1.5.0"
mockall = "0.13.1"
notify = "8.2.0"
num-bigint = "0.4.6"
num-integer = "0.1.46"
num-traits = "0.2.19"
p256 = { version = "0.13.2", features = ["pem", "pkcs8", "std"] }
pathdiff = { version = "0.2.3", features = ["camino"] }
pem = "3.0.5"
Expand Down
7 changes: 3 additions & 4 deletions crates/icp-canister-interfaces/src/cycles_ledger.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use bigdecimal::BigDecimal;
use candid::{CandidType, Nat, Principal};
use serde::Deserialize;

Expand Down Expand Up @@ -214,9 +213,9 @@ impl WithdrawError {
WithdrawError::TooOld => "created_at_time is too old.".to_string(),
WithdrawError::InsufficientFunds { balance } => {
format!(
"Insufficient cycles. Requested: {}T cycles, balance: {}T cycles.",
BigDecimal::new(requested_amount.into(), CYCLES_LEDGER_DECIMALS),
BigDecimal::from_biguint(balance.0.clone(), CYCLES_LEDGER_DECIMALS)
"Insufficient cycles. Requested: {} cycles, balance: {} cycles.",
Nat::from(requested_amount), // Convert to Nat to get underscores in the output
balance.0
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-canister-interfaces/src/icp_ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use candid::Principal;

/// 0.0001 ICP, a.k.a. 10k e8s
pub const ICP_LEDGER_BLOCK_FEE_E8S: u64 = 10_000;

pub const ICP_LEDGER_SYMBOL: &str = "ICP";
pub const ICP_LEDGER_CID: &str = "ryjl3-tyaaa-aaaaa-aaaba-cai";
pub const ICP_LEDGER_PRINCIPAL: Principal = Principal::from_slice(&[0, 0, 0, 0, 0, 0, 0, 2, 1, 1]);

Expand Down
3 changes: 3 additions & 0 deletions crates/icp-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ indicatif.workspace = true
itertools.workspace = true
k256.workspace = true
lazy_static.workspace = true
num-bigint.workspace = true
num-integer.workspace = true
num-traits.workspace = true
p256.workspace = true
pem.workspace = true
phf.workspace = true
Expand Down
6 changes: 4 additions & 2 deletions crates/icp-cli/src/commands/canister/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use icp_canister_interfaces::cycles_ledger::CanisterSettingsArg;

use crate::{
commands::args,
commands::parsers::parse_cycles_amount,
operations::create::CreateOperation,
progress::{ProgressManager, ProgressManagerSettings},
};
Expand Down Expand Up @@ -49,8 +50,9 @@ pub(crate) struct CreateArgs {
#[arg(long, short = 'q')]
pub(crate) quiet: bool,

/// Cycles to fund canister creation (in raw cycles).
#[arg(long, default_value_t = DEFAULT_CANISTER_CYCLES)]
/// Cycles to fund canister creation.
/// Supports suffixes: k (thousand), m (million), b (billion), t (trillion).
#[arg(long, default_value_t = DEFAULT_CANISTER_CYCLES, value_parser = parse_cycles_amount)]
pub(crate) cycles: u128,

/// The subnet to create canisters on.
Expand Down
12 changes: 4 additions & 8 deletions crates/icp-cli/src/commands/canister/settings/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::collections::{HashMap, HashSet};
use std::io::Write;

use crate::commands::args;
use crate::commands::parsers::parse_cycles_amount;

#[derive(Clone, Debug, Default, Args)]
pub(crate) struct ControllerOpt {
Expand Down Expand Up @@ -101,7 +102,9 @@ pub(crate) struct UpdateArgs {
#[arg(long, value_parser = freezing_threshold_parser)]
freezing_threshold: Option<u64>,

#[arg(long, value_parser = reserved_cycles_limit_parser)]
/// Reserved cycles limit for the canister.
/// Supports suffixes: k (thousand), m (million), b (billion), t (trillion).
#[arg(long, value_parser = parse_cycles_amount)]
reserved_cycles_limit: Option<u128>,

#[arg(long, value_parser = memory_parser)]
Expand Down Expand Up @@ -293,13 +296,6 @@ fn freezing_threshold_parser(freezing_threshold: &str) -> Result<u64, String> {
Err("Must be a value between 0..2^64-1 inclusive".to_string())
}

fn reserved_cycles_limit_parser(reserved_cycles_limit: &str) -> Result<u128, String> {
if let Ok(num) = reserved_cycles_limit.parse::<u128>() {
return Ok(num);
}
Err("Must be a value between 0..2^128-1 inclusive".to_string())
}

fn log_visibility_parser(log_visibility: &str) -> Result<LogVisibility, String> {
match log_visibility {
"public" => Ok(LogVisibility::Public),
Expand Down
19 changes: 13 additions & 6 deletions crates/icp-cli/src/commands/canister/top_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ use candid::{Decode, Encode, Nat};
use clap::Args;
use icp::context::Context;
use icp_canister_interfaces::cycles_ledger::{
CYCLES_LEDGER_DECIMALS, CYCLES_LEDGER_PRINCIPAL, WithdrawArgs, WithdrawResponse,
CYCLES_LEDGER_PRINCIPAL, WithdrawArgs, WithdrawResponse,
};

use crate::commands::args;
use crate::commands::parsers::parse_cycles_amount;
use crate::operations::token::TokenAmount;

#[derive(Debug, Args)]
pub(crate) struct TopUpArgs {
/// Amount of cycles to top up
#[arg(long)]
/// Amount of cycles to top up.
/// Supports suffixes: k (thousand), m (million), b (billion), t (trillion).
#[arg(long, value_parser = parse_cycles_amount)]
pub(crate) amount: u128,

#[command(flatten)]
Expand Down Expand Up @@ -54,10 +57,14 @@ pub(crate) async fn exec(ctx: &Context, args: &TopUpArgs) -> Result<(), anyhow::
bail!("failed to top up: {}", err.format_error(args.amount));
}

let amount = TokenAmount {
amount: BigDecimal::new(args.amount.into(), 0),
symbol: "cycles".to_string(),
};

let _ = ctx.term.write_line(&format!(
"Topped up canister {} with {}T cycles",
args.cmd_args.canister,
BigDecimal::new(args.amount.into(), CYCLES_LEDGER_DECIMALS)
"Topped up canister {} with {}",
args.cmd_args.canister, amount
));

Ok(())
Expand Down
16 changes: 10 additions & 6 deletions crates/icp-cli/src/commands/cycles/balance.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use bigdecimal::BigDecimal;
use icp::context::Context;
use icp_canister_interfaces::cycles_ledger::CYCLES_LEDGER_PRINCIPAL;

use crate::commands::token;
use crate::operations::token::balance::get_balance;
use crate::operations::token::TokenAmount;
use crate::operations::token::balance::get_raw_balance;

pub(crate) async fn exec(
ctx: &Context,
Expand All @@ -19,13 +22,14 @@ pub(crate) async fn exec(
.await?;

// Get the balance from the ledger
let balance_info = get_balance(&agent, "cycles").await?;
let cycles = get_raw_balance(&agent, CYCLES_LEDGER_PRINCIPAL).await?;
let cycles_amount = TokenAmount {
amount: BigDecimal::from_biguint(cycles.0, 0),
symbol: "cycles".to_string(),
};

// Output information
let _ = ctx.term.write_line(&format!(
"Balance: {} {}",
balance_info.amount, balance_info.symbol
));
let _ = ctx.term.write_line(&format!("Balance: {cycles_amount}"));

Ok(())
}
9 changes: 6 additions & 3 deletions crates/icp-cli/src/commands/cycles/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ use clap::Args;
use icp::context::Context;

use crate::commands::args::TokenCommandArgs;
use crate::commands::parsers::{parse_cycles_amount, parse_token_amount};
use crate::operations::token::mint::mint_cycles;

#[derive(Debug, Args)]
pub(crate) struct MintArgs {
/// Amount of ICP to mint to cycles.
#[arg(long, conflicts_with = "cycles")]
/// Supports suffixes: k (thousand), m (million), b (billion), t (trillion).
#[arg(long, conflicts_with = "cycles", value_parser = parse_token_amount)]
pub(crate) icp: Option<BigDecimal>,

/// Amount of cycles to mint. Automatically determines the amount of ICP needed.
#[arg(long, conflicts_with = "icp")]
/// Supports suffixes: k (thousand), m (million), b (billion), t (trillion).
#[arg(long, conflicts_with = "icp", value_parser = parse_cycles_amount)]
pub(crate) cycles: Option<u128>,

#[command(flatten)]
Expand Down Expand Up @@ -42,7 +45,7 @@ pub(crate) async fn exec(ctx: &Context, args: &MintArgs) -> Result<(), anyhow::E

// Display results
let _ = ctx.term.write_line(&format!(
"Minted {} TCYCLES to your account, new balance: {} TCYCLES.",
"Minted {} to your account, new balance: {}.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"Minted {} to your account, new balance: {}.",
"Minted {} cycles to your account, new balance: {} cycles.",

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The symbol is included in the struct that is displayed

mint_info.deposited, mint_info.new_balance
));

Expand Down
4 changes: 4 additions & 0 deletions crates/icp-cli/src/commands/cycles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::commands::token;

pub(crate) mod balance;
pub(crate) mod mint;
pub(crate) mod transfer;

#[derive(Subcommand, Debug)]
pub(crate) enum Command {
Expand All @@ -12,4 +13,7 @@ pub(crate) enum Command {

/// Convert icp to cycles
Mint(mint::MintArgs),

/// Transfer cycles to another principal
Transfer(transfer::TransferArgs),
}
55 changes: 55 additions & 0 deletions crates/icp-cli/src/commands/cycles/transfer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use candid::Principal;
use clap::Args;
use icp::context::Context;
use icp_canister_interfaces::cycles_ledger::{CYCLES_LEDGER_BLOCK_FEE, CYCLES_LEDGER_PRINCIPAL};

use crate::commands::args::TokenCommandArgs;
use crate::commands::parsers::parse_cycles_amount;
use crate::operations::token::transfer::icrc1_transfer;

#[derive(Debug, Args)]
pub(crate) struct TransferArgs {
/// Cycles amount to transfer.
/// Supports suffixes: k (thousand), m (million), b (billion), t (trillion).
#[arg(value_parser = parse_cycles_amount)]
pub(crate) amount: u128,

/// The receiver of the cycles transfer
pub(crate) receiver: Principal,

#[command(flatten)]
pub(crate) token_command_args: TokenCommandArgs,
}

pub(crate) async fn exec(ctx: &Context, args: &TransferArgs) -> Result<(), anyhow::Error> {
let selections = args.token_command_args.selections();

// Agent
let agent = ctx
.get_agent(
&selections.identity,
&selections.network,
&selections.environment,
)
.await?;

// Execute transfer
let transfer_info = icrc1_transfer(
&agent,
CYCLES_LEDGER_PRINCIPAL,
args.amount.into(),
args.receiver,
CYCLES_LEDGER_BLOCK_FEE.into(),
0,
"cycles".to_string(),
)
.await?;

// Output information
let _ = ctx.term.write_line(&format!(
"Transferred {} to {} in block {}",
transfer_info.transferred, transfer_info.receiver, transfer_info.block_index
));

Ok(())
}
1 change: 1 addition & 0 deletions crates/icp-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub(crate) mod environment;
pub(crate) mod identity;
pub(crate) mod network;
pub(crate) mod new;
pub(crate) mod parsers;
pub(crate) mod project;
pub(crate) mod sync;
pub(crate) mod token;
Expand Down
Loading
Loading