diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3146bd73a..1499a56fc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -92,7 +92,6 @@ /rust/x509/ @dfinity/consensus /svelte/svelte-motoko-starter/ @dfinity/sdk -/svelte/svelte-starter/ @dfinity/sdk /svelte/sveltekit-starter/ @dfinity/sdk /wasm/counter @dfinity/languages diff --git a/.github/workflows/hosting-photo-storage-example.yml b/.github/workflows/hosting-photo-storage-example.yml index 8c15a6701..f484a88a8 100644 --- a/.github/workflows/hosting-photo-storage-example.yml +++ b/.github/workflows/hosting-photo-storage-example.yml @@ -20,15 +20,17 @@ jobs: - uses: actions/checkout@v1 - name: Provision Darwin run: bash .github/workflows/provision-darwin.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh - name: Hosting Photo Storage Darwin run: | pushd hosting/photo-storage - # verify frontend deps install and build npm install npm run build - # verify that frontend asset canister deploys - dfx start --background - dfx deploy + icp network start -d + icp deploy popd hosting-photo-storage-linux: runs-on: ubuntu-22.04 @@ -36,13 +38,15 @@ jobs: - uses: actions/checkout@v1 - name: Provision Linux run: bash .github/workflows/provision-linux.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh - name: Hosting Photo Storage Linux run: | pushd hosting/photo-storage - # verify frontend deps install and build npm install npm run build - # verify that frontend asset canister deploys - dfx start --background - dfx deploy + icp network start -d + icp deploy popd diff --git a/.github/workflows/hosting-static-website-example.yaml b/.github/workflows/hosting-static-website-example.yaml index dbe965b8f..44ea5890a 100644 --- a/.github/workflows/hosting-static-website-example.yaml +++ b/.github/workflows/hosting-static-website-example.yaml @@ -14,17 +14,21 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: - hosting-unity-static-website-darwin: + hosting-static-website-darwin: runs-on: macos-15 steps: - uses: actions/checkout@v1 - name: Provision Darwin run: bash .github/workflows/provision-darwin.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh - name: Hosting Static Website Darwin run: | - dfx start --background pushd hosting/static-website - dfx deploy + icp network start -d + icp deploy popd hosting-static-website-linux: runs-on: ubuntu-22.04 @@ -32,9 +36,13 @@ jobs: - uses: actions/checkout@v1 - name: Provision Linux run: bash .github/workflows/provision-linux.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh - name: Hosting Static Website Linux run: | - dfx start --background pushd hosting/static-website - dfx deploy + icp network start -d + icp deploy popd diff --git a/.github/workflows/hosting-unity-webgl-example.yaml b/.github/workflows/hosting-unity-webgl-example.yaml index 8fc4fb645..e3359169f 100644 --- a/.github/workflows/hosting-unity-webgl-example.yaml +++ b/.github/workflows/hosting-unity-webgl-example.yaml @@ -5,7 +5,7 @@ on: - master pull_request: paths: - - motoko/unity-webgl-template/** + - hosting/unity-webgl-template/** - .github/workflows/provision-darwin.sh - .github/workflows/provision-linux.sh - .github/workflows/hosting-unity-webgl-example.yaml @@ -20,11 +20,15 @@ jobs: - uses: actions/checkout@v1 - name: Provision Darwin run: bash .github/workflows/provision-darwin.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh - name: Hosting Unity Webgl Darwin run: | - dfx start --background pushd hosting/unity-webgl-template - dfx deploy + icp network start -d + icp deploy popd hosting-unity-webgl-linux: runs-on: ubuntu-22.04 @@ -32,9 +36,13 @@ jobs: - uses: actions/checkout@v1 - name: Provision Linux run: bash .github/workflows/provision-linux.sh + - name: Pre-download network launcher + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/workflows/pre-download-launcher.sh - name: Hosting Unity Webgl Linux run: | - dfx start --background pushd hosting/unity-webgl-template - dfx deploy + icp network start -d + icp deploy popd diff --git a/.github/workflows/pre-download-launcher.sh b/.github/workflows/pre-download-launcher.sh new file mode 100644 index 000000000..d01958c36 --- /dev/null +++ b/.github/workflows/pre-download-launcher.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Pre-download the icp-cli network launcher to avoid GitHub API rate limits. +# icp-cli v0.1.0 doesn't support ICP_CLI_GITHUB_TOKEN yet, so `icp network start` +# hits the unauthenticated GitHub API rate limit (60 req/hr) when fetching the +# latest launcher version. This script uses the authenticated `gh` CLI to get +# the version, downloads the binary directly, and sets ICP_CLI_NETWORK_LAUNCHER_PATH +# so icp-cli skips the API call entirely. +# +# Requires: GH_TOKEN env var (for authenticated GitHub API access via gh CLI) +# +# This workaround can be removed once icp-cli supports ICP_CLI_GITHUB_TOKEN. +set -ex + +VERSION=$(gh release view --repo dfinity/icp-cli-network-launcher --json tagName -q .tagName) + +ARCH=$(uname -m) +case "$ARCH" in + arm64|aarch64) ARCH="arm64" ;; + x86_64) ARCH="x86_64" ;; + *) echo "Unsupported architecture: $ARCH"; exit 1 ;; +esac + +OS=$(uname -s) +case "$OS" in + Darwin) OS="darwin" ;; + Linux) OS="linux" ;; + *) echo "Unsupported OS: $OS"; exit 1 ;; +esac + +TARBALL="icp-cli-network-launcher-${ARCH}-${OS}-${VERSION}" +URL="https://github.com/dfinity/icp-cli-network-launcher/releases/download/${VERSION}/${TARBALL}.tar.gz" + +LAUNCHER_DIR="$HOME/.icp-cli-launcher" +mkdir -p "$LAUNCHER_DIR" +curl -sL "$URL" | tar xz -C "$LAUNCHER_DIR" + +LAUNCHER_PATH="${LAUNCHER_DIR}/${TARBALL}/icp-cli-network-launcher" +chmod +x "$LAUNCHER_PATH" + +echo "ICP_CLI_NETWORK_LAUNCHER_PATH=${LAUNCHER_PATH}" >> "$GITHUB_ENV" +echo "Network launcher ${VERSION} downloaded to ${LAUNCHER_PATH}" diff --git a/.github/workflows/provision-darwin.sh b/.github/workflows/provision-darwin.sh index e4c9b2a4c..dc6f9448e 100755 --- a/.github/workflows/provision-darwin.sh +++ b/.github/workflows/provision-darwin.sh @@ -16,6 +16,12 @@ curl --location --output node.pkg "https://nodejs.org/dist/v$version/node-v$vers sudo installer -pkg node.pkg -store -target / rm node.pkg +# Install icp-cli +npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm + +# Install ic-mops (for Motoko projects) +npm install -g ic-mops + # Install DFINITY SDK. curl --location --output install-dfx.sh "https://raw.githubusercontent.com/dfinity/sdk/master/public/install-dfxvm.sh" DFX_VERSION=${DFX_VERSION:=0.30.2} DFXVM_INIT_YES=true bash install-dfx.sh diff --git a/.github/workflows/provision-linux.sh b/.github/workflows/provision-linux.sh index 8cc46d385..ab1331263 100755 --- a/.github/workflows/provision-linux.sh +++ b/.github/workflows/provision-linux.sh @@ -11,6 +11,12 @@ sudo bash nodesource_setup.sh sudo apt-get install --yes nodejs rm nodesource_setup.sh +# Install icp-cli +npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm + +# Install ic-mops (for Motoko projects) +npm install -g ic-mops + # Install DFINITY SDK. wget --output-document install-dfx.sh "https://raw.githubusercontent.com/dfinity/sdk/master/public/install-dfxvm.sh" DFX_VERSION=${DFX_VERSION:=0.30.2} DFXVM_INIT_YES=true bash install-dfx.sh diff --git a/.gitignore b/.gitignore index c20f9c04c..8f2c5e5f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ .dfx/ +**/.icp/cache/ build/ node_modules/ +package-lock.json dist/ .DS_Store _MACOSX diff --git a/.gitmodules b/.gitmodules index 72826dc66..76a5288c6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,9 +2,6 @@ path = archive/c/qr/QR-Code-generator url = https://github.com/nayuki/QR-Code-generator branch = fd6917601d0a77b6b6df81599118212d8cdb9a27 -[submodule "svelte/svelte-starter/internet-identity"] - path = svelte/svelte-starter/internet-identity - url = https://github.com/dfinity/internet-identity.git [submodule "svelte/svelte-motoko-starter/internet-identity"] path = svelte/svelte-motoko-starter/internet-identity url = https://github.com/dfinity/internet-identity.git diff --git a/hosting/godot-html5-template/README.md b/hosting/godot-html5-template/README.md index 527db0047..7b81d76ca 100644 --- a/hosting/godot-html5-template/README.md +++ b/hosting/godot-html5-template/README.md @@ -1,27 +1,22 @@ ---- -keywords: [html5, html, godot, hosting, host a website, beginner] ---- - # Godot HTML5 sample [View this sample's code on GitHub](https://github.com/dfinity/examples/tree/master/hosting/godot-html5-template) ## Overview -The example shows how to deploy a Godot HTML5 build on the IC in an asset canister. The Godot HTML5 build is deployed as frontend, no backend is needed in this sample. -This example project can be cloned, installed, and deployed locally, for learning and testing purposes. The instructions are based on running the example on either macOS or Linux, but when using WSL2 on Windows, the instructions will be the same. +The example shows how to deploy a Godot HTML5 build on ICP in an asset canister. The Godot HTML5 build is deployed as frontend, no backend is needed in this sample. -## Prerequisites +## Project structure -This example requires an installation of: +The `/frontend` folder contains the pre-built Godot HTML5 export. The frontend is deployed as an asset canister. -- [x] Install the [IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/install/). +## Prerequisites -- [x] Download and install [git](https://git-scm.com/downloads). +- [x] Install [icp-cli](https://cli.icp.build): `npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm` ## Install -Clone the example dapp project: +Clone the example project: ```bash git clone https://github.com/dfinity/examples @@ -29,19 +24,27 @@ cd examples/hosting/godot-html5-template ``` ## Deployment -The local replica is started by running this command: + +Start the local network: ```bash -dfx start --background +icp network start -d ``` -When the local replica is up and running, run this command to deploy the canisters: +Deploy the canisters: ```bash -dfx deploy +icp deploy +``` + +The URL for the frontend depends on the canister ID. When deployed, the URL will look like this: + +``` +http://{canister_id}.localhost:8000 ``` -If you get error code 500 after deploying to the IC mainnet, try to use `raw` keyword in the URL like this: `https://.raw.ic0.app`. +Stop the local network when done: -## License -This project is licensed under the Apache 2.0 license, see `LICENSE.md` for details. See `CONTRIBUTE.md` for details about how to contribute to this project. +```bash +icp network stop +``` diff --git a/hosting/godot-html5-template/dfx.json b/hosting/godot-html5-template/dfx.json deleted file mode 100644 index 9d0771583..000000000 --- a/hosting/godot-html5-template/dfx.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "canisters": { - "godot_html5_assets": { - "frontend": { - "entrypoint": "src/godot_html5_assets/src/index.html" - }, - "source": [ - "src/godot_html5_assets/assets", - "src/godot_html5_assets/src" - ], - "type": "assets" - } - }, - "version": 1 -} \ No newline at end of file diff --git a/hosting/godot-html5-template/icp.yaml b/hosting/godot-html5-template/icp.yaml new file mode 100644 index 000000000..3f825be06 --- /dev/null +++ b/hosting/godot-html5-template/icp.yaml @@ -0,0 +1,10 @@ +canisters: + - name: godot_html5_assets + recipe: + type: "@dfinity/asset-canister@v2.1.0" + configuration: + dir: dist + build: + - mkdir -p dist + - cp -r src/godot_html5_assets/assets/* dist/ + - cp -r src/godot_html5_assets/src/* dist/ diff --git a/hosting/my_crypto_blog/BUILD.md b/hosting/my_crypto_blog/BUILD.md index 24cfcb754..0a260e8e7 100644 --- a/hosting/my_crypto_blog/BUILD.md +++ b/hosting/my_crypto_blog/BUILD.md @@ -1,112 +1,27 @@ # Continue building locally -Projects deployed through ICP Ninja are temporary; they will only be live for 20 minutes before they are removed. The command-line tool `dfx` can be used to continue building your ICP Ninja project locally and deploy it to the mainnet. +Projects deployed through ICP Ninja are temporary; they will only be live for 30 minutes before they are removed. To continue building locally, follow these steps. -To migrate your ICP Ninja project off of the web browser and develop it locally, follow these steps. +### 1. Install developer tools -### 1. Install developer tools. +Install [icp-cli](https://cli.icp.build) and [Node.js](https://nodejs.org/en/download/): -You can install the developer tools natively or use Dev Containers. - -#### Option 1: Natively install developer tools - -> Installing `dfx` natively is currently only supported on macOS and Linux systems. On Windows, it is recommended to use the Dev Containers option. - -1. Install `dfx` with the following command: - -``` - -sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)" - -``` - -> On Apple Silicon (e.g., Apple M1 chip), make sure you have Rosetta installed (`softwareupdate --install-rosetta`). - -2. [Install NodeJS](https://nodejs.org/en/download/package-manager). - -3. For Rust projects, you will also need to: - -- Install [Rust](https://doc.rust-lang.org/cargo/getting-started/installation.html#install-rust-and-cargo): `curl https://sh.rustup.rs -sSf | sh` - -- Install [candid-extractor](https://crates.io/crates/candid-extractor): `cargo install candid-extractor` - -4. For Motoko projects, you will also need to: - -- Install the Motoko package manager [Mops](https://docs.mops.one/quick-start#2-install-mops-cli): `npm i -g ic-mops` - -Lastly, navigate into your project's directory that you downloaded from ICP Ninja. - -#### Option 2: Dev Containers - -Continue building your projects locally by installing the [Dev Container extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) for VS Code and [Docker](https://docs.docker.com/engine/install/). - -Make sure Docker is running, then navigate into your project's directory that you downloaded from ICP Ninja and start the Dev Container by selecting `Dev-Containers: Reopen in Container` in VS Code's command palette (F1 or Ctrl/Cmd+Shift+P). - -> Note that local development ports (e.g. the ports used by `dfx` or `vite`) are forwarded from the Dev Container to your local machine. In the VS code terminal, use Ctrl/Cmd+Click on the displayed local URLs to open them in your browser. To view the current port mappings, click the "Ports" tab in the VS Code terminal window. - -### 2. Start the local development environment. - -``` -dfx start --background +```bash +npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm ``` -### 3. Create a local developer identity. +Then navigate into your project's directory that you downloaded from ICP Ninja. -To manage your project's canisters, it is recommended that you create a local [developer identity](https://internetcomputer.org/docs/building-apps/getting-started/identities) rather than use the `dfx` default identity that is not stored securely. +### 2. Deploy locally -To create a new identity, run the commands: +Start the local network and deploy the project: +```bash +icp network start -d +icp deploy ``` -dfx identity new IDENTITY_NAME - -dfx identity use IDENTITY_NAME - -``` - -Replace `IDENTITY_NAME` with your preferred identity name. The first command `dfx start --background` starts the local `dfx` processes, then `dfx identity new` will create a new identity and return your identity's seed phase. Be sure to save this in a safe, secure location. - -The third command `dfx identity use` will tell `dfx` to use your new identity as the active identity. Any canister smart contracts created after running `dfx identity use` will be owned and controlled by the active identity. - -Your identity will have a principal ID associated with it. Principal IDs are used to identify different entities on ICP, such as users and canisters. - -[Learn more about ICP developer identities](https://internetcomputer.org/docs/building-apps/getting-started/identities). - -### 4. Deploy the project locally. - -Deploy your project to your local developer environment with: - -``` -npm install -dfx deploy - -``` - -Your project will be hosted on your local machine. The local canister URLs for your project will be shown in the terminal window as output of the `dfx deploy` command. You can open these URLs in your web browser to view the local instance of your project. - -### 5. Obtain cycles. - -To deploy your project to the mainnet for long-term public accessibility, first you will need [cycles](https://internetcomputer.org/docs/building-apps/getting-started/tokens-and-cycles). Cycles are used to pay for the resources your project uses on the mainnet, such as storage and compute. - -> This cost model is known as ICP's [reverse gas model](https://internetcomputer.org/docs/building-apps/essentials/gas-cost), where developers pay for their project's gas fees rather than users pay for their own gas fees. This model provides an enhanced end user experience since they do not need to hold tokens or sign transactions when using a dapp deployed on ICP. - -> Learn how much a project may cost by using the [pricing calculator](https://internetcomputer.org/docs/building-apps/essentials/cost-estimations-and-examples). - -Cycles can be obtained through [converting ICP tokens into cycles using `dfx`](https://internetcomputer.org/docs/building-apps/developer-tools/dfx/dfx-cycles#dfx-cycles-convert). - -### 6. Deploy to the mainnet. - -Once you have cycles, run the command: - -``` - -dfx deploy --network ic - -``` - -After your project has been deployed to the mainnet, it will continuously require cycles to pay for the resources it uses. You will need to [top up](https://internetcomputer.org/docs/building-apps/canister-management/topping-up) your project's canisters or set up automatic cycles management through a service such as [CycleOps](https://cycleops.dev/). - -> If your project's canisters run out of cycles, they will be removed from the network. +The local canister URL will be shown in the terminal output. Open it in your web browser. ## Additional examples diff --git a/hosting/my_crypto_blog/README.md b/hosting/my_crypto_blog/README.md index d88e5d3c0..f6d174a7d 100644 --- a/hosting/my_crypto_blog/README.md +++ b/hosting/my_crypto_blog/README.md @@ -1,22 +1,63 @@ # My Crypto Blog -This frontend-only asset canister allows you to serve static files without a backend canister. -Asset canisters can be used to serve static frontend files, such as HTML, CSS, and JavaScript files, to users through a web browser. +[View this sample's code on GitHub](https://github.com/dfinity/examples/tree/master/hosting/my_crypto_blog) -## Deploying from ICP Ninja +## Overview -When viewing this project in ICP Ninja, you can deploy it directly to the mainnet for free by clicking "Run" in the upper right corner. Open this project in ICP Ninja: +A simple blog-style web application hosted entirely onchain on ICP. Built with React, Vite, and Tailwind CSS, it demonstrates how to deploy a frontend-only application as an asset canister — no backend needed. -[![](https://icp.ninja/assets/open.svg)](https://icp.ninja/i?g=https://github.com/dfinity/examples/hosting/my_crypto_blog) +The app fetches blog posts from an external API and displays them in a card layout. ## Project structure -The `/frontend` folder contains web assets for the application's user interface. The user interface is written using the React framework. +The `/frontend` folder contains the web assets for the application's user interface, built with React, Vite, and Tailwind CSS. The frontend is deployed as an asset canister — no backend canister is needed. + +## Deploying from ICP Ninja + +This example can be deployed directly from [ICP Ninja](https://icp.ninja), a browser-based IDE for ICP. To continue developing locally after deploying from ICP Ninja, see [BUILD.md](BUILD.md). + +[![Open in ICP Ninja](https://icp.ninja/assets/open.svg)](https://icp.ninja/i?g=https://github.com/dfinity/examples/hosting/my_crypto_blog) + +> **Note:** ICP Ninja currently uses `dfx` under the hood, which is why this example includes a `dfx.json` configuration file. `dfx` is the legacy CLI, being superseded by [icp-cli](https://cli.icp.build), which is what developers should use for local development. + +## Build and deploy from the command line + +### Prerequisites + +- [x] Install [Node.js](https://nodejs.org/en/download/) +- [x] Install [icp-cli](https://cli.icp.build): `npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm` + +### Install + +Clone the example project: + +```bash +git clone https://github.com/dfinity/examples +cd examples/hosting/my_crypto_blog +``` + +### Deployment + +Start the local network: + +```bash +icp network start -d +``` + +Deploy the canister: + +```bash +icp deploy +``` -## Build and deploy from the command-line +The URL for the frontend depends on the canister ID. When deployed, the URL will look like this: -To migrate your ICP Ninja project off of the web browser and develop it locally, follow these steps. These steps are necessary if you want to deploy this project for long-term, production use on the mainnet. +``` +http://{canister_id}.localhost:8000 +``` -### 1. Download your project from ICP Ninja using the 'Download files' button on the upper left corner under the pink ninja star icon. +Stop the local network when done: -### 2. Open the `BUILD.md` file for further instructions. +```bash +icp network stop +``` diff --git a/hosting/my_crypto_blog/frontend/package.json b/hosting/my_crypto_blog/frontend/package.json index aca87be1b..14c52d283 100644 --- a/hosting/my_crypto_blog/frontend/package.json +++ b/hosting/my_crypto_blog/frontend/package.json @@ -8,20 +8,16 @@ "dev": "vite" }, "dependencies": { - "@dfinity/agent": "2.4.1", - "@dfinity/auth-client": "2.4.1", - "@dfinity/candid": "2.4.1", - "@dfinity/principal": "2.4.1", - "react": "18.3.1", - "react-dom": "18.3.1" + "react": "~19.2.4", + "react-dom": "~19.2.4" }, "devDependencies": { - "@types/react": "18.3.12", - "@types/react-dom": "18.3.1", - "@vitejs/plugin-react": "4.3.3", - "autoprefixer": "^10.4.20", - "postcss": "8.4.48", - "tailwindcss": "3.4.14", - "vite": "5.4.11" + "@types/react": "~19.2.14", + "@types/react-dom": "~19.2.3", + "@vitejs/plugin-react": "~5.1.4", + "autoprefixer": "~10.4.24", + "postcss": "~8.5.6", + "tailwindcss": "~3.4.19", + "vite": "~7.3.1" } } diff --git a/hosting/my_crypto_blog/icp.yaml b/hosting/my_crypto_blog/icp.yaml new file mode 100644 index 000000000..29e5edb5f --- /dev/null +++ b/hosting/my_crypto_blog/icp.yaml @@ -0,0 +1,8 @@ +canisters: + - name: frontend + recipe: + type: "@dfinity/asset-canister@v2.1.0" + configuration: + dir: frontend/dist + build: + - npm run build --prefix frontend diff --git a/hosting/oisy-signer-demo/BUILD.md b/hosting/oisy-signer-demo/BUILD.md index 24cfcb754..0a260e8e7 100644 --- a/hosting/oisy-signer-demo/BUILD.md +++ b/hosting/oisy-signer-demo/BUILD.md @@ -1,112 +1,27 @@ # Continue building locally -Projects deployed through ICP Ninja are temporary; they will only be live for 20 minutes before they are removed. The command-line tool `dfx` can be used to continue building your ICP Ninja project locally and deploy it to the mainnet. +Projects deployed through ICP Ninja are temporary; they will only be live for 30 minutes before they are removed. To continue building locally, follow these steps. -To migrate your ICP Ninja project off of the web browser and develop it locally, follow these steps. +### 1. Install developer tools -### 1. Install developer tools. +Install [icp-cli](https://cli.icp.build) and [Node.js](https://nodejs.org/en/download/): -You can install the developer tools natively or use Dev Containers. - -#### Option 1: Natively install developer tools - -> Installing `dfx` natively is currently only supported on macOS and Linux systems. On Windows, it is recommended to use the Dev Containers option. - -1. Install `dfx` with the following command: - -``` - -sh -ci "$(curl -fsSL https://internetcomputer.org/install.sh)" - -``` - -> On Apple Silicon (e.g., Apple M1 chip), make sure you have Rosetta installed (`softwareupdate --install-rosetta`). - -2. [Install NodeJS](https://nodejs.org/en/download/package-manager). - -3. For Rust projects, you will also need to: - -- Install [Rust](https://doc.rust-lang.org/cargo/getting-started/installation.html#install-rust-and-cargo): `curl https://sh.rustup.rs -sSf | sh` - -- Install [candid-extractor](https://crates.io/crates/candid-extractor): `cargo install candid-extractor` - -4. For Motoko projects, you will also need to: - -- Install the Motoko package manager [Mops](https://docs.mops.one/quick-start#2-install-mops-cli): `npm i -g ic-mops` - -Lastly, navigate into your project's directory that you downloaded from ICP Ninja. - -#### Option 2: Dev Containers - -Continue building your projects locally by installing the [Dev Container extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) for VS Code and [Docker](https://docs.docker.com/engine/install/). - -Make sure Docker is running, then navigate into your project's directory that you downloaded from ICP Ninja and start the Dev Container by selecting `Dev-Containers: Reopen in Container` in VS Code's command palette (F1 or Ctrl/Cmd+Shift+P). - -> Note that local development ports (e.g. the ports used by `dfx` or `vite`) are forwarded from the Dev Container to your local machine. In the VS code terminal, use Ctrl/Cmd+Click on the displayed local URLs to open them in your browser. To view the current port mappings, click the "Ports" tab in the VS Code terminal window. - -### 2. Start the local development environment. - -``` -dfx start --background +```bash +npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm ``` -### 3. Create a local developer identity. +Then navigate into your project's directory that you downloaded from ICP Ninja. -To manage your project's canisters, it is recommended that you create a local [developer identity](https://internetcomputer.org/docs/building-apps/getting-started/identities) rather than use the `dfx` default identity that is not stored securely. +### 2. Deploy locally -To create a new identity, run the commands: +Start the local network and deploy the project: +```bash +icp network start -d +icp deploy ``` -dfx identity new IDENTITY_NAME - -dfx identity use IDENTITY_NAME - -``` - -Replace `IDENTITY_NAME` with your preferred identity name. The first command `dfx start --background` starts the local `dfx` processes, then `dfx identity new` will create a new identity and return your identity's seed phase. Be sure to save this in a safe, secure location. - -The third command `dfx identity use` will tell `dfx` to use your new identity as the active identity. Any canister smart contracts created after running `dfx identity use` will be owned and controlled by the active identity. - -Your identity will have a principal ID associated with it. Principal IDs are used to identify different entities on ICP, such as users and canisters. - -[Learn more about ICP developer identities](https://internetcomputer.org/docs/building-apps/getting-started/identities). - -### 4. Deploy the project locally. - -Deploy your project to your local developer environment with: - -``` -npm install -dfx deploy - -``` - -Your project will be hosted on your local machine. The local canister URLs for your project will be shown in the terminal window as output of the `dfx deploy` command. You can open these URLs in your web browser to view the local instance of your project. - -### 5. Obtain cycles. - -To deploy your project to the mainnet for long-term public accessibility, first you will need [cycles](https://internetcomputer.org/docs/building-apps/getting-started/tokens-and-cycles). Cycles are used to pay for the resources your project uses on the mainnet, such as storage and compute. - -> This cost model is known as ICP's [reverse gas model](https://internetcomputer.org/docs/building-apps/essentials/gas-cost), where developers pay for their project's gas fees rather than users pay for their own gas fees. This model provides an enhanced end user experience since they do not need to hold tokens or sign transactions when using a dapp deployed on ICP. - -> Learn how much a project may cost by using the [pricing calculator](https://internetcomputer.org/docs/building-apps/essentials/cost-estimations-and-examples). - -Cycles can be obtained through [converting ICP tokens into cycles using `dfx`](https://internetcomputer.org/docs/building-apps/developer-tools/dfx/dfx-cycles#dfx-cycles-convert). - -### 6. Deploy to the mainnet. - -Once you have cycles, run the command: - -``` - -dfx deploy --network ic - -``` - -After your project has been deployed to the mainnet, it will continuously require cycles to pay for the resources it uses. You will need to [top up](https://internetcomputer.org/docs/building-apps/canister-management/topping-up) your project's canisters or set up automatic cycles management through a service such as [CycleOps](https://cycleops.dev/). - -> If your project's canisters run out of cycles, they will be removed from the network. +The local canister URL will be shown in the terminal output. Open it in your web browser. ## Additional examples diff --git a/hosting/oisy-signer-demo/README.md b/hosting/oisy-signer-demo/README.md index 73b0b6c43..6283c2a67 100644 --- a/hosting/oisy-signer-demo/README.md +++ b/hosting/oisy-signer-demo/README.md @@ -1,21 +1,63 @@ # OISY Signer Demo -This frontend-only asset canister is a sample application to demonstrate interaction with the OISY Wallet. It connects to the OISY signer, fetches balances for ICP and ckUSDC, and performs self-transfers of 1 token each, using the ICRC-1 standard. +[View this sample's code on GitHub](https://github.com/dfinity/examples/tree/master/hosting/oisy-signer-demo) -## Deploying from ICP Ninja +## Overview -When viewing this project in ICP Ninja, you can deploy it directly to the mainnet for free by clicking "Run" in the upper right corner. Open this project in ICP Ninja: +A sample application demonstrating interaction with the [OISY Wallet](https://oisy.com). It connects to the OISY signer, fetches balances for **TESTICP** and **TICRC1** (testnet tokens), and performs self-transfers of 1 token each using the ICRC-1 standard. No backend canister is needed — the frontend is deployed as an asset canister. -[![](https://icp.ninja/assets/open.svg)](https://icp.ninja/i?g=https://github.com/dfinity/examples/hosting/oisy-signer-demo) +Testnet tokens can be obtained for free using the [ICP Faucet](https://faucet.internetcomputer.org). In OISY, select the **IC (testnet tokens)** network to view them. ## Project structure -The `/frontend` folder contains web assets for the application's user interface. The user interface is written using the React framework. +The `/frontend` folder contains the web assets for the application's user interface, built with React, Vite, and Tailwind CSS. + +## Deploying from ICP Ninja + +This example can be deployed directly from [ICP Ninja](https://icp.ninja), a browser-based IDE for ICP. To continue developing locally after deploying from ICP Ninja, see [BUILD.md](BUILD.md). + +[![Open in ICP Ninja](https://icp.ninja/assets/open.svg)](https://icp.ninja/i?g=https://github.com/dfinity/examples/hosting/oisy-signer-demo) + +> **Note:** ICP Ninja currently uses `dfx` under the hood, which is why this example includes a `dfx.json` configuration file. `dfx` is the legacy CLI, being superseded by [icp-cli](https://cli.icp.build), which is what developers should use for local development. + +## Build and deploy from the command line + +### Prerequisites + +- [x] Install [Node.js](https://nodejs.org/en/download/) +- [x] Install [icp-cli](https://cli.icp.build): `npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm` + +### Install + +Clone the example project: + +```bash +git clone https://github.com/dfinity/examples +cd examples/hosting/oisy-signer-demo +``` + +### Deployment + +Start the local network: + +```bash +icp network start -d +``` + +Deploy the canister: + +```bash +icp deploy +``` -## Build and deploy from the command-line +The URL for the frontend depends on the canister ID. When deployed, the URL will look like this: -To migrate your ICP Ninja project off of the web browser and develop it locally, follow these steps. These steps are necessary if you want to deploy this project for long-term, production use on the mainnet. +``` +http://{canister_id}.localhost:8000 +``` -### 1. Download your project from ICP Ninja using the 'Download files' button on the upper left corner under the pink ninja star icon. +Stop the local network when done: -### 2. Open the `BUILD.md` file for further instructions. +```bash +icp network stop +``` diff --git a/hosting/oisy-signer-demo/frontend/package.json b/hosting/oisy-signer-demo/frontend/package.json index 70d37cc91..1d1bd5f30 100644 --- a/hosting/oisy-signer-demo/frontend/package.json +++ b/hosting/oisy-signer-demo/frontend/package.json @@ -13,36 +13,30 @@ "format:check": "prettier --check ." }, "dependencies": { - "@dfinity/agent": "2.4.1", - "@dfinity/ledger-icp": "4.0.0", - "@dfinity/ledger-icrc": "2.9.1", - "@dfinity/principal": "2.4.1", - "@dfinity/utils": "2.13.2", - "@slide-computer/signer": "3.16.0", - "@slide-computer/signer-agent": "3.16.0", - "@slide-computer/signer-web": "3.16.0", - "bignumber.js": "9.3.1", - "class-variance-authority": "0.7.1", - "lucide-react": "0.536.0", - "react": "19.1.1", - "react-dom": "19.1.1", - "tailwind-variants": "2.1.0" + "@icp-sdk/canisters": "~3.5.0", + "@icp-sdk/core": "~5.0.0", + "@slide-computer/signer": "4.2.2", + "@slide-computer/signer-agent": "4.2.2", + "@slide-computer/signer-web": "4.2.2", + "class-variance-authority": "~0.7.1", + "lucide-react": "~0.575.0", + "react": "~19.2.4", + "react-dom": "~19.2.4" }, "devDependencies": { - "@eslint/js": "9.32.0", - "@vitejs/plugin-react": "5.0.0", - "autoprefixer": "10.4.21", - "eslint": "9.32.0", - "eslint-config-prettier": "10.1.8", - "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "5.2.0", - "eslint-plugin-react-refresh": "0.4.20", - "globals": "16.3.0", - "postcss": "8.5.6", - "prettier": "3.6.2", - "prettier-plugin-tailwindcss": "0.6.14", - "tailwindcss": "3.4.17", - "vite": "7.1.0", - "vite-plugin-node-polyfills": "0.24.0" + "@eslint/js": "~9.32.0", + "@vitejs/plugin-react": "~5.1.4", + "autoprefixer": "~10.4.24", + "eslint": "~9.32.0", + "eslint-config-prettier": "~10.1.8", + "eslint-plugin-react": "~7.37.5", + "eslint-plugin-react-hooks": "~5.2.0", + "eslint-plugin-react-refresh": "~0.4.20", + "globals": "~17.3.0", + "postcss": "~8.5.6", + "prettier": "~3.8.1", + "prettier-plugin-tailwindcss": "~0.7.2", + "tailwindcss": "~3.4.19", + "vite": "~7.3.1" } } diff --git a/hosting/oisy-signer-demo/frontend/src/App.jsx b/hosting/oisy-signer-demo/frontend/src/App.jsx index c4a289a7c..f616b8cb4 100644 --- a/hosting/oisy-signer-demo/frontend/src/App.jsx +++ b/hosting/oisy-signer-demo/frontend/src/App.jsx @@ -4,10 +4,10 @@ import { Button } from '@/components/ui/button'; import { Switch } from '@/components/ui/switch'; import { OisyIcon } from '@/components/ui/oisyIcon'; import ICPLogo from './assets/icp.svg'; -import USDCLogo from './assets/usdc.svg'; +import TICRC1Logo from './assets/ticrc1.svg'; import OISYLogo from './assets/oisy.svg'; import { useOisyWallet } from './hooks/useOisyWallet'; -import { CKUSDC_LEDGER_ID } from './libs/constants'; +import { TESTICP_LEDGER_ID, TICRC1_LEDGER_ID } from './libs/constants'; import { toMainUnit } from './libs/utils'; // Helper functions for button styling and content @@ -25,7 +25,7 @@ const getButtonContent = (isConnected) => { ); } - + return ( <> @@ -42,15 +42,17 @@ export default function App() { principal, accountIdentifier, isLoading, - icpBalance, - ckUsdcBalance, - icpMetadata, - ckUsdcMetadata, - transferIcp, - transferCkUsdc, + testIcpBalance, + tIcrc1Balance, + testIcpMetadata, + tIcrc1Metadata, + transferTestIcp, + transferTIcrc1, } = useOisyWallet(); - const [darkMode, setDarkMode] = useState(false); + const [darkMode, setDarkMode] = useState( + () => window.matchMedia('(prefers-color-scheme: dark)').matches + ); const [error, setError] = useState(null); const [success, setSuccess] = useState(null); @@ -76,20 +78,19 @@ export default function App() { }; const handleTransfer = async (token) => { - const result = token === 'ICP' ? await transferIcp() : await transferCkUsdc(); + const result = token === 'TESTICP' ? await transferTestIcp() : await transferTIcrc1(); if (result.success && result.blockIndex !== undefined) { - const url = - token === 'ICP' - ? `https://dashboard.internetcomputer.org/transaction/${result.blockIndex}` - : `https://dashboard.internetcomputer.org/ethereum/${CKUSDC_LEDGER_ID}/transaction/${result.blockIndex}`; + const ledgerId = token === 'TESTICP' ? TESTICP_LEDGER_ID : TICRC1_LEDGER_ID; + const url = `https://dashboard.internetcomputer.org/tokens/${ledgerId}/transaction/${result.blockIndex}`; setSuccess( {token} transfer successful.{' '} View on Dashboard - + {' '} + (transactions can take up to 10 minutes to appear) ); } else { @@ -99,7 +100,7 @@ export default function App() { return (
{/* Header */} @@ -130,10 +131,22 @@ export default function App() { the Signer Standard and ICRC-1 tokens.

- After connecting your wallet, you’ll be able to view your balances for{' '} - ICP and ckUSDC and trigger a test transfer of 1 + After connecting your wallet, you'll be able to view your balances for{' '} + TESTICP and TICRC1 and trigger a test transfer of 1 token to your own principal.

+

+ You can obtain testnet tokens for free using the{' '} + + ICP Faucet + + . In OISY, select the IC (testnet tokens) network to view them. +

This app is purely for demonstration purposes and does not store any user data.

Click Connect at the top right to begin, or explore the references @@ -171,7 +184,7 @@ export default function App() {

{isLoading ? ( -
+
Loading token balances... @@ -179,13 +192,13 @@ export default function App() {
) : (
- {/* ICP Card */} -
+ {/* TESTICP Card */} +
- {/* ckUSDC Card */} -
+ {/* TICRC1 Card */} + @@ -263,7 +276,7 @@ export default function App() { )} {/* Footer */} -