diff --git a/package-lock.json b/package-lock.json index f329ddb3..38664020 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,8 @@ "packages/sns", "packages/cmc", "packages/ckbtc", - "packages/ic-management" + "packages/ic-management", + "packages/ledger-icp" ], "devDependencies": { "@size-limit/esbuild": "^9.0.0", @@ -710,6 +711,10 @@ "resolved": "packages/ledger", "link": true }, + "node_modules/@dfinity/ledger-icp": { + "resolved": "packages/ledger-icp", + "link": true + }, "node_modules/@dfinity/nns": { "resolved": "packages/nns", "link": true @@ -7065,6 +7070,11 @@ "@dfinity/utils": "^0.0.23" } }, + "packages/ledger-icp": { + "version": "0.0.1", + "license": "Apache-2.0", + "devDependencies": {} + }, "packages/nns": { "name": "@dfinity/nns", "version": "0.16.8", @@ -7609,6 +7619,9 @@ "version": "file:packages/ledger", "requires": {} }, + "@dfinity/ledger-icp": { + "version": "file:packages/ledger-icp" + }, "@dfinity/nns": { "version": "file:packages/nns", "requires": { diff --git a/package.json b/package.json index 08a921e7..0c05b515 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "packages/sns", "packages/cmc", "packages/ckbtc", - "packages/ic-management" + "packages/ic-management", + "packages/ledger-icp" ], "scripts": { "did": "scripts/compile-idl-js", @@ -20,7 +21,7 @@ "protoc": "bash ./scripts/update_proto.sh", "test": "jest", "test-all": "npm ci && npm run build --workspace=packages/utils && npm run build --workspace=packages/ledger && npm run test --workspaces", - "docs": "node scripts/docs.js && prettier --write packages/nns/README.md packages/sns/README.md packages/cmc/README.md packages/utils/README.md packages/ledger/README.md packages/ckbtc/README.md packages/ic-management/README.md", + "docs": "node scripts/docs.js && prettier --write packages/nns/README.md packages/sns/README.md packages/cmc/README.md packages/utils/README.md packages/ledger-icp/README.md packages/ledger/README.md packages/ckbtc/README.md packages/ic-management/README.md", "build": "npm run build --workspaces", "size": "size-limit --json", "update:agent": "./scripts/update-agent" @@ -93,6 +94,17 @@ "@dfinity/utils" ] }, + { + "name": "@dfinity/ledger-icp", + "path": "./packages/ledger-icp/dist/index.js", + "limit": "4 kB", + "ignore": [ + "@dfinity/agent", + "@dfinity/candid", + "@dfinity/principal", + "@dfinity/utils" + ] + }, { "name": "@dfinity/nns", "path": "./packages/nns/dist/index.js", diff --git a/packages/ledger-icp/LICENSE b/packages/ledger-icp/LICENSE new file mode 100644 index 00000000..4874b73b --- /dev/null +++ b/packages/ledger-icp/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 DFINITY LLC. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/ledger-icp/README.md b/packages/ledger-icp/README.md new file mode 100644 index 00000000..78a2652f --- /dev/null +++ b/packages/ledger-icp/README.md @@ -0,0 +1,193 @@ +# ledger-icp-js + +A library for interfacing with the [ICP ledger](https://internetcomputer.org/icp-tokens/) on the Internet Computer. + +[![npm version](https://img.shields.io/npm/v/@dfinity/ledger-icp.svg?logo=npm)](https://www.npmjs.com/package/@dfinity/ledger-icp) [![GitHub license](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +> ℹ️ This library is meant to interface with the ICP ledger only. If you are looking to interact with Snses, ckBTC, or other ICRC tokens, use the [ledger-icrc-js](../ledger-icrc) library. + +## Table of contents + +- [Installation](#installation) +- [Usage](#usage) +- [Features](#features) +- [Resources](#resources) + +## Installation + +You can use `ledger-icp-js` by installing it in your project. + +```bash +npm i @dfinity/ledger-icp +``` + +The bundle needs peer dependencies, be sure that following resources are available in your project as well. + +```bash +npm i @dfinity/agent @dfinity/candid @dfinity/principal @dfinity/utils +``` + +## Usage + +The features are available through the class `LedgerCanister`. It has to be instantiated with a canister ID. + +e.g. fetching a token metadata. + +```ts +import { createAgent } from "@dfinity/utils"; + +const agent = await createAgent({ + identity, + host: HOST, +}); + +const { metadata } = LedgerCanister.create({ + agent, + canisterId: MY_LEDGER_CANISTER_ID, +}); + +const data = await metadata(); +``` + +## Features + +`ledger-icp-js` implements following features: + + + +### :factory: IcrcLedgerCanister + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L27) + +#### Methods + +- [create](#gear-create) +- [metadata](#gear-metadata) +- [transactionFee](#gear-transactionfee) +- [balance](#gear-balance) +- [transfer](#gear-transfer) +- [totalTokensSupply](#gear-totaltokenssupply) +- [transferFrom](#gear-transferfrom) +- [approve](#gear-approve) +- [allowance](#gear-allowance) + +##### :gear: create + +| Method | Type | +| -------- | ---------------------------------------------------------------------- | +| `create` | `(options: IcrcLedgerCanisterOptions<_SERVICE>) => IcrcLedgerCanister` | + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L28) + +##### :gear: metadata + +The token metadata (name, symbol, etc.). + +| Method | Type | +| ---------- | ------------------------------------------------------------- | +| `metadata` | `(params: QueryParams) => Promise` | + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L42) + +##### :gear: transactionFee + +The ledger transaction fees. + +| Method | Type | +| ---------------- | ------------------------------------------ | +| `transactionFee` | `(params: QueryParams) => Promise` | + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L50) + +##### :gear: balance + +Returns the balance for a given account provided as owner and with optional subaccount. + +| Method | Type | +| --------- | -------------------------------------------- | +| `balance` | `(params: BalanceParams) => Promise` | + +Parameters: + +- `params`: The parameters to get the balance of an account. + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L59) + +##### :gear: transfer + +Transfers tokens from the sender to the given account. + +| Method | Type | +| ---------- | --------------------------------------------- | +| `transfer` | `(params: TransferParams) => Promise` | + +Parameters: + +- `params`: The parameters to transfer tokens. + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L72) + +##### :gear: totalTokensSupply + +Returns the total supply of tokens. + +| Method | Type | +| ------------------- | ------------------------------------------ | +| `totalTokensSupply` | `(params: QueryParams) => Promise` | + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L88) + +##### :gear: transferFrom + +Transfers a token amount from the `from` account to the `to` account using the allowance of the spender's account (`SpenderAccount = { owner = caller; subaccount = spender_subaccount }`). The ledger draws the fees from the `from` account. + +Reference: https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-2/README.md#icrc2_transfer_from + +| Method | Type | +| -------------- | ------------------------------------------------- | +| `transferFrom` | `(params: TransferFromParams) => Promise` | + +Parameters: + +- `params`: The parameters to transfer tokens from to. + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L101) + +##### :gear: approve + +This method entitles the `spender` to transfer token `amount` on behalf of the caller from account `{ owner = caller; subaccount = from_subaccount }`. + +Reference: https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-2/README.md#icrc2_approve + +| Method | Type | +| --------- | -------------------------------------------- | +| `approve` | `(params: ApproveParams) => Promise` | + +Parameters: + +- `params`: The parameters to approve. + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L123) + +##### :gear: allowance + +Returns the token allowance that the `spender` account can transfer from the specified `account`, and the expiration time for that allowance, if any. + +Reference: https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-2/README.md#icrc2_allowance + +| Method | Type | +| ----------- | ------------------------------------------------- | +| `allowance` | `(params: AllowanceParams) => Promise` | + +Parameters: + +- `params`: The parameters to call the allowance. + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ledger/src/ledger.canister.ts#L145) + + + +## Resources + +- [Ledger & Tokenization Working Group Standards](https://github.com/dfinity/ICRC-1/) +- [ICP ledger](https://github.com/dfinity/ic/tree/master/rs/rosetta-api/icp_ledger) diff --git a/packages/ledger-icp/candid/ledger.certified.idl.d.ts b/packages/ledger-icp/candid/ledger.certified.idl.d.ts new file mode 100644 index 00000000..8e1474b8 --- /dev/null +++ b/packages/ledger-icp/candid/ledger.certified.idl.d.ts @@ -0,0 +1,2 @@ +import type { IDL } from "@dfinity/candid"; +export const idlFactory: IDL.InterfaceFactory; diff --git a/packages/ledger-icp/candid/ledger.certified.idl.js b/packages/ledger-icp/candid/ledger.certified.idl.js new file mode 100644 index 00000000..a3ab1bf3 --- /dev/null +++ b/packages/ledger-icp/candid/ledger.certified.idl.js @@ -0,0 +1,324 @@ +/* Do not edit. Compiled with ./scripts/compile-idl-js from packages/ledger-icp/candid/ledger.did */ +export const idlFactory = ({ IDL }) => { + const SubAccount = IDL.Vec(IDL.Nat8); + const Account = IDL.Record({ + 'owner' : IDL.Principal, + 'subaccount' : IDL.Opt(SubAccount), + }); + const FeatureFlags = IDL.Record({ 'icrc2' : IDL.Bool }); + const UpgradeArgs = IDL.Record({ + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const Tokens = IDL.Record({ 'e8s' : IDL.Nat64 }); + const TextAccountIdentifier = IDL.Text; + const Duration = IDL.Record({ 'secs' : IDL.Nat64, 'nanos' : IDL.Nat32 }); + const ArchiveOptions = IDL.Record({ + 'num_blocks_to_archive' : IDL.Nat64, + 'trigger_threshold' : IDL.Nat64, + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'cycles_for_archive_creation' : IDL.Opt(IDL.Nat64), + 'node_max_memory_size_bytes' : IDL.Opt(IDL.Nat64), + 'controller_id' : IDL.Principal, + }); + const InitArgs = IDL.Record({ + 'send_whitelist' : IDL.Vec(IDL.Principal), + 'token_symbol' : IDL.Opt(IDL.Text), + 'transfer_fee' : IDL.Opt(Tokens), + 'minting_account' : TextAccountIdentifier, + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'accounts_overflow_trim_quantity' : IDL.Opt(IDL.Nat64), + 'transaction_window' : IDL.Opt(Duration), + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'archive_options' : IDL.Opt(ArchiveOptions), + 'initial_values' : IDL.Vec(IDL.Tuple(TextAccountIdentifier, Tokens)), + 'token_name' : IDL.Opt(IDL.Text), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const LedgerCanisterPayload = IDL.Variant({ + 'Upgrade' : IDL.Opt(UpgradeArgs), + 'Init' : InitArgs, + }); + const BlockIndex = IDL.Nat64; + const GetBlocksArgs = IDL.Record({ + 'start' : BlockIndex, + 'length' : IDL.Nat64, + }); + const Memo = IDL.Nat64; + const AccountIdentifier = IDL.Vec(IDL.Nat8); + const TimeStamp = IDL.Record({ 'timestamp_nanos' : IDL.Nat64 }); + const Operation = IDL.Variant({ + 'Approve' : IDL.Record({ + 'fee' : Tokens, + 'from' : AccountIdentifier, + 'allowance_e8s' : IDL.Int, + 'allowance' : Tokens, + 'expires_at' : IDL.Opt(TimeStamp), + 'spender' : AccountIdentifier, + }), + 'Burn' : IDL.Record({ + 'from' : AccountIdentifier, + 'amount' : Tokens, + 'spender' : IDL.Opt(AccountIdentifier), + }), + 'Mint' : IDL.Record({ 'to' : AccountIdentifier, 'amount' : Tokens }), + 'Transfer' : IDL.Record({ + 'to' : AccountIdentifier, + 'fee' : Tokens, + 'from' : AccountIdentifier, + 'amount' : Tokens, + }), + 'TransferFrom' : IDL.Record({ + 'to' : AccountIdentifier, + 'fee' : Tokens, + 'from' : AccountIdentifier, + 'amount' : Tokens, + 'spender' : AccountIdentifier, + }), + }); + const Transaction = IDL.Record({ + 'memo' : Memo, + 'icrc1_memo' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'operation' : IDL.Opt(Operation), + 'created_at_time' : TimeStamp, + }); + const Block = IDL.Record({ + 'transaction' : Transaction, + 'timestamp' : TimeStamp, + 'parent_hash' : IDL.Opt(IDL.Vec(IDL.Nat8)), + }); + const BlockRange = IDL.Record({ 'blocks' : IDL.Vec(Block) }); + const QueryArchiveError = IDL.Variant({ + 'BadFirstBlockIndex' : IDL.Record({ + 'requested_index' : BlockIndex, + 'first_valid_index' : BlockIndex, + }), + 'Other' : IDL.Record({ + 'error_message' : IDL.Text, + 'error_code' : IDL.Nat64, + }), + }); + const QueryArchiveResult = IDL.Variant({ + 'Ok' : BlockRange, + 'Err' : QueryArchiveError, + }); + const QueryArchiveFn = IDL.Func([GetBlocksArgs], [QueryArchiveResult], []); + const ArchivedBlocksRange = IDL.Record({ + 'callback' : QueryArchiveFn, + 'start' : BlockIndex, + 'length' : IDL.Nat64, + }); + const QueryBlocksResponse = IDL.Record({ + 'certificate' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'blocks' : IDL.Vec(Block), + 'chain_length' : IDL.Nat64, + 'first_block_index' : BlockIndex, + 'archived_blocks' : IDL.Vec(ArchivedBlocksRange), + }); + const ArchivedEncodedBlocksRange = IDL.Record({ + 'callback' : IDL.Func( + [GetBlocksArgs], + [ + IDL.Variant({ + 'Ok' : IDL.Vec(IDL.Vec(IDL.Nat8)), + 'Err' : QueryArchiveError, + }), + ], + [], + ), + 'start' : IDL.Nat64, + 'length' : IDL.Nat64, + }); + const QueryEncodedBlocksResponse = IDL.Record({ + 'certificate' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'blocks' : IDL.Vec(IDL.Vec(IDL.Nat8)), + 'chain_length' : IDL.Nat64, + 'first_block_index' : IDL.Nat64, + 'archived_blocks' : IDL.Vec(ArchivedEncodedBlocksRange), + }); + const AccountBalanceArgs = IDL.Record({ 'account' : AccountIdentifier }); + const AccountBalanceArgsDfx = IDL.Record({ + 'account' : TextAccountIdentifier, + }); + const Archive = IDL.Record({ 'canister_id' : IDL.Principal }); + const Archives = IDL.Record({ 'archives' : IDL.Vec(Archive) }); + const Icrc1Tokens = IDL.Nat; + const Value = IDL.Variant({ + 'Int' : IDL.Int, + 'Nat' : IDL.Nat, + 'Blob' : IDL.Vec(IDL.Nat8), + 'Text' : IDL.Text, + }); + const Icrc1Timestamp = IDL.Nat64; + const TransferArg = IDL.Record({ + 'to' : Account, + 'fee' : IDL.Opt(Icrc1Tokens), + 'memo' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(Icrc1Timestamp), + 'amount' : Icrc1Tokens, + }); + const Icrc1BlockIndex = IDL.Nat; + const Icrc1TransferError = IDL.Variant({ + 'GenericError' : IDL.Record({ + 'message' : IDL.Text, + 'error_code' : IDL.Nat, + }), + 'TemporarilyUnavailable' : IDL.Null, + 'BadBurn' : IDL.Record({ 'min_burn_amount' : Icrc1Tokens }), + 'Duplicate' : IDL.Record({ 'duplicate_of' : Icrc1BlockIndex }), + 'BadFee' : IDL.Record({ 'expected_fee' : Icrc1Tokens }), + 'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }), + 'TooOld' : IDL.Null, + 'InsufficientFunds' : IDL.Record({ 'balance' : Icrc1Tokens }), + }); + const Icrc1TransferResult = IDL.Variant({ + 'Ok' : Icrc1BlockIndex, + 'Err' : Icrc1TransferError, + }); + const AllowanceArgs = IDL.Record({ + 'account' : Account, + 'spender' : Account, + }); + const Allowance = IDL.Record({ + 'allowance' : Icrc1Tokens, + 'expires_at' : IDL.Opt(TimeStamp), + }); + const ApproveArgs = IDL.Record({ + 'fee' : IDL.Opt(Icrc1Tokens), + 'memo' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(TimeStamp), + 'amount' : Icrc1Tokens, + 'expected_allowance' : IDL.Opt(Icrc1Tokens), + 'expires_at' : IDL.Opt(TimeStamp), + 'spender' : Account, + }); + const ApproveError = IDL.Variant({ + 'GenericError' : IDL.Record({ + 'message' : IDL.Text, + 'error_code' : IDL.Nat, + }), + 'TemporarilyUnavailable' : IDL.Null, + 'Duplicate' : IDL.Record({ 'duplicate_of' : Icrc1BlockIndex }), + 'BadFee' : IDL.Record({ 'expected_fee' : Icrc1Tokens }), + 'AllowanceChanged' : IDL.Record({ 'current_allowance' : Icrc1Tokens }), + 'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }), + 'TooOld' : IDL.Null, + 'Expired' : IDL.Record({ 'ledger_time' : IDL.Nat64 }), + 'InsufficientFunds' : IDL.Record({ 'balance' : Icrc1Tokens }), + }); + const ApproveResult = IDL.Variant({ + 'Ok' : Icrc1BlockIndex, + 'Err' : ApproveError, + }); + const SendArgs = IDL.Record({ + 'to' : TextAccountIdentifier, + 'fee' : Tokens, + 'memo' : Memo, + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(TimeStamp), + 'amount' : Tokens, + }); + const TransferArgs = IDL.Record({ + 'to' : AccountIdentifier, + 'fee' : Tokens, + 'memo' : Memo, + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(TimeStamp), + 'amount' : Tokens, + }); + const TransferError = IDL.Variant({ + 'TxTooOld' : IDL.Record({ 'allowed_window_nanos' : IDL.Nat64 }), + 'BadFee' : IDL.Record({ 'expected_fee' : Tokens }), + 'TxDuplicate' : IDL.Record({ 'duplicate_of' : BlockIndex }), + 'TxCreatedInFuture' : IDL.Null, + 'InsufficientFunds' : IDL.Record({ 'balance' : Tokens }), + }); + const TransferResult = IDL.Variant({ + 'Ok' : BlockIndex, + 'Err' : TransferError, + }); + const TransferFeeArg = IDL.Record({}); + const TransferFee = IDL.Record({ 'transfer_fee' : Tokens }); + return IDL.Service({ + '_blocks' : IDL.Func([GetBlocksArgs], [QueryBlocksResponse], []), + '_encoded_blocks' : IDL.Func( + [GetBlocksArgs], + [QueryEncodedBlocksResponse], + [], + ), + 'account_balance' : IDL.Func([AccountBalanceArgs], [Tokens], []), + 'account_balance_dfx' : IDL.Func([AccountBalanceArgsDfx], [Tokens], []), + 'account_identifier' : IDL.Func([Account], [AccountIdentifier], []), + 'archives' : IDL.Func([], [Archives], []), + 'decimals' : IDL.Func([], [IDL.Record({ 'decimals' : IDL.Nat32 })], []), + 'icrc1_balance_of' : IDL.Func([Account], [Icrc1Tokens], []), + 'icrc1_decimals' : IDL.Func([], [IDL.Nat8], []), + 'icrc1_fee' : IDL.Func([], [Icrc1Tokens], []), + 'icrc1_metadata' : IDL.Func([], [IDL.Vec(IDL.Tuple(IDL.Text, Value))], []), + 'icrc1_minting_account' : IDL.Func([], [IDL.Opt(Account)], []), + 'icrc1_name' : IDL.Func([], [IDL.Text], []), + 'icrc1_supported_standards' : IDL.Func( + [], + [IDL.Vec(IDL.Record({ 'url' : IDL.Text, 'name' : IDL.Text }))], + [], + ), + 'icrc1_symbol' : IDL.Func([], [IDL.Text], []), + 'icrc1_total_supply' : IDL.Func([], [Icrc1Tokens], []), + 'icrc1_transfer' : IDL.Func([TransferArg], [Icrc1TransferResult], []), + 'icrc2_allowance' : IDL.Func([AllowanceArgs], [Allowance], []), + 'icrc2_approve' : IDL.Func([ApproveArgs], [ApproveResult], []), + 'name' : IDL.Func([], [IDL.Record({ 'name' : IDL.Text })], []), + 'send_dfx' : IDL.Func([SendArgs], [BlockIndex], []), + 'symbol' : IDL.Func([], [IDL.Record({ 'symbol' : IDL.Text })], []), + 'transfer' : IDL.Func([TransferArgs], [TransferResult], []), + 'transfer_fee' : IDL.Func([TransferFeeArg], [TransferFee], []), + }); +}; +export const init = ({ IDL }) => { + const SubAccount = IDL.Vec(IDL.Nat8); + const Account = IDL.Record({ + 'owner' : IDL.Principal, + 'subaccount' : IDL.Opt(SubAccount), + }); + const FeatureFlags = IDL.Record({ 'icrc2' : IDL.Bool }); + const UpgradeArgs = IDL.Record({ + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const Tokens = IDL.Record({ 'e8s' : IDL.Nat64 }); + const TextAccountIdentifier = IDL.Text; + const Duration = IDL.Record({ 'secs' : IDL.Nat64, 'nanos' : IDL.Nat32 }); + const ArchiveOptions = IDL.Record({ + 'num_blocks_to_archive' : IDL.Nat64, + 'trigger_threshold' : IDL.Nat64, + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'cycles_for_archive_creation' : IDL.Opt(IDL.Nat64), + 'node_max_memory_size_bytes' : IDL.Opt(IDL.Nat64), + 'controller_id' : IDL.Principal, + }); + const InitArgs = IDL.Record({ + 'send_whitelist' : IDL.Vec(IDL.Principal), + 'token_symbol' : IDL.Opt(IDL.Text), + 'transfer_fee' : IDL.Opt(Tokens), + 'minting_account' : TextAccountIdentifier, + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'accounts_overflow_trim_quantity' : IDL.Opt(IDL.Nat64), + 'transaction_window' : IDL.Opt(Duration), + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'archive_options' : IDL.Opt(ArchiveOptions), + 'initial_values' : IDL.Vec(IDL.Tuple(TextAccountIdentifier, Tokens)), + 'token_name' : IDL.Opt(IDL.Text), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const LedgerCanisterPayload = IDL.Variant({ + 'Upgrade' : IDL.Opt(UpgradeArgs), + 'Init' : InitArgs, + }); + return [LedgerCanisterPayload]; +}; diff --git a/packages/ledger-icp/candid/ledger.d.ts b/packages/ledger-icp/candid/ledger.d.ts new file mode 100644 index 00000000..33d4a136 --- /dev/null +++ b/packages/ledger-icp/candid/ledger.d.ts @@ -0,0 +1,280 @@ +import type { ActorMethod } from "@dfinity/agent"; +import type { Principal } from "@dfinity/principal"; + +export interface Account { + owner: Principal; + subaccount: [] | [SubAccount]; +} +export interface AccountBalanceArgs { + account: AccountIdentifier; +} +export interface AccountBalanceArgsDfx { + account: TextAccountIdentifier; +} +export type AccountIdentifier = Uint8Array; +export interface Allowance { + allowance: Icrc1Tokens; + expires_at: [] | [TimeStamp]; +} +export interface AllowanceArgs { + account: Account; + spender: Account; +} +export interface ApproveArgs { + fee: [] | [Icrc1Tokens]; + memo: [] | [Uint8Array]; + from_subaccount: [] | [SubAccount]; + created_at_time: [] | [TimeStamp]; + amount: Icrc1Tokens; + expected_allowance: [] | [Icrc1Tokens]; + expires_at: [] | [TimeStamp]; + spender: Account; +} +export type ApproveError = + | { + GenericError: { message: string; error_code: bigint }; + } + | { TemporarilyUnavailable: null } + | { Duplicate: { duplicate_of: Icrc1BlockIndex } } + | { BadFee: { expected_fee: Icrc1Tokens } } + | { AllowanceChanged: { current_allowance: Icrc1Tokens } } + | { CreatedInFuture: { ledger_time: bigint } } + | { TooOld: null } + | { Expired: { ledger_time: bigint } } + | { InsufficientFunds: { balance: Icrc1Tokens } }; +export type ApproveResult = { Ok: Icrc1BlockIndex } | { Err: ApproveError }; +export interface Archive { + canister_id: Principal; +} +export interface ArchiveOptions { + num_blocks_to_archive: bigint; + trigger_threshold: bigint; + max_message_size_bytes: [] | [bigint]; + cycles_for_archive_creation: [] | [bigint]; + node_max_memory_size_bytes: [] | [bigint]; + controller_id: Principal; +} +export interface ArchivedBlocksRange { + callback: QueryArchiveFn; + start: BlockIndex; + length: bigint; +} +export interface ArchivedEncodedBlocksRange { + callback: [Principal, string]; + start: bigint; + length: bigint; +} +export interface Archives { + archives: Array; +} +export interface Block { + transaction: Transaction; + timestamp: TimeStamp; + parent_hash: [] | [Uint8Array]; +} +export type BlockIndex = bigint; +export interface BlockRange { + blocks: Array; +} +export interface Duration { + secs: bigint; + nanos: number; +} +export interface FeatureFlags { + icrc2: boolean; +} +export interface GetBlocksArgs { + start: BlockIndex; + length: bigint; +} +export type Icrc1BlockIndex = bigint; +export type Icrc1Timestamp = bigint; +export type Icrc1Tokens = bigint; +export type Icrc1TransferError = + | { + GenericError: { message: string; error_code: bigint }; + } + | { TemporarilyUnavailable: null } + | { BadBurn: { min_burn_amount: Icrc1Tokens } } + | { Duplicate: { duplicate_of: Icrc1BlockIndex } } + | { BadFee: { expected_fee: Icrc1Tokens } } + | { CreatedInFuture: { ledger_time: bigint } } + | { TooOld: null } + | { InsufficientFunds: { balance: Icrc1Tokens } }; +export type Icrc1TransferResult = + | { Ok: Icrc1BlockIndex } + | { Err: Icrc1TransferError }; +export interface InitArgs { + send_whitelist: Array; + token_symbol: [] | [string]; + transfer_fee: [] | [Tokens]; + minting_account: TextAccountIdentifier; + maximum_number_of_accounts: [] | [bigint]; + accounts_overflow_trim_quantity: [] | [bigint]; + transaction_window: [] | [Duration]; + max_message_size_bytes: [] | [bigint]; + icrc1_minting_account: [] | [Account]; + archive_options: [] | [ArchiveOptions]; + initial_values: Array<[TextAccountIdentifier, Tokens]>; + token_name: [] | [string]; + feature_flags: [] | [FeatureFlags]; +} +export type LedgerCanisterPayload = + | { Upgrade: [] | [UpgradeArgs] } + | { Init: InitArgs }; +export type Memo = bigint; +export type Operation = + | { + Approve: { + fee: Tokens; + from: AccountIdentifier; + allowance_e8s: bigint; + allowance: Tokens; + expires_at: [] | [TimeStamp]; + spender: AccountIdentifier; + }; + } + | { + Burn: { + from: AccountIdentifier; + amount: Tokens; + spender: [] | [AccountIdentifier]; + }; + } + | { Mint: { to: AccountIdentifier; amount: Tokens } } + | { + Transfer: { + to: AccountIdentifier; + fee: Tokens; + from: AccountIdentifier; + amount: Tokens; + }; + } + | { + TransferFrom: { + to: AccountIdentifier; + fee: Tokens; + from: AccountIdentifier; + amount: Tokens; + spender: AccountIdentifier; + }; + }; +export type QueryArchiveError = + | { + BadFirstBlockIndex: { + requested_index: BlockIndex; + first_valid_index: BlockIndex; + }; + } + | { Other: { error_message: string; error_code: bigint } }; +export type QueryArchiveFn = ActorMethod<[GetBlocksArgs], QueryArchiveResult>; +export type QueryArchiveResult = + | { Ok: BlockRange } + | { Err: QueryArchiveError }; +export interface QueryBlocksResponse { + certificate: [] | [Uint8Array]; + blocks: Array; + chain_length: bigint; + first_block_index: BlockIndex; + archived_blocks: Array; +} +export interface QueryEncodedBlocksResponse { + certificate: [] | [Uint8Array]; + blocks: Array; + chain_length: bigint; + first_block_index: bigint; + archived_blocks: Array; +} +export interface SendArgs { + to: TextAccountIdentifier; + fee: Tokens; + memo: Memo; + from_subaccount: [] | [SubAccount]; + created_at_time: [] | [TimeStamp]; + amount: Tokens; +} +export type SubAccount = Uint8Array; +export type TextAccountIdentifier = string; +export interface TimeStamp { + timestamp_nanos: bigint; +} +export interface Tokens { + e8s: bigint; +} +export interface Transaction { + memo: Memo; + icrc1_memo: [] | [Uint8Array]; + operation: [] | [Operation]; + created_at_time: TimeStamp; +} +export interface TransferArg { + to: Account; + fee: [] | [Icrc1Tokens]; + memo: [] | [Uint8Array]; + from_subaccount: [] | [SubAccount]; + created_at_time: [] | [Icrc1Timestamp]; + amount: Icrc1Tokens; +} +export interface TransferArgs { + to: AccountIdentifier; + fee: Tokens; + memo: Memo; + from_subaccount: [] | [SubAccount]; + created_at_time: [] | [TimeStamp]; + amount: Tokens; +} +export type TransferError = + | { + TxTooOld: { allowed_window_nanos: bigint }; + } + | { BadFee: { expected_fee: Tokens } } + | { TxDuplicate: { duplicate_of: BlockIndex } } + | { TxCreatedInFuture: null } + | { InsufficientFunds: { balance: Tokens } }; +export interface TransferFee { + transfer_fee: Tokens; +} +export type TransferFeeArg = {}; +export type TransferResult = { Ok: BlockIndex } | { Err: TransferError }; +export interface UpgradeArgs { + maximum_number_of_accounts: [] | [bigint]; + icrc1_minting_account: [] | [Account]; + feature_flags: [] | [FeatureFlags]; +} +export type Value = + | { Int: bigint } + | { Nat: bigint } + | { Blob: Uint8Array } + | { Text: string }; +export interface _SERVICE { + account_balance: ActorMethod<[AccountBalanceArgs], Tokens>; + account_balance_dfx: ActorMethod<[AccountBalanceArgsDfx], Tokens>; + account_identifier: ActorMethod<[Account], AccountIdentifier>; + archives: ActorMethod<[], Archives>; + decimals: ActorMethod<[], { decimals: number }>; + icrc1_balance_of: ActorMethod<[Account], Icrc1Tokens>; + icrc1_decimals: ActorMethod<[], number>; + icrc1_fee: ActorMethod<[], Icrc1Tokens>; + icrc1_metadata: ActorMethod<[], Array<[string, Value]>>; + icrc1_minting_account: ActorMethod<[], [] | [Account]>; + icrc1_name: ActorMethod<[], string>; + icrc1_supported_standards: ActorMethod< + [], + Array<{ url: string; name: string }> + >; + icrc1_symbol: ActorMethod<[], string>; + icrc1_total_supply: ActorMethod<[], Icrc1Tokens>; + icrc1_transfer: ActorMethod<[TransferArg], Icrc1TransferResult>; + icrc2_allowance: ActorMethod<[AllowanceArgs], Allowance>; + icrc2_approve: ActorMethod<[ApproveArgs], ApproveResult>; + name: ActorMethod<[], { name: string }>; + query_blocks: ActorMethod<[GetBlocksArgs], QueryBlocksResponse>; + query_encoded_blocks: ActorMethod< + [GetBlocksArgs], + QueryEncodedBlocksResponse + >; + send_dfx: ActorMethod<[SendArgs], BlockIndex>; + symbol: ActorMethod<[], { symbol: string }>; + transfer: ActorMethod<[TransferArgs], TransferResult>; + transfer_fee: ActorMethod<[TransferFeeArg], TransferFee>; +} diff --git a/packages/ledger-icp/candid/ledger.did b/packages/ledger-icp/candid/ledger.did new file mode 100644 index 00000000..7c790487 --- /dev/null +++ b/packages/ledger-icp/candid/ledger.did @@ -0,0 +1,455 @@ +// Generated from IC repo commit 117db5eb586321cf0a1a49ff03106a0e55502715 'rs/rosetta-api/icp_ledger/ledger.did' by import-candid +// This is the official Ledger interface that is guaranteed to be backward compatible. + +// Amount of tokens, measured in 10^-8 of a token. +type Tokens = record { + e8s : nat64; +}; + +// Number of nanoseconds from the UNIX epoch in UTC timezone. +type TimeStamp = record { + timestamp_nanos: nat64; +}; + +// AccountIdentifier is a 32-byte array. +// The first 4 bytes is big-endian encoding of a CRC32 checksum of the last 28 bytes. +type AccountIdentifier = blob; + +// Subaccount is an arbitrary 32-byte byte array. +// Ledger uses subaccounts to compute the source address, which enables one +// principal to control multiple ledger accounts. +type SubAccount = blob; + +// Sequence number of a block produced by the ledger. +type BlockIndex = nat64; + +type Transaction = record { + memo : Memo; + icrc1_memo: opt blob; + operation : opt Operation; + created_at_time : TimeStamp; +}; + +// An arbitrary number associated with a transaction. +// The caller can set it in a `transfer` call as a correlation identifier. +type Memo = nat64; + +// Arguments for the `transfer` call. +type TransferArgs = record { + // Transaction memo. + // See comments for the `Memo` type. + memo: Memo; + // The amount that the caller wants to transfer to the destination address. + amount: Tokens; + // The amount that the caller pays for the transaction. + // Must be 10000 e8s. + fee: Tokens; + // The subaccount from which the caller wants to transfer funds. + // If null, the ledger uses the default (all zeros) subaccount to compute the source address. + // See comments for the `SubAccount` type. + from_subaccount: opt SubAccount; + // The destination account. + // If the transfer is successful, the balance of this address increases by `amount`. + to: AccountIdentifier; + // The point in time when the caller created this request. + // If null, the ledger uses current IC time as the timestamp. + created_at_time: opt TimeStamp; +}; + +type TransferError = variant { + // The fee that the caller specified in the transfer request was not the one that ledger expects. + // The caller can change the transfer fee to the `expected_fee` and retry the request. + BadFee : record { expected_fee : Tokens; }; + // The account specified by the caller doesn't have enough funds. + InsufficientFunds : record { balance: Tokens; }; + // The request is too old. + // The ledger only accepts requests created within 24 hours window. + // This is a non-recoverable error. + TxTooOld : record { allowed_window_nanos: nat64 }; + // The caller specified `created_at_time` that is too far in future. + // The caller can retry the request later. + TxCreatedInFuture : null; + // The ledger has already executed the request. + // `duplicate_of` field is equal to the index of the block containing the original transaction. + TxDuplicate : record { duplicate_of: BlockIndex; } +}; + +type TransferResult = variant { + Ok : BlockIndex; + Err : TransferError; +}; + +// Arguments for the `account_balance` call. +type AccountBalanceArgs = record { + account: AccountIdentifier; +}; + +type TransferFeeArg = record {}; + +type TransferFee = record { + // The fee to pay to perform a transfer + transfer_fee: Tokens; +}; + +type GetBlocksArgs = record { + // The index of the first block to fetch. + start : BlockIndex; + // Max number of blocks to fetch. + length : nat64; +}; + +type Operation = variant { + Mint : record { + to : AccountIdentifier; + amount : Tokens; + }; + Burn : record { + from : AccountIdentifier; + spender : opt AccountIdentifier; + amount : Tokens; + }; + Transfer : record { + from : AccountIdentifier; + to : AccountIdentifier; + amount : Tokens; + fee : Tokens; + }; + Approve : record { + from : AccountIdentifier; + spender : AccountIdentifier; + // This field is deprecated and should not be used. + allowance_e8s : int; + allowance: Tokens; + fee : Tokens; + expires_at : opt TimeStamp; + }; + TransferFrom : record { + from : AccountIdentifier; + to : AccountIdentifier; + spender : AccountIdentifier; + amount : Tokens; + fee : Tokens; + }; +}; + + + +type Block = record { + parent_hash : opt blob; + transaction : Transaction; + timestamp : TimeStamp; +}; + +// A prefix of the block range specified in the [GetBlocksArgs] request. +type BlockRange = record { + // A prefix of the requested block range. + // The index of the first block is equal to [GetBlocksArgs.from]. + // + // Note that the number of blocks might be less than the requested + // [GetBlocksArgs.len] for various reasons, for example: + // + // 1. The query might have hit the replica with an outdated state + // that doesn't have the full block range yet. + // 2. The requested range is too large to fit into a single reply. + // + // NOTE: the list of blocks can be empty if: + // 1. [GetBlocksArgs.len] was zero. + // 2. [GetBlocksArgs.from] was larger than the last block known to the canister. + blocks : vec Block; +}; + +// An error indicating that the arguments passed to [QueryArchiveFn] were invalid. +type QueryArchiveError = variant { + // [GetBlocksArgs.from] argument was smaller than the first block + // served by the canister that received the request. + BadFirstBlockIndex : record { + requested_index : BlockIndex; + first_valid_index : BlockIndex; + }; + + // Reserved for future use. + Other : record { + error_code : nat64; + error_message : text; + }; +}; + +type QueryArchiveResult = variant { + // Successfully fetched zero or more blocks. + Ok : BlockRange; + // The [GetBlocksArgs] request was invalid. + Err : QueryArchiveError; +}; + +// A function that is used for fetching archived ledger blocks. +type QueryArchiveFn = func (GetBlocksArgs) -> (QueryArchiveResult) query; + +// The result of a "query_blocks" call. +// +// The structure of the result is somewhat complicated because the main ledger canister might +// not have all the blocks that the caller requested: One or more "archive" canisters might +// store some of the requested blocks. +// +// Note: as of Q4 2021 when this interface is authored, the IC doesn't support making nested +// query calls within a query call. +type QueryBlocksResponse = record { + // The total number of blocks in the chain. + // If the chain length is positive, the index of the last block is `chain_len - 1`. + chain_length : nat64; + + // System certificate for the hash of the latest block in the chain. + // Only present if `query_blocks` is called in a non-replicated query context. + certificate : opt blob; + + // List of blocks that were available in the ledger when it processed the call. + // + // The blocks form a contiguous range, with the first block having index + // [first_block_index] (see below), and the last block having index + // [first_block_index] + len(blocks) - 1. + // + // The block range can be an arbitrary sub-range of the originally requested range. + blocks : vec Block; + + // The index of the first block in "blocks". + // If the blocks vector is empty, the exact value of this field is not specified. + first_block_index : BlockIndex; + + // Encoding of instructions for fetching archived blocks whose indices fall into the + // requested range. + // + // For each entry `e` in [archived_blocks], `[e.from, e.from + len)` is a sub-range + // of the originally requested block range. + archived_blocks : vec ArchivedBlocksRange; +}; + +type ArchivedBlocksRange = record { + // The index of the first archived block that can be fetched using the callback. + start : BlockIndex; + + // The number of blocks that can be fetch using the callback. + length : nat64; + + // The function that should be called to fetch the archived blocks. + // The range of the blocks accessible using this function is given by [from] + // and [len] fields above. + callback : QueryArchiveFn; +}; + +type ArchivedEncodedBlocksRange = record { + callback : func (GetBlocksArgs) -> ( + variant { Ok : vec blob; Err : QueryArchiveError }, + ) query; + start : nat64; + length : nat64; +}; + +type QueryEncodedBlocksResponse = record { + certificate : opt blob; + blocks : vec blob; + chain_length : nat64; + first_block_index : nat64; + archived_blocks : vec ArchivedEncodedBlocksRange; +}; + +type Archive = record { + canister_id: principal; +}; + +type Archives = record { + archives: vec Archive; +}; + +type Duration = record { + secs: nat64; + nanos: nat32; +}; + +type ArchiveOptions = record { + trigger_threshold : nat64; + num_blocks_to_archive : nat64; + node_max_memory_size_bytes: opt nat64; + max_message_size_bytes: opt nat64; + controller_id: principal; + cycles_for_archive_creation: opt nat64; +}; + +// Account identifier encoded as a 64-byte ASCII hex string. +type TextAccountIdentifier = text; + +// Arguments for the `send_dfx` call. +type SendArgs = record { + memo: Memo; + amount: Tokens; + fee: Tokens; + from_subaccount: opt SubAccount; + to: TextAccountIdentifier; + created_at_time: opt TimeStamp; +}; + +type AccountBalanceArgsDfx = record { + account: TextAccountIdentifier; +}; + +type FeatureFlags = record { + icrc2 : bool; +}; + +type InitArgs = record { + minting_account: TextAccountIdentifier; + icrc1_minting_account: opt Account; + initial_values: vec record {TextAccountIdentifier; Tokens}; + max_message_size_bytes: opt nat64; + transaction_window: opt Duration; + archive_options: opt ArchiveOptions; + send_whitelist: vec principal; + transfer_fee: opt Tokens; + token_symbol: opt text; + token_name: opt text; + feature_flags : opt FeatureFlags; + maximum_number_of_accounts : opt nat64; + accounts_overflow_trim_quantity: opt nat64; +}; + +type Icrc1BlockIndex = nat; +// Number of nanoseconds since the UNIX epoch in UTC timezone. +type Icrc1Timestamp = nat64; +type Icrc1Tokens = nat; + +type Account = record { + owner : principal; + subaccount : opt SubAccount; +}; + +type TransferArg = record { + from_subaccount : opt SubAccount; + to : Account; + amount : Icrc1Tokens; + fee : opt Icrc1Tokens; + memo : opt blob; + created_at_time: opt Icrc1Timestamp; +}; + +type Icrc1TransferError = variant { + BadFee : record { expected_fee : Icrc1Tokens }; + BadBurn : record { min_burn_amount : Icrc1Tokens }; + InsufficientFunds : record { balance : Icrc1Tokens }; + TooOld; + CreatedInFuture : record { ledger_time : nat64 }; + TemporarilyUnavailable; + Duplicate : record { duplicate_of : Icrc1BlockIndex }; + GenericError : record { error_code : nat; message : text }; +}; + +type Icrc1TransferResult = variant { + Ok : Icrc1BlockIndex; + Err : Icrc1TransferError; +}; + +// The value returned from the [icrc1_metadata] endpoint. +type Value = variant { + Nat : nat; + Int : int; + Text : text; + Blob : blob; +}; + +type UpgradeArgs = record { + maximum_number_of_accounts : opt nat64; + icrc1_minting_account : opt Account; + feature_flags : opt FeatureFlags; +}; + +type LedgerCanisterPayload = variant { + Init: InitArgs; + Upgrade: opt UpgradeArgs; +}; + +type ApproveArgs = record { + from_subaccount : opt SubAccount; + spender : Account; + amount : Icrc1Tokens; + expected_allowance : opt Icrc1Tokens; + expires_at : opt TimeStamp; + fee : opt Icrc1Tokens; + memo : opt blob; + created_at_time: opt TimeStamp; +}; + +type ApproveError = variant { + BadFee : record { expected_fee : Icrc1Tokens }; + InsufficientFunds : record { balance : Icrc1Tokens }; + AllowanceChanged : record { current_allowance : Icrc1Tokens }; + Expired : record { ledger_time : nat64 }; + TooOld; + CreatedInFuture : record { ledger_time : nat64 }; + Duplicate : record { duplicate_of : Icrc1BlockIndex }; + TemporarilyUnavailable; + GenericError : record { error_code : nat; message : text }; +}; + +type ApproveResult = variant { + Ok : Icrc1BlockIndex; + Err : ApproveError; +}; + +type AllowanceArgs = record { + account : Account; + spender : Account; +}; + +type Allowance = record { + allowance : Icrc1Tokens; + expires_at : opt TimeStamp; +}; + +service: (LedgerCanisterPayload) -> { + // Transfers tokens from a subaccount of the caller to the destination address. + // The source address is computed from the principal of the caller and the specified subaccount. + // When successful, returns the index of the block containing the transaction. + transfer : (TransferArgs) -> (TransferResult); + + // Returns the amount of Tokens on the specified account. + account_balance : (AccountBalanceArgs) -> (Tokens) query; + + // Returns the account identifier for the given Principal and subaccount. + account_identifier : (Account) -> (AccountIdentifier) query; + + // Returns the current transfer_fee. + transfer_fee : (TransferFeeArg) -> (TransferFee) query; + + // Queries blocks in the specified range. + query_blocks : (GetBlocksArgs) -> (QueryBlocksResponse) query; + + // Queries encoded blocks in the specified range + query_encoded_blocks : (GetBlocksArgs) -> (QueryEncodedBlocksResponse) query; + + // Returns token symbol. + symbol : () -> (record { symbol: text }) query; + + // Returns token name. + name : () -> (record { name: text }) query; + + // Returns token decimals. + decimals : () -> (record { decimals: nat32 }) query; + + // Returns the existing archive canisters information. + archives : () -> (Archives) query; + + send_dfx : (SendArgs) -> (BlockIndex); + account_balance_dfx : (AccountBalanceArgsDfx) -> (Tokens) query; + + // The following methods implement the ICRC-1 Token Standard. + // https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1 + icrc1_name : () -> (text) query; + icrc1_symbol : () -> (text) query; + icrc1_decimals : () -> (nat8) query; + icrc1_metadata : () -> (vec record { text; Value }) query; + icrc1_total_supply : () -> (Icrc1Tokens) query; + icrc1_fee : () -> (Icrc1Tokens) query; + icrc1_minting_account : () -> (opt Account) query; + icrc1_balance_of : (Account) -> (Icrc1Tokens) query; + icrc1_transfer : (TransferArg) -> (Icrc1TransferResult); + icrc1_supported_standards : () -> (vec record { name : text; url : text }) query; + icrc2_approve : (ApproveArgs) -> (ApproveResult); + icrc2_allowance : (AllowanceArgs) -> (Allowance) query; +} diff --git a/packages/ledger-icp/candid/ledger.idl.d.ts b/packages/ledger-icp/candid/ledger.idl.d.ts new file mode 100644 index 00000000..8e1474b8 --- /dev/null +++ b/packages/ledger-icp/candid/ledger.idl.d.ts @@ -0,0 +1,2 @@ +import type { IDL } from "@dfinity/candid"; +export const idlFactory: IDL.InterfaceFactory; diff --git a/packages/ledger-icp/candid/ledger.idl.js b/packages/ledger-icp/candid/ledger.idl.js new file mode 100644 index 00000000..49275a90 --- /dev/null +++ b/packages/ledger-icp/candid/ledger.idl.js @@ -0,0 +1,344 @@ +/* Do not edit. Compiled with ./scripts/compile-idl-js from packages/ledger-icp/candid/ledger.did */ +export const idlFactory = ({ IDL }) => { + const SubAccount = IDL.Vec(IDL.Nat8); + const Account = IDL.Record({ + 'owner' : IDL.Principal, + 'subaccount' : IDL.Opt(SubAccount), + }); + const FeatureFlags = IDL.Record({ 'icrc2' : IDL.Bool }); + const UpgradeArgs = IDL.Record({ + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const Tokens = IDL.Record({ 'e8s' : IDL.Nat64 }); + const TextAccountIdentifier = IDL.Text; + const Duration = IDL.Record({ 'secs' : IDL.Nat64, 'nanos' : IDL.Nat32 }); + const ArchiveOptions = IDL.Record({ + 'num_blocks_to_archive' : IDL.Nat64, + 'trigger_threshold' : IDL.Nat64, + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'cycles_for_archive_creation' : IDL.Opt(IDL.Nat64), + 'node_max_memory_size_bytes' : IDL.Opt(IDL.Nat64), + 'controller_id' : IDL.Principal, + }); + const InitArgs = IDL.Record({ + 'send_whitelist' : IDL.Vec(IDL.Principal), + 'token_symbol' : IDL.Opt(IDL.Text), + 'transfer_fee' : IDL.Opt(Tokens), + 'minting_account' : TextAccountIdentifier, + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'accounts_overflow_trim_quantity' : IDL.Opt(IDL.Nat64), + 'transaction_window' : IDL.Opt(Duration), + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'archive_options' : IDL.Opt(ArchiveOptions), + 'initial_values' : IDL.Vec(IDL.Tuple(TextAccountIdentifier, Tokens)), + 'token_name' : IDL.Opt(IDL.Text), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const LedgerCanisterPayload = IDL.Variant({ + 'Upgrade' : IDL.Opt(UpgradeArgs), + 'Init' : InitArgs, + }); + const AccountIdentifier = IDL.Vec(IDL.Nat8); + const AccountBalanceArgs = IDL.Record({ 'account' : AccountIdentifier }); + const AccountBalanceArgsDfx = IDL.Record({ + 'account' : TextAccountIdentifier, + }); + const Archive = IDL.Record({ 'canister_id' : IDL.Principal }); + const Archives = IDL.Record({ 'archives' : IDL.Vec(Archive) }); + const Icrc1Tokens = IDL.Nat; + const Value = IDL.Variant({ + 'Int' : IDL.Int, + 'Nat' : IDL.Nat, + 'Blob' : IDL.Vec(IDL.Nat8), + 'Text' : IDL.Text, + }); + const Icrc1Timestamp = IDL.Nat64; + const TransferArg = IDL.Record({ + 'to' : Account, + 'fee' : IDL.Opt(Icrc1Tokens), + 'memo' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(Icrc1Timestamp), + 'amount' : Icrc1Tokens, + }); + const Icrc1BlockIndex = IDL.Nat; + const Icrc1TransferError = IDL.Variant({ + 'GenericError' : IDL.Record({ + 'message' : IDL.Text, + 'error_code' : IDL.Nat, + }), + 'TemporarilyUnavailable' : IDL.Null, + 'BadBurn' : IDL.Record({ 'min_burn_amount' : Icrc1Tokens }), + 'Duplicate' : IDL.Record({ 'duplicate_of' : Icrc1BlockIndex }), + 'BadFee' : IDL.Record({ 'expected_fee' : Icrc1Tokens }), + 'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }), + 'TooOld' : IDL.Null, + 'InsufficientFunds' : IDL.Record({ 'balance' : Icrc1Tokens }), + }); + const Icrc1TransferResult = IDL.Variant({ + 'Ok' : Icrc1BlockIndex, + 'Err' : Icrc1TransferError, + }); + const AllowanceArgs = IDL.Record({ + 'account' : Account, + 'spender' : Account, + }); + const TimeStamp = IDL.Record({ 'timestamp_nanos' : IDL.Nat64 }); + const Allowance = IDL.Record({ + 'allowance' : Icrc1Tokens, + 'expires_at' : IDL.Opt(TimeStamp), + }); + const ApproveArgs = IDL.Record({ + 'fee' : IDL.Opt(Icrc1Tokens), + 'memo' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(TimeStamp), + 'amount' : Icrc1Tokens, + 'expected_allowance' : IDL.Opt(Icrc1Tokens), + 'expires_at' : IDL.Opt(TimeStamp), + 'spender' : Account, + }); + const ApproveError = IDL.Variant({ + 'GenericError' : IDL.Record({ + 'message' : IDL.Text, + 'error_code' : IDL.Nat, + }), + 'TemporarilyUnavailable' : IDL.Null, + 'Duplicate' : IDL.Record({ 'duplicate_of' : Icrc1BlockIndex }), + 'BadFee' : IDL.Record({ 'expected_fee' : Icrc1Tokens }), + 'AllowanceChanged' : IDL.Record({ 'current_allowance' : Icrc1Tokens }), + 'CreatedInFuture' : IDL.Record({ 'ledger_time' : IDL.Nat64 }), + 'TooOld' : IDL.Null, + 'Expired' : IDL.Record({ 'ledger_time' : IDL.Nat64 }), + 'InsufficientFunds' : IDL.Record({ 'balance' : Icrc1Tokens }), + }); + const ApproveResult = IDL.Variant({ + 'Ok' : Icrc1BlockIndex, + 'Err' : ApproveError, + }); + const BlockIndex = IDL.Nat64; + const GetBlocksArgs = IDL.Record({ + 'start' : BlockIndex, + 'length' : IDL.Nat64, + }); + const Memo = IDL.Nat64; + const Operation = IDL.Variant({ + 'Approve' : IDL.Record({ + 'fee' : Tokens, + 'from' : AccountIdentifier, + 'allowance_e8s' : IDL.Int, + 'allowance' : Tokens, + 'expires_at' : IDL.Opt(TimeStamp), + 'spender' : AccountIdentifier, + }), + 'Burn' : IDL.Record({ + 'from' : AccountIdentifier, + 'amount' : Tokens, + 'spender' : IDL.Opt(AccountIdentifier), + }), + 'Mint' : IDL.Record({ 'to' : AccountIdentifier, 'amount' : Tokens }), + 'Transfer' : IDL.Record({ + 'to' : AccountIdentifier, + 'fee' : Tokens, + 'from' : AccountIdentifier, + 'amount' : Tokens, + }), + 'TransferFrom' : IDL.Record({ + 'to' : AccountIdentifier, + 'fee' : Tokens, + 'from' : AccountIdentifier, + 'amount' : Tokens, + 'spender' : AccountIdentifier, + }), + }); + const Transaction = IDL.Record({ + 'memo' : Memo, + 'icrc1_memo' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'operation' : IDL.Opt(Operation), + 'created_at_time' : TimeStamp, + }); + const Block = IDL.Record({ + 'transaction' : Transaction, + 'timestamp' : TimeStamp, + 'parent_hash' : IDL.Opt(IDL.Vec(IDL.Nat8)), + }); + const BlockRange = IDL.Record({ 'blocks' : IDL.Vec(Block) }); + const QueryArchiveError = IDL.Variant({ + 'BadFirstBlockIndex' : IDL.Record({ + 'requested_index' : BlockIndex, + 'first_valid_index' : BlockIndex, + }), + 'Other' : IDL.Record({ + 'error_message' : IDL.Text, + 'error_code' : IDL.Nat64, + }), + }); + const QueryArchiveResult = IDL.Variant({ + 'Ok' : BlockRange, + 'Err' : QueryArchiveError, + }); + const QueryArchiveFn = IDL.Func( + [GetBlocksArgs], + [QueryArchiveResult], + ['query'], + ); + const ArchivedBlocksRange = IDL.Record({ + 'callback' : QueryArchiveFn, + 'start' : BlockIndex, + 'length' : IDL.Nat64, + }); + const QueryBlocksResponse = IDL.Record({ + 'certificate' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'blocks' : IDL.Vec(Block), + 'chain_length' : IDL.Nat64, + 'first_block_index' : BlockIndex, + 'archived_blocks' : IDL.Vec(ArchivedBlocksRange), + }); + const ArchivedEncodedBlocksRange = IDL.Record({ + 'callback' : IDL.Func( + [GetBlocksArgs], + [ + IDL.Variant({ + 'Ok' : IDL.Vec(IDL.Vec(IDL.Nat8)), + 'Err' : QueryArchiveError, + }), + ], + ['query'], + ), + 'start' : IDL.Nat64, + 'length' : IDL.Nat64, + }); + const QueryEncodedBlocksResponse = IDL.Record({ + 'certificate' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'blocks' : IDL.Vec(IDL.Vec(IDL.Nat8)), + 'chain_length' : IDL.Nat64, + 'first_block_index' : IDL.Nat64, + 'archived_blocks' : IDL.Vec(ArchivedEncodedBlocksRange), + }); + const SendArgs = IDL.Record({ + 'to' : TextAccountIdentifier, + 'fee' : Tokens, + 'memo' : Memo, + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(TimeStamp), + 'amount' : Tokens, + }); + const TransferArgs = IDL.Record({ + 'to' : AccountIdentifier, + 'fee' : Tokens, + 'memo' : Memo, + 'from_subaccount' : IDL.Opt(SubAccount), + 'created_at_time' : IDL.Opt(TimeStamp), + 'amount' : Tokens, + }); + const TransferError = IDL.Variant({ + 'TxTooOld' : IDL.Record({ 'allowed_window_nanos' : IDL.Nat64 }), + 'BadFee' : IDL.Record({ 'expected_fee' : Tokens }), + 'TxDuplicate' : IDL.Record({ 'duplicate_of' : BlockIndex }), + 'TxCreatedInFuture' : IDL.Null, + 'InsufficientFunds' : IDL.Record({ 'balance' : Tokens }), + }); + const TransferResult = IDL.Variant({ + 'Ok' : BlockIndex, + 'Err' : TransferError, + }); + const TransferFeeArg = IDL.Record({}); + const TransferFee = IDL.Record({ 'transfer_fee' : Tokens }); + return IDL.Service({ + 'account_balance' : IDL.Func([AccountBalanceArgs], [Tokens], ['query']), + 'account_balance_dfx' : IDL.Func( + [AccountBalanceArgsDfx], + [Tokens], + ['query'], + ), + 'account_identifier' : IDL.Func([Account], [AccountIdentifier], ['query']), + 'archives' : IDL.Func([], [Archives], ['query']), + 'decimals' : IDL.Func( + [], + [IDL.Record({ 'decimals' : IDL.Nat32 })], + ['query'], + ), + 'icrc1_balance_of' : IDL.Func([Account], [Icrc1Tokens], ['query']), + 'icrc1_decimals' : IDL.Func([], [IDL.Nat8], ['query']), + 'icrc1_fee' : IDL.Func([], [Icrc1Tokens], ['query']), + 'icrc1_metadata' : IDL.Func( + [], + [IDL.Vec(IDL.Tuple(IDL.Text, Value))], + ['query'], + ), + 'icrc1_minting_account' : IDL.Func([], [IDL.Opt(Account)], ['query']), + 'icrc1_name' : IDL.Func([], [IDL.Text], ['query']), + 'icrc1_supported_standards' : IDL.Func( + [], + [IDL.Vec(IDL.Record({ 'url' : IDL.Text, 'name' : IDL.Text }))], + ['query'], + ), + 'icrc1_symbol' : IDL.Func([], [IDL.Text], ['query']), + 'icrc1_total_supply' : IDL.Func([], [Icrc1Tokens], ['query']), + 'icrc1_transfer' : IDL.Func([TransferArg], [Icrc1TransferResult], []), + 'icrc2_allowance' : IDL.Func([AllowanceArgs], [Allowance], ['query']), + 'icrc2_approve' : IDL.Func([ApproveArgs], [ApproveResult], []), + 'name' : IDL.Func([], [IDL.Record({ 'name' : IDL.Text })], ['query']), + 'query_blocks' : IDL.Func( + [GetBlocksArgs], + [QueryBlocksResponse], + ['query'], + ), + 'query_encoded_blocks' : IDL.Func( + [GetBlocksArgs], + [QueryEncodedBlocksResponse], + ['query'], + ), + 'send_dfx' : IDL.Func([SendArgs], [BlockIndex], []), + 'symbol' : IDL.Func([], [IDL.Record({ 'symbol' : IDL.Text })], ['query']), + 'transfer' : IDL.Func([TransferArgs], [TransferResult], []), + 'transfer_fee' : IDL.Func([TransferFeeArg], [TransferFee], ['query']), + }); +}; +export const init = ({ IDL }) => { + const SubAccount = IDL.Vec(IDL.Nat8); + const Account = IDL.Record({ + 'owner' : IDL.Principal, + 'subaccount' : IDL.Opt(SubAccount), + }); + const FeatureFlags = IDL.Record({ 'icrc2' : IDL.Bool }); + const UpgradeArgs = IDL.Record({ + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const Tokens = IDL.Record({ 'e8s' : IDL.Nat64 }); + const TextAccountIdentifier = IDL.Text; + const Duration = IDL.Record({ 'secs' : IDL.Nat64, 'nanos' : IDL.Nat32 }); + const ArchiveOptions = IDL.Record({ + 'num_blocks_to_archive' : IDL.Nat64, + 'trigger_threshold' : IDL.Nat64, + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'cycles_for_archive_creation' : IDL.Opt(IDL.Nat64), + 'node_max_memory_size_bytes' : IDL.Opt(IDL.Nat64), + 'controller_id' : IDL.Principal, + }); + const InitArgs = IDL.Record({ + 'send_whitelist' : IDL.Vec(IDL.Principal), + 'token_symbol' : IDL.Opt(IDL.Text), + 'transfer_fee' : IDL.Opt(Tokens), + 'minting_account' : TextAccountIdentifier, + 'maximum_number_of_accounts' : IDL.Opt(IDL.Nat64), + 'accounts_overflow_trim_quantity' : IDL.Opt(IDL.Nat64), + 'transaction_window' : IDL.Opt(Duration), + 'max_message_size_bytes' : IDL.Opt(IDL.Nat64), + 'icrc1_minting_account' : IDL.Opt(Account), + 'archive_options' : IDL.Opt(ArchiveOptions), + 'initial_values' : IDL.Vec(IDL.Tuple(TextAccountIdentifier, Tokens)), + 'token_name' : IDL.Opt(IDL.Text), + 'feature_flags' : IDL.Opt(FeatureFlags), + }); + const LedgerCanisterPayload = IDL.Variant({ + 'Upgrade' : IDL.Opt(UpgradeArgs), + 'Init' : InitArgs, + }); + return [LedgerCanisterPayload]; +}; diff --git a/packages/ledger-icp/esbuild.mjs b/packages/ledger-icp/esbuild.mjs new file mode 100644 index 00000000..f3cda319 --- /dev/null +++ b/packages/ledger-icp/esbuild.mjs @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +import { build } from "../../scripts/esbuild.mjs"; + +build(); diff --git a/packages/ledger-icp/jest.config.js b/packages/ledger-icp/jest.config.js new file mode 100644 index 00000000..e75ede62 --- /dev/null +++ b/packages/ledger-icp/jest.config.js @@ -0,0 +1,7 @@ +const rootJestConfig = require("../../jest.config"); + +module.exports = { + ...rootJestConfig, + setupFiles: [`../../test-setup.ts`], + modulePathIgnorePatterns: ["./dist"], +}; diff --git a/packages/ledger-icp/package.json b/packages/ledger-icp/package.json new file mode 100644 index 00000000..7b863b19 --- /dev/null +++ b/packages/ledger-icp/package.json @@ -0,0 +1,46 @@ +{ + "name": "@dfinity/ledger-icp", + "version": "0.0.1", + "description": "A library for interfacing with the ICP ledger on the Internet Computer.", + "license": "Apache-2.0", + "main": "dist/cjs/index.cjs.js", + "module": "dist/esm/index.js", + "types": "dist/types/index.d.ts", + "files": [ + "dist", + "README.md", + "LICENSE" + ], + "scripts": { + "rmdir": "node ../../scripts/rmdir.mjs", + "ts-declaration": "tsc --emitDeclarationOnly --outDir dist/types", + "build": "npm run rmdir && mkdir -p dist && cp -R candid dist && node esbuild.mjs && npm run ts-declaration", + "prepack": "npm run build", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/dfinity/ic-js.git", + "directory": "packages/ledger-icp" + }, + "bugs": { + "url": "https://github.com/dfinity/ic-js" + }, + "keywords": [ + "internet computer", + "internet-computer", + "ic", + "dfinity", + "Ledger", + "ICP ledger", + "token", + "icp" + ], + "homepage": "https://github.com/dfinity/ic-js#readme", + "peerDependencies": { + "@dfinity/agent": "^0.19.2", + "@dfinity/candid": "^0.19.2", + "@dfinity/principal": "^0.19.2", + "@dfinity/utils": "^0.0.23" + } +} diff --git a/packages/ledger-icp/src/index.ts b/packages/ledger-icp/src/index.ts new file mode 100644 index 00000000..f59d2fbb --- /dev/null +++ b/packages/ledger-icp/src/index.ts @@ -0,0 +1 @@ +export * from "./ledger.canister"; diff --git a/packages/ledger-icp/src/ledger.canister.spec.ts b/packages/ledger-icp/src/ledger.canister.spec.ts new file mode 100644 index 00000000..2ff65568 --- /dev/null +++ b/packages/ledger-icp/src/ledger.canister.spec.ts @@ -0,0 +1,2 @@ +it("should be true to path CI until effective implementation", () => + expect(true).toBeTruthy()); diff --git a/packages/ledger-icp/src/ledger.canister.ts b/packages/ledger-icp/src/ledger.canister.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/packages/ledger-icp/src/ledger.canister.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/ledger-icp/tsconfig.json b/packages/ledger-icp/tsconfig.json new file mode 100644 index 00000000..ca17af18 --- /dev/null +++ b/packages/ledger-icp/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*", "candid/**/*"] +} diff --git a/scripts/build-next b/scripts/build-next index 4f62740b..3dee425a 100755 --- a/scripts/build-next +++ b/scripts/build-next @@ -7,6 +7,7 @@ npm ci node ./scripts/update-version.mjs utils node ./scripts/update-version.mjs nns-proto node ./scripts/update-version.mjs ledger +node ./scripts/update-version.mjs ledger-icp node ./scripts/update-version.mjs nns node ./scripts/update-version.mjs sns node ./scripts/update-version.mjs cmc diff --git a/scripts/compile-idl-js b/scripts/compile-idl-js index f412d86c..f7ef5b5e 100755 --- a/scripts/compile-idl-js +++ b/scripts/compile-idl-js @@ -26,6 +26,7 @@ did_files_to_compile() { did_files_to_compile_for_pkg "sns" did_files_to_compile_for_pkg "cmc" did_files_to_compile_for_pkg "ledger" + did_files_to_compile_for_pkg "ledger-icp" did_files_to_compile_for_pkg "ckbtc" did_files_to_compile_for_pkg "ic-management" } diff --git a/scripts/docs.js b/scripts/docs.js index 400cdbca..1a1c405b 100644 --- a/scripts/docs.js +++ b/scripts/docs.js @@ -33,6 +33,8 @@ const ledgerInputFiles = [ "./packages/ledger/src/index.canister.ts", ]; +const ledgerICPInputFiles = ["./packages/ledger/src/ledger.canister.ts"]; + const ckBTCInputFiles = [ "./packages/ckbtc/src/minter.canister.ts", "./packages/ckbtc/src/utils/btc.utils.ts", @@ -78,6 +80,13 @@ generateDocumentation({ buildOptions, }); +generateDocumentation({ + inputFiles: ledgerICPInputFiles, + outputFile: "./packages/ledger-icp/README.md", + markdownOptions, + buildOptions, +}); + generateDocumentation({ inputFiles: ckBTCInputFiles, outputFile: "./packages/ckbtc/README.md", diff --git a/scripts/import-candid b/scripts/import-candid index 4aeabfed..3b3e9e15 100755 --- a/scripts/import-candid +++ b/scripts/import-candid @@ -73,6 +73,9 @@ mkdir -p packages/ledger/candid import_did "rs/rosetta-api/icrc1/ledger/ledger.did" "icrc1_ledger.did" "ledger" import_did "rs/rosetta-api/icrc1/index/index.did" "icrc1_index.did" "ledger" +mkdir -p packages/ledger-icp/candid +import_did "rs/rosetta-api/icp_ledger/ledger.did" "ledger.did" "ledger-icp" + mkdir -p packages/ckbtc/candid import_did "rs/bitcoin/ckbtc/minter/ckbtc_minter.did" "minter.did" "ckbtc"