diff --git a/blog/news-and-updates/2023-10-25-update.mdx b/blog/news-and-updates/2023-10-25-update.mdx new file mode 100644 index 0000000000..597d9819ff --- /dev/null +++ b/blog/news-and-updates/2023-10-25-update.mdx @@ -0,0 +1,60 @@ +--- +title: Developer weekly update October 25, 2023 +description: This week, we're excited to share the first video tutorial in the developer journey series, announce the name for the dfx version manager, and take a look at the details of a proposed new workflow for SNS launches. +tags: [Devs] +image: /img/blog/dev-update-blog-oct-25.jpg +--- + +# Developer weekly update October 25, 2023 + +![October 25 2023](../../static/img/blog/dev-update-blog-oct-25.jpg) + +Hello developers and welcome back to developer weekly! This week, we're excited to share the first video tutorial in the developer journey series, announce the name for the `dfx` version manager, and take a look at the details of a proposed new workflow for SNS launches. + +## Developer journey video series + +In previous dev updates, we've introduced the developer journey documentation series and provided updates when new 'levels' of the tutorial series have been published. In today's update, we're excited to share that the first video corresponding to the documentation has been released! + +The first video, **ICP Developer Journey 0.1 | Overview of the Internet Computer** corresponds to the very first page in the developer journey series, which can be found [here](/docs/current/tutorials/developer-journey/level-0/ic-overview). + +New videos will be released every week, and will follow each page of the developer journey documentation - that means there will be a total of 36 videos! + +The first video can be found on the DFINITY Youtube channel: + +[![ICP Developer Journey 0.1 | Overview of the Internet Computer](https://img.youtube.com/vi/oBUpJ4CqmN0/0.jpg)](https://youtu.be/oBUpJ4CqmN0?si=q5r223tFnWoZTMGz) + +## `dfx` version manager name decision + +Last week, we asked for your feedback on naming an upcoming tool known as the `dfx` version manager. The results are in, and a name has been decided! + +The `dfx` version manager will be called **dfxvm**. + +Stay tuned for more updates on this new tool! + +## Proposed new SNS workflow + +Recently, a new SNS hand-off workflow has been proposed on the developer forum. This new workflow has been proposed because there has been a high amount of friction during the canister hand-off process, especially when handing off the SNS's asset canister. + +For an SNS to be launched, the dapp's canisters must be handed over from the developers to the SNS itself. Prior to August 2023, this process included the following steps: + +- An SNS is first approved to be launched through an NNS proposal. + +- The dapp's canisters are then created and initialized, with the SNS governance canister's ID being publicly known. + +- Then, developers hand over the dapp's canisters to the SNS. + +- The SNS root canister is set as the controller of the canisters, and the SNS's proposal methods are configured so that they can only be called by the governance canister. + +- Lastly, an NNS proposal is used to start the SNS decentralization swap and launch the SNS. + +This process was amended in August 2023 to simplify and condense several steps, ultimately providing an SNS to be created through a single NNS proposal. In this revised workflow, the dapp's canisters are handed over from the developers to the NNS, then an NNS proposal creates the SNS canisters, initializes them, hands them over to the SNS, then starts the decentralization swap and launches the SNS. + +This is how the SNS process currently operates. + +The newly proposed workflow takes this current workflow and adds an additional step where once the SNS is launched, the SNS community upgrades the dapp's canisters through an SNS proposal. Within this upgrade, they can set the privileges within the dapp appropriately. + +You can read more about this proposed workflow and provide your thoughts on the [developer forum](https://forum.dfinity.org/t/handing-over-dapp-canisters-to-an-sns-dao/23877). + +That'll wrap up this week. Tune back in next week for more developer updates! + +-DFINITY diff --git a/blog/news-and-updates/team-spotlight-fi.mdx b/blog/news-and-updates/team-spotlight-fi.mdx index a6af4db6e2..d0fa39117a 100644 --- a/blog/news-and-updates/team-spotlight-fi.mdx +++ b/blog/news-and-updates/team-spotlight-fi.mdx @@ -1,6 +1,6 @@ --- title: Team spotlight - Financial integration -description: For this spotlight showcase, we're going to dive into the financial integration team, also known as the team behind the development of the IC ledgers and token standards. +description: For this spotlight showcase, we're going to dive into the financial integration (FI) team, also known as the team behind the development of the IC ledgers and token standards. tags: [Team spotlight] image: /img/blog/dev-update-blog-FI.jpg --- @@ -11,7 +11,7 @@ Hello IC developers and welcome to another DFINITY team spotlight! For this spot **To dive right in, what is the purpose of the Financial Integration team?** -*The Financial Integration team has three responsibilities:* +*The Financial Integration team contributes to the IC as follows:* - *The development of the Ledgers and the standards around fungible tokens.* @@ -23,9 +23,9 @@ Hello IC developers and welcome to another DFINITY team spotlight! For this spot *The team is composed of 5 developers and 1 researcher.* -**Tokens and their tokenomics are a core piece of blockchains and interacting with them. On a fundamental level, what role do tokens and tokenomics play on the IC?** +**Tokens and tokenomics are are essential concepts for blockchains. On a fundamental level, what role do tokens and tokenomics play on the IC?** -*Tokens and tokenomics are essential in the Internet Computer (IC). Tokens serve as a medium of exchange and incentivize participation by rewarding users, developers, and validators. They can also enable decentralized applications (DApps) through smart contracts and play a role in governance, allowing token holders to influence network decisions. Additionally, tokens promote decentralization, reduce reliance on intermediaries, facilitate interoperability between blockchains, and define economic models for various projects. In essence, tokens and tokenomics are the foundational elements that drive the functionality, security, and growth of the IC and other blockchain networks.* +*The Internet Computer's utility token is ICP, named after the Internet Computer Protocol. This utility token is used for several functions within the network, such as staking to participate in the governance of the network, for getting cycles powering canister smart contracts, or the protocol rewards independent node providers (NPs) with newly minted ICP tokens for having their sovereign nodes contribute to the protocol. There are various other tokens that the community has created or governance tokens that were created in the process of decentralizing dapps by means of SNSs. Similar to the ICP token, SNS communities use SNS tokens to govern their dapp in a decentralized fashion.* **Could you explain the difference between ICP, an ICRC token, and an ICRC-1 token? When would developers use one over another?** diff --git a/docs/concepts/governance.md b/docs/concepts/governance.md index 534e2f20b5..7a453d0d26 100644 --- a/docs/concepts/governance.md +++ b/docs/concepts/governance.md @@ -1,7 +1,7 @@ # Neurons and governance ## Overview -As a decentralized blockchain, all changes to the configuration and behavior of the Internet Computer are controlled by a governance body called the Network Nervous System (NNS). The NNS controls many aspects of the Internet Computer blockchain including the following: +As a decentralized blockchain, all changes to the configuration and behavior of the Internet Computer are controlled by a governance system called the Network Nervous System (NNS). The NNS controls many aspects of the Internet Computer blockchain including: - Which data center providers participate in the network. @@ -9,14 +9,10 @@ As a decentralized blockchain, all changes to the configuration and behavior of - Assignment of nodes to subnet blockchains. -- Whether upgrades to canisters or to a new protocol version are allowed or not. +- Upgrades to newer protocol versions or upgrades of system canisters. -In addition, only members of the governance body can vote to adopt or reject requests to upgrade Internet Computer replicas or modify the Internet Computer protocol. +## Who can vote? -## Voting rights for stakeholders +To favor the long-term sustainability of ICP over short-term interests, only ICP token holders who stake their tokens can participate in the governance process. A staked amount of ICP is called a **neuron**. The amount of ICP staked in a neuron can only be converted back to ICP after the neuron’s lock-up period, called the “dissolve delay”, has elapsed. The longer the dissolve delay of a neuron, the higher the voting power associated with the neuron. -Because tokens on the Internet Computer are generally liquid, they do not represent a stable enough commitment on the part of their holders for them to be used for governance purposes. To provide the stability required for responsible governance, tokens can be converted to **neurons**. A neuron represents a number of ICP tokens that cannot be exchanged for a minimum period of time (the lock-up period). - -When a person or organization has some number of ICP tokens locked up in a neuron, the neuron holder has the right to vote on proposals, and to be paid for voting in proportion to the number of ICP locked up, the length of the lock-up period and the relative number of votes cast. - -The Internet Computer blockchain tracks the number of ICP tokens that are locked up in neurons and provides the logic necessary for voting in conjunction with managing ICP token account balances. +Neuron holders constitute the governing body of the NNS. Through their neurons, they can vote on proposals and thereby govern the ICP. To incentivize governance participation, neuron holders receive voting rewards. These rewards depend on the number of votes cast and the amount of ICP staked in the respective neurons. diff --git a/docs/concepts/what-is-ic.md b/docs/concepts/what-is-ic.md new file mode 100644 index 0000000000..aa2826f62d --- /dev/null +++ b/docs/concepts/what-is-ic.md @@ -0,0 +1,96 @@ +# What is the Internet Computer? + +The **Internet Computer** is a blockchain that enables developers, organizations, and entrepreneurs to build and deploy secure, autonomous, and tamper-proof **[canisters](/how-it-works/canister-lifecycle/)**, an evolution of **smart contracts**. + +As a dapp developer, you might find it useful to think of the Internet Computer as providing the following key features: + +- A **globally-accessible, public blockchain** for running smart contracts at web speed, that can serve interactive web content to users. You can read more about the architecture of the IC [here](/how-it-works/architecture-of-the-internet-computer/). + +- A secure cryptographic protocol (**[Internet Computer protocol](/how-it-works/core-ic-protocol-overview/)**) run by nodes machines operated by independent node providers in independent data centers all over the world. This guarantees the secure execution of smart contracts. + +- A **network of independent blockchains**, known as [subnets](./nodes-subnets.md), connected using [chain-key cryptography](/how-it-works/#Chain-key-cryptography) that can [scale out](/how-it-works/scalability/) its capacity as required. + +## An open blockchain + +The Internet Computer is a blockchain hosted on node machines operated by independent parties and located in geographically distributed data centers. The nodes run the [Internet Computer protocol](/how-it-works/core-ic-protocol-overview/), an advanced cryptographic fault-tolerant protocol which ensures that smart contracts running on the blockchain cannot be tampered with or stopped. The Internet Computer is composed of individual subnet blockchains running in parallel and connected using [chain-key cryptography](/how-it-works/#Chain-key-cryptography). This means that canisters running on a subnet can seamlessly call canisters hosted in any other subnet of the Internet Computer blockchain. + +Another important feature of the Internet Computer is that it runs under the control of a decentralized, permissionless governance system, called **[Network Nervous System](/how-it-works/#Network-nervous-system)** (NNS), which runs completely on-chain. The NNS can make decisions on several topics, including scaling out the Internet Computer by creating new subnet blockchains, updating the node machines, and configuring parameters used in the Internet Computer protocol. Anyone can participate in the governance and submit new proposals to the NNS or vote on open proposals. To do so, users have to stake ICP, the Internet Computer utility token, and [create a **neuron** with the NNS](/docs/current/tokenomics/token-holders/nns-app-quickstart). + +## Building the next generation of software and services + +The Internet Computer protocol reduces platform-based risks and paves the way for innovation by re-imagining how software is built, deployed, and accessed. + +For example, with the Internet Computer, developers can focus on writing code using canisters without environment-related distractions such as: + +- Physical or virtual network configuration requirements. + +- Load balancing services. + +- Firewalls, network topology, or port management. + +- Database configuration and maintenance. + +- Storage volumes and devices. + +By enabling developers to focus on building applications and delivering value, the Internet Computer helps simplify the development process, reduce time to market, and foster innovation. + +For end-users, the Internet Computer provides a secure environment for accessing dapps with fewer risks. Because of the inherent security of the blockchain, programs running on the Internet Computer cannot be hijacked by malicious code, which also reduces the total cost of ownership for both application end-users or organizations. + +In addition, because dapps can be "autonomous" and public, developers can write services that communicate with each other and share functions in ways that increase productivity and efficiency while leaving room to innovate and improve projects with confidence. + +The Internet Computer also enables developers to use [cryptographically-secure identities](/how-it-works/web-authentication-identity/) to enforce access controls, reducing the need to rely on usernames and passwords or external identity management plug-ins. + +## Learn more + +- [Architecture of the Internet Computer](/how-it-works/architecture-of-the-internet-computer/). + +- [The Internet Computer Protocol](/how-it-works/core-ic-protocol-overview/). + +- [Peer-to-peer layer](/how-it-works/peer-to-peer-p2p/). + +- [Consensus layer](/how-it-works/consensus/). + +- [Message routing layer](/how-it-works/message-routing/). + +- [Execution layer](/how-it-works/execution-layer/). + +- [Chain-key cryptography](/how-it-works/chain-key-technology/). + +- [Chain-key tokens](/how-it-works/chain-key-tokens/). + +- [The Network Nervous System](https://internetcomputer.org/nns/). + +- [Service Nervous Systems](https://internetcomputer.org/sns/). + +- [Canisters](/how-it-works/canister-lifecycle/). + +- [Internet Identity](/how-it-works/web-authentication-identity/). + +## Get started developing on the IC + +- Get started developing on the IC by embarking on your [developer journey](/docs/current/tutorials/developer-journey). + +- [Designing a dapp](/docs/current/developer-docs/backend/design-dapps). + +- [Building backend canisters with Motoko](/docs/current/developer-docs/backend/motoko/). + +- [Building backend canisters with Rust](/docs/current/developer-docs/backend/rust/). + +## Connect with the IC community + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + diff --git a/docs/developer-docs/gas-cost.md b/docs/developer-docs/gas-cost.md index 5803b8c050..703a2a3348 100644 --- a/docs/developer-docs/gas-cost.md +++ b/docs/developer-docs/gas-cost.md @@ -71,9 +71,9 @@ To derive the estimated cost for a GB Storage per month, we assume a 30 day mont | HTTPS outcall request message size (per byte) | For sending an HTTPS outcall to a server outside the IC, per request byte (http_request) | Sending canister | $0.000000006806072 | $0.000000017800496 | | HTTPS outcall response message size (per byte) | For sending an HTTPS outcall to a server outside the IC, per reserved response byte (http_request) | Sending canister | $0.000000013612144 | $0.000000035600992 | -Cost per Transaction in USD (XDR/USD exchange rate as of November 23, 2022): +Cost per Transaction in USD (XDR/USD exchange rate as of November 23, 2022). -Assuming a 30-day month —  +The following table shows the calculated storage cost per GB for a 30-day month: | | | 13-node Application Subnets | 34-node Application Subnets | |----------------------|------------------------------------|-----------------------------|-----------------------------| diff --git a/docs/developer-docs/integrations/independently-verifying-ic-signatures.md b/docs/developer-docs/integrations/independently-verifying-ic-signatures.md index 4a4f516e21..3b73f294b2 100644 --- a/docs/developer-docs/integrations/independently-verifying-ic-signatures.md +++ b/docs/developer-docs/integrations/independently-verifying-ic-signatures.md @@ -120,6 +120,44 @@ match result { You can reference the crate's implementation logic [here](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` + +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. + + +The following is an example of how this library can be used: + +```javascript +import initSigVerifier, {verifyIcSignature} from '@dfinity/standalone-sig-verifier-web'; + +async function example(dataRaw, signatureRaw, derPublicKey, root_key) { + // load wasm module + await initSigVerifier(); + try { + // call the signature verification wasm function + verifyIcSignature(dataRaw, signatureRaw, derPublicKey, root_key); + console.log('signature verified successfully') + } catch (error) { + // the library throws an error if the signature is invalid + console.error('signature verification failed', error) + } +} +``` + +:::caution + +When using this library, you should keep the following in mind: + +- Verifying signatures on the frontend is unsafe, as malicious actors could modify frontend code in order to bypass signature verification. Therefore, it is recommended that this library be used for demos, backends, or other situations where the code either cannot be modified or where modifications do not create a security risk. + +- This library is built from the `ic`'s `master` branch, meaning the API used may change. + +- This library's resulting Wasm module is large (400 kB when gzipped); this should be taken into consideration for your project. + +::: + +You can download the library [here](https://www.npmjs.com/package/@dfinity/standalone-sig-verifier-web). + ## Resources - Rust [ic-validator-ingress-message](https://github.com/dfinity/ic/tree/master/rs/validator) crate. diff --git a/docs/developer-docs/integrations/sns/index.md b/docs/developer-docs/integrations/sns/index.md index 9cffedd900..2a3833f8b0 100644 --- a/docs/developer-docs/integrations/sns/index.md +++ b/docs/developer-docs/integrations/sns/index.md @@ -17,13 +17,13 @@ You will find * [Alternative DAOs](./introduction/dao-alternatives.md) presenting alternative ways how to get a DAO. ## Preparing an SNS launch -This section introduces the ideas and tools needed when considering to form a DAO, including less technical aspects, such as planning the tokenomics, as well as more technical aspects, such as how different configuration choices can technically be set in the SNS. +This section introduces the ideas and tools needed when considering to form a DAO, including less technical aspects, such as designing a tokenomics proposal, as well as more technical aspects, such as how different configuration choices can technically be set in the SNS. In this documentation you will find * [An introduction to SNS preparation](./tokenomics/index.md). * [The SNS launch checklist](./tokenomics/sns-checklist.md) providing a summary of what to consider when launching an SNS. * [Pre-deployment considerations](./tokenomics/predeployment-considerations.md) introducing some non-technical considerations to take into account when planning an SNS launch. -* [SNS tokenomics](./tokenomics/tokenomics-intro.md) providing and introduction to tokenomics that can be considered when planning an SNS's tokenomics. +* [SNS tokenomics](./tokenomics/tokenomics-intro.md) providing and introduction to tokenomics that can be considered when designing an SNS's tokenomics. * [SNS rewards](./tokenomics/rewards.md) providing and introduction to SNS rewards that can be considered when planning an SNS's tokenomics. * A (technical) introduction how to convert the configurations into [SNS parameters](./tokenomics/preparation.md). diff --git a/docs/developer-docs/integrations/sns/introduction/sns-architecture.md b/docs/developer-docs/integrations/sns/introduction/sns-architecture.md index 3cc448ed7b..3798fdb1a6 100644 --- a/docs/developer-docs/integrations/sns/introduction/sns-architecture.md +++ b/docs/developer-docs/integrations/sns/introduction/sns-architecture.md @@ -5,8 +5,8 @@ sidebar_position: 2 ## Overview The core architecture of the SNS closely resembles the architecture of the Network Nervous System -(NNS), the DAO that governs the Internet Computer platform. -It includes a governance system that enables decentralized decision making and a ledger canister +(NNS), the DAO that governs the Internet Computer. +It includes a governance canister that enables decentralized decision making and a ledger canister that defines a token unique to each SNS. In contrast to the SNS, the NNS contains additional canisters that are important to run the IC platform (e.g., the cycles minting canister that is responsible for creating cycles, the registry diff --git a/docs/developer-docs/integrations/sns/testing/testing-locally.md b/docs/developer-docs/integrations/sns/testing/testing-locally.md index 3db139fe1a..ab6ba3ff0f 100644 --- a/docs/developer-docs/integrations/sns/testing/testing-locally.md +++ b/docs/developer-docs/integrations/sns/testing/testing-locally.md @@ -5,7 +5,7 @@ sidebar_position: 2 ## Overview -To help developers, DFINITY has created the [sns-testing repo](https://github.com/dfinity/sns-testing) which has scripts that help developers test the SNS process. Developers can run a local version of the Internet Computer on their local machine, deploy their dapp locally and run through [the stages](../launching/launch-summary.md) of decentralizing their dapp. +To help developers, DFINITY has created the [sns-testing repo](https://github.com/dfinity/sns-testing) which has scripts that help developers test the SNS process. Developers can run a local version of the IC execution environment on their local machine, deploy their dapp locally and run through [the stages](../launching/launch-summary.md) of decentralizing their dapp. :::info `sns-testing` repo might not work for any dapp. It is intended to showcase one example dapp and so one can tweak for their own dapp. diff --git a/docs/developer-docs/production/canister-history.md b/docs/developer-docs/production/canister-history.md deleted file mode 100644 index e9cad7db87..0000000000 --- a/docs/developer-docs/production/canister-history.md +++ /dev/null @@ -1,233 +0,0 @@ -# Canister 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. - -Viewing a canister's history can be important in use-cases such as: - -- Verifying that a canister's controller has not maliciously modified the code. - -- Verifying that a canister's controller does not maliciously change the list of controllers for the canister. For example, if a canister's controller list only displays the governance canister as the current controller, users can trust that the canister's code has not been maliciously altered. - -## How canister history works - -Canister history was introduced and released by the NNS DAO proposal [122617](https://dashboard.internetcomputer.org/proposal/122617). - -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. -::: - -You can read more about this feature on the [developer forum](https://forum.dfinity.org/t/canister-history-on-the-ic/21745). - -## Canister history example - -The following is an example of a Rust canister that displays the canister history feature and its functionality. This code includes in-line comments that document the different features and functions relating to canister history. - -```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 -} - -/// Returns all (reflexive and transitive) controllers of a canister characterized by a given principal -/// by implementing BFS over the controllers. -#[ic_cdk::update] -async fn reflexive_transitive_controllers(canister_id: Principal) -> Vec { - let mut ctrls = vec![canister_id]; - let mut queue = vec![canister_id]; - while !queue.is_empty() { - let cur = queue.pop().unwrap(); - // check if the principal characterizes a canister by determining if it is an opaque principal - if cur.as_slice().last() == Some(&0x01) { - let info = info(cur).await; - for c in info.controllers { - if !ctrls.contains(&c) { - ctrls.push(c); - queue.push(c); - } - } - } - } - ctrls -} - -/// Specifies a canister snapshot by providing a Unix timestamp in nanoseconds -/// or a canister version. -#[derive(CandidType, Deserialize, Clone)] -pub enum CanisterSnapshot { - #[serde(rename = "at_timestamp")] - AtTimestamp(u64), - #[serde(rename = "at_version")] - AtVersion(u64), -} - -/// Maps the latest canister change of the canister characterized by a given principal before or at the given `CanisterSnapshot` -/// and returns an optional integer characterizing the maximum clock skew (in nanoseconds) -/// between the subnet hosting the canister and the given `CanisterSnapshot` -/// (i.e., if this integer is `None`, then no assumptions on clock skew are needed). -/// Returns `None` if no change to map can be determined due to unavailability of canister changes in canister history -/// or due to ambiguity between canister changes with the same timestamp. -/// Traps if a canister_info call is rejected (in particular, if the given principal does not characterize a canister). -async fn map_canister_change( - canister_id: Principal, - canister_deployment: CanisterSnapshot, - f: impl Fn(&CanisterChange) -> Option, -) -> Option<(T, Option)> { - let info = info(canister_id).await; - let mut map_change = None; - let mut skew = None; - for c in info.recent_changes { - if let Some(x) = f(&c) { - match &canister_deployment { - CanisterSnapshot::AtTimestamp(t) => { - if *t == c.timestamp_nanos { - return None; - } - if *t >= c.timestamp_nanos { - map_change = Some(x); - } - let d = if *t >= c.timestamp_nanos { - *t - c.timestamp_nanos - } else { - c.timestamp_nanos - *t - }; - skew = Some(std::cmp::min(d, skew.unwrap_or(d))); - } - CanisterSnapshot::AtVersion(v) => { - if *v >= c.canister_version { - map_change = Some(x); - } else { - break; - } - } - }; - } - } - map_change.map(|x| (x, skew)) -} - -/// Returns the controllers of the canister characterized by a given principal and at the given `CanisterSnapshot` -/// and an optional integer characterizing the maximum clock skew (in nanoseconds) -/// between the subnet hosting the canister and the given `CanisterSnapshot` -/// (i.e., if this integer is `None`, then no assumptions on clock skew are needed). -/// Returns `None` if the controllers cannot be determined due to unavailability of canister changes in canister history -/// or due to ambiguity between canister changes with the same timestamp. -/// Traps if a canister_info call is rejected (in particular, if the given principal does not characterize a canister). -#[ic_cdk::update] -async fn canister_controllers( - canister_id: Principal, - canister_deployment: CanisterSnapshot, -) -> Option<(Vec, Option)> { - map_canister_change(canister_id, canister_deployment, |c| match &c.details { - Creation(creation) => Some(creation.controllers.clone()), - ControllersChange(ctrls) => Some(ctrls.controllers.clone()), - _ => None, - }) - .await -} - -/// Returns the module hash of the canister characterized by a given principal and at the given `CanisterSnapshot` -/// and an optional integer characterizing the maximum clock skew (in nanoseconds) -/// between the subnet hosting the canister and the given `CanisterSnapshot` -/// (i.e., if this integer is `None`, then no assumptions on clock skew are needed). -/// Returns `None` if the module hash cannot be determined due to unavailability of canister changes in canister history -/// or due to ambiguity between canister changes with the same timestamp. -/// Traps if a canister_info call is rejected (in particular, if the given principal does not characterize a canister). -#[ic_cdk::update] -async fn canister_module_hash( - canister_id: Principal, - canister_deployment: CanisterSnapshot, -) -> Option<(Option>, Option)> { - map_canister_change(canister_id, canister_deployment, |c| match &c.details { - Creation(_) => Some(None), - CodeUninstall => Some(None), - CodeDeployment(code_deployment) => Some(Some(code_deployment.module_hash.clone())), - _ => None, - }) - .await -} - -/// Returns the deployment chain of the canister characterized by a given principal and at the given `CanisterSnapshot`: -/// a list of canister changes starting with the change resulting in the canister deployment characterized by the given principal and at the given `CanisterSnapshot` -/// and with each subsequent change resulting in the canister deployment triggering the previous change, -/// and an optional integer characterizing the maximum clock skew (in nanoseconds) -/// between the subnets hosting the canisters from the deployment chain and the given `CanisterSnapshot` -/// (i.e., if this integer is `None`, then no assumptions on clock skew are needed). -/// The deployment chain stops if a canister change in the deployment chain cannot be determined (due to unavailability of canister changes in canister history -/// or due to ambiguity between canister changes with the same timestamp) -/// or upon encountering a change from a user principal or upon encountering a loop among canisters from the deployment chain. -/// Traps if a canister_info call is rejected (in particular, if the given principal does not characterize a canister). -#[ic_cdk::update] -async fn canister_deployment_chain( - canister_id: Principal, - canister_deployment: CanisterSnapshot, -) -> (Vec, Option) { - let mut current_canister_id = canister_id; - let mut current_canister_deployment = canister_deployment; - let mut visited_canister_ids = vec![]; // canister IDs of canisters from the deployment chain - let mut deployment_chain = vec![]; - let mut skew = None; - loop { - visited_canister_ids.push(current_canister_id); - match map_canister_change( - current_canister_id, - current_canister_deployment.clone(), - |c| match &c.details { - CodeDeployment(_) => Some(c.clone()), - _ => None, - }, - ) - .await - { - Some((c, s)) => { - let mut done = false; - match &c.origin { - FromUser(_) => { - done = true; - } - FromCanister(o) => { - if visited_canister_ids.contains(&o.canister_id) { - done = true; - } else { - current_canister_id = o.canister_id; - current_canister_deployment = match o.canister_version { - None => CanisterSnapshot::AtTimestamp(c.timestamp_nanos), - Some(v) => CanisterSnapshot::AtVersion(v), - }; - } - } - }; - deployment_chain.push(c); - skew = s - .map(|dt| Some(std::cmp::min(dt, skew.unwrap_or(dt)))) - .unwrap_or(skew); - if done { - break; - } - } - None => { - break; - } - }; - } - (deployment_chain, skew) -} -``` \ No newline at end of file diff --git a/docs/developer-docs/setup/cycles/index.md b/docs/developer-docs/setup/cycles/index.md index fbdf0a9987..543ba3459d 100644 --- a/docs/developer-docs/setup/cycles/index.md +++ b/docs/developer-docs/setup/cycles/index.md @@ -1,15 +1,13 @@ # Acquiring and managing cycles ## What are ICP cycles? -The Internet Computer blockchain (IC) provides an execution environment for canisters. The Internet Computer consists of hundreds of nodes that are run by node providers. Node providers use infrastructure (CPUs, RAM, and storage) and resources (electricity and network bandwidth) to run the platform. To make the Internet Computer sustainable, developers need to pay for the resources consumed by their canisters. Cycles are used to pay for the resources used by canisters. +The Internet Computer (IC) blockchain runs on a network of nodes owned and operated by a growing community of independent node providers (NPs) distributed across the globe. NPs spend money for running nodes, e.g. they purchase hardware and require electricity and network bandwidth. The Internet Computer Protocol compensates NPs on a monthly basis by minting and distributing rewards in the form of ICP tokens. -Cycles are not currency. You can use ICP tokens to purchase cycles and transfer them to a container called a "cycles wallet." - -When a canister needs more cycles, a developer can transfer them from the wallet to the canister. Active canisters deployed to the IC continuously burn cycles and need to be "topped-up" to keep working. +To make the IC sustainable, canister smart contracts are required to pay for the resources they consume, e.g. storage and compute. Resource consumption is not paid in ICP tokens but **cycles**. It’s typically the canister’s developer who charges the canister with cycles. As the canister is used, its cycle balance is continuously reduced. Eventually, the canister needs to be “topped up” with more cycles. The default way to get cycles is to convert ICP tokens to cycles. When doing so, the protocol burns the ICP tokens. ## Why are cycles different from ICP tokens? -Cycles are different from ICP tokens to ensure that the price of hosting a canister is not volatile. This helps decrease the risk of building dapps becoming economically infeasible if the ICP token price increases. +While the value of an ICP token is volatile, cycles are not. They are pegged to [XDR](https://en.wikipedia.org/wiki/Special_drawing_rights), a basket of fiat currencies. This has the benefit that resource consumption, e.g. smart contract executions, on the IC has a somewhat stable price. :::info Cycles are measured in very large numbers, such as billions and trillions. When you talk about cycle transfers and replenishment, you will usually operate with trillions of cycles. diff --git a/docs/developer-docs/setup/playground.md b/docs/developer-docs/setup/playground.md index 59c90dc9a4..29631509f8 100644 --- a/docs/developer-docs/setup/playground.md +++ b/docs/developer-docs/setup/playground.md @@ -73,11 +73,11 @@ This command calls the `hello_world_backend` canister that has been deployed to Any commands that intend to target a canister deployed to the playground must use the `--playground` or `--network playground` flag in order to target the borrowed canister(s). ::: -### Defining custom playground networks +## Creating a custom playground with separate pool creation -Using a custom playground network can be beneficial for several development workflows, such as sharing a canister pool with a development team to avoid managing cycles wallets for developer, or using a canister pool for CI preview deployments without having to continuously create and delete canisters. +As an alternative to a staging environment or the Motoko mainnet playground, the Motoko playground allows for custom, private playgrounds to be deployed. Using a custom playground allows for extensive customization, such as enabling access control by restricting the playground's usage to only allow certain principals, configuring more generous canister timeouts and the amount of available cycles, and allowing some (or all) of the function calls that the mainnet Motoko playground does not allow, such as sending cycles to other canisters. -Custom playground networks can be defined in the project's `dfx.json` file in the `network` definition section. The following steps can be used to define a custom playground network: +Using a custom playground can help simplify development for teams, since the whole team can use a custom playground without needing to manage individual cycle balances. - #### Step 1: Clone the Motoko playground repo with the command: @@ -85,23 +85,48 @@ Custom playground networks can be defined in the project's `dfx.json` file in th git clone https://github.com/dfinity/motoko-playground ``` -- #### Step 2: Add access control if desired. +- #### Step 2: To create a separate pool, first use the current Motoko playground pool and `wasm-utils` canisters as the starting point. -- #### Step 3: Modify the `install_code` to skip Wasm analysis. This step is important if you plan on using large Wasm files or intend to use calls that are limited by the Wasm analysis. +These can be found [here](https://github.com/dfinity/motoko-playground/tree/main/service). -- #### Step 4: Deploy your canisters. +- #### Step 3: Then, edit the `pool/Main.mo` file to change your custom playground settings, such as: -- #### Step 5: Configure your custom playground network in the `dfx.json` file as shown below: +- Add access control [here](https://github.com/dfinity/motoko-playground/blob/main/service/pool/Main.mo#L134) as desired, such as creating an `whitelist` of principals that are permitted to use the custom playground. +- Configure the canister's time to live [here](https://github.com/dfinity/motoko-playground/blob/main/service/pool/Types.mo#L22). + +- Change the Wasm transformation to fit your desired configuration [here](https://github.com/dfinity/motoko-playground/blob/main/service/pool/Main.mo#L150). In some cases, this may just be `wasm = args.wasm_module`, since if there is an `allowlist` in place, the principals allowed to install canisters can be trusted, such as: + +```motoko +let wasm = args.wasm_module; ``` + +- #### Step 4: Then deploy the pool canister, and if necessary, deploy the `wasm-utils` canister: + +``` +dfx deploy pool +dfx deploy wasm-utils +``` + +- #### Step 5: Lastly, define the local playground network in your project's `dfx.json` file. In this definition, you will need to set the playground canister's ID (the `pool` canister ID) and define the amount of seconds before a canister is returned to the pool, as shown below: + +```json "": { "playground": { "playground_canister": "", "timeout_seconds": - } + }, + "providers": [ + "https://icp0.io" + ] } ``` +If the value `` is set as `playground`, then the command `dfx deploy --playground` will deploy to your custom playground. Otherwise, the command has to use `--network `. + +:::info +This network definition can also go into `networks.json` file so it applies to every project, not just the current project, since `dfx.json` files are project-specific. To see where the `networks.json` file is located, use the command `dfx info networks-json-path`. + ## Motoko playground in the web browser Motoko playground is also available through the Motoko playground frontend canister, which can be accessed at the following public URL: @@ -266,3 +291,5 @@ window.addEventListener('message', responseListener) :::info This example works for `localhost` out of the box. To use this feature in production, please submit a PR to the [Motoko playground](https://github.com/dfinity/motoko-playground.git) repository that adds your application's public URL to the file `src/integrations/allowedOrigins.js`. ::: + + diff --git a/docs/references/ledger.md b/docs/references/ledger.md index 29d8cca6a0..2207fe5416 100644 --- a/docs/references/ledger.md +++ b/docs/references/ledger.md @@ -33,11 +33,22 @@ The ledger canister keeps track of **accounts**: h = sha224(“\x0Aaccount-id” || principal || subaccount_identifier) -So, there are two steps to obtain the account corresponding to a principal and a subaccount identifier: -- First, hash using SHA224 the concatenation of domain separator `\x0Aaccount-id`, the principal and the subaccount identifier. Here, the domain separator consists of a string (here \"account-id\") prepended by a single byte equal to the length of the string (here, \\x0A). +The following call to the method `account_identifier` on the ledger canister (`ryjl3-tyaaa-aaaaa-aaaba-cai`) can be used to get your account identifier; replace the value `PRINCIPAL` with your account's principal: -- Then, prepend with the (big endian representation of the) CRC32 of the resulting hash value. +``` +dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai account_identifier '(record {owner = principal "PRINCIPAL"; subaccount = opt blob "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01" })' --candid rs/rosetta-api/icp_ledger/ledger.did + +( + blob "\af^\f8\c2R\e0/\07\f5;%\d4\1a\ac\a4\9cB\0a\94\1a\94\9c\e2X\fc\85\bdn\c51N\1c", +) +``` + +On the backend, the method `account_identifier` completes the following steps to get the account identifier: + +- First, it hashes the principal and the subaccount identifier using SHA224 the concatenation of domain separator `\x0Aaccount-id`. Here, the domain separator consists of a string (here \"account-id\") prepended by a single byte equal to the length of the string (here, \\x0A). + +- Then, it is prepended with the (big endian representation of the) CRC32 of the resulting hash value. #### Default account {#_default_account} diff --git a/docs/tutorials/developer-journey/_attachments/CandidUI.png b/docs/tutorials/developer-journey/_attachments/CandidUI.png new file mode 100644 index 0000000000..c8f7f11b17 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/CandidUI.png differ diff --git a/docs/tutorials/developer-journey/_attachments/CandidUI_icrc.png b/docs/tutorials/developer-journey/_attachments/CandidUI_icrc.png new file mode 100644 index 0000000000..c8f7f11b17 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/CandidUI_icrc.png differ diff --git a/docs/tutorials/developer-journey/_attachments/Candid_BTC.png b/docs/tutorials/developer-journey/_attachments/Candid_BTC.png new file mode 100644 index 0000000000..4319625177 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/Candid_BTC.png differ diff --git a/docs/tutorials/developer-journey/_attachments/Candid_BTC2.png b/docs/tutorials/developer-journey/_attachments/Candid_BTC2.png new file mode 100644 index 0000000000..3499689f49 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/Candid_BTC2.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns0.png b/docs/tutorials/developer-journey/_attachments/nns0.png new file mode 100644 index 0000000000..99308a9af7 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns0.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns1.png b/docs/tutorials/developer-journey/_attachments/nns1.png new file mode 100644 index 0000000000..4557399549 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns1.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns10.png b/docs/tutorials/developer-journey/_attachments/nns10.png new file mode 100644 index 0000000000..1ec088e98a Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns10.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns11.png b/docs/tutorials/developer-journey/_attachments/nns11.png new file mode 100644 index 0000000000..f612f3fcfb Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns11.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns12.png b/docs/tutorials/developer-journey/_attachments/nns12.png new file mode 100644 index 0000000000..f17e83c0e8 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns12.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns13.png b/docs/tutorials/developer-journey/_attachments/nns13.png new file mode 100644 index 0000000000..2f2c2e8785 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns13.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns14.png b/docs/tutorials/developer-journey/_attachments/nns14.png new file mode 100644 index 0000000000..5774a7c289 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns14.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns15.png b/docs/tutorials/developer-journey/_attachments/nns15.png new file mode 100644 index 0000000000..104abe1630 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns15.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns16.png b/docs/tutorials/developer-journey/_attachments/nns16.png new file mode 100644 index 0000000000..13198ecc40 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns16.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns17.png b/docs/tutorials/developer-journey/_attachments/nns17.png new file mode 100644 index 0000000000..cf631f7875 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns17.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns2.png b/docs/tutorials/developer-journey/_attachments/nns2.png new file mode 100644 index 0000000000..b1e2b88334 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns2.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns3.png b/docs/tutorials/developer-journey/_attachments/nns3.png new file mode 100644 index 0000000000..9b27ba996e Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns3.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns4.png b/docs/tutorials/developer-journey/_attachments/nns4.png new file mode 100644 index 0000000000..17f57b84e0 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns4.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns5.png b/docs/tutorials/developer-journey/_attachments/nns5.png new file mode 100644 index 0000000000..0bbbb5753b Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns5.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns6.png b/docs/tutorials/developer-journey/_attachments/nns6.png new file mode 100644 index 0000000000..ce3e2d5f9b Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns6.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns7.png b/docs/tutorials/developer-journey/_attachments/nns7.png new file mode 100644 index 0000000000..c3bf2133e6 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns7.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns8.png b/docs/tutorials/developer-journey/_attachments/nns8.png new file mode 100644 index 0000000000..477f0ad543 Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns8.png differ diff --git a/docs/tutorials/developer-journey/_attachments/nns9.png b/docs/tutorials/developer-journey/_attachments/nns9.png new file mode 100644 index 0000000000..0990cee42b Binary files /dev/null and b/docs/tutorials/developer-journey/_attachments/nns9.png differ diff --git a/docs/tutorials/developer-journey/index.md b/docs/tutorials/developer-journey/index.md index 034059953b..6a900cbbb1 100644 --- a/docs/tutorials/developer-journey/index.md +++ b/docs/tutorials/developer-journey/index.md @@ -6,6 +6,15 @@ Are you ready to get started developing on the Internet Computer, but not sure w The developer journey is designed to give both new and existing developers a clear learning path to develop on the Internet Computer. Starting at level 0 with an introduction to the Internet Computer, terminology, and setting up a developer environment, to level 5 that details building complex dapps, the Developer Journey contains essential information for developers of all skill levels. +:::info + +In this developer journey, we focus on developing canisters and applications using Motoko. In the future, there will be additional variations of the developer journey that focus on different developer paths, such as: + +- Rust development. +- ckBTC-focused development. +- ckETH-focused development. + +::: ## Level 0: Pre-flight operations @@ -35,29 +44,30 @@ The developer journey is designed to give both new and existing developers a cle - [2.5 Unit, integration, and end2end testing](level-2/2.5-unit-testing.md) - [2.6 Motoko level 2](level-2/2.6-motoko-lvl2.md) -### Level 3: Space engineer -- [3.1 Motoko package managers.](level-3/3.1-package-managers.md) -- [3.2 Using HTTPS outcalls.](level-3/3.2-https-outcalls.md) -- [3.3 Certified data.](level-3/3.3-certified-data.md) -- [3.4 Introduction to agents.](level-3/3.4-intro-to-agents.md) -- [3.5 Identities and authentication.](level-3/3.5-identities-and-auth.md) -- [3.6 Motoko level 3.](level-3/3.6-motoko-lvl3.md) +## Level 3: Space engineer + +- [3.1 Motoko package managers](level-3/3.1-package-managers.md) +- [3.2 Using HTTPS outcalls](level-3/3.2-https-outcalls.md) +- [3.3 Certified data](level-3/3.3-certified-data.md) +- [3.4 Introduction to agents](level-3/3.4-intro-to-agents.md) +- [3.5 Identities and authentication](level-3/3.5-identities-and-auth.md) +- [3.6 Motoko level 3](level-3/3.6-motoko-lvl3.md) -### Level 4: Space pilot +## Level 4: Space pilot -- 4.1 Using the ICP ledger -- 4.2 ICRC-1 tokens -- 4.3 ckBTC and Bitcoin integration -- 4.4 NNS governance and staking -- 4.5 Using quill -- 4.6 Motoko level 4 +- [4.1 Using the ICP ledger](level-4/4.1-icp-ledger.md) +- [4.2 ICRC-1 tokens](level-4/4.2-icrc-tokens.md) +- [4.3 ckBTC and Bitcoin integration](level-4/4.3-ckbtc-and-bitcoin.md) +- [4.4 NNS governance and staking](level-4/4.4-nns-governance.md) +- [4.5 Using quill](level-4/4.5-using-quill.md) +- [4.6 Motoko level 4](level-4/4.6-motoko-lvl4.md) -### Level 5: Internet Computer astronaut +## Level 5: Internet Computer astronaut -- 5.1 Developing an encrypted notes dapp with vetKD -- 5.2 Developing a dapp using the IC Ethereum integration -- 5.3 Creating a DEX -- 5.4 Creating NFTs on the IC -- 5.5 Creating an SNS -- 5.6 Next steps +- [5.1 Developing an encrypted notes dapp with vetKD] +- [5.2 Developing a dapp using the IC Ethereum integration] +- [5.3 Creating a DEX] +- [5.4 Creating NFTs on the IC] +- [5.5 Creating an SNS] +- [5.6 Next steps] diff --git a/docs/tutorials/developer-journey/level-0/01-ic-overview.md b/docs/tutorials/developer-journey/level-0/01-ic-overview.md index 94efe8f9a1..00e586d79f 100644 --- a/docs/tutorials/developer-journey/level-0/01-ic-overview.md +++ b/docs/tutorials/developer-journey/level-0/01-ic-overview.md @@ -1,5 +1,7 @@ # 0.1 Overview of the Internet Computer +[![ICP Developer Journey 0.1 | Overview of the Internet Computer](https://img.youtube.com/vi/oBUpJ4CqmN0/0.jpg)](https://youtu.be/oBUpJ4CqmN0?si=q5r223tFnWoZTMGz) + ## Overview The **Internet Computer (IC)** is a secure and transparent blockchain-based network that can be used to host data and programs. Programs and their data hosted on the IC are referred to as **decentralized applications**, often abbreviated to **dapps**. @@ -109,6 +111,27 @@ II can be integrated with dapps on the IC and helps secure your online identity Want to go further into this topic? Check out [this documentation.](https://internetcomputer.org/how-it-works/web-authentication-identity/) +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + + ## Next steps - [0.2 Internet Computer terminology](02-ic-terms.md). diff --git a/docs/tutorials/developer-journey/level-0/02-ic-terms.md b/docs/tutorials/developer-journey/level-0/02-ic-terms.md index 06b5f710af..44b422ac16 100644 --- a/docs/tutorials/developer-journey/level-0/02-ic-terms.md +++ b/docs/tutorials/developer-journey/level-0/02-ic-terms.md @@ -73,6 +73,26 @@ This page introduces some of the most commonly used terminology that developers - **Motoko:** Motoko is a programming language developed and designed for programming on the Internet Computer. It was designed specifically to support the IC's unique features and attributes, such as the actor model and smart contract compilation to WebAssembly. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps - [0.3 Developer environment setup](03-dev-env.md). diff --git a/docs/tutorials/developer-journey/level-0/03-dev-env.md b/docs/tutorials/developer-journey/level-0/03-dev-env.md index e17398d1f4..61a2209c80 100644 --- a/docs/tutorials/developer-journey/level-0/03-dev-env.md +++ b/docs/tutorials/developer-journey/level-0/03-dev-env.md @@ -106,6 +106,27 @@ In future modules, we'll refer to this directory as the **working directory**. E #### Why does this matter? We'll use this working directory to contain the projects that we build throughout our developer journey. This will help keep things organized in our local file structure. + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps - [0.4 Introduction to canisters](04-intro-canisters.md). diff --git a/docs/tutorials/developer-journey/level-0/04-intro-canisters.md b/docs/tutorials/developer-journey/level-0/04-intro-canisters.md index bca37f52dc..67fbc18469 100644 --- a/docs/tutorials/developer-journey/level-0/04-intro-canisters.md +++ b/docs/tutorials/developer-journey/level-0/04-intro-canisters.md @@ -72,6 +72,26 @@ For network bandwidth, cycles are charged at the time of usage. When a canister If a canister runs out of cycles, the canister is uninstalled. The code and state are deleted, but the remainder of the canister's information remains. To avoid unexpected deletion, canisters have a 'freezing threshold'. If a canister's balance dips below this threshold, then the canister will stop processing any new requests. Replies will still be processed. The system will throw an error if the canister attempts to perform any action that would result in the canister's cycles balance dipping below the freezing threshold. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps - [0.5 Introduction to languages](05-intro-languages.md). diff --git a/docs/tutorials/developer-journey/level-0/05-intro-languages.md b/docs/tutorials/developer-journey/level-0/05-intro-languages.md index 574122c45b..78dbcb578f 100644 --- a/docs/tutorials/developer-journey/level-0/05-intro-languages.md +++ b/docs/tutorials/developer-journey/level-0/05-intro-languages.md @@ -103,6 +103,26 @@ Solidity is supported on the IC through [Bitfinity](https://docs.bitfinity.netwo C++ is available through the [icpp-pro CDK](https://docs.icpp.world/) developed by icpp World. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps - [0.6 Introduction to dfx](06-intro-dfx.md). diff --git a/docs/tutorials/developer-journey/level-0/06-intro-dfx.md b/docs/tutorials/developer-journey/level-0/06-intro-dfx.md index b85f0650c3..99ef31f00d 100644 --- a/docs/tutorials/developer-journey/level-0/06-intro-dfx.md +++ b/docs/tutorials/developer-journey/level-0/06-intro-dfx.md @@ -200,7 +200,26 @@ In this simple 'Hello, world' program, there are a few key elements: We'll explore actor objects, classes, and asynchronous messages in a future tutorial. For now, this will wrap up our introduction to `dfx`. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps - [1.1 Exploring a live demo.](../level-1/1.1-live-demo.md) - diff --git a/docs/tutorials/developer-journey/level-1/1.1-live-demo.md b/docs/tutorials/developer-journey/level-1/1.1-live-demo.md index faa516828e..30dc9f30d7 100644 --- a/docs/tutorials/developer-journey/level-1/1.1-live-demo.md +++ b/docs/tutorials/developer-journey/level-1/1.1-live-demo.md @@ -142,6 +142,26 @@ You can play around with this user interface by inputting different text, such a ![Candid UI 4](../_attachments/candid-4.png) +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Now that we've explored a live canister deployed on the Motoko playground, we'll move onto developing our own dapp rather than using the default template files. But first, let's go over the basics of Motoko in Motoko level 1. diff --git a/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.md b/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.md index 93fecbfd5d..d62c077fbf 100644 --- a/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.md +++ b/docs/tutorials/developer-journey/level-1/1.2-motoko-lvl1.md @@ -291,9 +291,29 @@ The output of this canister call will be: ("Hello, Paris!") ``` +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. ## Next steps Now that we've covered the basics of Motoko, let's put these concepts all together in practice by developing our first dapp! - [1.3 Developing your first dapp](1.3-first-dapp.md). + diff --git a/docs/tutorials/developer-journey/level-1/1.3-first-dapp.md b/docs/tutorials/developer-journey/level-1/1.3-first-dapp.md index da4980a1d2..7e4a8176f9 100644 --- a/docs/tutorials/developer-journey/level-1/1.3-first-dapp.md +++ b/docs/tutorials/developer-journey/level-1/1.3-first-dapp.md @@ -709,7 +709,7 @@ function displayResults() { resultsDiv.innerHTML = resultHTML; }; -//This helper updates the local JS object that teh browser holds +//This helper updates the local JS object that the browser holds // Example JSON that the frontend will get using the values above // [["Motoko","0"],["Python","0"],["Rust","0"],["TypeScript","0"]] function updateLocalVoteCounts(arrayOfVoteArrays){ @@ -755,8 +755,29 @@ Congratulations! You've just developed your first full dapp! You can find the finish code's repo [here](https://github.com/jessiemongeon1/dev-journey-poll-dapp/tree/main) for you to clone or fork. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps In this tutorial, we only deployed our dapp to our local environment. In the next module, we'll set up a cycles wallet and acquire cycles in order for us to deploy our dapp to the Internet Computer mainnet. - [1.4 Acquiring and using cycles](1.4-using-cycles.md). + diff --git a/docs/tutorials/developer-journey/level-1/1.4-using-cycles.md b/docs/tutorials/developer-journey/level-1/1.4-using-cycles.md index 61984e46fe..3cbb683607 100644 --- a/docs/tutorials/developer-journey/level-1/1.4-using-cycles.md +++ b/docs/tutorials/developer-journey/level-1/1.4-using-cycles.md @@ -251,8 +251,29 @@ To further explore cycle management please see the following articles: - **[Getting free cycles from DFINITY cycles faucet](/docs/developer-docs/setup/cycles/cycles-faucet.md)**. - **[Converting ICP tokens into cycles](/docs/developer-docs/setup/cycles/converting_icp_tokens_into_cycles.md)**. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps In this tutorial, we set up our identity and acquired free cycles from the cycles faucet. Now that we have cycles, we can deploy our first dapp on the IC mainnet. - [1.5 Deploying canisters](1.5-deploying-canisters.md). + diff --git a/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.md b/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.md index da87f5a215..17fbfb46fb 100644 --- a/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.md +++ b/docs/tutorials/developer-journey/level-1/1.5-deploying-canisters.md @@ -115,8 +115,29 @@ https://5h5yf-eiaaa-aaaaa-qaada-cai.icp0.io If you open this URL in your web browser, you will see the same poll dapp frontend that you saw when you deployed it locally. The only difference is that now your dapp is hosted 100% on-chain, does not rely on your local execution environment to keep running, and you can send this URL to your friends and get them to vote on your poll! +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Now that we have canisters running on the mainnet, the next steps are to learn how we can manage these canisters, such as how to upgrade them or delete them. - [1.6 Managing canisters](1.6-managing-canisters.md) + diff --git a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md index 8cc3a76e92..8c1834ed1c 100644 --- a/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md +++ b/docs/tutorials/developer-journey/level-1/1.6-managing-canisters.md @@ -4,6 +4,12 @@ Now that we have canisters deployed on the mainnet, the next step is to learn how to manage those canisters. Managing a canister includes workflows such as obtaining information, setting an identity as the canister's owner, and deleting a canister. We'll dive into these different workflows and more in this guide to assure that you have the core fundamentals of how to maintain canisters. +## The IC management canister + +To enable canister management, the IC management canister exposes management functionality to end users and other canisters. While it is titled the 'management canister', it is not actually a canister that exists with an isolated state, Wasm code, etc; it is a facade. It is important to understand the management canister's role, however, in order to understand some of the advanced IC features, such as threshold ECDSA and integrations like Bitcoin. + +Management operations such as updating a canister, creating a canister, and stopping or starting a canister, are sent to the management canister and then executed. When executed, the messages are sent to the relevant subnet and intercepted by the execution environment, which triggers the execution of the operation. + ## Prerequisites Before you start, verify that you have set up your developer environment according to the instructions in [0.3 Developer environment setup](../level-0/03-dev-env.md). @@ -347,8 +353,29 @@ dfx canister --network ic stop --all dfx canister --network ic delete --all ``` +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps In the next step of our developer journey, we'll explore upgrading canisters, storage, and persistence. - [2.1 Storage and persistence](../level-2/2.1-storage-persistence.md). + diff --git a/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.md b/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.md index c35b3e25ff..5c85b92900 100644 --- a/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.md +++ b/docs/tutorials/developer-journey/level-2/2.1-storage-persistence.md @@ -181,6 +181,25 @@ Now, navigate back to the Candid UI URL provided in the output and click the 'Ca ![Counter Candid UI 2](../_attachments/counter_ui2.png) +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. ## Next steps diff --git a/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.md b/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.md index 70670dbb77..f19e5fa73c 100644 --- a/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.md +++ b/docs/tutorials/developer-journey/level-2/2.2-advanced-canister-calls.md @@ -245,6 +245,26 @@ The output should resemble the following: (5 : nat) ``` +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, let's dive into using third-party canisters diff --git a/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.md b/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.md index 7d6615fb0c..32e612c30f 100644 --- a/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.md +++ b/docs/tutorials/developer-journey/level-2/2.3-third-party-canisters.md @@ -141,8 +141,29 @@ URLs: Now, we can interact with the II canister locally using the CLI or the Candid UI. In a future tutorial we'll integrate our backend canister with the II canister. For now, that'll wrap up this module. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, let's take a deeper dive into an introduction of Candid and the role that it plays in development on the IC. - [2.4 Introduction to Candid](2.4-intro-candid.md). + diff --git a/docs/tutorials/developer-journey/level-2/2.4-intro-candid.md b/docs/tutorials/developer-journey/level-2/2.4-intro-candid.md index 97b5ed8a1d..4554233e38 100644 --- a/docs/tutorials/developer-journey/level-2/2.4-intro-candid.md +++ b/docs/tutorials/developer-journey/level-2/2.4-intro-candid.md @@ -300,6 +300,26 @@ Lastly, call the 'get' method again to return our final counter value: ![Candid UI 5](../_attachments/candid_ui-5.png) +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, let's explore how to test and debug projects and canisters. diff --git a/docs/tutorials/developer-journey/level-2/2.5-unit-testing.md b/docs/tutorials/developer-journey/level-2/2.5-unit-testing.md index 7244109be0..6b2b8e116d 100644 --- a/docs/tutorials/developer-journey/level-2/2.5-unit-testing.md +++ b/docs/tutorials/developer-journey/level-2/2.5-unit-testing.md @@ -416,6 +416,26 @@ jobs: To learn more about Github workflows, check out the [Github documentation here](https://docs.github.com/en/actions/using-workflows). +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps To wrap up level 2 of our developer journey, we'll dive into Motoko level 2 and learn more about Motoko's fundamentals. diff --git a/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.md b/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.md index 9f6066da95..28f0514c8a 100644 --- a/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.md +++ b/docs/tutorials/developer-journey/level-2/2.6-motoko-lvl2.md @@ -374,6 +374,26 @@ dfx canister call daemon launch This command makes a call to the `daemon` canister, directly to the public function `launch`. The result of this call should return a `("\"The daemon process is running\"")` response. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps That'll wrap up level 2 of our developer journey! In the next level, we'll start by taking a look at using package managers for Motoko. diff --git a/docs/tutorials/developer-journey/level-3/3.1-package-managers.md b/docs/tutorials/developer-journey/level-3/3.1-package-managers.md index e7f4012fbc..a9f6816ac5 100644 --- a/docs/tutorials/developer-journey/level-3/3.1-package-managers.md +++ b/docs/tutorials/developer-journey/level-3/3.1-package-managers.md @@ -1,4 +1,4 @@ -# 3.1: Motoko package managers +# 3.1 Motoko package managers ## Overview @@ -159,11 +159,31 @@ actor characterCount { }; ``` +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, let's dive into using HTTPS outcalls: -- [3.2: HTTPS outcalls](3.2-https-outcalls.md). +- [3.2 HTTPS outcalls](3.2-https-outcalls.md). diff --git a/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.md b/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.md index 9b82586bd5..9e261a10e2 100644 --- a/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.md +++ b/docs/tutorials/developer-journey/level-3/3.2-https-outcalls.md @@ -1,4 +1,4 @@ -# 3.2: Using HTTPS outcalls +# 3.2 Using HTTPS outcalls ## Overview @@ -791,8 +791,29 @@ Once you open the Candid UI, you can use the 'Call' button to call the `send_htt You can play with a version of this canister running on-chain here: https://a4gq6-oaaaa-aaaab-qaa4q-cai.raw.ic0.app/?id=fc4tu-siaaa-aaaap-qbonq-cai. + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, let's dive deeper into certified variables: -- [3.3: Certified variables](3.3-certified-data.md). +- [3.3 Certified variables](3.3-certified-data.md). diff --git a/docs/tutorials/developer-journey/level-3/3.3-certified-data.md b/docs/tutorials/developer-journey/level-3/3.3-certified-data.md index 43114285ef..751143ff89 100644 --- a/docs/tutorials/developer-journey/level-3/3.3-certified-data.md +++ b/docs/tutorials/developer-journey/level-3/3.3-certified-data.md @@ -1,4 +1,4 @@ -# 3.3: Certified data +# 3.3 Certified data ## Overview @@ -344,8 +344,28 @@ Canisters using HTTP asset certification: - [NNS frontend.](https://github.com/dfinity/nns-dapp/blob/49126394df77b9583e508277fc736eda51de47be/rs/src/assets.rs#L123) - [Certified assets canister.](https://github.com/dfinity/certified-assets) +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, let's dive deeper into agents: -- [3.4: Introduction to agents](3.4-intro-to-agents.md). +- [3.4 Introduction to agents](3.4-intro-to-agents.md). diff --git a/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.md b/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.md index f87ba697e8..c957210244 100644 --- a/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.md +++ b/docs/tutorials/developer-journey/level-3/3.4-intro-to-agents.md @@ -1,4 +1,4 @@ -# 3.4: Introduction to agents +# 3.4 Introduction to agents ## Overview @@ -230,8 +230,28 @@ Enter a value, then select 'Generate!'. You will see a random maze generated in That'll wrap things up for this module! You can read more about agents, such as the Node.js agent, [here](/docs/current/developer-docs/agents/). +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, let's take a look at identities and authentication. -- [3.5: Identities and authentication](3.5-identities-and-auth.md). \ No newline at end of file +- [3.5 Identities and authentication](3.5-identities-and-auth.md). \ No newline at end of file diff --git a/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.md b/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.md index de7abdaa1d..1c463eb9d2 100644 --- a/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.md +++ b/docs/tutorials/developer-journey/level-3/3.5-identities-and-auth.md @@ -1,4 +1,4 @@ -# 3.5: Identities and authentication +# 3.5 Identities and authentication ## Overview @@ -311,8 +311,29 @@ Your Internet Identity's principal ID will be returned: You've now integrated Internet Identity into a local dapp! That'll wrap things up for this module. +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps Next, we'll take a look at Motoko level 3: -- [3.6: Motoko level 3](3.6-motoko-lvl3.md). +- [3.6 Motoko level 3](3.6-motoko-lvl3.md). + diff --git a/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.md b/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.md index 04d886fa82..cc39e8f1ed 100644 --- a/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.md +++ b/docs/tutorials/developer-journey/level-3/3.6-motoko-lvl3.md @@ -1,4 +1,4 @@ -# 3.6: Motoko level 3 +# 3.6 Motoko level 3 ## Overview @@ -547,8 +547,28 @@ system func timer(setGlobalTimer : Nat64 -> ()) : async () { } ``` +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + ## Next steps That'll wrap up level 3 of our developer journey! In the next level, we'll start by taking a look at using the ICP ledger. -- 4.1: Using the ICP ledger. \ No newline at end of file +- [4.1 Using the ICP ledger.](../level-4/4.1-icp-ledger.md) \ No newline at end of file diff --git a/docs/tutorials/developer-journey/level-4/4.1-icp-ledger.md b/docs/tutorials/developer-journey/level-4/4.1-icp-ledger.md new file mode 100644 index 0000000000..878654d9c4 --- /dev/null +++ b/docs/tutorials/developer-journey/level-4/4.1-icp-ledger.md @@ -0,0 +1,342 @@ +# 4.1 Using the ICP ledger + +## Overview + +Recall from previous modules that ICP is the native token of the Internet Computer. ICP tokens have three key functionalities on the Internet Computer: + +- Facilitating the network's governance through neuron staking. We'll dive deeper into staking tokens in [4.4 NNS governance and staking](4.4-nns-governance.md). + +- Creating cycles by converting ICP into cycles, which are then used to pay for canister computation and resources. We briefly covered converting ICP into cycles in [1.4 Acquiring and using cycles](../level-1/1.4-using-cycles.md). + +- Rewarding NNS participants by providing ICP tokens to users that stake ICP in neurons and actively participate in voting on proposals. We'll dive deeper into NNS rewards in [4.4 NNS governance and staking](4.4-nns-governance.md). + +To interact with the ICP token, such as send it to another account or convert it into cycles, a specialized canister known as the ICP ledger canister can be used. The ledger canister is used to hold ledger accounts and record a traceable history of all ICP transactions. + +In this tutorial, we'll dive into how to deploy a local instance of the ICP ledger canister and how to interact with it. This workflow is important to learn since your local replica cannot access the mainnet ICP ledger, so to test your project's integration with the ICP ledger, you need to deploy a local instance of the ledger. The local instance, however, will not have the history and balances that the mainnet ICP ledger contains. + +The ICP ledger can only be used to interact with ICP tokens; to interact with other tokens, such as ICRC tokens, an ICRC ledger will need to be used. This ledger is covered in the module [4.2 ICRC tokens](4.2-icrc-tokens.md). + +## Accounts + +An ICP ledger account is identified by the `AccountIdentifier` value, which is a value derived from the account owner's IC principal and subaccount identifier. Accounts can only be owned by one principal; however, since a principal can refer to a canister, joint accounts can be implemented as a canister. The ICP ledger uses `AccountIdentifier`s instead of just using principal IDs since `AccountIdentifier`s allow a principal to control multiple accounts. Accounts can include a subaccount, which is an optional bitstring that distinguishes between different accounts under the same account owner. + +If you are familiar with an Ethereum or Bitcoin user's public key, a principal identifier can be thought of as the IC equivalent. When you use a principal, your corresponding secret key is used to sign messages, authenticate with the ledger, and execute transactions on your account. + +## Transaction types + +Within the ICP ledger canister, there are three types of transactions: + +- Minting: A minting transaction generates a new token for an account. + +- Burning: A burning transaction eliminates a token from existence. + +- Transferring: A transferring transaction transfers ICP between accounts. + +All transactions are recorded in the ledger canister as a **hashed blockchain**. The ICP ledger canister runs on the NNS system subnet blockchain on the mainnet. + +When state changes are recorded, each new transaction is inserted into a block and assigned a unique index value. The entire blockchain is authenticated regularly by signing the latest block using a signature. This signature can be verified by anyone using the root public key of the IC. The ledger can be queried to retrieve specific transactions. + +## Deploying the ICP ledger locally + +To deploy the ICP ledger canister locally, there are two workflows: + +- Using the `dfx-nns` command to deploy an entire instance of the NNS locally, since the ICP ledger is part of the NNS. This workflow will install an ICP ledger canister with the canister ID of `ryjl3-tyaaa-aaaaa-aaaba-cai`. This is a straightforward workflow, but it is heavyweight in the sense that it installs several things in addition to the ledger canister. + +- Deploy the ICP ledger canister locally using the Wasm file. This is the method that we'll showcase in this tutorial since it provides greater control over the deployment, such as defining the ledger's minting account, customizing the initialization arguments, and choosing which Wasm version of the ledger to use. + +The ICP ledger canister running on the mainnet is not meant to be used for other token deployments. It contains legacy code designed to be backwards compatible and should not be used for developing new ledgers. To develop a new token or ledger, the ICRC ledger can be used, which we'll cover in a [future module](4.2-icrc-tokens.md). + +### Prerequisites + +Before you start, verify that you have set up your developer environment according to the instructions in [0.3 Developer environment setup](../level-0/03-dev-env.md). + +### Creating a new project + +To get started, create a new project in your working directory. Open a terminal window, navigate into your working directory (`developer_journey`), then use the commands: + +``` +dfx start --clean --background +dfx new icp_ledger_canister +cd icp_ledger_canister +``` + +### Locating the Wasm and Candid files + +Next, we need to download the ledger's Wasm and Candid files from the latest replica version. You can find the latest replica version on the [dashboard](https://dashboard.internetcomputer.org/releases) under the **Elect new replica binary revision** field. + +Then, use the following URL to download the Wasm module: `https://download.dfinity.systems/ic//canisters/ledger-canister.wasm.gz`. + +For example, in this tutorial we'll use the URL https://download.dfinity.systems/ic/d87954601e4b22972899e9957e800406a0a6b929/canisters/ledger-canister.wasm.gz. + +Similarly, the following URL can be used to download the Candid file: `https://raw.githubusercontent.com/dfinity/ic//rs/rosetta-api/icp_ledger/ledger.did`. + +In this tutorial, we'll use the URL https://raw.githubusercontent.com/dfinity/ic/d87954601e4b22972899e9957e800406a0a6b929/rs/rosetta-api/icp_ledger/ledger.did. + +Now let's open the `dfx.json` file in the project's directory and replace the existing content with the following: + +```json +{ + "canisters": { + "icp_ledger_canister": { + "type": "custom", + "candid": "https://raw.githubusercontent.com/dfinity/ic/d87954601e4b22972899e9957e800406a0a6b929/rs/rosetta-api/icp_ledger/ledger.did", + "wasm": "https://download.dfinity.systems/ic/d87954601e4b22972899e9957e800406a0a6b929/canisters/ledger-canister.wasm.gz", + "remote": { + "id": { + "ic": "ryjl3-tyaaa-aaaaa-aaaba-cai" + } + } + } + }, + "defaults": { + "build": { + "args": "", + "packtool": "" + } + }, + "output_env_file": ".env", + "version": 1 +} +``` + +### Creating a `minting` account + +To interact with our ICP ledger, create a new identity that will act as the `minting` account, then export the account's ID as the environment variable `MINTER_ACCOUNT_ID`: + +``` +dfx identity new minter +dfx identity use minter +export MINTER_ACCOUNT_ID=$(dfx ledger account-id) +``` + +Any transfer made from the minting account will make a `Mint` transaction, while transfers to the minting account will make a `Burn` transaction. + +Now, switch back to your DevJourney identity and export its account ID as the environment variable `DEFAULT_ACCOUNT_ID`: + +``` +dfx identity use DevJourney +export DEFAULT_ACCOUNT_ID=$(dfx ledger account-id) +``` + +### Deploying the canister + +With these variables set, we can deploy the ledger canister. To deploy the canister with archiving options enabled, run the following command: + +``` +dfx deploy --specified-id ryjl3-tyaaa-aaaaa-aaaba-cai icp_ledger_canister --argument " + (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\"; + } + }) +" +``` + +In this command, we deploy the ICP ledger canister locally and pass parameters that do the following: + +- Deploy the ICP ledger canister with the same canister ID as the mainnet ledger canister to simplify switching between local and mainnet deployments. + +- Set the minting account to the `MINTING_ACCOUNT_ID` environmental variable. + +- Mint 100 ICP tokens to the `DEFAULT_ACCOUNT_ID` value. + +- Set the transfer fee to `0.0001` ICP. + +- Name the token `Local ICP` / `LICP`. + + +:::info +Since we're using the ICP ledger locally, we create a local token called LICP that we'll use for local integration testing. This LICP token does not have any value on the mainnet, and cannot be used in place of ICP for mainnet transactions. +::: + +## Interacting with the ICP ledger canister + +There are several ways to interact with the ICP ledger, such as: + +- Using the `dfx ledger` command, which is the `dfx` shortcut for interacting with the ledger. + +- Using the `dfx canister` command to interact directly with the ledger canister. + +- Using the Candid UI. + +- Using `nns-js` to interact with the ICP ledger from your web application. + +- Using the `ic-cdk` to make inter-canister calls from another canister to the ICP ledger canister. + +### Using `dfx ledger` + +To get your local ledger account ID, you can use the command: + +``` +dfx ledger account-id +``` + +Then, to check the balance of that account, use the command: + +``` +dfx ledger --network ic balance ACCOUNT_ID +``` + +Replace `ACCOUNT_ID` with the output from the `dfx ledger account-id` command. + +:::info +To use the mainnet ledger, use the flag `--network ic` with any `dfx ledger` command. +::: + +To transfer tokens from one account to another, use the command: + +``` +dfx ledger transfer --amount AMOUNT --memo MEMO RECEIVER_ACCOUNT_ID +``` + +Replace `AMOUNT` with the number of tokens to transfer, `MEMO` with a brief message to describe the reason for the transfer, and `RECEIVER_ACCOUNT_ID` with the account ID to receive the tokens. + +### Using `dfx canister` + +The `dfx canister` command can be used to call additional methods of the ICP ledger canister, such as the token's name. To call the token's name, use the command: + +``` +dfx canister call icp_ledger_canister name +``` + +In our example, this command will return the following output: + +``` +("Local ICP") +``` + +Similarly, the following command can be used to return the token's symbol: + +``` +dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai symbol '()' +``` + +In our example, this command will return the following output: + +``` +(record { symbol = "LICP" }) +``` + +To query the canister's archives, use the command: + +``` +dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai archives '()' +``` + +In our local example, there are no archives that have been created so far, resulting in the following output: + +``` +(record { archives = vec {} }) +``` + +To transfer tokens to another account, you will need to get their `AccountIdentifier`. Their `AccountIdentifier` can be derived by getting the identity's principal with the command: + +``` +dfx identity get-principal --identity IDENTITY +``` + +For example, if you want to send LICP to the `minting` account we created earlier, you can get the principal with the command: + +``` +dfx identity get-principal --identity minter +``` + +This will return the principal: + +``` +sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe +``` + +Then, you can get the `AccountIdentifier` with the command: + +``` +dfx ledger account-id --of-principal sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe +``` + +This will return the following output: + +``` +d52f7f2b7277f025bcaa5c90b10d122274faba289 +``` + +Then, let's combine the output of these commands to form a transfer transaction: + +``` +export TO_ACCOUNT = "d52f7f2b7277f025bcaa5c90b10d122274faba2891bea519105309ae1f0af91d" +dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai transfer '(record { to = $(python3 -c 'print("vec{" + ";".join([str(b) for b in bytes.fromhex("'$TO_ACCOUNT'")]) + "}")'); memo = 1:nat64; amount = record {e8s = 200_000_000 }; fee = record { e8s = 10_000 }; })' +``` + +The output of this command will return the block index that the transaction took place in. Since our example is deployed locally and we haven't run any other commands, our transaction takes place within the first block: + +``` +(variant { Ok = 1 : nat64 }) +``` + +To confirm that the transaction was successful, query the balance of the `AccountIdentifier` with the command: + +``` +dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai account_balance '(record { account = '$(python3 -c 'print("vec{" + ";".join([str(b) for b in bytes.fromhex("'$TO_ACCOUNT'")]) + "}")')' })' +``` + +This should return a balance of `200_000_000`: + +``` +(record { e8s = 200_000_000 : nat64 }) +``` + +### Using the Candid UI + +Alternatively, the Candid UI can be used to interact with the local ICP ledger's methods by navigating to the URL provided when the canister was deployed, such as: + +http://127.0.0.1:4943/?canisterId=bnz7o-iuaaa-aaaaa-qaaaa-cai&id=ryjl3-tyaaa-aaaaa-aaaba-cai + +After navigating to this URL in a web browser, the Candid UI will resemble the following: + +![Candid UI](../_attachments/CandidUI.png) + +## Resources + +For information on how to use `nns-js` to interact with the ledger from the web application, see the documentation [here](/docs/current/developer-docs/integrations/ledger/interact-with-ledger#interact-with-icp-ledger-from-your-web-application). + +For more information on using the `ic-cdk` to make inter-canister calls to the ICP ledger, see the documentation [here](/docs/current/developer-docs/integrations/ledger/interact-with-ledger#interacting-with-icp-from-a-canister-inter-canister-calls-via-ic-cdk). + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + +## Next steps + +Next, we'll dive into ICRC-1 tokens and how to deploy your own token using the ICRC-1 standard. + +- [4.2 ICRC-1 tokens](4.2-icrc-tokens.md). + diff --git a/docs/tutorials/developer-journey/level-4/4.2-icrc-tokens.md b/docs/tutorials/developer-journey/level-4/4.2-icrc-tokens.md new file mode 100644 index 0000000000..f2480c3fee --- /dev/null +++ b/docs/tutorials/developer-journey/level-4/4.2-icrc-tokens.md @@ -0,0 +1,456 @@ +# 4.2 ICRC-1 tokens + +## Overview + +For developers to create their own fungible tokens on the Internet Computer, the ICRC-1 token standard can be used. The acronym "ICRC" stands for "Internet Computer Request for Comments", as the standard was created by the Internet Computer working group. More information can be found on the working group [here](https://github.com/dfinity/ICRC). + +:::info +Standards defined within the ICRC group are not specific to tokens; anything can be standardized using an ICRC standard. Some examples may be the standardization of metadata fields or digital assets other than tokens. +::: + +The purpose of the ICRC-1 standard is to create a universally accepted standard for creating and recording token transactions on the Internet Computer. The ICRC-1 standard defines the general functionalities of ledgers; any tokens and their corresponding ledgers that want to support the ICRC-1 standard must fulfill all requirements within the standard. A detailed account of the standard can be found [here](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1). + +There are several extensions of the ICRC-1 standard, such as the [ICRC-2 standard](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-2/README.md). Not all ICRC standards must be extensions of the ICRC-1 standard, though. For this tutorial, we'll focus on the ICRC-1 standard, ICRC-1 ledger, and briefly look into the ICRC-2 standard's endpoints. + +## What's the difference between the ICP and ICRC-1 ledgers? + +The ICP ledger is a specific implementation of a ledger, which initially did not follow a standard. The ICP ledger existed prior to the ideation and creation of the ICRC-1 standard. + +ICRC-1 is an official standard and is not a specific implementation of a ledger. There are several different ICRC-1 ledgers with different implementations, but all follow the same standard. + +The ICP and ICRC-1 ledger use different endpoints, different transactions, different block objects, in addition to other subtle differences. + +### `Account`s versus `AccountIdentifier`s? + +The most important difference between the ICP ledger and the ICRC-1 standard is their implementation of accounts. The ICRC-1 standard specifies `Account`s as a `struct` data type that contains a principal and an optional subaccount. + + +```candid +type Subaccount = blob; +type Account = record { owner : principal; subaccount : opt Subaccount; }; +``` + +In contrast, the ICP ledger uses `AccountIdentifier`s to represent accounts, which are essentially a hash of the ICRC-1 `Account` value. + +An `Account` can be converted into an `AccountIdentifier`, but an `AccountIdentifier` cannot be converted into an `Account`. This factor provides the ICP ledger with a level of anonymity, though it means the ICP ledger cannot have the same internal representation as an ICRC-1 ledger. + +### Endpoints + +The ICP ledger implements all ICRC-1 endpoints, but is not an implementation of an ICRC-1 ledger due to the ICP ledger's use of `AccountIdentifier`s. + +## Index canisters + +If you want to find information about a transaction for a specific `Account` or `AccountIdentifier`, you could query all of the transactions within the ICP or ICRC-1 ledger, then parse through the transaction records for the results you're looking for. If you're querying a local ledger canister, the transaction history may not be very long and this process may have low latency. However, if you're using the mainnet ledgers, parsing the transaction history may be a hassle. + +As an alternative, an **index** canister can be queried. The index canister provides an endpoint for querying the transaction list for a specific account, as well as other information such as an account's current balance. Since the ICP and ICRC-1 ledgers use different account representations (`Account` and `AccountIdentifier`), the ICP and ICRC-1 index canisters do not use the same endpoints. + +On the mainnet, the ICP index canister runs on the NNS subnet and has the canister ID [qhbym-qaaaa-aaaaa-aaafq-cai](https://dashboard.internetcomputer.org/canister/qhbym-qaaaa-aaaaa-aaafq-cai). + +There are several ICRC-1 compatible ledgers, and in turn several ICRC-1 index canisters. One example is the ICRC-1 ledger for ckBTC transactions, which has the canister ID [n5wcd-faaaa-aaaar-qaaea-cai](https://dashboard.internetcomputer.org/canister/n5wcd-faaaa-aaaar-qaaea-cai). + +## Extensions of the standard + +The ICRC-1 standard intentionally excludes certain ledger functions that are necessary for building diverse DeFi applications, such as: + +- Transaction notifications for smart contracts. + +- An interface and structure for fetching blocks. + +- Pre-signed transactions. + +The ICRC-1 standard defines the `icrc1_supported_standards` endpoint to accommodate these functions through extensions of the standard. This endpoint returns all specifications implemented by the ledger, such as `ICRC-2` or `DIP-20`. + +## Metadata + +The ICRC-1 token standard allows for several optional metadata fields to be specified. Metadata can be used to help improve the user experience and simplify the token's integration with wallets. Each metadata key is an arbitrary Unicode string that uses the format `:`, where the namespace `icrc1` is reserved for metadata defined for the ICRC-1 standard. Metadata entries include: + +- `icrc1:symbol`: The token's currency code, such as `variant { Text = "XTKN" }`. + +- `icrc1:name`: The token's name, such as `variant { Text = "Test Token" }`. + +- `icrc1:decimals`: The number of decimals used by the token, such as `variant { Nat = 8 }` + +- `icrc1:fee`: The token's default transfer fee, such as `variant { Nat = 10_000 }`. + +## Deploying a ICRC-1 ledger locally + +Deploying an ICRC-1 ledger canister locally uses the same steps that we used in the last module to deploy the local ICP canister, but we'll use different Wasm and Candid files. + +### Prerequisites + +Before you start, verify that you have set up your developer environment according to the instructions in [0.3 Developer environment setup](../level-0/03-dev-env.md). + +### Creating a new project + +To get started, create a new project in your working directory. Open a terminal window, navigate into your working directory (`developer_journey`), then use the commands: + +``` +dfx start --clean --background +dfx new icrc1_ledger_canister +cd icrc1_ledger_canister +``` + +### Locating the Wasm and Candid files + +We can access the Wasm and Candid files in the same way that we located the ICP ledger files. Remember that we'll need the latest replica version, which can be found on the [dashboard](https://dashboard.internetcomputer.org/releases) under the **Elect new replica binary revision** field. + +Then, use the following URL to download the Wasm module: `https://download.dfinity.systems/ic//canisters/ic-icrc1-ledger.wasm.gz`. In this tutorial we'll use the URL https://download.dfinity.systems/ic/d87954601e4b22972899e9957e800406a0a6b929/canisters/ic-icrc1-ledger.wasm.gz. + +Use the following URL can be used to download the Candid file: `https://raw.githubusercontent.com/dfinity/ic//rs/rosetta-api/icrc1/ledger/ledger.did`. In this tutorial, we'll use the URL https://raw.githubusercontent.com/dfinity/ic/d87954601e4b22972899e9957e800406a0a6b929/rs/rosetta-api/icrc1/ledger/ledger.did. + +Open the `dfx.json` file in the project's directory and replace the existing content with the following: + +```json +{ + "canisters": { + "icrc1_ledger_canister": { + "type": "custom", + "candid": "https://raw.githubusercontent.com/dfinity/ic/d87954601e4b22972899e9957e800406a0a6b929/rs/rosetta-api/icrc1/ledger/ledger.did", + "wasm": "https://download.dfinity.systems/ic/d87954601e4b22972899e9957e800406a0a6b929/canisters/ic-icrc1-ledger.wasm.gz", + } + }, + "defaults": { + "build": { + "args": "", + "packtool": "" + } + }, + "output_env_file": ".env", + "version": 1 +} +``` + +Next, we'll use the `minter` identity we created in the last module, [4.1 Using the ICP ledger](4.1-icp-ledger.md). If you need to export the `minter` identity's principal again, run the commands: + +``` +dfx identity use minter +export MINTER_ACCOUNT_ID=$(dfx ledger account-id) +``` + +The environment variable `MINTER_ACCOUNT_ID` is the principal ID responsible for minting and burning tokens. + +Then, export the name and symbol of your token: + +``` +export TOKEN_NAME="Dev Journey Token" +export TOKEN_SYMBOL="DJTK" +``` + +The environment variable `TOKEN_SYMBOL` is the token's ticker symbol, and the `TOKEN_NAME` variable is the token's full name. + +Then, set the identity that you want to use to deploy the ledger. In the previous module [4.1 Using the ICP ledger](4.1-icp-ledger.md), we used the `DevJourney` identity, which we'll use again: + +``` +dfx identity use DevJourney +export DEPLOY_ID=$(dfx identity get-principal) +``` + +It is recommended to mint some tokens when the ledger is deployed so that you can interact with the ledger and send tokens to other identities. To do this, set an amount of `PRE_MINTED_TOKENS` and a `TRANSFER_FEE`: + +``` +export PRE_MINTED_TOKENS=10_000_000_000 +export TRANSFER_FEE=10_000 +``` + +The environment variable `PRE_MINTED_TOKENS` is the number of tokens minted during the ledger's initial deployment. These are held by the account that deploys the ledger canister. + +The environment variable `TRANSFER_FEE` is the fee that users will pay whenever they make a transfer using the ledger. + +Next, set the values for the ledger's archiving options. The values we're setting in this tutorial are the recommended values, but you can alter them to fit your project's needs: + +``` +dfx identity new archive_controller +dfx identity use archive_controller +export ARCHIVE_CONTROLLER=$(dfx identity get-principal) +export TRIGGER_THRESHOLD=2000 +export NUM_OF_BLOCK_TO_ARCHIVE=1000 +export CYCLE_FOR_ARCHIVE_CREATION=10000000000000 +``` + +In these commands, the following environment variables are set: + +- `ARCHIVE_CONTROLLER`: Principal of the archive canister's controller. + +- `TRIGGER_THRESHOLD`: The number of blocks to archive once the trigger threshold is exceeded. + +- `NUM_OF_BLOCK_TO_ARCHIVE`: The amount of blocks to be archived. + +- `CYCLE_FOR_ARCHIVE_CREATION`: The amount of cycles to be sent to the archive canister when it is deployed. + +Then, specify which standard(s) you want your ledger to support. For example, to support just the ICRC-1 standard, set the `FEATURE_FLAGS` to false: + +``` +export FEATURE_FLAGS=false +``` + +The `FEATURE_FLAGS` is used to enable or disable certain ICRC-1 standard extensions. If you want to support the ICRC-2 standard extension, then set this flag to true: + +``` +export FEATURE_FLAGS=true +``` + +Now, let's deploy the ICRC-1 ledger canister locally using the environment variables that we've set using the command: + +``` +dfx deploy icrc1_ledger_canister --specified-id mxzaz-hqaaa-aaaar-qaada-cai --argument "(variant {Init = +record { + token_symbol = \"${TOKEN_SYMBOL}\"; + token_name = \"${TOKEN_NAME}\"; + minting_account = record { owner = principal \"${MINTER}\" }; + transfer_fee = ${TRANSFER_FEE}; + metadata = vec {}; + feature_flags = opt record{icrc2 = ${FEATURE_FLAGS}}; + initial_balances = vec { record { record { owner = principal \"${DEPLOY_ID}\"; }; ${PRE_MINTED_TOKENS}; }; }; + archive_options = record { + num_blocks_to_archive = ${NUM_OF_BLOCK_TO_ARCHIVE}; + trigger_threshold = ${TRIGGER_THRESHOLD}; + controller_id = principal \"${ARCHIVE_CONTROLLER}\"; + cycles_for_archive_creation = opt ${CYCLE_FOR_ARCHIVE_CREATION}; + }; + } +})" +``` + +:::info +Specifying the canister ID as `mxzaz-hqaaa-aaaar-qaada-cai` is an optional step that is used in this tutorial for consistency. +::: + +### Deploying a ICRC-1 ledger on the mainnet + +To deploy an instance of the ICRC-1 ledger on the mainnet, there are several important things to note: + +- You will need to remove the argument `--specified-id mxzaz-hqaaa-aaaar-qaada-cai`, since you will receive a unique canister ID when the canister is deployed. + +- You will need to use the argument `--network ic` to specify deploying to the mainnet. + +- You can specify the amount of initially minted tokens by setting `initial_values = vec {}`. + +- Always set the `archive_options` field, otherwise the ledger's capacity is limited to the memory of a single canister. + +- Assure that the ledger canister has sufficient cycles, since it will require cycles to create new instances of the archive canister on demand. + +## Interacting with the ICRC-1 ledger + +Like the ICP ledger, the ICRC-1 ledger can be interacted with using the `dfx canister` command or the Candid UI. You can also use the `ic-cdk` for making inter-canister calls to the ICRC-1 ledger or the `ledger-icrc-js` library. In this tutorial, we'll cover using `dfx canister` and the Candid UI, and provide resources for the `ic-cdk` and `ledger-icrc-js` options. + +### Using the `dfx canister` command with ICRC-1 endpoints + +In this tutorial, we'll cover the endpoints for the ICRC-1 ledger canister and the endpoints for the ICRC-2 extension. For the ICRC-2 endpoints, you will need to have set `FEATURE_FLAGS=true` in the previous step before the canister was deployed. + +To confirm that your local canister supports the ICRC-2 extension, you can check the list of supported standards with the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_supported_standards '()' +``` + +This should return the following output: + +``` +( + vec { + record { + url = "https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1"; + name = "ICRC-1"; + }; + record { + url = "https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-2"; + name = "ICRC-2"; + }; + }, +) +``` + + +To get the token symbol of the ICRC-1 ledger, use the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_symbol '()' +``` + +This command returns: + +``` +("DJTK") +``` + +To return the token's decimals of the ICRC-1 ledger, use the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_decimals '()' +``` + +This command returns: + +``` +(8 : nat8) +``` + +To return the token's metadata of the ICRC-1 ledger, use the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_metadata '()' +``` + +This command returns: + +``` +( + vec { + record { "icrc1:decimals"; variant { Nat = 8 : nat } }; + record { "icrc1:name"; variant { Text = "Dev Journey Token" } }; + record { "icrc1:symbol"; variant { Text = "DJTK" } }; + record { "icrc1:fee"; variant { Nat = 10_000 : nat } }; + record { "icrc1:max_memo_length"; variant { Nat = 32 : nat } }; + }, +) +``` + +To return the total token supply of the ICRC-1 ledger, use the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_total_supply '()' +``` + +This command should return the amount of tokens that we minted using the `PRE_MINTED_TOKENS` variable: + +``` +(10_000_000_000 : nat) +``` + +To return the token's transfer fee of the ICRC-1 ledger, use the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_fee '()' +``` + +This command returns: + +``` +(10_000 : nat) +``` + +To return the minting account principal of the ICRC-1 ledger, use the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_minting_account '()' +``` + +This command returns: + +``` +( + opt record { + owner = principal "rrd6e-uoar3-ehz42-jxkun-ymmmv-jw4rn-re7se-5hymk-aoizl-bfb3j-uqe"; + subaccount = null; + }, +) +``` + +To fetch the balance of an account, in this tutorial the `DEPLOY_ID` account, use the command: + +``` +dfx canister call icrc1_ledger_canister icrc1_balance_of "(record {owner = principal \"${DEPLOY_ID}\"; })" +``` + +Since we haven't transferred any tokens, this command returns the amount that we minted in the `PRE_MINTED_TOKENS` variable: + +``` +(10_000_000_000 : nat) +``` + +To transfer tokens using the ICRC-1 ledger, use the following command: + +``` +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;})" +``` + +This command uses the `DEPLOY_ID` account principal to transfer 10_000 tokens. The output of this command will return: + +``` +(variant { Ok = 1 : nat }) +``` + +### Using ICRC-2 endpoints + + +The [ICRC-2 standard](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-2/README.md) enables the approve-transfer-from pattern that became popular in the Ethereum ecosystem with the ERC-20 token standard. It specifies a way for an account owner to delegate token transfers to a third party, usually a canister, on the owner's behalf. + +For example, to approve 100_000 tokens for the principal `sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe`, you can use the command: + +``` +dfx canister call icrc1_ledger_canister icrc2_approve "(record { amount = 100_000; spender = record{owner = principal \"sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe\";} })" +``` + +This command will return the block index of the transaction, such as: + +``` +(variant { Ok = 2 : nat }) +``` + +Then, to confirm that this command worked correctly, you check the principal's allowance by running the command: + +``` +dfx canister call icrc1_ledger_canister icrc2_allowance "(record { account = record{owner = principal \"${DEPLOY_ID}\";}; spender = record{owner = principal \"sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe\";} })" +``` + +This command should reflect the 100_000 tokens we approved previously: + +``` +(record { allowance = 100_000 : nat; expires_at = null }) +``` + +An expiration date can be sent for the approval, such as: + +``` +dfx canister call icrc1_ledger_canister icrc2_transfer_from "(record { amount = 90_000; from = record{owner = principal \"${DEPLOY_ID}\"}; to= record{owner = principal \"${DEPLOY_ID}\"}; })" +``` + +This command will return the block index of the transaction, such as: + +``` +(variant { Ok = 3 : nat }) +``` + +### Using the Candid UI + +To interact with the ICRC-1 ledger using the Candid UI, navigate to the URL provided when the canister was deployed. If you specified the canister ID when the canister was deployed, this URL will be: + +``` +http://127.0.0.1:4943/?canisterId=bnz7o-iuaaa-aaaaa-qaaaa-cai&id=mxzaz-hqaaa-aaaar-qaada-cai +``` + +This URL will display the following Candid UI: + +![Candid UI ICRC](../_attachments/CandidUI_icrc.png) + +## Resources + +- [ic-cdk Rust crate](/docs/current/developer-docs/integrations/icrc-1/interact-with-ICRC-1-ledger#icrc-ledger-types-rust-crate). + +- [ledger-icrc-js](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icrc). + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + +## Next steps + +Next, we'll dive into ckBTC: + +- [4.3 ckBTC and Bitcoin integration](4.3-ckbtc-and-bitcoin.md). \ No newline at end of file diff --git a/docs/tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin.md b/docs/tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin.md new file mode 100644 index 0000000000..61059de0e1 --- /dev/null +++ b/docs/tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin.md @@ -0,0 +1,357 @@ +# 4.3 ckBTC and Bitcoin integration + +## Overview + +One of the key features of the Internet Computer is known as **chain-key cryptography**. Chain-key cryptography is a feature that encompasses several cryptographic mechanisms that enable novel workflows and functionalities such as chain-key tokens. Chain-key tokens are not wrapped tokens; they are twin tokens that are backed 1:1 with the original token (BTC, ETC) that use chain-key cryptography to transfer and use the original tokens with less fees and higher transfer speeds than using the token's native blockchain network. + +Currently, the IC supports an integration with the Bitcoin network that includes the chain-key bitcoin (ckBTC) token, and has an Ethereum integration in development. + +:::info +In this tutorial and other pages of the IC developer documentation, note that we use the lowercase version of **bitcoin** to refer to the token BTC, and use the uppercase version **Bitcoin** to refer to the Bitcoin network itself. This capitalization distinction is in accordance with the Bitcoin style guide. +::: + +## Bitcoin integration architecture + +Through the IC's integration with the Bitcoin network, canisters deployed on the IC are able to receive, hold, and send bitcoin. Each of these functions utilize transactions on the Bitcoin network, and allow canisters to act as if they are users on the Bitcoin network. + +At the core of this integration is a novel protocol for chain-key signatures that is based on **threshold ECDSA**. [Threshold ECDSA](/docs/current/developer-docs/integrations/t-ecdsa/t-ecdsa-how-it-works) is a protocol suite that includes several features that include [key generation](https://csrc.nist.gov/glossary/term/key_generation), [periodic key re-sharing](https://www.youtube.com/watch?v=gKUi-2T7tdc), [computing pre-signatures](/docs/current/developer-docs/integrations/t-ecdsa/t-ecdsa-how-it-works/#:~:text=Computing%20pre%2Dsignatures%2C%20signing%3A,requests%20to%20precompute%20pre%20signatures), [XNet key re-sharing](/docs/current/developer-docs/integrations/t-ecdsa/t-ecdsa-how-it-works/#:~:text=XNet%20key%20re,source%20subnet%20uses), and public key retrieval. + +On a high level, subnets that have ECDSA enabled hold a threshold ECDSA master key, which is generated using the IC's key generation protocol. A master key can be used to generate canister ECDSA keys. It is important to know that an ECDSA private key only exists in a secret-shared form during it's lifetime, whether it is being generated, shared within a subnet, or shared from one subnet to another. + +We'll dive deeper into threshold ECDSA in a future tutorial. You can also take a deep dive in the [technology overview to learn more](/docs/current/developer-docs/integrations/t-ecdsa/t-ecdsa-how-it-works). + +On the protocol-level, the [Bitcoin integration](https://wiki.internetcomputer.org/wiki/Bitcoin_Integration) and chain-key ECDSA each expose an API on the IC management canister. Remember that the IC management canister isn't a canister but a facade that is used to enable functionality for management operations such as starting or stopping a canister. While the Bitcoin API is specific to the Bitcoin network, the chain-key ECDSA signature API can be used for other workflows, such as the integration with other blockchains like Ethereum. + +For a canister to make a Bitcoin transaction, a request must be sent to a Bitcoin-enabled subnet. On that subnet, a Bitcoin canister is implemented as a typical NNS-managed canister that is accessible through the management canister Bitcoin API. The Bitcoin canister holds the IC's on-chain Bitcoin state, which includes the UTXO set, the most recent Bitcoin blocks, and the current outgoing transactions being sent to the Bitcoin network. When a canister submits a transaction to the Bitcoin management canister API, the transaction is queued to be submitted to the Bitcoin network. To send transactions to the Bitcoin network, an adapter connects to the nodes of the Bitcoin network and functions similarly to a traditional Bitcoin node. In every subnet round, the Bitcoin adapter obtains the pending transactions and queues them for being submitted asynchronously. + +## What is ckBTC? + +The ckBTC token is an on-chain IC token that is backed 1:1 by bitcoin (BTC), where 1 BTC can be redeemed for 1 ckBTC, and vise versa. The unique chain-key cryptography used to create ckBTC makes it different from other tokens that are pegged to the price of BTC, such that other tokens typically rely on a third-party bridge to convert BTC to the pegged token. ckBTC does not use a third-party bridge, making it more secure than other pegged, or 'wrapped', tokens. + +In comparison to traditional BTC, ckBTC has much faster transfers at a much cheaper rate. A ckBTC transfer is finalized within seconds and costs 0.0000001 ckBTC, which is approximately two orders of magnitude lower than the traditional Bitcoin miner fees. + +The functionality of ckBTC is provided through the combination of two canisters: + +- The ckBTC minter: The minter is responsible for minting and burning ckBTC. New ckBTC tokens are minted whenever the ckBTC minter receives bitcoin and burns ckBTC tokens whenever an owner of ckBTC tokens requests a withdrawal of bitcoin. + +- The ckBTC ledger: The ledger is responsible for transferring ckBTC between accounts and keeping a record of account balances. + +## Bitcoin use-cases on the IC + +The IC's Bitcoin integration enables use-cases such as: + +- ckBTC: An ICRC-2 compliant 'twin token' using chain-key cryptography that is backed 1:1 by bitcoins. + +- Decentralization swaps: ckBTC can be used to buy tokens in an SNS decentralization swap. + +- Bitcoin smart contracts: Canisters can hold bitcoin directly on the Bitcoin network, allowing powerful smart contracts to offer Bitcoin functionality. For example, on-chain Bitcoin wallets that use biometric authentication would allow users to complete Bitcoin transactions within the application without managing a Bitcoin private key. + +- Trading bitcoin: ckBTC can be traded directly on decentralized exchanges for bitcoin without third-party custody of the assets. + +## Deploying a Bitcoin dapp + +In this tutorial, we'll be deploying an example application using a local instance of the Bitcoin network and then simulate Bitcoin transactions using it. This example showcases the IC's Bitcoin integration, however it does not use ckBTC. + +:::info +Developing with ckBTC uses a different workflow, which will be showcased in a future variation of the developer journey series focused entirely on ckBTC. +::: + +For this tutorial, we'll take a look at developing and testing a Bitcoin dapp using `dfx`, which supports both the Bitcoin API and the ECDSA API. + +### Prerequisites + +Before you start, verify that you have set up your developer environment according to the instructions in [0.3 Developer environment setup](../level-0/03-dev-env.md). + +### Setting up a local Bitcoin network + +To develop a Bitcoin dapp locally, first a local Bitcoin network instance must be running. A local Bitcoin network allows developers to mine blocks quickly, which facilitates testing without having to rely on the slow Bitcoin testnet or the Bitcoin mainnet. + +To get started, first download the [Bitcoin core](https://bitcoin.org/en/download). It is recommended to use the `.tar.gz` version for Mac users. + +:::info +At the time of this guide, the latest version is Bitcoin `25.0`. If you are downloading another version, be sure to change the version number in the following commands. +::: + +Then, unpack the `.tar.gz` file with the command: + +``` +tar -xfz bitcoin-25.0-x86_64-apple-darwin.tar.gz +``` + +Navigate into the newly unpacked directory and create a new empty directory called `data`: + +``` +cd bitcoin-25.0 +mkdir data +``` + +Then, while still in the root directory of `bitcoin-25.0`, open the `bitcoin.conf` file and insert the following content at the beginning of the file: + +``` +# Enable regtest mode. This is required to setup a private bitcoin network. +regtest=1 + +# Dummy credentials that are required by `bitcoin-cli`. +rpcuser=ic-btc-integration +rpcpassword=QPQiNaph19FqUsCrBRN0FII7lyM26B51fAMeBQzCb-E= +rpcauth=ic-btc-integration:cdf2741387f3a12438f69092f0fdad8e$62081498c98bee09a0dce2b30671123fa561932992ce377585e8e08bb0c11dfa +``` + +This snippet of configuration enables `regtest` mode, which is required for a local, private Bitcoin network instance. 'Regtest' is short for "regression testing mode." Then, it sets some test credentials that will be used by the Bitcoin network for authentication. + +Then, start the local Bitcoin instance with the command: + +``` +./bin/bitcoind -conf=$(pwd)/bitcoin.conf -datadir=$(pwd)/data --port=18444 +``` + +:::caution +The above command uses port `18444`, assuming it is available on your machine. If this port isn't available, specify a different port in the `--port` argument. +::: + +Once running, the Bitcoin instance will take a moment to spin up and synchronize block headers. Once synchronized, it is ready to use. The output will take up the entirety of the terminal window. + +### Cloning the `basic_bitcoin` example + +Now that our local instance of the Bitcoin network is up and running, it's time to start developing a Bitcoin dapp locally. + +To get started, open a new terminal window, navigate into your working directory (`developer_journey`), then use the following commands to clone the DFINITY examples repo and navigate into the `basic_bitcoin` directory: + +``` +git clone https://github.com/dfinity/examples/ +cd examples/motoko/basic_bitcoin +``` + +:::info +A Rust version of this project exists at `examples/rust/basic_bitcoin`. +::: + +Then, start the local replica with the command: + +``` +dfx start --clean --background +``` + +Once the local replica has been started, it should return output that indicates it has connected to the local Bitcoin node: + +``` +Oct 17 21:09:20.046 INFO s:/n:/ic_btc_adapter/ic_btc_adapter Starting the adapter with config: { + "network": "regtest", + "dns_seeds": [], + "nodes": [ + "127.0.0.1:18444" + ], + "socks_proxy": null, + "idle_seconds": 3600, + "ipv6_only": false, + "logger": { + "node_id": 100, + "dc_id": 200, + "level": "info", + "format": "text_full", + "debug_overrides": [], + "sampling_rates": {}, + "enabled_tags": [], + "target": "Stdout", + "block_on_overflow": true + }, + "incoming_source": { + "Path": "/var/folders/_k/vfkshzzs0yb6w81nh24q5ccm0000gn/T/ic-btc-adapter-socket.1416.1697576959" + } +} +Creating canister: g4xu7-jiaaa-aaaan-aaaaq-cai (bitcoin integration) +Installing canister: bitcoin integration +2023-10-17 21:09:27.650935 UTC: [Canister g4xu7-jiaaa-aaaan-aaaaq-cai] Sending request: Initial(GetSuccessorsRequestInitial { network: Regtest, anchor: BlockHash([6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15]), processed_block_hashes: [] }) +Initialized replica. +Dashboard: http://localhost:49497/_/dashboard +``` + +::caution +If you receive the error message "Failed to connect to 127.0.0.1:18444 ::: Connecting to the stream timed out." this indicates that `dfx` isn't able to connect to your local Bitcoin instance. This error may occur if you used a port other than `18444` but did not edit the `dfx.json` file to reflect your custom port. +::: + +The output will take up the terminal window, so open another terminal window and navigate back into the `examples/motoko/basic_bitcoin` directory. + +This project uses [submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules), which must be initialized using the command: + +``` +git submodule update --init --recursive +``` + +Then, install the `llvm`, `binaryen`, and `cmake` packages. If you're running on Mac, you can use [Homebrew](https://brew.sh/) to install them: + +``` +brew install llvm binaryen cmake +``` + +### Deploying the example canister + +Now we can deploy our Bitcoin canister! To deploy the canister locally, run the command: + +``` +dfx deploy basic_bitcoin --argument '(variant { regtest })' +``` + +You will receive output that resembles the following: + +``` +Installing canisters... +Creating UI canister on the local network. +The UI canister on the "local" network is "bd3sg-teaaa-aaaaa-qaaba-cai" +Installing code for canister basic_bitcoin, with canister ID bkyz2-fmaaa-aaaaa-qaaaq-cai +Deployed canisters. +URLs: + Backend canister via Candid interface: + basic_bitcoin: http://127.0.0.1:4943/?canisterId=bd3sg-teaaa-aaaaa-qaaba-cai&id=bkyz2-fmaaa-aaaaa-qaaaq-cai +``` + +Our local Bitcoin dapp is ready to use! Let's take a look at how we can interact with it. + +### Generating a Bitcoin address + +To receive Bitcoin, you will need a Bitcoin address. There are different types of Bitcoin addresses, such as a `P2PKH` address or a `P2SH` address. Most Bitcoin addresses can be generated using an ECDSA public key. In this Bitcoin example canister, the code contains an example that generates a `P2PKH` address using the `ecdsa_public_key` API. + +To generate a `P2PKH` address, make the following call to the canister's method `get_p2pkh_address`: + +``` +dfx canister call basic_bitcoin get_p2pkh_address +``` + +This command will return the generated `P2PKH` address: + +``` +("mmucK4F2UhnjGU9V9rhKjTsjyrUzMCyKnt") +``` + +Your output will be different, since each ECDSA public key is unique. + +Alternatively, you can use the Candid UI. To use this method, open the Candid UI URL that was returned in the previous step when we deployed the `basic_bitcoin` canister. + +In the Candid UI, find the `get_p2pkh_address` method, then select the `Call` button under it. + +![Generating a Bitcoin address](../_attachments/Candid_BTC.png) + +The `P2PKH` address will be returned in the UI: + +![Generating a Bitcoin address result](../_attachments/Candid_BTC2.png) + +### Receiving BTC + +To receive BTC on your local network, you need to mine blocks, since BTC are minted as a reward for mining a block. On the Bitcoin testnet and mainnet, we cannot control when blocks are mined. On our local Bitcoin network, however, we can manually mine blocks using the following command within the `bitcoind` directory: + +``` +./bin/bitcoin-cli -conf=$(pwd)/bitcoin.conf generatetoaddress
+``` + +For example, to mine a block and have the canister receive the BTC reward, use the command: + +``` +./bin/bitcoin-cli -conf=$(pwd)/bitcoin.conf generatetoaddress 1 BTC_ADDRESS +``` + +Replace `BTC_ADDRESS` with the generated `P2PKH` address we got in the last step. + +If successful, you'll receive the hash of the block that was just mined, which resembles the following: + +``` +[ + "639b8cceef7f6da5a6cc56e6e6a4f7b11dc42416e94773a858ee5d004acb59c1" +] +``` + +In the terminal window that is showing the output of `dfx start --clean --background`, you will see a log that resembles: + +``` +Oct 17 21:57:40.893 INFO s:/n:/ic_btc_adapter/blockchainmanager Added headers: Height = 2, Active chain's tip = 7f592c802fd9bd33fe84b6c4016e46047e6b0b903a24a61e3e4446f0fd3d735d +``` + +This indicates that your canister has ingested the block as expected. The first block may take up to 30 seconds to sync, but subsequent blocks sync much faster. + +### Checking your BTC balance + +To check the balance of your Bitcoin address to confirm that it received the BTC, run the following command: + +``` +dfx canister call basic_bitcoin get_balance '("BTC_ADDRESS")' +``` + +Replace `BTC_ADDRESS` with your generated `P2PKH` address. Our balance should be `5_000_000_00`, which is equal to 50 BTC. + +``` +(5_000_000_000 : nat64) +``` + +:::caution +Remember that this is a local deployment. The BTC we mine here is only valid on our local Bitcoin network for testing purposes, and cannot be spent or used anywhere else. +::: + +### Sending BTC + +Previously, we mined a single block and received a reward of 50 BTC for that block. One prerequisite to sending this BTC to someone else, however, is that first, 100 additional blocks must be mined. This is known as the Coinbase maturity rule. + +To mine 100 additional blocks, run the command: + +``` +./bin/bitcoin-cli -conf=$(pwd)/bitcoin.conf generatetoaddress 100 BTC_ADDRESS +``` + +Replace `BTC_ADDRESS` with your generated `P2PKH` address. + +You should receive output and `dfx` log entries similar to the ones we got for mining a single block. + +Now we can send BTC using the canister's `send` endpoint. In this example, we'll send 1 BTC to the address `n2dcQfuwFw7M2UYzLfM6P7DwewsQaygb8S`. You can replace this address with any test address you would like. + +``` +dfx canister call basic_bitcoin send '(record { destination_address = "n2dcQfuwFw7M2UYzLfM6P7DwewsQaygb8S"; amount_in_satoshi = 100000000; })' +``` + +:::info +Note that this command sends BTC in 'satoshi'. 1 BTC is equivalent to 100_000_000 satoshi. +::: + +This command will create a transaction and send it to the local Bitcoin instance running. After running this command, you now need to mine a block so that the transaction we just sent becomes a part of the blockchain. Without mining a block, the transaction is not recorded on-chain. + +In the `bitcoind` directory, run the following command to mine another block: + +``` +./bin/bitcoin-cli -conf=$(pwd)/bitcoin.conf generatetoaddress 1 mtbZzVBwLnDmhH4pE9QynWAgh6H3aC1E6M +``` + +Now, we can check that the address `n2dcQfuwFw7M2UYzLfM6P7DwewsQaygb8S` has a balance of 1 BTC: + +``` +dfx canister call basic_bitcoin get_balance '("n2dcQfuwFw7M2UYzLfM6P7DwewsQaygb8S")' +``` + +## Resources + +- [ckBTC wiki page](https://wiki.internetcomputer.org/wiki/Chain-key_Bitcoin). +- [ckBTC developer documentation page](/docs/current/developer-docs/integrations/bitcoin/ckbtc). +- [Bitcoin integration GitHub repository](https://github.com/dfinity/ic/tree/master/rs/bitcoin/ckbtc/minter). + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + +## Next steps + +Next, we'll explore the IC's governance and token staking: + +- [4.4 NNS governance and staking](4.4-nns-governance.md). + diff --git a/docs/tutorials/developer-journey/level-4/4.4-nns-governance.md b/docs/tutorials/developer-journey/level-4/4.4-nns-governance.md new file mode 100644 index 0000000000..a6a8409bba --- /dev/null +++ b/docs/tutorials/developer-journey/level-4/4.4-nns-governance.md @@ -0,0 +1,218 @@ +# 4.4 NNS governance and staking + +## Overview + +When blockchain networks need to be upgraded, traditionally they use a method known as a 'hard fork', which involves substantial work and manual coordination. In comparison, the Internet Computer upgrades itself weekly, which can be seen on the [ICP dashboard](https://dashboard.internetcomputer.org/releases). + +Each upgrade made to the IC is first introduced as an NNS proposal. Then, users who stake ICP governance tokens can vote on this proposal. If the proposal is accepted, the upgrade gets executed automatically. + +In this tutorial, we'll explore how to use the NNS dapp and how to stake ICP tokens into a neuron to receive NNS voting power. + +## What is the NNS? + +The Network Nervous System (NNS) is the governing body of the Internet Computer. It is a decentralized autonomous organization that is hosted fully on-chain and is responsible for making protocol-level upgrades to the IC. The goal of the NNS is to allow the IC to be governed in a secure, open, and decentralized way. Therefore, it has complete control over the network. Some examples of upgrades made to the IC through the NNS are: + +- Upgrade the protocol and software used by the network's node machines. + +- Create new subnets. + +- Split and divide subnets. + +- Configure economic parameters that control how much users pay for resources. + +When an NNS proposal is submitted, the network participants vote on whether to adopt the proposed changes or reject them. Voting is done via a liquid democracy, where ICP holders can stake ICP within a voting neuron in return for the ability to vote on proposals that change the IC. + +### Neurons + +Neurons are entities that hold ICP tokens in return for benefits such as voting power or voting rewards on the NNS. ICP tokens that are staked within a neuron cannot be immediately withdrawn; neurons require a notice be given before ICP can be taken out of the neuron. The length of time before ICP can be withdrawn from a neuron is known as the neuron's "dissolve delay". + +The dissolve delay determines how long the neuron will take to dissolve if the neuron is placed into "dissolve mode". Once dissolved, the neuron owner can unlock the staked balance of ICP. This configuration provides neuron owners with an incentive to vote with a long-term view focused on maximizing their ICP's value at a later date. Neuron owners can configure higher dissolve delays up to a maximum of eight years, but cannot decrease it below the natural passage of time. + +The neuron's voting power is proportional to the quantity of ICP staked within the neuron, the length of their dissolve delay, and the amount of time since the neuron was created. Neurons can be configured to vote automatically or manually. To vote automatically, the neuron can be configured to follow the voting decision of a group of neurons, where it decides to approve a proposal if more than half of the followed group approves, and rejects the proposal if more than half of the followed group rejects. Voting automatically can be useful for neuron owners who may not have the necessary time to evaluate each proposal, or who do not fully understand a proposal's details. + +Anyone holding ICP can create a neuron, and are encouraged to do so through reward incentives such as newly minted ICP tokens. Reward amounts are determined by the amount of ICP locked in the neuron, the neuron's dissolve delay time, the neuron's age, and the proportion of possible votes that it participated in to the sum of total voting activity across all neurons. Rewards are distributed this way because the total reward pool is a capped value that is divided between all NNS voters. + +Neurons can also be used to submit new proposals to the NNS. To prevent neurons from spamming proposals, a fee is charged to the neuron if their submitted proposal is rejected. + +To learn more about neurons and their attributes, check out the documentation [here](/docs/current/tokenomics/nns/nns-intro#neurons). + +### Proposals + +If a proposal has a majority approval, it will be accepted and autonomously executed. Proposals each adhere to a specific proposal type, which defines what information the proposal includes. For each proposal type, the NNS maintains a corresponding system function which is executed using the proposal's content to fill the function's parameters whenever a proposal of that type is approved and adopted. Each proposal type is belongs to a proposal topic, such as "#NetworkEconomics" or "#NodeAdmin". + +Each NNS proposal contains the following fields: + +- Summary: A field of text that describes the proposal. + +- URL: The web address of any additional content that is required to evaluate the proposal. + +- Proposer: The ID of the neuron that submitted the proposal. + +- Proposal type: The type of proposal and what topic it belongs to. + +- Parameters: Any parameters that will be passed to the system function that is executed if the proposal is approved. + +- Unique identity: A unique identity value the NNS assigns to each proposal it receives. + +For detailed information about different proposal types and topics, see the documentation [here](/docs/current/tokenomics/nns/nns-intro#topics). + +## Why is the NNS important to developers? + +For developers who are focused on building their own dapps and projects, you may be asking, "Why does the NNS matter to me?" + +There are several reasons that all users and developers on the IC should be familiar with and take part in the governance of the network through the NNS, but for developers specifically, these reasons include: + +- Voting on features and changes that may effect your project's architecture, workflow, or functionality: Developers who stake ICP in a neuron and receive voting rights can have a direct say in whether they agree or disagree with a proposed change or feature, and can vote on the proposal accordingly. + +- Having the ability to submit proposals that introduce changes necessary for your project: Neuron owners have the ability to submit proposals for changes or features that they'd like to introduce to enhance their workflows or enable new functionality. + +- Receiving ICP rewards that can be converted into cycles, which are necessary for mainnet canister deployments: Neurons that regularly vote on proposals receive rewards in the form of ICP tokens, which can be converted into cycles and then used to pay for a project's resources on the mainnet. + +- Gaining a comprehensive understanding of the NNS and SNSs, allowing you to envision creating an SNS for your project: By interacting with the NNS and the SNSs for different applications on the IC, developers can be inspired to turn their application into an SNS as well. + + +## Using the NNS dapp + +To use the NNS dapp, first navigate to the dapp's URL at https://nns.ic0.app/. + +You will be prompted to log in with your Internet Identity. If you need to create one, check out the previous module [3.5 Identities and authentication](../level-3/3.5-identities-and-auth.md). + +![NNS login](../_attachments/nns0.png) + +### Transferring ICP tokens into your Internet Identity 'Main' account + +Once logged in, you can see your balance for each token on the NNS dapp. Tokens include ICP, ckBTC, and dapp-specific tokens for dapps that have an SNS, such as OpenChat (CHAT) and Hot or Not (HOT). For this tutorial, we'll be staking ICP in an IC neuron, so assure that you have some ICP tokens available. + +If you need to obtain ICP tokens, they can be purchased through a crypto exchange, or they can be received through other activities such as receiving grants from the DFINITY foundation. They will need to be sent to the ICP wallet address shown in the NNS dapp. The following screenshot shows this address beneath the current balance under the 'Main' account with the balance of `5.10 ICP`: + +![NNS dapp 1](../_attachments/nns1.png) + +Alternatively, you can send ICP tokens to this Internet Identity address from your local `dfx` developer identity if that is where you have ICP tokens. You can do so with the `dfx ledger` commands. First, get your developer identity principal with the command: + +``` +dfx identity get-principal +``` + +This command will return your identity's principal: + +``` +tsqwz-udeik-5migd-ehrev-pvoqv-szx2g-akh5s-fkyqc-zy6q7-snav6-uqe +``` + +Then, check the balance of your identity's ledger account to assure that it is the correct account: + +``` +dfx ledger --network ic balance +``` + +The flag `--network ic` is required, since we are intending to use real ICP on the mainnet. + +If the balance is correct, then you can transfer ICP tokens to your Internet Identity 'Main' address with the command: + +``` +dfx ledger --network ic transfer --icp --memo +``` + +For example, for the 'Main' account in this example, we could transfer 1 ICP to the account with the command: + +``` +dfx ledger --network ic transfer 365cf45f3521653e866a078b157a8d8701c3f63183a6d41ff8ddb913c4a978d3 --icp 1 --memo Developer Journey +``` + +### Staking ICP in a neuron + +To stake your ICP tokens in a neuron, select 'My Neuron Staking' on the left navigation bar. Then select 'Stake Neurons' in the bottom of the window. + +![NNS dapp 2](../_attachments/nns2.png) + +To stake ICP in a neuron, enter how many you'd like to stake and select the source wallet. + +![NNS dapp 3](../_attachments/nns3.png) + +Then, you'll need to set the dissolve delay. + +![NNS dapp 4](../_attachments/nns4.png) + +To receive voting power, you'll need to set this value to at least 6 months. Click on the 'Min' button to set the minimum value. + +![NNS dapp 5](../_attachments/nns5.png) + +To set the maximum value, select the 'Max' button. The maximum dissolve delay is 8 years. + +![NNS dapp 6](../_attachments/nns6.png) + +Then confirm the setting to create your neuron. + +![NNS dapp 7](../_attachments/nns7.png) + +Once your neuron has been created, you can follow other neurons. As we discussed earlier, setting up following will automate your neuron's participation in voting on proposals, allowing you to maximize your neuron rewards. To follow a specific topic, select the drop-down menu next to the group you'd like to follow. In this example, we'll select "All except Governance, and SNS & Neurons' Fund". + +![NNS dapp 8](../_attachments/nns8.png) + +Then, you can select a specific group of neurons to follow by selecting 'Add Followee'. + +![NNS dapp 9](../_attachments/nns9.png) + +A list of available neurons will be displayed. In this example, we'll follow the 'DFINITY Foundation' neuron. + +![NNS dapp 10](../_attachments/nns10.png) + +Then confirm that your following settings have been updated. + +![NNS dapp 11](../_attachments/nns11.png) + +Close this window. Now, let's take a look at the details of our neuron. From the 'My Neuron Staking' page, you will see your neuron, its staked balance, its neuron ID, and its dissolve delay time. Select on the neuron to see additional details. + +![NNS dapp 12](../_attachments/nns12.png) + +From the neuron's detailed menu, you can execute actions such as increase the staked amount of ICP, increase the dissolve delay, or start dissolving the neuron. You will also see information regarding the neuron's maturity, which will increase over time and by voting on proposals. + +![NNS dapp 13](../_attachments/nns13.png) + +If you scroll further, you can see advanced details and settings, such as when the neuron was created, its neuron account ID, and options to participate in the neurons' fund or split the neuron. For more information about these advanced options, check out the documentation [here](/docs/current/tokenomics/token-holders/nns-app-quickstart). + +![NNS dapp 14](../_attachments/nns14.png) + +Lastly, at the very bottom of the window there will be information about the neurons that are being followed, any hotkeys that are set, and the neuron's voting history. + +![NNS dapp 15](../_attachments/nns15.png) + +### Interacting with NNS proposals + +Earlier, we set up following for our neuron, meaning that the neuron will automatically vote on proposals that fall into the category we configured. To interact with proposals manually, select 'Vote on Proposals' on the left navigation bar, then select 'Internet Computer'. All of the currently available proposals will be displayed. + +![NNS dapp 16](../_attachments/nns16.png) + +If you click on one, however, you'll notice that you cannot vote on it. That's because the proposals were created prior to the neuron that we just created, so we aren't eligible to vote on the currently open proposals. All future proposals will be available to us. + +![NNS dapp 17](../_attachments/nns17.png) + +For additional information the NNS dapp, proposals, and neuron staking, check out the [NNS quick start guide](/docs/current/tokenomics/token-holders/nns-app-quickstart). + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + +## Next steps + +Next, we'll dive into how to use the tool quill: + +- [4.5 Using quill](4.5-using-quill.md). + + diff --git a/docs/tutorials/developer-journey/level-4/4.5-using-quill.md b/docs/tutorials/developer-journey/level-4/4.5-using-quill.md new file mode 100644 index 0000000000..09dfdc811a --- /dev/null +++ b/docs/tutorials/developer-journey/level-4/4.5-using-quill.md @@ -0,0 +1,429 @@ +# 4.5 Using quill + +## Overview + +Now that we've covered both the ICP ledger and the NNS, it's time to take a look at a CLI tool that can be used to interact with both. Quill is a ledger and governance toolkit that provides support for self-custody of ICP or ckBTC tokens and functionality to interact with the NNS, SNSs, and ICP ledger from a **cold wallet**. + +To hold tokens or digital assets, there are three types of wallet options you can use: + +- Centralized wallet services: A wallet service owned and operated by a centralized third-party, such as a centralized exchange. On a centralized wallet service, the user is not in control of the wallet's private key. + +- Hot wallets: Any wallet that uses an application on a device connected to the internet. With hot wallets, users are in full control of their wallet's private key. + +- Cold wallets: A wallet that uses an offline device that is not connected to the internet. Like hot wallets, cold wallets also provide users with full control of the wallet's private key. + +Each of these options has their benefits, but there is an equal tradeoff between convenience and security. For example, while cold wallets are quite secure since they do not have access to the internet and are safe from malicious cyber attacks, it is not convenient to use since there must be additional steps taken to move the assets to a hot wallet or centralized wallet in order to spend and trade the assets. The opposite is true for hot wallets; while they are convenient to use, they are susceptible to attacks. + +You can read more about different types of self-custody wallet options in the documentation [here](/docs/current/tokenomics/token-holders/custody-options-intro). + +In this tutorial, we'll take a look at how to use quill for workflows like interacting with the ICP ledger, sending or receiving ckBTC, and interacting with the NNS and neurons. + +## What is quill? + +Quill is a CLI tool used for interacting with the IC's governance and ledger canisters. A unique feature of quill is the ability to create signed messages on an offline computer, or a 'cold wallet'. Once these messages are created, they must be transferred to an online computer, however, in order for them to take effect on the mainnet. Since the Internet Computer uses cryptographically verifiable messages, messages can be created on an offline computer then transmitted to the IC on a computer connected to the internet, since the IC will accept the message no matter how it was created. + +To support cold wallets, quill uses two steps to send query and update calls to the IC. First, quill is used with different subcommands to generate and sign messages based on the subcommand's inputted parameters and arguments. This step does not require connection to the internet. Then, in the second step the signed messages are sent to the IC, which does require an internet connection. To connect to the internet, users will need to transport the signed messages from the cold wallet computer to another computer using a USB stick or a QR code. + +While it is important to know that quill supports cold wallet workflows, quill can also be used on a computer connected to the internet without using any cold wallet workflows. + +:::info + +Transactions that use query requests, such as obtaining an account's balance or returning proposal information, require an internet connection and cannot be run on cold wallets. This is because submitting these query calls locally would not be beneficial, since the mainnet canisters being queried are not running on the local replica. Additionally, query calls do not require the same cryptographic validity that update calls do, therefore they do not need a signature to be generated and can be submitted directly to the mainnet. + +In this tutorial, we'll see that query calls do not generate output and can be submitted directly to the mainnet, while update calls will generate a JSON response that must be saved and submitted using `quill send`. + +::: + +## Downloading and installing quill + +:::info +To install quill on a cold wallet, you can either follow the steps below then disconnect the computer from the internet, or you can download the release file and transport it to the offline machine using a device such as a USB flash drive. + +In this tutorial, we'll be using quill on a machine with an internet connection, but we'll include notes with information for cold wallet workflows. +::: + +First, start by downloading the latest quill release from GitHub [here](https://github.com/dfinity/quill/releases). + +This tutorial will showcase the MacOS steps; please see the instructions here for [Linux](https://github.com/dfinity/quill#linux) and [Windows](https://github.com/dfinity/quill#windows). + +Then, move the file to the `/usr/local/bin` directory to use it in the CLI: + +``` +mv quill-macos-x86_64 /usr/local/bin/quill +``` + +Next, give the file executable permissions: + +``` +chmod +x /usr/local/bin/quill +``` + +Check that quill is now available for use by running the command: + +``` +quill -h +``` + +## Using quill's basic commands + +First, we need an account to use with quill. We can create a new account, or we can use an existing ledger account. To create a new account, generate the account's private key by running the command: + +``` +quill generate +``` + +This command will return the principal and account IDs for our newly generated private key: + +``` +Principal id: hzpq4-g6feu-vbvwx-oeo5c-fjiz4-de4bq-7q4y2-rldok-whjrq-mnayv-mqe +Legacy account id: 438f6fdc8e33539bbf73625c141cfbfa4b41fd943595f8e1ccd0b8c9e9758772 +``` + +Alternatively, we can use a private key file for our existing ledger account with an ICP balance. To use an existing ledger account, you will need the account's `.pem` file. To get this `.pem` file, we can use the `dfx identity export` command. First, assure that you're using the `dfx` identity you intend to be: + +``` +dfx identity whoami +``` + +Then, export the identity's `.pem` file with the command: + +``` +dfx identity export default > identity.pem +``` + +:::info +In this command, the `>` character indicates that we want to save the output of `dfx identity export default` to a file called `identity.pem`. +::: + +Then, we can pass this `.pem` file into our quill commands with the flag `--pem-file identity.pem`. + +Next, let's use quill to get our account's balance. Use the following command: + +``` +quill --pem-file identity.pem account-balance PRINCIPAL_ID +``` + +Replace `PRINCIPAL_ID` with the principal value returned from the command `dfx identity get-principal` for the identity that you generated the `.pem` file for. + +Running commands with quill will generate the transaction, then ask if we'd like to send the message or not, such as: + +``` +Sending message with + + Call type: update + Sender: 2vxsx-fae + Canister id: ryjl3-tyaaa-aaaaa-aaaba-cai + Method name: icrc1_balance_of + Arguments: ( + record { + owner = principal "hzpq4-g6feu-vbvwx-oeo5c-fjiz4-de4bq-7q4y2-rldok-whjrq-mnayv-mqe"; + subaccount = null; + }, +) + +Do you want to send this message? [y/N] +``` + +This subcommand, `account-balance`, cannot be run on offline machines, so selecting 'N' will cancel the request. Selecting 'Y' will query the mainnet for the result, which will be returned such as: + +``` +Request ID: 0x7c8e03ccaa28ad463cd568cc52b14d5c7739fa81039d4548e34818e333d5e752 +The request is being processed... +The request is being processed... +The request is being processed... +(100_000_000 : nat) +``` + +Now, if we want to transfer ICP to another account, we can use the command: + +``` +quill --pem-file identity.pem transfer --amount AMOUNT ACCOUNT_ID +``` + +:::caution +To use the quill transfer command, we need to have a balance of ICP. ICP can be bought through a crypto exchange, or ICP can be received through community activities such as participating in the NNS governance and receiving developer grants. +::: + +Replace `AMOUNT` with the numerical number of how many ICP tokens to transfer and replace `ACCOUNT_ID` with the account ID that should receive the ICP. For example: + +``` +quill --pem-file identity.pem transfer --amount 0.5 365cf45f3521653e866a078b157a8d8701c3f63183a6d41ff8ddb913c4a978d3 +``` + +This command will output the transaction's JSON content. This content can be saved to a file then submitted as a transaction such as: + +``` +quill --pem-file identity.pem transfer --amount 0.5 365cf45f3521653e866a078b157a8d8701c3f63183a6d41ff8ddb913c4a978d3 > transfer_transaction.json +quill --pem-file identity.pem send transfer_transaction.json +``` + +Then we'll be prompted to confirm sending this transaction to the mainnet. On a cold wallet, the `transaction1.json` file can be transferred to an online machine to be sent with the `quill --pem-file identity.pem send transfer_transaction.json` command. + +## Using quill with ckBTC + +Quill can be used to create transactions for interacting with ckBTC. To get started, check the ckBTC balance of your ledger account with the command: + +``` +quill ckbtc balance --of PRINCIPAL_ID +``` + +Replace `PRINCIPAL_ID` with the principal ID for the identity you want to use. + +Like the `account-balance` command, the `quill ckbtc balance` command cannot be run on offline machines, so selecting 'N' will cancel the request. Selecting 'Y' will query the mainnet for the result, which will be returned such as: + +``` +Request ID: 0xbdeef0e77df3c032b9c63d5c0e08aa766bfb33d81ab2b5f783ce0c7eafdccb58 +The request is being processed... +The request is being processed... +(0 : nat) +``` + +Then, to retrieve BTC in exchange for ckBTC use the command: + +``` +quill ckbtc retrieve-btc WITHDRAW_ADDRESS --satoshis AMOUNT > retrieve_transaction.json +``` + +Replace `PRINCIPAL_ID` with your principal ID, and replace `AMOUNT` with the number of Satoshis to retrieve. + +Then, to submit this transaction, run the command: + +``` +quill send retrieve_transaction.json +``` + +The output confirming the transaction will resemble the following: + +``` +Sending message with + + Call type: update + Sender: 2vxsx-fae + Canister id: mxzaz-hqaaa-aaaar-qaada-cai + Method name: icrc1_transfer + Arguments: ( + record { + to = record { + owner = principal "mqygn-kiaaa-aaaar-qaadq-cai"; + subaccount = opt blob "\0e\b6\de\93\b1y\ae\83+\b3\22\e8\e3\d6\84f0\04E\cb=\e5\b8\afy\bb\8dL\bc\ea\96\d0"; + }; + fee = null; + memo = null; + from_subaccount = null; + created_at_time = opt (1_697_834_874_304_780_000 : nat64); + amount = 1_000 : nat; + }, +) + +Do you want to send this message? [y/N] +``` + +With quill, you can also transfer ckBTC to another address with the command: + +``` +quill ckbtc transfer PRINCIPAL_ID --satoshis AMOUNT > ckBTC_transfer_transaction.json +``` + +Then, to submit this transaction, run the command: + +``` +quill send ckBTC_transfer_transaction.json +``` + +The output confirming the transaction will resemble the following: + +``` +Sending message with + + Call type: update + Sender: 2vxsx-fae + Canister id: mxzaz-hqaaa-aaaar-qaada-cai + Method name: icrc1_transfer + Arguments: ( + record { + to = record { + owner = principal "hzpq4-g6feu-vbvwx-oeo5c-fjiz4-de4bq-7q4y2-rldok-whjrq-mnayv-mqe"; + subaccount = null; + }; + fee = null; + memo = null; + from_subaccount = null; + created_at_time = opt (1_697_835_095_032_290_000 : nat64); + amount = 1_000 : nat; + }, +) + +Do you want to send this message? [y/N] +``` + +## Using quill with the NNS + +Quill can be used with both the NNS and any SNS that has been launched on the IC. + +In the previous module, [4.4 NNS governance and staking](4.4-nns-governance.md), we took a look at how to interact with the NNS and neurons through the NNS dapp. Now, let's look at how to use quill instead to perform the same functions. + +First, let's get some information about a neuron. You'll need a neuron's ID, which you can find on the NNS dapp, as we took a look at in the last module: + +![Neuron ID](../_attachments/nns14.png) + +Then, we can use the command: + +``` +quill get-neuron-info NEURON_ID +``` + +Replace `NEURON_ID` with the ID of a neuron. Since this command is a query command, it cannot be run on offline machines, so selecting 'N' will cancel the request. Selecting 'Y' will query the mainnet for the result, which will be returned such as: + +``` +Request ID: 0xf8fa04049bb2d0f968203e008427301f8a6d49018c50647d44f26eabf0fdd114 +The request is being processed... +The request is being processed... +The request is being processed... +The request is being processed... +( + variant { + Ok = record { + dissolve_delay_seconds = 252_383_885 : nat64; + recent_ballots = vec {}; + created_timestamp_seconds = 1_697_751_704 : nat64; + state = 2 : int32; + stake_e8s = 200_000_000 : nat64; + joined_community_fund_timestamp_seconds = null; + retrieved_at_timestamp_seconds = 1_697_835_643 : nat64; + known_neuron_data = null; + voting_power = 399_939_067 : nat64; + age_seconds = 0 : nat64; + } + }, +) +``` + +Now, to get a list of all neurons that belong to your identity's principal, run the command: + +``` +quill --pem-file identity.pem list-neurons > list_neurons.json +``` + +Then, submit the command with: + +``` +quill send list_neurons.json +``` + +To manage a neuron and make a configuration change to it, you can use the command: + +``` +quill --pem-file identity.pem neuron-manage NEURON_ID +``` + +For a full list of arguments to use with this command, use `quill neuron-manage --help` for the full list. For example, to start dissolving a neuron, run the command: + +``` +quill --pem-file identity.pem neuron-manage NEURON_ID --start-dissolving > manage_neuron.json +``` + +Then, submit the command with: + +``` +quill send manage_neuron.json +``` + +To stake ICP in a neuron, you can use the `quill neuron-stake` command: + +``` +quill --pem-file identity.pem neuron-stake --amount AMOUNT --name NAME > stake_neuron.json +``` + +Replace `AMOUNT` with the amount of ICP to stake in the neuron, and replace `NAME` with the name of the neuron. + +Then, submit the command with: + +``` +quill send stake_neuron.json +``` + +Lastly, quill can be used to get information about the NNS's current proposals. For example, to list currently pending proposals, run the command: + +``` +quill list-proposals --limit 3 +``` + +The `--limit` command is used to limit how many are returned; in this command the most recent 3 proposals are returned. Since this command is a query command, it cannot be run on offline machines, so selecting 'N' will cancel the request. Selecting 'Y' will query the mainnet for the result, which will be returned such as: + +``` + record { + id = opt record { id = 125_319 : nat64 }; + status = 1 : int32; + topic = 8 : int32; + failure_reason = null; + ballots = vec { + record { + 14_315_117_116_521_128_082 : nat64; + record { vote = 0 : int32; voting_power = 197_278_881 : nat64 }; + }; + }; + proposal_timestamp_seconds = 1_697_817_106 : nat64; + reward_event_round = 0 : nat64; + deadline_timestamp_seconds = opt (1_698_162_706 : nat64); + failed_timestamp_seconds = 0 : nat64; + reject_cost_e8s = 1_000_000_000 : nat64; + derived_proposal_information = null; + latest_tally = opt record { + no = 12_288_248_589_007 : nat64; + yes = 90_977_820_988_843 : nat64; + total = 45_249_721_684_450_311 : nat64; + timestamp_seconds = 1_697_837_007 : nat64; + }; + reward_status = 1 : int32; + decided_timestamp_seconds = 0 : nat64; + proposal = opt record { + url = ""; + title = opt "Upgrade Nns Canister: 3r4gx-wqaaa-aaaaq-aaaia-cai to wasm with hash: 538efcf1a59b8cfbfa2d665681bb269068011c8b46564b57143f41fbf7b1aa01"; + action = opt variant { + ExecuteNnsFunction = record { + nns_function = 4 : int32; + payload = vec {}; + } + }; + summary = "# Upgrade SNS aggregator canister to commit `eeefa5e413aab9e005063cc4fcefef28ee37139f`\nWasm sha256 hash: `538efcf1a59b8cfbfa2d665681bb269068011c8b46564b57143f41fbf7b1aa01` (`sns_aggregator.wasm.gz`)\n\n## Change Log\n\n* Updated libraries provided by the `ic` repository to `release-2023-06-07_23-01`.\n\n## Commit Log\n\n```\n+ bash -xc \"git log --format=\'%C(auto) %h %s\' 05982aef6..eeefa5e41 ./rs/sns_aggregator/\"\n e61e92223 GIX-1935: Add fields SNS aggregator (#3533)\n d9c1647ec Use Principal instead of candid::Principal (#3452)\n a531d848c Robust traits (#3442)\n d98bee949 Smaller patch (#3440)\n 6d545dd1b Update sns_aggregator IC cargo dependencies to release-2023-06-07_23-01 (#3407)\n 8aa4329ee Bump snsdemo (#3396)\n 28fb107e2 Snsdemo update (#3369)\n```\n\n## Wasm Verification\n\nTo build the wasm module yourself and verify its hash, run the following commands from the root of the [nns-dapp repo](https://github.com/dfinity/nns-dapp):\n\n```\ngit fetch # to ensure you have the latest changes.\ngit checkout \"eeefa5e413aab9e005063cc4fcefef28ee37139f\"\n./scripts/docker-build\nsha256sum sns_aggregator.wasm.gz\n```\n"; + }; + proposer = opt record { id = 36 : nat64 }; + executed_timestamp_seconds = 0 : nat64; + }; +``` + +To get detailed information about this proposal, take the value `id = opt record { id = 125_319 }`, in this case 125319, and input it into the `get-proposal-info` subcommand: + +``` +quill get-proposal-info 125319 +``` + +## Resources + +- [Quill CLI reference](/docs/current/references/quill-cli-reference/) + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + +## Next steps + +To finish the level 4 developer journey section, we'll wrap up with Motoko level 4: + +- [4.6 Motoko level 4](4.6-motoko-lvl4.md). \ No newline at end of file diff --git a/docs/tutorials/developer-journey/level-4/4.6-motoko-lvl4.md b/docs/tutorials/developer-journey/level-4/4.6-motoko-lvl4.md new file mode 100644 index 0000000000..0f8f61a929 --- /dev/null +++ b/docs/tutorials/developer-journey/level-4/4.6-motoko-lvl4.md @@ -0,0 +1,523 @@ +# 4.6 Motoko level 4 + +## Overview + +In this final Motoko module of the developer journey series, we'll cover the following Motoko concepts and components: + +- Mutable state. + +- Local objects and classes. + +- Message inspection. + +- Errors and options. + +## Mutable state + +Every actor in Motoko uses an internal, mutable state. This internal state is private, and cannot be directly shared with other actors. This is a core Motoko design feature, where mutable data is always kept private to the actor that has allocated it, and it is not shared remotely. + +Mutable states are not shareable, since sharing them would mean moving an object's code among other actors and executing it remotely, which poses a security risk, or alternatively sharing the state with a bit of remote logic, which poses another risk. + +The term **mutable** refers to something that can be changed or altered, whereas the term **immutable** refers to something that cannot be changed or altered, and has a permanent definition. + +To understand mutable state, let's take a look at an example where an actor's private state is altered using mutation operations. + +### Immutable variables versus mutable variables + +Immutable variables use the `let` syntax when being declared, such as: + +```motoko +let textImmutable : Text = "Developer Journey"; +let numImmutable : Nat = 50; +``` + +Mutable variables use the `var` syntax when being declared, such as: + +```motoko +var pairMutable : (Text, Nat) = (textImmutable, numImmutable); +var textMutable : Text = textImmutable; +``` + +To update the values of the mutable variables, we can use the following syntax with the assignment operation `:=`, which works for all types: + +```motoko +textMutable := textMutable # "xyz"; +pairMutable := (textMutable, pairMutable.1); +pairMutable +``` + +In this syntax, we update each mutable variable using an update rule for their current values. An actor processes calls by performing updates on its internal mutable variables using the same syntax as above. + +### Reading data from mutable memory + +When data is read from the actor's state, each mutable and immutable variable will look alike, however they will behave differently. For example, consider the following variable declarations: + +```motoko +let x : Nat = 0 +``` + +and: + +```motoko +var x : Nat = 0 +``` + +The only difference between these two variable declarations is the use of `let` for the immutable variable, and `var` for the mutable variable. However, these variable contain much different meanings, especially in the context of larger projects and programs. + +In the immutable variable definition using `let`, each occurrence of the variable equals `0`. Replacing each occurrence with the value `0` will not change the program. + +In the mutable variable definition using `var`, each occurrence of the variable is determined by the mutable, dynamic state of the actor. Each occurrence must read and produce the current value of the memory call for variable `x`. + +`let` bound variables are more fundamental to a program. To demonstrate why, consider the following `var` bound variable that uses a single element, a mutable array, that is bound to itself using a `let` bound variable: + +```motoko +var x : Nat = 0 ; +let y : [var Nat] = [var 0] ; +``` + +In this example, instead of declaring `x` as a mutable variable that initially holds the value `0`, the variable `y` is used, which is an immutable variable that defines a mutable array that holds a single entry of `0`. + +It is important to note that the read/write syntax for mutable arrays is not as readable as `var` bound variables; therefore, reading and writing to variable `x` will be easier than variable `y`. + +:::info +The Motoko standard library provides an Array library that can be used for both mutable and immutable arrays. This library can be imported with the statement: + +`import Array "mo:base/Array";` +::: + +### Immutable arrays + +Before going deeper into mutable arrays, first let's cover immutable arrays, which share the same syntax but do not permit updates. + +For example, consider the following immutable array: + +```motoko +let a : [Nat] = [1, 2, 3] ; +``` + +Then, to read from this array we can use the traditional bracket syntax of `[` and `]`, to read the desired index: + +```motoko +let x : Nat = a[2] + a[0] ; +``` + +### Mutable arrays + +Since by design, remote actors in Motoko do not share their mutable state, the Motoko type system defines a firm distinction between mutable and immutable arrays. This distinction impacts the language's types, subtypes, and the language's abstractions for asynchronous communication. + +Mutable arrays cannot be used in place of immutable onces, since the Motoko definition of subtyping for arrays distinguishes cases for the purposes of type soundness. In regards to actor communication, immutable arrays are safe to send and share, while mutable arrays can only be shared in messages and have non-sharable types. + +To declare a mutable array, the `[var _]` syntax is used. Note that this uses the `var` keyword for both the expression and types: + +```motoko +let a : [var Nat] = [var 1, 2, 3] ; +``` + +This array holds three numbers with type `Nat`. These three values can be updated, but the number of entries cannot. + +To declare a mutable array with a dynamic size, such that the number of entries within the array can be updated, the following `Array_init` syntax can be used: + +```motoko +var size : Nat = 52 ; +let x : [var Nat] = Array.init(size, 5); +``` + +Using this syntax, this mutable array will have `size` number of entries, each with an initial value of `5`. Then, to update this mutable array, you can use the syntax: + +```motoko +x[2] := 42; +``` + +Using this syntax, each entry can be updated via an assignment to that individual entry. In this example, the index entry of `2` gets updated from equalling `52` to equal `42`. + +:::caution + +There are two important notes about subtyping with mutable values: + +- Subtyping does not permit mutable values to be used as immutable values. +- Subtyping does not permit a mutable array of type `[var Nat]` to be used in places that expect an immutable array of type `[Nat]`. + +This is because mutable arrays require different rules for subtyping; in particular, mutable arrays have less flexible subtyping definitions. Additionally, Motoko does not allow mutable arrays to be shared across asynchronous communication, since the mutable state is never shared. + +::: + +## Local objects and classes + +Motoko objects encapsulate the canister's local state using `var` bound variables, packaging the state with any public methods that are used to interact with or update it. As we mentioned earlier, any objects that include a mutable state are not shareable. To provide a workflow to overcome this limitation, an actor's objects are sharable and always execute remotely. Actor objects and classes communicate exclusively with Motoko data. + +In comparison, local objects and classes can pass any Motoko data to another object's methods, including other objects. Local objects and classes are essentially the non-shareable counterparts to actor objects and classes. + +Classes are defined by the keyword `class`, followed by the name for the constructor and the type being defined, optional type arguments, an argument list, and an optional type annotation for constructed objects. + +In the previous section, we introduced mutable state declarations of private mutable state using `var` bound variables and mutable arrays. In this section, we'll use mutable state to implement simple objects. + +### Object classes versus actor classes + +First, let's clearly define the difference between object and actor classes: + +- Object classes: Object classes refer to blueprint used to define a series of related objects with customizable states. Motoko uses a class definition which simplifies building objects of the same implementation and type. + +- Actor classes: When an object class exposes a service, the corresponding Motoko construct is an actor class, which follows a similar design. + +For example, let's look at the following object declaration of the object `counter`: + +```motoko +object counter { + var count = 0; + public func inc() { count += 1 }; + public func read() : Nat { count }; + public func bump() : Nat { + inc(); + read() + }; +}; +``` + +In this declaration, a single object, called `counter` is defined. In this object there are three public functions, `inc`, `read`, and `bump`, which use the keyword `public` to declare each as a sharable function. This object definition also include a single private mutable variable called `count`, defined by the `var` declaration. + +By default, all declarations in an object block are private, such as the variable `count` is in this example. + +### Object types + +In the previous object declaration, `counter` has the following object type, which is expressed using a list of `field` type pairs: + +```motoko +{ + inc : () -> () ; + read : () -> Nat ; + bump : () -> Nat ; +} +``` + +Each `field` type includes an identifier, a colon `:`, and a type for the field's content. Since in this example each `field` is a function, each includes an arrow `->` to display the type form. The type for the variable `count` is not included in the object's type, since it's presence and information are inaccessible from outside the object. + +The inability to access the variable `count` provides an important benefit: the object has a normal general type with fewer fields, and in return is interchangeable with objects that implement the same `counter` object type differently, without including a field such as `count`. + +For example, the following variation of the `counter` declaration above uses the same object type, but uses a different implementation of the `count` variable using an ordinary `Nat` value. This object type is interchangeable with the previous example: + +```motoko +import Nat8 "mo:base/Nat8"; +object byteCounter { + var count : Nat8 = 0; + public func inc() { count += 1 }; + public func read() : Nat { Nat8.toNat(count) }; + public func bump() : Nat { inc(); read() }; +}; +``` + +### Object subtyping + +Next, let's take a look at object subtyping. In Motoko, object subtyping refers to objects that may have various types. Object types with less fields are typically considered subtypes. Object subtypes in Motoko use structural subtyping, where the equality of two types is based on their structure. Two classes with different names but equivalent definitions produce type-compatible objects. + +To demonstrate an example of subtyping, let's use a simple counter with a more general type that uses fewer public functions: + +```motoko +object bumpCounter { + var c = 0; + public func bump() : Nat { + c += 1; + c + }; +}; +``` + +The object type for the object `bumpCounter` exposes only one operation, `bump`: + +```motoko +{ + bump : () -> Nat ; +} +``` + +This example exposes the most common operation and only permits a certain behavior. In another part of a program, we may want to implement another version with more generality, such as our example from earlier: + +```motoko +{ + inc : () -> () ; + read : () -> Nat ; + bump : () -> Nat ; +} +``` + +Lastly, we may implement a type with additional operations, such as a `write` operation: + +```motoko +{ + inc : () -> () ; + read : () -> Nat ; + bump : () -> Nat ; + write : Nat -> () ; +} +``` + +If a function expects to receive an object using the first type `({ bump: () → Nat })`, any of these versions of the type will work since they are equal to, or a subtype of, the most general version. If we want to use a function that expects to receive an object that uses an additional operation not included in the other types, such as the `write` operation, then only that type will work. + +### Object classes + +Now let's move onto object classes. An object class is a package of entities that share a common name. For example, let's define a class example for counters that start at zero: + +```motoko +class Counter() { + var c = 0; + public func inc() : Nat { + c += 1; + return c; + } +}; +``` + +Using this definition, we can construct new counters each with their own unique state that start at zero, such as: + +```motoko +let c1 = Counter(); +let c2 = Counter(); +``` + +Then, we can use each counter, `c1` and `c2`, independently of one another: + +```motoko +let x = c1.inc(); +let y = c2.inc(); +(x, y) +``` + +In comparison, the same results can be achieved by using a constructor function to return an object: + +``` +func Counter() : { inc : () -> Nat } = + object { + var c = 0; + public func inc() : Nat { c += 1; c } + }; +``` + +Note that the return type of this function is `{ inc : () -> Nat }`, which could be named to use in further type declarations, such as `type Counter = { inc : () -> Nat };`. + +### Data arguments + +In our object class, we initialized counter functions to start with a value of zero. If we want to initialize the counter with a value other than zero, we can pass a data argument into the constructor function: + +```motoko +class Counter(init : Nat) { + var c = init; + public func inc() : Nat { c += 1; c }; +}; +``` + +Notice that now the value of `c` is set to `init` rather than set to `0`, to reflect that now the counter value will accept a data argument as an initial value. + + +## Message inspection + +When a canister receives an ingress message submitted through HTTP, the canister can inspect and either accept or decline the message before executing it. For example, when a canister receives an update call, it uses the canister method `canister_inspect_method` to determine if the message will be accepted. If a canister does not contain a Wasm module, the message will be rejected automatically. If the canister is not empty, but it does not implement the `canister_inspect_message` method, then the ingress method will be accepted. `canister_inspect_method` is not used for HTTP query calls, inter-canister calls, for calls made to the management canister. + +Message inspection is designed to mitigate some denial of service attacks, since it drains canister of their cycles for placing unsolicited calls that are rejected. + +Actors can elect to inspect messages and make a decision on whether to execute them or not by declaring a system function called `inspect`. Using the message's attributes, this function produces a true or false value that indicates if the canister decides to accept or decline the message. If a call traps, it will return a false value. + +The argument type of the `inspect` function depends on the actor's interface. The formal argument of the `inspect` function is a record of fields for the following types: + +- `caller`: The principal value for the caller of the message. + +- `arg`: The message's argument content in raw binary. + +- `msg`: A variant of decoding functions, which contains one variant per shared function and the ID of the actor. + + +The inspect system function should not be used as a definitive form of access control since it is executed by a single replica and does not go through full consensus and could be maliciously spoofed. + +Consider the following `inspect` function example that denies all ingress messages and ignores all message information: + +```motoko +system func inspect({}) : Bool { false } +``` + +In comparison, the following `inspect` function example declines all messages where the principal value is anonymous: + +```motoko +system func inspect({ caller : Principal }) : Bool { + not (Principal.isAnonymous(caller)); +} +``` + +Messages can also be declined based on their raw size in bytes (of their arguments prior to any decoding from the Candid binary to the Motoko value), such as: + +```motoko +system func inspect({ arg : Blob }) : Bool { + arg.size() <= 512; +} +``` + +## Errors and options + +In Motoko, there are three primary methods for representing and handling errors. These values are: + +- Option values: Non-informative `null` values that indicate some error. + +- Result variants: Descriptive `#err` value that provides more information about the error. + +- Error values: Values that can be thrown and caught in an asynchronous manner, similar to exceptions, that contain a numeric code and a message. + + +### Error handling best practices + +Motoko error handling best practices recommend to use `Option` and `Result` error handling methods over `Exceptions` wherever possible. This is because both `Option` and `Result` work in synchronous and asynchronous contexts, making APIs safer to use since it encourages clients to consider the error cases along with the success cases. It is recommended to use `Exceptions` only to signal unexpected error cases. + +### Error reporting with `Option` values + +If a function wants to return the value of type `A`, or signal an error can return a value of option type `?A`, the `null` value can designate the error. For example, consider the following `markDone` function that returns an async value of `?Seconds`. + +```motoko +public shared func markDoneOption(id : TodoId) : async ?Seconds { + switch (todos.get(id)) { + case (?(#todo(todo))) { + let now = Time.now(); + todos.put(id, #done(now)); + ?(secondsBetween(todo.opened, now)) + }; + case _ { null }; + } +}; +``` + +Then, we can use the following error callsite: + + +```motoko +public shared func doneTodo2(id : Todo.TodoId) : async Text { + switch (await Todo.markDoneOption(id)) { + case null { + "Something went wrong." + }; + case (?seconds) { + "Congrats! That took " # Int.toText(seconds) # " seconds." + }; + }; +}; +``` + +One drawback of this method is that all possible errors return a single, non-informative `null` value that only tells the user that 'Something went wrong'. + +### Error reporting with `Result` variants + +As an alternative to using `Option` types, `Result` variants can be used to return richer, more defined errors that provide better descriptions of what went wrong. `Result` variants are a built-in type that is defined as such: + +```Motoko +type Result = { #ok : Ok; #err : Err } +``` + +Since `Result` includes the `Err` type parameters, the `Result` type allows us to select the type used to describe errors. Consider the following example that uses `Result` variants to signal errors: + +```Motoko +public shared func markDoneResult(id : TodoId) : async Result.Result { + switch (todos.get(id)) { + case (?(#todo(todo))) { + let now = Time.now(); + todos.put(id, #done(now)); + #ok(secondsBetween(todo.opened, now)) + }; + case (?(#done(time))) { + #err(#alreadyDone(time)) + }; + case null { + #err(#notFound) + }; + } +}; +``` + +Then, we can use the following error callsite: + +```motoko +public shared func doneTodo3(id : Todo.TodoId) : async Text { + switch (await Todo.markDoneResult(id)) { + case (#err(#notFound)) { + "There is no todo with that ID." + }; + case (#err(#alreadyDone(at))) { + let doneAgo = secondsBetween(at, Time.now()); + "You've already completed this todo " # Int.toText(doneAgo) # " seconds ago." + }; + case (#ok(seconds)) { + "Congrats! That took " # Int.toText(seconds) # " seconds." + }; + }; +}; +``` + +This callsite returns more detailed errors, such as 'There is no todo with that ID', or 'You've already completed this todo', which is much more useful than 'Something went wrong'. + +You can learn more about working with `Option` and `Result` types [here](/docs/current/motoko/main/errors#working-with-optionresult). + +### Asynchronous errors + +Asynchronous errors is a restricted form of exception error handling. Since Motoko error values can only be thrown and caught in asynchronous contexts, non-shared functions cannot employ structured error handling. A shared function can only be exited by throwing an `Error` value and then trying to call a shared function on another actor. If this shared function returns an `Error` type, the failure is caught. This error handling cannot be used in regular code outside of an asynchronous context. + +Asynchronous error handling generally should only be used for catching and signally unexpected, irrecoverable failures. If a failure can be handled by the caller, it should return a `Result` instead. The following example demonstrates a form of asynchronous error handling: + +```motoko +public shared func markDoneException(id : TodoId) : async Seconds { + switch (todos.get(id)) { + case (?(#todo(todo))) { + let now = Time.now(); + todos.put(id, #done(now)); + secondsBetween(todo.opened, now) + }; + case (?(#done(time))) { + throw Error.reject("Already done") + }; + case null { + throw Error.reject("Not Found") + }; + } +}; +``` + +Then, we can use the following error callsite: + +```motoko +public shared func doneTodo4(id : Todo.TodoId) : async Text { + try { + let seconds = await Todo.markDoneException(id); + "Congrats! That took " # Int.toText(seconds) # " seconds."; + } catch (e) { + "Something went wrong."; + } +}; +``` + +## Resources + +- [Motoko mutable state](/docs/current/motoko/main/mutable-state). + +- [Motoko message inspection](/docs/current/motoko/main/message-inspection). + +- [Local object classes](/docs/current/motoko/main/local-objects-classes). + +- [Motoko error handling](docs/current/motoko/main/errors). + +## Need help? + +Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The IC community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out: + +- [Developer Discord community](https://discord.com/invite/cA7y6ezyE2), which is a large chatroom for IC developers to ask questions, get help, or chat with other developers asynchronously via text chat. + +- [Developer journey forum discussion](https://forum.dfinity.org/t/developer-journey-feedback-and-discussion/23893). + +- [Developer tooling working group](https://www.google.com/calendar/event?eid=MHY0cjBubmlnYXY1cTkzZzVzcmozb3ZjZm5fMjAyMzEwMDVUMTcwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Motoko bootcamp](https://github.com/motoko-bootcamp/bootcamp-2022), a week-long crash course to learning all things Motoko. + +- [Motoko developer working group](https://www.google.com/calendar/event?eid=ZWVnb2luaHU0ZjduMTNpZHI3MWJkcWVwNWdfMjAyMzEwMTJUMTUwMDAwWiBjX2Nnb2VxOTE3cnBlYXA3dnNlM2lzMWhsMzEwQGc&ctz=Europe/Zurich). + +- [Upcoming events and conferences](https://dfinity.org/events-and-news/). + +- [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 our [developer Discord](https://discord.com/invite/cA7y6ezyE2) group. + +## Next steps + +That'll wrap up level 4 of the developer journey! Next, we'll dive into the final level, level 5: + +- 5.1 Developing an encrypted notes dapp with vetKD. \ No newline at end of file diff --git a/docs/tutorials/developer-journey/level-4/index.md b/docs/tutorials/developer-journey/level-4/index.md new file mode 100644 index 0000000000..5cf6a064b5 --- /dev/null +++ b/docs/tutorials/developer-journey/level-4/index.md @@ -0,0 +1,87 @@ +# Level 4: Space pilot + +- [4.1 Using the ICP ledger](4.1-icp-ledger.md): In this tutorial, we'll dive into how to deploy a local instance of the ICP ledger canister and how to interact with it: + - Accounts. + - Transaction types. + - Deploying the ICP ledger locally. + - Prerequisites. + - Creating a new project. + - Locating the Wasm and Candid files. + - Creating a `minting` account. + - Deploying the canister. + - Interacting with the ICP ledger canister. + - Using `dfx ledger`. + - Using `dfx canister`. + - Using the Candid UI. + - Resources. + +- [4.2 ICRC-1 tokens](4.2-icrc-tokens.md): For developers to create their own fungible tokens on the Internet Computer, the ICRC-1 token standard can be used. For this tutorial, we'll focus on the ICRC-1 standard, ICRC-1 ledger, and briefly look into the ICRC-2 standard: + - What’s the difference between the ICP and ICRC-1 ledgers? + - `Account`s versus `AccountIdentifier`s. + - Endpoints. + - Index canisters. + - Extensions of the standard. + - Metadata. + - Deploying the ICRC-1 ledger locally. + - Prerequisites. + - Creating a new project. + - Locating the Wasm and Candid files. + - Deploying the ICRC-1 ledger on the mainnet. + - Interacting with the ICRC-1 ledger. + - Using the `dfx canister` command with ICRC-1 endpoints. + - Using ICRC-2 endpoints. + - Using the Candid UI. + - Resources. + +- [4.3 ckBTC and Bitcoin integration](4.3-ckbtc-and-bitcoin.md): One of the key features of the Internet Computer is known as **chain-key cryptography**. This feature enables integrations with other networks, such as the Bitcoin network. In this tutorial, we take a look at ckBTC and the Internet Computer's Bitcoin integration: + - Bitcoin integration architecture. + - What is ckBTC? + - Bitcoin use-cases on the IC. + - Deploying a Bitcoin dapp. + - Prerequisites. + - Setting up a local Bitcoin network. + - Cloning the `basic_bitcoin` example. + - Deploying the example canister. + - Generating a Bitcoin address. + - Receiving BTC. + - Checking your BTC balance. + - Sending BTC. + - Resources. + +- [4.4 NNS governance and staking](4.4-nns-governance.md): The Network Nervous System (NNS) is the governing body of the Internet Computer. It is a decentralized autonomous organization that is hosted fully on-chain and is responsible for making protocol-level upgrades to the IC: + - What is the NNS? + - Neurons. + - Proposals. + - Why is the NNS important to developers? + - Using the NNS dapp. + - Transferring ICP tokens into your Internet Identity `Main` account. + - Staking ICP in a neuron. + - Interacting with NNS proposals. + +- [4.5 Using quill](4.5-using-quill.md): Quill is a ledger and governance toolkit that provides support for self-custody of ICP tokens and functionality to interact with the NNS, SNSs, and ICP ledger from a **cold wallet**: + - What is quill? + - Downloading and installing quill. + - Using quill’s basic commands. + - Using quill with ckBTC. + - Using quill with the NNS. + - Resources. + +- [4.6 Motoko level 4](4.6-motoko-lvl4.md): In this final Motoko module of the developer journey series, we'll cover the following Motoko concepts and components: + - Mutable state. + - Immutable variables versus mutable variables. + - Reading data from mutable memory. + - Immutable arrays. + - Mutable arrays. + - Local objects and classes. + - Object classes versus actor classes. + - Object types. + - Object subtyping. + - Object classes. + - Data arguments. + - Message inspection. + - Errors and options. + - Error handling best practices. + - Error reporting with `Option` values. + - Error reporting with `Result` variants . + - Asynchronous errors. + - Resources. diff --git a/docs/tutorials/index.mdx b/docs/tutorials/index.mdx index 0f41b83ce8..80c12f6938 100644 --- a/docs/tutorials/index.mdx +++ b/docs/tutorials/index.mdx @@ -7,6 +7,16 @@ This section contains Internet Computer tutorials that will guide developers to ## Developer journey +:::info + +In this developer journey, we focus on developing canisters and applications using Motoko. In the future, there will be additional variations of the developer journey that focus on different developer paths, such as: + +- Rust development. +- ckBTC-focused development. +- ckETH-focused development. + +::: + ### Level 0: Pre-flight operations - [0.1 Overview of the Internet Computer](developer-journey/level-0/01-ic-overview.md) @@ -36,21 +46,21 @@ This section contains Internet Computer tutorials that will guide developers to ### Level 3: Space engineer -- [3.1 Motoko package managers.](developer-journey/level-3/3.1-package-managers.md) -- [3.2 Using HTTPS outcalls.](developer-journey/level-3/3.2-https-outcalls.md) -- [3.3 Certified data.](developer-journey/level-3/3.3-certified-data.md) -- [3.4 Introduction to agents.](developer-journey/level-3/3.4-intro-to-agents.md) -- [3.5 Identities and authentication.](developer-journey/level-3/3.5-identities-and-auth.md) -- [3.6 Motoko level 3.](developer-journey/level-3/3.6-motoko-lvl3.md) +- [3.1 Motoko package managers](developer-journey/level-3/3.1-package-managers.md) +- [3.2 Using HTTPS outcalls](developer-journey/level-3/3.2-https-outcalls.md) +- [3.3 Certified data](developer-journey/level-3/3.3-certified-data.md) +- [3.4 Introduction to agents](developer-journey/level-3/3.4-intro-to-agents.md) +- [3.5 Identities and authentication](developer-journey/level-3/3.5-identities-and-auth.md) +- [3.6 Motoko level 3](developer-journey/level-3/3.6-motoko-lvl3.md) ### Level 4: Space pilot -- 4.1 Using the ICP ledger -- 4.2 ICRC-1 tokens -- 4.3 ckBTC and Bitcoin integration -- 4.4 NNS governance and staking -- 4.5 Using quill -- 4.6 Motoko level 4 +- [4.1 Using the ICP ledger](developer-journey/level-4/4.1-icp-ledger.md) +- [4.2 ICRC-1 tokens](developer-journey/level-4/4.2-icrc-tokens.md) +- [4.3 ckBTC and Bitcoin integration](developer-journey/level-4/4.3-ckbtc-and-bitcoin.md) +- [4.4 NNS governance and staking](developer-journey/level-4/4.4-nns-governance.md) +- [4.5 Using quill](developer-journey/level-4/4.5-using-quill.md) +- [4.6 Motoko level 4](developer-journey/level-4/4.6-motoko-lvl4.md) ### Level 5: Internet Computer astronaut diff --git a/how-it-works/6_webaccess/01_web_access.card.md b/how-it-works/6_webaccess/01_web_access.card.md index 021859ce34..66ecba8bdb 100644 --- a/how-it-works/6_webaccess/01_web_access.card.md +++ b/how-it-works/6_webaccess/01_web_access.card.md @@ -6,7 +6,7 @@ title: Serving Web content # Smart Contracts serve the web -The Internet Computer is the only blockchain that can host a full dapp – frontend, +The Internet Computer is the only blockchain that can host a entire dapp – frontend, backend and data. This is a crucial and distinguishing feature allowing dapps to run 100% on-chain inheriting the security and decentralization of blockchain without sacrificing speed or affordability. This is possible because the IC can diff --git a/plugins/utils/redirects.js b/plugins/utils/redirects.js index 1238e58e89..2a78ab9c2d 100644 --- a/plugins/utils/redirects.js +++ b/plugins/utils/redirects.js @@ -172,9 +172,8 @@ const redirects = ` /docs/developers-guide/tutorials-intro.html /docs/current/tutorials/developer-journey/ /docs/quickstart/quickstart.html /docs/current/developer-docs/setup/ /apis/site/proxy /docs/current/references/http-gateway-protocol-spec - /docs/developers-guide/concepts/what-is-ic /docs/current/concepts/ + /docs/developers-guide/concepts/what-is-ic /docs/current/concepts/what-is-ic /language-guide/index /docs/current/tutorials/developer-journey/level-0/intro-languages - /docs/current/concepts/what-is-IC /docs/current/concepts/ /docs/current/concepts/data-centers /docs/current/concepts/ ` .split(/[\r\n]+/) diff --git a/roadmap/2_boundary_nodes/deployed/3_canister_blacklisting.md b/roadmap/2_boundary_nodes/deployed/3_canister_blacklisting.md index 7143e27d84..5779ea8f6d 100644 --- a/roadmap/2_boundary_nodes/deployed/3_canister_blacklisting.md +++ b/roadmap/2_boundary_nodes/deployed/3_canister_blacklisting.md @@ -6,4 +6,4 @@ links: eta: October 2022 is_community: false --- -This feature gives node providers decentralized means to specify a deny-list for canisters. As node providers are the first to be contacted if questionable content is being stored on the Internet Computer, adding a deny-listing feature will allow them to make independent decisions about blocking such content, while users can choose which boundary node to use. +This feature gives node providers decentralized means to specify a deny-list for canisters. As node providers are the first to be contacted if questionable content is being stored in a canister smart contract on ICP, adding a deny-listing feature will allow them to make independent decisions about blocking such content, while users can choose which boundary node to use. diff --git a/roadmap/2_boundary_nodes/upcoming/sev_snp_nodes.md b/roadmap/2_boundary_nodes/upcoming/sev_snp_nodes.md index 201a7eb618..84622cabbf 100644 --- a/roadmap/2_boundary_nodes/upcoming/sev_snp_nodes.md +++ b/roadmap/2_boundary_nodes/upcoming/sev_snp_nodes.md @@ -6,6 +6,6 @@ links: eta: is_community: false --- -This feature targets securing the boundary node Virtual Machine (VM) using trusted execution via AMD SEV-SNP. Implementation will involve evaluating a vanilla SEV-SNP and [AMDESE / sev-guest](https://github.com/AMDESE/sev-guest) demo, transforming the structure of the boundary node VM so it can be booted as a SEV-SNP secured VM, and defining steps to enable remote attestation for external parties. +This feature targets securing the boundary node Virtual Machine (VM) using trusted execution via AMD SEV-SNP. The implementation will include the evaluation of a vanilla SEV-SNP and [AMDESE / sev-guest](https://github.com/AMDESE/sev-guest) demo, transforming the structure of the boundary node VM so it can be booted as a SEV-SNP secured VM, and defining steps to enable remote attestation for external parties. diff --git a/roadmap/6_infrastructure/in-progress/2_Remuneration_V2.md b/roadmap/6_infrastructure/in-progress/2_Remuneration_V2.md index 148787602c..16a58b93a8 100644 --- a/roadmap/6_infrastructure/in-progress/2_Remuneration_V2.md +++ b/roadmap/6_infrastructure/in-progress/2_Remuneration_V2.md @@ -1,5 +1,5 @@ --- -title: Remuneration V2 +title: Node Provider Remuneration V2 links: Forum Post: https://forum.dfinity.org/t/the-state-and-direction-of-decentralization-nodes-on-the-internet-computer/9170 Proposal: @@ -7,7 +7,7 @@ eta: is_community: true --- -For the further growth of the IC network, the new Replica HW specification has been defined. This new Hardware specification is generic (instead of vendor specific) and supports VM memory encryption and attestation which will be needed in future features on the IC. Since the HW specification is different, a new version of the remuneration, which will be called V2 (Version 2) remuneration model is being defined. Based on feedback and discussion within the community, this remuneration is based on the following: +For the further growth of the IC network, the NNS agreed on a new replica hardware specification. The new specification is generic, i.e. not vendor specific. It is ready for upcoming ICP improvements. For example, it supports VM memory encryption and attestation which will further increase the security of dapps running on ICP. The new specification results in different captical expenses for the independent node providers running replica nodes. Consequently, a new NP reward structure (remuneration) is required. Based on feedback and discussion within the community, this remuneration is based on: - Higher rewards for the first nodes of a new NP in order to attract more NPs in an effort to improve ownership decentralization. - More refined rewards for nodes in new geographies, like South America, Africa, Asia and Australia, to stimulate further geographical decentralization. diff --git a/showcase.json b/showcase.json index ab46b71e42..300476c257 100644 --- a/showcase.json +++ b/showcase.json @@ -103,7 +103,6 @@ ], "description": "ICDex is flagship product by ICLighthouse, an orderbook based DEX that runs 100% on-chain. The world's first orderbook DEX - made possible by advanced ICP smart contracts", "usesInternetIdentity": true, - "stats": "Supports ckBTC", "twitter": "https://twitter.com/ICLighthouse", "display": "Normal", "logo": "/img/showcase/icdex_logo.webp", @@ -161,7 +160,7 @@ "twitter": "https://twitter.com/bitfinitynet", "description": "Bitfinity is the EVM compatibility layer for the IC. Using Bitfinity, you can deploy your Solidity smart contracts to the Internet Computer, taking advantage of is many advantageous DeFi capabilities: HTTP Outcalls, the BTC integration and more.", "usesInternetIdentity": true, - "stats": "1000+ TPS", + "stats": "1,000+ TPS", "display": "Large", "logo": "/img/showcase/bitfinity_evm.png", "screenshots": [ @@ -325,7 +324,7 @@ "website": "https://boomdao.xyz/", "tags": ["Games", "DAO", "Tools / Infrastructure", "NFT", "Metaverse"], "description": "BOOM DAO is an all-in-one web3 game platform and protocol running 100% on-chain on the Internet Computer. We are on a mission to build the gaming vertical of the Internet Computer blockchain, power the next generation of fully on-chain games on ICP, and provide a collaborative hub for all things web3 gaming.", - "stats": "+23000 DAO Members", + "stats": "23,000+ DAO Members", "logo": "/img/showcase/boom-dao-logo.webp", "display": "Large", "usesInternetIdentity": true, @@ -571,7 +570,7 @@ "description": "Internet Identity is a privacy-enhancing authentication framework for applications on the Internet Computer. It provides users with a easy-to-use and secure anonymizing login to Web3 services running on ICP without being tracked across dapps.", "github": "https://github.com/dfinity/internet-identity", "usesInternetIdentity": true, - "stats": "1 000 000+ ", + "stats": "1,000,000+ users", "logo": "/img/showcase/internetidentity_logo.webp", "screenshots": [ "/img/showcase/internetidentity_screenshot_0.gif" @@ -610,7 +609,7 @@ "display": "Normal", "id": "signals", "oneLiner": "A location based app for empowering local communities", - "stats": "5,000+", + "stats": "5,000+ users", "tags": [ "SocialFi" ], @@ -649,7 +648,7 @@ ], "description": "Plug Wallet, built and open sourced by Fleek, is a browser extension that allows you to access your ICP, Cycles and other tokens - as well as log into Internet Computer dapps with one click.", "github": "https://github.com/Psychedelic/plug", - "stats": "100 000 users", + "stats": "100,000+ users", "display": "Normal", "logo": "/img/showcase/plug_logo.webp", "video": "/img/showcase/plug_video.mp4", @@ -771,7 +770,7 @@ ], "description": "Mora allows users to create a unique Web3 space where they can have independent content data, subscription relationships, financial information, and even complex algorithms. From its inception, a planet will be monitored by Launch Trail to ensure compliance with the protocol and establish trust. The Launch Trail will be controlled by the Mora Dao Canister.", "usesInternetIdentity": true, - "stats": "2000+ articles", + "stats": "2,000+ articles", "logo": "/img/showcase/mora_logo.png", "screenshots": [ "/img/showcase/mora_banner.jpg" @@ -958,7 +957,6 @@ "website": "https://rubaru.app/", "tags": ["SocialFi"], "description": "RuBaRu aims to create a vibrant 100% On-Chain DAO-based tokenized economy owned & governed by the community, where creators, influencers, consumers, and brands coexist harmoniously. By doing so, we unlock new opportunities, reshape digital creativity, drive economic growth, and foster a thriving ecosystem of shared prosperity.", - "stats": "100% On-Chain Data Storage", "logo": "/img/showcase/rubaru_logo.png", "display": "Large", "usesInternetIdentity": true, @@ -981,7 +979,6 @@ ], "description": "ntagle connects inexpensive physical NFC tags to canisters, giving IC dapp developers the ability to create transferrable HW wallets, Physical NFTs, etc. Any tag can use any integration, meaning dapps can make web3 phygital experiences available to all ntagle owners with a single deploy.", "usesInternetIdentity": false, - "stats": "Working MVP", "logo": "/img/showcase/ntagle_icon.webp", "github": "https://github.com/InternetComputerOG/ntagle-core", "twitter": "https://twitter.com/ntagled", @@ -1023,7 +1020,7 @@ "description": "Kontribute is a web3 creators platform that brings story writing and digital art collectibles together. Features include: decentralized story storage, likes, tipping, polls, NFT marketplace and NFT minting.", "github": "https://github.com/teambonsai/bonsai_dapp", "usesInternetIdentity": true, - "stats": "1000+ users", + "stats": "1,000+ users", "display": "Normal", "logo": "/img/showcase/kontribute_logo.webp", "screenshots": [ @@ -1628,7 +1625,6 @@ ], "description": "This Python Agent built for the Internet Computer opens the door for Python developers to more easily become Web3 builders. Featuring basic modules to interact with canisters on the Internet Computer, this Agent, still under development, was a prize winner at the Warpspeed Internet Computer ecosystem hackathon in China.", "github": "https://github.com/rocklabs-io/ic-py", - "stats": "Warp Speed Hackathon Award", "display": "Normal", "logo": "/img/showcase/pythonagent_logo.webp", "screenshots": [ @@ -1680,7 +1676,6 @@ "website": "https://obsidiantears.xyz/", "tags": ["Games", "NFT", "Metaverse"], "description": "Obsidian Tears is a 2D adventure featuring original art, story, music and over 50 collectable NFT artifacts. Our mission is to make a great story after our favorite old time classics, and to empower others to do the same.", - "stats": "First 2D RPG on the IC", "logo": "/img/showcase/obsidian-tears-logo.webp", "display": "Large", "usesInternetIdentity": false, @@ -1829,7 +1824,7 @@ "display": "Normal", "id": "cyqlio", "oneLiner": "Curated Internet Computer projects gallery.", - "stats": "5000+ users", + "stats": "5,000+ users", "tags": [ "Tools / Infrastructure" ], @@ -1954,7 +1949,7 @@ ], "description": "IC coins by market cap. Aggregates stats from all Internet Computer based DEXes. Price, Volume & liquidity score charts.", "usesInternetIdentity": false, - "stats": "1000 users", + "stats": "1,000+ users", "logo": "/img/showcase/icpcoins_logo.png", "github": "https://github.com/vvv-interactive/icpcoins", "screenshots": [ @@ -2137,7 +2132,6 @@ "Games" ], "usesInternetIdentity": true, - "stats": "Play weekly", "logo": "/img/showcase/football-god_logo.webp", "screenshots": [ "/img/showcase/football-god_screenshot.webp" @@ -2241,7 +2235,7 @@ "website": "https://can1.metaforo.io/", "tags": [ "SocialFi"], "description": "Metaforo: a Web3 forum prioritizing decentralization, community ownership, and token-gated governance. By shifting the Front-End to IC, we boost reliability, security, and scalability, enabling a seamless user experience without intermediaries.", - "stats": "1000+ users after the development of an on-chain voting system using ICP", + "stats": "1,000+ users", "logo": "/img/showcase/metaforo-icp_logo.png", "usesInternetIdentity": true, "github": "https://github.com/metaforo/metaforo-icp", @@ -2263,7 +2257,6 @@ "display": "Normal", "id": "rakeoff", "oneLiner": "Rakeoff is a user-friendly crypto staking rewards platform on ICP.", - "stats": "Hackathon winner", "tags": [ "Bitcoin", "DeFi", @@ -2295,7 +2288,6 @@ "website": "https://tswaanda.com", "tags": ["DeFi"], "description": "Tswaanda is revolutionizing African agriculture by connecting smallholder farmers to profitable markets, empowering growth through trade and financial inclusion.", - "stats": "3 users", "logo": "/img/showcase/tswaanda_logo.jpg", "usesInternetIdentity": true, "authOrigins": ["https://4qia7-eaaaa-aaaal-qb34a-cai.icp0.io"], @@ -2351,7 +2343,6 @@ "video": "", "display": "Normal", "oneLiner": "Transparent, tamper-proof voting on blockchain.", - "stats": "100% On Chain Data Storage", "tags": [ "Tools / Infrastructure" ], @@ -2463,7 +2454,6 @@ "display": "Normal", "id": "nacdb-database", "oneLiner": "A distributed database that allows seamless scanning", - "stats": "0 users", "tags": [ "Tools / Infrastructure" ], @@ -2485,7 +2475,7 @@ ], "description": "Fleek brings decentralized web-hosting to the Internet Computer. With thousands of webpages deployed, Fleek enables anyone to deploy their content on Web3.0", "usesInternetIdentity": false, - "stats": "1 000+ websites", + "stats": "1,000+ websites", "logo": "/img/showcase/fleek_logo.webp", "screenshots": [ "/img/showcase/fleek_screenshot_0.webp" @@ -2529,7 +2519,7 @@ "SocialFi" ], "description": "The uniquely-designed DID is your passport in web3. Your data and assets will be connected to HashKey DID and your private information will be kept in your own hands.", - "stats": "Multi-Chain DID, 1,200,000 users, 3,200,000 Credentials, 30 Eco-members", + "stats": "1,200,000 users, 3,200,000 Credentials, 30 Eco-members", "logo": "/img/showcase/hashkeydid_logo.svg", "usesInternetIdentity": false, "github": "https://github.com/hashkeydid/hashkeydid-icp", @@ -2543,7 +2533,6 @@ "DAO","Tools / Infrastructure","Metaverse" ], "description": "The boundaryless autonomous organization.", - "stats": "7+ Grants Project", "logo": "/img/showcase/nnsdao_logo.png", "usesInternetIdentity": false, "github": "https://github.com/NnsDao", @@ -2668,7 +2657,7 @@ "website": "https://web3.motoko-book.dev/", "tags": ["Tools / Infrastructure"], "description": "This book guides beginners into the world of Web3 programming in Motoko on the Internet Computer. It covers a broad range of concepts from the very basics to advanced async programming.", - "stats": "100 monthly users Google Analytics 17-06-2023", + "stats": "100 monthly users", "logo": "/img/showcase/motoko-book_logo.png", "usesInternetIdentity": "false", "github": "https://github.com/Web3NL/motoko-book", @@ -2682,7 +2671,6 @@ "website": "https://jqajc-hiaaa-aaaak-qck5a-cai.icp0.io/#/", "tags": ["Tools / Infrastructure"], "description": "InfinitiNote is an ICP-based AI-Enabled Note taking application, that allows users to create Notebooks, store Notes, and collaboratively edit in real-time with capability for file uploads and enhacned by LLAMA AI.", - "stats": "Just Launched", "logo": "/img/showcase/in_logo.jpg", "usesInternetIdentity": "true", "github": "https://github.com/hafezrouzati/infinitinote", @@ -2724,7 +2712,6 @@ "display": "Normal", "id": "safenote", "oneLiner": "A tool for secure notes exchanging. Built with privacy in mind.", - "stats": "1+ user", "tags": [ "Tools / Infrastructure" ], @@ -2790,7 +2777,7 @@ "display": "Normal", "id": "ics2", "oneLiner": "store and organize your files in IC ecosystem", - "stats": "100+", + "stats": "100+ users", "tags": [ "Tools / Infrastructure" ], @@ -2812,7 +2799,6 @@ "display": "Normal", "id": "ava", "oneLiner": "aVa: Action-Based Decentralized Reputation Landscape.", - "stats": "All II users", "tags": [ "Tools / Infrastructure" ], @@ -2824,7 +2810,7 @@ }, { "name": "Open Internet Metaverse", - "description": "OIM allows you to create virtual spaces and host them like Websites on the Internet Computer - everything in 3D. You can include 3D objects, images, videos and more in your spaces and thus make it your home on the 3D Web. By linking to others' spaces, you can create your personal virtual neighborhood in the \"Metaverse\" (aka Internet).", + "description": "OIM is the 1st On-Chain 3D-Web. It allows you to create virtual spaces and host them like Websites on the Internet Computer - everything in 3D. You can include 3D objects, images, videos and more in your spaces and thus make it your home on the 3D Web. By linking to others' spaces, you can create your personal virtual neighborhood in the \"Metaverse\" (aka Internet).", "website": "https://vdfyi-uaaaa-aaaai-acptq-cai.ic0.app", "logo": "/img/showcase/open-internet-metaverse_logo.webp", "screenshots": [], @@ -2832,7 +2818,6 @@ "display": "Normal", "id": "open-internet-metaverse", "oneLiner": "Create Your Virtual Space as a 3D-Website on the Internet Computer", - "stats": "1st On-Chain 3D-Web", "tags": [ "Tools / Infrastructure", "Metaverse" @@ -2855,7 +2840,7 @@ ], "display": "Normal", "oneLiner": "FishVerse is a W2E fishing game that is built on ICP technology", - "stats": "5000", + "stats": "5,000 players", "tags": [ "NFT", "Metaverse", @@ -2879,7 +2864,7 @@ "display": "Normal", "id": "bravo-app", "oneLiner": "Token Stats, Blockchain Visual Explorer, Account Searching and more..", - "stats": "1024 Members", + "stats": "1,024 members", "tags": [ "NFT", "Tools / Infrastructure", @@ -3011,7 +2996,6 @@ "display": "Normal", "id": "ccamp", "oneLiner": "Modular, and custom data-driven Cross-chain Asset Management Protocol", - "stats": "Cross-chain", "tags": [ "Bitcoin", "Tools / Infrastructure", diff --git a/sidebars.js b/sidebars.js index 0f28b1bb6a..94bc215148 100644 --- a/sidebars.js +++ b/sidebars.js @@ -80,6 +80,22 @@ const sidebars = { "tutorials/developer-journey/level-3/3.6-motoko-lvl3", ], }, + { + type: "category", + label: "Level 4: Space pilot", + link: { + type: "doc", + id: "tutorials/developer-journey/level-4/index", + }, + items: [ + "tutorials/developer-journey/level-4/4.1-icp-ledger", + "tutorials/developer-journey/level-4/4.2-icrc-tokens", + "tutorials/developer-journey/level-4/4.3-ckbtc-and-bitcoin", + "tutorials/developer-journey/level-4/4.4-nns-governance", + "tutorials/developer-journey/level-4/4.5-using-quill", + "tutorials/developer-journey/level-4/4.6-motoko-lvl4", + ], + }, ], }, { @@ -150,6 +166,7 @@ const sidebars = { id: "concepts/index", }, items: [ + "concepts/what-is-ic", "concepts/canisters-code", "developer-docs/gas-cost", "concepts/governance", diff --git a/src/css/custom.scss b/src/css/custom.scss index df66124aff..124043c0d5 100644 --- a/src/css/custom.scss +++ b/src/css/custom.scss @@ -51,6 +51,7 @@ @import "./sidebar.scss"; @import "./subnav.scss"; @import "./map.scss"; +@import "./spinner.scss"; // specifically target the dev docs namespace; // we don't want to apply these styles to the marketing pages diff --git a/src/css/spinner.scss b/src/css/spinner.scss new file mode 100644 index 0000000000..2a4f1bdb9e --- /dev/null +++ b/src/css/spinner.scss @@ -0,0 +1,73 @@ +.spinner { + display: inline-block; + span { + width: 15px; + height: 15px; + margin-right: 8px; + border-radius: 100%; + display: inline-block; + + animation: sk-bouncedelay 1.4s infinite ease-in-out both; + } + + .bounce1 { + animation: sk-bouncedelay 1.4s infinite ease-in-out both, + spinner-color-1 2.8s steps(1) infinite both; + animation-delay: -0.32s; + } + + .bounce2 { + animation: sk-bouncedelay 1.4s infinite ease-in-out both, + spinner-color-2 2.8s steps(1) infinite both; + animation-delay: -0.16s; + } + + .bounce3 { + animation: sk-bouncedelay 1.4s infinite ease-in-out both, + spinner-color-3 2.8s steps(1) infinite both; + background-color: #fbb03b; + } +} + +@keyframes spinner-color-1 { + 100%, + 0% { + background-color: #29abe2; + } + 50% { + background-color: #522785; + } +} + +@keyframes spinner-color-2 { + 100%, + 0% { + background-color: #f15a24; + } + 50% { + background-color: #ed1e79; + } +} + +@keyframes spinner-color-3 { + 100%, + 0% { + background-color: #fbb03b; + } + 50% { + background-color: #29abe2; + } +} + +@keyframes sk-bouncedelay { + 0%, + 80%, + 100% { + -webkit-transform: scale(0); + transform: scale(0); + } + 40% { + -webkit-transform: scale(1); + transform: scale(1); + } +} diff --git a/src/pages/capabilities/webassembly.tsx b/src/pages/capabilities/webassembly.tsx index 929ce1b19a..ffdac2d66d 100644 --- a/src/pages/capabilities/webassembly.tsx +++ b/src/pages/capabilities/webassembly.tsx @@ -109,8 +109,8 @@ function WebAssemblyPage() {

