Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: dfinity/examples
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 798ef4c3f4f668d501016992b42f41a2e4ef753f
Choose a base ref
..
head repository: dfinity/examples
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 78c99a798d8adf787200ab49e6087c5d274b5780
Choose a head ref
Showing with 7,805 additions and 12,333 deletions.
  1. +2 −3 .github/CODEOWNERS
  2. +23 −0 .github/workflows/rust-parallel-calls-example.yml
  3. +0 −66 .github/workflows/rust-threshold-mock-example.yml
  4. +1 −1 .ic-commit
  5. +0 −17 motoko/ic-pos/.eslintrc.cjs
  6. +2 −0 motoko/ic-pos/.gitignore
  7. +15 −0 motoko/ic-pos/CHANGELOG.md
  8. +58 −43 motoko/ic-pos/README.md
  9. +7 −4 motoko/ic-pos/dfx.json
  10. +24 −0 motoko/ic-pos/eslint.config.js
  11. +2 −2 motoko/ic-pos/{src → }/index.html
  12. +0 −5,704 motoko/ic-pos/package-lock.json
  13. +22 −21 motoko/ic-pos/package.json
  14. +4,917 −0 motoko/ic-pos/pnpm-lock.yaml
  15. +6 −0 motoko/ic-pos/public/.ic-assets.json5
  16. BIN motoko/ic-pos/{src → }/public/cash-register.mp3
  17. +63 −0 motoko/ic-pos/scripts/deploy.sh
  18. +26 −31 motoko/ic-pos/src/declarations/icpos/icpos.did
  19. +19 −20 motoko/ic-pos/src/declarations/icpos/icpos.did.d.ts
  20. +20 −19 motoko/ic-pos/src/declarations/icpos/icpos.did.js
  21. +0 −244 motoko/ic-pos/src/declarations/icpos_frontend/icpos_frontend.did
  22. +0 −228 motoko/ic-pos/src/declarations/icpos_frontend/icpos_frontend.did.d.ts
  23. +0 −262 motoko/ic-pos/src/declarations/icpos_frontend/icpos_frontend.did.js
  24. +0 −50 motoko/ic-pos/src/declarations/icpos_frontend/index.d.ts
  25. +0 −43 motoko/ic-pos/src/declarations/icpos_frontend/index.js
  26. +42 −34 motoko/ic-pos/src/declarations/icrc1_index/icrc1_index.did
  27. +39 −40 motoko/ic-pos/src/declarations/icrc1_index/icrc1_index.did.d.ts
  28. +36 −40 motoko/ic-pos/src/declarations/icrc1_index/icrc1_index.did.js
  29. +2 −3 motoko/ic-pos/src/declarations/icrc1_index/index.js
  30. +93 −67 motoko/ic-pos/src/declarations/icrc1_ledger/icrc1_ledger.did
  31. +70 −43 motoko/ic-pos/src/declarations/icrc1_ledger/icrc1_ledger.did.d.ts
  32. +64 −43 motoko/ic-pos/src/declarations/icrc1_ledger/icrc1_ledger.did.js
  33. +2 −3 motoko/ic-pos/src/declarations/icrc1_ledger/index.js
  34. +2 −3 motoko/ic-pos/src/declarations/internet_identity/index.js
  35. +325 −49 motoko/ic-pos/src/declarations/internet_identity/internet_identity.did
  36. +200 −22 motoko/ic-pos/src/declarations/internet_identity/internet_identity.did.d.ts
  37. +271 −26 motoko/ic-pos/src/declarations/internet_identity/internet_identity.did.js
  38. +2 −8 motoko/ic-pos/src/icpos/main.mo
  39. +0 −45 motoko/ic-pos/src/icpos_frontend/App.tsx
  40. +31 −0 motoko/ic-pos/src/icpos_frontend/actors.tsx
  41. +0 −93 motoko/ic-pos/src/icpos_frontend/auth/context/AuthProvider.tsx
  42. +0 −5 motoko/ic-pos/src/icpos_frontend/auth/hooks/useAuth.tsx
  43. +0 −15 motoko/ic-pos/src/icpos_frontend/auth/types/auth-context.type.ts
  44. +0 −28 motoko/ic-pos/src/icpos_frontend/canisters/ckbtc-index/hooks/useCkBtcIndex.tsx
  45. +0 −53 motoko/ic-pos/src/icpos_frontend/canisters/ckbtc-ledger/hooks/useCkBtcLedger.tsx
  46. +0 −45 motoko/ic-pos/src/icpos_frontend/canisters/ckbtc-ledger/hooks/useCkBtcLedgerAnon.tsx
  47. +0 −59 motoko/ic-pos/src/icpos_frontend/canisters/ic-pos/hooks/useIcPos.tsx
  48. +0 −12 motoko/ic-pos/src/icpos_frontend/canisters/ic-pos/state/merchant.state.ts
  49. +0 −10 motoko/ic-pos/src/icpos_frontend/canisters/icrc/types/transfer.type.ts
  50. +12 −0 motoko/ic-pos/src/icpos_frontend/components/FullpageError.tsx
  51. +2 −9 motoko/ic-pos/src/icpos_frontend/components/HistoryButton.tsx
  52. +25 −0 motoko/ic-pos/src/icpos_frontend/components/LogoutButton.tsx
  53. +44 −0 motoko/ic-pos/src/icpos_frontend/components/NewTransactionNotifier.tsx
  54. +2 −2 motoko/ic-pos/src/icpos_frontend/{pages/charge/components → components/charge}/ChargeButton.tsx
  55. +1 −1 motoko/ic-pos/src/icpos_frontend/{pages/charge/components → components/charge}/KeyPad.tsx
  56. +1 −1 motoko/ic-pos/src/icpos_frontend/{pages/charge/components → components/charge}/KeyPadButton.tsx
  57. 0 motoko/ic-pos/src/icpos_frontend/{pages/charge/types → components/charge}/key.type.ts
  58. +26 −26 motoko/ic-pos/src/icpos_frontend/{pages/config/components → components/config}/ConfigForm.tsx
  59. +6 −10 motoko/ic-pos/src/icpos_frontend/{pages/history/components → components/history}/TransactionRow.tsx
  60. +2 −2 motoko/ic-pos/src/icpos_frontend/{pages/merchant/components → components/merchant}/ChargeButton.tsx
  61. +2 −2 motoko/ic-pos/src/icpos_frontend/{pages/merchant/components → components/merchant}/SendButton.tsx
  62. 0 .../ic-pos/src/icpos_frontend/{pages/receive/components → components/receive}/TransactionOverlay.tsx
  63. +35 −13 motoko/ic-pos/src/icpos_frontend/{pages/send/components → components/send}/SendForm.tsx
  64. +25 −18 motoko/ic-pos/src/icpos_frontend/{pages/initial-config/components → components/setup}/ConfigForm.tsx
  65. +37 −0 motoko/ic-pos/src/icpos_frontend/components/start/LoginButton.tsx
  66. +16 −0 motoko/ic-pos/src/icpos_frontend/hooks/useHandleAgentError.tsx
  67. +49 −0 motoko/ic-pos/src/icpos_frontend/hooks/useLatestTransactions.tsx
  68. +34 −0 motoko/ic-pos/src/icpos_frontend/hooks/useMerchant.tsx
  69. +70 −0 motoko/ic-pos/src/icpos_frontend/hooks/useNewTransactions.tsx
  70. +37 −0 motoko/ic-pos/src/icpos_frontend/hooks/useTokenBalance.tsx
  71. +28 −0 motoko/ic-pos/src/icpos_frontend/hooks/useUpdateMerchant.tsx
  72. +1 −1 motoko/ic-pos/src/icpos_frontend/index.css
  73. +54 −14 motoko/ic-pos/src/icpos_frontend/main.tsx
  74. +0 −38 motoko/ic-pos/src/icpos_frontend/pages/config/ConfigPage.tsx
  75. +0 −72 motoko/ic-pos/src/icpos_frontend/pages/history/HistoryPage.tsx
  76. +0 −34 motoko/ic-pos/src/icpos_frontend/pages/initial-config/InitialConfigPage.tsx
  77. +0 −88 motoko/ic-pos/src/icpos_frontend/pages/merchant/MerchantPage.tsx
  78. +0 −21 motoko/ic-pos/src/icpos_frontend/pages/not-found/NotFoundPage.tsx
  79. +0 −61 motoko/ic-pos/src/icpos_frontend/pages/receive-select-principal/ReceiveSelectPrincipalPage.tsx
  80. +0 −86 motoko/ic-pos/src/icpos_frontend/pages/receive-select-principal/components/SelectPrincipalForm.tsx
  81. +0 −82 motoko/ic-pos/src/icpos_frontend/pages/send/SendPage.tsx
  82. +0 −45 motoko/ic-pos/src/icpos_frontend/pages/start/StartPage.tsx
  83. +0 −13 motoko/ic-pos/src/icpos_frontend/pages/start/components/LoginButton.tsx
  84. +274 −0 motoko/ic-pos/src/icpos_frontend/routeTree.gen.ts
  85. +0 −98 motoko/ic-pos/src/icpos_frontend/router.tsx
  86. +30 −0 motoko/ic-pos/src/icpos_frontend/routes/__root.tsx
  87. +24 −12 motoko/ic-pos/src/icpos_frontend/{pages/charge/ChargePage.tsx → routes/charge.tsx}
  88. +41 −0 motoko/ic-pos/src/icpos_frontend/routes/config.tsx
  89. +53 −0 motoko/ic-pos/src/icpos_frontend/routes/history.tsx
  90. +72 −0 motoko/ic-pos/src/icpos_frontend/routes/index.tsx
  91. +38 −0 motoko/ic-pos/src/icpos_frontend/routes/login.tsx
  92. +33 −25 motoko/ic-pos/src/icpos_frontend/{pages/receive/ReceivePage.tsx → routes/receive.tsx}
  93. +108 −0 motoko/ic-pos/src/icpos_frontend/routes/send.tsx
  94. +32 −0 motoko/ic-pos/src/icpos_frontend/routes/setup.tsx
  95. +0 −19 motoko/ic-pos/src/public/ckBTC.svg
  96. +34 −0 motoko/ic-pos/tsconfig.app.json
  97. +16 −22 motoko/ic-pos/tsconfig.json
  98. +15 −3 motoko/ic-pos/tsconfig.node.json
  99. +40 −65 motoko/ic-pos/vite.config.ts
  100. +93 −41 rust/parallel_calls/Cargo.lock
  101. +1 −1 rust/parallel_calls/src/callee/Cargo.toml
  102. +1 −1 rust/parallel_calls/src/caller/Cargo.toml
  103. +1 −1 rust/parallel_calls/src/multi_subnet/Cargo.toml
  104. +4 −1 rust/parallel_calls/src/multi_subnet/src/main.rs
  105. +0 −14 rust/parallel_calls/src/parallel_calls_backend/Cargo.toml
  106. +0 −3 rust/parallel_calls/src/parallel_calls_backend/parallel_calls_backend.did
  107. +0 −8 rust/parallel_calls/src/parallel_calls_backend/src/lib.rs
  108. +0 −17 rust/threshold-mock/.gitignore
  109. +0 −19 rust/threshold-mock/CONTRIBUTING.md
  110. +0 −2,624 rust/threshold-mock/Cargo.lock
  111. +0 −38 rust/threshold-mock/Cargo.toml
  112. +0 −201 rust/threshold-mock/LICENSE
  113. +0 −15 rust/threshold-mock/Makefile
  114. +0 −31 rust/threshold-mock/README.md
  115. +0 −5 rust/threshold-mock/canister_ids.json
  116. +0 −95 rust/threshold-mock/chainkey_testing_canister.did
  117. +0 −16 rust/threshold-mock/dfx.json
  118. +0 −70 rust/threshold-mock/src/ecdsa.rs
  119. +0 −117 rust/threshold-mock/src/lib.rs
  120. +0 −167 rust/threshold-mock/src/schnorr.rs
  121. +0 −137 rust/threshold-mock/src/vetkd.rs
  122. +0 −324 rust/threshold-mock/tests/tests.rs
