From 825583daba2e53aefcf26c682d5d900d00fb6bf6 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 04:49:17 +0530 Subject: [PATCH 01/26] chore: Update package.json and yarn.lock with zustand dependency --- frontend/package.json | 3 ++- frontend/yarn.lock | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index e040214f6..65830f503 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,7 +14,8 @@ "react-canvas-confetti": "1.2.1", "sass": "^1.72.0", "styled-components": "^6.1.8", - "usehooks-ts": "^2.14.0" + "usehooks-ts": "^2.14.0", + "zustand": "^4.5.2" }, "devDependencies": { "@testing-library/jest-dom": "^6.4.2", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 0f813ba46..0f2d578a7 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -5621,6 +5621,7 @@ string-length@^4.0.1: strip-ansi "^6.0.0" "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + name string-width-cjs version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6019,6 +6020,11 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + usehooks-ts@^2.14.0: version "2.16.0" resolved "https://registry.yarnpkg.com/usehooks-ts/-/usehooks-ts-2.16.0.tgz#31deaa2f1147f65666aae925bd890b54e63b0d3f" @@ -6142,6 +6148,7 @@ word-wrap@^1.2.5: integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + name wrap-ansi-cjs version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -6229,3 +6236,10 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zustand@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.2.tgz#fddbe7cac1e71d45413b3682cdb47b48034c3848" + integrity sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g== + dependencies: + use-sync-external-store "1.2.0" From be4eb877d0af4e05f1dcd65721ec64d2c6a244e0 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 18:53:01 +0530 Subject: [PATCH 02/26] chore: Add StakingValidations component and getStakingContractInfo function --- .../components/Main/StakingValidations.tsx | 14 +++++++ frontend/service/Autonolas.ts | 40 ++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 frontend/components/Main/StakingValidations.tsx diff --git a/frontend/components/Main/StakingValidations.tsx b/frontend/components/Main/StakingValidations.tsx new file mode 100644 index 000000000..a796d3fc4 --- /dev/null +++ b/frontend/components/Main/StakingValidations.tsx @@ -0,0 +1,14 @@ +import { useEffect } from 'react'; + +import { AutonolasService } from '@/service/Autonolas'; + +export const StakingValidations = () => { + useEffect(() => { + const getRewards = async () => { + await AutonolasService.getStakingContractInfo(); + }; + getRewards(); + }, []); + + return null; +}; diff --git a/frontend/service/Autonolas.ts b/frontend/service/Autonolas.ts index 1be76ed44..d12397004 100644 --- a/frontend/service/Autonolas.ts +++ b/frontend/service/Autonolas.ts @@ -1,4 +1,4 @@ -import { ethers } from 'ethers'; +import { BigNumber, ethers } from 'ethers'; import { Contract as MulticallContract } from 'ethers-multicall'; import { @@ -146,6 +146,43 @@ const getAvailableRewardsForEpoch = async (): Promise => { return rewardsPerSecond * livenessPeriod; }; +type StakingContractInfo = { + availableRewards: number; + maxNumServices: number; + getServiceIds: number[]; +}; + +/** + * function to get the staking contract info + */ +const getStakingContractInfo = async (): Promise< + StakingContractInfo | undefined +> => { + const contractCalls = [ + serviceStakingTokenMechUsageContract.availableRewards(), + serviceStakingTokenMechUsageContract.maxNumServices(), + serviceStakingTokenMechUsageContract.getServiceIds(), + ]; + + await gnosisMulticallProvider.init(); + + const multicallResponse = await gnosisMulticallProvider.all(contractCalls); + const [availableRewardsInBN, maxNumServicesInBN, getServiceIdsInBN] = + multicallResponse; + + const availableRewards = parseFloat( + ethers.utils.formatUnits(availableRewardsInBN, 18), + ); + const getServiceIds = getServiceIdsInBN.map((id: BigNumber) => id.toNumber()); + const maxNumServices = maxNumServicesInBN.toNumber(); + + return { + availableRewards, + maxNumServices, + getServiceIds, + }; +}; + const getServiceRegistryInfo = async ( operatorAddress: Address, // generally masterSafeAddress serviceId: number, @@ -188,4 +225,5 @@ export const AutonolasService = { getAgentStakingRewardsInfo, getAvailableRewardsForEpoch, getServiceRegistryInfo, + getStakingContractInfo, }; From cb35f72665faf89a04409b037597ead94b0897f7 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 19:06:12 +0530 Subject: [PATCH 03/26] chore: Update StakingContractInfo type in Autonolas.ts --- frontend/service/Autonolas.ts | 8 +------- frontend/types/Autonolas.ts | 6 ++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/service/Autonolas.ts b/frontend/service/Autonolas.ts index d12397004..65bf9f8eb 100644 --- a/frontend/service/Autonolas.ts +++ b/frontend/service/Autonolas.ts @@ -18,7 +18,7 @@ import { } from '@/constants'; import { gnosisMulticallProvider } from '@/constants/providers'; import { ServiceRegistryL2ServiceState } from '@/enums'; -import { Address, StakingRewardsInfo } from '@/types'; +import { Address, StakingContractInfo, StakingRewardsInfo } from '@/types'; const REQUIRED_MECH_REQUESTS_SAFETY_MARGIN = 1; @@ -146,12 +146,6 @@ const getAvailableRewardsForEpoch = async (): Promise => { return rewardsPerSecond * livenessPeriod; }; -type StakingContractInfo = { - availableRewards: number; - maxNumServices: number; - getServiceIds: number[]; -}; - /** * function to get the staking contract info */ diff --git a/frontend/types/Autonolas.ts b/frontend/types/Autonolas.ts index dfc441581..1eb7c5756 100644 --- a/frontend/types/Autonolas.ts +++ b/frontend/types/Autonolas.ts @@ -9,3 +9,9 @@ export type StakingRewardsInfo = { accruedServiceStakingRewards: number; minimumStakedAmount: number; }; + +export type StakingContractInfo = { + availableRewards: number; + maxNumServices: number; + getServiceIds: number[]; +}; From 788edaecabfe6e263b20b9680fae8efcc06e92a8 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 19:06:37 +0530 Subject: [PATCH 04/26] chore: Add useStakingContractInfo hook for fetching staking contract info --- .../components/store/stackingContractInfo.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 frontend/components/store/stackingContractInfo.ts diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/components/store/stackingContractInfo.ts new file mode 100644 index 000000000..b6225f803 --- /dev/null +++ b/frontend/components/store/stackingContractInfo.ts @@ -0,0 +1,33 @@ +import { create } from 'zustand'; + +import { AutonolasService } from '@/service/Autonolas'; + +export const useStakingContractInfo = create((set) => ({ + // maxNumServices: null, + // availableRewards: null, + // getServiceIds: null, + isStakingContractInfoLoading: false, + isRewardsAvailable: false, + fetchStakingContractInfo: async () => { + try { + set({ isStakingContractInfoLoading: true }); + const info = await AutonolasService.getStakingContractInfo(); + + if (!info) return; + + const { availableRewards, maxNumServices, getServiceIds } = info; + + set({ + // availableRewards, + // maxNumServices, + // getServiceIds, + isRewardsAvailable: availableRewards > 0, + hasEnoughServiceSlots: getServiceIds.length < maxNumServices, + }); + } catch (error) { + console.error('Failed to fetch staking contract info', error); + } finally { + set({ isStakingContractInfoLoading: false }); + } + }, +})); From 93c93e3ff25654fa4a63c0d3c15ddfc0e2cd8e8d Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 19:20:43 +0530 Subject: [PATCH 05/26] chore: Refactor useStakingContractInfo hook and fetchStakingContractInfo function --- .../components/store/stackingContractInfo.ts | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/components/store/stackingContractInfo.ts index b6225f803..bd8efa942 100644 --- a/frontend/components/store/stackingContractInfo.ts +++ b/frontend/components/store/stackingContractInfo.ts @@ -1,14 +1,14 @@ +import { useCallback, useEffect } from 'react'; import { create } from 'zustand'; import { AutonolasService } from '@/service/Autonolas'; -export const useStakingContractInfo = create((set) => ({ - // maxNumServices: null, - // availableRewards: null, - // getServiceIds: null, - isStakingContractInfoLoading: false, - isRewardsAvailable: false, - fetchStakingContractInfo: async () => { +export const useStakingContractInfo = create<{ + isStakingContractInfoLoading: boolean; + isRewardsAvailable: boolean; + hasEnoughServiceSlots: boolean; +}>((set) => { + const fetchStakingContractInfo = useCallback(async () => { try { set({ isStakingContractInfoLoading: true }); const info = await AutonolasService.getStakingContractInfo(); @@ -29,5 +29,18 @@ export const useStakingContractInfo = create((set) => ({ } finally { set({ isStakingContractInfoLoading: false }); } - }, -})); + }, [set]); + + useEffect(() => { + fetchStakingContractInfo(); + }, [fetchStakingContractInfo]); + + return { + // maxNumServices: null, + // availableRewards: null, + // getServiceIds: null, + isStakingContractInfoLoading: true, + isRewardsAvailable: false, + hasEnoughServiceSlots: false, + }; +}); From 9c77e1cba6a7c849c13e5b5826ccb2ea29f5ef49 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 19:34:06 +0530 Subject: [PATCH 06/26] chore: Refactor StakingValidations component and fetchStakingContractInfo function --- .../components/Main/StakingValidations.tsx | 68 +++++++++++++++++-- .../components/store/stackingContractInfo.ts | 61 +++++++++-------- 2 files changed, 94 insertions(+), 35 deletions(-) diff --git a/frontend/components/Main/StakingValidations.tsx b/frontend/components/Main/StakingValidations.tsx index a796d3fc4..aa1c61bac 100644 --- a/frontend/components/Main/StakingValidations.tsx +++ b/frontend/components/Main/StakingValidations.tsx @@ -1,14 +1,70 @@ +import { Flex, Typography } from 'antd'; import { useEffect } from 'react'; -import { AutonolasService } from '@/service/Autonolas'; +import { Alert } from '../common/Alert'; +import { useStakingContractInfo } from '../store/stackingContractInfo'; +import { CardSection } from '../styled/CardSection'; + +const { Text, Paragraph } = Typography; + +const COVER_PREV_BLOCK_BORDER_STYLE = { marginBottom: '-1px' }; export const StakingValidations = () => { + const { + hasEnoughServiceSlots, + isRewardsAvailable, + isStakingContractInfoLoading, + fetchStakingContractInfo, + } = useStakingContractInfo(); + useEffect(() => { - const getRewards = async () => { - await AutonolasService.getStakingContractInfo(); - }; - getRewards(); - }, []); + fetchStakingContractInfo(); + }, [fetchStakingContractInfo]); + + if (isStakingContractInfoLoading) return null; + + if (!isRewardsAvailable) { + return ( + + + No rewards available + + There are no rewards available for staking. + + + } + type="error" + fullWidth + /> + + ); + } + + if (!hasEnoughServiceSlots) { + return ( + + + + Not enough service slots + + + You have reached the maximum number of services allowed for + staking. + + + } + type="error" + fullWidth + /> + + ); + } return null; }; diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/components/store/stackingContractInfo.ts index bd8efa942..a53763862 100644 --- a/frontend/components/store/stackingContractInfo.ts +++ b/frontend/components/store/stackingContractInfo.ts @@ -1,46 +1,49 @@ -import { useCallback, useEffect } from 'react'; import { create } from 'zustand'; import { AutonolasService } from '@/service/Autonolas'; +const initialState = { + isStakingContractInfoLoading: true, + isRewardsAvailable: false, + hasEnoughServiceSlots: false, + maxNumServices: 0, +}; + export const useStakingContractInfo = create<{ isStakingContractInfoLoading: boolean; isRewardsAvailable: boolean; hasEnoughServiceSlots: boolean; + fetchStakingContractInfo: () => Promise; + maxNumServices: number; }>((set) => { - const fetchStakingContractInfo = useCallback(async () => { - try { - set({ isStakingContractInfoLoading: true }); - const info = await AutonolasService.getStakingContractInfo(); - - if (!info) return; - - const { availableRewards, maxNumServices, getServiceIds } = info; - - set({ - // availableRewards, - // maxNumServices, - // getServiceIds, - isRewardsAvailable: availableRewards > 0, - hasEnoughServiceSlots: getServiceIds.length < maxNumServices, - }); - } catch (error) { - console.error('Failed to fetch staking contract info', error); - } finally { - set({ isStakingContractInfoLoading: false }); - } - }, [set]); - - useEffect(() => { - fetchStakingContractInfo(); - }, [fetchStakingContractInfo]); - return { // maxNumServices: null, // availableRewards: null, // getServiceIds: null, + ...initialState, isStakingContractInfoLoading: true, isRewardsAvailable: false, - hasEnoughServiceSlots: false, + fetchStakingContractInfo: async () => { + try { + set({ isStakingContractInfoLoading: true }); + const info = await AutonolasService.getStakingContractInfo(); + + if (!info) return; + + const { availableRewards, maxNumServices, getServiceIds } = info; + + set({ + // availableRewards, + maxNumServices, + // getServiceIds, + isRewardsAvailable: availableRewards > 0, + hasEnoughServiceSlots: getServiceIds.length < maxNumServices, + }); + } catch (error) { + console.error('Failed to fetch staking contract info', error); + } finally { + set({ isStakingContractInfoLoading: false }); + } + }, }; }); From 1cafb91e6f957b74dc3f4a84a66cdb82e765c6cc Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 19:34:21 +0530 Subject: [PATCH 07/26] chore: Add StakingValidations component to Main --- frontend/components/Main/Main.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/components/Main/Main.tsx b/frontend/components/Main/Main.tsx index cfede1da7..b2fc3effb 100644 --- a/frontend/components/Main/Main.tsx +++ b/frontend/components/Main/Main.tsx @@ -12,6 +12,7 @@ import { MainHeader } from './MainHeader'; import { MainNeedsFunds } from './MainNeedsFunds'; import { MainOlasBalance } from './MainOlasBalance'; import { MainRewards } from './MainRewards'; +import { StakingValidations } from './StakingValidations'; export const Main = () => { const { goto } = usePageState(); @@ -40,6 +41,7 @@ export const Main = () => { style={{ borderTopColor: 'transparent' }} > + From df6c489e7788a7ab8494cd4fcaf628090609ab0d Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 19:39:29 +0530 Subject: [PATCH 08/26] feat: Add canStartAgent check to MainHeader component --- frontend/components/Main/MainHeader.tsx | 11 ++++++++++- frontend/components/store/stackingContractInfo.ts | 12 ++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/frontend/components/Main/MainHeader.tsx b/frontend/components/Main/MainHeader.tsx index e222970b6..d24089a3f 100644 --- a/frontend/components/Main/MainHeader.tsx +++ b/frontend/components/Main/MainHeader.tsx @@ -14,6 +14,8 @@ import { useWallet } from '@/hooks/useWallet'; import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; +import { useStakingContractInfo } from '../store/stackingContractInfo'; + const { Text } = Typography; const LOADING_MESSAGE = @@ -38,6 +40,7 @@ export const MainHeader = () => { isBalanceLoaded, setIsPaused: setIsBalancePollingPaused, } = useBalance(); + const { canStartAgent } = useStakingContractInfo(); const safeOlasBalanceWithStaked = useMemo(() => { if (safeBalance?.OLAS === undefined) return; @@ -259,7 +262,12 @@ export const MainHeader = () => { } return ( - ); @@ -273,6 +281,7 @@ export const MainHeader = () => { services, storeState?.isInitialFunded, totalEthBalance, + canStartAgent, ]); return ( diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/components/store/stackingContractInfo.ts index a53763862..955e6977b 100644 --- a/frontend/components/store/stackingContractInfo.ts +++ b/frontend/components/store/stackingContractInfo.ts @@ -6,6 +6,7 @@ const initialState = { isStakingContractInfoLoading: true, isRewardsAvailable: false, hasEnoughServiceSlots: false, + canStartAgent: false, maxNumServices: 0, }; @@ -13,6 +14,7 @@ export const useStakingContractInfo = create<{ isStakingContractInfoLoading: boolean; isRewardsAvailable: boolean; hasEnoughServiceSlots: boolean; + canStartAgent: boolean; fetchStakingContractInfo: () => Promise; maxNumServices: number; }>((set) => { @@ -31,13 +33,15 @@ export const useStakingContractInfo = create<{ if (!info) return; const { availableRewards, maxNumServices, getServiceIds } = info; + const isRewardsAvailable = availableRewards > 0; + const hasEnoughServiceSlots = getServiceIds.length < maxNumServices; + const canStartAgent = isRewardsAvailable && hasEnoughServiceSlots; set({ - // availableRewards, maxNumServices, - // getServiceIds, - isRewardsAvailable: availableRewards > 0, - hasEnoughServiceSlots: getServiceIds.length < maxNumServices, + isRewardsAvailable, + hasEnoughServiceSlots, + canStartAgent, }); } catch (error) { console.error('Failed to fetch staking contract info', error); From 79108c8741966ae523878e0b3587b0dc3dde5153 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 31 May 2024 19:45:47 +0530 Subject: [PATCH 09/26] chore: Remove unused maxNumServices property in useStakingContractInfo hook --- frontend/components/store/stackingContractInfo.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/components/store/stackingContractInfo.ts index 955e6977b..3dcdff63c 100644 --- a/frontend/components/store/stackingContractInfo.ts +++ b/frontend/components/store/stackingContractInfo.ts @@ -7,7 +7,6 @@ const initialState = { isRewardsAvailable: false, hasEnoughServiceSlots: false, canStartAgent: false, - maxNumServices: 0, }; export const useStakingContractInfo = create<{ @@ -16,12 +15,8 @@ export const useStakingContractInfo = create<{ hasEnoughServiceSlots: boolean; canStartAgent: boolean; fetchStakingContractInfo: () => Promise; - maxNumServices: number; }>((set) => { return { - // maxNumServices: null, - // availableRewards: null, - // getServiceIds: null, ...initialState, isStakingContractInfoLoading: true, isRewardsAvailable: false, @@ -38,7 +33,6 @@ export const useStakingContractInfo = create<{ const canStartAgent = isRewardsAvailable && hasEnoughServiceSlots; set({ - maxNumServices, isRewardsAvailable, hasEnoughServiceSlots, canStartAgent, From abb11e2aa267b973268631f53233343c798fcf19 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 7 Jun 2024 00:52:32 +0530 Subject: [PATCH 10/26] feat: Update file paths and imports for MainHeader and StakingValidations --- frontend/components/Main/Main.tsx | 4 +-- .../Main/{ => MainHeader}/MainHeader.tsx | 35 ++++++++++++------- .../{ => MainHeader}/StakingValidations.tsx | 6 ++-- 3 files changed, 28 insertions(+), 17 deletions(-) rename frontend/components/Main/{ => MainHeader}/MainHeader.tsx (96%) rename frontend/components/Main/{ => MainHeader}/StakingValidations.tsx (90%) diff --git a/frontend/components/Main/Main.tsx b/frontend/components/Main/Main.tsx index 089a615a4..af6cc73cc 100644 --- a/frontend/components/Main/Main.tsx +++ b/frontend/components/Main/Main.tsx @@ -8,11 +8,11 @@ import { useBalance, usePageState, useServices } from '@/hooks'; import { KeepAgentRunning } from './KeepAgentRunning'; import { MainAddFunds } from './MainAddFunds'; import { MainGasBalance } from './MainGasBalance'; -import { MainHeader } from './MainHeader'; +import { MainHeader } from './MainHeader/MainHeader'; +import { StakingValidations } from './MainHeader/StakingValidations'; import { MainNeedsFunds } from './MainNeedsFunds'; import { MainOlasBalance } from './MainOlasBalance'; import { MainRewards } from './MainRewards'; -import { StakingValidations } from './StakingValidations'; export const Main = () => { const { goto } = usePageState(); diff --git a/frontend/components/Main/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx similarity index 96% rename from frontend/components/Main/MainHeader.tsx rename to frontend/components/Main/MainHeader/MainHeader.tsx index ed8a9a63c..e755e09fb 100644 --- a/frontend/components/Main/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -15,7 +15,7 @@ import { useWallet } from '@/hooks/useWallet'; import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; -import { useStakingContractInfo } from '../store/stackingContractInfo'; +import { useStakingContractInfo } from '../../store/stackingContractInfo'; const { Text, Title, Paragraph } = Typography; @@ -76,10 +76,28 @@ const FirstRunModal = ({ ); }; +const useSetupTrayIcon = () => { + const { safeBalance } = useBalance(); + const { serviceStatus } = useServices(); + const { setTrayIcon } = useElectronApi(); + + useEffect(() => { + if (safeBalance && safeBalance.ETH < LOW_BALANCE) { + setTrayIcon?.('low-gas'); + } else if (serviceStatus === DeploymentStatus.DEPLOYED) { + setTrayIcon?.('running'); + } else if (serviceStatus === DeploymentStatus.STOPPED) { + setTrayIcon?.('paused'); + } + }, [safeBalance, serviceStatus, setTrayIcon]); + + return null; +}; + export const MainHeader = () => { const { storeState } = useStore(); const { services, serviceStatus, setServiceStatus } = useServices(); - const { showNotification, setTrayIcon } = useElectronApi(); + const { showNotification } = useElectronApi(); const { getServiceTemplates } = useServiceTemplates(); const { wallets, masterSafeAddress } = useWallet(); const { @@ -94,6 +112,9 @@ export const MainHeader = () => { const [isModalOpen, setIsModalOpen] = useState(false); const handleModalClose = useCallback(() => setIsModalOpen(false), []); + // hook to setup tray icon + useSetupTrayIcon(); + const { minimumStakedAmountRequired } = useReward(); const safeOlasBalanceWithStaked = useMemo(() => { @@ -110,16 +131,6 @@ export const MainHeader = () => { [getServiceTemplates], ); - useEffect(() => { - if (safeBalance && safeBalance.ETH < LOW_BALANCE) { - setTrayIcon?.('low-gas'); - } else if (serviceStatus === DeploymentStatus.DEPLOYED) { - setTrayIcon?.('running'); - } else if (serviceStatus === DeploymentStatus.STOPPED) { - setTrayIcon?.('paused'); - } - }, [safeBalance, serviceStatus, setTrayIcon]); - const agentHead = useMemo(() => { if ( serviceButtonState === ServiceButtonLoadingState.Starting || diff --git a/frontend/components/Main/StakingValidations.tsx b/frontend/components/Main/MainHeader/StakingValidations.tsx similarity index 90% rename from frontend/components/Main/StakingValidations.tsx rename to frontend/components/Main/MainHeader/StakingValidations.tsx index aa1c61bac..01a113379 100644 --- a/frontend/components/Main/StakingValidations.tsx +++ b/frontend/components/Main/MainHeader/StakingValidations.tsx @@ -1,9 +1,9 @@ import { Flex, Typography } from 'antd'; import { useEffect } from 'react'; -import { Alert } from '../common/Alert'; -import { useStakingContractInfo } from '../store/stackingContractInfo'; -import { CardSection } from '../styled/CardSection'; +import { Alert } from '../../common/Alert'; +import { useStakingContractInfo } from '../../store/stackingContractInfo'; +import { CardSection } from '../../styled/CardSection'; const { Text, Paragraph } = Typography; From 936fe4a54ce2eb2212ae6836d13f4aeb93637dc2 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 26 Jun 2024 20:43:40 +0530 Subject: [PATCH 11/26] chore: Update StakingContractInfo to use serviceIds instead of getServiceIds --- frontend/components/store/stackingContractInfo.ts | 12 ++++++++---- frontend/service/Autonolas.ts | 4 ++-- frontend/types/Autonolas.ts | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/components/store/stackingContractInfo.ts index 3dcdff63c..f1d8fb608 100644 --- a/frontend/components/store/stackingContractInfo.ts +++ b/frontend/components/store/stackingContractInfo.ts @@ -9,13 +9,17 @@ const initialState = { canStartAgent: false, }; -export const useStakingContractInfo = create<{ +type StakingContractInfoStore = { isStakingContractInfoLoading: boolean; isRewardsAvailable: boolean; hasEnoughServiceSlots: boolean; canStartAgent: boolean; fetchStakingContractInfo: () => Promise; -}>((set) => { +}; + +export const useStakingContractInfo = create()(( + set, +) => { return { ...initialState, isStakingContractInfoLoading: true, @@ -27,9 +31,9 @@ export const useStakingContractInfo = create<{ if (!info) return; - const { availableRewards, maxNumServices, getServiceIds } = info; + const { availableRewards, maxNumServices, serviceIds } = info; const isRewardsAvailable = availableRewards > 0; - const hasEnoughServiceSlots = getServiceIds.length < maxNumServices; + const hasEnoughServiceSlots = serviceIds.length < maxNumServices; const canStartAgent = isRewardsAvailable && hasEnoughServiceSlots; set({ diff --git a/frontend/service/Autonolas.ts b/frontend/service/Autonolas.ts index 222164035..a20fd9c96 100644 --- a/frontend/service/Autonolas.ts +++ b/frontend/service/Autonolas.ts @@ -179,13 +179,13 @@ const getStakingContractInfo = async (): Promise< const availableRewards = parseFloat( ethers.utils.formatUnits(availableRewardsInBN, 18), ); - const getServiceIds = getServiceIdsInBN.map((id: BigNumber) => id.toNumber()); + const serviceIds = getServiceIdsInBN.map((id: BigNumber) => id.toNumber()); const maxNumServices = maxNumServicesInBN.toNumber(); return { availableRewards, maxNumServices, - getServiceIds, + serviceIds, }; }; diff --git a/frontend/types/Autonolas.ts b/frontend/types/Autonolas.ts index 1eb7c5756..7855a89f1 100644 --- a/frontend/types/Autonolas.ts +++ b/frontend/types/Autonolas.ts @@ -13,5 +13,5 @@ export type StakingRewardsInfo = { export type StakingContractInfo = { availableRewards: number; maxNumServices: number; - getServiceIds: number[]; + serviceIds: number[]; }; From ee44d0942ad86354a2d94783ceb61dd9c7a0a768 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 02:39:44 +0530 Subject: [PATCH 12/26] chore: Update MainHeader component with new features and improvements --- .../components/Main/MainHeader/MainHeader.tsx | 96 ++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index c16872fc8..1e0432889 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -1,11 +1,25 @@ import { InfoCircleOutlined } from '@ant-design/icons'; -import { Badge, Button, Flex, Modal, Popover, Typography } from 'antd'; +import { + Badge, + Button, + Flex, + Modal, + Popover, + PopoverProps, + Typography, +} from 'antd'; import { formatUnits } from 'ethers/lib/utils'; import Image from 'next/image'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Chain, DeploymentStatus } from '@/client'; -import { COLOR, LOW_BALANCE, SERVICE_TEMPLATES } from '@/constants'; +import { + COLOR, + LOW_BALANCE, + SERVICE_TEMPLATES, + SUPPORT_URL, +} from '@/constants'; +import { UNICODE_SYMBOLS } from '@/constants/unicode'; import { useBalance, useServiceTemplates } from '@/hooks'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useReward } from '@/hooks/useReward'; @@ -77,6 +91,61 @@ const FirstRunModal = ({ ); }; +const cannotStartAgentText = ( + + Cannot start agent  + + +); + +const otherPopoverProps: PopoverProps = { + arrow: false, + placement: 'bottomRight', +}; + +const JoinOlasCommunity = () => ( +
+ + Join the Olas community Discord server to report or stay up to date on the + issue. + + + + Olas community Discord server {UNICODE_SYMBOLS.EXTERNAL_LINK} + +
+); + +const NoRewardsAvailablePopover = () => ( + } + title="No rewards available" + > + {cannotStartAgentText} + +); + +const NoJobsAvailablePopover = () => ( + } + title="No jobs available" + > + {cannotStartAgentText} + +); + +const AgentEvictedPopover = () => ( + + {cannotStartAgentText} + +); + const useSetupTrayIcon = () => { const { safeBalance } = useBalance(); const { serviceStatus } = useServices(); @@ -118,6 +187,18 @@ export const MainHeader = () => { const { minimumStakedAmountRequired } = useReward(); + const { + isStakingContractInfoLoading, + hasEnoughServiceSlots, + isRewardsAvailable, + isAgentEvicted, + fetchStakingContractInfo, + } = useStakingContractInfo(); + + useEffect(() => { + fetchStakingContractInfo(); + }, [fetchStakingContractInfo]); + const safeOlasBalanceWithStaked = useMemo(() => { if (safeBalance?.OLAS === undefined) return; if (totalOlasStakedBalance === undefined) return; @@ -363,10 +444,19 @@ export const MainHeader = () => { canStartAgent, ]); + const cannotStartAgent = useMemo(() => { + if (!isRewardsAvailable) return ; + if (!hasEnoughServiceSlots) return ; + if (isAgentEvicted) return ; + throw new Error('Cannot start agent, please contact support'); + }, [isRewardsAvailable, isAgentEvicted, hasEnoughServiceSlots]); + return ( {agentHead} - {serviceToggleButton} + {isStakingContractInfoLoading ? null : ( + <>{canStartAgent ? serviceToggleButton : cannotStartAgent} + )} ); From 83a235809427b367424a9257c6160390d8ac5166 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 02:43:31 +0530 Subject: [PATCH 13/26] chore: Update AgentEvictedPopover content --- frontend/components/Main/MainHeader/MainHeader.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 1e0432889..5a29ca4cd 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -136,10 +136,12 @@ const NoJobsAvailablePopover = () => ( ); +const evictedDescription = + "You didn't run your agent enough and it missed its targets multiple times. Please wait a few days and try to run your agent again."; const AgentEvictedPopover = () => ( {evictedDescription}} title="Your agent was evicted" > {cannotStartAgentText} From 6556a8d3ca336370eb93143cb86a0221df995aad Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 02:43:45 +0530 Subject: [PATCH 14/26] chore: Implement isAgentEvicted flag in StakingContractInfo store --- frontend/components/store/stackingContractInfo.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/components/store/stackingContractInfo.ts index f1d8fb608..51b88d57f 100644 --- a/frontend/components/store/stackingContractInfo.ts +++ b/frontend/components/store/stackingContractInfo.ts @@ -6,6 +6,7 @@ const initialState = { isStakingContractInfoLoading: true, isRewardsAvailable: false, hasEnoughServiceSlots: false, + isAgentEvicted: false, // TODO: Implement this canStartAgent: false, }; @@ -13,6 +14,7 @@ type StakingContractInfoStore = { isStakingContractInfoLoading: boolean; isRewardsAvailable: boolean; hasEnoughServiceSlots: boolean; + isAgentEvicted: boolean; // TODO: Implement this canStartAgent: boolean; fetchStakingContractInfo: () => Promise; }; From 696f71dd7a5ff1ab636042557c624d0fd8ae76ab Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 02:49:43 +0530 Subject: [PATCH 15/26] chore: Remove StakingValidations component from MainHeader --- frontend/components/Main/Main.tsx | 2 - .../Main/MainHeader/StakingValidations.tsx | 70 ------------------- 2 files changed, 72 deletions(-) delete mode 100644 frontend/components/Main/MainHeader/StakingValidations.tsx diff --git a/frontend/components/Main/Main.tsx b/frontend/components/Main/Main.tsx index af6cc73cc..81864ae22 100644 --- a/frontend/components/Main/Main.tsx +++ b/frontend/components/Main/Main.tsx @@ -9,7 +9,6 @@ import { KeepAgentRunning } from './KeepAgentRunning'; import { MainAddFunds } from './MainAddFunds'; import { MainGasBalance } from './MainGasBalance'; import { MainHeader } from './MainHeader/MainHeader'; -import { StakingValidations } from './MainHeader/StakingValidations'; import { MainNeedsFunds } from './MainNeedsFunds'; import { MainOlasBalance } from './MainOlasBalance'; import { MainRewards } from './MainRewards'; @@ -48,7 +47,6 @@ export const Main = () => { style={{ borderTopColor: 'transparent' }} > - diff --git a/frontend/components/Main/MainHeader/StakingValidations.tsx b/frontend/components/Main/MainHeader/StakingValidations.tsx deleted file mode 100644 index 01a113379..000000000 --- a/frontend/components/Main/MainHeader/StakingValidations.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { Flex, Typography } from 'antd'; -import { useEffect } from 'react'; - -import { Alert } from '../../common/Alert'; -import { useStakingContractInfo } from '../../store/stackingContractInfo'; -import { CardSection } from '../../styled/CardSection'; - -const { Text, Paragraph } = Typography; - -const COVER_PREV_BLOCK_BORDER_STYLE = { marginBottom: '-1px' }; - -export const StakingValidations = () => { - const { - hasEnoughServiceSlots, - isRewardsAvailable, - isStakingContractInfoLoading, - fetchStakingContractInfo, - } = useStakingContractInfo(); - - useEffect(() => { - fetchStakingContractInfo(); - }, [fetchStakingContractInfo]); - - if (isStakingContractInfoLoading) return null; - - if (!isRewardsAvailable) { - return ( - - - No rewards available - - There are no rewards available for staking. - - - } - type="error" - fullWidth - /> - - ); - } - - if (!hasEnoughServiceSlots) { - return ( - - - - Not enough service slots - - - You have reached the maximum number of services allowed for - staking. - -
- } - type="error" - fullWidth - /> - - ); - } - - return null; -}; From 2d95886346d2ef6e211e22790eb0646d6f1e480b Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 02:57:38 +0530 Subject: [PATCH 16/26] chore: Update MainHeader component with new features and improvements (move to utils.tsx) --- .../components/Main/MainHeader/MainHeader.tsx | 135 ++---------------- frontend/components/Main/MainHeader/utils.tsx | 103 +++++++++++++ 2 files changed, 116 insertions(+), 122 deletions(-) create mode 100644 frontend/components/Main/MainHeader/utils.tsx diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 5a29ca4cd..5a427f892 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -1,25 +1,9 @@ -import { InfoCircleOutlined } from '@ant-design/icons'; -import { - Badge, - Button, - Flex, - Modal, - Popover, - PopoverProps, - Typography, -} from 'antd'; -import { formatUnits } from 'ethers/lib/utils'; +import { Badge, Button, Flex, Modal, Typography } from 'antd'; import Image from 'next/image'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Chain, DeploymentStatus } from '@/client'; -import { - COLOR, - LOW_BALANCE, - SERVICE_TEMPLATES, - SUPPORT_URL, -} from '@/constants'; -import { UNICODE_SYMBOLS } from '@/constants/unicode'; +import { LOW_BALANCE } from '@/constants'; import { useBalance, useServiceTemplates } from '@/hooks'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useReward } from '@/hooks/useReward'; @@ -30,11 +14,16 @@ import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; import { useStakingContractInfo } from '../../store/stackingContractInfo'; +import { + AgentEvictedPopover, + NoJobsAvailablePopover, + NoRewardsAvailablePopover, + requiredGas, + requiredOlas, + StartingButtonPopover, +} from './utils'; -const { Text, Title, Paragraph } = Typography; - -const LOADING_MESSAGE = - 'Starting the agent may take a while, so feel free to minimize the app. We’ll notify you once it’s running. Please, don’t quit the app.'; +const { Title, Paragraph } = Typography; enum ServiceButtonLoadingState { Starting, @@ -91,63 +80,6 @@ const FirstRunModal = ({ ); }; -const cannotStartAgentText = ( - - Cannot start agent  - - -); - -const otherPopoverProps: PopoverProps = { - arrow: false, - placement: 'bottomRight', -}; - -const JoinOlasCommunity = () => ( -
- - Join the Olas community Discord server to report or stay up to date on the - issue. - - - - Olas community Discord server {UNICODE_SYMBOLS.EXTERNAL_LINK} - -
-); - -const NoRewardsAvailablePopover = () => ( - } - title="No rewards available" - > - {cannotStartAgentText} - -); - -const NoJobsAvailablePopover = () => ( - } - title="No jobs available" - > - {cannotStartAgentText} - -); - -const evictedDescription = - "You didn't run your agent enough and it missed its targets multiple times. Please wait a few days and try to run your agent again."; -const AgentEvictedPopover = () => ( - {evictedDescription}} - title="Your agent was evicted" - > - {cannotStartAgentText} - -); - const useSetupTrayIcon = () => { const { safeBalance } = useBalance(); const { serviceStatus } = useServices(); @@ -324,25 +256,7 @@ export const MainHeader = () => { } if (serviceButtonState === ServiceButtonLoadingState.Starting) { - return ( - - - - - {LOADING_MESSAGE} - - } - > - - - ); + return ; } if (serviceStatus === DeploymentStatus.DEPLOYED) { @@ -369,29 +283,6 @@ export const MainHeader = () => { ); } - const olasCostOfBond = Number( - formatUnits( - `${SERVICE_TEMPLATES[0].configuration.olas_cost_of_bond}`, - 18, - ), - ); - - const olasRequiredToStake = Number( - formatUnits( - `${SERVICE_TEMPLATES[0].configuration.olas_required_to_stake}`, - 18, - ), - ); - - const requiredOlas = olasCostOfBond + olasRequiredToStake; - - const requiredGas = Number( - formatUnits( - `${SERVICE_TEMPLATES[0].configuration.monthly_gas_estimate}`, - 18, - ), - ); - const isDeployable = (() => { // case where required values are undefined (not fetched from the server) if (totalEthBalance === undefined) return false; @@ -447,8 +338,8 @@ export const MainHeader = () => { ]); const cannotStartAgent = useMemo(() => { - if (!isRewardsAvailable) return ; if (!hasEnoughServiceSlots) return ; + if (!isRewardsAvailable) return ; if (isAgentEvicted) return ; throw new Error('Cannot start agent, please contact support'); }, [isRewardsAvailable, isAgentEvicted, hasEnoughServiceSlots]); diff --git a/frontend/components/Main/MainHeader/utils.tsx b/frontend/components/Main/MainHeader/utils.tsx new file mode 100644 index 000000000..3b476030d --- /dev/null +++ b/frontend/components/Main/MainHeader/utils.tsx @@ -0,0 +1,103 @@ +import { InfoCircleOutlined } from '@ant-design/icons'; +import { Button, Flex, Popover, PopoverProps, Typography } from 'antd'; +import { formatUnits } from 'ethers/lib/utils'; + +import { COLOR, SERVICE_TEMPLATES, SUPPORT_URL } from '@/constants'; +import { UNICODE_SYMBOLS } from '@/constants/unicode'; + +const { Paragraph, Text } = Typography; + +export const LOADING_MESSAGE = + 'Starting the agent may take a while, so feel free to minimize the app. We’ll notify you once it’s running. Please, don’t quit the app.'; + +const olasCostOfBond = Number( + formatUnits(`${SERVICE_TEMPLATES[0].configuration.olas_cost_of_bond}`, 18), +); +const olasRequiredToStake = Number( + formatUnits( + `${SERVICE_TEMPLATES[0].configuration.olas_required_to_stake}`, + 18, + ), +); + +export const requiredOlas = olasCostOfBond + olasRequiredToStake; +export const requiredGas = Number( + formatUnits(`${SERVICE_TEMPLATES[0].configuration.monthly_gas_estimate}`, 18), +); + +export const cannotStartAgentText = ( + + Cannot start agent  + + +); + +export const otherPopoverProps: PopoverProps = { + arrow: false, + placement: 'bottomRight', +}; + +export const JoinOlasCommunity = () => ( +
+ + Join the Olas community Discord server to report or stay up to date on the + issue. + + + + Olas community Discord server {UNICODE_SYMBOLS.EXTERNAL_LINK} + +
+); + +export const NoRewardsAvailablePopover = () => ( + } + title="No rewards available" + > + {cannotStartAgentText} + +); + +export const NoJobsAvailablePopover = () => ( + } + title="No jobs available" + > + {cannotStartAgentText} + +); + +const evictedDescription = + "You didn't run your agent enough and it missed its targets multiple times. Please wait a few days and try to run your agent again."; +export const AgentEvictedPopover = () => ( + {evictedDescription}} + title="Your agent was evicted" + > + {cannotStartAgentText} + +); + +export const StartingButtonPopover = () => ( + + + + + {LOADING_MESSAGE} + + } + > + + +); From 2cc967a7c8a3a0fd98824e23eb488ec5a72183ba Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 02:59:43 +0530 Subject: [PATCH 17/26] chore: Add FirstRunModal component to MainHeader --- .../Main/MainHeader/FirstRunModal.tsx | 52 ++++++++++++++++++ .../components/Main/MainHeader/MainHeader.tsx | 54 +------------------ 2 files changed, 54 insertions(+), 52 deletions(-) create mode 100644 frontend/components/Main/MainHeader/FirstRunModal.tsx diff --git a/frontend/components/Main/MainHeader/FirstRunModal.tsx b/frontend/components/Main/MainHeader/FirstRunModal.tsx new file mode 100644 index 000000000..50b06f92b --- /dev/null +++ b/frontend/components/Main/MainHeader/FirstRunModal.tsx @@ -0,0 +1,52 @@ +import { Button, Flex, Modal, Typography } from 'antd'; +import Image from 'next/image'; +import { FC } from 'react'; + +import { useReward } from '@/hooks/useReward'; + +const { Title, Paragraph } = Typography; + +type FirstRunModalProps = { open: boolean; onClose: () => void }; + +export const FirstRunModal: FC = ({ open, onClose }) => { + const { minimumStakedAmountRequired } = useReward(); + + if (!open) return null; + return ( + + Got it + , + ]} + > + + OLAS logo + + + {`Your agent is running and you've staked ${minimumStakedAmountRequired} OLAS!`} + + Your agent is working towards earning rewards. + + Pearl is designed to make it easy for you to earn staking rewards every + day. Simply leave the app and agent running in the background for ~1hr a + day. + + + ); +}; diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 5a427f892..6ff27cce9 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -1,4 +1,4 @@ -import { Badge, Button, Flex, Modal, Typography } from 'antd'; +import { Badge, Button, Flex, Typography } from 'antd'; import Image from 'next/image'; import { useCallback, useEffect, useMemo, useState } from 'react'; @@ -14,6 +14,7 @@ import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; import { useStakingContractInfo } from '../../store/stackingContractInfo'; +import { FirstRunModal } from './FirstRunModal'; import { AgentEvictedPopover, NoJobsAvailablePopover, @@ -23,63 +24,12 @@ import { StartingButtonPopover, } from './utils'; -const { Title, Paragraph } = Typography; - enum ServiceButtonLoadingState { Starting, Pausing, NotLoading, } -const FirstRunModal = ({ - open, - onClose, -}: { - open: boolean; - onClose: () => void; -}) => { - const { minimumStakedAmountRequired } = useReward(); - - if (!open) return null; - return ( - - Got it - , - ]} - > - - OLAS logo - - - {`Your agent is running and you've staked ${minimumStakedAmountRequired} OLAS!`} - - Your agent is working towards earning rewards. - - Pearl is designed to make it easy for you to earn staking rewards every - day. Simply leave the app and agent running in the background for ~1hr a - day. - - - ); -}; - const useSetupTrayIcon = () => { const { safeBalance } = useBalance(); const { serviceStatus } = useServices(); From 630b06ade61668e91c681884a1496721a3685064 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 14:15:59 +0530 Subject: [PATCH 18/26] chore: Refactor MainHeader component and dependencies --- frontend/components/Main/MainHeader/MainHeader.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 6ff27cce9..3177340eb 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -288,11 +288,17 @@ export const MainHeader = () => { ]); const cannotStartAgent = useMemo(() => { + if (canStartAgent) return null; if (!hasEnoughServiceSlots) return ; if (!isRewardsAvailable) return ; if (isAgentEvicted) return ; throw new Error('Cannot start agent, please contact support'); - }, [isRewardsAvailable, isAgentEvicted, hasEnoughServiceSlots]); + }, [ + canStartAgent, + isRewardsAvailable, + isAgentEvicted, + hasEnoughServiceSlots, + ]); return ( From 98c7d2f7e351361a9050dc16060ad67145280960 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 22:31:51 +0530 Subject: [PATCH 19/26] chore: Update MainHeader component with useStakingContractInfo hook --- frontend/components/Main/MainHeader/MainHeader.tsx | 2 +- .../stackingContractInfo.ts => store/useStakingContractInfo.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename frontend/{components/store/stackingContractInfo.ts => store/useStakingContractInfo.ts} (100%) diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 3177340eb..3f28ec170 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -12,8 +12,8 @@ import { useStore } from '@/hooks/useStore'; import { useWallet } from '@/hooks/useWallet'; import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; +import { useStakingContractInfo } from '@/store/useStakingContractInfo'; -import { useStakingContractInfo } from '../../store/stackingContractInfo'; import { FirstRunModal } from './FirstRunModal'; import { AgentEvictedPopover, diff --git a/frontend/components/store/stackingContractInfo.ts b/frontend/store/useStakingContractInfo.ts similarity index 100% rename from frontend/components/store/stackingContractInfo.ts rename to frontend/store/useStakingContractInfo.ts From f956a4a8d2b96ca62c78067e469cb3c4514393ad Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 22:33:42 +0530 Subject: [PATCH 20/26] Refactor MainHeader component and dependencies --- frontend/components/Main/MainHeader/utils.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/components/Main/MainHeader/utils.tsx b/frontend/components/Main/MainHeader/utils.tsx index 3b476030d..8e6d03588 100644 --- a/frontend/components/Main/MainHeader/utils.tsx +++ b/frontend/components/Main/MainHeader/utils.tsx @@ -25,7 +25,7 @@ export const requiredGas = Number( formatUnits(`${SERVICE_TEMPLATES[0].configuration.monthly_gas_estimate}`, 18), ); -export const cannotStartAgentText = ( +const CannotStartAgentText = () => ( Cannot start agent  @@ -56,7 +56,7 @@ export const NoRewardsAvailablePopover = () => ( content={} title="No rewards available" > - {cannotStartAgentText} + ); @@ -66,7 +66,7 @@ export const NoJobsAvailablePopover = () => ( content={} title="No jobs available" > - {cannotStartAgentText} + ); @@ -78,7 +78,7 @@ export const AgentEvictedPopover = () => ( content={
{evictedDescription}
} title="Your agent was evicted" > - {cannotStartAgentText} + ); From 6e18beb51e61a263626bca0a6d6f6acd82a348e6 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Thu, 27 Jun 2024 22:42:09 +0530 Subject: [PATCH 21/26] chore: move to constants and components --- .../components/Main/MainHeader/MainHeader.tsx | 7 +++--- .../MainHeader/{utils.tsx => components.tsx} | 23 +++---------------- .../components/Main/MainHeader/constants.tsx | 18 +++++++++++++++ 3 files changed, 24 insertions(+), 24 deletions(-) rename frontend/components/Main/MainHeader/{utils.tsx => components.tsx} (79%) create mode 100644 frontend/components/Main/MainHeader/constants.tsx diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 3f28ec170..48c084498 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -14,15 +14,14 @@ import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; import { useStakingContractInfo } from '@/store/useStakingContractInfo'; -import { FirstRunModal } from './FirstRunModal'; import { AgentEvictedPopover, NoJobsAvailablePopover, NoRewardsAvailablePopover, - requiredGas, - requiredOlas, StartingButtonPopover, -} from './utils'; +} from './components'; +import { requiredGas, requiredOlas } from './constants'; +import { FirstRunModal } from './FirstRunModal'; enum ServiceButtonLoadingState { Starting, diff --git a/frontend/components/Main/MainHeader/utils.tsx b/frontend/components/Main/MainHeader/components.tsx similarity index 79% rename from frontend/components/Main/MainHeader/utils.tsx rename to frontend/components/Main/MainHeader/components.tsx index 8e6d03588..bebc54171 100644 --- a/frontend/components/Main/MainHeader/utils.tsx +++ b/frontend/components/Main/MainHeader/components.tsx @@ -1,30 +1,11 @@ import { InfoCircleOutlined } from '@ant-design/icons'; import { Button, Flex, Popover, PopoverProps, Typography } from 'antd'; -import { formatUnits } from 'ethers/lib/utils'; -import { COLOR, SERVICE_TEMPLATES, SUPPORT_URL } from '@/constants'; +import { COLOR, SUPPORT_URL } from '@/constants'; import { UNICODE_SYMBOLS } from '@/constants/unicode'; const { Paragraph, Text } = Typography; -export const LOADING_MESSAGE = - 'Starting the agent may take a while, so feel free to minimize the app. We’ll notify you once it’s running. Please, don’t quit the app.'; - -const olasCostOfBond = Number( - formatUnits(`${SERVICE_TEMPLATES[0].configuration.olas_cost_of_bond}`, 18), -); -const olasRequiredToStake = Number( - formatUnits( - `${SERVICE_TEMPLATES[0].configuration.olas_required_to_stake}`, - 18, - ), -); - -export const requiredOlas = olasCostOfBond + olasRequiredToStake; -export const requiredGas = Number( - formatUnits(`${SERVICE_TEMPLATES[0].configuration.monthly_gas_estimate}`, 18), -); - const CannotStartAgentText = () => ( Cannot start agent  @@ -82,6 +63,8 @@ export const AgentEvictedPopover = () => ( ); +const LOADING_MESSAGE = + 'Starting the agent may take a while, so feel free to minimize the app. We’ll notify you once it’s running. Please, don’t quit the app.'; export const StartingButtonPopover = () => ( Date: Mon, 1 Jul 2024 15:55:14 +0530 Subject: [PATCH 22/26] Refactor MainHeader component and dependencies --- .../{components.tsx => CannotStartAgent.tsx} | 68 +++++++++---------- .../components/Main/MainHeader/MainHeader.tsx | 62 +++++++++-------- 2 files changed, 64 insertions(+), 66 deletions(-) rename frontend/components/Main/MainHeader/{components.tsx => CannotStartAgent.tsx} (59%) diff --git a/frontend/components/Main/MainHeader/components.tsx b/frontend/components/Main/MainHeader/CannotStartAgent.tsx similarity index 59% rename from frontend/components/Main/MainHeader/components.tsx rename to frontend/components/Main/MainHeader/CannotStartAgent.tsx index bebc54171..244f1fab2 100644 --- a/frontend/components/Main/MainHeader/components.tsx +++ b/frontend/components/Main/MainHeader/CannotStartAgent.tsx @@ -1,11 +1,24 @@ import { InfoCircleOutlined } from '@ant-design/icons'; -import { Button, Flex, Popover, PopoverProps, Typography } from 'antd'; +import { Popover, PopoverProps, Typography } from 'antd'; import { COLOR, SUPPORT_URL } from '@/constants'; import { UNICODE_SYMBOLS } from '@/constants/unicode'; +import { useStakingContractInfo } from '@/store/useStakingContractInfo'; const { Paragraph, Text } = Typography; +const evictedDescription = + "You didn't run your agent enough and it missed its targets multiple times. Please wait a few days and try to run your agent again."; +const AgentEvictedPopover = () => ( + {evictedDescription}} + title="Your agent was evicted" + > + + +); + const CannotStartAgentText = () => ( Cannot start agent  @@ -13,12 +26,12 @@ const CannotStartAgentText = () => ( ); -export const otherPopoverProps: PopoverProps = { +const otherPopoverProps: PopoverProps = { arrow: false, placement: 'bottomRight', }; -export const JoinOlasCommunity = () => ( +const JoinOlasCommunity = () => (
Join the Olas community Discord server to report or stay up to date on the @@ -31,7 +44,7 @@ export const JoinOlasCommunity = () => (
); -export const NoRewardsAvailablePopover = () => ( +const NoRewardsAvailablePopover = () => ( } @@ -41,7 +54,7 @@ export const NoRewardsAvailablePopover = () => ( ); -export const NoJobsAvailablePopover = () => ( +const NoJobsAvailablePopover = () => ( } @@ -51,36 +64,17 @@ export const NoJobsAvailablePopover = () => ( ); -const evictedDescription = - "You didn't run your agent enough and it missed its targets multiple times. Please wait a few days and try to run your agent again."; -export const AgentEvictedPopover = () => ( - {evictedDescription}} - title="Your agent was evicted" - > - - -); +export const CannotStartAgent = () => { + const { + canStartAgent, + hasEnoughServiceSlots, + isRewardsAvailable, + isAgentEvicted, + } = useStakingContractInfo(); -const LOADING_MESSAGE = - 'Starting the agent may take a while, so feel free to minimize the app. We’ll notify you once it’s running. Please, don’t quit the app.'; -export const StartingButtonPopover = () => ( - - - - - {LOADING_MESSAGE} -
- } - > - - -); + if (canStartAgent) return null; + if (!hasEnoughServiceSlots) return ; + if (!isRewardsAvailable) return ; + if (isAgentEvicted) return ; + throw new Error('Cannot start agent, please contact support'); +}; diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 48c084498..19649b373 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -1,9 +1,10 @@ -import { Badge, Button, Flex, Typography } from 'antd'; +import { InfoCircleOutlined } from '@ant-design/icons'; +import { Badge, Button, Flex, Popover, Typography } from 'antd'; import Image from 'next/image'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Chain, DeploymentStatus } from '@/client'; -import { LOW_BALANCE } from '@/constants'; +import { COLOR, LOW_BALANCE } from '@/constants'; import { useBalance, useServiceTemplates } from '@/hooks'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useReward } from '@/hooks/useReward'; @@ -14,15 +15,34 @@ import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; import { useStakingContractInfo } from '@/store/useStakingContractInfo'; -import { - AgentEvictedPopover, - NoJobsAvailablePopover, - NoRewardsAvailablePopover, - StartingButtonPopover, -} from './components'; +import { CannotStartAgent } from './CannotStartAgent'; import { requiredGas, requiredOlas } from './constants'; import { FirstRunModal } from './FirstRunModal'; +const { Text } = Typography; + +const LOADING_MESSAGE = + 'Starting the agent may take a while, so feel free to minimize the app. We’ll notify you once it’s running. Please, don’t quit the app.'; +const StartingButtonPopover = () => ( + + + + + {LOADING_MESSAGE} + + } + > + + +); + enum ServiceButtonLoadingState { Starting, Pausing, @@ -60,24 +80,21 @@ export const MainHeader = () => { isBalanceLoaded, setIsPaused: setIsBalancePollingPaused, } = useBalance(); - const { canStartAgent } = useStakingContractInfo(); const [isModalOpen, setIsModalOpen] = useState(false); const handleModalClose = useCallback(() => setIsModalOpen(false), []); - // hook to setup tray icon - useSetupTrayIcon(); - const { minimumStakedAmountRequired } = useReward(); const { isStakingContractInfoLoading, - hasEnoughServiceSlots, - isRewardsAvailable, - isAgentEvicted, + canStartAgent, fetchStakingContractInfo, } = useStakingContractInfo(); + // hook to setup tray icon + useSetupTrayIcon(); + useEffect(() => { fetchStakingContractInfo(); }, [fetchStakingContractInfo]); @@ -286,24 +303,11 @@ export const MainHeader = () => { canStartAgent, ]); - const cannotStartAgent = useMemo(() => { - if (canStartAgent) return null; - if (!hasEnoughServiceSlots) return ; - if (!isRewardsAvailable) return ; - if (isAgentEvicted) return ; - throw new Error('Cannot start agent, please contact support'); - }, [ - canStartAgent, - isRewardsAvailable, - isAgentEvicted, - hasEnoughServiceSlots, - ]); - return ( {agentHead} {isStakingContractInfoLoading ? null : ( - <>{canStartAgent ? serviceToggleButton : cannotStartAgent} + <>{canStartAgent ? serviceToggleButton : } )} From 0300647c798272c17844260f09123c9f10ce1918 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Tue, 2 Jul 2024 03:31:12 +0530 Subject: [PATCH 23/26] refractor: StakingContractProvider context added --- .../Main/MainHeader/CannotStartAgent.tsx | 2 +- .../components/Main/MainHeader/MainHeader.tsx | 13 +--- .../context/StakingContractInfoProvider.tsx | 70 +++++++++++++++++++ frontend/hooks/useStakingContractInfo.ts | 21 ++++++ frontend/pages/_app.tsx | 17 +++-- 5 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 frontend/context/StakingContractInfoProvider.tsx create mode 100644 frontend/hooks/useStakingContractInfo.ts diff --git a/frontend/components/Main/MainHeader/CannotStartAgent.tsx b/frontend/components/Main/MainHeader/CannotStartAgent.tsx index 244f1fab2..77fe6524e 100644 --- a/frontend/components/Main/MainHeader/CannotStartAgent.tsx +++ b/frontend/components/Main/MainHeader/CannotStartAgent.tsx @@ -3,7 +3,7 @@ import { Popover, PopoverProps, Typography } from 'antd'; import { COLOR, SUPPORT_URL } from '@/constants'; import { UNICODE_SYMBOLS } from '@/constants/unicode'; -import { useStakingContractInfo } from '@/store/useStakingContractInfo'; +import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; const { Paragraph, Text } = Typography; diff --git a/frontend/components/Main/MainHeader/MainHeader.tsx b/frontend/components/Main/MainHeader/MainHeader.tsx index 19649b373..24c971486 100644 --- a/frontend/components/Main/MainHeader/MainHeader.tsx +++ b/frontend/components/Main/MainHeader/MainHeader.tsx @@ -9,11 +9,11 @@ import { useBalance, useServiceTemplates } from '@/hooks'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useReward } from '@/hooks/useReward'; import { useServices } from '@/hooks/useServices'; +import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; import { useStore } from '@/hooks/useStore'; import { useWallet } from '@/hooks/useWallet'; import { ServicesService } from '@/service'; import { WalletService } from '@/service/Wallet'; -import { useStakingContractInfo } from '@/store/useStakingContractInfo'; import { CannotStartAgent } from './CannotStartAgent'; import { requiredGas, requiredOlas } from './constants'; @@ -86,19 +86,12 @@ export const MainHeader = () => { const { minimumStakedAmountRequired } = useReward(); - const { - isStakingContractInfoLoading, - canStartAgent, - fetchStakingContractInfo, - } = useStakingContractInfo(); + const { isStakingContractInfoLoading, canStartAgent } = + useStakingContractInfo(); // hook to setup tray icon useSetupTrayIcon(); - useEffect(() => { - fetchStakingContractInfo(); - }, [fetchStakingContractInfo]); - const safeOlasBalanceWithStaked = useMemo(() => { if (safeBalance?.OLAS === undefined) return; if (totalOlasStakedBalance === undefined) return; diff --git a/frontend/context/StakingContractInfoProvider.tsx b/frontend/context/StakingContractInfoProvider.tsx new file mode 100644 index 000000000..82d037b14 --- /dev/null +++ b/frontend/context/StakingContractInfoProvider.tsx @@ -0,0 +1,70 @@ +import { createContext, PropsWithChildren, useEffect, useState } from 'react'; + +import { AutonolasService } from '@/service/Autonolas'; + +type StakingContractInfoProviderContextType = { + isStakingContractInfoLoading: boolean; + isRewardsAvailable: boolean; + hasEnoughServiceSlots: boolean; + isAgentEvicted: boolean; // TODO: Implement this + canStartAgent: boolean; +}; + +export const StakingContractInfoProviderContext = + createContext({ + isStakingContractInfoLoading: true, + isRewardsAvailable: false, + hasEnoughServiceSlots: false, + isAgentEvicted: false, + canStartAgent: false, + }); + +export const StakingContractInfoProviderProvider = ({ + children, +}: PropsWithChildren) => { + const [isStakingContractInfoLoading, setIsStakingContractInfoLoading] = + useState(true); + const [isRewardsAvailable, setIsRewardsAvailable] = useState(false); + const [hasEnoughServiceSlots, setHasEnoughServiceSlots] = useState(false); + const [isAgentEvicted, setIsAgentEvicted] = useState(false); + const [canStartAgent, setCanStartAgent] = useState(false); + + useEffect(() => { + (async () => { + try { + setIsStakingContractInfoLoading(true); + + const info = await AutonolasService.getStakingContractInfo(); + if (!info) return; + + const { availableRewards, maxNumServices, serviceIds } = info; + const isRewardsAvailable = availableRewards > 0; + const hasEnoughServiceSlots = serviceIds.length < maxNumServices; + const canStartAgent = isRewardsAvailable && hasEnoughServiceSlots; + + setIsRewardsAvailable(isRewardsAvailable); + setHasEnoughServiceSlots(hasEnoughServiceSlots); + setCanStartAgent(canStartAgent); + setIsAgentEvicted(false); // TODO: Implement this + } catch (error) { + console.error('Failed to fetch staking contract info', error); + } finally { + setIsStakingContractInfoLoading(false); + } + })(); + }, []); + + return ( + + {children} + + ); +}; diff --git a/frontend/hooks/useStakingContractInfo.ts b/frontend/hooks/useStakingContractInfo.ts new file mode 100644 index 000000000..03a266aeb --- /dev/null +++ b/frontend/hooks/useStakingContractInfo.ts @@ -0,0 +1,21 @@ +import { useContext } from 'react'; + +import { StakingContractInfoProviderContext } from '@/context/StakingContractInfoProvider'; + +export const useStakingContractInfo = () => { + const { + canStartAgent, + hasEnoughServiceSlots, + isAgentEvicted, + isRewardsAvailable, + isStakingContractInfoLoading, + } = useContext(StakingContractInfoProviderContext); + + return { + canStartAgent, + hasEnoughServiceSlots, + isAgentEvicted, + isRewardsAvailable, + isStakingContractInfoLoading, + }; +}; diff --git a/frontend/pages/_app.tsx b/frontend/pages/_app.tsx index 9c91f90b1..30fe0807b 100644 --- a/frontend/pages/_app.tsx +++ b/frontend/pages/_app.tsx @@ -12,6 +12,7 @@ import { MasterSafeProvider } from '@/context/MasterSafeProvider'; import { OnlineStatusProvider } from '@/context/OnlineStatusProvider'; import { RewardProvider } from '@/context/RewardProvider'; import { SettingsProvider } from '@/context/SettingsProvider'; +import { StakingContractInfoProviderProvider } from '@/context/StakingContractInfoProvider'; import { StoreProvider } from '@/context/StoreProvider'; import { WalletProvider } from '@/context/WalletProvider'; import { mainTheme } from '@/theme'; @@ -38,13 +39,15 @@ export default function App({ Component, pageProps }: AppProps) { - {isMounted ? ( - - - - - - ) : null} + + {isMounted ? ( + + + + + + ) : null} + From 8466d40d5e778adb16eb5201ea6433acbf31ff1b Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Tue, 2 Jul 2024 03:49:48 +0530 Subject: [PATCH 24/26] refractor: remove zustand --- .../Main/MainHeader/CannotStartAgent.tsx | 20 +++---- frontend/package.json | 3 +- frontend/store/useStakingContractInfo.ts | 53 ------------------- frontend/yarn.lock | 12 ----- 4 files changed, 11 insertions(+), 77 deletions(-) delete mode 100644 frontend/store/useStakingContractInfo.ts diff --git a/frontend/components/Main/MainHeader/CannotStartAgent.tsx b/frontend/components/Main/MainHeader/CannotStartAgent.tsx index 77fe6524e..a0ecd2032 100644 --- a/frontend/components/Main/MainHeader/CannotStartAgent.tsx +++ b/frontend/components/Main/MainHeader/CannotStartAgent.tsx @@ -7,25 +7,25 @@ import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; const { Paragraph, Text } = Typography; +const CannotStartAgentText = () => ( + + Cannot start agent  + + +); + const evictedDescription = "You didn't run your agent enough and it missed its targets multiple times. Please wait a few days and try to run your agent again."; const AgentEvictedPopover = () => ( {evictedDescription}} title="Your agent was evicted" + content={
{evictedDescription}
} >
); -const CannotStartAgentText = () => ( - - Cannot start agent  - - -); - const otherPopoverProps: PopoverProps = { arrow: false, placement: 'bottomRight', @@ -47,8 +47,8 @@ const JoinOlasCommunity = () => ( const NoRewardsAvailablePopover = () => ( } title="No rewards available" + content={} > @@ -57,8 +57,8 @@ const NoRewardsAvailablePopover = () => ( const NoJobsAvailablePopover = () => ( } title="No jobs available" + content={} > diff --git a/frontend/package.json b/frontend/package.json index 65830f503..e040214f6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,8 +14,7 @@ "react-canvas-confetti": "1.2.1", "sass": "^1.72.0", "styled-components": "^6.1.8", - "usehooks-ts": "^2.14.0", - "zustand": "^4.5.2" + "usehooks-ts": "^2.14.0" }, "devDependencies": { "@testing-library/jest-dom": "^6.4.2", diff --git a/frontend/store/useStakingContractInfo.ts b/frontend/store/useStakingContractInfo.ts deleted file mode 100644 index 51b88d57f..000000000 --- a/frontend/store/useStakingContractInfo.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { create } from 'zustand'; - -import { AutonolasService } from '@/service/Autonolas'; - -const initialState = { - isStakingContractInfoLoading: true, - isRewardsAvailable: false, - hasEnoughServiceSlots: false, - isAgentEvicted: false, // TODO: Implement this - canStartAgent: false, -}; - -type StakingContractInfoStore = { - isStakingContractInfoLoading: boolean; - isRewardsAvailable: boolean; - hasEnoughServiceSlots: boolean; - isAgentEvicted: boolean; // TODO: Implement this - canStartAgent: boolean; - fetchStakingContractInfo: () => Promise; -}; - -export const useStakingContractInfo = create()(( - set, -) => { - return { - ...initialState, - isStakingContractInfoLoading: true, - isRewardsAvailable: false, - fetchStakingContractInfo: async () => { - try { - set({ isStakingContractInfoLoading: true }); - const info = await AutonolasService.getStakingContractInfo(); - - if (!info) return; - - const { availableRewards, maxNumServices, serviceIds } = info; - const isRewardsAvailable = availableRewards > 0; - const hasEnoughServiceSlots = serviceIds.length < maxNumServices; - const canStartAgent = isRewardsAvailable && hasEnoughServiceSlots; - - set({ - isRewardsAvailable, - hasEnoughServiceSlots, - canStartAgent, - }); - } catch (error) { - console.error('Failed to fetch staking contract info', error); - } finally { - set({ isStakingContractInfoLoading: false }); - } - }, - }; -}); diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 0f2d578a7..18458a9fa 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -6020,11 +6020,6 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -use-sync-external-store@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== - usehooks-ts@^2.14.0: version "2.16.0" resolved "https://registry.yarnpkg.com/usehooks-ts/-/usehooks-ts-2.16.0.tgz#31deaa2f1147f65666aae925bd890b54e63b0d3f" @@ -6236,10 +6231,3 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zustand@^4.5.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.2.tgz#fddbe7cac1e71d45413b3682cdb47b48034c3848" - integrity sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g== - dependencies: - use-sync-external-store "1.2.0" From fbbfbf9edd1a9a84d74cbf728e4d8902f1e7f73c Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Tue, 2 Jul 2024 03:54:39 +0530 Subject: [PATCH 25/26] chore: move to variable --- frontend/components/Main/MainHeader/CannotStartAgent.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/components/Main/MainHeader/CannotStartAgent.tsx b/frontend/components/Main/MainHeader/CannotStartAgent.tsx index a0ecd2032..4e37f4227 100644 --- a/frontend/components/Main/MainHeader/CannotStartAgent.tsx +++ b/frontend/components/Main/MainHeader/CannotStartAgent.tsx @@ -7,7 +7,7 @@ import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; const { Paragraph, Text } = Typography; -const CannotStartAgentText = () => ( +const cannotStartAgentText = ( Cannot start agent  @@ -22,7 +22,7 @@ const AgentEvictedPopover = () => ( title="Your agent was evicted" content={
{evictedDescription}
} > - + {cannotStartAgentText} ); @@ -50,7 +50,7 @@ const NoRewardsAvailablePopover = () => ( title="No rewards available" content={} > - + {cannotStartAgentText} ); @@ -60,7 +60,7 @@ const NoJobsAvailablePopover = () => ( title="No jobs available" content={} > - + {cannotStartAgentText} ); From a1605a1c2111abc2c9698af354f11d21434d09f4 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Tue, 2 Jul 2024 13:38:08 +0530 Subject: [PATCH 26/26] chore: address review changes --- frontend/context/StakingContractInfoProvider.tsx | 12 ++++++------ frontend/hooks/useStakingContractInfo.ts | 4 ++-- frontend/pages/_app.tsx | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/context/StakingContractInfoProvider.tsx b/frontend/context/StakingContractInfoProvider.tsx index 82d037b14..c53300e0c 100644 --- a/frontend/context/StakingContractInfoProvider.tsx +++ b/frontend/context/StakingContractInfoProvider.tsx @@ -2,7 +2,7 @@ import { createContext, PropsWithChildren, useEffect, useState } from 'react'; import { AutonolasService } from '@/service/Autonolas'; -type StakingContractInfoProviderContextType = { +type StakingContractInfoContextProps = { isStakingContractInfoLoading: boolean; isRewardsAvailable: boolean; hasEnoughServiceSlots: boolean; @@ -10,8 +10,8 @@ type StakingContractInfoProviderContextType = { canStartAgent: boolean; }; -export const StakingContractInfoProviderContext = - createContext({ +export const StakingContractInfoContext = + createContext({ isStakingContractInfoLoading: true, isRewardsAvailable: false, hasEnoughServiceSlots: false, @@ -19,7 +19,7 @@ export const StakingContractInfoProviderContext = canStartAgent: false, }); -export const StakingContractInfoProviderProvider = ({ +export const StakingContractInfoProvider = ({ children, }: PropsWithChildren) => { const [isStakingContractInfoLoading, setIsStakingContractInfoLoading] = @@ -55,7 +55,7 @@ export const StakingContractInfoProviderProvider = ({ }, []); return ( - {children} - + ); }; diff --git a/frontend/hooks/useStakingContractInfo.ts b/frontend/hooks/useStakingContractInfo.ts index 03a266aeb..69301068e 100644 --- a/frontend/hooks/useStakingContractInfo.ts +++ b/frontend/hooks/useStakingContractInfo.ts @@ -1,6 +1,6 @@ import { useContext } from 'react'; -import { StakingContractInfoProviderContext } from '@/context/StakingContractInfoProvider'; +import { StakingContractInfoContext } from '@/context/StakingContractInfoProvider'; export const useStakingContractInfo = () => { const { @@ -9,7 +9,7 @@ export const useStakingContractInfo = () => { isAgentEvicted, isRewardsAvailable, isStakingContractInfoLoading, - } = useContext(StakingContractInfoProviderContext); + } = useContext(StakingContractInfoContext); return { canStartAgent, diff --git a/frontend/pages/_app.tsx b/frontend/pages/_app.tsx index 30fe0807b..4cbfa6f85 100644 --- a/frontend/pages/_app.tsx +++ b/frontend/pages/_app.tsx @@ -12,7 +12,7 @@ import { MasterSafeProvider } from '@/context/MasterSafeProvider'; import { OnlineStatusProvider } from '@/context/OnlineStatusProvider'; import { RewardProvider } from '@/context/RewardProvider'; import { SettingsProvider } from '@/context/SettingsProvider'; -import { StakingContractInfoProviderProvider } from '@/context/StakingContractInfoProvider'; +import { StakingContractInfoProvider } from '@/context/StakingContractInfoProvider'; import { StoreProvider } from '@/context/StoreProvider'; import { WalletProvider } from '@/context/WalletProvider'; import { mainTheme } from '@/theme'; @@ -39,7 +39,7 @@ export default function App({ Component, pageProps }: AppProps) { - + {isMounted ? ( @@ -47,7 +47,7 @@ export default function App({ Component, pageProps }: AppProps) { ) : null} - +