Skip to content

Commit

Permalink
fix links
Browse files Browse the repository at this point in the history
  • Loading branch information
jessiemongeon1 committed Oct 14, 2024
1 parent e041003 commit c6e640d
Show file tree
Hide file tree
Showing 18 changed files with 18,126 additions and 852 deletions.
18,031 changes: 18,031 additions & 0 deletions hosting/photo-storage/package-lock.json

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions motoko/dip721-nft-container/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ When upgrading canister code, however, it is necessary to explicitly handle cani
### 2. Certified data.
Generally, when a function only reads data, instead of modifying the state of the canister, it is
beneficial to use a [query call instead of an update call](https://internetcomputer.org/docs/current/concepts/canisters-code.md#query-and-update-methods).
But, since query calls do not go through consensus, [certified responses](https://internetcomputer.org/docs/current/developer-docs/security/general-security-best-practices)
But, since query calls do not go through consensus, [certified responses](https://internetcomputer.org/docs/current/developer-docs/security/security-best-practices/overview)
should be used wherever possible. The HTTP interface of the Rust implementation shows how certified data can be handled.

### 3. Delegating control over assets.
Expand All @@ -47,7 +47,7 @@ In case an error occurs during any part of the upgrade (including `post_upgdrade

The Rust CDK (Canister Development Kit) currently only supports one value in stable memory, so it is necessary to create an object that can hold everything you care about.
In addition, not every data type can be stored in stable memory; only ones that implement the [CandidType trait](https://docs.rs/candid/latest/candid/types/trait.CandidType.html)
(usually via the [CandidType derive macro](https://docs.rs/candid/latest/candid/derive.CandidType.html)) can be written to stable memory.
(usually via the [CandidType derive macro](https://docs.rs/candid/latest/candid/derive.CandidType.html)) can be written to stable memory.

Since the state of our canister includes a `RbTree` which does not implement the `CandidType`, it has to be converted into a data structure (in this case a `Vec`) that implements `CandidType`.
Luckily, both `RbTree` and `Vec` implement functions that allow converting to/from iterators, so the conversion can be done quite easily.
Expand Down Expand Up @@ -76,7 +76,7 @@ For a much more detailed explanation of how certification works, see [this expla
- **Operator**: sort of a delegated owner. The operator does not own the NFT but can do the same actions an owner can do.
- **Custodian**: creator of the NFT collection/canister. They can do anything (transfer, add/remove operators, burn, and even un-burn) to NFTs, but also mint new ones or change the symbol or description of the collection.

The NFT example canister keeps access control in these three levels very simple:
The NFT example canister keeps access control in these three levels very simple:
- For every level of control, a separate list (or set) of principals is kept.
- Those three levels are then manually checked every single time someone attempts to do something for which they require authorization.
- If a user is not authorized to call a certain function an error is returned.
Expand All @@ -88,7 +88,7 @@ Using this management canister address, we can construct its principal and set t

## NFT sample code tutorial

### Prerequisites
### Prerequisites

- [x] Install the [IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/install/index.mdx).
- [x] Download and install [git.](https://git-scm.com/downloads)
Expand All @@ -108,7 +108,7 @@ cd examples/motoko/dip721-nft-container
### Step 3: Run a local instance of the Internet Computer:

```bash
dfx start --background
dfx start --background
```

**If this is not a new installation, you may need to run `start` with the `--clean` flag.**
Expand All @@ -123,7 +123,7 @@ This command deploys the DIP721 NFT canister with the following initialization a

```bash
dfx deploy --argument "(
principal\"$(dfx identity get-principal)\",
principal\"$(dfx identity get-principal)\",
record {
logo = record {
logo_type = \"image/png\";
Expand All @@ -137,15 +137,15 @@ dfx deploy --argument "(
```

#### What this does
- `principal`: the initial custodian of the collection. A custodian is a user who can administrate the collection i.e. an "Admin" user.
- `principal`: the initial custodian of the collection. A custodian is a user who can administrate the collection i.e. an "Admin" user.

:::info
`"$(dfx identity get-principal)"` automatically interpolates the default identity used by dfx on your machine into the argument that gets passed to `deploy`.
:::

- `logo`: The image that represents this NFT collection.
- `name`: The name of the NFT collection.
- `symbol`: A short, unique symbol to identify the token.
- `symbol`: A short, unique symbol to identify the token.
- `maxLimit`: The maximum number of NFTs that are allowed in this collection.

You will receive output that resembles the following:
Expand All @@ -164,8 +164,8 @@ Use the following command to mint an NFT:
```bash
dfx canister call dip721_nft_container mintDip721 \
"(
principal\"$(dfx identity get-principal)\",
vec {
principal\"$(dfx identity get-principal)\",
vec {
record {
purpose = variant{Rendered};
data = blob\"hello\";
Expand Down Expand Up @@ -208,7 +208,7 @@ You should see a principal returned:
o4f3h-cbpnm-4hnl7-pejut-c4vii-a5u5u-bk2va-e72lb-edvgw-z4wuq-5qe
```
Transfer the NFT from the default user to `ALICE`.
Transfer the NFT from the default user to `ALICE`.
Here the arguments are:
`from`: principal that owns the NFT
Expand Down Expand Up @@ -255,7 +255,7 @@ Output:
### `getMetadataDip721`
Provide a token ID.
Provide a token ID.
The token ID was provided to you when you ran `mintDip721`, e.g. `(variant { Ok = record { id = 1 : nat; token_id = 0 : nat64 } })` So, the token ID is 0 in this case.
```bash
Expand Down Expand Up @@ -410,7 +410,7 @@ Output:
### `ownerOfDip721`
Provide a token ID.
Provide a token ID.
The token ID was provided to you when you ran `mintDip721`, e.g. `(variant { Ok = record { id = 1 : nat; token_id = 0 : nat64 } })` So, the token ID is 0 in this case.
```bash
Expand Down
40 changes: 20 additions & 20 deletions motoko/encrypted-notes-dapp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ This is an **example dapp** that demonstrates the potential of building **canist

- The frontend re-uses the generated public and private key pair for every identity in the same browser. In a better implementation, this key pair should be unique per principal.
- The public/private key pair should not be managed by the web browser at all. [WebAuthn](https://en.wikipedia.org/wiki/WebAuthn) should be used to push the key management to the operating system.
- Integer overflows are possible in the Rust canister, e.g., for `NEXT_NOTE`.
- Integer overflows are possible in the Rust canister, e.g., for `NEXT_NOTE`.
- Users may lose their notes if they accidentally clean the browser data (localStorage) while no other device is synced to the dapp.
- Lack of key update: Given that the key used to encrypt the notes is never refreshed, the privacy of the data is no longer guaranteed if an attacker learns this key (for instance, by corrupting the local storage in one of the connected devices).

Expand All @@ -37,11 +37,11 @@ This is an **example dapp** that demonstrates the potential of building **canist

You can play around with the [dapp deployed on ICP](https://cvhrw-2yaaa-aaaaj-aaiqa-cai.icp0.io/) and see a quick introduction on [YouTube](https://youtu.be/DZQmtPSxvbs).

We wanted to build an example of a simple (but not too simple) dapp running purely on the IC. This example relies upon the **web-serving** and **storage capabilities** of the IC. We focused on the following two key features for our example dapp:
1. Client-side **end-to-end encryption**.
We wanted to build an example of a simple (but not too simple) dapp running purely on the IC. This example relies upon the **web-serving** and **storage capabilities** of the IC. We focused on the following two key features for our example dapp:
1. Client-side **end-to-end encryption**.
2. **Multi-user** and **multi-device** support.

To demonstrate the potential of the IC as a platform for developing such dapps, we implemented this example using two distinct canister development kits (CDKs). The Motoko CDK allows developers to implement actor-based dapps using the [Motoko](https://internetcomputer.org/docs/current/motoko/getting-started/motoko-introduction) language. The Rust CDK allows implementing dapps in [Rust](https://internetcomputer.org/docs/current/developer-docs/backend/rust/index). In both cases, canisters are compiled into WebAssembly files that are then deployed onto the IC.
To demonstrate the potential of the IC as a platform for developing such dapps, we implemented this example using two distinct canister development kits (CDKs). The Motoko CDK allows developers to implement actor-based dapps using the [Motoko](https://internetcomputer.org/docs/current/motoko/getting-started/motoko-introduction) language. The Rust CDK allows implementing dapps in [Rust](https://internetcomputer.org/docs/current/developer-docs/backend/rust/). In both cases, canisters are compiled into WebAssembly files that are then deployed onto the IC.

## Architecture

Expand Down Expand Up @@ -110,7 +110,7 @@ Follow the steps below to deploy this sample project.

## Prerequisites
- [x] Install the [IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/install/index).
- [x] Download and install [Docker](https://docs.docker.com/get-docker/) if using the Docker option.
- [x] Download and install [Docker](https://docs.docker.com/get-docker/) if using the Docker option.
- [x] Download the GitHub repo containing this project's files: `git clone https://github.com/dfinity/examples`

### Step 1. Navigate inside of the project's folder:
Expand All @@ -131,20 +131,20 @@ export BUILD_ENV=motoko


**Building the Rust canister requires either the Rust toolchain installed on your system or Docker-backed deployment (see below).**
### Step 3: Deploy locally.

### Step 3: Deploy locally.

### Option 1: Docker deployment
**This option does not yet work on Apple M1; the combination of DFX and Docker do not currently support the required architecture.**

- #### Step 1: Install and start Docker by following the instructions.
- #### Step 2: For Motoko build/deployment set environmental variable:

```bash
export BUILD_ENV=motoko
```

- #### Step 3: Run the following Bash script that builds a Docker image, compiles the canister, and deploys this dapp (all inside the Docker instance).
- #### Step 3: Run the following Bash script that builds a Docker image, compiles the canister, and deploys this dapp (all inside the Docker instance).

Execution can take a few minutes:

Expand Down Expand Up @@ -247,11 +247,11 @@ npm run dev


:::caution
If you have opened this page previously, please remove all local store data for this page from your web browser, and hard-reload the page.
If you have opened this page previously, please remove all local store data for this page from your web browser, and hard-reload the page.

For example in Chrome, go to Inspect → Application → Local Storage → http://localhost:3000/ → Clear All, and then reload.
:::


### Mainnet deployment

Expand Down Expand Up @@ -286,11 +286,11 @@ dfx canister --network ic install www --mode=upgrade

## Security considerations and best practices

If you base your application on this example, we recommend you familiarize yourself with and adhere to the [security best practices](https://internetcomputer.org/docs/current/references/security/) for developing on the Internet Computer. This example may not implement all the best practices, see also the [disclaimer](#disclaimer-please-read-carefully) above.
If you base your application on this example, we recommend you familiarize yourself with and adhere to the [security best practices](https://internetcomputer.org/docs/current/references/security/) for developing on the Internet Computer. This example may not implement all the best practices, see also the [disclaimer](#disclaimer-please-read-carefully) above.

For example, the following aspects are particularly relevant for this app:
For example, the following aspects are particularly relevant for this app:
* [Make sure any action that only a specific user should be able to do requires authentication](https://internetcomputer.org/docs/current/developer-docs/security/security-best-practices/overview), since a user should only be able to manage their own notes.
* [Protect key material against XSS using Web Crypto API](https://internetcomputer.org/docs/current/references/security/web-app-development-security-best-practices#crypto-protect-key-material-against-xss-using-web-crypto-api), since this app stores private keys in the browser.
* [Protect key material against XSS using Web Crypto API](https://internetcomputer.org/docs/current/references/security/web-app-development-security-best-practices#crypto-protect-key-material-against-xss-using-web-crypto-api), since this app stores private keys in the browser.
* [Use secure cryptographic schemes](https://internetcomputer.org/docs/current/references/security/general-security-best-practices#use-secure-cryptographic-schemes), since notes are being encrypted.

## User interaction with "Encrypted Notes" dapp
Expand Down Expand Up @@ -320,9 +320,9 @@ Fig. 2. Basic single-device scenario for a user.

- #### Step 3: Once logged in for the first time, your notes list should be empty.

At this moment, your _Local Storage_ should be populated with additional variables (see Fig. 2(d)): **ic-identity**, **ic-delegation**.
At this moment, your _Local Storage_ should be populated with additional variables (see Fig. 2(d)): **ic-identity**, **ic-delegation**.

These variables are used for storing/retrieving notes from the backend canister.
These variables are used for storing/retrieving notes from the backend canister.

In addition, another two variables are generated in the _IndexedDB_: **PrivateKey**, **PublicKey**. These two variables are used for encrypting/decrypting the shared secret key.

Expand All @@ -341,7 +341,7 @@ Fig. 3. Scenario for a user with multiple registered devices.

- #### Step 1: Perform steps 1-3 of Scenario I on Device A.

- #### Step 2:. Perform steps 1-3 of Scenario I on Device B.
- #### Step 2:. Perform steps 1-3 of Scenario I on Device B.

One subtle difference that you might observe on Device B is that the message "Synchronizing..." (Fig. 3(a)) appears for a short time. As Device A was the first to log in, it was also the first one to generate a shared secret. Device B has to retrieve it. To do that, Device B first uploads its public key (pub B) to the backend canister. Device A retrieves pub B using periodic polling. Device A then re-encrypts the shared secret with pub B and uploads it to the backend. Afterward, Device B can retrieve the encrypted shared secret and decrypt it with its private key.

Expand Down Expand Up @@ -380,7 +380,7 @@ Fig. 4. Scenario for a user adding/removing devices.

## Unit testing

The unit tests are implemented in `src/encrypted_notes_motoko/test/test.mo` using the [Motoko Matchers](https://kritzcreek.github.io/motoko-matchers/) library.
The unit tests are implemented in `src/encrypted_notes_motoko/test/test.mo` using the [Motoko Matchers](https://kritzcreek.github.io/motoko-matchers/) library.

The easiest way to run all tests involves the following steps:

Expand Down Expand Up @@ -483,7 +483,7 @@ frontend www canister (an "asset" canister) is the way we describe a set of file
`dependencies`: an array of whatever canisters are being used to serve your app, to ensure that `dfx` builds and deploys them before your app.
`frontend: { entrypoint: ""}`: This set of keys tells `dfx` to build it as a frontend canister, and entrypoint is wherever your app entrypoint winds up residing at the end of an npm build
`source`: where the rest of your app resides at the end of npm build
`type`: "assets" for an assets or static canister.
`type`: "assets" for an assets or static canister.

**Binary targets**:
You can also just deploy arbitrary binary targets as long as they're wasm binaries. For that, use the keys:
Expand All @@ -508,7 +508,7 @@ This dapp uses the web browser's `_Local Storage_` and `_IndexedDB_` for storing

:::

A symmetric key for encrypting/decrypting the notes is stored in RAM (this key is shared between multiple devices). For a better understanding of the mechanics of the dapp, please see the `_Local Storage_`/`_IndexedDB_` windows in your web browser.
A symmetric key for encrypting/decrypting the notes is stored in RAM (this key is shared between multiple devices). For a better understanding of the mechanics of the dapp, please see the `_Local Storage_`/`_IndexedDB_` windows in your web browser.

In Chrome, go to: _Developer Tools→Application→Local Storage_/_IndexedDB_.

Expand Down
30 changes: 20 additions & 10 deletions motoko/encrypted-notes-dapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ export { idlFactory } from "./minimal_dapp.did.js";
* beginning in dfx 0.15.0
*/
export const canisterId =
process.env.CANISTER_ID_MINIMAL_DAPP ||
process.env.MINIMAL_DAPP_CANISTER_ID;
process.env.CANISTER_ID_MINIMAL_DAPP;

export const createActor = (canisterId, options = {}) => {
const agent = options.agent || new HttpAgent({ ...options.agentOptions });
Expand Down Expand Up @@ -40,4 +39,4 @@ export const createActor = (canisterId, options = {}) => {
});
};

export const minimal_dapp = createActor(canisterId);
export const minimal_dapp = canisterId ? createActor(canisterId) : undefined;
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import type { Principal } from '@dfinity/principal';
import type { ActorMethod } from '@dfinity/agent';
import type { IDL } from '@dfinity/candid';

export interface _SERVICE {
'count' : ActorMethod<[], bigint>,
'getCount' : ActorMethod<[], bigint>,
'reset' : ActorMethod<[], bigint>,
}
export declare const idlFactory: IDL.InterfaceFactory;
export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[];
Loading

0 comments on commit c6e640d

Please sign in to comment.