5 changes: 2 additions & 3 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -28,8 +28,8 @@
/motoko/pub-sub/ @dfinity/growth
/motoko/query_stats/ @dfinity/sdk
/motoko/random_maze/ @dfinity/languages
/motoko/send_http_get/ @dfinity/networking
/motoko/send_http_post/ @dfinity/networking
/motoko/send_http_get/ @dfinity/growth
/motoko/send_http_post/ @dfinity/growth
/motoko/superheroes/ @dfinity/growth
/motoko/threshold-ecdsa/ @dfinity/crypto-team
/motoko/threshold-schnorr/ @dfinity/crypto-team
@@ -69,7 +69,6 @@
/rust/send_http_post/ @dfinity/growth
/rust/simd/ @dfinity/execution
/rust/threshold-ecdsa/ @dfinity/crypto-team
/rust/threshold-mock/ @dfinity/crypto-team
/rust/threshold-schnorr/ @dfinity/crypto-team
/rust/token_transfer/ @dfinity/growth
/rust/token_transfer_from/ @dfinity/growth
23 changes: 23 additions & 0 deletions .github/workflows/rust-parallel-calls-example.yml
Original file line number Diff line number Diff line change
@@ -42,3 +42,26 @@ jobs:
dfx start --background
make test
popd
rust-parallel-calls-pocket-ic-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: recursive
- name: Provision Linux
run: bash .github/workflows/provision-linux.sh
- name: Install PocketIC server
uses: dfinity/pocketic@main
- name: Test parallel calls with PocketIC
run: |
pushd rust/parallel_calls
cargo build --release --target wasm32-unknown-unknown -p callee
cargo build --release --target wasm32-unknown-unknown -p caller
export CALLER_WASM=$(cargo build --target wasm32-unknown-unknown -p caller --message-format=json \
| jq -r 'select(.reason == "compiler-artifact") | .filenames[] | select(endswith(".wasm"))')
export CALLEE_WASM=$(cargo build --target wasm32-unknown-unknown -p callee --message-format=json \
| jq -r 'select(.reason == "compiler-artifact") | .filenames[] | select(endswith(".wasm"))')
cargo run
popd
66 changes: 0 additions & 66 deletions .github/workflows/rust-threshold-mock-example.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .ic-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8869fff652952265e0871ad137b40ad29880c9e6
a700085f0575a440cb44941da69cfa2efeea3ab9
17 changes: 0 additions & 17 deletions motoko/ic-pos/.eslintrc.cjs

