Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .sources/VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
chain-fusion-signer v0.4.0 a18c52a
papi v0.1.1 168bc9d
ic-pub-key v1.0.1 f89fa55
icp-cli v0.3.1 c4c4618
icp-cli v1.0.0 9eed60c
motoko v1.9.0 e7c78d7
motoko-core v2.4.0 cd37dbf
cdk-rs ic-cdk v0.20.1 / ic-cdk-timers v1.0.0 / ic-cdk-executor v2.0.0 317f55c
Expand Down
2 changes: 1 addition & 1 deletion .sources/icp-cli
Submodule icp-cli updated 39 files
+7 −0 .github/scripts/init-docker.sh
+31 −1 .github/workflows/checks.yml
+84 −9 .github/workflows/test.yml
+6 −0 .github/workflows/validate-examples.yml
+10 −0 CHANGELOG.md
+24 −24 Cargo.lock
+1 −1 Cargo.toml
+29 −1 crates/icp-cli/src/commands/canister/call.rs
+1 −1 crates/icp-cli/src/commands/canister/create.rs
+64 −2 crates/icp-cli/src/commands/canister/install.rs
+16 −15 crates/icp-cli/src/commands/canister/settings/update.rs
+3 −1 crates/icp-cli/src/commands/identity/account_id.rs
+1 −1 crates/icp-cli/src/commands/identity/delegation/sign.rs
+12 −11 crates/icp-cli/src/commands/identity/link/web.rs
+3 −1 crates/icp-cli/src/commands/identity/principal.rs
+118 −50 crates/icp-cli/src/commands/identity/reauth.rs
+41 −22 crates/icp-cli/src/commands/network/ping.rs
+85 −0 crates/icp-cli/src/commands/settings.rs
+21 −4 crates/icp-cli/src/main.rs
+41 −7 crates/icp-cli/src/operations/install.rs
+114 −0 crates/icp-cli/tests/canister_call_tests.rs
+336 −0 crates/icp-cli/tests/canister_install_tests.rs
+5 −3 crates/icp-cli/tests/canister_settings_tests.rs
+190 −0 crates/icp-cli/tests/identity_tests.rs
+71 −0 crates/icp-cli/tests/network_ping_tests.rs
+6 −1 crates/icp/src/context/init.rs
+13 −4 crates/icp/src/context/mod.rs
+4 −4 crates/icp/src/context/tests.rs
+425 −29 crates/icp/src/identity/key.rs
+57 −19 crates/icp/src/identity/mod.rs
+2 −2 crates/icp/src/lib.rs
+1 −1 crates/icp/src/prelude.rs
+12 −0 crates/icp/src/settings.rs
+1 −1 docs/concepts/environments.md
+51 −11 docs/reference/cli.md
+1 −1 examples/icp-network-connected/networks/staging.yaml
+1 −1 examples/icp-network-inline/icp.yaml
+1 −1 network-launcher-version
+1 −1 rust-toolchain.toml
2 changes: 1 addition & 1 deletion .sources/icp-cli-templates
Submodule icp-cli-templates updated 52 files
+16 −0 .github/workflows/test-templates.yml
+19 −0 Makefile
+1 −1 README.md
+1 −4 bitcoin-starter/motoko-backend/canister.yaml
+5 −1 bitcoin-starter/motoko-backend/mops.toml
+1 −1 hello-world/README.md
+8 −2 hello-world/cargo-generate.toml
+0 −4 hello-world/frontend/app/tsconfig.node.json
+0 −34 hello-world/frontend/app/vite.config.ts
+0 −9 hello-world/frontend/package.json
+1 −5 hello-world/motoko-backend/canister.yaml
+5 −1 hello-world/motoko-backend/mops.toml
+0 −0 hello-world/react-frontend/.gitignore
+0 −0 hello-world/react-frontend/.node-version
+3 −6 hello-world/react-frontend/canister.yaml
+0 −0 hello-world/react-frontend/eslint.config.js
+2 −2 hello-world/react-frontend/index.html
+3 −3 hello-world/react-frontend/package.json
+0 −0 hello-world/react-frontend/public/icp.svg
+8 −0 hello-world/react-frontend/public/react.svg
+0 −0 hello-world/react-frontend/public/vite.svg
+5 −0 hello-world/react-frontend/src/App.css
+9 −5 hello-world/react-frontend/src/App.tsx
+0 −0 hello-world/react-frontend/src/index.css
+0 −0 hello-world/react-frontend/src/main.tsx
+0 −0 hello-world/react-frontend/src/vite-env.d.ts
+0 −0 hello-world/react-frontend/tsconfig.app.json
+0 −0 hello-world/react-frontend/tsconfig.json
+2 −1 hello-world/react-frontend/tsconfig.node.json
+69 −0 hello-world/react-frontend/vite.config.ts
+12 −0 hello-world/rename-dirs.rhai
+24 −0 hello-world/vue-frontend/.gitignore
+15 −0 hello-world/vue-frontend/canister.yaml
+16 −0 hello-world/vue-frontend/index.html
+22 −0 hello-world/vue-frontend/package.json
+100 −0 hello-world/vue-frontend/public/icp.svg
+1 −0 hello-world/vue-frontend/public/vite.svg
+2 −0 hello-world/vue-frontend/public/vue.svg
+120 −0 hello-world/vue-frontend/src/App.scss
+74 −0 hello-world/vue-frontend/src/App.vue
+103 −0 hello-world/vue-frontend/src/index.css
+7 −0 hello-world/vue-frontend/src/main.js
+1 −0 hello-world/vue-frontend/src/vite-env.d.ts
+22 −0 hello-world/vue-frontend/tsconfig.json
+69 −0 hello-world/vue-frontend/vite.config.ts
+1 −5 motoko/icp.yaml
+4 −1 motoko/mops.toml
+2 −1 static-website/icp.yaml
+69 −0 tests/README.md
+180 −0 tests/lib.sh
+51 −0 tests/matrix.yaml
+78 −0 tests/run.sh
2 changes: 1 addition & 1 deletion .sources/icskills
Submodule icskills updated 111 files
6 changes: 3 additions & 3 deletions docs/concepts/edge-infrastructure.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ Around 20 API boundary nodes are currently deployed worldwide. An up-to-date lis

