From 549b67c6a8bdd5dba1b4289a695b37971cd7a6ed Mon Sep 17 00:00:00 2001 From: belopash Date: Tue, 15 Oct 2024 02:41:00 +0500 Subject: [PATCH] feat: refactoring --- .eslintignore | 1 + .../graphql.config.ts => graphql.config.ts | 2 +- package.json | 13 +- ....graphql => squid-subsquid-network.graphql | 14 +- src/App.tsx | 29 +- src/AppRoutes.tsx | 4 +- .../contracts/abi/GatewayRegistration.abi.ts | 132 -- .../contracts/abi/WorkerRegistration.abi.ts | 78 - src/api/contracts/abi/reaward-treasury.abi.ts | 20 - src/api/contracts/abi/soft-cap.abi.ts | 26 - src/api/contracts/abi/staking.abi.ts | 74 - src/api/contracts/abi/vesting.abi.ts | 215 --- src/api/contracts/claim.ts | 105 -- .../useAddStakeGateway.ts | 104 -- .../gateway-registration/useAutoExtension.ts | 67 - .../useComputationUnits.ts | 28 - .../useRegisterGateway.ts | 117 -- .../gateway-registration/useStakeGateway.ts | 136 -- .../useUnregisterGateway.ts | 112 -- .../gateway-registration/useUnstakeGateway.ts | 107 -- src/api/contracts/index.ts | 1 + src/api/contracts/staking.ts | 30 +- src/api/contracts/subsquid.generated.ts | 1364 +++++++++++++++++ src/api/contracts/vesting.ts | 144 -- .../worker-registration/WorkerMetadata.ts | 6 +- .../worker-registration/useRegisterWorker.ts | 151 -- .../useUnregisterWorker.ts | 113 -- .../worker-registration/useUpdateWorker.ts | 13 +- .../worker-registration/useWithdrawWorker.ts | 106 -- .../accounts-graphql.ts | 23 +- src/api/subsquid-network-squid/datasource.ts | 2 +- .../gateways-graphql.ts | 8 +- src/api/subsquid-network-squid/graphql.tsx | 22 +- .../settings-graphql.ts | 6 +- .../subsquid-network-squid/workers-graphql.ts | 142 +- src/components/Alert/Alert.tsx | 50 - src/components/Alert/index.ts | 1 - src/components/Button/ConnectButton.tsx | 5 +- .../ConfirmDialog/ConfirmDialog.tsx | 6 +- src/components/HelpTooltip/HelpTooltip.tsx | 20 +- .../SourceWallet/useMySourceOptions.tsx | 20 +- src/components/Table/NoItems.tsx | 20 +- src/components/Table/TableList.tsx | 9 +- src/components/Toaster/index.tsx | 45 + src/hooks/useSquidNetworkHeightHooks.tsx | 30 +- src/icons/DashboardIcon.tsx | 19 - src/icons/DoorIcon.tsx | 17 - src/icons/HandIcon.tsx | 2 +- src/icons/InfoIcon.tsx | 10 - src/icons/LogoutIcon.tsx | 10 - src/icons/NetworkNodeIcon.tsx | 2 +- src/icons/SavingsIcon.tsx | 17 - src/icons/WalletIcon.tsx | 22 - src/icons/WarningIcon.tsx | 37 - src/layouts/NetworkLayout/LogoutMenuItem.tsx | 4 +- src/layouts/NetworkLayout/NetworkLayout.tsx | 3 +- src/layouts/NetworkLayout/NetworkMenu.tsx | 166 +- .../NetworkLayout/SyncSquidSnackbar.tsx | 42 - src/layouts/NetworkLayout/UserMenu.tsx | 36 +- src/lib/formatters/formatters.ts | 38 +- src/lib/network/utils.ts | 33 +- src/network/useContracts.ts | 3 + src/pages/AssetsPage/Assets.tsx | 11 +- src/pages/AssetsPage/ClaimButton.tsx | 319 ++-- src/pages/AssetsPage/ReleaseButton.tsx | 47 +- src/pages/AssetsPage/Vesting.tsx | 74 +- src/pages/AssetsPage/Vestings.tsx | 62 +- src/pages/DashboardPage/Summary.tsx | 11 +- src/pages/DashboardPage/Workers.tsx | 4 +- src/pages/DelegationsPage/DelegationsPage.tsx | 4 +- src/pages/GatewaysPage/AddNewGateway.tsx | 250 +-- src/pages/GatewaysPage/AutoExtension.tsx | 53 +- src/pages/GatewaysPage/Gateway.tsx | 4 +- src/pages/GatewaysPage/GatewayStake.tsx | 464 +++--- src/pages/GatewaysPage/GatewayUnregister.tsx | 105 +- src/pages/GatewaysPage/GatewayUnstake.tsx | 87 +- src/pages/GatewaysPage/GatewaysPage.tsx | 173 ++- src/pages/GatewaysPage/gateway-schema.ts | 3 +- src/pages/WorkersPage/AddNewWorker.tsx | 374 +++-- src/pages/WorkersPage/Worker.tsx | 26 +- src/pages/WorkersPage/WorkerCard.tsx | 4 +- src/pages/WorkersPage/WorkerDelegate.tsx | 87 +- src/pages/WorkersPage/WorkerStatus.tsx | 8 +- src/pages/WorkersPage/WorkerUndelegate.tsx | 7 +- src/pages/WorkersPage/WorkerUnregister.tsx | 223 ++- src/pages/WorkersPage/WorkerVersion.tsx | 12 +- src/pages/WorkersPage/WorkerWithdraw.tsx | 129 ++ src/pages/WorkersPage/WorkersPage.tsx | 46 +- src/schema/decimal.ts | 3 +- src/theme/theme.tsx | 22 +- tsconfig.json | 36 +- tsconfig.node.json | 3 +- wagmi.config.ts | 798 ++++++++++ yarn.lock | 1088 +++++++++---- 94 files changed, 5101 insertions(+), 3618 deletions(-) rename src/api/subsquid-network-squid/graphql.config.ts => graphql.config.ts (93%) rename src/api/subsquid-network-squid/api.graphql => squid-subsquid-network.graphql (99%) delete mode 100644 src/api/contracts/abi/GatewayRegistration.abi.ts delete mode 100644 src/api/contracts/abi/WorkerRegistration.abi.ts delete mode 100644 src/api/contracts/abi/reaward-treasury.abi.ts delete mode 100644 src/api/contracts/abi/soft-cap.abi.ts delete mode 100644 src/api/contracts/abi/staking.abi.ts delete mode 100644 src/api/contracts/abi/vesting.abi.ts delete mode 100644 src/api/contracts/claim.ts delete mode 100644 src/api/contracts/gateway-registration/useAddStakeGateway.ts delete mode 100644 src/api/contracts/gateway-registration/useAutoExtension.ts delete mode 100644 src/api/contracts/gateway-registration/useComputationUnits.ts delete mode 100644 src/api/contracts/gateway-registration/useRegisterGateway.ts delete mode 100644 src/api/contracts/gateway-registration/useStakeGateway.ts delete mode 100644 src/api/contracts/gateway-registration/useUnregisterGateway.ts delete mode 100644 src/api/contracts/gateway-registration/useUnstakeGateway.ts create mode 100644 src/api/contracts/index.ts create mode 100644 src/api/contracts/subsquid.generated.ts delete mode 100644 src/api/contracts/vesting.ts delete mode 100644 src/api/contracts/worker-registration/useRegisterWorker.ts delete mode 100644 src/api/contracts/worker-registration/useUnregisterWorker.ts delete mode 100644 src/api/contracts/worker-registration/useWithdrawWorker.ts delete mode 100644 src/components/Alert/Alert.tsx delete mode 100644 src/components/Alert/index.ts create mode 100644 src/components/Toaster/index.tsx delete mode 100644 src/icons/DashboardIcon.tsx delete mode 100644 src/icons/DoorIcon.tsx delete mode 100644 src/icons/InfoIcon.tsx delete mode 100644 src/icons/LogoutIcon.tsx delete mode 100644 src/icons/SavingsIcon.tsx delete mode 100644 src/icons/WalletIcon.tsx delete mode 100644 src/icons/WarningIcon.tsx delete mode 100644 src/layouts/NetworkLayout/SyncSquidSnackbar.tsx create mode 100644 src/pages/WorkersPage/WorkerWithdraw.tsx create mode 100644 wagmi.config.ts diff --git a/.eslintignore b/.eslintignore index 18115e8..3dd49f8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ node_modules .yarn build dist +**/*.generated.* \ No newline at end of file diff --git a/src/api/subsquid-network-squid/graphql.config.ts b/graphql.config.ts similarity index 93% rename from src/api/subsquid-network-squid/graphql.config.ts rename to graphql.config.ts index 32a48e1..4b45f16 100644 --- a/src/api/subsquid-network-squid/graphql.config.ts +++ b/graphql.config.ts @@ -8,7 +8,7 @@ export default { schema: process.env.SQUID_API_URL || 'https://subsquid.squids.live/subsquid-network-testnet/v/v5/graphql', - documents: ['src/api/subsquid-network-squid/*.graphql'], + documents: ['*.graphql'], hooks: { afterOneFileWrite: ['prettier --write'], }, diff --git a/package.json b/package.json index cec5c75..8d1b51a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "preview": "vite preview --outDir build --host 127.0.0.1 --port 3005", "upg": "yarn upgrade-interactive", "prepare": "husky install", - "codegen": "graphql-codegen --config src/api/subsquid-network-squid/graphql.config.ts" + "codegen": "graphql-codegen --config graphql.config.ts" }, "lint-staged": { "src/**/*.{js,jsx,ts,tsx}": "eslint --cache --fix" @@ -39,11 +39,11 @@ "graphql": "^16.9.0", "lodash-es": "^4.17.21", "material-ui-popup-state": "^5.1.2", - "notistack": "^3.0.1", "pretty-bytes": "^6.1.1", "qs": "^6.12.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-hot-toast": "^2.4.1", "react-router-dom": "^6.24.0", "react-scroll": "^1.9.0", "react-syntax-highlighter": "^15.5.0", @@ -52,8 +52,8 @@ "use-debounce": "^10.0.1", "use-element-position": "^1.0.13", "use-local-storage-state": "^19.3.1", - "viem": "^2.10.9", - "wagmi": "^2.9.2", + "viem": "^2.21.25", + "wagmi": "^2.12.17", "yup": "^1.4.0" }, "devDependencies": { @@ -76,6 +76,7 @@ "@typescript-eslint/eslint-plugin": "^7.14.1", "@typescript-eslint/parser": "^7.14.1", "@vitejs/plugin-react": "^4.3.1", + "@wagmi/cli": "^2.1.16", "dotenv": "^16.4.5", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", @@ -90,8 +91,8 @@ "husky": "^9.0.11", "lint-staged": "^15.2.7", "prettier": "^3.3.2", - "type-fest": "^4.20.1", - "typescript": "^5.5.2", + "type-fest": "^4.26.1", + "typescript": "^5.6.3", "vite": "^5.4.2", "vite-plugin-html": "^3.2.2", "vite-plugin-html-env": "^1.2.8", diff --git a/src/api/subsquid-network-squid/api.graphql b/squid-subsquid-network.graphql similarity index 99% rename from src/api/subsquid-network-squid/api.graphql rename to squid-subsquid-network.graphql index 7badd4a..00fe859 100644 --- a/src/api/subsquid-network-squid/api.graphql +++ b/squid-subsquid-network.graphql @@ -63,6 +63,13 @@ fragment WorkerFragment on Worker { stakerApr totalDelegation capedDelegation + owner { + id + type + } + realOwner { + id + } } fragment WorkerFullFragment on Worker { @@ -88,13 +95,6 @@ fragment WorkerFullFragment on Worker { timestamp uptime } - owner { - id - type - } - realOwner { - id - } } query allWorkers { diff --git a/src/App.tsx b/src/App.tsx index 0c58bd5..c84da10 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,12 +3,11 @@ import React from 'react'; import { CssBaseline, ThemeProvider } from '@mui/material'; import { RainbowKitProvider } from '@rainbow-me/rainbowkit'; import { QueryClientProvider } from '@tanstack/react-query'; -import { SnackbarProvider } from 'notistack'; import { BrowserRouter } from 'react-router-dom'; import { WagmiProvider } from 'wagmi'; import { queryClient } from '@api/client'; -import { Alert } from '@components/Alert'; +import { Toaster } from '@components/Toaster'; import { SquidHeightProvider } from '@hooks/useSquidNetworkHeightHooks'; import { rainbowConfig } from '@network/config'; @@ -21,30 +20,24 @@ function App() { const rainbowkitTheme = useCreateRainbowKitTheme(themeName); return ( - - - + <> + + - + - + + {/* */} + - - - + + + ); } diff --git a/src/AppRoutes.tsx b/src/AppRoutes.tsx index b67438e..ce6c1e9 100644 --- a/src/AppRoutes.tsx +++ b/src/AppRoutes.tsx @@ -7,7 +7,6 @@ import { AssetsPage } from '@pages/AssetsPage/AssetsPage.tsx'; import { Vesting } from '@pages/AssetsPage/Vesting.tsx'; import { DashboardPage } from '@pages/DashboardPage/DashboardPage.tsx'; import { DelegationsPage } from '@pages/DelegationsPage/DelegationsPage.tsx'; -import { AddNewGateway } from '@pages/GatewaysPage/AddNewGateway.tsx'; import { Gateway } from '@pages/GatewaysPage/Gateway.tsx'; import { GatewaysPage } from '@pages/GatewaysPage/GatewaysPage.tsx'; import { AddNewWorker } from '@pages/WorkersPage/AddNewWorker.tsx'; @@ -35,7 +34,7 @@ export const AppRoutes = () => { } index /> - } path="add" /> + {/* } path="add" /> */} } path=":peerId" /> } path=":peerId/edit" /> @@ -44,7 +43,6 @@ export const AppRoutes = () => { } index /> - } path="add" /> } path=":peerId" /> } path="*" /> diff --git a/src/api/contracts/abi/GatewayRegistration.abi.ts b/src/api/contracts/abi/GatewayRegistration.abi.ts deleted file mode 100644 index baf8013..0000000 --- a/src/api/contracts/abi/GatewayRegistration.abi.ts +++ /dev/null @@ -1,132 +0,0 @@ -export const GATEWAY_REGISTRATION_CONTRACT_ABI = [ - { - type: 'function', - name: 'register', - inputs: [ - { - name: 'peerId', - type: 'bytes', - internalType: 'bytes', - }, - { - name: 'metadata', - type: 'string', - internalType: 'string', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'setMetadata', - inputs: [ - { - name: 'peerId', - type: 'bytes', - internalType: 'bytes', - }, - { - name: 'metadata', - type: 'string', - internalType: 'string', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'stake', - inputs: [ - { - name: 'amount', - type: 'uint256', - internalType: 'uint256', - }, - { - name: 'durationBlocks', - type: 'uint128', - internalType: 'uint128', - }, - { - name: 'withAutoExtension', - type: 'bool', - internalType: 'bool', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'unregister', - inputs: [ - { - name: 'peerId', - type: 'bytes', - internalType: 'bytes', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'unstake', - inputs: [], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'computationUnitsAmount', - inputs: [ - { - name: 'amount', - type: 'uint256', - internalType: 'uint256', - }, - { - name: 'durationBlocks', - type: 'uint256', - internalType: 'uint256', - }, - ], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'addStake', - inputs: [ - { - name: 'amount', - type: 'uint256', - internalType: 'uint256', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'disableAutoExtension', - inputs: [], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'enableAutoExtension', - inputs: [], - outputs: [], - stateMutability: 'nonpayable', - }, -] as const; diff --git a/src/api/contracts/abi/WorkerRegistration.abi.ts b/src/api/contracts/abi/WorkerRegistration.abi.ts deleted file mode 100644 index 8f2c7a8..0000000 --- a/src/api/contracts/abi/WorkerRegistration.abi.ts +++ /dev/null @@ -1,78 +0,0 @@ -export const WORKER_REGISTRATION_CONTRACT_ABI = [ - { - type: 'function', - name: 'bondAmount', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'register', - inputs: [ - { - name: 'peerId', - type: 'bytes', - internalType: 'bytes', - }, - { - name: 'metadata', - type: 'string', - internalType: 'string', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'updateMetadata', - inputs: [ - { - name: 'peerId', - type: 'bytes', - internalType: 'bytes', - }, - { - name: 'metadata', - type: 'string', - internalType: 'string', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - inputs: [ - { - internalType: 'bytes', - name: 'peerId', - type: 'bytes', - }, - ], - name: 'deregister', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - - { - type: 'function', - name: 'withdraw', - inputs: [ - { - name: 'peerId', - type: 'bytes', - internalType: 'bytes', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, -] as const; diff --git a/src/api/contracts/abi/reaward-treasury.abi.ts b/src/api/contracts/abi/reaward-treasury.abi.ts deleted file mode 100644 index f51a666..0000000 --- a/src/api/contracts/abi/reaward-treasury.abi.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const REWARD_TREASURY_CONTRACT_ABI = [ - { - type: 'function', - name: 'claimFor', - inputs: [ - { - name: 'rewardDistribution', - type: 'address', - internalType: 'contract IRewardsDistribution', - }, - { - name: 'receiver', - type: 'address', - internalType: 'address', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, -] as const; diff --git a/src/api/contracts/abi/soft-cap.abi.ts b/src/api/contracts/abi/soft-cap.abi.ts deleted file mode 100644 index 2f3a6f8..0000000 --- a/src/api/contracts/abi/soft-cap.abi.ts +++ /dev/null @@ -1,26 +0,0 @@ -export const SOFT_CAP_ABI = [ - { - type: 'function', - name: 'cap', - inputs: [{ name: 'x', type: 'uint256', internalType: 'UD60x18' }], - outputs: [{ name: '', type: 'uint256', internalType: 'UD60x18' }], - stateMutability: 'pure', - }, - { - type: 'function', - name: 'capedStake', - inputs: [{ name: 'workerId', type: 'uint256', internalType: 'uint256' }], - outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }], - stateMutability: 'view', - }, - { - type: 'function', - name: 'capedStakeAfterDelegation', - inputs: [ - { name: 'workerId', type: 'uint256', internalType: 'uint256' }, - { name: 'delegationAmount', type: 'int256', internalType: 'int256' }, - ], - outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }], - stateMutability: 'view', - }, -] as const; diff --git a/src/api/contracts/abi/staking.abi.ts b/src/api/contracts/abi/staking.abi.ts deleted file mode 100644 index c0493ad..0000000 --- a/src/api/contracts/abi/staking.abi.ts +++ /dev/null @@ -1,74 +0,0 @@ -export const STAKING_CONTRACT_ABI = [ - { - type: 'function', - name: 'deposit', - inputs: [ - { - name: 'worker', - type: 'uint256', - internalType: 'uint256', - }, - { - name: 'amount', - type: 'uint256', - internalType: 'uint256', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'withdraw', - inputs: [ - { - type: 'uint256', - name: 'worker', - }, - { - type: 'uint256', - name: 'amount', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'claimable', - inputs: [ - { - name: 'staker', - type: 'address', - internalType: 'address', - }, - ], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'delegated', - inputs: [ - { - name: 'worker', - type: 'uint256', - internalType: 'uint256', - }, - ], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, -] as const; diff --git a/src/api/contracts/abi/vesting.abi.ts b/src/api/contracts/abi/vesting.abi.ts deleted file mode 100644 index 7c2108e..0000000 --- a/src/api/contracts/abi/vesting.abi.ts +++ /dev/null @@ -1,215 +0,0 @@ -export const VESTING_CONTRACT_ABI = [ - { - type: 'function', - name: 'depositedIntoProtocol', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'duration', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'end', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'execute', - inputs: [ - { - name: 'to', - type: 'address', - internalType: 'address', - }, - { - name: 'data', - type: 'bytes', - internalType: 'bytes', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'execute', - inputs: [ - { - name: 'to', - type: 'address', - internalType: 'address', - }, - { - name: 'data', - type: 'bytes', - internalType: 'bytes', - }, - { - name: 'requiredApprove', - type: 'uint256', - internalType: 'uint256', - }, - ], - outputs: [ - { - name: '', - type: 'bytes', - internalType: 'bytes', - }, - ], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'expectedTotalAmount', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'immediateReleaseBIP', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'releasable', - inputs: [ - { - name: 'token', - type: 'address', - internalType: 'address', - }, - ], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'releasable', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'release', - inputs: [ - { - name: 'token', - type: 'address', - internalType: 'address', - }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'released', - inputs: [ - { - name: 'token', - type: 'address', - internalType: 'address', - }, - ], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'start', - inputs: [], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'vestedAmount', - inputs: [ - { - name: 'token', - type: 'address', - internalType: 'address', - }, - { - name: 'timestamp', - type: 'uint64', - internalType: 'uint64', - }, - ], - outputs: [ - { - name: '', - type: 'uint256', - internalType: 'uint256', - }, - ], - stateMutability: 'view', - }, -] as const; diff --git a/src/api/contracts/claim.ts b/src/api/contracts/claim.ts deleted file mode 100644 index 03d0b95..0000000 --- a/src/api/contracts/claim.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { useState } from 'react'; - -import { encodeFunctionData } from 'viem'; -import { waitForTransactionReceipt } from 'viem/actions'; -import { useWriteContract, useClient } from 'wagmi'; - -import { REWARD_TREASURY_CONTRACT_ABI } from '@api/contracts/abi/reaward-treasury.abi'; -import { VESTING_CONTRACT_ABI } from '@api/contracts/abi/vesting.abi'; -import { AccountType, SourceWallet } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount.ts'; -import { useContracts } from '@network/useContracts.ts'; - -import { TxResult, errorMessage, WriteContractRes } from './utils'; - -export type ClaimRequest = { - wallet: SourceWallet; -}; - -function useClaimFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ wallet }: ClaimRequest): Promise => { - try { - return { - tx: await writeContractAsync({ - address: contracts.REWARD_TREASURY, - abi: REWARD_TREASURY_CONTRACT_ABI, - functionName: 'claimFor', - args: [contracts.REWARD_DISTRIBUTION, wallet.id as `0x${string}`], - }), - }; - } catch (e) { - return { error: errorMessage(e) }; - } - }; -} - -function useClaimFromVestingContract() { - const contracts = useContracts(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ wallet }: ClaimRequest): Promise => { - try { - const data = encodeFunctionData({ - abi: REWARD_TREASURY_CONTRACT_ABI, - functionName: 'claimFor', - args: [contracts.REWARD_DISTRIBUTION, account as `0x${string}`], - }); - - return { - tx: await writeContractAsync({ - account, - address: wallet.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.REWARD_TREASURY, data], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useClaim() { - const client = useClient(); - const { setWaitHeight } = useSquidNetworkHeight(); - const [isPending, setLoading] = useState(false); - const [error, setError] = useState(null); - - const claimFromWallet = useClaimFromWallet(); - const claimFromVestingContract = useClaimFromVestingContract(); - - const claim = async ({ wallet }: ClaimRequest): Promise => { - setLoading(true); - - const res = - wallet.type === AccountType.User - ? await claimFromWallet({ wallet }) - : await claimFromVestingContract({ wallet }); - - if (!res.tx) { - setLoading(false); - setError(res.error); - - return { success: false, failedReason: res.error }; - } - - const receipt = await waitForTransactionReceipt(client!, { hash: res.tx }); - setWaitHeight(receipt.blockNumber, []); - - setLoading(false); - - return { success: true }; - }; - - return { - claim, - isPending, - error, - }; -} diff --git a/src/api/contracts/gateway-registration/useAddStakeGateway.ts b/src/api/contracts/gateway-registration/useAddStakeGateway.ts deleted file mode 100644 index 07d60e1..0000000 --- a/src/api/contracts/gateway-registration/useAddStakeGateway.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { useState } from 'react'; - -import { logger } from '@logger'; -import { usePublicClient, useWriteContract } from 'wagmi'; - -import { AccountType, SourceWallet } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useContracts } from '@network/useContracts.ts'; - -import { GATEWAY_REGISTRATION_CONTRACT_ABI } from '../abi/GatewayRegistration.abi'; -import { useApproveSqd } from '../sqd'; -import { errorMessage, TxResult, isApproveRequiredError, WriteContractRes } from '../utils'; - -type AddStakeGatewayRequest = { - amount: string; - wallet: SourceWallet; -}; - -function useAddStakeFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - const [approveSqd] = useApproveSqd(); - - const tryCallContract = async ({ amount }: AddStakeGatewayRequest) => { - try { - return { - tx: await writeContractAsync({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'addStake', - args: [BigInt(amount)], - }), - }; - } catch (e) { - return { error: errorMessage(e) }; - } - }; - - return async (req: AddStakeGatewayRequest): Promise => { - logger.debug(`stake to gateway via worker contract...`); - - const res = await tryCallContract(req); - // Try to approve SQD - if (isApproveRequiredError(res.error)) { - const approveRes = await approveSqd({ - contractAddress: contracts.GATEWAY_REGISTRATION, - amount: req.amount, - }); - if (!approveRes.success) { - return { error: approveRes.failedReason }; - } - - logger.debug(`approved SQD successfully, now trying to register one more time...`); - - return tryCallContract(req); - } - - return res; - }; -} - -export function useAddStakeGateway() { - const client = usePublicClient(); - const { setWaitHeight } = useSquidNetworkHeight(); - const [isLoading, setLoading] = useState(false); - const [error, setError] = useState(null); - - const stakeFromWallet = useAddStakeFromWallet(); - - const addStakeToGateway = async (req: AddStakeGatewayRequest): Promise => { - setLoading(true); - - if (req.wallet.type !== AccountType.User) { - throw new Error('Vesting contracts are not supported yet.'); - } - - const res = await stakeFromWallet(req); - - if (!res.tx) { - setLoading(false); - setError(res.error); - - return { success: false, failedReason: res.error }; - } - - if (!client) { - return { success: false, failedReason: 'missing client' }; - } - - const receipt = await client.waitForTransactionReceipt({ hash: res.tx }); - setWaitHeight(receipt.blockNumber, []); - - setLoading(false); - - return { success: true }; - }; - - return { - addStakeToGateway, - isLoading, - error, - }; -} diff --git a/src/api/contracts/gateway-registration/useAutoExtension.ts b/src/api/contracts/gateway-registration/useAutoExtension.ts deleted file mode 100644 index bd8841b..0000000 --- a/src/api/contracts/gateway-registration/useAutoExtension.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { useState } from 'react'; - -import { useWriteContract, usePublicClient } from 'wagmi'; - -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useContracts } from '@network/useContracts'; - -import { GATEWAY_REGISTRATION_CONTRACT_ABI } from '../abi/GatewayRegistration.abi'; -import { errorMessage, TxResult, WriteContractRes } from '../utils'; - -export function useAutoExtension() { - const client = usePublicClient(); - const { setWaitHeight } = useSquidNetworkHeight(); - const [isLoading, setLoading] = useState(false); - const [error, setError] = useState(null); - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - const setAutoExtension = async (enable: boolean): Promise => { - setLoading(true); - - let res: TxResult; - try { - res = { - tx: enable - ? await writeContractAsync({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'enableAutoExtension', - args: [], - }) - : await writeContractAsync({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'disableAutoExtension', - args: [], - }), - }; - } catch (e) { - res = { error: errorMessage(e) }; - } - - if (!res.tx) { - setLoading(false); - setError(res.error); - - return { success: false, failedReason: res.error }; - } - - if (!client) { - return { success: false, failedReason: 'missing client' }; - } - - const receipt = await client.waitForTransactionReceipt({ hash: res.tx }); - setWaitHeight(receipt.blockNumber, []); - - setLoading(false); - - return { success: true }; - }; - - return { - setAutoExtension, - isLoading, - error, - }; -} diff --git a/src/api/contracts/gateway-registration/useComputationUnits.ts b/src/api/contracts/gateway-registration/useComputationUnits.ts deleted file mode 100644 index 25abc23..0000000 --- a/src/api/contracts/gateway-registration/useComputationUnits.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { useReadContract } from 'wagmi'; - -import { useContracts } from '@network/useContracts'; - -import { GATEWAY_REGISTRATION_CONTRACT_ABI } from '../abi/GatewayRegistration.abi'; - -export function useComputationUnits({ - amount, - lockDuration, -}: { - amount: string; - lockDuration: number; -}) { - const contracts = useContracts(); - - const { data, isLoading, isPending } = useReadContract({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'computationUnitsAmount', - args: [BigInt(amount), BigInt(lockDuration)], - }); - - return { - data: data?.toString(), - isLoading, - isPending, - }; -} diff --git a/src/api/contracts/gateway-registration/useRegisterGateway.ts b/src/api/contracts/gateway-registration/useRegisterGateway.ts deleted file mode 100644 index dd91c05..0000000 --- a/src/api/contracts/gateway-registration/useRegisterGateway.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { useState } from 'react'; - -import { peerIdToHex } from '@lib/network'; -import { logger } from '@logger'; -import { encodeFunctionData } from 'viem'; -import { usePublicClient, useWriteContract } from 'wagmi'; - -import { AccountType } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount'; -import { useContracts } from '@network/useContracts.ts'; - -import { TxResult, errorMessage, WriteContractRes } from '../utils'; -import { VESTING_CONTRACT_ABI } from '../abi/vesting.abi'; - -import { encodeGatewayMetadata, GetawayMetadata } from './GatewayMetadata'; -import { GATEWAY_REGISTRATION_CONTRACT_ABI } from '../abi/GatewayRegistration.abi'; - -export interface RegisterGatewayRequest extends GetawayMetadata { - peerId: string; - source: { - id: string; - type: AccountType; - }; -} - -function useRegisterGatewayFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ peerId, ...rest }: RegisterGatewayRequest): Promise => { - logger.debug(`registering gateway via worker contract...`); - - try { - return { - tx: await writeContractAsync({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'register', - args: [peerIdToHex(peerId), encodeGatewayMetadata(rest)], - }), - }; - } catch (e: unknown) { - return { - error: errorMessage(e), - }; - } - }; -} - -function useRegisterGatewayFromVestingContract() { - const contracts = useContracts(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ peerId, source, ...rest }: RegisterGatewayRequest): Promise => { - try { - const data = encodeFunctionData({ - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'register', - args: [peerIdToHex(peerId), encodeGatewayMetadata(rest)], // encodeMetadata(rest) - }); - - return { - tx: await writeContractAsync({ - account, - address: source.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.GATEWAY_REGISTRATION, data], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useRegisterGateway() { - const client = usePublicClient(); - const { address } = useAccount(); - const [error, setError] = useState(null); - const [isLoading, setLoading] = useState(false); - - const { setWaitHeight } = useSquidNetworkHeight(); - const registerGatewayFromWallet = useRegisterGatewayFromWallet(); - const registerGatewayFromVestingContract = useRegisterGatewayFromVestingContract(); - - const registerGateway = async (req: RegisterGatewayRequest): Promise => { - setLoading(true); - - const { tx, error } = - req.source.type === AccountType.User - ? await registerGatewayFromWallet(req) - : await registerGatewayFromVestingContract(req); - - if (!tx) { - logger.debug(`registering gateway failed ${error}`); - setLoading(false); - setError(error); - return { success: false, failedReason: error }; - } - - if (!client) { - return { success: false, failedReason: 'missing client' }; - } - - const receipt = await client.waitForTransactionReceipt({ hash: tx }); - setWaitHeight(receipt.blockNumber, ['myGateways', { address }]); - setLoading(false); - setError(null); - - return { success: true }; - }; - - return { registerGateway, isLoading, error }; -} diff --git a/src/api/contracts/gateway-registration/useStakeGateway.ts b/src/api/contracts/gateway-registration/useStakeGateway.ts deleted file mode 100644 index 18f5873..0000000 --- a/src/api/contracts/gateway-registration/useStakeGateway.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { useState } from 'react'; - -import { logger } from '@logger'; -import { encodeFunctionData } from 'viem'; -import { usePublicClient, useWriteContract } from 'wagmi'; - -import { AccountType, SourceWallet } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount'; -import { useContracts } from '@network/useContracts.ts'; - -import { GATEWAY_REGISTRATION_CONTRACT_ABI } from '../abi/GatewayRegistration.abi'; -import { VESTING_CONTRACT_ABI } from '../abi/vesting.abi'; -import { useApproveSqd } from '../sqd'; -import { errorMessage, TxResult, isApproveRequiredError, WriteContractRes } from '../utils'; - -type StakeGatewayRequest = { - amount: string; - durationBlocks: number; - wallet: SourceWallet; -}; - -function useStakeFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - const [approveSqd] = useApproveSqd(); - - const tryCallContract = async ({ amount, durationBlocks }: StakeGatewayRequest) => { - try { - return { - tx: await writeContractAsync({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'stake', - args: [BigInt(amount), BigInt(durationBlocks), false], - }), - }; - } catch (e) { - return { error: errorMessage(e) }; - } - }; - - return async (req: StakeGatewayRequest): Promise => { - logger.debug(`stake to gateway via worker contract...`); - - const res = await tryCallContract(req); - // Try to approve SQD - if (isApproveRequiredError(res.error)) { - const approveRes = await approveSqd({ - contractAddress: contracts.GATEWAY_REGISTRATION, - amount: req.amount, - }); - if (!approveRes.success) { - return { error: approveRes.failedReason }; - } - - logger.debug(`approved SQD successfully, now trying to register one more time...`); - - return tryCallContract(req); - } - - return res; - }; -} - -function useStakeFromVestingContract() { - const contracts = useContracts(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ amount, wallet, durationBlocks }: StakeGatewayRequest): Promise => { - try { - const data = encodeFunctionData({ - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'stake', - args: [BigInt(amount), BigInt(durationBlocks), false], - }); - - return { - tx: await writeContractAsync({ - account, - address: wallet.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.GATEWAY_REGISTRATION, data, BigInt(amount)], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useStakeGateway() { - const client = usePublicClient(); - const { setWaitHeight } = useSquidNetworkHeight(); - const [isLoading, setLoading] = useState(false); - const [error, setError] = useState(null); - - const stakeFromWallet = useStakeFromWallet(); - const stakeFromVestingContract = useStakeFromVestingContract(); - - const stakeToGateway = async (req: StakeGatewayRequest): Promise => { - setLoading(true); - - const res = - req.wallet.type === AccountType.User - ? await stakeFromWallet(req) - : await stakeFromVestingContract(req); - - if (!res.tx) { - setLoading(false); - setError(res.error); - - return { success: false, failedReason: res.error }; - } - - if (!client) { - return { success: false, failedReason: 'missing client' }; - } - - const receipt = await client.waitForTransactionReceipt({ hash: res.tx }); - setWaitHeight(receipt.blockNumber, []); - - setLoading(false); - - return { success: true }; - }; - - return { - stakeToGateway, - isLoading, - error, - }; -} diff --git a/src/api/contracts/gateway-registration/useUnregisterGateway.ts b/src/api/contracts/gateway-registration/useUnregisterGateway.ts deleted file mode 100644 index f65cc62..0000000 --- a/src/api/contracts/gateway-registration/useUnregisterGateway.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { useState } from 'react'; - -import { peerIdToHex } from '@lib/network'; -import { logger } from '@logger'; -import { encodeFunctionData } from 'viem'; -import { useWriteContract, usePublicClient } from 'wagmi'; - -import { AccountType, GatewayFragmentFragment } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount'; -import { useContracts } from '@network/useContracts.ts'; - -import { TxResult, errorMessage, WriteContractRes } from '../utils'; -import { VESTING_CONTRACT_ABI } from '../abi/vesting.abi'; - -import { GATEWAY_REGISTRATION_CONTRACT_ABI } from '../abi/GatewayRegistration.abi'; - -export interface UnregisterGatewayRequest { - gateway: GatewayFragmentFragment; -} - -function useUnregisterGatewayFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract(); - - return async ({ gateway }: UnregisterGatewayRequest): Promise => { - logger.debug(`unregistering gateway via worker contract...`); - - try { - return { - tx: await writeContractAsync({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'unregister', - args: [peerIdToHex(gateway.id)], - }), - }; - } catch (e: unknown) { - return { - error: errorMessage(e), - }; - } - }; -} - -function useUnregisterGatewayFromVestingContract() { - const contracts = useContracts(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract(); - - return async ({ gateway }: UnregisterGatewayRequest): Promise => { - try { - const data = encodeFunctionData({ - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'unregister', - args: [peerIdToHex(gateway.id)], - }); - - return { - tx: await writeContractAsync({ - account, - address: gateway.owner.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.GATEWAY_REGISTRATION, data], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useUnregisterGateway() { - const client = usePublicClient(); - const { address } = useAccount(); - const [error, setError] = useState(null); - const [isLoading, setLoading] = useState(false); - - const { setWaitHeight } = useSquidNetworkHeight(); - const unregisterGatewayFromWallet = useUnregisterGatewayFromWallet(); - const unregisterGatewayFromVestingContract = useUnregisterGatewayFromVestingContract(); - - const unregisterGateway = async (req: UnregisterGatewayRequest): Promise => { - setLoading(true); - - const { tx, error } = - req.gateway.owner.type === AccountType.User - ? await unregisterGatewayFromWallet(req) - : await unregisterGatewayFromVestingContract(req); - - if (!tx) { - logger.debug(`unregistering gateway failed ${error}`); - setLoading(false); - setError(error); - return { success: false, failedReason: error }; - } - - if (!client) { - return { success: false, failedReason: 'missing client' }; - } - - const receipt = await client.waitForTransactionReceipt({ hash: tx }); - setWaitHeight(receipt.blockNumber, ['myGateways', { address }]); - setLoading(false); - setError(null); - - return { success: true }; - }; - - return { unregisterGateway, isLoading, error }; -} diff --git a/src/api/contracts/gateway-registration/useUnstakeGateway.ts b/src/api/contracts/gateway-registration/useUnstakeGateway.ts deleted file mode 100644 index b88549b..0000000 --- a/src/api/contracts/gateway-registration/useUnstakeGateway.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { useState } from 'react'; - -import { encodeFunctionData } from 'viem'; -import { useWriteContract, usePublicClient } from 'wagmi'; - -import { AccountType, GatewayStakeFragmentFragment } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount'; -import { useContracts } from '@network/useContracts.ts'; - -import { TxResult, errorMessage, WriteContractRes } from '../utils'; -import { VESTING_CONTRACT_ABI } from '../abi/vesting.abi'; - -import { GATEWAY_REGISTRATION_CONTRACT_ABI } from '../abi/GatewayRegistration.abi'; - -type UnstakeGatewayRequest = { - operator: GatewayStakeFragmentFragment; -}; - -function useUnstakeFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - return async ({}: UnstakeGatewayRequest): Promise => { - try { - return { - tx: await writeContractAsync({ - address: contracts.GATEWAY_REGISTRATION, - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'unstake', - }), - }; - } catch (e) { - return { error: errorMessage(e) }; - } - }; -} - -function useUnstakeFromVestingContract() { - const contracts = useContracts(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ operator }: UnstakeGatewayRequest): Promise => { - try { - const data = encodeFunctionData({ - abi: GATEWAY_REGISTRATION_CONTRACT_ABI, - functionName: 'unstake', - }); - - return { - tx: await writeContractAsync({ - account, - address: operator.owner.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.GATEWAY_REGISTRATION, data], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useUnstakeGateway() { - const client = usePublicClient(); - const { setWaitHeight } = useSquidNetworkHeight(); - const [isLoading, setLoading] = useState(false); - const [error, setError] = useState(null); - - const unstakeFromWallet = useUnstakeFromWallet(); - const unstakeFromVestingContract = useUnstakeFromVestingContract(); - - const unstakeFromGateway = async (req: UnstakeGatewayRequest): Promise => { - setLoading(true); - - const res = - req.operator.owner.type === AccountType.User - ? await unstakeFromWallet(req) - : await unstakeFromVestingContract(req); - - if (!res.tx) { - setLoading(false); - setError(res.error); - - return { success: false, failedReason: res.error }; - } - - if (!client) { - return { success: false, failedReason: 'missing client' }; - } - - const receipt = await client.waitForTransactionReceipt({ hash: res.tx }); - setWaitHeight(receipt.blockNumber, []); - - setLoading(false); - - return { success: true }; - }; - - return { - unstakeFromGateway, - isLoading, - error, - }; -} diff --git a/src/api/contracts/index.ts b/src/api/contracts/index.ts new file mode 100644 index 0000000..d325827 --- /dev/null +++ b/src/api/contracts/index.ts @@ -0,0 +1 @@ +export * from './subsquid.generated'; diff --git a/src/api/contracts/staking.ts b/src/api/contracts/staking.ts index b12eb0f..803b64e 100644 --- a/src/api/contracts/staking.ts +++ b/src/api/contracts/staking.ts @@ -14,14 +14,12 @@ import { } from 'wagmi'; import { useApproveSqd } from '@api/contracts/sqd'; -import { VESTING_CONTRACT_ABI } from '@api/contracts/abi/vesting.abi'; import { AccountType, Worker, SourceWallet } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; import { useAccount } from '@network/useAccount'; import { useContracts } from '@network/useContracts.ts'; -import { SOFT_CAP_ABI } from './abi/soft-cap.abi'; -import { STAKING_CONTRACT_ABI } from './abi/staking.abi'; +import { softCapAbi, stakingAbi, vestingAbi } from './subsquid.generated'; import { errorMessage, TxResult, isApproveRequiredError, WriteContractRes } from './utils'; type WorkerDepositRequest = { @@ -41,7 +39,7 @@ function useDelegateFromWallet() { return { tx: await writeContractAsync({ address: contracts.STAKING, - abi: STAKING_CONTRACT_ABI, + abi: stakingAbi, functionName: 'deposit', args: [BigInt(worker.id), BigInt(amount)], }), @@ -82,7 +80,7 @@ function useDepositFromVestingContract() { return async ({ worker, amount, wallet }: WorkerDepositRequest): Promise => { try { const data = encodeFunctionData({ - abi: STAKING_CONTRACT_ABI, + abi: stakingAbi, functionName: 'deposit', args: [BigInt(worker.id), BigInt(amount)], }); @@ -91,7 +89,7 @@ function useDepositFromVestingContract() { tx: await writeContractAsync({ account, address: wallet.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, + abi: vestingAbi, functionName: 'execute', args: [contracts.STAKING, data, BigInt(amount)], }), @@ -104,7 +102,7 @@ function useDepositFromVestingContract() { export function useWorkerDelegate() { const client = useClient(); - const { setWaitHeight } = useSquidNetworkHeight(); + const { setWaitHeight } = useSquidHeight(); const [isPending, setLoading] = useState(false); const [error, setError] = useState(null); @@ -154,7 +152,7 @@ function useUndelegateFromWallet() { return { tx: await writeContractAsync({ address: contracts.STAKING, - abi: STAKING_CONTRACT_ABI, + abi: stakingAbi, functionName: 'withdraw', args: [BigInt(worker.id), BigInt(amount)], }), @@ -173,7 +171,7 @@ function useUndelegateFromVestingContract() { return async ({ worker, amount, wallet }: WorkerDepositRequest): Promise => { try { const data = encodeFunctionData({ - abi: STAKING_CONTRACT_ABI, + abi: stakingAbi, functionName: 'withdraw', args: [BigInt(worker.id), BigInt(amount)], }); @@ -182,7 +180,7 @@ function useUndelegateFromVestingContract() { tx: await writeContractAsync({ account, address: wallet.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, + abi: vestingAbi, functionName: 'execute', args: [contracts.STAKING, data, BigInt(amount)], }), @@ -195,7 +193,7 @@ function useUndelegateFromVestingContract() { export function useWorkerUndelegate() { const client = usePublicClient(); - const { setWaitHeight } = useSquidNetworkHeight(); + const { setWaitHeight } = useSquidHeight(); const [isPending, setLoading] = useState(false); const [error, setError] = useState(null); @@ -238,11 +236,11 @@ export function useWorkerUndelegate() { export function useCapedStake({ workerId }: { workerId?: string }) { const contracts = useContracts(); - const { currentHeight, isLoading: isHeightLoading } = useSquidNetworkHeight(); + const { currentHeight, isLoading: isHeightLoading } = useSquidHeight(); const { data, isLoading } = useReadContract({ address: contracts.SOFT_CAP, - abi: SOFT_CAP_ABI, + abi: softCapAbi, functionName: 'capedStake', args: [BigInt(workerId || -1)], blockNumber: BigInt(currentHeight), @@ -279,13 +277,13 @@ export function useCapedStakeAfterDelegation({ contracts: [ { address: contracts.SOFT_CAP, - abi: SOFT_CAP_ABI, + abi: softCapAbi, functionName: 'capedStakeAfterDelegation', args: [BigInt(workerId), BigInt(amount || 0n) * (undelegate ? -1n : 1n)], }, { address: contracts.STAKING, - abi: STAKING_CONTRACT_ABI, + abi: stakingAbi, functionName: 'delegated', args: [BigInt(workerId)], }, diff --git a/src/api/contracts/subsquid.generated.ts b/src/api/contracts/subsquid.generated.ts new file mode 100644 index 0000000..4466a3d --- /dev/null +++ b/src/api/contracts/subsquid.generated.ts @@ -0,0 +1,1364 @@ +import { + createUseReadContract, + createUseWriteContract, + createUseSimulateContract, + createUseWatchContractEvent, +} from 'wagmi/codegen' + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// GatewayRegistry +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const gatewayRegistryAbi = [ + { + type: 'function', + inputs: [ + { name: 'peerId', internalType: 'bytes', type: 'bytes' }, + { name: 'metadata', internalType: 'string', type: 'string' }, + ], + name: 'register', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'peerId', internalType: 'bytes', type: 'bytes' }, + { name: 'metadata', internalType: 'string', type: 'string' }, + ], + name: 'setMetadata', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'amount', internalType: 'uint256', type: 'uint256' }, + { name: 'durationBlocks', internalType: 'uint128', type: 'uint128' }, + { name: 'withAutoExtension', internalType: 'bool', type: 'bool' }, + ], + name: 'stake', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'peerId', internalType: 'bytes', type: 'bytes' }], + name: 'unregister', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'unstake', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'amount', internalType: 'uint256', type: 'uint256' }, + { name: 'durationBlocks', internalType: 'uint256', type: 'uint256' }, + ], + name: 'computationUnitsAmount', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'amount', internalType: 'uint256', type: 'uint256' }], + name: 'addStake', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'disableAutoExtension', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'enableAutoExtension', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'operator', internalType: 'address', type: 'address' }], + name: 'canUnstake', + outputs: [{ name: '', internalType: 'bool', type: 'bool' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'amount', internalType: 'uint256', type: 'uint256' }, + { name: 'durationBlocks', internalType: 'uint256', type: 'uint256' }, + ], + name: 'computationUnitsAmount', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'operator', internalType: 'address', type: 'address' }], + name: 'getStake', + outputs: [ + { + name: '', + internalType: 'struct IGatewayRegistry.Stake', + type: 'tuple', + components: [ + { name: 'amount', internalType: 'uint256', type: 'uint256' }, + { name: 'lockStart', internalType: 'uint128', type: 'uint128' }, + { name: 'lockEnd', internalType: 'uint128', type: 'uint128' }, + { name: 'duration', internalType: 'uint128', type: 'uint128' }, + { name: 'autoExtension', internalType: 'bool', type: 'bool' }, + { name: 'oldCUs', internalType: 'uint256', type: 'uint256' }, + ], + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'minStake', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NetworkController +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const networkControllerAbi = [ + { + type: 'function', + inputs: [], + name: 'bondAmount', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'epochLength', + outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'workerEpochLength', + outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }], + stateMutability: 'view', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// RewardTreasury +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const rewardTreasuryAbi = [ + { + type: 'function', + inputs: [ + { + name: 'rewardDistribution', + internalType: 'contract IRewardsDistribution', + type: 'address', + }, + { name: 'receiver', internalType: 'address', type: 'address' }, + ], + name: 'claimFor', + outputs: [], + stateMutability: 'nonpayable', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Router +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const routerAbi = [ + { + type: 'function', + inputs: [], + name: 'networkController', + outputs: [ + { + name: '', + internalType: 'contract INetworkController', + type: 'address', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'rewardCalculation', + outputs: [ + { + name: '', + internalType: 'contract IRewardCalculation', + type: 'address', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'rewardTreasury', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'staking', + outputs: [{ name: '', internalType: 'contract IStaking', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'workerRegistration', + outputs: [ + { + name: '', + internalType: 'contract IWorkerRegistration', + type: 'address', + }, + ], + stateMutability: 'view', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SQD +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const sqdAbi = [ + { + type: 'event', + inputs: [ + { name: 'owner', type: 'address', indexed: true }, + { name: 'spender', type: 'address', indexed: true }, + { name: 'value', type: 'uint256', indexed: false }, + ], + name: 'Approval', + }, + { + type: 'event', + inputs: [ + { name: 'from', type: 'address', indexed: true }, + { name: 'to', type: 'address', indexed: true }, + { name: 'value', type: 'uint256', indexed: false }, + ], + name: 'Transfer', + }, + { + type: 'function', + inputs: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + ], + name: 'allowance', + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'spender', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + name: 'approve', + outputs: [{ type: 'bool' }], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'account', type: 'address' }], + name: 'balanceOf', + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'decimals', + outputs: [{ type: 'uint8' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'name', + outputs: [{ type: 'string' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'symbol', + outputs: [{ type: 'string' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'totalSupply', + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'recipient', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + name: 'transfer', + outputs: [{ type: 'bool' }], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'sender', type: 'address' }, + { name: 'recipient', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [{ type: 'bool' }], + stateMutability: 'nonpayable', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SoftCap +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const softCapAbi = [ + { + type: 'function', + inputs: [{ name: 'x', internalType: 'UD60x18', type: 'uint256' }], + name: 'cap', + outputs: [{ name: '', internalType: 'UD60x18', type: 'uint256' }], + stateMutability: 'pure', + }, + { + type: 'function', + inputs: [{ name: 'workerId', internalType: 'uint256', type: 'uint256' }], + name: 'capedStake', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'workerId', internalType: 'uint256', type: 'uint256' }, + { name: 'delegationAmount', internalType: 'int256', type: 'int256' }, + ], + name: 'capedStakeAfterDelegation', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Staking +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const stakingAbi = [ + { + type: 'function', + inputs: [ + { name: 'worker', internalType: 'uint256', type: 'uint256' }, + { name: 'amount', internalType: 'uint256', type: 'uint256' }, + ], + name: 'deposit', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'worker', type: 'uint256' }, + { name: 'amount', type: 'uint256' }, + ], + name: 'withdraw', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'staker', internalType: 'address', type: 'address' }], + name: 'claimable', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'worker', internalType: 'uint256', type: 'uint256' }], + name: 'delegated', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vesting +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const vestingAbi = [ + { + type: 'function', + inputs: [], + name: 'depositedIntoProtocol', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'duration', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'end', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'to', internalType: 'address', type: 'address' }, + { name: 'data', internalType: 'bytes', type: 'bytes' }, + ], + name: 'execute', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'to', internalType: 'address', type: 'address' }, + { name: 'data', internalType: 'bytes', type: 'bytes' }, + { name: 'requiredApprove', internalType: 'uint256', type: 'uint256' }, + ], + name: 'execute', + outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'expectedTotalAmount', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'immediateReleaseBIP', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'token', internalType: 'address', type: 'address' }], + name: 'releasable', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'releasable', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'token', internalType: 'address', type: 'address' }], + name: 'release', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'token', internalType: 'address', type: 'address' }], + name: 'released', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'start', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'token', internalType: 'address', type: 'address' }, + { name: 'timestamp', internalType: 'uint64', type: 'uint64' }, + ], + name: 'vestedAmount', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// WorkerRegistry +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +export const workerRegistryAbi = [ + { + type: 'function', + inputs: [], + name: 'bondAmount', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'peerId', internalType: 'bytes', type: 'bytes' }, + { name: 'metadata', internalType: 'string', type: 'string' }, + ], + name: 'register', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'peerId', internalType: 'bytes', type: 'bytes' }, + { name: 'metadata', internalType: 'string', type: 'string' }, + ], + name: 'updateMetadata', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'peerId', internalType: 'bytes', type: 'bytes' }], + name: 'deregister', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'peerId', internalType: 'bytes', type: 'bytes' }], + name: 'withdraw', + outputs: [], + stateMutability: 'nonpayable', + }, +] as const + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// React +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ + */ +export const useReadGatewayRegistry = /*#__PURE__*/ createUseReadContract({ + abi: gatewayRegistryAbi, +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"computationUnitsAmount"` + */ +export const useReadGatewayRegistryComputationUnitsAmount = + /*#__PURE__*/ createUseReadContract({ + abi: gatewayRegistryAbi, + functionName: 'computationUnitsAmount', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"canUnstake"` + */ +export const useReadGatewayRegistryCanUnstake = + /*#__PURE__*/ createUseReadContract({ + abi: gatewayRegistryAbi, + functionName: 'canUnstake', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"getStake"` + */ +export const useReadGatewayRegistryGetStake = + /*#__PURE__*/ createUseReadContract({ + abi: gatewayRegistryAbi, + functionName: 'getStake', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"minStake"` + */ +export const useReadGatewayRegistryMinStake = + /*#__PURE__*/ createUseReadContract({ + abi: gatewayRegistryAbi, + functionName: 'minStake', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ + */ +export const useWriteGatewayRegistry = /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"register"` + */ +export const useWriteGatewayRegistryRegister = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'register', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"setMetadata"` + */ +export const useWriteGatewayRegistrySetMetadata = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'setMetadata', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"stake"` + */ +export const useWriteGatewayRegistryStake = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'stake', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"unregister"` + */ +export const useWriteGatewayRegistryUnregister = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'unregister', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"unstake"` + */ +export const useWriteGatewayRegistryUnstake = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'unstake', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"addStake"` + */ +export const useWriteGatewayRegistryAddStake = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'addStake', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"disableAutoExtension"` + */ +export const useWriteGatewayRegistryDisableAutoExtension = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'disableAutoExtension', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"enableAutoExtension"` + */ +export const useWriteGatewayRegistryEnableAutoExtension = + /*#__PURE__*/ createUseWriteContract({ + abi: gatewayRegistryAbi, + functionName: 'enableAutoExtension', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ + */ +export const useSimulateGatewayRegistry = + /*#__PURE__*/ createUseSimulateContract({ abi: gatewayRegistryAbi }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"register"` + */ +export const useSimulateGatewayRegistryRegister = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'register', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"setMetadata"` + */ +export const useSimulateGatewayRegistrySetMetadata = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'setMetadata', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"stake"` + */ +export const useSimulateGatewayRegistryStake = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'stake', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"unregister"` + */ +export const useSimulateGatewayRegistryUnregister = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'unregister', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"unstake"` + */ +export const useSimulateGatewayRegistryUnstake = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'unstake', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"addStake"` + */ +export const useSimulateGatewayRegistryAddStake = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'addStake', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"disableAutoExtension"` + */ +export const useSimulateGatewayRegistryDisableAutoExtension = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'disableAutoExtension', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link gatewayRegistryAbi}__ and `functionName` set to `"enableAutoExtension"` + */ +export const useSimulateGatewayRegistryEnableAutoExtension = + /*#__PURE__*/ createUseSimulateContract({ + abi: gatewayRegistryAbi, + functionName: 'enableAutoExtension', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link networkControllerAbi}__ + */ +export const useReadNetworkController = /*#__PURE__*/ createUseReadContract({ + abi: networkControllerAbi, +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link networkControllerAbi}__ and `functionName` set to `"bondAmount"` + */ +export const useReadNetworkControllerBondAmount = + /*#__PURE__*/ createUseReadContract({ + abi: networkControllerAbi, + functionName: 'bondAmount', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link networkControllerAbi}__ and `functionName` set to `"epochLength"` + */ +export const useReadNetworkControllerEpochLength = + /*#__PURE__*/ createUseReadContract({ + abi: networkControllerAbi, + functionName: 'epochLength', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link networkControllerAbi}__ and `functionName` set to `"workerEpochLength"` + */ +export const useReadNetworkControllerWorkerEpochLength = + /*#__PURE__*/ createUseReadContract({ + abi: networkControllerAbi, + functionName: 'workerEpochLength', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link rewardTreasuryAbi}__ + */ +export const useWriteRewardTreasury = /*#__PURE__*/ createUseWriteContract({ + abi: rewardTreasuryAbi, +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link rewardTreasuryAbi}__ and `functionName` set to `"claimFor"` + */ +export const useWriteRewardTreasuryClaimFor = + /*#__PURE__*/ createUseWriteContract({ + abi: rewardTreasuryAbi, + functionName: 'claimFor', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link rewardTreasuryAbi}__ + */ +export const useSimulateRewardTreasury = + /*#__PURE__*/ createUseSimulateContract({ abi: rewardTreasuryAbi }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link rewardTreasuryAbi}__ and `functionName` set to `"claimFor"` + */ +export const useSimulateRewardTreasuryClaimFor = + /*#__PURE__*/ createUseSimulateContract({ + abi: rewardTreasuryAbi, + functionName: 'claimFor', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link routerAbi}__ + */ +export const useReadRouter = /*#__PURE__*/ createUseReadContract({ + abi: routerAbi, +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link routerAbi}__ and `functionName` set to `"networkController"` + */ +export const useReadRouterNetworkController = + /*#__PURE__*/ createUseReadContract({ + abi: routerAbi, + functionName: 'networkController', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link routerAbi}__ and `functionName` set to `"rewardCalculation"` + */ +export const useReadRouterRewardCalculation = + /*#__PURE__*/ createUseReadContract({ + abi: routerAbi, + functionName: 'rewardCalculation', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link routerAbi}__ and `functionName` set to `"rewardTreasury"` + */ +export const useReadRouterRewardTreasury = /*#__PURE__*/ createUseReadContract({ + abi: routerAbi, + functionName: 'rewardTreasury', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link routerAbi}__ and `functionName` set to `"staking"` + */ +export const useReadRouterStaking = /*#__PURE__*/ createUseReadContract({ + abi: routerAbi, + functionName: 'staking', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link routerAbi}__ and `functionName` set to `"workerRegistration"` + */ +export const useReadRouterWorkerRegistration = + /*#__PURE__*/ createUseReadContract({ + abi: routerAbi, + functionName: 'workerRegistration', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link sqdAbi}__ + */ +export const useReadSqd = /*#__PURE__*/ createUseReadContract({ abi: sqdAbi }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"allowance"` + */ +export const useReadSqdAllowance = /*#__PURE__*/ createUseReadContract({ + abi: sqdAbi, + functionName: 'allowance', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"balanceOf"` + */ +export const useReadSqdBalanceOf = /*#__PURE__*/ createUseReadContract({ + abi: sqdAbi, + functionName: 'balanceOf', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"decimals"` + */ +export const useReadSqdDecimals = /*#__PURE__*/ createUseReadContract({ + abi: sqdAbi, + functionName: 'decimals', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"name"` + */ +export const useReadSqdName = /*#__PURE__*/ createUseReadContract({ + abi: sqdAbi, + functionName: 'name', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"symbol"` + */ +export const useReadSqdSymbol = /*#__PURE__*/ createUseReadContract({ + abi: sqdAbi, + functionName: 'symbol', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"totalSupply"` + */ +export const useReadSqdTotalSupply = /*#__PURE__*/ createUseReadContract({ + abi: sqdAbi, + functionName: 'totalSupply', +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link sqdAbi}__ + */ +export const useWriteSqd = /*#__PURE__*/ createUseWriteContract({ abi: sqdAbi }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"approve"` + */ +export const useWriteSqdApprove = /*#__PURE__*/ createUseWriteContract({ + abi: sqdAbi, + functionName: 'approve', +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"transfer"` + */ +export const useWriteSqdTransfer = /*#__PURE__*/ createUseWriteContract({ + abi: sqdAbi, + functionName: 'transfer', +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"transferFrom"` + */ +export const useWriteSqdTransferFrom = /*#__PURE__*/ createUseWriteContract({ + abi: sqdAbi, + functionName: 'transferFrom', +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link sqdAbi}__ + */ +export const useSimulateSqd = /*#__PURE__*/ createUseSimulateContract({ + abi: sqdAbi, +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"approve"` + */ +export const useSimulateSqdApprove = /*#__PURE__*/ createUseSimulateContract({ + abi: sqdAbi, + functionName: 'approve', +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"transfer"` + */ +export const useSimulateSqdTransfer = /*#__PURE__*/ createUseSimulateContract({ + abi: sqdAbi, + functionName: 'transfer', +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link sqdAbi}__ and `functionName` set to `"transferFrom"` + */ +export const useSimulateSqdTransferFrom = + /*#__PURE__*/ createUseSimulateContract({ + abi: sqdAbi, + functionName: 'transferFrom', + }) + +/** + * Wraps __{@link useWatchContractEvent}__ with `abi` set to __{@link sqdAbi}__ + */ +export const useWatchSqdEvent = /*#__PURE__*/ createUseWatchContractEvent({ + abi: sqdAbi, +}) + +/** + * Wraps __{@link useWatchContractEvent}__ with `abi` set to __{@link sqdAbi}__ and `eventName` set to `"Approval"` + */ +export const useWatchSqdApprovalEvent = + /*#__PURE__*/ createUseWatchContractEvent({ + abi: sqdAbi, + eventName: 'Approval', + }) + +/** + * Wraps __{@link useWatchContractEvent}__ with `abi` set to __{@link sqdAbi}__ and `eventName` set to `"Transfer"` + */ +export const useWatchSqdTransferEvent = + /*#__PURE__*/ createUseWatchContractEvent({ + abi: sqdAbi, + eventName: 'Transfer', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link softCapAbi}__ + */ +export const useReadSoftCap = /*#__PURE__*/ createUseReadContract({ + abi: softCapAbi, +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link softCapAbi}__ and `functionName` set to `"cap"` + */ +export const useReadSoftCapCap = /*#__PURE__*/ createUseReadContract({ + abi: softCapAbi, + functionName: 'cap', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link softCapAbi}__ and `functionName` set to `"capedStake"` + */ +export const useReadSoftCapCapedStake = /*#__PURE__*/ createUseReadContract({ + abi: softCapAbi, + functionName: 'capedStake', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link softCapAbi}__ and `functionName` set to `"capedStakeAfterDelegation"` + */ +export const useReadSoftCapCapedStakeAfterDelegation = + /*#__PURE__*/ createUseReadContract({ + abi: softCapAbi, + functionName: 'capedStakeAfterDelegation', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link stakingAbi}__ + */ +export const useReadStaking = /*#__PURE__*/ createUseReadContract({ + abi: stakingAbi, +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link stakingAbi}__ and `functionName` set to `"claimable"` + */ +export const useReadStakingClaimable = /*#__PURE__*/ createUseReadContract({ + abi: stakingAbi, + functionName: 'claimable', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link stakingAbi}__ and `functionName` set to `"delegated"` + */ +export const useReadStakingDelegated = /*#__PURE__*/ createUseReadContract({ + abi: stakingAbi, + functionName: 'delegated', +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link stakingAbi}__ + */ +export const useWriteStaking = /*#__PURE__*/ createUseWriteContract({ + abi: stakingAbi, +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link stakingAbi}__ and `functionName` set to `"deposit"` + */ +export const useWriteStakingDeposit = /*#__PURE__*/ createUseWriteContract({ + abi: stakingAbi, + functionName: 'deposit', +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link stakingAbi}__ and `functionName` set to `"withdraw"` + */ +export const useWriteStakingWithdraw = /*#__PURE__*/ createUseWriteContract({ + abi: stakingAbi, + functionName: 'withdraw', +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link stakingAbi}__ + */ +export const useSimulateStaking = /*#__PURE__*/ createUseSimulateContract({ + abi: stakingAbi, +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link stakingAbi}__ and `functionName` set to `"deposit"` + */ +export const useSimulateStakingDeposit = + /*#__PURE__*/ createUseSimulateContract({ + abi: stakingAbi, + functionName: 'deposit', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link stakingAbi}__ and `functionName` set to `"withdraw"` + */ +export const useSimulateStakingWithdraw = + /*#__PURE__*/ createUseSimulateContract({ + abi: stakingAbi, + functionName: 'withdraw', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ + */ +export const useReadVesting = /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"depositedIntoProtocol"` + */ +export const useReadVestingDepositedIntoProtocol = + /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'depositedIntoProtocol', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"duration"` + */ +export const useReadVestingDuration = /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'duration', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"end"` + */ +export const useReadVestingEnd = /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'end', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"expectedTotalAmount"` + */ +export const useReadVestingExpectedTotalAmount = + /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'expectedTotalAmount', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"immediateReleaseBIP"` + */ +export const useReadVestingImmediateReleaseBip = + /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'immediateReleaseBIP', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"releasable"` + */ +export const useReadVestingReleasable = /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'releasable', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"released"` + */ +export const useReadVestingReleased = /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'released', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"start"` + */ +export const useReadVestingStart = /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'start', +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"vestedAmount"` + */ +export const useReadVestingVestedAmount = /*#__PURE__*/ createUseReadContract({ + abi: vestingAbi, + functionName: 'vestedAmount', +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link vestingAbi}__ + */ +export const useWriteVesting = /*#__PURE__*/ createUseWriteContract({ + abi: vestingAbi, +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"execute"` + */ +export const useWriteVestingExecute = /*#__PURE__*/ createUseWriteContract({ + abi: vestingAbi, + functionName: 'execute', +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"release"` + */ +export const useWriteVestingRelease = /*#__PURE__*/ createUseWriteContract({ + abi: vestingAbi, + functionName: 'release', +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link vestingAbi}__ + */ +export const useSimulateVesting = /*#__PURE__*/ createUseSimulateContract({ + abi: vestingAbi, +}) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"execute"` + */ +export const useSimulateVestingExecute = + /*#__PURE__*/ createUseSimulateContract({ + abi: vestingAbi, + functionName: 'execute', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link vestingAbi}__ and `functionName` set to `"release"` + */ +export const useSimulateVestingRelease = + /*#__PURE__*/ createUseSimulateContract({ + abi: vestingAbi, + functionName: 'release', + }) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link workerRegistryAbi}__ + */ +export const useReadWorkerRegistry = /*#__PURE__*/ createUseReadContract({ + abi: workerRegistryAbi, +}) + +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"bondAmount"` + */ +export const useReadWorkerRegistryBondAmount = + /*#__PURE__*/ createUseReadContract({ + abi: workerRegistryAbi, + functionName: 'bondAmount', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link workerRegistryAbi}__ + */ +export const useWriteWorkerRegistry = /*#__PURE__*/ createUseWriteContract({ + abi: workerRegistryAbi, +}) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"register"` + */ +export const useWriteWorkerRegistryRegister = + /*#__PURE__*/ createUseWriteContract({ + abi: workerRegistryAbi, + functionName: 'register', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"updateMetadata"` + */ +export const useWriteWorkerRegistryUpdateMetadata = + /*#__PURE__*/ createUseWriteContract({ + abi: workerRegistryAbi, + functionName: 'updateMetadata', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"deregister"` + */ +export const useWriteWorkerRegistryDeregister = + /*#__PURE__*/ createUseWriteContract({ + abi: workerRegistryAbi, + functionName: 'deregister', + }) + +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"withdraw"` + */ +export const useWriteWorkerRegistryWithdraw = + /*#__PURE__*/ createUseWriteContract({ + abi: workerRegistryAbi, + functionName: 'withdraw', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link workerRegistryAbi}__ + */ +export const useSimulateWorkerRegistry = + /*#__PURE__*/ createUseSimulateContract({ abi: workerRegistryAbi }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"register"` + */ +export const useSimulateWorkerRegistryRegister = + /*#__PURE__*/ createUseSimulateContract({ + abi: workerRegistryAbi, + functionName: 'register', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"updateMetadata"` + */ +export const useSimulateWorkerRegistryUpdateMetadata = + /*#__PURE__*/ createUseSimulateContract({ + abi: workerRegistryAbi, + functionName: 'updateMetadata', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"deregister"` + */ +export const useSimulateWorkerRegistryDeregister = + /*#__PURE__*/ createUseSimulateContract({ + abi: workerRegistryAbi, + functionName: 'deregister', + }) + +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link workerRegistryAbi}__ and `functionName` set to `"withdraw"` + */ +export const useSimulateWorkerRegistryWithdraw = + /*#__PURE__*/ createUseSimulateContract({ + abi: workerRegistryAbi, + functionName: 'withdraw', + }) diff --git a/src/api/contracts/vesting.ts b/src/api/contracts/vesting.ts deleted file mode 100644 index de2bdbf..0000000 --- a/src/api/contracts/vesting.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { useState } from 'react'; - -import { keepPreviousData } from '@tanstack/react-query'; -import { chunk } from 'lodash-es'; -import { erc20Abi, MulticallResponse } from 'viem'; -import { waitForTransactionReceipt } from 'viem/actions'; -import { useReadContracts, useWriteContract, useClient } from 'wagmi'; - -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useContracts } from '@network/useContracts'; - -import { errorMessage, WriteContractRes } from './utils'; -import { VESTING_CONTRACT_ABI } from './abi/vesting.abi'; - -export function useVestingContracts({ addresses }: { addresses?: `0x${string}`[] }) { - const contracts = useContracts(); - const { currentHeight, isLoading: isSquidHeightLoading } = useSquidNetworkHeight(); - - const { data, isLoading } = useReadContracts({ - contracts: addresses?.flatMap(address => { - const vestingContract = { abi: VESTING_CONTRACT_ABI, address } as const; - return [ - { - ...vestingContract, - functionName: 'start', - }, - { - ...vestingContract, - functionName: 'end', - }, - { - ...vestingContract, - functionName: 'depositedIntoProtocol', - }, - { - ...vestingContract, - functionName: 'releasable', - args: [contracts.SQD], - }, - { - ...vestingContract, - functionName: 'released', - args: [contracts.SQD], - }, - { - abi: erc20Abi, - address: contracts.SQD, - functionName: 'balanceOf', - args: [address], - }, - { - ...vestingContract, - functionName: 'immediateReleaseBIP', - }, - { - ...vestingContract, - functionName: 'expectedTotalAmount', - }, - ] as const; - }), - allowFailure: true, - blockNumber: BigInt(currentHeight), - query: { - enabled: !isSquidHeightLoading && !!addresses?.length, - placeholderData: keepPreviousData, - select: res => { - if (res?.some(r => r.status === 'success')) { - return chunk(res, 8).map(ch => ({ - start: Number(unwrapResult(ch[0])) * 1000, - end: Number(unwrapResult(ch[1])) * 1000, - deposited: unwrapResult(ch[2])?.toString(), - releasable: unwrapResult(ch[3])?.toString(), - released: unwrapResult(ch[4])?.toString(), - balance: unwrapResult(ch[5])?.toString(), - initialRelease: Number(unwrapResult(ch[6]) || 0) / 100, - expectedTotal: unwrapResult(ch[7])?.toString(), - })); - } else if (res?.length === 0) { - return []; - } - - return undefined; - }, - }, - }); - - return { - data, - isLoading: isLoading, - }; -} - -export function useVestingContract({ address }: { address?: `0x${string}` }) { - const { data, isLoading } = useVestingContracts({ addresses: address ? [address] : [] }); - - return { - data: data?.[0], - isLoading, - }; -} - -function unwrapResult(result?: MulticallResponse): T | undefined { - return result?.status === 'success' ? (result.result as T) : undefined; -} - -export function useVestingContractRelease() { - const client = useClient(); - const { setWaitHeight } = useSquidNetworkHeight(); - const [isLoading, setLoading] = useState(false); - const [error, setError] = useState(null); - const { SQD } = useContracts(); - - const { writeContractAsync } = useWriteContract({}); - - const release = async ({ address }: { address: `0x${string}` }): Promise => { - setLoading(true); - - try { - const hash = await writeContractAsync({ - abi: VESTING_CONTRACT_ABI, - functionName: 'release', - args: [SQD], - address, - }); - - const receipt = await waitForTransactionReceipt(client!, { hash }); - setWaitHeight(receipt.blockNumber, []); - - return { success: true }; - } catch (e) { - const failedReason = errorMessage(e); - setError(failedReason); - return { success: false, failedReason }; - } finally { - setLoading(false); - } - }; - - return { - release, - isLoading, - error, - }; -} diff --git a/src/api/contracts/worker-registration/WorkerMetadata.ts b/src/api/contracts/worker-registration/WorkerMetadata.ts index 5c86c37..86bdc06 100644 --- a/src/api/contracts/worker-registration/WorkerMetadata.ts +++ b/src/api/contracts/worker-registration/WorkerMetadata.ts @@ -2,9 +2,9 @@ import { pickBy } from 'lodash-es'; import isEmpty from 'lodash-es/isEmpty'; export interface WorkerMetadata { - name: string; - email: string; - description: string; + name?: string; + email?: string; + description?: string; website?: string; } diff --git a/src/api/contracts/worker-registration/useRegisterWorker.ts b/src/api/contracts/worker-registration/useRegisterWorker.ts deleted file mode 100644 index f8fc204..0000000 --- a/src/api/contracts/worker-registration/useRegisterWorker.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { useState } from 'react'; - -import { peerIdToHex } from '@lib/network'; -import { logger } from '@logger'; -import { encodeFunctionData } from 'viem'; -import { waitForTransactionReceipt } from 'viem/actions'; -import { useWriteContract, usePublicClient, useClient } from 'wagmi'; - -import { useApproveSqd } from '@api/contracts/sqd'; -import { VESTING_CONTRACT_ABI } from '@api/contracts/abi/vesting.abi'; -import { AccountType, SourceWallet } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount'; -import { useContracts } from '@network/useContracts.ts'; - -import { TxResult, errorMessage, isApproveRequiredError, WriteContractRes } from '../utils'; - -import { encodeWorkerMetadata, WorkerMetadata } from './WorkerMetadata'; -import { WORKER_REGISTRATION_CONTRACT_ABI } from '../abi/WorkerRegistration.abi'; - -export interface AddWorkerRequest extends WorkerMetadata { - peerId: string; - source: SourceWallet; -} - -function useRegisterFromWallet() { - const contracts = useContracts(); - const publicClient = usePublicClient(); - const [approveSqd] = useApproveSqd(); - - const { writeContractAsync } = useWriteContract({}); - - const tryCallRegistrationContract = async ({ - peerId, - ...rest - }: AddWorkerRequest): Promise => { - try { - return { - tx: await writeContractAsync({ - address: contracts.WORKER_REGISTRATION, - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'register', - args: [peerIdToHex(peerId), encodeWorkerMetadata(rest)], - }), - }; - } catch (e: unknown) { - return { - error: errorMessage(e), - }; - } - }; - - return async (req: AddWorkerRequest): Promise => { - logger.debug(`registering worker via worker contract...`); - - const res = await tryCallRegistrationContract(req); - // Try to approve SQD - if (isApproveRequiredError(res.error)) { - const bond = await publicClient!.readContract({ - address: contracts.WORKER_REGISTRATION, - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'bondAmount', - }); - - const approveRes = await approveSqd({ - contractAddress: contracts.WORKER_REGISTRATION, - amount: bond.toString(), - }); - if (!approveRes.success) { - return { error: approveRes.failedReason }; - } - - logger.debug(`approved SQD successfully, now trying to register one more time...`); - - return tryCallRegistrationContract(req); - } - - return res; - }; -} - -function useRegisterWorkerFromVestingContract() { - const contracts = useContracts(); - const publicClient = usePublicClient(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ peerId, source, ...rest }: AddWorkerRequest): Promise => { - try { - const bond = await publicClient!.readContract({ - address: contracts.WORKER_REGISTRATION, - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'bondAmount', - }); - - const data = encodeFunctionData({ - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'register', - args: [peerIdToHex(peerId), encodeWorkerMetadata(rest)], - }); - - return { - tx: await writeContractAsync({ - account, - address: source.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.WORKER_REGISTRATION, data, bond], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useRegisterWorker() { - const client = useClient(); - const { address } = useAccount(); - const [error, setError] = useState(null); - const [isLoading, setLoading] = useState(false); - - const { setWaitHeight } = useSquidNetworkHeight(); - const registerWorkerContract = useRegisterFromWallet(); - const registerVestingContract = useRegisterWorkerFromVestingContract(); - - const registerWorker = async (req: AddWorkerRequest): Promise => { - setLoading(true); - - const { tx, error } = - req.source.type === AccountType.Vesting - ? await registerVestingContract(req) - : await registerWorkerContract(req); - - if (!tx) { - logger.debug(`registering worker failed ${error}`); - setLoading(false); - setError(error); - return { success: false, failedReason: error }; - } - - const receipt = await waitForTransactionReceipt(client!, { hash: tx }); - setWaitHeight(receipt.blockNumber, ['myWorkers', { address }]); - setLoading(false); - setError(null); - - return { success: true }; - }; - - return { registerWorker, isLoading, error }; -} diff --git a/src/api/contracts/worker-registration/useUnregisterWorker.ts b/src/api/contracts/worker-registration/useUnregisterWorker.ts deleted file mode 100644 index 3350817..0000000 --- a/src/api/contracts/worker-registration/useUnregisterWorker.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { useState } from 'react'; - -import { peerIdToHex } from '@lib/network'; -import { logger } from '@logger'; -import { encodeFunctionData } from 'viem'; -import { waitForTransactionReceipt } from 'viem/actions'; -import { useWriteContract, useClient } from 'wagmi'; - -import { VESTING_CONTRACT_ABI } from '@api/contracts/abi/vesting.abi'; -import { AccountType } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount'; -import { useContracts } from '@network/useContracts.ts'; - -import { TxResult, errorMessage, WriteContractRes } from '../utils'; - -import { WORKER_REGISTRATION_CONTRACT_ABI } from '../abi/WorkerRegistration.abi'; - -export interface UnregisterWorkerRequest { - peerId: string; - source: { - id: string; - type: AccountType; - }; -} - -function useUnregisterWorkerFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ peerId }: { peerId: string }): Promise => { - try { - return { - tx: await writeContractAsync({ - address: contracts.WORKER_REGISTRATION, - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'deregister', - args: [peerIdToHex(peerId)], - }), - }; - } catch (e) { - return { error: errorMessage(e) }; - } - }; -} - -function useUnregisterWorkerFromVestingContract() { - const contracts = useContracts(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ peerId, source }: UnregisterWorkerRequest): Promise => { - try { - const data = encodeFunctionData({ - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'deregister', - args: [peerIdToHex(peerId)], - }); - - return { - tx: await writeContractAsync({ - account, - address: source.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.WORKER_REGISTRATION, data], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useUnregisterWorker() { - const client = useClient(); - const { address } = useAccount(); - const [isLoading, setLoading] = useState(false); - const { setWaitHeight } = useSquidNetworkHeight(); - const [error, setError] = useState(null); - - const unregisterWorkerFromWallet = useUnregisterWorkerFromWallet(); - const unregisterWorkerFromVestingContract = useUnregisterWorkerFromVestingContract(); - - const unregisterWorker = async (req: UnregisterWorkerRequest): Promise => { - setLoading(true); - - const { tx, error } = - req.source.type === AccountType.User - ? await unregisterWorkerFromWallet(req) - : await unregisterWorkerFromVestingContract(req); - - if (!tx) { - logger.debug(`update worker failed ${error}`); - setLoading(false); - setError(error); - return { success: false, failedReason: error }; - } - - const receipt = await waitForTransactionReceipt(client!, { hash: tx }); - setWaitHeight(receipt.blockNumber, ['myWorkers', { address }]); - setLoading(false); - setError(null); - - return { success: true }; - }; - - return { - unregisterWorker, - isLoading, - error, - }; -} diff --git a/src/api/contracts/worker-registration/useUpdateWorker.ts b/src/api/contracts/worker-registration/useUpdateWorker.ts index daf7236..28263e7 100644 --- a/src/api/contracts/worker-registration/useUpdateWorker.ts +++ b/src/api/contracts/worker-registration/useUpdateWorker.ts @@ -7,15 +7,14 @@ import { waitForTransactionReceipt } from 'viem/actions'; import { useWriteContract, useClient } from 'wagmi'; import { AccountType } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; import { useAccount } from '@network/useAccount'; import { useContracts } from '@network/useContracts.ts'; +import { vestingAbi, workerRegistryAbi } from '../subsquid.generated'; import { TxResult, errorMessage, WriteContractRes } from '../utils'; -import { VESTING_CONTRACT_ABI } from '../abi/vesting.abi'; import { encodeWorkerMetadata, WorkerMetadata } from './WorkerMetadata'; -import { WORKER_REGISTRATION_CONTRACT_ABI } from '../abi/WorkerRegistration.abi'; export interface UpdateWorkerRequest extends WorkerMetadata { peerId: string; @@ -34,7 +33,7 @@ function useUpdateWorkerFromWallet() { return { tx: await writeContractAsync({ address: contracts.WORKER_REGISTRATION, - abi: WORKER_REGISTRATION_CONTRACT_ABI, + abi: workerRegistryAbi, functionName: 'updateMetadata', args: [peerIdToHex(peerId), encodeWorkerMetadata(rest)], }), @@ -53,7 +52,7 @@ function useUpdateWorkerFromVestingContract() { return async ({ peerId, source, ...rest }: UpdateWorkerRequest): Promise => { try { const data = encodeFunctionData({ - abi: WORKER_REGISTRATION_CONTRACT_ABI, + abi: workerRegistryAbi, functionName: 'updateMetadata', args: [peerIdToHex(peerId), encodeWorkerMetadata(rest)], }); @@ -62,7 +61,7 @@ function useUpdateWorkerFromVestingContract() { tx: await writeContractAsync({ account, address: source.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, + abi: vestingAbi, functionName: 'execute', args: [contracts.WORKER_REGISTRATION, data], }), @@ -79,7 +78,7 @@ export function useUpdateWorker() { const [error, setError] = useState(null); const [isLoading, setLoading] = useState(false); - const { setWaitHeight } = useSquidNetworkHeight(); + const { setWaitHeight } = useSquidHeight(); const updateWorkerFromWallet = useUpdateWorkerFromWallet(); const updateWorkerFromVestingContract = useUpdateWorkerFromVestingContract(); diff --git a/src/api/contracts/worker-registration/useWithdrawWorker.ts b/src/api/contracts/worker-registration/useWithdrawWorker.ts deleted file mode 100644 index 1229877..0000000 --- a/src/api/contracts/worker-registration/useWithdrawWorker.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { useState } from 'react'; - -import { peerIdToHex } from '@lib/network'; -import { logger } from '@logger'; -import { encodeFunctionData } from 'viem'; -import { waitForTransactionReceipt } from 'viem/actions'; -import { useWriteContract, useClient } from 'wagmi'; - -import { VESTING_CONTRACT_ABI } from '@api/contracts/abi/vesting.abi'; -import { UnregisterWorkerRequest } from '@api/contracts/worker-registration/useUnregisterWorker'; -import { AccountType } from '@api/subsquid-network-squid'; -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; -import { useAccount } from '@network/useAccount'; -import { useContracts } from '@network/useContracts.ts'; - -import { TxResult, errorMessage, WriteContractRes } from '../utils'; - -import { WORKER_REGISTRATION_CONTRACT_ABI } from '../abi/WorkerRegistration.abi'; - -function useWithdrawWorkerFromWallet() { - const contracts = useContracts(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ peerId }: { peerId: string }): Promise => { - try { - return { - tx: await writeContractAsync({ - address: contracts.WORKER_REGISTRATION, - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'withdraw', - args: [peerIdToHex(peerId)], - }), - }; - } catch (e) { - return { error: errorMessage(e) }; - } - }; -} - -function useWithdrawWorkerFromVestingContract() { - const contracts = useContracts(); - const { address: account } = useAccount(); - const { writeContractAsync } = useWriteContract({}); - - return async ({ peerId, source }: UnregisterWorkerRequest): Promise => { - try { - const data = encodeFunctionData({ - abi: WORKER_REGISTRATION_CONTRACT_ABI, - functionName: 'withdraw', - args: [peerIdToHex(peerId)], - }); - - return { - tx: await writeContractAsync({ - account, - address: source.id as `0x${string}`, - abi: VESTING_CONTRACT_ABI, - functionName: 'execute', - args: [contracts.WORKER_REGISTRATION, data], - }), - }; - } catch (e: unknown) { - return { error: errorMessage(e) }; - } - }; -} - -export function useWithdrawWorker() { - const client = useClient(); - const { address } = useAccount(); - const [isLoading, setLoading] = useState(false); - const { setWaitHeight } = useSquidNetworkHeight(); - const [error, setError] = useState(null); - - const withdrawWorkerFromWallet = useWithdrawWorkerFromWallet(); - const withdrawWorkerFromVestingContract = useWithdrawWorkerFromVestingContract(); - - const withdrawWorker = async (req: UnregisterWorkerRequest): Promise => { - setLoading(true); - - const { tx, error } = - req.source.type === AccountType.User - ? await withdrawWorkerFromWallet(req) - : await withdrawWorkerFromVestingContract(req); - - if (!tx) { - logger.debug(`withdraw worker failed ${error}`); - setLoading(false); - setError(error); - return { success: false, failedReason: error }; - } - - const receipt = await waitForTransactionReceipt(client!, { hash: tx }); - setWaitHeight(receipt.blockNumber, ['myWorkers', { address }]); - setLoading(false); - setError(null); - - return { success: true }; - }; - - return { - withdrawWorker, - isLoading, - error, - }; -} diff --git a/src/api/subsquid-network-squid/accounts-graphql.ts b/src/api/subsquid-network-squid/accounts-graphql.ts index f316701..ebc1858 100644 --- a/src/api/subsquid-network-squid/accounts-graphql.ts +++ b/src/api/subsquid-network-squid/accounts-graphql.ts @@ -4,7 +4,7 @@ import BigNumber from 'bignumber.js'; import { useAccount } from '@network/useAccount'; -import { useSquidDataSource } from './datasource'; +import { useSquid } from './datasource'; import { AccountType, useAccountQuery, @@ -23,7 +23,7 @@ export type SourceWalletWithBalance = SourceWallet & { }; export function useMySources({ enabled }: { enabled?: boolean } = {}) { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { address } = useAccount(); const requestEnabled = enabled && !!address; const { data: data, isPending } = useAccountQuery( @@ -40,33 +40,22 @@ export function useMySources({ enabled }: { enabled?: boolean } = {}) { const res = useMemo((): SourceWalletWithBalance[] => { return !wallet - ? [ - { - type: AccountType.User, - id: address as string, - balance: '0', - }, - ] + ? [] : [wallet, ...wallet.owned].map(a => ({ type: a.type, id: a.id, balance: a.balance, })); - }, [address, wallet]); - - const vestingContracts = useMemo(() => { - return res.filter(a => a.type === AccountType.Vesting); - }, [res]); + }, [wallet]); return { sources: res, - vestingContracts, isPending, }; } export function useMyAssets() { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { address } = useAccount(); const enabled = !!address; @@ -144,7 +133,7 @@ export class BlockchainApiVesting { } export function useVestingByAddress({ address }: { address?: string }) { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const account = useAccount(); const { data, isPending } = useVestingByAddressQuery( diff --git a/src/api/subsquid-network-squid/datasource.ts b/src/api/subsquid-network-squid/datasource.ts index bb378bd..5832d6b 100644 --- a/src/api/subsquid-network-squid/datasource.ts +++ b/src/api/subsquid-network-squid/datasource.ts @@ -1,6 +1,6 @@ import { NetworkName, getSubsquidNetwork } from '@network/useSubsquidNetwork'; -export function useSquidDataSource() { +export function useSquid() { const network = getSubsquidNetwork(); return { diff --git a/src/api/subsquid-network-squid/gateways-graphql.ts b/src/api/subsquid-network-squid/gateways-graphql.ts index de4a7c0..19b1950 100644 --- a/src/api/subsquid-network-squid/gateways-graphql.ts +++ b/src/api/subsquid-network-squid/gateways-graphql.ts @@ -1,4 +1,4 @@ -import { useSquidDataSource } from '@api/subsquid-network-squid/datasource'; +import { useSquid } from '@api/subsquid-network-squid/datasource'; import { useAccount } from '@network/useAccount'; import { useGatewayByPeerIdQuery, useMyGatewaysQuery, useMyGatewayStakesQuery } from './graphql'; @@ -21,7 +21,7 @@ import { useGatewayByPeerIdQuery, useMyGatewaysQuery, useMyGatewayStakesQuery } // } export function useMyGateways() { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { address } = useAccount(); const enabled = !!address; @@ -45,7 +45,7 @@ export function useMyGateways() { } export function useGatewayByPeerId(peerId?: string) { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const enabled = !!peerId; const { data, isLoading } = useGatewayByPeerIdQuery( @@ -70,7 +70,7 @@ export function useGatewayByPeerId(peerId?: string) { } export function useMyGatewayStake() { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { address } = useAccount(); const enabled = !!address; diff --git a/src/api/subsquid-network-squid/graphql.tsx b/src/api/subsquid-network-squid/graphql.tsx index 5661a72..a40bcd0 100644 --- a/src/api/subsquid-network-squid/graphql.tsx +++ b/src/api/subsquid-network-squid/graphql.tsx @@ -5277,6 +5277,8 @@ export type WorkerFragmentFragment = { jailed?: boolean; dialOk?: boolean; jailReason?: string; + owner: { __typename?: 'Account'; id: string; type: AccountType }; + realOwner: { __typename?: 'Account'; id: string }; }; export type WorkerFullFragmentFragment = { @@ -5339,6 +5341,8 @@ export type AllWorkersQuery = { jailed?: boolean; dialOk?: boolean; jailReason?: string; + owner: { __typename?: 'Account'; id: string; type: AccountType }; + realOwner: { __typename?: 'Account'; id: string }; }>; }; @@ -5437,6 +5441,8 @@ export type MyWorkersQuery = { jailed?: boolean; dialOk?: boolean; jailReason?: string; + owner: { __typename?: 'Account'; id: string; type: AccountType }; + realOwner: { __typename?: 'Account'; id: string }; }>; }; @@ -5552,6 +5558,8 @@ export type MyDelegationsQuery = { jailed?: boolean; dialOk?: boolean; jailReason?: string; + owner: { __typename?: 'Account'; id: string; type: AccountType }; + realOwner: { __typename?: 'Account'; id: string }; }; }>; }; @@ -5763,6 +5771,13 @@ export const WorkerFragmentFragmentDoc = ` stakerApr totalDelegation capedDelegation + owner { + id + type + } + realOwner { + id + } } ${WorkerBaseFragmentFragmentDoc} ${WorkerStatusFragmentFragmentDoc}`; @@ -5790,13 +5805,6 @@ export const WorkerFullFragmentFragmentDoc = ` timestamp uptime } - owner { - id - type - } - realOwner { - id - } } ${WorkerFragmentFragmentDoc}`; export const GatewayFragmentFragmentDoc = ` diff --git a/src/api/subsquid-network-squid/settings-graphql.ts b/src/api/subsquid-network-squid/settings-graphql.ts index 47f1b5d..e2a8c03 100644 --- a/src/api/subsquid-network-squid/settings-graphql.ts +++ b/src/api/subsquid-network-squid/settings-graphql.ts @@ -1,10 +1,10 @@ import { toSqd } from '@lib/network'; -import { useSquidDataSource } from './datasource'; +import { useSquid } from './datasource'; import { useCurrentEpochQuery, useNetworkSummaryQuery, useSettingsQuery } from './graphql'; export function useNetworkSettings() { - const dataSource = useSquidDataSource(); + const dataSource = useSquid(); const { data, isPending } = useSettingsQuery(dataSource); const settings = data?.settingsConnection.edges?.[0]?.node; @@ -21,7 +21,7 @@ export function useNetworkSettings() { } export function useNetworkSummary() { - const dataSource = useSquidDataSource(); + const dataSource = useSquid(); const { data: networkStats, isLoading: isNetworkStatsLoading } = useNetworkSummaryQuery( dataSource, {}, diff --git a/src/api/subsquid-network-squid/workers-graphql.ts b/src/api/subsquid-network-squid/workers-graphql.ts index 3e303df..987a7d0 100644 --- a/src/api/subsquid-network-squid/workers-graphql.ts +++ b/src/api/subsquid-network-squid/workers-graphql.ts @@ -2,18 +2,15 @@ import { useMemo } from 'react'; import { calculateDelegationCapacity } from '@lib/network'; import BigNumber from 'bignumber.js'; -import { groupBy, mapValues, values } from 'lodash-es'; import { compare as compareSemver } from 'semver'; import { PartialDeep, SimplifyDeep } from 'type-fest'; import { useAccount } from '@network/useAccount.ts'; -import { useSquidDataSource } from './datasource'; +import { useSquid } from './datasource'; import { - ClaimType, MyDelegationsQuery, useAllWorkersQuery, - useMyClaimsQuery, useMyDelegationsQuery, useMyWorkerDelegationsQuery, useMyWorkersCountQuery, @@ -198,7 +195,7 @@ export function useWorkers({ sortBy: WorkerSortBy; sortDir: SortDir; }) { - const dataSource = useSquidDataSource(); + const dataSource = useSquid(); const { isPending: isSettingsLoading } = useNetworkSettings(); const { data, isPending } = useAllWorkersQuery(dataSource, {}); @@ -244,7 +241,7 @@ export function useWorkers({ } export function useMyWorkers({ sortBy, sortDir }: { sortBy: WorkerSortBy; sortDir: SortDir }) { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { address } = useAccount(); const { isPending: isSettingsLoading } = useNetworkSettings(); @@ -278,7 +275,7 @@ export function useMyWorkers({ sortBy, sortDir }: { sortBy: WorkerSortBy; sortDi } export function useWorkerByPeerId(peerId?: string) { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const enabled = !!peerId; const { isPending: isSettingsLoading } = useNetworkSettings(); const { address } = useAccount(); @@ -309,75 +306,68 @@ export function useWorkerByPeerId(peerId?: string) { }; } -export function useMyClaimsAvailable({ source }: { source?: string } = {}) { - const { address } = useAccount(); - const datasource = useSquidDataSource(); - - const { data, isLoading } = useMyClaimsQuery(datasource, { - address: address || '', - }); - - const { sources, claims, hasClaimsAvailable, currentSourceTotalClaimsAvailable } = useMemo(() => { - const allWorkers = [ - ...(data?.workers || []).map(w => ({ - ...w, - type: ClaimType.Worker, - })), - ...(data?.delegations || []).map(d => { - return { - ...d.worker, - type: ClaimType.Delegation, - owner: d.owner, - claimableReward: d.claimableReward, - }; - }), - ]; - - const filteredWorkers = source ? allWorkers.filter(w => w.owner.id === source) : allWorkers; - - return { - hasClaimsAvailable: allWorkers.some(w => BigInt(w.claimableReward) > 0), - currentSourceTotalClaimsAvailable: filteredWorkers.reduce( - (t, i) => t.plus(i.claimableReward), - BigNumber(0), - ), - sources: values( - mapValues(groupBy(allWorkers, 'owner.id'), g => { - const total = g.reduce((t, i) => t.plus(i.claimableReward), BigNumber(0)); - - return { - ...g[0].owner, - balance: total.toFixed(0), - }; - }), - ), - - claims: values( - mapValues(groupBy(filteredWorkers, 'id'), g => { - const total = g.reduce((t, i) => t.plus(i.claimableReward), BigNumber(0)); - - return { - ...g[0], - claimableReward: total.toFixed(0), - }; - }), - ), - }; - }, [data?.delegations, data?.workers, source]); - - return { - isLoading, - hasClaimsAvailable, - currentSourceTotalClaimsAvailable, - sources, - claims, - }; -} +// export function useMyClaimsAvailable() { +// const { address } = useAccount(); +// const datasource = useSquidDataSource(); + +// const { data, isLoading } = useMyClaimsQuery(datasource, { +// address: address || '', +// }); + +// const { sources, claims } = useMemo(() => { +// const allWorkers = [ +// ...(data?.workers || []).map(w => ({ +// ...w, +// type: ClaimType.Worker, +// })), +// ...(data?.delegations || []).map(d => { +// return { +// ...d.worker, +// type: ClaimType.Delegation, +// owner: d.owner, +// claimableReward: d.claimableReward, +// }; +// }), +// ]; + +// const filteredWorkers = source ? allWorkers.filter(w => w.owner.id === source) : allWorkers; + +// return { +// sources: values( +// mapValues(groupBy(allWorkers, 'owner.id'), g => { +// const total = g.reduce((t, i) => t.plus(i.claimableReward), BigNumber(0)); + +// return { +// ...g[0].owner, +// balance: total.toFixed(0), +// }; +// }), +// ), + +// claims: values( +// mapValues(groupBy(filteredWorkers, 'id'), g => { +// const total = g.reduce((t, i) => t.plus(i.claimableReward), BigNumber(0)); + +// return { +// ...g[0], +// claimableReward: total.toFixed(0), +// }; +// }), +// ), +// }; +// }, [data?.delegations, data?.workers, source]); + +// return { +// isLoading, +// sources, +// claims, +// }; +// } export function useMyDelegations({ sortBy, sortDir }: { sortBy: WorkerSortBy; sortDir: SortDir }) { const { address } = useAccount(); const { isPending: isSettingsLoading } = useNetworkSettings(); - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { data, isLoading } = useMyDelegationsQuery( datasource, @@ -443,7 +433,7 @@ export function useMyDelegations({ sortBy, sortDir }: { sortBy: WorkerSortBy; so export function useIsWorkerOperator() { const { address } = useAccount(); - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { data, isLoading } = useMyWorkersCountQuery( datasource, { @@ -469,7 +459,7 @@ export function useWorkerDelegationInfo({ workerId?: string; enabled?: boolean; }) { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { data, isLoading } = useWorkerDelegationInfoQuery( datasource, { @@ -493,7 +483,7 @@ export function useWorkerDelegationInfo({ } export function useWorkerOwner({ workerId, enabled }: { workerId?: string; enabled?: boolean }) { - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { data, isLoading } = useWorkerOwnerQuery( datasource, { @@ -521,7 +511,7 @@ export function useMyWorkerDelegations({ enabled?: boolean; }) { const { address } = useAccount(); - const datasource = useSquidDataSource(); + const datasource = useSquid(); const { data, isLoading } = useMyWorkerDelegationsQuery( datasource, { diff --git a/src/components/Alert/Alert.tsx b/src/components/Alert/Alert.tsx deleted file mode 100644 index a438e25..0000000 --- a/src/components/Alert/Alert.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, { forwardRef } from 'react'; - -import { Alert as MaterialAlert, styled } from '@mui/material'; -import { InternalSnack, useSnackbar } from 'notistack'; - -export const AlertTitle = styled('div', { - name: 'AlertTitle', -})(({ theme }) => ({ - fontWeight: 500, - fontSize: '1.125rem', - marginBottom: theme.spacing(1), - maxWidth: 360, -})); - -export const AlertMessage = styled('div', { - name: 'AlertMessage', -})(({ theme }) => ({ - fontSize: '1rem', - fontWeight: 'normal', - maxWidth: 360, -})); - -export const Alert = forwardRef( - ( - { - id, - severity, - title, - message, - }: { - title?: string; - severity: 'warning'; - } & InternalSnack, - ref, - ) => { - const { closeSnackbar } = useSnackbar(); - - return ( - closeSnackbar(id)} - > - {title && {title}} - {message} - - ); - }, -); diff --git a/src/components/Alert/index.ts b/src/components/Alert/index.ts deleted file mode 100644 index 79e3b15..0000000 --- a/src/components/Alert/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Alert'; diff --git a/src/components/Button/ConnectButton.tsx b/src/components/Button/ConnectButton.tsx index 388b0c2..55208d3 100644 --- a/src/components/Button/ConnectButton.tsx +++ b/src/components/Button/ConnectButton.tsx @@ -1,12 +1,11 @@ import { MouseEventHandler } from 'react'; +import { LoginOutlined } from '@mui/icons-material'; import { Button } from '@mui/material'; -import { WalletIcon } from '@icons/WalletIcon'; - function ConnectButton({ onClick }: { onClick?: MouseEventHandler }) { return ( - ); diff --git a/src/components/ConfirmDialog/ConfirmDialog.tsx b/src/components/ConfirmDialog/ConfirmDialog.tsx index 08c04c1..90ce909 100644 --- a/src/components/ConfirmDialog/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog/ConfirmDialog.tsx @@ -95,8 +95,8 @@ export function ConfirmDialog({ maxWidth = 440, minWidth = 440, confirmColor = 'info', - confirmButtonText = 'CONFIRM', - cancelButtonText = 'CANCEL', + confirmButtonText = 'Confirm', + cancelButtonText = 'Cancel', disableBackdropClick = false, disableConfirmButton = false, hideCancelButton = false, @@ -139,7 +139,7 @@ export function ConfirmDialog({ {!hideCancelButton ? ( - ) : null} diff --git a/src/components/HelpTooltip/HelpTooltip.tsx b/src/components/HelpTooltip/HelpTooltip.tsx index 261d740..869b6fe 100644 --- a/src/components/HelpTooltip/HelpTooltip.tsx +++ b/src/components/HelpTooltip/HelpTooltip.tsx @@ -1,8 +1,7 @@ import React, { PropsWithChildren } from 'react'; -import { Box, Tooltip } from '@mui/material'; - -import { InfoIcon } from '@icons/InfoIcon'; +import { InfoOutlined } from '@mui/icons-material'; +import { Stack, Tooltip } from '@mui/material'; // export const Help = styled(Box)(({ theme, color }) => ({ // width: 15, @@ -21,14 +20,19 @@ import { InfoIcon } from '@icons/InfoIcon'; export const HelpTooltip = ({ title, + children, + placement = 'end', }: PropsWithChildren<{ title: React.ReactNode; + placement?: 'start' | 'end'; }>) => { return ( - - - - - + + {placement === 'end' && children} + + + + {placement === 'start' && children} + ); }; diff --git a/src/components/SourceWallet/useMySourceOptions.tsx b/src/components/SourceWallet/useMySourceOptions.tsx index 6335388..efe8a54 100644 --- a/src/components/SourceWallet/useMySourceOptions.tsx +++ b/src/components/SourceWallet/useMySourceOptions.tsx @@ -1,26 +1,10 @@ -import React from 'react'; +import { useMySources } from '@api/subsquid-network-squid'; -import { SourceWalletWithBalance, useMySources } from '@api/subsquid-network-squid'; - -import { SourceWalletOption } from './SourceWalletOption'; - -export function useMySourceOptions({ - enabled = true, - sourceDisabled, -}: { enabled?: boolean; sourceDisabled?: (w: SourceWalletWithBalance) => boolean } = {}) { +export function useMySourceOptions({ enabled = true }: { enabled?: boolean }) { const { sources, isPending } = useMySources({ enabled }); - const options = sources.map(s => { - return { - label: , - value: s.id, - disabled: sourceDisabled?.(s), - }; - }); - return { sources, isPending, - options, }; } diff --git a/src/components/Table/NoItems.tsx b/src/components/Table/NoItems.tsx index e14fd4e..e0a74c8 100644 --- a/src/components/Table/NoItems.tsx +++ b/src/components/Table/NoItems.tsx @@ -1,6 +1,14 @@ -import { Box, SxProps, Typography } from '@mui/material'; +import React from 'react'; -export function NoItems({ sx }: { sx?: SxProps }) { +import { ErrorOutlineOutlined } from '@mui/icons-material'; +import { Box, Stack, SxProps, Typography } from '@mui/material'; + +export function NoItems({ + sx, + children, +}: React.PropsWithChildren<{ + sx?: SxProps; +}>) { return ( - No items to show + + + + {children || No items to show} + + ); } diff --git a/src/components/Table/TableList.tsx b/src/components/Table/TableList.tsx index 2724791..7e61789 100644 --- a/src/components/Table/TableList.tsx +++ b/src/components/Table/TableList.tsx @@ -2,9 +2,12 @@ import { styled, Table } from '@mui/material'; export const TableList = styled(Table, { name: 'TableList', -})(() => ({ - '& tbody tr:last-child td': { - border: 'none', +})(({ theme }) => ({ + // '& tbody tr:last-child td': { + // border: 'none', + // }, + '& td, & th': { + borderBottomColor: theme.palette.divider, }, '& tr td:first-child, & tr th:first-child': { paddingLeft: 0, diff --git a/src/components/Toaster/index.tsx b/src/components/Toaster/index.tsx new file mode 100644 index 0000000..3bd412b --- /dev/null +++ b/src/components/Toaster/index.tsx @@ -0,0 +1,45 @@ +import { Dangerous, Report } from '@mui/icons-material'; +import { Alert, AlertColor, Box, CircularProgress, Typography } from '@mui/material'; +import toast, { Toaster as Toaster_ } from 'react-hot-toast'; + +export function Toaster() { + return ( + + {t => { + const content = typeof t.message === 'function' ? t.message(t) : t.message; + + const { color, icon } = + t.type === 'error' + ? { color: 'error', icon: } + : t.type === 'success' + ? { color: 'success' } + : t.type === 'loading' + ? { + color: 'info', + icon: ( + + + + ), + } + : {}; + + return ( + + ); + }} + + ); +} diff --git a/src/hooks/useSquidNetworkHeightHooks.tsx b/src/hooks/useSquidNetworkHeightHooks.tsx index 789b3ae..fdb88a6 100644 --- a/src/hooks/useSquidNetworkHeightHooks.tsx +++ b/src/hooks/useSquidNetworkHeightHooks.tsx @@ -10,9 +10,11 @@ import { import { logger } from '@logger'; import { useQueryClient } from '@tanstack/react-query'; import { max, partition } from 'lodash-es'; +// import { useSnackbar, } from 'notistack'; +import { toast } from 'react-hot-toast'; import { useBlockNumber } from 'wagmi'; -import { useSquidDataSource, useSquidNetworkHeightQuery } from '@api/subsquid-network-squid'; +import { useSquid, useSquidNetworkHeightQuery } from '@api/subsquid-network-squid'; import { localStorageStringSerializer, useLocalStorageState } from '@hooks/useLocalStorageState'; type HeightHook = { height: number; invalidateQueries: unknown[] }; @@ -31,7 +33,7 @@ const SquidHeightContext = createContext<{ setWaitHeight: () => {}, }); -export function useSquidNetworkHeight() { +export function useSquidHeight() { const { isLoading, currentHeight, waitHeight, setWaitHeight } = useContext(SquidHeightContext); return { @@ -45,8 +47,8 @@ export function useSquidNetworkHeight() { export function SquidHeightProvider({ children }: PropsWithChildren) { const queryClient = useQueryClient(); - const dataSource = useSquidDataSource(); - const [heightHooksRaw, setHeightHooksRaw] = useLocalStorageState('squid_height_hooks', { + const dataSource = useSquid(); + const [heightHooksRaw, setHeightHooksRaw] = useLocalStorageState('sqd_height_hooks', { defaultValue: '[]', serializer: localStorageStringSerializer, storageSync: false, @@ -58,6 +60,7 @@ export function SquidHeightProvider({ children }: PropsWithChildren) { refetchInterval: 2000, }, ); + // const { enqueueSnackbar } = useSnackbar(); const currentHeight = data?.squidStatus?.height || 0; @@ -89,6 +92,21 @@ export function SquidHeightProvider({ children }: PropsWithChildren) { }); }, [currentHeight, heightHooks, queryClient, setHeightHooksRaw]); + const maxWaitHeight = useMemo(() => { + return max(heightHooks.map(h => h.height)) || 0; + }, [heightHooks]); + + useEffect(() => { + if (maxWaitHeight > 0) { + toast.loading(`Syncing ${currentHeight} block of ${maxWaitHeight}`, { + id: 'squid-sync', + duration: Infinity, + }); + } else { + toast.remove('squid-sync'); + } + }, [maxWaitHeight, currentHeight]); + const setWaitHeight = useCallback( (height: bigint | string, invalidateQueries: unknown[] = []) => { heightHooks.push({ @@ -102,10 +120,6 @@ export function SquidHeightProvider({ children }: PropsWithChildren) { [heightHooks, setHeightHooksRaw], ); - const maxWaitHeight = useMemo(() => { - return max(heightHooks.map(h => h.height)) || 0; - }, [heightHooks]); - const { data: chainHeight } = useBlockNumber(); useEffect(() => { if (isLoading) return; diff --git a/src/icons/DashboardIcon.tsx b/src/icons/DashboardIcon.tsx deleted file mode 100644 index 0ff48a3..0000000 --- a/src/icons/DashboardIcon.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; - -export function DashboardIcon({ variant }: { variant: 'filled' | 'outlined' }) { - return variant === 'filled' ? ( - - - - ) : ( - - - - ); -} diff --git a/src/icons/DoorIcon.tsx b/src/icons/DoorIcon.tsx deleted file mode 100644 index fdd129d..0000000 --- a/src/icons/DoorIcon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -export function DoorIcon({ variant }: { variant: 'filled' | 'outlined' }) { - return variant === 'filled' ? ( - - - - ) : ( - - - - ); -} diff --git a/src/icons/HandIcon.tsx b/src/icons/HandIcon.tsx index 6236ea9..750b9d0 100644 --- a/src/icons/HandIcon.tsx +++ b/src/icons/HandIcon.tsx @@ -1,4 +1,4 @@ -export function HandIcon({ variant }: { variant: 'filled' | 'outlined' }) { +export function HandIcon({ variant = 'filled' }: { variant?: 'filled' | 'outlined' }) { return variant === 'filled' ? ( - - - ); -} diff --git a/src/icons/LogoutIcon.tsx b/src/icons/LogoutIcon.tsx deleted file mode 100644 index 4110335..0000000 --- a/src/icons/LogoutIcon.tsx +++ /dev/null @@ -1,10 +0,0 @@ -export function LogoutIcon() { - return ( - - - - ); -} diff --git a/src/icons/NetworkNodeIcon.tsx b/src/icons/NetworkNodeIcon.tsx index c6c8cc6..1b8f245 100644 --- a/src/icons/NetworkNodeIcon.tsx +++ b/src/icons/NetworkNodeIcon.tsx @@ -1,4 +1,4 @@ -export function NetworkNodeIcon({ variant }: { variant: 'filled' | 'outlined' }) { +export function NetworkNodeIcon({ variant = 'filled' }: { variant?: 'filled' | 'outlined' }) { return variant === 'filled' ? ( - - - ) : ( - - - - ); -} diff --git a/src/icons/WalletIcon.tsx b/src/icons/WalletIcon.tsx deleted file mode 100644 index 8b5a6d1..0000000 --- a/src/icons/WalletIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -export function WalletIcon({ size = 24 }: { size?: number }) { - return ( - - - - - ); -} diff --git a/src/icons/WarningIcon.tsx b/src/icons/WarningIcon.tsx deleted file mode 100644 index ad38fba..0000000 --- a/src/icons/WarningIcon.tsx +++ /dev/null @@ -1,37 +0,0 @@ -export function WarningIcon({ - className, - color = 'warning', - size = 24, -}: { - className?: string; - size?: number; - color?: 'error' | 'warning'; -}) { - return color === 'warning' ? ( - - - - ) : ( - - - - ); -} diff --git a/src/layouts/NetworkLayout/LogoutMenuItem.tsx b/src/layouts/NetworkLayout/LogoutMenuItem.tsx index 94f5a65..6f43f1d 100644 --- a/src/layouts/NetworkLayout/LogoutMenuItem.tsx +++ b/src/layouts/NetworkLayout/LogoutMenuItem.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { LogoutIcon } from '@icons/LogoutIcon'; +import { LogoutOutlined } from '@mui/icons-material'; import { useAppReload } from '../../index.tsx'; @@ -9,5 +9,5 @@ import { BasicMenuItem } from './BasicMenuItem'; export function LogoutMenuItem() { const reload = useAppReload({ to: '/' }); - return reload()} />; + return reload()} />; } diff --git a/src/layouts/NetworkLayout/NetworkLayout.tsx b/src/layouts/NetworkLayout/NetworkLayout.tsx index 18bcf71..609f203 100644 --- a/src/layouts/NetworkLayout/NetworkLayout.tsx +++ b/src/layouts/NetworkLayout/NetworkLayout.tsx @@ -27,7 +27,6 @@ import { getChainId, getSubsquidNetwork } from '@network/useSubsquidNetwork'; import { ColorVariant } from '../../theme'; import { NetworkMenu } from './NetworkMenu'; -import { SyncSquidSnackbar } from './SyncSquidSnackbar'; import { UserMenu } from './UserMenu'; const APP_BAR_HEIGHT = 60; @@ -278,7 +277,7 @@ export const NetworkLayout = ({ return (
- + {/* */} {/* */} diff --git a/src/layouts/NetworkLayout/NetworkMenu.tsx b/src/layouts/NetworkLayout/NetworkMenu.tsx index 0ff71e8..c25421f 100644 --- a/src/layouts/NetworkLayout/NetworkMenu.tsx +++ b/src/layouts/NetworkLayout/NetworkMenu.tsx @@ -1,80 +1,38 @@ import React, { ForwardedRef, forwardRef } from 'react'; -import { Box, Button, styled, Typography } from '@mui/material'; +import { + ArrowOutwardOutlined, + BackHand, + BackHandOutlined, + Dashboard, + DashboardOutlined, + Lan, + LanOutlined, + Savings, + SavingsOutlined, + SensorDoor, + SensorDoorOutlined, + SmsOutlined, +} from '@mui/icons-material'; +import { Button, styled } from '@mui/material'; import { Link, useLocation } from 'react-router-dom'; import { useIsWorkerOperator } from '@api/subsquid-network-squid'; -import { ContactsIcon } from '@icons/ContactsIcon'; -import { DashboardIcon } from '@icons/DashboardIcon'; -import { DoorIcon } from '@icons/DoorIcon'; -import { HandIcon } from '@icons/HandIcon'; -import { NetworkNodeIcon } from '@icons/NetworkNodeIcon'; -import { OpenInNewIcon } from '@icons/OpenInNewIcon'; -import { SavingsIcon } from '@icons/SavingsIcon'; import { useWorkersChatUrl } from '@network/useWorkersChat'; interface NetworkMenuProps { onItemClick: () => void; } -const MenuItem = styled(Button)(({ theme: { palette, spacing, breakpoints } }) => ({ - display: 'flex', - alignItems: 'center', - // justifyContent: 'center', - height: spacing(7), - minWidth: 0, +const MenuItem = styled(Button)(({ theme: { palette, spacing, breakpoints, typography } }) => ({ + ...typography.subtitle2, - // padding: spacing(0), - // [breakpoints.up('xl')]: { - // }, + height: spacing(7), + display: 'flex', justifyContent: 'flex-start', - padding: spacing(0, 2.5), + padding: spacing(0, 3), borderRadius: 0, - '& .leftIcon': { - display: 'flex', - alignItems: 'center', - // marginRight: spacing(0), - - // [breakpoints.up('xl')]: { - // }, - marginRight: spacing(1.5), - }, - - '& .rightIcon': { - alignItems: 'center', - justifyContent: 'center', - marginLeft: spacing(1), - }, - // '& svg:not(.badge) path': { - // transition: 'fill 300ms ease-out', - // }, - // ['&:hover']: { - // backgroundColor: palette.background.paper, - // color: palette.info.contrastText, - // // '& svg:not(.badge) path': { - // // fill: 'red', - // // }, - // // '& svg.badge path': { - // // fill: 'inherit', - // // }, - // }, - // [`&.selected`]: { - // // backgroundColor: palette.info.main, - // // color: palette.info.contrastText, - // // '& svg:not(.badge) path': { - // // fill: palette.info.contrastText, - // // }, - // }, - - // [`&.${buttonClasses.disabled}`]: { - // opacity: 0.4, - // backgroundColor: 'transparent', - // color: palette.text.secondary, - // '& svg:not(.badge) path': { - // fill: palette.text.secondary, - // }, - // }, })); export const Item = forwardRef( @@ -95,8 +53,8 @@ export const Item = forwardRef( path: string; target?: string; disabled?: boolean; - LeftIcon: any; - RightIcon?: any; + LeftIcon: React.ReactNode | ((active: boolean) => React.ReactNode); + RightIcon?: React.ReactNode | ((active: boolean) => React.ReactNode); label?: string; onClick?: () => void; }, @@ -109,8 +67,15 @@ export const Item = forwardRef( // const compact = useMediaQuery(theme.breakpoints.down('xl')); // const mobile = useMediaQuery(theme.breakpoints.down('xs')); - const button = ( + // LeftIcon.props.on = active; + + const startIcon = typeof LeftIcon === 'function' ? LeftIcon(active) : LeftIcon; + const endIcon = typeof RightIcon === 'function' ? RightIcon(active) : RightIcon; + + return ( {startIcon}} + endIcon={{endIcon}} ref={ref} onClick={onClick} className={active ? 'selected' : undefined} @@ -121,31 +86,19 @@ export const Item = forwardRef( target={target} rel={target ? 'noreferrer' : undefined} > - - - {/* {!compact || mobile ? ( - <> - - ) : null} - - */} - {label} - {RightIcon ? ( - - - + <> + ) : null} + + */} + {label} ); - - if (disabled) return button; - - return button; - // - // { button } - // }, + // + // { button } + // ); export const NetworkMenu = ({ onItemClick }: NetworkMenuProps) => { @@ -154,11 +107,36 @@ export const NetworkMenu = ({ onItemClick }: NetworkMenuProps) => { return ( <> - - - - - + (active ? : )} + label="Dashboard" + onClick={onItemClick} + path="/dashboard" + /> + (active ? : )} + label="Assets" + onClick={onItemClick} + path="/assets" + /> + (active ? : )} + label="Workers" + onClick={onItemClick} + path="/workers" + /> + (active ? : )} + label="Delegations" + onClick={onItemClick} + path="/delegations" + /> + (active ? : )} + label="Portals" + onClick={onItemClick} + path="/portals" + />
@@ -174,16 +152,16 @@ export const NetworkMenu = ({ onItemClick }: NetworkMenuProps) => { label="Operators Chat" path={workersChatUrl || '/null'} target="_blank" - LeftIcon={ContactsIcon} - RightIcon={OpenInNewIcon} + LeftIcon={} + RightIcon={} /> ) : null} } + RightIcon={} /> ); diff --git a/src/layouts/NetworkLayout/SyncSquidSnackbar.tsx b/src/layouts/NetworkLayout/SyncSquidSnackbar.tsx deleted file mode 100644 index 480889b..0000000 --- a/src/layouts/NetworkLayout/SyncSquidSnackbar.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; - -import { Box, Card, CircularProgress, Stack, Typography, useTheme } from '@mui/material'; - -import { useSquidNetworkHeight } from '@hooks/useSquidNetworkHeightHooks'; - -export const SyncSquidSnackbar = () => { - const theme = useTheme(); - - const { isWaiting, waitHeight, currentHeight } = useSquidNetworkHeight(); - - if (!isWaiting) return null; - - return ( - - - - - - Synced {currentHeight} block of {waitHeight} - - - - - ); -}; diff --git a/src/layouts/NetworkLayout/UserMenu.tsx b/src/layouts/NetworkLayout/UserMenu.tsx index c06b33b..f9f5470 100644 --- a/src/layouts/NetworkLayout/UserMenu.tsx +++ b/src/layouts/NetworkLayout/UserMenu.tsx @@ -1,8 +1,8 @@ import React, { useCallback, useMemo, useRef, useState } from 'react'; import { addressFormatter } from '@lib/formatters/formatters'; -import { ExpandMore } from '@mui/icons-material'; -import { Box, Button, Menu, Stack, styled, Typography } from '@mui/material'; +import { AccountBalanceWalletOutlined, ExpandMore } from '@mui/icons-material'; +import { Box, Button, Menu, styled, Typography } from '@mui/material'; import { useConnectModal } from '@rainbow-me/rainbowkit'; import { useAccount } from 'wagmi'; @@ -45,27 +45,27 @@ export function UserMenu() { return ( <> - } + endIcon={ + + } > {maskedAddress} - - + 0 && n < 0.1 ** decimals) { -// return `<0.01 ${SQD_TOKEN}`; -// } - -// return `${numberWithSpacesFormatter(value.toFixed(decimals))} ${SQD_TOKEN}`; -// } - export function peerIdToHex(peerId: string) { return toHex(bs58.decode(peerId)); } + +export function unwrapMulticallResult(result?: MulticallResponse): T | undefined { + return result?.status === 'success' ? (result.result as T) : undefined; +} diff --git a/src/network/useContracts.ts b/src/network/useContracts.ts index cf24249..6bca571 100644 --- a/src/network/useContracts.ts +++ b/src/network/useContracts.ts @@ -2,6 +2,7 @@ import { NetworkName, getSubsquidNetwork } from './useSubsquidNetwork.ts'; export function useContracts(): { SQD: `0x${string}`; + ROUTER: `0x${string}`; WORKER_REGISTRATION: `0x${string}`; STAKING: `0x${string}`; REWARD_TREASURY: `0x${string}`; @@ -23,6 +24,7 @@ export function useContracts(): { GATEWAY_REGISTRATION: `0xAB46F688AbA4FcD1920F21E9BD16B229316D8b0a`, SOFT_CAP: `0x52f31c9c019f840A9C0e74F66ACc95455B254BeA`, SQD_TOKEN: 'tSQD', + ROUTER: '0xD2093610c5d27c201CD47bCF1Df4071610114b64', }; } case NetworkName.Mainnet: { @@ -35,6 +37,7 @@ export function useContracts(): { GATEWAY_REGISTRATION: `0x8a90a1ce5fa8cf71de9e6f76b7d3c0b72feb8c4b`, SOFT_CAP: `0x0eb27b1cbba04698dd7ce0f2364584d33a616545`, SQD_TOKEN: 'SQD', + ROUTER: '0x67F56D27dab93eEb07f6372274aCa277F49dA941', }; } } diff --git a/src/pages/AssetsPage/Assets.tsx b/src/pages/AssetsPage/Assets.tsx index 8899e7f..ba1a813 100644 --- a/src/pages/AssetsPage/Assets.tsx +++ b/src/pages/AssetsPage/Assets.tsx @@ -47,11 +47,12 @@ function TokenBalance({ sx, balance }: { sx?: SxProps; balance?: TokenBal return ( - - - {balance?.name} - - + + + + {balance?.name} + + {tokenFormatter(balance?.value || 0, SQD_TOKEN, 3)} diff --git a/src/pages/AssetsPage/ClaimButton.tsx b/src/pages/AssetsPage/ClaimButton.tsx index ba32ff7..8df057f 100644 --- a/src/pages/AssetsPage/ClaimButton.tsx +++ b/src/pages/AssetsPage/ClaimButton.tsx @@ -1,19 +1,35 @@ -import { useEffect, useMemo, useState } from 'react'; +import { useMemo, useState } from 'react'; import { tokenFormatter } from '@lib/formatters/formatters'; import { fromSqd } from '@lib/network/utils'; +import { TollOutlined } from '@mui/icons-material'; import { LoadingButton } from '@mui/lab'; import { Box, TableBody, TableCell, TableRow } from '@mui/material'; +import BigNumber from 'bignumber.js'; import { useFormik } from 'formik'; +import toast from 'react-hot-toast'; +import { encodeFunctionData } from 'viem'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useWriteContract } from 'wagmi'; import * as yup from 'yup'; -import { useClaim } from '@api/contracts/claim'; -import { ClaimType, useMyClaimsAvailable, useMySources } from '@api/subsquid-network-squid'; -import { BlockchainContractError } from '@components/BlockchainContractError'; +import { rewardTreasuryAbi, useReadRouterRewardTreasury, vestingAbi } from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; +import { + AccountType, + ClaimType, + useAccountQuery, + useMyClaimsQuery, + useSquid, + Worker, +} from '@api/subsquid-network-squid'; import { ContractCallDialog } from '@components/ContractCallDialog'; import { Form, FormikSelect, FormRow } from '@components/Form'; +import { Loader } from '@components/Loader'; import { SourceWalletOption } from '@components/SourceWallet'; import { TableList } from '@components/Table/TableList.tsx'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useAccount } from '@network/useAccount'; import { useContracts } from '@network/useContracts'; import { WorkerName } from '@pages/WorkersPage/WorkerName'; @@ -22,104 +38,207 @@ export const claimSchema = yup.object({ }); export function ClaimButton() { - const { SQD_TOKEN } = useContracts(); - const { claim, error, isPending } = useClaim(); + const [open, setOpen] = useState(false); + + return ( + <> + } + onClick={() => setOpen(true)} + color="info" + variant="contained" + loading={open} + > + CLAIM + + setOpen(false)} /> + + ); +} + +export function ClaimDialog({ open, onClose }: { open: boolean; onClose: () => void }) { + const client = useClient(); + const account = useAccount(); + const squid = useSquid(); + + const { setWaitHeight } = useSquidHeight(); + + const contracts = useContracts(); + const contractWriter = useWriteContract({}); + + const rewardTreasuryAddress = useReadRouterRewardTreasury({ + address: contracts.ROUTER, + }); + + const accountQuery = useAccountQuery( + squid, + { address: account.address || '0x' }, + { enabled: open }, + ); + const claimsQuery = useMyClaimsQuery( + squid, + { address: account.address || '0x' }, + { enabled: open }, + ); + + const isLoading = + accountQuery.isLoading || claimsQuery.isLoading || rewardTreasuryAddress.isLoading; + + const sources = useMemo(() => { + if (!accountQuery.data?.accountById) return []; + + return [accountQuery.data.accountById, ...accountQuery.data.accountById.owned].map(s => { + const claims: (Pick & { + type: ClaimType; + claimableReward: string; + })[] = []; + + claimsQuery.data?.delegations.forEach(d => { + if (d.owner.id !== s.id) return; + + claims.push({ + id: d.worker.id, + peerId: d.worker.peerId, + name: d.worker.name, + claimableReward: d.claimableReward, + type: ClaimType.Delegation, + }); + }); + + claimsQuery.data?.workers.forEach(w => { + if (w.owner.id !== s.id) return; + + claims.push({ + id: w.id, + peerId: w.peerId, + name: w.name, + claimableReward: w.claimableReward, + type: ClaimType.Worker, + }); + }); + + const totalClaimableBalance = claims.reduce( + (t, i) => t.plus(i.claimableReward), + BigNumber(0), + ); + + return { + id: s.id, + type: s.type, + claims: claims.sort( + (a, b) => BigNumber(a.claimableReward).comparedTo(b.claimableReward) * -1, + ), + totalClaimableBalance: totalClaimableBalance.toString(), + disabled: totalClaimableBalance.lte(0), + }; + }); + }, [accountQuery.data?.accountById, claimsQuery.data?.delegations, claimsQuery.data?.workers]); + + const initialValues = useMemo(() => { + const option = sources.find(c => !c.disabled) || sources?.[0]; + + return { + source: option?.id || '', + }; + }, [sources]); + const formik = useFormik({ - initialValues: { - source: '', - amount: 0, - max: 0, - }, + initialValues, validationSchema: claimSchema, validateOnChange: true, validateOnBlur: true, validateOnMount: true, + enableReinitialize: true, onSubmit: async values => { - const wallet = claimableSources.find(w => w?.id === values.source); - if (!wallet) return; + if (!client) return; + if (!account.address) return; + if (!rewardTreasuryAddress.data) return; - const { failedReason } = await claim({ - wallet, - }); + try { + const { source } = claimSchema.cast(values); - if (!failedReason) { - handleClose(); - } - }, - }); + const wallet = sources.find(w => w?.id === source); + if (!wallet) return; - const [open, setOpen] = useState(false); - const handleOpen = () => setOpen(true); - const handleClose = () => setOpen(false); - - const { sources } = useMySources(); - const { - claims, - hasClaimsAvailable, - sources: claimableSources, - isLoading: isClaimsLoading, - currentSourceTotalClaimsAvailable, - } = useMyClaimsAvailable({ - source: formik.values.source, - }); + let hash: `0x${string}`; + switch (wallet.type) { + case AccountType.User: { + hash = await contractWriter.writeContractAsync({ + address: rewardTreasuryAddress.data, + abi: rewardTreasuryAbi, + functionName: 'claimFor', + args: [contracts.REWARD_DISTRIBUTION, account.address], + }); + break; + } + case AccountType.Vesting: { + const data = encodeFunctionData({ + abi: rewardTreasuryAbi, + functionName: 'claimFor', + args: [contracts.REWARD_DISTRIBUTION, account.address], + }); - const options = useMemo( - () => - sources.map(s => { - const claimableSource = claimableSources.find(cs => cs.id === s.id); - return { - label: , - value: s.id, - disabled: fromSqd(claimableSource?.balance).eq(0), - }; - }), - [claimableSources, sources], - ); - - useEffect(() => { - if (isClaimsLoading) return; - else if (formik.values.source) return; + hash = await contractWriter.writeContractAsync({ + address: wallet.id as `0x${string}`, + abi: vestingAbi, + functionName: 'execute', + args: [rewardTreasuryAddress.data, data], + }); + break; + } + default: + return; + } - const source = claimableSources?.[0]; - if (!source) return; + const receipt = await waitForTransactionReceipt(client, { hash }); + setWaitHeight(receipt.blockNumber, []); - formik.setValues({ - ...formik.values, - source: source.id, - }); - }, [formik, isClaimsLoading, claimableSources]); + onClose(); + } catch (e: unknown) { + toast.error(errorMessage(e)); + } + }, + }); return ( - <> - - CLAIM - - { - if (!confirmed) return handleClose(); - - formik.handleSubmit(); - }} - loading={isPending} - confirmColor="info" - disableConfirmButton={currentSourceTotalClaimsAvailable.lte(0)} - > + { + if (!confirmed) return onClose(); + + formik.handleSubmit(); + }} + loading={contractWriter.isPending} + confirmColor="info" + disableConfirmButton={!formik.isValid} + confirmButtonText="Claim" + > + {isLoading ? ( + + ) : (
({ + label: ( + + ), + value: s.id, + disabled: s.disabled, + }))} formik={formik} + onChange={e => { + const source = sources.find(s => s.id === e.target.value); + if (!source) return; + + formik.setFieldValue('source', source.id); + }} /> @@ -132,28 +251,28 @@ export function ClaimButton() { > - {claims.map(w => { - return ( - - - - - - {w.type === ClaimType.Worker ? 'Worker reward' : 'Delegation reward'} - - - {tokenFormatter(fromSqd(w.claimableReward), SQD_TOKEN)} - - - ); - })} + {sources + .find(s => s.id === formik.values.source) + ?.claims.map(w => { + return ( + + + + + + {w.type === ClaimType.Worker ? 'Worker reward' : 'Delegation reward'} + + + {tokenFormatter(fromSqd(w.claimableReward), contracts.SQD_TOKEN)} + + + ); + })} - - -
- + )} +
); } diff --git a/src/pages/AssetsPage/ReleaseButton.tsx b/src/pages/AssetsPage/ReleaseButton.tsx index 2391ca5..d20d5d8 100644 --- a/src/pages/AssetsPage/ReleaseButton.tsx +++ b/src/pages/AssetsPage/ReleaseButton.tsx @@ -1,12 +1,17 @@ import React from 'react'; -import { fromSqd } from '@lib/network'; import { LoadingButton } from '@mui/lab'; +import { Alert } from '@mui/material'; +import { toast } from 'react-hot-toast'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient } from 'wagmi'; import * as yup from 'yup'; -import { useVestingContract, useVestingContractRelease } from '@api/contracts/vesting'; +import { useWriteVestingRelease } from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; import { SourceWallet } from '@api/subsquid-network-squid'; -import { BlockchainContractError } from '@components/BlockchainContractError'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useContracts } from '@network/useContracts'; export const claimSchema = yup.object({ source: yup.string().label('Source').trim().required('Source is required'), @@ -19,29 +24,37 @@ export function ReleaseButton({ vesting: SourceWallet; disabled?: boolean; }) { - const { release, error, isLoading } = useVestingContractRelease(); - const { data, isLoading: isVestingLoading } = useVestingContract({ - address: vesting.id as `0x${string}`, - }); - const isDisabled = isVestingLoading || fromSqd(data?.releasable).lte(0); + const client = useClient(); + const { setWaitHeight } = useSquidHeight(); + const { SQD } = useContracts(); + + const { writeContractAsync, isPending } = useWriteVestingRelease({}); + + const onClick = async () => { + try { + const hash = await writeContractAsync({ + args: [SQD], + address: vesting.id as `0x${string}`, + }); + + const receipt = await waitForTransactionReceipt(client!, { hash }); + setWaitHeight(receipt.blockNumber, []); + } catch (e: unknown) { + toast.error(errorMessage(e)); + } + }; return ( <> { - e.stopPropagation(); - await release({ - address: vesting.id as `0x${string}`, - }); - }} + loading={isPending} + onClick={onClick} variant="outlined" color="secondary" - disabled={disabled || isDisabled} + disabled={disabled} > RELEASE - ); } diff --git a/src/pages/AssetsPage/Vesting.tsx b/src/pages/AssetsPage/Vesting.tsx index 4e36114..80bdf77 100644 --- a/src/pages/AssetsPage/Vesting.tsx +++ b/src/pages/AssetsPage/Vesting.tsx @@ -1,11 +1,13 @@ import { dateFormat } from '@i18n'; import { addressFormatter, percentFormatter, tokenFormatter } from '@lib/formatters/formatters'; -import { fromSqd } from '@lib/network/utils'; -import { Divider, Stack, styled, useMediaQuery, useTheme } from '@mui/material'; +import { fromSqd, unwrapMulticallResult } from '@lib/network/utils'; +import { Divider, Stack, styled } from '@mui/material'; import { Box } from '@mui/system'; +import { keepPreviousData } from '@tanstack/react-query'; import { useParams, useSearchParams } from 'react-router-dom'; +import { useReadContracts } from 'wagmi'; -import { useVestingContract } from '@api/contracts/vesting'; +import { sqdAbi, vestingAbi } from '@api/contracts'; import { useVestingByAddress } from '@api/subsquid-network-squid'; import { Card } from '@components/Card'; import SquaredChip from '@components/Chip/SquaredChip'; @@ -45,13 +47,71 @@ export const Title = styled(SquaredChip)(({ theme }) => ({ })); export function Vesting({ backPath }: { backPath: string }) { - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down('xs')); + const { SQD_TOKEN, SQD } = useContracts(); const { address } = useParams<{ address: `0x${string}` }>(); - const { data: vestingInfo, isLoading: isVestingInfoLoading } = useVestingContract({ address }); + + const vestingContract = { abi: vestingAbi, address } as const; + const { data: vestingInfo, isLoading: isVestingInfoLoading } = useReadContracts({ + contracts: [ + { + ...vestingContract, + functionName: 'start', + }, + { + ...vestingContract, + functionName: 'end', + }, + { + ...vestingContract, + functionName: 'depositedIntoProtocol', + }, + { + ...vestingContract, + functionName: 'releasable', + args: [SQD], + }, + { + ...vestingContract, + functionName: 'released', + args: [SQD], + }, + { + abi: sqdAbi, + address: SQD, + functionName: 'balanceOf', + args: [address || '0x'], + }, + { + ...vestingContract, + functionName: 'immediateReleaseBIP', + }, + { + ...vestingContract, + functionName: 'expectedTotalAmount', + }, + ] as const, + query: { + placeholderData: keepPreviousData, + select: res => { + if (res?.some(r => r.status === 'success')) { + return { + start: Number(unwrapMulticallResult(res[0])) * 1000, + end: Number(unwrapMulticallResult(res[1])) * 1000, + deposited: unwrapMulticallResult(res[2])?.toString(), + releasable: unwrapMulticallResult(res[3])?.toString(), + released: unwrapMulticallResult(res[4])?.toString(), + balance: unwrapMulticallResult(res[5])?.toString(), + initialRelease: Number(unwrapMulticallResult(res[6]) || 0) / 100, + expectedTotal: unwrapMulticallResult(res[7])?.toString(), + }; + } + + return undefined; + }, + }, + }); const { data: vesting, isPending: isVestingLoading } = useVestingByAddress({ address }); - const { SQD_TOKEN } = useContracts(); const [searchParams] = useSearchParams(); diff --git a/src/pages/AssetsPage/Vestings.tsx b/src/pages/AssetsPage/Vestings.tsx index 4ffc95d..056e9f2 100644 --- a/src/pages/AssetsPage/Vestings.tsx +++ b/src/pages/AssetsPage/Vestings.tsx @@ -1,8 +1,11 @@ import { tokenFormatter } from '@lib/formatters/formatters'; -import { fromSqd } from '@lib/network/utils'; +import { fromSqd, unwrapMulticallResult } from '@lib/network/utils'; import { Box, TableBody, TableCell, TableHead, TableRow } from '@mui/material'; +import { keepPreviousData } from '@tanstack/react-query'; +import chunk from 'lodash-es/chunk'; +import { useReadContracts } from 'wagmi'; -import { useVestingContracts } from '@api/contracts/vesting'; +import { sqdAbi, vestingAbi } from '@api/contracts'; import { useMyAssets } from '@api/subsquid-network-squid'; import SquaredChip from '@components/Chip/SquaredChip'; import { DashboardTable, NoItems } from '@components/Table'; @@ -13,10 +16,54 @@ import { SourceWalletName } from './VestingName'; export function MyVestings() { const { assets, isLoading } = useMyAssets(); - const { data, isLoading: isVestingsLoading } = useVestingContracts({ - addresses: assets.vestings.map(v => v.id as `0x${string}`), + const { SQD_TOKEN, SQD } = useContracts(); + + const { data, isLoading: isVestingsLoading } = useReadContracts({ + contracts: assets.vestings?.flatMap(address => { + const vestingContract = { abi: vestingAbi, address: address.id as `0x${string}` } as const; + return [ + { + ...vestingContract, + functionName: 'depositedIntoProtocol', + }, + { + ...vestingContract, + functionName: 'releasable', + args: [SQD], + }, + { + ...vestingContract, + functionName: 'released', + args: [SQD], + }, + { + abi: sqdAbi, + address: SQD, + functionName: 'balanceOf', + args: [address], + }, + ] as const; + }), + allowFailure: true, + query: { + enabled: !!assets?.vestings?.length, + placeholderData: keepPreviousData, + select: res => { + if (res?.some(r => r.status === 'success')) { + return chunk(res, 4).map(ch => ({ + deposited: unwrapMulticallResult(ch[0])?.toString(), + releasable: unwrapMulticallResult(ch[1])?.toString(), + released: unwrapMulticallResult(ch[2])?.toString(), + balance: unwrapMulticallResult(ch[3])?.toString(), + })); + } else if (res?.length === 0) { + return []; + } + + return undefined; + }, + }, }); - const { SQD_TOKEN } = useContracts(); return ( {tokenFormatter(fromSqd(d?.releasable), SQD_TOKEN)} - + diff --git a/src/pages/DashboardPage/Summary.tsx b/src/pages/DashboardPage/Summary.tsx index ac9c8c6..a5fc235 100644 --- a/src/pages/DashboardPage/Summary.tsx +++ b/src/pages/DashboardPage/Summary.tsx @@ -166,9 +166,7 @@ function CurrentEpoch() { } > - - {data?.epoch?.number || 0} - + {data?.epoch?.number || 0} ); } @@ -304,10 +302,9 @@ function WorkersApr({ length }: { length?: number }) { sx={{ height: 1, overflow: 'visible' }} title={} action={ - - {`Last ${aprs.length} days`} - - + + {`Last ${aprs.length} days`} + } > diff --git a/src/pages/DashboardPage/Workers.tsx b/src/pages/DashboardPage/Workers.tsx index e111a88..4238daf 100644 --- a/src/pages/DashboardPage/Workers.tsx +++ b/src/pages/DashboardPage/Workers.tsx @@ -21,7 +21,7 @@ import { Location, useLocationState } from '@hooks/useLocationState'; import { DelegationCapacity } from '@pages/WorkersPage/DelegationCapacity'; import { WorkerDelegate } from '@pages/WorkersPage/WorkerDelegate'; import { WorkerName } from '@pages/WorkersPage/WorkerName'; -import { WorkerStatus } from '@pages/WorkersPage/WorkerStatus'; +import { WorkerStatusChip } from '@pages/WorkersPage/WorkerStatus'; import { WorkerVersion } from '@pages/WorkersPage/WorkerVersion'; function TableNavigation({ @@ -168,7 +168,7 @@ export function Workers() { /> - + diff --git a/src/pages/DelegationsPage/DelegationsPage.tsx b/src/pages/DelegationsPage/DelegationsPage.tsx index 958fa2e..ee416c8 100644 --- a/src/pages/DelegationsPage/DelegationsPage.tsx +++ b/src/pages/DelegationsPage/DelegationsPage.tsx @@ -13,7 +13,7 @@ import { useContracts } from '@network/useContracts'; import { DelegationCapacity } from '@pages/WorkersPage/DelegationCapacity'; import { WorkerDelegate } from '@pages/WorkersPage/WorkerDelegate'; import { WorkerName } from '@pages/WorkersPage/WorkerName'; -import { WorkerStatus } from '@pages/WorkersPage/WorkerStatus'; +import { WorkerStatusChip } from '@pages/WorkersPage/WorkerStatus'; import { WorkerUndelegate } from '@pages/WorkersPage/WorkerUndelegate'; export function MyDelegations() { @@ -95,7 +95,7 @@ export function MyDelegations() { - + {worker.stakerApr != null ? percentFormatter(worker.stakerApr) : '-'} diff --git a/src/pages/GatewaysPage/AddNewGateway.tsx b/src/pages/GatewaysPage/AddNewGateway.tsx index 5a6a246..982f196 100644 --- a/src/pages/GatewaysPage/AddNewGateway.tsx +++ b/src/pages/GatewaysPage/AddNewGateway.tsx @@ -1,27 +1,56 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; +import { peerIdToHex } from '@lib/network'; +import { Add } from '@mui/icons-material'; import { LoadingButton } from '@mui/lab'; -import { Box } from '@mui/material'; +import { Alert, SxProps } from '@mui/material'; import { useFormik } from 'formik'; -import { useNavigate } from 'react-router-dom'; +import toast from 'react-hot-toast'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useWriteContract } from 'wagmi'; -import { useRegisterGateway } from '@api/contracts/gateway-registration/useRegisterGateway'; +import { gatewayRegistryAbi } from '@api/contracts'; +import { encodeGatewayMetadata } from '@api/contracts/gateway-registration/GatewayMetadata'; +import { errorMessage } from '@api/contracts/utils'; import { AccountType, useMySources } from '@api/subsquid-network-squid'; -import { BlockchainContractError } from '@components/BlockchainContractError'; -import { Card } from '@components/Card'; -import { Form, FormikTextInput, FormRow } from '@components/Form'; +import { ContractCallDialog } from '@components/ContractCallDialog'; +import { Form, FormikSwitch, FormikTextInput, FormRow } from '@components/Form'; import { FormikSelect } from '@components/Form/FormikSelect'; import { Loader } from '@components/Loader'; import { SourceWalletOption } from '@components/SourceWallet'; -import { CenteredPageWrapper, NetworkPageTitle } from '@layouts/NetworkLayout'; -import { ConnectedWalletRequired } from '@network/ConnectedWalletRequired'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useContracts } from '@network/useContracts'; import { addGatewaySchema } from './gateway-schema'; -function AddGatewayForm() { - const navigate = useNavigate(); - const { registerGateway, isLoading: isRegistering, error } = useRegisterGateway(); +export function AddGatewayButton({ sx, disabled }: { sx?: SxProps; disabled?: boolean }) { + const [open, setOpen] = useState(false); + + return ( + <> + } + variant="contained" + onClick={() => setOpen(true)} + > + ADD PORTAL + + setOpen(false)} /> + + ); +} + +export function AddGatewayDialog({ open, onClose }: { open: boolean; onClose: () => void }) { + const client = useClient(); + const contracts = useContracts(); + // const { registerGateway, isLoading: isRegistering, error } = useRegisterGateway(); const { sources, isPending: isDataLoading } = useMySources(); + const { writeContractAsync, isPending } = useWriteContract(); + const { setWaitHeight } = useSquidHeight(); const formik = useFormik({ initialValues: { @@ -40,21 +69,31 @@ function AddGatewayForm() { validateOnMount: true, onSubmit: async values => { + if (!client) return; + const source = sources.find(s => s.id === values.source); if (!source) return; - const castedValues = addGatewaySchema.cast(values); - if (!castedValues.public) { - delete castedValues.email; + try { + const castedValues = addGatewaySchema.cast(values); + if (!castedValues.public) { + delete castedValues.email; + } + + const hash = await writeContractAsync({ + address: contracts.GATEWAY_REGISTRATION, + abi: gatewayRegistryAbi, + functionName: 'register', + args: [peerIdToHex(castedValues.peerId), encodeGatewayMetadata(castedValues)], + }); + + const receipt = await waitForTransactionReceipt(client, { hash }); + setWaitHeight(receipt.blockNumber, []); + + onClose(); + } catch (e: unknown) { + toast.custom({errorMessage(e)}); } - - const { success } = await registerGateway({ - ...castedValues, - source, - }); - if (!success) return; - - navigate('/portals'); }, }); @@ -72,101 +111,86 @@ function AddGatewayForm() { }, [formik, isDataLoading, sources]); return ( - <> + { + if (!confirmed) return onClose(); + + formik.handleSubmit(); + }} + loading={isPending} + confirmButtonText="Register" + > {isDataLoading ? ( ) : (
- - - { - return { - label: , - value: s.id, - disabled: s.type !== AccountType.User, - }; - })} - formik={formik} - /> - - - - - - - - - {/* - - */} - - {formik.values.public ? ( - <> - - - - - - - - - - - - - - ) : null} - - - - - - REGISTER - - + + { + return { + label: , + value: s.id, + disabled: s.type !== AccountType.User, + }; + })} + formik={formik} + /> + + + + + + + + + + + + + {formik.values.public ? ( + <> + + + + + + + + + + + + + + ) : null}
)} - - ); -} - -export function AddNewGateway() { - return ( - - - - - - +
); } diff --git a/src/pages/GatewaysPage/AutoExtension.tsx b/src/pages/GatewaysPage/AutoExtension.tsx index 66db15d..b0a7e35 100644 --- a/src/pages/GatewaysPage/AutoExtension.tsx +++ b/src/pages/GatewaysPage/AutoExtension.tsx @@ -1,24 +1,51 @@ import { Box, FormControlLabel, FormGroup, Switch, Typography } from '@mui/material'; +import toast from 'react-hot-toast'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { usePublicClient, useWriteContract } from 'wagmi'; -import { useAutoExtension } from '@api/contracts/gateway-registration/useAutoExtension'; -import { GatewayStakeFragmentFragment } from '@api/subsquid-network-squid'; +import { gatewayRegistryAbi } from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useContracts } from '@network/useContracts'; -export function AutoExtension({ - stake, - disabled, -}: { - stake?: GatewayStakeFragmentFragment; - disabled?: boolean; -}) { - const { setAutoExtension } = useAutoExtension(); +export function AutoExtension({ value, disabled }: { value?: boolean; disabled?: boolean }) { + const client = usePublicClient(); + const { setWaitHeight } = useSquidHeight(); + const contracts = useContracts(); + const { writeContractAsync } = useWriteContract({}); + + const handleChange = async () => { + if (!client) return; + + try { + const hash = value + ? await writeContractAsync({ + address: contracts.GATEWAY_REGISTRATION, + abi: gatewayRegistryAbi, + functionName: 'disableAutoExtension', + args: [], + }) + : await writeContractAsync({ + address: contracts.GATEWAY_REGISTRATION, + abi: gatewayRegistryAbi, + functionName: 'enableAutoExtension', + args: [], + }); + + const receipt = await waitForTransactionReceipt(client, { hash }); + setWaitHeight(receipt.blockNumber, []); + } catch (e) { + toast.error(errorMessage(e)); + } + }; return ( await setAutoExtension(!stake?.autoExtension)} />} + disabled={disabled} + checked={value} + control={} label={Auto Extension} labelPlacement="start" /> diff --git a/src/pages/GatewaysPage/Gateway.tsx b/src/pages/GatewaysPage/Gateway.tsx index 62bb10a..44857ff 100644 --- a/src/pages/GatewaysPage/Gateway.tsx +++ b/src/pages/GatewaysPage/Gateway.tsx @@ -14,7 +14,7 @@ import { CenteredPageWrapper } from '@layouts/NetworkLayout'; import { Title } from '@pages/WorkersPage/Worker'; import { GatewayCard } from './GatewayCard'; -import { GatewayUnregister } from './GatewayUnregister'; +import { GatewayUnregisterButton } from './GatewayUnregister'; export const DescLabel = styled(Box, { name: 'DescLabel', @@ -99,7 +99,7 @@ export const Gateway = ({ backPath }: { backPath: string }) => { - + ); diff --git a/src/pages/GatewaysPage/GatewayStake.tsx b/src/pages/GatewaysPage/GatewayStake.tsx index 65223ad..ad33e6e 100644 --- a/src/pages/GatewaysPage/GatewayStake.tsx +++ b/src/pages/GatewaysPage/GatewayStake.tsx @@ -1,25 +1,37 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import { useMemo, useState } from 'react'; import { dateFormat } from '@i18n'; -import { tokenFormatter } from '@lib/formatters/formatters'; -import { fromSqd, toSqd } from '@lib/network/utils'; -import { Box, Button, Chip, Stack } from '@mui/material'; +import { numberWithCommasFormatter, tokenFormatter } from '@lib/formatters/formatters'; +import { fromSqd, toSqd, unwrapMulticallResult } from '@lib/network/utils'; +import { LockOutlined as LockIcon } from '@mui/icons-material'; +import { LoadingButton } from '@mui/lab'; +import { Alert, Box, Chip, Stack } from '@mui/material'; import * as yup from '@schema'; import BigNumber from 'bignumber.js'; import { useFormik } from 'formik'; +import toast from 'react-hot-toast'; import { useDebounce } from 'use-debounce'; +import { readContract, waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useReadContracts, useWriteContract } from 'wagmi'; -import { useAddStakeGateway } from '@api/contracts/gateway-registration/useAddStakeGateway'; -import { useComputationUnits } from '@api/contracts/gateway-registration/useComputationUnits'; -import { useStakeGateway } from '@api/contracts/gateway-registration/useStakeGateway'; +import { + gatewayRegistryAbi, + sqdAbi, + useReadNetworkControllerWorkerEpochLength, + useReadRouterNetworkController, +} from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; import { AccountType } from '@api/subsquid-network-squid'; import { useMyGatewayStake } from '@api/subsquid-network-squid/gateways-graphql'; -import { BlockchainContractError } from '@components/BlockchainContractError'; import { ContractCallDialog } from '@components/ContractCallDialog'; import { Form, FormikSelect, FormikTextInput, FormRow } from '@components/Form'; import { HelpTooltip } from '@components/HelpTooltip'; import { Loader } from '@components/Loader'; +import { SourceWalletOption } from '@components/SourceWallet'; import { useMySourceOptions } from '@components/SourceWallet/useMySourceOptions'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useAccount } from '@network/useAccount'; +import { useContracts } from '@network/useContracts'; const MIN_BLOCKS_LOCK = 1000; @@ -41,197 +53,299 @@ export const stakeSchema = yup.object({ .required('Lock min blocks is required'), }); -export function GatewayStake({ disabled }: { disabled?: boolean }) { - const { data, isLoading: isStakeLoading } = useMyGatewayStake(); - +export function GatewayStakeButton({ + stake, + disabled, +}: { + stake?: { amount: bigint; duration: bigint }; + disabled?: boolean; +}) { const [open, setOpen] = useState(false); - const handleOpen = () => setOpen(true); - const handleClose = () => setOpen(false); - const stakeGateway = useStakeGateway(); - const addStakeGateway = useAddStakeGateway(); - const { stakeToGateway, error, isLoading } = useMemo(() => { - if (BigNumber(data?.stake?.amount || 0).gt(0)) { + return ( + <> + } + onClick={() => setOpen(true)} + variant="contained" + color="info" + disabled={disabled} + > + LOCK + + setOpen(false)} /> + + ); +} + +export function GatewayStakeDialog({ + stake, + open, + onClose, +}: { + stake?: { amount: bigint; duration: bigint }; + open: boolean; + onClose: () => void; +}) { + const client = useClient(); + const { address } = useAccount(); + const { GATEWAY_REGISTRATION, ROUTER, SQD } = useContracts(); + const { setWaitHeight } = useSquidHeight(); + + const networkController = useReadRouterNetworkController({ + address: ROUTER, + }); + const workerEpochLength = useReadNetworkControllerWorkerEpochLength({ + address: networkController.data, + }); + + // const myGatewaysStake = useMyGatewayStake(); + const gatewayRegistryContract = useWriteContract(); + const { sources, isPending: isSourcesLoading } = useMySourceOptions({ enabled: open }); + + const { data: lastBlockInfo, isLoading: isLastBlockInfoLoading } = useMyGatewayStake(); + + const options = useMemo(() => { + return sources.map(source => { return { - stakeToGateway: addStakeGateway.addStakeToGateway, - error: addStakeGateway.error, - isLoading: addStakeGateway.isLoading, + label: , + value: source.id, + disabled: source.balance === '0' || source.type !== AccountType.User, + max: fromSqd(source.balance).toString(), }; - } else { - return stakeGateway; - } - }, [addStakeGateway, data?.stake?.amount, stakeGateway]); - - const { - sources, - options, - isPending: isSourceLoading, - } = useMySourceOptions({ - sourceDisabled: s => s.balance === '0' || s.type !== AccountType.User, - }); + }); + }, [sources]); - const formik = useFormik({ - initialValues: { - source: '', + const isLoading = isSourcesLoading || isLastBlockInfoLoading; + + const initialValues = useMemo(() => { + const option = options.find(option => !option.disabled) || options?.[0]; + + return { + source: option?.value || '', amount: '0', - max: '0', - autoExtension: false, - durationBlocks: MIN_BLOCKS_LOCK.toString(), - }, + max: option?.max || '0', + durationBlocks: (stake?.duration || MIN_BLOCKS_LOCK).toString(), + }; + }, [options, stake?.duration]); + + const formik = useFormik({ + initialValues, validationSchema: stakeSchema, validateOnChange: true, validateOnBlur: true, validateOnMount: true, + enableReinitialize: true, onSubmit: async values => { - const wallet = sources.find(w => w?.id === values.source); - if (!wallet) return; + if (!address || !client) return; + + try { + const castedValues = stakeSchema.cast(values); + + const amount = BigInt(toSqd(castedValues.amount)); - const { failedReason } = await stakeToGateway({ - amount: toSqd(values.amount), - durationBlocks: Number(values.durationBlocks), - wallet, - }); + const allowance = await readContract(client, { + abi: sqdAbi, + functionName: 'allowance', + address: SQD, + args: [address, GATEWAY_REGISTRATION], + }); - if (!failedReason) { - handleClose(); + if (allowance < amount) { + await gatewayRegistryContract.writeContractAsync({ + abi: sqdAbi, + address: SQD, + functionName: 'approve', + args: [GATEWAY_REGISTRATION, amount], + }); + } + + const contract = { + abi: gatewayRegistryAbi, + address: GATEWAY_REGISTRATION, + }; + + const hash = await gatewayRegistryContract.writeContractAsync( + (stake?.amount || 0n) > 0n + ? { + ...contract, + functionName: 'addStake', + args: [amount], + } + : { + ...contract, + functionName: 'stake', + args: [amount, BigInt(castedValues.durationBlocks), false], + }, + ); + + const receipt = await waitForTransactionReceipt(client, { hash }); + setWaitHeight(receipt.blockNumber, []); + + onClose(); + } catch (e: unknown) { + toast.custom({errorMessage(e)}); } }, }); - const source = useMemo(() => { - if (isSourceLoading) return; + const [debouncedValues] = useDebounce(stakeSchema.cast(formik.values), 500); + + const newContractValues = useReadContracts({ + contracts: [ + { + address: GATEWAY_REGISTRATION, + abi: gatewayRegistryAbi, + functionName: 'computationUnitsAmount', + args: [ + (stake?.amount || 0n) + BigInt(toSqd(debouncedValues.amount)), + BigInt(debouncedValues.durationBlocks), + ], + }, + ], + query: { + select: res => { + if (!res) return; + + return { + computationUnitsAmount: unwrapMulticallResult(res[0]) || 0n, + }; + }, + }, + }); + + const preview = useMemo(() => { + if (!newContractValues.data || !lastBlockInfo) return; + + const workerEpochLengthValue = workerEpochLength.data || 0n; + + const epochCount = Math.ceil(debouncedValues.durationBlocks / Number(workerEpochLengthValue)); - return ( - (formik.values.source - ? sources.find(c => c.id === formik.values.source) - : sources.find(c => fromSqd(c.balance).gte(0))) || sources?.[0] + const cuPerEpoch = Number( + epochCount <= 1 + ? newContractValues.data.computationUnitsAmount + : (newContractValues.data.computationUnitsAmount * workerEpochLengthValue) / + BigInt(debouncedValues.durationBlocks), ); - }, [formik.values.source, isSourceLoading, sources]); - useEffect(() => { - if (!source) return; + const unlockAt = + (Number(debouncedValues.durationBlocks) + 1) * 12_000 + + new Date(lastBlockInfo.lastBlockTimestampL1).getTime(); - formik.setValues({ - ...formik.values, - source: source.id, - max: fromSqd(source.balance).toFixed(), - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [source]); - - const [lockDuration] = useDebounce(formik.values.durationBlocks, 500); - const [amount] = useDebounce(fromSqd(data?.stake?.amount || 0).plus(formik.values.amount), 500); - const unlockAt = useMemo(() => { - if (!data) return Date.now(); - return (Number(lockDuration) + 1) * 12_000 + new Date(data.lastBlockTimestampL1).getTime(); - }, [data, lockDuration]); - const { data: computationUnits, isPending: isComputationUnitsLoading } = useComputationUnits({ - amount: toSqd(amount), - lockDuration: Number(lockDuration), - }); + const totalAmount = new BigNumber(stake?.amount.toString() || 0) + .plus(toSqd(debouncedValues.amount)) + .toString(); + + return { + epochCount, + cuPerEpoch, + unlockAt, + totalAmount, + isPending: newContractValues.isPending, + }; + }, [ + debouncedValues.amount, + debouncedValues.durationBlocks, + lastBlockInfo, + newContractValues.data, + newContractValues.isPending, + stake?.amount, + workerEpochLength.data, + ]); return ( - <> - - { - if (!confirmed) return handleClose(); - - formik.handleSubmit(); - }} - loading={isLoading} - confirmButtonText="Lock" - > - {isSourceLoading ? ( - - ) : ( -
- - { - const wallet = sources.find(w => w?.id === e.target.value); - if (!wallet) return; - - formik.setFieldValue('source', wallet.id); - - const balance = fromSqd(wallet.balance).toNumber(); - formik.setFieldValue('max', balance); - }} - /> - - - { - formik.setValues({ - ...formik.values, - amount: formik.values.max, - }); - }} - label="Max" - /> - ), - }} - /> - - - - - {/* - - */} - - - Total amount - {tokenFormatter(amount, 'SQD', 6)} - - - Expected CU - {isComputationUnitsLoading ? '-' : computationUnits} - - - Unlock at - - ~{dateFormat(unlockAt, 'dateTime')} - - - - + { + if (!confirmed) return onClose(); - - - )} -
- + formik.handleSubmit(); + }} + disableConfirmButton={!formik.isValid} + loading={gatewayRegistryContract.isPending} + confirmButtonText="Lock" + > + {isLoading ? ( + + ) : ( +
+ + { + const wallet = options.find(w => w?.value === e.target.value); + if (!wallet) return; + + formik.setFieldValue('source', wallet.value); + formik.setFieldValue('max', wallet.max); + }} + /> + + + { + formik.setValues({ + ...formik.values, + amount: formik.values.max || '0', + }); + }} + label="Max" + /> + ), + }} + /> + + + + + {/* + + */} + + + Total amount + {tokenFormatter(fromSqd(preview?.totalAmount), 'SQD', 6)} + + + Epoch count + {numberWithCommasFormatter(preview?.epochCount)} + + + Expected CU + {numberWithCommasFormatter(preview?.cuPerEpoch)} + + + Unlock at + + ~{dateFormat(preview?.unlockAt, 'dateTime')} + + + +
+ )} +
); } diff --git a/src/pages/GatewaysPage/GatewayUnregister.tsx b/src/pages/GatewaysPage/GatewayUnregister.tsx index f32cade..40b46f1 100644 --- a/src/pages/GatewaysPage/GatewayUnregister.tsx +++ b/src/pages/GatewaysPage/GatewayUnregister.tsx @@ -1,46 +1,87 @@ -import { LoadingButton } from '@mui/lab'; -import { Box } from '@mui/material'; -import { useNavigate } from 'react-router-dom'; +import { useState } from 'react'; -import { useUnregisterGateway } from '@api/contracts/gateway-registration/useUnregisterGateway'; -import { BlockchainContractError } from '@components/BlockchainContractError'; -import { useAccount } from '@network/useAccount'; +import { peerIdToHex } from '@lib/network'; +import { LoadingButton } from '@mui/lab'; +import toast from 'react-hot-toast'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useWriteContract } from 'wagmi'; -export function GatewayUnregister({ - gateway, -}: { - gateway: any; // PickDeep; -}) { - const navigate = useNavigate(); - const { - unregisterGateway, - error: unregisterError, - isLoading: isDeregistering, - } = useUnregisterGateway(); - const { address } = useAccount(); +import { gatewayRegistryAbi } from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; +import { Gateway } from '@api/subsquid-network-squid'; +import { ContractCallDialog } from '@components/ContractCallDialog'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useContracts } from '@network/useContracts'; - if (gateway.realOwner.id !== address) return null; +export function GatewayUnregisterButton({ gateway }: { gateway: Pick }) { + const [open, setOpen] = useState(false); return ( - + <> { - e.stopPropagation(); - - const { failedReason } = await unregisterGateway({ gateway }); - - if (!failedReason) { - navigate('/portals'); - } - }} + // startIcon={} + loading={open} + onClick={() => setOpen(true)} variant="outlined" color="error" > UNREGISTER + setOpen(false)} gateway={gateway} /> + + ); +} + +export function GatewayUnregisterDialog({ + open, + onClose, + gateway, +}: { + open: boolean; + onClose: () => void; + gateway: Pick; +}) { + const client = useClient(); + const { setWaitHeight } = useSquidHeight(); + + const contracts = useContracts(); + const gatewayRegistryContract = useWriteContract(); + + const handleSubmit = async () => { + if (!client) return; + + try { + const hash = await gatewayRegistryContract.writeContractAsync({ + address: contracts.GATEWAY_REGISTRATION, + abi: gatewayRegistryAbi, + functionName: 'unregister', + args: [peerIdToHex(gateway.id)], + }); + + const receipt = await waitForTransactionReceipt(client, { hash }); + setWaitHeight(receipt.blockNumber, []); + + onClose(); + } catch (e: unknown) { + toast.error(errorMessage(e)); + } + }; + + return ( + { + if (!confirmed) return onClose(); - - + handleSubmit(); + }} + loading={gatewayRegistryContract.isPending} + confirmButtonText="Confirm" + hideCancelButton={false} + > + Are you sure you want to unregister this gateway? This will disable the gateway, but you can + re-register it later. + ); } diff --git a/src/pages/GatewaysPage/GatewayUnstake.tsx b/src/pages/GatewaysPage/GatewayUnstake.tsx index 7fac705..12c356d 100644 --- a/src/pages/GatewaysPage/GatewayUnstake.tsx +++ b/src/pages/GatewaysPage/GatewayUnstake.tsx @@ -1,11 +1,18 @@ -import React from 'react'; +import React, { useState } from 'react'; +import { LockOpen as LockOpenIcon } from '@mui/icons-material'; import { LoadingButton } from '@mui/lab'; -import { useNavigate } from 'react-router-dom'; +import { SxProps } from '@mui/material'; +import toast from 'react-hot-toast'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useWriteContract } from 'wagmi'; import * as yup from 'yup'; -import { useUnstakeGateway } from '@api/contracts/gateway-registration/useUnstakeGateway'; -import { useMyGatewayStake } from '@api/subsquid-network-squid/gateways-graphql'; +import { gatewayRegistryAbi } from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; +import { ContractCallDialog } from '@components/ContractCallDialog'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useContracts } from '@network/useContracts'; export const stakeSchema = yup.object({ source: yup.string().label('Source').trim().required('Source is required'), @@ -17,33 +24,69 @@ export const stakeSchema = yup.object({ // .max(yup.ref('max'), ({ max }) => `Amount should be less than ${formatSqd(max)} `), }); -export function GatewayUnstake() { - const { data, isLoading: isStakeLoading } = useMyGatewayStake(); - - const navigate = useNavigate(); - const { unstakeFromGateway, isLoading } = useUnstakeGateway(); +export function GatewayUnstakeButton({ sx, disabled }: { sx?: SxProps; disabled?: boolean }) { + const [open, setOpen] = useState(false); return ( <> } + disabled={disabled} + loading={open} variant="contained" color="error" - onClick={async e => { - e.stopPropagation(); - - if (!data?.stake) return; - - const { failedReason } = await unstakeFromGateway({ operator: data.stake }); - - if (!failedReason) { - navigate('/portals'); - } - }} + onClick={() => setOpen(true)} + sx={sx} > UNLOCK + setOpen(false)} /> ); } + +export function GatewayUnstakeDialog({ onClose, open }: { onClose: () => void; open: boolean }) { + const client = useClient(); + const { setWaitHeight } = useSquidHeight(); + + const contracts = useContracts(); + const gatewayRegistryContract = useWriteContract(); + + const handleSubmit = async () => { + if (!client) return; + + try { + const hash = await gatewayRegistryContract.writeContractAsync({ + address: contracts.GATEWAY_REGISTRATION, + abi: gatewayRegistryAbi, + functionName: 'unstake', + args: [], + }); + + const receipt = await waitForTransactionReceipt(client, { hash }); + setWaitHeight(receipt.blockNumber, []); + + onClose(); + } catch (e: unknown) { + toast.error(errorMessage(e)); + } + }; + + return ( + { + if (!confirmed) return onClose(); + + handleSubmit(); + }} + loading={gatewayRegistryContract.isPending} + confirmButtonText="Confirm" + hideCancelButton={false} + > + Are you sure you want to unlock your tokens? This will disable your portals and return all + locked tokens to your wallet. + + ); +} diff --git a/src/pages/GatewaysPage/GatewaysPage.tsx b/src/pages/GatewaysPage/GatewaysPage.tsx index d09d18c..89f0cda 100644 --- a/src/pages/GatewaysPage/GatewaysPage.tsx +++ b/src/pages/GatewaysPage/GatewaysPage.tsx @@ -3,7 +3,6 @@ import React, { useMemo } from 'react'; import { dateFormat } from '@i18n'; import { numberWithCommasFormatter, tokenFormatter } from '@lib/formatters/formatters'; import { fromSqd } from '@lib/network'; -import { Add } from '@mui/icons-material'; import { Box, Button, @@ -13,59 +12,104 @@ import { TableCell, TableHead, TableRow, + Tooltip, + Typography, useMediaQuery, useTheme, } from '@mui/material'; -import { Link, Outlet } from 'react-router-dom'; +import { Outlet } from 'react-router-dom'; +import { + useReadGatewayRegistryComputationUnitsAmount, + useReadGatewayRegistryGetStake, + useReadNetworkControllerWorkerEpochLength, + useReadRouterNetworkController, +} from '@api/contracts'; import { useMyGateways, useMyGatewayStake } from '@api/subsquid-network-squid/gateways-graphql'; import SquaredChip from '@components/Chip/SquaredChip'; +import { HelpTooltip } from '@components/HelpTooltip'; import { DashboardTable, NoItems } from '@components/Table'; import { CenteredPageWrapper } from '@layouts/NetworkLayout'; import { ConnectedWalletRequired } from '@network/ConnectedWalletRequired'; +import { useAccount } from '@network/useAccount'; import { useContracts } from '@network/useContracts'; import { ColumnLabel, ColumnValue, SummarySection } from '@pages/DashboardPage/Summary'; +import { AddGatewayButton } from './AddNewGateway'; import { AutoExtension } from './AutoExtension'; import { GatewayName } from './GatewayName'; -import { GatewayStake } from './GatewayStake'; -import { GatewayUnregister } from './GatewayUnregister'; -import { GatewayUnstake } from './GatewayUnstake'; +import { GatewayStakeButton } from './GatewayStake'; +import { GatewayUnregisterButton } from './GatewayUnregister'; +import { GatewayUnstakeButton } from './GatewayUnstake'; export function MyStakes() { const theme = useTheme(); const narrowXs = useMediaQuery(theme.breakpoints.down('xs')); - const { data: stake, isLoading: isStakeLoading } = useMyGatewayStake(); - const { SQD_TOKEN } = useContracts(); + const { address } = useAccount(); + const { GATEWAY_REGISTRATION, ROUTER, SQD_TOKEN } = useContracts(); + + const { data: stake, isLoading: isStakeLoading } = useReadGatewayRegistryGetStake({ + address: GATEWAY_REGISTRATION, + args: [address || '0x'], + }); + const { data: cuAmount, isLoading: isCuAmountLoading } = + useReadGatewayRegistryComputationUnitsAmount({ + address: GATEWAY_REGISTRATION, + args: [stake?.amount || 0n, stake?.duration || 0n], + }); + const { data: lastBlockInfo, isLoading: isLastBlockInfoLoading } = useMyGatewayStake(); + const { data: workerEpochLength, isLoading: isWorkerEpochLengthLoading } = + useReadNetworkControllerWorkerEpochLength({ + address: useReadRouterNetworkController({ address: ROUTER }).data, + }); + + const isLoading = + isStakeLoading || isCuAmountLoading || isLastBlockInfoLoading || isWorkerEpochLengthLoading; const unlockDate = useMemo(() => { - if (!stake?.stake) return; - if (!stake.stake.lockEnd) return; + if (!stake || !lastBlockInfo) return; return ( - (Number(stake.stake.lockEnd) - stake.lastBlockL1 + 1) * 12_000 + - new Date(stake.lastBlockTimestampL1).getTime() + (Number(stake.lockEnd) - lastBlockInfo.lastBlockL1 + 1) * 12_000 + + new Date(lastBlockInfo.lastBlockTimestampL1).getTime() ); - }, [stake]); + }, [lastBlockInfo, stake]); + + const cuPerEpoch = useMemo(() => { + if (!stake || !workerEpochLength || !lastBlockInfo) return 0; + + if (stake.lockEnd < lastBlockInfo.lastBlockL1) return 0; + + const computationUnits = + stake.lockStart > lastBlockInfo.lastBlockL1 ? stake.oldCUs : cuAmount || 0n; + if (stake.duration < workerEpochLength) return computationUnits; + + return (computationUnits * workerEpochLength) / stake.duration; + }, [cuAmount, lastBlockInfo, stake, workerEpochLength]); return ( <> } action={ - - - + + (lastBlockInfo?.lastBlockL1 || 0n)} + /> + (lastBlockInfo?.lastBlockL1 || 0n)} + /> } > - + } @@ -77,30 +121,41 @@ export function MyStakes() { width={0.75} > } spacing={1} flex={1}> - - Amount - - {tokenFormatter(fromSqd(stake?.stake?.amount), SQD_TOKEN, 3)} - - - Allocated CUs - {stake?.stake?.computationUnitsPending ? ( - - ) : stake?.stake?.locked ? ( - - ) : BigInt(stake?.stake?.amount || 0) > 0n ? ( - - ) : null} + Amount + + + {stake && + lastBlockInfo && + (stake.lockStart > lastBlockInfo.lastBlockL1 ? ( + + ) : stake.lockEnd > lastBlockInfo.lastBlockL1 ? ( + + ) : ( + + ))} + + + {tokenFormatter(fromSqd(stake?.amount), SQD_TOKEN, 3)} + + + + + Available CUs + + - {numberWithCommasFormatter(stake?.stake?.computationUnits || 0)} - {stake?.stake?.computationUnitsPending + {numberWithCommasFormatter(cuPerEpoch || 0)} + {/* {stake?.stake?.computationUnitsPending ? ` (${numberWithCommasFormatter(stake?.stake?.computationUnitsPending)})` - : ``} + : ``} */} @@ -108,9 +163,9 @@ export function MyStakes() { Unlocked At - {unlockDate && !stake?.stake?.autoExtension + {unlockDate && !stake?.autoExtension ? dateFormat(unlockDate, narrowXs ? 'date' : 'dateTime') - : '-'} + : 'N/A'} @@ -124,22 +179,36 @@ export function MyStakes() { export function MyGateways() { const { data: gateways, isLoading: isGatewaysLoading } = useMyGateways(); + // const [isProMode, setProMode] = useLocalStorageState('sqd_portals_pro_mode', { + // defaultValue: false, + // serializer: localStorageBoolSerializer, + // storageSync: false, + // }); return ( - - + + + {/* + + setProMode(!isProMode)} />} + label={Pro mode} + labelPlacement="end" + /> + + */} + + + + + } > @@ -162,7 +231,7 @@ export function MyGateways() { {dateFormat(gateway.createdAt)} - + @@ -170,7 +239,15 @@ export function MyGateways() { })} ) : ( - + + No portal registered yet + {/* {!isProMode && ( + + )} */} + )} diff --git a/src/pages/GatewaysPage/gateway-schema.ts b/src/pages/GatewaysPage/gateway-schema.ts index 96d6764..cc384e3 100644 --- a/src/pages/GatewaysPage/gateway-schema.ts +++ b/src/pages/GatewaysPage/gateway-schema.ts @@ -27,8 +27,7 @@ export const addGatewaySchema = editGatewaySchema.shape({ peerId: yup .string() .matches(/^[a-z1-9]+$/i, 'Peer ID must contains only base 58 symbols') - .max(52) - .min(52) + .length(52) .label('Peer ID') .trim() .required('Peer ID is required'), diff --git a/src/pages/WorkersPage/AddNewWorker.tsx b/src/pages/WorkersPage/AddNewWorker.tsx index 5c6368e..f88e35c 100644 --- a/src/pages/WorkersPage/AddNewWorker.tsx +++ b/src/pages/WorkersPage/AddNewWorker.tsx @@ -1,134 +1,229 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useMemo, useState } from 'react'; -import { fromSqd } from '@lib/network/utils'; +import { fromSqd, peerIdToHex } from '@lib/network/utils'; +import { Add } from '@mui/icons-material'; import { LoadingButton } from '@mui/lab'; -import { Box } from '@mui/material'; +import { SxProps } from '@mui/material'; import BigNumber from 'bignumber.js'; import { useFormik } from 'formik'; -import { useNavigate } from 'react-router-dom'; +import toast from 'react-hot-toast'; import useLocalStorageState from 'use-local-storage-state'; +import { encodeFunctionData } from 'viem'; +import { readContract, waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useWriteContract } from 'wagmi'; -import { useRegisterWorker } from '@api/contracts/worker-registration/useRegisterWorker'; -import { useMySources } from '@api/subsquid-network-squid'; -import { useNetworkSettings } from '@api/subsquid-network-squid/settings-graphql'; -import { BlockchainContractError } from '@components/BlockchainContractError'; -import { Card } from '@components/Card'; +import { + sqdAbi, + useReadRouterWorkerRegistration, + useReadWorkerRegistryBondAmount, + vestingAbi, + workerRegistryAbi, +} from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; +import { encodeWorkerMetadata } from '@api/contracts/worker-registration/WorkerMetadata'; +import { AccountType, useAccountQuery, useSquid } from '@api/subsquid-network-squid'; import { ConfirmDialog } from '@components/ConfirmDialog'; +import { ContractCallDialog } from '@components/ContractCallDialog'; import { Form, FormikCheckBoxInput, FormikTextInput, FormRow } from '@components/Form'; import { FormikSelect } from '@components/Form/FormikSelect'; import { Loader } from '@components/Loader'; import { SourceWalletOption } from '@components/SourceWallet'; -import { CenteredPageWrapper, NetworkPageTitle } from '@layouts/NetworkLayout'; -import { ConnectedWalletRequired } from '@network/ConnectedWalletRequired'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useAccount } from '@network/useAccount'; +import { useContracts } from '@network/useContracts'; import { useWorkersChatUrl } from '@network/useWorkersChat'; import { addWorkerSchema } from './worker-schema'; -function JoinChatDialog({ open, onResult }: { open: boolean; onResult: () => void }) { - const [, setSkipWorkerJoinChat] = useLocalStorageState('skip_join_workers_chat'); - const chatUrl = useWorkersChatUrl(); +export function AddNewWorker({ sx, disabled }: { sx?: SxProps; disabled?: boolean }) { + const [open, setOpen] = useState(false); - const formik = useFormik({ - initialValues: { - doNotShow: false, - }, - - onSubmit: async values => { - setSkipWorkerJoinChat(values.doNotShow); - onResult(); - }, - }); + const [isJoinChatOpen, setJoinChatOpen] = useState(false); + const [skipWorkerJoinChat] = useLocalStorageState('sqd_skip_join_workers_chat'); return ( - window.open(chatUrl)} - onResult={formik.submitForm} - > -
- Join the Subsquid Network node operators chat for support and updates on worker - images. - - - -
-
+ <> + } + variant="contained" + onClick={() => setOpen(true)} + > + ADD WORKER + + { + setOpen(false); + + if (confirmed && !skipWorkerJoinChat) { + setJoinChatOpen(true); + } + }} + /> + { + setJoinChatOpen(false); + }} + /> + ); } -function AddWorkerForm() { - const navigate = useNavigate(); - const { bondAmount, isPending: isSettingsLoading } = useNetworkSettings(); - const { sources, isPending: isContractsLoading } = useMySources(); - const { registerWorker, isLoading, error } = useRegisterWorker(); - const [isJoinChatOpen, setJoinChatOpen] = useState(false); - const [skipWorkerJoinChat] = useLocalStorageState('skip_join_workers_chat'); +export function AddNewWorkerDialog({ + open, + onResult, +}: { + open: boolean; + onResult: (confirmed: boolean) => void; +}) { + const client = useClient(); + const account = useAccount(); + const squid = useSquid(); - const formik = useFormik({ - initialValues: { + const { setWaitHeight } = useSquidHeight(); + + const contracts = useContracts(); + const contractWriter = useWriteContract(); + + const { data: workerRegistryAddress, isLoading: isWorkerRegistryAddressLoading } = + useReadRouterWorkerRegistration({ + address: contracts.ROUTER, + }); + + const { data: bondAmount, isPending: isBondLoading } = useReadWorkerRegistryBondAmount({ + address: workerRegistryAddress, + }); + + const { data: accountQuery, isLoading: isAccountQueryLoading } = useAccountQuery(squid, { + address: account.address || '0x', + }); + + const isLoading = isWorkerRegistryAddressLoading || isBondLoading || isAccountQueryLoading; + + const sources = useMemo(() => { + if (!accountQuery?.accountById) return []; + + return [accountQuery.accountById, ...accountQuery.accountById.owned].map(s => { + return { + id: s.id, + type: s.type, + balance: s.balance, + disabled: !bondAmount || BigNumber(s.balance).lte(bondAmount.toString()), + }; + }); + }, [accountQuery?.accountById, bondAmount]); + + const initialValues = useMemo(() => { + const source = sources.find(c => !c.disabled) || sources?.[0]; + + return { name: '', description: '', website: '', email: '', peerId: '', - source: '', - }, + source: source?.id || '', + bond: fromSqd(bondAmount).toString(), + }; + }, [bondAmount, sources]); + + const formik = useFormik({ + initialValues, validationSchema: addWorkerSchema, validateOnChange: true, validateOnBlur: true, validateOnMount: true, + enableReinitialize: true, onSubmit: async values => { - const source = sources.find(s => s.id === values.source); - if (!source) return; - - const { success } = await registerWorker({ - ...values, - source, - }); - if (!success) return; - - if (skipWorkerJoinChat) { - navigate('/workers'); - } else { - setJoinChatOpen(true); - } - }, - }); + if (!client || !account.address || !workerRegistryAddress || !bondAmount) return; - const source = useMemo(() => { - if (isContractsLoading) return; - if (isSettingsLoading) return; + try { + const { peerId, source: sourceId, ...metadata } = addWorkerSchema.cast(values); - return ( - (formik.values.source - ? sources.find(c => c.id === formik.values.source) - : sources.find(c => fromSqd(c.balance).gte(fromSqd(bondAmount)))) || sources?.[0] - ); - }, [bondAmount, formik.values.source, isContractsLoading, isSettingsLoading, sources]); + const source = sources.find(s => s.id === sourceId); + if (!source) return; - useEffect(() => { - if (!source) return; + const peerIdHex = peerIdToHex(peerId); + const functionData = { + abi: workerRegistryAbi, + functionName: 'register', + args: [peerIdHex, encodeWorkerMetadata(metadata)], + } as const; - formik.setValues({ - ...formik.values, - source: source.id, - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [source]); + let transactionHash: `0x${string}`; + switch (source.type) { + case AccountType.User: { + const allowance = await readContract(client, { + abi: sqdAbi, + functionName: 'allowance', + address: contracts.SQD, + args: [source.id as `0x${string}`, workerRegistryAddress], + }); + + if (allowance < bondAmount) { + await contractWriter.writeContractAsync({ + abi: sqdAbi, + address: contracts.SQD, + functionName: 'approve', + args: [workerRegistryAddress, bondAmount], + }); + } + + transactionHash = await contractWriter.writeContractAsync({ + address: workerRegistryAddress, + ...functionData, + }); + break; + } + case AccountType.Vesting: { + transactionHash = await contractWriter.writeContractAsync({ + address: source.id as `0x${string}`, + abi: vestingAbi, + functionName: 'execute', + args: [workerRegistryAddress, encodeFunctionData(functionData), bondAmount], + }); + break; + } + default: + return; + } + + const receipt = await waitForTransactionReceipt(client, { hash: transactionHash }); + setWaitHeight(receipt.blockNumber, []); + + formik.resetForm(); + + onResult(true); + } catch (error) { + toast.error(errorMessage(error)); + } + }, + }); return ( <> - {isContractsLoading ? ( - - ) : ( - <> -
- + { + if (!confirmed) return onResult(confirmed); + + formik.handleSubmit(); + }} + loading={isLoading} + confirmButtonText="Confirm" + > + {isLoading ? ( + + ) : ( + <> + , value: s.id, - disabled: BigNumber(s.balance).lt(bondAmount), + disabled: s.disabled, }; })} formik={formik} /> + + + - - - - - REGISTER - - -
- { - navigate('/workers'); - setJoinChatOpen(false); - }} - /> - - )} + + + )} + ); } -export function AddNewWorker() { +function JoinChatDialog({ + open, + onResult, +}: { + open: boolean; + onResult: (confirmed: boolean) => void; +}) { + const [, setSkipWorkerJoinChat] = useLocalStorageState('sqd_skip_join_workers_chat'); + const chatUrl = useWorkersChatUrl(); + + const formik = useFormik({ + initialValues: { + doNotShow: false, + }, + + onSubmit: async values => { + setSkipWorkerJoinChat(values.doNotShow); + onResult(true); + }, + }); + return ( - - - - - - + window.open(chatUrl)} + onResult={(confirmed: boolean) => { + if (!confirmed) onResult(confirmed); + + formik.handleSubmit(); + }} + > +
+ Join the Subsquid Network node operators chat for support and updates on worker + images. + + + +
+
); } + +// export function AddNewWorker() { +// return ( +// +// +// +// +// +// +// ); +// } diff --git a/src/pages/WorkersPage/Worker.tsx b/src/pages/WorkersPage/Worker.tsx index 7d11c67..b8a8973 100644 --- a/src/pages/WorkersPage/Worker.tsx +++ b/src/pages/WorkersPage/Worker.tsx @@ -10,7 +10,11 @@ import { fromSqd } from '@lib/network'; import { Box, Divider, Stack, styled } from '@mui/material'; import { useParams, useSearchParams } from 'react-router-dom'; -import { useWorkerByPeerId, WorkerStatus as ApiWorkerStatus } from '@api/subsquid-network-squid'; +import { + useWorkerByPeerId, + WorkerStatus as ApiWorkerStatus, + WorkerStatus, +} from '@api/subsquid-network-squid'; import { Card } from '@components/Card'; import SquaredChip from '@components/Chip/SquaredChip'; import { Loader } from '@components/Loader'; @@ -18,13 +22,14 @@ import { NotFound } from '@components/NotFound'; import { CenteredPageWrapper, NetworkPageTitle } from '@layouts/NetworkLayout'; import { useAccount } from '@network/useAccount'; import { useContracts } from '@network/useContracts'; -import { WorkerUnregister } from '@pages/WorkersPage/WorkerUnregister'; +import { WorkerUnregisterButton } from '@pages/WorkersPage/WorkerUnregister'; import { DelegationCapacity } from './DelegationCapacity'; import { WorkerCard } from './WorkerCard'; import { WorkerDelegate } from './WorkerDelegate'; import { WorkerUndelegate } from './WorkerUndelegate'; import { WorkerVersion } from './WorkerVersion'; +import { WorkerWithdrawButton } from './WorkerWithdraw'; // const sx = { // background: '#000', @@ -240,8 +245,21 @@ export const Worker = ({ backPath }: { backPath: string }) => { {worker.realOwner.id === address && worker.status !== ApiWorkerStatus.Withdrawn ? ( - - + + {worker.status === WorkerStatus.Deregistered || + worker.status === WorkerStatus.Deregistering ? ( + + ) : ( + + )} ) : null} diff --git a/src/pages/WorkersPage/WorkerCard.tsx b/src/pages/WorkersPage/WorkerCard.tsx index 7e6462e..0760292 100644 --- a/src/pages/WorkersPage/WorkerCard.tsx +++ b/src/pages/WorkersPage/WorkerCard.tsx @@ -7,7 +7,7 @@ import { Avatar } from '@components/Avatar'; import { CopyToClipboard } from '@components/CopyToClipboard'; import { EditIcon } from '@icons/EditIcon'; -import { WorkerStatus } from './WorkerStatus'; +import { WorkerStatusChip } from './WorkerStatus'; // export const PeerIdRow = styled(Box, { // name: 'PeerIdRow', @@ -76,7 +76,7 @@ export const WorkerCard = ({ {/*
*/}
- + diff --git a/src/pages/WorkersPage/WorkerDelegate.tsx b/src/pages/WorkersPage/WorkerDelegate.tsx index bfb7f20..0b73866 100644 --- a/src/pages/WorkersPage/WorkerDelegate.tsx +++ b/src/pages/WorkersPage/WorkerDelegate.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { percentFormatter } from '@lib/formatters/formatters'; import { fromSqd, toSqd } from '@lib/network/utils'; @@ -10,18 +10,23 @@ import { useFormik } from 'formik'; import { useDebounce } from 'use-debounce'; import { useCapedStakeAfterDelegation, useWorkerDelegate } from '@api/contracts/staking'; -import { useWorkerDelegationInfo, Worker, WorkerStatus } from '@api/subsquid-network-squid'; +import { + useMySources, + useWorkerDelegationInfo, + Worker, + WorkerStatus, +} from '@api/subsquid-network-squid'; import { BlockchainContractError } from '@components/BlockchainContractError'; import { ContractCallDialog } from '@components/ContractCallDialog'; import { Form, FormDivider, FormikSelect, FormikTextInput, FormRow } from '@components/Form'; import { HelpTooltip } from '@components/HelpTooltip'; -import { useMySourceOptions } from '@components/SourceWallet/useMySourceOptions'; +import { SourceWalletOption } from '@components/SourceWallet'; export const EXPECTED_APR_TIP = ( - + An estimated delegation APR. The realized APR may differ significantly and depends on the worker uptime and the total amount of SQD delegated to the worker, which may change over time. - + ); export const delegateSchema = yup.object({ @@ -54,21 +59,31 @@ export function WorkerDelegate({ }; const handleClose = () => setOpen(false); - const { - sources, - options, - isPending: isSourceLoading, - } = useMySourceOptions({ - enabled: open, - sourceDisabled: s => BigNumber(s.balance).lte(0), - }); + const { sources, isPending: isSourceLoading } = useMySources({}); + + const options = useMemo(() => { + return sources.map(s => { + return { + label: , + value: s.id, + disabled: s.balance === '0', + max: fromSqd(s.balance).toString(), + }; + }); + }, [sources]); + + const initialValues = useMemo(() => { + const option = options.find(c => !c.disabled) || options?.[0]; + + return { + source: option?.value || '', + amount: '0', + max: option?.max || '0', + }; + }, [options]); const formik = useFormik({ - initialValues: { - source: '', - amount: '', - max: '0', - }, + initialValues, validationSchema: delegateSchema, validateOnChange: true, validateOnBlur: true, @@ -90,27 +105,6 @@ export function WorkerDelegate({ }, }); - const source = useMemo(() => { - if (isSourceLoading) return; - - return ( - (formik.values.source - ? sources.find(c => c.id === formik.values.source) - : sources.find(c => fromSqd(c.balance).gte(0))) || sources?.[0] - ); - }, [formik.values.source, isSourceLoading, sources]); - - useEffect(() => { - if (!source) return; - - formik.setValues({ - ...formik.values, - source: source.id, - max: fromSqd(source.balance).toFixed(), - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [source]); - const [delegation] = useDebounce(formik.values.amount, 500); const { isPending: isExpectedAprPending, stakerApr } = useExpectedAprAfterDelegation({ workerId: worker?.id, @@ -148,11 +142,11 @@ export function WorkerDelegate({ options={options} formik={formik} onChange={e => { - const wallet = sources.find(w => w?.id === e.target.value); - if (!wallet) return; + const option = options.find(w => w?.value === e.target.value); + if (!option) return; - formik.setFieldValue('source', wallet.id); - formik.setFieldValue('max', fromSqd(wallet.balance).toFixed()); + formik.setFieldValue('source', option.value); + formik.setFieldValue('max', option.max); }} /> @@ -183,10 +177,9 @@ export function WorkerDelegate({ Expected APR - - {isExpectedAprPending ? '-' : percentFormatter(stakerApr)} - - + + {isExpectedAprPending ? '-' : percentFormatter(stakerApr)} + diff --git a/src/pages/WorkersPage/WorkerStatus.tsx b/src/pages/WorkersPage/WorkerStatus.tsx index 60244bc..7ee92a9 100644 --- a/src/pages/WorkersPage/WorkerStatus.tsx +++ b/src/pages/WorkersPage/WorkerStatus.tsx @@ -21,10 +21,10 @@ export const Chip = styled(MaterialChip)(({ theme }) => ({ }, })); -export function WorkerStatus({ worker }: { worker: WorkerStatusFragmentFragment }) { +export function WorkerStatusChip({ worker }: { worker: WorkerStatusFragmentFragment }) { const { label, color, tip } = useMemo((): { label: string; - color: 'error' | 'success' | 'primary'; + color: 'error' | 'warning' | 'success' | 'primary'; tip?: string; } => { if (!worker.status) return { label: 'Unknown', color: 'primary' }; @@ -32,9 +32,9 @@ export function WorkerStatus({ worker }: { worker: WorkerStatusFragmentFragment switch (worker.status) { case Status.Active: if (worker.jailed) { - return { label: 'Jailed', color: 'error', tip: worker.jailReason || 'Unknown' }; + return { label: 'Jailed', color: 'warning', tip: worker.jailReason || 'Unknown' }; } else if (!worker.online) { - return { label: 'Offline', color: 'primary' }; + return { label: 'Offline', color: 'error' }; } return { label: 'Online', color: 'success' }; diff --git a/src/pages/WorkersPage/WorkerUndelegate.tsx b/src/pages/WorkersPage/WorkerUndelegate.tsx index 38bdb10..94f385f 100644 --- a/src/pages/WorkersPage/WorkerUndelegate.tsx +++ b/src/pages/WorkersPage/WorkerUndelegate.tsx @@ -198,10 +198,9 @@ export function WorkerUndelegate({ Expected APR - - {isExpectedAprPending ? '-' : percentFormatter(stakerApr)} - - + + {isExpectedAprPending ? '-' : percentFormatter(stakerApr)} + diff --git a/src/pages/WorkersPage/WorkerUnregister.tsx b/src/pages/WorkersPage/WorkerUnregister.tsx index 6a322d6..7d84de1 100644 --- a/src/pages/WorkersPage/WorkerUnregister.tsx +++ b/src/pages/WorkersPage/WorkerUnregister.tsx @@ -1,66 +1,185 @@ -import React from 'react'; +import React, { useState } from 'react'; +import { peerIdToHex } from '@lib/network'; import { LoadingButton } from '@mui/lab'; -import { Box } from '@mui/material'; +import toast from 'react-hot-toast'; +import { encodeFunctionData } from 'viem'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useWriteContract } from 'wagmi'; -import { useUnregisterWorker } from '@api/contracts/worker-registration/useUnregisterWorker'; -import { useWithdrawWorker } from '@api/contracts/worker-registration/useWithdrawWorker'; -import { AccountType, useWorkerOwner, Worker, WorkerStatus } from '@api/subsquid-network-squid'; -import { BlockchainContractError } from '@components/BlockchainContractError'; +import { useReadRouterWorkerRegistration, vestingAbi, workerRegistryAbi } from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; +import { Account, AccountType, Worker } from '@api/subsquid-network-squid'; +import { ContractCallDialog } from '@components/ContractCallDialog'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useAccount } from '@network/useAccount'; +import { useContracts } from '@network/useContracts'; -export function WorkerUnregister({ +export function WorkerUnregisterButton({ worker, + owner, disabled, }: { worker: Pick; + owner: Pick; disabled?: boolean; }) { - const { - unregisterWorker, - error: unregisterError, - isLoading: isDeregistering, - } = useUnregisterWorker(); - const { withdrawWorker, error: withdrawError, isLoading: isWithdrawing } = useWithdrawWorker(); - const { data } = useWorkerOwner({ workerId: worker.id, enabled: !disabled }); + const [open, setOpen] = useState(false); return ( - - - {worker.status === WorkerStatus.Deregistered || worker.status === WorkerStatus.Withdrawn ? ( - { - e.stopPropagation(); - await withdrawWorker({ - peerId: worker.peerId, - source: data?.owner || { id: '', type: AccountType.User }, - }); - }} - disabled={disabled || worker.status === WorkerStatus.Withdrawn} - variant="outlined" - color="error" - > - WITHDRAW - - ) : ( - { - e.stopPropagation(); - await unregisterWorker({ - peerId: worker.peerId, - source: data?.owner || { id: '', type: AccountType.User }, - }); - }} - variant="outlined" - color="error" - > - UNREGISTER - - )} - - - + <> + } + loading={open} + onClick={() => setOpen(true)} + variant="outlined" + color="error" + disabled={disabled} + > + UNREGISTER + + setOpen(false)} + worker={worker} + owner={owner} + /> + ); } + +export function WorkerUnregisterDialog({ + open, + onClose, + worker, + owner, +}: { + open: boolean; + onClose: () => void; + worker: Pick; + owner: Pick; +}) { + const client = useClient(); + const account = useAccount(); + const { setWaitHeight } = useSquidHeight(); + + const contracts = useContracts(); + const contractWriter = useWriteContract(); + + const { data: registrationAddress } = useReadRouterWorkerRegistration({ + address: contracts.ROUTER, + }); + + const handleSubmit = async () => { + if (!client || !account.address || !registrationAddress) return; + + try { + let transactionHash: `0x${string}`; + const peerIdHex = peerIdToHex(worker.peerId); + const functionData = { + abi: workerRegistryAbi, + functionName: 'deregister', + args: [peerIdHex], + } as const; + + switch (owner.type) { + case AccountType.User: { + transactionHash = await contractWriter.writeContractAsync({ + address: registrationAddress, + ...functionData, + }); + break; + } + case AccountType.Vesting: { + transactionHash = await contractWriter.writeContractAsync({ + address: owner.id as `0x${string}`, + abi: vestingAbi, + functionName: 'execute', + args: [registrationAddress, encodeFunctionData(functionData)], + }); + break; + } + default: + return; + } + + const receipt = await waitForTransactionReceipt(client, { hash: transactionHash }); + setWaitHeight(receipt.blockNumber, []); + onClose(); + } catch (error) { + toast.error(errorMessage(error)); + } + }; + + return ( + { + if (!confirmed) return onClose(); + handleSubmit(); + }} + loading={contractWriter.isPending} + confirmButtonText="Confirm" + hideCancelButton={false} + > + Are you sure you want to unregister this worker? This will disable the worker, but you can + re-register it later. You will be able to withdraw your tokens after the end of the lock + period. + + ); +} + +// export function WorkerUnregister({ +// worker, +// disabled, +// }: { +// worker: Pick; +// disabled?: boolean; +// }) { +// const { +// unregisterWorker, +// error: unregisterError, +// isLoading: isDeregistering, +// } = useUnregisterWorker(); +// const { withdrawWorker, error: withdrawError, isLoading: isWithdrawing } = useWithdrawWorker(); +// const { data } = useWorkerOwner({ workerId: worker.id, enabled: !disabled }); + +// return ( +// <> +// {worker.status === WorkerStatus.Deregistered || worker.status === WorkerStatus.Withdrawn ? ( +// { +// e.stopPropagation(); +// await withdrawWorker({ +// peerId: worker.peerId, +// source: data?.owner || { id: '', type: AccountType.User }, +// }); +// }} +// disabled={disabled || worker.status === WorkerStatus.Withdrawn} +// variant="outlined" +// color="error" +// > +// WITHDRAW +// +// ) : ( +// { +// e.stopPropagation(); +// await unregisterWorker({ +// peerId: worker.peerId, +// source: data?.owner || { id: '', type: AccountType.User }, +// }); +// }} +// variant="outlined" +// color="error" +// > +// UNREGISTER +// +// )} +// +// ); +// } diff --git a/src/pages/WorkersPage/WorkerVersion.tsx b/src/pages/WorkersPage/WorkerVersion.tsx index b343ee0..7f732e1 100644 --- a/src/pages/WorkersPage/WorkerVersion.tsx +++ b/src/pages/WorkersPage/WorkerVersion.tsx @@ -1,8 +1,8 @@ -import { Box, Stack, styled } from '@mui/material'; +import { Report, Warning } from '@mui/icons-material'; +import { Box, Stack, styled, Tooltip } from '@mui/material'; import { satisfies } from 'semver'; import { Worker, useNetworkSettings } from '@api/subsquid-network-squid'; -import { WarningIcon } from '@icons/WarningIcon'; export const WorkerVersionName = styled(Box, { name: 'WorkerVersionName', @@ -22,9 +22,13 @@ export const WorkerVersion = ({ worker }: { worker: Pick }) = {!satisfies(worker.version, recommendedWorkerVersion, { includePrerelease: true }) ? ( !satisfies(worker.version, minimalWorkerVersion, { includePrerelease: true }) ? ( - + + + ) : ( - + + + ) ) : null} diff --git a/src/pages/WorkersPage/WorkerWithdraw.tsx b/src/pages/WorkersPage/WorkerWithdraw.tsx new file mode 100644 index 0000000..47eddba --- /dev/null +++ b/src/pages/WorkersPage/WorkerWithdraw.tsx @@ -0,0 +1,129 @@ +import React, { useState } from 'react'; + +import { peerIdToHex } from '@lib/network'; +import { LoadingButton } from '@mui/lab'; +import toast from 'react-hot-toast'; +import { encodeFunctionData } from 'viem'; +import { waitForTransactionReceipt } from 'viem/actions'; +import { useClient, useWriteContract } from 'wagmi'; + +import { vestingAbi, workerRegistryAbi } from '@api/contracts'; +import { errorMessage } from '@api/contracts/utils'; +import { Account, AccountType, Worker } from '@api/subsquid-network-squid'; +import { ContractCallDialog } from '@components/ContractCallDialog'; +import { useSquidHeight } from '@hooks/useSquidNetworkHeightHooks'; +import { useAccount } from '@network/useAccount'; +import { useContracts } from '@network/useContracts'; + +export function WorkerWithdrawButton({ + worker, + owner, + disabled, +}: { + worker: Pick; + owner: Pick; + disabled?: boolean; +}) { + const [open, setOpen] = useState(false); + + return ( + <> + } + loading={open} + onClick={() => setOpen(true)} + variant="outlined" + color="error" + disabled={disabled} + > + WITHDRAW + + setOpen(false)} + worker={worker} + owner={owner} + /> + + ); +} + +export function WorkerWithdrawDialog({ + open, + onClose, + worker, + owner, +}: { + open: boolean; + onClose: () => void; + worker: Pick; + owner: Pick; +}) { + const client = useClient(); + const account = useAccount(); + const { setWaitHeight } = useSquidHeight(); + + const contracts = useContracts(); + const contractWriter = useWriteContract(); + + const handleSubmit = async () => { + if (!client) return; + if (!account.address) return; + + try { + let hash: `0x${string}`; + switch (owner.type) { + case AccountType.User: { + hash = await contractWriter.writeContractAsync({ + address: contracts.WORKER_REGISTRATION, + abi: workerRegistryAbi, + functionName: 'withdraw', + args: [peerIdToHex(worker.peerId)], + }); + break; + } + case AccountType.Vesting: { + const data = encodeFunctionData({ + abi: workerRegistryAbi, + functionName: 'withdraw', + args: [peerIdToHex(worker.peerId)], + }); + + hash = await contractWriter.writeContractAsync({ + address: owner.id as `0x${string}`, + abi: vestingAbi, + functionName: 'execute', + args: [contracts.WORKER_REGISTRATION, data], + }); + break; + } + default: + return; + } + + const receipt = await waitForTransactionReceipt(client, { hash }); + setWaitHeight(receipt.blockNumber, []); + + onClose(); + } catch (e: unknown) { + toast.error(errorMessage(e)); + } + }; + + return ( + { + if (!confirmed) return onClose(); + + handleSubmit(); + }} + loading={contractWriter.isPending} + confirmButtonText="Confirm" + hideCancelButton={false} + > + Are you sure you want to withdraw your tokens from this worker? + + ); +} diff --git a/src/pages/WorkersPage/WorkersPage.tsx b/src/pages/WorkersPage/WorkersPage.tsx index 2095e43..738e55c 100644 --- a/src/pages/WorkersPage/WorkersPage.tsx +++ b/src/pages/WorkersPage/WorkersPage.tsx @@ -1,10 +1,9 @@ import { percentFormatter, tokenFormatter } from '@lib/formatters/formatters.ts'; import { fromSqd } from '@lib/network'; -import { Add } from '@mui/icons-material'; -import { Box, Button, TableBody, TableCell, TableHead, TableRow } from '@mui/material'; -import { Link, Outlet } from 'react-router-dom'; +import { Box, Button, Stack, TableBody, TableCell, TableHead, TableRow } from '@mui/material'; +import { Outlet } from 'react-router-dom'; -import { SortDir, useMyWorkers, WorkerSortBy } from '@api/subsquid-network-squid'; +import { SortDir, useMyWorkers, WorkerSortBy, WorkerStatus } from '@api/subsquid-network-squid'; import SquaredChip from '@components/Chip/SquaredChip'; import { DashboardTable, SortableHeaderCell, NoItems } from '@components/Table'; import { Location, useLocationState } from '@hooks/useLocationState'; @@ -13,10 +12,12 @@ import { ConnectedWalletRequired } from '@network/ConnectedWalletRequired'; import { useAccount } from '@network/useAccount'; import { useContracts } from '@network/useContracts'; import { WorkerName } from '@pages/WorkersPage/WorkerName'; -import { WorkerStatus } from '@pages/WorkersPage/WorkerStatus'; +import { WorkerStatusChip } from '@pages/WorkersPage/WorkerStatus'; -import { WorkerUnregister } from './WorkerUnregister'; +import { AddNewWorker } from './AddNewWorker'; +import { WorkerUnregisterButton } from './WorkerUnregister'; import { WorkerVersion } from './WorkerVersion'; +import { WorkerWithdrawButton } from './WorkerWithdraw'; export function MyWorkers() { const [query, setQuery] = useLocationState({ @@ -37,16 +38,12 @@ export function MyWorkers() { title={ <> - + + + + } > @@ -93,7 +90,7 @@ export function MyWorkers() {
- + @@ -109,7 +106,20 @@ export function MyWorkers() { - + {worker.status === WorkerStatus.Deregistered || + worker.status === WorkerStatus.Deregistering ? ( + + ) : ( + + )} diff --git a/src/schema/decimal.ts b/src/schema/decimal.ts index 3e1c8ba..ab3c5bc 100644 --- a/src/schema/decimal.ts +++ b/src/schema/decimal.ts @@ -57,7 +57,8 @@ class DecimalSchema< this.withMutation(() => { this.transform(value => { - return BigNumber(value); + const res = BigNumber(value || 0); + return res.isNaN() ? BigNumber(0) : res; }); }); } diff --git a/src/theme/theme.tsx b/src/theme/theme.tsx index 42f0509..7b8798d 100644 --- a/src/theme/theme.tsx +++ b/src/theme/theme.tsx @@ -144,14 +144,14 @@ declare module '@mui/material/styles/createPalette' { } } -declare module 'notistack' { - interface VariantOverrides { - subsquid: { - title: string; - severity: 'warning' | 'success' | 'error' | 'info'; - }; - } -} +// declare module 'notistack' { +// interface VariantOverrides { +// subsquid: { +// title: string; +// severity: 'warning' | 'success' | 'error' | 'info'; +// }; +// } +// } const fontFamily = `'Matter', 'Inter', sans-serif`; @@ -179,14 +179,14 @@ export const useCreateTheme = (mode: PaletteType) => { typography: { fontFamily, h1: { - fontSize: 64, + fontSize: 60, lineHeight: 1, fontWeight: 500, color: colors.text.primary, letterSpacing: '-0.01rem', }, h2: { - fontSize: 40, + fontSize: 36, lineHeight: 1, fontWeight: 500, color: colors.text?.primary, @@ -306,7 +306,7 @@ export const useCreateTheme = (mode: PaletteType) => { styleOverrides: { root: { textTransform: 'none', - transition: 'all 300ms ease-out', + // transition: 'all 300ms ease-out', borderRadius: 360, boxShadow: 'none', textShadow: 'none', diff --git a/tsconfig.json b/tsconfig.json index 1f33217..cc08f86 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,25 +20,25 @@ "jsx": "react-jsx", /* Paths */ - "baseUrl": "./", + // "baseUrl": "./", "paths": { - "@components/*": ["src/components/*"], - "@layouts/*": ["src/layouts/*"], - "@contexts/*": ["src/contexts/*"], - "@loaders/*": ["src/loaders/*"], - "@hooks/*": ["src/hooks/*"], - "@utils/*": ["src/utils/*"], - "@pages/*": ["src/pages/*"], - "@api/*": ["src/api/*"], - "@lib/*": ["src/lib/*"], - "@icons/*": ["src/icons/*"], - "@images/*": ["src/images/*"], - "@i18n": ["src/i18n/index"], - "@logger": ["src/logger/index"], - "@apps": ["src/apps/apps"], - "@apps/*": ["src/apps/*"], - "@network/*": ["src/network/*"], - "@schema": ["src/schema"], + "@components/*": ["./src/components/*"], + "@layouts/*": ["./src/layouts/*"], + "@contexts/*": ["./src/contexts/*"], + "@loaders/*": ["./src/loaders/*"], + "@hooks/*": ["./src/hooks/*"], + "@utils/*": ["./src/utils/*"], + "@pages/*": ["./src/pages/*"], + "@api/*": ["./src/api/*"], + "@lib/*": ["./src/lib/*"], + "@icons/*": ["./src/icons/*"], + "@images/*": ["./src/images/*"], + "@i18n": ["./src/i18n/index"], + "@logger": ["./src/logger/index"], + "@apps": ["./src/apps/apps"], + "@apps/*": ["./src/apps/*"], + "@network/*": ["./src/network/*"], + "@schema": ["./src/schema"], } }, "include": [ diff --git a/tsconfig.node.json b/tsconfig.node.json index 97ede7e..2b2f61d 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -7,5 +7,6 @@ "allowSyntheticDefaultImports": true, "strict": true }, - "include": ["vite.config.ts"] + "include": ["vite.config.ts"], + "exclude": ["dist", "node_modules"], } diff --git a/wagmi.config.ts b/wagmi.config.ts new file mode 100644 index 0000000..590beb8 --- /dev/null +++ b/wagmi.config.ts @@ -0,0 +1,798 @@ +import { defineConfig } from '@wagmi/cli'; +import { react } from '@wagmi/cli/plugins'; +import { erc20Abi } from 'viem'; + +export default defineConfig({ + out: 'src/api/contracts/subsquid.generated.ts', + contracts: [ + { + name: 'SQD', + abi: erc20Abi, + }, + { + name: 'Router', + abi: [ + { + type: 'function', + name: 'networkController', + inputs: [], + outputs: [ + { + name: '', + type: 'address', + internalType: 'contract INetworkController', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'rewardCalculation', + inputs: [], + outputs: [ + { + name: '', + type: 'address', + internalType: 'contract IRewardCalculation', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'rewardTreasury', + inputs: [], + outputs: [ + { + name: '', + type: 'address', + internalType: 'address', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'staking', + inputs: [], + outputs: [ + { + name: '', + type: 'address', + internalType: 'contract IStaking', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'workerRegistration', + inputs: [], + outputs: [ + { + name: '', + type: 'address', + internalType: 'contract IWorkerRegistration', + }, + ], + stateMutability: 'view', + }, + ], + }, + { + name: 'WorkerRegistry', + abi: [ + { + type: 'function', + name: 'bondAmount', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'register', + inputs: [ + { + name: 'peerId', + type: 'bytes', + internalType: 'bytes', + }, + { + name: 'metadata', + type: 'string', + internalType: 'string', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'updateMetadata', + inputs: [ + { + name: 'peerId', + type: 'bytes', + internalType: 'bytes', + }, + { + name: 'metadata', + type: 'string', + internalType: 'string', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + inputs: [ + { + internalType: 'bytes', + name: 'peerId', + type: 'bytes', + }, + ], + name: 'deregister', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + + { + type: 'function', + name: 'withdraw', + inputs: [ + { + name: 'peerId', + type: 'bytes', + internalType: 'bytes', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + ], + }, + { + name: 'Staking', + abi: [ + { + type: 'function', + name: 'deposit', + inputs: [ + { + name: 'worker', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'amount', + type: 'uint256', + internalType: 'uint256', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'withdraw', + inputs: [ + { + type: 'uint256', + name: 'worker', + }, + { + type: 'uint256', + name: 'amount', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'claimable', + inputs: [ + { + name: 'staker', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'delegated', + inputs: [ + { + name: 'worker', + type: 'uint256', + internalType: 'uint256', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + ], + }, + { + name: 'Vesting', + abi: [ + { + type: 'function', + name: 'depositedIntoProtocol', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'duration', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'end', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'execute', + inputs: [ + { + name: 'to', + type: 'address', + internalType: 'address', + }, + { + name: 'data', + type: 'bytes', + internalType: 'bytes', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'execute', + inputs: [ + { + name: 'to', + type: 'address', + internalType: 'address', + }, + { + name: 'data', + type: 'bytes', + internalType: 'bytes', + }, + { + name: 'requiredApprove', + type: 'uint256', + internalType: 'uint256', + }, + ], + outputs: [ + { + name: '', + type: 'bytes', + internalType: 'bytes', + }, + ], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'expectedTotalAmount', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'immediateReleaseBIP', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'releasable', + inputs: [ + { + name: 'token', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'releasable', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'release', + inputs: [ + { + name: 'token', + type: 'address', + internalType: 'address', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'released', + inputs: [ + { + name: 'token', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'start', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'vestedAmount', + inputs: [ + { + name: 'token', + type: 'address', + internalType: 'address', + }, + { + name: 'timestamp', + type: 'uint64', + internalType: 'uint64', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + ], + }, + { + name: 'GatewayRegistry', + abi: [ + { + type: 'function', + name: 'register', + inputs: [ + { + name: 'peerId', + type: 'bytes', + internalType: 'bytes', + }, + { + name: 'metadata', + type: 'string', + internalType: 'string', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'setMetadata', + inputs: [ + { + name: 'peerId', + type: 'bytes', + internalType: 'bytes', + }, + { + name: 'metadata', + type: 'string', + internalType: 'string', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'stake', + inputs: [ + { + name: 'amount', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'durationBlocks', + type: 'uint128', + internalType: 'uint128', + }, + { + name: 'withAutoExtension', + type: 'bool', + internalType: 'bool', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'unregister', + inputs: [ + { + name: 'peerId', + type: 'bytes', + internalType: 'bytes', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'unstake', + inputs: [], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'computationUnitsAmount', + inputs: [ + { + name: 'amount', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'durationBlocks', + type: 'uint256', + internalType: 'uint256', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'addStake', + inputs: [ + { + name: 'amount', + type: 'uint256', + internalType: 'uint256', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'disableAutoExtension', + inputs: [], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'enableAutoExtension', + inputs: [], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'canUnstake', + inputs: [ + { + name: 'operator', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: '', + type: 'bool', + internalType: 'bool', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'computationUnitsAmount', + inputs: [ + { + name: 'amount', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'durationBlocks', + type: 'uint256', + internalType: 'uint256', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'getStake', + inputs: [ + { + name: 'operator', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: '', + type: 'tuple', + internalType: 'struct IGatewayRegistry.Stake', + components: [ + { + name: 'amount', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'lockStart', + type: 'uint128', + internalType: 'uint128', + }, + { + name: 'lockEnd', + type: 'uint128', + internalType: 'uint128', + }, + { + name: 'duration', + type: 'uint128', + internalType: 'uint128', + }, + { + name: 'autoExtension', + type: 'bool', + internalType: 'bool', + }, + { + name: 'oldCUs', + type: 'uint256', + internalType: 'uint256', + }, + ], + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'minStake', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + ], + }, + { + name: 'RewardTreasury', + abi: [ + { + type: 'function', + name: 'claimFor', + inputs: [ + { + name: 'rewardDistribution', + type: 'address', + internalType: 'contract IRewardsDistribution', + }, + { + name: 'receiver', + type: 'address', + internalType: 'address', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + ], + }, + { + name: 'SoftCap', + abi: [ + { + type: 'function', + name: 'cap', + inputs: [{ name: 'x', type: 'uint256', internalType: 'UD60x18' }], + outputs: [{ name: '', type: 'uint256', internalType: 'UD60x18' }], + stateMutability: 'pure', + }, + { + type: 'function', + name: 'capedStake', + inputs: [{ name: 'workerId', type: 'uint256', internalType: 'uint256' }], + outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + name: 'capedStakeAfterDelegation', + inputs: [ + { name: 'workerId', type: 'uint256', internalType: 'uint256' }, + { name: 'delegationAmount', type: 'int256', internalType: 'int256' }, + ], + outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }], + stateMutability: 'view', + }, + ], + }, + { + name: 'NetworkController', + abi: [ + { + type: 'function', + name: 'bondAmount', + inputs: [], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'epochLength', + inputs: [], + outputs: [ + { + name: '', + type: 'uint128', + internalType: 'uint128', + }, + ], + stateMutability: 'view', + }, + { + type: 'function', + name: 'workerEpochLength', + inputs: [], + outputs: [ + { + name: '', + type: 'uint128', + internalType: 'uint128', + }, + ], + stateMutability: 'view', + }, + ], + }, + ], + plugins: [react({})], +}); diff --git a/yarn.lock b/yarn.lock index e189a65..3f592d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,10 +12,10 @@ __metadata: languageName: node linkType: hard -"@adraffy/ens-normalize@npm:1.10.0": - version: 1.10.0 - resolution: "@adraffy/ens-normalize@npm:1.10.0" - checksum: 10c0/78ae700847a2516d5a0ae12c4e23d09392a40c67e73b137eb7189f51afb1601c8d18784aeda2ed288a278997824dc924d1f398852c21d41ee2c4c564f2fb4d26 +"@adraffy/ens-normalize@npm:1.11.0": + version: 1.11.0 + resolution: "@adraffy/ens-normalize@npm:1.11.0" + checksum: 10c0/5111d0f1a273468cb5661ed3cf46ee58de8f32f84e2ebc2365652e66c1ead82649df94c736804e2b9cfa831d30ef24e1cc3575d970dbda583416d3a98d8870a6 languageName: node linkType: hard @@ -1148,6 +1148,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/aix-ppc64@npm:0.19.12" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/aix-ppc64@npm:0.21.5" @@ -1155,6 +1162,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/android-arm64@npm:0.19.12" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/android-arm64@npm:0.21.5" @@ -1162,6 +1176,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/android-arm@npm:0.19.12" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/android-arm@npm:0.21.5" @@ -1169,6 +1190,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/android-x64@npm:0.19.12" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/android-x64@npm:0.21.5" @@ -1176,6 +1204,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/darwin-arm64@npm:0.19.12" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/darwin-arm64@npm:0.21.5" @@ -1183,6 +1218,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/darwin-x64@npm:0.19.12" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/darwin-x64@npm:0.21.5" @@ -1190,6 +1232,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/freebsd-arm64@npm:0.19.12" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/freebsd-arm64@npm:0.21.5" @@ -1197,6 +1246,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/freebsd-x64@npm:0.19.12" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/freebsd-x64@npm:0.21.5" @@ -1204,6 +1260,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-arm64@npm:0.19.12" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-arm64@npm:0.21.5" @@ -1211,6 +1274,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-arm@npm:0.19.12" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-arm@npm:0.21.5" @@ -1218,6 +1288,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-ia32@npm:0.19.12" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-ia32@npm:0.21.5" @@ -1225,6 +1302,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-loong64@npm:0.19.12" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-loong64@npm:0.21.5" @@ -1232,6 +1316,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-mips64el@npm:0.19.12" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-mips64el@npm:0.21.5" @@ -1239,6 +1330,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-ppc64@npm:0.19.12" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-ppc64@npm:0.21.5" @@ -1246,6 +1344,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-riscv64@npm:0.19.12" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-riscv64@npm:0.21.5" @@ -1253,6 +1358,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-s390x@npm:0.19.12" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-s390x@npm:0.21.5" @@ -1260,6 +1372,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/linux-x64@npm:0.19.12" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-x64@npm:0.21.5" @@ -1267,6 +1386,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/netbsd-x64@npm:0.19.12" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/netbsd-x64@npm:0.21.5" @@ -1274,6 +1400,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/openbsd-x64@npm:0.19.12" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/openbsd-x64@npm:0.21.5" @@ -1281,6 +1414,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/sunos-x64@npm:0.19.12" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/sunos-x64@npm:0.21.5" @@ -1288,6 +1428,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/win32-arm64@npm:0.19.12" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/win32-arm64@npm:0.21.5" @@ -1295,6 +1442,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/win32-ia32@npm:0.19.12" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/win32-ia32@npm:0.21.5" @@ -1302,6 +1456,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.19.12": + version: 0.19.12 + resolution: "@esbuild/win32-x64@npm:0.19.12" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/win32-x64@npm:0.21.5" @@ -2378,7 +2539,7 @@ __metadata: languageName: node linkType: hard -"@metamask/json-rpc-engine@npm:^7.0.0, @metamask/json-rpc-engine@npm:^7.3.2": +"@metamask/json-rpc-engine@npm:^7.0.0": version: 7.3.3 resolution: "@metamask/json-rpc-engine@npm:7.3.3" dependencies: @@ -2389,15 +2550,26 @@ __metadata: languageName: node linkType: hard -"@metamask/json-rpc-middleware-stream@npm:^6.0.2": - version: 6.0.2 - resolution: "@metamask/json-rpc-middleware-stream@npm:6.0.2" +"@metamask/json-rpc-engine@npm:^8.0.1, @metamask/json-rpc-engine@npm:^8.0.2": + version: 8.0.2 + resolution: "@metamask/json-rpc-engine@npm:8.0.2" dependencies: - "@metamask/json-rpc-engine": "npm:^7.3.2" + "@metamask/rpc-errors": "npm:^6.2.1" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.3.0" + checksum: 10c0/57a584e713be98837b56b1985fc14020b74939af200c304e9dcde0a59b622f0d4b1fd07a9032dd3652b72ce330e47db8b9aa13402a443ad8c09667a4204c4c17 + languageName: node + linkType: hard + +"@metamask/json-rpc-middleware-stream@npm:^7.0.1": + version: 7.0.2 + resolution: "@metamask/json-rpc-middleware-stream@npm:7.0.2" + dependencies: + "@metamask/json-rpc-engine": "npm:^8.0.2" "@metamask/safe-event-emitter": "npm:^3.0.0" "@metamask/utils": "npm:^8.3.0" readable-stream: "npm:^3.6.2" - checksum: 10c0/a91b8d834253a1700d96cf0f08d2362e2db58365f751cb3e60b3c5e9422a1f443a8a515d5a653ced59535726717d0f827c1aaf2a33dd33efb96a05f653bb0915 + checksum: 10c0/5819e5cd1460046d309218110a76727d5b5b7b0fb379efd2e938e145905a359c2b6d4278d390760227ad5823e3f4bcaa001cbb5abeeeb014b08badbb1fa29f1f languageName: node linkType: hard @@ -2420,15 +2592,15 @@ __metadata: languageName: node linkType: hard -"@metamask/providers@npm:^15.0.0": - version: 15.0.0 - resolution: "@metamask/providers@npm:15.0.0" +"@metamask/providers@npm:16.1.0": + version: 16.1.0 + resolution: "@metamask/providers@npm:16.1.0" dependencies: - "@metamask/json-rpc-engine": "npm:^7.3.2" - "@metamask/json-rpc-middleware-stream": "npm:^6.0.2" + "@metamask/json-rpc-engine": "npm:^8.0.1" + "@metamask/json-rpc-middleware-stream": "npm:^7.0.1" "@metamask/object-multiplex": "npm:^2.0.0" "@metamask/rpc-errors": "npm:^6.2.1" - "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/safe-event-emitter": "npm:^3.1.1" "@metamask/utils": "npm:^8.3.0" detect-browser: "npm:^5.2.0" extension-port-stream: "npm:^3.0.0" @@ -2436,7 +2608,7 @@ __metadata: is-stream: "npm:^2.0.0" readable-stream: "npm:^3.6.2" webextension-polyfill: "npm:^0.10.0" - checksum: 10c0/c079cb8440f7cbd8ba863070a8c5c1ada4ad99e31694ec7b0c537b1cb11e66f9d4271e737633ce89f98248208ba076bfc90ddab94ce0299178fdab9a8489fb09 + checksum: 10c0/ef0fe2cad0db6e2fd1c0b73894419e4dc153e1742e8b16e233164eaec941ef3d4859728e4a2e733e818b56093abd889fc96c7a75dccf9878cbdab45fd3b36e2c languageName: node linkType: hard @@ -2457,16 +2629,16 @@ __metadata: languageName: node linkType: hard -"@metamask/safe-event-emitter@npm:^3.0.0": +"@metamask/safe-event-emitter@npm:^3.0.0, @metamask/safe-event-emitter@npm:^3.1.1": version: 3.1.1 resolution: "@metamask/safe-event-emitter@npm:3.1.1" checksum: 10c0/4dd51651fa69adf65952449b20410acac7edad06f176dc6f0a5d449207527a2e85d5a21a864566e3d8446fb259f8840bd69fdb65932007a882f771f473a2b682 languageName: node linkType: hard -"@metamask/sdk-communication-layer@npm:0.26.4": - version: 0.26.4 - resolution: "@metamask/sdk-communication-layer@npm:0.26.4" +"@metamask/sdk-communication-layer@npm:0.28.2": + version: 0.28.2 + resolution: "@metamask/sdk-communication-layer@npm:0.28.2" dependencies: bufferutil: "npm:^4.0.8" date-fns: "npm:^2.29.3" @@ -2479,17 +2651,17 @@ __metadata: eventemitter2: ^6.4.7 readable-stream: ^3.6.2 socket.io-client: ^4.5.1 - checksum: 10c0/01f9704942f6751ba03819117ba611dae3712310bdf54fed1637a526d5fd972fc6fe097be27a5ed4b657a8dea8e497861ce81efa1879000d10696c787e8356e2 + checksum: 10c0/7d51316eb313bd4464e8e5d787c4d88228e40673414883a693f5772908cb5c17903db0d3101bc04ee9db218728525a0ad3a8545c6e7d933b48f3ae6ce8a474bc languageName: node linkType: hard -"@metamask/sdk-install-modal-web@npm:0.26.4": - version: 0.26.4 - resolution: "@metamask/sdk-install-modal-web@npm:0.26.4" +"@metamask/sdk-install-modal-web@npm:0.28.1": + version: 0.28.1 + resolution: "@metamask/sdk-install-modal-web@npm:0.28.1" dependencies: qr-code-styling: "npm:^1.6.0-rc.1" peerDependencies: - i18next: 23.2.3 + i18next: 23.11.5 react: ^18.2.0 react-dom: ^18.2.0 react-native: "*" @@ -2500,19 +2672,20 @@ __metadata: optional: true react-native: optional: true - checksum: 10c0/2bd87481e2630e739d19cfd211e5c68ebe7bd24ee4760764381ef93e4127afb5d6d4ca51b539c424c3bd2368dfe421daf86d689e1462b09c84509d0042968e45 + checksum: 10c0/e7bc9789d6499ff1f2ec2587b0604c4df445bc35e0914165289348fe9325ccff60ef094b5ebe39310af9c68ee8d6d71ed0a6a217e2d3947a2aa92a4c7063e4a1 languageName: node linkType: hard -"@metamask/sdk@npm:0.26.4": - version: 0.26.4 - resolution: "@metamask/sdk@npm:0.26.4" +"@metamask/sdk@npm:0.28.4": + version: 0.28.4 + resolution: "@metamask/sdk@npm:0.28.4" dependencies: "@metamask/onboarding": "npm:^1.0.1" - "@metamask/providers": "npm:^15.0.0" - "@metamask/sdk-communication-layer": "npm:0.26.4" - "@metamask/sdk-install-modal-web": "npm:0.26.4" + "@metamask/providers": "npm:16.1.0" + "@metamask/sdk-communication-layer": "npm:0.28.2" + "@metamask/sdk-install-modal-web": "npm:0.28.1" "@types/dom-screen-wake-lock": "npm:^1.0.0" + "@types/uuid": "npm:^10.0.0" bowser: "npm:^2.9.0" cross-fetch: "npm:^4.0.0" debug: "npm:^4.3.4" @@ -2538,7 +2711,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 10c0/74c671a1dae8f148ad6917f06c01a4d8f57ad9f4be911a7f9f0101be42871efa65a7836779e380a25644a4489a78bda54f68021d2e6066e09dcf08cfd57187f8 + checksum: 10c0/734045ba59e01baf9d5e87cfe85eeb44433e497ac845810f43361ce821260d6a2d89e34a2fe17a877a0f659b137767475fadf3ed23bc4562ad03220817c6df4c languageName: node linkType: hard @@ -2878,15 +3051,6 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:1.2.0, @noble/curves@npm:~1.2.0": - version: 1.2.0 - resolution: "@noble/curves@npm:1.2.0" - dependencies: - "@noble/hashes": "npm:1.3.2" - checksum: 10c0/0bac7d1bbfb3c2286910b02598addd33243cb97c3f36f987ecc927a4be8d7d88e0fcb12b0f0ef8a044e7307d1844dd5c49bb724bfa0a79c8ec50ba60768c97f6 - languageName: node - linkType: hard - "@noble/curves@npm:1.3.0, @noble/curves@npm:~1.3.0": version: 1.3.0 resolution: "@noble/curves@npm:1.3.0" @@ -2896,30 +3060,30 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:1.4.0, @noble/curves@npm:~1.4.0": - version: 1.4.0 - resolution: "@noble/curves@npm:1.4.0" +"@noble/curves@npm:1.6.0, @noble/curves@npm:^1.4.0, @noble/curves@npm:~1.6.0": + version: 1.6.0 + resolution: "@noble/curves@npm:1.6.0" dependencies: - "@noble/hashes": "npm:1.4.0" - checksum: 10c0/31fbc370df91bcc5a920ca3f2ce69c8cf26dc94775a36124ed8a5a3faf0453badafd2ee4337061ffea1b43c623a90ee8b286a5a81604aaf9563bdad7ff795d18 + "@noble/hashes": "npm:1.5.0" + checksum: 10c0/f3262aa4d39148e627cd82b5ac1c93f88c5bb46dd2566b5e8e52ffac3a0fc381ad30c2111656fd2bd3b0d37d43d540543e0d93a5ff96a6cb184bc3bfe10d1cd9 languageName: node linkType: hard -"@noble/hashes@npm:1.3.2": - version: 1.3.2 - resolution: "@noble/hashes@npm:1.3.2" - checksum: 10c0/2482cce3bce6a596626f94ca296e21378e7a5d4c09597cbc46e65ffacc3d64c8df73111f2265444e36a3168208628258bbbaccba2ef24f65f58b2417638a20e7 - languageName: node - linkType: hard - -"@noble/hashes@npm:1.3.3, @noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2": +"@noble/hashes@npm:1.3.3, @noble/hashes@npm:~1.3.2": version: 1.3.3 resolution: "@noble/hashes@npm:1.3.3" checksum: 10c0/23c020b33da4172c988e44100e33cd9f8f6250b68b43c467d3551f82070ebd9716e0d9d2347427aa3774c85934a35fa9ee6f026fca2117e3fa12db7bedae7668 languageName: node linkType: hard -"@noble/hashes@npm:1.4.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:~1.4.0": +"@noble/hashes@npm:1.5.0, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:~1.5.0": + version: 1.5.0 + resolution: "@noble/hashes@npm:1.5.0" + checksum: 10c0/1b46539695fbfe4477c0822d90c881a04d4fa2921c08c552375b444a48cac9930cb1ee68de0a3c7859e676554d0f3771999716606dc4d8f826e414c11692cdd9 + languageName: node + linkType: hard + +"@noble/hashes@npm:^1.3.1": version: 1.4.0 resolution: "@noble/hashes@npm:1.4.0" checksum: 10c0/8c3f005ee72e7b8f9cff756dfae1241485187254e3f743873e22073d63906863df5d4f13d441b7530ea614b7a093f0d889309f28b59850f33b66cb26a779a4a5 @@ -3331,23 +3495,23 @@ __metadata: languageName: node linkType: hard -"@safe-global/safe-apps-provider@npm:0.18.1": - version: 0.18.1 - resolution: "@safe-global/safe-apps-provider@npm:0.18.1" +"@safe-global/safe-apps-provider@npm:0.18.3": + version: 0.18.3 + resolution: "@safe-global/safe-apps-provider@npm:0.18.3" dependencies: - "@safe-global/safe-apps-sdk": "npm:^8.1.0" + "@safe-global/safe-apps-sdk": "npm:^9.1.0" events: "npm:^3.3.0" - checksum: 10c0/9e6375132930cedd0935baa83cd026eb7c76776c7285edb3ff8c463ccf48d1e30cea03e93ce7199d3d3efa3cd035495e5f85fc361e203a2c03a4459d1989e726 + checksum: 10c0/7209d761919969c0859e8b9df90fd46d06c3f99424ecd5fd2e0b8080355a880504ee5c46cebcbaa94739f8be272f3f7102a9f40cf18e6c1a9e1d7dd29d77ee5e languageName: node linkType: hard -"@safe-global/safe-apps-sdk@npm:8.1.0, @safe-global/safe-apps-sdk@npm:^8.1.0": - version: 8.1.0 - resolution: "@safe-global/safe-apps-sdk@npm:8.1.0" +"@safe-global/safe-apps-sdk@npm:9.1.0, @safe-global/safe-apps-sdk@npm:^9.1.0": + version: 9.1.0 + resolution: "@safe-global/safe-apps-sdk@npm:9.1.0" dependencies: "@safe-global/safe-gateway-typescript-sdk": "npm:^3.5.3" - viem: "npm:^1.0.0" - checksum: 10c0/b6ad0610ed39a1106ecaa91e43e411dd361c8d4d9712cb3fbf15342950b86fe387ce331bd91ae35c90ff036cded188272ea45ca4e3534c2b08e7e3d3c741fdc0 + viem: "npm:^2.1.1" + checksum: 10c0/13af12122a6b1388e7960a76c3c421ea5ed97197646cd1f720b9fc9364fad0cc8f21cda23773130cd6bf57935a36f9e93f5222569cc80382709430b5cad26fda languageName: node linkType: hard @@ -3365,28 +3529,10 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2": - version: 1.1.5 - resolution: "@scure/base@npm:1.1.5" - checksum: 10c0/6eb07be0202fac74a57c79d0d00a45f6f7e57447010c1e3d90a4275d197829727b7abc54b248fc6f9bef9ae374f7be5ee9154dde5b5b73da773560bf17aa8504 - languageName: node - linkType: hard - -"@scure/base@npm:~1.1.6": - version: 1.1.7 - resolution: "@scure/base@npm:1.1.7" - checksum: 10c0/2d06aaf39e6de4b9640eb40d2e5419176ebfe911597856dcbf3bc6209277ddb83f4b4b02cb1fd1208f819654268ec083da68111d3530bbde07bae913e2fc2e5d - languageName: node - linkType: hard - -"@scure/bip32@npm:1.3.2": - version: 1.3.2 - resolution: "@scure/bip32@npm:1.3.2" - dependencies: - "@noble/curves": "npm:~1.2.0" - "@noble/hashes": "npm:~1.3.2" - "@scure/base": "npm:~1.1.2" - checksum: 10c0/2e9c1ce67f72b6c3329483f5fd39fb43ba6dcf732ed7ac63b80fa96341d2bc4cad1ea4c75bfeb91e801968c00df48b577b015fd4591f581e93f0d91178e630ca +"@scure/base@npm:~1.1.7, @scure/base@npm:~1.1.8": + version: 1.1.9 + resolution: "@scure/base@npm:1.1.9" + checksum: 10c0/77a06b9a2db8144d22d9bf198338893d77367c51b58c72b99df990c0a11f7cadd066d4102abb15e3ca6798d1529e3765f55c4355742465e49aed7a0c01fe76e8 languageName: node linkType: hard @@ -3401,24 +3547,14 @@ __metadata: languageName: node linkType: hard -"@scure/bip32@npm:1.4.0": - version: 1.4.0 - resolution: "@scure/bip32@npm:1.4.0" - dependencies: - "@noble/curves": "npm:~1.4.0" - "@noble/hashes": "npm:~1.4.0" - "@scure/base": "npm:~1.1.6" - checksum: 10c0/6849690d49a3bf1d0ffde9452eb16ab83478c1bc0da7b914f873e2930cd5acf972ee81320e3df1963eb247cf57e76d2d975b5f97093d37c0e3f7326581bf41bd - languageName: node - linkType: hard - -"@scure/bip39@npm:1.2.1": - version: 1.2.1 - resolution: "@scure/bip39@npm:1.2.1" +"@scure/bip32@npm:1.5.0": + version: 1.5.0 + resolution: "@scure/bip32@npm:1.5.0" dependencies: - "@noble/hashes": "npm:~1.3.0" - "@scure/base": "npm:~1.1.0" - checksum: 10c0/fe951f69dd5a7cdcefbe865bce1b160d6b59ba19bd01d09f0718e54fce37a7d8be158b32f5455f0e9c426a7fbbede3e019bf0baa99bacc88ef26a76a07e115d4 + "@noble/curves": "npm:~1.6.0" + "@noble/hashes": "npm:~1.5.0" + "@scure/base": "npm:~1.1.7" + checksum: 10c0/3319beda59e7f129d770cbe49709a2d1742f2deb6989b12e37aa1a47cd128a8c943bdd9286c6a5513ef4539307c4bca8f89f9aa91f294cac4598cbf95fa0c01d languageName: node linkType: hard @@ -3432,13 +3568,13 @@ __metadata: languageName: node linkType: hard -"@scure/bip39@npm:1.3.0": - version: 1.3.0 - resolution: "@scure/bip39@npm:1.3.0" +"@scure/bip39@npm:1.4.0": + version: 1.4.0 + resolution: "@scure/bip39@npm:1.4.0" dependencies: - "@noble/hashes": "npm:~1.4.0" - "@scure/base": "npm:~1.1.6" - checksum: 10c0/1ae1545a7384a4d9e33e12d9e9f8824f29b0279eb175b0f0657c0a782c217920054f9a1d28eb316a417dfc6c4e0b700d6fbdc6da160670107426d52fcbe017a8 + "@noble/hashes": "npm:~1.5.0" + "@scure/base": "npm:~1.1.8" + checksum: 10c0/dcdceeac348ed9c0f545c1a7ef8854ef62d6eb4e7b7aaafa4e2ef27f7e1c5744b0cd26292afd04e1ee59ae035b19abdd65174a444b8db8c238ccc662f6b90eac languageName: node linkType: hard @@ -3772,6 +3908,7 @@ __metadata: "@typescript-eslint/eslint-plugin": "npm:^7.14.1" "@typescript-eslint/parser": "npm:^7.14.1" "@vitejs/plugin-react": "npm:^4.3.1" + "@wagmi/cli": "npm:^2.1.16" axios: "npm:^1.7.2" base58-universal: "npm:^2.0.0" bignumber.js: "npm:^9.1.2" @@ -3797,28 +3934,28 @@ __metadata: lint-staged: "npm:^15.2.7" lodash-es: "npm:^4.17.21" material-ui-popup-state: "npm:^5.1.2" - notistack: "npm:^3.0.1" prettier: "npm:^3.3.2" pretty-bytes: "npm:^6.1.1" qs: "npm:^6.12.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" + react-hot-toast: "npm:^2.4.1" react-router-dom: "npm:^6.24.0" react-scroll: "npm:^1.9.0" react-syntax-highlighter: "npm:^15.5.0" recharts: "npm:^2.12.7" semver: "npm:^7.6.3" - type-fest: "npm:^4.20.1" - typescript: "npm:^5.5.2" + type-fest: "npm:^4.26.1" + typescript: "npm:^5.6.3" use-debounce: "npm:^10.0.1" use-element-position: "npm:^1.0.13" use-local-storage-state: "npm:^19.3.1" - viem: "npm:^2.16.5" + viem: "npm:^2.21.25" vite: "npm:^5.4.2" vite-plugin-html: "npm:^3.2.2" vite-plugin-html-env: "npm:^1.2.8" vite-tsconfig-paths: "npm:^4.3.2" - wagmi: "npm:^2.9.2" + wagmi: "npm:^2.12.17" yup: "npm:^1.4.0" languageName: unknown linkType: soft @@ -4227,6 +4364,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "@types/uuid@npm:10.0.0" + checksum: 10c0/9a1404bf287164481cb9b97f6bb638f78f955be57c40c6513b7655160beb29df6f84c915aaf4089a1559c216557dc4d2f79b48d978742d3ae10b937420ddac60 + languageName: node + linkType: hard + "@types/ws@npm:^8.0.0": version: 8.5.10 resolution: "@types/ws@npm:8.5.10" @@ -4499,34 +4643,69 @@ __metadata: languageName: node linkType: hard -"@wagmi/connectors@npm:5.0.21": - version: 5.0.21 - resolution: "@wagmi/connectors@npm:5.0.21" +"@wagmi/cli@npm:^2.1.16": + version: 2.1.16 + resolution: "@wagmi/cli@npm:2.1.16" + dependencies: + abitype: "npm:^1.0.4" + bundle-require: "npm:^4.0.2" + cac: "npm:^6.7.14" + change-case: "npm:^5.4.4" + chokidar: "npm:^3.5.3" + dedent: "npm:^0.7.0" + dotenv: "npm:^16.3.1" + dotenv-expand: "npm:^10.0.0" + esbuild: "npm:^0.19.0" + execa: "npm:^8.0.1" + fdir: "npm:^6.1.1" + find-up: "npm:^6.3.0" + fs-extra: "npm:^11.2.0" + ora: "npm:^6.3.1" + pathe: "npm:^1.1.2" + picocolors: "npm:^1.0.0" + picomatch: "npm:^3.0.0" + prettier: "npm:^3.0.3" + viem: "npm:2.x" + zod: "npm:^3.22.2" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + bin: + wagmi: dist/esm/cli.js + checksum: 10c0/289fc520d8403c5d0fd51e7dfab934365770d32f9a9ce58a3e25a4cbfe09948c5109d674fe8bb2c8d36fc5737c2a590f3f5d5f907ac5715316111e839107f6d4 + languageName: node + linkType: hard + +"@wagmi/connectors@npm:5.1.15": + version: 5.1.15 + resolution: "@wagmi/connectors@npm:5.1.15" dependencies: "@coinbase/wallet-sdk": "npm:4.0.4" - "@metamask/sdk": "npm:0.26.4" - "@safe-global/safe-apps-provider": "npm:0.18.1" - "@safe-global/safe-apps-sdk": "npm:8.1.0" - "@walletconnect/ethereum-provider": "npm:2.13.0" - "@walletconnect/modal": "npm:2.6.2" + "@metamask/sdk": "npm:0.28.4" + "@safe-global/safe-apps-provider": "npm:0.18.3" + "@safe-global/safe-apps-sdk": "npm:9.1.0" + "@walletconnect/ethereum-provider": "npm:2.17.0" + "@walletconnect/modal": "npm:2.7.0" cbw-sdk: "npm:@coinbase/wallet-sdk@3.9.3" peerDependencies: - "@wagmi/core": 2.11.6 + "@wagmi/core": 2.13.8 typescript: ">=5.0.4" viem: 2.x peerDependenciesMeta: typescript: optional: true - checksum: 10c0/9530d5f35be860526fdf86acfded4fbc7b8b9cc929182828452d3c1d518363b8d0942c3cc6e9088b44fa3832a2606551fb2bb888b2aced45629b97a4f27946ad + checksum: 10c0/99b282618772aaf5321875e89b4dd8e03c0a2de47a6c4faa52704b3fcd6bfcba2548504b79424cd96cc939b41df20c521241f402d6b3021f6858618aad057b0f languageName: node linkType: hard -"@wagmi/core@npm:2.11.6": - version: 2.11.6 - resolution: "@wagmi/core@npm:2.11.6" +"@wagmi/core@npm:2.13.8": + version: 2.13.8 + resolution: "@wagmi/core@npm:2.13.8" dependencies: eventemitter3: "npm:5.0.1" - mipd: "npm:0.0.5" + mipd: "npm:0.0.7" zustand: "npm:4.4.1" peerDependencies: "@tanstack/query-core": ">=5.0.0" @@ -4537,13 +4716,13 @@ __metadata: optional: true typescript: optional: true - checksum: 10c0/a19145915d55cac4c51a119fb762c8d01e14d910f642bb45f9c30ea6d575773acb70f2abd8d9e24e6eff881d7f3515b93eb758a87b6a9f6d8b9c608d5b1a388e + checksum: 10c0/20adc34fd2e400ae977745a6c9ca11f1fc35c022ee806b52997c3de510734835dec002fe4c0f8f916cdffc199eea7f301c3ee0e7d131e38969afbd357a32e6fa languageName: node linkType: hard -"@walletconnect/core@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/core@npm:2.13.0" +"@walletconnect/core@npm:2.17.0": + version: 2.17.0 + resolution: "@walletconnect/core@npm:2.17.0" dependencies: "@walletconnect/heartbeat": "npm:1.2.2" "@walletconnect/jsonrpc-provider": "npm:1.0.14" @@ -4552,17 +4731,16 @@ __metadata: "@walletconnect/jsonrpc-ws-connection": "npm:1.0.14" "@walletconnect/keyvaluestorage": "npm:1.1.1" "@walletconnect/logger": "npm:2.1.2" - "@walletconnect/relay-api": "npm:1.0.10" + "@walletconnect/relay-api": "npm:1.0.11" "@walletconnect/relay-auth": "npm:1.0.4" "@walletconnect/safe-json": "npm:1.0.2" "@walletconnect/time": "npm:1.0.2" - "@walletconnect/types": "npm:2.13.0" - "@walletconnect/utils": "npm:2.13.0" + "@walletconnect/types": "npm:2.17.0" + "@walletconnect/utils": "npm:2.17.0" events: "npm:3.3.0" - isomorphic-unfetch: "npm:3.1.0" lodash.isequal: "npm:4.5.0" uint8arrays: "npm:3.1.0" - checksum: 10c0/e1356eb8ac94f8f6743814337607244557280d43a6e2ec14591beb21dca0e73cc79b16f0a2ace60ef447149778c5383a1fd4eac67788372d249c8c5f6d8c7dc2 + checksum: 10c0/34ae5b9b68c08c1dd3ebb2a6ebff8697307e76fbfe4d6b51d5d090da5cd1613e1c66fa5ac3a87c914333458d7b5bf075bb664292f6b2c7d438c72f706d87416d languageName: node linkType: hard @@ -4575,21 +4753,21 @@ __metadata: languageName: node linkType: hard -"@walletconnect/ethereum-provider@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/ethereum-provider@npm:2.13.0" +"@walletconnect/ethereum-provider@npm:2.17.0": + version: 2.17.0 + resolution: "@walletconnect/ethereum-provider@npm:2.17.0" dependencies: "@walletconnect/jsonrpc-http-connection": "npm:1.0.8" "@walletconnect/jsonrpc-provider": "npm:1.0.14" "@walletconnect/jsonrpc-types": "npm:1.0.4" "@walletconnect/jsonrpc-utils": "npm:1.0.8" - "@walletconnect/modal": "npm:2.6.2" - "@walletconnect/sign-client": "npm:2.13.0" - "@walletconnect/types": "npm:2.13.0" - "@walletconnect/universal-provider": "npm:2.13.0" - "@walletconnect/utils": "npm:2.13.0" + "@walletconnect/modal": "npm:2.7.0" + "@walletconnect/sign-client": "npm:2.17.0" + "@walletconnect/types": "npm:2.17.0" + "@walletconnect/universal-provider": "npm:2.17.0" + "@walletconnect/utils": "npm:2.17.0" events: "npm:3.3.0" - checksum: 10c0/4bc3c76b7a9e81ac505fcff99244bfa9f14419ee2de322e491dacd94669923adf5e9e1a2298ae84b33e3d5985a0bfab6b7715237e6f2ce23ec02c67dedb58898 + checksum: 10c0/b046a9c296e95b22841f0b2efd28a4ce1a38529a9ba412d3c8ffc482879d79c3d2a24b8c0ec712baecf781938b4321ab5c1ecad5573d078add7c47b0cfd08a25 languageName: node linkType: hard @@ -4706,43 +4884,43 @@ __metadata: languageName: node linkType: hard -"@walletconnect/modal-core@npm:2.6.2": - version: 2.6.2 - resolution: "@walletconnect/modal-core@npm:2.6.2" +"@walletconnect/modal-core@npm:2.7.0": + version: 2.7.0 + resolution: "@walletconnect/modal-core@npm:2.7.0" dependencies: valtio: "npm:1.11.2" - checksum: 10c0/5e3fb21a1fc923ec0d2a3e33cc360e3d56278a211609d5fd4cc4d6e3b4f1acb40b9783fcc771b259b78c7e731af3862def096aa1da2e210e7859729808304c94 + checksum: 10c0/84b11735c005e37e661aa0f08b2e8c8098db3b2cacd957c4a73f4d3de11b2d5e04dd97ab970f8d22fc3e8269fea3297b9487e177343bbab8dd69b3b917fb7f60 languageName: node linkType: hard -"@walletconnect/modal-ui@npm:2.6.2": - version: 2.6.2 - resolution: "@walletconnect/modal-ui@npm:2.6.2" +"@walletconnect/modal-ui@npm:2.7.0": + version: 2.7.0 + resolution: "@walletconnect/modal-ui@npm:2.7.0" dependencies: - "@walletconnect/modal-core": "npm:2.6.2" + "@walletconnect/modal-core": "npm:2.7.0" lit: "npm:2.8.0" motion: "npm:10.16.2" qrcode: "npm:1.5.3" - checksum: 10c0/5d8f0a2703b9757dfa48ad3e48a40e64608f6a28db31ec93a2f10e942dcc5ee986c03ffdab94018e905836d339131fc928bc14614a94943011868cdddc36a32a + checksum: 10c0/b717f1fc9854b7d14a4364720fce2d44167f547533340704644ed2fdf9d861b3798ffd19a3b51062a366a8bc39f84b9a8bb3dd04e9e33da742192359be00b051 languageName: node linkType: hard -"@walletconnect/modal@npm:2.6.2": - version: 2.6.2 - resolution: "@walletconnect/modal@npm:2.6.2" +"@walletconnect/modal@npm:2.7.0": + version: 2.7.0 + resolution: "@walletconnect/modal@npm:2.7.0" dependencies: - "@walletconnect/modal-core": "npm:2.6.2" - "@walletconnect/modal-ui": "npm:2.6.2" - checksum: 10c0/1cc309f63d061e49fdf7b10d28093d7ef1a47f4624f717f8fd3bf6097ac3b00cea4acc45c50e8bd386d4bcfdf10f4dcba960f7129c557b9dc42ef7d05b970807 + "@walletconnect/modal-core": "npm:2.7.0" + "@walletconnect/modal-ui": "npm:2.7.0" + checksum: 10c0/2f3074eebbca41a46e29680dc2565bc762133508774f05db0075a82b0b66ecc8defca40a94ad63669676090a7e3ef671804592b10e91636ab1cdeac014a1eb11 languageName: node linkType: hard -"@walletconnect/relay-api@npm:1.0.10": - version: 1.0.10 - resolution: "@walletconnect/relay-api@npm:1.0.10" +"@walletconnect/relay-api@npm:1.0.11": + version: 1.0.11 + resolution: "@walletconnect/relay-api@npm:1.0.11" dependencies: "@walletconnect/jsonrpc-types": "npm:^1.0.2" - checksum: 10c0/2709bbe45f60579cd2e1c74b0fd03c36ea409cd8a9117e00a7485428d0c9ba7eb02e525c21e5286db2b6ce563b1d29053b0249c2ed95f8adcf02b11e54f61fcd + checksum: 10c0/2595d7e68d3a93e7735e0b6204811762898b0ce1466e811d78be5bcec7ac1cde5381637615a99104099165bf63695da5ef9381d6ded29924a57a71b10712a91d languageName: node linkType: hard @@ -4769,20 +4947,20 @@ __metadata: languageName: node linkType: hard -"@walletconnect/sign-client@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/sign-client@npm:2.13.0" +"@walletconnect/sign-client@npm:2.17.0": + version: 2.17.0 + resolution: "@walletconnect/sign-client@npm:2.17.0" dependencies: - "@walletconnect/core": "npm:2.13.0" + "@walletconnect/core": "npm:2.17.0" "@walletconnect/events": "npm:1.0.1" "@walletconnect/heartbeat": "npm:1.2.2" "@walletconnect/jsonrpc-utils": "npm:1.0.8" "@walletconnect/logger": "npm:2.1.2" "@walletconnect/time": "npm:1.0.2" - "@walletconnect/types": "npm:2.13.0" - "@walletconnect/utils": "npm:2.13.0" + "@walletconnect/types": "npm:2.17.0" + "@walletconnect/utils": "npm:2.17.0" events: "npm:3.3.0" - checksum: 10c0/58c702997f719cab9b183d23c53efee561a3a407de24e464e339e350124a71eeccb1bd651f0893ad0f39343ce42a7ff3666bbd28cb8dfc6a0e8d12c94eacc288 + checksum: 10c0/48f7d13b3db49584a40dc2653f49fabadd100a324e2213476b8d9e4d6fe0808a08ae14103d2e5b609abff3115197003d8570d606275dbd0f6774d0d49da10c61 languageName: node linkType: hard @@ -4795,9 +4973,9 @@ __metadata: languageName: node linkType: hard -"@walletconnect/types@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/types@npm:2.13.0" +"@walletconnect/types@npm:2.17.0": + version: 2.17.0 + resolution: "@walletconnect/types@npm:2.17.0" dependencies: "@walletconnect/events": "npm:1.0.1" "@walletconnect/heartbeat": "npm:1.2.2" @@ -4805,46 +4983,48 @@ __metadata: "@walletconnect/keyvaluestorage": "npm:1.1.1" "@walletconnect/logger": "npm:2.1.2" events: "npm:3.3.0" - checksum: 10c0/9962284daf92d6b27a009b90b908518b3f028f10f2168ddbc37ad2cb2b20cb0e65d170aa4343e2ea445c519cf79e78264480e2b2c4ab9f974f2c15962db5b012 + checksum: 10c0/bdc0c062da1edb4410882d9cfca1bb30eb0afd7caea90d5e7a66eaf15e28380e9ef97635cd5e5a017947f4c814c1f780622b4d8946b11a335d415ae066ec7ade languageName: node linkType: hard -"@walletconnect/universal-provider@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/universal-provider@npm:2.13.0" +"@walletconnect/universal-provider@npm:2.17.0": + version: 2.17.0 + resolution: "@walletconnect/universal-provider@npm:2.17.0" dependencies: "@walletconnect/jsonrpc-http-connection": "npm:1.0.8" "@walletconnect/jsonrpc-provider": "npm:1.0.14" "@walletconnect/jsonrpc-types": "npm:1.0.4" "@walletconnect/jsonrpc-utils": "npm:1.0.8" "@walletconnect/logger": "npm:2.1.2" - "@walletconnect/sign-client": "npm:2.13.0" - "@walletconnect/types": "npm:2.13.0" - "@walletconnect/utils": "npm:2.13.0" + "@walletconnect/sign-client": "npm:2.17.0" + "@walletconnect/types": "npm:2.17.0" + "@walletconnect/utils": "npm:2.17.0" events: "npm:3.3.0" - checksum: 10c0/79d14cdce74054859f26f69a17215c59367d961d0f36e7868601ed98030bd0636b3806dd68b76cc66ec4a70d5f6ec107fbe18bb6a1022a5161ea6d71810a0ed9 + checksum: 10c0/7c1afc79054db5add4e937d7adaadb4fc26aecffb5d749d388418fa5d4eb153807ab4de301b642cd80669b4e5c6bcae917f18cf5ce8696d87da8b3705b60d1ec languageName: node linkType: hard -"@walletconnect/utils@npm:2.13.0": - version: 2.13.0 - resolution: "@walletconnect/utils@npm:2.13.0" +"@walletconnect/utils@npm:2.17.0": + version: 2.17.0 + resolution: "@walletconnect/utils@npm:2.17.0" dependencies: "@stablelib/chacha20poly1305": "npm:1.0.1" "@stablelib/hkdf": "npm:1.0.1" "@stablelib/random": "npm:1.0.2" "@stablelib/sha256": "npm:1.0.1" "@stablelib/x25519": "npm:1.0.3" - "@walletconnect/relay-api": "npm:1.0.10" + "@walletconnect/relay-api": "npm:1.0.11" + "@walletconnect/relay-auth": "npm:1.0.4" "@walletconnect/safe-json": "npm:1.0.2" "@walletconnect/time": "npm:1.0.2" - "@walletconnect/types": "npm:2.13.0" + "@walletconnect/types": "npm:2.17.0" "@walletconnect/window-getters": "npm:1.0.1" "@walletconnect/window-metadata": "npm:1.0.1" detect-browser: "npm:5.3.0" + elliptic: "npm:^6.5.7" query-string: "npm:7.1.3" uint8arrays: "npm:3.1.0" - checksum: 10c0/2dbdb9ed790492411eb5c4e6b06aa511f6c0204c4ff283ecb5a4d339bb1bf3da033ef3a0c0af66b94df0553676f408222c2feca8c601b0554be2bbfbef43d6ec + checksum: 10c0/d1da74b2cd7af35f16d735fe408cfc820c611b2709bd00899e4e91b0b0a6dcd8f344f97df34d0ef8cabc121619a40b62118ffa2aa233ddba9863d1ba23480a0c languageName: node linkType: hard @@ -4937,24 +5117,9 @@ __metadata: languageName: node linkType: hard -"abitype@npm:0.9.8": - version: 0.9.8 - resolution: "abitype@npm:0.9.8" - peerDependencies: - typescript: ">=5.0.4" - zod: ^3 >=3.19.1 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - checksum: 10c0/ec559461d901d456820faf307e21b2c129583d44f4c68257ed9d0d44eae461114a7049046e715e069bc6fa70c410f644e06bdd2c798ac30d0ada794cd2a6c51e - languageName: node - linkType: hard - -"abitype@npm:1.0.5": - version: 1.0.5 - resolution: "abitype@npm:1.0.5" +"abitype@npm:1.0.6, abitype@npm:^1.0.4": + version: 1.0.6 + resolution: "abitype@npm:1.0.6" peerDependencies: typescript: ">=5.0.4" zod: ^3 >=3.22.0 @@ -4963,7 +5128,7 @@ __metadata: optional: true zod: optional: true - checksum: 10c0/dc954877fba19e2b7a70f1025807d69fa5aabec8bd58ce94e68d1a5ec1697fff3fe5214b4392508db7191762150f19a2396cf66ffb1d3ba8c1f37a89fd25e598 + checksum: 10c0/30ca97010bbf34b9aaed401858eeb6bc30419f7ff11eb34adcb243522dd56c9d8a9d3d406aa5d4f60a7c263902f5136043005698e3f073ea882a4922d43a2929 languageName: node linkType: hard @@ -5451,6 +5616,17 @@ __metadata: languageName: node linkType: hard +"bl@npm:^5.0.0": + version: 5.1.0 + resolution: "bl@npm:5.1.0" + dependencies: + buffer: "npm:^6.0.3" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.4.0" + checksum: 10c0/528a9c3d7d6b87af98c46f10a887654d027c28c503c7f7de87440e643f0056d7a2319a967762b8ec18150c64799d2825a277147a752a0570a7407c0b705b0d01 + languageName: node + linkType: hard + "bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" @@ -5592,6 +5768,17 @@ __metadata: languageName: node linkType: hard +"bundle-require@npm:^4.0.2": + version: 4.2.1 + resolution: "bundle-require@npm:4.2.1" + dependencies: + load-tsconfig: "npm:^0.2.3" + peerDependencies: + esbuild: ">=0.17" + checksum: 10c0/f458ce39f8dd23f900f1877f475f36aa502ecf888cc97cfa2b8d1e9178d091a0d4c09f07afff001aae8b805ba6a94ca71bbbd9efe08b0e03c870bd61e8c00cb3 + languageName: node + linkType: hard + "busboy@npm:^1.6.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" @@ -5601,6 +5788,13 @@ __metadata: languageName: node linkType: hard +"cac@npm:^6.7.14": + version: 6.7.14 + resolution: "cac@npm:6.7.14" + checksum: 10c0/4ee06aaa7bab8981f0d54e5f5f9d4adcd64058e9697563ce336d8a3878ed018ee18ebe5359b2430eceae87e0758e62ea2019c3f52ae6e211b1bd2e133856cd10 + languageName: node + linkType: hard + "cacache@npm:^18.0.0": version: 18.0.2 resolution: "cacache@npm:18.0.2" @@ -5714,7 +5908,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:~5.3.0": +"chalk@npm:^5.0.0, chalk@npm:~5.3.0": version: 5.3.0 resolution: "chalk@npm:5.3.0" checksum: 10c0/8297d436b2c0f95801103ff2ef67268d362021b8210daf8ddbe349695333eb3610a71122172ff3b0272f1ef2cf7cc2c41fdaa4715f52e49ffe04c56340feed09 @@ -5777,6 +5971,13 @@ __metadata: languageName: node linkType: hard +"change-case@npm:^5.4.4": + version: 5.4.4 + resolution: "change-case@npm:5.4.4" + checksum: 10c0/2a9c2b9c9ad6ab2491105aaf506db1a9acaf543a18967798dcce20926c6a173aa63266cb6189f3086e3c14bf7ae1f8ea4f96ecc466fcd582310efa00372f3734 + languageName: node + linkType: hard + "character-entities-legacy@npm:^1.0.0": version: 1.1.4 resolution: "character-entities-legacy@npm:1.1.4" @@ -5805,7 +6006,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.6.0": +"chokidar@npm:^3.5.3, chokidar@npm:^3.6.0": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -5888,7 +6089,7 @@ __metadata: languageName: node linkType: hard -"cli-spinners@npm:^2.5.0": +"cli-spinners@npm:^2.5.0, cli-spinners@npm:^2.6.1": version: 2.9.2 resolution: "cli-spinners@npm:2.9.2" checksum: 10c0/907a1c227ddf0d7a101e7ab8b300affc742ead4b4ebe920a5bf1bc6d45dce2958fcd195eb28fa25275062fe6fa9b109b93b63bc8033396ed3bcb50297008b3a3 @@ -5969,7 +6170,7 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.1.0, clsx@npm:^1.2.1": +"clsx@npm:^1.2.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" checksum: 10c0/34dead8bee24f5e96f6e7937d711978380647e936a22e76380290e35486afd8634966ce300fc4b74a32f3762c7d4c0303f442c3e259f4ce02374eb0c82834f27 @@ -6475,6 +6676,13 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^0.7.0": + version: 0.7.0 + resolution: "dedent@npm:0.7.0" + checksum: 10c0/7c3aa00ddfe3e5fcd477958e156156a5137e3bb6ff1493ca05edff4decf29a90a057974cc77e75951f8eb801c1816cb45aea1f52d628cdd000b82b36ab839d1b + languageName: node + linkType: hard + "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -6698,6 +6906,13 @@ __metadata: languageName: node linkType: hard +"dotenv-expand@npm:^10.0.0": + version: 10.0.0 + resolution: "dotenv-expand@npm:10.0.0" + checksum: 10c0/298f5018e29cfdcb0b5f463ba8e8627749103fbcf6cf81c561119115754ed582deee37b49dfc7253028aaba875ab7aea5fa90e5dac88e511d009ab0e6677924e + languageName: node + linkType: hard + "dotenv-expand@npm:^8.0.2": version: 8.0.3 resolution: "dotenv-expand@npm:8.0.3" @@ -6705,7 +6920,7 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^16.0.0, dotenv@npm:^16.4.5": +"dotenv@npm:^16.0.0, dotenv@npm:^16.3.1, dotenv@npm:^16.4.5": version: 16.4.5 resolution: "dotenv@npm:16.4.5" checksum: 10c0/48d92870076832af0418b13acd6e5a5a3e83bb00df690d9812e94b24aff62b88ade955ac99a05501305b8dc8f1b0ee7638b18493deb6fe93d680e5220936292f @@ -6782,6 +6997,21 @@ __metadata: languageName: node linkType: hard +"elliptic@npm:^6.5.7": + version: 6.5.7 + resolution: "elliptic@npm:6.5.7" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/799959b6c54ea3564e8961f35abdf8c77e37617f3051614b05ab1fb6a04ddb65bd1caa75ed1bae375b15dda312a0f79fed26ebe76ecf05c5a7af244152a601b8 + languageName: node + linkType: hard + "emoji-regex@npm:^10.3.0": version: 10.3.0 resolution: "emoji-regex@npm:10.3.0" @@ -7064,6 +7294,86 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.19.0": + version: 0.19.12 + resolution: "esbuild@npm:0.19.12" + dependencies: + "@esbuild/aix-ppc64": "npm:0.19.12" + "@esbuild/android-arm": "npm:0.19.12" + "@esbuild/android-arm64": "npm:0.19.12" + "@esbuild/android-x64": "npm:0.19.12" + "@esbuild/darwin-arm64": "npm:0.19.12" + "@esbuild/darwin-x64": "npm:0.19.12" + "@esbuild/freebsd-arm64": "npm:0.19.12" + "@esbuild/freebsd-x64": "npm:0.19.12" + "@esbuild/linux-arm": "npm:0.19.12" + "@esbuild/linux-arm64": "npm:0.19.12" + "@esbuild/linux-ia32": "npm:0.19.12" + "@esbuild/linux-loong64": "npm:0.19.12" + "@esbuild/linux-mips64el": "npm:0.19.12" + "@esbuild/linux-ppc64": "npm:0.19.12" + "@esbuild/linux-riscv64": "npm:0.19.12" + "@esbuild/linux-s390x": "npm:0.19.12" + "@esbuild/linux-x64": "npm:0.19.12" + "@esbuild/netbsd-x64": "npm:0.19.12" + "@esbuild/openbsd-x64": "npm:0.19.12" + "@esbuild/sunos-x64": "npm:0.19.12" + "@esbuild/win32-arm64": "npm:0.19.12" + "@esbuild/win32-ia32": "npm:0.19.12" + "@esbuild/win32-x64": "npm:0.19.12" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/0f2d21ffe24ebead64843f87c3aebe2e703a5ed9feb086a0728b24907fac2eb9923e4a79857d3df9059c915739bd7a870dd667972eae325c67f478b592b8582d + languageName: node + linkType: hard + "esbuild@npm:^0.21.3": version: 0.21.5 resolution: "esbuild@npm:0.21.5" @@ -7803,6 +8113,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.1.1": + version: 6.4.0 + resolution: "fdir@npm:6.4.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/9a03efa1335d78ea386b701799b08ad9e7e8da85d88567dc162cd28dd8e9486e8c269b3e95bfeb21dd6a5b14ebf69d230eb6e18f49d33fbda3cd97432f648c48 + languageName: node + linkType: hard + "figures@npm:^3.0.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -7889,6 +8211,16 @@ __metadata: languageName: node linkType: hard +"find-up@npm:^6.3.0": + version: 6.3.0 + resolution: "find-up@npm:6.3.0" + dependencies: + locate-path: "npm:^7.1.0" + path-exists: "npm:^5.0.0" + checksum: 10c0/07e0314362d316b2b13f7f11ea4692d5191e718ca3f7264110127520f3347996349bf9e16805abae3e196805814bc66ef4bff2b8904dc4a6476085fc9b0eba07 + languageName: node + linkType: hard + "flat-cache@npm:^3.0.4": version: 3.2.0 resolution: "flat-cache@npm:3.2.0" @@ -7983,6 +8315,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^11.2.0": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/d77a9a9efe60532d2e790e938c81a02c1b24904ef7a3efb3990b835514465ba720e99a6ea56fd5e2db53b4695319b644d76d5a0e9988a2beef80aa7b1da63398 + languageName: node + linkType: hard + "fs-minipass@npm:^2.0.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -8219,12 +8562,12 @@ __metadata: languageName: node linkType: hard -"goober@npm:^2.0.33": - version: 2.1.14 - resolution: "goober@npm:2.1.14" +"goober@npm:^2.1.10": + version: 2.1.16 + resolution: "goober@npm:2.1.16" peerDependencies: csstype: ^3.0.10 - checksum: 10c0/184eda787a9a14cffbaa8284e98dc127095e538b4acab2a84b81babca84253bb883e16208822e02584f27c7a69f3ec47341e5060dfa40a0e07c32ac1f79b2714 + checksum: 10c0/f4c8256bf9c27873d47c1443f348779ac7f322516cb80a5dc647a6ebe790ce6bb9d3f487a0fb8be0b583fb96b9b2f6b7463f7fea3cd680306f95fa6fc9db1f6a languageName: node linkType: hard @@ -8963,6 +9306,13 @@ __metadata: languageName: node linkType: hard +"is-interactive@npm:^2.0.0": + version: 2.0.0 + resolution: "is-interactive@npm:2.0.0" + checksum: 10c0/801c8f6064f85199dc6bf99b5dd98db3282e930c3bc197b32f2c5b89313bb578a07d1b8a01365c4348c2927229234f3681eb861b9c2c92bee72ff397390fa600 + languageName: node + linkType: hard + "is-lambda@npm:^1.0.1": version: 1.0.1 resolution: "is-lambda@npm:1.0.1" @@ -9108,6 +9458,13 @@ __metadata: languageName: node linkType: hard +"is-unicode-supported@npm:^1.1.0": + version: 1.3.0 + resolution: "is-unicode-supported@npm:1.3.0" + checksum: 10c0/b8674ea95d869f6faabddc6a484767207058b91aea0250803cbf1221345cb0c56f466d4ecea375dc77f6633d248d33c47bd296fb8f4cdba0b4edba8917e83d8a + languageName: node + linkType: hard + "is-upper-case@npm:^2.0.2": version: 2.0.2 resolution: "is-upper-case@npm:2.0.2" @@ -9205,16 +9562,6 @@ __metadata: languageName: node linkType: hard -"isomorphic-unfetch@npm:3.1.0": - version: 3.1.0 - resolution: "isomorphic-unfetch@npm:3.1.0" - dependencies: - node-fetch: "npm:^2.6.1" - unfetch: "npm:^4.2.0" - checksum: 10c0/d3b61fca06304db692b7f76bdfd3a00f410e42cfa7403c3b250546bf71589d18cf2f355922f57198e4cc4a9872d3647b20397a5c3edf1a347c90d57c83cf2a89 - languageName: node - linkType: hard - "isomorphic-ws@npm:^5.0.0": version: 5.0.0 resolution: "isomorphic-ws@npm:5.0.0" @@ -9224,21 +9571,12 @@ __metadata: languageName: node linkType: hard -"isows@npm:1.0.3": - version: 1.0.3 - resolution: "isows@npm:1.0.3" - peerDependencies: - ws: "*" - checksum: 10c0/adec15db704bb66615dd8ef33f889d41ae2a70866b21fa629855da98cc82a628ae072ee221fe9779a9a19866cad2a3e72593f2d161a0ce0e168b4484c7df9cd2 - languageName: node - linkType: hard - -"isows@npm:1.0.4": - version: 1.0.4 - resolution: "isows@npm:1.0.4" +"isows@npm:1.0.6": + version: 1.0.6 + resolution: "isows@npm:1.0.6" peerDependencies: ws: "*" - checksum: 10c0/46f43b07edcf148acba735ddfc6ed985e1e124446043ea32b71023e67671e46619c8818eda8c34a9ac91cb37c475af12a3aeeee676a88a0aceb5d67a3082313f + checksum: 10c0/f89338f63ce2f497d6cd0f86e42c634209328ebb43b3bdfdc85d8f1589ee75f02b7e6d9e1ba274101d0f6f513b1b8cbe6985e6542b4aaa1f0c5fd50d9c1be95c languageName: node linkType: hard @@ -9696,6 +10034,13 @@ __metadata: languageName: node linkType: hard +"load-tsconfig@npm:^0.2.3": + version: 0.2.5 + resolution: "load-tsconfig@npm:0.2.5" + checksum: 10c0/bf2823dd26389d3497b6567f07435c5a7a58d9df82e879b0b3892f87d8db26900f84c85bc329ef41c0540c0d6a448d1c23ddc64a80f3ff6838b940f3915a3fcb + languageName: node + linkType: hard + "localforage@npm:^1.8.1": version: 1.10.0 resolution: "localforage@npm:1.10.0" @@ -9723,6 +10068,15 @@ __metadata: languageName: node linkType: hard +"locate-path@npm:^7.1.0": + version: 7.2.0 + resolution: "locate-path@npm:7.2.0" + dependencies: + p-locate: "npm:^6.0.0" + checksum: 10c0/139e8a7fe11cfbd7f20db03923cacfa5db9e14fa14887ea121345597472b4a63c1a42a8a5187defeeff6acf98fd568da7382aa39682d38f0af27433953a97751 + languageName: node + linkType: hard + "lodash-es@npm:^4.17.21": version: 4.17.21 resolution: "lodash-es@npm:4.17.21" @@ -9775,6 +10129,16 @@ __metadata: languageName: node linkType: hard +"log-symbols@npm:^5.1.0": + version: 5.1.0 + resolution: "log-symbols@npm:5.1.0" + dependencies: + chalk: "npm:^5.0.0" + is-unicode-supported: "npm:^1.1.0" + checksum: 10c0/c14f8567c6618a7f96209c4c4b9fb3b794187116904712f7b526e465a5c9535728aec983735a5bef919247d0e54b9b72b6680a7fb9fc72d76b945dac4865e669 + languageName: node + linkType: hard + "log-update@npm:^4.0.0": version: 4.0.0 resolution: "log-update@npm:4.0.0" @@ -10164,17 +10528,15 @@ __metadata: languageName: node linkType: hard -"mipd@npm:0.0.5": - version: 0.0.5 - resolution: "mipd@npm:0.0.5" - dependencies: - viem: "npm:^1.1.4" +"mipd@npm:0.0.7": + version: 0.0.7 + resolution: "mipd@npm:0.0.7" peerDependencies: typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/6b0a82cdc9eec5c12132b46422799cf536b1062b307a6aa0ce57ef240c56bd2dd231a5eda367c8a8962cbff73dd1af6131b8d769e3b47a06f0fc9d148b56f3dd + checksum: 10c0/c536e4fcdc15793b4538f72da389f8901a7eccb2e1eb55d8878f234a45f1c271064650e76fa2967b94743e19cc32ceab3c7b1e0dc614e28a45b0bbd6c987795d languageName: node linkType: hard @@ -10432,19 +10794,6 @@ __metadata: languageName: node linkType: hard -"notistack@npm:^3.0.1": - version: 3.0.1 - resolution: "notistack@npm:3.0.1" - dependencies: - clsx: "npm:^1.1.0" - goober: "npm:^2.0.33" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 10c0/dd5bd492dbaf8d07a1f45a53ae195c5d481bc7136d73a756eb076534d315216a3cd2f4628263be55ad21d8bfed6ec546e5063584ffcc2798fb2aac56e5ccf0cf - languageName: node - linkType: hard - "npm-run-path@npm:^5.1.0": version: 5.3.0 resolution: "npm-run-path@npm:5.3.0" @@ -10664,6 +11013,23 @@ __metadata: languageName: node linkType: hard +"ora@npm:^6.3.1": + version: 6.3.1 + resolution: "ora@npm:6.3.1" + dependencies: + chalk: "npm:^5.0.0" + cli-cursor: "npm:^4.0.0" + cli-spinners: "npm:^2.6.1" + is-interactive: "npm:^2.0.0" + is-unicode-supported: "npm:^1.1.0" + log-symbols: "npm:^5.1.0" + stdin-discarder: "npm:^0.1.0" + strip-ansi: "npm:^7.0.1" + wcwidth: "npm:^1.0.1" + checksum: 10c0/f8753e234c9967c86cfb73e7396e1a51ed8771c4921d539af8e8962b32c7928cefef7b3c4ce730a504be72b1437f91cc0523f468927b9fe322498c4edcc50203 + languageName: node + linkType: hard + "os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -10696,6 +11062,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^4.0.0": + version: 4.0.0 + resolution: "p-limit@npm:4.0.0" + dependencies: + yocto-queue: "npm:^1.0.0" + checksum: 10c0/a56af34a77f8df2ff61ddfb29431044557fcbcb7642d5a3233143ebba805fc7306ac1d448de724352861cb99de934bc9ab74f0d16fe6a5460bdbdf938de875ad + languageName: node + linkType: hard + "p-locate@npm:^4.1.0": version: 4.1.0 resolution: "p-locate@npm:4.1.0" @@ -10714,6 +11089,15 @@ __metadata: languageName: node linkType: hard +"p-locate@npm:^6.0.0": + version: 6.0.0 + resolution: "p-locate@npm:6.0.0" + dependencies: + p-limit: "npm:^4.0.0" + checksum: 10c0/d72fa2f41adce59c198270aa4d3c832536c87a1806e0f69dffb7c1a7ca998fb053915ca833d90f166a8c082d3859eabfed95f01698a3214c20df6bb8de046312 + languageName: node + linkType: hard + "p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" @@ -10813,6 +11197,13 @@ __metadata: languageName: node linkType: hard +"path-exists@npm:^5.0.0": + version: 5.0.0 + resolution: "path-exists@npm:5.0.0" + checksum: 10c0/b170f3060b31604cde93eefdb7392b89d832dfbc1bed717c9718cbe0f230c1669b7e75f87e19901da2250b84d092989a0f9e44d2ef41deb09aa3ad28e691a40a + languageName: node + linkType: hard + "path-is-absolute@npm:^1.0.0": version: 1.0.1 resolution: "path-is-absolute@npm:1.0.1" @@ -10909,6 +11300,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^3.0.0": + version: 3.0.1 + resolution: "picomatch@npm:3.0.1" + checksum: 10c0/70ec738569f1864658378b7abdab8939d15dae0718c1df994eae3346fd33daf6a3c1ff4e0c1a0cd1e2c0319130985b63a2cff34d192f2f2acbb78aca76111736 + languageName: node + linkType: hard + "pidtree@npm:~0.6.0": version: 0.6.0 resolution: "pidtree@npm:0.6.0" @@ -11036,6 +11434,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.0.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" + bin: + prettier: bin/prettier.cjs + checksum: 10c0/b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26 + languageName: node + linkType: hard + "prettier@npm:^3.3.2": version: 3.3.2 resolution: "prettier@npm:3.3.2" @@ -11316,6 +11723,18 @@ __metadata: languageName: node linkType: hard +"react-hot-toast@npm:^2.4.1": + version: 2.4.1 + resolution: "react-hot-toast@npm:2.4.1" + dependencies: + goober: "npm:^2.1.10" + peerDependencies: + react: ">=16" + react-dom: ">=16" + checksum: 10c0/591ecec3c6adc1cdb70f00165a57baa3d7f75d0d30fa767213c36496bdcc6be2b2e6a3edbf7c04f7d726a1b17dcfb5e7feb2136b04b17c9ccb769894b970f365 + languageName: node + linkType: hard + "react-is@npm:^16.10.2, react-is@npm:^16.13.1, react-is@npm:^16.7.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" @@ -12393,6 +12812,15 @@ __metadata: languageName: node linkType: hard +"stdin-discarder@npm:^0.1.0": + version: 0.1.0 + resolution: "stdin-discarder@npm:0.1.0" + dependencies: + bl: "npm:^5.0.0" + checksum: 10c0/3bbf7f8107e49c05b4a46bd739afdd34605cf1f06a038c8b2a33d034bf146344fc0ebc5149df1e6422510dd219971a220f25b1102413ef5128fe267683fbef9d + languageName: node + linkType: hard + "stream-shift@npm:^1.0.2": version: 1.0.3 resolution: "stream-shift@npm:1.0.3" @@ -12879,10 +13307,10 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.20.1": - version: 4.20.1 - resolution: "type-fest@npm:4.20.1" - checksum: 10c0/c31da16fe170a74c5b7e102e70e764ba8ec6ade128e782a56f842aefa07307df5a6353e6b5601d3b30ff2d856d8b955f89813df639e4758fedcf8e426b2d854e +"type-fest@npm:^4.26.1": + version: 4.26.1 + resolution: "type-fest@npm:4.26.1" + checksum: 10c0/d2719ff8d380befe8a3c61068f37f28d6fa2849fd140c5d2f0f143099e371da6856aad7c97e56b83329d45bfe504afe9fd936a7cff600cc0d46aa9ffb008d6c6 languageName: node linkType: hard @@ -12952,23 +13380,23 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.5.2": - version: 5.5.2 - resolution: "typescript@npm:5.5.2" +"typescript@npm:^5.6.3": + version: 5.6.3 + resolution: "typescript@npm:5.6.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/8ca39b27b5f9bd7f32db795045933ab5247897660627251e8254180b792a395bf061ea7231947d5d7ffa5cb4cc771970fd4ef543275f9b559f08c9325cccfce3 + checksum: 10c0/44f61d3fb15c35359bc60399cb8127c30bae554cd555b8e2b46d68fa79d680354b83320ad419ff1b81a0bdf324197b29affe6cc28988cd6a74d4ac60c94f9799 languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.5.2#optional!builtin": - version: 5.5.2 - resolution: "typescript@patch:typescript@npm%3A5.5.2#optional!builtin::version=5.5.2&hash=5adc0c" +"typescript@patch:typescript@npm%3A^5.6.3#optional!builtin": + version: 5.6.3 + resolution: "typescript@patch:typescript@npm%3A5.6.3#optional!builtin::version=5.6.3&hash=5adc0c" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/6721ac8933a70c252d7b640b345792e103d881811ff660355617c1836526dbb71c2044e2e77a8823fb3570b469f33276875a4cab6d3c4de4ae7d7ee1c3074ae4 + checksum: 10c0/ac8307bb06bbfd08ae7137da740769b7d8c3ee5943188743bb622c621f8ad61d244767480f90fbd840277fbf152d8932aa20c33f867dea1bb5e79b187ca1a92f languageName: node linkType: hard @@ -13050,13 +13478,6 @@ __metadata: languageName: node linkType: hard -"unfetch@npm:^4.2.0": - version: 4.2.0 - resolution: "unfetch@npm:4.2.0" - checksum: 10c0/a5c0a896a6f09f278b868075aea65652ad185db30e827cb7df45826fe5ab850124bf9c44c4dafca4bf0c55a0844b17031e8243467fcc38dd7a7d435007151f1b - languageName: node - linkType: hard - "unique-filename@npm:^3.0.0": version: 3.0.0 resolution: "unique-filename@npm:3.0.0" @@ -13411,45 +13832,25 @@ __metadata: languageName: node linkType: hard -"viem@npm:^1.0.0, viem@npm:^1.1.4": - version: 1.21.4 - resolution: "viem@npm:1.21.4" - dependencies: - "@adraffy/ens-normalize": "npm:1.10.0" - "@noble/curves": "npm:1.2.0" - "@noble/hashes": "npm:1.3.2" - "@scure/bip32": "npm:1.3.2" - "@scure/bip39": "npm:1.2.1" - abitype: "npm:0.9.8" - isows: "npm:1.0.3" - ws: "npm:8.13.0" - peerDependencies: - typescript: ">=5.0.4" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/8b29c790181e44c4c95b9ffed1a8c1b6c2396eb949b95697cc390ca8c49d88ef9e2cd56bd4800b90a9bbc93681ae8d63045fc6fa06e00d84f532bef77967e751 - languageName: node - linkType: hard - -"viem@npm:^2.10.9": - version: 2.17.0 - resolution: "viem@npm:2.17.0" +"viem@npm:2.x, viem@npm:^2.1.1, viem@npm:^2.21.25": + version: 2.21.25 + resolution: "viem@npm:2.21.25" dependencies: - "@adraffy/ens-normalize": "npm:1.10.0" - "@noble/curves": "npm:1.4.0" - "@noble/hashes": "npm:1.4.0" - "@scure/bip32": "npm:1.4.0" - "@scure/bip39": "npm:1.3.0" - abitype: "npm:1.0.5" - isows: "npm:1.0.4" - ws: "npm:8.17.1" + "@adraffy/ens-normalize": "npm:1.11.0" + "@noble/curves": "npm:1.6.0" + "@noble/hashes": "npm:1.5.0" + "@scure/bip32": "npm:1.5.0" + "@scure/bip39": "npm:1.4.0" + abitype: "npm:1.0.6" + isows: "npm:1.0.6" + webauthn-p256: "npm:0.0.10" + ws: "npm:8.18.0" peerDependencies: typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/c4830eb204b654eb54bafd9c229137871642c40bbd40562bf40eda914a31073bd0f662eb39721e8e6fb8791920f3e463b968b29cc9a5c12e2ed342415f6ff33b + checksum: 10c0/8c9c9e6ed5c16484c7d27b3cfc4ec3ebf90f32a7ddaac2a2cbec417e65ec77470009619dcc3a24bf7284f3ee6d04b274d0da933154758b75edafc95f45223fcb languageName: node linkType: hard @@ -13543,12 +13944,12 @@ __metadata: languageName: node linkType: hard -"wagmi@npm:^2.9.2": - version: 2.10.9 - resolution: "wagmi@npm:2.10.9" +"wagmi@npm:^2.12.17": + version: 2.12.17 + resolution: "wagmi@npm:2.12.17" dependencies: - "@wagmi/connectors": "npm:5.0.21" - "@wagmi/core": "npm:2.11.6" + "@wagmi/connectors": "npm:5.1.15" + "@wagmi/core": "npm:2.13.8" use-sync-external-store: "npm:1.2.0" peerDependencies: "@tanstack/react-query": ">=5.0.0" @@ -13558,7 +13959,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/a7e2d127e9e04b758e76f1c204d4133fd348945787ba16e6d6db8604996e27643b606250056e785d5f6b08be8bf67d3402aa81d0a4b297359a5f0782bf683485 + checksum: 10c0/a64b5fd364c051297ad9efec292be46c7e00f0718f944bc7974f4715b617f762f1c167f6cfb86881c0a51474320aaeef10b230b7722771a7285252fd1bf6e53b languageName: node linkType: hard @@ -13578,6 +13979,16 @@ __metadata: languageName: node linkType: hard +"webauthn-p256@npm:0.0.10": + version: 0.0.10 + resolution: "webauthn-p256@npm:0.0.10" + dependencies: + "@noble/curves": "npm:^1.4.0" + "@noble/hashes": "npm:^1.4.0" + checksum: 10c0/27d836d81a1fec24a31d2d9b652f8ff6876b51940d1003bbd14dc5cfa57c58d84223b5a4eece229516522fd997bc0bc7be618ac42b129fb5fa42fa530060b16d + languageName: node + linkType: hard + "webcrypto-core@npm:^1.7.8": version: 1.7.8 resolution: "webcrypto-core@npm:1.7.8" @@ -13760,24 +14171,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.13.0": - version: 8.13.0 - resolution: "ws@npm:8.13.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/579817dbbab3ee46669129c220cfd81ba6cdb9ab5c3e9a105702dd045743c4ab72e33bb384573827c0c481213417cc880e41bc097e0fc541a0b79fa3eb38207d - languageName: node - linkType: hard - -"ws@npm:8.17.1": - version: 8.17.1 - resolution: "ws@npm:8.17.1" +"ws@npm:8.18.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -13786,7 +14182,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10c0/f4a49064afae4500be772abdc2211c8518f39e1c959640457dcee15d4488628620625c783902a52af2dd02f68558da2868fd06e6fd0e67ebcd09e6881b1b5bfe + checksum: 10c0/25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 languageName: node linkType: hard @@ -13967,6 +14363,13 @@ __metadata: languageName: node linkType: hard +"yocto-queue@npm:^1.0.0": + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: 10c0/cb287fe5e6acfa82690acb43c283de34e945c571a78a939774f6eaba7c285bacdf6c90fbc16ce530060863984c906d2b4c6ceb069c94d1e0a06d5f2b458e2a92 + languageName: node + linkType: hard + "yup@npm:^1.4.0": version: 1.4.0 resolution: "yup@npm:1.4.0" @@ -13979,6 +14382,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.22.2": + version: 3.23.8 + resolution: "zod@npm:3.23.8" + checksum: 10c0/8f14c87d6b1b53c944c25ce7a28616896319d95bc46a9660fe441adc0ed0a81253b02b5abdaeffedbeb23bdd25a0bf1c29d2c12dd919aef6447652dd295e3e69 + languageName: node + linkType: hard + "zustand@npm:4.4.1": version: 4.4.1 resolution: "zustand@npm:4.4.1"