From e9e0bcc4ae0740e6716dfe66d3aa084c3a021fcd Mon Sep 17 00:00:00 2001 From: Eric Swanson <64809312+ericswanson-dfinity@users.noreply.github.com> Date: Tue, 17 Oct 2023 10:03:50 -0700 Subject: [PATCH 1/2] fix: dfx ledger transfer outputs messages about duplicates to log, not stdout (#3420) If the replica reports a duplicate transaction in `dfx ledger transfer`, dfx prints out a message about this. This change logs that message at info level, rather than printing it to stdout. This makes the stdout output of `dfx ledger transfer` consistent. Why info level, rather than warn level? Anyone calling `dfx ledger transfer`, even without specifying `--created-at-time`, can see this duplicate transaction message. This is because dfx retries failures, and uses a consistent created_at_time (either from `--created-at-time`, or by getting the current system time before the first attempt). It's possible that a call succeeds, but there is an i/o error before dfx receives the response. In this case dfx will retry, and get a duplicate transaction result. Motivation: https://github.com/dfinity/sdk/pull/3419#discussion_r1360248149 --- CHANGELOG.md | 4 ++ e2e/tests-dfx/ledger.bash | 47 +++++++++---------- .../src/commands/ledger/create_canister.rs | 1 + src/dfx/src/commands/ledger/top_up.rs | 1 + src/dfx/src/commands/ledger/transfer.rs | 1 + src/dfx/src/commands/quickstart.rs | 5 +- src/dfx/src/lib/operations/cmc.rs | 3 ++ src/dfx/src/lib/operations/ledger.rs | 4 +- 8 files changed, 40 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f065842eb8..ac8fbcd87b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ # UNRELEASED +### fix: `dfx ledger transfer` now logs to stderr messages about duplicates rather than printing them to stdout + +The message "transaction is a duplicate of another transaction in block ...", previously printed to stdout, is now logged to stderr. This means that the output of `dfx ledger transfer` to stdout will contain only "Transfer sent at block height ". + ### feat: added `dfx cycles` command This won't work on mainnet yet, but can work locally after installing the cycles ledger. diff --git a/e2e/tests-dfx/ledger.bash b/e2e/tests-dfx/ledger.bash index f030490dd3..56a0375a87 100644 --- a/e2e/tests-dfx/ledger.bash +++ b/e2e/tests-dfx/ledger.bash @@ -43,32 +43,32 @@ current_time_nanoseconds() { @test "ledger balance & transfer" { dfx identity use alice assert_command dfx ledger account-id - assert_match 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 + assert_eq 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 assert_command dfx ledger balance - assert_match "1000000000.00000000 ICP" + assert_eq "1000000000.00000000 ICP" assert_command dfx ledger transfer --amount 100 --memo 1 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 # to bob - assert_match "Transfer sent at block height" + assert_contains "Transfer sent at block height" # The sender(alice) paid transaction fee which is 0.0001 ICP assert_command dfx ledger balance - assert_match "999999899.99990000 ICP" + assert_eq "999999899.99990000 ICP" dfx identity use bob assert_command dfx ledger account-id - assert_match 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 + assert_eq 22ca7edac648b814e81d7946e8bacea99280e07c5f51a04ba7a38009d8ad8e89 assert_command dfx ledger balance - assert_match "1000000100.00000000 ICP" + assert_eq "1000000100.00000000 ICP" assert_command dfx ledger transfer --icp 100 --e8s 1 --memo 2 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # to alice - assert_match "Transfer sent at block height" + assert_contains "Transfer sent at block height" # The sender(bob) paid transaction fee which is 0.0001 ICP # 10100 - 100 - 0.0001 - 0.00000001 = 9999.99989999 assert_command dfx ledger balance - assert_match "999999999.99989999 ICP" + assert_eq "999999999.99989999 ICP" # Transaction Deduplication t=$(current_time_nanoseconds) @@ -77,25 +77,24 @@ current_time_nanoseconds() { # shellcheck disable=SC2154 block_height=$(echo "$stdout" | sed '1q' | sed 's/Transfer sent at block height //') # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_eq "Transfer sent at block height $block_height" "$stdout" assert_command dfx ledger transfer --icp 1 --memo 1 --created-at-time $((t+1)) 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # shellcheck disable=SC2154 - assert_match "Transfer sent at block height" "$stdout" + assert_contains "Transfer sent at block height" "$stdout" # shellcheck disable=SC2154 - assert_not_match "Transfer sent at block height $block_height" "$stdout" + assert_not_contains "Transfer sent at block height $block_height" "$stdout" assert_command dfx ledger transfer --icp 1 --memo 1 --created-at-time "$t" 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # shellcheck disable=SC2154 - assert_match "transaction is a duplicate of another transaction in block $block_height" "$stdout" - # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_eq "transaction is a duplicate of another transaction in block $block_height" "$stderr" + assert_eq "Transfer sent at block height $block_height" "$stdout" assert_command dfx ledger transfer --icp 1 --memo 2 --created-at-time "$t" 345f723e9e619934daac6ae0f4be13a7b0ba57d6a608e511a00fd0ded5866752 # shellcheck disable=SC2154 - assert_match "Transfer sent at block height" "$stdout" + assert_contains "Transfer sent at block height" "$stdout" # shellcheck disable=SC2154 - assert_not_match "Transfer sent at block height $block_height" "$stdout" + assert_not_contains "Transfer sent at block height $block_height" "$stdout" } @@ -178,13 +177,13 @@ tc_to_num() { assert_command dfx ledger top-up "$wallet" --icp 5 --created-at-time "$t" # shellcheck disable=SC2154 - assert_match "transaction is a duplicate of another transaction in block $block_height" "$stdout" + assert_contains "transaction is a duplicate of another transaction in block $block_height" "$stderr" # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_contains "Transfer sent at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Using transfer at block height $block_height" "$stdout" + assert_contains "Using transfer at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Canister was topped up with" "$stdout" + assert_contains "Canister was topped up with" "$stdout" } @test "ledger create-canister" { @@ -226,13 +225,13 @@ tc_to_num() { assert_command dfx ledger create-canister --amount=100 --created-at-time "$t" "$(dfx identity get-principal)" # shellcheck disable=SC2154 - assert_match "transaction is a duplicate of another transaction in block $block_height" "$stdout" + assert_contains "transaction is a duplicate of another transaction in block $block_height" "$stderr" # shellcheck disable=SC2154 - assert_match "Transfer sent at block height $block_height" "$stdout" + assert_contains "Transfer sent at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Using transfer at block height $block_height" "$stdout" + assert_contains "Using transfer at block height $block_height" "$stdout" # shellcheck disable=SC2154 - assert_match "Canister created with id: $created_canister_id" "$stdout" + assert_contains "Canister created with id: $created_canister_id" "$stdout" } diff --git a/src/dfx/src/commands/ledger/create_canister.rs b/src/dfx/src/commands/ledger/create_canister.rs index df10e517d1..0f1bd2fdec 100644 --- a/src/dfx/src/commands/ledger/create_canister.rs +++ b/src/dfx/src/commands/ledger/create_canister.rs @@ -77,6 +77,7 @@ pub async fn exec(env: &dyn Environment, opts: CreateCanisterOpts) -> DfxResult let height = transfer_cmc( agent, + env.get_logger(), memo, amount, fee, diff --git a/src/dfx/src/commands/ledger/top_up.rs b/src/dfx/src/commands/ledger/top_up.rs index f68da4ca2d..80265460f0 100644 --- a/src/dfx/src/commands/ledger/top_up.rs +++ b/src/dfx/src/commands/ledger/top_up.rs @@ -71,6 +71,7 @@ pub async fn exec(env: &dyn Environment, opts: TopUpOpts) -> DfxResult { let height = transfer_cmc( agent, + env.get_logger(), memo, amount, fee, diff --git a/src/dfx/src/commands/ledger/transfer.rs b/src/dfx/src/commands/ledger/transfer.rs index 27d623c64c..256f5df953 100644 --- a/src/dfx/src/commands/ledger/transfer.rs +++ b/src/dfx/src/commands/ledger/transfer.rs @@ -80,6 +80,7 @@ pub async fn exec(env: &dyn Environment, opts: TransferOpts) -> DfxResult { let _block_height = transfer( agent, + env.get_logger(), &canister_id, memo, amount, diff --git a/src/dfx/src/commands/quickstart.rs b/src/dfx/src/commands/quickstart.rs index 19eb300825..dce97ef9b8 100644 --- a/src/dfx/src/commands/quickstart.rs +++ b/src/dfx/src/commands/quickstart.rs @@ -31,6 +31,7 @@ use ic_utils::interfaces::{ use indicatif::ProgressBar; use num_traits::Inv; use rust_decimal::Decimal; +use slog::Logger; use tokio::runtime::Runtime; /// Use the `dfx quickstart` command to perform initial one time setup for your identity and/or wallet. This command @@ -151,13 +152,14 @@ async fn step_deploy_wallet( eprintln!("Run this command again at any time to continue from here."); return Ok(()); } - let wallet = step_interact_ledger(agent, ident_principal, rounded).await?; + let wallet = step_interact_ledger(agent, env.get_logger(), ident_principal, rounded).await?; step_finish_wallet(env, agent, wallet, ident).await?; Ok(()) } async fn step_interact_ledger( agent: &Agent, + logger: &Logger, ident_principal: Principal, to_spend: Decimal, ) -> DfxResult { @@ -169,6 +171,7 @@ async fn step_interact_ledger( let icpts = ICPTs::from_decimal(to_spend)?; let height = transfer_cmc( agent, + logger, Memo(MEMO_CREATE_CANISTER /* 👽 */), icpts, TRANSACTION_FEE, diff --git a/src/dfx/src/lib/operations/cmc.rs b/src/dfx/src/lib/operations/cmc.rs index 5db9b608ae..695ee3c65d 100644 --- a/src/dfx/src/lib/operations/cmc.rs +++ b/src/dfx/src/lib/operations/cmc.rs @@ -8,12 +8,14 @@ use crate::lib::nns_types::icpts::ICPTs; use crate::lib::operations::ledger::transfer; use candid::{Decode, Encode, Principal}; use ic_agent::Agent; +use slog::Logger; const NOTIFY_CREATE_CANISTER_METHOD: &str = "notify_create_canister"; const NOTIFY_TOP_UP_METHOD: &str = "notify_top_up"; pub async fn transfer_cmc( agent: &Agent, + logger: &Logger, memo: Memo, amount: ICPTs, fee: ICPTs, @@ -26,6 +28,7 @@ pub async fn transfer_cmc( AccountIdentifier::new(MAINNET_CYCLE_MINTER_CANISTER_ID, Some(to_subaccount)).to_address(); transfer( agent, + logger, &MAINNET_LEDGER_CANISTER_ID, memo, amount, diff --git a/src/dfx/src/lib/operations/ledger.rs b/src/dfx/src/lib/operations/ledger.rs index c5206bf173..6f5c45b7c8 100644 --- a/src/dfx/src/lib/operations/ledger.rs +++ b/src/dfx/src/lib/operations/ledger.rs @@ -20,6 +20,7 @@ use ic_agent::{ lookup_value, Agent, AgentError, }; use ic_utils::{call::SyncCall, Canister}; +use slog::{info, Logger}; use std::time::{SystemTime, UNIX_EPOCH}; const ACCOUNT_BALANCE_METHOD: &str = "account_balance_dfx"; @@ -98,6 +99,7 @@ pub async fn xdr_permyriad_per_icp(agent: &Agent) -> DfxResult { #[context("Failed to transfer funds.")] pub async fn transfer( agent: &Agent, + logger: &Logger, canister_id: &Principal, memo: Memo, amount: ICPTs, @@ -138,7 +140,7 @@ pub async fn transfer( match result { Ok(block_height) => break block_height, Err(TransferError::TxDuplicate { duplicate_of }) => { - println!("{}", TransferError::TxDuplicate { duplicate_of }); + info!(logger, "{}", TransferError::TxDuplicate { duplicate_of }); break duplicate_of; } Err(transfer_err) => bail!(transfer_err), From ff2e1beb725c693ac595f96c2faa9f5a8e3a9908 Mon Sep 17 00:00:00 2001 From: Eric Swanson <64809312+ericswanson-dfinity@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:27:04 -0700 Subject: [PATCH 2/2] test: reformat cycles-ledger.bash to match rest (#3423) All the other e2e test scripts use 2-space indents. I created this script before making them all consistent. --- e2e/tests-dfx/cycles-ledger.bash | 370 +++++++++++++++---------------- 1 file changed, 185 insertions(+), 185 deletions(-) diff --git a/e2e/tests-dfx/cycles-ledger.bash b/e2e/tests-dfx/cycles-ledger.bash index 3bfe2316d3..b5194c857c 100644 --- a/e2e/tests-dfx/cycles-ledger.bash +++ b/e2e/tests-dfx/cycles-ledger.bash @@ -4,25 +4,25 @@ load ../utils/_ load ../utils/cycles-ledger setup() { - standard_setup - install_asset cycles-ledger - install_shared_asset subnet_type/shared_network_settings/system - install_cycles_ledger_canisters + standard_setup + install_asset cycles-ledger + install_shared_asset subnet_type/shared_network_settings/system + install_cycles_ledger_canisters - dfx identity new --storage-mode plaintext cycle-giver - dfx identity new --storage-mode plaintext alice - dfx identity new --storage-mode plaintext bob + dfx identity new --storage-mode plaintext cycle-giver + dfx identity new --storage-mode plaintext alice + dfx identity new --storage-mode plaintext bob - dfx_start_for_nns_install + dfx_start_for_nns_install - dfx extension install nns --version 0.2.1 || true - dfx nns install --ledger-accounts "$(dfx ledger account-id --identity cycle-giver)" + dfx extension install nns --version 0.2.1 || true + dfx nns install --ledger-accounts "$(dfx ledger account-id --identity cycle-giver)" } teardown() { - dfx_stop + dfx_stop - standard_teardown + standard_teardown } current_time_nanoseconds() { @@ -30,263 +30,263 @@ current_time_nanoseconds() { } @test "balance" { - ALICE=$(dfx identity get-principal --identity alice) - ALICE_SUBACCT1="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - ALICE_SUBACCT1_CANDID="\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" - ALICE_SUBACCT2="9C9B9A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - ALICE_SUBACCT2_CANDID="\9C\9B\9A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" - BOB=$(dfx identity get-principal --identity bob) + ALICE=$(dfx identity get-principal --identity alice) + ALICE_SUBACCT1="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT1_CANDID="\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + ALICE_SUBACCT2="9C9B9A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT2_CANDID="\9C\9B\9A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + BOB=$(dfx identity get-principal --identity bob) - assert_command dfx deploy cycles-ledger - assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise - assert_eq "0 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "0 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice - assert_eq "0.000 TC (trillion cycles)." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "0.000 TC (trillion cycles)." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise - assert_eq "0 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise + assert_eq "0 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob - assert_eq "0.000 TC (trillion cycles)." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "0.000 TC (trillion cycles)." - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 1_700_400_200_150;})" --identity cycle-giver - assert_eq "(record { balance = 1_700_400_200_150 : nat; txid = 0 : nat })" + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 1_700_400_200_150;})" --identity cycle-giver + assert_eq "(record { balance = 1_700_400_200_150 : nat; txid = 0 : nat })" - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT1_CANDID\"};cycles = 3_750_000_000_000;})" --identity cycle-giver - assert_eq "(record { balance = 3_750_000_000_000 : nat; txid = 1 : nat })" + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT1_CANDID\"};cycles = 3_750_000_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 3_750_000_000_000 : nat; txid = 1 : nat })" - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT2_CANDID\"};cycles = 760_500_000_000;})" --identity cycle-giver - assert_eq "(record { balance = 760_500_000_000 : nat; txid = 2 : nat })" + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT2_CANDID\"};cycles = 760_500_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 760_500_000_000 : nat; txid = 2 : nat })" - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_900_000_000_000;})" --identity cycle-giver - assert_eq "(record { balance = 2_900_000_000_000 : nat; txid = 3 : nat })" + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_900_000_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 2_900_000_000_000 : nat; txid = 3 : nat })" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice - assert_eq "1700400200150 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "1700400200150 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT1" - assert_eq "3750000000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT1" + assert_eq "3750000000000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" - assert_eq "760500000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "760500000000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "2900000000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2900000000000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice - assert_eq "1.700 TC (trillion cycles)." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "1.700 TC (trillion cycles)." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --subaccount "$ALICE_SUBACCT1" - assert_eq "3.750 TC (trillion cycles)." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --subaccount "$ALICE_SUBACCT1" + assert_eq "3.750 TC (trillion cycles)." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --subaccount "$ALICE_SUBACCT2" - assert_eq "0.760 TC (trillion cycles)." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "0.760 TC (trillion cycles)." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob - assert_eq "2.900 TC (trillion cycles)." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "2.900 TC (trillion cycles)." - # can see cycles balance of other accounts - assert_command dfx cycles balance --owner "$ALICE" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob - assert_eq "1.700 TC (trillion cycles)." + # can see cycles balance of other accounts + assert_command dfx cycles balance --owner "$ALICE" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "1.700 TC (trillion cycles)." - assert_command dfx cycles balance --owner "$ALICE" --subaccount "$ALICE_SUBACCT1" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob - assert_eq "3.750 TC (trillion cycles)." + assert_command dfx cycles balance --owner "$ALICE" --subaccount "$ALICE_SUBACCT1" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "3.750 TC (trillion cycles)." - assert_command dfx cycles balance --owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity anonymous - assert_eq "2.900 TC (trillion cycles)." + assert_command dfx cycles balance --owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity anonymous + assert_eq "2.900 TC (trillion cycles)." } @test "transfer" { - ALICE=$(dfx identity get-principal --identity alice) - ALICE_SUBACCT1="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - ALICE_SUBACCT1_CANDID="\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" - ALICE_SUBACCT2="9C9B9A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - ALICE_SUBACCT2_CANDID="\9C\9B\9A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" - BOB=$(dfx identity get-principal --identity bob) - BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE=$(dfx identity get-principal --identity alice) + ALICE_SUBACCT1="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT1_CANDID="\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + ALICE_SUBACCT2="9C9B9A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ALICE_SUBACCT2_CANDID="\9C\9B\9A\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + BOB=$(dfx identity get-principal --identity bob) + BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - assert_command dfx deploy cycles-ledger - assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 3_000_000_000_000;})" --identity cycle-giver - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT1_CANDID\"};cycles = 2_000_000_000_000;})" --identity cycle-giver - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT2_CANDID\"};cycles = 1_000_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 3_000_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT1_CANDID\"};cycles = 2_000_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\"; subaccount = opt blob \"$ALICE_SUBACCT2_CANDID\"};cycles = 1_000_000_000_000;})" --identity cycle-giver - # account to account - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice - assert_eq "3000000000000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "0 cycles." + # account to account + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "3000000000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "0 cycles." - assert_command dfx cycles transfer 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" - assert_eq "Transfer sent at block index 3" + assert_command dfx cycles transfer 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" + assert_eq "Transfer sent at block index 3" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice - assert_eq "2999899900000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "2999899900000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "100000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "100000 cycles." - # account to subaccount - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice - assert_eq "2999899900000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" - assert_eq "0 cycles." + # account to subaccount + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "2999899900000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "0 cycles." - assert_command dfx cycles transfer 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" --to-subaccount "$BOB_SUBACCT1" - assert_eq "Transfer sent at block index 4" + assert_command dfx cycles transfer 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" --to-subaccount "$BOB_SUBACCT1" + assert_eq "Transfer sent at block index 4" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice - assert_eq "2999799800000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice + assert_eq "2999799800000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" - assert_eq "100000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "100000 cycles." - # subaccount to account - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" - assert_eq "1000000000000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "100000 cycles." + # subaccount to account + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "1000000000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "100000 cycles." - # assert_command dfx canister call cycles-ledger icrc1_transfer "(record {to = record{owner = principal \"$BOB\"}; amount = 100_000;})" --identity alice - assert_command dfx cycles transfer 700000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" --from-subaccount "$ALICE_SUBACCT2" + # assert_command dfx canister call cycles-ledger icrc1_transfer "(record {to = record{owner = principal \"$BOB\"}; amount = 100_000;})" --identity alice + assert_command dfx cycles transfer 700000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" --from-subaccount "$ALICE_SUBACCT2" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" - assert_eq "999899300000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "999899300000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "800000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "800000 cycles." - # subaccount to subaccount - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" - assert_eq "999899300000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" - assert_eq "100000 cycles." + # subaccount to subaccount + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "999899300000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "100000 cycles." - assert_command dfx cycles transfer 400000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" --to-subaccount "$BOB_SUBACCT1" --from-subaccount "$ALICE_SUBACCT2" - assert_eq "Transfer sent at block index 6" + assert_command dfx cycles transfer 400000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" --to-subaccount "$BOB_SUBACCT1" --from-subaccount "$ALICE_SUBACCT2" + assert_eq "Transfer sent at block index 6" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" - assert_eq "999798900000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity alice --subaccount "$ALICE_SUBACCT2" + assert_eq "999798900000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" - assert_eq "500000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "500000 cycles." } @test "transfer deduplication" { - ALICE=$(dfx identity get-principal --identity alice) - BOB=$(dfx identity get-principal --identity bob) + ALICE=$(dfx identity get-principal --identity alice) + BOB=$(dfx identity get-principal --identity bob) - assert_command dfx deploy cycles-ledger - assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 3_000_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 3_000_000_000_000;})" --identity cycle-giver - assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "3000000000000 cycles." + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "3000000000000 cycles." - assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "0 cycles." + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "0 cycles." - t=$(current_time_nanoseconds) + t=$(current_time_nanoseconds) - assert_command dfx cycles transfer 100000 --created-at-time "$t" --memo 1 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "Transfer sent at block index 1" + assert_command dfx cycles transfer 100000 --created-at-time "$t" --memo 1 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "Transfer sent at block index 1" - assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "2999899900000 cycles." + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999899900000 cycles." - assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "100000 cycles." + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "100000 cycles." - # same memo and created-at-time: dupe - assert_command dfx cycles transfer 100000 --created-at-time "$t" --memo 1 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_contains "transaction is a duplicate of another transaction in block 1" - assert_contains "Transfer sent at block index 1" + # same memo and created-at-time: dupe + assert_command dfx cycles transfer 100000 --created-at-time "$t" --memo 1 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_contains "transaction is a duplicate of another transaction in block 1" + assert_contains "Transfer sent at block index 1" - assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "2999899900000 cycles." + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999899900000 cycles." - assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "100000 cycles." + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "100000 cycles." - # different memo and same created-at-time same: not dupe - assert_command dfx cycles transfer 100000 --created-at-time "$t" --memo 2 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_contains "Transfer sent at block index 2" + # different memo and same created-at-time same: not dupe + assert_command dfx cycles transfer 100000 --created-at-time "$t" --memo 2 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_contains "Transfer sent at block index 2" - assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "2999799800000 cycles." + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999799800000 cycles." - assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "200000 cycles." + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "200000 cycles." - # same memo and different created-at-time same: not dupe - assert_command dfx cycles transfer 100000 --created-at-time $((t+1)) --memo 1 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_contains "Transfer sent at block index 3" + # same memo and different created-at-time same: not dupe + assert_command dfx cycles transfer 100000 --created-at-time $((t+1)) --memo 1 --identity alice --to-owner "$BOB" --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_contains "Transfer sent at block index 3" - assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "2999699700000 cycles." + assert_command dfx cycles balance --precise --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "2999699700000 cycles." - assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_eq "300000 cycles." + assert_command dfx cycles balance --precise --identity bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "300000 cycles." } @test "howto" { - # This is the equivalent of https://www.notion.so/dfinityorg/How-to-install-and-test-the-cycles-ledger-521c9f3c410f4a438514a03e35464299 - ALICE=$(dfx identity get-principal --identity alice) - BOB=$(dfx identity get-principal --identity bob) + # This is the equivalent of https://www.notion.so/dfinityorg/How-to-install-and-test-the-cycles-ledger-521c9f3c410f4a438514a03e35464299 + ALICE=$(dfx identity get-principal --identity alice) + BOB=$(dfx identity get-principal --identity bob) - assert_command dfx deploy cycles-ledger - assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 + assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-depositor --argument "(record {ledger_id = principal \"$(dfx canister id cycles-ledger)\"})" --with-cycles 10000000000000 - assert_command dfx ledger balance --identity cycle-giver - assert_eq "1000000000.00000000 ICP" + assert_command dfx ledger balance --identity cycle-giver + assert_eq "1000000000.00000000 ICP" - assert_command dfx canister status cycles-depositor - assert_contains "Balance: 10_000_000_000_000 Cycles" + assert_command dfx canister status cycles-depositor + assert_contains "Balance: 10_000_000_000_000 Cycles" - dfx canister status cycles-depositor + dfx canister status cycles-depositor - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise - assert_eq "0 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "0 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise - assert_eq "0 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise + assert_eq "0 cycles." - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 500_000_000;})" --identity cycle-giver - assert_eq "(record { balance = 500_000_000 : nat; txid = 0 : nat })" + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$ALICE\";};cycles = 500_000_000;})" --identity cycle-giver + assert_eq "(record { balance = 500_000_000 : nat; txid = 0 : nat })" - assert_command dfx canister status cycles-depositor - assert_contains "Balance: 9_999_500_000_000 Cycles" + assert_command dfx canister status cycles-depositor + assert_contains "Balance: 9_999_500_000_000 Cycles" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise - assert_eq "500000000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "500000000 cycles." - assert_command dfx cycles transfer 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" - assert_eq "Transfer sent at block index 1" + assert_command dfx cycles transfer 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" + assert_eq "Transfer sent at block index 1" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise - assert_eq "399900000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "399900000 cycles." - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise - assert_eq "100000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --precise + assert_eq "100000 cycles." - assert_command dfx canister call cycles-ledger send "(record {amount = 100_000;to = principal \"$(dfx canister id cycles-depositor)\"})" --identity alice - assert_eq "(variant { Ok = 2 : nat })" + assert_command dfx canister call cycles-ledger send "(record {amount = 100_000;to = principal \"$(dfx canister id cycles-depositor)\"})" --identity alice + assert_eq "(variant { Ok = 2 : nat })" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise - assert_eq "299800000 cycles." + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --precise + assert_eq "299800000 cycles." - assert_command dfx canister status cycles-depositor - assert_contains "Balance: 9_999_500_100_000 Cycles" + assert_command dfx canister status cycles-depositor + assert_contains "Balance: 9_999_500_100_000 Cycles" }