HTTP gateways translate standard HTTP requests into IC API calls and forward them to API boundary nodes. Because of this translation layer, browsers and other HTTP clients can access canisters directly without installing any special software. For example, a website fully hosted on ICP is accessible in any browser through a normal HTTPS URL.

The HTTP Gateway Protocol (defined in the [HTTP Gateway Protocol Specification](../references/http-gateway-spec.md)) specifies exactly how this translation works. HTTP gateways are not part of ICP itself and can be operated by anyone. This open model encourages a diverse set of gateways, enhancing redundancy and availability.
The HTTP Gateway Protocol (defined in the [HTTP Gateway Protocol Specification](../references/http-gateway-protocol-spec.md)) specifies exactly how this translation works. HTTP gateways are not part of ICP itself and can be operated by anyone. This open model encourages a diverse set of gateways, enhancing redundancy and availability.

## HTTP Gateway Protocol

When a browser opens a URL hosted by a canister, the following happens:

1. The browser makes a normal HTTPS request to the domain (for example, `https://<canister-id>.icp0.io`). It has no awareness that the site runs on ICP.
1. The browser makes a normal HTTPS request to the domain (for example, `https://<canister-id>.icp.net`). It has no awareness that the site runs on ICP.
2. The HTTP gateway receives the request and translates it into a query call to the canister's `http_request` method, placing the path, headers, and body into the call payload.
3. An API boundary node receives the IC API call and forwards it to a replica on the subnet that hosts the target canister.
4. The canister executes the `http_request` query, constructs an HTTP response (status, headers, body), and returns it.
Expand All @@ -66,7 +66,7 @@ For practical guidance on certifying canister responses, see [Certified variable

## Further reading

- [HTTP Gateway Protocol Specification](../references/http-gateway-spec.md): detailed protocol definition
- [HTTP Gateway Protocol Specification](../references/http-gateway-protocol-spec.md): detailed protocol definition
- [ic-http-gateway library](https://github.com/dfinity/ic-http-gateway-protocol/tree/main/packages/ic-http-gateway-protocol): the main implementation of the HTTP Gateway Protocol
- [response-verification](https://github.com/dfinity/response-verification): libraries for certifying canister responses to work with the HTTP gateway protocol
- [Certified variables guide](../guides/backends/certified-variables.md): how to certify canister responses
Expand Down
2 changes: 1 addition & 1 deletion docs/concepts/network-economics.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ICP has four protocol-level uses:

**2. Cycle conversion.** ICP can be burned to mint cycles through the Cycles Minting Canister (CMC). Cycles are pegged to the XDR basket of currencies at a rate of 1 trillion cycles = 1 XDR. This means developer infrastructure costs are stable in fiat terms even as ICP's market price changes. See [Cycles](cycles.md) for details.

**3. Node provider rewards.** Nodes that run the Internet Computer are owned by independent node providers. These providers are compensated in newly minted ICP. Rewards are specified in XDR and converted to ICP based on a 30-day moving average exchange rate, so providers receive stable real-world compensation regardless of price fluctuations. The Cycles Minting Canister (CMC) fetches the ICP/XDR rate every 5 minutes from the [exchange rate canister](chain-fusion/exchange-rate-canister.md#how-rates-are-computed), which aggregates rates from external sources. It uses the start-of-day rates for the past 30 days to compute the moving average. The current conversion rate is available on the [ICP dashboard](https://dashboard.internetcomputer.org/network) and from the [CMC metrics endpoint](https://rkp4c-7iaaa-aaaaa-aaaca-cai.raw.icp0.io/metrics).
**3. Node provider rewards.** Nodes that run the Internet Computer are owned by independent node providers. These providers are compensated in newly minted ICP. Rewards are specified in XDR and converted to ICP based on a 30-day moving average exchange rate, so providers receive stable real-world compensation regardless of price fluctuations. The Cycles Minting Canister (CMC) fetches the ICP/XDR rate every 5 minutes from the [exchange rate canister](chain-fusion/exchange-rate-canister.md#how-rates-are-computed), which aggregates rates from external sources. It uses the start-of-day rates for the past 30 days to compute the moving average. The current conversion rate is available on the [ICP dashboard](https://dashboard.internetcomputer.org/network) and from the [CMC metrics endpoint](https://rkp4c-7iaaa-aaaaa-aaaca-cai.raw.icp.net/metrics).

**4. SNS decentralization swaps.** Users can commit ICP to participate in the decentralization swap of an SNS. In return they receive the SNS's governance assets at a uniform price. The ICP raised enters the SNS treasury under NNS control and funds future development and operations.

Expand Down
2 changes: 1 addition & 1 deletion docs/concepts/network-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ For how the protocol achieves this (block making, notarization, finalization, an

Boundary nodes are the entry point for all external traffic to ICP. They serve two purposes:

1. **HTTP gateway.** When a user's browser requests `https://<canister-id>.icp0.io`, a boundary node translates that HTTP request into a canister message, routes it to the correct subnet, and returns the response.
1. **HTTP gateway.** When a user's browser requests `https://<canister-id>.icp.net`, a boundary node translates that HTTP request into a canister message, routes it to the correct subnet, and returns the response.
2. **API endpoint.** Agent libraries (like [`@icp-sdk/core/agent`](https://js.icp.build/core/latest/libs/agent) in JavaScript) send ingress messages to boundary nodes, which forward them to the target canister's subnet.

Boundary nodes also cache query responses and provide TLS termination. They are not part of consensus and cannot modify canister state: they are routing infrastructure.
Expand Down
2 changes: 1 addition & 1 deletion docs/concepts/principals.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ICP defines five principal classes, though one (derived IDs) has never been impl

**2. Canister IDs:** Each canister on ICP has a unique principal derived when the canister is created. Canister principals look like `ryjl3-tyaaa-aaaaa-aaaba-cai`. When a canister makes a call to another canister, the callee sees the calling canister's canister ID as the caller principal.

**3. Self-authenticating IDs:** User identities are derived from public keys using a domain-separated hash. Anyone holding the corresponding private key can authenticate and call canisters under that principal. Self-authenticating principals look like `o2ivq-5dsbb-hhfso-w2o5v-7qiaq-g4fbm-6qhhb-xbj6w-szpxa-lflfa-mae` for Ed25519 keys or similar for ECDSA keys. The [Internet Identity](https://identity.ic0.app/) service manages key-backed identities for end users.
**3. Self-authenticating IDs:** User identities are derived from public keys using a domain-separated hash. Anyone holding the corresponding private key can authenticate and call canisters under that principal. Self-authenticating principals look like `o2ivq-5dsbb-hhfso-w2o5v-7qiaq-g4fbm-6qhhb-xbj6w-szpxa-lflfa-mae` for Ed25519 keys or similar for ECDSA keys. The [Internet Identity](https://id.ai/) service manages key-backed identities for end users.

**4. Anonymous principal (`2vxsx-fae`):** Messages that are not signed use the anonymous principal as their caller identity. Any canister can check whether a caller is anonymous and decide how to handle unsigned requests (for example, allowing public reads but rejecting state changes from anonymous callers).

Expand Down
22 changes: 15 additions & 7 deletions docs/getting-started/project-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,22 @@ Each canister has its own `canister.yaml` that defines how to build and deploy i

<Tabs syncKey="lang">
<TabItem label="Motoko">
The Motoko backend uses the `@dfinity/motoko` recipe:
The Motoko backend uses the `@dfinity/motoko` recipe, which compiles via `mops build`:

```yaml
name: backend
recipe:
type: "@dfinity/motoko@v4.1.0"
configuration:
main: src/main.mo
candid: backend.did
type: "@dfinity/motoko@v5.0.0"
```

The recipe takes no source or Candid configuration. Instead, the source file (and optionally the Candid file and compiler flags) are declared in a `mops.toml` at the project root. The `[canisters]` key must match the canister `name`:

```toml
[toolchain]
moc = "1.9.0"

[canisters]
backend = "src/main.mo"
```
</TabItem>
<TabItem label="Rust">
Expand All @@ -99,12 +106,13 @@ The Rust backend uses the `@dfinity/rust` recipe:
```yaml
name: backend
recipe:
type: "@dfinity/rust@v3.2.0"
type: "@dfinity/rust@v3.3.0"
configuration:
package: backend
shrink: true
candid: backend.did
```

The `package` parameter (the Cargo package to build) defaults to the canister `name`, so it can be omitted when they match. Set it explicitly only when they differ.
</TabItem>
</Tabs>

Expand Down
12 changes: 6 additions & 6 deletions docs/guides/authentication/internet-identity.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ When a user authenticates through Internet Identity, the following happens:
4. Your frontend receives this delegation and uses it to sign canister calls.
5. The backend canister sees the user's **principal** (derived from the delegation chain) as `msg.caller`.

**Principal-per-app isolation:** II derives a different principal for each frontend origin. A user logging into `https://app-a.icp0.io` gets a different principal than when logging into `https://app-b.icp0.io`, even with the same passkey. This prevents apps from correlating users across services.
**Principal-per-app isolation:** II derives a different principal for each frontend origin. A user logging into `https://app-a.icp.net` gets a different principal than when logging into `https://app-b.icp.net`, even with the same passkey. This prevents apps from correlating users across services.

**Delegations expire.** The frontend sets a `maxTimeToLive` when requesting the delegation (default recommendation: 8 hours). After expiry, the user must re-authenticate. The maximum allowed delegation lifetime is 30 days (2,592,000,000,000,000 nanoseconds).

Expand Down Expand Up @@ -381,7 +381,7 @@ canisters:
settings:
environment_variables:
trusted_attribute_signers: "rdmx6-jaaaa-aaaaa-aaadq-cai" # required
frontend_origins: "https://your-app.icp0.io" # required, comma-separated
frontend_origins: "https://your-app.icp.net" # required, comma-separated
trusted_sso_domains: "your-org.com" # optional; omit to reject all sso:* keys
```

Expand All @@ -400,7 +400,7 @@ use std::cell::RefCell;
use std::collections::HashSet;

const II_PRINCIPAL: &str = "rdmx6-jaaaa-aaaaa-aaadq-cai";
const TRUSTED_ORIGIN: &str = "https://your-app.icp0.io";
const TRUSTED_ORIGIN: &str = "https://your-app.icp.net";
const FRESHNESS_NS: u64 = 300_000_000_000; // 5 minutes

thread_local! {
Expand Down Expand Up @@ -553,7 +553,7 @@ icp deploy -e ic

## Alternative origins

By default, each frontend origin produces a different user principal. If you serve your app from multiple domains (for example, migrating from `<canister-id>.icp0.io` to a custom domain), users would get different principals on each domain.
By default, each frontend origin produces a different user principal. If you serve your app from multiple domains (for example, migrating from `<canister-id>.icp.net` to a custom domain), users would get different principals on each domain.

:::note
II now automatically handles the `icp0.io` vs `ic0.app` domain difference: you do **not** need to use `derivationOrigin` or `ii-alternative-origins` for that case. Use alternative origins only when you have two genuinely distinct custom domains that should share the same user principal.
Expand Down Expand Up @@ -595,7 +595,7 @@ To keep principals consistent across your own custom domains, configure **altern
```javascript
const authClient = new AuthClient({
identityProvider: "https://id.ai",
derivationOrigin: "https://xxxxx.icp0.io", // primary origin A
derivationOrigin: "https://xxxxx.icp.net", // primary origin A
});
```

Expand Down Expand Up @@ -625,4 +625,4 @@ For full details, see the [Internet Identity specification](../../references/int

{/* TODO: Add Unity native app integration via deep links: see portal native-apps/unity_ii_* */}

{/* Upstream: informed by dfinity/portal (docs/building-apps/authentication/overview.mdx, docs/building-apps/authentication/integrate-internet-identity.mdx, docs/building-apps/authentication/alternative-origins.mdx); dfinity/icskills (skills/internet-identity/SKILL.md); dfinity/icp-js-sdk-docs (public/auth/latest.zip api/client/AuthClient, scopedKeys, SignedAttributes, AuthClientCreateOptions; public/core/latest.zip libs/identity/api.mdAttributesIdentity); dfinity/cdk-rs (ic-cdk/src/api.rs); dfinity/motoko-identity-attributes (README.md, src/lib.mo, src/Internal/Verify.mo @ v0.4.1 the mixin and its verification order); caffeinelabs/motoko-core (src/CallerAttributes.mo getAttributes wrapper, src/Map.mo); caffeinelabs/motoko (src/prelude/prim.mo callerInfoData/Signer, test/run-drun/caller-info/caller-info.mo); dfinity/icp-cli (docs/reference/canister-settings.md#environment_variables) */}
{/* Upstream: informed by dfinity/portal (docs/building-apps/authentication/overview.mdx, docs/building-apps/authentication/integrate-internet-identity.mdx, docs/building-apps/authentication/alternative-origins.mdx); dfinity/icskills (skills/internet-identity/SKILL.md); dfinity/icp-js-sdk-docs (public/auth/latest.zip api/client/: AuthClient, scopedKeys, SignedAttributes, AuthClientCreateOptions; public/core/latest.zip libs/identity/api.md: AttributesIdentity); dfinity/cdk-rs (ic-cdk/src/api.rs); dfinity/motoko-identity-attributes (README.md, src/lib.mo, src/Internal/Verify.mo @ v0.4.1: the mixin and its verification order); caffeinelabs/motoko-core (src/CallerAttributes.mo getAttributes wrapper, src/Map.mo); caffeinelabs/motoko (src/prelude/prim.mo callerInfoData/Signer, test/run-drun/caller-info/caller-info.mo); dfinity/icp-cli (docs/reference/canister-settings.md#environment_variables) */}
6 changes: 3 additions & 3 deletions docs/guides/authentication/verifiable-credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Returns the consent text shown to the user in the II dialog. This message must c
Returns the URL used to derive the user's principal for this issuer. If you do not use [alternative derivation origins](../../references/internet-identity-spec.md), return the canister's default URL:

```
https://<issuer-canister-id>.icp0.io
https://<issuer-canister-id>.icp.net
```

If you use alternative origins, return the same value as your `derivationOrigin` login parameter. The returned value is verified via `.well-known/ii-alternative-origins`.
Expand Down Expand Up @@ -365,10 +365,10 @@ See the [demo relying party implementation](https://github.com/dfinity/vc-playgr
### Live demo environment

A demo relying party is deployed on ICP for testing:
[https://l7rua-raaaa-aaaap-ahh6a-cai.icp0.io/](https://l7rua-raaaa-aaaap-ahh6a-cai.icp0.io/)
[https://l7rua-raaaa-aaaap-ahh6a-cai.icp.net/](https://l7rua-raaaa-aaaap-ahh6a-cai.icp.net/)

Use the II staging instance to avoid using real user credentials:
[https://fgte5-ciaaa-aaaad-aaatq-cai.ic0.app/](https://fgte5-ciaaa-aaaad-aaatq-cai.ic0.app/)
[https://fgte5-ciaaa-aaaad-aaatq-cai.icp.net/](https://fgte5-ciaaa-aaaad-aaatq-cai.icp.net/)

A demo issuer is deployed that will issue any requested credential. Explore the issuer canister on the [NNS dashboard](https://dashboard.internetcomputer.org/canister/qdiif-2iaaa-aaaap-ahjaq-cai) or browse its implementation in the [vc-playground repository](https://github.com/dfinity/vc-playground).

Expand Down
22 changes: 14 additions & 8 deletions docs/guides/canister-calls/candid.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,23 @@ For the complete type reference, including subtyping rules, see the [Candid spec

The Motoko compiler generates Candid descriptions automatically from your actor's type signature. When you build with icp-cli, the `.did` file is placed in the build output directory. No manual authoring needed.

You can also provide a hand-written `.did` file by setting the `candid` field in `icp.yaml`. This is useful when you want an explicit API contract that is versioned independently of the implementation:
You can also provide a hand-written `.did` file by setting the `candid` field for the canister in `mops.toml` (the `@dfinity/motoko` recipe v5 and later builds with `mops build`). This is useful when you want an explicit API contract that is versioned independently of the implementation:

```yaml
# icp.yaml
canisters:
- name: backend
recipe:
type: "@dfinity/motoko@v4.1.0"
configuration:
main: backend/app.mo
candid: backend/backend.did # Optional: overrides auto-generation
type: "@dfinity/motoko@v5.0.0"
```

Declare the source and Candid file under the canister's entry in `mops.toml`:

```toml
# mops.toml
[canisters.backend]
main = "backend/app.mo"
candid = "backend/backend.did" # Optional: overrides auto-generation
```

If `candid` is omitted, the Motoko recipe auto-generates the interface from the source.
Expand Down Expand Up @@ -159,9 +166,8 @@ Reference the generated `.did` file in your `icp.yaml`:
canisters:
- name: my_canister
recipe:
type: "@dfinity/rust@v3.2.0"
type: "@dfinity/rust@v3.3.0"
configuration:
package: my_canister
candid: src/my_canister/my_canister.did
```

Expand Down Expand Up @@ -439,7 +445,7 @@ For type selector configuration and advanced options, see the [`ic-cdk-bindgen`
| `didc decode <hex>` | Decode binary Candid back to text |
| `didc subtype new.did old.did` | Check that `new` is a safe upgrade from `old` |

**Candid UI**: a web interface for calling canister methods directly from a browser, generated automatically for every deployed canister. Useful for testing and debugging without writing frontend code. Access it at `https://a4gq6-oaaaa-aaaab-qaa4q-cai.icp0.io/?id=<canister-id>` for mainnet canisters.
**Candid UI**: a web interface for calling canister methods directly from a browser, generated automatically for every deployed canister. Useful for testing and debugging without writing frontend code. Access it at `https://a4gq6-oaaaa-aaaab-qaa4q-cai.icp.net/?id=<canister-id>` for mainnet canisters.

## Next steps

Expand Down
Loading
Loading