This file was deleted.

2 changes: 2 additions & 0 deletions motoko/ic-pos/.gitignore
Original file line number Diff line number Diff line change
@@ -32,3 +32,5 @@ yarn-error.log*

# misc
scratch/
canister_ids.json

15 changes: 15 additions & 0 deletions motoko/ic-pos/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## [0.4.0] - 2024-11-25

### Changed
- Major front-end overhaul, upgrading many libraries and components.
- Removed recoil for state management, now using Tanstack Router and Tanstack Query.
- Removed old axios based fetching, replacing with Tanstack Query.
- Replacing custom actor and session implementations with `ic-use-actor` and `ic-use-internet-identity`
- Upgraded Vite to new version.
- Upgraded eslint rules and version
- Cleaned up and refactored project setup, routes, and components.
- Upgrading to newer versions of the icrc canisters.

### Fixed
- User sessions now survive page reloads.

## [0.3.0] - 2022-09-10

### Added
101 changes: 58 additions & 43 deletions motoko/ic-pos/README.md
Original file line number Diff line number Diff line change
@@ -4,8 +4,6 @@ keywords: [advanced, motoko, bitcoin, pos, point of sale, ckbtc]

# IC-POS

[View this sample's code on GitHub](https://github.com/dfinity/examples/tree/master/motoko/ic-pos)

![](./media/header.png)


@@ -27,20 +25,20 @@ For deeper understanding of the ICP < > BTC integration, see the IC wiki article

IC-POS is deployed on the Internet Computer. You can try it out here:

https://hngac-6aaaa-aaaal-qb6tq-cai.icp0.io/
https://hngac-6aaaa-aaaal-qb6tq-cai.icp0.io

https://github.com/kristoferlund/ic-pos/assets/9698363/f67d9952-3ee1-4876-a5e5-6ed0e29bae9d
**Note:** The live version of IC-POS uses real ckBTC tokens. To test, use only fractions of a token to avoid losing funds.

## Architecture

### Backend

The backend is written in Motoko and consists of one canister, `icpos`. It exposes four public methods:
The backend is written in Motoko and consists of one canister, `icpos`. It exposes five public methods:

- `getMerchant` - returns the store configuration for a given principal.
- `updateMerchant` - updates the store configuration for a given principal.
- `setCourierApiKey` - sets the Courier API key used to send email and SMS notifications. Only the canister controller can call this method.
- `setLedgerId` - sets the ledger ID to monitor for transactions. Only the canister controller can call this method.
- `setLedgerId` - xsets the ledger ID to monitor for transactions. Only the canister controller can call this method.
- `getLogs` - The canister maintains a debug log that can be fetched using this method.

In addition to the public methods, the canister uses a [timer](https://internetcomputer.org/docs/current/motoko/main/timers/) to monitor ledger transactions. When a new transaction is found that matches a configured store – depending on the store settings – the canister will send a notification either by email or SMS.
@@ -56,37 +54,57 @@ The frontend interacts with the following IC canisters:
- `ckbtc index` - to fetch transaction history.
- `internet identity` - to authenticate users.

# Local deployment
## Setup, dev environment

## Prerequisites
Pre-requisites:

- [x] Install the [IC SDK](https://internetcomputer.org/docs/current/developer-docs/setup/install/index.mdx).
- [x] Install [Node.js](https://nodejs.org/en/).
- [x] Clone the example dapp project: `git clone https://github.com/dfinity/examples`
- [Local Internet Computer dev environment](https://internetcomputer.org/docs/current/developer-docs/backend/rust/dev-env)
- [Node 20+](https://nodejs.org/en/)
- [pnpm](https://pnpm.io/installation)

## Deploy using script

### Step 1: Start a local instance of the replica:
To get started quickly and deploy the IC-POS app locally, you can run a deploy script. This script will start a local replica, deploy the necessary canisters, and build and deploy the frontend.

```bash
bash ./scripts/deploy.sh
```

Once the script has finished, you should proceed to step 10 to create a store and mint yourself some test tokens.

## Deploy manually

### 1. Clone the examples repository and navigate to the IC-POS project:

```bash
git clone https://github.com/dfinity/examples
cd examples/motoko/ic-pos
```


### 2. Start a local instance of the replica:

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

### Step 2: Deploy the Internet Identity canister:
### 3. Deploy the Internet Identity canister:

Integration with the [Internet Identity](https://internetcomputer.org/internet-identity/) allows store owners to securely setup and manage their store. The Internet Identity canister is already deployed on the IC mainnet. For local development, you need to deploy it to your local instance of the IC.

```bash
dfx deploy --network local internet_identity
dfx deploy internet_identity
```

### Step 3: Save the current principal as a variable:
### 4. Save the current principal as a variable:

The principal will be used when deploying the ledger canister.

```bash
export OWNER=$(dfx identity get-principal)
```

### Step 3: Deploy the ckBTC ledger canister:
### 5. Deploy the ckBTC ledger canister:

The responsibilities of the ledger canister is to keep track of token balances and handle token transfers.

@@ -101,7 +119,7 @@ Take a moment to read the details of the call we are making below. Not only are
- Setting the transfer fee to 10 LCKBTC.

```bash
dfx deploy --network local --specified-id mxzaz-hqaaa-aaaar-qaada-cai icrc1_ledger --argument '
dfx deploy icrc1_ledger --argument '
(variant {
Init = record {
token_name = "Local ckBTC";
@@ -129,61 +147,61 @@ dfx deploy --network local --specified-id mxzaz-hqaaa-aaaar-qaada-cai icrc1_ledg
'
```

### Step 4: Deploy the index canister:
### 6. Deploy the index canister

The index canister syncs the ledger transactions and indexes them by account.

```bash
dfx deploy --network local icrc1_index --argument '
dfx deploy icrc1_index --argument '
record {
ledger_id = (principal "mxzaz-hqaaa-aaaar-qaada-cai");
}
'
```

### Step 5: Deploy the icpos canister:
### 7. Deploy the icpos canister

The icpos canister manages the store configuration and sends notifications when a payment is received.

The `--argument '(0)'` argument is used to initialize the canister with `startBlock` set to 0. This is used to tell the canister to start monitoring the ledger from block 0. When deploying to the IC mainnet, this should be set to the current block height to prevent the canister from processing old transactions.

```bash
dfx deploy --network local icpos --argument '(0)'
dfx deploy icpos --argument '(0)'
```

### Step 6: Configure the icpos canister:
### 8. Configure the icpos canister

ic-pos uses [Courier](https://courier.com/) to send email and SMS notifications. If you want to enable notifications, you need to sign up for a Courier account and and create and API key. Then issue the following command:
IC-POS uses [Courier](https://courier.com/) to send email and SMS notifications. If you want to enable notifications, you need to sign up for a Courier account and and create and API key. Then issue the following command:

```bash
dfx canister --network local call icpos setCourierApiKey "pk_prod_..."
dfx canister call icpos setCourierApiKey "pk_prod_..."
```

### Step 7: Build and run the frontend:
### 9. Build and run the frontend

Run npm to install dependencies and start the frontend. The frontend will be available at http://localhost:5173.
Run npm to install dependencies and start a development version of the frontend.

```bash
npm install
npm run dev
pnpm install
pnpm run dev
```

Why don't we deploy the frontend as a local canister? Vite uses lazy loading of modules. This does not work when deploying to a local canister. When deploying to the IC mainnet, this is not an issue. Also, running using `npm run dev` allows for hot reloading of the frontend code when making changes.
The app should now be accessible at a local url, typically `http://localhost:5173`.

### Step 8: Make a transfer!
### 10. Make a transfer!

Now that everything is up and running, you can make a transfer to your newly created store.

Transfers made from the owner principal will not trigger notifications in the UI since they are regarded as `mint` transactions. To test notifications, you need to make a transfer from another principal.

Now that everything is up and running, you can make a transfer to your newly created store.

The easiest way to do this is to create two stores using two different Internet Identity accounts, using two different web browsers. Then, transfer some tokens from one store to the other.

#### 8.1: Create the first store and supply it with some tokens:
#### 10.1 Create the first store and supply it with some tokens

Log in to the frontend using the Internet Identity. Configure the store and navigate to the `Receive` page. Click on the principal pill to copy the address to your clipboard. Then, using the `dfx` command, mint some tokens from your owner principal to the store principal.
Log in to the frontend using the Internet Identity. Configure the store with a name and then, on the main store page, click on the principal pill to copy the address to your clipboard. Using the `dfx` command, now mint some tokens from your owner principal to the store principal.

```bash
dfx canister --network local call icrc1_ledger icrc1_transfer '
dfx canister call icrc1_ledger icrc1_transfer '
(record {
to=(record {
owner=(principal "[STORE PRINCIPAL 1 HERE]")
@@ -193,9 +211,9 @@ dfx canister --network local call icrc1_ledger icrc1_transfer '
'
```

#### 8.2: Create the second store:
#### 10.2 Create the second store

Log in to the frontend using **a new Internet Identity on another web browser**. Configure the store and navigate to the `Receive` page. Click on the principal pill to copy the address to your clipboard.
Log in to the frontend using **a new Internet Identity using another web browser**. Give this store a name as well and copy the store principal like in the previous step.

Now, go back to the first browser/store, navigate to the `Send` page, and transfer some tokens to the second store.

@@ -205,14 +223,11 @@ If everything is working, you should see a notification in the second store.

## Possible improvements

- Login state is not persisted. Reloading the app will log the user out. This should be done using `localStorage` or `sessionStorage`.
- Show more information about transactions. A transaction detail page.
- Show more information about transactions.
- A transaction detail page.
- Pagination, currently only the first 5 transactions are shown.
- Show a confirmation dialog after the user clicks on the `Send` button.

## Known issues

-

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.
Loading