diff --git a/README.md b/README.md
index 681eb8a50b..220bf01d62 100644
--- a/README.md
+++ b/README.md
@@ -588,11 +588,11 @@ The [Ecosystem Helper](https://mvw4g-yiaaa-aaaam-abnva-cai.icp0.io/) is an oncha
### Asset guidelines
-| Asset | | Requirements | Format | Notes |
-|-------------|----------|--------------|--------------|-----------------------------------------------------------------------------------|
-| logo | required | 112x112px | webp/svg/png | Currently displayed 56x56px |
-| screenshots | optional | 1024x576px | webp/jpg | The schema supports multiple files, but only the first one will be displayed |
-| video | optional | max 10MB | webm/mp4 | If there is a video file specified, it will be displayed instead of a screenshot. |
+| Asset | | Requirements | Format | Notes |
+|-------------|----------|---------------------------------|---------------------------|----------------------------------------------------------------------------------------|
+| logo | required | 112x112px (1:1 aspect ratio) | svg(recommended)/png/webp | Optimize file size with [SVGOMG](https://svgomg.net) or [TinyPNG](https://tinypng.com) |
+| screenshots | optional | 1024x576px | webp/jpg | The schema supports multiple files, but only the first one will be displayed |
+| video | optional | max 10MB | webm/mp4 | If there is a video file specified, it will be displayed instead of a screenshot. |
### Tags
diff --git a/blog/features/vetkey-primer.md b/blog/features/vetkey-primer.md
index 47dbd496d3..224bc23bb3 100644
--- a/blog/features/vetkey-primer.md
+++ b/blog/features/vetkey-primer.md
@@ -63,7 +63,7 @@ Considering that blockchains are very public places where transparency has been
Note that we care most about the secret ***key derivation*** here, as that is the most sensitive part which we want to protect from one central (potentially untrusted, unauthorized, or compromised) party, and hence the **KD** in VETKD. To deal with the centralization point, we need to move into the distributed setting. Assuming there is no one trusted party, we distribute trust amongst multiple parties, and require that some *threshold* of them collaborate on shares of the master secret key to derive decryption keys.
How do parties **get shares** of the master secret key? This is done by leveraging a distributed key generation (DKG) protocol, where a threshold of honest parties (or nodes) work together to obtain a set of master key shares. Assuming no collusion between nodes, at no point does any one node hold the full private key.
-Click around to learn more about [threshold cryptography]( https://en.wikipedia.org/wiki/Threshold_cryptosystem), [DKG](https://en.wikipedia.org/wiki/Distributed_key_generation) and chapter 22 in the [Boneh-Shoup book](http://toc.cryptobook.us/).
+Click around to learn more about [threshold cryptography]( https://en.wikipedia.org/wiki/Threshold_cryptosystem), [DKG](https://en.wikipedia.org/wiki/Distributed_key_generation) and chapter 22 in the [Boneh-Shoup book](https://toc.cryptobook.us/).
It’s clear from above that we don't want a centralised key derivation process and this is why we need the **T** for the KD process, but what about **V** and **E**? Perhaps this is best highlighted by a scenario.
@@ -100,7 +100,7 @@ At a first glance, we could guess that we will need a distributed key generation
Crucially, An observation buried in [BF01] gives us the answer. Moni Naor noted that an IBE scheme can be directly converted into a signature scheme. Considering the key derivation of Boneh-Franklin IBE specifically, the resulting signature scheme happens to be BLS.
### BLS signatures
-Digital signatures are used everywhere in cryptography and in the blockchain world to attest to the authenticity of a message, transaction, or other pieces of information. As they are so prevalent, it’s really worth spending time getting to know them. You can get a high level view on wikipedia ([Digital Signatures](https://en.wikipedia.org/wiki/Digital_signature) and [BLS](https://en.wikipedia.org/wiki/BLS_digital_signature)), and dive into the [Boneh-Shoup book](http://toc.cryptobook.us/) when you want more formal details.
+Digital signatures are used everywhere in cryptography and in the blockchain world to attest to the authenticity of a message, transaction, or other pieces of information. As they are so prevalent, it’s really worth spending time getting to know them. You can get a high level view on wikipedia ([Digital Signatures](https://en.wikipedia.org/wiki/Digital_signature) and [BLS](https://en.wikipedia.org/wiki/BLS_digital_signature)), and dive into the [Boneh-Shoup book](https://toc.cryptobook.us/) when you want more formal details.
BLS signatures are a particular type of digital signature introduced in by Dan Boneh, Ben Lynn, and Hovav Shacham in 2001.
@@ -132,7 +132,7 @@ This page contains a high level view and description of VETKD and its building b
It also shows one possible way of building VETKD, there are others, some with fancy features, that are described more in the paper. There are many use cases and motivations for building VETKD, these are discussed in [the video](https://youtu.be/baM6jHnmMq8) and can be written up if you like. There are also extensions that could be built depending on what is needed in the community. Finally, note that this page is hosted onchain.
## References
-* [BS23](http://toc.cryptobook.us/) - The Boneh-Shoup Book.
+* [BS23](https://toc.cryptobook.us/) - The Boneh-Shoup Book.
* [BF01](https://crypto.stanford.edu/~dabo/papers/bfibe.pdf) - The IBE paper.
* [BLS01](https://www.iacr.org/archive/asiacrypt2001/22480516.pdf) - The BLS paper.
* [DH76](https://ee.stanford.edu/~hellman/publications/24.pdf) - Diffie and Hellman's New Directions paper.
diff --git a/blog/news-and-updates/2023-12-06-update.mdx b/blog/news-and-updates/2023-12-06-update.mdx
index 9932cab04c..da5a0ab057 100644
--- a/blog/news-and-updates/2023-12-06-update.mdx
+++ b/blog/news-and-updates/2023-12-06-update.mdx
@@ -15,7 +15,7 @@ Hello developers and welcome back to developer weekly! This week, we have some v
On Friday, December 1st, the NNS proposals to enable ckETH on ICP went live. We're excited to announce that all proposals were passed by the NNS, and ckETH is now live on the mainnet!
-ckETH has been added to the ICP dashboard, which you can view [here](http://dashboard.internetcomputer.org/ethereum). You can learn how to interact with ckETH by reviewing the ckETH minter documentation [here](https://github.com/dfinity/ic/blob/master/rs/ethereum/cketh/minter/README.adoc).
+ckETH has been added to the ICP dashboard, which you can view [here](https://dashboard.internetcomputer.org/ethereum). You can learn how to interact with ckETH by reviewing the ckETH minter documentation [here](https://github.com/dfinity/ic/blob/master/rs/ethereum/cketh/minter/README.adoc).
ckETH support is also live in the ICRC-1 wallet, which includes ckETH has a pre-defined token. The index canister has been integrated, allowing you to mint directly to your principal. The ICRC-1 wallet canister can be found [here](https://e4hv6-7yaaa-aaaao-a2ida-cai.icp0.io/)
diff --git a/blog/news-and-updates/2024-08-14-update.mdx b/blog/news-and-updates/2024-08-14-update.mdx
index 326605868f..19a6175e1a 100644
--- a/blog/news-and-updates/2024-08-14-update.mdx
+++ b/blog/news-and-updates/2024-08-14-update.mdx
@@ -27,7 +27,7 @@ The digital assets section of the developer docs has gotten an overhaul! Before,
- [Token standards](/docs/current/developer-docs/defi/tokens/token-standards)
-- [Asset flow](/docs/current/developer-docs/defi/tokens/asset_flow/)
+- [Asset flow](/docs/current/developer-docs/defi/overview)
- [Ledger integration options](/docs/current/developer-docs/defi/tokens/advanced/direct_integration)
diff --git a/blog/news-and-updates/2024-10-09-update.mdx b/blog/news-and-updates/2024-10-09-update.mdx
index dbd6623103..40e3630da4 100644
--- a/blog/news-and-updates/2024-10-09-update.mdx
+++ b/blog/news-and-updates/2024-10-09-update.mdx
@@ -40,7 +40,7 @@ Developer office hours are back in the ICP developer Discord server! Every Wedne
Be sure to drop in to the session and ask questions, share your project, or simply listen in on the discussion.
-[Join the ICP developer Discord server](https://discord.gg/RMZNkGMp8N).
+[Join the ICP developer Discord server](https://discord.internetcomputer.org).
## Community spotlight: KongSwap
@@ -50,4 +50,4 @@ You can [try KongSwap yourself](https://www.kongswap.io/?viewtab=swap&pool=ICP_c
That'll wrap up this week. Tune back in next week for more developer updates!
--DFINITY
\ No newline at end of file
+-DFINITY
diff --git a/blog/news-and-updates/2024-12-04-update.mdx b/blog/news-and-updates/2024-12-04-update.mdx
new file mode 100644
index 0000000000..e4f2792748
--- /dev/null
+++ b/blog/news-and-updates/2024-12-04-update.mdx
@@ -0,0 +1,42 @@
+---
+title: Developer weekly update December 4, 2024
+description: This week we have a new release of dfx, an important update about the Bitcoin integration, and an update from the community project Juno.
+tags: [Devs]
+image: /img/blog/dev-update-blog-dec-4.jpg
+---
+
+# Developer weekly update December 4, 2024
+
+![December 4 2024](../../static/img/blog/dev-update-blog-dec-4.jpg)
+
+Hello developers, and welcome to this week's developer weekly update! This week we have a new release of `dfx`, an important update about the Bitcoin integration, and an update from the community project Juno. Let's get started!
+
+## dfx v0.24.3
+
+The latest version of `dfx` is now promoted! This latest update includes new features such as:
+
+- PocketIC now supports Bitcoin through the `--enable-bitcoin` and `--bitcoin-node` flags.
+
+- The canisters for the ICP, ckBTC, and ckETH ledger canisters can now be pulled.
+
+- The frontend canister now supports setting canister permissions in the init arguments.
+
+- Output for `dfx start` and `dfx cycles` have been improved.
+
+[Read the full release notes](https://github.com/dfinity/sdk/releases/tag/0.24.3).
+
+## Bitcoin integration updates
+
+The Bitcoin Testnet API is being migrated from Testnet v3 to Testnet v4. To support this work, the ckTestBTC minter has been stopped and the Bitcoin Testnet API has been disabled. Once the migration has finished, these features will be re-enabled.
+
+You can stay up to date on the status via the [forum](https://forum.dfinity.org/t/direct-integration-with-bitcoin/6147/743?u=cryptoschindler).
+
+## Juno v0.0.39
+
+A new version of Juno has been released! This latest version introduces backups to Juno through the new ICP canister snapshot feature. Backups are available through both the Juno API and the Juno CLI tool.
+
+[Learn more in the Juno release notes](https://github.com/junobuild/juno/releases/tag/v0.0.39).
+
+That'll wrap up this week. Tune back in next week for more developer updates!
+
+-DFINITY
\ No newline at end of file
diff --git a/blog/news-and-updates/team-spotlight-sdk.mdx b/blog/news-and-updates/team-spotlight-sdk.mdx
index bc127d5054..6ffa92964b 100644
--- a/blog/news-and-updates/team-spotlight-sdk.mdx
+++ b/blog/news-and-updates/team-spotlight-sdk.mdx
@@ -67,7 +67,7 @@ Hey devs and welcome to this edition of ICP team spotlight! In this issue, we sa
**The SDK team is pretty involved with the dev community on the forum and Discord server, which I'm sure has lead to features derived as a result of community feedback. What are some of the improvements made as a direct result of developer feedback?**
-*Lots! We built the [developer feedback board](http://dx.internetcomputer.org) a while back, and every two weeks, our internal focus group meets to go over the latest items and check-in on the progress we’ve made addressing others. One thing that's come as a result of the feedback received is the `dfx` version manager. Developers expressed that they want a way to switch `dfx` versions easily. We spent some time working out how best to accomplish that, and the `dfx` version manager was born. Another example is the Cycles Ledger - we heard feedback that the Cycles Wallet was a pain to use and developers wanted a better solution. We are continuously looking for ways to improve our tooling, so keep the feedback coming!*
+*Lots! We built the [developer feedback board](https://dx.internetcomputer.org) a while back, and every two weeks, our internal focus group meets to go over the latest items and check-in on the progress we’ve made addressing others. One thing that's come as a result of the feedback received is the `dfx` version manager. Developers expressed that they want a way to switch `dfx` versions easily. We spent some time working out how best to accomplish that, and the `dfx` version manager was born. Another example is the Cycles Ledger - we heard feedback that the Cycles Wallet was a pain to use and developers wanted a better solution. We are continuously looking for ways to improve our tooling, so keep the feedback coming!*
**Where should developers look for the latest SDK updates?**
diff --git a/docs/developer-docs/defi/dex/overview.mdx b/docs/developer-docs/defi/dex/overview.mdx
index 3ac89097e9..1e63f6763d 100644
--- a/docs/developer-docs/defi/dex/overview.mdx
+++ b/docs/developer-docs/defi/dex/overview.mdx
@@ -32,7 +32,7 @@ Some examples of DEXs running on ICP include:
## Interacting with a DEX
-To use a decentralized exchange (DEX) on ICP, you can interact with the web application for the exchange, use [tooling such as an SDK or API](#tooling) for more technical interactions, or create your own decentralized exchange application. DEXs are used to interact with the token mechanics of [ICP](docs/current/developer-docs/defi/tokens/token-standards#icp-tokens), the native token of the Internet Computer, and [ICRC-1](/docs/current/developer-docs/defi/tokens/token-standards#icrc-1) compliant tokens.
+To use a decentralized exchange (DEX) on ICP, you can interact with the web application for the exchange, use [tooling such as an SDK or API](#tooling) for more technical interactions, or create your own decentralized exchange application. DEXs are used to interact with the token mechanics of [ICP](/docs/current/developer-docs/defi/tokens/token-standards#icp-tokens), the native token of the Internet Computer, and [ICRC-1](/docs/current/developer-docs/defi/tokens/token-standards#icrc-1) compliant tokens.
### Tooling
diff --git a/docs/developer-docs/defi/tokens/asset_flow/_category_.yml b/docs/developer-docs/defi/tokens/asset_flow/_category_.yml
deleted file mode 100644
index 947103ef9c..0000000000
--- a/docs/developer-docs/defi/tokens/asset_flow/_category_.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-label: 'Asset Flow'
-position: 7
-collapsed: true
\ No newline at end of file
diff --git a/docs/developer-docs/defi/tokens/asset_flow/index.mdx b/docs/developer-docs/defi/tokens/asset_flow/index.mdx
deleted file mode 100644
index 0750563296..0000000000
--- a/docs/developer-docs/defi/tokens/asset_flow/index.mdx
+++ /dev/null
@@ -1,146 +0,0 @@
----
-keywords: [intermediate, tokens, tutorial, ledger, asset flow]
----
-
-import TabItem from "@theme/TabItem";
-import { AdornedTabs } from "/src/components/Tabs/AdornedTabs";
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
-
-
-# Asset flow
-
-
-
-## Overview
-
-When interacting with the [ICP or ICRC-1 ledgers](/docs/developer-docs/defi/tokens/ledger/overview.mdx), there are different asset flow operations that can be executed. These operations are:
-
-* **Transfer**: A simple transfer between two entities.
-* **Approve**: Approving tokens to be spent by another entity.
-* **Mint**: Creating new tokens (**Requires minting account privileges**).
-* **Burn**: Destroying tokens.
-* **TransferFrom**: Spend approved tokens on behalf of another entity.
-
-Both ledger types support these operations. There are several ways on how to create transactions corresponding to each asset flow operation. This guide will demonstrate how to use `dfx` using `Rust` code.
-
-### Prerequisites
-
-* Download and install [`dfx`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-parent).
-
-* Setup an [ICP Rust agent](https://crates.io/crates/ic-agent).
-
-## Transfer tokens
-
-To transfer tokens, your transaction will need the following required fields:
-
-* `to`: The account that will receive the tokens.
-* `amount`: The amount of tokens to be sent.
-
-Additionally, the transaction takes the following optional fields:
-
-* `from_subaccount`: The subaccount of the approver.
-* `fee`: The fee paid by the sender for the transfer. If not set, the default fee will have to be paid.
-* `memo`: An arbitrary 32 bytes array to ensure transaction hash uniqueness.
-* `created_at_time`: A timestamp that is used to trigger the [deduplication mechanism](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/README.md#transaction_deduplication).
-
-### dfx
-Here is an example command for a `Transfer` transaction using `dfx`:
-```bash
-dfx canister call icrc1_ledger_canister icrc1_transfer "(record { to = record { owner = principal \"sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe\";}; amount = 10_000;})"
-```
-
-### Rust
-Here is an example Rust code snippet for making a `Transfer` transaction:
-```bash
-let to = icrc_ledger_types::icrc1::account::Account{ owner:ic_principal::Principal::from_slice(&[1, 2, 3, 4]) , subaccount: None};
-let amount = candid::Nat::from(500u64);
-let transfer_arg = icrc_ledger_types::icrc1::transfer::TransferArg{
- from_subaccount: None,
- to,
- amount,
- fee: None,
- memo: : None,
- created_at_time: : None,
-}
-candid::Decode!(&ic_agent.update("icrc1_transfer", &candid::Encode!(&transfer_arg)?).await.unwrap(), Result).unwrap();
-```
-:::info
-Mint and burn operations are technically speaking also transfers. They work exactly like regular transfers with certain conditions that have to be met. They are the following:
-* For **mint** operations, the sender of the transfer has to be the minter account. This means that if you want to make mint transactions, you will need to know the private key of the minter account. The recipient will receive the newly minted tokens.
-* For **burn** operations, the receiver needs to be set to the mint account while the sender can be any account. You can request the minter account by calling the `icrc1_minting_account` endpoint of the ledger.
-:::
-
-## Approve tokens
-To approve tokens, your transaction will need the following required fields:
-
-* `spender`: The account that is allowed to spend the tokens.
-* `amount`: The maximum amount of tokens to be spent by the spender.
-
-Additionally, the transaction takes the following optional fields:
-
-* `from_subaccount`: The subaccount of the approver.
-* `expected_allowance`: If set, this field serves as a guarantee that before the new approved amount is set, the expected allowance reflects the previously set approved amount.
-* `expires_at`: The timestamp at which the allowance will expire.
-* `fee`: The fee paid by the approver for the approval. If not set, the default fee will have to be paid.
-* `memo`: An arbitrary 32 bytes array to ensure transaction hash uniqueness.
-* `created_at_time`: A timestamp that is used to trigger the [deduplication mechanism](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/README.md#transaction_deduplication).
-
-### dfx
-Here is an example command for an `Approve` transaction using `dfx`:
-```bash
-dfx canister call icrc1_ledger_canister icrc2_approve "(record { amount = 500; spender = record{owner = principal \"sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe\";} })"
-```
-
-### Rust
-Here is an example Rust code snippet for making an `Approve` transaction:
-```bash
-let spender = icrc_ledger_types::icrc1::account::Account{ owner:ic_principal::Principal::from_slice(&[1, 2, 3, 4]) , subaccount: None};
-let amount = candid::Nat::from(500u64);
-let approve_args = icrc_ledger_types::icrc1::approve::ApproveArgs{
- from_subaccount: None,
- spender,
- amount,
- expected_allowance: None,
- expires_at: None,
- fee: None,
- memo: : None,
- created_at_time: : None,
-}
-candid::Decode!(&ic_agent.update("icrc2_approve", &candid::Encode!(&approve_args)?).await.unwrap(), Result).unwrap();
-```
-
-## Transferring approved tokens
-To transfer approved tokens, your transaction will need the following required fields:
-* `to`: The account that will receive the tokens.
-* `from`: The approvers account who's tokens will be transferred.
-* `amount`: The amount of tokens to be sent.
-Additionally, the transaction takes the following optional fields:
-* `spender_subaccount`: The subaccount of the spender.
-* `fee`: The fee paid by the sender for the transfer. If not set the default fee will have to be paid.
-* `memo`: An arbitrary 32 bytes array to ensure transaction hash uniqueness.
-* `created_at_time`: A timestamp that is used to trigger the [deduplication mechanism](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/README.md#transaction_deduplication).
-
-### dfx
-Here is an example command for a `TransferFrom` transaction using `dfx`:
-```bash
-dfx canister call icrc1_ledger_canister icrc2_transfer_from "(record { from = record { owner = principal \"ltyfs-qiaaa-aaaak-aan3a-cai\";}; to = record { owner = principal \"sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe\";}; amount = 500;})"
-```
-
-### Rust
-Here is an example Rust code snippet for making a `TransferFrom` transaction:
-```bash
-let to = icrc_ledger_types::icrc1::account::Account{ owner:ic_principal::Principal::from_slice(&[1, 2, 3, 4]) , subaccount: None};
-let from = icrc_ledger_types::icrc1::account::Account{ owner:ic_principal::Principal::from_slice(&[5, 6, 7, 8]) , subaccount: None};
-let amount = candid::Nat::from(500u64);
-let transfer_from_arg = icrc_ledger_types::icrc1::transfer_from::TransferFromArgs{
- spender_subaccount: None,
- from,
- to,
- amount,
- fee: None,
- memo: : None,
- created_at_time: : None,
-}
-candid::Decode!(&ic_agent.update("icrc2_transfer_from", &candid::Encode!(&transfer_from_arg)?).await.unwrap(), Result).unwrap();
-```
\ No newline at end of file
diff --git a/docs/developer-docs/defi/tokens/ledger/overview.mdx b/docs/developer-docs/defi/tokens/ledger/overview.mdx
deleted file mode 100644
index 3700da07a1..0000000000
--- a/docs/developer-docs/defi/tokens/ledger/overview.mdx
+++ /dev/null
@@ -1,31 +0,0 @@
----
-keywords: [intermediate, rosetta, tutorial, accountidentifier]
----
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Ledger overview
-
-In this section, you will learn about the different types of ledgers that exist on the Internet Computer. This guide will go into detail about what the different ledgers are, what their purposes are, and how they differ from ledgers you may be familiar with from other blockchains.
-
-## ICP ledger
-The ICP ledger is a canister that is responsible for keeping track of ICP balances, processing new transactions, and providing clients with data about the history of transactions. It stores all data onchain. For every transaction, a single block is created, which points to its parent block by storing the parent block's hash.
-
-The ICP ledger uses `AccountIdentifiers` as its internal account representation. It is compatible with the ICRC-1 standard; however, due to the fact that it uses `AccountIdentifiers` instead of `Accounts'` it stores information in a different block format than ICRC-1 ledgers. The same is true for the minting account of the ICP ledger.
-
-It runs on the NNS subnet, as it is part of the NNS, and its controller is the governance canister. Upgrades to the ICP ledger have to be approved by the NNS, making the process decentralized.
-
-## ICRC-1 ledgers
-ICRC-1 ledgers are a standardized version of ledgers on the Internet Computer. While [ICRC-1](/docs/current/developer-docs/defi/tokens/token-standards) is the network standard defining how ledger canisters should behave, an ICRC-1 ledger is a single implementation of the ICRC-1 standard. It differs from the ICP ledger as it uses `Accounts` as its internal representation.
-
-ICRC-1 ledgers are stand-alone implementations, but in many cases, they are part of a larger software structure, such as an SNS or chain-key token implementation.
-
-## Differences from other blockchains
-One of the biggest differences between ledgers deployed on ICP and ledgers deployed on other blockchains is that most account-based blockchains have the balances of accounts baked into their base protocol (e.g., Ethereum). This is not the case with either the ICP or ICRC-1 ledgers.
-
-The ICP ledger canister sits on the application layer of the network rather than the protocol level. Consensus on the Internet Computer is independent of the existence of the ICP ledger. Nevertheless, the ICP ledger is fundamentally important to the way the network functions, especially due to its importance as a part of the NNS.
-
-Since the ICP ledger runs on the application layer, transfers of the ICP token do not happen at the protocol level as they do on other chains. All ICP token transactions go through this canister. Any information gathered about historic ICP token transactions originates from the ICP ledger canister. This includes the ICP index canister, which fetches blocks periodically from the ICP ledger canister.
-
-ICRC-1 ledgers are very similar in this regard; however, they resemble tokens that can often be found on other blockchains more closely. They are also run by a canister that runs the ICRC-1 ledger code, and all transactions of the ICRC-1 token go through an ICRC-1 ledger canister.
-
-
diff --git a/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx b/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx
index 0a370a10bd..21cca18718 100644
--- a/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx
+++ b/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx
@@ -135,7 +135,7 @@ Open the `dfx.json` file in your project's directory. Replace the existing conte
"ic": "ryjl3-tyaaa-aaaaa-aaaba-cai"
}
},
- "init_arg" : "(variant { Init = record { minting_account = "MINTER_ACCOUNT_ID"; initial_values = vec { record { "DEFAULT_ACCOUNT_ID"; record { e8s = 10_000_000_000 : nat64; }; }; }; send_whitelist = vec {}; transfer_fee = opt record { e8s = 10_000 : nat64; }; token_symbol = opt \"LICP\"; token_name = opt \"Local ICP\"; } })"
+ "init_arg" : "(variant { Init = record { minting_account = \"MINTER_ACCOUNT_ID\"; initial_values = vec { record { \"DEFAULT_ACCOUNT_ID\"; record { e8s = 10_000_000_000 : nat64; }; }; }; send_whitelist = vec {}; transfer_fee = opt record { e8s = 10_000 : nat64; }; token_symbol = opt \"LICP\"; token_name = opt \"Local ICP\"; } })"
}
},
"defaults": {
diff --git a/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx b/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx
index 313893e937..19b9dfc9a6 100644
--- a/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx
+++ b/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx
@@ -33,11 +33,11 @@ If using `dfx` version 0.17.1 or newer, choose 'Motoko' for the backend language
### Step 3: Determine ledger file locations.
-Go to the [releases overview](https://dashboard.internetcomputer.org/releases) and copy the latest replica binary revision. At the time of writing, this is `aba60ffbc46acfc8990bf4d5685c1360bd7026b9`.
+Search for [ledger-suite-icrc releases](https://github.com/dfinity/ic/releases?q=ledger-suite-icrc&expanded=false) and select the latest ICRC ledger suite release. At the time of writing, this is [`ledger-suite-icrc-2024-11-28`](https://github.com/dfinity/ic/releases/tag/ledger-suite-icrc-2024-11-28).
-The URL for the ledger Wasm module is `https://download.dfinity.systems/ic//canisters/ic-icrc1-ledger.wasm.gz`, so with the above revision it would be `https://download.dfinity.systems/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/canisters/ic-icrc1-ledger.wasm.gz`.
+The URL for the ledger Wasm module is `https://github.com/dfinity/ic/releases/download//ic-icrc1-ledger.wasm.gz`, so with the above release it would be `https://github.com/dfinity/ic/releases/download/ledger-suite-icrc-2024-11-28/ic-icrc1-ledger.wasm.gz`.
-The URL for the ledger .did file is `https://raw.githubusercontent.com/dfinity/ic//rs/ledger_suite/icrc1/ledger/ledger.did`, so with the above revision it would be `https://raw.githubusercontent.com/dfinity/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/rs/ledger_suite/icrc1/ledger/ledger.did`.
+The URL for the ledger .did file is `https://github.com/dfinity/ic/releases/download//ledger.did`, so with the above release it would be `https://github.com/dfinity/ic/releases/download/ledger-suite-icrc-2024-11-28/ledger.did`.
#### Optional:
@@ -51,15 +51,15 @@ chmod +x download_latest_icrc1_ledger.sh
These files will be used by the `dfx.json` file as described in the next step.
### Step 4: Configure the `dfx.json` file.
-Open the `dfx.json` file in your project's directory. Replace the existing content with the following and make sure you replace `` in the `candid` and `wasm` URLs as shown in step 3:
+Open the `dfx.json` file in your project's directory. Replace the existing content with the following and make sure you replace `` in the `candid` and `wasm` URLs as shown in step 3:
``` json
{
"canisters": {
"icrc1_ledger_canister": {
"type": "custom",
- "candid": "https://raw.githubusercontent.com/dfinity/ic//rs/ledger_suite/icrc1/ledger/ledger.did",
- "wasm": "https://download.dfinity.systems/ic//canisters/ic-icrc1-ledger.wasm.gz"
+ "candid": "https://github.com/dfinity/ic/releases/download//ledger.did",
+ "wasm": "https://github.com/dfinity/ic/releases/download//ic-icrc1-ledger.wasm.gz"
}
},
"defaults": {
diff --git a/docs/developer-docs/defi/tokens/ledger/setup/overview.mdx b/docs/developer-docs/defi/tokens/ledger/setup/overview.mdx
deleted file mode 100644
index e466f691fc..0000000000
--- a/docs/developer-docs/defi/tokens/ledger/setup/overview.mdx
+++ /dev/null
@@ -1,12 +0,0 @@
----
-keywords: [intermediate, rosetta, tutorial, accountidentifier]
----
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Ledger setup
-
-## Overview
-
-In this section you will learn how to setup a local instance of a ledger. This guide will go into depth on how to install, deploy and initialize two types of ledgers:
-* [ICP Ledger Setup](/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx)
-* [ICRC-1 Ledger Setup](/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx)
diff --git a/docs/developer-docs/defi/tokens/ledger/usage/overview.mdx b/docs/developer-docs/defi/tokens/ledger/usage/overview.mdx
deleted file mode 100644
index 50b8f356e2..0000000000
--- a/docs/developer-docs/defi/tokens/ledger/usage/overview.mdx
+++ /dev/null
@@ -1,12 +0,0 @@
----
-keywords: [intermediate, rosetta, tutorial, accountidentifier]
----
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Ledger usage
-
-## Overview
-
-In this section you will learn how to use a ledger. This guide will go into depth on how to interact with two types of ledgers:
-* [Using the ICP ledger](/docs/developer-docs/defi/tokens/ledger/usage/icp_ledger_usage.mdx)
-* [Using the ICRC-1 ledger](/docs/developer-docs/defi/tokens/ledger/usage/icrc1_ledger_usage.mdx)
diff --git a/docs/developer-docs/defi/wallets/overview.mdx b/docs/developer-docs/defi/wallets/overview.mdx
index 0a9f3ac970..d8a8733fa8 100644
--- a/docs/developer-docs/defi/wallets/overview.mdx
+++ b/docs/developer-docs/defi/wallets/overview.mdx
@@ -27,7 +27,7 @@ On ICP, both developers and end users will use different types of wallets for di
| Type of wallet | Activities | Examples |
|----------------|------------|----------|
|[Asset wallet](overview.mdx) | Hold, transfer, and receive assets such as fungible tokens including ICP and other ICRC1/ICRC2 tokens (ex. ckBTC, ckETH) and non-fungible tokens. View token holdings. Stake ICP and create a neuron to participate in the NNS. User based authentication. | Plug, Stoic, Oisy. [View the full list](#third-party-custody). |
-| [Canister-controlled wallet](/docs/current/developer-docs/smart-contracts/overview/introduction) | Using [Chain Fusion](/docs/current/developer-docs/multi-chain/overview), canisters on ICP can hold, sign, and transact with assets on various chains including ICP, Bitcoin, Ethereum, EVMs, and more. | [Cycles wallet](/docs/current/developer-docs/defi/cycles/cycles-wallet) (will be depreciated from dfx). Holds cycles needed to deploy, upgrade, and perform other operations on canisters. The cycles wallet is still supported, but has been replaced by the [cycles ledger](docs/current/developer-docs/defi/cycles/cycles-ledger). It is recommended to use the cycles ledger instead. |
+| [Canister-controlled wallet](/docs/current/developer-docs/smart-contracts/overview/introduction) | Using [Chain Fusion](/docs/current/developer-docs/multi-chain/overview), canisters on ICP can hold, sign, and transact with assets on various chains including ICP, Bitcoin, Ethereum, EVMs, and more. | [Cycles wallet](/docs/current/developer-docs/defi/cycles/cycles-wallet) (will be depreciated from dfx). Holds cycles needed to deploy, upgrade, and perform other operations on canisters. The cycles wallet is still supported, but has been replaced by the [cycles ledger](/docs/current/developer-docs/defi/cycles/cycles-ledger). It is recommended to use the cycles ledger instead. |
### Other authentication methods
diff --git a/docs/developer-docs/gas-cost.mdx b/docs/developer-docs/gas-cost.mdx
index abfef6f732..8a35ed2ae8 100644
--- a/docs/developer-docs/gas-cost.mdx
+++ b/docs/developer-docs/gas-cost.mdx
@@ -236,7 +236,7 @@ Getting cycles back from a canister
- To withdraw cycles from a canister, the [canister must be deleted](/docs/current/tutorials/developer-journey/level-1/1.6-managing-canisters#getting-cycles-back-from-a-canister).
Topping up canisters
- - [Top up your canisters](docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister).
+ - [Top up your canisters](/docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister).
- [Cycles management services](/docs/current/developer-docs/smart-contracts/topping-up/cycles_management_services).
- [Cycle.express](https://cycle.express/).
diff --git a/docs/developer-docs/getting-started/install.mdx b/docs/developer-docs/getting-started/install.mdx
index 8469a2110b..ce5bc0a57f 100644
--- a/docs/developer-docs/getting-started/install.mdx
+++ b/docs/developer-docs/getting-started/install.mdx
@@ -136,6 +136,8 @@ It also has dependencies of a few additional, important packages:
- [**Candid**](/docs/current/developer-docs/smart-contracts/candid/candid-concepts): An interface description language (IDL) used to interact with a canister's methods. A **method** is a function exposed by the canister that can be called by a user, another canister, or the application's frontend.
+For troubleshooting common `dfx` errors, see [IC SDK troubleshooting](troubleshooting.mdx).
+
## Next step
Next, you must create a developer identity. This identity will be used to control and manage your project's canisters.
diff --git a/docs/developer-docs/getting-started/tokens-and-cycles.mdx b/docs/developer-docs/getting-started/tokens-and-cycles.mdx
index 14f2fef3d2..e773172e10 100644
--- a/docs/developer-docs/getting-started/tokens-and-cycles.mdx
+++ b/docs/developer-docs/getting-started/tokens-and-cycles.mdx
@@ -50,9 +50,9 @@ The Internet Computer supports creating and deploying custom fungible or non-fun
## What is a ledger?
-A [**ledger**](/docs/current/developer-docs/defi/tokens/ledger/overview) is a system canister used to store accounts and their transactions. Each token on the Internet Computer has its **own** ledger. This means that there are separate ledgers for ICP tokens, cycles, and every ICRC token that has been deployed on the network.
+A [**ledger**](/docs/current/developer-docs//defi/overview) is a system canister used to store accounts and their transactions. Each token on the Internet Computer has its **own** ledger. This means that there are separate ledgers for ICP tokens, cycles, and every ICRC token that has been deployed on the network.
-[Learn more about ledgers](/docs/current/developer-docs/defi/tokens/ledger/overview).
+[Learn more about ledgers](/docs/current/developer-docs//defi/overview).
## Obtaining cycles
diff --git a/docs/developer-docs/getting-started/troubleshooting.mdx b/docs/developer-docs/getting-started/troubleshooting.mdx
new file mode 100644
index 0000000000..06197041f5
--- /dev/null
+++ b/docs/developer-docs/getting-started/troubleshooting.mdx
@@ -0,0 +1,113 @@
+---
+keywords: [intermediate, test, tutorial, troubleshooting, dfx troubleshooting, ic sdk, dfx, ic sdk troubleshooting]
+---
+
+import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
+
+# IC SDK troubleshooting
+
+
+
+## Overview
+
+This section provides information to help you troubleshoot and resolve or work around common issues that are related to the following tasks:
+
+- Downloading and installing the IC SDK.
+
+- Creating, building, or deploying canisters.
+
+- Using the [IC SDK](/docs/current/developer-docs/getting-started/install).
+
+- Running the local replica.
+
+## Migrating an existing project
+
+Currently, there is no automatic migration or backward compatibility for any projects that you might have created using previous versions of the IC SDK. After upgrading to the latest version, you might see error or failure messages if you attempt to build or install a project created with a previous version of the IC SDK.
+
+In many cases, however, you can continue to work with projects from a previous release by manually changing the `dfx` setting in the `dfx.json` configuration file, then rebuilding the project to be compatible with the version of the IC SDK you have currently installed.
+
+For example, if you have a project that was created with IC SDK version `0.8.0`, open the `dfx.json` file in a text editor and change the `dfx` setting to the latest version or remove the section entirely.
+
+## Restarting the local replica
+
+In some cases, starting the local replica fails due to stale state. If you encounter issues when running `dfx start` to start the local replica:
+
+- #### Step 1: Interrupt the local replica process through Ctrl+C if necessary, then stop the local replica:
+
+```bash
+dfx stop
+```
+
+- #### Step 2: If not all `dfx` processes can be stopped, forcibly end them:
+
+```
+dfx killall
+```
+
+- #### Step 3: Restart the local replica in a clean state by running the following command:
+
+```bash
+dfx start --clean --background
+```
+
+The `--clean` option removes checkpoints and stale state information from your project’s cache so that you can restart the local replica and web server processes in a clean state.
+
+:::danger
+Resetting the state information by running `dfx start --clean` removes your existing canisters and new canister IDs may differ from old ones.
+:::
+
+- #### Step 4: Recreate your canisters:
+
+```bash
+dfx canister create --all
+dfx build
+dfx canister install --all
+```
+
+## Removing the canisters directory
+
+If you run into problems building or deploying canisters after successfully connecting to ICP and registering canister identifiers, you should remove the `canisters` directory before attempting to rebuild or redeploy the canisters.
+
+You can remove the `canisters` directory for a project by running the following command in the project’s root directory:
+
+```bash
+rm -rf ./.dfx/* canisters/*
+```
+
+## Reinstalling `dfx`
+
+Some bugs can be addressed by uninstalling and reinstalling the IC SDK:
+
+```bash
+~/.cache/dfinity/uninstall.sh && sh -ci "$(curl -sSL https://internetcomputer.org/install.sh)"
+```
+
+If you have modified the location of the IC SDK binary (the binary is titled `dfx`), you might want run the following command to uninstall the version of the IC SDK that is in your PATH, then reinstall the latest version of the IC SDK:
+
+```bash
+rm -rf ~/.cache/dfinity && rm $(which dfx) && sh -ci "$(curl -sSL https://internetcomputer.org/install.sh)"
+```
+
+## Xcode prerequisite
+
+For macOS environments, you should have **Developer Command Line Tools** installed if you want to create a Git repository for your project.
+
+You can check whether you have the developer tools installed by running `xcode-select -p`. You can install the developer tools by running `xcode-select --install`.
+
+## Memory leak
+
+Fixing memory leaks is an ongoing process. If you encounter any error messages related to memory leaks, you should do the following:
+
+- #### Step 1: Run `dfx stop` to stop currently running processes.
+
+- #### Step 2: Uninstall the IC SDK to prevent further degradation.
+
+- #### Step 3: Re-install the IC SDK
+
+- #### Step 4: Run `dfx start` to restart replica processes.
+
+Alternatively, you can remove the `.cache/dfinity` directory and re-install the latest IC SDK `dfx` binary:
+
+```bash
+rm -rf ~/.cache/dfinity && sh -ci "$(curl -sSL https://internetcomputer.org/install.sh)"
+```
diff --git a/docs/developer-docs/identity/authentication/email-password.mdx b/docs/developer-docs/identity/authentication/email-password.mdx
deleted file mode 100644
index 0f8dd90b6f..0000000000
--- a/docs/developer-docs/identity/authentication/email-password.mdx
+++ /dev/null
@@ -1,25 +0,0 @@
----
-keywords: [intermediate, tutorial, user sign in, user login, email password, nfid]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Email & password
-
-
-
-## Overview
-
-For some dapps, authenticating with a traditional email and password method may be desired. To support this workflow, [NFID](https://nfid.one/) can be used. NFID is a form of digital identity with a backend built entirely on ICP. It supports authentication with dapps through an email and password login or an existing Google account.
-
-[Learn how to use NFID](nfid.mdx).
-
-## Resources
-
-- [How NFID works](https://docs.nfid.one/embed/how-it-works/overview).
-
-- [NFID documentation](https://docs.nfid.one/embed/integration/quickstart).
-
-- [NFID playground](https://playground.nfid.one/).
-
-- [NFID Medium blog post](https://medium.com/dfinity/nfid-the-digital-identity-protocol-7d8a39f7ac85).
\ No newline at end of file
diff --git a/docs/developer-docs/identity/authentication/msq.mdx b/docs/developer-docs/identity/authentication/msq.mdx
deleted file mode 100644
index 6e9cd8b6ef..0000000000
--- a/docs/developer-docs/identity/authentication/msq.mdx
+++ /dev/null
@@ -1,140 +0,0 @@
----
-keywords: [authentication, msq, integration]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# MSQ
-
-
-
-## Overview
-
-[MSQ](https://icp.msq.tech/) is a [MetaMask Snap](https://metamask.io/snaps/) designed to allow users to use Metamask to authenticate with dapps deployed on ICP. MSQ uses a scoped-identity architecture, meaning each user gets a unique and dedicated identity for each domain they interact with. Scoped-identity architectures help protect users from signature-stealing attacks.
-
-I'll let you decide what is the best way to explain this!
-
-Response from MSQ team: https://forum.dfinity.org/t/msq-hits-the-metamask-snap-store/30499/23
-
-It provides two primary features:
-
-- User authorization: Web services can sign arbitrary data with a user's scoped key pair.
-
-- ICRC-1 payments: Users can request to perform ICRC-1 transfers to pay for goods or services.
-
-## Installation
-
-Insall the `msq` package with the command:
-
-```
-npm install @fort-major/msq-client
-```
-
-Then, import it into your project's `package.json` file:
-
-```json title="package.json"
-"dependencies": {
- ...
- "@fort-major/msq-client": "^0.3",
- ...
-}
-```
-
-Users will need to connect to MetaMask and the MSQ Snap.
-
-The MSQ client library does this using the following function. For example, a user who interacts with a frontend element (e.g., button) that triggers the function will be prompted to connect using Metamask and install the MSQ Snap.
-
-```typescript title="src/frontend/index.tsx"
-const result = await MsqClient.create();
-
-if (!("Ok" in result)) {
- // handle possible errors
-}
-```
-
-Then, retrieve the client with the following code:
-
-```typescript title="src/frontend/index.tsx"
-import { TMsqCreateOk, MsqClient } from "@fort-major/msq-client";
-
-const msq: MsqClient = (result as TMsqCreateOk).Ok;
-```
-
-The MSQ client library version correlates with the respective Snap version. For example, the client library version `0.2.4` works with Snap version `0.2.x` or `0.3.x`, but does not work with `1.x.x`.
-
-## User authorization
-
-To enable users to authorize with MSQ and interact with your dapp, you can call the `requestLogin()` function of the client:
-
-```typescript title="src/frontend/index.tsx"
-import { Identity } from "@dfinity/identity";
-
-const identity: Identity | null = await msq.requestLogin();
-
-if (identity === null) {
- // the user has rejected to log in
-}
-```
-
-This function returns an identity object which can then be supplied to an agent's `HttpAgent` constructor which can then be used to call canisters on a user's behalf:
-
-```typescript title="src/frontend/index.tsx"
-import { HttpAgent } from "@dfinity/agent";
-
-const agent = new HttpAgent({ identity });
-```
-
-Authorization for a user lasts indefinitely unless explicitly ended. The following code can be used to check if a user's session exists:
-
-```typescript title="src/frontend/index.tsx"
-if (msq.isAuthorized()) {
-}
-```
-
-To stop the user's session, use the `requestLogout()` function:
-
-```typescript title="src/frontend/index.tsx"
-if (await msq.requestLogout()) {
-} else {
-}
-```
-
-You can learn more about user authentication in the [MSQ documentation](https://github.com/fort-major/msq/blob/master/documentation/integration.md).
-
-## ICRC-1 payments
-
-MSQ enables users to make payments using a pre-defined ICRC-1 account through the `requestICRC1Payment()` function:
-
-```typescript
-const blockId: bigint | null = await msq.requestICRC1Payment({
- if (blockId === null) {
- renderErrorScreen("Payment failed");
- },
- // A canister ID of the valid `ICRC-1` token:
- tokenCanisterId,
- to: {
- // Payment recipient's `principal` ID
- owner,
- // Payment recipient's `subaccount` ID
- subaccount,
- },
- // An amount of tokens that the user needs to transfer to the recipient
- amount,
- // An optional ICRC-1 memo
- memo,
-});
-```
-
-This function returns either a `bigint` or `null`. A `bigint` response will indicate the block number of the executed ICRC-1 transaction and means that the payment was successful. That block number can then be used to query the token canister, verify the payment, and execute some business logic.
-
-MSQ supports ICRC-1 token payments by default through a series of whitelisted ICRC-1 tokens. If you accept payment of a whitelisted token, your workflow will execute as expected. However, if you accept a token that isn't currently whitelisted, the user will be prompted to add the token to their personal whitelist.
-
-[View the MSQ documentation for the full list of whitelisted ICRC-1 tokens](https://github.com/fort-major/msq/blob/master/documentation/integration.md#icrc-1-payments).
-
-## Resources
-
-- [MSQ GitHub repo](https://github.com/fort-major/msq/blob/master/)
-
-- [MSQ documentation](https://github.com/fort-major/msq/blob/master/documentation/integration.md)
-
-- [MSQ MetaMask Snap](https://snaps.metamask.io/snap/npm/fort-major/msq/)
diff --git a/docs/developer-docs/identity/authentication/nfid.mdx b/docs/developer-docs/identity/authentication/nfid.mdx
deleted file mode 100644
index e086bb819a..0000000000
--- a/docs/developer-docs/identity/authentication/nfid.mdx
+++ /dev/null
@@ -1,302 +0,0 @@
----
-keywords: [intermediate, tutorial, user sign in, user login, nfid]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-import '/src/components/CenterImages/center.scss';
-
-
-# NFID
-
-
-
-## Overview
-
-[NFID](https://nfid.one/) is a form of digital identity built on ICP. Similar to Internet Identity, NFID allows users to sign into services without downloading an app or extension and can be used across several different dapps.
-
-NFID is different from Internet Identity, however, in the fact that is allows you to sign in to a dapp using your email or Google account. With Internet Identity, these log in options aren't available. This makes NFID a great option for those that want to use email or Google authentication methods.
-
-NFID also supports signing in with a passkey stored on a mobile device or local keychain, which is the same method used by Internet Identity.
-
-## Using NFID
-
-### Prerequisites
-
-Before starting the guide, verify the following:
-
-- [x] You have `Node.js` `16.0.0` or newer installed for frontend development and can install packages using `npm install` in your project. For information about installing node for your local operating system and package manager, see the [Node](https://nodejs.org/en/) website.
-
-- [x] You have downloaded and installed the IC SDK package as described in the [download and install](/docs/current/developer-docs/getting-started/install) page.
-
-Check out the [GitHub repo for this project](https://github.com/internet-identity-labs/motoko-bootcamp/tree/main) to clone and deploy the project quickly.
-
-### Create a new project
-
-First, create a new project with the `dfx new` command:
-
-```
-dfx new NFID_project
-```
-
-If using `dfx` v0.17.0 and newer, select 'Motoko' and 'Vanilla JS' when prompted.
-
-### Edit the backend canister
-
-Replace the default Motoko backend canister code (`src/NFID_backend/main.mo`) with the following:
-
-```motoko title="src/NFID_backend/main.mo"
-import Principal "mo:base/Principal";
-
-actor {
- public shared query({caller}) func greet(name : Text) : async Text {
- return "Hello, " # name # "! " # "Your PrincipalId is: " # Principal.toText(caller);
- };
-};
-```
-
-### Update the project's `dfx.json` file.
-
-Replace the `dfx.json` file's content with the following configuration:
-
-```json title="dfx.json"
-{
- "canisters": {
- "NFID_backend": {
- "main": "src/NFID_backend/main.mo",
- "type": "motoko"
- },
- "NFID_frontend": {
- "dependencies": [
- "NFID_backend"
- ],
- "frontend": {
- "entrypoint": "src/NFID_frontend/src/index.html"
- },
- "source": [
- "src/NFID_frontend/assets"
- ],
- "type": "assets"
- }
- },
- "defaults": {
- "build": {
- "args": "",
- "packtool": ""
- }
- },
- "version": 1
-}
-```
-
-### Install the `auth-client` package.
-
-Install the DFINITY `auth-client` package with the command:
-
-```
-npm install --save @dfinity/auth-client
-```
-
-### Create a file called `index.html` in the subdirectory `src/NFID_frontend/src/`.
-
-Insert the following code into the `index.html` file:
-
-```html title="src/NFID_frontend/src/index.html"
-
-
-
-
-
- NFID example
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-### Create an `index.js` file in the `src/NFID_frontend/src` subdirectory.
-
-Insert the following code into this new `index.js` file:
-
-```javascript title="src/NFID_frontend/src/index.js"
-import { Actor } from "@dfinity/agent";
-import { AuthClient } from "@dfinity/auth-client";
-import { NFID_backend } from "../../declarations/NFID_backend";
-
-let authClient = null;
-
-async function init() {
- authClient = await AuthClient.create();
-}
-
-document.querySelector("form").addEventListener("submit", async (e) => {
- e.preventDefault();
- const button = e.target.querySelector("button");
-
- const name = document.getElementById("name").value.toString();
-
- button.setAttribute("disabled", true);
-
- // Interact with foo actor, calling the greet method
- const greeting = await NFID_backend.greet(name);
-
- button.removeAttribute("disabled");
-
- document.getElementById("greeting").innerText = greeting;
-
- return false;
-});
-
-function handleSuccess() {
- const principalId = authClient.getIdentity().getPrincipal().toText();
-
- document.getElementById(
- "principalId"
- ).innerText = `Your PrincipalId: ${principalId}`;
-}
-
-document.getElementById("login").addEventListener("click", async (e) => {
- if (!authClient) throw new Error("AuthClient not initialized");
-
- authClient.login({
- onSuccess: handleSuccess,
- });
-});
-
-init();
-```
-
-### Deploy your project
-
-Deploy the project with the command:
-
-```bash
-dfx deploy
-```
-
-You will receive the URL for the frontend and backend canisters running locally:
-
-```bash
-Deployed canisters.
-URLs:
- Frontend canister via browser
- NFID_frontend: http://127.0.0.1:4943/?canisterId=br5f7-7uaaa-aaaaa-qaaca-cai
- Backend canister via Candid interface:
- NFID_backend: http://127.0.0.1:4943/?canisterId=bw4dl-smaaa-aaaaa-qaacq-cai&id=be2us-64aaa-aaaaa-qaabq-cai
-```
-
-Open the `NFID_frontend` URL in your web browser. You'll see the following UI:
-
-![UI](../_attachments/default-ui.png)
-
-### Configure NFID
-
-Currently, the `Log me in` button doesn't have any functionality when clicked. Let's configure it to use NFID.
-
-Replace the existing `index.js` code with the following:
-
-```javascript title="src/NFID_frontend/src/index.js"
-import { Actor } from "@dfinity/agent";
-import { AuthClient } from "@dfinity/auth-client";
-import { NFID_backend } from "../../declarations/NFID_backend";
-
-let authClient = null;
-
-async function init() {
- authClient = await AuthClient.create();
-}
-
-document.querySelector("form").addEventListener("submit", async (e) => {
- e.preventDefault();
- const button = e.target.querySelector("button");
-
- const name = document.getElementById("name").value.toString();
-
- button.setAttribute("disabled", true);
-
- // Interact with foo actor, calling the greet method
- const greeting = await NFID_backend.greet(name);
-
- button.removeAttribute("disabled");
-
- document.getElementById("greeting").innerText = greeting;
-
- return false;
-});
-
-function handleSuccess() {
- const principalId = authClient.getIdentity().getPrincipal().toText();
-
- document.getElementById(
- "principalId"
- ).innerText = `Your PrincipalId: ${principalId}`;
-
- Actor.agentOf(NFID_backend).replaceIdentity(
- authClient.getIdentity()
- );
-}
-
-document.getElementById("login").addEventListener("click", async (e) => {
- if (!authClient) throw new Error("AuthClient not initialized");
-
- const APP_NAME = "NFID example";
- const APP_LOGO = "https://nfid.one/icons/favicon-96x96.png";
- const CONFIG_QUERY = `?applicationName=${APP_NAME}&applicationLogo=${APP_LOGO}`;
-
- const identityProvider = `https://nfid.one/authenticate${CONFIG_QUERY}`;
-
- authClient.login({
- identityProvider,
- onSuccess: handleSuccess,
- windowOpenerFeatures: `
- left=${window.screen.width / 2 - 525 / 2},
- top=${window.screen.height / 2 - 705 / 2},
- toolbar=0,location=0,menubar=0,width=525,height=705
- `,
- });
-});
-
-init();
-```
-
-
-### Redeploy the canisters
-
-To implement the changes, redeploy the canisters with `dfx deploy`.
-
-Now, when you click 'Log me in', you'll get an NFID login prompt:
-
-![NFID login](../_attachments/nfid-ui.png)
-
-## Resources
-
-- [GitHub repo for this project](https://github.com/internet-identity-labs/motoko-bootcamp/tree/main).
-
-- [Video tutorial for this project](https://www.youtube.com/watch?v=jqNQQf6V6zg).
-
-- [How NFID works](https://docs.nfid.one/embed/how-it-works/overview).
-
-- [NFID documentation](https://docs.nfid.one/embed/integration/quickstart).
-
-- [NFID playground](https://playground.nfid.one/).
-
-- [NFID Medium blog post](https://medium.com/dfinity/nfid-the-digital-identity-protocol-7d8a39f7ac85).
-
-
diff --git a/docs/developer-docs/identity/authentication/overview.mdx b/docs/developer-docs/identity/authentication/overview.mdx
index 69a38f69fb..0531a84618 100644
--- a/docs/developer-docs/identity/authentication/overview.mdx
+++ b/docs/developer-docs/identity/authentication/overview.mdx
@@ -20,9 +20,9 @@ Authentication methods available on ICP include:
- [Internet Identity](/docs/current/developer-docs/identity/internet-identity/overview): ICP's native identity service that uses a cryptographic public/private key pair for authentication.
-- [Email and password](email-password.mdx): Authentication with an email and password.
+- [Email and password](https://nfid.one): Authentication with an email and password.
-- [NFID](nfid.mdx): A digital form of identity that allows users to use an email and password or their Google account.
+- [NFID](https://nfid.one/): A digital form of identity that allows users to use an email and password or their Google account.
- [`ic-auth`](https://github.com/id-daniel-mccoy/ic-auth): A modular tool to integrate wallet providers into ICP apps. Supports Stoic, Plug, Internet Identity, and NFID.
@@ -30,12 +30,12 @@ Authentication methods available on ICP include:
The following tools enable authenticating with ICP dapps using wallet addresses from other chains and ecosystems:
-- [Sign in with Bitcoin](siwb.mdx): An authentication standard that enables Bitcoin wallet-based authentication for ICP applications.
+- [Sign in with Bitcoin](https://github.com/AstroxNetwork/ic-siwb): An authentication standard that enables Bitcoin wallet-based authentication for ICP applications.
-- [Sign in with Ethereum](siwe.mdx): An authentication standard that enables Ethereum wallet-based authentication for ICP applications.
+- [Sign in with Ethereum](https://github.com/kristoferlund/ic-siwe-react-demo-rust): An authentication standard that enables Ethereum wallet-based authentication for ICP applications.
-- [Sign in with Solana](siws.mdx): An authentication standard that enables Solana wallet-based authentication for ICP applications.
+- [Sign in with Solana](https://github.com/kristoferlund/ic-siws): An authentication standard that enables Solana wallet-based authentication for ICP applications.
-- [MSQ library](msq.mdx): A client library for dapps to enable user interaction with ICP solely via their existing MetaMask wallet using the [Metamask Snaps](https://metamask.io/snaps/) feature.
+- [MSQ library](https://icp.msq.tech/): A client library for dapps to enable user interaction with ICP solely via their existing MetaMask wallet using the [Metamask Snaps](https://metamask.io/snaps/) feature.
diff --git a/docs/developer-docs/identity/authentication/siwb.mdx b/docs/developer-docs/identity/authentication/siwb.mdx
deleted file mode 100644
index db240c12a0..0000000000
--- a/docs/developer-docs/identity/authentication/siwb.mdx
+++ /dev/null
@@ -1,131 +0,0 @@
----
-keywords: [advanced, bitcoin, sign in, bitcoin sign in]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Sign in with Bitcoin
-
-
-
-## Overview
-
-Sign in with Bitcoin (SIWB) is a fork of the [sign in with Ethereum](siwe.mdx) package that enables dapps to provide users with the option to authenticate with their Bitcoin wallet address.
-
-SIWB supports the popular BTC wallets [Wizz](https://wizzwallet.io/) and [Unisat](https://unisat.io/).
-
-### Key features
-
-- Consistent principal generation: Ensures that logging in with a BTC wallet will produce the same principal consistently.
-
-- Session identity uniqueness: Each session identity is specific to the application's context, avoiding cross-app identity exploits.
-
-- Direct BTC-to-principal mapping: Each BTC address has a 1:1 correlation with a principal.
-
-- Timebound sessions: Developers can set session expiration times for control and security enhancement.
-
-- Prebuilt identity provider: A prebuilt canister to integrate into any existing ICP dapp.
-
-## Usage
-
-The SIWB package can be downloaded from its [GitHub repo](https://github.com/AstroxNetwork/ic-siwb.git) which includes an example integration.
-
-To use the example integration, clone the repo, then deploy the included pre-built canisters:
-
-```
-git clone https://github.com/AstroxNetwork/ic-siwb.git
-cd ic-siwb
-dfx start --clean --background
-npm install
-dfx deploy
-```
-
-This example deploys the prebuild `ic_siwb_provider` canister alongside an example `ic_siwb_test_canister`.
-
-:::caution
-
-If you are deploying on a Mac OS X machine and receive an error such as:
-
-```
-secp256k1-sys@0.8.1: error: unable to create target: 'No available targets are compatible with triple "wasm32-unknown-unknown"'
-error: failed to run custom build command for `secp256k1-sys v0.8.1`
-```
-
-This is due to the default Mac OS X clang compiler not supporting compiling to target wasm32-unknown-unknown.
-
-You can remedy this error by installing another compiler using `brew` that does support wasm32-unknown-unknown:
-
-```
-brew install llvm
-export PATH="/opt/homebrew/opt/llvm/bin:$PATH" && export LDFLAGS="-L/opt/homebrew/opt/llvm/lib" && export CPPFLAGS="-I/opt/homebrew/opt/llvm/include"
-cargo build --target wasm32-unknown-unknown --release
-```
-:::
-
-
-As part of the canisters' deployment, both will require initialization arguments. The first is the `ic_siwb_provider` canister. Before initialization, this canister's ID will be printed on the terminal in a line such as:
-
-```
-Installing canisters...
-Installing code for canister ic_siwb_provider, with canister ID bkyz2-fmaaa-aaaaa-qaaaq-cai
-This canister requires an initialization argument.
-```
-
-Copy the canister's ID. Then, configure the initialization arguments as prompted:
-
-- URI: The full URL, such as `http://localhost:3000`.
-- Salt: A string used to generate seed that uniquely identifies each user principal.
-- Domain: The domain name, such as `localhost`.
-- Optional runtime feature enabled: Select yes to enable and no to disable.
-- Optional statement: A message presented to the user by the Bitcoin wallet.
-- Optional scheme: The scheme used to serve the frontend that uses SIWB. Defaults to "https".
-- Optional network: Defaults to the Bitcoin mainnet.
-- Optional session expiration time: Time to live for a session in nanoseconds.
-- Optional target: All canisters for which the identity delegation is allowed. Defaults to None.
-- Optional sign in expiration time: Time to live for a sign in message in nanoseconds.
-
-An example of the canister's initialization configuration can be found below:
-
-```
-(
- record {
- uri = "http://localhost:3000";
- runtime_features = null;
- domain = "localhost";
- statement = null;
- scheme = null;
- salt = "test";
- network = null;
- session_expires_in = null;
- targets = null;
- sign_in_expires_in = null;
- },
-)
-```
-
-Next, you will need to pass the canister ID for `ic_siwb_provider` to the `ic_siwb_test_canister` as its initialization argument when prompted:
-
-```
-Installing code for canister ic_siwb_test_canister, with canister ID bd3sg-teaaa-aaaaa-qaaba-cai
-This canister requires an initialization argument.
-✔ Enter a text (type :e to use editor) · bkyz2-fmaaa-aaaaa-qaaaq-cai
-Sending the following argument:
-("bkyz2-fmaaa-aaaaa-qaaaq-cai")
-```
-
-Once both canisters have been installed, initialized, and deployed, you will receive the local URLs for both canisters:
-
-```
-URLs:
- Backend canister via Candid interface:
- ic_siwb_provider: http://127.0.0.1:4943/?canisterId=be2us-64aaa-aaaaa-qaabq-cai&id=bkyz2-fmaaa-aaaaa-qaaaq-cai
- ic_siwb_test_canister: http://127.0.0.1:4943/?canisterId=be2us-64aaa-aaaaa-qaabq-cai&id=bd3sg-teaaa-aaaaa-qaaba-cai
-```
-
-You can view the full frontend example in the [project's repo](https://github.com/AstroxNetwork/ic-siwb/tree/main/examples/frontend).
-
-## Resources
-
-- [View this project on GitHub](https://github.com/AstroxNetwork/ic-siwb/tree/main)
-
-- [Join the forum conversation for this project](https://forum.dfinity.org/t/sign-in-with-bitcoin-on-icp/32734)
diff --git a/docs/developer-docs/identity/authentication/siwe.mdx b/docs/developer-docs/identity/authentication/siwe.mdx
deleted file mode 100644
index 2241ad0234..0000000000
--- a/docs/developer-docs/identity/authentication/siwe.mdx
+++ /dev/null
@@ -1,39 +0,0 @@
----
-keywords: [advanced, ethereum, sign in, ethereum sign in]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Sign in with Ethereum
-
-
-
-## Overview
-
-The [SIWE](https://eips.ethereum.org/EIPS/eip-4361) standard defines a protocol for off-chain authentication of Ethereum accounts. This protocol is designed to enable Ethereum wallet-based authentication for applications on other platforms, such as the Internet Computer (ICP).
-
-By integrating the third party library [ic_siwe](https://github.com/kristoferlund/ic-siwe/tree/main/packages/ic_siwe) or adding the pre-built [ic_siwe_provider](https://github.com/kristoferlund/ic-siwe/tree/main/packages/ic_siwe_provider) canister to your project, you can enable users to sign into your application using their Ethereum wallets.
-
-The goal of the `ic_siwe` project is to enhance the interoperability between Ethereum and ICP, enabling developers to build applications that leverage the strengths of both platforms.
-
-### Key features
-
-- **Ethereum Wallet Sign-In**: Enables Ethereum wallet sign-in for ICP applications. Sign in with any Ethereum wallet to generate an ICP identity and session.
-- **Session identity uniqueness**: Ensures that session identities are specific to each application's context, preventing cross-app identity misuse.
-- **Consistent principal generation**: Guarantees that logging in with an Ethereum wallet consistently produces the same principal, irrespective of the client used.
-- **Direct Ethereum address to principal mapping**: Creates a 1:1 correlation between Ethereum addresses and principals within the scope of the current application.
-- **Timebound sessions**: Allows developers to set expiration times for sessions, enhancing security and control.
-
-## Usage
-
-While the `ic_siwe` library can be integrated with any Rust-based ICP project, using the pre-built [ic-siwe-provider](https://github.com/kristoferlund/ic-siwe/tree/main/packages/ic_siwe_provider) canister is the easiest way to integrate Ethereum wallet authentication into an ICP app built using any language.
-
-The canister is designed as a plug-and-play solution for developers, enabling easy integration into existing ICP applications with minimal coding requirements. By adding the pre built `ic_siwe_provider` canister to the `dfx.json` of an ICP project, developers can quickly enable Ethereum wallet-based authentication for their applications. The canister simplifies the authentication flow by managing the creation and verification of SIWE messages and handling user session management.
-
-## React demo application
-
-A demo application that uses the `ic_siwe_provider` canister to demonstrate the full login flow is available in two versions:
-- [ic-siwe-react-demo-rust](https://github.com/kristoferlund/ic-siwe-react-demo-rust)
-- [ic-siwe-react-demo-ts](https://github.com/kristoferlund/ic-siwe-react-demo-ts)
-
-The demo uses another package from the `ic-siwe` project, [ic-use-siwe-identity](https://github.com/kristoferlund/ic-siwe/tree/main/packages/ic-use-siwe-identity), a React hook and context provider for easy frontend integration with SIWE enabled ICP canisters.
\ No newline at end of file
diff --git a/docs/developer-docs/identity/authentication/siws.mdx b/docs/developer-docs/identity/authentication/siws.mdx
deleted file mode 100644
index ca1fe8472e..0000000000
--- a/docs/developer-docs/identity/authentication/siws.mdx
+++ /dev/null
@@ -1,58 +0,0 @@
----
-keywords: [advanced, solana sign in, solana sign in]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Sign in with Solana
-
-
-
-## Overview
-
-The `ic-siws` (SIWS) project provides ICP dapps with a way to enable Solana-based authentication. The project's goal is to enhance the interoperability between ICP and Solana by enabling developers to build dapps that can use both chains.
-
-The [`ic-siwe` (SIWE)](siwe.mdx) project is also available for enabling Ethereum-based authentication.
-
-You can try the deployed demo here: https://guidq-3qaaa-aaaal-qiteq-cai.icp0.io
-
-### Key features
-
-- **Solana Wallet Sign-In**: Enables any Solana wallet to generate an ICP identity and sign into ICP dapps.
-
-- **Prebuilt identity solution**: Provides a prebuilt canister that can be integrated into any ICP project, independent of the project's programming language.
-
-- **Direct Solana wallet address to `Principal` mapping**: Uses a 1:1 correlation between Solana addresses and `Principals`.
-
-- **Consistent principal generation**: Ensures each Solana wallet produces the same `Principal`.
-
-- **Session identity uniqueness**: Verifies that each session identity is specific to each application's context.
-
-- **Timebound sessions**: Developers can set expiration times for sessions to enhance control and security.
-
-
-## Usage
-
-To use SIWS, developers have two possible workflows:
-
-1. Use the prebuilt [ic_siws_provider](https://github.com/kristoferlund/ic-siws/tree/main/packages/ic_siws_provider)**: The pre-built identity provider canister can be integrated with any ICP project by adding the canister's information to the project's `dfx.json` file. When using the pre-built canister solution, the following login workflow is used:
-
-- An ICP dapp requests a SIWS message on behalf of a user from the `ic_siws_provider` canister.
-
-- The dapp displays the SIWS message to the user who must sign it with their Solana wallet.
-
-- The dapp sends the signed SIWS message to the `ic_siws_provider` canister. The canister verifies the signature and creates an ICP Principal for the user.
-
-- The dapp retrieves the Principal from the `ic_siws_provider` canister and can now use the new Principal to make authenticated calls for the user.
-
-2. **Use the [ic_siws](https://crates.io/crates/ic_siws) Rust library directly**: Provides developers with full control over the SIWS integration through the `ic_swis` library.
-
-## Resources
-
-- [ic_siws Rust library](https://github.com/kristoferlund/ic-siws/tree/main/packages/ic_siws)
-
-- [`ic-siws-provider` prebuilt canister](https://github.com/kristoferlund/ic-siws/tree/main/packages/ic_siws_provider)
-
-- [ic-siws-react-demo-rust](https://github.com/kristoferlund/ic-siws-react-demo-rust): A demo dapp written in Rust that demonstrates how to integrate SIWS.
-
-- [ic-use-siws-identity](https://github.com/kristoferlund/ic-siws/tree/main/packages/ic-use-siws-identity): A React hook and context provider for enabling frontend integration with SIWS-enabled canisters.
diff --git a/docs/developer-docs/multi-chain/bitcoin/using-btc/btc-comparison.mdx b/docs/developer-docs/multi-chain/bitcoin/using-btc/btc-comparison.mdx
index a01e76a9a8..b2df1912b3 100644
--- a/docs/developer-docs/multi-chain/bitcoin/using-btc/btc-comparison.mdx
+++ b/docs/developer-docs/multi-chain/bitcoin/using-btc/btc-comparison.mdx
@@ -37,7 +37,7 @@ Canister smart contracts on ICP have special properties that allow developers to
To learn more about full canister smart contract functionality, refer to the [smart contracts documentation](/docs/current/developer-docs/smart-contracts/overview/introduction).
-Specifically, through protocol-level integration of ICP with the [Bitcoin network](docs/current/developer-docs/multi-chain/bitcoin/overview), ICP smart contracts can interact with the Bitcoin network directly. Canister smart contracts can run [queries against the full Bitcoin UTXO](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/read-state) set, including finding the balance of any Bitcoin address. They can [hold](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/generate-addresses), [sign](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/sign-transactions), and [submit transactions](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/submit-transactions) to the Bitcoin network.
+Specifically, through protocol-level integration of ICP with the [Bitcoin network](/docs/current/developer-docs/multi-chain/bitcoin/overview), ICP smart contracts can interact with the Bitcoin network directly. Canister smart contracts can run [queries against the full Bitcoin UTXO](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/read-state) set, including finding the balance of any Bitcoin address. They can [hold](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/generate-addresses), [sign](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/sign-transactions), and [submit transactions](/docs/current/developer-docs/multi-chain/bitcoin/using-btc/submit-transactions) to the Bitcoin network.
The [Threshold Schnorr integration](/docs/current/developer-docs/smart-contracts/signatures/t-schnorr) allows developers to interact with Runes and Ordinals directly in canisters. A [Schnorr canister example](https://github.com/dfinity/examples/tree/master/motoko/t-schnorr) is available in Motoko and Rust.
diff --git a/docs/developer-docs/multi-chain/ethereum/using-eth/eth-dev-workflow.mdx b/docs/developer-docs/multi-chain/ethereum/using-eth/eth-dev-workflow.mdx
index 6d676c3016..e1bd07ef5c 100644
--- a/docs/developer-docs/multi-chain/ethereum/using-eth/eth-dev-workflow.mdx
+++ b/docs/developer-docs/multi-chain/ethereum/using-eth/eth-dev-workflow.mdx
@@ -41,7 +41,7 @@ Additional sample projects can be found in the [EVM RPC](../evm-rpc/samples.mdx)
## Integrating with Ethereum
-The Ethereum integration can be incorporated into dapps for several purposes, such as authentication, as shown in the [Sign In With Ethereum (SIWE)](/docs/current/developer-docs/identity/authentication/siwe) example. The SIWE example showcases how to use an Ethereum wallet to sign into ICP applications. It creates a 1:1 correlation between Ethereum addresses and ICP principals within the scope of the application. It also guarantees that logging in with an Ethereum wallet will consistently produce the same principal regardless of the client used.
+The Ethereum integration can be incorporated into dapps for several purposes, such as authentication, as shown in the [Sign In With Ethereum (SIWE)](https://github.com/kristoferlund/ic-siwe) example. The SIWE example showcases how to use an Ethereum wallet to sign into ICP applications. It creates a 1:1 correlation between Ethereum addresses and ICP principals within the scope of the application. It also guarantees that logging in with an Ethereum wallet will consistently produce the same principal regardless of the client used.
## Using ckETH
diff --git a/docs/developer-docs/security/security-best-practices/inter-canister-calls.mdx b/docs/developer-docs/security/security-best-practices/inter-canister-calls.mdx
index 939b722ae8..5f4796e3b2 100644
--- a/docs/developer-docs/security/security-best-practices/inter-canister-calls.mdx
+++ b/docs/developer-docs/security/security-best-practices/inter-canister-calls.mdx
@@ -153,7 +153,7 @@ To address issues around message ordering that can lead to bugs, one usually emp
The locks would usually be released in the callback. That bears the risk that the lock may never be released in case the callback traps, as we discussed in [securely handle traps in callbacks](#securely-handle-traps-in-callbacks). The code examples below shows how one can securely implement a lock per caller.
- In Rust, one can use the drop pattern where each caller lock (`CallerGuard` struct) implementats the `Drop` trait to release the lock. From Rust CDK version `0.5.1`, any local variables still go out of scope if the callback traps, so the lock on the caller is released even in that case. Technically, the CDK calls into the `ic0.call_on_cleanup` API to release these resources. Recall that `ic0.call_on_cleanup` is executed if the `reply` or the `reject` callback executed and trapped.
-- In Motoko, one can use the [`try`/`finally`](docs/current/motoko/main/reference/language-manual/#try) control flow construct. This construct guarantees that the lock is released in the `finally` block regardless of any errors or traps in the `try` or `catch` blocks.
+- In Motoko, one can use the [`try`/`finally`](/docs/current/motoko/main/reference/language-manual/#try) control flow construct. This construct guarantees that the lock is released in the `finally` block regardless of any errors or traps in the `try` or `catch` blocks.
diff --git a/docs/developer-docs/smart-contracts/advanced-features/async-code.mdx b/docs/developer-docs/smart-contracts/advanced-features/async-code.mdx
index 1bfdbf6f3b..4ab1db4151 100644
--- a/docs/developer-docs/smart-contracts/advanced-features/async-code.mdx
+++ b/docs/developer-docs/smart-contracts/advanced-features/async-code.mdx
@@ -1,5 +1,13 @@
+---
+keywords: [advanced, concept, async code, inter-canister calls, async inter-canister, async]
+---
+
+import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
+
# Async code and inter-canister calls
+
+
## Overview
In programming, the [async/await pattern](https://en.wikipedia.org/wiki/Async/await) is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a similar way to an ordinary synchronous function.
diff --git a/docs/developer-docs/smart-contracts/advanced-features/composite-query.mdx b/docs/developer-docs/smart-contracts/advanced-features/composite-query.mdx
index 5c058ff694..7c2663b012 100644
--- a/docs/developer-docs/smart-contracts/advanced-features/composite-query.mdx
+++ b/docs/developer-docs/smart-contracts/advanced-features/composite-query.mdx
@@ -2,8 +2,11 @@
keywords: [advanced, tutorial, composite queries, queries]
---
-
+import TabItem from "@theme/TabItem";
+import { AdornedTabs } from "/src/components/Tabs/AdornedTabs";
+import { AdornedTab } from "/src/components/Tabs/AdornedTab";
import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
+import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
# Composite queries
@@ -12,23 +15,24 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
## Overview
The Internet Computer Protocol supports two types of messages: updates and queries. An update message is executed on all nodes and persists canister state changes. A query message discards state changes and typically executes on a single node. It is possible to execute a query message as an update. In such a case, the query still discards the state changes, but the execution happens on all nodes and the result of execution goes through consensus. This “query-as-update” execution mode is also known as replicated query.
-An update can call other updates and queries. However a query cannot make any calls, which can hinder development of scalable decentralized applications (dapps), especially those that shard data across multiple canisters.
+An update can call other updates and queries. However a query cannot make any calls, which can hinder development of scalable decentralized applications, especially those that shard data across multiple canisters.
-Composite queries solve this problem. A composite query is a new type of query that you can add to your canister using the following annotations:
+Composite queries solve this problem. You can add composite queries to your canister using the following annotations:
* Candid: `composite_query`
- * Azle: `$query`; in combination with `async`
* Motoko: `composite query`
* Rust: `#[query(composite = true)]`
-Users and the client-side JavaScript code can invoke a composite query endpoint of a canister using the same query URL as for existing regular queries. In contrast to regular queries, a composite query can call other composite and regular queries. Due to limitations of the current implementation, composite queries have two restrictions:
+Users and the client-side JavaScript code can invoke a composite query endpoint of a canister using the same query URL for existing regular queries. In contrast to regular queries, a composite query can call other composite and regular queries. Due to limitations of the current implementation, composite queries have two restrictions:
- * A composite query cannot call canisters on another subnet.
- * A composite query cannot be executed as an update. As a result, updates cannot call composite queries.
+| Query | Update | Composite query |
+|--------|--------|----------------|
+| Cannot call other queries or composite queries| Can call other updates and queries ; Cannot call composite queries| Can call other queries and composite queries |
+| Can be called as an update | Cannot be called as a query | Cannot be called as an update |
+| Can call canisters on another subnet | Can call canisters on another subnet | Cannot call canisters on another subnet |
-These restrictions will be hopefully lifted in future implementations.
-Composite queries are enabled in the following releases:
+Composite queries were enabled in the following releases:
| Platform / Language | Version |
| -------------------------- | ------- |
@@ -36,7 +40,6 @@ Composite queries are enabled in the following releases:
| Candid | [2023-06-30 (Rust 0.9.0)](https://github.com/dfinity/candid/blob/master/Changelog.md#2023-06-30-rust-090) |
| Motoko | [0.9.4](https://github.com/dfinity/motoko/releases/tag/0.9.4), revision: [2d9902f](https://github.com/dfinity/motoko/commit/2d9902fb75bb04e377c28913c311aa2be373e159) |
| Rust | [0.6.8](https://github.com/dfinity/cdk-rs/blob/219ae179b9c5ef0ebfff20b926a90f6624ebe704/src/ic-cdk/CHANGELOG.md#068---2022-11-28) |
-| Azle | [0.11.0](https://github.com/demergent-labs/azle/releases/tag/0.11.0) |
## Sample code
@@ -45,104 +48,35 @@ As an example, consider a partitioned key-value store, where a single frontend d
- First, determines the ID of the data partition canister that holds the value with the given key.
- Then, makes a call into the `get` or `put` function of that canister and parses the result.
-Below is a simplified example of the frontend code. Take note of the line `#[query(composite = true)]` which is used to leverage the new composite query feature:
-
-```rust
-#[query(composite = true)]
-async fn frontend_get(key: u128) -> Option {
- let canister_id = get_partition_for_key(key);
- match call(canister_id, "get", (key, ), ).await {
- Ok(r) => {
- let (res,): (Option,) = r;
- res
- },
- Err(_) => None,
- }
-}
-```
-
-The backend simply stores the key value pairs in a `BTreeMap` in stable memory:
+
+
-```rust
-#[query]
-fn get(key: u128) -> Option {
- STORE.with(|store| store.borrow().get(&key))
-}
+```motoko no-repl file=../../../references/samples/motoko/composite_query/src/map/Map.mo
```
-## Using composite queries
-### Prerequisites
- - [x] [Download and install the IC SDK.](/docs/current/developer-docs/getting-started/install)
- - [x] [Download and install git.](https://git-scm.com/downloads)
+
+
-### Setting up the example
-- #### Step 1: Open a terminal window and clone the DFINITY examples repo with the command:
-
-```bash
-git clone https://github.com/dfinity/examples.git
+```rust file=../../../references/samples/rust/composite_query/src/kv_frontend/lib.rs
```
+
-- #### Step 2: Navigate into the `rust/composite_query/src` directory, start a local replica, and build the frontend canister with the commands:
-
-```bash
-cd rust/composite_query/src
-dfx start
-dfx canister create kv_frontend
-dfx build kv_frontend
-During compilation of the fronted canister, the backend canister's wasm code will be compiled and inlined in the frontend canister's wasm code.
-```
+}>
-- #### Step 3: Then, install the frontend canister with the command:
+[Learn more about Azle](https://demergent-labs.github.io/azle/the_azle_book.html).
-```
-dfx canister install kv_frontend
-```
-
-### Interacting with the canisters
-- #### Step 1: To add a key-value pair via the frontend canister, run the following command:
-
-```bash
-dfx canister call kv_frontend put '(1, 1337)'
-```
-
-:::note
-The first call to put might be slow to respond because the data partition canisters have to be created first.
-:::
-
-The output should resemble the following indicating that no value has previously been registered for this key:
-```(null)```
-
-- #### Step 2: Retrieve the value associated with a key using composite queries with the command:
-
-```bash
-dfx canister call kv_frontend get '(1)'
-```
-
-The output should resemble the following:
-```(opt (1337 : nat))```
-
-This workflow displays the ability to fetch the value using composite queries with very low latency.
-
-## Comparing composite queries to calls from update functions
-Let’s now compare the performance of composite query calls with those of an equivalent implementation that leverages calls from update functions. To do this, you will use the `get_update` method, which contains the exact same logic, but is implemented based on update calls. Run the following command in your terminal window:
-
-```bash
-dfx canister call kv_frontend get_update '(1)'
-```
+
-The output will resemble the following:
-```(opt (1_337 : nat))```
+}>
-You can observe that with update calls you receive the very same result, but the call is at least one order of magnitude slower compared to composite query calls.
+[Learn more about Kybra](https://demergent-labs.github.io/kybra/).
-:::note
-The examples repository also contains an equivalent [Motoko example](https://github.com/dfinity/examples/tree/master/motoko/composite_query).
-:::
+
+
## Resources
The following example canisters demonstrate how to use composite queries:
- * [Azle example](https://github.com/demergent-labs/azle/tree/main/examples/composite_queries)
* [Motoko example](https://github.com/dfinity/examples/tree/master/motoko/composite_query)
* [Rust example](https://github.com/dfinity/examples/tree/master/rust/composite_query)
diff --git a/docs/developer-docs/smart-contracts/advanced-features/handling-get-post-requests.mdx b/docs/developer-docs/smart-contracts/advanced-features/handling-get-post-requests.mdx
index 8c49d27288..1d1f801617 100644
--- a/docs/developer-docs/smart-contracts/advanced-features/handling-get-post-requests.mdx
+++ b/docs/developer-docs/smart-contracts/advanced-features/handling-get-post-requests.mdx
@@ -8,7 +8,7 @@ import { AdornedTab } from "/src/components/Tabs/AdornedTab";
import { BetaChip } from "/src/components/Chip/BetaChip";
import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-# Handling GET/POST requests
+# HTTPS gateways and incoming requests
@@ -16,382 +16,138 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
Canisters running on ICP can use HTTP requests in two ways: incoming and outgoing. Incoming HTTP requests refer to HTTP requests that are sent to a canister and can be used to retrieve data from a canister or send new data to the canister. Outgoing HTTP requests refer to HTTP requests that the canister sends to other canisters or external services to retrieve data or send new data.
-### Outgoing HTTP requests
+## HTTP gateways
-For outgoing HTTP requests, the [HTTPS outcalls](./https-outcalls/https-outcalls-how-to-use.mdx) feature should be used.
+The ICP HTTP gateway protocol enables conventional HTTP clients to interact with the ICP network. HTTP gateways run adjacent to ICP and provide a connection used by software such as web browsers to send and receive standard HTTP requests and responses, including static assets, such as HTML, JavaScript, images, or videos. The HTTP gateway makes this workflow possible by translating standard HTTP requests into API canister calls that ICP canisters can understand and vice versa for HTTP responses.
-- [How to use HTTPS outcalls](./https-outcalls/https-outcalls-how-to-use.mdx)
+There are several HTTP gateway instances maintained for ICP, but it should be noted that an HTTP gateway is a centralized component that could become compromised, creating a threat for users receiving HTTP content.
-- [HTTPS outcalls: `GET`](./https-outcalls/https-outcalls-get.mdx)
+DFINITY exclusively controls the HTTP gateways that serve canisters on `ic0.app` and `icp0.io`. Developers can then also configure their own [custom domains](https://internetcomputer.org/docs/current/developer-docs/web-apps/custom-domains/using-custom-domains) to point at the DFINITY controlled HTTP gateways.
-- [HTTPS outcalls: `POST`](./https-outcalls/https-outcalls-post.mdx)
+Alternatively, developers can run their own HTTP gateways on their custom domains instead of using the DFINITY controlled gateways, but this is not well supported yet.
-- [HTTPS outcalls: technology overview](/docs/current/references/https-outcalls-how-it-works)
+For a more secure solution, it is possible to run your own HTTP gateway instance locally.
-### Incoming HTTP requests
+### Terminology
-To handle incoming HTTP requests, canisters must define methods for `http_requests` and `http_requests_update` for `GET` and `POST` requests respectively.
+- **Request**: A message sent to a server or endpoint.
-All HTTP requests are handled by the ICP HTTP Gateway, therefore you cannot make direct `POST` calls to a canister's `http_request_update` method with HTTP clients such as curl. Instead, you can make a `POST` call to a canister's HTTP endpoint, then configure the canister's `http_request` method to [upgrade the call to `http_request_update` if necessary](/docs/current/references/http-gateway-protocol-spec#upgrade-to-update-calls). Below is an example `POST` call to a canister's endpoint:
+- **Client**: A service that is able to send an HTTP formatted request and receive a response from a server.
-```
-curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' https://.raw.ic0.app/
-```
+- **Gateway**: Enables the transfer of inbound and outbound messages.
-## `GET` requests
+## HTTP request lifecycle
-HTTP `GET` requests are used to retrieve and return existing data from an endpoint. To handle a canister's incoming `GET` requests, the `http_request` method can be exposed. Users and other services can call this method using a `query` call. To return HTTP response data, the following examples display how to configure the `http_request` to return an HTTP `GET` request.
+On ICP, an HTTP request goes through the following lifecycle:
-
-
+1. An HTTP client makes an outbound request.
-In Motoko, a `case` configuration can be used to return different `GET` responses based on the endpoint:
-
-```motoko no-repl
-import FHM "mo:StableHashMap/FunctionalStableHashMap";
-import SHA256 "mo:motoko-sha/SHA256";
-import CertTree "mo:ic-certification/CertTree";
-import CanisterSigs "mo:ic-certification/CanisterSigs";
-import CertifiedData "mo:base/CertifiedData";
-import HTTP "./Http";
-import Iter "mo:base/Iter";
-import Blob "mo:base/Blob";
-import Option "mo:base/Option";
-import Time "mo:base/Time";
-import Text "mo:base/Text";
-import Debug "mo:base/Debug";
-import Prelude "mo:base/Prelude";
-import Principal "mo:base/Principal";
-import Buffer "mo:base/Buffer";
-import Nat8 "mo:base/Nat8";
-import CertifiedCache "lib";
-import Int "mo:base/Int";
-
-actor Self {
- type HttpRequest = HTTP.HttpRequest;
- type HttpResponse = HTTP.HttpResponse;
-
- var two_days_in_nanos = 2 * 24 * 60 * 60 * 1000 * 1000 * 1000;
-
- stable var entries : [(Text, (Blob, Nat))] = [];
- var cache = CertifiedCache.fromEntries(
- entries,
- Text.equal,
- Text.hash,
- Text.encodeUtf8,
- func(b : Blob) : Blob { b },
- two_days_in_nanos + Int.abs(Time.now()),
- );
-
- public query func http_request(req : HttpRequest) : async HttpResponse {
- switch (req.method, not Option.isNull(Array.find(req.headers, isGzip)), req.url) {
- case ("GET", false, "/stream") {{
- status_code = 200;
- headers = [ ("content-type", "text/plain") ];
- body = Text.encodeUtf8("Counter");
- streaming_strategy = ?#Callback({
- callback = http_streaming;
- token = {
- arbitrary_data = "start";
- }
- });
- upgrade = ?false;
- }};
- case ("GET", false, _) {{
- status_code = 200;
- headers = [ ("content-type", "text/plain") ];
- body = Text.encodeUtf8("Counter is " # Nat.toText(counter) # "\n" # req.url # "\n");
- streaming_strategy = null;
- upgrade = null;
- }};
- case ("GET", true, _) {{
- status_code = 200;
- headers = [ ("content-type", "text/plain"), ("content-encoding", "gzip") ];
- body = "\1f\8b\08\00\98\02\1b\62\00\03\2b\2c\4d\2d\aa\e4\02\00\d6\80\2b\05\06\00\00\00";
- streaming_strategy = null;
- upgrade = null;
- }};
- };
- }
-}
-```
+2. The HTTP gateway intercepts the request and resolves the canister ID of the request's destination.
-Check out the [certified cache](https://github.com/krpeacock/certified-cache/blob/8657652c4062ef0e91ebe269843ccef1bb4796ae/src/demo.mo#L40) example project to see this code in use.
+3. The request is encoded with Candid and sent in a query call to the destination canister's `http_request` method.
-
-
+4. This request is sent to an ICP API boundary node, which will then forward the request to a replica node on the relevant subnet.
-```rust
-use http::{Request, Response, StatusCode};
+5. The canister receives and processes the request, then returns the response.
-#[query]
-fn respond_to(req: Request<()>) -> http::Result> {
- if req.uri() != "/hello" {
- return Response::builder()
- .status(StatusCode::NOT_FOUND)
- .body(())
- }
+6. The HTTP gateway decodes the Candid encoding on the response.
- let response_header = req.headers().contains_key("Hello!");
- let body = req.body();
+7. If the canister requests it, the gateway sends the request again via an update call to the canister's `http_request_update` method. The update call goes through consensus on the subnet.
-}
-```
+8. If the response size [exceeds the maximum response size](/docs/current/developer-docs/smart-contracts/maintain/resource-limits), the HTTP gateway fetches additional response body data through query calls.
-Check out the [Rust documentation](https://docs.rs/ic-cdk/latest/ic_cdk/attr.query.html) for more info on query calls.
+9. The HTTP gateway validates the response's certificate, if applicable.
-
-}>
-
-```typescript
-import {
- call,
- candidEncode,
- id,
- IDL,
- Principal,
- query,
- reply,
- update
-} from 'azle';
-import {
- HttpRequestArgs,
- HttpResponse,
- HttpTransformArgs
-} from 'azle/canisters/management';
-
-export default class {
- @update([], IDL.Text)
- async xkcd(): Promise {
- const httpResponse = await call('aaaaa-aa', 'http_request', {
- paramIdlTypes: [HttpRequestArgs],
- returnIdlType: HttpResponse,
- args: [
- {
- url: `https://xkcd.com/642/info.0.json`,
- max_response_bytes: [2_000n],
- method: {
- get: null
- },
- headers: [],
- body: [],
- transform: [
- {
- function: [id(), 'xkcdTransform'],
- context: Uint8Array.from([])
- }
- ]
- }
- ],
- payment: 50_000_000n
- });
-
- return Buffer.from(httpResponse.body).toString();
- }
+10. The HTTP gateway returns the decoded response to the HTTP client.
- @update([], HttpResponse, { manual: true })
- async xkcdRaw(): Promise {
- const httpResponse = await call(
- Principal.fromText('aaaaa-aa'),
- 'http_request',
- {
- raw: candidEncode(`
- (
- record {
- url = "https://xkcd.com/642/info.0.json";
- max_response_bytes = 2_000 : nat64;
- method = variant { get };
- headers = vec {};
- body = null;
- transform = record { function = func "${id().toString()}".xkcdTransform; context = vec {} };
- }
- )
- `),
- payment: 50_000_000n
- }
- );
-
- reply({ raw: httpResponse });
- }
+Additional details can be found in the [HTTP gateway specification](https://internetcomputer.org/docs/current/references/http-gateway-protocol-spec).
- @query([HttpTransformArgs], HttpResponse)
- xkcdTransform(args: HttpTransformArgs): HttpResponse {
- return {
- ...args.response,
- headers: []
- };
- }
-}
+## Running a local HTTP gateway
-```
+To run your own local HTTP gateway, a proof-of-concept implementation can be used that enables a secure end-to-end connection with canisters deployed on ICP.
-Check out the [Azle documentation](https://github.com/demergent-labs/azle/tree/main/tests/end_to_end/candid_rpc/class_syntax/outgoing_http_requests) for more info on HTTP requests.
+This implementation features:
-
-
+- Translation between HTTP asset requests and ICP API calls.
-```python
-from kybra import (
- Alias,
- blob,
- Func,
- ic,
- nat,
- nat16,
- Opt,
- Query,
- query,
- Record,
- StableBTreeMap,
- Tuple,
- Variant,
- Vec,
-)
+- Detects ICP domains from principals and custom domain records.
+- Terminates TLS connections locally.
-class Token(Record):
- arbitrary_data: str
+- Bypasses remote gateway denylists.
+- Resolves crypto domains.
-class StreamingCallbackHttpResponse(Record):
- body: blob
- token: Opt[Token]
+### Installation
+You can download the pre-built installation package for your [operating system](https://github.com/dfinity/http-proxy?tab=readme-ov-file#installation).
-Callback = Func(Query[[Token], StreamingCallbackHttpResponse])
+Once installed, you will have the option to start or stop the IC HTTP proxy service. Start the service to begin using it. Once the proxy is running, it will handle all traffic on your computer. Any traffic that's not meant for the ICP mainnet will pass through the gateway, and traffic that is meant for ICP will be intercepted by the proxy. The proxy will log traffic in the file `$HOME/Library/Preferences/dfinity/ichttpproxy/ic-http-proxy-proxy.log` on macOS machines, or in the `tmp` directory on Windows machines.
+For example, make the following `curl` request to the NNS:
-class CallbackStrategy(Record):
- callback: Callback
- token: Token
+```
+curl -v https://nns.ic0.app
+```
+This will result in a log entry of:
+
+```
+{"level":30, "time": "2024-06-17T13:46:40.947Z","pid":43956,"hostname":"JessieMgeonsMBP.attlocal.net","name":"IC HTTP Proxy Server","msg":"Proxying web3 request for nns.ic0.app:443"}
+```
-class StreamingStrategy(Variant, total=False):
- Callback: CallbackStrategy
+## Outgoing HTTP requests
+For outgoing HTTP requests, the [HTTPS outcalls](./https-outcalls/https-outcalls-how-to-use.mdx) feature should be used.
-HeaderField = Alias[Tuple[str, str]]
+- [How to use HTTPS outcalls](./https-outcalls/https-outcalls-how-to-use.mdx)
+- [HTTPS outcalls: `GET`](./https-outcalls/https-outcalls-get.mdx)
-class HttpResponse(Record):
- status_code: nat16
- headers: Vec[HeaderField]
- body: blob
- streaming_strategy: Opt[StreamingStrategy]
- upgrade: Opt[bool]
+- [HTTPS outcalls: `POST`](./https-outcalls/https-outcalls-post.mdx)
+- [HTTPS outcalls: technology overview](/docs/current/references/https-outcalls-how-it-works)
-class HttpRequest(Record):
- method: str
- url: str
- headers: Vec[HeaderField]
- body: blob
- certificate_version: Opt[nat16]
+## Incoming HTTP requests
+To handle incoming HTTP requests, canisters must define methods for `http_requests` and `http_requests_update` for `GET` and `POST` requests respectively.
-stable_storage = StableBTreeMap[str, nat](
- memory_id=0, max_key_size=15, max_value_size=1_000
-)
+All HTTP requests are handled by the ICP HTTP Gateway, therefore you cannot make direct `POST` calls to a canister's `http_request_update` method with HTTP clients such as curl. Instead, you can make a `POST` call to a canister's HTTP endpoint, then configure the canister's `http_request` method to [upgrade the call to `http_request_update` if necessary](/docs/current/references/http-gateway-protocol-spec#upgrade-to-update-calls). Below is an example `POST` call to a canister's endpoint:
-stable_storage.insert("counter", 0)
+```
+curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' https://.raw.ic0.app/
+```
+## `GET` requests
-def isGzip(x: HeaderField) -> bool:
- return x[0].lower() == "accept-encoding" and "gzip" in x[1].lower()
+HTTP `GET` requests are used to retrieve and return existing data from an endpoint. To handle a canister's incoming `GET` requests, the `http_request` method can be exposed. Users and other services can call this method using a `query` call. To return HTTP response data, the following examples display how to configure the `http_request` to return an HTTP `GET` request.
+
+
-@query
-def http_request(req: HttpRequest) -> HttpResponse:
- ic.print("Hello from http_request")
+In Motoko, a `case` configuration can be used to return different `GET` responses based on the endpoint.
- if req["method"] == "GET":
- if next(filter(isGzip, req["headers"]), None) is None:
- if req["url"] == "/stream":
- return {
- "status_code": 200,
- "headers": [("content-type", "text/plain")],
- "body": "Counter".encode("utf-8"),
- "streaming_strategy": {
- "Callback": {
- "callback": (ic.id(), "http_streaming"),
- "token": {"arbitrary_data": "start"},
- }
- },
- "upgrade": False,
- }
- return {
- "status_code": 200,
- "headers": [("content-type", "text/plain")],
- "body": f"Counter is {stable_storage.get('counter')}\n{req['url']}".encode(
- "utf-8"
- ),
- "streaming_strategy": None,
- "upgrade": None,
- }
- return {
- "status_code": 200,
- "headers": [("content-type", "text/plain"), ("content-encoding", "gzip")],
- "body": bytes(
- [
- 31,
- 139,
- 8,
- 0,
- 152,
- 2,
- 27,
- 98,
- 0,
- 3,
- 43,
- 44,
- 77,
- 45,
- 170,
- 228,
- 2,
- 0,
- 214,
- 128,
- 43,
- 5,
- 6,
- 0,
- 0,
- 0,
- ]
- ),
- "streaming_strategy": None,
- "upgrade": None,
- }
+Check out the [certified cache](https://github.com/krpeacock/certified-cache/blob/8657652c4062ef0e91ebe269843ccef1bb4796ae/src/demo.mo#L40) example project to see an example of this implementation.
- if req["method"] == "POST":
- return {
- "status_code": 204,
- "headers": [],
- "body": "".encode("utf-8"),
- "streaming_strategy": None,
- "upgrade": True,
- }
+
+
- return {
- "status_code": 400,
- "headers": [],
- "body": "Invalid request".encode("utf-8"),
- "streaming_strategy": None,
- "upgrade": None,
- }
-```
+Rust canisters can use the `query` attribute.
-:::caution
+Check out the [Rust documentation](https://docs.rs/ic-cdk/latest/ic_cdk/attr.query.html) for more info on query calls.
-Kybra canisters must be deployed from a Python virtual environment. [Learn more in the Kybra docs](/docs/current/developer-docs/backend/python/).
+
+}>
-:::
+[Learn more about Azle](https://demergent-labs.github.io/azle/the_azle_book.html).
-Check out the [Kybra documentation](https://demergent-labs.github.io/kybra/http.html) for more info on HTTP requests.
+
-
+}>
+
+[Learn more about Kybra](https://demergent-labs.github.io/kybra/).
+
+
## `POST` requests
@@ -401,352 +157,160 @@ HTTP `POST` requests are used to send data to an endpoint with the intention of
-In Motoko, a `case` configuration can be used to return different `POST` responses based on the endpoint:
-
-```motoko no-repl
-import FHM "mo:StableHashMap/FunctionalStableHashMap";
-import SHA256 "mo:motoko-sha/SHA256";
-import CertTree "mo:ic-certification/CertTree";
-import CanisterSigs "mo:ic-certification/CanisterSigs";
-import CertifiedData "mo:base/CertifiedData";
-import HTTP "./Http";
-import Iter "mo:base/Iter";
-import Blob "mo:base/Blob";
-import Option "mo:base/Option";
-import Time "mo:base/Time";
-import Text "mo:base/Text";
-import Debug "mo:base/Debug";
-import Prelude "mo:base/Prelude";
-import Principal "mo:base/Principal";
-import Buffer "mo:base/Buffer";
-import Nat8 "mo:base/Nat8";
-import CertifiedCache "lib";
-import Int "mo:base/Int";
-
-actor Self {
- type HttpRequest = HTTP.HttpRequest;
- type HttpResponse = HTTP.HttpResponse;
-
- var two_days_in_nanos = 2 * 24 * 60 * 60 * 1000 * 1000 * 1000;
-
- stable var entries : [(Text, (Blob, Nat))] = [];
- var cache = CertifiedCache.fromEntries(
- entries,
- Text.equal,
- Text.hash,
- Text.encodeUtf8,
- func(b : Blob) : Blob { b },
- two_days_in_nanos + Int.abs(Time.now()),
- );
-
- public func http_request_update(req : HttpRequest) : async HttpResponse {
- switch (req.method, not Option.isNull(Array.find(req.headers, isGzip))) {
- case ("POST", false) {
- counter += 1;
- {
- status_code = 201;
- headers = [ ("content-type", "text/plain") ];
- body = Text.encodeUtf8("Counter updated to " # Nat.toText(counter) # "\n");
- streaming_strategy = null;
- upgrade = null;
- }
- };
- case ("POST", true) {
- counter += 1;
- {
- status_code = 201;
- headers = [ ("content-type", "text/plain"), ("content-encoding", "gzip") ];
- body = "\1f\8b\08\00\37\02\1b\62\00\03\2b\2d\48\49\2c\49\e5\02\00\a8\da\91\6c\07\00\00\00";
-
- streaming_strategy = null;
- upgrade = null;
- }
- };
- };
- };
-}
-
-```
+In Motoko, a `case` configuration can be used to return different `POST` responses based on the endpoint.
-Check out the [certified cache](https://github.com/krpeacock/certified-cache/blob/8657652c4062ef0e91ebe269843ccef1bb4796ae/src/demo.mo#L76) example project to see this code in use.
+Check out the [certified cache](https://github.com/krpeacock/certified-cache/blob/8657652c4062ef0e91ebe269843ccef1bb4796ae/src/demo.mo#L40) example project to see an example of this implementation.
-```rust
-use http::{Request, Response, StatusCode};
-
-#[update]
-fn respond_to(req: Request<()>) -> http::Result> {
- let mut builder = Response::builder()
- .header("Hello!")
- .status(StatusCode::OK);
-
- if req.headers().contains_key("Another-Header") {
- builder = builder.header("Another-Header", "Ack");
- }
-
- builder.body(())
-}
-```
+Rust canisters can use the `update` attribute.
Check out the [Rust documentation](https://docs.rs/ic-cdk/latest/ic_cdk/attr.update.html) for more info on update calls.
-}>
-
-```typescript
-import {
- call,
- candidEncode,
- id,
- IDL,
- Principal,
- query,
- reply,
- update
-} from 'azle';
-import {
- HttpRequestArgs,
- HttpResponse,
- HttpTransformArgs
-} from 'azle/canisters/management';
-
-export default class {
- @update([], IDL.Text)
- async xkcd(): Promise {
- const httpResponse = await call('aaaaa-aa', 'http_request', {
- paramIdlTypes: [HttpRequestArgs],
- returnIdlType: HttpResponse,
- args: [
- {
- url: `https://xkcd.com/642/info.0.json`,
- max_response_bytes: [2_000n],
- method: {
- get: null
- },
- headers: [],
- body: [],
- transform: [
- {
- function: [id(), 'xkcdTransform'] as [
- Principal,
- string
- ],
- context: Uint8Array.from([])
- }
- ]
- }
- ],
- payment: 50_000_000n
- });
-
- return Buffer.from(httpResponse.body).toString();
- }
-
- @update([], HttpResponse, { manual: true })
- async xkcdRaw(): Promise {
- const httpResponse = await call(
- Principal.fromText('aaaaa-aa'),
- 'http_request',
- {
- raw: candidEncode(`
- (
- record {
- url = "https://xkcd.com/642/info.0.json";
- max_response_bytes = 2_000 : nat64;
- method = variant { post };
- headers = vec {};
- body = null;
- transform = record { function = func "${id().toString()}".xkcdTransform; context = vec {} };
- }
- )
- `),
- payment: 50_000_000n
- }
- );
-
- reply({ raw: httpResponse });
- }
-
- @query([HttpTransformArgs], HttpResponse)
- xkcdTransform(args: HttpTransformArgs): HttpResponse {
- return {
- ...args.response,
- headers: []
- };
- }
-}
-```
-
-Check out the [Azle documentation](https://github.com/demergent-labs/azle/tree/main/tests/end_to_end/candid_rpc/class_syntax/outgoing_http_requests) for more info on HTTP requests.
-
-
-
-
-```python
-from kybra import (
- Alias,
- blob,
- Func,
- ic,
- nat,
- nat16,
- Opt,
- Query,
- query,
- Record,
- StableBTreeMap,
- Tuple,
- update,
- Variant,
- Vec,
-)
+}>
+[Learn more about Azle](https://demergent-labs.github.io/azle/the_azle_book.html).
-class Token(Record):
- arbitrary_data: str
+
+}>
-class StreamingCallbackHttpResponse(Record):
- body: blob
- token: Opt[Token]
+[Learn more about Kybra](https://demergent-labs.github.io/kybra/).
+
+
-Callback = Func(Query[[Token], StreamingCallbackHttpResponse])
+## Serving HTTP requests
+Canisters can serve or handle an incoming HTTP request using the
+[HTTP Gateway Protocol](/docs/current/references/http-gateway-protocol-spec).
+This allows developers to host web applications and APIs from a canister.
-class CallbackStrategy(Record):
- callback: Callback
- token: Token
+The following example returns 'Hello, World!' in the body at the `/hello`
+endpoint.
+
+
-class StreamingStrategy(Variant, total=False):
- Callback: CallbackStrategy
+```motoko
+import HashMap = "mo:base/HashMap";
+import Blob = "mo:base/Blob";
+import Text "mo:base/Text";
+import Option "mo:base/Option";
+actor {
-HeaderField = Alias[Tuple[str, str]]
+ public type HttpRequest = {
+ body: Blob;
+ headers: [HeaderField];
+ method: Text;
+ url: Text;
+ };
+ public type ChunkId = Nat;
+ public type SetAssetContentArguments = {
+ chunk_ids: [ChunkId];
+ content_encoding: Text;
+ key: Key;
+ sha256: ?Blob;
+ };
+ public type Path = Text;
+ public type Key = Text;
-class HttpResponse(Record):
- status_code: nat16
- headers: Vec[HeaderField]
- body: blob
- streaming_strategy: Opt[StreamingStrategy]
- upgrade: Opt[bool]
+ public type HttpResponse = {
+ body: Blob;
+ headers: [HeaderField];
+ status_code: Nat16;
+ };
+ public type HeaderField = (Text, Text);
-class HttpRequest(Record):
- method: str
- url: str
- headers: Vec[HeaderField]
- body: blob
+ private func removeQuery(str: Text): Text {
+ return Option.unwrap(Text.split(str, #char '?').next());
+ };
+ public query func http_request(req: HttpRequest): async (HttpResponse) {
+ let path = removeQuery(req.url);
+ if(path == "/hello") {
+ return {
+ body = Text.encodeUtf8("root page :" # path);
+ headers = [];
+ status_code = 200;
+ };
+ };
-stable_storage = StableBTreeMap[str, nat](
- memory_id=0, max_key_size=15, max_value_size=1_000
-)
+ return {
+ body = Text.encodeUtf8("404 Not found :" # path);
+ headers = [];
+ status_code = 404;
+ };
+ };
+}
+```
-stable_storage.insert("counter", 0)
+
+
-def isGzip(x: HeaderField) -> bool:
- return x[0].lower() == "accept-encoding" and "gzip" in x[1].lower()
+```rust
+type HeaderField = (String, String);
-@update
-def http_request_update(req: HttpRequest) -> HttpResponse:
- ic.print("Hello from update")
- global stable_storage
+struct HttpResponse {
+ status_code: u16,
+ headers: Vec,
+ body: Cow<'static, Bytes>,
+}
- if req["method"] == "POST":
- counter = stable_storage.get("counter") or 0
- stable_storage.insert("counter", counter + 1)
+struct HttpRequest {
+ method: String,
+ url: String,
+ headers: Vec<(String, String)>,
+ body: ByteBuf,
+}
- if next(filter(isGzip, req["headers"]), None) is None:
- return {
- "status_code": 201,
- "headers": [("content-type", "text/plain")],
- "body": f"Counter updated to {stable_storage.get('counter')}".encode(
- "utf-8"
- ),
- "streaming_strategy": None,
- "upgrade": None,
- }
- return {
- "status_code": 201,
- "headers": [("content-type", "text/plain"), ("content-encoding", "gzip")],
- "body": bytes(
- [
- 31,
- 139,
- 8,
- 0,
- 55,
- 2,
- 27,
- 98,
- 0,
- 3,
- 43,
- 45,
- 72,
- 73,
- 44,
- 73,
- 229,
- 2,
- 0,
- 168,
- 218,
- 145,
- 108,
- 7,
- 0,
- 0,
- 0,
- ]
- ),
- "streaming_strategy": None,
- "upgrade": None,
+#[query]
+fn http_request(req: HttpRequest) -> HttpResponse {
+ let path = req.url.path();
+ if path == "/hello" {
+ HttpResponse {
+ status_code: 200,
+ headers: Vec::new(),
+ body: b"hello, world!".to_vec(),
+ streaming_strategy: None,
+ upgrade: None,
}
-
- return {
- "status_code": 400,
- "headers": [],
- "body": "Invalid request".encode("utf-8"),
- "streaming_strategy": None,
- "upgrade": None,
- }
-
-
-@query
-def http_streaming(token: Token) -> StreamingCallbackHttpResponse:
- ic.print("Hello from http_streaming")
- if token["arbitrary_data"] == "start":
- return {"body": " is ".encode("utf-8"), "token": {"arbitrary_data": "next"}}
- if token["arbitrary_data"] == "next":
- return {
- "body": f"{stable_storage.get('counter')}".encode("utf-8"),
- "token": {"arbitrary_data": "last"},
+ } else {
+ HttpResponse {
+ status_code: 404,
+ headers: Vec::new(),
+ body: b"404 Not found :".to_vec(),
+ streaming_strategy: None,
+ upgrade: None,
}
- if token["arbitrary_data"] == "last":
- return {"body": " streaming\n".encode("utf-8"), "token": None}
- ic.trap("unreachable")
+ }
+}
```
-:::caution
+
+}>
-Kybra canisters must be deployed from a Python virtual environment. [Learn more in the Kybra docs](/docs/current/developer-docs/backend/python/).
+[Learn more about Azle](https://demergent-labs.github.io/azle/the_azle_book.html).
-:::
+
-Check out the [Kybra documentation](https://demergent-labs.github.io/kybra/http.html) for more info on HTTP requests.
+}>
-
+[Learn more about Kybra](https://demergent-labs.github.io/kybra/).
+
+
## Resources
+- [HTTP gateway specification](https://internetcomputer.org/docs/current/references/http-gateway-protocol-spec)
+
- [How to use HTTPS outcalls](./https-outcalls/https-outcalls-how-to-use.mdx)
- [HTTPS outcalls: `GET`](./https-outcalls/https-outcalls-get.mdx)
diff --git a/docs/developer-docs/smart-contracts/advanced-features/http-gateways.mdx b/docs/developer-docs/smart-contracts/advanced-features/http-gateways.mdx
deleted file mode 100644
index d8ad3d5506..0000000000
--- a/docs/developer-docs/smart-contracts/advanced-features/http-gateways.mdx
+++ /dev/null
@@ -1,93 +0,0 @@
----
-keywords: [advanced, tutorial, http, http gateways, gateways]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# HTTP gateways
-
-
-
-## Overview
-
-The ICP HTTP gateway protocol enables conventional HTTP clients to interact with the ICP network. HTTP gateways run adjacent to ICP and provide a connection used by software such as web browsers to send and receive standard HTTP requests and responses, including static assets, such as HTML, JavaScript, images, or videos. The HTTP gateway makes this workflow possible by translating standard HTTP requests into API canister calls that ICP canisters can understand and vice versa for HTTP responses.
-
-There are several HTTP gateway instances maintained for ICP, but it should be noted that an HTTP gateway is a centralized component that could become compromised, creating a threat for users receiving HTTP content.
-
-DFINITY exclusively controls the HTTP gateways that serve canisters on `ic0.app` and `icp0.io`. Developers can then also configure their own [custom domains](https://internetcomputer.org/docs/current/developer-docs/web-apps/custom-domains/using-custom-domains) to point at the DFINITY controlled HTTP gateways.
-
-Alternatively, developers can run their own HTTP gateways on their custom domains instead of using the DFINITY controlled gateways, but this is not well supported yet.
-
-For a more secure solution, it is possible to run your own HTTP gateway instance locally.
-
-### Terminology
-
-- **Request**: A message sent to a server or endpoint.
-
-- **Client**: A service that is able to send an HTTP formatted request and receive a response from a server.
-
-- **Gateway**: Enables the transfer of inbound and outbound messages.
-
-## HTTP request lifecycle
-
-On ICP, an HTTP request goes through the following lifecycle:
-
-1. An HTTP client makes an outbound request.
-
-2. The HTTP gateway intercepts the request and resolves the canister ID of the request's destination.
-
-3. The request is encoded with Candid and sent in a query call to the destination canister's `http_request` method.
-
-4. This request is sent to an ICP API boundary node, which will then forward the request to a replica node on the relevant subnet.
-
-5. The canister receives and processes the request, then returns the response.
-
-6. The HTTP gateway decodes the Candid encoding on the response.
-
-7. If the canister requests it, the gateway sends the request again via an update call to the canister's `http_request_update` method. The update call goes through consensus on the subnet.
-
-8. If the response size [exceeds the maximum response size](/docs/current/developer-docs/smart-contracts/maintain/resource-limits), the HTTP gateway fetches additional response body data through query calls.
-
-9. The HTTP gateway validates the response's certificate, if applicable.
-
-10. The HTTP gateway returns the decoded response to the HTTP client.
-
-Additional details can be found in the [HTTP gateway specification](https://internetcomputer.org/docs/current/references/http-gateway-protocol-spec).
-
-## Running a local HTTP gateway
-
-To run your own local HTTP gateway, a proof-of-concept implementation can be used that enables a secure end-to-end connection with canisters deployed on ICP.
-
-This implementation features:
-
-- Translation between HTTP asset requests and ICP API calls.
-
-- Detects ICP domains from principals and custom domain records.
-
-- Terminates TLS connections locally.
-
-- Bypasses remote gateway denylists.
-
-- Resolves crypto domains.
-
-### Installation
-
-You can download the pre-built installation package for your [operating system](https://github.com/dfinity/http-proxy?tab=readme-ov-file#installation).
-
-Once installed, you will have the option to start or stop the IC HTTP proxy service. Start the service to begin using it. Once the proxy is running, it will handle all traffic on your computer. Any traffic that's not meant for the ICP mainnet will pass through the gateway, and traffic that is meant for ICP will be intercepted by the proxy. The proxy will log traffic in the file `$HOME/Library/Preferences/dfinity/ichttpproxy/ic-http-proxy-proxy.log` on macOS machines, or in the `tmp` directory on Windows machines.
-
-For example, make the following `curl` request to the NNS:
-
-```
-curl -v https://nns.ic0.app
-```
-
-This will result in a log entry of:
-
-```
-{"level":30, "time": "2024-06-17T13:46:40.947Z","pid":43956,"hostname":"JessieMgeonsMBP.attlocal.net","name":"IC HTTP Proxy Server","msg":"Proxying web3 request for nns.ic0.app:443"}
-```
-
-## Resources
-
-- [HTTP gateway specification](https://internetcomputer.org/docs/current/references/http-gateway-protocol-spec).
diff --git a/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-get.mdx b/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-get.mdx
index 35877a0f31..2dfc04365c 100644
--- a/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-get.mdx
+++ b/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-get.mdx
@@ -15,319 +15,14 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
## Overview
-A minimal example to make a `GET` HTTP request. The purpose of this dapp is only to show how to make HTTP requests from a canister.
+A minimal example to make a `GET` HTTP request. The purpose of this dapp is only to show how to make HTTP requests from a canister. It sends a `GET` request to the Coinbase API and retrieves some historical data about the ICP token.
-The sample code is in both Motoko and Rust. This sample canister sends a `GET` request to the Coinbase API and retrieves some historical data about the ICP token.
-
-
-**The main intent of this canister is to show developers how to make idempotent `GET` requests.**
-
-This example takes less than 5 minutes to complete.
-
-### Sample dapp
-
-The canister in this tutorial will have only **one public method** named `get_icp_usd_exchange()` which, when called, will trigger an HTTP `GET` request to an external service. The canister will not have a frontend (only a backend), but like all canisters, you can interact with its public methods via the Candid web UI, which will look like this:
-
-
-![Candid web UI](../_attachments/https-get.webp)
-
-The `get_icp_usd_exchange()` method returns Coinbase data on the exchange rate between USD and ICP for a certain day. The data will look like this:
-
-The API response looks like this:
-```
- [
- [
- 1682978460, <-- start timestamp
- 5.714, <-- lowest price during time range
- 5.718, <-- highest price during range
- 5.714, <-- price at open
- 5.714, <-- price at close
- 243.5678 <-- volume of traded
- ],
-]
-```
-
-## Code structure
-
-Before you dive in, here is the structure of the code you will touch:
-
-
-
-
-```motoko no-repl
-
-//Import some custom types from `src/backend_canister/Types.mo` file
-import Types "Types";
-
-actor {
-
- //0. method that uses the HTTPS outcalls feature and returns a string
- public func foo() : async Text {
-
- //1. DECLARE MANAGEMENT CANISTER
- let ic : Types.IC = actor ("aaaaa-aa");
-
- //2. SETUP ARGUMENTS FOR HTTP GET request
- let request : Types.HttpRequestArgs = {
- //construct the request
- };
-
- //3. ADD CYCLES TO PAY FOR HTTP REQUEST
- //code to add cycles
-
- //4. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
- let response : Types.HttpResponsePayload = await ic.http_request(request);
-
- //5. DECODE THE RESPONSE
- //code to decode response
-
- //6. RETURN RESPONSE OF THE BODY
- response
- };
-
- //7. CREATE TRANSFORM FUNCTION
- public query func transform(raw : Types.TransformArgs) : async Types.CanisterHttpResponsePayload {
- ////code for the transform function
- }
-
-};
-```
-
-You will also create some custom types in `Types.mo`. It will look like this:
-
-```motoko no-repl
-module Types {
-
- //type declarations for s, HTTP responses, management canister, etc...
-
-}
-```
-
-
-
-
-Here is how the management canister is declared in a Rust canister (e.g. `lib.rs`):
-
-```rust
-//1. DECLARE MANAGEMENT CANISTER
-use ic_cdk::api::management_canister::http_request::{
- http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod, HttpResponse, TransformArgs,
- TransformContext,
-};
-
-//Update method using the HTTPS outcalls feature
-#[ic_cdk::update]
-async fn foo() {
- //2. SETUP ARGUMENTS FOR HTTP GET request
- let request = CanisterHttpRequestArgument {
- //instantiate the request
- };
-
- //3. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
- //Note: in Rust, `http_request()` already sends the cycles needed
- //so no need for explicit Cycles.add() as in Motoko
- match http_request(request).await {
-
- //4. DECODE AND RETURN THE RESPONSE
- Ok((response,)) => {
- //Ok case
- }
- Err((r, m)) => {
- //error case
- }
- }
-}
-
-// 4. CREATE TRANSFORM FUNCTION
-#[ic_cdk::query]
-fn transform(raw: TransformArgs) -> HttpResponse { }
-```
-
-
-
-
-
-- #### Step 1: Create a new project by running the following command:
+## `GET` example
-```bash
-dfx new send_http_get_motoko
-cd send_http_get_motoko
-npm install
-```
-
-
-
-
-```bash
-dfx new send_http_get_rust --type=rust
-cd send_http_get_rust
-npm install
-rustup target add wasm32-unknown-unknown
-```
-
-
-
-
-
-
-- #### Step 2: Edit the backend canister's code.
-
-
-
-
-Open the `src/send_http_get_motoko_backend/main.mo` file in a text editor and replace content with:
-
-```motoko no-repl title="src/send_http_get_motoko_backend/main.mo"
-import Debug "mo:base/Debug";
-import Blob "mo:base/Blob";
-import Cycles "mo:base/ExperimentalCycles";
-import Error "mo:base/Error";
-import Array "mo:base/Array";
-import Nat8 "mo:base/Nat8";
-import Nat64 "mo:base/Nat64";
-import Text "mo:base/Text";
-
-//import the custom types you have in Types.mo
-import Types "Types";
-
-
-//Actor
-actor {
-
-//This method sends a GET request to a URL with a free API you can test.
-//This method returns Coinbase data on the exchange rate between USD and ICP
-//for a certain day.
-//The API response looks like this:
-// [
-// [
-// 1682978460, <-- start timestamp
-// 5.714, <-- lowest price during time range
-// 5.718, <-- highest price during range
-// 5.714, <-- price at open
-// 5.714, <-- price at close
-// 243.5678 <-- volume of ICP traded
-// ],
-// ]
-
- public func get_icp_usd_exchange() : async Text {
-
- //1. DECLARE MANAGEMENT CANISTER
- //You need this so you can use it to make the HTTP request
- let ic : Types.IC = actor ("aaaaa-aa");
-
- //2. SETUP ARGUMENTS FOR HTTP GET request
-
- // 2.1 Setup the URL and its query parameters
- let ONE_MINUTE : Nat64 = 60;
- let start_timestamp : Types.Timestamp = 1682978460; //May 1, 2023 22:01:00 GMT
- let end_timestamp : Types.Timestamp = 1682978520;//May 1, 2023 22:02:00 GMT
- let host : Text = "api.pro.coinbase.com";
- let url = "https://" # host # "/products/ICP-USD/candles?start=" # Nat64.toText(start_timestamp) # "&end=" # Nat64.toText(start_timestamp) # "&granularity=" # Nat64.toText(ONE_MINUTE);
-
- // 2.2 prepare headers for the system http_request call
- let request_headers = [
- { name = "Host"; value = host # ":443" },
- { name = "User-Agent"; value = "exchange_rate_canister" },
- ];
-
- // 2.2.1 Transform context
- let transform_context : Types.TransformContext = {
- function = transform;
- context = Blob.fromArray([]);
- };
-
- // 2.3 The HTTP request
- let http_request : Types.HttpRequestArgs = {
- url = url;
- max_response_bytes = null; //optional for request
- headers = request_headers;
- body = null; //optional for request
- method = #get;
- transform = ?transform_context;
- };
-
- //3. ADD CYCLES TO PAY FOR HTTP REQUEST
-
- //The IC specification spec says, "Cycles to pay for the call must be explicitly transferred with the call"
- //The management canister will make the HTTP request so it needs cycles
- //See: /docs/current/motoko/main/canister-maintenance/cycles
-
- //The way Cycles.add() works is that it adds those cycles to the next asynchronous call
- //"Function add(amount) indicates the additional amount of cycles to be transferred in the next remote call"
- //See: /docs/current/references/ic-interface-spec#ic-http_request
- Cycles.add(20_949_972_000);
-
- //4. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
- //Since the cycles were added above, you can just call the management canister with HTTPS outcalls below
- let http_response : Types.HttpResponsePayload = await ic.http_request(http_request);
-
- //5. DECODE THE RESPONSE
-
- //As per the type declarations in `src/Types.mo`, the BODY in the HTTP response
- //comes back as [Nat8s] (e.g. [2, 5, 12, 11, 23]). Type signature:
-
- //public type HttpResponsePayload = {
- // status : Nat;
- // headers : [HttpHeader];
- // body : [Nat8];
- // };
-
- //You need to decode that [Nat8] array that is the body into readable text.
- //To do this, you:
- // 1. Convert the [Nat8] into a Blob
- // 2. Use Blob.decodeUtf8() method to convert the Blob to a ?Text optional
- // 3. You use a switch to explicitly call out both cases of decoding the Blob into ?Text
- let response_body: Blob = Blob.fromArray(http_response.body);
- let decoded_text: Text = switch (Text.decodeUtf8(response_body)) {
- case (null) { "No value returned" };
- case (?y) { y };
- };
-
- //6. RETURN RESPONSE OF THE BODY
- //The API response will looks like this:
-
- // ("[[1682978460,5.714,5.718,5.714,5.714,243.5678]]")
-
- //Which can be formatted as this
- // [
- // [
- // 1682978460, <-- start/timestamp
- // 5.714, <-- low
- // 5.718, <-- high
- // 5.714, <-- open
- // 5.714, <-- close
- // 243.5678 <-- volume
- // ],
- // ]
- decoded_text
- };
-
- //7. CREATE TRANSFORM FUNCTION
- public query func transform(raw : Types.TransformArgs) : async Types.CanisterHttpResponsePayload {
- let transformed : Types.CanisterHttpResponsePayload = {
- status = raw.response.status;
- body = raw.response.body;
- headers = [
- {
- name = "Content-Security-Policy";
- value = "default-src 'self'";
- },
- { name = "Referrer-Policy"; value = "strict-origin" },
- { name = "Permissions-Policy"; value = "geolocation=(self)" },
- {
- name = "Strict-Transport-Security";
- value = "max-age=63072000";
- },
- { name = "X-Frame-Options"; value = "DENY" },
- { name = "X-Content-Type-Options"; value = "nosniff" },
- ];
- };
- transformed;
- };
-};
+```motoko no-repl file=../../../../references/samples/motoko/send_http_get/src/send_http_get_backend/main.mo
```
- `get_icp_usd_exchange()` is an update call. All methods that make HTTPS outcalls must be update calls because they go through consensus, even if the HTTPS outcall is a `GET`.
@@ -337,418 +32,35 @@ actor {
-Open the `src/send_http_get_rust_backend/src/lib.rs` file in a text editor and replace the content with:
-
-```rust title="src/send_http_get_rust_backend/src/lib.rs"
-//1. IMPORT MANAGEMENT CANISTER
-//This includes all methods and types needed
-use ic_cdk::api::management_canister::http_request::{
- http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod, HttpResponse, TransformArgs,
- TransformContext, TransformFunc,
-};
-
-
-//Update method using the HTTPS outcalls feature
-#[ic_cdk::update]
-async fn get_icp_usd_exchange() -> String {
- //2. SETUP ARGUMENTS FOR HTTP GET request
-
- // 2.1 Setup the URL and its query parameters
- type Timestamp = u64;
- let start_timestamp: Timestamp = 1682978460; //May 1, 2023 22:01:00 GMT
- let seconds_of_time: u64 = 60; //start with 60 seconds
- let host = "api.pro.coinbase.com";
- let url = format!(
- "https://{}/products/ICP-USD/candles?start={}&end={}&granularity={}",
- host, start_timestamp, start_timestamp, seconds_of_time
- );
-
- // 2.2 Prepare headers for the system http_request call
- //Note that `HttpHeader` is declared in line 4
- let request_headers = vec![
- HttpHeader {
- name: "Host".to_string(),
- value: format!("{host}:443"),
- },
- HttpHeader {
- name: "User-Agent".to_string(),
- value: "exchange_rate_canister".to_string(),
- },
- ];
-
- //note "CanisterHttpRequestArgument" and "HttpMethod" are declared in line 4
- let request = CanisterHttpRequestArgument {
- url: url.to_string(),
- method: HttpMethod::GET,
- body: None, //optional for request
- max_response_bytes: None, //optional for request
- transform: Some(TransformContext {
- // The "method" parameter needs to have the same name as the function name of your transform function
- function: TransformFunc(candid::Func {
- principal: ic_cdk::api::id(),
- method: "transform".to_string(),
- }),
- // The "TransformContext" function does need a context parameter, it can be empty
- context: vec![],
- }),
- headers: request_headers,
- };
-
- //3. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
-
- //Note: in Rust, `http_request()` needs to pass cycles if you are using ic_cdk: ^0.9.0
- let cycles = 230_949_972_000;
-
- match http_request(request, cycles).await {
- //4. DECODE AND RETURN THE RESPONSE
-
- //See:https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/struct.HttpResponse.html
- Ok((response,)) => {
- //if successful, `HttpResponse` has this structure:
- // pub struct HttpResponse {
- // pub status: Nat,
- // pub headers: Vec,
- // pub body: Vec,
- // }
-
- //You need to decode that Vec that is the body into readable text.
- //To do this:
- // 1. Call `String::from_utf8()` on response.body
- // 3. You use a switch to explicitly call out both cases of decoding the Blob into ?Text
-
- //The API response will look like this:
-
- // ("[[1682978460,5.714,5.718,5.714,5.714,243.5678]]")
-
- //Which can be formatted as this
- // [
- // [
- // 1682978460, <-- start/timestamp
- // 5.714, <-- low
- // 5.718, <-- high
- // 5.714, <-- open
- // 5.714, <-- close
- // 243.5678 <-- volume
- // ],
- // ]
-
- //Return the body as a string and end the method
- String::from_utf8(response.body).expect("Transformed response is not UTF-8 encoded.")
- }
- Err((r, m)) => {
- let message =
- format!("The http_request resulted into error. RejectionCode: {r:?}, Error: {m}");
-
- //Return the error as a string and end the method
- message
- }
- }
-}
-
-// Strips all data that is not needed from the original response.
-#[ic_cdk::query]
-fn transform(raw: TransformArgs) -> HttpResponse {
- let headers = vec![
- HttpHeader {
- name: "Content-Security-Policy".to_string(),
- value: "default-src 'self'".to_string(),
- },
- HttpHeader {
- name: "Referrer-Policy".to_string(),
- value: "strict-origin".to_string(),
- },
- HttpHeader {
- name: "Permissions-Policy".to_string(),
- value: "geolocation=(self)".to_string(),
- },
- HttpHeader {
- name: "Strict-Transport-Security".to_string(),
- value: "max-age=63072000".to_string(),
- },
- HttpHeader {
- name: "X-Frame-Options".to_string(),
- value: "DENY".to_string(),
- },
- HttpHeader {
- name: "X-Content-Type-Options".to_string(),
- value: "nosniff".to_string(),
- },
- ];
-
- let mut res = HttpResponse {
- status: raw.response.status.clone(),
- body: raw.response.body.clone(),
- headers,
- };
-
- if res.status == 200u64 {
- res.body = raw.response.body;
- } else {
- ic_cdk::api::print(format!("Received an error from coinbase: err = {:?}", raw));
- }
- res
-}
+```rust file=../../../../references/samples/rust/send_http_get/src/send_http_get_backend/src/lib.rs
```
- `get_icp_usd_exchange() -> String` returns a `String`, but this is not necessary. In this tutorial, this is done for easier testing.
- The `lib.rs` file uses [http_request](https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/fn.http_request.html) which is a convenient Rust CDK method that already sends cycles to the management canister under the hood. It knows how many cycles to send for a 13-node subnet in most cases. If your HTTPS outcall needs more cycles, you should use the [http_request_with_cycles()](https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/fn.http_request_with_cycles.html) method and explicitly call the cycles needed.
- The Rust CDK method `http_request` used above wraps the management canister method [`http_request`](/docs/current/references/ic-interface-spec#ic-http_request), but it is not strictly the same.
-
-
-
-:::caution
-
-Headers in the response may not always be identical across all nodes that process the request for consensus, causing the result of the call to be "No consensus could be reached." This particular error message can be hard to debug, but one method to resolve this error is to edit the response using the transform function. The transform function is run before consensus, and can be used to remove some headers from the response. For example, the following Rust variation removes all headers aside from the body and status code of the call:
-
-```rust title="src/send_http_get_rust_backend/src/lib.rs"
-use ic_cdk::{
- api::management_canister::http_request::{HttpResponse, TransformArgs},
- query,
-};
-
-#[query]
-fn transform(raw: TransformArgs) -> HttpResponse {
- let mut res = HttpResponse {
- status: raw.response.status.clone(),
- body: raw.response.body.clone(),
- ..Default::default()
- };
-
- if i32::try_from(res.status.clone().0).unwrap() == 200 {
- res.body = raw.response.body;
- } else {
- ic_cdk::api::print(format!("Received an error from proxy: err = {:?}", raw));
- }
-
- res
-}
-```
-:::
-
-
-- #### Step 3: Edit the Type or Candid files.
-
-
-
-
-Open the `src/send_http_get_motoko_backend/Types.mo` file in a text editor and replace content with:
-
-```motoko no-repl title="src/send_http_get_motoko_backend/Types.mo"
-module Types {
-
- public type Timestamp = Nat64;
-
- //1. Type that describes the Request arguments for an HTTPS outcall
- //See: /docs/current/references/ic-interface-spec#ic-http_request
- public type HttpRequestArgs = {
- url : Text;
- max_response_bytes : ?Nat64;
- headers : [HttpHeader];
- body : ?[Nat8];
- method : HttpMethod;
- transform : ?TransformRawResponseFunction;
- };
-
- public type HttpHeader = {
- name : Text;
- value : Text;
- };
-
- public type HttpMethod = {
- #get;
- #post;
- #head;
- };
-
- public type HttpResponsePayload = {
- status : Nat;
- headers : [HttpHeader];
- body : [Nat8];
- };
-
- //2. HTTPS outcalls have an optional "transform" key. These two types help describe it.
- //"The transform function may, for example, transform the body in any way, add or remove headers,
- //modify headers, etc. "
- //See: /docs/current/references/ic-interface-spec#ic-http_request
-
-
- //2.1 This type describes a function called "TransformRawResponse" used in line 14 above
- //"If provided, the calling canister itself must export this function."
- //In this minimal example for a `GET` request, you declare the type for completeness, but
- //you do not use this function. You will pass "null" to the HTTP request.
- public type TransformRawResponseFunction = {
- function : shared query TransformArgs -> async HttpResponsePayload;
- context : Blob;
- };
-
- //2.2 These types describes the arguments the transform function needs
- public type TransformArgs = {
- response : HttpResponsePayload;
- context : Blob;
- };
-
- public type CanisterHttpResponsePayload = {
- status : Nat;
- headers : [HttpHeader];
- body : [Nat8];
- };
-
- public type TransformContext = {
- function : shared query TransformArgs -> async HttpResponsePayload;
- context : Blob;
- };
-
-
- //3. Declaring the management canister which you use to make the HTTPS outcall
- public type IC = actor {
- http_request : HttpRequestArgs -> async HttpResponsePayload;
- };
-
-}
-```
-
-
-
-
-Open the `src/send_http_get_rust_backend/send_http_get_rust_backend.did` file in a text editor and replace the content with:
-
-You update the Candid interface file so it matches the method `get_icp_usd_exchange()` in `lib.rs`.
-
-```candid title="src/send_http_get_rust_backend/send_http_get_rust_backend.did"
-service : {
- "get_icp_usd_exchange": () -> (text);
-}
-```
-
-Open the `src/send_http_get_rust_backend/Cargo.toml` file in a text editor and replace the content with:
-
-```bash title="src/send_http_get_rust_backend/Cargo.toml"
-[package]
-name = "send_http_get_rust_backend"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[lib]
-crate-type = ["cdylib"]
+To use HTTPS outcalls you must update the canister's Candid file:
-[dependencies]
-candid = "0.10"
-ic-cdk = "0.13"
+```candid file=../../../../references/samples/rust/send_http_get/src/send_http_get_backend/send_http_get_backend.did
```
-
-
-
+Update the `Cargo.toml` file to use the correct dependencies:
-- #### Step 4: Test the dapp locally.
-
-
-
-
-Deploy the dapp locally:
-
-```bash
-dfx start --clean --background
-dfx deploy
+```toml file=../../../../references/samples/rust/send_http_get/src/send_http_get_backend/Cargo.toml
```
-If successful, the terminal should return canister URLs you can open:
-
-```bash
-Deployed canisters.
-URLs:
- Frontend canister via browser
- send_http_get_motoko_frontend: http://127.0.0.1:4943/?canisterId=asrmz-lmaaa-aaaaa-qaaeq-cai
- Backend canister via Candid interface:
- send_http_get_motoko_backend: http://127.0.0.1:4943/?canisterId=a3shf-5eaaa-aaaaa-qaafa-cai&id=avqkn-guaaa-aaaaa-qaaea-cai
-```
-
-Open the Candid web UI for the backend (the `send_http_get_motoko_backend` one) and call the `get_icp_usd_exchange()` method:
-
-![Candid web UI](../_attachments/https-get.webp)
-
-
-
-
-Test the dapp locally.
-
-Deploy the dapp locally:
-
-```bash
-dfx start --clean --background
-dfx deploy
-```
-
-If successful, the terminal should return canister URLs you can open:
-
-```bash
-Deployed canisters.
-URLs:
- Frontend canister via browser
- send_http_get_rust_frontend: http://127.0.0.1:4943/?canisterId=ajuq4-ruaaa-aaaaa-qaaga-cai
- Backend canister via Candid interface:
- send_http_get_rust_backend: http://127.0.0.1:4943/?canisterId=aovwi-4maaa-aaaaa-qaagq-cai&id=a4tbr-q4aaa-aaaaa-qaafq-cai
-```
-
-Open the Candid web UI for the backend (the `send_http_get_rust_backend` one) and call the `get_icp_usd_exchange()` method:
-
-![Candid web UI](../_attachments/https-get-candid-3-rust.webp)
-
+:::caution
-- #### Step 5: Test the dapp on mainnet.
-
-
-
-
-Deploy the dapp locally:
-
-```bash
-dfx deploy --network ic
-```
-
-If successful, the terminal should return canister URLs you can open:
-
-```bash
-Committing batch.
-Deployed canisters.
-URLs:
- Frontend canister via browser
- send_http_get_motoko_frontend: https://ff5va-7qaaa-aaaap-qbona-cai.icp0.io/
- Backend canister via Candid interface:
- send_http_get_motoko_backend: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai
-```
-
-
-
-
-Deploy the dapp to mainnet:
-
-```bash
-dfx deploy --network ic
-```
+Headers in the response may not always be identical across all nodes that process the request for consensus, causing the result of the call to be "No consensus could be reached." This particular error message can be hard to debug, but one method to resolve this error is to edit the response using the transform function. The transform function is run before consensus, and can be used to remove some headers from the response.
-If successful, the terminal should return canister URLs you can open:
+:::
-```bash
-Committing batch.
-Deployed canisters.
-URLs:
- Frontend canister via browser
- send_http_get_rust_frontend: https://ff5va-7qaaa-aaaap-qbona-cai.icp0.io/
- Backend canister via Candid interface:
- send_http_get_rust_backend: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai
-```
-You can see play with the dapp's `get_icp_usd_exchange` method onchain here: [https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai](https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai).
+You can see a deployed version of this canister and its `get_icp_usd_exchange` method onchain here: [https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai](https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai).
-
-
## Additional resources
diff --git a/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use.mdx b/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use.mdx
index 438a28dc85..62288f1a15 100644
--- a/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use.mdx
+++ b/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use.mdx
@@ -41,15 +41,7 @@ The following parameters should be supplied within the request:
- `body`: Optional; The content of the request's body.
-- `transform`: An optional function that transforms raw responses to [sanitized responses](https://en.wikipedia.org/wiki/HTML_sanitization), and a byte-encoded context that is provided to the function upon invocation, along with the response to be sanitized. If provided, the calling canister itself must export this function. An example written in Rust is shown below:
-
-```rust
-async fn transform(raw: CanisterHttpResponsePayload) -> CanisterHttpResponsePayload {
- let mut sanitized = raw.clone();
- sanitized.headers = vec![];
- sanitized
-}
-```
+- `transform`: An optional function that transforms raw responses to [sanitized responses](https://en.wikipedia.org/wiki/HTML_sanitization), and a byte-encoded context that is provided to the function upon invocation, along with the response to be sanitized. If provided, the calling canister itself must export this function.
### The response
diff --git a/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-post.mdx b/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-post.mdx
index e750ab4f23..59371eb8f4 100644
--- a/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-post.mdx
+++ b/docs/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-post.mdx
@@ -14,35 +14,12 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
## Overview
-A minimal example of how to make a `POST` HTTP request. The purpose of this dapp is only to show how to make HTTP requests from a canister.
-
-The sample code is in both Motoko and Rust. This sample canister sends a `POST` request with some JSON to a free API where you can verify the headers and body were sent correctly.
-
-**The main intent of this canister is to show developers how to make idempotent `POST` requests.**
-
-This example takes less than 5 minutes to complete.
+A minimal example of how to make a `POST` HTTP request. The purpose of this dapp is only to show how to make HTTP requests from a canister. It sends a `POST` request with some JSON to a free API where you can verify the headers and body were sent correctly.
:::caution
-The HTTPS outcalls feature only works for sending HTTP POST requests to servers or API endpoints that support **IPV6**.
+The HTTPS outcalls feature only works for sending HTTP `POST` requests to servers or API endpoints that support **IPV6**.
:::
-### Candid web UI of canister
-
-The canister in this tutorial will have only **one public method** which, when called, will trigger an HTTP `POST` request. The canister will not have a frontend (only a backend), but like all canisters, you can interact with its public methods via the Candid web UI, which will look like this:
-
-![Candid web UI](../_attachments/https-post-candid-2-motoko.webp)
-
-When you call the method, the canister will send an HTTP `POST` request with the following JSON in the response body:
-
-```json
-{
- "name": "Grogu",
- "force_sensitive": "true"
-}
-```
-
-### Verifying the HTTP POST request
-
In order to verify that your canister sent the HTTP request you expected, this canister is sending HTTP requests to a [public API service](https://putsreq.com/aL1QS5IbaQd4NTqN3a81/inspect) where the HTTP request can be inspected. As you can see the image below, the `POST` request headers and body can be inspected to make sure it is what the canister sent.
![Public API to inspect POST request](../../_attachments/https-post-requestbin-result.webp)
@@ -55,696 +32,42 @@ The recommended way for HTTP `POST` requests is to add the idempotency keys in t
Developers should be careful that the destination server understands and uses idempotency keys. A canister can be coded to send idempotency keys, but it is ultimately up to the recipient server to know what to do with them. Here is an [example of an API service that uses idempotency keys](https://stripe.com/docs/api/idempotent_requests).
-## Code structure
-
-Before you dive in, here is the structure of the code you will touch:
+## `POST` example
-```motoko no-repl
-
-//Import some custom types from `src/backend_canister/Types.mo` file
-import Types "Types";
-
-actor {
-
-//method that uses the HTTPS outcalls feature and returns a string
- public func foo() : async Text {
-
- //1. DECLARE MANAGEMENT CANISTER
- let ic : Types.IC = actor ("aaaaa-aa");
-
- //2. SETUP ARGUMENTS FOR HTTP GET request
- let request : Types.HttpRequestArgs = {
- //construct the request
- };
-
- //3. ADD CYCLES TO PAY FOR HTTP REQUEST
- //code to add cycles
-
- //4. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
- let response : Types.HttpResponsePayload = await ic.http_request(request);
-
- //5. DECODE THE RESPONSE
- //code to decode response
-
- //6. RETURN RESPONSE OF THE BODY
- response
- };
-};
-```
-
-You will also create some custom types in `Types.mo`. This will look like this:
-
-```motoko no-repl
-module Types {
-
- //type declarations for HTTP requests, HTTP responses, management canister, etc...
-
-}
+```motoko no-repl file=../../../../references/samples/motoko/send_http_post/src/send_http_post_backend/main.mo
```
-```rust
-//1. DECLARE MANAGEMENT CANISTER
-use ic_cdk::api::management_canister::http_request::{
- http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod, HttpResponse, TransformArgs,
- TransformContext,
-};
-
-//Update method using the HTTPS outcalls feature
-#[ic_cdk::update]
-async fn foo() {
- //2. SETUP ARGUMENTS FOR HTTP GET request
- let request = CanisterHttpRequestArgument {
- //instantiate the request
- };
-
- //3. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
- //Note: in Rust, `http_request()` already sends the cycles needed
- //so no need for explicit Cycles.add() as in Motoko
- match http_request(request).await {
-
- //4. DECODE AND RETURN THE RESPONSE
- Ok((response,)) => {
- //Ok case
- }
- Err((r, m)) => {
- //error case
- }
- }
-}
+```rust file=../../../../references/samples/rust/send_http_post/src/send_http_post_backend/src/lib.rs
```
-
-
-
-- #### Step 1: Create a new project by running the following command:
+To use HTTPS outcalls you must update the canister's Candid file:
-
-
-
-```bash
-dfx new send_http_post_motoko
-cd send_http_post_motoko
-npm install
+```candid file=../../../../references/samples/rust/send_http_post/src/send_http_post_backend/send_http_post_backend.did
```
-
-
+Update the `Cargo.toml` file to use the correct dependencies:
-```bash
-dfx new send_http_post_rust --type=rust
-cd send_http_post_rust
-npm install
-rustup target add wasm32-unknown-unknown
+```toml file=../../../../references/samples/rust/send_http_post/src/send_http_post_backend/Cargo.toml
```
+:::caution
+Headers in the response may not always be identical across all nodes that process the request for consensus, causing the result of the call to be "No consensus could be reached." This particular error message can be hard to debug, but one method to resolve this error is to edit the response using the transform function. The transform function is run before consensus, and can be used to remove some headers from the response.
-- #### Step 2: Edit the backend canister's code.
-
-
-
-
-Open the `src/send_http_post_motoko_backend/main.mo` file in a text editor and replace content with:
-
-```motoko no-repl title="src/send_http_post_motoko_backend/main.mo"
-import Debug "mo:base/Debug";
-import Blob "mo:base/Blob";
-import Cycles "mo:base/ExperimentalCycles";
-import Array "mo:base/Array";
-import Nat8 "mo:base/Nat8";
-import Text "mo:base/Text";
-
-//import the custom types you have in Types.mo
-import Types "Types";
-
-actor {
-
- //function to transform the response
- public query func transform(raw : Types.TransformArgs) : async Types.CanisterHttpResponsePayload {
- let transformed : Types.CanisterHttpResponsePayload = {
- status = raw.response.status;
- body = raw.response.body;
- headers = [
- {
- name = "Content-Security-Policy";
- value = "default-src 'self'";
- },
- { name = "Referrer-Policy"; value = "strict-origin" },
- { name = "Permissions-Policy"; value = "geolocation=(self)" },
- {
- name = "Strict-Transport-Security";
- value = "max-age=63072000";
- },
- { name = "X-Frame-Options"; value = "DENY" },
- { name = "X-Content-Type-Options"; value = "nosniff" },
- ];
- };
- transformed;
- };
-
-//PUBLIC METHOD
-//This method sends a POST request to a URL with a free API you can test.
- public func send_http_post_request() : async Text {
-
- //1. DECLARE MANAGEMENT CANISTER
- //You need this so you can use it to make the HTTP request
- let ic : Types.IC = actor ("aaaaa-aa");
-
- //2. SETUP ARGUMENTS FOR HTTP GET request
-
- // 2.1 Setup the URL and its query parameters
- //This URL is used because it allows you to inspect the HTTP request sent from the canister
- let host : Text = "putsreq.com";
- let url = "https://putsreq.com/aL1QS5IbaQd4NTqN3a81"; //HTTPS that accepts IPV6
-
- // 2.2 Prepare headers for the system http_request call
-
- //idempotency keys should be unique so create a function that generates them.
- let idempotency_key: Text = generateUUID();
- let request_headers = [
- { name = "Host"; value = host # ":443" },
- { name = "User-Agent"; value = "http_post_sample" },
- { name= "Content-Type"; value = "application/json" },
- { name= "Idempotency-Key"; value = idempotency_key }
- ];
-
- // The request body is an array of [Nat8] (see Types.mo) so do the following:
- // 1. Write a JSON string
- // 2. Convert ?Text optional into a Blob, which is an intermediate representation before you cast it as an array of [Nat8]
- // 3. Convert the Blob into an array [Nat8]
- let request_body_json: Text = "{ \"name\" : \"Grogu\", \"force_sensitive\" : \"true\" }";
- let request_body_as_Blob: Blob = Text.encodeUtf8(request_body_json);
- let request_body_as_nat8: [Nat8] = Blob.toArray(request_body_as_Blob); // e.g [34, 34,12, 0]
-
-
- // 2.2.1 Transform context
- let transform_context : Types.TransformContext = {
- function = transform;
- context = Blob.fromArray([]);
- };
-
- // 2.3 The HTTP request
- let http_request : Types.HttpRequestArgs = {
- url = url;
- max_response_bytes = null; //optional for request
- headers = request_headers;
- //note: type of `body` is ?[Nat8] so it is passed here as "?request_body_as_nat8" instead of "request_body_as_nat8"
- body = ?request_body_as_nat8;
- method = #post;
- transform = ?transform_context;
- // transform = null; //optional for request
- };
-
- //3. ADD CYCLES TO PAY FOR HTTP REQUEST
-
- //The management canister will make the HTTP request so it needs cycles
- //See: /docs/current/motoko/main/canister-maintenance/cycles
-
- //The way Cycles.add() works is that it adds those cycles to the next asynchronous call
- //See: /docs/current/references/ic-interface-spec#ic-http_request
- Cycles.add(21_850_258_000);
-
- //4. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
- //Since the cycles were added above, you can just call the management canister with HTTPS outcalls below
- let http_response : Types.HttpResponsePayload = await ic.http_request(http_request);
-
- //5. DECODE THE RESPONSE
-
- //As per the type declarations in `Types.mo`, the BODY in the HTTP response
- //comes back as [Nat8s] (e.g. [2, 5, 12, 11, 23]). Type signature:
-
- //public type HttpResponsePayload = {
- // status : Nat;
- // headers : [HttpHeader];
- // body : [Nat8];
- // };
-
- // You need to decode that [Na8] array that is the body into readable text.
- //To do this:
- // 1. Convert the [Nat8] into a Blob
- // 2. Use Blob.decodeUtf8() method to convert the Blob to a ?Text optional
- // 3. Use Motoko syntax "Let... else" to unwrap what is returned from Text.decodeUtf8()
- let response_body: Blob = Blob.fromArray(http_response.body);
- let decoded_text: Text = switch (Text.decodeUtf8(response_body)) {
- case (null) { "No value returned" };
- case (?y) { y };
- };
-
- //6. RETURN RESPONSE OF THE BODY
- let result: Text = decoded_text # ". See more info of the request sent at at: " # url # "/inspect";
- result
- };
-
- //PRIVATE HELPER FUNCTION
- //Helper method that generates a Universally Unique Identifier
- //this method is used for the Idempotency Key used in the request headers of the POST request.
- //For the purposes of this exercise, it returns a constant, but in practice, it should return unique identifiers
- func generateUUID() : Text {
- "UUID-123456789";
- }
-};
-```
-
-
-
-
-Open the `src/send_http_post_rust_backend/src/lib.rs` file in a text editor and replace the content with:
-
-```rust title="src/send_http_post_rust_backend/src/lib.rs"
-//1. IMPORT MANAGEMENT CANISTER
-//This includes all methods and types needed
-use ic_cdk::api::management_canister::http_request::{
- http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod, HttpResponse, TransformArgs,
- TransformContext,
-};
-
-use serde::{Serialize, Deserialize};
-use serde_json::{self, Value};
-
-// This struct is legacy code and is not really used in the code.
-#[derive(Serialize, Deserialize)]
-struct Context {
- bucket_start_time_index: usize,
- closing_price_index: usize,
-}
-
-//Update method using the HTTPS outcalls feature
-#[ic_cdk::update]
-async fn send_http_post_request() -> String {
- //2. SETUP ARGUMENTS FOR HTTP GET request
-
- // 2.1 Setup the URL
- let host = "putsreq.com";
- let url = "https://putsreq.com/aL1QS5IbaQd4NTqN3a81";
-
- // 2.2 Prepare headers for the system http_request call
- //Note that `HttpHeader` is declared in line 4
- let request_headers = vec![
- HttpHeader {
- name: "Host".to_string(),
- value: format!("{host}:443"),
- },
- HttpHeader {
- name: "User-Agent".to_string(),
- value: "demo_HTTP_POST_canister".to_string(),
- },
- //For the purposes of this exercise, Idempotency-Key" is hard coded, but in practice
- //it should be generated via code and unique to each POST request. Common to create helper methods for this
- HttpHeader {
- name: "Idempotency-Key".to_string(),
- value: "UUID-123456789".to_string(),
- },
- HttpHeader {
- name: "Content-Type".to_string(),
- value: "application/json".to_string(),
- },
- ];
-
- //note "CanisterHttpRequestArgument" and "HttpMethod" are declared in line 4.
- //CanisterHttpRequestArgument has the following types:
-
- // pub struct CanisterHttpRequestArgument {
- // pub url: String,
- // pub max_response_bytes: Option,
- // pub method: HttpMethod,
- // pub headers: Vec,
- // pub body: Option>,
- // pub transform: Option,
- // }
- //see: https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/struct.CanisterHttpRequestArgument.html
-
- //Where "HttpMethod" has structure:
- // pub enum HttpMethod {
- // GET,
- // POST,
- // HEAD,
- // }
- //See: https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/enum.HttpMethod.html
-
- //Since the body in HTTP request has type Option> it needs to look something like this: Some(vec![104, 101, 108, 108, 111]) ("hello" in ASCII)
- //where the vector of u8s are the UTF. In order to send JSON via POST, do the following:
- //1. Declare a JSON string to send
- //2. Convert that JSON string to array of UTF8 (u8)
- //3. Wrap that array in an optional
- let json_string : String = "{ \"name\" : \"Grogu\", \"force_sensitive\" : \"true\" }".to_string();
-
- //note: here, r#""# is used for raw strings in Rust, which allows you to include characters like " and \ without needing to escape them.
- //You could have used "serde_json" as well.
- let json_utf8: Vec = json_string.into_bytes();
- let request_body: Option> = Some(json_utf8);
-
- // This struct is legacy code and is not really used in the code. Need to be removed in the future
- // The "TransformContext" function does need a CONTEXT parameter, but this implementation is not necessary
- // the TransformContext(transform, context) below accepts this "context", but it does nothing with it in this implementation.
- // bucket_start_time_index and closing_price_index are meaningless
- let context = Context {
- bucket_start_time_index: 0,
- closing_price_index: 4,
- };
-
- let request = CanisterHttpRequestArgument {
- url: url.to_string(),
- max_response_bytes: None, //optional for request
- method: HttpMethod::POST,
- headers: request_headers,
- body: request_body,
- transform: Some(TransformContext::new(transform, serde_json::to_vec(&context).unwrap())),
- };
-
- //3. MAKE HTTP REQUEST AND WAIT FOR RESPONSE
-
- //Note: in Rust, `http_request()` already sends the cycles needed
- //so no need for explicit Cycles.add() as in Motoko
- match http_request(request).await {
- //4. DECODE AND RETURN THE RESPONSE
-
- //See:https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/struct.HttpResponse.html
- Ok((response,)) => {
- //if successful, `HttpResponse` has this structure:
- // pub struct HttpResponse {
- // pub status: Nat,
- // pub headers: Vec,
- // pub body: Vec,
- // }
-
- //You need to decode that Vec that is the body into readable text.
- //To do this:
- // 1. Call `String::from_utf8()` on response.body
- // 3. Use a switch to explicitly call out both cases of decoding the Blob into ?Text
- let str_body = String::from_utf8(response.body)
- .expect("Transformed response is not UTF-8 encoded.");
- ic_cdk::api::print(format!("{:?}", str_body));
-
- //The API response will looks like this:
- // { successful: true }
-
- //Return the body as a string and end the method
- let result: String = format!(
- "{}. See more info of the request sent at: {}/inspect",
- str_body, url
- );
- result
- }
- Err((r, m)) => {
- let message =
- format!("The http_request resulted into error. RejectionCode: {r:?}, Error: {m}");
-
- //Return the error as a string and end the method
- message
- }
- }
-
-}
-
-// Strips all data that is not needed from the original response.
-#[ic_cdk::query]
-fn transform(raw: TransformArgs) -> HttpResponse {
-
- let headers = vec![
- HttpHeader {
- name: "Content-Security-Policy".to_string(),
- value: "default-src 'self'".to_string(),
- },
- HttpHeader {
- name: "Referrer-Policy".to_string(),
- value: "strict-origin".to_string(),
- },
- HttpHeader {
- name: "Permissions-Policy".to_string(),
- value: "geolocation=(self)".to_string(),
- },
- HttpHeader {
- name: "Strict-Transport-Security".to_string(),
- value: "max-age=63072000".to_string(),
- },
- HttpHeader {
- name: "X-Frame-Options".to_string(),
- value: "DENY".to_string(),
- },
- HttpHeader {
- name: "X-Content-Type-Options".to_string(),
- value: "nosniff".to_string(),
- },
- ];
-
-
- let mut res = HttpResponse {
- status: raw.response.status.clone(),
- body: raw.response.body.clone(),
- headers,
- ..Default::default()
- };
-
- if res.status == 200 {
-
- res.body = raw.response.body;
- } else {
- ic_cdk::api::print(format!("Received an error from coinbase: err = {:?}", raw));
- }
- res
-}
-```
-
-- `send_http_post_request() -> String` returns a `String`, but this is not necessary. In this tutorial, this is done for easier testing.
-- The `lib.rs` file used [http_request](https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/fn.http_request.html) which is a convenient Rust CDK method that already sends cycles to the management canister under the hood. It knows how many cycles to send for a 13-node subnet and most cases. If your HTTPS outcall needs more cycles, you should use [http_request_with_cycles()](https://docs.rs/ic-cdk/latest/ic_cdk/api/management_canister/http_request/fn.http_request_with_cycles.html) method and explicitly call the cycles needed.
-- The Rust CDK method `http_request` used above wraps the management canister method [`http_request`](/docs/current/references/ic-interface-spec#ic-http_request), but it is not strictly the same.
-
-
-
-
-
-
-- #### Step 3: Edit the Type or Candid files.
-
-
-
-
-Create the `src/send_http_post_motoko_backend/Types.mo` file in a text editor and replace content with:
-
-```motoko no-repl title="src/send_http_post_motoko_backend/Types.mo"
-module Types {
-
- //1. Type that describes the Request arguments for an HTTPS outcall
- //See: /docs/current/references/ic-interface-spec#ic-http_request
- public type HttpRequestArgs = {
- url : Text;
- max_response_bytes : ?Nat64;
- headers : [HttpHeader];
- body : ?[Nat8];
- method : HttpMethod;
- transform : ?TransformRawResponseFunction;
- };
-
- public type HttpHeader = {
- name : Text;
- value : Text;
- };
-
- public type HttpMethod = {
- #get;
- #post;
- #head;
- };
-
- public type HttpResponsePayload = {
- status : Nat;
- headers : [HttpHeader];
- body : [Nat8];
- };
-
- //2. HTTPS outcalls have an optional "transform" key. These two types help describe it.
- //"The transform function may, for example, transform the body in any way, add or remove headers,
- //modify headers, etc. "
- //See: /docs/current/references/ic-interface-spec#ic-http_request
-
- //2.1 This type describes a function called "TransformRawResponse" used in line 14 above
- //"If provided, the calling canister itself must export this function."
- //In this minimal example for a GET request, declare the type for completeness, but
- //you do not use this function. You will pass "null" to the HTTP request.
- public type TransformRawResponseFunction = {
- function : shared query TransformArgs -> async HttpResponsePayload;
- context : Blob;
- };
-
- //2.2 This type describes the arguments the transform function needs
- public type TransformArgs = {
- response : HttpResponsePayload;
- context : Blob;
- };
-
- public type CanisterHttpResponsePayload = {
- status : Nat;
- headers : [HttpHeader];
- body : [Nat8];
- };
-
- public type TransformContext = {
- function : shared query TransformArgs -> async HttpResponsePayload;
- context : Blob;
- };
-
-
- //3. Declaring the management canister which is used to make the HTTPS outcall
- public type IC = actor {
- http_request : HttpRequestArgs -> async HttpResponsePayload;
- };
-
-}
-
-```
-
-
-
-
-Open the `src/hello_http_rust_backend/hello_http_rust_backend.did` file in a text editor and replace content with:
-
-Update the Candid interface file so it matches the method `send_http_post_request()` in `lib.rs`.
-
-```candid title="src/hello_http_rust_backend/hello_http_rust_backend.did"
-service : {
- "send_http_post_request": () -> (text);
-}
-```
-
-Open the `src/send_http_post_rust_backend/Cargo.toml` file in a text editor and replace content with:
-
-```bash title="src/send_http_post_rust_backend/Cargo.toml"
-[package]
-name = "send_http_post_rust_backend"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[lib]
-crate-type = ["cdylib"]
-
-[dependencies]
-candid = "0.10"
-ic-cdk = "0.13"
-serde = "1.0.152"
-serde_json = "1.0.93"
-serde_bytes = "0.11.9"
-
-```
-
-
-
-
-
-
-- #### Step 4: Test the dapp locally.
-
-
-
-
-Deploy the dapp locally:
-
-```bash
-dfx start --clean --background
-dfx deploy
-```
-
-If successful, the terminal should return canister URLs you can open:
-
-```bash
-Deployed canisters.
-URLs:
- Backend canister via Candid interface:
- send_http_post_motoko_backend: http://127.0.0.1:4943/?canisterId=dccg7-xmaaa-aaaaa-qaamq-cai&id=dfdal-2uaaa-aaaaa-qaama-cai
-```
-
-Open the candid web UI for the backend and call the `send_http_post_motoko_request()` method:
-
-![Candid web UI](../_attachments/https-post-candid-2-motoko.webp)
-
-
-
-
-Deploy the dapp locally:
-
-```bash
-dfx start --clean --background
-dfx deploy
-```
-
-If successful, the terminal should return canister URLs you can open:
-
-```bash
-Deployed canisters.
-URLs:
- Backend canister via Candid interface:
- send_http_post_rust_backend: http://127.0.0.1:4943/?canisterId=dxfxs-weaaa-aaaaa-qaapa-cai&id=dzh22-nuaaa-aaaaa-qaaoa-cai
-```
-
-Open the candid web UI for backend and call the `send_http_post_request()` method:
-
-![Candid web UI](../_attachments/https-post-candid-2-motoko.webp)
-
-
-
-
-- #### Step 5: Test the dapp on mainnet.
-
-
-
-
-Deploy the dapp to mainnet:
-
-```bash
-dfx deploy --network ic
-```
-
-If successful, the terminal should return canister URLs you can open:
-
-```bash
-Committing batch.
-Deployed canisters.
-URLs:
- Frontend canister via browser
- send_http_post_motoko_frontend: https://fx3cz-taaaa-aaaap-qbooa-cai.icp0.io/
- Backend canister via Candid interface:
- send_http_post_motoko_backend: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fc4tu-siaaa-aaaap-qbonq-cai
-```
-
-You can see play with the dapp's `send_http_post_request` method onchain here: [https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fc4tu-siaaa-aaaap-qbonq-cai](https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fc4tu-siaaa-aaaap-qbonq-cai).
-
-
-
-
-Deploy the dapp to mainnet:
-
-```bash
-dfx deploy --network ic
-```
-
-If successful, the terminal should return canister URLs you can open:
-
-```bash
-Committing batch.
-Deployed canisters.
-URLs:
- Frontend canister via browser
- send_http_post_rust_frontend: https://f6yjf-fiaaa-aaaap-qbopq-cai.icp0.io/
- Backend canister via Candid interface:
- send_http_post_rust_backend: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fzzpr-iqaaa-aaaap-qbopa-cai
-```
-
-You can see play with the dapp's `send_http_post_request` method onchain here: [https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai](https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai).
+:::
-
-
+You can see a deployed version of this canister's `send_http_post_request` method onchain here: [https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai](https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.icp0.io/?id=fm664-jyaaa-aaaap-qbomq-cai).
## Additional resources
diff --git a/docs/developer-docs/smart-contracts/advanced-features/serving-http-request.mdx b/docs/developer-docs/smart-contracts/advanced-features/serving-http-request.mdx
deleted file mode 100644
index 51824af6f9..0000000000
--- a/docs/developer-docs/smart-contracts/advanced-features/serving-http-request.mdx
+++ /dev/null
@@ -1,272 +0,0 @@
----
-keywords: [advanced, tutorial, serving http, http requests]
----
-
-import TabItem from "@theme/TabItem";
-import { AdornedTabs } from "/src/components/Tabs/AdornedTabs";
-import { AdornedTab } from "/src/components/Tabs/AdornedTab";
-import { BetaChip } from "/src/components/Chip/BetaChip";
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Serving an HTTP request
-
-
-
-## Overview
-
-Canisters can serve or handle an incoming HTTP request using the
-[HTTP Gateway Protocol](/docs/current/references/http-gateway-protocol-spec).
-
-This allows developers to host web applications and APIs from a canister.
-
-## How it works
-
-An HTTP request from a client gets intercepted by the HTTP Gateway Protocol,
-which identifies the target canister and encodes the request in Candid. This
-encoded request is then sent to the canister for processing. Once processed, the
-canister replies with an HTTP response. Finally, the HTTP Gateway Protocol
-decodes the response using Candid and sends it back to the client, completing
-the communication loop.
-
-For detailed information on how it works, please refer to the
-[HTTP Gateway Protocol specification](/docs/current/references/http-gateway-protocol-spec).
-
-## How to make a request
-
-The following example returns 'Hello, World!' in the body at the `/hello`
-endpoint.
-
-
-
-
-```motoko
-import HashMap = "mo:base/HashMap";
-import Blob = "mo:base/Blob";
-import Text "mo:base/Text";
-import Option "mo:base/Option";
-
-actor {
-
- public type HttpRequest = {
- body: Blob;
- headers: [HeaderField];
- method: Text;
- url: Text;
- };
-
- public type ChunkId = Nat;
- public type SetAssetContentArguments = {
- chunk_ids: [ChunkId];
- content_encoding: Text;
- key: Key;
- sha256: ?Blob;
- };
- public type Path = Text;
- public type Key = Text;
-
- public type HttpResponse = {
- body: Blob;
- headers: [HeaderField];
- status_code: Nat16;
- };
-
- public type HeaderField = (Text, Text);
-
- private func removeQuery(str: Text): Text {
- return Option.unwrap(Text.split(str, #char '?').next());
- };
-
- public query func http_request(req: HttpRequest): async (HttpResponse) {
- let path = removeQuery(req.url);
- if(path == "/hello") {
- return {
- body = Text.encodeUtf8("root page :" # path);
- headers = [];
- status_code = 200;
- };
- };
-
- return {
- body = Text.encodeUtf8("404 Not found :" # path);
- headers = [];
- status_code = 404;
- };
- };
-}
-```
-
-
-
-
-
-```rust
-type HeaderField = (String, String);
-
-struct HttpResponse {
- status_code: u16,
- headers: Vec,
- body: Cow<'static, Bytes>,
-}
-
-struct HttpRequest {
- method: String,
- url: String,
- headers: Vec<(String, String)>,
- body: ByteBuf,
-}
-
-#[query]
-fn http_request(req: HttpRequest) -> HttpResponse {
- let path = req.url.path();
- if path == "/hello" {
- HttpResponse {
- status_code: 200,
- headers: Vec::new(),
- body: b"hello, world!".to_vec(),
- streaming_strategy: None,
- upgrade: None,
- }
- } else {
- HttpResponse {
- status_code: 404,
- headers: Vec::new(),
- body: b"404 Not found :".to_vec(),
- streaming_strategy: None,
- upgrade: None,
- }
- }
-}
-```
-
-
-
-}>
-
-```typescript
-import { IDL, query } from 'azle';
-
-type HeaderField = [string, string];
-const HeaderField = IDL.Tuple(IDL.Text, IDL.Text);
-
-type HttpResponse = {
- status_code: number;
- headers: HeaderField[];
- body: Uint8Array;
-};
-const HttpResponse = IDL.Record({
- status_code: IDL.Nat16,
- headers: IDL.Vec(HeaderField),
- body: IDL.Vec(IDL.Nat8)
-});
-
-type HttpRequest = {
- method: string;
- url: string;
- headers: HeaderField[];
- body: Uint8Array;
-};
-const HttpRequest = IDL.Record({
- method: IDL.Text,
- url: IDL.Text,
- headers: IDL.Vec(HeaderField),
- body: IDL.Vec(IDL.Nat8)
-});
-
-export default class {
- @query([HttpRequest], HttpResponse)
- getThing(req: HttpRequest): HttpResponse {
- const path = new URL(req.url).pathname;
- if (path === '/hello') {
- return {
- status_code: 200,
- headers: [],
- body: Buffer.from('hello, world!')
- };
- }
- return {
- body: new TextEncoder().encode('404 Not found :'),
- headers: [],
- status_code: 404
- };
- }
-}
-```
-
-
-
-}>
-
-```python
-from kybra import blob, Func, nat16, Opt, query, Query, Record, Tuple, Variant, Vec
-
-
-class HttpRequest(Record):
- method: str
- url: str
- headers: Vec["Header"]
- body: blob
-
-
-class HttpResponse(Record):
- status_code: nat16
- headers: Vec["Header"]
- body: blob
- streaming_strategy: Opt["StreamingStrategy"]
- upgrade: Opt[bool]
-
-
-Header = Tuple[str, str]
-
-
-class StreamingStrategy(Variant):
- Callback: "CallbackStrategy"
-
-
-class CallbackStrategy(Record):
- callback: "Callback"
- token: "Token"
-
-
-Callback = Func(Query[["Token"], "StreamingCallbackHttpResponse"])
-
-
-class StreamingCallbackHttpResponse(Record):
- body: blob
- token: Opt["Token"]
-
-
-class Token(Record):
- arbitrary_data: str
-
-
-@query
-def http_request(req: HttpRequest) -> HttpResponse:
- path = req.url.path
- if path == "/hello":
- return {
- "status_code": 200,
- "headers": [],
- "body": Buffer.from_text("hello, world!").encode("utf-8"),
- }
- else:
- return {
- "status_code": 404,
- "headers": [],
- "body": b"404 Not found :",
-}
-```
-
-To learn more about serving an HTTP request in Python, refer to
-[the Kybra book reference on incoming HTTP requests](https://demergent-labs.github.io/kybra/http.html).
-
-
-
-
-## Additional examples
-
-The
-[HTTP counter project](https://github.com/dfinity/examples/tree/master/motoko/http_counter)
-is an example in Motoko of a 'counter' application that uses the `http_request`
-method to read the current counter value or access some pre-stored data and the
-`http_request_update` method to increment the counter and retrieve the updated
-value.
diff --git a/docs/developer-docs/smart-contracts/best-practices/general.mdx b/docs/developer-docs/smart-contracts/best-practices/general.mdx
index 0ccb29ce34..0ad4374f35 100644
--- a/docs/developer-docs/smart-contracts/best-practices/general.mdx
+++ b/docs/developer-docs/smart-contracts/best-practices/general.mdx
@@ -18,7 +18,7 @@ This guide outlines essential development best practices for building on the Int
Ensure all canisters have sufficient cycles to sustain operations for several years initially. Given the cost-effectiveness of storage and computation on ICP compared to other platforms, this upfront investment is usually modest.
-Refer to [topping up cycles page](docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister) to learn how to top-up cycles effectively.
+Refer to [topping up cycles page](/docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister) to learn how to top-up cycles effectively.
Refer to the [cycles estimate](/docs/current/developer-docs/gas-cost) page to estimate cycle usage.
@@ -26,7 +26,7 @@ Refer to the [cycles estimate](/docs/current/developer-docs/gas-cost) page to es
ICP features a mechanism to prevent canisters from running out of cycles. Canisters have a configurable `freezing_threshold`, dynamically evaluated in cycles. Set `freezing_threshold` conservatively, ensuring at least 90 to 180 days' worth of cycles for proactive management.
-Refer to [this resource](docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister#managing-cycle-depletion-with-freezing-threshold) to learn how to configure the `freezing_threshold` of a canister.
+Refer to [this resource](/docs/current/developer-docs/smart-contracts/topping-up/topping-up-canister#managing-cycle-depletion-with-freezing-threshold) to learn how to configure the `freezing_threshold` of a canister.
To make sure you won’t get surprised by a high cycle burn rate or hitting an instruction limit, you can use the recently added [performance counter API](https://internetcomputer.org/blog/features/async-performance-counter) to profile your canisters even before going live.
diff --git a/docs/developer-docs/smart-contracts/best-practices/reproducible-builds.mdx b/docs/developer-docs/smart-contracts/best-practices/reproducible-builds.mdx
index 30f6fe250d..bce4af1759 100644
--- a/docs/developer-docs/smart-contracts/best-practices/reproducible-builds.mdx
+++ b/docs/developer-docs/smart-contracts/best-practices/reproducible-builds.mdx
@@ -26,7 +26,7 @@ However, build tools aren’t perfect, and may fail to ensure reproducible build
ICP does not allow you to access the Wasm module of an arbitrary canister. This is a design decision, as developers might want to keep some code private. However, ICP does allow anyone to access the SHA-256 of the Wasm module.
-To obtain this hash, you must first note the principal of the canister whose code you want to check. For example, to check the code of the Internet Identity canister, the principal is `rdmx6-jaaaa-aaaaa-aaadq-cai`. Then, the easiest way to access this data is using [`dfx`](docs/current/developer-docs/getting-started/install) from a command line using the following command:
+To obtain this hash, you must first note the principal of the canister whose code you want to check. For example, to check the code of the Internet Identity canister, the principal is `rdmx6-jaaaa-aaaaa-aaadq-cai`. Then, the easiest way to access this data is using [`dfx`](/docs/current/developer-docs/getting-started/install) from a command line using the following command:
```bash
dfx canister --network ic info rdmx6-jaaaa-aaaaa-aaadq-cai
diff --git a/docs/developer-docs/smart-contracts/best-practices/troubleshooting.mdx b/docs/developer-docs/smart-contracts/best-practices/troubleshooting.mdx
index f49b2967bc..123fa74c0d 100644
--- a/docs/developer-docs/smart-contracts/best-practices/troubleshooting.mdx
+++ b/docs/developer-docs/smart-contracts/best-practices/troubleshooting.mdx
@@ -22,15 +22,15 @@ On subnets with higher loads, your application may experience elevated latencies
### Recommendation: Consider moving the canister to another subnet.
-If your canister is running on a subnet that has a consistently high load and thus elevated latency, consider adding a [compute allocation](docs/current/developer-docs/gas-cost#execution-and-compute-allocation) setting. A compute allocation of 1% will guarantee your canister is scheduled for execution once every 100 rounds.
+If your canister is running on a subnet that has a consistently high load and thus elevated latency, consider adding a [compute allocation](/docs/current/developer-docs/gas-cost#execution-and-compute-allocation) setting. A compute allocation of 1% will guarantee your canister is scheduled for execution once every 100 rounds.
## Troubleshooting best practices
### Recommendation: Use query calls instead of update calls when possible.
-[Query calls](/docs/current/developer-docs/web-apps/design-dapps#using-query-calls) are executed on a single node within a subnet and do not go through consensus, therefore they can be returned much faster than an update call. For some applications, query calls can be used in place of update calls to reduce latency.
+[Query calls](/docs/current/developer-docs/smart-contracts/call/overview/#query-calls) are executed on a single node within a subnet and do not go through consensus, therefore they can be returned much faster than an update call. For some applications, query calls can be used in place of update calls to reduce latency.
-However, the security trade-offs of query calls must be considered. Since query calls do not go through consensus, it is not recommended that they are used for retrieving sensitive information that requires data assurance. For example, returning financial data on a decentralized exchange dapp should not use basic query calls, as it is important the call return data that has been validated through the subnet's consensus. As an alternative, [certified queries](/docs/current/developer-docs/web-apps/design-dapps#using-query-calls) may be used.
+However, the security trade-offs of query calls must be considered. Since query calls do not go through consensus, it is not recommended that they are used for retrieving sensitive information that requires data assurance. For example, returning financial data on a decentralized exchange dapp should not use basic query calls, as it is important the call return data that has been validated through the subnet's consensus. As an alternative, [certified queries](/docs/current/developer-docs/smart-contracts/call/overview/#query-calls) may be used.
### Recommendation: Use efficient query calls.
diff --git a/docs/developer-docs/smart-contracts/maintain/control.mdx b/docs/developer-docs/smart-contracts/maintain/control.mdx
index c146596dc9..49c8878b1c 100644
--- a/docs/developer-docs/smart-contracts/maintain/control.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/control.mdx
@@ -9,39 +9,19 @@ import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
# Control
-
+
## Overview
-A canister is managed by a list of controllers. A controller is specified by a principal, which can be self-authenticating, e.g. a `dfx` developer identity, or another canister. Canisters can have multiple controllers where each controller has the same administrative rights, or it has no controller, in which case the canister becomes immutable, or blackholed, and cannot be upgraded or deleted.
+A canister is managed by a list of controllers. A controller is specified by a principal, which can be self-authenticating, e.g. a `dfx` developer identity, or another canister. Canisters can have multiple controllers where each has the same administrative rights, or it can have no controller, in which case the canister becomes immutable (blackholed) and cannot be upgraded or deleted.
## Setting the controllers of a canister
-The controllers of a canister are set when the canister is created. If no explicit controller settings are specified, the default controller is the principal that created the canister. If the canister is created with `dfx` then the default controller list contains the current developer identity.
+When a canister is created, the default controller list contains the developer identity used to create the canister. Additional controllers can be specified during canister creation or they can be added in the future.
-## Update the controllers of a canister
+To specify a different controller upon canister creation, the [`dfx canister create --controller `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-create) command can be used.
-The controllers of a canister can be updated by any of the existing controllers. To update the controllers with `dfx`, the following commands can be used:
-
-### Add a controller
-
-```sh
-dfx canister update-settings CANISTER_NAME --add-controller CONTROLLER
-```
-
-### Remove a controller
-
-```sh
-dfx canister update-settings CANISTER_NAME --remove-controller CONTROLLER
-```
-
-### Set the controller
-
-The following command sets only the specified controller and removes all other controllers:
-
-```sh
-dfx canister update-settings CANISTER_NAME --set-controller CONTROLLER
-```
+To update a canister's controllers after the canister has been created, the [`dfx canister update-settings`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-update-settings) command can be used with the `--add-controller ` or `--remove-controller ` flag to add or remove controllers respectively.
## Actions available only to controllers
@@ -68,7 +48,7 @@ A canister that can be used for this purpose is the [Threshold canister](https:/
The [Launchtrail canister](https://github.com/spinner-cash/launchtrail) can be used to schedule the upgrade of a canister at a future time to give the public enough time to review the proposed changes. The canister also keeps a complete record of all actions and their execution results. The Launchtrail canister itself should be immutable without a controller.
-### Decentralized Autonomous Organization (DAO)
+### Decentralized autonomous organization (DAO)
A canister is controlled by a DAO, and all upgrades and administrative actions are decided by a vote of the DAO members. The most common DAO model for applications on the Internet Computer is the [Service Nervous System (SNS)](/docs/developer-docs/daos/sns/index.mdx).
diff --git a/docs/developer-docs/smart-contracts/maintain/delete.mdx b/docs/developer-docs/smart-contracts/maintain/delete.mdx
index 4f4b4b354c..72bb900183 100644
--- a/docs/developer-docs/smart-contracts/maintain/delete.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/delete.mdx
@@ -5,45 +5,15 @@ keywords: [beginner, tutorial, maintain canisters, delete canisters, delete]
import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
-
# Delete
-
+
## Overview
-If you want to permanently delete a specific canister or all canisters for a specific project on a given deployment (either local or remote), you can do so by running the command:
-
-```
-dfx canister delete // Delete local canister
-dfx canister delete --network ic // Delete canister on mainnet
-```
-
-Deleting a canister removes the canister identifier, code, and state. Before you can delete a canister, however, you must first stop the canister to clear any pending message requests or replies.
-
-## Delete all canisters
-
-To delete all canisters for a project:
-
-- #### Step 1: Open a new terminal and navigate to your project directory.
-
-- #### Step 2: Start the local canister execution environment, if necessary.
-
-In most cases, this step is only necessary if you are running the canisters locally.
-
-If you were deleting canisters to run on a remote execution environment, e.g. ICP blockchain, you would include the `--network` command-line option to perform tasks on the environment specified under this parameter.
-
-- #### Step 3: Check the status of the project canisters running on the local canister execution environment by running the following command:
-
-dfx canister status --all
-
-- #### Step 4: Stop all of the project canisters by running the following command:
-
-dfx canister stop --all
-
-- #### Step 5: Delete all of the project canisters by running the following command:
+If you want to permanently delete a specific canister or all canisters for a project, you can use the [`dfx canister delete `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-delete) command.
-dfx canister delete --all
+Deleting a canister permanently removes its code and state. This action cannot be undone and once the canister is deleted, its ID cannot be reused. Before you can delete a canister, you must first stop the canister using [`dfx canister stop `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-stop) to clear any pending message requests or replies.
## Errors related to canister deletion
diff --git a/docs/developer-docs/smart-contracts/maintain/history.mdx b/docs/developer-docs/smart-contracts/maintain/history.mdx
index 62e56f4c84..4d4aa075e7 100644
--- a/docs/developer-docs/smart-contracts/maintain/history.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/history.mdx
@@ -10,14 +10,13 @@ import { BetaChip } from "/src/components/Chip/BetaChip"
import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
-
# History
## Overview
-The Internet Computer tracks the history of a deployed canister through the canister's Wasm module hashes and controller changes. This tracking provides insight into the canister's history, such as what code has been used to run the canister, and which controller deployed that code.
+The Internet Computer tracks the history of a deployed canister through the canister's Wasm module hashes and controller changes. This tracking provides insight into the canister's history, such as what code has been used to run the canister and which controller deployed that code.
Viewing a canister's history can be important in use cases such as:
@@ -31,8 +30,8 @@ Canister history was introduced and released by the NNS DAO proposal [122617](ht
Canister history information is made available via inter-canister calls made to the `canister_info` method of the management canister, using a canister's ID as an argument for the call. A canister's history stores the 20 most recent changes to the canister, including the canister's creation, Wasm module installations, reinstallations, upgrades, and changes to the list of canister controllers. It is important to note that since only the 20 most recent changes are stored, this feature cannot be used for auditing canisters that are frequently changed within a short period of time.
-:::info
-Note that canister history is only available for changes that have happened since this feature was rolled out on 023-06-05, 9:47:46 AM UTC, across all subnets.
+:::danger
+Canister history is only available for changes that have happened since this feature was rolled out on 23-06-05, 9:47:46 AM UTC, across all subnets.
:::
You can read more about this feature on the [developer forum](https://forum.dfinity.org/t/canister-history-on-the-ic/21745).
@@ -45,74 +44,49 @@ To get a canister's history, make a call to the IC management canister's `canist
```motoko
-actor {
- let IC =
- actor "aaaaa-aa" : actor {
+import Principal "mo:base/Principal";
+
+actor Info {
+ type canister_info_args = {
+ canister_id : Principal;
+ num_requested_changes : ?Nat64
+ };
+
+ type canister_info_result = {
+ total_num_changes : Nat64;
+ module_hash : ?Blob;
+ controllers : [Principal]
+ };
- canister_info : { canister_id : Principal } ->
- async ();
+ let IC = actor "aaaaa-aa" : actor {
+ canister_info : {canister_id : Principal} -> async canister_info_result
+ };
- };
-};
+ public func getInfo() : async canister_info_result {
+ await IC.canister_info {canister_id = Principal.fromActor(Info)}
+ }
+
+}
```
-```rust
-use candid::{CandidType, Principal};
-use ic_cdk::api::management_canister::main::{
- canister_info, CanisterChange,
- CanisterChangeDetails::{CodeDeployment, CodeUninstall, ControllersChange, Creation},
- CanisterChangeOrigin::{FromCanister, FromUser},
- CanisterInfoRequest, CanisterInfoResponse,
-};
-use serde::Deserialize;
-
-/// Returns canister info with all available canister changes for a canister characterized by a given principal.
-/// Traps if the canister_info management call is rejected (in particular, if the principal does not characterize a canister).
-#[ic_cdk::update]
-async fn info(canister_id: Principal) -> CanisterInfoResponse {
- let request = CanisterInfoRequest {
- canister_id,
- num_requested_changes: Some(20),
- };
- canister_info(request).await.unwrap().0
-}
+```rust file=../../../references/samples/rust/canister-info/src/lib.rs
```
}>
-```typescript
-import { call, IDL, Principal, query, update } from 'azle';
-import {
- CanisterInfoArgs,
- CanisterInfoResult,
-} from 'azle/canisters/management';
-
-type State = {
- createdCanisterId: Principal;
-};
-
-let state: State = {
- createdCanisterId: Principal.fromText('aaaaa-aa')
-};
-
-export default class {
- @update([CanisterInfoArgs], CanisterInfoResult)
- async getCanisterInfo(args: CanisterInfoArgs): Promise {
- return await call('aaaaa-aa', 'canister_info', {
- paramIdlTypes: [CanisterInfoArgs],
- returnIdlType: CanisterInfoResult,
- args: [args]
- });
- }
-}
+[Learn more about Azle](https://demergent-labs.github.io/azle/get_started.html).
-```
+
+
+}>
+
+[Learn more about Kybra](https://demergent-labs.github.io/kybra/).
\ No newline at end of file
diff --git a/docs/developer-docs/smart-contracts/maintain/import.mdx b/docs/developer-docs/smart-contracts/maintain/import.mdx
index 910b8a36d9..4aac16cab1 100644
--- a/docs/developer-docs/smart-contracts/maintain/import.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/import.mdx
@@ -19,11 +19,11 @@ Third-party canisters include canisters created by DFINITY or by developers in I
- Using non-production data and environments.
- Faster completion time when run locally.
-To pull these canisters from the mainnet to be tested using a local replica, the [`dfx deps`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-deps) command and workflow can be used.
+To pull these canisters from the mainnet to be tested locally, the [`dfx deps`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-deps) command and workflow can be used.
In this workflow, a **service provider** configures a canister to be `pullable`, then deploys the canister to the mainnet. A service provider can be any community developer creating a public, third-party canister.
-Then a **service consumer** can pull the canister as a dependency directly from the mainnet and then deploy the dependency on a local replica.
+Then a **service consumer** can pull the canister as a dependency directly from the mainnet and then deploy the dependency locally.
## Determining if a canister should be `pullable`
@@ -39,39 +39,9 @@ If a service canister depends on other canisters, those dependencies should also
If the canister is meant for personal use and not intended for others, the canister should not be `pullable`.
-If a canister Wasm is published for other developers to use the canister should not be `pullable` since the canister ID of the instance is not static. Users can test integrations locally and deploy them directly. An example of this canister type is the asset canister generated by dfx.
+If a canister's Wasm is published for other developers to use, then the canister should not be `pullable` since the canister ID of the instance is not static. Users can test integrations locally and deploy them using the Wasm file directly.
-## `Pullable` dfx.json example
-
-For a canister to be `pullable`, the `dfx.json` file must include a `pullable` definition:
-
-```json
-{
- "canisters": {
- "service": {
- "type": "motoko",
- "main": "src/pullable/main.mo",
- "pullable": {
- "dependencies": [],
- "wasm_url": "https://github.com/lwshang/pullable/releases/latest/download/service.wasm",
- "init_guide": "A natural number, e.g. 1"
- }
- }
- }
-}
-```
-
-:::caution
-The Wasm module of a `pullable` canister must be hosted via a URL so that service consumers can download it.
-
-GitHub Releases are a good, free option if the project is open source on GitHub. The GitHub URL schema is:
-
-`https://github.com///releases/latest/download/`
-
-In a future version of this feature, direct Wasm downloads from the replica will likely be supported.
-:::
-
-## Service provider workflow overview
+## Service provider workflow
First, a service provider must configure a canister to be `pullable` by setting it as such in the `dfx.json` file.
An example of a provider `dfx.json` which has a `pullable` "service" canister can be found below:
@@ -95,39 +65,42 @@ An example of a provider `dfx.json` which has a `pullable` "service" canister ca
}
```
+:::danger
+The Wasm module of a `pullable` canister must be hosted via a public URL where service consumers can download it.
+
+GitHub Releases are a good, free option if the project is open source on GitHub. The GitHub URL schema is:
+
+`https://github.com///releases/latest/download/`
+
+:::
+
The `pullable` object will be serialized as a part of the `dfx` metadata and attached to the Wasm.
-To better understand the `pullable` object, let's look at each property in depth.
+To better understand the `pullable` object, let's look at each property in depth:
- `wasm_url`: A URL used to download the canister Wasm module which will be deployed locally.
-- `wasm_hash`: A SHA256 hash of the Wasm module located at `wasm_url`. This field is optional. In most cases, the Wasm module at `wasm_url` will be the same as the onchain Wasm module. This means that dfx can read the state tree to obtain and verify the module hash. In some cases, the Wasm module at `wasm_url` is not the same as the onchain Wasm module. For example, the Internet Identity canister provides a `development` variant to be integrated locally. In these cases, `wasm_hash` provides the expected hash, and `dfx` verifies the downloaded Wasm against this.
+- `wasm_hash`: A SHA256 hash of the Wasm module located at `wasm_url`. This field is optional. In most cases, the Wasm module at `wasm_url` will be the same as the onchain Wasm module. This means that `dfx` can read the state tree to obtain and verify the module hash. In some cases, the Wasm module at `wasm_url` is not the same as the onchain Wasm module. For example, the Internet Identity canister provides a `development` variant to be integrated locally. In these cases, `wasm_hash` provides the expected hash, and `dfx` verifies the downloaded Wasm against this.
:::caution
-If the `wasm_hash` of the Wasm module at `wasm_url` does not match, dfx will abort with an error message indicating that there is a hash mismatch. In this scenario, the service consumer should contact the service provider. It is the responsibility of the service provider to assure that the correct Wasm module can be downloaded from the `wasm_url`.
+If the `wasm_hash` of the Wasm module at `wasm_url` does not match, `dfx` will abort with an error message indicating that there is a hash mismatch. In this scenario, the service consumer should contact the service provider. It is the responsibility of the service provider to assure that the correct Wasm module can be downloaded from the `wasm_url`.
:::
-- `dependencies`: An array of Canister IDs (`Principal`) of direct dependencies.
+- `dependencies`: An array of canister IDs (`Principal`) of direct dependencies.
- `init_guide`: A message to guide consumers how to initialize the canister.
### Canister metadata requirements
-A service provider canister used in production or in a production environment running on the mainnet should have public `dfx` metadata.
-
-The canister Wasm downloaded from `wasm_url` should have the following metadata (public or private):
-
-- `candid:service`
-- `candid:args`
-- `dfx`
+A service provider canister used in production or in a production environment running on the mainnet should have public `dfx` metadata and public or private `candid:service` and `candid:args` metadata.
All metadata sections are handled by `dfx` when the canister is built.
### Deployment process
-Service providers will use the following deployment process to deploy their `pullable` canister.
+Service providers should use the following deployment process to deploy their `pullable` canister.
-- #### Step 1: Deploy the canister to the mainnet with the command:
+- #### Step 1: From within your project's repo, deploy the canister to the mainnet with the command:
```
-dfx deploy --network ic
+dfx deploy --network ic
```
- #### Step 2: If you're using GitHub, `git tag` and `GitHub release` with the commands:
@@ -140,9 +113,8 @@ git push --tags
You can follow [this guide](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release) to create a release.
- #### Step 3: Attach the Wasm to the release assets.
-Edit the release and attach the deployed Wasm as a release asset.
-The deployed Wasm file will be located at:
+Edit the release and attach the deployed Wasm as a release asset. The deployed Wasm file will be located at:
```
.dfx/ic/canisters//.wasm
@@ -158,15 +130,15 @@ The workflow with CI will follow these steps:
2. Download the canister Wasm from the release assets (`wget https://github.com/lwshang/pullable/releases/latest/download/service.wasm`).
3. Install (upgrade) the canister using the downloaded Wasm (`dfx canister --network ic install service --wasm service.wasm --argument '(1 : nat)' --mode upgrade`).
-## Service consumer workflow overview
+## Consumer workflow
-The following workflow can be used for service consumers to pull a `pullable` canister as a dependency.
+The following workflow can be used for consumers to pull a `pullable` canister as a dependency.
-### Step 1: Declare "pull" dependencies in `dfx.json`.
+- #### Step 1: Declare "pull" dependencies in `dfx.json`.
-First, to pull the dependencies from the mainnet, the `dfx.json` file must include the `dependencies` configuration for the canister.
+First, the `dfx.json` file must include the `dependencies` configuration for the canister.
-An example `dfx.json` in which the service consumer is developing a canister named "dapp", which has two pull dependencies, can be found below:
+An example `dfx.json` in which the consumer is developing a canister named "dapp" that has two pull dependencies can be found below:
- "dep_b" has canister ID of `yhgn4-myaaa-aaaaa-aabta-cai` on the mainnet.
- "dep_c" has canister ID of `yahli-baaaa-aaaaa-aabtq-cai` on the mainnet.
@@ -193,9 +165,13 @@ An example `dfx.json` in which the service consumer is developing a canister nam
}
```
-### Step 2: Pull the dependencies using the `dfx deps pull` command.
+- #### Step 2: Pull the dependencies using the `dfx deps pull` command.
+
+:::danger
+`dfx deps pull` connects to the mainnet by default (`--network ic`). You can choose other network as usual, e.g. `--network local`.
+:::
-Running the command `dfx deps pull` will do the following:
+Running this command will do the following:
1. First, it will resolve the dependency graph by fetching the `dependencies` field in the `dfx` metadata recursively.
2. Then, it will download the Wasm of all direct and indirect dependencies from `wasm_url` into the shared cache.
@@ -205,7 +181,7 @@ Running the command `dfx deps pull` will do the following:
6. The `candid:service` of direct dependencies is saved as `deps/candid/.did`.
7. The `deps/pulled.json` which contains major info of all direct and indirect dependencies is saved.
-For the example project, you will find following files in `deps/`:
+For the example project, you will find the following files in `deps/`:
- `yhgn4-myaaa-aaaaa-aabta-cai.did` and `yahli-baaaa-aaaaa-aabtq-cai.did`: Candid files that can be imported by "dapp".
- `pulled.json`: A json file with the following content:
@@ -245,13 +221,9 @@ In this file, you can see there are three dependencies:
- `yhgn4-myaaa-aaaaa-aabta-cai`: "dep_b" in `dfx.json`.
- `yahli-baaaa-aaaaa-aabtq-cai`: "dep_c" in `dfx.json`.
-- `yofga-2qaaa-aaaaa-aabsq-cai`: an indirect dependency that both "dep_b" and "dep_c" depend on.
+- `yofga-2qaaa-aaaaa-aabsq-cai`: An indirect dependency that both "dep_b" and "dep_c" depend on.
-:::caution
-`dfx deps pull` connects to the mainnet by default (`--network ic`). You can choose other network as usual, e.g. `--network local`.
-:::
-
-### Step 3: Set init arguments using `dfx deps init`
+- #### Step 3: Set init arguments using `dfx deps init`
Running the command `dfx deps init` will iterate over all dependencies in the `pulled.json` file and set an empty argument for any that do not need an `init` argument. Then, it will print the list of dependencies that do require an `init` argument.
@@ -263,27 +235,27 @@ Using the example above, you can run the following commands:
```
dfx deps init
+```
+
+
+Output
+
+```
WARN: The following canister(s) require an init argument. Please run `dfx deps init ` to set them individually:
yofga-2qaaa-aaaaa-aabsq-cai
yahli-baaaa-aaaaa-aabtq-cai (dep_c)
```
+
+
- If you try to set an `init` argument for an individual dependency without an argument, it will result in the following error:
```
-dfx deps init yofga-2qaaa-aaaaa-aabsq-cai
Error: Canister yofga-2qaaa-aaaaa-aabsq-cai requires an init argument. The following info might be helpful:
init_guide => A natural number, e.g. 10.
candid:args => (nat)
```
-```
-dfx deps init deps_c
-Error: Canister yahli-baaaa-aaaaa-aabtq-cai (dep_c) requires an init argument. The following info might be helpful:
-init_guide => A natural number, e.g. 20.
-candid:args => (nat)
-```
-
- To set an init argument with an argument using the `--argument` flag, the following commands can be used:
```
@@ -312,112 +284,35 @@ The resulting generated file `init.json` will have the following content:
}
```
-### Step 4: Deploy the pulled dependencies on a local replica using the `dfx deps deploy` command.
+- #### Step 4: Deploy the pulled dependencies on a local replica using the `dfx deps deploy` command.
Running the `dfx deps deploy` command will:
1. First, create the dependencies on the local replica with the same mainnet canister ID.
2. Then, it will install the downloaded Wasm with the init arguments in the `init.json` file.
-You can also specify the name or principal to deploy one particular dependency.
+You can also specify the canister name or principal to deploy one particular dependency.
Using the example above, you can run the following command to deploy all dependencies:
```
dfx deps deploy
+```
+
+
+Output
Creating canister: yofga-2qaaa-aaaaa-aabsq-cai
Installing canister: yofga-2qaaa-aaaaa-aabsq-cai
Creating canister: yhgn4-myaaa-aaaaa-aabta-cai (dep_b)
Installing canister: yhgn4-myaaa-aaaaa-aabta-cai (dep_b)
Creating canister: yahli-baaaa-aaaaa-aabtq-cai (dep_c)
Installing canister: yahli-baaaa-aaaaa-aabtq-cai (dep_c)
-```
-
-To deploy one particular dependency, the following command can be used:
-
-```
-dfx deps deploy yofga-2qaaa-aaaaa-aabsq-cai
-Installing canister: yofga-2qaaa-aaaaa-aabsq-cai
-```
-
-```
-dfx deps deploy dep_b
-Installing canister: yhgn4-myaaa-aaaaa-aabta-cai (dep_b)
-```
+
:::info
`dfx deps deploy` always creates the canister with the anonymous identity so that dependencies and application canisters will have different controllers. It will also always install the canister in "reinstall" mode so that the canister status will be discarded.
:::
-## Interactive example
-
-Now that you've explored the concepts and overview of using the `dfx deps` workflow, let's take a look at using an interactive example to demonstrate the functionality.
-
-This example project will demonstrate an application canister pulling its dependency from the mainnet and integrating with it locally.
-
-In this example, the `app` canister defines a method called `double_service` which makes an inter-canister call to the `service` canister.
-
-- #### Step 1: First, assure that you have installed the [IC SDK](https://github.com/dfinity/sdk).
-
-- #### Step 2: Then, open a terminal window and create a new dfx project with the command:
-
-```
-dfx new pull_deps_example
-```
-
-- #### Step 3: Then, open the project's `dfx.json` file in a text or code editor. Declare the pull dependency with the following configuration:
-
-```
-{
- "canisters": {
- "service": {
- "type": "pull",
- "id": "ig5e5-aqaaa-aaaan-qdxya-cai"
- }
- },
-}
-```
-
-Save the file.
-
-- #### Step 4: Use `dfx deps pull` to pull from the mainnet:
-
-```
-dfx deps pull
-Fetching dependencies of canister ig5e5-aqaaa-aaaan-qdxya-cai...
-Found 1 dependencies:
-ig5e5-aqaaa-aaaan-qdxya-cai
-Pulling canister ig5e5-aqaaa-aaaan-qdxya-cai...
-```
-
-- #### Step 5: Configure the `init` argument:
-
-```
-dfx deps init service --argument 1
-```
-
-- #### Step 6: Deploy on a local replica with the commands:
-
-```
-dfx start --clean --background
-dfx deps deploy
-dfx deploy app
-```
-
-- #### Step 7: Test the app by making the following call:
-
-```
-dfx canister call app double_service
-```
-
-In this step, the `app` canister's `double_service` method is being called, which sends an inter-canister call to the `service` canister. The call will succeed since both canisters are now deployed on the local replica.
-
-The output will resemble the following:
-
-```
-(2 : nat)
-```
-
## Frequently asked questions
- #### Why download the Wasm into shared cache instead of a project subfolder?
diff --git a/docs/developer-docs/smart-contracts/maintain/logs.mdx b/docs/developer-docs/smart-contracts/maintain/logs.mdx
index 5e99b5b927..6ed299224c 100644
--- a/docs/developer-docs/smart-contracts/maintain/logs.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/logs.mdx
@@ -23,7 +23,11 @@ The canister logging feature is designed to p
- Queries, only if called in replicated mode.
-A canister's controller is able to retrieve the canister's logs, even when executions trap, using `dfx canister logs`.
+A canister's controller is able to retrieve the canister's logs, even when executions trap, using [`dfx canister logs `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-logs):
+
+```
+dfx canister logs
+```
:::info
Non-replicated calls are not currently supported for logging.
@@ -31,94 +35,28 @@ Non-replicated calls are not currently supported for logging.
## Log visibility
-By default, a canister's logs are only visible to the controllers of the canister. A canister's logs can be made public with the `--log-visibility` flag:
+By default, a canister's logs are only visible to the controllers of the canister. A canister's logs can be made public by updating the canister's settings with [`dfx canister update-settings`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-update-settings) command:
-```
-dfx canister update-settings CANISTER_ID --log-visibility public
+```bash
+dfx canister update-settings --log-visibility public
```
### Log viewer allow lists
Canister log allow lists enable principals that are not controllers of the canister to view the logs without the logs being public. Log allow lists are supported in `dfx` versions `0.24.2` and newer.
-To add a principal to the canister's log allow list, update the canister's settings with the `--set-log-viewer` or `--add-log-viewer` flags:
+To specify principals in the canister's log allow list, update the canister's settings with the flags:
-```
-dfx canister update-settings CANISTER_ID --set-log-viewer PRINCIPAL_ID // Set a single principal as a log viewer
-dfx canister update-settings CANISTER_ID --add-log-viewer PRINCIPAL_ID // Add a principal to a list of log viewers
-```
+- `dfx canister update-settings --set-log-viewer `: Set a single principal as a log viewer.
-You can also configure a principal as a log viewer when you create a canister with:
+- `dfx canister update-settings --add-log-viewer `: Add a principal to a list of log viewers.
-```
-dfx canister create CANISTER_NAME --log-viewer PRINCIPAL_ID
-```
+- `dfx canister update-settings --remove-log-viewer `: Remove a principal from the log viewer list.
-Or, you can set the `canisters[].initialization_values.log_visibility.allowed_viewers` configuration setting in your project's `dfx.json` file.
-
-To remove a principal from the canister's log allow list, use the `--remove-log-viewer` flag:
+You can also configure a principal as a log viewer when you create a canister:
```
-dfx canister update-settings CANISTER_ID --remove-log-viewer PRINCIPAL_ID
+dfx canister create --log-viewer
```
-## Using `dfx`
-
-A canister's logs can be viewed using the [`dfx canister logs`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister/#dfx-canister-logs) command.
-
-As an example, consider a Rust canister with the following code:
-
-```rust
-use std::cell::RefCell;
-
-use candid::{Nat, Principal};
-use ic_cdk::{
- export_candid, println,
-};
-
-thread_local! {
- // create a cell that holds a counter
- static COUNTER: std::cell::RefCell = RefCell::default();
-}
-
-
-#[ic_cdk::update]
-fn produce_logs() {
- // print the counter value
- COUNTER.with_borrow_mut(|counter| {
- println!("counter: {}", *counter);
- *counter += 1;
- });
-}
-
-export_candid!();
-```
-
-This simple canister provides an incremental counter method that includes a print function that will return output to the command line and the canister's logs.
-
-:::info
-Note that this example uses update calls, as non-replicated query calls do not currently support logging.
-:::
-
-You can call the canister's method and view the associated logged output for each call. For example, if this canister is deployed as `logs_backend`, you can call the canister's `produce_logs` method a few times to increment the counter and get the following command line output:
-
-```
-dfx canister call logs_backend produce_logs
-2024-06-04 21:14:25.882276 UTC: [Canister br5f7-7uaaa-aaaaa-qaaca-cai] counter: 0
-()
-dfx canister call logs_backend produce_logs
-2024-06-04 21:18:18.094003 UTC: [Canister br5f7-7uaaa-aaaaa-qaaca-cai] counter: 1
-()
-dfx canister call logs_backend produce_logs
-2024-06-04 21:18:46.036022 UTC: [Canister br5f7-7uaaa-aaaaa-qaaca-cai] counter: 2
-()
-```
-
-Then, you can call the canister's logs, which in this case will return the same output that was logged to the command line:
-
-```
-dfx canister logs logs_backend
-[0. 2024-06-04T21:14:25.882276Z]: counter: 0
-[1. 2024-06-04T21:18:18.094003Z]: counter: 1
-[2. 2024-06-04T21:18:46.036022Z]: counter: 2
-```
\ No newline at end of file
+Or, you can set the `canisters[].initialization_values.log_visibility.allowed_viewers` configuration setting in your project's `dfx.json` file to set the canister log allowed viewers upon canister creation.
diff --git a/docs/developer-docs/smart-contracts/maintain/recovery.mdx b/docs/developer-docs/smart-contracts/maintain/recovery.mdx
index f52eb61d83..4b0a1f3730 100644
--- a/docs/developer-docs/smart-contracts/maintain/recovery.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/recovery.mdx
@@ -11,7 +11,7 @@ import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
## Overview
-A canister is managed and maintained by **controllers**. A controller can be a single developer identity, a list of developer identities, or another canister. If a canister does not have a controller, it cannot be upgraded, deleted, or otherwise maintained. Canisters can have several controllers. If access to a canister's controller(s) is lost, the canister cannot be upgraded or further maintained. If a canister's code traps with an unrecoverable error and cannot be upgraded, the canister can potentially be recovered using canister snapshots or an NNS proposal.
+A canister is managed and maintained by **controllers**. A controller can be a single developer identity, a list of developer identities, or another canister. If a canister does not have a controller, it cannot be upgraded, deleted, or otherwise maintained. This also applies if access to all canister's controllers identities are lost. If a canister's code traps with an unrecoverable error and cannot be upgraded, the canister can potentially be recovered using canister snapshots or an NNS proposal.
## Canister snapshots
@@ -20,20 +20,3 @@ One method for recovering a canister is to roll the canister back to a snapshot
## Recovering a canister that does not have controllers
If a canister is unable to be upgraded via any of the canister's existing controllers, either due to the canister not having controllers or loss of access to the canister's controllers, there is no supported method to recover that canister.
-
-## Recovering a canister with an NNS proposal
-
-If a canister does not have a snapshot that can be used for recovery, one possible last resort recovery method can be used, however it requires that the canister have the NNS root canister `r7inp-6aaaa-aaaaa-aaabq-cai` configured as a controller of the canister.
-
-To add the NNS root canister as a controller of your canister, use the command:
-
-```sh
-dfx canister update-settings CANISTER_NAME --network ic --add-controller r7inp-6aaaa-aaaaa-aaabq-cai
-```
-
-:::info
-This step cannot be taken after access to a canister's controllers is already lost, since only a current controller of the canister can add additional controllers. If a canister's code has failed and cannot be upgraded, but access to the canister's controllers is possible, then this step can be performed.
-:::
-
-Then, when the canister needs to be recovered, it may be recovered by using the System Canister Management NNS proposal used for upgrading all system canisters. When submitting this proposal, include the canister ID of the broken canister and a new Wasm module for the canister. Once this proposal is submitted, the NNS DAO will vote on whether to upgrade the canister using the proposed new Wasm file or not. If the proposal is passed, the canister will be upgraded and potentially recovered.
-
diff --git a/docs/developer-docs/smart-contracts/maintain/settings.mdx b/docs/developer-docs/smart-contracts/maintain/settings.mdx
index dd3675042d..9e0efe905f 100644
--- a/docs/developer-docs/smart-contracts/maintain/settings.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/settings.mdx
@@ -9,162 +9,89 @@ import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
# Settings
-
+
## Overview
-Each canister has a group of possible settings that control its behavior. Only a controller of the canister can read and modify its settings. Currently, there are seven canister setting fields:
+Each canister has a group of possible settings that control its behavior.
+
+:::caution
+Only a controller of the canister can read and modify a canister's settings.
+:::
+
+Currently, there are seven canister setting fields:
1. `controllers`: The list of controllers of the canister.
-1. `compute_allocation`: Amount of compute that this canister has allocated.
-1. `memory_allocation`: Amount of memory (storage) that this canister has allocated.
-1. `freezing_threshold`: A safety threshold to protect against canister deletion due to running out of cycles.
+1. `compute_allocation`: Amount of compute that the canister has allocated.
+1. `memory_allocation`: Amount of memory (storage) that the canister has allocated.
+1. `freezing_threshold`: A safety threshold to prevent the canister from running out of cycles and avoid being deleted.
1. `reserved_cycles_limit`: A safety threshold to protect against spending too many cycles for resource reservation.
1. `wasm_memory_limit`: A safety threshold to protect against reaching the 4GiB hard limit of 32-bit Wasm memory.
1. `log_visibility`: Controls who can read the canister logs.
-## Viewing a canister's current settings
+## Viewing current settings
There are two ways to read the settings of a canister:
-1. Command line: `dfx canister status `. Note that this command returns canister settings together with other canister status information.
-1. Programmatically: Call the `canister_status` endpoint of the IC management canister. The canister settings will be in the `settings` field of the result.
+1. Command line: [`dfx canister status `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-status). Note that this command returns the canister's settings, along with other canister status information.
+2. Programmatically: Call the [`canister_status`](/docs/current/references/ic-interface-spec) endpoint of the IC management canister. The canister's settings will be in the `settings` field of the result.
-Note that only a controller of the canister can read canister settings.
-
-An example of using `dfx` in a command line:
+### Command line
```bash
-> dfx canister status ajuq4-ruaaa-aaaaa-qaaga-cai
-Canister status call result for ajuq4-ruaaa-aaaaa-qaaga-cai.
-Controllers: bi7oa-57tth-fsnsf-6xrdb-rruo4-fsiws-xkedg-2uzrc-t6jas-7fo3c-jqe bnz7o-iuaaa-aaaaa-qaaaa-cai
+dfx canister status ajuq4-ruaaa-aaaaa-qaaga-cai
+```
+
+
+Output
+
+```
+Canister status call result for .
+Status: Running
+Controllers: hoqq7-3eo6j-dee4s-aiabk-6rqxw-kwgyo-rhru7-bdgmk-k5ipv-chkhx-cqe mwylj-4aaaa-aaaak-aflyq-cai
Memory allocation: 0
Compute allocation: 0
Freezing threshold: 2_592_000
+Idle cycles burned per day: 31_243_414
+Memory Size: Nat(3057320)
+Balance: 196_157_756_924 Cycles
+Reserved: 0 Cycles
Reserved cycles limit: 5_000_000_000_000 Cycles
-Wasm memory limit: 0 Bytes
-...
+Wasm memory limit: 3_221_225_472 Bytes
+Module hash: 0x46cb1e5494b8467a13d0b6a68156b044eb79ce1325aa4bd4a697e36c9b967129
+Number of queries: 1_469
+Instructions spent in queries: 429_285_142
+Total query request payload size (bytes): 1_626_898
+Total query response payload size (bytes): 1_161_862
+Log visibility: controllers
```
-An example of programmatically reading canister settings:
+
+
+### Programmatically
-```motoko
-actor {
- let IC =
- actor "aaaaa-aa" : actor {
-
- canister_status : { canister_id : Principal } ->
- async ();
-
- };
-};
+```motoko no-repl file=../../../references/samples/motoko/query_stats/src/query_stats_backend/main.mo
```
-```rust
-use ic_cdk::api::call::CallResult;
-use ic_cdk::api::management_canister::main::{
- canister_status, CanisterIdRecord, DefiniteCanisterSettings,
-};
-
-#[ic_cdk::update]
-async fn read_canister_settings() -> CallResult {
- let response = canister_status(CanisterIdRecord {
- canister_id: ic_cdk::id(),
- })
- .await?
- .0;
- println!("settings: {:?}", response.settings);
- Ok(response.settings)
-}
+```rust file=../../../references/samples/rust/query_stats/src/lib.rs
```
-
}>
-```typescript
-import { call, IDL, Principal, query, update } from 'azle';
-import {
- CanisterStatusArgs,
- CanisterStatusResult,
-} from 'azle/canisters/management';
-
-type State = {
- createdCanisterId: Principal;
-};
-
-let state: State = {
- createdCanisterId: Principal.fromText('aaaaa-aa')
-};
-
-export default class {
-
- @update([CanisterStatusArgs], CanisterStatusResult)
- async getCanisterStatus(
- args: CanisterStatusArgs
- ): Promise {
- return await call('aaaaa-aa', 'canister_status', {
- paramIdlTypes: [CanisterStatusArgs],
- returnIdlType: CanisterStatusResult,
- args: [args]
- });
- }
-}
-```
+[Learn more about Azle](https://demergent-labs.github.io/azle/the_azle_book.html).
}>
-```python
-from kybra import (
- Async,
- blob,
- CallResult,
- match,
- nat,
- Principal,
- query,
- update,
- void,
-)
-from kybra.canisters.management import (
- CanisterStatusArgs,
- CanisterStatusResult
- management_canister,
-)
-
-class GetCanisterStatusResult(Variant, total=False):
- Ok: CanisterStatusResult
- Err: str
-
-
-class State(TypedDict):
- created_canister_id: Principal
-
-
-state: State = {"created_canister_id": Principal.from_str("aaaaa-aa")}
-
-@update
-def get_canister_status(args: CanisterStatusArgs) -> Async[GetCanisterStatusResult]:
- canister_status_result_call_result: CallResult[
- CanisterStatusResult
- ] = yield management_canister.canister_status({"canister_id": args["canister_id"]})
-
- return match(
- canister_status_result_call_result,
- {
- "Ok": lambda canister_status_result: {"Ok": canister_status_result},
- "Err": lambda err: {"Err": err},
- },
- )
-```
+[Learn more about Kybra](https://demergent-labs.github.io/kybra/).
@@ -173,154 +100,20 @@ def get_canister_status(args: CanisterStatusArgs) -> Async[GetCanisterStatusResu
There are two ways to modify the settings of a canister:
-1. Command line: `dfx canister update-settings --`.
-1. Programmatically: Call the `update_settings` endpoint of the IC management canister.
+1. Command line: `dfx canister update-settings --`.
+1. Programmatically: Call the [`update_settings`](/docs/current/references/ic-interface-spec#ic-update_settings) endpoint of the IC management canister.
Note that only a controller of the canister can modify canister settings.
-An example of using `dfx` in a command line:
+### Command line
```bash
-> dfx canister update-settings ajuq4-ruaaa-aaaaa-qaaga-cai --wasm-memory-limit 3000000000
-> dfx canister status ajuq4-ruaaa-aaaaa-qaaga-cai
-...
-Wasm memory limit: 3_000_000_000 Bytes
-...
-```
-
-An example of programmatically modifying canister settings:
-
-
-
-
-```motoko
-actor {
- let IC =
- actor "aaaaa-aa" : actor {
- update_settings : { canister_id : Principal } ->
- async ();
- };
-};
-```
-
-
-
-
-```rust
-use ic_cdk::api::call::CallResult;
-use ic_cdk::api::management_canister::main::{
- update_settings, CanisterSettings, UpdateSettingsArgument,
-};
-use candid::Nat;
-
-#[ic_cdk::update]
-async fn modify_canister_settings() -> CallResult<()> {
- update_settings(UpdateSettingsArgument{
- canister_id: ic_cdk::id(),
- settings: CanisterSettings {
- wasm_memory_limit: Some(Nat::from(3_000_000_000_u64)),
- // Other fields remain the same.
- .. CanisterSettings::default()
- }
- })
- .await
-}
+dfx canister update-settings --wasm-memory-limit 3000000000
```
-
+### Programmatically
-}>
-
-```typescript
-import { call, IDL, Principal, query, update } from 'azle';
-import {
- UpdateSettingsArgs,
-} from 'azle/canisters/management';
-
-type State = {
- createdCanisterId: Principal;
-};
-
-let state: State = {
- createdCanisterId: Principal.fromText('aaaaa-aa')
-};
-
-export default class {
- @update([IDL.Principal], IDL.Bool)
- async executeUpdateSettings(canisterId: Principal): Promise {
- await call('aaaaa-aa', 'update_settings', {
- paramIdlTypes: [UpdateSettingsArgs],
- args: [
- {
- canister_id: canisterId,
- settings: {
- controllers: [],
- compute_allocation: [1n],
- memory_allocation: [3_000_000n],
- freezing_threshold: [2_000_000n],
- reserved_cycles_limit: []
- },
- sender_canister_version: []
- }
- ]
- });
-
- return true;
- }
-}
-```
-
-
-
-}>
-
-```python
-from kybra import (
- Async,
- blob,
- CallResult,
- match,
- nat,
- Principal,
- query,
- update,
- void,
-)
-from kybra.canisters.management import (
- management_canister,
-)
-
-from typing import TypedDict
-
-
-class State(TypedDict):
- created_canister_id: Principal
-
-
-state: State = {"created_canister_id": Principal.from_str("aaaaa-aa")}
-
-
-@update
-def execute_update_settings(canister_id: Principal) -> Async[DefaultResult]:
- call_result: CallResult[void] = yield management_canister.update_settings(
- {
- "canister_id": canister_id,
- "settings": {
- "controllers": None,
- "compute_allocation": 1,
- "memory_allocation": 3_000_000,
- "freezing_threshold": 2_000_000,
- },
- }
- )
-
- return match(
- call_result, {"Ok": lambda _: {"Ok": True}, "Err": lambda err: {"Err": err}}
- )
-```
-
-
-
+From within your canister, make a call to the [`update_settings`](/docs/current/references/ic-interface-spec#ic-update_settings) endpoint of the IC management canister.
## Controllers
@@ -339,7 +132,7 @@ For example, an idle canister that has compute allocation of 50% for one hour wi
:::info
The rental fee increases the amount of cycles a canister consumes while idle or frozen.
To successfully increase the compute allocation, a canister must have sufficient cycles
-to run for at least [freezing threshold](#freezing-threshold) seconds.
+to run for at least the current [freezing threshold](#freezing-threshold) number of seconds.
:::
The default value of compute allocation is 0%.
@@ -362,7 +155,7 @@ Canisters pay a rental fee for memory allocation, meaning that the payment depen
:::info
The rental fee increases the amount of cycles a canister consumes while idle or frozen.
To successfully increase the memory allocation, a canister must have sufficient cycles
-to run for at least [freezing threshold](#freezing-threshold) seconds.
+to run for at least the current [freezing threshold](#freezing-threshold) number of seconds.
:::
The default value of memory allocation is 0 bytes, which means that there is no default memory allocation.
@@ -382,7 +175,7 @@ A frozen canister does not execute messages and pays only for renting resources
See also the `idle_cycles_burned_per_day` field in the canister's status to learn how many cycles a canister consumes in its idle or frozen state.
:::
-The default value of the freezing threshold is 2592000 (approximately 30 days).
+The default value of the freezing threshold is 2_592_000 (approximately 30 days).
## Reserved cycles limit
@@ -430,4 +223,4 @@ The default value of the field is `controllers`.
Common errors related to canister settings include:
-- [Invalid settings](/docs/current/references/execution-errors#invalid-settings).
\ No newline at end of file
+- [Invalid settings](/docs/current/references/execution-errors#invalid-settings).
diff --git a/docs/developer-docs/smart-contracts/maintain/snapshots.mdx b/docs/developer-docs/smart-contracts/maintain/snapshots.mdx
index 47e5eacdf0..bd4ba13384 100644
--- a/docs/developer-docs/smart-contracts/maintain/snapshots.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/snapshots.mdx
@@ -19,69 +19,65 @@ Canister snapshots are supported in `dfx` version 0.23.0 and newer.
## Creating a snapshot
-To create a snapshot, first the canister must be stopped. Then, use the `dfx canister snapshot create` command:
+To create a snapshot, first the canister must be stopped. Then, use the [`dfx canister snapshot create `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-snapshot-create) command:
```
dfx canister stop
dfx canister snapshot create
```
+
+Output
+
+```
+Created a new snapshot of canister . Snapshot ID: 0000000000000000800000000010000a0101
+```
+
+
+
Only a controller of a canister can take a snapshot or roll a canister back to a snapshot.
:::info
Currently, only one snapshot per canister can be saved. Taking another snapshot of a canister that already has a snapshot saved will overwrite the previous snapshot.
-:::
-:::info
To take a snapshot of a canister on the mainnet, include the flag `--network ic` in the two commands shown above.
:::
-The canister snapshot ID will be returned:
-
-```
-Created a new snapshot of canister hello_backend. Snapshot ID: 0000000000000000800000000010000a0101
-```
-This ID can be used to load the snapshot at a later time. To list all snapshots saved for a canister, use the command:
+The snapshot ID can be used to load the snapshot at a later time. To list all snapshots saved for a canister, use the command [`dfx canister snapshot list `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-snapshot-list):
```
dfx canister snapshot list
```
-The snapshot ID, snapshot size, and timestamp of when the snapshot was taken will be returned:
+
+Output
```
0000000000000000800000000010000a0101: 2.39MiB, taken at 2024-09-16 19:40:23 UTC
```
+
+
## Loading a snapshot
-To load a saved snapshot, first the canister must be stopped. Then, use the `dfx canister snapshot load` command:
+To load a saved snapshot, first the canister must be stopped. Then, use the [`dfx canister snapshot load `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-snapshot-load) command:
```
dfx canister stop
dfx canister snapshot load
```
-:::info
-To load a snapshot on the mainnet, include the flag `--network ic` in the two commands shown above.
-:::
-
Loading a snapshot will replace the canister's current code and data with the snapshot code and data. Any new data that was added to the canister after the snapshot was taken will be deleted.
## Deleting snapshots
-To delete a saved snapshot, use the command:
+To delete a saved snapshot, use the command [`dfx canister snapshot delete `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-snapshot-delete)
```
dfx canister snapshot delete
```
-:::info
-To delete a snapshot on the mainnet, include the flag `--network ic` in the command shown above.
-:::
-
-
## Errors related to canister snapshots
Common errors related to canister snapshots include:
diff --git a/docs/developer-docs/smart-contracts/maintain/state.mdx b/docs/developer-docs/smart-contracts/maintain/state.mdx
index c84b3311bb..36f1ab4edd 100644
--- a/docs/developer-docs/smart-contracts/maintain/state.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/state.mdx
@@ -7,7 +7,7 @@ import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
# State
-
+
## Overview
@@ -15,31 +15,10 @@ After you deploy a canister, it can begin rec
Although canisters are normally placed in the Running state by default, there are cases where you might want to temporarily or permanently stop a canister. For example, you might want to stop a canister before upgrading it. Stopping a canister helps to ensure proper handling of any messages that are in progress and need to either run to completion or be rolled back. You might also want to stop a canister to clear its message queue cleanly as a prerequisite to deleting the canister.
-You can check the current status of all canisters or a specified canister by running the `dfx canister status` command. For example, to see the status for all canisters running on the local canister execution environment, you would run the following command:
+To modify the state of a canister:
- dfx canister status --all
+- [`dfx canister status `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-status): Check if the canister is `Running`, `Stopping`, or `Stopped`. This command also returns details about the canister's settings.
-This command returns output similar to the following if canisters are currently running:
+- [`dfx canister stop `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-stop): Stop the canister. The canister's status will change to `Stopping` if it has in-flight messages that must be addressed before it can be stopped.
- Canister status_check's status is Running.
- Canister status_check_assets's status is Running.
-
-You can stop canisters that are currently running by running the `dfx canister stop` command.
-
- dfx canister stop --all
-
-This command displays output similar to the following:
-
- Stopping code for canister status_check, with canister_id 75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
- Stopping code for canister status_check_assets, with canister_id cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
-
-If you were to rerun the `dfx canister status` command, you might see a status of `Stopped` indicating that there were no pending messages that needed to processed or a status of `Stopping` indicating that there were messages in-flight that needed to be addressed.
-
-To restart a canister-for example, after a successful canister upgrade—you can run the `dfx canister start` command. For example, to restart all of the canisters, you would run the following command:
-
- dfx canister start --all
-
-This command displays output similar to the following:
-
- Starting code for canister status_check, with canister_id 75hes-oqbaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
- Starting code for canister status_check_assets, with canister_id cxeji-wacaa-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa-q
+- [`dfx canister start `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-start): Start the canister. After a canister has been stopped with `dfx canister stop`, the only way to restart it is through `dfx canister start`. Other commands, such as `dfx deploy`, do not start the canister if it has been manually stopped.
diff --git a/docs/developer-docs/smart-contracts/maintain/storage.mdx b/docs/developer-docs/smart-contracts/maintain/storage.mdx
index 1a5fdbcead..19847ca6c6 100644
--- a/docs/developer-docs/smart-contracts/maintain/storage.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/storage.mdx
@@ -7,13 +7,13 @@ import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
# Storage
-
+
## Overview
When developing projects on ICP, there are two primary forms of data storage that your canisters can utilize. The first type of storage is the canister's **heap memory**, sometimes referred to as the canister's *main memory*. Heap memory is **temporary**, and any data stored in a canister's heap memory is cleared whenever the canister is reinstalled or upgraded.
-The second type of storage available to a canister is **stable memory**. Stable memory is a unique feature of ICP that defines a separate data store aside from a canister's regular Wasm heap memory data storage. It is a secondary storage type that can be used to store data long-term, since all data stored in stable memory will persist across all canister processes.
+The second type of storage available to a canister is **stable memory**. Stable memory is a unique feature of ICP that defines a separate data store aside from a canister's regular Wasm heap memory data storage. It is a secondary storage type that can be used to store data long-term, since all data stored in stable memory will persist across all canister processes.
## Heap memory
@@ -23,7 +23,7 @@ Heap memory is limited to a maximum of 4GiB of data.
## Stable memory
-Stable memory is a feature unique to the Internet Computer Protocol that provides a long-term, persistent data storage option separate from a canister's heap memory. When a canister is reinstalled or upgraded, the data stored in stable memory is not cleared or removed. The stable memory is preserved throughout the process, while any other WebAssembly state is discarded.
+Stable memory is a feature unique to the Internet Computer Protocol that provides a long-term, persistent data storage option separate from a canister's heap memory. Unless a canister is reinstalled or its data is cleared due to cycle depletion, the data stored in stable memory is not cleared or removed. The stable memory is preserved throughout the process, while any other WebAssembly state is discarded.
To use stable memory, you must anticipate which portions of the canister's data you want to persist across upgrades by indicating this within the canister code. More information about this can be found in the section below, [Storage handling in different languages](#storage-handling-in-different-languages).
@@ -31,7 +31,7 @@ By default, a canister's stable memory is empty. The maximum storage limit for s
## Storage cost
-Storage cost is calculated on the GiB of storage used by a canister per second, costing `127_000` cycles on a 13-node subnet and `127_000 / 13 * 34` cycles on a subnet with 34 nodes. In USD, this works out to about $0.431 and $1.127, respectively, for storing 1 GiB of data for a 30-day month. The cost is the same whether the canister is using heap memory, stable memory, or both.
+Storage cost is calculated based on the GiB of storage used by a canister per second, costing `127_000` cycles on a 13-node subnet and `127_000 / 13 * 34` cycles on a subnet with 34 nodes. In USD, this works out to about $0.43 and $1.13, respectively, for storing 1 GiB of data for a 30-day month. The cost is the same whether the canister is using heap memory, stable memory, or both.
[Learn more about storage costs](/docs/current/developer-docs/gas-cost).
@@ -39,11 +39,10 @@ Storage cost is calculated on the GiB of storage used by a canister per second,
### Motoko storage handling
-In Motoko canisters, stable memory can be utilized through the Motoko **stable storage** and **stable variable** features. Stable storage is a Motoko-specific term used to refer to Motoko's implementation of stable memory used to persist data across canister upgrades. Stable variables are Motoko-defined variables that use the `stable` modifying keyword to indicate that the variable's value should persist across canister upgrades, such as:
+In Motoko canisters, stable memory can be utilized through the Motoko **stable storage** and **stable variable** features. Stable storage is a Motoko-specific term used to refer to Motoko's implementation of stable memory to persist data across canister upgrades. Stable variables are Motoko-defined variables that use the `stable` modifying keyword to indicate that the variable's value should persist across canister upgrades, such as:
```motoko
actor Counter {
-
stable var value = 0;
public func inc() : async Nat {
value += 1;
@@ -106,9 +105,9 @@ This garbage collector is still in beta testing and should be used with caution.
### Rust storage handling
-To utilize stable memory for canisters written in Rust, the crates [ic-stable-memory](https://github.com/seniorjoinu/ic-stable-memory) and [ic-stable-structures](https://github.com/dfinity/stable-structures) can be used. It is recommended to review the documentation for these crates to learn more, or [review the tutorial on the stable structures crate](https://mmapped.blog/posts/14-stable-structures.html).
+To utilize stable memory for canisters written in Rust, the crate [ic-stable-structures](https://github.com/dfinity/stable-structures) can be used. It is recommended to review the documentation for these crates to learn more, or [review the tutorial on the stable structures crate](https://mmapped.blog/posts/14-stable-structures.html).
-As good practice, stable memory should be versioned since the stable memory decoding mechanism may need to guess the data's format in situations where the serialization format or stable data layout of a canister drastically changes. To make this process easier, stable memory should be versioned. This can be as simple as declaring that the first byte of the canister's stable memory will be used to represent the version number.
+As good practice, stable memory should be versioned since the stable memory decoding mechanism may need to guess the data's format in situations where the serialization format or stable data layout of a canister drastically changes. This can be as simple as declaring that the first byte of the canister's stable memory will be used to represent the version number.
To utilize stable memory when upgrading a Rust canister, the following workflow is used:
diff --git a/docs/developer-docs/smart-contracts/maintain/trapping.mdx b/docs/developer-docs/smart-contracts/maintain/trapping.mdx
index 6e6b0aad4d..4f77674b52 100644
--- a/docs/developer-docs/smart-contracts/maintain/trapping.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/trapping.mdx
@@ -1,24 +1,30 @@
+---
+keywords: [beginner, tutorial, maintain canisters, canister trapping, traps, traps during upgrades, handling traps]
+---
+
+import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
+import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
+
# Trapping
-## Overview
+
+## Overview
Trapping, in the context of WebAssembly code, refers to an interruption of code execution that returns an error. Trapping is defined by [the WebAssembly documentation](https://webassembly.github.io/spec/core/intro/overview.html) as:
-
*“Under some conditions, certain instructions may produce a trap, which immediately aborts execution. Traps cannot be handled by WebAssembly code, but are reported to the outside environment, where they typically can be caught.”*
-
On ICP, canister code is compiled into WebAssembly before it is executed. This means that canisters can trap. Some example cases when canisters might trap include:
-- Canister code panics (e.g. in Rust)
-- Dividing by zero
-- Calling a System API in a context that is not permitted by ICP ([see overview of imports for a list of APIs and which contexts they are available in](/docs/current/references/ic-interface-spec#system-api-imports))
-- Accessing [heap data](/docs/current/developer-docs/smart-contracts/maintain/storage) that is out of bounds
+- Canister code panics (e.g. in Rust).
+- Dividing by zero.
+- Calling a System API in a context that is not permitted by ICP ([see a list of APIs and which contexts they are available in](/docs/current/references/ic-interface-spec#system-api-imports)).
+- Accessing [heap data](/docs/current/developer-docs/smart-contracts/maintain/storage) that is out of bounds.
## What happens when a canister traps?
-If a canister traps during a message execution, then two things happen:
+If a canister traps during a message execution, two things happen:
- Message execution immediately ends and an error is returned.
- Any state changes made by the canister during this message execution will be rolled back.
@@ -29,42 +35,31 @@ If a canister traps during a message execution, then two things happen:
Using pre_ and post_upgrade hooks is discouraged. It is error-prone and can render a canister unusable. Per best practices, using these methods should be avoided if possible.
:::
-Special care should be taken when writing a `pre_upgrade` hook for your canister which will run during an upgrade. If the [pre_upgrade](/docs/current/references/ic-interface-spec#system-api-upgrades) hook traps,
-then the canister upgrade would fail. This is extremely important as it can mean your canister can be permanently bricked if such a trap occurs
-in the `pre_upgrade` hook as this will always run against the current canister's Wasm module.
+Special care should be taken when writing a `pre_upgrade` hook for your canister which will run during an upgrade against the current canister's Wasm module. If the [`pre_upgrade`](/docs/current/references/ic-interface-spec#system-api-upgrades) hook traps, then the canister upgrade will fail. This is extremely important as it means your canister can be permanently unrecoverable.
In order to avoid unexpected surprises, it is strongly recommended that your canisters use stable memory directly, which removes the need for having a `pre_upgrade` hook in the first place.
-
## Traps during inter-canister calls
-Trapping is an important concern when using inter-canister calls. Since the state is rolled back only for the current message execution, this means
-that if there's a trap in a callback handler execution, the state only rolls back to the point before this message execution. In particular, any
-state changes made by the canister before making the inter-canister call and calling `await` to wait for the response will not be rolled back
-(as this was a separate message execution that happened before the callback handler was invoked).
-
-
-This is quite important as it might affect how one can implement canisters safely. Generally speaking, traps should be avoided in callback handler
-invocations. If this is not possible, then it's recommended to use the [cleanup system API call](/docs/current/references/ic-interface-spec#system-api-call) to ensure that any cleanup action is performed (e.g. releasing a lock that was acquired before making an inter-canister call).
+Trapping is an important concern when using inter-canister calls. Since the state is rolled back only for the current message execution, this means that if there's a trap in a callback handler execution, the state only rolls back to the point before this message execution. In particular, any state changes made by the canister before making the inter-canister call and calling `await` to wait for the response will not be rolled back (as this was a separate message execution that happened before the callback handler was invoked).
+This is quite important as it might affect how one can implement canisters safely. Generally speaking, traps should be avoided in callback handler invocations. If this is not possible, then it's recommended to use the [cleanup system API call](/docs/current/references/ic-interface-spec#system-api-call) to ensure that any cleanup action is performed (e.g. releasing a lock that was acquired before making an inter-canister call).
## When to use traps explicitly
-
-Traps can also be useful in certain situations. If you encounter an unrecoverable error while processing a message, it might be better to trap and
-roll back any changes made in that message execution to avoid leaving your canister in a weird state. Another case would be if an invariant that
-should generally hold is violated -- again a trap might be the best option to ensure that there's no further damage done and the broken invariant
-can be investigated and fixed.
-
+Traps can also be useful in certain situations. If you encounter an unrecoverable error while processing a message, it might be better to trap and roll back any changes made in that message execution to avoid leaving your canister in a weird state. Another case would be if an invariant that should generally hold is violated.
## Troubleshooting why your canister trapped
Some of the common root causes of canister traps include:
- *“Heap out of bounds”*: Usually means that your canister is attempting to access heap memory that has not been allocated yet. This typically points to a programming error. Look for places where memory is allocated (e.g. creating vectors) and whether you try to access such memory before allocating it.
+
- *“Stable memory out of bounds”*: Similar to *“heap out of bounds”* but for stable memory.
+
- *“Integer division by zero”*: The canister attempted to divide by zero. Inspect the canister's code for any division operations.
-- *“Unreachable”*: Typically produced when the canister panic's, e.g. for Rust canisters. Unfortunately, the system does not capture a backtrace at the moment, so you won't see more information. It's recommended to use the [panic hook](https://github.com/dfinity/cdk-rs/blob/08cbe397fcbaf62dd1edbec218492f967e80dd00/src/ic-cdk/src/printer.rs#L5) so that panic's are converted to an explicit call to [ic0.trap](/docs/current/references/ic-interface-spec#debugging-aids) which will append an error message that will be more useful for debugging.
+
+- *“Unreachable”*: Typically produced when the canister panics, e.g. for Rust canisters. It's recommended to use the [panic hook](https://github.com/dfinity/cdk-rs/blob/08cbe397fcbaf62dd1edbec218492f967e80dd00/src/ic-cdk/src/printer.rs#L5) so that panics are converted to an explicit call to [ic0.trap](/docs/current/references/ic-interface-spec#debugging-aids) which will append an error message that will be more useful for debugging.
## Errors related to canister trapping
diff --git a/docs/developer-docs/smart-contracts/maintain/upgrade.mdx b/docs/developer-docs/smart-contracts/maintain/upgrade.mdx
index bd0252614a..86b6d53bec 100644
--- a/docs/developer-docs/smart-contracts/maintain/upgrade.mdx
+++ b/docs/developer-docs/smart-contracts/maintain/upgrade.mdx
@@ -11,28 +11,21 @@ import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
## Overview
-Unlike a canister reinstall that preserves the canister identifier but no state, a canister upgrade enables you to preserve the state of a deployed canister, and change the code.
+Unlike a canister reinstall that preserves the canister identifier but no state, a canister upgrade enables you to preserve the state of a deployed canister and change the code.
For example, assume you have a dapp that manages professional profiles and social connections. If you want to add a new feature to the dapp, you need to be able to update the canister code without losing any of the previously-stored data. A canister upgrade enables you to update existing canister identifiers with program changes without losing the program state.
+:::tip
To preserve state when you are upgrading a canister written in Motoko, be sure to use the `stable` keyword to identify the variables you want to preserve. For more information about preserving variable state in Motoko, see [stable variables and upgrade methods](/docs/current/motoko/main/canister-maintenance/upgrades).
+:::
-To upgrade a canister:
+To upgrade a canister, first you must:
-- #### Step 1: Open a new terminal and navigate to your project directory.
+1. Edit the canister's code and save the changes.
- Start `dfx` with the command `dfx start --background`.
+2. Use [`dfx build `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-build) to compile the code into a new Wasm module.
-- #### Step 2: Verify you have canister identifiers for all of the canisters you want to upgrade.
-
- Note that your canister code must identify the variables for which to maintain state by using the `stable` keyword in the variable declaration.
-
- For more information about declaring stable variables, see the [**Motoko documentation**](/docs/current/motoko/main/stable-memory/stablememory).
-
-- #### Step 3: Upgrade all of the canisters by running the following command:
-
- dfx canister install --all --mode upgrade // Local
- dfx canister install --all --mode upgrade --network ic // Mainnet
+3. Use [`dfx canister install --mode upgrade`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-install) to install the new Wasm module.
## Errors related to canister upgrades
diff --git a/docs/developer-docs/smart-contracts/test/overview.mdx b/docs/developer-docs/smart-contracts/test/overview.mdx
index 7ee17e05d8..65f8e6da18 100644
--- a/docs/developer-docs/smart-contracts/test/overview.mdx
+++ b/docs/developer-docs/smart-contracts/test/overview.mdx
@@ -34,7 +34,7 @@ For Rust unit testing, refer to the guide on [effective Rust containers](https:/
### Integration testing
-Integration testing refers to testing multiple components of a code or application together to ensure that they operate correctly. Integration testing often includes testing how several functions within a canister interact with one another, how different canisters may send and receive information from each other, or how a canister may obtain and digest external information from HTTPS outcalls. One common form of integration testing is continuous integration (CI) testing. CI testing uses an automated workflow to continuously test several components of an application.
+Integration testing refers to testing multiple components of an application together to ensure that they operate correctly. Integration testing often includes testing how several functions within a canister interact with one another, how different canisters may send and receive information from each other, or how a canister may obtain and digest external information from HTTPS outcalls. One common form of integration testing is continuous integration (CI) testing. CI testing uses an automated workflow to continuously test several components of an application.
GitHub CI testing is a common workflow used by developers that can be configured to run tests whenever new code is pushed to a repository. [Learn more about CI tests](https://docs.github.com/en/actions/using-workflows).
@@ -63,8 +63,4 @@ PocketIC is a comprehensive testing suite that can be used for testing canisters
Light Replica is a community-contributed tool designed to replicate the local testing environment that the Ethereum tools Hardhat or Truffle provide. Light Replica replicates the behavior of a real ICP node by running a local instance of a node, then providing additional logging and functionality to enable canister testing. Light Replica can be used to test any Wasm file as if it were a canister deployed on the mainnet.
-[Learn more about Light Replica](https://github.com/icopen/lightic/tree/main).
-
-### Manual staging environments
-
-As an alternative to using the environments provided by PocketIC or Light Replica, you can also manually make a staging environment with `dfx` that you can test your code against. [Learn more about creating a staging environment with dfx](staging-environment.mdx).
\ No newline at end of file
+[Learn more about Light Replica](https://github.com/icopen/lightic/tree/main).
\ No newline at end of file
diff --git a/docs/developer-docs/smart-contracts/test/pocket-ic.mdx b/docs/developer-docs/smart-contracts/test/pocket-ic.mdx
index b8a265f851..9f0a76e226 100644
--- a/docs/developer-docs/smart-contracts/test/pocket-ic.mdx
+++ b/docs/developer-docs/smart-contracts/test/pocket-ic.mdx
@@ -42,27 +42,12 @@ While PocketIC can support integration with any language, Rust and Python will b
## PocketIC Rust
-To use PocketIC, the latest PocketIC server binary must be downloaded from the PocketIC repo. You can download the latest version for macOS or Linux systems [here](https://github.com/dfinity/pocketic#download-the-pocketic-server).
+To use PocketIC, the latest PocketIC server binary must be downloaded from the PocketIC repo. [Download the latest version for macOS or Linux systems](https://github.com/dfinity/pocketic?tab=readme-ov-file#download-the-pocketic-server).
:::info
PocketIC is currently not natively supported on Windows systems.
:::
-Once the binary file is downloaded, unzip the file and make it executable:
-
-```bash
-gzip -d pocket-ic.gz
-chmod +x pocket-ic
-```
-
-:::info
-On macOS systems, to bypass developer verification from Apple, you may need to run:
-
-```
-xattr -dr com.apple.quarantine pocket-ic
-```
-:::
-
The PocketIC binary can be left in your working directory or you can specify the path to the binary by setting the `POCKET_IC_BIN` environmental variable.
Add PocketIC Rust do your project with the command:
@@ -83,37 +68,11 @@ Then, in your code you can create a new PocketIC instance with the code:
let pic = PocketIc::new();
```
-### Example: Single canister testing on a single subnet
+### Single canister testing on a single subnet
-The following is a simple, but complete testing example with a counter canister:
+[View an example of testing a canister on a single subnet](https://crates.io/crates/pocket-ic).
-```rust
-use candid::encode_one;
-use pocket_ic::PocketIc;
-
- #[test]
- fn test_counter_canister() {
- let pic = PocketIc::new();
- // Create an empty canister as the anonymous principal and add cycles.
- let canister_id = pic.create_canister();
- pic.add_cycles(canister_id, 2_000_000_000_000);
-
- let wasm_bytes = load_counter_wasm(...);
- pic.install_canister(canister_id, wasm_bytes, vec![], None);
- // 'inc' is a counter canister method.
- call_counter_canister(&pic, canister_id, "inc");
- // Check if it had the desired effect.
- let reply = call_counter_canister(&pic, canister_id, "read");
- assert_eq!(reply, WasmResult::Reply(vec![0, 0, 0, 1]));
- }
-
-fn call_counter_canister(pic: &PocketIc, canister_id: CanisterId, method: &str) -> WasmResult {
- pic.update_call(canister_id, Principal::anonymous(), method, encode_one(()).unwrap())
- .expect("Failed to call counter canister")
-}
-```
-
-### Example: Multi-subnet testing
+### Multi-subnet testing
Versions of PocketIC `v2.0.0` and newer support multi-subnet testing. Multi-subnet testing allows for simulating multiple, different types of subnets locally. For example, to create an IC instance with an NNS subnet and two application subnets, use the code:
@@ -160,26 +119,7 @@ For a larger, more complex example that uses cross canister calls on two differe
## PocketIC Python
-To use PocketIC, the latest PocketIC server binary must be downloaded from the PocketIC repo. You can download the latest version for macOS or Linux systems [here](https://github.com/dfinity/pocketic#download-the-pocketic-server).
-
-:::info
-PocketIC is currently not supported natively on Windows systems.
-:::
-
-Once the binary file is downloaded, unzip the file and make it executable:
-
-```bash
-gzip -d pocket-ic.gz
-chmod +x pocket-ic
-```
-
-:::info
-On macOS systems, to bypass developer verification from Apple, you may need to run:
-
-```bash
-xattr -dr com.apple.quarantine pocket-ic
-```
-:::
+To use PocketIC, the latest PocketIC server binary must be downloaded from the PocketIC repo. [Download the latest version for macOS or Linux systems](https://github.com/dfinity/pocketic#download-the-pocketic-server).
The PocketIC binary can be left in your working directory or you can specify the path to the binary by setting the `POCKET_IC_BIN` environmental variable.
@@ -195,22 +135,9 @@ To import PocketIC into your Python code, use the line:
from pocket_ic import PocketIC
```
-### Example: Create a canister with cycles
+### Create a canister with cycles and call the canister
-```python
-from pocket_ic import PocketIC
-
-pic = PocketIC()
-canister_id = pic.create_canister()
-pic.add_cycles(canister_id, 2_000_000_000_000)
-```
-
-### Make canister calls
-
-```python
-response = pic.update_call(canister_id, method="greeting", ...)
-assert(response == 'Hello, PocketIC!')
-```
+[View an example of how to create a canister with cycles, and then call the canister](https://pypi.org/project/pocket-ic/).
### Make a call directly with a canister object
@@ -225,49 +152,9 @@ response = my_canister.greeting()
assert(response == 'Hello, PocketIC!')
```
-### Example: Single canister testing on a single subnet
+### Single canister testing on a single subnet
-The following is a simple, but complete testing example with a counter canister:
-
-```python title="src/example_backend/src/main.py"
-import sys
-import os
-import unittest
-import ic
-from pocket_ic import PocketIC
-
-
-class CounterCanisterTests(unittest.TestCase):
- def test_counter_canister(self):
- pic = PocketIC()
- canister_id = pic.create_canister()
- pic.add_cycles(canister_id, 1_000_000_000_000_000_000)
-
- with open("counter.wasm", "rb") as wasm_file:
- wasm_module = wasm_file.read()
- pic.install_code(canister_id, bytes(wasm_module), [])
-
- self.assertEqual(
- pic.update_call(canister_id, "read", ic.encode([])),
- [0, 0, 0, 0],
- )
- self.assertEqual(
- pic.update_call(canister_id, "write", ic.encode([])),
- [1, 0, 0, 0],
- )
- self.assertEqual(
- pic.update_call(canister_id, "write", ic.encode([])),
- [2, 0, 0, 0],
- )
- self.assertEqual(
- pic.update_call(canister_id, "read", ic.encode([])),
- [2, 0, 0, 0],
- )
-
-
-if __name__ == "__main__":
- unittest.main()
-```
+[View a complete example of testing a single canister on a single subnet](https://github.com/dfinity/pocketic-py/blob/main/examples/counter_canister/counter_canister_test.py).
To see more examples and run them locally, clone the [PocketIC Python repo](https://github.com/dfinity/pocketic-py), then run the following command, replacing the example name with the example you'd like to run. For example, to run the `counter_canister` example, use the command:
diff --git a/docs/developer-docs/smart-contracts/test/staging-environment.mdx b/docs/developer-docs/smart-contracts/test/staging-environment.mdx
deleted file mode 100644
index 8cd50071c3..0000000000
--- a/docs/developer-docs/smart-contracts/test/staging-environment.mdx
+++ /dev/null
@@ -1,81 +0,0 @@
----
-keywords: [intermediate, test, tutorial, staging environment, staging]
----
-
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-import { GlossaryTooltip } from "/src/components/Tooltip/GlossaryTooltip";
-
-
-# Staging environment
-
-
-
-## Overview
-
-Having a separate deployment environment available where features can be end-to-end tested before they get deployed to the production environment can be helpful. While local deployments mirror the live mainnet as closely as possible, it is not the same. The local instance only runs as a single subnet. If you want to test canisters of two different subnets connecting to each other, you cannot do this locally. Other benefits of using a staging environment include being able to test an integration with other services, deployment workflows, and estimating costs before setting a feature live.
-
-## Setting up a staging environment
-
-In a staging environment it is possible to run any `dfx` command that would otherwise take `--network ic` but using `--network myStaging` instead. `myStaging` can be replaced with any other name, except the three reserved ones: `ic`, `local`, and `playground`.
-
-:::info
-Deploying to the playground is ICP's equivalent of deploying to a testnet network.
-:::
-
-
-Networks are defined in two ways: assumed and explicitly configured. dfx only contains the `ic` network as an assumed environment. The flag `--network ic` can be used to run any command on the mainnet.
-
-All other networks are explicitly configured in `dfx.json`. The `"networks"` section should contain at least the `local` network, which gets chosen by default if no other network is specified with the `--network` flag.
-
-## Network definition
-
-To add a staging network named `myStaging` to `dfx.json`, add this code under `"networks"` in your `dfx.json`:
-
-``` json title="dfx.json"
-"myStaging": {
- "providers": [
- "https://icp0.io"
- ],
- "type": "persistent"
-}
-```
-
-This value for `"providers"` tells `dfx` where to connect to the network. It is identical to the one in the hard-coded `ic` network.
-The type `persistent` tells `dfx` that the canisters on this network will stay there and the canister identifiers will be saved in the `canister_ids.json` file.
-
-### Configuring a wallet
-
-If you are using a cycles wallet, the cycles wallet for each network is stored separately. The newly created `myStaging` network has no wallet configured yet.
-
-:::caution
-Please note that the cycles wallet will be removed from dfx in a future release.
-
-It is recommended to use the cycles ledger instead.
-:::
-
-To use the same cycles wallet as on the main `ic` network, first make sure the correct identity is set by running the command:
-
-```bash
-dfx identity use
-```
-
-Then, read the `ic` network's currently configured wallet using:
-
-```bash
-dfx identity get-wallet --network ic
-```
-
-Set the wallet for the newly defined network with the command:
-
-```bash
-dfx identity set-wallet --network myStaging
-```
-
-These commands can be used together, such as:
-
-```bash
-dfx identity set-wallet "$(dfx identity get-wallet --network ic)" --network myStaging
-```
-
-If you prefer to use a separate cycles wallet for the staging environment, follow the instructions in the step 'Creating a cycles wallet' in the [deploying to the mainnet guide](/docs/current/developer-docs/getting-started/deploy-and-manage).
diff --git a/docs/developer-docs/smart-contracts/test/troubleshooting.mdx b/docs/developer-docs/smart-contracts/test/troubleshooting.mdx
deleted file mode 100644
index b0baf73ca8..0000000000
--- a/docs/developer-docs/smart-contracts/test/troubleshooting.mdx
+++ /dev/null
@@ -1,162 +0,0 @@
----
-keywords: [intermediate, test, tutorial, troubleshooting]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Troubleshooting resources
-
-
-
-## Overview
-
-This section provides information to help you troubleshoot and resolve or work around common issues that are related to the following tasks:
-
-- Downloading and installing the IC SDK.
-
-- Creating, building, or deploying canisters.
-
-- Using the [IC SDK](/docs/current/developer-docs/getting-started/install).
-
-- Running the local canister execution environment.
-
-## Migrating an existing project
-
-Currently, there is no automatic migration or backward compatibility for any projects that you might have created using previous versions of the IC SDK. After upgrading to the latest version, you might see error or failure messages if you attempt to build or install a project created with a previous version of the IC SDK.
-
-In many cases, however, you can continue to work with projects from a previous release by manually changing the `dfx` setting in the `dfx.json` configuration file, then rebuilding the project to be compatible with the version of the IC SDK you have currently installed.
-
-For example, if you have a project that was created with IC SDK version `0.8.0`, open the `dfx.json` file in a text editor and change the `dfx` setting to the latest version or remove the section entirely.
-
-## Restarting the local canister execution environment
-
-In some cases, starting the local canister execution environment fails due to stale state. If you encounter issues when running `dfx start` to start the local canister execution environment:
-
-- #### Step 1: In the terminal that displays the ICP emulation the execution environment uses, press Control-C to interrupt the local canister execution environment process.
-
-- #### Step 2: Stop the local canister execution environment by running the following command:
-
-```bash
-dfx stop
-```
-
-- #### Step 3: Restart the local canister execution environment in a clean state by running the following command:
-
-```bash
-dfx start --clean
-```
-
-The `--clean` option removes checkpoints and stale state information from your project’s cache so that you can restart the local canister execution environment and web server processes in a clean state.
-
-:::caution
-Keep in mind, however, that if you reset the state information by running `dfx start --clean`, your existing canisters are also removed.
-:::
-
-- #### Step 4: After running `dfx start --clean`, recreate your canisters by running the following commands:
-
-```bash
-dfx canister create --all
-dfx build
-dfx canister install --all
-```
-
-## Removing the canisters directory
-
-If you run into problems building or deploying canisters after successfully connecting to ICP and registering canister identifiers, you should remove the `canisters` directory before attempting to rebuild or redeploy the canisters.
-
-You can remove the `canisters` directory for a project by running the following command in the project’s root directory:
-
-```bash
-rm -rf ./.dfx/* canisters/*
-```
-
-## Reinstalling dfx
-
-Many of the bugs you might encounter can be addressed by uninstalling and reinstalling the IC SDK. Here are a few ways to reinstall the IC SDK.
-
-If you only have one version of the IC SDK installed in your development environment, you can usually run the following command to uninstall and reinstall the latest version of IC SDK:
-
-```bash
-~/.cache/dfinity/uninstall.sh && sh -ci "$(curl -sSL https://internetcomputer.org/install.sh)"
-```
-
-If you have modified the location of the IC SDK binary (the binary is titled `dfx`), you might want run the following command to uninstall the version of the IC SDK that is in your PATH, then reinstall the latest version of the IC SDK:
-
-```bash
-rm -rf ~/.cache/dfinity && rm $(which dfx) && sh -ci "$(curl -sSL https://internetcomputer.org/install.sh)"
-```
-
-## Xcode prerequisite
-
-Some versions of the IC SDK prompted you to install Xcode when creating a new project on a macOS computer. The prompt has been removed and the `dfx new` command does not require you to install any macOS developer tools. However, you should have **Developer Command Line Tools** installed if you want to create a Git repository for your project.
-
-You can check whether you have the developer tools installed by running `xcode-select -p`. You can install the developer tools by running `xcode-select --install`.
-
-## Apple ARM silicon
-If you are using a Mac with Apple silicon and are having issues (such as `bad CPU type in executable: dfx`), you may need to install Rosetta.
-
-```bash
-softwareupdate --install-rosetta
-```
-
-## Failed build when using VMs
-
-If you are running the IC SDK using a virtual machine image on Ubuntu or CentOS, you might see an error message that looks like this when you attempt to run the `dfx build` command:
-
-```bash
-Building hello...
-An error occurred:
-Io(
- Os {
- code: 2,
- kind: NotFound,
- message: "No such file or directory",
- },
-)
-```
-
-## Address in use error or orphan processes
-
-If you are developing projects locally, you often have the local replica running either in a separate terminal or in the background. If the local environment processes do not get properly terminated, you might see operating system errors indicating that an address is already in use or or be unable to stop processes normally using the `dfx stop` command.
-
-There are several scenarios in which you might encounter this issue. For example, if you run `dfx start` in a local project directory then change to a different local project directory without first stopping the canister execution environment processes, you might see this issue.
-
-If you encounter an issue where you suspect or you receive a message that an address is already in use or that a process is already running in the background, perform the following steps:
-
-- #### Step 1: Run the following command to see which process is listening to the 4943 port if you are using the default binding to localhost:
-
-```bash
-lsof -i tcp:4943
-```
-
-- #### Step 2: Run the following command to terminate any orphan processes:
-
-```bash
-killall dfx replica
-```
-
-- #### Step 3: Close the current terminal and open a new terminal window.
-
-- #### Step 4: In the new terminal, run the following command to run the local canister execution environment in a clean state:
-
-```bash
-dfx start --clean --background
-```
-
-## Memory leak
-
-Fixing memory leaks is an ongoing process. If you encounter any error messages related to memory leaks, you should do the following:
-
-- #### Step 1: Run `dfx stop` to stop currently running processes.
-
-- #### Step 2: Uninstall the IC SDK to prevent further degradation.
-
-- #### Step 3: Re-install the IC SDK
-
-- #### Step 4: Run `dfx start` to restart replica processes.
-
-Alternatively, you can remove the `.cache/dfinity` directory and re-install the latest IC SDK `dfx` binary. For example:
-
-```bash
-rm -rf ~/.cache/dfinity && sh -ci "$(curl -sSL https://internetcomputer.org/install.sh)"
-```
diff --git a/docs/developer-docs/smart-contracts/topping-up/cycles_management_services.mdx b/docs/developer-docs/smart-contracts/topping-up/cycles_management_services.mdx
index 3a4d7eb73a..378ac9766b 100644
--- a/docs/developer-docs/smart-contracts/topping-up/cycles_management_services.mdx
+++ b/docs/developer-docs/smart-contracts/topping-up/cycles_management_services.mdx
@@ -33,144 +33,4 @@ Popular cycles management services include:
## Creating custom autonomous top-up solutions
-To create an autonomous canister that doesn't rely on a third-party service, you can create your own autonomous canister top-up solution. One option is to use a similar architecture implemented by [CycleOps](https://github.com/CycleOperators/cycles-manager/tree/main), where one canister acts as the cycles manager for the project and provides the API used to request more cycles when a canister within the project has its cycles balance dip below a preset threshold. Below is a sample code for this architecture, where 'CyclesManager' is the management canister and 'Child' is another canister in the project that requests cycles from the 'CyclesManager'.
-
-:::caution
-
-You will still need to top up the CyclesManager canister manually.
-
-:::
-
-Here is example code for the 'CyclesManager' canister:
-
-```motoko no-repl title="CyclesManager.mo"
-// Import packages
-import { logand } "mo:base/Bool";
-import { trap } "mo:base/Debug";
-import Principal "mo:base/Principal";
-import { endsWith; size } "mo:base/Text";
-
-// Import the Mops package CyclesManager
-import CyclesManager "mo:cycles-manager/CyclesManager";
-
-// Implements the cycles_manager_transferCycles API of the CyclesManager.Interface
-
-actor CyclesManager {
- // Initializes a cycles manager
- stable let cyclesManager = CyclesManager.init({
- // By default, with each transfer request 500 billion cycles will be transferred
- // to the requesting canister, provided they are permitted to request cycles
- //
- // This means that if a canister is added with no quota, it will default to the quota of #fixedAmount(500)
- defaultCyclesSettings = {
- quota = #fixedAmount(500_000_000_000);
- };
- // Allow an aggregate of 10 trillion cycles to be transferred every 24 hours
- aggregateSettings = {
- quota = #rate({
- maxAmount = 10_000_000_000_000;
- durationInSeconds = 24 * 60 * 60;
- });
- };
- // 50 billion is a good default minimum for most low use canisters
- minCyclesPerTopup = ?50_000_000_000;
- });
-
- // @required - IMPORTANT!!!
- // Allows canisters to request cycles from this "manager canister" that implements
- // the cycles manager
- public shared ({ caller }) func cycles_manager_transferCycles(
- cyclesRequested: Nat
- ): async CyclesManager.TransferCyclesResult {
- if (not isCanister(caller)) trap("Calling principal must be a canister");
-
- let result = await* CyclesManager.transferCycles({
- cyclesManager;
- canister = caller;
- cyclesRequested;
- });
- result;
- };
-
- // A very basic example of adding a canister to the cycles manager
- // This adds a canister with a 1 trillion cycles allowed per 24 hours cycles quota
- //
- // IMPORTANT: You must add authorization for production implementations so that not just any canister can add themselves
- public shared func addCanisterWith1TrillionPer24HoursLimit(canisterId: Principal) {
- CyclesManager.addChildCanister(cyclesManager, canisterId, {
- // This top up rule 1 Trillion every 24 hours
- quota = ?(#rate({
- maxAmount = 1_000_000_000_000;
- durationInSeconds = 24 * 60 * 60;
- }));
- })
- };
-
- // **DO NOT USE IN PRODUCTION** - for developer debugging and testing purposes only
- public func toText() : async Text {
- let result = CyclesManager.toText(cyclesManager);
- result;
- };
-
- func isCanister(p : Principal) : Bool {
- let principal_text = Principal.toText(p);
- // Canister principals have 27 characters
- size(principal_text) == 27
- and
- // Canister principals end with "-cai"
- endsWith(principal_text, #text "-cai");
- };
-}
-```
-
-Here is example code for the 'Child' canister:
-
-```motoko no-repl Child.mo
-
-// Import the Mops package CyclesManager
-import CyclesRequester "mo:cycles-manager/CyclesRequester";
-import CyclesManager "mo:cycles-manager/CyclesManager";
-
-import { print } "mo:base/Debug";
-
-actor Child {
- // Stable variable holding the cycles requester
- stable var cyclesRequester: ?CyclesRequester.CyclesRequester = null;
-
- // A simple counter, for the purposes of this example
- stable var counter: Nat = 0;
-
- // Initialize the cycles requester
- // As an alternative, you can also initialize the cycles requester in the constructor
- public func initializeCyclesRequester(
- batteryCanisterPrincipal: Principal,
- topupRule: CyclesRequester.TopupRule,
- ) {
- cyclesRequester := ?CyclesRequester.init({
- batteryCanisterPrincipal;
- topupRule
- });
- };
-
- // An example of adding cycles request functionality to an arbitrary update function
- public func justAnotherCounterExample(): async () {
- // before doing something, check if we need to request cycles
- let result = await* requestTopupIfLow();
- print(debug_show(result));
-
- // Do something in the rest of the function;
- counter += 1;
- };
-
- // Local helper function you can use in your actor if the cyclesRequester could possibly be null
- func requestTopupIfLow(): async* CyclesManager.TransferCyclesResult {
- switch(cyclesRequester) {
- case null #err(#other("CyclesRequester not initialized"));
- case (?requester) await* CyclesRequester.requestTopupIfBelowThreshold(requester);
- }
- };
-}
-```
-
-[View the full example on GitHub](https://github.com/CycleOperators/cycles-manager/tree/main/example).
-
+To create an autonomous canister that doesn't rely on a third-party service, you can create your own autonomous canister top-up solution. One option is to use a similar architecture implemented by [CycleOps](https://github.com/CycleOperators/cycles-manager/tree/main), where one canister acts as the cycles manager for the project and provides the API used to request more cycles when a canister within the project has its cycles balance dip below a preset threshold. Below is a sample code for this architecture, where 'CyclesManager' is the management canister and 'Child' is another canister in the project that requests cycles from the 'CyclesManager'.
\ No newline at end of file
diff --git a/docs/developer-docs/smart-contracts/topping-up/topping-up-canister.mdx b/docs/developer-docs/smart-contracts/topping-up/topping-up-canister.mdx
index bb2f56208d..7cc81e5220 100644
--- a/docs/developer-docs/smart-contracts/topping-up/topping-up-canister.mdx
+++ b/docs/developer-docs/smart-contracts/topping-up/topping-up-canister.mdx
@@ -17,9 +17,9 @@ A canister needs to have cycles deposited con
Anyone can top up any canister deployed to ICP; you do not need to be the owner or controller of the canister. All you need is the canister's principal.
-There are a few different ways to top up canisters, such as:
+There are a few different ways to top up canisters:
-- Using [`dfx`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/).
+- Using [`dfx cycles top-up`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-cycles#dfx-cycles-top-up).
- Through the [NNS frontend dapp](https://nns.ic0.app).
@@ -47,13 +47,14 @@ The following examples will demonstrate how to interact with and top up a canist
### Checking the cycles balance of a canister
-Canister cycles balances are not exposed publicly by default; you can only see them if you are the controller of a canister. Using `jqylk-byaaa-aaaal-qbymq-cai` as an example, you can query it by calling:
+Canister cycles balances are available through the [`dfx canister status`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-status) command. They are not exposed publicly by default; you can only see them if you are the controller of a canister:
```bash
-dfx canister status jqylk-byaaa-aaaal-qbymq-cai --network ic
+dfx canister status jqylk-byaaa-aaaal-qbymq-cai --network=ic
```
-The output will look like this:
+
+Output
```bash
Canister status call result for jqylk-byaaa-aaaal-qbymq-cai.
@@ -67,91 +68,46 @@ Balance: 9_811_813_913_485 Cycles
Module hash: 0xe7866e1949e3688a78d8d29bd63e1c13cd6bfb8fbe29444fa606a20e0b1e33f0
```
-Canisters can check their balance programmatically. For example:
+
+
+Canisters can check their balance programmatically.
-Motoko canisters can use the [ExperimentalCycles library](/docs/current/motoko/main/base/ExperimentalCycles) to interact with cycles:
-
-``` motoko no-repl
-import Cycles "mo:base/ExperimentalCycles";
-import Debug "mo:base/Debug";
-
-actor {
- public func main() : async() {
- Debug.print("Main balance: " # debug_show(Cycles.balance()));
- };
-}
-```
+Motoko canisters can use the [ExperimentalCycles library](/docs/current/motoko/main/base/ExperimentalCycles) to interact with cycles.
-Rust canisters can use the function `canister_balance128()` from the [Rust IC CDK](https://docs.rs/ic-cdk/latest/ic_cdk/api/fn.canister_balance128.html):
-
-```rust
-let current_canister_balance = ic_cdk::api::canister_balance();
-```
+Rust canisters can use the function `canister_balance128()` from the [Rust IC CDK](https://docs.rs/ic-cdk/latest/ic_cdk/api/fn.canister_balance128.html).
### Option 1: If you have ICP on your account
-If you have ICP on the account associated with a `dfx` identity, you can convert ICP into cycles, then top up a canister with those cycles:
-
-```bash
-dfx ledger account-id
-dfx ledger balance --network ic
-dfx ledger top-up --icp 1 jqylk-byaaa-aaaal-qbymq-cai --network ic
-```
-
-- The `dfx ledger account-id` returns the ledger account ID of the current `dfx` identity used.
-- The `dfx ledger --network ic balance` command checks the balance on the `account` associated with the current `dfx` identity used.
-- `top-up --icp 1 jqylk-byaaa-aaaal-qbymq-cai` command converts 1 ICP into cycles and uses them to refill canister `jqylk-byaaa-aaaal-qbymq-cai`.
-- `--network ic` tells `dfx` to use the mainnet as the network (rather than the local replica).
+If you have ICP associated with your [developer identity](/docs/current/developer-docs/getting-started/identities) you can use [`dfx ledger top-up`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-ledger) to convert some ICP into cycles, then top up a canister with those cycles:
### Option 2: If you have cycles
-If you already have cycles, you can top up a canister with the command `dfx cycles top-up `:
+If you already have cycles, you can top up a canister with the command [`dfx cycles top-up`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-cycles#dfx-cycles-top-up):
```bash
-dfx cycles balance --network ic
dfx cycles top-up jqylk-byaaa-aaaal-qbymq-cai 1T --network ic
```
-:::warning
-This workflow uses the cycles ledger, a feature that requires `dfx` version `0.19.0`. To enable this feature, you will need to set the following environmental variable:
-
-```bash
-DFX_CYCLES_LEDGER_SUPPORT_ENABLE=1
-```
-:::
-
-- The `cycles balance --network ic` command checks the cycles balance of your identity on the mainnet.
-- The `cycles top-up` command transfers cycles to the canister of your choice.
-
### Special case: topping up a cycles wallet
-:::info
-Please note that the cycles wallet will be removed from `dfx` in a future release.
+:::danger
+The cycles wallet will be removed from `dfx` in a future release.
It is recommended to use the cycles ledger instead.
:::
-Cycles wallets are canisters like any other, so you can top them up as well. If you have a cycles wallet you control via dfx, there is another option as well for sending cycles from your cycles wallet to a canister of your choice: `dfx wallet send [OPTIONS] `.
+Cycles wallets are canisters like any other. If you have a cycles wallet you control via `dfx`, there is another option for sending cycles from your cycles wallet to a canister of your choice: [`dfx wallet send [OPTIONS] `](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-wallet#dfx-wallet-send).
-In this example, it is assumed you are sending cycles to a cycles wallet with the principal ID `dfds-sddds-aaaal-qbsms-cai`.
-
-```bash
-dfx wallet balance --network ic
-dfx wallet send 1T dfds-sddds-aaaal-qbsms-cai --network ic
-```
-
-- The `wallet balance --network ic` checks the cycles balance of your cycles wallet on the mainnet.
-- The `wallet send 1T dfds-sddds-aaaal-qbsms-cai --network ic` takes one trillion cycles from your cycles wallet and sends them to cycles wallet `dfds-sddds-aaaal-qbsms-cai`.
## Topping up a canister with the NNS frontend dapp
@@ -167,26 +123,4 @@ You can also top up any canister via the [NNS frontend dapp](https://nns.ic0.app
ICP features a mechanism to prevent canisters from running out of cycles. Canisters have a configurable `freezing_threshold`, dynamically evaluated in cycles.
-In the output of the `dfx canister status` command, you may have noticed the `freezing threshold` value. The freezing threshold is a value defined in seconds, which is used to calculate how many cycles a canister must retain in its cycles balance. This calculation is based on the canister's memory consumption. The default freezing threshold value is `2_592_000s`, which corresponds to 30 days.
-
-The freezing threshold is important because if a canister runs out of cycles, it will be uninstalled. The freezing threshold protects it from deletion since if the cycles balance dips below the threshold, the canister will stop processing any new requests; however, it will continue to reply to existing requests.
-
-For example, to set a freezing threshold for your `poll_backend` canister, use the command:
-
-```
-dfx canister update-settings poll_backend --freezing-threshold 3472000
-```
-
-Then, confirm that this threshold has been set by running the `dfx canister status poll_backend --network ic ` command again:
-
-```bash
-Canister status call result for poll_backend.
-Status: Stopped
-Controllers: lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
-Memory allocation: 0
-Compute allocation: 0
-Freezing threshold: 3_472_000
-Memory Size: Nat(2363181)
-Balance: 3_100_000_000_000 Cycles
-Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
-```
+[Learn more about freezing thresholds](/docs/current/developer-docs/smart-contracts/maintain/settings#freezing-threshold).
diff --git a/docs/developer-docs/smart-contracts/write/overview.mdx b/docs/developer-docs/smart-contracts/write/overview.mdx
index fdc353021e..fb24557f70 100644
--- a/docs/developer-docs/smart-contracts/write/overview.mdx
+++ b/docs/developer-docs/smart-contracts/write/overview.mdx
@@ -58,7 +58,7 @@ The typical development workflow of the frontend is:
3. The developer deploys the project. `dfx` will compile the frontend asset files into an asset canister.
4. Users open the application in the browser by navigating to the URL `https://.icp0.io` or a [custom domain](/docs/current/developer-docs/web-apps/custom-domains/using-custom-domains) if one has been registered for the canister.
5. The canister serves the web assets to the browser via its `http_request` endpoint that gets invoked for each HTTP request.
-6. When the JS code runs in the browser, it can call the backend canister endpoints using the [ICP JavaScript agent](/docs/current/developer-docs/web-apps/browser-js/js-request-api) library, which is analogous to `web3.js` and `ethers.js` of Ethereum.
+6. When the JS code runs in the browser, it can call the backend canister endpoints using the [ICP JavaScript agent](/docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent) library, which is analogous to `web3.js` and `ethers.js` of Ethereum.
#### Limitations
Server-side rendering (SSR) does not work in canisters because they require JS code that is not built into canisters.
@@ -107,7 +107,7 @@ Navigate into your project directory:
cd hello
```
-For projects created with `dfx new`, the project structure will resemble the following. If you are using an ICP Ninja project or other sample project, project structure may vary.
+For projects created with `dfx new`, the project structure will resemble the following. If you are using an ICP Ninja project or other sample project, project structure may vary.
@@ -226,7 +226,7 @@ In this directory, the following files and directories are notable:
### Reviewing the default program code
-Open the backend canister source code file in your code editor. The backend canister's code will be located in the `src/hello_backend` subdirectory. For projects created with `dfx new`, the default backend code will resemble the following. If you are using an ICP Ninja project or other sample project, program code will vary.
+Open the backend canister source code file in your code editor. The backend canister's code will be located in the `src/hello_backend` subdirectory. For projects created with `dfx new`, the default backend code will resemble the following. If you are using an ICP Ninja project or other sample project, program code will vary.
diff --git a/docs/developer-docs/web-apps/application-frontends/overview.mdx b/docs/developer-docs/web-apps/application-frontends/overview.mdx
index e2283a9d12..3c88956dad 100644
--- a/docs/developer-docs/web-apps/application-frontends/overview.mdx
+++ b/docs/developer-docs/web-apps/application-frontends/overview.mdx
@@ -21,7 +21,7 @@ Application frontends exist in the following forms:
- A frontend canister that communicates with backend canister(s) to provide a full-stack dapp.
-- Backend canisters that communicate with an external frontend application that isn't hosted on ICP. To facilitate this communication, [the ICP JavaScript agent](/docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent) can be used. [Learn more about the JS request API](/docs/current/developer-docs/web-apps/browser-js/js-request-api).
+- Backend canisters that communicate with an external frontend application that isn't hosted on ICP. To facilitate this communication, [the ICP JavaScript agent](/docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent) can be used. [Learn more about the JS request API](/docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent).
- A frontend canister that doesn't communicate with any backend canisters and only provides web assets.
diff --git a/docs/developer-docs/web-apps/browser-js/js-request-api.mdx b/docs/developer-docs/web-apps/browser-js/js-request-api.mdx
deleted file mode 100644
index 2e27a28d9a..0000000000
--- a/docs/developer-docs/web-apps/browser-js/js-request-api.mdx
+++ /dev/null
@@ -1,78 +0,0 @@
----
-keywords: [intermediate, browser js, javascript, ICP JavaScript agent, agents]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# JavaScript request API
-
-
-
-## Overview
-
-To make API calls to ICP endpoints and canisters from a JavaScript program, the ICP JavaScript agent can be used. It provides call, query, and readState methods to an actor.
-
-## Install the ICP JavaScript agent
-
-To install the [ICP JavaScript agent](https://www.npmjs.com/package/@dfinity/agent) with `npm`, use the command:
-
-```
-npm i --save @dfinity/agent
-```
-
-## Import the ICP JavaScript agent in the browser
-
-To import the [ICP JavaScript agent](https://www.npmjs.com/package/@dfinity/agent) in the browser, use the import statement:
-
-```
-import * as agent from "@dfinity/agent";
-```
-
-You can also use individual exports:
-
-```
-import { Actor, HttpAgent } from '@dfinity/agent';
-```
-
-## Making API calls
-
-To make API calls, the [ICP JavaScript agent](https://www.npmjs.com/package/@dfinity/agent) uses the [`fetch`](https://www.npmjs.com/package/isomorphic-fetch) API. Here is an example:
-
-```javascript
-import fetch from 'isomorphic-fetch';
-import { HttpAgent } from '@dfinity/agent';
-
-const host = process.env.DFX_NETWORK === 'local' ? 'http://127.0.0.1:4943' : 'https://icp-api.io';
-
-const agent = new HttpAgent({ fetch, host });
-```
-
-This example includes a `host` option, since the agent will not be able to determine the host using the global context.
-
-You can also pass `fetchOptions` to the agent's constructor, such as a custom header:
-
-```javascript
-import fetch from 'isomorphic-fetch';
-import { HttpAgent } from '@dfinity/agent';
-
-const host = process.env.DFX_NETWORK === 'local' ? 'http://127.0.0.1:4943' : 'https://ic0.app';
-
-/**
- * @type {RequestInit}
- */
-const fetchOptions = {
- headers: {
- 'X-Custom-Header': 'value',
- },
-};
-
-const agent = new HttpAgent({ fetch, host, fetchOptions });
-```
-## ICP JavaScript agent documentation
-
-To learn more about the [ICP JavaScript agent](https://www.npmjs.com/package/@dfinity/agent), check out the [ICP JavaScript agent documentation page](/docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent).
-
-
-## Resources
-
-You can learn more about using the ICP JavaScript agent to make API calls in the [API documentation](https://agent-js.icp.xyz/agent/index.html).
\ No newline at end of file
diff --git a/docs/developer-docs/web-apps/custom-domains/dns-setup.mdx b/docs/developer-docs/web-apps/custom-domains/dns-setup.mdx
index cdc3f73de0..d5ab678687 100644
--- a/docs/developer-docs/web-apps/custom-domains/dns-setup.mdx
+++ b/docs/developer-docs/web-apps/custom-domains/dns-setup.mdx
@@ -58,7 +58,7 @@ The resulting configuration should look similar to the following screenshot:
![DNS Configuration for `example.ic-domain.live` on Namecheap](namecheap-subdomain.png)
-Now, you are all set to register your custom domain with the boundary nodes, and you can continue with step 2 of the [general custom domains instructions](using-custom-domains#custom-domains-on-the-boundary-nodes).
+Now, you are all set to register your custom domain with the boundary nodes, and you can continue with step 2 of the [general custom domains instructions](./using-custom-domains#custom-domains-on-the-boundary-nodes).
## GoDaddy
@@ -171,7 +171,7 @@ The resulting configuration should look similar to the following screenshot:
![DNS Configuration for `example.ic-domain.live` on GoDaddy](godaddy-subdomain.png)
-Now, you are all set to register your custom domain with the boundary nodes, and you can continue with step 2 of the [general custom domains instructions](using-custom-domains#custom-domains-on-the-boundary-nodes).
+Now, you are all set to register your custom domain with the boundary nodes, and you can continue with step 2 of the [general custom domains instructions](./using-custom-domains#custom-domains-on-the-boundary-nodes).
## Amazon Route 53
@@ -201,4 +201,4 @@ The resulting configuration should look similar to the following screenshot:
![DNS Configuration for `example.ic-domain.live` on Amazon Route 53](route53-subdomain.png)
-Now, you are all set to register your custom domain with the boundary nodes, and you can continue with step 2 of the [general custom domains instructions](using-custom-domains#custom-domains-on-the-boundary-nodes).
+Now, you are all set to register your custom domain with the boundary nodes, and you can continue with step 2 of the [general custom domains instructions](./using-custom-domains#custom-domains-on-the-boundary-nodes).
diff --git a/docs/developer-docs/web-apps/design-dapps.mdx b/docs/developer-docs/web-apps/design-dapps.mdx
deleted file mode 100644
index 8709825343..0000000000
--- a/docs/developer-docs/web-apps/design-dapps.mdx
+++ /dev/null
@@ -1,45 +0,0 @@
----
-keywords: [beginner, concept, dapp design, design considerations]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Dapp design considerations
-
-
-
-## Overview
-
-As you come up with ideas for dapps, you are going to make many design decisions about how to structure and organize your project. On the Internet Computer, there are a few design decisions that you should pay particular attention to as you plan the implementation for your app.
-
-## Single or multiple canister architecture
-
-One of the first decisions you might want to consider when designing your dapp is whether it should be encapsulated in a single canister or consist of multiple canisters.
-
-For example, if you are writing a simple service with no frontend, you might want to use a single canister to simplify project management and maintenance and focus on adding features. If your dapp has both frontend assets and backend business logic, your project is likely to consist of at least two canisters, with one canister for managing user interface components and another canister for the backend services the application provides.
-
-In planning, you might also consider placing some common reusable services in their own canister so that they can be imported and called from other more-specialized canisters or made available for other developers to use. The [LinkedUp](https://github.com/dfinity/linkedup) sample dapp illustrates this approach by splitting the professional service dapp into two canisters. In the LinkedUp example, the functions that establish social connections are defined in the `connectd` canister and separate from the functions used to set up professional profiles that are defined in the `linkedup` canister. It is easy to imagine extending the dapp with a third canister, for example to schedule events based on profile attributes or shared connections.
-
-## Segregating actors from types and utilities
-
-In planning the architecture for your project, one common practice is to place the code for the main actor in one file with separate additional files for defining the types you program uses and utility functions that don’t require an actor.
-
-For example, you might set up the backend logic for your dapp to consist of the following files:
-
-- `Main.mo` or `main.rs` with the functions that require an actor to send query and update calls.
-
-- `Util.mo` or `util.rs` with helper functions that can be imported for the actor to use.
-
-- `Types.mo` or `types.rs` with all of the data type definitions for your dapp.
-
-## Using query calls
-
-As discussed in [query and update methods](/docs/current/concepts/canisters-code#query-update), queries return results faster than update calls. Therefore, explicitly marking a function as a `query` is an effective strategy for improving application performance. In the planning and design phase, you should consider how best to use query calls instead of functions that can perform queries or updates.
-
-That is a good general rule to follow and can be applied broadly to most categories of dapps. However, you should also consider the security and performance trade-off that queries don’t go through consensus and do not appear on the blockchain. For some dapps, that trade-off might be appropriate. For example, if you are developing a blogging platform, queries that retrieve articles matching a tag probably don’t warrant going through consensus to ensure that a majority of nodes agree on the results. However, if your dapp is retrieving sensitive information—like financial data—you might want more assurance about your results than a basic query provides.
-
-As an alternative to basic queries, the Internet Computer also supports **certified queries**. Certified queries enable you to receive **authenticated responses** that end users can trust. Using certified queries is an advanced technique that is not covered in the tutorials or other developer-focused documentation, but you can learn about how the authentication works and what you need to do to configure your program to return certified data in response to queries in the [IC interface specification](/references/ic-interface-spec.md).
-
-## Data storage and retrieval
-
-The Internet Computer enables you to use **stable memory** to handle long-term data storage—often referred to as orthogonal persistence—and to use **query calls** to retrieve your data. Efficiently retrieving data using one or more keys can typically be achieved by using data structures like hash tables. It is also possible to implement a more traditional database inside a canister.
diff --git a/docs/developer-docs/web-apps/independently-verifying-ic-signatures.mdx b/docs/developer-docs/web-apps/independently-verifying-ic-signatures.mdx
index fb53b2f504..4136775964 100644
--- a/docs/developer-docs/web-apps/independently-verifying-ic-signatures.mdx
+++ b/docs/developer-docs/web-apps/independently-verifying-ic-signatures.mdx
@@ -44,17 +44,17 @@ The call is calculated using the content record, which allows the signature to b
A transaction's signature can be delegated from one key to another. If delegation is used, the `sender_delegation` field contains an array of delegations with the following fields:
-- `delegation` (`map`): A map containing the fields:
+`delegation` (`map`): A map containing the fields:
- - `pubkey` (`blob`): A public key.
+ - `pubkey` (`blob`): A public key.
- - `expiration` (`nat`): The delegation's expiration, defined in nanoseconds analogously to the `ingress_expiry`.
+ - `expiration` (`nat`): The delegation's expiration, defined in nanoseconds analogously to the `ingress_expiry`.
- - `targets` (`array` of `CanisterId`, optional): Sets the delegation to apply only for requests sent to the canisters within the canister list; has a maximum of 1000 canisters.
+ - `targets` (`array` of `CanisterId`, optional): Sets the delegation to apply only for requests sent to the canisters within the canister list; has a maximum of 1000 canisters.
- - `senders` (`array` of `Principal`, optional): Sets the delegation to only apply for requests originating from the principals in the list.
+ - `senders` (`array` of `Principal`, optional): Sets the delegation to only apply for requests originating from the principals in the list.
- - `signature` (`blob`): The signature for the `32-byte` delegation field map, using the 27 bytes `\x1Aic-request-auth-delegation` as the domain separator.
+ - `signature` (`blob`): The signature for the `32-byte` delegation field map, using the 27 bytes `\x1Aic-request-auth-delegation` as the domain separator.
The first delegation in the array has a signature created using the public key corresponding to the `sender_pubkey` field. All subsequent delegations are signed with the public key corresponding to the key contained in the preceding delegation.
@@ -64,15 +64,9 @@ The `sender_sig` field is calculated by concatenating the domain separator, `\x0
To verify a signature with an agent, an accepted identity is required. The following are accepted identity and signature types:
-- Ed25519 and ECDSA signatures.
+- Ed25519 and ECDSA signatures: Plain signatures are supported for these schemes.
- - Plain signatures are supported for the schemes.
-
-- Ed25519 or ECDSA on curve P-256 (also known as secp256r1).
-
- - Using SHA-256 as a hash function.
-
- - Using the Koblitz curve in secp256k1.
+- Ed25519 or ECDSA on curve P-256 (also known as secp256r1): Support for using SHA-256 as a hash function or using the Koblitz curve in secp256k1.
When these identities are encoded as a `Principal`, an agent will attach a suffix byte, which indicates whether the identity is anonymous or self-authenticating.
@@ -125,7 +119,7 @@ match result {
[Reference the crate's implementation logic](https://sourcegraph.com/github.com/dfinity/ic/-/blob/rs/validator/src/ingress_validation.rs?L605) for additional context.
-## Verifying signatures with the library `@dfinity/standalone-sig-verifier-web`
+## Verifying signatures with the JavaScript/TypeScript wrapper `@dfinity/standalone-sig-verifier-web`
An `npm` library has been created as a JavaScript/TypeScript wrapper for the [`ic-standalone-sig-verifier`](https://github.com/dfinity/ic/tree/master/rs/crypto/standalone-sig-verifier) Rust crate.
diff --git a/docs/developer-docs/web-apps/obtain-verify-ic-pubkey.mdx b/docs/developer-docs/web-apps/obtain-verify-ic-pubkey.mdx
deleted file mode 100644
index f973f38922..0000000000
--- a/docs/developer-docs/web-apps/obtain-verify-ic-pubkey.mdx
+++ /dev/null
@@ -1,40 +0,0 @@
----
-keywords: [intermediate, tutorial, verifying public key, obtaining public key, public key, ic public key]
----
-
-import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow";
-
-# Verifying the public key
-
-
-
-## Overview
-
-When a user or canister receives a response from ICP, that response will have a certificate that validates the response has not been altered or changed. This certificate is signed by the root of trust, which is the ICP root public key. This public key can be used to additionally verify that a user or canister is interacting with a version of ICP that has not been tampered with, verifying that the response's certificate is valid.
-
-### Local
-
-In a local canister execution environment, the key can be fetched via the [`/api/v2/status`](/docs/current/references/ic-interface-spec#api-status) endpoint.
-
-### Mainnet
-
-On the mainnet, you can use [the ICP JavaScript agent](https://github.com/dfinity/agent-js) or [agent-rs](https://github.com/dfinity/agent-rs) to fetch the public key, as these agents have the root key [hard-coded](https://github.com/dfinity/agent-js/blob/main/packages/agent/src/agent/proxy.ts#L244C1-L250C2).
-
-## Verifying the public key
-
-Once you have obtained the public key, you can validate it is correct by using `dfx` to ping the network you're using, such as:
-
-```bash
-dfx ping ic // mainnet
-dfx ping local // local canister execution
-```
-
-This ping command will return the public root key of the network specified:
-
-```json
-{
- "ic_api_version": "0.18.0" "replica_health_status": "healthy" "root_key": [48, 129, 130, 48, 29, 6, 13, 43, 6, 1, 4, 1, 130, 220, 124, 5, 3, 1, 2, 1, 6, 12, 43, 6, 1, 4, 1, 130, 220, 124, 5, 3, 2, 1, 3, 97, 0, 129, 76, 14, 110, 199, 31, 171, 88, 59, 8, 189, 129, 55, 60, 37, 92, 60, 55, 27, 46, 132, 134, 60, 152, 164, 241, 224, 139, 116, 35, 93, 20, 251, 93, 156, 12, 213, 70, 217, 104, 95, 145, 58, 12, 11, 44, 197, 52, 21, 131, 191, 75, 67, 146, 228, 103, 219, 150, 214, 91, 155, 180, 203, 113, 113, 18, 248, 71, 46, 13, 90, 77, 20, 80, 95, 253, 116, 132, 176, 18, 145, 9, 28, 95, 135, 185, 136, 131, 70, 63, 152, 9, 26, 11, 170, 174]
-}
-```
-
-
diff --git a/docs/other/updates/release-notes/0.9.2-rn.md b/docs/other/updates/release-notes/0.9.2-rn.md
index 0eb30dbd45..0a29147c98 100644
--- a/docs/other/updates/release-notes/0.9.2-rn.md
+++ b/docs/other/updates/release-notes/0.9.2-rn.md
@@ -2,7 +2,7 @@
An overview of the 0.9.2 release:
-Be sure to see the [0.9.0 Release Notes](0.9.0-rn) and follow the instructions due to breaking changes since dfx 0.8.4.
+Be sure to see the [0.9.0 Release Notes](./0.9.0-rn) and follow the instructions due to breaking changes since dfx 0.8.4.
## Changes to DFX
diff --git a/docs/other/updates/release-notes/sdk-release-notes.md b/docs/other/updates/release-notes/sdk-release-notes.md
index b1044e7e2b..bd12238016 100644
--- a/docs/other/updates/release-notes/sdk-release-notes.md
+++ b/docs/other/updates/release-notes/sdk-release-notes.md
@@ -26,7 +26,7 @@ To see a list of known problems with `dfx` or to report a problem you discovered
Joining the [DFINITY Developer Forum](https://forum.dfinity.org/) is an effective way to learn from community members, ask questions, solicit help from other developers, and provide insight and feedback about your experiences.
-If you have questions that aren’t answered by the community, you might also want to check out [Troubleshooting](/docs/current/developer-docs/smart-contracts/test/troubleshooting) topics for information about common issues, workarounds for known issues, or help troubleshooting warnings or errors.
+If you have questions that aren’t answered by the community, you might also want to check out [Troubleshooting](/docs/current/developer-docs/getting-started/troubleshooting) topics for information about common issues, workarounds for known issues, or help troubleshooting warnings or errors.
For technical support, send email to [DFINITY Support](mailto:support@dfinity.org).
diff --git a/docs/references/id-encoding-spec.mdx b/docs/references/id-encoding-spec.mdx
index 2b0d3ba3ff..f758d88d5d 100644
--- a/docs/references/id-encoding-spec.mdx
+++ b/docs/references/id-encoding-spec.mdx
@@ -57,10 +57,10 @@ Links describing our CRC32 function (resp. the polynomial used therein):
* Table entry “CRC-32” on [Wikipedia](https://en.wikipedia.org/wiki/Cyclic_redundancy_check).
* Row “IEEE 802.3; CRC-32” in [Koopman's database](https://users.ece.cmu.edu/~koopman/crc/crc32.html).
-* Entry “CRC-32/ISO-HDLC” in the [CRC catalogue](http://reveng.sourceforge.net/crc-catalogue/all.htm).
+* Entry “CRC-32/ISO-HDLC” in the [CRC catalogue](https://reveng.sourceforge.net/crc-catalogue/all.htm).
* Row labeled “CRC-32” in this [online calculator](https://crccalc.com/).
-Our CRC32 function is defined by the following parameters in the [CRC catalogue](http://reveng.sourceforge.net/crc-catalogue/all.htm) and [online calculator](https://crccalc.com/):
+Our CRC32 function is defined by the following parameters in the [CRC catalogue](https://reveng.sourceforge.net/crc-catalogue/all.htm) and [online calculator](https://crccalc.com/):
```
diff --git a/docs/tutorials/developer-journey/level-0/01-ic-overview.mdx b/docs/tutorials/developer-journey/level-0/01-ic-overview.mdx
index 394d081e66..cbfb3be778 100644
--- a/docs/tutorials/developer-journey/level-0/01-ic-overview.mdx
+++ b/docs/tutorials/developer-journey/level-0/01-ic-overview.mdx
@@ -148,7 +148,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-0/02-ic-terms.mdx b/docs/tutorials/developer-journey/level-0/02-ic-terms.mdx
index 567d03bc8a..dcfd9fffdd 100644
--- a/docs/tutorials/developer-journey/level-0/02-ic-terms.mdx
+++ b/docs/tutorials/developer-journey/level-0/02-ic-terms.mdx
@@ -108,7 +108,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-0/03-dev-env.mdx b/docs/tutorials/developer-journey/level-0/03-dev-env.mdx
index 21aaca9694..9c0d9e6fca 100644
--- a/docs/tutorials/developer-journey/level-0/03-dev-env.mdx
+++ b/docs/tutorials/developer-journey/level-0/03-dev-env.mdx
@@ -144,7 +144,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-0/04-intro-canisters.mdx b/docs/tutorials/developer-journey/level-0/04-intro-canisters.mdx
index 96cfc37437..ef433d13b7 100644
--- a/docs/tutorials/developer-journey/level-0/04-intro-canisters.mdx
+++ b/docs/tutorials/developer-journey/level-0/04-intro-canisters.mdx
@@ -110,7 +110,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-0/05-intro-languages.mdx b/docs/tutorials/developer-journey/level-0/05-intro-languages.mdx
index a32c27562a..64942b9790 100644
--- a/docs/tutorials/developer-journey/level-0/05-intro-languages.mdx
+++ b/docs/tutorials/developer-journey/level-0/05-intro-languages.mdx
@@ -140,7 +140,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-0/06-intro-dfx.mdx b/docs/tutorials/developer-journey/level-0/06-intro-dfx.mdx
index b20ca4c355..9363851f66 100644
--- a/docs/tutorials/developer-journey/level-0/06-intro-dfx.mdx
+++ b/docs/tutorials/developer-journey/level-0/06-intro-dfx.mdx
@@ -273,7 +273,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-1/1.1-live-demo.mdx b/docs/tutorials/developer-journey/level-1/1.1-live-demo.mdx
index 19ade8ec07..45048c1422 100644
--- a/docs/tutorials/developer-journey/level-1/1.1-live-demo.mdx
+++ b/docs/tutorials/developer-journey/level-1/1.1-live-demo.mdx
@@ -187,7 +187,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.mdx b/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.mdx
index fc9780c46a..1bd3fa8fe4 100644
--- a/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.mdx
+++ b/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.mdx
@@ -326,9 +326,9 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- [Upcoming hackathons](https://dfinity.org/hackathons/).
-- [Weekly developer office hours](https://discord.gg/4a7SZzRk?event=1164114241893187655) to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
+- Weekly developer office hours, hosted on the [ICP Discord](https://discord.internetcomputer.org) server to ask questions, get clarification, and chat with other developers live via voice chat.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-1/1.3-first-dapp.mdx b/docs/tutorials/developer-journey/level-1/1.3-first-dapp.mdx
index bf3df76b22..6c600cf950 100644
--- a/docs/tutorials/developer-journey/level-1/1.3-first-dapp.mdx
+++ b/docs/tutorials/developer-journey/level-1/1.3-first-dapp.mdx
@@ -1035,7 +1035,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-1/1.4-using-cycles.mdx b/docs/tutorials/developer-journey/level-1/1.4-using-cycles.mdx
index 0b751df45e..3e860517f8 100644
--- a/docs/tutorials/developer-journey/level-1/1.4-using-cycles.mdx
+++ b/docs/tutorials/developer-journey/level-1/1.4-using-cycles.mdx
@@ -252,7 +252,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.mdx b/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.mdx
index c15abce0e1..a7908ef799 100644
--- a/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.mdx
+++ b/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.mdx
@@ -153,7 +153,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.mdx b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.mdx
index bc3408e826..ed868ae122 100644
--- a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.mdx
+++ b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.mdx
@@ -429,7 +429,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.mdx b/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.mdx
index c569b1273e..1fdb682f73 100644
--- a/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.mdx
+++ b/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.mdx
@@ -266,7 +266,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.mdx b/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.mdx
index c08daf44e4..a33395e8bb 100644
--- a/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.mdx
+++ b/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.mdx
@@ -284,7 +284,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.mdx b/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.mdx
index a89f1576bd..08f6bb4838 100644
--- a/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.mdx
+++ b/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.mdx
@@ -220,7 +220,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-2/2.4-intro-candid.mdx b/docs/tutorials/developer-journey/level-2/2.4-intro-candid.mdx
index d732fae54f..aff7247042 100644
--- a/docs/tutorials/developer-journey/level-2/2.4-intro-candid.mdx
+++ b/docs/tutorials/developer-journey/level-2/2.4-intro-candid.mdx
@@ -378,7 +378,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-2/2.5-unit-testing.mdx b/docs/tutorials/developer-journey/level-2/2.5-unit-testing.mdx
index d8f5710824..2f17abc20b 100644
--- a/docs/tutorials/developer-journey/level-2/2.5-unit-testing.mdx
+++ b/docs/tutorials/developer-journey/level-2/2.5-unit-testing.mdx
@@ -477,7 +477,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.mdx b/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.mdx
index 68b9daf376..fd256620d3 100644
--- a/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.mdx
+++ b/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.mdx
@@ -451,7 +451,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-3/3.1-package-managers.mdx b/docs/tutorials/developer-journey/level-3/3.1-package-managers.mdx
index 670751d230..62aa662f97 100644
--- a/docs/tutorials/developer-journey/level-3/3.1-package-managers.mdx
+++ b/docs/tutorials/developer-journey/level-3/3.1-package-managers.mdx
@@ -236,7 +236,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.mdx b/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.mdx
index 9c1a657229..2252d3bf31 100644
--- a/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.mdx
+++ b/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.mdx
@@ -847,7 +847,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-3/3.3-certified-data.mdx b/docs/tutorials/developer-journey/level-3/3.3-certified-data.mdx
index 162459fd29..54cf4234af 100644
--- a/docs/tutorials/developer-journey/level-3/3.3-certified-data.mdx
+++ b/docs/tutorials/developer-journey/level-3/3.3-certified-data.mdx
@@ -380,7 +380,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.mdx b/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.mdx
index 8163f35a1c..f69860c7a2 100644
--- a/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.mdx
+++ b/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.mdx
@@ -274,7 +274,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.mdx b/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.mdx
index e592315991..74e931c1e3 100644
--- a/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.mdx
+++ b/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.mdx
@@ -386,7 +386,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.mdx b/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.mdx
index 417aaa827b..1381c7e081 100644
--- a/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.mdx
+++ b/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.mdx
@@ -640,7 +640,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-4/4.1-icp-ledger.mdx b/docs/tutorials/developer-journey/level-4/4.1-icp-ledger.mdx
index b15fe0ce6b..1de4aa6288 100644
--- a/docs/tutorials/developer-journey/level-4/4.1-icp-ledger.mdx
+++ b/docs/tutorials/developer-journey/level-4/4.1-icp-ledger.mdx
@@ -348,7 +348,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-4/4.2-icrc-tokens.mdx b/docs/tutorials/developer-journey/level-4/4.2-icrc-tokens.mdx
index 3edcdd6ce0..a23fdeb212 100644
--- a/docs/tutorials/developer-journey/level-4/4.2-icrc-tokens.mdx
+++ b/docs/tutorials/developer-journey/level-4/4.2-icrc-tokens.mdx
@@ -511,7 +511,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin.mdx b/docs/tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin.mdx
index 7acc981d66..38d44f0ecb 100644
--- a/docs/tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin.mdx
+++ b/docs/tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin.mdx
@@ -362,7 +362,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-4/4.4-nns-governance.mdx b/docs/tutorials/developer-journey/level-4/4.4-nns-governance.mdx
index c1263b3ff6..c50a3b4068 100644
--- a/docs/tutorials/developer-journey/level-4/4.4-nns-governance.mdx
+++ b/docs/tutorials/developer-journey/level-4/4.4-nns-governance.mdx
@@ -305,7 +305,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-4/4.5-using-quill.mdx b/docs/tutorials/developer-journey/level-4/4.5-using-quill.mdx
index 811d8d9991..35f5ba8437 100644
--- a/docs/tutorials/developer-journey/level-4/4.5-using-quill.mdx
+++ b/docs/tutorials/developer-journey/level-4/4.5-using-quill.mdx
@@ -457,7 +457,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-4/4.6-motoko-lvl4.mdx b/docs/tutorials/developer-journey/level-4/4.6-motoko-lvl4.mdx
index 9b1294ef31..6a306ce0eb 100644
--- a/docs/tutorials/developer-journey/level-4/4.6-motoko-lvl4.mdx
+++ b/docs/tutorials/developer-journey/level-4/4.6-motoko-lvl4.mdx
@@ -641,7 +641,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-5/5.1-vetKeys-tutorial.mdx b/docs/tutorials/developer-journey/level-5/5.1-vetKeys-tutorial.mdx
index e44b24c627..15aa03d90e 100644
--- a/docs/tutorials/developer-journey/level-5/5.1-vetKeys-tutorial.mdx
+++ b/docs/tutorials/developer-journey/level-5/5.1-vetKeys-tutorial.mdx
@@ -780,7 +780,7 @@ Then, you can see the note has been saved in the 'Your notes' section:
- [The first Community Conversation](https://youtu.be/baM6jHnmMq8).
-- [vetKeys primer blog post](ttps://internetcomputer.org/blog/features/vetkey-primer).
+- [vetKeys primer blog post](https://internetcomputer.org/blog/features/vetkey-primer).
- [vetKeys research paper](https://eprint.iacr.org/2023/616.pdf).
@@ -807,7 +807,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-5/5.2-ICP-ETH-tutorial.mdx b/docs/tutorials/developer-journey/level-5/5.2-ICP-ETH-tutorial.mdx
index 4156d4d955..16c6e83584 100644
--- a/docs/tutorials/developer-journey/level-5/5.2-ICP-ETH-tutorial.mdx
+++ b/docs/tutorials/developer-journey/level-5/5.2-ICP-ETH-tutorial.mdx
@@ -377,7 +377,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-5/5.3-token-swap-tutorial.mdx b/docs/tutorials/developer-journey/level-5/5.3-token-swap-tutorial.mdx
index c18f873932..3cb68ccaf7 100644
--- a/docs/tutorials/developer-journey/level-5/5.3-token-swap-tutorial.mdx
+++ b/docs/tutorials/developer-journey/level-5/5.3-token-swap-tutorial.mdx
@@ -828,7 +828,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-5/5.4-NFT-tutorial.mdx b/docs/tutorials/developer-journey/level-5/5.4-NFT-tutorial.mdx
index 0fa48340e9..3b994efeae 100644
--- a/docs/tutorials/developer-journey/level-5/5.4-NFT-tutorial.mdx
+++ b/docs/tutorials/developer-journey/level-5/5.4-NFT-tutorial.mdx
@@ -593,7 +593,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-5/5.5-auction-tutorial.mdx b/docs/tutorials/developer-journey/level-5/5.5-auction-tutorial.mdx
index 93dbb9dbe9..4de9493fde 100644
--- a/docs/tutorials/developer-journey/level-5/5.5-auction-tutorial.mdx
+++ b/docs/tutorials/developer-journey/level-5/5.5-auction-tutorial.mdx
@@ -390,7 +390,7 @@ Did you get stuck somewhere in this tutorial, or feel like you need additional h
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
## Next steps
diff --git a/docs/tutorials/developer-journey/level-5/5.6-next-steps.mdx b/docs/tutorials/developer-journey/level-5/5.6-next-steps.mdx
index 31e72e963a..7f54573111 100644
--- a/docs/tutorials/developer-journey/level-5/5.6-next-steps.mdx
+++ b/docs/tutorials/developer-journey/level-5/5.6-next-steps.mdx
@@ -106,4 +106,4 @@ Several of ICP's repositories are open-source, and external contributions are en
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the [Discord](https://discord.internetcomputer.org) server.
-- Submit your feedback to the [ICP Developer feedback board](http://dx.internetcomputer.org).
+- Submit your feedback to the [ICP Developer feedback board](https://dx.internetcomputer.org).
diff --git a/docusaurus.config.js b/docusaurus.config.js
index c7cd65939e..013e249e17 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -38,6 +38,14 @@ const snsDataPlugin = require("./plugins/sns-data");
const airtablePlugin = require("./plugins/airtable");
const youtubePlugin = require("./plugins/youtube");
+const remarkPlugins = [
+ math,
+ simplePlantUML,
+ require("remark-code-import"),
+ require("./plugins/remark/validate-links.js"),
+];
+const rehypePlugins = [katex];
+
const isDeployPreview = !!process.env.PREVIEW_CANISTER_ID;
if (process.env.PREVIEW_CANISTER_ID) {
@@ -86,17 +94,6 @@ const subnavItems = [
},
],
},
- {
- type: "dropdown",
- position: "left",
- label: "Frameworks",
- items: [
- {
- label: "Juno",
- href: "/docs/current/developer-docs/web-apps/frameworks/juno",
- },
- ],
- },
{
type: "dropdown",
position: "left",
@@ -106,13 +103,11 @@ const subnavItems = [
label: "Awesome Internet Computer",
href: "https://github.com/dfinity/awesome-internet-computer#readme",
},
- { label: "Sample Code", to: "/samples" },
{
label: "SDK Release Notes",
type: "doc",
docId: "other/updates/release-notes/release-notes",
},
- { label: "Developer Tools", to: "/tooling" },
{ label: "Developer Grants", href: "https://dfinity.org/grants" },
{
label: "Playground",
@@ -203,6 +198,11 @@ const marketingNav = {
href: "/capabilities/sustainability",
description: "Building green, efficient tech",
},
+ {
+ name: "Library",
+ href: "/library",
+ description: "Resources to get you started",
+ },
/*
{
name: "ICP as a Bitcoin L2",
@@ -656,16 +656,16 @@ const config = {
},
sidebarPath: require.resolve("./sidebars.js"),
- remarkPlugins: [math, simplePlantUML, require("remark-code-import")],
- rehypePlugins: [katex],
+ remarkPlugins,
+ rehypePlugins,
editUrl: "https://github.com/dfinity/portal/edit/master/",
},
blog: {
path: "blog",
blogSidebarCount: "ALL",
postsPerPage: "ALL",
- remarkPlugins: [math, simplePlantUML, require("remark-code-import")],
- rehypePlugins: [katex],
+ remarkPlugins,
+ rehypePlugins,
},
theme: {
customCss: require.resolve("./src/css/custom.scss"),
diff --git a/plugins/airtable.js b/plugins/airtable.js
index ac40986094..822eb98ff9 100644
--- a/plugins/airtable.js
+++ b/plugins/airtable.js
@@ -156,11 +156,21 @@ async function fetchAirtableRecords({ apiKey, baseId, tableName, viewId }) {
}
async function processEventsData(records) {
+ const endDateCutoff = new Date(Date.now() - 6 * 30 * 24 * 60 * 60 * 1000)
+ .toISOString()
+ .split("T")[0];
+
+ const today = new Date().toISOString().split("T")[0];
+
records = await Promise.all(
records.map(async (record) => {
const parsedRecord = parseAirtableData(record);
- let imageUrl = await fetchShareImage(parsedRecord.eventLink);
+ // Only fetch share image for current/future events
+ let imageUrl = null;
+ if (parsedRecord.endDate >= today) {
+ imageUrl = await fetchShareImage(parsedRecord.eventLink);
+ }
// If no share image is found, use a default image
if (!imageUrl) {
@@ -171,10 +181,6 @@ async function processEventsData(records) {
})
);
- const endDatecutoff = new Date(Date.now() - 6 * 30 * 24 * 60 * 60 * 1000)
- .toISOString()
- .split("T")[0];
-
records = records.filter((rec) => {
if (!rec.startDate || new Date(rec.startDate) == "Invalid Date") {
logger.warn("Invalid event, no start date: " + rec.eventName);
@@ -186,7 +192,7 @@ async function processEventsData(records) {
return false;
}
- if (rec.endDate < endDatecutoff) {
+ if (rec.endDate < endDateCutoff) {
// old event
return false;
}
diff --git a/plugins/remark/validate-links.js b/plugins/remark/validate-links.js
new file mode 100644
index 0000000000..c7fb6f2022
--- /dev/null
+++ b/plugins/remark/validate-links.js
@@ -0,0 +1,35 @@
+// Validate links for Kapa.ai
+
+const visit = require("unist-util-visit");
+
+function isExpectedLink(url) {
+ return (
+ url.startsWith("https://") ||
+ url.startsWith("http://localhost") ||
+ url.startsWith("http://127.0.0.1") ||
+ (url.startsWith("http://") && url.includes(".localhost")) ||
+ url.startsWith("chrome://") ||
+ url.startsWith("mailto:") ||
+ url.startsWith("/") ||
+ url.startsWith("#") ||
+ url.startsWith(".")
+ );
+}
+
+module.exports = function validateLinks() {
+ return async (ast) => {
+ visit(ast, "link", (node) => {
+ const url = node.url;
+ if (url.startsWith("docs/developer-docs/")) {
+ throw new Error(
+ `Link requires a leading \`/\` character: \`${url}\` (plugins/remark/validate-links.js)`
+ );
+ }
+ if (!isExpectedLink(url)) {
+ console.warn(
+ `Unexpected link: \`${url}\` (plugins/remark/validate-links.js)`
+ );
+ }
+ });
+ };
+};
diff --git a/plugins/utils/redirects.js b/plugins/utils/redirects.js
index fd63a56ab7..3217b7a205 100644
--- a/plugins/utils/redirects.js
+++ b/plugins/utils/redirects.js
@@ -83,8 +83,8 @@ const redirects = `
/docs/current/developer-docs/build/languages/rust/* /docs/current/developer-docs/backend/rust/
/docs/current/developer-docs/build/project-setup/cycles-wallet /docs/current/developer-docs/defi/cycles/cycles-wallet
/docs/current/developer-docs/build/project-setup/manage-canisters /docs/current/developer-docs/smart-contracts/maintain/settings
- /docs/current/developer-docs/build/project-setup/design-dapps /docs/current/developer-docs/web-apps/design-dapps
- /docs/current/developer-docs/build/troubleshooting /docs/current/developer-docs/smart-contracts/test/troubleshooting
+ /docs/current/developer-docs/build/project-setup/design-dapps /docs/current/developer-docs/smart-contracts/overview/introduction
+ /docs/current/developer-docs/build/troubleshooting /docs/current/developer-docs/getting-started/troubleshooting
/docs/current/developer-docs/build/agents/ /docs/current/developer-docs/developer-tools/off-chain/agents/overview
/docs/current/developer-docs/build/agents/javascript/javascript-intro /docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent
/docs/current/developer-docs/build/agents/javascript/* /docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent
@@ -100,14 +100,14 @@ const redirects = `
/docs/developers-guide/concepts/concepts-intro /docs/current/developer-docs/getting-started/network-overview
/docs/developers-guide/customize-projects /docs/current/developer-docs/smart-contracts/compile
/docs/developers-guide/default-wallet /docs/current/developer-docs/defi/cycles/cycles-wallet
- /docs/developers-guide/design-apps /docs/current/developer-docs/web-apps/design-dapps
+ /docs/developers-guide/design-apps /docs/current/developer-docs/smart-contracts/overview/introduction
/docs/developers-guide/glossary /docs/current/references/glossary
/docs/developers-guide/install-upgrade-remove /docs/current/developer-docs/getting-started/install
/docs/developers-guide/lang-service-ide /docs/current/developer-docs/developer-tools/ide/vs-code
/docs/developers-guide/reinstalling-dfx /docs/current/developer-docs/getting-started/install
/docs/developers-guide/sample-apps /samples
/docs/developers-guide/sdk-guide /docs/current/developer-docs/getting-started/install
- /docs/developers-guide/troubleshooting /docs/current/developer-docs/smart-contracts/test/troubleshooting
+ /docs/developers-guide/troubleshooting /docs/current/developer-docs/getting-started/troubleshooting
/docs/developers-guide/tutorials-intro /docs/current/motoko/main/getting-started/motoko-introduction
/docs/developers-guide/tutorials/default-frontend /docs/current/developer-docs/web-apps/application-frontends/default-frontend
/docs/developers-guide/tutorials/my-contacts /docs/current/developer-docs/web-apps/application-frontends/add-stylesheet
@@ -327,7 +327,7 @@ const redirects = `
/docs/current/developer-docs/setup/pocket-ic /docs/current/developer-docs/smart-contracts/test/pocket-ic
/docs/current/developer-docs/production/staging-environment /docs/current/developer-docs/smart-contracts/deploy/custom-testnets
/docs/current/developer-docs/backend/reproducible-builds /docs/current/developer-docs/smart-contracts/best-practices/reproducible-builds
- /docs/current/developer-docs/backend/troubleshooting /docs/current/developer-docs/smart-contracts/test/troubleshooting
+ /docs/current/developer-docs/backend/troubleshooting /docs/current/developer-docs/getting-started/troubleshooting
/docs/current/developer-docs/integrations/t-ecdsa /docs/current/developer-docs/smart-contracts/signatures/t-ecdsa
/docs/current/developer-docs/integrations/vetkeys/ /docs/current/developer-docs/smart-contracts/encryption/vetkeys
/docs/current/developer-docs/integrations/vetkeys/using-vetkeys /docs/current/developer-docs/smart-contracts/encryption/using-vetkeys
@@ -345,7 +345,7 @@ const redirects = `
/docs/current/developer-docs/frontend/existing-frontend /docs/current/developer-docs/web-apps/application-frontends/existing-frontend
/docs/current/developer-docs/production/custom-domain/ /docs/current/developer-docs/web-apps/custom-domains/using-custom-domains
/docs/current/developer-docs/production/custom-domain/dns-setup /docs/current/developer-docs/web-apps/custom-domains/dns-setup
- /docs/current/developer-docs/backend/design-dapps /docs/current/developer-docs/web-apps/design-dapps
+ /docs/current/developer-docs/backend/design-dapps /docs/current/developer-docs/smart-contracts/overview/introduction
/docs/current/developer-docs/integrations/independently-verifying-ic-signatures /docs/current/developer-docs/web-apps/independently-verifying-ic-signatures
/docs/current/developer-docs/integrations/internet-identity/overview /docs/current/developer-docs/identity/internet-identity/overview
/docs/current/developer-docs/integrations/internet-identity/creating-ii /docs/current/developer-docs/identity/internet-identity/creating-ii
@@ -419,7 +419,7 @@ const redirects = `
/docs/current/developer-docs/integrations/bitcoin/local-development /docs/current/developer-docs/multi-chain/bitcoin/using-btc/local-development
/docs/current/developer-docs/integrations/ethereum/overview /docs/current/developer-docs/multi-chain/ethereum/overview
/docs/current/developer-docs/integrations/ethereum/evm-rpc /docs/current/developer-docs/multi-chain/ethereum/evm-rpc/evm-rpc-canister
- /docs/current/developer-docs/integrations/ethereum/siwe /docs/current/developer-docs/identity/authentication/siwe
+ /docs/current/developer-docs/integrations/ethereum/siwe /docs/current/developer-docs/identity/authentication/overview
/docs/current/developer-docs/integrations/bitcoin/bitcoin-how-it-works /docs/current/references/bitcoin-how-it-works
/docs/current/developer-docs/integrations/bitcoin/ckbtc-reference /docs/current/references/ckbtc-reference
/docs/current/developer-docs/integrations/https-outcalls/https-outcalls-how-it-works /docs/current/references/https-outcalls-how-it-works
@@ -445,7 +445,7 @@ const redirects = `
/docs/current/developer-docs/smart-contracts/overview/development-cycle /docs/current/developer-docs/smart-contracts/overview/canister-lifecycle
/docs/current/developer-docs/web-apps/user-login/internet-identity/integrate-identity /docs/current/developer-docs/identity/internet-identity/integrate-internet-identity
/docs/current/developer-docs/multi-chain/ethereum/cketh /docs/current/developer-docs/multi-chain/chain-key-tokens/cketh/overview
- /docs/current/developer-docs/multi-chain/ethereum/siwe /docs/current/developer-docs/identity/authentication/siwe
+ /docs/current/developer-docs/multi-chain/ethereum/siwe /docs/current/developer-docs/identity/authentication/overview
/docs/current/developer-docs/multi-chain/bitcoin/ckbtc /docs/current/developer-docs/multi-chain/chain-key-tokens/ckbtc/overview
/docs/current/developer-docs/multi-chain/bitcoin/read-state /docs/current/developer-docs/multi-chain/bitcoin/using-btc/read-state
/docs/current/developer-docs/multi-chain/bitcoin/submit-transactions /docs/current/developer-docs/multi-chain/bitcoin/using-btc/submit-transactions
@@ -522,9 +522,9 @@ const redirects = `
/docs/current/developer-docs/web-apps/user-login/internet-identity/creating-ii /docs/current/developer-docs/identity/internet-identity/creating-ii
/docs/current/developer-docs/web-apps/user-login/internet-identity/integrate-internet-identity /docs/current/developer-docs/identity/internet-identity/integrate-internet-identity
/docs/current/developer-docs/web-apps/user-login/internet-identity/alternative-origins /docs/current/developer-docs/identity/internet-identity/alternative-origins
- /docs/current/developer-docs/web-apps/user-login/nfid /docs/current/developer-docs/identity/authentication/nfid
- /docs/current/developer-docs/web-apps/user-login/email-password /docs/current/developer-docs/identity/authentication/email-password
- /docs/current/developer-docs/multi-chain/ethereum/using-eth/siwe /docs/current/developer-docs/identity/authentication/siwe
+ /docs/current/developer-docs/web-apps/user-login/nfid /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/web-apps/user-login/email-password /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/multi-chain/ethereum/using-eth/siwe /docs/current/developer-docs/identity/authentication/overview
/docs/current/developer-docs/build/cdks/motoko-dfinity/motoko/ /docs/current/motoko/main/getting-started/motoko-introduction
/docs/current/developer-docs/defi/icrc-1/icrc1-index-setup /docs/current/developer-docs/defi/tokens/indexes
/docs/current/defi/icp-tokens/icp-index-local-setup /docs/current/developer-docs/defi/tokens/indexes
@@ -639,8 +639,24 @@ const redirects = `
/docs/current/developer-docs/getting-started/deploy/local /docs/current/developer-docs/getting-started/deploy-and-manage
/docs/current/developer-docs/getting-started/deploy/testnet /docs/current/developer-docs/getting-started/deploy-and-manage
/docs/current/developer-docs/getting-started/deploy-and-manage /docs/current/developer-docs/getting-started/deploy-and-manage
+ /docs/current/developer-docs/smart-contracts/test/troubleshooting /docs/current/developer-docs/getting-started/troubleshooting
+ /docs/current/developer-docs/smart-contracts/advanced-features/http-gateways /docs/current/developer-docs/smart-contracts/advanced-features/handling-get-post-requests
+ /docs/current/developer-docs/smart-contracts/advanced-features/serving-http-request /docs/current/developer-docs/smart-contracts/advanced-features/handling-get-post-requests
/docs/current/developer-docs/smart-contracts/write/default-template /docs/current/developer-docs/smart-contracts/write/overview
/developers /docs/current/home
+ /docs/current/developer-docs/identity/authentication/email-password /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/identity/authentication/nfid /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/identity/authentication/siwb /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/identity/authentication/siwe /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/identity/authentication/siws /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/identity/authentication/msq /docs/current/developer-docs/identity/authentication/overview
+ /docs/current/developer-docs/web-apps/browser-js/js-request-api /docs/current/developer-docs/developer-tools/off-chain/agents/javascript-agent
+ /docs/current/developer-docs/defi/tokens/asset_flow/index /docs/current/developer-docs/defi/overview
+ /docs/current/developer-docs/defi/tokens/ledger/overview /docs/current/developer-docs/defi/overview
+ /docs/current/developer-docs/defi/tokens/ledger/setup/overview /docs/current/developer-docs/defi/overview
+ /docs/current/developer-docs/defi/tokens/ledger/usage/overview /docs/current/developer-docs/defi/overview
+ /docs/current/developer-docs/web-apps/obtain-verify-ic-pubkey /docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-ping
+ /docs/current/developer-docs/web-apps/design-dapps /docs/current/developer-docs/smart-contracts/overview/introduction
`
.split(/[\r\n]+/)
.map((line) => line.trim().replace(/^#.*$/, "").trim())
diff --git a/roadmap/entries/data-decentralization.json b/roadmap/entries/data-decentralization.json
index d44f59a9b9..bf2f768e0e 100644
--- a/roadmap/entries/data-decentralization.json
+++ b/roadmap/entries/data-decentralization.json
@@ -14,21 +14,23 @@
"in_beta": false
},
{
- "title": "API Boundary Nodes (NNS controlled)",
- "overview": "In the new boundary-node architecture, API boundary nodes are placed under the full control of the NNS and function as the edge of the IC.",
- "status": "in_progress",
+ "title": "HTTP Gateways",
+ "overview": "The HTTP Gateway becomes a standalone component as part of the new Boundary Node architecture.",
"forum": "https://forum.dfinity.org/t/boundary-node-roadmap/15562",
"proposal": "https://dashboard.internetcomputer.org/proposal/35671",
"docs": "",
+ "eta": "",
+ "status": "in_progress",
"is_community": false,
"in_beta": false,
- "milestone_id": "Solenoid"
+ "milestone_id": "Solenoid",
+ "imported": true
},
{
- "title": "HTTP Gateways",
- "overview": "The HTTP Gateway becomes a standalone component as part of the new Boundary Node architecture.",
- "forum": "https://forum.dfinity.org/t/boundary-node-roadmap/15562",
- "proposal": "https://dashboard.internetcomputer.org/proposal/35671",
+ "title": "Incident Handling under the New Boundary Node Architecture",
+ "overview": "To protect the core of the Internet Computer, processes must be established to configure temporary rate limits at API boundary nodes during incidents.",
+ "forum": "https://forum.dfinity.org/t/incident-handling-with-the-new-boundary-node-architecture/36390",
+ "proposal": "https://dashboard.internetcomputer.org/proposal/134031",
"docs": "",
"eta": "",
"status": "in_progress",
@@ -42,9 +44,9 @@
"overview": "As part of the new boundary-node architecture, the HTTP gateway is turned into a standalone service, which is easily deployable by anyone, including end users.",
"forum": "https://forum.dfinity.org/t/boundary-node-roadmap/15562",
"proposal": "https://dashboard.internetcomputer.org/proposal/35671",
- "docs": "",
+ "docs": "https://github.com/dfinity/ic-gateway",
"eta": "",
- "status": "upcoming",
+ "status": "in_progress",
"is_community": false,
"in_beta": false,
"milestone_id": "Solenoid"
@@ -55,8 +57,8 @@
"description": "ICP is accessible through a decentralized edge infrastructure, which is split into NNS-controlled API Boundary Nodes and HTTP Gateways. The NNS will appoint node machines to run API Boundary Nodes and anyone will be able to run HTTP Gateways, enabling a much more decentralized ICP edge infrastructure with a diverse set of service providers.",
"milestone_id": "Solenoid",
"status": "in_progress",
- "eta": "Q2 2024",
- "eta_to_render": "December 2024"
+ "eta": "Q1 2025",
+ "eta_to_render": "January 2025"
},
{
"title": "SEV-SNP-protected API Boundary Nodes",
@@ -113,17 +115,6 @@
"is_community": false,
"in_beta": false
},
- {
- "title": "Public access to a subset of node metrics",
- "overview": "Giving node providers access to a subnet of node metrics to help them find out what is failing in case of node issues.",
- "forum": "",
- "proposal": "",
- "docs": "",
- "eta": "",
- "status": "in_progress",
- "is_community": false,
- "in_beta": false
- },
{
"title": "Off-chain observability stack for Node Providers",
"overview": "Observability solution for Node Providers to enable them to independently triage node health and take corrective action in case of problems.",
@@ -137,16 +128,15 @@
"imported": true
},
{
- "title": "Alerting of NP in case of Node Failure",
- "overview": "Alert Node Providers if one of their nodes starts misbehaving or underperforming.",
- "forum": "",
+ "title": "Performance-based node provider rewards",
+ "overview": "Node rewards are awarded according to the node's contributions to the protocol, based on trustworthy node metrics, which are provided and signed by the IC network itself. This creates a cryptoeconomic incentive to encourage honest node provider behaviour.",
+ "forum": "https://forum.dfinity.org/t/performance-based-node-rewards/35208",
"proposal": "",
"docs": "",
"eta": "",
"status": "in_progress",
- "is_community": true,
- "in_beta": false,
- "imported": true
+ "is_community": false,
+ "in_beta": false
},
{
"title": "HTTP Asset Caching",
@@ -218,18 +208,7 @@
{
"title": "Strengthened node provider checks and audits",
"overview": "Strengthening the checks of entities intending to join ICP as node providers. May also include node provider audits.",
- "forum": "",
- "proposal": "",
- "docs": "",
- "eta": "",
- "status": "",
- "is_community": false,
- "in_beta": false
- },
- {
- "title": "Penalties for non-compliant node providers",
- "overview": "Non-compliant node providers are penalized economically or excluded from future network participation. This creates a cryptoeconomic incentive to encourage honest node provider behaviour.",
- "forum": "",
+ "forum": "https://forum.dfinity.org/t/technical-working-group-node-providers/30255",
"proposal": "",
"docs": "",
"eta": "",
@@ -270,18 +249,6 @@
"is_community": false,
"in_beta": false
},
- {
- "title": "Decentralized virtual personhood validation",
- "overview": "Scalable, decentralized, virtual proof of personhood to distinguish people from machines.",
- "forum": "https://forum.dfinity.org/t/long-term-r-d-people-parties-proof-of-human-proposal/9636",
- "proposal": "https://dashboard.internetcomputer.org/proposal/35668",
- "docs": "",
- "eta": "",
- "status": "",
- "is_community": false,
- "in_beta": false,
- "imported": true
- },
{
"title": "Public contributions to IC repository",
"overview": "Allowing for contributions by the public to the IC source code repository.",
diff --git a/roadmap/entries/data-digital_assets.json b/roadmap/entries/data-digital_assets.json
index 83836b7ef8..4febddec6f 100644
--- a/roadmap/entries/data-digital_assets.json
+++ b/roadmap/entries/data-digital_assets.json
@@ -84,7 +84,7 @@
"milestone_id": "Poloidal",
"status": "in_progress",
"eta": "",
- "eta_to_render": "January 2025"
+ "eta_to_render": "February 2025"
},
{
"title": "Rosetta for ICRC ledgers",
diff --git a/roadmap/entries/data-governance.json b/roadmap/entries/data-governance.json
index 481bc3aa19..36a28319ba 100644
--- a/roadmap/entries/data-governance.json
+++ b/roadmap/entries/data-governance.json
@@ -9,7 +9,7 @@
"milestone_id": "Plasma",
"status": "in_progress",
"eta": "",
- "eta_to_render": "November 2024"
+ "eta_to_render": "January 2025"
},
{
@@ -132,7 +132,7 @@
"proposal": "",
"docs": "",
"eta": "",
- "status": "in_progress",
+ "status": "deployed",
"is_community": true,
"in_beta": false,
"milestone_id": "Plasma"
diff --git a/roadmap/entries/deployed-decentralization.json b/roadmap/entries/deployed-decentralization.json
index ea6d97aa36..7dd642dd7b 100644
--- a/roadmap/entries/deployed-decentralization.json
+++ b/roadmap/entries/deployed-decentralization.json
@@ -119,6 +119,40 @@
"is_community": false,
"in_beta": false,
"imported": true
+ },
+ {
+ "title": "Alerting of Node Providers in case of Node Failure",
+ "overview": "Alert Node Providers if one of their nodes starts misbehaving or underperforming.",
+ "forum": "",
+ "proposal": "",
+ "docs": "https://wiki.internetcomputer.org/wiki/Node_Provider_Alerting_Options",
+ "eta": "",
+ "status": "deployed",
+ "is_community": true,
+ "in_beta": false,
+ "imported": true
+ },
+ {
+ "title": "Public access to a subset of node metrics",
+ "overview": "Giving node providers access to a subset of node metrics to help them find out in a fully decentralized manner whether nodes are behaving well, and to roughly compare node performance.",
+ "forum": "https://forum.dfinity.org/t/public-internet-computer-ic-node-metrics-available-now/32961",
+ "proposal": "",
+ "docs": "https://github.com/dfinity/ic-observability-stack",
+ "eta": "",
+ "status": "deployed",
+ "is_community": false,
+ "in_beta": false
+ },
+ {
+ "title": "API Boundary Nodes (NNS controlled)",
+ "overview": "In the new boundary-node architecture, API boundary nodes are placed under the full control of the NNS and function as the edge of the IC.",
+ "status": "deployed",
+ "forum": "https://forum.dfinity.org/t/boundary-node-roadmap/15562",
+ "proposal": "https://dashboard.internetcomputer.org/proposal/35671",
+ "docs": "https://github.com/dfinity/ic/tree/master/rs/boundary_node/ic_boundary",
+ "is_community": false,
+ "in_beta": false,
+ "milestone_id": "Solenoid"
}
]
-}
\ No newline at end of file
+}
diff --git a/roadmap/roadmap.json b/roadmap/roadmap.json
index a2341fa69a..986f2844bd 100644
--- a/roadmap/roadmap.json
+++ b/roadmap/roadmap.json
@@ -2373,6 +2373,48 @@
"name": "Digital Assets",
"description": "DeFi protocols, real-word asset tokenization, and other digital asset solutions are strong drivers of web3 adoption. ICP’s Chain Fusion capabilities, unparalleled scalability, and the ability to serve web assets from chain opens up novel digital asset classes. Moreover, it makes ICP an attractive platform to build multi chain custody solutions and wallets.",
"milestones": [
+ {
+ "name": "OISY Wallet v1.0 - The official Launch",
+ "milestone_id": "Helios",
+ "description": "With the Helios release, officially named v1.0, OISY will step out of the beta status into its first production version. This includes functional coverage of all key features like buy, receive, send, swap, and convert from and to chain-key tokens, and with several major blockchains integrated, also a true multi-chain nature. Behind the scenes, it also includes setting up proper processes for product improvement, marketing, automated testing, and setting up a user friendly support process.",
+ "eta": "January 2025",
+ "status": "in_progress",
+ "elements": [
+ {
+ "title": "Solana Integration",
+ "overview": "OISY widens its multi-chain reach beyond Bitcoin and Ethereum, and will integrate with the most important networks. Solana is the first one to be implemented, a crucial step forward in our mission to deliver a true multi-chain wallet for decentralized finance (DeFi) users.",
+ "status": "in_progress",
+ "forum": "",
+ "proposal": "",
+ "docs": "",
+ "is_community": false,
+ "in_beta": false,
+ "milestone_id": "Helios"
+ },
+ {
+ "title": "In-Wallet Swaps",
+ "overview": "Introducing in-wallet swaps, this release will enhance flexibility for managing assets, allowing users to seamlessly change their asset allocation directly in OISY using DEX liquidity, mitigating risk or aiming for a higher yield.",
+ "status": "in_progress",
+ "forum": "",
+ "proposal": "",
+ "docs": "",
+ "is_community": false,
+ "in_beta": false,
+ "milestone_id": "Helios"
+ },
+ {
+ "title": "Promote Chain-Key Tokens",
+ "overview": "With improved screens, flows, and helper texts for chain fusion conversions, OISY will provide users with the right information at the right places to make informed decisions to easily convert native tokens into their chain fusion twins or vice versa.",
+ "status": "in_progress",
+ "forum": "",
+ "proposal": "",
+ "docs": "",
+ "is_community": false,
+ "in_beta": false,
+ "milestone_id": "Helios"
+ }
+ ]
+ },
{
"name": "The Orbit Multi-Custody Asset Framework",
"milestone_id": "Poloidal",
diff --git a/scripts/clean-showcase.sh b/scripts/clean-showcase.sh
new file mode 100755
index 0000000000..ee568cb178
--- /dev/null
+++ b/scripts/clean-showcase.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# The objective of this script is to flag entries to be removed by a human reviewer.
+# An entry is flagged if it meets one of the next requirements:
+# 1. The `usesInternetIdentity` field is set to `true` and the `website` field is a GitHub URL.
+# 2. The website is unreachable (HTTP status code in the 4XX or 5XX range).
+
+# Input JSON file
+INPUT_FILE="showcase.json"
+
+# Temporary file to store intermediate results
+TEMP_FILE="temp.json"
+TEMP_FILE_2="temp2.json"
+
+# Substitute `usesInternetIdentity: true` with `usesInternetIdentity: false` for all entries with a GitHub URL instead of a website.
+jq '[.[] | if (.usesInternetIdentity == true) and ((.website // "") | test("^https://github.com/")) then .usesInternetIdentity = false else . end]' "$INPUT_FILE" > "$TEMP_FILE"
+
+# Function to check the status of a website
+check_canister_website() {
+ local url=$1
+ # Get the HTTP headers and extract the status code
+ local response_status
+ response_status=$(curl -s -o /dev/null -I -w "%{http_code}" "$url")
+
+ echo "HTTP status: $response_status"
+
+ # If the status is in the 4XX or 5XX range, return failure
+ if [[ "$response_status" -ge 400 && "$response_status" -lt 600 ]]; then
+ echo "HTTP $response_status error detected for $url"
+ return 1
+ fi
+
+ return 0
+}
+
+# Start output as an empty array
+echo "[" > "$TEMP_FILE_2"
+
+# Process each entry in the filtered JSON
+first_item=true
+jq -c '.[]' "$TEMP_FILE" | while read -r item; do
+ website=$(echo "$item" | jq -r '.website')
+ echo "Processing $website"
+
+ # Check if the header is present for the website
+ if check_canister_website "$website"; then
+ # Add valid entries to the output file, handling comma placement
+ if [ "$first_item" = true ]; then
+ first_item=false
+ echo "$item" >> "$TEMP_FILE_2"
+ else
+ echo ",$item" >> "$TEMP_FILE_2"
+ fi
+ fi
+done
+
+# Close the JSON array
+echo "]" >> "$TEMP_FILE_2"
+
+jq '.' "$TEMP_FILE_2" > "$INPUT_FILE"
+
+# Clean up temporary files
+rm -f "$TEMP_FILE"
+rm -f "$TEMP_FILE_2"
+
+echo "Showcase file has been cleaned up successfullly."
diff --git a/search/Cargo.toml b/search/Cargo.toml
index 579fffccd5..9107bc33ad 100644
--- a/search/Cargo.toml
+++ b/search/Cargo.toml
@@ -1,2 +1,3 @@
[workspace]
-members = ["src/search", "src/search-cli", "src/search_canister"]
+resolver = "2"
+members = ["src/search", "src/search-cli", "src/search_canister"]
\ No newline at end of file
diff --git a/search/rust-toolchain.toml b/search/rust-toolchain.toml
new file mode 100644
index 0000000000..624eb0ea63
--- /dev/null
+++ b/search/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "1.76.0"
diff --git a/showcase.json b/showcase.json
index c3b18d15a8..e3f835c8a8 100644
--- a/showcase.json
+++ b/showcase.json
@@ -372,28 +372,27 @@
],
"youtube": "https://www.youtube.com/@junobuild"
},
-
-{
- "id": "oisy",
- "name": "OISY Wallet",
- "oneLiner": "Browser-based multi-chain wallet",
- "website": "https://oisy.com",
- "github": "https://github.com/dfinity/oisy-wallet",
- "display": "Large",
- "tags": [
- "Ethereum",
- "DeFi",
- "Wallet",
- "Chain Fusion"
- ],
- "twitter": "https://x.com/oisy",
- "description": "OISY Wallet is a new browser-based multi-chain wallet, powered by Internet Computer’s chain fusion technology. It is fully on-chain and implements network custody, an innovative approach that leverages the Internet Computer’s advanced cryptography to eliminate the need for you to handle private keys directly.",
- "usesInternetIdentity": true,
- "logo": "/img/showcase/oisy_logo.svg",
- "screenshots": [
- "/img/showcase/oisy-preview.webp"
- ]
-},
+ {
+ "id": "oisy",
+ "name": "OISY Wallet",
+ "oneLiner": "Browser-based multi-chain wallet",
+ "website": "https://oisy.com",
+ "github": "https://github.com/dfinity/oisy-wallet",
+ "display": "Large",
+ "tags": [
+ "Ethereum",
+ "DeFi",
+ "Wallet",
+ "Chain Fusion"
+ ],
+ "twitter": "https://x.com/oisy",
+ "description": "OISY Wallet is a new browser-based multi-chain wallet, powered by Internet Computer’s chain fusion technology. It is fully on-chain and implements network custody, an innovative approach that leverages the Internet Computer’s advanced cryptography to eliminate the need for you to handle private keys directly.",
+ "usesInternetIdentity": true,
+ "logo": "/img/showcase/oisy_logo.svg",
+ "screenshots": [
+ "/img/showcase/oisy-preview.webp"
+ ]
+ },
{
"id": "kinic",
"name": "Kinic",
@@ -742,25 +741,6 @@
"/img/showcase/internetidentity_screenshot_0.gif"
]
},
- {
- "id": "Arth",
- "name": "Arth",
- "tags": [
- "DeFi",
- "Wallet",
- "Bitcoin",
- "Chain Fusion"
- ],
- "description": "The mobile payments app that combines the power of Bitcoin with the convenience of mobile payments. With ckBTC, you can easily swap ckBTC from Bitcoin, view balances, and seamlessly make payments using QR codes.",
- "usesInternetIdentity": true,
- "website": "https://play.google.com/store/apps/details?id=com.foo.arth&pli=1",
- "display": "Normal",
- "logo": "/img/showcase/arth_logo.png",
- "screenshots": [
- "/img/showcase/arth_ss.webp"
- ],
- "submittableId": "36143434"
- },
{
"id": "astrox",
"name": "AstroX ME",
@@ -1816,19 +1796,6 @@
"logo": "/img/showcase/dbox_logo.png",
"submittableId": "22737412"
},
- {
- "id": "icadashboard",
- "name": "ICA Dashboard",
- "website": "https://dashboard.internetcomputer.org/",
- "tags": [
- "Tools / Infrastructure"
- ],
- "description": "The Internet Computer Association maintains a public dashboard where anyone can track the latest statistics for the Internet Computer blockchain. Tracking everything from blocks per second, to NNS proposals and their information and voting record, as well the latest state of the network, and transaction data. ",
- "oneLiner": "ICA Official Dashboard",
- "display": "Normal",
- "logo": "/img/showcase/icadashboard_logo.webp",
- "screenshots": []
- },
{
"id": "icpcoins",
"name": "ICP Coins",
@@ -1920,19 +1887,6 @@
"/img/showcase/welcomeintothemetaverse_screenshot_0.webp"
]
},
- {
- "id": "lo-fiplayer",
- "name": "Lo-Fi Player",
- "website": "https://hl2zz-gyaaa-aaaad-qas3a-cai.raw.ic0.app/",
- "tags": [
- "Games"
- ],
- "description": "Lo-Fi Player is a dapp hosted on the Internet Computer that lets users listen to relaxing beats delivered by blockchain. The back-end is using machine learning to build and develop the AI produced tunes, and users can interact within the player to change the sound to their liking. ",
- "logo": "/img/showcase/lo-fiplayer_logo.webp",
- "screenshots": [
- "/img/showcase/lo-fiplayer_screenshot_0.webp"
- ]
- },
{
"id": "reversi",
"name": "Reversi",
@@ -2500,24 +2454,6 @@
"twitter": "https://twitter.com/Faceless_Proj",
"submittableId": "35639090"
},
- {
- "name": "Sama Network",
- "description": "SAMA network, with its original designed consensus and business sharding separation, builds a highly secure and private distributed computational system. It provides data security and computational power for the World Wide Web without altering users’ habits.",
- "website": "https://sama.network/",
- "logo": "/img/showcase/sama_network_logo.png",
- "display": "Normal",
- "id": "sama_network",
- "oneLiner": "A blockchain OS with high throughput, business data full-stack encryption, and distributed computing capabilities.",
- "stats": "Private alpha testnet has been launched; the network and user interface are ready for operation.",
- "tags": [
- "Tools / Infrastructure",
- "Enterprise"
- ],
- "usesInternetIdentity": false,
- "twitter": "https://twitter.com/sama_network",
- "youtube": "https://www.youtube.com/@sama_network",
- "submittableId": "40741075"
- },
{
"name": "221Bravo App",
"description": "Home for ICP Data-Detectives. Token Stats, Visual Explorer, Account Searching and more.",
@@ -2671,27 +2607,6 @@
"youtube": "https://www.youtube.com/channel/UCrCMtg7PhCHX1tKpw5NIU7g",
"submittableId": "44034269"
},
- {
- "id": "taxlint",
- "name": "TaxLint",
- "oneLiner": "A decentralised, private, and secure automated Tax Report aimed to help users to count ICP and ICRC1 token transactions.",
- "website": "https://www.taxlint.online/",
- "tags": [
- "DeFi",
- "Tools / Infrastructure"
- ],
- "description": "A decentralised, private, and secure automated Tax Report aimed to help users to count ICP and ICRC1 token transactions.",
- "usesInternetIdentity": true,
- "logo": "/img/showcase/taxlint_logo.png",
- "github": "https://github.com/TaxLintDAO/taxlint",
- "twitter": "https://twitter.com/taxlint",
- "display": "Normal",
- "stats": "150+ users",
- "screenshots": [
- "/img/showcase/taxlint_screenshot.png"
- ],
- "submittableId": "43956470"
- },
{
"name": "InheritX",
"description": "InheritX is a blockchain-based application developed on Internet Computer (ICP) that allows users to create a digital will and bequeath their assets to designated beneficiaries in the event of their death.",
@@ -2869,7 +2784,7 @@
],
"description": "POC of a decentralized secret management solution that leverages Internet Computer (IC) technology. It aims to provide a means for services to share secrets in a flexible, transparent, and secure way. It simplifies the flow of secret management between consumers in the cluster as well as rotate secrets based on config for added security.",
"stats": "100% on chain ACL",
- "usesInternetIdentity": true,
+ "usesInternetIdentity": false,
"github": "https://github.com/Zondax/vault-k8s-canister",
"youtube": "https://youtu.be/99MahI1SO7c",
"twitter": "https://twitter.com/_zondax_",
@@ -2921,7 +2836,7 @@
"Tools / Infrastructure"
],
"description": "POC of a decentralized mind and body data management tooling that leverages Internet Computer (IC) technology. This POC provides methods and interface to submit HTTP Outcall requests to a proxy API that interfaces with a Firebase FIrestore database. It provides an example front end react application that interacts with a motoko backend.",
- "usesInternetIdentity": true,
+ "usesInternetIdentity": false,
"github": "https://github.com/blueberryxtech/ic-mind-body-canister",
"submittableId": "44190088"
},
@@ -3450,22 +3365,6 @@
"logo": "/img/showcase/gamebloc_logo.png",
"submittableId": "44503915"
},
- {
- "id": "allkinds",
- "name": "AllKinds",
- "oneLiner": "A web3 social network where people find more meaningful connections.",
- "website": "https://allkinds.xyz/",
- "github": "https://github.com/AllKinds/AllkindsICP",
- "twitter": "https://twitter.com/Allkindsxyz",
- "tags": [
- "SocialFi"
- ],
- "description": "A web3 social network where people find more meaningful connections.",
- "usesInternetIdentity": true,
- "display": "Normal",
- "logo": "/img/showcase/allkinds_logo.svg",
- "submittableId": "43688836"
- },
{
"id": "dmail-network",
"name": "Dmail Network",
@@ -3553,23 +3452,6 @@
"logo": "/img/showcase/frontrow_logo.png",
"submittableId": "43814286"
},
- {
- "id": "myordinalsloan",
- "name": "MyOrdinals.Loan",
- "oneLiner": "Peer-to-peer Bitcoin lending using ckBTC. Users borrow or lend ckBTC, securing transactions with unique Ordinal Inscriptions (Ordinals) as collateral.",
- "website": "https://myordinals.loan/",
- "tags": [
- "Bitcoin",
- "DeFi",
- "Chain Fusion"
- ],
- "twitter": "https://twitter.com/MyOrdinalsLoan",
- "description": "Peer-to-peer Bitcoin lending using ckBTC. Users borrow or lend ckBTC, securing transactions with unique Ordinal Inscriptions (Ordinals) as collateral.",
- "usesInternetIdentity": false,
- "display": "Normal",
- "logo": "/img/showcase/myordinalsloan_logo.png",
- "submittableId": "41341564"
- },
{
"id": "icto",
"name": "ICTO",
@@ -4646,22 +4528,6 @@
"github": "https://github.com/NeutronStarDAO/icecube",
"twitter": "https://x.com/icecubeapp"
},
- {
- "id": "bridge-23-app",
- "name": "Bridge 23",
- "oneLiner": "Bridge 23 is a fully featured data marketplace running on ICP where everyone can sell their data directly to merchants, companies and institutions.",
- "description": "Bridge 23 is a fully featured data marketplace running on ICP where everyone can sell their data directly to merchants, companies and institutions.",
- "stats": "5000+ waitlist, 100+ users, 4000+ tokenized products",
- "website": "https://alpha.bridge23.app/login",
- "logo": "/img/showcase/bridge23_logo.png",
- "display": "Normal",
- "tags": [
- "Tools / Infrastructure"
- ],
- "usesInternetIdentity": true,
- "github": "https://github.com/bridge-23/Bridge23app.0.1.0-alpha",
- "twitter": "https://x.com/bridge23inc"
- },
{
"id": "event-hub-attention-dao",
"name": "Event Hub",
@@ -4822,28 +4688,6 @@
"github": "https://github.com/supaIC/Cipher-AI-Vault",
"website": "https://qehbq-rqaaa-aaaan-ql2iq-cai.icp0.io/"
},
- {
- "id": "scoge",
- "name": "SCOGÉ Universe",
- "oneLiner": "T.A.O.S City’s finest distributor of Luxury Fashion and Consumer goods",
- "website": "https://uqjdj-siaaa-aaaag-aaoxq-cai.icp0.io",
- "tags": [
- "NFT",
- "Metaverse",
- "Games"
- ],
- "description": "SCOGÉ is a cutting-edge fashion-centric gamified metaverse platform that revolutionizes the way styles are born, stories are told, and interaction between users. Users embark on an enthralling journey, wielding unique powers to craft thrilling experiences while discovering T.A.O.S City and the evolving SCOGÉ Universe.",
- "logo": "/img/showcase/scoge_logo.webp",
- "display": "Normal",
- "usesInternetIdentity": false,
- "twitter": "https://twitter.com/_scoge_",
- "screenshots": [
- "/img/showcase/scoge_screenshots.webp"
- ],
- "video": "/img/showcase/scoge_video.mp4",
- "videoContentType": "video/mp4",
- "submittableId": "34276514"
- },
{
"id": "zkLama",
"name": "zkLama",
@@ -4997,5 +4841,21 @@
],
"github": "https://github.com/tolgayayci/dfx-dashboard",
"website": "https://dfx-dashboard-docs.netlify.app/"
+ },
+ {
+ "id": "icptokens",
+ "name": "ICP Tokens",
+ "tags": [
+ "Tools / Infrastructure"
+ ],
+ "stats": "15,000+ users",
+ "website": "https://icptokens.net",
+ "github": "https://github.com/CyberNinjasLab",
+ "youtube": "https://www.youtube.com/watch?v=2hKfVcJviTM",
+ "twitter": "https://x.com/ICPTokens",
+ "description": "Advanced tool for tracking ICP tokens, designed to simplify the way you monitor, analyze, and manage tokens within the Internet Computer DeFi ecosystem. Portfolio insights, advanced charts and bubble maps for visual insights.",
+ "usesInternetIdentity": true,
+ "display": "Normal",
+ "logo": "/img/showcase/icptokens_logo.svg"
}
-]
\ No newline at end of file
+]
diff --git a/sidebars.js b/sidebars.js
index 651b7ea0aa..bbff85da62 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -127,6 +127,17 @@ const sidebars = {
label: "Overview",
id: "developer-docs/smart-contracts/call/overview",
},
+ {
+ type: "doc",
+ label: "Async code & inter-canister calls",
+ id: "developer-docs/smart-contracts/advanced-features/async-code",
+ },
+ {
+ type: "doc",
+ label: "Composite queries",
+ id: "developer-docs/smart-contracts/advanced-features/composite-query",
+ },
+ "developer-docs/smart-contracts/advanced-features/query-stats",
{
type: "category",
label: "Candid",
@@ -183,78 +194,60 @@ const sidebars = {
id: "developer-docs/smart-contracts/test/overview",
},
"developer-docs/smart-contracts/test/pocket-ic",
- "developer-docs/smart-contracts/test/troubleshooting",
],
},
+ ],
+ },
{
type: "category",
label: "Advanced features",
items: [
- {
- type: "doc",
- label: "Async code & inter-canister calls",
- id: "developer-docs/smart-contracts/advanced-features/async-code",
- },
- {
- type: "doc",
- label: "Composite queries",
- id: "developer-docs/smart-contracts/advanced-features/composite-query",
- },
- {
- type: "category",
- label: "Incoming HTTP requests",
- items: [
- {
- type: "doc",
- label: "GET/POST requests",
- id: "developer-docs/smart-contracts/advanced-features/handling-get-post-requests",
- },
- {
- type: "doc",
- label: "Serving requests",
- id: "developer-docs/smart-contracts/advanced-features/serving-http-request",
- },
- {
- type: "doc",
- label: "HTTP gateways",
- id: "developer-docs/smart-contracts/advanced-features/http-gateways",
- },
- ],
- },
- {
- type: "category",
- label: "HTTPS outcalls",
- items: [
- {
- label: "Overview",
- type: "doc",
- id: "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-overview",
- },
- "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use",
- "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-get",
- "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-post",
- ],
- },
{
type: "category",
- label: "HTTP certification",
- items: [
+ label: "HTTP/HTTPS",
+ items:
+ [
{
type: "doc",
- id: "developer-docs/web-apps/http-compatible-canisters/custom-http-canisters",
- label: "Custom HTTP canisters",
+ label: "HTTP gateways & incoming requests",
+ id: "developer-docs/smart-contracts/advanced-features/handling-get-post-requests",
},
{
- type: "doc",
- id: "developer-docs/web-apps/http-compatible-canisters/serving-json-over-http",
- label: "Serving JSON over HTTP",
+ type: "category",
+ label: "HTTPS outcalls",
+ items: [
+ {
+ label: "Overview",
+ type: "doc",
+ id: "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-overview",
+ },
+ "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use",
+ "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-get",
+ "developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-post",
+ ],
},
{
- type: "doc",
- id: "developer-docs/web-apps/http-compatible-canisters/serving-static-assets-over-http",
- label: "Serving static assets over HTTP",
+ type: "category",
+ label: "HTTP certification",
+ items: [
+ {
+ type: "doc",
+ id: "developer-docs/web-apps/http-compatible-canisters/custom-http-canisters",
+ label: "Custom HTTP canisters",
+ },
+ {
+ type: "doc",
+ id: "developer-docs/web-apps/http-compatible-canisters/serving-json-over-http",
+ label: "Serving JSON over HTTP",
+ },
+ {
+ type: "doc",
+ id: "developer-docs/web-apps/http-compatible-canisters/serving-static-assets-over-http",
+ label: "Serving static assets over HTTP",
+ },
+ ],
},
- ],
+ ]
},
{
type: "doc",
@@ -288,12 +281,11 @@ const sidebars = {
"developer-docs/smart-contracts/signatures/signing-messages-t-schnorr",
],
},
+ "developer-docs/web-apps/independently-verifying-ic-signatures",
],
},
"developer-docs/smart-contracts/advanced-features/periodic-tasks",
- "developer-docs/smart-contracts/advanced-features/query-stats",
"developer-docs/smart-contracts/advanced-features/simd",
- "developer-docs/smart-contracts/advanced-features/system-canisters",
"developer-docs/smart-contracts/advanced-features/time-and-timestamps",
],
},
@@ -328,8 +320,6 @@ const sidebars = {
},
],
},
- ],
- },
{
type: "category",
label: "Developer tools",
@@ -549,17 +539,9 @@ const sidebars = {
],
},
{
- type: "category",
- label: "Browser JS",
- items: [
- "developer-docs/web-apps/browser-js/js-frameworks",
- "developer-docs/web-apps/browser-js/js-request-api",
- ],
- },
- {
- type: "category",
- label: "Frameworks",
- items: ["developer-docs/web-apps/frameworks/juno"],
+ type: "doc",
+ label: "JS frameworks",
+ id: "developer-docs/web-apps/browser-js/js-frameworks",
},
{
type: "category",
@@ -569,9 +551,7 @@ const sidebars = {
"developer-docs/web-apps/custom-domains/using-custom-domains",
],
},
- "developer-docs/web-apps/design-dapps",
- "developer-docs/web-apps/independently-verifying-ic-signatures",
- "developer-docs/web-apps/obtain-verify-ic-pubkey",
+ "developer-docs/web-apps/frameworks/juno",
],
},
{
@@ -776,10 +756,6 @@ const sidebars = {
],
},
{
- type: "category",
- label: "Identity",
- items: [
- {
type: "category",
label: "Authentication",
items: [
@@ -788,7 +764,6 @@ const sidebars = {
type: "doc",
id: "developer-docs/identity/authentication/overview",
},
-
{
type: "category",
label: "Internet Identity (II)",
@@ -803,14 +778,6 @@ const sidebars = {
"developer-docs/identity/internet-identity/alternative-origins",
],
},
- "developer-docs/identity/authentication/email-password",
- "developer-docs/identity/authentication/nfid",
- "developer-docs/identity/authentication/siwb",
- "developer-docs/identity/authentication/siwe",
- "developer-docs/identity/authentication/siws",
- "developer-docs/identity/authentication/msq",
- ],
- },
{
type: "category",
label: "Verifiable credentials",
@@ -841,23 +808,13 @@ const sidebars = {
label: "Tokens",
items: [
"developer-docs/defi/tokens/token-standards",
- "developer-docs/defi/tokens/asset_flow/index",
{
type: "category",
label: "Ledgers",
items: [
- {
- type: "doc",
- label: "Overview",
- id: "developer-docs/defi/tokens/ledger/overview",
- },
{
type: "category",
label: "Setup",
- link: {
- type: "doc",
- id: "developer-docs/defi/tokens/ledger/setup/overview",
- },
items: [
"developer-docs/defi/tokens/ledger/setup/icp_ledger_setup",
"developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup"
@@ -866,10 +823,6 @@ const sidebars = {
{
type: "category",
label: "Usage",
- link: {
- type: "doc",
- id: "developer-docs/defi/tokens/ledger/usage/overview",
- },
items: [
"developer-docs/defi/tokens/ledger/usage/icp_ledger_usage",
"developer-docs/defi/tokens/ledger/usage/icrc1_ledger_usage"
@@ -892,7 +845,7 @@ const sidebars = {
},
{
type: "category",
- label: "Advanced",
+ label: "Rosetta",
items: [
{
type: "category",
@@ -1228,101 +1181,6 @@ const sidebars = {
},
],
},
- {
- type: "category",
- label: "Sample apps",
- items: [
- "samples/overview",
- {
- type: "category",
- label: "Hosting",
- items: [
- "references/samples/hosting/godot-html5-template/README",
- "references/samples/hosting/photo-storage/README",
- "references/samples/hosting/static-website/README",
- "references/samples/hosting/unity-webgl-template/README",
- ],
- },
- {
- type: "category",
- label: "Motoko",
- items: [
- "references/samples/motoko/basic_bitcoin/README",
- "references/samples/motoko/basic_dao/README",
- "references/samples/motoko/cert-var/README",
- "references/samples/motoko/classes/README",
- "references/samples/motoko/composite_query/README",
- "references/samples/motoko/counter/README",
- {
- type: "doc",
- label: "CRUD example",
- id: "references/samples/motoko/superheroes/README",
- },
- "references/samples/motoko/encrypted-notes-dapp-vetkd/README",
- "references/samples/motoko/encrypted-notes-dapp/README",
- "references/samples/motoko/life/README",
- "references/samples/motoko/hello_cycles/README",
- "references/samples/motoko/send_http_get/README",
- "references/samples/motoko/send_http_post/README",
- "references/samples/motoko/ic-pos/README",
- "references/samples/motoko/icrc2-swap/README",
- "references/samples/motoko/internet_identity_integration/README",
- "references/samples/motoko/minimal-counter-dapp/README",
- "references/samples/motoko/parallel_calls/README",
- "references/samples/motoko/pub-sub/README",
- "references/samples/motoko/random_maze/README",
- "references/samples/motoko/threshold-ecdsa/README",
- "references/samples/motoko/token_transfer/README",
- "references/samples/motoko/token_transfer_from/README",
- "references/samples/motoko/vetkd/README",
- ],
- },
- {
- type: "category",
- label: "Rust",
- items: [
- "references/samples/rust/basic_bitcoin/README",
- "references/samples/rust/basic_dao/README",
- "references/samples/rust/canister-info/README",
- "references/samples/rust/composite_query/README",
- "references/samples/rust/counter/README",
- "references/samples/rust/defi/src/frontend/README",
- "references/samples/rust/encrypted-notes-dapp-vetkd/README",
- "references/samples/rust/encrypted-notes-dapp/README",
- "references/samples/rust/icp_transfer/README",
- "references/samples/rust/nft-wallet/README",
- "references/samples/rust/parallel_calls/README",
- "references/samples/rust/performance_counters/README",
- "references/samples/rust/periodic_tasks/README",
- "references/samples/rust/pub-sub/README",
- "references/samples/rust/qrcode/README",
- "references/samples/rust/send_http_get/README",
- "references/samples/rust/send_http_post/README",
- "references/samples/rust/threshold-ecdsa/README",
- "references/samples/rust/token_transfer/README",
- "references/samples/rust/token_transfer_from/README",
- "references/samples/rust/vetkd/README",
- ],
- },
- {
- type: "category",
- label: "Native dapps",
- items: [
- "references/samples/native-apps/unity_ii_applink/README",
- "references/samples/native-apps/unity_ii_deeplink/README",
- "references/samples/native-apps/unity_ii_deeplink/ii_integration_dapp/README",
- ],
- },
- {
- type: "category",
- label: "Svelte",
- items: [
- "references/samples/svelte/svelte-motoko-starter/README",
- "references/samples/svelte/svelte-starter/README",
- ],
- },
- ],
- },
{
type: "category",
label: "References",
@@ -1424,6 +1282,7 @@ const sidebars = {
label: "Ingress messages",
id: "references/ingress-messages",
},
+ "developer-docs/smart-contracts/advanced-features/system-canisters",
{
type: "category",
label: "Node providers",
diff --git a/src/components/Common/Icons/DownloadIcon.tsx b/src/components/Common/Icons/DownloadIcon.tsx
new file mode 100644
index 0000000000..478b346198
--- /dev/null
+++ b/src/components/Common/Icons/DownloadIcon.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+const DownloadIcon: React.FC<{ className?: string }> = ({ className }) => {
+ return (
+
+ );
+};
+
+export default DownloadIcon;
diff --git a/src/components/Common/sampleItems.ts b/src/components/Common/sampleItems.ts
index c54901efea..1bd4d013f7 100644
--- a/src/components/Common/sampleItems.ts
+++ b/src/components/Common/sampleItems.ts
@@ -265,7 +265,7 @@ export const sampleItems: SampleItem[] = [
},
motoko:
"https://github.com/dfinity/examples/tree/master/motoko/send_http_get",
- docs: "docs/current/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use",
+ docs: "/docs/current/developer-docs/smart-contracts/advanced-features/https-outcalls/https-outcalls-how-to-use",
rust: "https://github.com/dfinity/examples/tree/master/rust/send_http_get",
},
},
diff --git a/src/pages/library.tsx b/src/pages/library.tsx
new file mode 100644
index 0000000000..8c2b8403d7
--- /dev/null
+++ b/src/pages/library.tsx
@@ -0,0 +1,288 @@
+import Link from "@docusaurus/Link";
+import AnimateSpawn from "@site/src/components/Common/AnimateSpawn";
+import DarkHeroStyles from "@site/src/components/Common/DarkHeroStyles";
+import ShareMeta from "@site/src/components/Common/ShareMeta";
+import { useDarkHeaderInHero } from "@site/src/utils/use-dark-header-in-hero";
+import transitions from "@site/static/transitions.json";
+import Layout from "@theme/Layout";
+import { motion } from "framer-motion";
+import React, { useEffect, useRef, useState } from "react";
+import DownloadIcon from "../components/Common/Icons/DownloadIcon";
+import LinkArrowRight from "../components/Common/Icons/LinkArrowRight";
+
+const quickstartCards = [
+ {
+ title: "Internet Computer in a Nutshell",
+ url: "/presentations/Internet Computer in a nutshell EN.pdf",
+ },
+ {
+ title: "Der Internet Computer in Kürze (German)",
+ url: "/presentations/Internet Computer in a nutshell DE.pdf",
+ },
+];
+
+const presentationCards = [
+ {
+ title: "ICP makes the Internet into a World Computer",
+ url: "https://internetcomputer.docsend.com/view/dzkwezufykwpb7p8",
+ },
+ {
+ title: "UTOPIA",
+ url: "https://utopia.docsend.com/view/ez8f34n53q2fg2de",
+ },
+];
+
+const whitepaperCards = [
+ {
+ title: "The Internet Computer for Geeks",
+ description: "The DFINITY Team",
+ url: "/whitepapers/The Internet Computer for Geeks.pdf",
+ },
+ {
+ title: "Internet Computer Consensus",
+ description:
+ "Jan Camenisch, Manu Drijvers, Timo Hanke, Yvonne-Anne Pignolet, Victor Shoup, Dominic Williams",
+ url: "/whitepapers/Internet Computer Consensus.pdf",
+ },
+ {
+ title:
+ "Advancing Blockchain Scalability: A Linear Optimization Framework for Diversified Node Allocation in Shards",
+ description: "Björn Assmann, Samuel J. Burri",
+ url: "/whitepapers/Advancing Blockchain Scalability_ A Linear Optimization Framework for Diversified Node Allocation in Shards.pdf",
+ },
+ {
+ title:
+ "Decentralized and Stateful Serverless Computing on the Internet Computer Blockchain",
+ description:
+ "Maksym Arutyunyan, Andriy Berestovskyy, Adam Bratschi-Kaye, Ulan Degenbaev, Manu Drijvers, Islam El-Ashi, Stefan Kaestle, Roman Kashitsyn, Maciej Kot, Yvonne-Anne Pignolet, Rostislav Rumenov, Dimitris Sarlis, Alin Sinpalean, Alexandru Uta, Bogdan Warinschi, and Alexandra Zapuc",
+ url: "/whitepapers/Decentralized and Stateful Serverless Computing on the Internet Computer Blockchain.pdf",
+ },
+ {
+ title: "Non-interactive distributed key generation and key resharing",
+ description: "Jens Groth",
+ url: "/whitepapers/Non-interactive distributed key generation and key resharing.pdf",
+ },
+ {
+ title: "vetKeys: How a Blockchain Can Keep Many Secrets",
+ description:
+ "Andrea Cerulli, Aisling Connolly, Gregory Neven, Franz-Stefan Preiss, Victor Shoup",
+ url: "/whitepapers/vetKeys_ How a Blockchain Can Keep Many Secrets.pdf",
+ },
+
+ {
+ title: "Smarter Contract Upgrades with Orthogonal Persistence",
+ description:
+ "Luc Bläser, Claudio Russo, Gabor Greif, Ryan Vandersmith, Jason Ibrahim",
+ url: "/whitepapers/Smarter Contract Upgrades with Orthogonal Persistence.pdf",
+ },
+ {
+ title: "Collecting Garbage on the Blockchain",
+ description:
+ "Luc Bläser, Claudio Russo, Ulan Degenbaev, Ömer S. Agacan, Gabor Greif, Jason Ibrahim",
+ url: "/whitepapers/Collecting Garbage on the Blockchain.pdf",
+ },
+ {
+ title: "A Decentralized Mechanism for Know-Your-Transaction Compliance",
+ description: "Thomas Locher",
+ url: "/whitepapers/A Decentralized Mechanism for Know-Your-Transaction Compliance.pdf",
+ },
+ {
+ title:
+ "Byzantine Reliable Broadcast with Low Communication and Time Complexity",
+ description: "Thomas Locher",
+ url: "/whitepapers/Byzantine Reliable Broadcast with Low Communicationand Time Complexity.pdf",
+ },
+ {
+ title: "Design and analysis of a distributed ECDSA signing service",
+ description: "Jens Groth and Victor Shoup",
+ url: "/whitepapers/Design and analysis of a distributed ECDSA signing service.pdf",
+ },
+ {
+ title: "Fully on-chain DAOs on the Internet Computer",
+ description: "Björn Assman and Lara Schmid",
+ url: "/whitepapers/Fully on-chain DAOs on the Internet Computer.pdf",
+ },
+ {
+ title:
+ "Lightweight Asynchronous Verifiable Secret Sharing with Optimal Resilience",
+ description: "Victor Shoup and Nigel P. Smart",
+ url: "/whitepapers/Lightweight Asynchronous Verifiable Secret Sharing with Optimal Resilience.pdf",
+ },
+ {
+ title: "Monitoring the Internet Computer",
+ description:
+ "David Basin, Daniel Stefan Dietiker, Srđan Krstić, Yvonne-Anne Pignolet, Martin Raszyk, Joshua Schneider & Arshavir Ter-Gabrielyan",
+ url: "/whitepapers/Monitoring the Internet Computer.pdf",
+ },
+
+ {
+ title:
+ "On the security of ECDSA with additive key derivation and presignatures",
+ description: "Jens Groth and Victor Shoup",
+ url: "/whitepapers/On the security of ECDSA with additive key derivation and presignatures.pdf",
+ },
+ {
+ title: "Trustworthy confidential virtual machines for the masses",
+ description:
+ "Anna Galanou, Khushboo Bindlish, Luca Preibsch, Yvonne-Anne Pignolet, Christof Fetzer, Rüdiger Kapitza",
+ url: "/whitepapers/Trustworthy confidential virtual machines for the masses.pdf",
+ },
+ {
+ title: "User-centric authentication in Web 3.0",
+ description: "Björn Tackmann, DFINITY Foundation",
+ url: "/whitepapers/User-centric authentication in Web 3.0.pdf",
+ },
+];
+
+const LibraryCard: React.FC<{
+ title: string;
+ subtitle?: string;
+ description?: string;
+ url: string;
+ highlighted?: boolean;
+}> = ({ title, subtitle, description, url, highlighted }) => {
+ return (
+
+
+