Skip to content
Merged
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
18 changes: 18 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# QuantaPool frontend configuration.
# All values have sensible testnet defaults baked in (see src/config/networks.ts),
# so an empty .env works for development.

# Active network: TEST_NET or MAIN_NET
VITE_NETWORK=TEST_NET

# RPC endpoint overrides
VITE_RPC_URL_TESTNET=https://qrlwallet.com/api/qrl-rpc/testnet
VITE_RPC_URL_MAINNET=

# Explorer base URL
VITE_EXPLORER_URL=https://zondscan.com

# Contract address overrides (defaults match config/testnet-hyperion.json)
VITE_DEPOSIT_POOL_ADDRESS=
VITE_STQRL_ADDRESS=
VITE_VALIDATOR_MANAGER_ADDRESS=
4 changes: 4 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
*.local
.env
64 changes: 64 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# QuantaPool Frontend

Minimal web app for the QuantaPool liquid staking protocol. Stake QRL, receive
stQRL, track the pool, and manage withdrawals.

Built to match the [MyQRLWallet](https://qrlwallet.com) design system:
Vite 7, React 19, TypeScript, MobX, TailwindCSS 4, Radix primitives.

## Development

```bash
cd frontend
npm install
npm run dev # http://127.0.0.1:5173
npm run build # type-check + production build
npm run lint # ESLint, zero-warnings policy
```

Configuration is optional — testnet defaults are baked in. Copy `.env.example`
to `.env` to override the RPC endpoint, explorer, or contract addresses.

## Architecture

```
src/
├── abi/ # Contract ABIs (generated from contracts/solidity)
├── components/
│ ├── Layout/ # Header (nav + connect), Footer
│ ├── UI/ # Shadcn-style primitives (Button, Card, Input, Tabs…)
│ ├── AmountInput # Amount field with 25/50/75/Max quick buttons
│ ├── StatsBar # Protocol stats row
│ └── TxBanner # Floating transaction status
├── config/networks.ts # RPC endpoints + contract addresses per network
├── pages/ # Stake (home), Withdrawals (request/claim), Stats
├── stores/ # MobX: poolStore drives all chain state + actions
└── utils/
├── format.ts # BigInt unit conversion + display formatting
├── nativeApp.ts # MyQRLWallet app WebView detection
└── web3/ # Lazy @theqrl/web3 loader, EIP-6963 extension connect
```

### Wallet connectivity

- **QRL Wallet extension** via EIP-6963 discovery (`theqrl.org` rdns) and the
`qrl_requestAccounts` / `qrl_sendTransaction` provider methods — the same
flow myqrlwallet-frontend uses.
- **MyQRLWallet mobile app**: detected via User-Agent. Designed so the
myqrlwallet-connect SDK can slot in as an additional provider source later.

### Contract flows

| Action | Contract call |
|---|---|
| Stake | `DepositPool.deposit()` (payable) |
| Request withdrawal | `DepositPool.requestWithdrawal(shares)` — locks shares, 128-block delay |
| Claim | `DepositPool.claimWithdrawal()` — FIFO, oldest request first |
| Cancel | `DepositPool.cancelWithdrawal(requestId)` |
| Pool data | `getPoolStatus()`, `getRewardStats()`, `ValidatorManager.getStats()` |

Regenerate ABIs after contract changes:

```bash
node scripts/compile.js # from the repo root, then copy abi arrays into frontend/src/abi
```
25 changes: 25 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ["dist", "src/abi"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
},
},
);
18 changes: 18 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/quantapool.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#030712" />
<title>QuantaPool — Liquid Staking for QRL</title>
<meta
name="description"
content="Stake QRL, receive stQRL, and earn validator rewards automatically. Post-quantum secure liquid staking on the QRL network."
/>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading