diff --git a/e2e/tests-dfx/cycles-ledger.bash b/e2e/tests-dfx/cycles-ledger.bash index 84c401d244..3bfe2316d3 100644 --- a/e2e/tests-dfx/cycles-ledger.bash +++ b/e2e/tests-dfx/cycles-ledger.bash @@ -25,7 +25,11 @@ teardown() { standard_teardown } -@test "cycles ledger balance" { +current_time_nanoseconds() { + echo "$(date +%s)"000000000 +} + +@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" @@ -99,9 +103,7 @@ teardown() { assert_eq "2.900 TC (trillion cycles)." } -@test "cycles ledger transfer" { - copy_cycles_ledger - +@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" @@ -113,9 +115,9 @@ teardown() { 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 icp-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 icp-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 icp-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 @@ -123,9 +125,8 @@ teardown() { assert_command dfx cycles balance --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --precise --identity bob assert_eq "0 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 100000 --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" --identity alice --to-owner "$BOB" - # assert_eq "(variant { Ok = 3 : nat })" + 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." @@ -139,9 +140,8 @@ teardown() { 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 canister call cycles-ledger icrc1_transfer "(record {to = record{owner = principal \"$BOB\"}; amount = 100_000;})" --identity alice 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 "(variant { Ok = 3 : nat })" + 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." @@ -172,8 +172,8 @@ teardown() { 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 canister call cycles-ledger icrc1_transfer "(record {to = record{owner = principal \"$BOB\"}; amount = 100_000;})" --identity alice 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." @@ -182,7 +182,65 @@ teardown() { assert_eq "500000 cycles." } -@test "cycles ledger howto" { +@test "transfer deduplication" { + 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 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 bob --cycles-ledger-canister-id "$(dfx canister id cycles-ledger)" + assert_eq "0 cycles." + + 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 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." + + # 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 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" + + 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." + + # 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 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) diff --git a/src/dfx/src/commands/cycles/transfer.rs b/src/dfx/src/commands/cycles/transfer.rs index 3b2f5fb756..384ebed8d6 100644 --- a/src/dfx/src/commands/cycles/transfer.rs +++ b/src/dfx/src/commands/cycles/transfer.rs @@ -31,7 +31,8 @@ pub struct TransferOpts { #[arg(long, requires("to_owner"))] 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- + /// 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)] created_at_time: Option,