From a4711092f67a6f065edb501ce0476d3ffd194049 Mon Sep 17 00:00:00 2001 From: Mohan Date: Fri, 27 Sep 2024 13:36:29 +0530 Subject: [PATCH] feat: staging to main (#376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: tray icon click, refactor for better DX around tray * fix: further nullish fallbacks * release: rc136 * fix: allowlist evm public keys in gitleaks CI * fix: updated for correct version * fix: edit [allowlist] regexes * fix: seperate allowlist for ignore evm pub keys * fix: make global allowlist array * fix: make allowlists singular * fix: combine allowlists * fix: use word boundaries * feat: refactor pearl tray * chore: delete old tray icons file * fix: use enum * bump: rc140 * fix: missing resize * chore: add electron.logger * fix: setTemplateImage for macOS tray icon * docs: updated docs * fix: missing setTemplateImage * fix: links * fix: only bind click events for windows (linux/mac do not support) * bump: rc142 * feat: Implement UX improvements on balances (#362) * feat: add constant for modal width * feat: add CustomModal component * feat: update modal width to use constant * feat: add AccountBalanceDetails dummy component * feat: add dummy OlasBalance in AccountBalanceDetails component * feat: add dummy XdaoBalance in AccountBalanceDetails component * Add YourWallet and Signer component * Add YourAgentWallet component * feat: add a button to trigger the modal * feat: remove comments code for balance * feat: integrate wallet address * feat: add signer, balances and update InfoBreakdown component * feat: extract Signer header * feat: add agent details * feat: as per new design * feat: update images * feat: Remove current balance tooltip * feat: renames * feat: replace icon with 'See breakdown' text * feat: Update account balance to include EOA xDAI for AccountBalances.tsx and YourAgent.tsx * feat: Compliance review comments (#366) * feat: update backup wallet message for clarity * remove: do not add more funds line * fix: 'This enables you to' -> 'you may recover your funds to your backup wallet if you lose ....' * feat: 'may' not 'can' * feat: 'Note that the backup wallet feature is not designed to restore access to your Pearl account but rather the funds ...' * feat: 'to avoid missing targets' * feat: Change to 'Your agent is at risk of missing its targets, which would result in several days' suspension.' * feat: Change to 'to be eligible for...' and Add ',' * feat: Change to 'Estimated Annual Percentage Yield (APY)'. Implement it across' * feat: Remove 'will' https * fix: broken .nvmrc * fix: stops build warning * fix: removed macUpdater listener, keeps firing after changing options * refactor: moved macUpdater event from main (clutter) * fix: use app.getAppPath, __dirname doesn't work in subdirectories * fix: return * feat: display last transaction with a 1-minute delay – persists even after navigating to other pages (#365) * feat: add a hook to delay 1 minute to show last transaction * changes * feat: update logic * release: rc143 * fix: missing `?` * feat: add win32 dev build * feat: UI of nested wallets in new Wallet screen (#368) * feat: update 'Address' component * feat: directory rename * feat: remove modal and create a different page for 'Your wallet' * feat: restructure Component order * fix: update tray icons & add retina images * feat: Show scrollbar when the content is taller that then window (#369) * feat: try with account-balances modal * feat: add scrollbar css globally * add scroll to botton on 'Add funds' click & add global scroll * feat: minor scroll-bar update * refactor: Add delay utility function for code readability * feat: hide body scroll and enable for main card * feat: add scroll to body * feat: fixed topbar * fix: Include current epoch's rewards in balance breakdown (#374) * fix: add current epoch rewards * feat: add wallet addresses to Signer tooltip * fix: Update balanceFormat function in YourAgentWallet component * feat: add XDAI balance instead of address * release: rc145 --------- Co-authored-by: truemiller Co-authored-by: Josh Miller <31908788+truemiller@users.noreply.github.com> --- .github/workflows/release_win.yml | 15 +- .gitleaks.toml | 12 +- .nvmrc | 2 +- README.md | 228 ++---------------- docs/dev/macos-setup.md | 97 ++++++++ docs/dev/rpcs.md | 43 ++++ docs/dev/ubuntu-setup.md | 79 ++++++ docs/dev/windows-setup.md | 98 ++++++++ electron/assets/icons/tray-logged-out.png | Bin 1336 -> 0 bytes electron/assets/icons/tray-low-gas.png | Bin 1433 -> 0 bytes electron/assets/icons/tray-paused.png | Bin 1312 -> 0 bytes electron/assets/icons/tray-running.png | Bin 1342 -> 0 bytes electron/assets/icons/tray/logged-out.png | Bin 0 -> 363 bytes electron/assets/icons/tray/logged-out@2x.png | Bin 0 -> 671 bytes electron/assets/icons/tray/logged-out@3x.png | Bin 0 -> 1034 bytes electron/assets/icons/tray/low-gas.png | Bin 0 -> 381 bytes electron/assets/icons/tray/low-gas@2x.png | Bin 0 -> 735 bytes electron/assets/icons/tray/low-gas@3x.png | Bin 0 -> 1075 bytes electron/assets/icons/tray/paused.png | Bin 0 -> 370 bytes electron/assets/icons/tray/paused@2x.png | Bin 0 -> 694 bytes electron/assets/icons/tray/paused@3x.png | Bin 0 -> 1049 bytes electron/assets/icons/tray/running.png | Bin 0 -> 362 bytes electron/assets/icons/tray/running@2x.png | Bin 0 -> 664 bytes electron/assets/icons/tray/running@3x.png | Bin 0 -> 1013 bytes electron/components/PearlTray.js | 147 +++++++++++ electron/icons.js | 30 --- electron/install.js | 2 +- electron/main.js | 120 ++------- electron/update.js | 21 +- frontend/components/AddressLink.tsx | 25 ++ frontend/components/InfoBreakdown.tsx | 14 +- frontend/components/InfoTooltip.tsx | 16 ++ frontend/components/Layout/TopBar.tsx | 4 +- frontend/components/Layout/index.tsx | 9 +- .../MainPage/MainHeader/FirstRunModal.tsx | 3 +- .../MainPage/header/AgentButton.tsx | 7 +- .../MainPage/header/LastTransaction.tsx | 28 ++- .../MainPage/modals/FirstRunModal.tsx | 3 +- .../MainPage/modals/MigrationModal.tsx | 3 +- .../MainPage/sections/AddFundsSection.tsx | 25 +- .../MainPage/sections/NeedsFundsSection.tsx | 1 - .../MainPage/sections/OlasBalanceSection.tsx | 98 +++----- .../StakingContractDetails.tsx | 2 +- .../WhatAreStakingContracts.tsx | 6 +- .../SettingsPage/AddBackupWalletPage.tsx | 6 +- .../SettingsPage/DebugInfoSection.tsx | 37 +-- .../SetupPage/Create/SetupBackupSigner.tsx | 6 +- .../components/SetupPage/SetupRestore.tsx | 6 +- frontend/components/YourWalletPage/Titles.tsx | 95 ++++++++ .../components/YourWalletPage/YourAgent.tsx | 181 ++++++++++++++ .../components/YourWalletPage/YourWallet.tsx | 158 ++++++++++++ frontend/components/YourWalletPage/styles.ts | 13 + frontend/components/styled/CardSection.tsx | 4 + frontend/components/styled/CustomModal.tsx | 33 +++ frontend/constants/colors.ts | 1 + frontend/constants/width.ts | 1 + frontend/context/BalanceProvider.tsx | 18 ++ frontend/context/PageStateProvider.tsx | 21 +- frontend/enums/PageState.ts | 1 + frontend/hooks/usePageState.ts | 5 +- frontend/hooks/useServices.ts | 4 + frontend/pages/index.tsx | 3 + frontend/public/NFT.png | Bin 0 -> 712281 bytes frontend/public/agent-wallet.png | Bin 0 -> 10579 bytes frontend/styles/globals.scss | 40 ++- frontend/types/Autonolas.ts | 2 +- frontend/utils/delay.ts | 2 + package.json | 4 +- pyproject.toml | 2 +- 69 files changed, 1287 insertions(+), 494 deletions(-) create mode 100644 docs/dev/macos-setup.md create mode 100644 docs/dev/rpcs.md create mode 100644 docs/dev/ubuntu-setup.md create mode 100644 docs/dev/windows-setup.md delete mode 100644 electron/assets/icons/tray-logged-out.png delete mode 100644 electron/assets/icons/tray-low-gas.png delete mode 100644 electron/assets/icons/tray-paused.png delete mode 100644 electron/assets/icons/tray-running.png create mode 100644 electron/assets/icons/tray/logged-out.png create mode 100644 electron/assets/icons/tray/logged-out@2x.png create mode 100644 electron/assets/icons/tray/logged-out@3x.png create mode 100644 electron/assets/icons/tray/low-gas.png create mode 100644 electron/assets/icons/tray/low-gas@2x.png create mode 100644 electron/assets/icons/tray/low-gas@3x.png create mode 100644 electron/assets/icons/tray/paused.png create mode 100644 electron/assets/icons/tray/paused@2x.png create mode 100644 electron/assets/icons/tray/paused@3x.png create mode 100644 electron/assets/icons/tray/running.png create mode 100644 electron/assets/icons/tray/running@2x.png create mode 100644 electron/assets/icons/tray/running@3x.png create mode 100644 electron/components/PearlTray.js delete mode 100644 electron/icons.js create mode 100644 frontend/components/AddressLink.tsx create mode 100644 frontend/components/InfoTooltip.tsx create mode 100644 frontend/components/YourWalletPage/Titles.tsx create mode 100644 frontend/components/YourWalletPage/YourAgent.tsx create mode 100644 frontend/components/YourWalletPage/YourWallet.tsx create mode 100644 frontend/components/YourWalletPage/styles.ts create mode 100644 frontend/components/styled/CustomModal.tsx create mode 100644 frontend/constants/width.ts create mode 100644 frontend/public/NFT.png create mode 100644 frontend/public/agent-wallet.png create mode 100644 frontend/utils/delay.ts diff --git a/.github/workflows/release_win.yml b/.github/workflows/release_win.yml index de00e3d13..55bba7b59 100644 --- a/.github/workflows/release_win.yml +++ b/.github/workflows/release_win.yml @@ -8,6 +8,13 @@ on: jobs: build-windows: runs-on: windows-latest + strategy: + matrix: + include: + - env: "production" + rpc: "https://rpc-gate.autonolas.tech/gnosis-rpc/" + - env: "development" + rpc: "https://virtual.gnosis.rpc.tenderly.co/78ca845d-2b24-44a6-9ce2-869a979e8b5b" defaults: run: shell: bash @@ -33,15 +40,15 @@ jobs: - name: Install dependencies run: poetry install - - name: install node deps + - name: install all deps run: yarn install-deps - name: set env vars to prod.env env: - NODE_ENV: production - DEV_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + NODE_ENV: ${{ matrix.env }} + DEV_RPC: ${{ matrix.rpc }} IS_STAGING: ${{ github.ref != 'refs/heads/main' && 'true' || 'false' }} - FORK_URL: https://rpc-gate.autonolas.tech/gnosis-rpc/ + FORK_URL: ${{ matrix.rpc }} GH_TOKEN: ${{ secrets.github_token}} run: | echo NODE_ENV=$NODE_ENV >> prod.env diff --git a/.gitleaks.toml b/.gitleaks.toml index 7dbdf15ee..975e353c4 100755 --- a/.gitleaks.toml +++ b/.gitleaks.toml @@ -534,8 +534,12 @@ regex = '''(?i)((key|api|token|secret|password)[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\| entropy = 3.7 secretGroup = 4 - [allowlist] -description = "global allow lists" -regexes = ['''219-09-9999''', '''078-05-1120''', '''(9[0-9]{2}|666)-\d{2}-\d{4}'''] -paths = ['''(.*?)(jpg|gif|doc|pdf|bin|svg|socket)$'''] +description = "allowlist" +regexTarget = "match" +regexes = [ + '''\b(0x)?[0-9a-fA-F]{40}\b''', # ignore evm public keys + '''219-09-9999''', # global allow lists + '''078-05-1120''', + '''(9[0-9]{2}|666)-\d{2}-\d{4}''' +] \ No newline at end of file diff --git a/.nvmrc b/.nvmrc index 922f10a16..2edeafb09 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.x +20 \ No newline at end of file diff --git a/README.md b/README.md index 76b4ede77..ebb5de653 100644 --- a/README.md +++ b/README.md @@ -2,223 +2,47 @@ Pearl -Pearl is an application used to run autonomous agents powered by the OLAS Network. - -## Technologies Used - -- Electron -- NodeJS (20.11 LTS) -- AntD (^5) -- NextJS (^14) -- Javascript / TypeScript -- Python (3.10) -- Poetry (^1.7.1) +A cross-platform desktop application used to run autonomous agents powered by the OLAS Network. ## Getting Started -### Installing system dependencies - -The following installation steps assume you have the following on each OS: - -- Linux: a debian based operating system such as Ubuntu with `apt` to install packages. -- MacOS: [Homebrew](https://brew.sh/) - -

NodeJS

- -NodeJS is best installed and managed through NVM. It allows you to install and select specific versions of NodeJS. Pearl has been built using version 20 LTS. - -
Linux
- -```bash -sudo apt install curl -curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash -source ~/.bashrc -nvm install --lts -nvm use --lts -``` - -
MacOS
- -```bash -brew install nvm -``` - -Set up NVM for console usage. Dependant on the shell, you should edit the config file to contain the following code. -If you're using Bash or Zsh, you might add them to your `~/.bash_profile`, `~/.bashrc`, or `~/.zshrc` file: - -```bash -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm -[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion -``` - -Close and reopen Terminal, or run `source ~/.bash_profile`, `source ~/.zshrc`, or `source ~/.bashrc` to reload the shell configuration. - -Verify your installation by running `nvm --version`. Then run: - -```bash -nvm install --lts -nvm use --lts -``` - -
- -

Yarn

- -Yarn is the package manager used for dependency management of the Electron app and NextJS frontend. - -```bash -npm install --global yarn -``` -
- -

Python

- -
Linux
- -```bash -sudo apt install python3 -``` - -
MacOS
- -```bash -brew install python -``` - -
- -

PIPX

- -
Linux
- -```bash -sudo apt install pipx -``` - -
MacOS
- -```bash -brew install pipx -``` - -
- -

Poetry

- -Poetry is used on the backend to install and manage dependencies, and create a virtual environment for the backend API. - -```bash -pipx install poetry -``` - -If promoted to run `pipx ensurepath`, run it. - -
- -

Setting up your .env file

- -Create an `.env` file in the root directory, or rename `.env.example` to `.env`. -Then set the following environment variables. - -

NODE_ENV

- -For development usage, set `NODE_ENV=development`. -For production usage, set `NODE_ENV=production`. - -
- -

FORK_URL

- -**This variable is required for both development and production.** -**Must be a Gnosis Mainnet RPC URL.** - -- In `development` this RPC url is only used if/when forking mainnet with Hardhat (covered later). This process allows you to test without losing funds. -- In `production` this RPC URL is used as the main RPC for Pearl. - -You can get a Gnosis RPC from [Nodies](https://www.nodies.app/). - -Once you have a Gnosis Mainnet RPC URL, set `FORK_URL=YOUR_RPC_URL_HERE` in your .env file. - -Note: this must be an external RPC. If you decide to use Hardhat for testing on a mainnet fork, do _not_ set your Hardhat Node URL here. -
- -

DEV_RPC

- -This environment variable is only used when `NODE_ENV=development` is set. - -In `development` mode, it is used throughout Pearl as the main RPC. - -If you're using Hardhat, you can set `DEV_RPC=http://localhost:8545`. -Or, you can use another, external RPC URL that wish to test on, ensuring that the chain ID is 100 (Gnosis Mainnet's chain ID). - -
- -

Installing project dependencies

- -Run the following command to install all project dependencies. - -```bash -yarn install-deps -``` - -

Running the application

- -Provided your system dependencies are installed, environment variables are set, and your RPC is running. - -You can start Pearl by running the following command in the root directory: - -```bash -yarn dev -``` - -This will run Electron, which launches the NextJS frontend and the Python backend as child processes. - -

Chain forking (for development)

- -In the interest of protecting your funds during development, you can run a forked version of Gnosis Mainnet. - -There are two recommended options, choose one: - -

Tenderly (preferred)

+### For Users -[Tenderly](https://tenderly.co/) is a service with a plethora of useful blockchain development tools. The tool required here gives you the ability to **fork networks**. +#### Downloading the latest release -You can also monitor all transactions, and fund your accounts with any token that you please. +**Note:** The release pages also contain Source Code `.zip` files and `dev-` prefixed builds. These are not intended for general use. Ignore them unless you're a developer! -1. Signup to [Tenderly](https://tenderly.co/), and select the plan you desire. **The Free plan should suffice for most users**. -2. Go to *Forks* under the *Development* tab -- in the left sidebar of your dashboard. -3. Click *Create Fork*, select "Gnosis Chain" as the network, and use Chain ID `100`. -4. Copy the RPC url into the appropriate .env variables in your repository. (Recommended to set both `FORK_URL` & `DEV_RPC` to this RPC url during development). -5. Click the *Fund Accounts* button to fund your accounts with XDAI (native token) and [OLAS](https://gnosisscan.io/token/0xce11e14225575945b8e6dc0d4f2dd4c570f79d9f). +- Go to the [Releases](https://github.com/valory-xyz/olas-operate-app/releases) page. +- Download the latest release for your operating system. + - If you're on Windows, download the `.exe` file. + - If you're on MacOS, download the `.dmg` file. + - Both Intel x64 and Apple Silicon ARM64 builds are available. +- Install the application by running the downloaded file. -
+### For Developers -

Hardhat

-Note: using Hardhat will result in the loss of chain state once your Hardhat node is turned off. +#### Setting up your development environment -Run the following command in the root of your project folder to start your Hardhat node: +- [Ubuntu Setup Guide](docs/dev/ubuntu-setup.md) +- [MacOS Setup Guide](docs/dev/macos-setup.md) +- [Windows Setup Guide](docs/dev/windows-setup.md) -```bash -npx hardhat node -``` +#### Setting up a development RPC endpoint -**Once Hardhat is running, you will be able to use `http://localhost:8545` as your development RPC.** +- [RPC Setup Guide](docs/dev/rpcs.md) -
Funding your addresses with Hardhat
+## Project Dependencies -There are scripts to fund addresses during testing/development: +There are three parts to the project: the Electron app (CommonJS), the NextJS frontend (TypeScript), and the Python backend/middleware. -- XDAI funding: +- [Electron dependencies](package.json) +- [Frontend dependencies](package.json) +- [Backend dependencies](backend/pyproject.toml) -```bash -poetry run python scripts/fund.py 0xYOURADDRESS -``` +## License -- OLAS funding: +- [Apache 2.0](LICENSE) -```bash -poetry run python scripts/transfer_olas.py PATH_TO_KEY_CONTAINING_OLAS ADDRESS_TO_TRANSFER AMOUNT -``` +## Security -
\ No newline at end of file +- [Security Policy](SECURITY.md) diff --git a/docs/dev/macos-setup.md b/docs/dev/macos-setup.md new file mode 100644 index 000000000..0193e72e1 --- /dev/null +++ b/docs/dev/macos-setup.md @@ -0,0 +1,97 @@ +# Setting up Pearl for development on MacOS + +### System dependencies + +## 1. Brew + +Brew is a package manager for MacOS, allowing you to install packages from the command line. + +```bash +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +``` + +## 2. Node Version Manager (NVM) + +NVM is a version manager for Node.js, allowing you to switch between different versions of Node.js. + +```bash +brew install nvm +``` + +Set up NVM for console usage. Dependant on the shell, you should edit the config file to contain the following code. + +If you're using Bash or Zsh, you might add them to your `~/.bash_profile`, `~/.bashrc`, or `~/.zshrc` file: + +```bash +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion +``` + +Close and reopen Terminal, or run `source ~/.bash_profile`, `source ~/.zshrc`, or `source ~/.bashrc` to reload the shell configuration. + +## 3. Node.js + +```bash +nvm install +nvm use +``` + +## 4. Yarn + +Yarn is the package manager used for dependency management of the Electron app and NextJS frontend. + +```bash +npm install --global yarn +``` + +## 5. Python + +Use Python 3.10 for the project. + +```bash +brew install python@3.10 +``` + +## 6. Pipx + +```bash +brew install pipx +``` + +## 7. Poetry + +```bash +pipx install poetry +``` + +If prompted to add the `poetry` command to your shell's config file, accept the prompt. + +### Installing project dependencies + +The `install-deps` script will install the dependencies for all parts of the project. +The Electron app, the NextJS frontend, and the Python backend. + +```bash +yarn install-deps +``` + +### Setup the .env file + +Duplicate the `.env.example` file and rename it to `.env`. + +```bash +cp .env.example .env +``` + +Then fill in the required environment variables. + +- `NODE_ENV` - Set to `development` for development. `production` is only used for production builds built through the release script. +- `FORK_URL` - Set to your desired HTTP RPC endpoint. +- `DEV_RPC` - Set to the same value as `FORK_URL`. + +### Run the project + +```bash +yarn dev +``` diff --git a/docs/dev/rpcs.md b/docs/dev/rpcs.md new file mode 100644 index 000000000..bbd4502d8 --- /dev/null +++ b/docs/dev/rpcs.md @@ -0,0 +1,43 @@ +# Acquiring RPC Endpoints for Development + +## Tenderly + +We use Tenderly to fork the Gnosis Mainnet chain for development purposes. This allows us to interact with the chain without risking real funds. + +### 1. Create a Tenderly Account + +Go to [Tenderly](https://tenderly.co/) and create an account. + +### 2. Create a Project + +Create a new project in Tenderly. + +### 3. Fork the Gnosis Mainnet + +1. Go to the _Forks_ section under the _Development_ tab in your Tenderly dashboard. + +2. Click _Create Fork_. + +3. Select "Gnosis Chain" as the network. + +4. Use Chain ID `100`. + +5. Copy the RPC URL provided by Tenderly. + +### 4. Set the RPC URL + +Set the `FORK_URL` and `DEV_RPC` environment variables in your `.env` file to the RPC URL provided by Tenderly. + +### 5. Fund Your Accounts + +Click the _Fund Accounts_ button in Tenderly to fund your accounts with XDAI (native token) and [OLAS](https://gnosisscan.io/token/0xce11e14225575945b8e6dc0d4f2dd4c570f79d9f). + +### 6. Keeping Your Fork Up-to-Date + +It is important to update your fork periodically to ensure that your forked chain is up-to-date with mainnet. You can do this by creating a new fork in Tenderly and updating your `FORK_URL` and `DEV_RPC` environment variables. + +Alternatively, you can try the Tenderly's virtual testnet feature, which can automatically update your fork for you relative to mainnet. Though, this sometimes results in instability. + +## Hardhat (deprecated) + +Hardhat is a local alternative to Tenderly for forking EVM chains. It is useful for development purposes, though the chain state is lost once the Hardhat node is turned off. diff --git a/docs/dev/ubuntu-setup.md b/docs/dev/ubuntu-setup.md new file mode 100644 index 000000000..47875b685 --- /dev/null +++ b/docs/dev/ubuntu-setup.md @@ -0,0 +1,79 @@ +# Setting up Pearl for development on Ubuntu + +### System dependencies + +## 1. Node Version Manager (NVM) + +NVM is a version manager for Node.js, allowing you to switch between different versions of Node.js. + +```bash +sudo apt install curl +curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash +source ~/.bashrc +``` + +## 3. Node.js + +```bash +nvm install +nvm use +``` + +## 4. Yarn + +Yarn is the package manager used for dependency management of the Electron app and NextJS frontend. + +```bash +npm install --global yarn +``` + +## 5. Python + +Use Python 3.10 for the project. + +```bash +sudo apt install python3.10 +``` + +## 6. Pipx + +```bash +sudo apt install pipx +``` + +## 7. Poetry + +```bash +pipx install poetry +``` + +If prompted to add the `poetry` command to your shell's config file, accept the prompt. + +### Installing project dependencies + +The `install-deps` script will install the dependencies for all parts of the project. +The Electron app, the NextJS frontend, and the Python backend. + +```bash +yarn install-deps +``` + +### Setup the .env file + +Duplicate the `.env.example` file and rename it to `.env`. + +```bash +cp .env.example .env +``` + +Then fill in the required environment variables. + +- `NODE_ENV` - Set to `development` for development. `production` is only used for production builds built through the release script. +- `FORK_URL` - Set to your desired HTTP RPC endpoint. +- `DEV_RPC` - Set to the same value as `FORK_URL`. + +### Run the project + +```bash +yarn dev +``` diff --git a/docs/dev/windows-setup.md b/docs/dev/windows-setup.md new file mode 100644 index 000000000..c56a19727 --- /dev/null +++ b/docs/dev/windows-setup.md @@ -0,0 +1,98 @@ +# Setting up Pearl for development on Windows + +- Development on Windows is experimental, but included here for reference. +- Please report any issues you encounter while setting up the project on Windows. +- You must be able to run PowerShell as an administrator to install the system dependencies. + +### Installing system dependencies + +## 1. Chocolatey + +Chocolatey is a package manager for Windows, allowing you to install packages from the command line. + +```powershell +# run as administrator +# https://chocolatey.org/install + +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) +``` + +## 2. Node Version Manager (NVM) + +NVM is a version manager for Node.js, allowing you to switch between different versions of Node.js. + +```powershell +# run as administrator +choco install nvm +``` + +## 3. Node.js v20 + +```powershell +# run as administrator +nvm install 20 +nvm use 20 +``` + +## 4. Yarn + +Yarn is the package manager used for dependency management of the Electron app and NextJS frontend. + +```powershell +npm install --global yarn +``` + +## 5. Python 3.10 + +```powershell +# run as administrator +choco install python3.10 +``` + +## 6. Pipx + +```powershell +# run as administrator +python3.10 -m pip install pipx +``` + +## 7. Poetry + +```powershell +# run as administrator +pipx install poetry +``` + +If prompted to add `poetry` to your PATH, follow the prompt. + +### Installing project dependencies + +The `install-deps` script will install the dependencies for all parts of the project. +The Electron app, the NextJS frontend, and the Python backend. + +```powershell +# run from the project root +poetry shell +yarn install-deps +``` + +### Setup the .env file + +Duplicate the `.env.example` file and rename it to `.env`. + +```powershell +# run from the project root +cp .env.example .env +``` + +Then fill in the required environment variables. + +- `NODE_ENV` - Set to `development` for development. `production` is only used for production builds built through the release script. +- `FORK_URL` - Set to your desired HTTP RPC endpoint. +- `DEV_RPC` - Set to the _same_ value as `FORK_URL`. + +### Run the project + +```powershell +yarn dev +``` diff --git a/electron/assets/icons/tray-logged-out.png b/electron/assets/icons/tray-logged-out.png deleted file mode 100644 index 16311b50e0b2f7b723fc121dd3655f3852a1f9b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1336 zcmV-81;_e{P)gg@h0~<6LJYkjB0-D#bz|1CL-OP=$R38HSH+Vrz5r1emcfw6gX9QzJ0$GEEzf$77GJKr30OQLmqUx3TdTtnmba4NOsF>1k!4 ztbz3@hG#FHKi3~WejFB+QOH7#M#F%li|7P@L$_|2<`qVU2!eMrW}Hs|q$7NIuIskq za}Ote%?z{PD?^#MGZV1D8ULF?}B zZlqr5S+#l}0Q}%J7~kF|6ic`)3}u8V7#$1BFG0{w>1*7$ZjS)WqHXFNs@>uE@$u&O<$5QQYnJb?BI0mAnad4^oUlH{m^t*x!tdeNO2 zo4L#P{f@d982uiu>*IYirx2%pMu;I#^)+-THSV&=B`nNODGU(iaH*agdca|8c9#04 zBr}5oM=0e-Z9j-n6NetKaW)Byd`b(%>lL{sFTtT~oMPQhuS2aj6~Rn z3n+{%0;-3wpG#ib+uH^r@^XKFznLeLq6sD9Qr5X70e7$hxo&{(^Yn#tiz|gY!t$+q zdwZC%7Ipxkd!s-IEhgIxic&+XR9e^9*Q2?!RIG)t)4{M*A$j-;zkwH2rvGnIF?*6(Gpbv8m|9CAqR`Yq zU;_ic0F;g|L{F{a8GGBn71cAs)SIHIV&&f;RWTga1p!$IkJdy4Y-&4nbOe30DFZ6V zE3jYf&o!*%c;V*n1FG_cw9Z_|zO3|#pK0!2NvCrwI*lzri*2h~l;V-|}n*unb&kG)J* zVGPk91GS`b=n=5P)`9a`Dv-ZIIw`49p^n=MDiJxqQEMwiB)dg&lTq-9Bb9Lq?q5C1 u7?X7louqVCGqwb|jiL^T^usz4M)VojcvJy-xAxuu0000HVEdW>2hv!eR{+l2SKK z^HHpU)&j_~teB88Ce}cj_`+x{76R#bEU^X(iT^>muE&zeWLDF(pDif`zW?6b+Ejg3S2OdiAhv^DUl76jLXrZwB`wjq|Fr7V<9r{8`R4*vpc44^QJUyQ7n z9}K|im>**JHnFu8d+7C=i|Sa&LfLFqho;jphdkh}vzg2lM!IF1mlI)9KEjdq@L_a1 zoubRfD3qF3T*O*)0XagipyV6^tL}duU1Ve96d?9}EDaa5BBKf!CHybU12rE|CUfHl z^9(TXAu-0_+^rymE~vq9xN8{3YDqMc$sEIPPQ{uC@@lUkbJm)`#K@h)eEW!$cVbO6 z91g2^l_5JHv?egh67hHq{?Tf8I=`y_={u=Z>PO_9?T3d4V;V0N#^doE)(o&_ay-mW zh`JZ}EFtpFr}4@u!pew>J(wg~Q*DZBJFCvi}6V4A=^>(-G0p>X}JCqToJSvO%#WYJky!xM=&Iuh@jLStn5{Z=6 z1&#s(&o^8X(ln3HFsV|u?G93&Wzy*nQvt!@Dp-^QpeLV^vZ|gptks|e?KCh3B(Tdj z9>lN!=OL@&{F?CF5eb>@7&+`jLlT8mtIq&2Bw^+{(0deEqmd`i@F;|r8tNb#jk?ww z?@5T3!dp?-!biWx(VgSH_Y9C^KVw-<>FaCA-@-KVbzu9Ww`}TPzgH|IdDfczw&G2}*D%8x_n~{qq3#s74Whe3qt}XUTE@ zJy}SIOGHP>0X88x<<&H$^Rn%oo;v69ecu_%2Ab%#Mn^{g#Fay#mJ-JXe9E5d=i~Vbw ng-|HOqsz~e1K+Cq+m!zR)h&o9IMXb?00000NkvXXu0mjfdoiS{ diff --git a/electron/assets/icons/tray-paused.png b/electron/assets/icons/tray-paused.png deleted file mode 100644 index 86a3b150164d386ee75d3ae9e6a32f360ed43d91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1312 zcmV+*1>gFKP)7~ivOrL zL?BYDt9yu!EL1EMUjMbS@*dV0LSYeGlv(L87=ShL ze1zreTsE7&>i0W~>R8A^#bVKfrUQ?IzofS=TGk0xrYpqpL>T7-1kw&}9NV@lijT68 z8%AXjYt04Z3q667BM5A$eR5rLb@c!sc0(*}1zMBQfQ%~kx95SH56H64!(eU!20j$V zG=jT3O`!rc9F4Xd$GKY(wJhr$;^u(GM3C3~4>D(+nOYd>&0)S>WXc;B6OBfr27YRg zU7mJkYL?|PnI__++q3Nt`aZ?Z#>U1o)SQ2=uCAOYUQ(FJWJ)+Q#F>eEs6HX<)^J-z z<{d@x@(5uyWW^3lS4Mhog@V)Mc*YZnju?-n=@AnZJtpAdDy(_|86^nc8w*i6J3H&@ zFSM3So(lv&WVL#yrvYFAm&sH{nv$zrsxLxRLwL+Qd?i7QYmFU@0}RyYP@y* zEMoL;xb6tQJGTIFnrB?M!$WfoF@@Gm=DCE)`V@)*iaEU0zQ1%3hm{F0%}qgJCMAxm zwVxFYJq2b7OcyxFwEZ7ph4^_wu9;Tg&^GFL-UvSjxPhKU0P=$iQKpuo_HHc1*fFxB z>I0h)g7PFv>AY$i^&E;@fi+D9a2IqoH5@nOH_WoO)kYoKW>ZLxBB_*$DQA)98P-A5 zfqiy$kJ&7G+)FE77tJbv7v9+%JM%v?Ti z>mB^T0Vz-batu(=y=)ba1zDtlzyc}-aE)0|DELGhr(Jc*LO)R(L5R~oU|I$ z7wl{ z$K!hk`$B-wy32(0HF#@aZ{6jcesH+ zJ=(ZbGj=As2zt!k1Gs$PkFQgKFP&vXvd>|X^j%d_1D14~5Zh{~S09n8=Y`i%vVQ^g W3_x;J3jyZ<0000P)o*;0Sj$)OP)DwtrAo>YRcIhNlNh(ogDv?iMx={$J zFx(|0c}!OkH3M9}1rNvp1o$IiCfOMbaeupeyWjqRjAcO8YV}~xFzPG=+F%(_j&t4f zya~&IGEqnfQDmGKSq7xB{~2XsA&`zounZ{2o;7b}%YP1CfW1m_Ize{FAXPeAwV zk;K`WL`oDkH;;fB3qvbu4=^ z5uBqam*Qp*)Gj1O^T z<`jm0NQ^~*dz2XggXe^0M22B>zc-Axi}s`@M*rrVw-70BSVlCR zPCNK%fwz^mCpF5-rBWC87>#ZFH+7z{v$M1FBXZ8ScXxMA(peH%DwRy^xyPQ+J(Qmi zb9MKD82m3Wg3K;qP>R^KHm1i-bi$%I1xVutgM>Tg(UKo<1Vz)T^ATfT~D z3=7aYc(vtJcz$nh&m^9~7&)w`A&J7OojHXlBw^-0w2uf7t{cfSYJj>bP61ylpnSIAVww*eZkz5<>F+`St=|3+jhFR0X7M2R*&Wjhn!*#!)C{9oi z-?RTxA)?#c+drYy5cv4HQZDP|O2t+yc-FM?SBDQ|&+8yEegG&3t`I%7iZ40`+_VAq zx*r56sK8|J$qFSYhQmccKo-KGHDux3iX$&j)y_PviCj1+2>@P+a@X?|r4(H8@?q;lvG zu>ID7^H2%uBp)6g1`38OiJ>?-C>bx=QxuW{s9QW{Nw^3|h?ZIwWG8y0oN*R?Fs>bC zQZb7R diff --git a/electron/assets/icons/tray/logged-out.png b/electron/assets/icons/tray/logged-out.png new file mode 100644 index 0000000000000000000000000000000000000000..6f26a5e1c734b781c70c13c56413ed890acbba74 GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBIR;M`$B+uf-brT#n+yb6ug`CG_v(<%U@vKK z&re_ta$4h{b9izPW61*57iVXeH0(aiotDJ0Z)U#Q>^FIFb!j5kx*`qE1{|7ls7pfB zYXWaBYK4K|swK()6w`h5vtns>)*7==3T9)yanN7ca{n?9EbKRa~ zu6yW~^{YN0;rb1&3t<<}7JW{*X7XW<3sd!vh-MsW&kNz3$wDUGIje9kk zgg4&3^u2V?xtjQ$PLr8S^YvD({LTKTz`b7Mv&DsdNBE_hEcWFul9&z*8wO8TKbLh* G2~7YPK#q?9 literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/logged-out@2x.png b/electron/assets/icons/tray/logged-out@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8748464f0736dbceb44fa2def24bbbd455c64bca GIT binary patch literal 671 zcmV;Q0$}}#P)7e1n*ZGNGfxoB(bRD5(M^RdR#C31D};8Y>$)jx961 znKzm2YFBTim6Yru3<>d=_=%3#M;IamVi#dBp&~*BAXLD=Z@~`QfhW8m4u~--0Sn#(&GggVTK=)o4)Yy5BCp~#2&QuMasBx~i2j$CEtgUjQ?5XSDbp$ZpRni0X zoi85V+ZR+9l0|`Xf7ySDst5FPFMRe$s!OqX1-d}5Kq8-O$Wh(pbv@7pu@W%HhQeI6 zzRP2P&ES$Q9Z|z#EiseJaIP0=c@$=B{d=ntUpFM{O3D` zznDfCG(V|PgP(mtFJg@D@4AuL1c4YxqO3*CP-2>zc54_^`#!8mY#WjL;Q>ATV67A4 zJ}mm)n6#aE+h4^o%Dp^szWcz>_fkGt%mO{2Kvm&|*d|zgnCvlRWR5*Y53o&Wm)!m@ zh!okz{V{XK8uSE%)s<*s>t1Lhgp>2l=5E1UYe*tbS#c@b0dMp3{002ovPDHLk FV1j7|9=HGi literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/logged-out@3x.png b/electron/assets/icons/tray/logged-out@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..b6b2ec8f6ea625db8dbfe8b29d1da624e6e0e17d GIT binary patch literal 1034 zcmV+l1oiugP)lJ06I2_tOi(jH*&tzpmI+)YNH=gcNSOe9=ng50WGShY!h3x0 z-K#5~@0U(@k^8$FEq1e6v7hkOGS0mW>LbU=2*A z%z${xv@COt%1+#|q9(&Fr4G67Mx^6*-69CVU=ggS26W<$-x06TChD{eUB& z;ihpa5(aK&sKQ8Ni&d$HY^FqaKGhBSzGQWg28P4LE=R!Xk+cvOPN z-)sGWeNNj9kb1;bC5A`f3mj()z)*LOM0f*(GVk-Scp`cVA3k7%Ru5oi9 z6>vbsa^1j1NMSxGxa*o{E!a|J;>0DM4~;rOnS_Gt6+MnSFKf8PP8F+0T4rIeTOK=D z!(zrP_#KrDrx3B<8eAoJ!1c~_T``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBIU!FM$B+uf*5HGJO%6Ofubk_rG{^=t$v*I} zztlLTAWR`_LD+&223ZeIyT2zd%c~upC!;Pi^X5mr?Ve_wekXGklh3Va;}9;IeV!wx zW#;4Dqa6}*?_A|izW&(x#8^0h~+l#s{Yt*P|vOi?$(H$-lMx}|AYSrwkPDQ znCtt#eqn;m%E)Nnx4)QH?6`E|xXSCwfX})b6OvUr4(`m@WIn;A<5E6{Df_E$@02UQ ZvhLYw>1F>U!4nu-44$rjF6*2UngAUZnGgT~ literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/low-gas@2x.png b/electron/assets/icons/tray/low-gas@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8de86da7f4aa526276b904ba9f7c2b9094cd7b56 GIT binary patch literal 735 zcmV<50wDc~P)SM|!aT53H>{qdZl49|%ViQkZkyC_42LY$xsu2e*+0F(;2^(VN4dEgC~#0Al# z6L1t>5 z6vBz4+Ke|cu1~)*b5P`IAr>|MPT5ItnBP+4KPrsM{GJ7m{J!2IWLASh@TvG}S2Nbs z=*n^K0eWxHH4zhg!^B`{t& zbFbF#k%?Aqw3IOxqZ?DD=ISP;)0lt4_gKy-8o-_B$$RS+gBXqaGxJLLM@E9*T+@de_z;FAzz^i_s RhwK0V002ovPDHLkV1g+aMMwYu literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/low-gas@3x.png b/electron/assets/icons/tray/low-gas@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..23e9a229fa3e83d0e309d269508a00dd9ac87f1b GIT binary patch literal 1075 zcmV-31kC%1P)CRQD=;pXM-Dr*c4DlHMC(rF>Sn02mC`vw$Mg1 zRnSL?K!JSVh2aHy zz``JC<16IH4jC4Tk3oyuVNrbr@*f=^Bsw=!j474kQ3Sq^JTIW5$Xn<#;Y&vs#0^s& zy_4U}`xN1A=IL(h;k!kLr; zbIJ&BC~3vy77hi!G*7rBh^t%Q#qAv5SYuy&NM zMuhk{p&xbl`={{q7unyvvCrr`8`I6L=@0o%X7J8aYy`~dnwXbET_L|u6Z4tZgxzmQ z*Yyk5@aP;j42I6(J@P{#e*es6j-nD~judC4UE-x-@`SQV6zGHu>acC}3C4P5&+81sK65E5L?VMulOclMTGu zymAWhI;siGtI;nI`FHEcY$Nj)L8$I&5Pz|I@a9usyhguRGp*_l3&Yes#yB>*kY@^M z4j5<28>ax@R2?=O6^5lQc}6Jc_x`4++c?h^!fzKsnZ7`#uv%fb%11G(z<3CZU21l? ziHx)S;4WPACp3vdO62EPlibU)@!VfLCeCBSxkD^x%$Ws+@qc9uRlLUOE literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/paused.png b/electron/assets/icons/tray/paused.png new file mode 100644 index 0000000000000000000000000000000000000000..4d13d7b7cbcf9fec6b13e720f1e0c19ca42d22a1 GIT binary patch literal 370 zcmV-&0ge8NP)mz`&3aumeh<0}Rci1WGt75G$|*qyp$bQX^6`3C(nO?wy`^oHM?eH{R~;=k1f&zz6WUrAd3XJ@Qd1ChDfg~%O6J`Y_@Rd+D z3q`-7pzN!2ZB>^M_Eu;4JzB9XO_nRk4_pWe*g5PLc8v4Q#D)_&=G>8bo2)bOThr2BK-#wMTrS~0)yc?29yrv Qwg3PC07*qoM6N<$f{@aaGynhq literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/paused@2x.png b/electron/assets/icons/tray/paused@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..eab10400a8208502eb13a9054e1ddd22cd59b80a GIT binary patch literal 694 zcmV;n0!jUeP)%=+1mW_ydzNRgyB5FJF-43zFSvHPUTl zkI!-@Z|2R7wd>WBwA%IUBM+a6Z;6+fh?mGiflTZn4<=Vct^ni;c=jWBf!)9p9uiBU zMG&wN{v-ay6Jbg0h%ND&c&B(R_D+09VN4Df;u-NZ@jdaUjPq)L6B`-3A=bo?#5W?u zAQMIcRcgGJ@p$zM<+Bjs1`|>AOs)l*0lSqLlah4>x6)iJB-TzaaLVTb$FeEIeqxNT z*e~KA;sv%vRm3mE55yDo9`}Xs#Ban?xTN&p>;8#&3wK?U;B(?D<`Zj`5C&NZ+v|kQ z$I$1#jN-QF$%zIoYvVg^mCs5A(gNeUQ1*=T9LIX{LX4GiK2mRrFeBQ;*d z_Ps~|<6H%OrJlL)@Y()HC`cX+-1)NoD?$$F?cSuu3t3%-;T@O)y#rQ$la3v>E1X3> ztP;>+U}3S^zT&~V^#d*k*7A^1sJ z?t#SSCRJf1TDam8W2mOrB1EIY<10G~2D`UZ|DmEW`OC>-roNs7UKMZc0?!Bom%Y3j zoQUOsuP@iWQu=Fsh?#^ev3;j?t8F8jL4WCfz}U}n3wI;lB?K`xctSJ?tMJ>%#V2k| zahC7217lDkoMVUZzn~BrvqhVgLXD07*qoM6N<$f)9i{r2qf` literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/paused@3x.png b/electron/assets/icons/tray/paused@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2e3983211a087218c9065b2325f73db2a492a6fd GIT binary patch literal 1049 zcmV+!1m^pRP)GT|;|> z70VlX$A1&=V}Q5f>jxZx4DB|KtwfG?XDGr*V)I3*InOh56r{OBNo;{O^h)`W1c^4W z_-%U63|fPC0fk)NHQEwn=9$}akvT|#660;9izUm9@g<``n+^X52G$TVVl3CFoVi^@ z@F6HLuHY0h1~6!w?kNPQC>etkR4IOZwlHWj;x(QbuW&f14xx(mEvz4B4gEy8jT{5z zjgPSI^n;(#E`R2E_fY;dJ4f3?(6wN}DgG^`fm`nb-R7vmiIAa9cy9Wy5iY<=bPdQc zY-Z}1;3>Y)Ncp`**Nvn>GC0n?l5p%78d8o9FqIJUC1#7T>+GR~V|IX)rmcN|bscGF zi0*J=9J2$m;sUzg^L+`s6B+Z#7s@S^aEt*3UzdC(187G!OcYYLu*RG<48}iZ_v7hr09*CJL4*}Zux*V3>PusQ~nzODfAxJ{|&k;{={^Ni8Je88mxUt TQ4i!s00000NkvXXu0mjfA@$QS literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/running.png b/electron/assets/icons/tray/running.png new file mode 100644 index 0000000000000000000000000000000000000000..858f061df2a613c3733b743d011ab4986e3731c0 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eB{(nyw$B+ufsllfOn+ybE4>r5MQMhN5#a`0j zo`0#aBw>xi8kUs|Rsq@{Uin%bxcjj6q)W%)*_Fw0o90hn)AHna+s*{DWJboHf`(J| z6W&>N&*Us-i{)oM%l7TaH@=gP4&2b6Y5uI)W&(l_{n(Jf| z5OcWq$(R4lGO@|pj?tdwr+a$}y_FyP%w(U{aN%N5>CrpE<;S-d*QKnR>HkTgNqFPk zN8trcdAZY_?>jXrrN2u1cj(_FHHED*Gk$8nl8e6G82{?Bx#6D^Y@)!RVDNPHb6Mw< G&;$S|PLx3a literal 0 HcmV?d00001 diff --git a/electron/assets/icons/tray/running@2x.png b/electron/assets/icons/tray/running@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..635ac5e0422d39bc5164547f1046b168140bb0a5 GIT binary patch literal 664 zcmV;J0%!e+P)o5>~AAbM+Zy+j4!VN@4>l?&W(2*O&RFnxF9p(gZgFs0IlvLpczzJY?yc#Q;wG*r` zyqPzd>`JRAX|?NZq#-Bn5?|00f02d^iP%CKT&jpv0Z0|_>sRmx-vci=Bo2rkjeu9- zE%6#ZgfVeWoDtuMpNendpUc>_uucv*;v?}tai4f5cHZp;u@c)mu_PW4cSMLoBAf&& zl)V&ty!(+FGZNtrJ(0C6t_8Xdzn2)jl68W5r>Pi8tZ%`gR=z24EN?ls4I4kPbK)iO z8H=I{;t6q&c(3N=;yWfjpiasFe(s0F57f`q1m6=sv5;63Ll|Ty>@N*ph@tO&9L1fX zB_}G>SsTA`uf|MNAT2Pi3xgIruW_Rn&%{}%!BaIZ7I&q5rJ5UdIaT%|_HRW37*8tb zKlPsr58v$_nt~Kip}t@CAEC(secZ2>J(JxP=stly&?k_~?-EKhwY)6{`oJpzb98Jh zR%;cH0lL8_nH%;hid$g?c##6jS?SjXK`g#fmB4UJJghO-hoJ^};1CI}%Zp^hm(bf?XH^K1^fcVAJa?u-%K3<0000{^bA~}Fy3Y$1BJpUVZaPV@i{*e z>Yje}^uWI_4y5RHPaRCwNfGfZFv08$0V&?XDE5fF@*%D89}QW;C{5JBgbXRQVUj#= z+bN`UPg|y<)j9-ueZ`90!o@k@LTJTGEtxb-h|#;P$FEq1?K4AR&;aDcM^-9?f>AIQ zGF!+YQ?tws3LCNJf#w-L&Ac5Gd3TvnPQe(sK_S=>s89~%7;?}JMuvh>zCn3hp@5?( z47QjKqmEaheCUKwJmwluW8{4WlSM9Iwh7;Q+99r(W_e)VhX`-Szn^ge zD!6G(c|ya@3}qNw*rY5qXE`%ZL6RLSVl`aqwcC$Du-PV;zg5tt;0)eG6!Ll3a9fa> zAX};@*T_J73Wox^fY%>X8caoaZv@`UKz55m2j-$-Pmwv~N~(lDb%a+cS~0nm$D<-V z{$A@J{1cho$NxaQV%9>N#Cy!Xe~0~rTu1n5oO>8Ulx_44n0tfI5<)`UVL$88^B1}M zU)lFT+gI!x8yow)r=R?+Y~xulFyTTNBn29rQeDOW?~wLB@!GWe9m8kp2~P27A3qIB zad?UH(1@=;yO^VBn3*!g2E!Kd*s%2^%tF@~uphJgeaQn2ro&Y*wl!$bR@*=4TDr^d zuW;P#P@fy5&j%e2>(Eh$9R;)4TFBMXM*}m>IYaF2MeIc9k8R}<-yF|?jmaj%SHl%T z`dzaEmi%{BMwT^FVI(wg)i4JQ`F^NlIk_;f>#)JdAfa0v7l(?e_-(@wD7ZuSi%{qk zPzc##qVP(g;EY({l|sSQ3R;{Mo`)IBXkhM-6efbketK+J5owLY*3BI9foO#Z*IETL zBfcV!aG^%j3H=n(x7uq=0P+%fQ6s*OBDxj&wh4aew03|~zmbvB6szP_n_3r0Px(%0 z`-D6yj0}5|>~D1|ey0)lq!wfi`6zOmQs$IzWd64=@biwJTbR>a#eC=7{sj4y_kg^I zi`-T>kQdyN6;eVUDZDh&-Y;4(71AFwLW*t4+eDul6F_6QA&Z0zo59G?4$nLToB|q< jLTHV{bZTotgOTwE3n8SQ3|CI+00000NkvXXu0mjfj} + */ +const trayIconPaths = { + [TrayIconStatus.LoggedOut]: `${appPath}/electron/assets/icons/tray/logged-out.png`, + [TrayIconStatus.LowGas]: `${appPath}/electron/assets/icons/tray/low-gas.png`, + [TrayIconStatus.Paused]: `${appPath}/electron/assets/icons/tray/paused.png`, + [TrayIconStatus.Running]: `${appPath}/electron/assets/icons/tray/running.png`, +}; + +/** Tray icons as native images + * @note macOS icons are resized + * @readonly + * @type {Record} */ +const trayIcons = Object.entries(trayIconPaths).reduce( + (acc, [status, path]) => ({ + ...acc, + [status]: (() => { + // Linux does not support nativeImage + if (isLinux) return path; + + // Windows and macOS support nativeImage + let trayIcon = Electron.nativeImage.createFromPath(path); + + if (isMac) { + // Resize icon for tray + trayIcon = trayIcon.resize(macTrayIconSize); + // Mark the image as a template image for MacOS to apply correct color + trayIcon.setTemplateImage(true); + } + + return trayIcon; + })(), + }), + {}, +); + +/** Cross-platform Electron Tray for Pearl, with context menu, icon, events. */ +class PearlTray extends Electron.Tray { + /** @param {() => Electron.BrowserWindow | null} activeWindowCallback */ + constructor(activeWindowCallback) { + // Set the tray icon to the logged-out state by default + super(trayIcons[TrayIconStatus.LoggedOut]); + + // Store the callback to retrieve the active window + this.activeWindowCallback = activeWindowCallback; + + this.setContextMenu(new PearlTrayContextMenu(activeWindowCallback)); + this.setToolTip('Pearl'); + + this.#bindClickEvents(); + this.#bindIpcListener(); + } + + #bindClickEvents = () => { + if (isWindows) { + isDev && logger.electron('binding windows click events to tray'); + // Windows: Handle single and double-clicks to show the window + this.on('click', () => this.activeWindowCallback()?.show()); + this.on('double-click', () => this.activeWindowCallback()?.show()); + this.on('right-click', () => this.popUpContextMenu()); + return; + } + isDev && + logger.electron('no click events bound to tray as not using win32'); + // macOS and Linux handle all clicks by displaying the context menu + // can show window by selecting 'Show app' on dropdown + // or clicking the app icon in the dock + }; + + #bindIpcListener = () => { + isDev && logger.electron('binding ipc listener for tray icon status'); + Electron.ipcMain.on('tray', (_event, status) => { + isDev && logger.electron('received tray icon status:', status); + switch (status) { + case TrayIconStatus.LoggedOut: { + this.setImage(trayIcons[TrayIconStatus.LoggedOut]); + break; + } + case TrayIconStatus.Running: { + this.setImage(trayIcons[TrayIconStatus.Running]); + break; + } + case TrayIconStatus.Paused: { + this.setImage(trayIcons[TrayIconStatus.Paused]); + break; + } + case TrayIconStatus.LowGas: { + this.setImage(trayIcons[TrayIconStatus.LowGas]); + break; + } + default: { + logger.electron('Unknown tray icon status:', status); + } + } + }); + }; +} + +/** + * Builds the context menu for the tray. + * @param {() => Electron.BrowserWindow | null} activeWindowCallback - A callback to retrieve the active window. + * @returns {Electron.Menu} The context menu for the tray. + */ +class PearlTrayContextMenu { + constructor(activeWindowCallback) { + return Electron.Menu.buildFromTemplate([ + { + label: 'Show app', + click: () => activeWindowCallback()?.show(), + }, + { + label: 'Hide app', + click: () => activeWindowCallback()?.hide(), + }, + { + label: 'Quit', + click: async () => { + Electron.app.quit(); + }, + }, + ]); + } +} + +module.exports = { PearlTray }; diff --git a/electron/icons.js b/electron/icons.js deleted file mode 100644 index 7c6c72e66..000000000 --- a/electron/icons.js +++ /dev/null @@ -1,30 +0,0 @@ -const { nativeImage } = require('electron'); - -const TRAY_ICONS_PATHS = { - LOGGED_OUT: `${__dirname}/assets/icons/tray-logged-out.png`, - LOW_GAS: `${__dirname}/assets/icons/tray-low-gas.png`, - PAUSED: `${__dirname}/assets/icons/tray-paused.png`, - RUNNING: `${__dirname}/assets/icons/tray-running.png`, -}; - -const TRAY_ICONS = { - LOGGED_OUT: nativeImage.createFromPath(TRAY_ICONS_PATHS.LOGGED_OUT), - LOW_GAS: nativeImage.createFromPath(TRAY_ICONS_PATHS.LOW_GAS), - PAUSED: nativeImage.createFromPath(TRAY_ICONS_PATHS.PAUSED), - RUNNING: nativeImage.createFromPath(TRAY_ICONS_PATHS.RUNNING), -}; - -try { - if (process.platform === 'darwin') { - // resize icons for macOS - const size = { width: 16, height: 16 }; - TRAY_ICONS.LOGGED_OUT = TRAY_ICONS.LOGGED_OUT.resize(size); - TRAY_ICONS.LOW_GAS = TRAY_ICONS.LOW_GAS.resize({ width: 16, height: 16 }); - TRAY_ICONS.PAUSED = TRAY_ICONS.PAUSED.resize({ width: 16, height: 16 }); - TRAY_ICONS.RUNNING = TRAY_ICONS.RUNNING.resize({ width: 16, height: 16 }); - } -} catch (e) { - console.log('Error resizing tray icons', e); -} - -module.exports = { TRAY_ICONS_PATHS, TRAY_ICONS }; diff --git a/electron/install.js b/electron/install.js index b135cacd2..8b2eb64cd 100644 --- a/electron/install.js +++ b/electron/install.js @@ -14,7 +14,7 @@ const homedir = os.homedir(); * - use "" (nothing as a suffix) for latest release candidate, for example "0.1.0rc26" * - use "alpha" for alpha release, for example "0.1.0rc26-alpha" */ -const OlasMiddlewareVersion = '0.1.0rc138'; +const OlasMiddlewareVersion = '0.1.0rc145'; const path = require('path'); const { app } = require('electron'); diff --git a/electron/main.js b/electron/main.js index d9769df1c..5b1c5ac96 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1,8 +1,6 @@ const { app, BrowserWindow, - Tray, - Menu, Notification, ipcMain, dialog, @@ -15,18 +13,17 @@ const os = require('os'); const next = require('next'); const http = require('http'); const AdmZip = require('adm-zip'); -const { TRAY_ICONS, TRAY_ICONS_PATHS } = require('./icons'); const { setupDarwin, setupUbuntu, setupWindows, Env } = require('./install'); const { paths } = require('./constants'); const { killProcesses } = require('./processes'); const { isPortAvailable, findAvailablePort } = require('./ports'); -const { PORT_RANGE, isWindows, isMac } = require('./constants'); -const { macUpdater } = require('./update'); +const { PORT_RANGE } = require('./constants'); const { setupStoreIpc } = require('./store'); const { logger } = require('./logger'); const { isDev } = require('./constants'); +const { PearlTray } = require('./components/PearlTray'); // Attempt to acquire the single instance lock const singleInstanceLock = app.requestSingleInstanceLock(); @@ -65,17 +62,17 @@ let appConfig = { }, }; -/** - * @type {BrowserWindow} - */ -let mainWindow; +/** @type {Electron.BrowserWindow | null} */ +let mainWindow = null; +/** @type {Electron.BrowserWindow | null} */ +let splashWindow = null; + +/** @type {Electron.Tray | null} */ +let tray = null; + +let operateDaemon, operateDaemonPid, nextAppProcess, nextAppProcessPid; -let tray, - splashWindow, - operateDaemon, - operateDaemonPid, - nextAppProcess, - nextAppProcessPid; +const getActiveWindow = () => splashWindow ?? mainWindow; function showNotification(title, body) { new Notification({ title, body }).show(); @@ -99,82 +96,10 @@ async function beforeQuit() { } tray?.destroy(); - mainWindow?.destroy(); splashWindow?.destroy(); + mainWindow?.destroy(); } -const getUpdatedTrayIcon = (iconPath) => { - const icon = iconPath; - if (icon.resize) { - icon.resize({ width: 16 }); - icon.setTemplateImage(true); - } - - return icon; -}; - -/** - * Creates the tray - */ -const createTray = () => { - const trayPath = getUpdatedTrayIcon( - isWindows || isMac ? TRAY_ICONS.LOGGED_OUT : TRAY_ICONS_PATHS.LOGGED_OUT, - ); - tray = new Tray(trayPath); - - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Show app', - click: () => mainWindow?.show(), - }, - { - label: 'Hide app', - click: () => mainWindow?.hide(), - }, - { - label: 'Quit', - click: () => app.quit(), - }, - ]); - tray.setToolTip('Pearl'); - tray.setContextMenu(contextMenu); - - ipcMain.on('tray', (_event, status) => { - const isSupportedOS = isWindows || isMac; - switch (status) { - case 'low-gas': { - const icon = getUpdatedTrayIcon( - isSupportedOS ? TRAY_ICONS.LOW_GAS : TRAY_ICONS_PATHS.LOW_GAS, - ); - tray.setImage(icon); - break; - } - case 'running': { - const icon = getUpdatedTrayIcon( - isSupportedOS ? TRAY_ICONS.RUNNING : TRAY_ICONS_PATHS.RUNNING, - ); - tray.setImage(icon); - - break; - } - case 'paused': { - const icon = getUpdatedTrayIcon( - isSupportedOS ? TRAY_ICONS.PAUSED : TRAY_ICONS_PATHS.PAUSED, - ); - tray.setImage(icon); - break; - } - case 'logged-out': { - const icon = getUpdatedTrayIcon( - isSupportedOS ? TRAY_ICONS.LOGGED_OUT : TRAY_ICONS_PATHS.LOGGED_OUT, - ); - tray.setImage(icon); - break; - } - } - }); -}; - const APP_WIDTH = 460; /** @@ -227,23 +152,23 @@ const createMainWindow = async () => { mainWindow.setMenuBarVisibility(true); ipcMain.on('close-app', () => { - mainWindow.close(); + mainWindow?.close(); }); ipcMain.on('minimize-app', () => { - mainWindow.minimize(); + mainWindow?.minimize(); }); app.on('activate', () => { - if (mainWindow.isMinimized()) { - mainWindow.restore(); + if (mainWindow?.isMinimized()) { + mainWindow?.restore(); } else { - mainWindow.show(); + mainWindow?.show(); } }); ipcMain.on('set-height', (_event, height) => { - mainWindow.setSize(width, height); + mainWindow?.setSize(width, height); }); ipcMain.on('show-notification', (_event, title, description) => { @@ -516,7 +441,7 @@ ipcMain.on('check', async function (event, _argument) { event.sender.send('response', 'Launching App'); await createMainWindow(); - createTray(); + tray = new PearlTray(getActiveWindow); } catch (e) { logger.electron(e); new Notification({ @@ -564,11 +489,6 @@ app.once('ready', async () => { createSplashWindow(); }); -// UPDATER EVENTS -macUpdater.on('update-downloaded', () => { - macUpdater.quitAndInstall(); -}); - // PROCESS SPECIFIC EVENTS (HANDLES NON-GRACEFUL TERMINATION) process.on('uncaughtException', (error) => { logger.electron('Uncaught Exception:', error); diff --git a/electron/update.js b/electron/update.js index 3946655a3..fe71d90b8 100644 --- a/electron/update.js +++ b/electron/update.js @@ -2,15 +2,26 @@ const { publishOptions } = require('./constants'); const electronUpdater = require('electron-updater'); const logger = require('./logger'); -const macUpdater = new electronUpdater.MacUpdater({ +const updateOptions = { ...publishOptions, - channels: ['latest', 'beta', 'alpha'], // automatically update to all channels + // token is not required for macUpdater as repo is public, should overwrite it to undefined + token: undefined, + channels: ['latest', 'beta', 'alpha'], +}; + +const macUpdater = new electronUpdater.MacUpdater({ + ...updateOptions, }); -macUpdater.setFeedURL({ ...publishOptions }); +macUpdater.setFeedURL({ ...updateOptions }); -macUpdater.autoDownload = true; -macUpdater.autoInstallOnAppQuit = true; +macUpdater.autoDownload = false; +macUpdater.autoInstallOnAppQuit = false; macUpdater.logger = logger; +// UPDATER EVENTS +macUpdater.on('update-downloaded', () => { + macUpdater.quitAndInstall(); +}); + module.exports = { macUpdater }; diff --git a/frontend/components/AddressLink.tsx b/frontend/components/AddressLink.tsx new file mode 100644 index 000000000..83c4dfa93 --- /dev/null +++ b/frontend/components/AddressLink.tsx @@ -0,0 +1,25 @@ +import { UNICODE_SYMBOLS } from '@/constants/symbols'; +import { Address } from '@/types/Address'; +import { truncateAddress } from '@/utils/truncate'; + +type AddressLinkProps = { address?: Address; hideLinkArrow?: boolean }; + +export const AddressLink = ({ + address, + hideLinkArrow = false, +}: AddressLinkProps) => { + if (!address) return null; + + return ( + + {truncateAddress(address)} + + {hideLinkArrow ? null : ( + <> +   + {UNICODE_SYMBOLS.EXTERNAL_LINK} + + )} + + ); +}; diff --git a/frontend/components/InfoBreakdown.tsx b/frontend/components/InfoBreakdown.tsx index 6fff80bc0..ed26b11e8 100644 --- a/frontend/components/InfoBreakdown.tsx +++ b/frontend/components/InfoBreakdown.tsx @@ -37,7 +37,13 @@ const Line = styled.span<{ color?: Color }>` `1px solid ${color === 'primary' ? COLOR.PURPLE_LIGHT : COLOR.BORDER_GRAY}`}; `; -type Info = { id?: number | string; left: ReactNode; right: ReactNode }; +type Info = { + id?: number | string; + left: ReactNode; + leftClassName?: string; + right: ReactNode; + rightClassName?: string; +}; type InfoBreakdownListProps = { list: Info[]; parentStyle?: CSSProperties; @@ -54,9 +60,11 @@ export const InfoBreakdownList = ({ {list.map((item, index) => ( - {item.left} + {item.left} - {item.right} + + {item.right} + ))} diff --git a/frontend/components/InfoTooltip.tsx b/frontend/components/InfoTooltip.tsx new file mode 100644 index 000000000..54529d0d7 --- /dev/null +++ b/frontend/components/InfoTooltip.tsx @@ -0,0 +1,16 @@ +import { InfoCircleOutlined } from '@ant-design/icons'; +import Tooltip, { TooltipPlacement } from 'antd/es/tooltip'; + +import { COLOR } from '@/constants/colors'; + +export const InfoTooltip = ({ + placement = 'topLeft', + children, +}: { + placement?: TooltipPlacement; + children: React.ReactNode; +}) => ( + + + +); diff --git a/frontend/components/Layout/TopBar.tsx b/frontend/components/Layout/TopBar.tsx index ddaf17016..9428fc7f8 100644 --- a/frontend/components/Layout/TopBar.tsx +++ b/frontend/components/Layout/TopBar.tsx @@ -35,8 +35,10 @@ const TrafficLights = styled.div` `; const TopBarContainer = styled.div` - position: sticky; + position: fixed; top: 0; + left: 0; + right: 0; z-index: 1; display: flex; align-items: center; diff --git a/frontend/components/Layout/index.tsx b/frontend/components/Layout/index.tsx index 42d6f1fdf..42610c1bf 100644 --- a/frontend/components/Layout/index.tsx +++ b/frontend/components/Layout/index.tsx @@ -32,6 +32,13 @@ const Container = styled.div<{ blur: 'true' | 'false' }>` `} `; +const Body = styled.div` + // check main.js for the height of the app ie, 700px + max-height: calc(700px - 45px); + padding-top: 45px; + overflow-y: auto; +`; + export const Layout = ({ children, }: PropsWithChildren & { vertical?: boolean }) => { @@ -53,7 +60,7 @@ export const Layout = ({ return ( - {children} + {children} ); }; diff --git a/frontend/components/MainPage/MainHeader/FirstRunModal.tsx b/frontend/components/MainPage/MainHeader/FirstRunModal.tsx index 73f017d70..ce75f568b 100644 --- a/frontend/components/MainPage/MainHeader/FirstRunModal.tsx +++ b/frontend/components/MainPage/MainHeader/FirstRunModal.tsx @@ -2,6 +2,7 @@ import { Button, Flex, Modal, Typography } from 'antd'; import Image from 'next/image'; import { FC } from 'react'; +import { MODAL_WIDTH } from '@/constants/width'; import { useServiceTemplates } from '@/hooks/useServiceTemplates'; import { getMinimumStakedAmountRequired } from '@/utils/service'; @@ -19,7 +20,7 @@ export const FirstRunModal: FC = ({ open, onClose }) => { return ( ( arrow={false} title={ - Your agent earned rewards for this epoch and stopped working. It’ll - return to work once the next epoch starts. + Your agent earned rewards for this epoch, so decided to stop working + until the next epoch. } > @@ -222,7 +223,7 @@ const AgentNotRunningButton = () => { setServiceStatus(DeploymentStatus.DEPLOYED); // TODO: remove this workaround, middleware should respond when agent is staked & confirmed running after `createService` call - await new Promise((resolve) => setTimeout(resolve, 5000)); + await delayInSeconds(5); // update provider states sequentially // service id is required before activeStakingContractInfo & balances can be updated diff --git a/frontend/components/MainPage/header/LastTransaction.tsx b/frontend/components/MainPage/header/LastTransaction.tsx index 91595e09b..f229d1cef 100644 --- a/frontend/components/MainPage/header/LastTransaction.tsx +++ b/frontend/components/MainPage/header/LastTransaction.tsx @@ -1,14 +1,25 @@ -import { Typography } from 'antd'; -import { useCallback, useState } from 'react'; +import { Skeleton, Typography } from 'antd'; +import { useCallback, useEffect, useState } from 'react'; +import styled from 'styled-components'; import { useInterval } from 'usehooks-ts'; import { useAddress } from '@/hooks/useAddress'; +import { usePageState } from '@/hooks/usePageState'; import { getLatestTransaction } from '@/service/Ethers'; import { TransactionInfo } from '@/types/TransactionInfo'; import { getTimeAgo } from '@/utils/time'; const { Text } = Typography; +const Loader = styled(Skeleton.Input)` + line-height: 1; + span { + width: 120px !important; + height: 12px !important; + margin-top: 6px !important; + } +`; + const POLLING_INTERVAL = 60 * 1000; // 1 minute /** @@ -16,6 +27,7 @@ const POLLING_INTERVAL = 60 * 1000; // 1 minute * by agent safe. */ export const LastTransaction = () => { + const { isPageLoadedAndOneMinutePassed } = usePageState(); const { multisigAddress } = useAddress(); const [isFetching, setIsFetching] = useState(true); @@ -35,7 +47,17 @@ export const LastTransaction = () => { // Poll for the latest transaction useInterval(() => fetchTransaction(), POLLING_INTERVAL); - if (isFetching) return null; + // Fetch the latest transaction on mount + useEffect(() => { + fetchTransaction(); + }, [fetchTransaction]); + + // Do not show the last transaction if the delay is not reached + if (!isPageLoadedAndOneMinutePassed) return null; + + if (isFetching) { + return ; + } if (!transaction) { return ( diff --git a/frontend/components/MainPage/modals/FirstRunModal.tsx b/frontend/components/MainPage/modals/FirstRunModal.tsx index 78de3d558..0c57b3b03 100644 --- a/frontend/components/MainPage/modals/FirstRunModal.tsx +++ b/frontend/components/MainPage/modals/FirstRunModal.tsx @@ -2,6 +2,7 @@ import { Button, Flex, Modal, Typography } from 'antd'; import Image from 'next/image'; import { FC } from 'react'; +import { MODAL_WIDTH } from '@/constants/width'; import { useServiceTemplates } from '@/hooks/useServiceTemplates'; import { getMinimumStakedAmountRequired } from '@/utils/service'; @@ -21,7 +22,7 @@ export const FirstRunModal: FC = ({ open, onClose }) => { return ( ` `; export const AddFundsSection = () => { + const fundSectionRef = useRef(null); const [isAddFundsVisible, setIsAddFundsVisible] = useState(false); + const addFunds = useCallback(async () => { + setIsAddFundsVisible(true); + + await delayInSeconds(0.1); + fundSectionRef?.current?.scrollIntoView({ behavior: 'smooth' }); + }, []); + const closeAddFunds = useCallback(() => setIsAddFundsVisible(false), []); + return ( <> @@ -57,12 +67,12 @@ export const AddFundsSection = () => { - {isAddFundsVisible && } + {isAddFundsVisible && } ); }; -export const OpenAddFundsSection = () => { +export const OpenAddFundsSection = forwardRef((_, ref) => { const { masterSafeAddress } = useWallet(); const truncatedFundingAddress: string | undefined = useMemo( @@ -79,7 +89,7 @@ export const OpenAddFundsSection = () => { [masterSafeAddress], ); return ( - <> + { handleCopy={handleCopyAddress} /> - + ); -}; +}); +OpenAddFundsSection.displayName = 'OpenAddFundsSection'; const AddFundsWarningAlertSection = () => ( diff --git a/frontend/components/MainPage/sections/NeedsFundsSection.tsx b/frontend/components/MainPage/sections/NeedsFundsSection.tsx index 71d0604fe..b153611c9 100644 --- a/frontend/components/MainPage/sections/NeedsFundsSection.tsx +++ b/frontend/components/MainPage/sections/NeedsFundsSection.tsx @@ -51,7 +51,6 @@ export const MainNeedsFunds = () => { )}
    -
  • Do not add more than these amounts.
  • Use the address in the “Add Funds” section below.
diff --git a/frontend/components/MainPage/sections/OlasBalanceSection.tsx b/frontend/components/MainPage/sections/OlasBalanceSection.tsx index 8b8dfd9ae..45e5d8a51 100644 --- a/frontend/components/MainPage/sections/OlasBalanceSection.tsx +++ b/frontend/components/MainPage/sections/OlasBalanceSection.tsx @@ -1,15 +1,15 @@ -import { InfoCircleOutlined } from '@ant-design/icons'; -import { Button, Flex, Skeleton, Tooltip, Typography } from 'antd'; +import { RightOutlined } from '@ant-design/icons'; +import { Button, Flex, Skeleton, Typography } from 'antd'; import { useMemo } from 'react'; import styled from 'styled-components'; import { CustomAlert } from '@/components/Alert'; -import { InfoBreakdownList } from '@/components/InfoBreakdown'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { LOW_MASTER_SAFE_BALANCE } from '@/constants/thresholds'; +import { Pages } from '@/enums/PageState'; import { useBalance } from '@/hooks/useBalance'; import { useElectronApi } from '@/hooks/useElectronApi'; -import { useReward } from '@/hooks/useReward'; +import { usePageState } from '@/hooks/usePageState'; import { useStore } from '@/hooks/useStore'; import { balanceFormat } from '@/utils/numberFormatters'; @@ -21,59 +21,6 @@ const Balance = styled.span` margin-right: 4px; `; -const OVERLAY_STYLE = { maxWidth: '300px', width: '300px' }; - -const CurrentBalance = () => { - const { totalOlasBalance, totalOlasStakedBalance } = useBalance(); - const { accruedServiceStakingRewards } = useReward(); - - const balances = useMemo(() => { - return [ - { - title: 'Staked amount', - value: balanceFormat(totalOlasStakedBalance ?? 0, 2), - }, - { - title: 'Unclaimed rewards', - value: balanceFormat(accruedServiceStakingRewards ?? 0, 2), - }, - { - // Unused funds should only be ‘free-floating’ OLAS that is neither unclaimed nor staked. - title: 'Unused funds', - value: balanceFormat( - (totalOlasBalance ?? 0) - - (totalOlasStakedBalance ?? 0) - - (accruedServiceStakingRewards ?? 0), - 2, - ), - }, - ]; - }, [accruedServiceStakingRewards, totalOlasBalance, totalOlasStakedBalance]); - - return ( - - Current balance  - ({ - left: item.title, - right: `${item.value} OLAS`, - }))} - size="small" - parentStyle={{ padding: 4, gap: 8 }} - /> - } - > - - - - ); -}; - const MainOlasBalanceAlert = styled.div` .ant-alert { margin-bottom: 8px; @@ -111,8 +58,8 @@ const LowTradingBalanceAlert = () => { {`To run your agent, add at least $${LOW_MASTER_SAFE_BALANCE} XDAI to your account.`} - Do it quickly to avoid your agent missing its targets and getting - suspended! + Your agent is at risk of missing its targets, which would result + in several days' suspension. } @@ -136,10 +83,10 @@ const AvoidSuspensionAlert = () => { Avoid suspension! - Run your agent for at least half an hour a day to make sure it - hits its targets. If it misses its targets 2 days in a row, it’ll - be suspended. You won’t be able to run it or earn rewards for - several days. + Run your agent for at least half an hour a day to avoid missing + targets. If it misses its targets 2 days in a row, it’ll be + suspended. You won’t be able to run it or earn rewards for several + days. - {data ? ( @@ -212,7 +185,7 @@ export const DebugInfoSection = () => { )} - +
); }; diff --git a/frontend/components/SetupPage/Create/SetupBackupSigner.tsx b/frontend/components/SetupPage/Create/SetupBackupSigner.tsx index edab5bfaa..08a9f677d 100644 --- a/frontend/components/SetupPage/Create/SetupBackupSigner.tsx +++ b/frontend/components/SetupPage/Create/SetupBackupSigner.tsx @@ -38,9 +38,9 @@ export const SetupBackupSigner = () => { Set backup wallet - To keep your funds safe, we encourage you to add one of your existing - crypto wallets as a backup. This enables you to recover your funds if - you lose both your password and seed phrase. + To help keep your funds safe, we encourage you to add one of your + existing crypto wallets as a backup. You may recover your funds to + your backup wallet if you lose both your password and seed phrase. diff --git a/frontend/components/SetupPage/SetupRestore.tsx b/frontend/components/SetupPage/SetupRestore.tsx index 99f57d61d..da04e9f5e 100644 --- a/frontend/components/SetupPage/SetupRestore.tsx +++ b/frontend/components/SetupPage/SetupRestore.tsx @@ -50,7 +50,7 @@ export const SetupRestoreMain = () => { If you don’t have the seed phrase but added a backup wallet to your - account, you can still restore your funds, but you won’t be able to + account, you may still restore your funds, but you won’t be able to recover access to your Pearl account.