From 3967b51efdc3b1fb78d2dbcfaf836aba8fea06c0 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 12:21:12 +0000 Subject: [PATCH 01/16] fix: enhance useServiceBalances to include service EOA and improve balance calculations --- frontend/hooks/useBalanceContext.ts | 44 ++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/frontend/hooks/useBalanceContext.ts b/frontend/hooks/useBalanceContext.ts index 51392983..f9d72b99 100644 --- a/frontend/hooks/useBalanceContext.ts +++ b/frontend/hooks/useBalanceContext.ts @@ -12,20 +12,15 @@ export const useBalanceContext = () => useContext(BalanceContext); * @param serviceConfigId * @returns */ -export const useServiceBalances = (serviceConfigId: string) => { - const { flatAddresses, serviceSafes } = useService({ +export const useServiceBalances = (serviceConfigId: string | undefined) => { + const { flatAddresses, serviceSafes, serviceEoa } = useService({ serviceConfigId, }); const { walletBalances, lowBalances, stakedBalances } = useBalanceContext(); - const serviceWalletBalances = useMemo( - () => - walletBalances?.filter((balance) => - flatAddresses.includes(balance.walletAddress), - ), - [flatAddresses, walletBalances], - ); - + /** + * Staked balances, only relevant to safes + */ const serviceStakedBalances = useMemo( () => stakedBalances?.filter((balance) => @@ -34,16 +29,23 @@ export const useServiceBalances = (serviceConfigId: string) => { [flatAddresses, stakedBalances], ); + /** Array of cross-chain wallet balances relevant to the service with is considered low */ const serviceLowBalances = useMemo( () => lowBalances?.filter((balance) => balance.walletAddress), [lowBalances], ); + /** + * Boolean indicating if the service has low balances + */ const isLowBalance = useMemo( () => serviceLowBalances?.length > 0, [serviceLowBalances], ); + /** + * Cross-chain unstaked balances in service safes + */ const serviceSafeBalances = useMemo( () => walletBalances?.filter((balance) => @@ -52,10 +54,32 @@ export const useServiceBalances = (serviceConfigId: string) => { [serviceSafes, walletBalances], ); + /** + * Cross-chain unstaked balances in service eoa (signer) + */ + const serviceEoaBalances = useMemo( + () => + walletBalances?.filter( + (balance) => balance.walletAddress === serviceEoa?.address, + ), + [serviceEoa?.address, walletBalances], + ); + + /** + * Balances i.e. native, erc20, etc + * Across all service wallets, including eoa + * @note NOT STAKED BALANCES + */ + const serviceWalletBalances = useMemo( + () => [...serviceSafeBalances, ...serviceEoaBalances], + [serviceEoaBalances, serviceSafeBalances], + ); + return { serviceWalletBalances, serviceStakedBalances, serviceSafeBalances, + serviceEoaBalances, serviceLowBalances, isLowBalance, }; From 209fa1de72646602c4c3fa16ae95d7eb01f5dea5 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 12:30:51 +0000 Subject: [PATCH 02/16] refactor: simplify balance calculations and add master EOA balances --- frontend/hooks/useBalanceContext.ts | 49 ++++++++++++++++++----------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/frontend/hooks/useBalanceContext.ts b/frontend/hooks/useBalanceContext.ts index f9d72b99..c2d7a080 100644 --- a/frontend/hooks/useBalanceContext.ts +++ b/frontend/hooks/useBalanceContext.ts @@ -94,24 +94,18 @@ export const useMasterBalances = () => { const { masterSafes, masterEoa } = useMasterWalletContext(); const { walletBalances, lowBalances, stakedBalances } = useBalanceContext(); - const masterWalletBalances = useMemo( - () => - walletBalances?.filter( - (balance) => - masterSafes?.find((safe) => safe.address === balance.walletAddress) || - masterEoa?.address === balance.walletAddress, - ), - [masterEoa?.address, masterSafes, walletBalances], - ); - - const masterStakedBalances = useMemo( - () => - stakedBalances?.filter((balance) => - masterSafes?.find((safe) => safe.address === balance.walletAddress), - ), - [masterSafes, stakedBalances], - ); + // TODO: unused, check only services stake? + // const masterStakedBalances = useMemo( + // () => + // stakedBalances?.filter((balance) => + // masterSafes?.find((safe) => safe.address === balance.walletAddress), + // ), + // [masterSafes, stakedBalances], + // ); + /** + * Array of low balances relevant to the master wallets (safes and eoa) + */ const masterLowBalances = useMemo( () => lowBalances?.filter((balance) => balance.walletAddress), [lowBalances], @@ -121,7 +115,8 @@ export const useMasterBalances = () => { () => masterLowBalances?.length > 0, [masterLowBalances], ); - // use flatAddresses for consistency + + // TODO: use flatAddresses for consistency const masterSafeBalances = useMemo( () => walletBalances?.filter((balance) => @@ -130,10 +125,26 @@ export const useMasterBalances = () => { [masterSafes, walletBalances], ); + const masterEoaBalances = useMemo( + () => + walletBalances?.filter( + (balance) => balance.walletAddress === masterEoa?.address, + ), + [masterEoa?.address, walletBalances], + ); + + /** + * Unstaked balances across master safes and eoas + */ + const masterWalletBalances = useMemo( + () => [...masterSafeBalances, ...masterEoaBalances], + [masterEoaBalances, masterSafeBalances], + ); + return { masterWalletBalances, - masterStakedBalances, masterSafeBalances, + masterEoaBalances, masterLowBalances, isLowBalance, }; From a9274263ccc9d40af3401598eddb9b81bbe5015f Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 12:38:15 +0000 Subject: [PATCH 03/16] feat: enhance OLAS balance calculations by integrating master and service wallet balances --- .../MainPage/sections/OlasBalanceSection.tsx | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/frontend/components/MainPage/sections/OlasBalanceSection.tsx b/frontend/components/MainPage/sections/OlasBalanceSection.tsx index 1132bd5a..5a7ca8ae 100644 --- a/frontend/components/MainPage/sections/OlasBalanceSection.tsx +++ b/frontend/components/MainPage/sections/OlasBalanceSection.tsx @@ -4,8 +4,14 @@ import { useMemo } from 'react'; import styled from 'styled-components'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; +import { TokenSymbol } from '@/enums/Token'; // import { Pages } from '@/enums/PageState'; -import { useBalanceContext } from '@/hooks/useBalanceContext'; +import { + useBalanceContext, + useMasterBalances, + useServiceBalances, +} from '@/hooks/useBalanceContext'; +import { useServices } from '@/hooks/useServices'; // import { usePageState } from '@/hooks/usePageState'; import { balanceFormat } from '@/utils/numberFormatters'; @@ -22,13 +28,52 @@ type MainOlasBalanceProps = { isBorderTopVisible?: boolean }; export const MainOlasBalance = ({ isBorderTopVisible = true, }: MainOlasBalanceProps) => { - const { isLoaded: isBalanceLoaded, totalOlasBalance } = useBalanceContext(); + const { selectedService } = useServices(); + const { isLoaded: isBalanceLoaded } = useBalanceContext(); + const { masterWalletBalances } = useMasterBalances(); + const { serviceStakedBalances, serviceWalletBalances } = useServiceBalances( + selectedService?.service_config_id, + ); // const { goto } = usePageState(); - const balance = useMemo(() => { - if (totalOlasBalance === undefined) return '--'; + const displayedBalance = useMemo(() => { + // olas across master wallets, safes and eoa + const masterWalletOlasBalance = masterWalletBalances?.reduce( + (acc, { symbol, balance }) => { + if (symbol === TokenSymbol.OLAS) { + return acc + Number(balance); + } + return acc; + }, + 0, + ); + + // olas across all service wallets + const serviceWalletOlasBalance = serviceWalletBalances?.reduce( + (acc, { symbol, balance }) => { + if (symbol === TokenSymbol.OLAS) { + return acc + Number(balance); + } + return acc; + }, + 0, + ); + + // olas staked across all services + const serviceStakedOlasBalance = serviceStakedBalances?.reduce( + (acc, { olasBondBalance, olasDepositBalance }) => { + return acc + Number(olasBondBalance) + Number(olasDepositBalance); + }, + 0, + ); + + const totalOlasBalance = + masterWalletOlasBalance + + serviceWalletOlasBalance + + serviceStakedOlasBalance; + return balanceFormat(totalOlasBalance, 2); - }, [totalOlasBalance]); + }, [masterWalletBalances, serviceStakedBalances, serviceWalletBalances]); return ( Current balance {UNICODE_SYMBOLS.OLAS} - {balance} + {displayedBalance} OLAS From c5388ad3ea965459618e0051c9f09adff5e86c44 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 12:38:35 +0000 Subject: [PATCH 04/16] fix: remove unused masterStakedBalances from useMasterBalances function --- frontend/hooks/useBalanceContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/hooks/useBalanceContext.ts b/frontend/hooks/useBalanceContext.ts index c2d7a080..0ecad8c9 100644 --- a/frontend/hooks/useBalanceContext.ts +++ b/frontend/hooks/useBalanceContext.ts @@ -92,7 +92,7 @@ export const useServiceBalances = (serviceConfigId: string | undefined) => { */ export const useMasterBalances = () => { const { masterSafes, masterEoa } = useMasterWalletContext(); - const { walletBalances, lowBalances, stakedBalances } = useBalanceContext(); + const { walletBalances, lowBalances } = useBalanceContext(); // TODO: unused, check only services stake? // const masterStakedBalances = useMemo( From 30d0a8a560f3718a338312e45276ee8a2eeca11e Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 12:39:01 +0000 Subject: [PATCH 05/16] refactor: reorganize low balance calculations in useMasterBalances for clarity --- frontend/hooks/useBalanceContext.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/frontend/hooks/useBalanceContext.ts b/frontend/hooks/useBalanceContext.ts index 0ecad8c9..5a7f744f 100644 --- a/frontend/hooks/useBalanceContext.ts +++ b/frontend/hooks/useBalanceContext.ts @@ -103,19 +103,6 @@ export const useMasterBalances = () => { // [masterSafes, stakedBalances], // ); - /** - * Array of low balances relevant to the master wallets (safes and eoa) - */ - const masterLowBalances = useMemo( - () => lowBalances?.filter((balance) => balance.walletAddress), - [lowBalances], - ); - - const isLowBalance = useMemo( - () => masterLowBalances?.length > 0, - [masterLowBalances], - ); - // TODO: use flatAddresses for consistency const masterSafeBalances = useMemo( () => @@ -141,6 +128,22 @@ export const useMasterBalances = () => { [masterEoaBalances, masterSafeBalances], ); + /** + * Array of low balances relevant to the master wallets (safes and eoa) + */ + const masterLowBalances = useMemo( + () => lowBalances?.filter((balance) => balance.walletAddress), + [lowBalances], + ); + + /** + * Boolean indicating if any master wallets have low balances + */ + const isLowBalance = useMemo( + () => masterLowBalances?.length > 0, + [masterLowBalances], + ); + return { masterWalletBalances, masterSafeBalances, From c64eceed2a46a611e02938d1beeda5276bd0855b Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 14:00:14 +0000 Subject: [PATCH 06/16] fix: comment out duplicate MainOlasBalance component in MainPage for clarity --- frontend/components/MainPage/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/MainPage/index.tsx b/frontend/components/MainPage/index.tsx index 0b73d4cd..7e444272 100644 --- a/frontend/components/MainPage/index.tsx +++ b/frontend/components/MainPage/index.tsx @@ -87,7 +87,7 @@ export const Main = () => { - + {/* */} From 2baf40ca4b36c35628f7cb5da78091845ed7ba5e Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 14:00:39 +0000 Subject: [PATCH 07/16] fix: comment out GasBalanceSection in MainPage for clarity --- frontend/components/MainPage/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/components/MainPage/index.tsx b/frontend/components/MainPage/index.tsx index 7e444272..240009ef 100644 --- a/frontend/components/MainPage/index.tsx +++ b/frontend/components/MainPage/index.tsx @@ -9,7 +9,6 @@ import { usePageState } from '@/hooks/usePageState'; import { MainHeader } from './header'; import { AddFundsSection } from './sections/AddFundsSection'; import { AlertSections } from './sections/AlertSections'; -import { GasBalanceSection } from './sections/GasBalanceSection'; import { KeepAgentRunningSection } from './sections/KeepAgentRunningSection'; import { MainNeedsFunds } from './sections/NeedsFundsSection'; import { MainOlasBalance } from './sections/OlasBalanceSection'; @@ -91,7 +90,7 @@ export const Main = () => { - + {/* */} From cd3aacb3bf04100e32d1f16901c305bf67c18259 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 14:33:56 +0000 Subject: [PATCH 08/16] feat: add agenttype to service templates --- frontend/client/types.ts | 2 ++ frontend/constants/serviceTemplates.ts | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/client/types.ts b/frontend/client/types.ts index 7f09e8b9..15aae662 100644 --- a/frontend/client/types.ts +++ b/frontend/client/types.ts @@ -1,3 +1,4 @@ +import { AgentType } from '@/enums/Agent'; import { StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; @@ -70,6 +71,7 @@ export type EnvVariableAttributes = { }; export type ServiceTemplate = { + agentType: AgentType; name: string; hash: string; description: string; diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index f64f7d9c..987c6a97 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -1,9 +1,11 @@ import { EnvProvisionType, ServiceTemplate } from '@/client'; +import { AgentType } from '@/enums/Agent'; import { ChainId } from '@/enums/Chain'; import { StakingProgramId } from '@/enums/StakingProgram'; export const SERVICE_TEMPLATES: ServiceTemplate[] = [ { + agentType: AgentType.PredictTrader, // TODO: remove if causes errors on middleware name: 'Trader Agent', hash: 'bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u', description: 'Trader agent for omen prediction markets', @@ -15,7 +17,7 @@ export const SERVICE_TEMPLATES: ServiceTemplate[] = [ [ChainId.Gnosis]: { staking_program_id: StakingProgramId.PearlBeta, // default, may be overwritten nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', - rpc: 'http://localhost:8545', + rpc: 'http://localhost:8545', // overwritten agent_id: 14, threshold: 1, use_staking: true, From 33a50972f8f20188895878c85d39e130143ef4bb Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 14:34:14 +0000 Subject: [PATCH 09/16] feat: add mechType to GNOSIS staking programs configuration --- frontend/config/stakingPrograms/gnosis.ts | 7 +++++++ frontend/config/stakingPrograms/index.ts | 2 ++ 2 files changed, 9 insertions(+) diff --git a/frontend/config/stakingPrograms/gnosis.ts b/frontend/config/stakingPrograms/gnosis.ts index d53dd334..e2a8361e 100644 --- a/frontend/config/stakingPrograms/gnosis.ts +++ b/frontend/config/stakingPrograms/gnosis.ts @@ -34,6 +34,7 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { stakingRequirements: { [TokenSymbol.OLAS]: 20, }, + mechType: MechType.Agent, mech: MECHS[ChainId.Gnosis][MechType.Agent].contract, activityChecker: ACTIVITY_CHECKERS[ChainId.Gnosis][MechType.Agent], contract: new MulticallContract( @@ -48,6 +49,7 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { stakingRequirements: { [TokenSymbol.OLAS]: 40, }, + mechType: MechType.Agent, mech: MECHS[ChainId.Gnosis][MechType.Agent].contract, activityChecker: ACTIVITY_CHECKERS[ChainId.Gnosis][MechType.Agent], contract: new MulticallContract( @@ -62,6 +64,7 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { stakingRequirements: { [TokenSymbol.OLAS]: 100, }, + mechType: MechType.Agent, mech: MECHS[ChainId.Gnosis][MechType.Agent].contract, activityChecker: ACTIVITY_CHECKERS[ChainId.Gnosis][MechType.Agent], contract: new MulticallContract( @@ -76,6 +79,7 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { stakingRequirements: { [TokenSymbol.OLAS]: 100, }, + mechType: MechType.Agent, mech: MECHS[ChainId.Gnosis][MechType.Agent].contract, activityChecker: ACTIVITY_CHECKERS[ChainId.Gnosis][MechType.Agent], contract: new MulticallContract( @@ -90,6 +94,7 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { stakingRequirements: { [TokenSymbol.OLAS]: 100, }, + mechType: MechType.Agent, mech: MECHS[ChainId.Gnosis][MechType.Agent].contract, activityChecker: ACTIVITY_CHECKERS[ChainId.Gnosis][MechType.Agent], contract: new MulticallContract( @@ -104,6 +109,7 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { stakingRequirements: { [TokenSymbol.OLAS]: 10, }, + mechType: MechType.Agent, mech: MECHS[ChainId.Gnosis][MechType.Agent].contract, activityChecker: ACTIVITY_CHECKERS[ChainId.Gnosis][MechType.Agent], contract: new MulticallContract( @@ -118,6 +124,7 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { stakingRequirements: { [TokenSymbol.OLAS]: 40, }, + mechType: MechType.Marketplace, mech: MECHS[ChainId.Gnosis][MechType.Marketplace].contract, activityChecker: ACTIVITY_CHECKERS[ChainId.Gnosis][MechType.Marketplace], contract: new MulticallContract( diff --git a/frontend/config/stakingPrograms/index.ts b/frontend/config/stakingPrograms/index.ts index 735d44e8..8c4be8c6 100644 --- a/frontend/config/stakingPrograms/index.ts +++ b/frontend/config/stakingPrograms/index.ts @@ -5,6 +5,7 @@ import { ChainId } from '@/enums/Chain'; import { StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; +import { MechType } from '../mechs'; import { GNOSIS_STAKING_PROGRAMS, GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES, @@ -26,6 +27,7 @@ export type StakingProgramConfig = { [tokenSymbol: string]: number; }; contract: MulticallContract; + mechType?: MechType; mech?: MulticallContract; activityChecker: MulticallContract; }; From 699660bbb5dc3dd9dee678ac2a26fe3c3ac531de Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 14:34:46 +0000 Subject: [PATCH 10/16] feat: enhance useActiveStakingContractInfo with service staking state and additional return values --- frontend/hooks/useStakingContractDetails.ts | 22 ++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/frontend/hooks/useStakingContractDetails.ts b/frontend/hooks/useStakingContractDetails.ts index b5b01915..41a8b34a 100644 --- a/frontend/hooks/useStakingContractDetails.ts +++ b/frontend/hooks/useStakingContractDetails.ts @@ -3,6 +3,7 @@ import { useContext } from 'react'; import { StakingContractDetailsContext } from '@/context/StakingContractDetailsProvider'; import { StakingProgramId } from '@/enums/StakingProgram'; +import { ServiceStakingState } from '@/types/Autonolas'; import { useServices } from './useServices'; @@ -27,10 +28,20 @@ export const useStakingContractContext = () => { }; }; +/** + * Returns ACTIVE staking contract details + * Has staked service speficic information that `useStakingContractDetails` does not have + + * @note requires serviceConfigId once multiple instances are supported + */ export const useActiveStakingContractInfo = () => { const { activeStakingContractDetails, isActiveStakingContractDetailsLoaded: isActiveStakingContractDetailsLoaded, + allStakingContractDetailsRecord, + refetchActiveStakingContractDetails, + isPaused, + setIsPaused, } = useStakingContractContext(); const { selectedService } = useServices(); @@ -40,8 +51,8 @@ export const useActiveStakingContractInfo = () => { return { allStakingContractDetailsRecord, refetchActiveStakingContractDetails, - setIsPaused, isPaused, + setIsPaused, }; } @@ -54,10 +65,12 @@ export const useActiveStakingContractInfo = () => { maxNumServices, } = activeStakingContractDetails ?? {}; - const isAgentEvicted = serviceStakingState === 2; + const isAgentEvicted = + serviceStakingState === ServiceStakingState.EvictedOrUnstaked; const isServiceStaked = - !!serviceStakingStartTime && serviceStakingState === 1; + !!serviceStakingStartTime && + serviceStakingState === ServiceStakingState.Staked; const isRewardsAvailable = availableRewards ?? 0 > 0; @@ -102,6 +115,9 @@ export const useActiveStakingContractInfo = () => { evictionExpiresAt, isActiveStakingContractDetailsLoaded, activeStakingContractDetails, + hasEnoughRewardsAndSlots, + hasEnoughServiceSlots, + isRewardsAvailable, }; }; From f38092b0b2215030f9ce530612e21ad0ba0a68c0 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 14:34:58 +0000 Subject: [PATCH 11/16] feat: add ServiceStakingState enum to improve clarity of staking states --- frontend/types/Autonolas.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/types/Autonolas.ts b/frontend/types/Autonolas.ts index fe1695d9..2c0e3fef 100644 --- a/frontend/types/Autonolas.ts +++ b/frontend/types/Autonolas.ts @@ -14,6 +14,12 @@ export const StakingRewardsInfoSchema = z.object({ export type StakingRewardsInfo = z.infer; +export enum ServiceStakingState { + NotStaked = 0, + Staked = 1, + EvictedOrUnstaked = 2, +} + export type StakingContractDetails = { availableRewards: number; /* number of slots available for staking */ @@ -24,7 +30,7 @@ export type StakingContractDetails = { /** time when service was staked (in seconds) - 0 = never staked */ serviceStakingStartTime: number; /** 0: not staked, 1: staked, 2: unstaked - current state of the service */ - serviceStakingState: number; + serviceStakingState: ServiceStakingState; /** OLAS cost of staking */ minStakingDeposit: number; /** estimated annual percentage yield */ From 9b325dde59d42b5bb53712238ac04787c86cf673 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 14:35:04 +0000 Subject: [PATCH 12/16] feat: refactor AgentButton and AgentNotRunningButton to use useActiveStakingContractInfo for improved clarity and functionality --- .../header/AgentButton/AgentButton.tsx | 12 ++++--- .../AgentButton/AgentNotRunningButton.tsx | 34 +++++++++++-------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/frontend/components/MainPage/header/AgentButton/AgentButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentButton.tsx index e0fc24a3..ba1f8180 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentButton.tsx @@ -4,7 +4,7 @@ import { useMemo } from 'react'; import { MiddlewareDeploymentStatus } from '@/client'; import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; -import { useStakingContractDetails } from '@/hooks/useStakingContractDetails'; +import { useActiveStakingContractInfo } from '@/hooks/useStakingContractDetails'; import { useStakingProgram } from '@/hooks/useStakingProgram'; import { assertRequired } from '@/types/Util'; @@ -21,20 +21,22 @@ export const AgentButton = () => { const { selectedService } = useServices(); const { activeStakingProgramId } = useStakingProgram(); + const serviceConfigId = selectedService?.service_config_id; + const { service, deploymentStatus: serviceStatus, isLoaded, - } = useService({ serviceConfigId: selectedService?.service_config_id }); + } = useService({ serviceConfigId }); assertRequired( + // TODO: review whether this causes agent button to not render activeStakingProgramId, 'Active staking program ID is required', ); - const { isEligibleForStaking, isAgentEvicted } = useStakingContractDetails( - activeStakingProgramId, - ); + const { isEligibleForStaking, isAgentEvicted } = + useActiveStakingContractInfo(); return useMemo(() => { if (!isLoaded) { diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx index 08c5ce38..fbe8aaf3 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -2,7 +2,9 @@ import { Button, ButtonProps } from 'antd'; import { useCallback, useMemo } from 'react'; import { MiddlewareChain, MiddlewareDeploymentStatus } from '@/client'; +import { MechType } from '@/config/mechs'; import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; +import { SERVICE_TEMPLATES } from '@/constants/serviceTemplates'; import { LOW_MASTER_SAFE_BALANCE } from '@/constants/thresholds'; import { TokenSymbol } from '@/enums/Token'; import { @@ -12,11 +14,9 @@ import { import { useElectronApi } from '@/hooks/useElectronApi'; import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; import { useActiveStakingContractInfo, useStakingContractContext, - useStakingContractDetails, } from '@/hooks/useStakingContractDetails'; import { useStakingProgram } from '@/hooks/useStakingProgram'; import { useStore } from '@/hooks/useStore'; @@ -26,7 +26,7 @@ import { WalletService } from '@/service/Wallet'; import { delayInSeconds } from '@/utils/delay'; /** Button used to start / deploy the agent */ -export const AgentNotRunningButton = (serviceConfigId: string) => { +export const AgentNotRunningButton = () => { const { masterWallets: wallets } = useMasterWalletContext(); const { selectedService, @@ -38,7 +38,6 @@ export const AgentNotRunningButton = (serviceConfigId: string) => { serviceConfigId: isLoaded && selectedService ? selectedService?.service_config_id : '', }); - const { serviceTemplate } = useServiceTemplates(); const { showNotification } = useElectronApi(); const { setIsPaused: setIsBalancePollingPaused, @@ -46,8 +45,9 @@ export const AgentNotRunningButton = (serviceConfigId: string) => { totalEthBalance, updateBalances, } = useBalanceContext(); - const { serviceSafeBalances, isLowBalance } = - useServiceBalances(serviceConfigId); + const { serviceSafeBalances, isLowBalance } = useServiceBalances( + selectedService?.service_config_id, + ); const { storeState } = useStore(); const { isAllStakingContractDetailsRecordLoaded, @@ -57,12 +57,11 @@ export const AgentNotRunningButton = (serviceConfigId: string) => { const { activeStakingProgramId } = useStakingProgram(); const { isEligibleForStaking, isAgentEvicted, isServiceStaked } = useActiveStakingContractInfo(); - const { hasEnoughServiceSlots } = useStakingContractDetails( - activeStakingProgramId, - ); + const { hasEnoughServiceSlots } = useActiveStakingContractInfo(); const requiredStakedOlas = service && + activeStakingProgramId && STAKING_PROGRAMS[service.home_chain_id][activeStakingProgramId] ?.stakingRequirements[TokenSymbol.OLAS]; @@ -102,15 +101,22 @@ export const AgentNotRunningButton = (serviceConfigId: string) => { }, [service]); const deployAndStartService = useCallback(async () => { - await ServicesService.createService({ + if (!activeStakingProgramId) return; + + const middlewareServiceResponse = await ServicesService.createService({ stakingProgramId: activeStakingProgramId, - serviceTemplate, + serviceTemplate: SERVICE_TEMPLATES[0], // TODO: support multi-agent, during optimus week deploy: true, - useMechMarketplace: false, + useMechMarketplace: + STAKING_PROGRAMS[+SERVICE_TEMPLATES[0].home_chain_id][ // TODO: support multi-agent, during optimus week + activeStakingProgramId + ].mechType === MechType.Marketplace, }); - await ServicesService.startService(serviceConfigId); - }, [activeStakingProgramId, serviceTemplate, serviceConfigId]); + await ServicesService.startService( + middlewareServiceResponse.service_config_id, + ); + }, [activeStakingProgramId]); const updateStatesSequentially = useCallback(async () => { await updateServicesState?.(); From 2157686a5347f5f6cfe491d4f9955a5b5a6a249e Mon Sep 17 00:00:00 2001 From: Atatakai Date: Thu, 21 Nov 2024 18:46:48 +0400 Subject: [PATCH 13/16] refactor: finalize useNeedsFunds hook, update MainNeedsFunds --- .../MainPage/sections/NeedsFundsSection.tsx | 11 +- frontend/hooks/useNeedsFunds.ts | 141 ++++++++++-------- 2 files changed, 84 insertions(+), 68 deletions(-) diff --git a/frontend/components/MainPage/sections/NeedsFundsSection.tsx b/frontend/components/MainPage/sections/NeedsFundsSection.tsx index b153611c..cb5abf40 100644 --- a/frontend/components/MainPage/sections/NeedsFundsSection.tsx +++ b/frontend/components/MainPage/sections/NeedsFundsSection.tsx @@ -6,6 +6,7 @@ import { CustomAlert } from '@/components/Alert'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useNeedsFunds } from '@/hooks/useNeedsFunds'; +import { useServices } from '@/hooks/useServices'; import { CardSection } from '../../styled/CardSection'; @@ -28,6 +29,9 @@ export const MainNeedsFunds = () => { needsInitialFunding, } = useNeedsFunds(); + const { selectedAgentConfig } = useServices(); + const { homeChainId } = selectedAgentConfig; + const electronApi = useElectronApi(); const message: ReactNode = useMemo( @@ -37,14 +41,14 @@ export const MainNeedsFunds = () => { {!hasEnoughOlasForInitialFunding && (
- {`${UNICODE_SYMBOLS.OLAS}${serviceFundRequirements.olas} OLAS `} + {`${UNICODE_SYMBOLS.OLAS}${serviceFundRequirements[homeChainId].olas} OLAS `} for staking
)} {!hasEnoughEthForInitialFunding && (
- {`$${serviceFundRequirements.eth} XDAI `} + {`$${serviceFundRequirements[homeChainId].eth} XDAI `} for trading
@@ -56,9 +60,10 @@ export const MainNeedsFunds = () => {
), [ + hasEnoughOlasForInitialFunding, serviceFundRequirements, + homeChainId, hasEnoughEthForInitialFunding, - hasEnoughOlasForInitialFunding, ], ); diff --git a/frontend/hooks/useNeedsFunds.ts b/frontend/hooks/useNeedsFunds.ts index fac61fae..46ef87a2 100644 --- a/frontend/hooks/useNeedsFunds.ts +++ b/frontend/hooks/useNeedsFunds.ts @@ -2,24 +2,20 @@ import { formatEther, formatUnits } from 'ethers/lib/utils'; import { useMemo } from 'react'; import { ServiceTemplate } from '@/client'; -import { CHAIN_CONFIG } from '@/config/chains'; import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; +import { getNativeTokenSymbol } from '@/config/tokens'; import { getServiceTemplate } from '@/constants/serviceTemplates'; +import { TokenSymbol } from '@/enums/Token'; -import { useBalanceContext } from './useBalanceContext'; +import { useBalanceContext, useMasterBalances } from './useBalanceContext'; import { useService } from './useService'; import { useStore } from './useStore'; -import { TokenSymbol } from '@/enums/Token'; -import { getNativeTokenSymbol, NATIVE_TOKEN_CONFIG } from '@/config/tokens'; -import { useMasterWalletContext } from './useWallet'; -export const useNeedsFunds = (serviceConfigId: string) => { +export const useNeedsFunds = (serviceConfigId?: string) => { const { storeState } = useStore(); const { service } = useService({ serviceConfigId }); - const { masterSafes } = useMasterWalletContext(); - const { isLoaded: isBalanceLoaded, walletBalances } = - useBalanceContext(); - + const { isLoaded: isBalanceLoaded, walletBalances } = useBalanceContext(); + const { masterSafeBalances } = useMasterBalances(); const isInitialFunded = storeState?.isInitialFunded; @@ -28,35 +24,38 @@ export const useNeedsFunds = (serviceConfigId: string) => { [service], ); - const serviceFundRequirements = useMemo< { + const serviceFundRequirements = useMemo<{ [chainId: number]: { - [tokenSymbol: string]: number; - } + [tokenSymbol: string]: number; + }; }>(() => { if (!serviceTemplate) return {}; const results: { [chainId: number]: { - [tokenSymbol: string]: number; - } + [tokenSymbol: string]: number; + }; } = {}; Object.entries(serviceTemplate.configurations).forEach( ([chainId, config]) => { - const serviceTemplateDefault = serviceTemplate.configurations[+chainId].staking_program_id - const serviceCurrent = service?.chain_configs[+chainId]?.chain_data?.user_params?.staking_program_id - - if (!serviceCurrent && !serviceTemplateDefault) return; - + const templateStakingProgramId = + serviceTemplate.configurations[+chainId].staking_program_id; + const serviceStakingProgramId = + service?.chain_configs[+chainId]?.chain_data?.user_params + ?.staking_program_id; + const stakingProgramId = + serviceStakingProgramId ?? templateStakingProgramId; + + if (!stakingProgramId) return; if (!service?.chain_configs[+chainId]) return; + const gasEstimate = config.monthly_gas_estimate; const monthlyGasEstimate = Number(formatUnits(`${gasEstimate}`, 18)); const minimumStakedAmountRequired = - STAKING_PROGRAMS[+chainId][ - service?.chain_configs[+chainId]?.chain_data?.user_params - ?.staking_program_id ?? - serviceTemplate.configurations[+chainId].staking_program_id - ].stakingRequirements.OLAS; + STAKING_PROGRAMS[+chainId]?.[stakingProgramId]?.stakingRequirements?.[ + TokenSymbol.OLAS + ] || 0; const nativeTokenSymbol = getNativeTokenSymbol(+chainId); @@ -69,48 +68,60 @@ export const useNeedsFunds = (serviceConfigId: string) => { ); return results; - }, [serviceTemplate]); - - const hasEnoughEthForInitialFunding = useMemo( - () => { - if (!serviceFundRequirements) return ; - if (!walletBalances) return ; - - const nativeBalancesByChain = walletBalances.reduce<{[chainId: number]: number}>((acc, {symbol, balance, chainId}) => { - if (getNativeTokenSymbol(chainId) !== symbol) return acc; - - if (!acc[chainId]) acc[chainId] = 0; - acc[chainId] += balance; - - return acc; - }, {}); - - const chainIds = Object.keys(serviceFundRequirements).map(Number); - - return chainIds.every(chainId => { - const nativeTokenSymbol = getNativeTokenSymbol(chainId); - const nativeTokenBalance = nativeBalancesByChain[chainId] || 0; - const nativeTokenRequired = serviceFundRequirements[chainId]?.[nativeTokenSymbol] || 0; - - return nativeTokenBalance >= nativeTokenRequired; - }); - - }, - [], - ); + }, [service?.chain_configs, serviceTemplate]); + + const hasEnoughEthForInitialFunding = useMemo(() => { + if (!serviceFundRequirements) return; + if (!walletBalances) return; + + const nativeBalancesByChain = walletBalances.reduce<{ + [chainId: number]: number; + }>((acc, { symbol, balance, chainId }) => { + if (getNativeTokenSymbol(chainId) !== symbol) return acc; + + if (!acc[chainId]) acc[chainId] = 0; + acc[chainId] += balance; + + return acc; + }, {}); + + const chainIds = Object.keys(serviceFundRequirements).map(Number); + + return chainIds.every((chainId) => { + const nativeTokenSymbol = getNativeTokenSymbol(chainId); + const nativeTokenBalance = nativeBalancesByChain[chainId] || 0; + const nativeTokenRequired = + serviceFundRequirements[chainId]?.[nativeTokenSymbol] || 0; + + return nativeTokenBalance >= nativeTokenRequired; + }); + }, [serviceFundRequirements, walletBalances]); - // TODO: refactor this to use the new balance context const hasEnoughOlasForInitialFunding = useMemo(() => { - const olasInSafe = safeBalance?.OLAS || 0; - const olasStakedBySafe = totalStakedOlasBalance || 0; - const olasRequiredToFundService = serviceFundRequirements.olas || 0; - const olasInSafeAndStaked = olasInSafe + olasStakedBySafe; - return olasInSafeAndStaked >= olasRequiredToFundService; - }, [ - safeBalance?.OLAS, - totalStakedOlasBalance, - serviceFundRequirements?.olas, - ]); + if (!serviceFundRequirements) return; + if (!masterSafeBalances) return; + + const olasBalancesByChain = masterSafeBalances.reduce<{ + [chainId: number]: number; + }>((acc, { symbol, balance, chainId }) => { + if (TokenSymbol.OLAS !== symbol) return acc; + + if (!acc[chainId]) acc[chainId] = 0; + acc[chainId] += balance; + + return acc; + }, {}); + + const chainIds = Object.keys(serviceFundRequirements).map(Number); + + return chainIds.every((chainId) => { + const olasBalance = olasBalancesByChain[chainId] || 0; + const olasRequired = + serviceFundRequirements[chainId]?.[TokenSymbol.OLAS] || 0; + + return olasBalance >= olasRequired; + }); + }, [masterSafeBalances, serviceFundRequirements]); const needsInitialFunding: boolean = useMemo(() => { if (isInitialFunded) return false; From 038f35efb1b5106235e7b93f6a8891b2ae702aa4 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 15:17:58 +0000 Subject: [PATCH 14/16] feat: rename ServiceStakingState to StakingState for consistency and clarity --- frontend/hooks/useStakingContractDetails.ts | 8 +++----- frontend/types/Autonolas.ts | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/frontend/hooks/useStakingContractDetails.ts b/frontend/hooks/useStakingContractDetails.ts index 41a8b34a..76bff9ba 100644 --- a/frontend/hooks/useStakingContractDetails.ts +++ b/frontend/hooks/useStakingContractDetails.ts @@ -3,7 +3,7 @@ import { useContext } from 'react'; import { StakingContractDetailsContext } from '@/context/StakingContractDetailsProvider'; import { StakingProgramId } from '@/enums/StakingProgram'; -import { ServiceStakingState } from '@/types/Autonolas'; +import { StakingState } from '@/types/Autonolas'; import { useServices } from './useServices'; @@ -65,12 +65,10 @@ export const useActiveStakingContractInfo = () => { maxNumServices, } = activeStakingContractDetails ?? {}; - const isAgentEvicted = - serviceStakingState === ServiceStakingState.EvictedOrUnstaked; + const isAgentEvicted = serviceStakingState === StakingState.Evicted; const isServiceStaked = - !!serviceStakingStartTime && - serviceStakingState === ServiceStakingState.Staked; + !!serviceStakingStartTime && serviceStakingState === StakingState.Staked; const isRewardsAvailable = availableRewards ?? 0 > 0; diff --git a/frontend/types/Autonolas.ts b/frontend/types/Autonolas.ts index 2c0e3fef..1194ece9 100644 --- a/frontend/types/Autonolas.ts +++ b/frontend/types/Autonolas.ts @@ -14,10 +14,10 @@ export const StakingRewardsInfoSchema = z.object({ export type StakingRewardsInfo = z.infer; -export enum ServiceStakingState { +export enum StakingState { NotStaked = 0, Staked = 1, - EvictedOrUnstaked = 2, + Evicted = 2, } export type StakingContractDetails = { @@ -29,8 +29,8 @@ export type StakingContractDetails = { minimumStakingDuration: number; /** time when service was staked (in seconds) - 0 = never staked */ serviceStakingStartTime: number; - /** 0: not staked, 1: staked, 2: unstaked - current state of the service */ - serviceStakingState: ServiceStakingState; + /** 0: not staked, 1: staked, 2: evicted */ + serviceStakingState: StakingState; /** OLAS cost of staking */ minStakingDeposit: number; /** estimated annual percentage yield */ From 38c4127d9e0eb3fa0a35b3170f535b909d47d081 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 21 Nov 2024 16:56:21 +0000 Subject: [PATCH 15/16] feat: refactor SettingsPage to use master wallet context and improve backup address handling --- frontend/components/SettingsPage/index.tsx | 42 ++++++++++++++++------ frontend/hooks/useMultisig.ts | 9 +++-- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/frontend/components/SettingsPage/index.tsx b/frontend/components/SettingsPage/index.tsx index e12725c9..a3c97cf1 100644 --- a/frontend/components/SettingsPage/index.tsx +++ b/frontend/components/SettingsPage/index.tsx @@ -1,5 +1,6 @@ import { CloseOutlined, SettingOutlined } from '@ant-design/icons'; import { Button, Card, Flex, Typography } from 'antd'; +import { isNil } from 'lodash'; import Link from 'next/link'; import { useMemo } from 'react'; @@ -11,7 +12,9 @@ import { SettingsScreen } from '@/enums/SettingsScreen'; import { useMultisig } from '@/hooks/useMultisig'; import { usePageState } from '@/hooks/usePageState'; import { useSettings } from '@/hooks/useSettings'; -import { useWalletContext } from '@/hooks/useWallet'; +import { useMasterWalletContext } from '@/hooks/useWallet'; +import { Address } from '@/types/Address'; +import { Optional } from '@/types/Util'; import { truncateAddress } from '@/utils/truncate'; import { CustomAlert } from '../Alert'; @@ -83,15 +86,34 @@ export const Settings = () => { }; const SettingsMain = () => { - const { wallets } = useWalletContext(); - const { backupSafeAddress } = useMultisig(); + const { masterEoa, masterSafes } = useMasterWalletContext(); + + const { owners } = useMultisig( + masterSafes?.[0], // TODO: all master safes should have the same address, but dirty implementation + ); + const { goto } = usePageState(); - const truncatedBackupSafeAddress: string | undefined = useMemo(() => { - if (backupSafeAddress) { - return truncateAddress(backupSafeAddress); + const masterSafeBackupAddresses = useMemo>(() => { + if (!owners) return; + if (!masterEoa) return; + + // TODO: handle edge cases where there are multiple owners due to middleware failure, or user interaction via safe.global + return owners.filter((owner) => owner !== masterEoa.address); + }, [owners, masterEoa]); + + const masterSafeBackupAddress = useMemo>(() => { + if (isNil(masterSafeBackupAddresses)) return; + if (!masterSafeBackupAddresses?.[0]) return; + + return masterSafeBackupAddresses[0]; + }, [masterSafeBackupAddresses]); + + const truncatedBackupSafeAddress: Optional = useMemo(() => { + if (masterSafeBackupAddress && masterSafeBackupAddress?.length) { + return truncateAddress(masterSafeBackupAddress); } - }, [backupSafeAddress]); + }, [masterSafeBackupAddress]); return ( { {/* Wallet backup */} Backup wallet - {backupSafeAddress ? ( + {masterSafeBackupAddress ? ( {truncatedBackupSafeAddress} {UNICODE_SYMBOLS.EXTERNAL_LINK} diff --git a/frontend/hooks/useMultisig.ts b/frontend/hooks/useMultisig.ts index 3793eb5e..1e6df3a8 100644 --- a/frontend/hooks/useMultisig.ts +++ b/frontend/hooks/useMultisig.ts @@ -15,14 +15,17 @@ import { Address } from '@/types/Address'; * @returns multisig owners * @note extend with further multisig functions as needed */ -export const useMultisig = (safe: Safe) => { +export const useMultisig = (safe?: Safe) => { const { data: owners, isFetched: ownersIsFetched, isPending: ownersIsPending, - } = useQuery({ - queryKey: REACT_QUERY_KEYS.MULTISIG_GET_OWNERS_KEY(safe), + } = useQuery({ + queryKey: safe ? REACT_QUERY_KEYS.MULTISIG_GET_OWNERS_KEY(safe) : [], queryFn: async () => { + if (!safe) { + return null; + } const contract = new Contract( safe.address, GNOSIS_SAFE_ABI, From 4c80e728cff3a732b7c02394e877542dbba97ebe Mon Sep 17 00:00:00 2001 From: Mohan Date: Fri, 22 Nov 2024 01:51:48 +0530 Subject: [PATCH 16/16] feat: refactor onboarding (#478) * feat: enhance StakingContractSection to use selected service's chain ID for contract details link * feat: update SetupWelcomeLogin to utilize selected service's chain ID for master safe and balance checks * feat: refactor Setup components for improved chain support and address validation * feat: enhance SetupCreateSafe and SetupEoaFunding components for improved error handling and user feedback * fix: remove redundant text and clean up SetupRestore component layout * Update frontend/components/SetupPage/Create/SetupEoaFunding.tsx Co-authored-by: Josh Miller <31908788+truemiller@users.noreply.github.com> * Update frontend/components/SetupPage/Create/SetupEoaFunding.tsx Co-authored-by: Josh Miller <31908788+truemiller@users.noreply.github.com> * Update frontend/components/SetupPage/Create/SetupEoaFunding.tsx Co-authored-by: Josh Miller <31908788+truemiller@users.noreply.github.com> * feat: refactor Setup components to use master wallet balances and simplify logic --------- Co-authored-by: Josh Miller <31908788+truemiller@users.noreply.github.com> --- frontend/components/Layout/TopBar.tsx | 4 +- .../StakingContractSection/index.tsx | 22 +- .../SetupPage/Create/SetupBackupSigner.tsx | 5 +- .../SetupPage/Create/SetupCreateSafe.tsx | 205 ++++++++++-------- .../SetupPage/Create/SetupEoaFunding.tsx | 93 ++++---- .../SetupPage/Create/SetupPassword.tsx | 3 +- .../SetupPage/Create/SetupSeedPhrase.tsx | 2 + .../components/SetupPage/SetupRestore.tsx | 3 + .../components/SetupPage/SetupWelcome.tsx | 37 +++- frontend/components/SetupPage/index.tsx | 6 +- frontend/config/mechs.ts | 9 +- frontend/config/stakingPrograms/index.ts | 14 +- frontend/constants/thresholds.ts | 10 +- frontend/pages/_app.tsx | 52 ++--- 14 files changed, 276 insertions(+), 189 deletions(-) diff --git a/frontend/components/Layout/TopBar.tsx b/frontend/components/Layout/TopBar.tsx index d552d243..9428fc7f 100644 --- a/frontend/components/Layout/TopBar.tsx +++ b/frontend/components/Layout/TopBar.tsx @@ -62,9 +62,7 @@ export const TopBar = () => { - - {`Pearl (Optimus) (alpha) ${envName ? `(${envName})` : ''}`.trim()} - + {`Pearl (alpha) ${envName ? `(${envName})` : ''}`.trim()} ); }; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/index.tsx b/frontend/components/ManageStakingPage/StakingContractSection/index.tsx index b23ffea3..51206d27 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/index.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/index.tsx @@ -1,13 +1,14 @@ import { Flex, Tag, theme, Typography } from 'antd'; import { useMemo } from 'react'; -import { MiddlewareChain } from '@/client'; import { CardSection } from '@/components/styled/CardSection'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { EXPLORER_URL } from '@/constants/urls'; import { StakingProgramId } from '@/enums/StakingProgram'; import { StakingProgramStatus } from '@/enums/StakingProgramStatus'; +import { useServices } from '@/hooks/useServices'; import { useStakingProgram } from '@/hooks/useStakingProgram'; +import { Maybe } from '@/types/Util'; import { CantMigrateAlert } from './CantMigrateAlert'; import { MigrateButton } from './MigrateButton'; @@ -41,6 +42,7 @@ export const StakingContractSection = ({ activeStakingProgramMeta, activeStakingProgramAddress, } = useStakingProgram(); + const { selectedService } = useServices(); // /** // * Returns `true` if this stakingProgram is active, @@ -84,6 +86,9 @@ export const StakingContractSection = ({ ); }, [migrateValidation]); + const chainId: Maybe = + selectedService?.home_chain_id; + return ( <> - - View contract details {UNICODE_SYMBOLS.EXTERNAL_LINK} - + + {chainId && ( + + View contract details {UNICODE_SYMBOLS.EXTERNAL_LINK} + + )} {!migrateValidation.canMigrate && ( { const [form] = Form.useForm(); const handleFinish = (values: { 'backup-signer': string }) => { + // important to lowercase the address before check summing, invalid checksums will cause ethers to throw + // returns null if invalid, ethers type is incorrect... const checksummedAddress = getAddress( - // important to lowercase the address before checksumming, invalid checksums will cause ethers to throw values['backup-signer'].toLowerCase(), - ) as Address | null; // returns null if invalid, ethers type is incorrect... + ) as Address | null; // If the address is invalid, show an error message if (!checksummedAddress) { diff --git a/frontend/components/SetupPage/Create/SetupCreateSafe.tsx b/frontend/components/SetupPage/Create/SetupCreateSafe.tsx index 2e16c158..d063157d 100644 --- a/frontend/components/SetupPage/Create/SetupCreateSafe.tsx +++ b/frontend/components/SetupPage/Create/SetupCreateSafe.tsx @@ -7,7 +7,6 @@ import { CardSection } from '@/components/styled/CardSection'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { SUPPORT_URL } from '@/constants/urls'; import { Pages } from '@/enums/Pages'; -import { useMultisig } from '@/hooks/useMultisig'; import { usePageState } from '@/hooks/usePageState'; import { useSetup } from '@/hooks/useSetup'; import { useMasterWalletContext } from '@/hooks/useWallet'; @@ -22,25 +21,60 @@ const capitalizedMiddlewareChainNames = { [+MiddlewareChain.OPTIMISM]: 'Optimism', }; +const YouWillBeRedirected = ({ text }: { text: string }) => ( + <> + logo + + {text} + + + You will be redirected once the account is created. + + +); + +const CreationError = () => ( + <> + logo + + Error, please restart the app and try again. + + + If the issue persists,{' '} + + contact Olas community support {UNICODE_SYMBOLS.EXTERNAL_LINK} + + . + + +); + export const SetupCreateSafe = () => { const { goto } = usePageState(); - const { - updateWallets, - masterSafeAddressKeyExistsForChain, - masterSafeAddress, - } = useMasterWalletContext(); - const { updateMasterSafeOwners } = useMultisig(); + const { masterSafes, refetch: updateWallets } = useMasterWalletContext(); + // const { updateMasterSafeOwners } = useMultisig(); const { backupSigner } = useSetup(); + const masterSafeAddress = useMemo(() => { + if (!masterSafes) return; + return masterSafes[0]?.address; + }, [masterSafes]); + const [isCreatingSafe, setIsCreatingSafe] = useState(false); - const [optimismFailed, setOptimismFailed] = useState(false); - const [ethereumFailed, setEthereumFailed] = useState(false); - const [baseFailed, setBaseFailed] = useState(false); + const [gnosisFailed, setGnosisFailed] = useState(false); + // const [optimismFailed, setOptimismFailed] = useState(false); + // const [ethereumFailed, setEthereumFailed] = useState(false); + // const [baseFailed, setBaseFailed] = useState(false); - const [isOptimismSuccess, setIsOptimismSuccess] = useState(false); - const [isEthereumSuccess, setIsEthereumSuccess] = useState(false); - const [isBaseSuccess, setIsBaseSuccess] = useState(false); + const [isGnosisSuccess, setIsGnosisSuccess] = useState(false); + // const [isOptimismSuccess, setIsOptimismSuccess] = useState(false); + // const [isEthereumSuccess, setIsEthereumSuccess] = useState(false); + // const [isBaseSuccess, setIsBaseSuccess] = useState(false); const createSafeWithRetries = useCallback( async (middlewareChain: MiddlewareChain, retries: number) => { @@ -48,21 +82,28 @@ export const SetupCreateSafe = () => { // If we have retried too many times, set failed if (retries <= 0) { - if (middlewareChain === MiddlewareChain.OPTIMISM) { - setOptimismFailed(true); - setIsOptimismSuccess(false); - throw new Error('Failed to create safe on Ethereum'); - } - if (middlewareChain === MiddlewareChain.ETHEREUM) { - setEthereumFailed(true); - setIsEthereumSuccess(false); - throw new Error('Failed to create safe on Ethereum'); - } - if (middlewareChain === MiddlewareChain.BASE) { - setBaseFailed(true); - setIsBaseSuccess(false); + // if (middlewareChain === MiddlewareChain.OPTIMISM) { + // setOptimismFailed(true); + // setIsOptimismSuccess(false); + // throw new Error('Failed to create safe on Ethereum'); + // } + // if (middlewareChain === MiddlewareChain.ETHEREUM) { + // setEthereumFailed(true); + // setIsEthereumSuccess(false); + // throw new Error('Failed to create safe on Ethereum'); + // } + // if (middlewareChain === MiddlewareChain.BASE) { + // setBaseFailed(true); + // setIsBaseSuccess(false); + // throw new Error('Failed to create safe on Base'); + // } + + if (middlewareChain === MiddlewareChain.GNOSIS) { + setGnosisFailed(true); + setIsGnosisSuccess(false); throw new Error('Failed to create safe on Base'); } + throw new Error('Failed to create safe as chain is not supported'); } @@ -71,20 +112,23 @@ export const SetupCreateSafe = () => { .then(async () => { // Attempt wallet and master safe updates before proceeding try { - await updateWallets(); - await updateMasterSafeOwners(); + await updateWallets?.(); + // await updateMasterSafeOwners(); } catch (e) { console.error(e); } // Set states for successful creation setIsCreatingSafe(false); - setOptimismFailed(false); + // setOptimismFailed(false); + setGnosisFailed(false); }) .catch(async (e) => { console.error(e); + // Wait for 5 seconds before retrying await delayInSeconds(5); + // Retry const newRetries = retries - 1; if (newRetries <= 0) { @@ -95,7 +139,11 @@ export const SetupCreateSafe = () => { createSafeWithRetries(middlewareChain, newRetries); }); }, - [backupSigner, updateMasterSafeOwners, updateWallets], + [ + backupSigner, + // updateMasterSafeOwners, + updateWallets, + ], ); const creationStatusText = useMemo(() => { @@ -109,37 +157,47 @@ export const SetupCreateSafe = () => { /** * Avoid creating safes if any of the following conditions are met: */ - [optimismFailed, baseFailed, ethereumFailed].some((x) => x) || // any of the chains failed + [ + // optimismFailed, baseFailed, ethereumFailed + gnosisFailed, + ].some((x) => x) || // any of the chains failed isCreatingSafe //|| // already creating a safe // [isBaseSuccess, isEthereumSuccess, isOptimismSuccess].some((x) => !x) // any of the chains are not successful ) return; const chainsToCreateSafesFor = { - [MiddlewareChain.OPTIMISM]: masterSafeAddressKeyExistsForChain( - MiddlewareChain.OPTIMISM, - ), - [MiddlewareChain.ETHEREUM]: masterSafeAddressKeyExistsForChain( - MiddlewareChain.ETHEREUM, - ), - [MiddlewareChain.BASE]: masterSafeAddressKeyExistsForChain( - MiddlewareChain.BASE, - ), + // [MiddlewareChain.OPTIMISM]: masterSafeAddressKeyExistsForChain( + // MiddlewareChain.OPTIMISM, + // ), + // [MiddlewareChain.ETHEREUM]: masterSafeAddressKeyExistsForChain( + // MiddlewareChain.ETHEREUM, + // ), + // [MiddlewareChain.BASE]: masterSafeAddressKeyExistsForChain( + // MiddlewareChain.BASE, + // ), + [MiddlewareChain.GNOSIS]: !!masterSafeAddress, }; const safeCreationsRequired = Object.entries(chainsToCreateSafesFor).reduce( (acc, [chain, safeAddressAlreadyExists]) => { const middlewareChain = +chain as MiddlewareChain; if (safeAddressAlreadyExists) { + // switch (middlewareChain) { + // case MiddlewareChain.OPTIMISM: + // setIsOptimismSuccess(true); + // break; + // case MiddlewareChain.ETHEREUM: + // setIsEthereumSuccess(true); + // break; + // case MiddlewareChain.BASE: + // setIsBaseSuccess(true); + // break; + // } + switch (middlewareChain) { - case MiddlewareChain.OPTIMISM: - setIsOptimismSuccess(true); - break; - case MiddlewareChain.ETHEREUM: - setIsEthereumSuccess(true); - break; - case MiddlewareChain.BASE: - setIsBaseSuccess(true); + case MiddlewareChain.GNOSIS: + setIsGnosisSuccess(true); break; } return acc; @@ -169,14 +227,16 @@ export const SetupCreateSafe = () => { }, [ backupSigner, createSafeWithRetries, - optimismFailed, + masterSafeAddress, isCreatingSafe, - isBaseSuccess, - isEthereumSuccess, - isOptimismSuccess, - baseFailed, - ethereumFailed, - masterSafeAddressKeyExistsForChain, + // optimismFailed, + // isBaseSuccess, + // isEthereumSuccess, + // isOptimismSuccess, + // baseFailed, + // ethereumFailed, + isGnosisSuccess, + gnosisFailed, ]); useEffect(() => { @@ -193,39 +253,10 @@ export const SetupCreateSafe = () => { padding="80px 24px" gap={12} > - {optimismFailed ? ( - <> - logo - - Error, please restart the app and try again. - - - If the issue persists,{' '} - - contact Olas community support {UNICODE_SYMBOLS.EXTERNAL_LINK} - - . - - + {gnosisFailed ? ( + ) : ( - <> - logo - - {creationStatusText} - - - You will be redirected once the account is created. - - + )} diff --git a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx index 9b566ca3..f9042667 100644 --- a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx +++ b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx @@ -1,7 +1,7 @@ import { CopyOutlined } from '@ant-design/icons'; import { Flex, message, Tooltip, Typography } from 'antd'; import { BigNumber, ethers } from 'ethers'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; import { useInterval } from 'usehooks-ts'; @@ -10,15 +10,14 @@ import { CustomAlert } from '@/components/Alert'; import { CardFlex } from '@/components/styled/CardFlex'; import { CardSection } from '@/components/styled/CardSection'; import { CHAIN_CONFIG } from '@/config/chains'; -import { - BASE_PROVIDER, - ETHEREUM_PROVIDER, - OPTIMISM_PROVIDER, -} from '@/constants/providers'; +import { PROVIDERS } from '@/constants/providers'; +import { NA } from '@/constants/symbols'; import { MIN_ETH_BALANCE_THRESHOLDS } from '@/constants/thresholds'; +import { ChainId } from '@/enums/Chain'; import { SetupScreen } from '@/enums/SetupScreen'; +import { useMasterBalances } from '@/hooks/useBalanceContext'; import { useSetup } from '@/hooks/useSetup'; -import { useWallet } from '@/hooks/useWallet'; +import { useMasterWalletContext } from '@/hooks/useWallet'; import { Address } from '@/types/Address'; import { copyToClipboard } from '@/utils/copyToClipboard'; import { delayInSeconds } from '@/utils/delay'; @@ -40,9 +39,18 @@ const AccountCreationCard = styled.div` const ICON_STYLE = { color: '#606F85' }; +const statusMessage = (isFunded?: boolean) => { + if (isFunded) { + return 'Funds have been received!'; + } else { + return 'Waiting for transaction'; + } +}; + type SetupEoaFundingWaitingProps = { chainName: string }; const SetupEoaFundingWaiting = ({ chainName }: SetupEoaFundingWaitingProps) => { - const { masterEoaAddress } = useWallet(); + const { masterEoa } = useMasterWalletContext(); + const masterEoaAddress = masterEoa?.address; return ( <> @@ -80,7 +88,7 @@ const SetupEoaFundingWaiting = ({ chainName }: SetupEoaFundingWaitingProps) => { - {`ETH: ${masterEoaAddress}`} + {`XDAI: ${masterEoaAddress || NA}`} {/* { const { goto } = useSetup(); - const statusMessage = useMemo(() => { - if (isFunded) { - return 'Funds have been received!'; - } else { - return 'Waiting for transaction'; - } - }, [isFunded]); - useEffect(() => { message.success(`${chainName} funds have been received!`); @@ -141,7 +141,7 @@ export const SetupEoaFundingForChain = ({ borderbottom={isFunded ? 'true' : 'false'} > - Status: {statusMessage} + Status: {statusMessage(isFunded)}
{!isFunded && } @@ -149,29 +149,38 @@ export const SetupEoaFundingForChain = ({ ); }; +// TODO: chain independent const eoaFundingMap = { - [MiddlewareChain.OPTIMISM]: { - provider: OPTIMISM_PROVIDER, - chainConfig: CHAIN_CONFIG.OPTIMISM, - requiredEth: - MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.OPTIMISM].safeCreation, - }, - [MiddlewareChain.ETHEREUM]: { - provider: ETHEREUM_PROVIDER, - chainConfig: CHAIN_CONFIG.ETHEREUM, - requiredEth: - MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.ETHEREUM].safeCreation, - }, - [MiddlewareChain.BASE]: { - provider: BASE_PROVIDER, - chainConfig: CHAIN_CONFIG.BASE, - requiredEth: MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.BASE].safeCreation, + // [MiddlewareChain.OPTIMISM]: { + // provider: OPTIMISM_PROVIDER, + // chainConfig: CHAIN_CONFIG.OPTIMISM, + // requiredEth: + // MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.OPTIMISM].safeCreation, + // }, + // [MiddlewareChain.ETHEREUM]: { + // provider: ETHEREUM_PROVIDER, + // chainConfig: CHAIN_CONFIG.ETHEREUM, + // requiredEth: + // MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.ETHEREUM].safeCreation, + // }, + // [MiddlewareChain.BASE]: { + // provider: BASE_PROVIDER, + // chainConfig: CHAIN_CONFIG.BASE, + // requiredEth: MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.BASE].safeCreation, + // }, + [MiddlewareChain.GNOSIS]: { + provider: PROVIDERS[ChainId.Gnosis].provider, + chainConfig: CHAIN_CONFIG[ChainId.Gnosis], + requiredEth: MIN_ETH_BALANCE_THRESHOLDS[ChainId.Gnosis].safeCreation, }, }; export const SetupEoaFunding = () => { const { goto } = useSetup(); - const { masterEoaAddress } = useWallet(); + const { masterEoa } = useMasterWalletContext(); + const { masterWalletBalances } = useMasterBalances(); + const masterEoaAddress = masterEoa?.address; + const [currentChain, setCurrentChain] = useState( +Object.keys(eoaFundingMap)[0] as MiddlewareChain, ); @@ -225,6 +234,14 @@ export const SetupEoaFunding = () => { goto(SetupScreen.SetupCreateSafe); }, 5000); + const eoaBalance = masterWalletBalances?.find( + (balance) => balance.walletAddress === masterEoaAddress, + ); + const isFunded = + eoaBalance?.chainId === ChainId.Gnosis && + eoaBalance.balance >= + MIN_ETH_BALANCE_THRESHOLDS[ChainId.Gnosis].safeCreation; + return ( @@ -235,15 +252,15 @@ export const SetupEoaFunding = () => { The app needs these funds to create your account on-chain. - {/* - Status: {statusMessage} + Status: {statusMessage(isFunded)} - */} + { const [form] = Form.useForm<{ password: string; terms: boolean }>(); const [isLoading, setIsLoading] = useState(false); - const isTermsAccepted = Form.useWatch('terms', form); const handleCreateEoa = async ({ password }: { password: string }) => { @@ -26,7 +25,7 @@ export const SetupPassword = () => { setIsLoading(true); AccountService.createAccount(password) .then(() => AccountService.loginAccount(password)) - .then(() => WalletService.createEoa(MiddlewareChain.OPTIMISM)) + .then(() => WalletService.createEoa(MiddlewareChain.GNOSIS)) // TODO: chain independent .then(({ mnemonic }: { mnemonic: string[] }) => { setMnemonic(mnemonic); goto(SetupScreen.SetupSeedPhrase); diff --git a/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx b/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx index 46a8d1bc..dd8811f6 100644 --- a/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx +++ b/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx @@ -18,6 +18,7 @@ export const SetupSeedPhrase = () => { Back up seed phrase + Seed phrase is needed to regain access to your account if you forget @@ -33,6 +34,7 @@ export const SetupSeedPhrase = () => { ))} + + If you don’t have the seed phrase but added a backup wallet to your @@ -134,6 +136,7 @@ export const SetupRestoreViaSeed = () => { export const SetupRestoreSetPassword = () => { const { goto } = useSetup(); const [password, setPassword] = useState(''); + return ( { const { goto } = useSetup(); const { goto: gotoPage } = usePageState(); - const { masterSafeAddress, masterWallets: wallets } = - useMasterWalletContext(); - const { isBalanceLoaded, masterEoaBalance: eoaBalance } = useBalanceContext(); + const { selectedService } = useServices(); + const { + masterSafes, + masterWallets: wallets, + masterEoa, + } = useMasterWalletContext(); + const { isLoaded } = useBalanceContext(); + const { masterWalletBalances } = useMasterBalances(); + + const masterSafe = + masterSafes?.find( + (safe) => safe.chainId === selectedService?.home_chain_id, + ) ?? null; + const eoaBalanceEth = masterWalletBalances?.find( + (balance) => balance.walletAddress === masterEoa?.address, + ); const [isLoggingIn, setIsLoggingIn] = useState(false); const [canNavigate, setCanNavigate] = useState(false); @@ -157,11 +174,11 @@ export const SetupWelcomeLogin = () => { useEffect(() => { // Navigate only when wallets and balances are loaded // To check if some setup steps were missed - if (canNavigate && wallets?.length && isBalanceLoaded) { + if (canNavigate && wallets?.length && isLoaded) { setIsLoggingIn(false); - if (!eoaBalance?.ETH) { + if (!eoaBalanceEth) { goto(SetupScreen.SetupEoaFundingIncomplete); - } else if (!masterSafeAddress) { + } else if (!masterSafe?.address) { goto(SetupScreen.SetupCreateSafe); } else { gotoPage(Pages.Main); @@ -169,11 +186,11 @@ export const SetupWelcomeLogin = () => { } }, [ canNavigate, - eoaBalance?.ETH, + eoaBalanceEth, goto, gotoPage, - isBalanceLoaded, - masterSafeAddress, + isLoaded, + masterSafe?.address, wallets?.length, ]); diff --git a/frontend/components/SetupPage/index.tsx b/frontend/components/SetupPage/index.tsx index 412f4bc8..935ac281 100644 --- a/frontend/components/SetupPage/index.tsx +++ b/frontend/components/SetupPage/index.tsx @@ -16,6 +16,10 @@ import { } from './SetupRestore'; import { SetupWelcome } from './SetupWelcome'; +const UnexpectedError = () => ( +
Something went wrong!
+); + export const Setup = () => { const { setupObject } = useContext(SetupContext); const setupScreen = useMemo(() => { @@ -45,7 +49,7 @@ export const Setup = () => { case SetupScreen.RestoreViaBackup: return ; default: - return <>Error; + return ; } }, [setupObject.state]); diff --git a/frontend/config/mechs.ts b/frontend/config/mechs.ts index 37517185..c55eb15c 100644 --- a/frontend/config/mechs.ts +++ b/frontend/config/mechs.ts @@ -1,3 +1,4 @@ +import { JsonFragment } from '@ethersproject/abi'; import { Contract as MulticallContract } from 'ethers-multicall'; import { AGENT_MECH_ABI } from '@/abis/agentMech'; @@ -24,14 +25,18 @@ export const MECHS: Mechs = { name: 'Agent Mech', contract: new MulticallContract( '0x77af31De935740567Cf4fF1986D04B2c964A786a', - AGENT_MECH_ABI, + AGENT_MECH_ABI.filter( + (abi) => (abi as JsonFragment).type === 'function', + ) as JsonFragment[], ), }, [MechType.Marketplace]: { name: 'Mech Marketplace', contract: new MulticallContract( '0x4554fE75c1f5576c1d7F765B2A036c199Adae329', - MECH_MARKETPLACE_ABI, + MECH_MARKETPLACE_ABI.filter( + (abi) => (abi as JsonFragment).type === 'function', + ) as JsonFragment[], ), }, }, diff --git a/frontend/config/stakingPrograms/index.ts b/frontend/config/stakingPrograms/index.ts index 8c4be8c6..8c22a192 100644 --- a/frontend/config/stakingPrograms/index.ts +++ b/frontend/config/stakingPrograms/index.ts @@ -10,10 +10,10 @@ import { GNOSIS_STAKING_PROGRAMS, GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES, } from './gnosis'; -import { - OPTIMISM_STAKING_PROGRAMS, - OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, -} from './optimism'; +// import { +// OPTIMISM_STAKING_PROGRAMS, +// OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, +// } from './optimism'; /** * Single non-chain specific staking program configuration @@ -40,19 +40,19 @@ export const STAKING_PROGRAMS: { [chainId: number | ChainId]: StakingProgramMap; } = { [ChainId.Gnosis]: GNOSIS_STAKING_PROGRAMS, - [ChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS, + // [ChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS, }; export const STAKING_PROGRAM_ADDRESS: { [chainId: number | ChainId]: Record; } = { [ChainId.Gnosis]: GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES, - [ChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, + // [ChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, }; export const INITIAL_DEFAULT_STAKING_PROGRAM_IDS: { [chainId: number | ChainId]: StakingProgramId; } = { [ChainId.Gnosis]: StakingProgramId.PearlBeta, - [ChainId.Optimism]: StakingProgramId.OptimusAlpha, + // [ChainId.Optimism]: StakingProgramId.OptimusAlpha, }; diff --git a/frontend/constants/thresholds.ts b/frontend/constants/thresholds.ts index 09d2b0c4..e85fa308 100644 --- a/frontend/constants/thresholds.ts +++ b/frontend/constants/thresholds.ts @@ -1,13 +1,15 @@ import { ChainId } from '@/enums/Chain'; +// TODO + /** * @warning must be updated to be dynamic */ export const MIN_ETH_BALANCE_THRESHOLDS = { - // [Chain.GNOSIS]: { - // safeCreation: 1.5, - // safeAddSigner: 0.1, - // }, + [ChainId.Gnosis]: { + safeCreation: 1.5, + safeAddSigner: 0.1, + }, [ChainId.Optimism]: { safeCreation: 0.005, safeAddSigner: 0.005, diff --git a/frontend/pages/_app.tsx b/frontend/pages/_app.tsx index 86d81156..63ecbdf7 100644 --- a/frontend/pages/_app.tsx +++ b/frontend/pages/_app.tsx @@ -38,37 +38,37 @@ export default function App({ Component, pageProps }: AppProps) { - - - - - - - - - - - - {isMounted ? ( - + + + + + + + + + + + + + {isMounted ? ( - - ) : null} - - - - - - - - - - - + ) : null} + + + + + + + + + + + +