From b022e493dbfa79bf40776c277cbd2860e4b734ad Mon Sep 17 00:00:00 2001 From: Eric Swanson Date: Tue, 17 Oct 2023 11:38:38 -0700 Subject: [PATCH] format, update docs --- CHANGELOG.md | 6 +- docs/cli-reference/dfx-cycles.md | 62 ++- e2e/tests-dfx/cycles-ledger.bash | 588 ++++++++++---------- src/dfx/src/commands/cycles/top_up.rs | 27 +- src/dfx/src/commands/cycles/transfer.rs | 22 +- src/dfx/src/lib/operations/cycles_ledger.rs | 5 +- 6 files changed, 371 insertions(+), 339 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbe9c4b45..d4c3c7487f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,10 @@ The message "transaction is a duplicate of another transaction in block ...", pr This won't work on mainnet yet, but can work locally after installing the cycles ledger. -Added the following subcommands and variants: +Added the following subcommands: - `dfx cycles balance` - - `dfx cycles transfer --to-owner ` (transfer from one account to another account) - - `dfx cycles transfer --top-up ` (transfer from an account to a canister) + - `dfx cycles transfer ` (transfer from one account to another account) + - `dfx cycles top-up ` (transfer from an account to a canister) ## Dependencies diff --git a/docs/cli-reference/dfx-cycles.md b/docs/cli-reference/dfx-cycles.md index c089b70878..7398fc60cf 100644 --- a/docs/cli-reference/dfx-cycles.md +++ b/docs/cli-reference/dfx-cycles.md @@ -70,25 +70,20 @@ dfx cycles balance --owner raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j Use the `dfx cycles transfer` command to transfer cycles from your account to another account. -The source of the transferred cycles is always the cycles ledger account associated with your identity's principal, or one of its subaccounts. - -The destination of the transferred cycles is one of the following: -- A cycles ledger account associated with another identity's principal, or one of its subaccounts. This mode uses the `--to-owner` and `--to-subaccount` options. -- A canister. This mode uses the `--top-up` option. - ### Basic usage ``` bash -dfx cycles transfer [options] +dfx cycles transfer [options] ``` ### Arguments You must specify the following argument for the `dfx cycles transfer` command. -| Argument | Description | -|--------------|-----------------------------------| -| `` | The number of cycles to transfer. | +| Argument | Description | +|------------|-----------------------------------| +| `` | The principal of the account to which you want to transfer cycles. | +| `` | The number of cycles to transfer. | ### Options @@ -96,11 +91,8 @@ You can specify the following options for the `dfx cycles transfer` command. | Option | Description | |----------------------------------|----------------------------------------------------------------------------------------| -| `--top-up ` | The canister which you want to top up. | -| `--to-owner ` | The principal of the account to which you want to transfer cycles. | | `--to-subaccount ` | The subaccount to which you want to transfer cycles. | | `--from-subaccount ` | The subaccount from which you want to transfer cycles. | -| `--fee ` | Specifies a transaction fee. Can only passed in `--to-owner` mode. | | `--memo ` | Specifies a numeric memo for this transaction. Can only be passed in `--to-owner mode. | | `--created-at-time ` | Specify the timestamp-nanoseconds for the `created_at_time` field on the transfer request. Useful for controlling transaction-de-duplication. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | @@ -109,17 +101,53 @@ You can specify the following options for the `dfx cycles transfer` command. Transfer 1 billion cycles to another account: ``` bash -dfx cycles transfer 1000000000 --to-owner raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j-dcecz-kae --network ic +dfx cycles transfer raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j-dcecz-kae 1000000000 --network ic ``` Transfer from a subaccount: ``` bash -dfx cycles transfer 1000000000 --from-subaccount 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f --to-owner raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j-dcecz-kae --network ic +dfx cycles transfer raxcz-bidhr-evrzj-qyivt-nht5a-eltcc-24qfc-o6cvi-hfw7j-dcecz-kae 1000000000 --from-subaccount 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f --network ic +``` + +## dfx cycles top-up + +Use the `dfx cycles top-up` command to send cycles from your account to a canister. + +### Basic usage + +``` bash +dfx cycles top-up [options] +``` + +### Arguments + +You must specify the following argument for the `dfx cycles transfer` command. + +| Argument | Description | +|------------|-------------------------------------------------------------------------| +| `` | The name of a canister in the current project, or a canister principal. | +| `` | The number of cycles to transfer. | + +### Options + +You can specify the following options for the `dfx cycles top-up` command. + +| Option | Description | +|----------------------------------|----------------------------------------------------------------------------------------| +| `--from-subaccount ` | The subaccount from which you want to transfer cycles. | +| `--created-at-time ` | Specify the timestamp-nanoseconds for the `created_at_time` field on the transfer request. Useful for controlling transaction-de-duplication. https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- | + +### Examples + +Send cycles to a canister in your project: + +``` bash +dfx cycles top-up my_backend 1000000000 --network ic ``` -Transfer to (top up) a canister: +Send cycles to a canister by principal: ``` bash -dfx cycles transfer 1000000000 --top-up bkyz2-fmaaa-aaaaa-qaaaq-cai --network ic +dfx cycles top-up bkyz2-fmaaa-aaaaa-qaaaq-cai 1000000000 --network ic ``` diff --git a/e2e/tests-dfx/cycles-ledger.bash b/e2e/tests-dfx/cycles-ledger.bash index 9c23ff061e..685ac4f072 100644 --- a/e2e/tests-dfx/cycles-ledger.bash +++ b/e2e/tests-dfx/cycles-ledger.bash @@ -4,29 +4,29 @@ 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 } add_cycles_ledger_canisters_to_project() { - jq -s '.[0] * .[1]' ../dfx.json dfx.json | sponge dfx.json + jq -s '.[0] * .[1]' ../dfx.json dfx.json | sponge dfx.json } current_time_nanoseconds() { @@ -34,381 +34,383 @@ 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 "$BOB" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + 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 "$BOB" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --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 cycles transfer "$BOB" 700000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --from-subaccount "$ALICE_SUBACCT2" + assert_eq "Transfer sent at block index 5" - 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 "$BOB" 400000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --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 "$BOB" 100000 --created-at-time "$t" --memo 1 --identity alice --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 "$BOB" 100000 --created-at-time "$t" --memo 1 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + # shellcheck disable=SC2154 + assert_contains "transaction is a duplicate of another transaction in block 1" "$stderr" + # shellcheck disable=SC2154 + assert_eq "Transfer sent at block index 1" "$stdout" - 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 "$BOB" 100000 --created-at-time "$t" --memo 2 --identity alice --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 "$BOB" 100000 --created-at-time $((t+1)) --memo 1 --identity alice --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 "top up canister principal check" { - BOB=$(dfx identity get-principal --identity bob) + BOB=$(dfx identity get-principal --identity bob) - assert_command dfx deploy cycles-ledger + assert_command dfx deploy cycles-ledger - assert_command_fail dfx cycles top-up "$BOB" 600000 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" - assert_contains "Invalid receiver: $BOB. Make sure the receiver is a canister." + assert_command_fail dfx cycles top-up "$BOB" 600000 --identity alice --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_contains "Invalid receiver: $BOB. Make sure the receiver is a canister." } @test "top-up" { - dfx_new - add_cycles_ledger_canisters_to_project - install_cycles_ledger_canisters - - BOB=$(dfx identity get-principal --identity bob) - BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - BOB_SUBACCT1_CANDID="\7C\7B\7A\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_SUBACCT2="6C6B6A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - BOB_SUBACCT2_CANDID="\6C\6B\6A\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" - - 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 - - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_400_000_000_000;})" --identity cycle-giver - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT1_CANDID\"};cycles = 2_600_000_000_000;})" --identity cycle-giver - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT2_CANDID\"};cycles = 2_700_000_000_000;})" --identity cycle-giver - - # account to canister - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "2400000000000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_000_000_000 Cycles" - - assert_command dfx cycles top-up e2e_project_backend 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob - - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "2399899900000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_000_100_000 Cycles" - - # subaccount to canister - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" - assert_eq "2600000000000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_000_100_000 Cycles" - - assert_command dfx cycles top-up e2e_project_backend 300000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --from-subaccount "$BOB_SUBACCT1" - - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" - assert_eq "2599899700000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_000_400_000 Cycles" - - # subaccount to canister - by canister id - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT2" - assert_eq "2700000000000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_000_400_000 Cycles" - - assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" 600000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --from-subaccount "$BOB_SUBACCT2" - - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT2" - assert_eq "2699899400000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_001_000_000 Cycles" + dfx_new + add_cycles_ledger_canisters_to_project + install_cycles_ledger_canisters + + BOB=$(dfx identity get-principal --identity bob) + BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT1_CANDID="\7C\7B\7A\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_SUBACCT2="6C6B6A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT2_CANDID="\6C\6B\6A\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" + + 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 + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_400_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT1_CANDID\"};cycles = 2_600_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT2_CANDID\"};cycles = 2_700_000_000_000;})" --identity cycle-giver + + # account to canister + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2400000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_000_000 Cycles" + + assert_command dfx cycles top-up e2e_project_backend 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2399899900000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_100_000 Cycles" + + # subaccount to canister + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "2600000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_100_000 Cycles" + + assert_command dfx cycles top-up e2e_project_backend 300000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --from-subaccount "$BOB_SUBACCT1" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT1" + assert_eq "2599899700000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_400_000 Cycles" + + # subaccount to canister - by canister id + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT2" + assert_eq "2700000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_400_000 Cycles" + + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" 600000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob --from-subaccount "$BOB_SUBACCT2" + + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob --subaccount "$BOB_SUBACCT2" + assert_eq "2699899400000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_001_000_000 Cycles" } @test "top-up deduplication" { - dfx_new - add_cycles_ledger_canisters_to_project - install_cycles_ledger_canisters - - BOB=$(dfx identity get-principal --identity bob) - BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - BOB_SUBACCT1_CANDID="\7C\7B\7A\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_SUBACCT2="6C6B6A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - BOB_SUBACCT2_CANDID="\6C\6B\6A\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" - - 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 - - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_400_000_000_000;})" --identity cycle-giver - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT1_CANDID\"};cycles = 2_600_000_000_000;})" --identity cycle-giver - assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT2_CANDID\"};cycles = 2_700_000_000_000;})" --identity cycle-giver - - # account to canister - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "2400000000000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_000_000_000 Cycles" - - t=$(current_time_nanoseconds) - assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time "$t" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity 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 bob - assert_eq "2399899900000 cycles." - assert_command dfx canister status e2e_project_backend - assert_contains "Balance: 3_100_000_100_000 Cycles" - - # same created-at-time: dupe - assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time "$t" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob - assert_contains "transaction is a duplicate of another transaction in block 3" - assert_contains "Transfer sent at block index 3" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "2399899900000 cycles." - - # different created-at-time: not dupe - assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time $((t+1)) 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob - assert_eq "Transfer sent at block index 4" - assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob - assert_eq "2399799800000 cycles." + dfx_new + add_cycles_ledger_canisters_to_project + install_cycles_ledger_canisters + + BOB=$(dfx identity get-principal --identity bob) + BOB_SUBACCT1="7C7B7A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT1_CANDID="\7C\7B\7A\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_SUBACCT2="6C6B6A030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + BOB_SUBACCT2_CANDID="\6C\6B\6A\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" + + 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 + + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\";};cycles = 2_400_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT1_CANDID\"};cycles = 2_600_000_000_000;})" --identity cycle-giver + assert_command dfx canister call cycles-depositor deposit "(record {to = record{owner = principal \"$BOB\"; subaccount = opt blob \"$BOB_SUBACCT2_CANDID\"};cycles = 2_700_000_000_000;})" --identity cycle-giver + + # account to canister + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2400000000000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_000_000 Cycles" + + t=$(current_time_nanoseconds) + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time "$t" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity 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 bob + assert_eq "2399899900000 cycles." + assert_command dfx canister status e2e_project_backend + assert_contains "Balance: 3_100_000_100_000 Cycles" + + # same created-at-time: dupe + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time "$t" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_contains "transaction is a duplicate of another transaction in block 3" + assert_contains "Transfer sent at block index 3" + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2399899900000 cycles." + + # different created-at-time: not dupe + assert_command dfx cycles top-up "$(dfx canister id e2e_project_backend)" --created-at-time $((t+1)) 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity bob + assert_eq "Transfer sent at block index 4" + assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob + assert_eq "2399799800000 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 "$BOB" 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + 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 cycles top-up cycles-depositor 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice - assert_eq "Transfer sent at block index 2" + assert_command dfx cycles top-up cycles-depositor 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice + assert_eq "Transfer sent at block index 2" - 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" } diff --git a/src/dfx/src/commands/cycles/top_up.rs b/src/dfx/src/commands/cycles/top_up.rs index 3d481e435b..ac2cfe9222 100644 --- a/src/dfx/src/commands/cycles/top_up.rs +++ b/src/dfx/src/commands/cycles/top_up.rs @@ -4,18 +4,18 @@ use crate::lib::nns_types::account_identifier::Subaccount; use crate::lib::operations::cycles_ledger; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::cycle_amount_parser; -use anyhow::Context; use candid::Principal; use clap::Parser; +use slog::warn; use std::time::{SystemTime, UNIX_EPOCH}; /// Send cycles to a canister. #[derive(Parser)] pub struct TopUpOpts { - /// Transfer cycles to this canister. + /// Send cycles to this canister. to: String, - /// The amount of cycles to send. + /// The number of cycles to send. #[arg(value_parser = cycle_amount_parser)] amount: u128, @@ -23,10 +23,6 @@ pub struct TopUpOpts { #[arg(long)] from_subaccount: Option, - /// Transfer cycles to this subaccount. - #[arg(long, conflicts_with("top_up"))] - to_subaccount: Option, - /// Transaction timestamp, in nanoseconds, for use in controlling transaction-deduplication, default is system-time. /// https://internetcomputer.org/docs/current/developer-docs/integrations/icrc-1/#transaction-deduplication- #[arg(long)] @@ -55,7 +51,7 @@ pub async fn exec(env: &dyn Environment, opts: TopUpOpts) -> DfxResult { let to = get_canister_id(env, &opts.to)?; let from_subaccount = opts.from_subaccount.map(|x| x.0); - let block_index = cycles_ledger::send( + let result = cycles_ledger::send( agent, to, amount, @@ -63,13 +59,14 @@ pub async fn exec(env: &dyn Environment, opts: TopUpOpts) -> DfxResult { from_subaccount, opts.cycles_ledger_canister_id, ) - .await - .with_context(|| { - format!( - "If you retry this operation, use --created-at-time {}", - created_at_time - ) - })?; + .await; + if result.is_err() && opts.created_at_time.is_none() { + warn!( + env.get_logger(), + "If you retry this operation, use --created-at-time {}", created_at_time + ); + } + let block_index = result?; println!("Transfer sent at block index {block_index}"); diff --git a/src/dfx/src/commands/cycles/transfer.rs b/src/dfx/src/commands/cycles/transfer.rs index 5c50cfa6a8..97c1cf9d01 100644 --- a/src/dfx/src/commands/cycles/transfer.rs +++ b/src/dfx/src/commands/cycles/transfer.rs @@ -4,9 +4,9 @@ use crate::lib::nns_types::account_identifier::Subaccount; use crate::lib::operations::cycles_ledger; use crate::lib::root_key::fetch_root_key_if_needed; use crate::util::clap::parsers::cycle_amount_parser; -use anyhow::Context; use candid::Principal; use clap::Parser; +use slog::warn; use std::time::{SystemTime, UNIX_EPOCH}; /// Transfer cycles to another principal. @@ -15,7 +15,7 @@ pub struct TransferOpts { /// Transfer cycles to this principal. to: Principal, - /// The amount of cycles to send. + /// The number of cycles to send. #[arg(value_parser = cycle_amount_parser)] amount: u128, @@ -59,8 +59,9 @@ pub async fn exec(env: &dyn Environment, opts: TransferOpts) -> DfxResult { let from_subaccount = opts.from_subaccount.map(|x| x.0); let to_subaccount = opts.to_subaccount.map(|x| x.0); - let block_index = cycles_ledger::transfer( + let result = cycles_ledger::transfer( agent, + env.get_logger(), amount, from_subaccount, opts.to, @@ -69,13 +70,14 @@ pub async fn exec(env: &dyn Environment, opts: TransferOpts) -> DfxResult { opts.memo, opts.cycles_ledger_canister_id, ) - .await - .with_context(|| { - format!( - "If you retry this operation, use --created-at-time {}", - created_at_time - ) - })?; + .await; + if result.is_err() && opts.created_at_time.is_none() { + warn!( + env.get_logger(), + "If you retry this operation, use --created-at-time {}", created_at_time + ); + } + let block_index = result?; println!("Transfer sent at block index {block_index}"); diff --git a/src/dfx/src/lib/operations/cycles_ledger.rs b/src/dfx/src/lib/operations/cycles_ledger.rs index 72700117e0..0ef996f188 100644 --- a/src/dfx/src/lib/operations/cycles_ledger.rs +++ b/src/dfx/src/lib/operations/cycles_ledger.rs @@ -11,6 +11,7 @@ use ic_utils::call::SyncCall; use ic_utils::Canister; use icrc_ledger_types::icrc1; use icrc_ledger_types::icrc1::transfer::{BlockIndex, TransferError}; +use slog::{info, Logger}; const ICRC1_BALANCE_OF_METHOD: &str = "icrc1_balance_of"; const ICRC1_TRANSFER_METHOD: &str = "icrc1_transfer"; @@ -50,6 +51,7 @@ pub async fn balance( pub async fn transfer( agent: &Agent, + logger: &Logger, amount: u128, from_subaccount: Option, owner: Principal, @@ -88,7 +90,8 @@ pub async fn transfer( { Ok(Ok(block_index)) => Ok(block_index), Ok(Err(TransferError::Duplicate { duplicate_of })) => { - println!( + info!( + logger, "{}", TransferError::Duplicate { duplicate_of: duplicate_of.clone()