diff --git a/Makefile b/Makefile index 889f43c..f9839bb 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ build: node_modules .PHONY: install .SILENT: install install: build - dfx canister install identity --mode reinstall --yes + dfx canister install identity --argument '(null)' --mode reinstall --yes $(shell make/install_ledger.sh) $(shell make/install_ledger_index.sh) dfx canister install github --mode reinstall --yes @@ -31,9 +31,9 @@ install: build .PHONY: upgrade .SILENT: upgrade upgrade: build - dfx canister install identity --mode=upgrade + dfx canister install identity --argument '(null)' --mode=upgrade dfx canister install icrc1_ledger --mode=upgrade - dfx canister install icrc1_index --mode=upgrade + dfx canister install icrc1_index --argument '(null)' --mode=upgrade dfx canister install github --mode=upgrade dfx canister install bounty --mode=upgrade @@ -41,6 +41,8 @@ upgrade: build .SILENT: clean clean: rm -fr .dfx + rm -fr node_modules + rm -fr target # tests .PHONY: test-1 diff --git a/icp/icrc1/index/ic-icrc1-index.wasm.gz b/icp/icrc1/index/ic-icrc1-index.wasm.gz index 4a5ce2f..7d020f3 100644 Binary files a/icp/icrc1/index/ic-icrc1-index.wasm.gz and b/icp/icrc1/index/ic-icrc1-index.wasm.gz differ diff --git a/icp/icrc1/index/index.did b/icp/icrc1/index/index.did index d5b495d..5cc7429 100644 --- a/icp/icrc1/index/index.did +++ b/icp/icrc1/index/index.did @@ -1,44 +1,91 @@ -type TxId = nat; +type Tokens = nat; -type Account = record { owner : principal; subaccount : opt blob }; +type InitArg = record { + ledger_id: principal; +}; + +type UpgradeArg = record { + ledger_id: opt principal; +}; + +type IndexArg = variant { + Init: InitArg; + Upgrade: UpgradeArg; +}; + +type GetBlocksRequest = record { + start : nat; + length : nat; +}; + +type Value = variant { + Blob : blob; + Text : text; + Nat : nat; + Nat64: nat64; + Int : int; + Array : vec Value; + Map : Map; +}; + +type Map = vec record { text; Value }; + +type Block = Value; + +type GetBlocksResponse = record { + chain_length: nat64; + blocks: vec Block; +}; + +type BlockIndex = nat; type SubAccount = blob; +type Account = record { owner : principal; subaccount : opt SubAccount }; + type Transaction = record { - kind : text; - mint : opt record { - amount : nat; - to : Account; - memo : opt blob; - created_at_time : opt nat64; - }; - burn : opt record { - amount : nat; - from : Account; - spender : opt Account; - memo : opt blob; - created_at_time : opt nat64; - }; - transfer : opt record { - amount : nat; - from : Account; - to : Account; - spender : opt Account; - memo : opt blob; - created_at_time : opt nat64; - fee : opt nat; - }; - approve : opt record { - amount : nat; - from : Account; - spender : opt Account; - expected_allowance : opt nat; - expires_at : opt nat64; - memo : opt blob; - created_at_time : opt nat64; - fee : opt nat; - }; - timestamp : nat64; + burn : opt Burn; + kind : text; + mint : opt Mint; + approve : opt Approve; + timestamp : nat64; + transfer : opt Transfer; +}; + +type Approve = record { + fee : opt nat; + from : Account; + memo : opt vec nat8; + created_at_time : opt nat64; + amount : nat; + expected_allowance : opt nat; + expires_at : opt nat64; + spender : Account; +}; + +type Burn = record { + from : Account; + memo : opt vec nat8; + created_at_time : opt nat64; + amount : nat; + spender : opt Account; +}; + +type Mint = record { + to : Account; + memo : opt vec nat8; + created_at_time : opt nat64; + amount : nat; +}; + +type Transfer = record { + to : Account; + fee : opt nat; + from : Account; + memo : opt vec nat8; + created_at_time : opt nat64; + amount : nat; + spender : opt Account; }; type GetAccountTransactionsArgs = record { @@ -46,20 +93,21 @@ type GetAccountTransactionsArgs = record { // The txid of the last transaction seen by the client. // If None then the results will start from the most recent // txid. - start : opt TxId; + start : opt BlockIndex; // Maximum number of transactions to fetch. max_results : nat; }; type TransactionWithId = record { - id : TxId; + id : BlockIndex; transaction : Transaction; }; type GetTransactions = record { + balance : Tokens; transactions : vec TransactionWithId; // The txid of the oldest transaction the account has - oldest_tx_id : opt TxId; + oldest_tx_id : opt BlockIndex; }; type GetTransactionsErr = record { @@ -76,13 +124,20 @@ type ListSubaccountsArgs = record { start: opt SubAccount; }; -// The initialization parameters of the Index canister. -type InitArgs = record { - ledger_id : principal; +type Status = record { + num_blocks_synced : BlockIndex; }; -service : (InitArgs) -> { - get_account_transactions : (GetAccountTransactionsArgs) -> (GetTransactionsResult); - ledger_id : () -> (principal) query; - list_subaccounts : (ListSubaccountsArgs) -> (vec SubAccount) query; -} \ No newline at end of file +type FeeCollectorRanges = record { + ranges : vec record { Account; vec record { BlockIndex; BlockIndex } }; +} + +service : (index_arg: opt IndexArg) -> { + get_account_transactions : (GetAccountTransactionsArgs) -> (GetTransactionsResult) query; + get_blocks : (GetBlocksRequest) -> (GetBlocksResponse) query; + get_fee_collectors_ranges : () -> (FeeCollectorRanges) query; + icrc1_balance_of : (Account) -> (Tokens) query; + ledger_id : () -> (principal) query; + list_subaccounts : (ListSubaccountsArgs) -> (vec SubAccount) query; + status : () -> (Status) query; +} diff --git a/icp/icrc1/ledger/ic-icrc1-ledger.wasm.gz b/icp/icrc1/ledger/ic-icrc1-ledger.wasm.gz index 0899c8d..ae4c78a 100644 Binary files a/icp/icrc1/ledger/ic-icrc1-ledger.wasm.gz and b/icp/icrc1/ledger/ic-icrc1-ledger.wasm.gz differ diff --git a/icp/icrc1/ledger/ledger.did b/icp/icrc1/ledger/ledger.did index c0e59ef..e2799db 100644 --- a/icp/icrc1/ledger/ledger.did +++ b/icp/icrc1/ledger/ledger.did @@ -6,6 +6,52 @@ type Timestamp = nat64; type Duration = nat64; type Tokens = nat; type TxIndex = nat; +type Allowance = record { allowance : nat; expires_at : opt Timestamp }; +type AllowanceArgs = record { account : Account; spender : Account }; +type Approve = record { + fee : opt nat; + from : Account; + memo : opt blob; + created_at_time : opt Timestamp; + amount : nat; + expected_allowance : opt nat; + expires_at : opt Timestamp; + spender : Account; +}; +type ApproveArgs = record { + fee : opt nat; + memo : opt blob; + from_subaccount : opt blob; + created_at_time : opt Timestamp; + amount : nat; + expected_allowance : opt nat; + expires_at : opt Timestamp; + spender : Account; +}; +type ApproveError = variant { + GenericError : record { message : text; error_code : nat }; + TemporarilyUnavailable; + Duplicate : record { duplicate_of : BlockIndex }; + BadFee : record { expected_fee : nat }; + AllowanceChanged : record { current_allowance : nat }; + CreatedInFuture : record { ledger_time : Timestamp }; + TooOld; + Expired : record { ledger_time : Timestamp }; + InsufficientFunds : record { balance : nat }; +}; +type ApproveResult = variant { Ok : BlockIndex; Err : ApproveError }; + +type HttpRequest = record { + url : text; + method : text; + body : blob; + headers : vec record { text; text }; +}; +type HttpResponse = record { + body : blob; + headers : vec record { text; text }; + status_code : nat16; +}; type Account = record { owner : principal; @@ -26,7 +72,7 @@ type TransferError = variant { BadBurn : record { min_burn_amount : Tokens }; InsufficientFunds : record { balance : Tokens }; TooOld; - CreatedInFuture : record { ledger_time : nat64 }; + CreatedInFuture : record { ledger_time : Timestamp }; TemporarilyUnavailable; Duplicate : record { duplicate_of : BlockIndex }; GenericError : record { error_code : nat; message : text }; @@ -60,29 +106,47 @@ type InitArgs = record { token_name : text; metadata : vec record { text; MetadataValue }; initial_balances : vec record { Account; nat }; + feature_flags : opt FeatureFlags; + maximum_number_of_accounts : opt nat64; + accounts_overflow_trim_quantity : opt nat64; archive_options : record { num_blocks_to_archive : nat64; + max_transactions_per_response : opt nat64; trigger_threshold : nat64; max_message_size_bytes : opt nat64; cycles_for_archive_creation : opt nat64; node_max_memory_size_bytes : opt nat64; controller_id : principal; + more_controller_ids : opt vec principal; }; - feature_flags : opt FeatureFlags; }; type ChangeFeeCollector = variant { Unset; SetTo: Account; }; +type ChangeArchiveOptions = record { + num_blocks_to_archive : opt nat64; + max_transactions_per_response : opt nat64; + trigger_threshold : opt nat64; + max_message_size_bytes : opt nat64; + cycles_for_archive_creation : opt nat64; + node_max_memory_size_bytes : opt nat64; + controller_id : opt principal; + more_controller_ids : opt vec principal; +}; + type UpgradeArgs = record { metadata : opt vec record { text; MetadataValue }; token_symbol : opt text; token_name : opt text; - transfer_fee : opt nat64; + transfer_fee : opt nat; change_fee_collector : opt ChangeFeeCollector; max_memo_length : opt nat16; feature_flags : opt FeatureFlags; + maximum_number_of_accounts: opt nat64; + accounts_overflow_trim_quantity: opt nat64; + change_archive_options : opt ChangeArchiveOptions; }; type LedgerArg = variant { @@ -158,38 +222,47 @@ type TransactionRange = record { type QueryArchiveFn = func (GetTransactionsRequest) -> (TransactionRange) query; type Transaction = record { - kind : text; - mint : opt record { - amount : nat; - to : Account; - memo : opt blob; - created_at_time : opt nat64; - }; - burn : opt record { - amount : nat; - from : Account; - memo : opt blob; - created_at_time : opt nat64; - }; - transfer : opt record { - amount : nat; - from : Account; - to : Account; - memo : opt blob; - created_at_time : opt nat64; - fee : opt nat; - }; - timestamp : nat64; -}; - -type Value = variant { - Blob : blob; - Text : text; + burn : opt Burn; + kind : text; + mint : opt Mint; + approve : opt Approve; + timestamp : Timestamp; + transfer : opt Transfer; +}; + +type Burn = record { + from : Account; + memo : opt blob; + created_at_time : opt Timestamp; + amount : nat; + spender : opt Account; +}; + +type Mint = record { + to : Account; + memo : opt blob; + created_at_time : opt Timestamp; + amount : nat; +}; + +type Transfer = record { + to : Account; + fee : opt nat; + from : Account; + memo : opt blob; + created_at_time : opt Timestamp; + amount : nat; + spender : opt Account; +}; + +type Value = variant { + Blob : blob; + Text : text; Nat : nat; - Nat64: nat64; + Nat64: nat64; Int : int; - Array : vec Value; - Map : Map; + Array : vec Value; + Map : Map; }; type Map = vec record { text; Value }; @@ -268,43 +341,7 @@ type DataCertificate = record { hash_tree : blob; }; -type ApproveArgs = record { - from_subaccount : opt Subaccount; - spender : Account; - amount : Tokens; - expected_allowance : opt Tokens; - expires_at : opt Timestamp; - fee : opt Tokens; - memo : opt blob; - created_at_time: opt Timestamp; -}; - -type ApproveError = variant { - BadFee : record { expected_fee : Tokens }; - InsufficientFunds : record { balance : Tokens }; - AllowanceChanged : record { current_allowance : Tokens }; - Expired : record { ledger_time : nat64 }; - TooOld; - CreatedInFuture : record { ledger_time : nat64 }; - Duplicate : record { duplicate_of : BlockIndex }; - TemporarilyUnavailable; - GenericError : record { error_code : nat; message : text }; -}; - -type ApproveResult = variant { - Ok : BlockIndex; - Err : ApproveError; -}; - -type AllowanceArgs = record { - account : Account; - spender : Account; -}; - -type Allowance = record { - allowance : Tokens; - expires_at : opt Timestamp; -}; +type StandardRecord = record { url : text; name : text }; type TransferFromArgs = record { spender_subaccount : opt Subaccount; @@ -327,13 +364,73 @@ type TransferFromError = variant { InsufficientFunds : record { balance : Tokens }; InsufficientAllowance : record { allowance : Tokens }; TooOld; - CreatedInFuture : record { ledger_time : nat64 }; + CreatedInFuture : record { ledger_time : Timestamp }; Duplicate : record { duplicate_of : BlockIndex }; TemporarilyUnavailable; GenericError : record { error_code : nat; message : text }; }; +type ArchiveInfo = record { + canister_id: principal; + block_range_start: BlockIndex; + block_range_end: BlockIndex; +}; + +type ICRC3Value = variant { + Blob : blob; + Text : text; + Nat : nat; + Int : int; + Array : vec ICRC3Value; + Map : vec record { text; ICRC3Value }; +}; + +type GetArchivesArgs = record { + // The last archive seen by the client. + // The Ledger will return archives coming + // after this one if set, otherwise it + // will return the first archives. + from : opt principal; +}; + +type GetArchivesResult = vec record { + // The id of the archive + canister_id : principal; + + // The first block in the archive + start : nat; + + // The last block in the archive + end : nat; +}; + +type GetBlocksResult = record { + // Total number of blocks in the + // block log + log_length : nat; + + blocks : vec record { id : nat; block: ICRC3Value }; + + archived_blocks : vec record { + args : vec GetBlocksArgs; + callback : func (vec GetBlocksArgs) -> (GetBlocksResult) query; + }; +}; + +type ICRC3DataCertificate = record { + // See https://internetcomputer.org/docs/current/references/ic-interface-spec#certification + certificate : blob; + + // CBOR encoded hash_tree + hash_tree : blob; +}; + service : (ledger_arg : LedgerArg) -> { + archives : () -> (vec ArchiveInfo) query; + get_transactions : (GetTransactionsRequest) -> (GetTransactionsResponse) query; + get_blocks : (GetBlocksArgs) -> (GetBlocksResponse) query; + get_data_certificate : () -> (DataCertificate) query; + icrc1_name : () -> (text) query; icrc1_symbol : () -> (text) query; icrc1_decimals : () -> (nat8) query; @@ -343,11 +440,14 @@ service : (ledger_arg : LedgerArg) -> { icrc1_minting_account : () -> (opt Account) query; icrc1_balance_of : (Account) -> (Tokens) query; icrc1_transfer : (TransferArg) -> (TransferResult); - icrc1_supported_standards : () -> (vec record { name : text; url : text }) query; - get_transactions : (GetTransactionsRequest) -> (GetTransactionsResponse) query; - get_blocks : (GetBlocksArgs) -> (GetBlocksResponse) query; - get_data_certificate : () -> (DataCertificate) query; + icrc1_supported_standards : () -> (vec StandardRecord) query; + icrc2_approve : (ApproveArgs) -> (ApproveResult); icrc2_allowance : (AllowanceArgs) -> (Allowance) query; icrc2_transfer_from : (TransferFromArgs) -> (TransferFromResult); -} \ No newline at end of file + + icrc3_get_archives : (GetArchivesArgs) -> (GetArchivesResult) query; + icrc3_get_tip_certificate : () -> (opt ICRC3DataCertificate) query; + icrc3_get_blocks : (vec GetBlocksArgs) -> (GetBlocksResult) query; + icrc3_supported_block_types : () -> (vec record { block_type : text; url : text }) query; +} diff --git a/make/install_ledger.sh b/make/install_ledger.sh index 6828a2f..64ecf8e 100755 --- a/make/install_ledger.sh +++ b/make/install_ledger.sh @@ -2,8 +2,8 @@ set -e -TOKEN_NAME=PROTK -TOKEN_SYMBOL=PRO +TOKEN_NAME="Local ckBTC" +TOKEN_SYMBOL=LckBTC PRE_MINTED_TOKENS=10_000_000_000 TRANSFER_FEE=10_000 TRIGGER_THRESHOLD=2000 @@ -11,36 +11,25 @@ NUM_OF_BLOCK_TO_ARCHIVE=1000 CYCLE_FOR_ARCHIVE_CREATION=10000000000000 FEATURE_FLAGS=true -# FIXME: this should be used as minting_account owner -MINTER_ACCOUNT_ID=$(dfx ledger account-id) -DEPLOY_ID=$(dfx identity get-principal) +MINTER=$(dfx identity get-principal) +dfx identity use default +DEFAULT=$(dfx identity get-principal) ARCHIVE_CONTROLLER=$(dfx identity get-principal) -dfx canister install icrc1_ledger --mode reinstall --yes --argument \ - " \ - (variant { \ - Init = record { \ - decimals = null; \ - token_symbol = \"${TOKEN_SYMBOL}\"; \ - transfer_fee = ${TRANSFER_FEE}; \ - metadata = vec {}; \ - minting_account = record { \ - owner = principal \"${DEPLOY_ID}\"; \ - subaccount = null; \ - }; \ - initial_balances = vec { record { record { owner = principal \"${DEPLOY_ID}\"; }; ${PRE_MINTED_TOKENS}; }; }; \ - fee_collector_account = null; \ - archive_options = record { \ - num_blocks_to_archive = ${NUM_OF_BLOCK_TO_ARCHIVE}; \ - trigger_threshold = ${TRIGGER_THRESHOLD}; \ - max_message_size_bytes = null; \ - cycles_for_archive_creation = opt ${CYCLE_FOR_ARCHIVE_CREATION}; \ - node_max_memory_size_bytes = null; \ - controller_id = principal \"${ARCHIVE_CONTROLLER}\"; \ - }; \ - max_memo_length = null; \ - token_name = \"${TOKEN_NAME}\"; \ - feature_flags = opt record{icrc2 = ${FEATURE_FLAGS}}; \ - } \ - }) \ - " +dfx canister install icrc1_ledger --mode reinstall --yes --argument "(variant { Init = +record { + token_symbol = \"${TOKEN_SYMBOL}\"; + token_name = \"${TOKEN_NAME}\"; + minting_account = record { owner = principal \"${MINTER}\" }; + transfer_fee = ${TRANSFER_FEE}; + metadata = vec {}; + feature_flags = opt record{icrc2 = ${FEATURE_FLAGS}}; + initial_balances = vec { record { record { owner = principal \"${DEFAULT}\"; }; ${PRE_MINTED_TOKENS}; }; }; + archive_options = record { + num_blocks_to_archive = ${NUM_OF_BLOCK_TO_ARCHIVE}; + trigger_threshold = ${TRIGGER_THRESHOLD}; + controller_id = principal \"${ARCHIVE_CONTROLLER}\"; + cycles_for_archive_creation = opt ${CYCLE_FOR_ARCHIVE_CREATION}; + }; + } +})" diff --git a/make/install_ledger_index.sh b/make/install_ledger_index.sh index 9de6b35..0cf40cf 100755 --- a/make/install_ledger_index.sh +++ b/make/install_ledger_index.sh @@ -2,7 +2,5 @@ set -e -DEPLOY_ID=$(dfx identity get-principal) - dfx canister install icrc1_index --mode reinstall --yes --argument \ - "(record { ledger_id = principal \"${DEPLOY_ID}\" })" + "(opt variant{Init = record {ledger_id = principal \"mxzaz-hqaaa-aaaar-qaada-cai\"}})"