The Internet Computer executes the code of an application on - multiple decentralized nodes. This is called replicated - execution, and it works even in the presence of untrusted and + multiple decentralized nodes, which are operated by node providers who are selected and vetted by the NNS token holders. This replicated + execution works even in the presence of untrusted and malicious nodes. A critical property for replicated execution is its determinism, which refers to executing identical code with the same inputs, invariably yielding the same result. This diff --git a/src/pages/icp-newsletter.tsx b/src/pages/icp-newsletter.tsx new file mode 100644 index 0000000000..f4ab5be1d8 --- /dev/null +++ b/src/pages/icp-newsletter.tsx @@ -0,0 +1,48 @@ +import Head from "@docusaurus/Head"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import React, { useEffect } from "react"; +import ShareMeta from "../components/Common/ShareMeta"; + +const IcpNewsletterRedirectPage: React.FC = () => { + const metaDescription = + "Stay informed with the latest on the Internet Computer. Browse the previous Newsletters for current updates."; + const title = "ICP News & Updates Mailing"; + const { siteConfig } = useDocusaurusContext(); + + const redirectTo = + "https://us16.campaign-archive.com/home/?u=33c727489e01ff5b6e1fb6cc6&id=7e9469a315"; + + useEffect(() => { + // redirect with JS as well, just in case... + window.location.href = redirectTo; + }, []); + + return ( + <> + + + {title} + + + + + + + + {/* add a small delay of 1 second to prevent anecdotal security warning */} + + + +

+ {/* spinner in the center of screen */} +
+ + + +
+
+ + ); +}; + +export default IcpNewsletterRedirectPage; diff --git a/src/pages/internet-identity.tsx b/src/pages/internet-identity.tsx index b932091198..25548b320b 100644 --- a/src/pages/internet-identity.tsx +++ b/src/pages/internet-identity.tsx @@ -382,7 +382,7 @@ function InternetIdentityPage() { className="tw-lead-sm mb-0 text-center mx-auto md:w-6/12" variants={transitions.item} > - Learn how to build a user-friendly dApp on the + Learn how to build a user-friendly dapp on the Internet Computer using Internet Identity, our core identity component. diff --git a/src/pages/sns/faq.tsx b/src/pages/sns/faq.tsx index e4b100d987..f5af65ab65 100644 --- a/src/pages/sns/faq.tsx +++ b/src/pages/sns/faq.tsx @@ -201,10 +201,11 @@ function SnsFaqPage() { unique in that they can fully control (via voting) every aspect of a dapp, since everything is on-chain. Having fully on-chain DAOs is important because it enables all decisions to be - executed on the blockchain. This is in contrast to existing DAOs + executed on the blockchain and thus facilitates true + decentralization. This is in contrast to existing DAOs on other blockchains where voting takes place on-chain but the execution of the results are often carried out by developers - off-chain. This facilitates true decentralization.{" "} + off-chain.{" "}

Therefore, SNS DAOs serve as a vehicle to deliver fully decentralized online services that are owned and governed by @@ -364,9 +365,8 @@ function SnsFaqPage() { id="how-do-you-get-sns-tokens" >

- Each SNS DAO will have its own unique SNS token. For example, - OpenChat will have CHAT tokens when they turn their dapp into an - SNS DAO.{" "} + Each SNS DAO has its own unique SNS token. For example, + OpenChat has CHAT tokens.{" "}

There are three main ways of acquiring SNS tokens:

    diff --git a/static/img/blog/dev-update-blog-oct-25.jpg b/static/img/blog/dev-update-blog-oct-25.jpg new file mode 100644 index 0000000000..c2be22abe4 Binary files /dev/null and b/static/img/blog/dev-update-blog-oct-25.jpg differ diff --git a/static/img/shareImages/share-icp-newsletter.jpg b/static/img/shareImages/share-icp-newsletter.jpg new file mode 100644 index 0000000000..569940a84b Binary files /dev/null and b/static/img/shareImages/share-icp-newsletter.jpg differ