From fd03faca6b7fc93cff49a1b4c285898fb545f914 Mon Sep 17 00:00:00 2001 From: truemiller Date: Tue, 17 Dec 2024 14:38:45 +0000 Subject: [PATCH 01/13] refactor: update balance calculations in AgentNotRunningButton for improved accuracy --- .../AgentButton/AgentNotRunningButton.tsx | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx index 86c2d4c9..60e51430 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -69,16 +69,20 @@ export const AgentNotRunningButton = () => { selectedService?.service_config_id, ); - const serviceStakedOlasBalanceOnHomeChain = serviceStakedBalances?.find( + const serviceStakedOlasBalancesOnHomeChain = serviceStakedBalances?.find( (stakedBalance) => stakedBalance.evmChainId === selectedAgentConfig.evmHomeChainId, ); const serviceTotalStakedOlas = sum([ - serviceStakedOlasBalanceOnHomeChain?.olasBondBalance, - serviceStakedOlasBalanceOnHomeChain?.olasDepositBalance, + serviceStakedOlasBalancesOnHomeChain?.olasBondBalance, + serviceStakedOlasBalancesOnHomeChain?.olasDepositBalance, ]); + const serviceOlasBalanceOnHomeChain = serviceSafeBalances?.find( + (balance) => balance.evmChainId === selectedAgentConfig.evmHomeChainId, + )?.balance; + const { masterSafeBalances, masterSafeNativeGasBalance } = useMasterBalances(); @@ -103,7 +107,10 @@ export const AgentNotRunningButton = () => { selectedStakingProgramId ]?.stakingRequirements[TokenSymbol.OLAS]; - const serviceSafeOlasWithStaked = sum([totalStakedOlasBalance]); + const serviceSafeOlasWithStaked = sum([ + serviceOlasBalanceOnHomeChain, + serviceTotalStakedOlas, + ]); const isDeployable = useMemo(() => { if (isServicesLoading) return false; @@ -143,25 +150,27 @@ export const AgentNotRunningButton = () => { selectedAgentConfig.operatingThresholds[WalletOwnerType.Master]; const tokenSymbol = CHAIN_CONFIG[selectedAgentConfig.evmHomeChainId].nativeToken.symbol; - const agentSafeNativeBalance = serviceSafeBalances?.find( - ({ symbol }) => symbol === tokenSymbol, - )?.balance; + const safeThreshold = masterThresholds[WalletType.Safe][tokenSymbol]; + // SERVICE IS STAKED, AND STARTING AGAIN if (isServiceStaked) { - const hasEnoughOlas = - (serviceSafeOlasWithStaked ?? 0) >= requiredStakedOlas; + const hasEnoughOlas = serviceSafeOlasWithStaked >= requiredStakedOlas; - // @note: Funds are transferred to the agent safe from the master safe. - // Hence, if the agent safe has enough funds, it is considered as enough. const hasEnoughNativeGas = - (masterSafeNativeGasBalance ?? 0) > safeThreshold || - (agentSafeNativeBalance ?? 0) > safeThreshold; - return hasEnoughOlas && hasEnoughNativeGas; + (masterSafeNativeGasBalance ?? 0) > safeThreshold; + return hasEnoughNativeGas && hasEnoughOlas; } + // SERVICE IS NOT STAKED AND/OR IS STARTING FOR THE FIRST TIME + const totalOlasStakedAndInSafes = sum([ + serviceOlasBalanceOnHomeChain, + serviceTotalStakedOlas, + masterSafeOlasBalance, + ]); + const hasEnoughForInitialDeployment = - (masterSafeOlasBalance ?? 0) >= requiredStakedOlas && + (totalOlasStakedAndInSafes ?? 0) >= requiredStakedOlas && (masterSafeNativeGasBalance ?? 0) >= safeThreshold; return hasEnoughForInitialDeployment; @@ -176,14 +185,14 @@ export const AgentNotRunningButton = () => { service, storeState, selectedAgentType, - isEligibleForStaking, isAgentEvicted, - masterSafeNativeGasBalance, + isEligibleForStaking, selectedAgentConfig.operatingThresholds, selectedAgentConfig.evmHomeChainId, + serviceOlasBalanceOnHomeChain, serviceTotalStakedOlas, + masterSafeNativeGasBalance, serviceSafeOlasWithStaked, - serviceSafeBalances, ]); const pauseAllPolling = useCallback(() => { From 2fb1dcd3d74d590dd227ad4cb95934f81ee5e6fd Mon Sep 17 00:00:00 2001 From: truemiller Date: Tue, 17 Dec 2024 14:39:46 +0000 Subject: [PATCH 02/13] refactor: simplify balance context usage in AgentNotRunningButton component --- .../MainPage/header/AgentButton/AgentNotRunningButton.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx index 60e51430..6d0ed723 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -59,11 +59,8 @@ export const AgentNotRunningButton = () => { selectedService?.service_config_id, ); - const { - setIsPaused: setIsBalancePollingPaused, - totalStakedOlasBalance, - updateBalances, - } = useBalanceContext(); + const { setIsPaused: setIsBalancePollingPaused, updateBalances } = + useBalanceContext(); const { serviceStakedBalances, serviceSafeBalances } = useServiceBalances( selectedService?.service_config_id, From 1980a31c270ef42a91c720a73e07a7f1cc3a8253 Mon Sep 17 00:00:00 2001 From: truemiller Date: Tue, 17 Dec 2024 15:34:51 +0000 Subject: [PATCH 03/13] chore: bump version to 0.2.0-rc39 in package.json and pyproject.toml --- package.json | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 61497686..86060bb8 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "start:frontend": "cd frontend && yarn start", "test:frontend": "cd frontend && yarn test" }, - "version": "0.2.0-rc36", + "version": "0.2.0-rc39", "engine": { "node": ">=20", "yarn": ">=1.22.0", diff --git a/pyproject.toml b/pyproject.toml index dc9cc21a..51f88e2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "olas-operate-middleware" -version = "0.2.0-rc36" +version = "0.2.0-rc39" description = "" authors = ["David Vilela ", "Viraj Patel "] readme = "README.md" From 1243e2e14b01bc8c53fcf44cece079e894af61b2 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 16:44:55 +0530 Subject: [PATCH 04/13] feat: enhance wallet page components with middleware chain support --- frontend/components/YourWalletPage/Titles.tsx | 15 +++- frontend/components/YourWalletPage/index.tsx | 82 +++++++++---------- frontend/hooks/useFeatureFlag.ts | 2 +- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/frontend/components/YourWalletPage/Titles.tsx b/frontend/components/YourWalletPage/Titles.tsx index c5f46af9..7a6cb8e9 100644 --- a/frontend/components/YourWalletPage/Titles.tsx +++ b/frontend/components/YourWalletPage/Titles.tsx @@ -1,5 +1,6 @@ import { Flex, Typography } from 'antd'; +import { MiddlewareChain } from '@/client'; import { InfoTooltip } from '@/components/InfoTooltip'; import { TokenSymbol } from '@/enums/Token'; import { Address } from '@/types/Address'; @@ -8,11 +9,16 @@ import { AddressLink } from '../AddressLink'; const { Paragraph, Text, Title } = Typography; -type SignerTitleProps = { signerText: string; signerAddress?: Address }; +type SignerTitleProps = { + signerText: string; + signerAddress: Address; + middlewareChain: MiddlewareChain; +}; export const SignerTitle = ({ signerText, signerAddress, + middlewareChain, }: SignerTitleProps) => ( <> Signer  @@ -28,7 +34,10 @@ export const SignerTitle = ({ {signerText} - + @@ -58,7 +67,7 @@ export const NativeTokenTitle = ({ symbol }: { symbol: TokenSymbol }) => (   - {/* TODO: address multi-agent tooltip, specfic to agent config */} + {/* TODO: address multi-agent tooltip, specific to agent config */} {symbol} is used by the agent to engage in prediction markets. This amount will fluctuate based on your agent's performance. diff --git a/frontend/components/YourWalletPage/index.tsx b/frontend/components/YourWalletPage/index.tsx index 3a221f40..e487405c 100644 --- a/frontend/components/YourWalletPage/index.tsx +++ b/frontend/components/YourWalletPage/index.tsx @@ -7,7 +7,7 @@ import { ThemeConfig, Typography, } from 'antd'; -import { isEmpty, isNil } from 'lodash'; +import { isNil } from 'lodash'; import { useMemo } from 'react'; import { AddressLink } from '@/components/AddressLink'; @@ -15,7 +15,6 @@ import { CardTitle } from '@/components/Card/CardTitle'; import { InfoBreakdownList } from '@/components/InfoBreakdown'; import { CardFlex } from '@/components/styled/CardFlex'; import { getNativeTokenSymbol } from '@/config/tokens'; -import { EvmChainId } from '@/enums/Chain'; import { Pages } from '@/enums/Pages'; import { TokenSymbol } from '@/enums/Token'; import { @@ -43,13 +42,26 @@ const yourWalletTheme: ThemeConfig = { }, }; -const Address = () => { - const { masterSafes } = useMasterWalletContext(); +const useYourWallet = () => { + const { selectedAgentConfig } = useServices(); + const { isLoading: isMasterSafeLoading, masterSafes } = + useMasterWalletContext(); + + return { + middlewareChain: selectedAgentConfig?.middlewareHomeChainId, + evmHomeChainId: selectedAgentConfig?.evmHomeChainId, + isMasterSafeLoading, + masterSafeAddress: masterSafes?.find( + ({ evmChainId }) => evmChainId === selectedAgentConfig?.evmHomeChainId, + )?.address, + }; +}; - if (!masterSafes) return ; - if (isEmpty(masterSafes)) return null; +const Address = () => { + const { isMasterSafeLoading, masterSafeAddress, middlewareChain } = + useYourWallet(); - const masterSafeAddress = masterSafes[0].address; // TODO: handle multiple safes in future + if (isMasterSafeLoading) return ; return ( @@ -58,7 +70,12 @@ const Address = () => { { left: 'Address', leftClassName: 'text-light', - right: , + right: ( + + ), rightClassName: 'font-normal', }, ]} @@ -107,49 +124,34 @@ const OlasBalance = () => { }; const MasterSafeNativeBalance = () => { - const { selectedAgentConfig } = useServices(); - const { masterSafes } = useMasterWalletContext(); + const { evmHomeChainId, masterSafeAddress } = useYourWallet(); const { masterSafeBalances } = useMasterBalances(); - const selectedMasterSafe = useMemo(() => { - if (!masterSafes) return; - if (!selectedAgentConfig) return; + const nativeTokenSymbol = getNativeTokenSymbol(evmHomeChainId); - return masterSafes.find( - (masterSafe) => - masterSafe.evmChainId === selectedAgentConfig.evmHomeChainId, - ); - }, [masterSafes, selectedAgentConfig]); - - const selectedMasterSafeNativeBalance: Optional = useMemo(() => { - if (isNil(selectedMasterSafe)) return; + const masterSafeNativeBalance: Optional = useMemo(() => { + if (isNil(masterSafeAddress)) return; if (isNil(masterSafeBalances)) return; return masterSafeBalances .filter(({ walletAddress, evmChainId, isNative }) => { return ( - evmChainId === selectedAgentConfig?.evmHomeChainId && // TODO: address multi chain, need to refactor as per product requirement + evmChainId === evmHomeChainId && // TODO: address multi chain, need to refactor as per product requirement isNative && - walletAddress === selectedMasterSafe.address + walletAddress === masterSafeAddress ); }) .reduce((acc, { balance }) => acc + balance, 0); - }, [ - masterSafeBalances, - selectedAgentConfig?.evmHomeChainId, - selectedMasterSafe, - ]); - - const nativeTokenSymbol = getNativeTokenSymbol(EvmChainId.Gnosis); + }, [masterSafeBalances, masterSafeAddress, evmHomeChainId]); return ( {getNativeTokenSymbol(EvmChainId.Gnosis)}, + left: {nativeTokenSymbol}, leftClassName: 'text-light', - right: `${balanceFormat(selectedMasterSafeNativeBalance, 2)} ${nativeTokenSymbol}`, + right: `${balanceFormat(masterSafeNativeBalance, 2)} ${nativeTokenSymbol}`, }, ]} parentStyle={infoBreakdownParentStyle} @@ -161,7 +163,9 @@ const MasterSafeNativeBalance = () => { const MasterEoaSignerNativeBalance = () => { const { masterEoa } = useMasterWalletContext(); const { masterWalletBalances } = useMasterBalances(); - const { selectedAgentConfig } = useServices(); + const { evmHomeChainId, middlewareChain } = useYourWallet(); + + const nativeTokenSymbol = getNativeTokenSymbol(evmHomeChainId); const masterEoaBalance: Optional = useMemo(() => { if (isNil(masterEoa)) return; @@ -172,25 +176,21 @@ const MasterEoaSignerNativeBalance = () => { ({ walletAddress, isNative, evmChainId }) => walletAddress === masterEoa.address && isNative && - selectedAgentConfig?.evmHomeChainId === evmChainId, // TODO: address multi chain, need to refactor as per product requirement + evmHomeChainId === evmChainId, // TODO: address multi chain, need to refactor as per product requirement ) .reduce((acc, { balance }) => acc + balance, 0); - }, [masterEoa, masterWalletBalances, selectedAgentConfig?.evmHomeChainId]); - - const nativeTokenSymbol = useMemo( - () => getNativeTokenSymbol(EvmChainId.Gnosis), // TODO: support multi chain - [], - ); + }, [masterEoa, masterWalletBalances, evmHomeChainId]); return ( ), leftClassName: 'text-light', diff --git a/frontend/hooks/useFeatureFlag.ts b/frontend/hooks/useFeatureFlag.ts index bfd9ec18..684a3afd 100644 --- a/frontend/hooks/useFeatureFlag.ts +++ b/frontend/hooks/useFeatureFlag.ts @@ -33,7 +33,7 @@ const FEATURES_CONFIG = FeaturesConfigSchema.parse({ 'low-funds': true, }, [AgentType.Memeooorr]: { - 'manage-wallet': false, + 'manage-wallet': true, 'last-transactions': false, 'rewards-streak': false, 'staking-contract-section': false, From f1bb7c4592eb121b6503364e1e4e2b6cf8af3c7e Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 16:52:03 +0530 Subject: [PATCH 05/13] feat: add feature flag for conditional rendering of WithdrawFunds component --- .../components/YourWalletPage/YourAgent.tsx | 17 +++++++++++------ frontend/hooks/useFeatureFlag.ts | 5 ++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/frontend/components/YourWalletPage/YourAgent.tsx b/frontend/components/YourWalletPage/YourAgent.tsx index 271cfa80..5c753f19 100644 --- a/frontend/components/YourWalletPage/YourAgent.tsx +++ b/frontend/components/YourWalletPage/YourAgent.tsx @@ -14,6 +14,7 @@ import { useBalanceContext, useServiceBalances, } from '@/hooks/useBalanceContext'; +import { useFeatureFlag } from '@/hooks/useFeatureFlag'; import { useReward } from '@/hooks/useReward'; import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; @@ -273,9 +274,13 @@ const YourAgentWalletBreakdown = () => { ); }; -export const YourAgentWallet = () => ( - <> - - - -); +export const YourAgentWallet = () => { + const isWithdrawFundsEnabled = useFeatureFlag('withdraw-funds'); + + return ( + <> + + {isWithdrawFundsEnabled && } + + ); +}; diff --git a/frontend/hooks/useFeatureFlag.ts b/frontend/hooks/useFeatureFlag.ts index 684a3afd..cba25363 100644 --- a/frontend/hooks/useFeatureFlag.ts +++ b/frontend/hooks/useFeatureFlag.ts @@ -6,8 +6,9 @@ import { assertRequired } from '@/types/Util'; import { useServices } from './useServices'; const FeatureFlagsSchema = z.enum([ - 'last-transactions', 'manage-wallet', + 'withdraw-funds', + 'last-transactions', 'rewards-streak', 'staking-contract-section', 'low-funds', @@ -27,6 +28,7 @@ const FeaturesConfigSchema = z.record( const FEATURES_CONFIG = FeaturesConfigSchema.parse({ [AgentType.PredictTrader]: { 'manage-wallet': true, + 'withdraw-funds': true, 'last-transactions': true, 'rewards-streak': true, 'staking-contract-section': true, @@ -34,6 +36,7 @@ const FEATURES_CONFIG = FeaturesConfigSchema.parse({ }, [AgentType.Memeooorr]: { 'manage-wallet': true, + 'withdraw-funds': false, 'last-transactions': false, 'rewards-streak': false, 'staking-contract-section': false, From 437ab496797db3710d702b1749b90ed01d542dbd Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 16:53:50 +0530 Subject: [PATCH 06/13] feat: disable withdrawal for mememooorr --- frontend/components/YourWalletPage/WithdrawFunds.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/components/YourWalletPage/WithdrawFunds.tsx b/frontend/components/YourWalletPage/WithdrawFunds.tsx index b268b880..28f1ced3 100644 --- a/frontend/components/YourWalletPage/WithdrawFunds.tsx +++ b/frontend/components/YourWalletPage/WithdrawFunds.tsx @@ -5,6 +5,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { COLOR } from '@/constants/colors'; import { useBalanceContext } from '@/hooks/useBalanceContext'; +import { useFeatureFlag } from '@/hooks/useFeatureFlag'; import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; import { useStakingContractCountdown } from '@/hooks/useStakingContractCountdown'; @@ -14,6 +15,7 @@ import { ServicesService } from '@/service/Services'; import { Address } from '@/types/Address'; import { CustomAlert } from '../Alert'; +import { FeatureNotEnabled } from '../FeatureNotEnabled'; const { Text } = Typography; @@ -54,7 +56,6 @@ const CompatibleMessage = () => ( export const WithdrawFunds = () => { const { selectedService, refetch: refetchServices } = useServices(); const { refetch: refetchMasterWallets } = useMasterWalletContext(); - const { updateBalances } = useBalanceContext(); const { service, isServiceRunning } = useService( @@ -64,6 +65,7 @@ export const WithdrawFunds = () => { const { isServiceStakedForMinimumDuration, selectedStakingContractDetails } = useActiveStakingContractDetails(); + // state const [isModalVisible, setIsModalVisible] = useState(false); const [withdrawAddress, setWithdrawAddress] = useState(''); const [isWithdrawalLoading, setIsWithdrawalLoading] = useState(false); @@ -148,6 +150,9 @@ export const WithdrawFunds = () => { [service, isServiceStakedForMinimumDuration, showModal], ); + const isWithdrawFundsEnabled = useFeatureFlag('withdraw-funds'); + if (!isWithdrawFundsEnabled) return ; + return ( <> {isServiceStakedForMinimumDuration ? ( From e98877cc0e7a46460405366931327209a65c05fb Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 17:47:00 +0530 Subject: [PATCH 07/13] feat: add BlockScout URL mapping and refactor wallet hooks for improved state management --- frontend/components/AddressLink.tsx | 7 +- .../components/YourWalletPage/YourAgent.tsx | 117 +++++++++++------- frontend/components/YourWalletPage/index.tsx | 18 +-- .../YourWalletPage/useYourWallet.ts | 34 +++++ frontend/constants/urls.ts | 8 ++ 5 files changed, 115 insertions(+), 69 deletions(-) create mode 100644 frontend/components/YourWalletPage/useYourWallet.ts diff --git a/frontend/components/AddressLink.tsx b/frontend/components/AddressLink.tsx index 3f005a59..9f8c56c6 100644 --- a/frontend/components/AddressLink.tsx +++ b/frontend/components/AddressLink.tsx @@ -7,16 +7,13 @@ import { truncateAddress } from '@/utils/truncate'; type AddressLinkProps = { address?: Address; hideLinkArrow?: boolean; - - // TODO: mark as required once balance breakdown is updated. - // and remove the default value - middlewareChain?: MiddlewareChain; + middlewareChain: MiddlewareChain; }; export const AddressLink = ({ address, hideLinkArrow = false, - middlewareChain = MiddlewareChain.GNOSIS, + middlewareChain, }: AddressLinkProps) => { if (!address) return null; if (!middlewareChain) return null; diff --git a/frontend/components/YourWalletPage/YourAgent.tsx b/frontend/components/YourWalletPage/YourAgent.tsx index 5c753f19..c92027d2 100644 --- a/frontend/components/YourWalletPage/YourAgent.tsx +++ b/frontend/components/YourWalletPage/YourAgent.tsx @@ -4,12 +4,12 @@ import Image from 'next/image'; import { useMemo } from 'react'; import styled from 'styled-components'; +import { MiddlewareChain } from '@/client'; import { OLAS_CONTRACTS } from '@/config/olasContracts'; -import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { EvmChainId } from '@/enums/Chain'; +import { NA, UNICODE_SYMBOLS } from '@/constants/symbols'; +import { BLOCKSCOUT_URL_BY_MIDDLEWARE_CHAIN } from '@/constants/urls'; import { ContractType } from '@/enums/Contract'; import { TokenSymbol } from '@/enums/Token'; -import { AgentSafe, Safe } from '@/enums/Wallet'; import { useBalanceContext, useServiceBalances, @@ -27,6 +27,7 @@ import { AddressLink } from '../AddressLink'; import { InfoBreakdownList } from '../InfoBreakdown'; import { Container, infoBreakdownParentStyle } from './styles'; import { OlasTitle, OwnershipNftTitle, ServiceNftIdTitle } from './Titles'; +import { useYourWallet } from './useYourWallet'; import { WithdrawFunds } from './WithdrawFunds'; const { Text, Paragraph } = Typography; @@ -40,8 +41,8 @@ const NftCard = styled(Card)` } `; -const SafeAddress = ({ serviceSafe }: { serviceSafe: Safe }) => { - const multisigAddress = serviceSafe.address; +const SafeAddress = ({ address }: { address: Address }) => { + const { middlewareChain } = useYourWallet(); return ( @@ -50,7 +51,12 @@ const SafeAddress = ({ serviceSafe }: { serviceSafe: Safe }) => { { left: 'Wallet Address', leftClassName: 'text-light text-sm', - right: , + right: ( + + ), rightClassName: 'font-normal text-sm', }, ]} @@ -60,11 +66,16 @@ const SafeAddress = ({ serviceSafe }: { serviceSafe: Safe }) => { ); }; -const AgentTitle = ({ serviceSafe }: { serviceSafe: AgentSafe }) => { - const agentName = useMemo( - () => (serviceSafe ? generateName(serviceSafe.address) : '--'), - [serviceSafe], - ); +const AgentTitle = ({ address }: { address: Address }) => { + const { middlewareChain } = useYourWallet(); + + const agentProfileLink = useMemo(() => { + if (!address) return null; + if (middlewareChain === MiddlewareChain.GNOSIS) { + return `https://predict.olas.network/agents/${address}`; + } + return null; + }, [address, middlewareChain]); return ( @@ -90,16 +101,14 @@ const AgentTitle = ({ serviceSafe }: { serviceSafe: AgentSafe }) => { } placement="top" > - {agentName} + {address ? generateName(address) : NA} - {/* TODO: address multi-agent at later point */} - - Agent profile {UNICODE_SYMBOLS.EXTERNAL_LINK} - + + {agentProfileLink && ( + + Agent profile {UNICODE_SYMBOLS.EXTERNAL_LINK} + + )} @@ -107,13 +116,14 @@ const AgentTitle = ({ serviceSafe }: { serviceSafe: AgentSafe }) => { ); }; +type ServiceAndNftDetailsProps = { serviceNftTokenId: number }; const ServiceAndNftDetails = ({ serviceNftTokenId, -}: { - serviceNftTokenId: number; -}) => { +}: ServiceAndNftDetailsProps) => { + const { middlewareChain, evmHomeChainId } = useYourWallet(); + const serviceRegistryL2ContractAddress = - OLAS_CONTRACTS[EvmChainId.Gnosis][ContractType.ServiceRegistryL2].address; + OLAS_CONTRACTS[evmHomeChainId][ContractType.ServiceRegistryL2].address; return ( @@ -130,7 +140,7 @@ const ServiceAndNftDetails = ({ {truncateAddress(serviceRegistryL2ContractAddress as Address)}{' '} @@ -141,7 +151,7 @@ const ServiceAndNftDetails = ({ {serviceNftTokenId} {UNICODE_SYMBOLS.EXTERNAL_LINK} @@ -156,12 +166,13 @@ const ServiceAndNftDetails = ({ const YourAgentWalletBreakdown = () => { const { isLoaded } = useBalanceContext(); const { selectedService } = useServices(); - const { serviceSafes, serviceNftTokenId, serviceEoa } = useService( + const { serviceNftTokenId, serviceEoa } = useService( selectedService?.service_config_id, ); const { serviceSafeBalances, serviceEoaBalances } = useServiceBalances( selectedService?.service_config_id, ); + const { serviceSafe, middlewareChain, evmHomeChainId } = useYourWallet(); const { availableRewardsForEpochEth, @@ -171,23 +182,27 @@ const YourAgentWalletBreakdown = () => { const reward = useMemo(() => { if (!isLoaded) return ; - if (!isEligibleForRewards) return 'Not yet earned'; - return `~${balanceFormat(availableRewardsForEpochEth, 2)} OLAS`; + if (isEligibleForRewards) { + return `~${balanceFormat(availableRewardsForEpochEth, 2)} OLAS`; + } + + return 'Not yet earned'; }, [isLoaded, isEligibleForRewards, availableRewardsForEpochEth]); - const serviceSafeOlasBalances = useMemo( + const serviceSafeOlas = useMemo( () => - serviceSafeBalances?.filter( - (walletBalance) => walletBalance.symbol === TokenSymbol.OLAS, + serviceSafeBalances?.find( + ({ symbol, evmChainId }) => + symbol === TokenSymbol.OLAS && evmChainId === evmHomeChainId, ), - [serviceSafeBalances], + [serviceSafeBalances, evmHomeChainId], ); const serviceSafeRewards = useMemo( () => [ { title: 'Claimed rewards', - value: `${balanceFormat(serviceSafeOlasBalances?.[0]?.balance ?? 0, 2)} OLAS`, + value: `${balanceFormat(serviceSafeOlas?.balance ?? 0, 2)} OLAS`, }, { title: 'Unclaimed rewards', @@ -198,30 +213,31 @@ const YourAgentWalletBreakdown = () => { value: reward, }, ], - [accruedServiceStakingRewards, reward, serviceSafeOlasBalances], + [accruedServiceStakingRewards, reward, serviceSafeOlas], ); const serviceSafeNativeBalances = useMemo( - () => serviceSafeBalances?.filter((balance) => balance.isNative), - [serviceSafeBalances], + () => + serviceSafeBalances?.filter( + ({ isNative, evmChainId }) => isNative && evmChainId === evmHomeChainId, + ), + [serviceSafeBalances, evmHomeChainId], ); const serviceEoaNativeBalances = useMemo( - () => serviceEoaBalances?.filter((balance) => balance.isNative), - [serviceEoaBalances], + () => + serviceEoaBalances?.filter( + ({ isNative, evmChainId }) => isNative && evmChainId === evmHomeChainId, + ), + [serviceEoaBalances, evmHomeChainId], ); - const serviceSafe = useMemo(() => { - if (isNil(serviceSafes) || isEmpty(serviceSafes)) return null; - return serviceSafes[0]; - }, [serviceSafes]); - - if (isNil(serviceSafe)) return null; + if (!serviceSafe) return null; return ( - }> + }> - + {!isEmpty(serviceSafeRewards) && ( @@ -256,7 +272,12 @@ const YourAgentWalletBreakdown = () => { { left: 'Signer', leftClassName: 'text-sm', - right: , + right: ( + + ), rightClassName: 'font-normal text-sm', }, ]} diff --git a/frontend/components/YourWalletPage/index.tsx b/frontend/components/YourWalletPage/index.tsx index e487405c..6d9e1c31 100644 --- a/frontend/components/YourWalletPage/index.tsx +++ b/frontend/components/YourWalletPage/index.tsx @@ -32,6 +32,7 @@ import { balanceFormat } from '@/utils/numberFormatters'; import { FeatureNotEnabled } from '../FeatureNotEnabled'; import { Container, infoBreakdownParentStyle } from './styles'; import { SignerTitle } from './Titles'; +import { useYourWallet } from './useYourWallet'; import { YourAgentWallet } from './YourAgent'; const { Text } = Typography; @@ -42,21 +43,6 @@ const yourWalletTheme: ThemeConfig = { }, }; -const useYourWallet = () => { - const { selectedAgentConfig } = useServices(); - const { isLoading: isMasterSafeLoading, masterSafes } = - useMasterWalletContext(); - - return { - middlewareChain: selectedAgentConfig?.middlewareHomeChainId, - evmHomeChainId: selectedAgentConfig?.evmHomeChainId, - isMasterSafeLoading, - masterSafeAddress: masterSafes?.find( - ({ evmChainId }) => evmChainId === selectedAgentConfig?.evmHomeChainId, - )?.address, - }; -}; - const Address = () => { const { isMasterSafeLoading, masterSafeAddress, middlewareChain } = useYourWallet(); @@ -227,7 +213,7 @@ export const YourWalletPage = () => { - {selectedService && } + {!selectedService && } ) : ( diff --git a/frontend/components/YourWalletPage/useYourWallet.ts b/frontend/components/YourWalletPage/useYourWallet.ts new file mode 100644 index 00000000..51469e05 --- /dev/null +++ b/frontend/components/YourWalletPage/useYourWallet.ts @@ -0,0 +1,34 @@ +import { useMemo } from 'react'; + +import { useService } from '@/hooks/useService'; +import { useServices } from '@/hooks/useServices'; +import { useMasterWalletContext } from '@/hooks/useWallet'; + +export const useYourWallet = () => { + const { selectedAgentConfig, selectedService } = useServices(); + const { serviceSafes } = useService(selectedService?.service_config_id); + const { isLoading: isMasterSafeLoading, masterSafes } = + useMasterWalletContext(); + + const evmHomeChainId = selectedAgentConfig?.evmHomeChainId; + + // master safe + const masterSafe = useMemo(() => { + return masterSafes?.find(({ evmChainId }) => evmChainId === evmHomeChainId); + }, [masterSafes, evmHomeChainId]); + + // agent safe + const serviceSafe = useMemo(() => { + return serviceSafes?.find( + ({ evmChainId }) => evmChainId === evmHomeChainId, + ); + }, [serviceSafes, evmHomeChainId]); + + return { + middlewareChain: selectedAgentConfig?.middlewareHomeChainId, + evmHomeChainId, + isMasterSafeLoading, + masterSafeAddress: masterSafe?.address, + serviceSafe, + }; +}; diff --git a/frontend/constants/urls.ts b/frontend/constants/urls.ts index 581b4e96..2847cd21 100644 --- a/frontend/constants/urls.ts +++ b/frontend/constants/urls.ts @@ -52,6 +52,14 @@ export const EXPLORER_URL_BY_MIDDLEWARE_CHAIN: Record< [MiddlewareChain.BASE]: BASE_EXPLORER_URL, }; +export const BLOCKSCOUT_URL_BY_MIDDLEWARE_CHAIN: Record< + string | MiddlewareChain, + Url +> = { + [MiddlewareChain.GNOSIS]: 'https://gnosis.blockscout.com', + [MiddlewareChain.BASE]: 'https://base.blockscout.com', +}; + export const SWAP_URL_BY_EVM_CHAIN: Record = { [EvmChainId.Gnosis]: COW_SWAP_GNOSIS_XDAI_OLAS_URL, // [EvmChainId.OPTIMISM]: COW_SWAP_GNOSIS_XDAI_OLAS_URL, From c8f0f3caed778ec3f937ab5f3bacb0ab8044d925 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 17:52:10 +0530 Subject: [PATCH 08/13] feat: enhance OlasBalance and MasterSafeNativeBalance components with middlewareChain display and update balanceFormat default decimals --- frontend/components/YourWalletPage/index.tsx | 18 +++++++++++++----- frontend/utils/numberFormatters.ts | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/frontend/components/YourWalletPage/index.tsx b/frontend/components/YourWalletPage/index.tsx index 6d9e1c31..240ad7c9 100644 --- a/frontend/components/YourWalletPage/index.tsx +++ b/frontend/components/YourWalletPage/index.tsx @@ -7,7 +7,7 @@ import { ThemeConfig, Typography, } from 'antd'; -import { isNil } from 'lodash'; +import { capitalize, isNil } from 'lodash'; import { useMemo } from 'react'; import { AddressLink } from '@/components/AddressLink'; @@ -74,6 +74,7 @@ const Address = () => { const OlasBalance = () => { const { totalStakedOlasBalance } = useBalanceContext(); const { masterWalletBalances } = useMasterBalances(); + const { middlewareChain } = useYourWallet(); const masterSafeOlasBalance = masterWalletBalances ?.filter((walletBalance) => walletBalance.symbol === TokenSymbol.OLAS) @@ -96,7 +97,9 @@ const OlasBalance = () => { return ( - {TokenSymbol.OLAS} + + {TokenSymbol.OLAS} ({capitalize(middlewareChain)}) + ({ left: item.title, @@ -110,7 +113,8 @@ const OlasBalance = () => { }; const MasterSafeNativeBalance = () => { - const { evmHomeChainId, masterSafeAddress } = useYourWallet(); + const { evmHomeChainId, masterSafeAddress, middlewareChain } = + useYourWallet(); const { masterSafeBalances } = useMasterBalances(); const nativeTokenSymbol = getNativeTokenSymbol(evmHomeChainId); @@ -135,7 +139,11 @@ const MasterSafeNativeBalance = () => { {nativeTokenSymbol}, + left: ( + + {nativeTokenSymbol} ({capitalize(middlewareChain)}) + + ), leftClassName: 'text-light', right: `${balanceFormat(masterSafeNativeBalance, 2)} ${nativeTokenSymbol}`, }, @@ -180,7 +188,7 @@ const MasterEoaSignerNativeBalance = () => { /> ), leftClassName: 'text-light', - right: `${balanceFormat(masterEoaBalance, 2)} ${nativeTokenSymbol}`, + right: `${balanceFormat(masterEoaBalance, 3)} ${nativeTokenSymbol}`, }, ]} parentStyle={infoBreakdownParentStyle} diff --git a/frontend/utils/numberFormatters.ts b/frontend/utils/numberFormatters.ts index 06a2ba04..c7eb43f8 100644 --- a/frontend/utils/numberFormatters.ts +++ b/frontend/utils/numberFormatters.ts @@ -5,7 +5,7 @@ import { BigNumberish, ethers } from 'ethers'; */ export const balanceFormat = ( balance: number | undefined, - decimals: 2, + decimals = 2, ): string => { if (balance === undefined) return '--'; return Intl.NumberFormat('en-US', { From cba71fb52575890734c592c4371ad9bcf4e3463f Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 17:53:11 +0530 Subject: [PATCH 09/13] feat: remove DebugInfoSection from SettingsPage for cleaner UI --- frontend/components/SettingsPage/index.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/components/SettingsPage/index.tsx b/frontend/components/SettingsPage/index.tsx index 06061043..52847048 100644 --- a/frontend/components/SettingsPage/index.tsx +++ b/frontend/components/SettingsPage/index.tsx @@ -18,7 +18,6 @@ import { CustomAlert } from '../Alert'; import { CardTitle } from '../Card/CardTitle'; import { CardSection } from '../styled/CardSection'; import { AddBackupWalletPage } from './AddBackupWalletPage'; -import { DebugInfoSection } from './DebugInfoSection'; const { Text, Paragraph } = Typography; @@ -161,9 +160,6 @@ const SettingsMain = () => { Backup wallet {walletBackup} - - {/* Debug info */} - ); }; From 32f3d0202c8519e5f12db3d834b2f70100a88188 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 17:57:08 +0530 Subject: [PATCH 10/13] feat: update OlasBalance filtering logic to include evmChainId and adjust conditional rendering of YourAgentWallet --- frontend/components/YourWalletPage/index.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/components/YourWalletPage/index.tsx b/frontend/components/YourWalletPage/index.tsx index 240ad7c9..137e5c26 100644 --- a/frontend/components/YourWalletPage/index.tsx +++ b/frontend/components/YourWalletPage/index.tsx @@ -74,10 +74,13 @@ const Address = () => { const OlasBalance = () => { const { totalStakedOlasBalance } = useBalanceContext(); const { masterWalletBalances } = useMasterBalances(); - const { middlewareChain } = useYourWallet(); + const { middlewareChain, evmHomeChainId } = useYourWallet(); const masterSafeOlasBalance = masterWalletBalances - ?.filter((walletBalance) => walletBalance.symbol === TokenSymbol.OLAS) + ?.filter( + ({ symbol, evmChainId }) => + symbol === TokenSymbol.OLAS && evmChainId === evmHomeChainId, + ) .reduce((acc, balance) => acc + balance.balance, 0); const olasBalances = useMemo(() => { @@ -221,7 +224,7 @@ export const YourWalletPage = () => { - {!selectedService && } + {selectedService && } ) : ( From 897527d52a5b0fc5d828a2717f1cc1de14eb3475 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Wed, 18 Dec 2024 14:48:03 +0100 Subject: [PATCH 11/13] chore: update hash --- frontend/constants/serviceTemplates.ts | 2 +- templates/memeooorr.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index 120b5087..eef0aebe 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -159,7 +159,7 @@ export const SERVICE_TEMPLATES: ServiceTemplate[] = [ { agentType: AgentType.Memeooorr, name: 'Memeooorr', - hash: 'bafybeieslmmd2k4xzpypzr6a2jlkisxodrmt4lbuwjvsvtm3ury3yxv32m', + hash: 'bafybeiadi4stgvnsdi6l2kqwm7hluuepzsb5ifty7gcyp3ejzh6ufay46y', description: 'Memeooorr @twitter_handle', // should be overwritten with twitter username image: 'https://gateway.autonolas.tech/ipfs/QmQYDGMg8m91QQkTWSSmANs5tZwKrmvUCawXZfXVVWQPcu', diff --git a/templates/memeooorr.yaml b/templates/memeooorr.yaml index 84029d46..93707937 100644 --- a/templates/memeooorr.yaml +++ b/templates/memeooorr.yaml @@ -1,6 +1,6 @@ name: "Memeooorr" description: "Memeooorr @twitter_handle" -hash: bafybeidbgqxeh2yhzrxl3tib5s23hp4ihqjjw6melv7ks47afxc5gil5em +hash: bafybeiadi4stgvnsdi6l2kqwm7hluuepzsb5ifty7gcyp3ejzh6ufay46y image: https://gateway.autonolas.tech/ipfs/QmQYDGMg8m91QQkTWSSmANs5tZwKrmvUCawXZfXVVWQPcu service_version: v0.0.1 home_chain: "base" From a771b571d91b305c07edbe1437c9c36358a01f4e Mon Sep 17 00:00:00 2001 From: truemiller Date: Wed, 18 Dec 2024 14:12:10 +0000 Subject: [PATCH 12/13] fix: await updateService call in AgentNotRunningButton for proper async handling --- .../MainPage/header/AgentButton/AgentNotRunningButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx index 6d0ed723..82a939a2 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -251,7 +251,7 @@ export const AgentNotRunningButton = () => { // Update the service if the hash is different if (!middlewareServiceResponse && service) { if (service.hash !== serviceTemplate.hash) { - return ServicesService.updateService({ + await ServicesService.updateService({ serviceConfigId: service.service_config_id, stakingProgramId: selectedStakingProgramId, // chainId: selectedAgentConfig.evmHomeChainId, From 44263de07830d5baaf31d9ab24f43515ebe6738c Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Wed, 18 Dec 2024 21:40:27 +0530 Subject: [PATCH 13/13] fix: update service wallet logic to use selected home chain dynamically --- frontend/hooks/useService.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/frontend/hooks/useService.ts b/frontend/hooks/useService.ts index 5c8202f3..5274afc5 100644 --- a/frontend/hooks/useService.ts +++ b/frontend/hooks/useService.ts @@ -2,12 +2,10 @@ import { useMemo } from 'react'; import { MiddlewareBuildingStatuses, - MiddlewareChain, MiddlewareDeploymentStatus, MiddlewareRunningStatuses, MiddlewareTransitioningStatuses, } from '@/client'; -import { EvmChainId } from '@/enums/Chain'; import { AgentEoa, AgentSafe, @@ -54,12 +52,12 @@ export const useService = (serviceConfigId?: string) => { return service?.chain_configs?.[service?.home_chain]?.chain_data.token; }, [service?.chain_configs, service?.home_chain]); - // TODO: quick hack to fix for refactor (only predict), will make it dynamic later const serviceWallets: AgentWallets = useMemo(() => { if (!service) return []; - if (!service.chain_configs?.[MiddlewareChain.GNOSIS]) return []; + if (!selectedService?.home_chain) return []; + if (!service.chain_configs?.[selectedService?.home_chain]) return []; - const chainConfig = service.chain_configs[MiddlewareChain.GNOSIS]; + const chainConfig = service.chain_configs[selectedService?.home_chain]; if (!chainConfig) return []; return [ @@ -77,12 +75,12 @@ export const useService = (serviceConfigId?: string) => { address: chainConfig.chain_data.multisig, owner: WalletOwnerType.Agent, type: WalletType.Safe, - evmChainId: EvmChainId.Gnosis, + evmChainId: asEvmChainId(selectedService?.home_chain), } as AgentSafe, ] : []), ]; - }, [service]); + }, [service, selectedService]); const addresses: ServiceChainIdAddressRecord = useMemo(() => { if (!service) return {};