diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5e98156e4..6883f3d34 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -60,15 +60,8 @@ jobs: # Download and build with PyInstaller - name: Get trader bin run: | - trader_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/trader.yaml')); print(config['service_version'])") - echo $trader_version make ./dist/aea_bin - #instead of this one mwe use make; mkdir dist && curl -L -o dist/aea_bin "https://github.com/valory-xyz/trader/releases/download/${trader_version}/trader_bin_${{ env.OS_ARCH }}" - # -- old optimus getter - # optimus_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/optimus.yaml')); print(config['service_version'])") - # echo $optimus_version - # mkdir dist && curl -L -o dist/aea_bin "https://github.com/valory-xyz/optimus/releases/download/${$optimus_version}/optimus_bin_${{ env.OS_ARCH }}" - name: Build with PyInstaller run: | poetry run pyinstaller operate/tendermint.py --onefile diff --git a/.github/workflows/release_dev.yml b/.github/workflows/release_dev.yml index 18d7aa1ea..ae1143804 100644 --- a/.github/workflows/release_dev.yml +++ b/.github/workflows/release_dev.yml @@ -60,15 +60,8 @@ jobs: # Download and build with PyInstaller - name: Get trader bin run: | - trader_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/trader.yaml')); print(config['service_version'])") - echo $trader_version make ./dist/aea_bin - #instead of this one mwe use make; mkdir dist && curl -L -o dist/aea_bin "https://github.com/valory-xyz/trader/releases/download/${trader_version}/trader_bin_${{ env.OS_ARCH }}" - # -- old optimus getter - # optimus_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/optimus.yaml')); print(config['service_version'])") - # echo $optimus_version - # mkdir dist && curl -L -o dist/aea_bin "https://github.com/valory-xyz/optimus/releases/download/${$optimus_version}/optimus_bin_${{ env.OS_ARCH }}" - name: Build with PyInstaller run: | poetry run pyinstaller operate/tendermint.py --onefile diff --git a/.gitignore b/.gitignore index fde33a2cf..7f9e0fcde 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,5 @@ leak_report *.log # custom script for development +.scripts/ custom-script.sh diff --git a/download_binaries.sh b/download_binaries.sh index 0904caa13..487feed39 100755 --- a/download_binaries.sh +++ b/download_binaries.sh @@ -2,12 +2,3 @@ BIN_DIR="electron/bins/" mkdir -p $BIN_DIR - -trader_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/trader.yaml')); print(config['service_version'])") -# optimus_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/optimus.yaml')); print(config['service_version'])") - -# curl -L -o "${BIN_DIR}aea_bin_x64" "https://github.com/valory-xyz/optimus/releases/download/${optimus_version}/optimus_bin_x64" -# curl -L -o "${BIN_DIR}aea_bin_arm64" "https://github.com/valory-xyz/optimus/releases/download/${optimus_version}/optimus_bin_arm64" - -curl -L -o "${BIN_DIR}aea_bin_x64" "https://github.com/valory-xyz/trader/releases/download/${trader_version}/trader_bin_x64" -curl -L -o "${BIN_DIR}aea_bin_arm64" "https://github.com/valory-xyz/trader/releases/download/${trader_version}/trader_bin_arm64" \ No newline at end of file diff --git a/electron/public/chains/optimism-chain.png b/electron/public/chains/optimism-chain.png new file mode 100644 index 000000000..f7ef4d672 Binary files /dev/null and b/electron/public/chains/optimism-chain.png differ diff --git a/electron/store.js b/electron/store.js index 330eed6da..e80ed8395 100644 --- a/electron/store.js +++ b/electron/store.js @@ -26,6 +26,7 @@ const schema = { }, }, agentsFunCelo: { type: 'object', default: defaultInitialAgentSettings }, + optimus: { type: 'object', default: defaultInitialAgentSettings }, }; /** diff --git a/frontend/client/enums.ts b/frontend/client/enums.ts index 1fcf8f7b9..f943aa482 100644 --- a/frontend/client/enums.ts +++ b/frontend/client/enums.ts @@ -1,3 +1,5 @@ +import { ValueOf } from '@/types/Util'; + export enum MiddlewareAction { STATUS = 0, BUILD = 1, @@ -5,17 +7,33 @@ export enum MiddlewareAction { STOP = 3, } +/** + * @note Use this enum to infer all the middleware chains existing in the system + * else use the SupportedMiddlewareChain enum for the chains that are supported by the agents and to be strictly typed. + * + * @warning The value doesn’t actually represent the real chain name; + * it reflects the open-autonomy internal name instead. + */ export enum MiddlewareChain { ETHEREUM = 'ethereum', GOERLI = 'goerli', GNOSIS = 'gnosis', SOLANA = 'solana', - OPTIMISM = 'optimism', + OPTIMISM = 'optimistic', // @note "optimistic" and not "optimism" BASE = 'base', MODE = 'mode', CELO = 'celo', } +const MIDDLEWARE_CHAINS = { + gnosis: MiddlewareChain.GNOSIS, + optimism: MiddlewareChain.OPTIMISM, + base: MiddlewareChain.BASE, + mode: MiddlewareChain.MODE, + celo: MiddlewareChain.CELO, +} as const; +export type SupportedMiddlewareChain = ValueOf; + export enum MiddlewareLedger { ETHEREUM = 0, SOLANA = 1, diff --git a/frontend/client/types.ts b/frontend/client/types.ts index f867c32e6..95e68dc7e 100644 --- a/frontend/client/types.ts +++ b/frontend/client/types.ts @@ -7,6 +7,7 @@ import { MiddlewareChain, MiddlewareDeploymentStatus, MiddlewareLedger, + SupportedMiddlewareChain, } from './enums'; export type ServiceHash = string; @@ -62,7 +63,7 @@ export type MiddlewareServiceResponse = { hash_history: { [block: string]: string; }; - home_chain: MiddlewareChain; + home_chain: SupportedMiddlewareChain; keys: ServiceKeys[]; service_path?: string; chain_configs: { @@ -81,8 +82,10 @@ export type ServiceTemplate = { description: string; image: string; service_version: string; - home_chain: string; - configurations: { [key: string]: ConfigurationTemplate }; + home_chain: SupportedMiddlewareChain; + configurations: Partial< + Record + >; env_variables: { [key: string]: EnvVariableAttributes }; deploy?: boolean; }; diff --git a/frontend/components/AddressLink.tsx b/frontend/components/AddressLink.tsx index 85f7ae16d..8e1220e8f 100644 --- a/frontend/components/AddressLink.tsx +++ b/frontend/components/AddressLink.tsx @@ -1,6 +1,6 @@ import { ReactNode } from 'react'; -import { MiddlewareChain } from '@/client'; +import { SupportedMiddlewareChain } from '@/client'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { EXPLORER_URL_BY_MIDDLEWARE_CHAIN } from '@/constants/urls'; import { Address } from '@/types/Address'; @@ -8,7 +8,7 @@ import { truncateAddress } from '@/utils/truncate'; type AddressLinkProps = { address: Address; - middlewareChain: MiddlewareChain; + middlewareChain: SupportedMiddlewareChain; prefix?: ReactNode; hideLinkArrow?: boolean; }; diff --git a/frontend/components/AgentForms/MemeooorrAgentForm/MemeooorrAgentForm.tsx b/frontend/components/AgentForms/MemeooorrAgentForm/MemeooorrAgentForm.tsx index 64d13a5e2..bc49972f9 100644 --- a/frontend/components/AgentForms/MemeooorrAgentForm/MemeooorrAgentForm.tsx +++ b/frontend/components/AgentForms/MemeooorrAgentForm/MemeooorrAgentForm.tsx @@ -78,7 +78,7 @@ export const MemeooorrAgentForm = ({ }: MemeooorrAgentFormProps) => { const [formState] = Form.useForm(); - const { isMemeooorrFieldUpdateCompleted } = useSharedContext(); + const { isMemeooorrFieldUpdateRequired } = useSharedContext(); const form = useMemo( () => formInstance || formState, [formInstance, formState], @@ -158,7 +158,7 @@ export const MemeooorrAgentForm = ({ diff --git a/frontend/components/AgentForms/common/formUtils.ts b/frontend/components/AgentForms/common/formUtils.ts index 6f1aff5af..775a81dc4 100644 --- a/frontend/components/AgentForms/common/formUtils.ts +++ b/frontend/components/AgentForms/common/formUtils.ts @@ -11,18 +11,18 @@ export const commonFieldProps: FormItemProps = { /** * Field properties for optional form fields. These fields are not required. */ -export const optionalFieldProps: FormItemProps = { +const optionalCommonFieldProps: FormItemProps = { rules: [{ required: false }], } as const; -export const modiusAgentFieldProps: FormItemProps = { +export const requiredFieldProps: FormItemProps = { ...commonFieldProps, validateFirst: true, normalize: (value: string) => value.trim(), } as const; -export const modiusAgentFieldOptionalProps: FormItemProps = { - ...optionalFieldProps, +export const optionalFieldProps: FormItemProps = { + ...optionalCommonFieldProps, validateFirst: true, normalize: (value: string) => value.trim(), } as const; @@ -68,10 +68,10 @@ export const validateSlug = (_: unknown, value?: string): Promise => { return Promise.reject('Please enter only the slug, not the full URL.'); } - // Slug should only contain lowercase letters, numbers, hyphens, and underscores - if (!/^[a-z0-9-_]+$/.test(value)) { + // Slug should only contain letters, numbers, hyphens, and underscores + if (!/^[a-zA-Z0-9-_]+$/.test(value)) { return Promise.reject( - 'Invalid slug format. Only lowercase letters, numbers, hyphens, and underscores are allowed.', + 'Invalid slug format. Only letters, numbers, hyphens, and underscores are allowed.', ); } diff --git a/frontend/components/SetupPage/SetupYourAgent/ModiusAgentForm/labels.tsx b/frontend/components/AgentForms/common/labels.tsx similarity index 94% rename from frontend/components/SetupPage/SetupYourAgent/ModiusAgentForm/labels.tsx rename to frontend/components/AgentForms/common/labels.tsx index e5ed2845b..291801b0b 100644 --- a/frontend/components/SetupPage/SetupYourAgent/ModiusAgentForm/labels.tsx +++ b/frontend/components/AgentForms/common/labels.tsx @@ -25,7 +25,7 @@ export const TenderlyAccessTokenLabel = () => ( To locate your personal access token: -
    +
    1. Connect to{' '} @@ -118,14 +118,14 @@ export const CoinGeckoApiKeyLabel = () => ( ); -export const ModiusGeminiApiKeyLabel = () => ( +export const GeminiApiKeyLabel = ({ name }: { name: 'Modius' | 'Optimus' }) => ( Gemini API key The Gemini API key allows you to chat with your agent and update its - goals through Modius’ profile. You can generate one for free on{' '} - + goals through {name}’ profile. You can generate one for free on{' '} + Google AI Studio . diff --git a/frontend/components/Layout/TopBar.tsx b/frontend/components/Layout/TopBar.tsx index d00c2379f..4eb45e6f2 100644 --- a/frontend/components/Layout/TopBar.tsx +++ b/frontend/components/Layout/TopBar.tsx @@ -1,8 +1,11 @@ -import { Typography } from 'antd'; +import { QuestionCircleOutlined, SettingOutlined } from '@ant-design/icons'; +import { Button, Flex, Typography } from 'antd'; import styled from 'styled-components'; import { COLOR } from '@/constants/colors'; +import { Pages } from '@/enums/Pages'; import { useElectronApi } from '@/hooks/useElectronApi'; +import { usePageState } from '@/hooks/usePageState'; import { useStore } from '@/hooks/useStore'; const { Text } = Typography; @@ -11,7 +14,6 @@ const TrafficLightIcon = styled.div` width: 12px; height: 12px; border-radius: 50%; - margin-left: 8px; -webkit-app-region: no-drag; `; @@ -29,6 +31,7 @@ const DisabledLight = styled(TrafficLightIcon)` const TrafficLights = styled.div` display: flex; + gap: 8px; align-items: center; margin-right: 24px; -webkit-app-region: no-drag; @@ -40,9 +43,10 @@ const TopBarContainer = styled.div` left: 0; right: 0; z-index: 1; + height: 45px; display: flex; align-items: center; - padding: 10px 8px; + padding: 0px 24px; border-radius: 8px 8px 0 0px; border-bottom: 1px solid ${COLOR.BORDER_GRAY}; background: ${COLOR.WHITE}; @@ -52,6 +56,7 @@ const TopBarContainer = styled.div` export const TopBar = () => { const electronApi = useElectronApi(); const store = useStore(); + const { goto } = usePageState(); const envName = store?.storeState?.environmentName; return ( @@ -63,6 +68,21 @@ export const TopBar = () => { {`Pearl (beta) ${envName ? `(${envName})` : ''}`.trim()} + + + + + + + + + ); +}; + +export const AgentProfileButton = () => { + const { middlewareChain, serviceSafe } = useYourWallet(); + const { selectedAgentType, selectedService } = useServices(); + const { service, deploymentStatus } = useService( + selectedService?.service_config_id, + ); + const { goto, show } = useAgentUi(); + + const handleAgentUiBrowserLinkClick = useCallback(async () => { + if (!goto || !show) { + message.error('Agent UI browser IPC methods are not available'); + return; + } + + if (deploymentStatus !== MiddlewareDeploymentStatus.DEPLOYED) { + message.error( + 'Please run the agent first, before attempting to view the agent UI', + ); + return; + } + + try { + await goto('http://127.0.0.1:8716'); + show(); + } catch (error) { + message.error('Failed to open agent UI browser'); + console.error(error); + } + }, [deploymentStatus, goto, show]); + + const agentProfileLink: ReactNode | null = useMemo(() => { + if (!serviceSafe?.address) return null; + + // gnosis - trader + if ( + middlewareChain === MiddlewareChain.GNOSIS && + selectedAgentType === AgentType.PredictTrader + ) { + return ( + + ); + } + + // base - memeooorr + const xUsername = getXUsername(service); + if ( + middlewareChain === MiddlewareChain.BASE && + selectedAgentType === AgentType.Memeooorr + ) { + return ( + + ); + } + + // mode - modius + if ( + middlewareChain === MiddlewareChain.MODE && + selectedAgentType === AgentType.Modius + ) { + return ; + } + + // optimism - optimus + if ( + middlewareChain === MiddlewareChain.OPTIMISM && + selectedAgentType === AgentType.Optimus + ) { + return ; + } + + return null; + }, [ + serviceSafe, + handleAgentUiBrowserLinkClick, + middlewareChain, + selectedAgentType, + service, + ]); + + return agentProfileLink; +}; diff --git a/frontend/components/MainPage/header/AgentSettingsButton.tsx b/frontend/components/MainPage/header/AgentSettingsButton.tsx new file mode 100644 index 000000000..55789506a --- /dev/null +++ b/frontend/components/MainPage/header/AgentSettingsButton.tsx @@ -0,0 +1,42 @@ +import { ControlOutlined } from '@ant-design/icons'; +import { Button, Tooltip, Typography } from 'antd'; + +import { Pages } from '@/enums/Pages'; +import { useFeatureFlag } from '@/hooks/useFeatureFlag'; +import { usePageState } from '@/hooks/usePageState'; + +const { Text } = Typography; + +export const AgentSettingsButton = () => { + const { goto } = usePageState(); + + const isAgentSettingsEnabled = useFeatureFlag('agent-settings'); + + const handleClick = (e: React.MouseEvent) => { + e.stopPropagation(); + goto(Pages.UpdateAgentTemplate); + }; + + return ( + + The agent cannot be configured at the moment + + ) + } + overlayInnerStyle={{ width: 'max-content' }} + placement="bottomLeft" + > + ) : ( @@ -97,7 +67,9 @@ export const SwitchAgentSection = () => { content="To switch, stop the agent you're running" showArrow={false} > - + )} diff --git a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx index 27b92d3d3..5eb904946 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx @@ -5,7 +5,7 @@ import { useMemo } from 'react'; import { MiddlewareDeploymentStatus, ServiceTemplate } from '@/client'; import { SERVICE_TEMPLATES } from '@/constants/serviceTemplates'; import { Pages } from '@/enums/Pages'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { STAKING_PROGRAM_IDS, StakingProgramId } from '@/enums/StakingProgram'; import { useBalanceContext } from '@/hooks/useBalanceContext'; import { useModals } from '@/hooks/useModals'; import { usePageState } from '@/hooks/usePageState'; @@ -142,11 +142,12 @@ export const MigrateButton = ({ configurations: { ...Object.entries(serviceTemplate.configurations).reduce( (acc, [middlewareChain]) => { + // @ts-expect-error TODO: to be fixed acc[middlewareChain] = { staking_program_id: stakingProgramIdToMigrateTo, use_mech_marketplace: stakingProgramIdToMigrateTo === - StakingProgramId.PearlBetaMechMarketplace, + STAKING_PROGRAM_IDS.PearlBetaMechMarketplace, }; return acc; }, @@ -164,7 +165,7 @@ export const MigrateButton = ({ deploy: true, useMechMarketplace: stakingProgramIdToMigrateTo === - StakingProgramId.PearlBetaMechMarketplace, + STAKING_PROGRAM_IDS.PearlBetaMechMarketplace, }; await ServicesService.createService(serviceConfigParams); diff --git a/frontend/components/Pages/AddBackupWalletViaSafePage/index.tsx b/frontend/components/Pages/AddBackupWalletViaSafePage.tsx similarity index 86% rename from frontend/components/Pages/AddBackupWalletViaSafePage/index.tsx rename to frontend/components/Pages/AddBackupWalletViaSafePage.tsx index 1ecb6b65e..856994880 100644 --- a/frontend/components/Pages/AddBackupWalletViaSafePage/index.tsx +++ b/frontend/components/Pages/AddBackupWalletViaSafePage.tsx @@ -1,13 +1,13 @@ import { Card, Flex, Skeleton, Typography } from 'antd'; import { CardTitle } from '@/components/Card/CardTitle'; +import { AllEvmChainId, EvmChainId } from '@/constants/chains'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { DISCORD_TICKET_URL } from '@/constants/urls'; -import { AllEvmChainId, EvmChainId } from '@/enums/Chain'; import { useServices } from '@/hooks/useServices'; import { useMasterWalletContext } from '@/hooks/useWallet'; -import { GoToMainPageButton } from '../GoToMainPageButton'; +import { GoToMainPageButton } from './GoToMainPageButton'; const { Text } = Typography; @@ -24,18 +24,17 @@ const safeChainPrefix = { }; export const AddBackupWalletViaSafePage = () => { + const { masterSafes } = useMasterWalletContext(); const { selectedAgentConfig: { evmHomeChainId }, } = useServices(); - const { masterSafes } = useMasterWalletContext(); - const masterSafe = masterSafes?.find( ({ evmChainId: chainId }) => evmHomeChainId === chainId, ); const safePrefix = - masterSafe?.evmChainId && safeChainPrefix[masterSafe?.evmChainId]; + masterSafe?.evmChainId && safeChainPrefix[masterSafe.evmChainId]; return ( { Manually add backup wallet via Safe interface: - {!masterSafe?.address && } - {masterSafe?.address && ( + {masterSafe?.address ? ( Open Safe interface {UNICODE_SYMBOLS.EXTERNAL_LINK} + ) : ( + )} diff --git a/frontend/components/SetupPage/AgentIntroduction/AgentIntroduction.tsx b/frontend/components/SetupPage/AgentIntroduction/AgentIntroduction.tsx index 52ebad2b6..38cb75855 100644 --- a/frontend/components/SetupPage/AgentIntroduction/AgentIntroduction.tsx +++ b/frontend/components/SetupPage/AgentIntroduction/AgentIntroduction.tsx @@ -9,6 +9,7 @@ import { useSharedContext } from '@/hooks/useSharedContext'; import { AGENTS_FUND_ONBOARDING_STEPS, MODIUS_ONBOARDING_STEPS, + OPTIMUS_ONBOARDING_STEPS, PREDICTION_ONBOARDING_STEPS, } from './constants'; import { IntroductionStep, OnboardingStep } from './IntroductionStep'; @@ -71,6 +72,7 @@ export const AgentIntroduction = () => { if (selectedAgentType === 'trader') return PREDICTION_ONBOARDING_STEPS; if (selectedAgentType === 'memeooorr') return AGENTS_FUND_ONBOARDING_STEPS; if (selectedAgentType === 'modius') return MODIUS_ONBOARDING_STEPS; + if (selectedAgentType === 'optimus') return OPTIMUS_ONBOARDING_STEPS; throw new Error('Invalid agent type'); }, [selectedAgentType]); diff --git a/frontend/components/SetupPage/AgentIntroduction/constants.ts b/frontend/components/SetupPage/AgentIntroduction/constants.ts index b48a9baa5..67fe77fb4 100644 --- a/frontend/components/SetupPage/AgentIntroduction/constants.ts +++ b/frontend/components/SetupPage/AgentIntroduction/constants.ts @@ -56,3 +56,21 @@ export const MODIUS_ONBOARDING_STEPS: OnboardingStep[] = [ // imgSrc: 'setup-agent-modius-3', // }, ] as const; + +export const OPTIMUS_ONBOARDING_STEPS: OnboardingStep[] = [ + { + title: 'Your AI portfolio manager', + desc: 'Optimus collects real-time market data from CoinGecko and autonomously manages your investments using Balancer, Sturdy and Uniswap — delivering hands-free portfolio growth. Requires ETH and USDC on Optimism as initial investments.', + imgSrc: 'setup-agent-optimus-1', + }, + { + title: 'Choose the best strategy', + desc: 'Optimus learns autonomously, adapts to changing market conditions, and selects the best next strategy to invest on your behalf.', + imgSrc: 'setup-agent-optimus-2', + }, + // { + // title: 'Take action', + // desc: 'Based on its analysis and real-time market data, your Optimus agent decides when its more convenient to buy, sell, or hold specific assets.', + // imgSrc: 'setup-agent-optimus-3', + // }, +] as const; diff --git a/frontend/components/SetupPage/Create/SetupCreateSafe.tsx b/frontend/components/SetupPage/Create/SetupCreateSafe.tsx index 499747d3e..948924d80 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 { SERVICE_TEMPLATES } from '@/constants/serviceTemplates'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { SUPPORT_URL } from '@/constants/urls'; -import { EvmChainName } from '@/enums/Chain'; import { Pages } from '@/enums/Pages'; import { useBackupSigner } from '@/hooks/useBackupSigner'; import { useMultisigs } from '@/hooks/useMultisig'; @@ -16,7 +15,7 @@ import { useServices } from '@/hooks/useServices'; import { useMasterWalletContext } from '@/hooks/useWallet'; import { WalletService } from '@/service/Wallet'; import { delayInSeconds } from '@/utils/delay'; -import { asEvmChainId } from '@/utils/middlewareHelpers'; +import { asEvmChainDetails, asEvmChainId } from '@/utils/middlewareHelpers'; const { Text, Title } = Typography; @@ -152,15 +151,12 @@ export const SetupCreateSafe = () => { (async () => { for (const middlewareChain of safeCreationsRequired) { setIsCreatingSafe(true); + const displayName = asEvmChainDetails(middlewareChain).displayName; try { await createSafeWithRetries(middlewareChain, 3); - message.success( - `${EvmChainName[asEvmChainId(middlewareChain)]} account created`, - ); + message.success(`${displayName} account created`); } catch (e) { - message.warning( - `Failed to create ${EvmChainName[asEvmChainId(middlewareChain)]} account`, - ); + message.warning(`Failed to create ${displayName} account`); console.error(e); } } diff --git a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx index a96dc0386..f7f779617 100644 --- a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx +++ b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx @@ -142,7 +142,7 @@ const SetupEoaFundingForChain = ({ The app needs these funds to create your account on-chain. - + Status: {statusMessage(isFunded)} diff --git a/frontend/components/SetupPage/SetupYourAgent/ModiusAgentForm/ModiusAgentForm.tsx b/frontend/components/SetupPage/SetupYourAgent/ModiusAgentForm/ModiusAgentForm.tsx index aace9d60c..26c2167d1 100644 --- a/frontend/components/SetupPage/SetupYourAgent/ModiusAgentForm/ModiusAgentForm.tsx +++ b/frontend/components/SetupPage/SetupYourAgent/ModiusAgentForm/ModiusAgentForm.tsx @@ -10,8 +10,8 @@ import { useStakingProgram } from '@/hooks/useStakingProgram'; import { onDummyServiceCreation } from '@/utils/service'; import { - modiusAgentFieldOptionalProps, - modiusAgentFieldProps, + optionalFieldProps, + requiredFieldProps, requiredRules, validateApiKey, validateMessages, @@ -20,11 +20,11 @@ import { import { InvalidGeminiApiCredentials } from '../../../AgentForms/common/InvalidGeminiApiCredentials'; import { CoinGeckoApiKeyLabel, - ModiusGeminiApiKeyLabel, + GeminiApiKeyLabel, TenderlyAccessTokenLabel, TenderlyAccountSlugLabel, TenderlyProjectSlugLabel, -} from './labels'; +} from '../../../AgentForms/common/labels'; import { ModiusFieldValues, useModiusFormValidate, @@ -151,7 +151,7 @@ export const ModiusAgentForm = ({ serviceTemplate }: ModiusAgentFormProps) => { } - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateApiKey }]} > @@ -160,7 +160,7 @@ export const ModiusAgentForm = ({ serviceTemplate }: ModiusAgentFormProps) => { } - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateSlug }]} > @@ -169,7 +169,7 @@ export const ModiusAgentForm = ({ serviceTemplate }: ModiusAgentFormProps) => { } - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateSlug }]} > @@ -178,7 +178,7 @@ export const ModiusAgentForm = ({ serviceTemplate }: ModiusAgentFormProps) => { } - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateApiKey }]} > @@ -186,8 +186,8 @@ export const ModiusAgentForm = ({ serviceTemplate }: ModiusAgentFormProps) => { } - {...modiusAgentFieldOptionalProps} + label={} + {...optionalFieldProps} > diff --git a/frontend/components/SetupPage/SetupYourAgent/OptimusAgentForm/OptimusAgentForm.tsx b/frontend/components/SetupPage/SetupYourAgent/OptimusAgentForm/OptimusAgentForm.tsx new file mode 100644 index 000000000..7c89e9fe3 --- /dev/null +++ b/frontend/components/SetupPage/SetupYourAgent/OptimusAgentForm/OptimusAgentForm.tsx @@ -0,0 +1,215 @@ +import { Button, Divider, Form, Input, message, Typography } from 'antd'; +import React, { useCallback, useState } from 'react'; +import { useUnmount } from 'usehooks-ts'; + +import { ServiceTemplate } from '@/client'; +import { COINGECKO_URL, TENDERLY_URL } from '@/constants/urls'; +import { SetupScreen } from '@/enums/SetupScreen'; +import { useSetup } from '@/hooks/useSetup'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; +import { onDummyServiceCreation } from '@/utils/service'; + +import { + optionalFieldProps, + requiredFieldProps, + requiredRules, + validateApiKey, + validateMessages, + validateSlug, +} from '../../../AgentForms/common/formUtils'; +import { InvalidGeminiApiCredentials } from '../../../AgentForms/common/InvalidGeminiApiCredentials'; +import { + CoinGeckoApiKeyLabel, + GeminiApiKeyLabel, + TenderlyAccessTokenLabel, + TenderlyAccountSlugLabel, + TenderlyProjectSlugLabel, +} from '../../../AgentForms/common/labels'; +import { + OptimusFieldValues, + useOptimusFormValidate, +} from './useOptimusFormValidate'; + +const { Text } = Typography; + +const SetupHeader = () => ( + + Set up your agent with access to a{' '} + + Tenderly + {' '} + project for simulating bridge and swap routes, and swap routes and provide a{' '} + + CoinGecko API key + {' '} + as a price source. + +); + +type OptimusAgentFormProps = { serviceTemplate: ServiceTemplate }; + +export const OptimusAgentForm = ({ + serviceTemplate, +}: OptimusAgentFormProps) => { + const { goto } = useSetup(); + const { defaultStakingProgramId } = useStakingProgram(); + + const [form] = Form.useForm(); + const [isSubmitting, setIsSubmitting] = useState(false); + const { + geminiApiKeyValidationStatus, + submitButtonText, + updateSubmitButtonText, + validateForm, + } = useOptimusFormValidate(); + + const onFinish = useCallback( + async (values: OptimusFieldValues) => { + if (!defaultStakingProgramId) return; + + try { + setIsSubmitting(true); + + // wait for agent setup to complete + updateSubmitButtonText('Setting up agent...'); + + const isFormValid = await validateForm(values); + if (!isFormValid) return; + + const overriddenServiceConfig: ServiceTemplate = { + ...serviceTemplate, + env_variables: { + ...serviceTemplate.env_variables, + TENDERLY_ACCESS_KEY: { + ...serviceTemplate.env_variables.TENDERLY_ACCESS_KEY, + value: values.tenderlyAccessToken, + }, + TENDERLY_ACCOUNT_SLUG: { + ...serviceTemplate.env_variables.TENDERLY_ACCOUNT_SLUG, + value: values.tenderlyAccountSlug, + }, + TENDERLY_PROJECT_SLUG: { + ...serviceTemplate.env_variables.TENDERLY_PROJECT_SLUG, + value: values.tenderlyProjectSlug, + }, + COINGECKO_API_KEY: { + ...serviceTemplate.env_variables.COINGECKO_API_KEY, + value: values.coinGeckoApiKey, + }, + GENAI_API_KEY: { + ...serviceTemplate.env_variables.GENAI_API_KEY, + value: values.geminiApiKey || '', + }, + }, + }; + + await onDummyServiceCreation( + defaultStakingProgramId, + overriddenServiceConfig, + ); + + message.success('Agent setup complete'); + + // move to next page + goto(SetupScreen.SetupEoaFunding); + } catch (error) { + message.error('Something went wrong. Please try again.'); + console.error(error); + } finally { + setIsSubmitting(false); + updateSubmitButtonText('Continue'); + } + }, + [ + defaultStakingProgramId, + serviceTemplate, + validateForm, + updateSubmitButtonText, + goto, + ], + ); + + // Clean up + useUnmount(async () => { + setIsSubmitting(false); + updateSubmitButtonText('Continue'); + }); + + const canSubmitForm = isSubmitting || !defaultStakingProgramId; + + return ( + <> + + + + + form={form} + name="setup-your-agent" + layout="vertical" + onFinish={onFinish} + validateMessages={validateMessages} + disabled={canSubmitForm} + > + } + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateApiKey }]} + > + + + + } + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateSlug }]} + > + + + + } + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateSlug }]} + > + + + + } + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateApiKey }]} + > + + + + } + {...optionalFieldProps} + > + + + {geminiApiKeyValidationStatus === 'invalid' && ( + + )} + + + + + + + ); +}; diff --git a/frontend/components/SetupPage/SetupYourAgent/OptimusAgentForm/useOptimusFormValidate.ts b/frontend/components/SetupPage/SetupYourAgent/OptimusAgentForm/useOptimusFormValidate.ts new file mode 100644 index 000000000..b9ef9fb4e --- /dev/null +++ b/frontend/components/SetupPage/SetupYourAgent/OptimusAgentForm/useOptimusFormValidate.ts @@ -0,0 +1,61 @@ +import { useCallback, useState } from 'react'; + +import { + validateGeminiApiKey, + ValidationStatus, +} from '../../../AgentForms/common/validations'; + +export type OptimusFieldValues = { + tenderlyAccessToken: string; + tenderlyAccountSlug: string; + tenderlyProjectSlug: string; + coinGeckoApiKey: string; + geminiApiKey?: string; +}; + +export const useOptimusFormValidate = ( + defaultSubmitButtonText = 'Continue', +) => { + const [isValidating, setIsValidating] = useState(false); + const [submitButtonText, setSubmitButtonText] = useState( + defaultSubmitButtonText, + ); + const [geminiApiKeyValidationStatus, setGeminiApiKeyValidationStatus] = + useState('unknown'); + + const handleValidate = useCallback(async (values: OptimusFieldValues) => { + setIsValidating(true); + + setGeminiApiKeyValidationStatus('unknown'); + setSubmitButtonText('Validating...'); + + try { + // gemini api key is optional, so we only validate if it's provided + if (values.geminiApiKey) { + const isGeminiApiValid = await validateGeminiApiKey( + values.geminiApiKey, + ); + setGeminiApiKeyValidationStatus(isGeminiApiValid ? 'valid' : 'invalid'); + if (!isGeminiApiValid) return; + } + + return true; + } catch (error) { + console.error('Error validating optimus form:', error); + } finally { + setIsValidating(false); + } + }, []); + + const updateSubmitButtonText = useCallback((value: string) => { + setSubmitButtonText(value); + }, []); + + return { + isValidating, + geminiApiKeyValidationStatus, + submitButtonText, + updateSubmitButtonText, + validateForm: handleValidate, + }; +}; diff --git a/frontend/components/SetupPage/SetupYourAgent/SetupYourAgent.tsx b/frontend/components/SetupPage/SetupYourAgent/SetupYourAgent.tsx index cfb790f20..31dcdd47b 100644 --- a/frontend/components/SetupPage/SetupYourAgent/SetupYourAgent.tsx +++ b/frontend/components/SetupPage/SetupYourAgent/SetupYourAgent.tsx @@ -12,6 +12,7 @@ import { LOCAL_FORM_THEME } from '@/theme'; import { SetupCreateHeader } from '../Create/SetupCreateHeader'; import { MemeooorrAgentSetup } from './MemeooorrAgentSetup'; import { ModiusAgentForm } from './ModiusAgentForm/ModiusAgentForm'; +import { OptimusAgentForm } from './OptimusAgentForm/OptimusAgentForm'; const { Title, Text } = Typography; @@ -43,10 +44,12 @@ export const SetupYourAgent = () => { {selectedAgentType === AgentType.Memeooorr && ( )} - {selectedAgentType === AgentType.Modius && ( )} + {selectedAgentType === AgentType.Optimus && ( + + )} ); diff --git a/frontend/components/UpdateAgentPage/ModiusUpdateForm.tsx b/frontend/components/UpdateAgentPage/ModiusUpdateForm.tsx index 34a562111..21b7ff797 100644 --- a/frontend/components/UpdateAgentPage/ModiusUpdateForm.tsx +++ b/frontend/components/UpdateAgentPage/ModiusUpdateForm.tsx @@ -8,8 +8,8 @@ import { useServices } from '@/hooks/useServices'; import { Nullable } from '@/types/Util'; import { - modiusAgentFieldOptionalProps, - modiusAgentFieldProps, + optionalFieldProps, + requiredFieldProps, requiredRules, validateApiKey, validateMessages, @@ -18,11 +18,11 @@ import { import { InvalidGeminiApiCredentials } from '../AgentForms/common/InvalidGeminiApiCredentials'; import { CoinGeckoApiKeyLabel, - ModiusGeminiApiKeyLabel, + GeminiApiKeyLabel, TenderlyAccessTokenLabel, TenderlyAccountSlugLabel, TenderlyProjectSlugLabel, -} from '../SetupPage/SetupYourAgent/ModiusAgentForm/labels'; +} from '../AgentForms/common/labels'; import { useModiusFormValidate } from '../SetupPage/SetupYourAgent/ModiusAgentForm/useModiusFormValidate'; import { CardLayout } from './CardLayout'; import { UpdateAgentContext } from './context/UpdateAgentProvider'; @@ -92,7 +92,7 @@ const ModiusUpdateForm = ({ initialFormValues }: ModiusUpdateFormProps) => { } name={['env_variables', 'TENDERLY_ACCESS_KEY']} - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateApiKey }]} > @@ -101,7 +101,7 @@ const ModiusUpdateForm = ({ initialFormValues }: ModiusUpdateFormProps) => { } name={['env_variables', 'TENDERLY_ACCOUNT_SLUG']} - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateSlug }]} > @@ -110,7 +110,7 @@ const ModiusUpdateForm = ({ initialFormValues }: ModiusUpdateFormProps) => { } name={['env_variables', 'TENDERLY_PROJECT_SLUG']} - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateSlug }]} > @@ -119,16 +119,16 @@ const ModiusUpdateForm = ({ initialFormValues }: ModiusUpdateFormProps) => { } name={['env_variables', 'COINGECKO_API_KEY']} - {...modiusAgentFieldProps} + {...requiredFieldProps} rules={[...requiredRules, { validator: validateApiKey }]} > } + label={} name={['env_variables', 'GENAI_API_KEY']} - {...modiusAgentFieldOptionalProps} + {...optionalFieldProps} rules={[{ validator: validateApiKey }]} > diff --git a/frontend/components/UpdateAgentPage/OptimusUpdateForm.tsx b/frontend/components/UpdateAgentPage/OptimusUpdateForm.tsx new file mode 100644 index 000000000..4dd8d355f --- /dev/null +++ b/frontend/components/UpdateAgentPage/OptimusUpdateForm.tsx @@ -0,0 +1,203 @@ +import { Button, Form, Input } from 'antd'; +import { get, isEqual, isUndefined, omitBy } from 'lodash'; +import { useCallback, useContext, useMemo } from 'react'; + +import { Pages } from '@/enums/Pages'; +import { usePageState } from '@/hooks/usePageState'; +import { useServices } from '@/hooks/useServices'; +import { Nullable } from '@/types/Util'; + +import { + optionalFieldProps, + requiredFieldProps, + requiredRules, + validateApiKey, + validateMessages, + validateSlug, +} from '../AgentForms/common/formUtils'; +import { InvalidGeminiApiCredentials } from '../AgentForms/common/InvalidGeminiApiCredentials'; +import { + CoinGeckoApiKeyLabel, + GeminiApiKeyLabel, + TenderlyAccessTokenLabel, + TenderlyAccountSlugLabel, + TenderlyProjectSlugLabel, +} from '../AgentForms/common/labels'; +import { useOptimusFormValidate } from '../SetupPage/SetupYourAgent/OptimusAgentForm/useOptimusFormValidate'; +import { CardLayout } from './CardLayout'; +import { UpdateAgentContext } from './context/UpdateAgentProvider'; + +type OptimusFormValues = { + env_variables: { + TENDERLY_ACCESS_KEY: string; + TENDERLY_ACCOUNT_SLUG: string; + TENDERLY_PROJECT_SLUG: string; + COINGECKO_API_KEY: string; + GENAI_API_KEY: string; + }; +}; + +type OptimusUpdateFormProps = { + initialFormValues: Nullable; +}; + +const OptimusUpdateForm = ({ initialFormValues }: OptimusUpdateFormProps) => { + const { + isEditing, + form, + confirmUpdateModal: confirmModal, + } = useContext(UpdateAgentContext); + + const { + geminiApiKeyValidationStatus, + submitButtonText, + updateSubmitButtonText, + validateForm, + } = useOptimusFormValidate('Save Changes'); + + const handleFinish = useCallback( + async (values: OptimusFormValues) => { + try { + const envVariables = values.env_variables; + const userInputs = { + tenderlyAccessToken: envVariables.TENDERLY_ACCESS_KEY, + tenderlyAccountSlug: envVariables.TENDERLY_ACCOUNT_SLUG, + tenderlyProjectSlug: envVariables.TENDERLY_PROJECT_SLUG, + coinGeckoApiKey: envVariables.COINGECKO_API_KEY, + geminiApiKey: envVariables.GENAI_API_KEY, + }; + const isFormValid = await validateForm(userInputs); + if (!isFormValid) return; + + updateSubmitButtonText('Updating agent...'); + confirmModal.openModal(); + } catch (error) { + console.error('Error validating form:', error); + } finally { + updateSubmitButtonText('Save Changes'); + } + }, + [validateForm, confirmModal, updateSubmitButtonText], + ); + + return ( + + form={form} + layout="vertical" + disabled={!isEditing} + onFinish={handleFinish} + validateMessages={validateMessages} + initialValues={{ ...initialFormValues }} + > + } + name={['env_variables', 'TENDERLY_ACCESS_KEY']} + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateApiKey }]} + > + + + + } + name={['env_variables', 'TENDERLY_ACCOUNT_SLUG']} + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateSlug }]} + > + + + + } + name={['env_variables', 'TENDERLY_PROJECT_SLUG']} + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateSlug }]} + > + + + + } + name={['env_variables', 'COINGECKO_API_KEY']} + {...requiredFieldProps} + rules={[...requiredRules, { validator: validateApiKey }]} + > + + + + } + name={['env_variables', 'GENAI_API_KEY']} + {...optionalFieldProps} + rules={[{ validator: validateApiKey }]} + > + + + {geminiApiKeyValidationStatus === 'invalid' && ( + + )} + + + + ); +}; + +/** + * Form for updating Optimus agent. + */ +export const OptimusUpdatePage = () => { + const { goto } = usePageState(); + const { selectedService } = useServices(); + const { unsavedModal, form } = useContext(UpdateAgentContext); + + const initialValues = useMemo>(() => { + if (!selectedService?.env_variables) return null; + + const envEntries = Object.entries(selectedService.env_variables); + + return envEntries.reduce( + (acc, [key, { value }]) => { + if (key === 'TENDERLY_ACCESS_KEY') { + acc.env_variables.TENDERLY_ACCESS_KEY = value; + } else if (key === 'TENDERLY_ACCOUNT_SLUG') { + acc.env_variables.TENDERLY_ACCOUNT_SLUG = value; + } else if (key === 'TENDERLY_PROJECT_SLUG') { + acc.env_variables.TENDERLY_PROJECT_SLUG = value; + } else if (key === 'COINGECKO_API_KEY') { + acc.env_variables.COINGECKO_API_KEY = value; + } else if (key === 'GENAI_API_KEY') { + acc.env_variables.GENAI_API_KEY = value; + } + + return acc; + }, + { env_variables: {} } as OptimusFormValues, + ); + }, [selectedService?.env_variables]); + + const handleBackClick = useCallback(() => { + // Check if there are unsaved changes and omit empty fields + const unsavedFields = omitBy( + get(form?.getFieldsValue(), 'env_variables'), + (value) => isUndefined(value), + ); + const previousValues = initialValues?.env_variables; + + const hasUnsavedChanges = !isEqual(unsavedFields, previousValues); + if (hasUnsavedChanges) { + unsavedModal.openModal(); + } else { + goto(Pages.Main); + } + }, [initialValues, form, unsavedModal, goto]); + + return ( + + + + ); +}; diff --git a/frontend/components/UpdateAgentPage/index.tsx b/frontend/components/UpdateAgentPage/index.tsx index 0c7c921d1..b2eb6bb1f 100644 --- a/frontend/components/UpdateAgentPage/index.tsx +++ b/frontend/components/UpdateAgentPage/index.tsx @@ -7,6 +7,7 @@ import { LOCAL_FORM_THEME } from '@/theme'; import { UpdateAgentProvider } from './context/UpdateAgentProvider'; import { MemeooorrUpdateSetup } from './MemeooorrUpdateSetup'; import { ModiusUpdatePage } from './ModiusUpdateForm'; +import { OptimusUpdatePage } from './OptimusUpdateForm'; export const UpdateAgentPage = () => { const { selectedAgentType } = useServices(); @@ -15,6 +16,7 @@ export const UpdateAgentPage = () => { {selectedAgentType === AgentType.Memeooorr && } {selectedAgentType === AgentType.Modius && } + {selectedAgentType === AgentType.Optimus && } ); diff --git a/frontend/components/YourWalletPage/AgentTitle.tsx b/frontend/components/YourWalletPage/AgentTitle.tsx index 1a033cf82..1e11ba0a3 100644 --- a/frontend/components/YourWalletPage/AgentTitle.tsx +++ b/frontend/components/YourWalletPage/AgentTitle.tsx @@ -1,204 +1,13 @@ -import { - Button, - Checkbox, - Flex, - message, - Modal, - Tooltip, - Typography, -} from 'antd'; +import { Flex, Tooltip, Typography } from 'antd'; import Image from 'next/image'; -import { useCallback, useMemo, useState } from 'react'; -import { MiddlewareChain, MiddlewareDeploymentStatus } from '@/client'; -import { NA, UNICODE_SYMBOLS } from '@/constants/symbols'; -import { GEMINI_API_URL } from '@/constants/urls'; -import { MODAL_WIDTH } from '@/constants/width'; -import { useAgentUi } from '@/context/AgentUiProvider'; -import { AgentType } from '@/enums/Agent'; -import { Pages } from '@/enums/Pages'; -import { useElectronApi } from '@/hooks/useElectronApi'; -import { usePageState } from '@/hooks/usePageState'; -import { useService } from '@/hooks/useService'; -import { useServices } from '@/hooks/useServices'; -import { useStore } from '@/hooks/useStore'; +import { NA } from '@/constants/symbols'; import { Address } from '@/types/Address'; import { generateName } from '@/utils/agentName'; -import { getXUsername } from '@/utils/x'; - -import { useYourWallet } from './useYourWallet'; const { Text, Paragraph } = Typography; -const AgentProfile = () => <>Agent profile {UNICODE_SYMBOLS.EXTERNAL_LINK}; - -const ExternalAgentProfileLink = ({ href }: { href: string }) => { - return ( - - - - ); -}; - -const ModiusAgentProfile = ({ onClick }: { onClick: () => void }) => { - const electronApi = useElectronApi(); - const { storeState } = useStore(); - const { selectedService, selectedAgentType } = useServices(); - const { goto } = usePageState(); - - const [isModalOpen, setIsModalOpen] = useState(false); - const [dontShowAgain, setDontShowAgain] = useState(false); - - const geminiApiKey = selectedService?.env_variables?.GENAI_API_KEY?.value; - - const canAccessProfile = useMemo(() => { - if (!storeState) return false; - return storeState.modius?.isProfileWarningDisplayed ?? false; - }, [storeState]); - - const handleAgentProfileClick = useCallback(() => { - if (!!geminiApiKey || canAccessProfile) { - onClick(); - return; - } - - setIsModalOpen(true); - }, [geminiApiKey, canAccessProfile, onClick]); - - const handleDoNotShowAgain = useCallback( - (value: boolean) => { - const key = `${selectedAgentType}.isProfileWarningDisplayed`; - electronApi.store?.set?.(key, value); - setIsModalOpen(false); - }, - [electronApi.store, selectedAgentType], - ); - - const handleProvideKey = useCallback(() => { - handleDoNotShowAgain(dontShowAgain); - goto(Pages.UpdateAgentTemplate); - }, [dontShowAgain, handleDoNotShowAgain, goto]); - - const handleProceed = useCallback(() => { - handleDoNotShowAgain(dontShowAgain); - onClick(); - }, [dontShowAgain, handleDoNotShowAgain, onClick]); - - return ( - <> - - - - setIsModalOpen(false)} - width={MODAL_WIDTH} - footer={null} - > - -
      - To unlock the full functionality of Modius profile, a Gemini API key - is required. You can get a free Gemini API key through the{' '} - - Google AI Studio - - . -
      - - - setDontShowAgain(e.target.checked)}> - {"Don't show again"} - - - - - - - -
      -
      - - ); -}; - export const AgentTitle = ({ address }: { address: Address }) => { - const { middlewareChain } = useYourWallet(); - const { selectedAgentType, selectedService } = useServices(); - const { service, deploymentStatus } = useService( - selectedService?.service_config_id, - ); - const { goto, show } = useAgentUi(); - - const handleAgentUiBrowserLinkClick = useCallback(async () => { - if (!goto || !show) { - message.error('Agent UI browser IPC methods are not available'); - return; - } - - if (deploymentStatus !== MiddlewareDeploymentStatus.DEPLOYED) { - message.error( - 'Please run the agent first, before attempting to view the agent UI', - ); - return; - } - - try { - await goto('http://127.0.0.1:8716'); - show(); - } catch (error) { - message.error('Failed to open agent UI browser'); - console.error(error); - } - }, [deploymentStatus, goto, show]); - - const agentProfileLink: JSX.Element | null = useMemo(() => { - if (!address) return null; - - // gnosis - trader - if ( - middlewareChain === MiddlewareChain.GNOSIS && - selectedAgentType === AgentType.PredictTrader - ) { - return ( - - ); - } - - // base - memeooorr - const xUsername = getXUsername(service); - if ( - middlewareChain === MiddlewareChain.BASE && - selectedAgentType === AgentType.Memeooorr - ) { - return ( - - ); - } - - // mode - modius - if ( - middlewareChain === MiddlewareChain.MODE && - selectedAgentType === AgentType.Modius - ) { - return ; - } - - return null; - }, [ - address, - handleAgentUiBrowserLinkClick, - middlewareChain, - selectedAgentType, - service, - ]); - return ( @@ -225,8 +34,6 @@ export const AgentTitle = ({ address }: { address: Address }) => { > {address ? generateName(address) : NA} - - {agentProfileLink}
      diff --git a/frontend/components/YourWalletPage/Titles.tsx b/frontend/components/YourWalletPage/Titles.tsx index 95487a20e..3206369ef 100644 --- a/frontend/components/YourWalletPage/Titles.tsx +++ b/frontend/components/YourWalletPage/Titles.tsx @@ -1,6 +1,6 @@ import { Flex, Typography } from 'antd'; -import { MiddlewareChain } from '@/client'; +import { SupportedMiddlewareChain } from '@/client'; import { InfoTooltip } from '@/components/InfoTooltip'; import { TokenSymbol } from '@/enums/Token'; import { Address } from '@/types/Address'; @@ -11,7 +11,7 @@ const { Paragraph, Text, Title } = Typography; type SignerTitleProps = { signerAddress: Address; - middlewareChain: MiddlewareChain; + middlewareChain: SupportedMiddlewareChain; }; export const SignerTitle = ({ diff --git a/frontend/components/YourWalletPage/YourAgent.tsx b/frontend/components/YourWalletPage/YourAgent.tsx index aa2fb556e..f05f7ba92 100644 --- a/frontend/components/YourWalletPage/YourAgent.tsx +++ b/frontend/components/YourWalletPage/YourAgent.tsx @@ -18,7 +18,9 @@ import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; import { Address } from '@/types/Address'; import { WalletBalance } from '@/types/Balance'; +import { asEvmChainDetails } from '@/utils/middlewareHelpers'; import { balanceFormat } from '@/utils/numberFormatters'; +import { isValidServiceId } from '@/utils/service'; import { truncateAddress } from '@/utils/truncate'; import { AddressLink } from '../AddressLink'; @@ -103,7 +105,7 @@ const ServiceAndNftDetails = ({ {serviceNftTokenId} {UNICODE_SYMBOLS.EXTERNAL_LINK} @@ -281,7 +283,7 @@ const YourAgentWalletBreakdown = () => { )} - {!isNil(serviceNftTokenId) && ( + {serviceNftTokenId && isValidServiceId(serviceNftTokenId) && ( )} diff --git a/frontend/components/YourWalletPage/index.tsx b/frontend/components/YourWalletPage/index.tsx index e85afbdbd..e90f04a8e 100644 --- a/frontend/components/YourWalletPage/index.tsx +++ b/frontend/components/YourWalletPage/index.tsx @@ -1,5 +1,5 @@ import { ConfigProvider, Flex, Skeleton, ThemeConfig, Typography } from 'antd'; -import { capitalize, isNil } from 'lodash'; +import { isNil } from 'lodash'; import { useMemo } from 'react'; import { AddressLink } from '@/components/AddressLink'; @@ -17,6 +17,7 @@ import { useServices } from '@/hooks/useServices'; import { useMasterWalletContext } from '@/hooks/useWallet'; import { type Address } from '@/types/Address'; import { Optional } from '@/types/Util'; +import { asEvmChainDetails } from '@/utils/middlewareHelpers'; import { balanceFormat } from '@/utils/numberFormatters'; import { FeatureNotEnabled } from '../FeatureNotEnabled'; @@ -96,7 +97,7 @@ const OlasBalance = () => { return ( - {TokenSymbol.OLAS} ({capitalize(middlewareChain)}) + {TokenSymbol.OLAS} ({asEvmChainDetails(middlewareChain).displayName}) ({ @@ -140,7 +141,8 @@ const MasterSafeNativeBalance = () => { { left: ( - {nativeTokenSymbol} ({capitalize(middlewareChain)}) + {nativeTokenSymbol} ( + {asEvmChainDetails(middlewareChain).displayName}) ), leftClassName: 'text-light', @@ -193,7 +195,7 @@ const MasterSafeErc20Balances = () => { { left: ( - {symbol} ({capitalize(middlewareChain)}) + {symbol} ({asEvmChainDetails(middlewareChain).displayName}) ), leftClassName: 'text-light', diff --git a/frontend/components/bridge/BridgeTransferFlow.tsx b/frontend/components/bridge/BridgeTransferFlow.tsx index c2d88523c..a6a539f9f 100644 --- a/frontend/components/bridge/BridgeTransferFlow.tsx +++ b/frontend/components/bridge/BridgeTransferFlow.tsx @@ -4,21 +4,23 @@ import { kebabCase } from 'lodash'; import Image from 'next/image'; import React from 'react'; +import { MiddlewareChain } from '@/client'; import { COLOR } from '@/constants/colors'; import { CrossChainTransferDetails, TokenTransfer } from '@/types/Bridge'; +import { asEvmChainDetails } from '@/utils/middlewareHelpers'; import { formatUnitsToNumber } from '@/utils/numberFormatters'; const { Text } = Typography; -const TransferChain = ({ chainName }: { chainName: string }) => ( +const TransferChain = ({ chainName }: { chainName: MiddlewareChain }) => ( chain logo - {chainName} + {asEvmChainDetails(chainName).displayName} ); diff --git a/frontend/components/bridge/BridgingSteps.tsx b/frontend/components/bridge/BridgingSteps.tsx index 5e7bbcafb..04a83ea5e 100644 --- a/frontend/components/bridge/BridgingSteps.tsx +++ b/frontend/components/bridge/BridgingSteps.tsx @@ -8,6 +8,7 @@ import { SUPPORT_URL } from '@/constants/urls'; import { TokenSymbol } from '@/enums/Token'; import { BridgingStepStatus as Status } from '@/types/Bridge'; import { Maybe, Nullable } from '@/types/Util'; +import { asEvmChainDetails } from '@/utils/middlewareHelpers'; import { ExportLogsButton } from '../ExportLogsButton'; @@ -183,7 +184,7 @@ export const BridgingSteps = ({ }: BridgingStepsProps) => { const bridgeStep: Step = useMemo(() => { return { - title: `Bridge funds to ${chainName}`, + title: `Bridge funds to ${asEvmChainDetails(chainName).displayName}`, ...generateBridgeStep(bridge.status, bridge.subSteps), }; }, [chainName, bridge]); diff --git a/frontend/components/bridge/DepositForBridging.tsx b/frontend/components/bridge/DepositForBridging.tsx index 29862dd9b..3abe413e0 100644 --- a/frontend/components/bridge/DepositForBridging.tsx +++ b/frontend/components/bridge/DepositForBridging.tsx @@ -239,8 +239,8 @@ export const DepositForBridging = ({ if (!areAllFundsReceived) return; updateQuoteId(bridgeFundingRequirements.id); updateCrossChainTransferDetails({ - fromChain: upperFirst(MiddlewareChain.ETHEREUM), - toChain: upperFirst(toMiddlewareChain), + fromChain: MiddlewareChain.ETHEREUM, + toChain: toMiddlewareChain, transfers: tokens.map((token) => { const toAmount = (() => { // TODO: reuse getFromToken function from utils.ts diff --git a/frontend/components/bridge/utils.ts b/frontend/components/bridge/utils.ts index ef28fc420..e4c045118 100644 --- a/frontend/components/bridge/utils.ts +++ b/frontend/components/bridge/utils.ts @@ -93,7 +93,7 @@ const useGetBridgeRequirementsParamsWithMonthlyGasEstimate = () => { const monthlyGasEstimate = SERVICE_TEMPLATES.find( (template) => template.home_chain === toMiddlewareChain, - )?.configurations[toMiddlewareChain].monthly_gas_estimate ?? 0; + )?.configurations[toMiddlewareChain]?.monthly_gas_estimate ?? 0; // amount = max(refill_requirement_masterSafe, monthly_gas_estimate) + refill_requirements_masterEOA const amount = diff --git a/frontend/components/custom-icons/AgentProfile.tsx b/frontend/components/custom-icons/AgentProfile.tsx new file mode 100644 index 000000000..782d4bb44 --- /dev/null +++ b/frontend/components/custom-icons/AgentProfile.tsx @@ -0,0 +1,17 @@ +export const AgentProfileSvg = () => ( + + + +); diff --git a/frontend/config/activityCheckers.ts b/frontend/config/activityCheckers.ts index 5d92bc25f..e0becd784 100644 --- a/frontend/config/activityCheckers.ts +++ b/frontend/config/activityCheckers.ts @@ -1,10 +1,20 @@ +/** + * Check if the staking contract has been removed from Voting (i.e., it will no longer receive OLAS used for rewards): + * [Etherscan Contract Link](https://etherscan.io/address/0x95418b46d5566D3d1ea62C12Aea91227E566c5c1#readContract#F10) + * If it has been removed, it shouldn’t be considered a staking contract anymore and also won’t appear in the Voting list: + * [Govern App](https://govern.olas.network/contracts) + */ + import { Contract as MulticallContract } from 'ethers-multicall'; import { MECH_ACTIVITY_CHECKER_ABI } from '@/abis/mechActivityChecker'; import { MEME_ACTIVITY_CHECKER_ABI } from '@/abis/memeActivityChecker'; import { REQUESTER_ACTIVITY_CHECKER_ABI } from '@/abis/requesterActivityChecker'; import { STAKING_ACTIVITY_CHECKER_ABI } from '@/abis/stakingActivityChecker'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { + OptimismStakingProgramId, + STAKING_PROGRAM_IDS, +} from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; export const getMechActivityCheckerContract = ( @@ -35,28 +45,28 @@ export const GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS: Record< string, MulticallContract > = { - [StakingProgramId.PearlAlpha]: getMechActivityCheckerContract( + [STAKING_PROGRAM_IDS.PearlAlpha]: getMechActivityCheckerContract( '0x155547857680A6D51bebC5603397488988DEb1c8', ), - [StakingProgramId.PearlBeta]: getMechActivityCheckerContract( + [STAKING_PROGRAM_IDS.PearlBeta]: getMechActivityCheckerContract( '0x155547857680A6D51bebC5603397488988DEb1c8', ), - [StakingProgramId.PearlBeta2]: getMechActivityCheckerContract( + [STAKING_PROGRAM_IDS.PearlBeta2]: getMechActivityCheckerContract( '0x155547857680A6D51bebC5603397488988DEb1c8', ), - [StakingProgramId.PearlBeta3]: getMechActivityCheckerContract( + [STAKING_PROGRAM_IDS.PearlBeta3]: getMechActivityCheckerContract( '0x155547857680A6D51bebC5603397488988DEb1c8', ), - [StakingProgramId.PearlBeta4]: getMechActivityCheckerContract( + [STAKING_PROGRAM_IDS.PearlBeta4]: getMechActivityCheckerContract( '0x155547857680A6D51bebC5603397488988DEb1c8', ), - [StakingProgramId.PearlBeta5]: getMechActivityCheckerContract( + [STAKING_PROGRAM_IDS.PearlBeta5]: getMechActivityCheckerContract( '0x155547857680A6D51bebC5603397488988DEb1c8', ), - [StakingProgramId.PearlBeta6]: getRequesterActivityCheckerContract( + [STAKING_PROGRAM_IDS.PearlBeta6]: getRequesterActivityCheckerContract( '0xfE1D36820546cE5F3A58405950dC2F5ccDf7975C', ), - [StakingProgramId.PearlBetaMechMarketplace]: + [STAKING_PROGRAM_IDS.PearlBetaMechMarketplace]: getRequesterActivityCheckerContract( '0x7Ec96996Cd146B91779f01419db42E67463817a0', ), @@ -66,25 +76,25 @@ export const BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS: Record< string, MulticallContract > = { - [StakingProgramId.MemeBaseAlpha2]: getMemeActivityCheckerContract( + [STAKING_PROGRAM_IDS.MemeBaseAlpha2]: getMemeActivityCheckerContract( '0x026AB1c5ea14E61f67d245685D9561c0c2Cb39Ba', ), - [StakingProgramId.MemeBaseBeta]: getMemeActivityCheckerContract( + [STAKING_PROGRAM_IDS.MemeBaseBeta]: getMemeActivityCheckerContract( '0x008F52AF7009e262967caa7Cb79468F92AFEADF9', ), - [StakingProgramId.MemeBaseBeta2]: getMemeActivityCheckerContract( + [STAKING_PROGRAM_IDS.MemeBaseBeta2]: getMemeActivityCheckerContract( '0x026AB1c5ea14E61f67d245685D9561c0c2Cb39Ba', ), - [StakingProgramId.MemeBaseBeta3]: getMemeActivityCheckerContract( + [STAKING_PROGRAM_IDS.MemeBaseBeta3]: getMemeActivityCheckerContract( '0x026AB1c5ea14E61f67d245685D9561c0c2Cb39Ba', ), - [StakingProgramId.AgentsFun1]: getRequesterActivityCheckerContract( + [STAKING_PROGRAM_IDS.AgentsFun1]: getRequesterActivityCheckerContract( '0x87C9922A099467E5A80367553e7003349FE50106', ), - [StakingProgramId.AgentsFun2]: getRequesterActivityCheckerContract( + [STAKING_PROGRAM_IDS.AgentsFun2]: getRequesterActivityCheckerContract( '0x4bEb05F76f4563DE7BCB6276915C3E1F71184D8f', ), - [StakingProgramId.AgentsFun3]: getRequesterActivityCheckerContract( + [STAKING_PROGRAM_IDS.AgentsFun3]: getRequesterActivityCheckerContract( '0xF0814A105c1b684922Fce8C3b80d7B6Ff1e399F9', ), } as const; @@ -93,28 +103,43 @@ export const MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS: Record< string, MulticallContract > = { - [StakingProgramId.ModiusAlpha]: getStakingActivityCheckerContract( + [STAKING_PROGRAM_IDS.ModiusAlpha]: getStakingActivityCheckerContract( '0x07bc3C23DbebEfBF866Ca7dD9fAA3b7356116164', ), - [StakingProgramId.OptimusAlpha]: getStakingActivityCheckerContract( + [STAKING_PROGRAM_IDS.OptimusAlpha]: getStakingActivityCheckerContract( '0x07bc3C23DbebEfBF866Ca7dD9fAA3b7356116164', ), - [StakingProgramId.ModiusAlpha2]: getStakingActivityCheckerContract( + [STAKING_PROGRAM_IDS.ModiusAlpha2]: getStakingActivityCheckerContract( '0x07bc3C23DbebEfBF866Ca7dD9fAA3b7356116164', ), - [StakingProgramId.ModiusAlpha3]: getStakingActivityCheckerContract( + [STAKING_PROGRAM_IDS.ModiusAlpha3]: getStakingActivityCheckerContract( '0x07bc3C23DbebEfBF866Ca7dD9fAA3b7356116164', ), - [StakingProgramId.ModiusAlpha4]: getStakingActivityCheckerContract( + [STAKING_PROGRAM_IDS.ModiusAlpha4]: getStakingActivityCheckerContract( '0x07bc3C23DbebEfBF866Ca7dD9fAA3b7356116164', ), } as const; +export const OPTIMISM_STAKING_PROGRAMS_ACTIVITY_CHECKERS: Record< + OptimismStakingProgramId, + MulticallContract +> = { + [STAKING_PROGRAM_IDS.OptimusAlpha2]: getStakingActivityCheckerContract( + '0x7Fd1F4b764fA41d19fe3f63C85d12bf64d2bbf68', + ), + [STAKING_PROGRAM_IDS.OptimusAlpha3]: getStakingActivityCheckerContract( + '0x7Fd1F4b764fA41d19fe3f63C85d12bf64d2bbf68', + ), + [STAKING_PROGRAM_IDS.OptimusAlpha4]: getStakingActivityCheckerContract( + '0x7Fd1F4b764fA41d19fe3f63C85d12bf64d2bbf68', + ), +} as const; + export const CELO_STAKING_PROGRAMS_ACTIVITY_CHECKERS: Record< string, MulticallContract > = { - [StakingProgramId.MemeCeloAlpha2]: getMemeActivityCheckerContract( + [STAKING_PROGRAM_IDS.MemeCeloAlpha2]: getMemeActivityCheckerContract( '0x3FD8C757dE190bcc82cF69Df3Cd9Ab15bCec1426', ), } as const; diff --git a/frontend/config/agents.ts b/frontend/config/agents.ts index d69eacd37..47abb3ec7 100644 --- a/frontend/config/agents.ts +++ b/frontend/config/agents.ts @@ -1,25 +1,42 @@ import { formatUnits } from 'ethers/lib/utils'; import { MiddlewareChain } from '@/client'; -import { MODIUS_SERVICE_TEMPLATE } from '@/constants/serviceTemplates'; +import { + MODIUS_SERVICE_TEMPLATE, + OPTIMUS_SERVICE_TEMPLATE, +} from '@/constants/serviceTemplates'; import { AgentType } from '@/enums/Agent'; import { EvmChainId } from '@/enums/Chain'; import { TokenSymbol } from '@/enums/Token'; import { AgentsFunBaseService } from '@/service/agents/AgentsFunBase'; import { ModiusService } from '@/service/agents/Modius'; +import { OptimismService } from '@/service/agents/Optimism'; import { PredictTraderService } from '@/service/agents/PredictTrader'; import { Address } from '@/types/Address'; import { AgentConfig } from '@/types/Agent'; -import { MODE_TOKEN_CONFIG } from './tokens'; +import { MODE_TOKEN_CONFIG, OPTIMISM_TOKEN_CONFIG } from './tokens'; -const modiusFundRequirements = - MODIUS_SERVICE_TEMPLATE.configurations[MiddlewareChain.MODE] - .fund_requirements; -const modiusUsdcConfig = - modiusFundRequirements?.[ - MODE_TOKEN_CONFIG[TokenSymbol.USDC].address as Address - ]; +const getModiusUsdcConfig = () => { + const modiusFundRequirements = + MODIUS_SERVICE_TEMPLATE.configurations[MiddlewareChain.MODE] + ?.fund_requirements; + const modiusUsdcConfig = MODE_TOKEN_CONFIG[TokenSymbol.USDC]; + const usdcSafeRequirement = + modiusFundRequirements?.[modiusUsdcConfig.address as Address]?.safe || 0; + return Number(formatUnits(usdcSafeRequirement, modiusUsdcConfig.decimals)); +}; + +const getOptimusUsdcConfig = () => { + const optimusFundRequirements = + OPTIMUS_SERVICE_TEMPLATE.configurations[MiddlewareChain.OPTIMISM] + ?.fund_requirements; + const optimusUsdcConfig = OPTIMISM_TOKEN_CONFIG[TokenSymbol.USDC]; + const usdcSafeRequirement = + optimusFundRequirements?.[optimusUsdcConfig.address as Address]?.safe || 0; + + return Number(formatUnits(usdcSafeRequirement, optimusUsdcConfig.decimals)); +}; export const AGENT_CONFIG: { [key in AgentType]: AgentConfig; @@ -59,14 +76,7 @@ export const AGENT_CONFIG: { middlewareHomeChainId: MiddlewareChain.MODE, requiresAgentSafesOn: [EvmChainId.Mode], additionalRequirements: { - [EvmChainId.Mode]: { - [TokenSymbol.USDC]: Number( - formatUnits( - modiusUsdcConfig?.safe || 0, - MODE_TOKEN_CONFIG[TokenSymbol.USDC].decimals, - ), - ), - }, + [EvmChainId.Mode]: { [TokenSymbol.USDC]: getModiusUsdcConfig() }, }, requiresMasterSafesOn: [EvmChainId.Mode], serviceApi: ModiusService, @@ -74,6 +84,23 @@ export const AGENT_CONFIG: { description: 'Invests crypto assets on your behalf and grows your portfolio on Mode network.', }, + [AgentType.Optimus]: { + isAgentEnabled: true, + isComingSoon: false, + requiresSetup: true, + name: 'Optimus agent', + evmHomeChainId: EvmChainId.Optimism, + middlewareHomeChainId: MiddlewareChain.OPTIMISM, + requiresAgentSafesOn: [EvmChainId.Optimism], + additionalRequirements: { + [EvmChainId.Optimism]: { [TokenSymbol.USDC]: getOptimusUsdcConfig() }, + }, + requiresMasterSafesOn: [EvmChainId.Optimism], + serviceApi: OptimismService, + displayName: 'Optimus agent', + description: + 'Invests crypto assets on your behalf and grows your portfolio on Optimus network.', + }, // TODO: celo (check each key) [AgentType.AgentsFunCelo]: { isAgentEnabled: false, diff --git a/frontend/config/chains.ts b/frontend/config/chains.ts index fb853ebfa..22191824c 100644 --- a/frontend/config/chains.ts +++ b/frontend/config/chains.ts @@ -18,8 +18,9 @@ export type ChainConfig = { rpc: HttpUrl; // TODO: the values are hardcoded, should be fetched from the backend /** - * Least amount of native token required to create a Safe - * @example for gnosis chain, 1.5 XDAI is required to create a Safe + * Least amount of native token required to create a Safe. + * @example for gnosis chain, 1.5 XDAI is required to create a Safe. + * For new chains, ask middleware team for the value. */ safeCreationThreshold: number; }; @@ -61,6 +62,15 @@ export const CELO_CHAIN_CONFIG: ChainConfig = { safeCreationThreshold: 0.005, } as const; +export const OPTIMISM_CHAIN_CONFIG: ChainConfig = { + evmChainId: EvmChainId.Optimism, + name: 'Optimism', + nativeToken: TOKEN_CONFIG[EvmChainId.Optimism][TokenSymbol.ETH], + middlewareChain: MiddlewareChainId.OPTIMISM, + rpc: process.env.OPTIMISM_RPC as HttpUrl, + safeCreationThreshold: 0.005, +} as const; + export const CHAIN_CONFIG: { [evmChainId in EvmChainId]: ChainConfig; } = { @@ -68,4 +78,5 @@ export const CHAIN_CONFIG: { [EvmChainId.Gnosis]: GNOSIS_CHAIN_CONFIG, [EvmChainId.Mode]: MODE_CHAIN_CONFIG, [EvmChainId.Celo]: CELO_CHAIN_CONFIG, + [EvmChainId.Optimism]: OPTIMISM_CHAIN_CONFIG, } as const; diff --git a/frontend/config/olasContracts.ts b/frontend/config/olasContracts.ts index 12303f635..bf398b250 100644 --- a/frontend/config/olasContracts.ts +++ b/frontend/config/olasContracts.ts @@ -42,6 +42,17 @@ const MODE_OLAS_CONTRACTS: ContractsByType = { ), }; +const OPTIMISM_OLAS_CONTRACTS: ContractsByType = { + [ContractType.ServiceRegistryL2]: new MulticallContract( + '0x3d77596beb0f130a4415df3D2D8232B3d3D31e44', + SERVICE_REGISTRY_L2_ABI, + ), + [ContractType.ServiceRegistryTokenUtility]: new MulticallContract( + '0xBb7e1D6Cb6F243D6bdE81CE92a9f2aFF7Fbe7eac', + SERVICE_REGISTRY_TOKEN_UTILITY_ABI, + ), +}; + const CELO_OLAS_CONTRACTS: ContractsByType = { [ContractType.ServiceRegistryL2]: new MulticallContract( '0xE3607b00E75f6405248323A9417ff6b39B244b50', @@ -60,4 +71,5 @@ export const OLAS_CONTRACTS: { [EvmChainId.Base]: BASE_OLAS_CONTRACTS, [EvmChainId.Mode]: MODE_OLAS_CONTRACTS, [EvmChainId.Celo]: CELO_OLAS_CONTRACTS, + [EvmChainId.Optimism]: OPTIMISM_OLAS_CONTRACTS, }; diff --git a/frontend/config/stakingPrograms/base.ts b/frontend/config/stakingPrograms/base.ts index b367a5462..f52f1a582 100644 --- a/frontend/config/stakingPrograms/base.ts +++ b/frontend/config/stakingPrograms/base.ts @@ -3,7 +3,7 @@ import { Contract as MulticallContract } from 'ethers-multicall'; import { STAKING_TOKEN_PROXY_ABI } from '@/abis/stakingTokenProxy'; import { AgentType } from '@/enums/Agent'; import { EvmChainId } from '@/enums/Chain'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { STAKING_PROGRAM_IDS } from '@/enums/StakingProgram'; import { TokenSymbol } from '@/enums/Token'; import { Address } from '@/types/Address'; @@ -13,21 +13,24 @@ import { StakingProgramMap } from '.'; export const BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES: Record = { - [StakingProgramId.MemeBaseAlpha2]: + [STAKING_PROGRAM_IDS.MemeBaseAlpha2]: '0xc653622FD75026a020995a1d8c8651316cBBc4dA', - [StakingProgramId.MemeBaseBeta]: + [STAKING_PROGRAM_IDS.MemeBaseBeta]: '0x6011E09e7c095e76980b22498d69dF18EB62BeD8', - [StakingProgramId.MemeBaseBeta2]: + [STAKING_PROGRAM_IDS.MemeBaseBeta2]: '0xfb7669c3AdF673b3A545Fa5acd987dbfdA805e22', - [StakingProgramId.MemeBaseBeta3]: + [STAKING_PROGRAM_IDS.MemeBaseBeta3]: '0xCA61633b03c54F64b6A7F1f9A9C0A6Feb231Cc4D', - [StakingProgramId.AgentsFun1]: '0x2585e63df7BD9De8e058884D496658a030b5c6ce', - [StakingProgramId.AgentsFun2]: '0x26FA75ef9Ccaa60E58260226A71e9d07564C01bF', - [StakingProgramId.AgentsFun3]: '0x4D4233EBF0473Ca8f34d105A6256A2389176F0Ce', + [STAKING_PROGRAM_IDS.AgentsFun1]: + '0x2585e63df7BD9De8e058884D496658a030b5c6ce', + [STAKING_PROGRAM_IDS.AgentsFun2]: + '0x26FA75ef9Ccaa60E58260226A71e9d07564C01bF', + [STAKING_PROGRAM_IDS.AgentsFun3]: + '0x4D4233EBF0473Ca8f34d105A6256A2389176F0Ce', }; export const BASE_STAKING_PROGRAMS: StakingProgramMap = { - [StakingProgramId.MemeBaseAlpha2]: { + [STAKING_PROGRAM_IDS.MemeBaseAlpha2]: { deprecated: true, chainId: EvmChainId.Base, name: 'MemeBase Alpha II', @@ -36,13 +39,17 @@ export const BASE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 100, }, activityChecker: - BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.MemeBaseAlpha2], + BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ + STAKING_PROGRAM_IDS.MemeBaseAlpha2 + ], contract: new MulticallContract( - BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.MemeBaseAlpha2], + BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.MemeBaseAlpha2 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.MemeBaseBeta]: { + [STAKING_PROGRAM_IDS.MemeBaseBeta]: { deprecated: true, chainId: EvmChainId.Base, name: 'MemeBase Beta I', @@ -51,13 +58,15 @@ export const BASE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 100, }, activityChecker: - BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.MemeBaseBeta], + BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.MemeBaseBeta], contract: new MulticallContract( - BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.MemeBaseBeta], + BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.MemeBaseBeta + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.MemeBaseBeta2]: { + [STAKING_PROGRAM_IDS.MemeBaseBeta2]: { deprecated: true, chainId: EvmChainId.Base, name: 'MemeBase Beta II', @@ -66,13 +75,17 @@ export const BASE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 1000, }, activityChecker: - BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.MemeBaseBeta2], + BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ + STAKING_PROGRAM_IDS.MemeBaseBeta2 + ], contract: new MulticallContract( - BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.MemeBaseBeta2], + BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.MemeBaseBeta2 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.MemeBaseBeta3]: { + [STAKING_PROGRAM_IDS.MemeBaseBeta3]: { deprecated: true, chainId: EvmChainId.Base, name: 'MemeBase Beta III', @@ -81,13 +94,17 @@ export const BASE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 5000, }, activityChecker: - BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.MemeBaseBeta3], + BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ + STAKING_PROGRAM_IDS.MemeBaseBeta3 + ], contract: new MulticallContract( - BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.MemeBaseBeta3], + BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.MemeBaseBeta3 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.AgentsFun1]: { + [STAKING_PROGRAM_IDS.AgentsFun1]: { chainId: EvmChainId.Base, name: 'Agents.fun 1', agentsSupported: [AgentType.Memeooorr], @@ -97,13 +114,13 @@ export const BASE_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Marketplace, mech: MECHS[EvmChainId.Base][MechType.Marketplace].contract, activityChecker: - BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.AgentsFun1], + BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.AgentsFun1], contract: new MulticallContract( - BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.AgentsFun1], + BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[STAKING_PROGRAM_IDS.AgentsFun1], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.AgentsFun2]: { + [STAKING_PROGRAM_IDS.AgentsFun2]: { chainId: EvmChainId.Base, name: 'Agents.fun 2', agentsSupported: [AgentType.Memeooorr], @@ -113,13 +130,13 @@ export const BASE_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Marketplace, mech: MECHS[EvmChainId.Base][MechType.Marketplace].contract, activityChecker: - BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.AgentsFun2], + BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.AgentsFun2], contract: new MulticallContract( - BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.AgentsFun2], + BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[STAKING_PROGRAM_IDS.AgentsFun2], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.AgentsFun3]: { + [STAKING_PROGRAM_IDS.AgentsFun3]: { chainId: EvmChainId.Base, name: 'Agents.fun 3', agentsSupported: [AgentType.Memeooorr], @@ -129,9 +146,9 @@ export const BASE_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Marketplace, mech: MECHS[EvmChainId.Base][MechType.Marketplace].contract, activityChecker: - BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.AgentsFun3], + BASE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.AgentsFun3], contract: new MulticallContract( - BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.AgentsFun3], + BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[STAKING_PROGRAM_IDS.AgentsFun3], STAKING_TOKEN_PROXY_ABI, ), }, diff --git a/frontend/config/stakingPrograms/celo.ts b/frontend/config/stakingPrograms/celo.ts index 87810d04e..3fac66ad8 100644 --- a/frontend/config/stakingPrograms/celo.ts +++ b/frontend/config/stakingPrograms/celo.ts @@ -3,7 +3,7 @@ import { Contract as MulticallContract } from 'ethers-multicall'; import { STAKING_TOKEN_PROXY_ABI } from '@/abis/stakingTokenProxy'; import { AgentType } from '@/enums/Agent'; import { EvmChainId } from '@/enums/Chain'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { STAKING_PROGRAM_IDS } from '@/enums/StakingProgram'; import { TokenSymbol } from '@/enums/Token'; import { Address } from '@/types/Address'; @@ -12,12 +12,12 @@ import { StakingProgramMap } from '.'; export const CELO_STAKING_PROGRAMS_CONTRACT_ADDRESSES: Record = { - [StakingProgramId.MemeCeloAlpha2]: + [STAKING_PROGRAM_IDS.MemeCeloAlpha2]: '0x95D12D193d466237Bc1E92a1a7756e4264f574AB', }; export const CELO_STAKING_PROGRAMS: StakingProgramMap = { - [StakingProgramId.MemeCeloAlpha2]: { + [STAKING_PROGRAM_IDS.MemeCeloAlpha2]: { chainId: EvmChainId.Celo, name: 'MemeCelo Alpha II', agentsSupported: [AgentType.AgentsFunCelo], @@ -25,9 +25,13 @@ export const CELO_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 100, }, activityChecker: - CELO_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.MemeCeloAlpha2], + CELO_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ + STAKING_PROGRAM_IDS.MemeCeloAlpha2 + ], contract: new MulticallContract( - CELO_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.MemeCeloAlpha2], + CELO_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.MemeCeloAlpha2 + ], STAKING_TOKEN_PROXY_ABI, ), }, diff --git a/frontend/config/stakingPrograms/gnosis.ts b/frontend/config/stakingPrograms/gnosis.ts index 2d8c59878..e035f6e29 100644 --- a/frontend/config/stakingPrograms/gnosis.ts +++ b/frontend/config/stakingPrograms/gnosis.ts @@ -3,7 +3,7 @@ import { Contract as MulticallContract } from 'ethers-multicall'; import { STAKING_TOKEN_PROXY_ABI } from '@/abis/stakingTokenProxy'; import { AgentType } from '@/enums/Agent'; import { EvmChainId } from '@/enums/Chain'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { STAKING_PROGRAM_IDS } from '@/enums/StakingProgram'; import { TokenSymbol } from '@/enums/Token'; import { Address } from '@/types/Address'; @@ -15,19 +15,25 @@ export const GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES: Record< string, Address > = { - [StakingProgramId.PearlAlpha]: '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', - [StakingProgramId.PearlBeta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', - [StakingProgramId.PearlBeta2]: '0x1c2F82413666d2a3fD8bC337b0268e62dDF67434', - [StakingProgramId.PearlBeta3]: '0xBd59Ff0522aA773cB6074ce83cD1e4a05A457bc1', - [StakingProgramId.PearlBeta4]: '0x3052451e1eAee78e62E169AfdF6288F8791F2918', - [StakingProgramId.PearlBeta5]: '0x4Abe376Fda28c2F43b84884E5f822eA775DeA9F4', - [StakingProgramId.PearlBeta6]: '0x6C6D01e8eA8f806eF0c22F0ef7ed81D868C1aB39', - [StakingProgramId.PearlBetaMechMarketplace]: + [STAKING_PROGRAM_IDS.PearlAlpha]: + '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', + [STAKING_PROGRAM_IDS.PearlBeta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', + [STAKING_PROGRAM_IDS.PearlBeta2]: + '0x1c2F82413666d2a3fD8bC337b0268e62dDF67434', + [STAKING_PROGRAM_IDS.PearlBeta3]: + '0xBd59Ff0522aA773cB6074ce83cD1e4a05A457bc1', + [STAKING_PROGRAM_IDS.PearlBeta4]: + '0x3052451e1eAee78e62E169AfdF6288F8791F2918', + [STAKING_PROGRAM_IDS.PearlBeta5]: + '0x4Abe376Fda28c2F43b84884E5f822eA775DeA9F4', + [STAKING_PROGRAM_IDS.PearlBeta6]: + '0x6C6D01e8eA8f806eF0c22F0ef7ed81D868C1aB39', + [STAKING_PROGRAM_IDS.PearlBetaMechMarketplace]: '0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA', } as const; export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { - [StakingProgramId.PearlAlpha]: { + [STAKING_PROGRAM_IDS.PearlAlpha]: { deprecated: true, name: 'Pearl Alpha', chainId: EvmChainId.Gnosis, @@ -38,13 +44,15 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Agent, mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, activityChecker: - GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.PearlAlpha], + GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.PearlAlpha], contract: new MulticallContract( - GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlAlpha], + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.PearlAlpha + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.PearlBeta]: { + [STAKING_PROGRAM_IDS.PearlBeta]: { chainId: EvmChainId.Gnosis, name: 'Pearl Beta', agentsSupported: [AgentType.PredictTrader], @@ -54,13 +62,13 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Agent, mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, activityChecker: - GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.PearlBeta], + GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.PearlBeta], contract: new MulticallContract( - GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta], + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[STAKING_PROGRAM_IDS.PearlBeta], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.PearlBeta2]: { + [STAKING_PROGRAM_IDS.PearlBeta2]: { chainId: EvmChainId.Gnosis, name: 'Pearl Beta 2', agentsSupported: [AgentType.PredictTrader], @@ -70,13 +78,15 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Agent, mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, activityChecker: - GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.PearlBeta2], + GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.PearlBeta2], contract: new MulticallContract( - GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta2], + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.PearlBeta2 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.PearlBeta3]: { + [STAKING_PROGRAM_IDS.PearlBeta3]: { chainId: EvmChainId.Gnosis, name: 'Pearl Beta 3', agentsSupported: [AgentType.PredictTrader], @@ -86,13 +96,15 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Agent, mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, activityChecker: - GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.PearlBeta3], + GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.PearlBeta3], contract: new MulticallContract( - GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta3], + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.PearlBeta3 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.PearlBeta4]: { + [STAKING_PROGRAM_IDS.PearlBeta4]: { chainId: EvmChainId.Gnosis, name: 'Pearl Beta 4', agentsSupported: [AgentType.PredictTrader], @@ -102,13 +114,15 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Agent, mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, activityChecker: - GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.PearlBeta4], + GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.PearlBeta4], contract: new MulticallContract( - GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta4], + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.PearlBeta4 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.PearlBeta5]: { + [STAKING_PROGRAM_IDS.PearlBeta5]: { chainId: EvmChainId.Gnosis, name: 'Pearl Beta 5', agentsSupported: [AgentType.PredictTrader], @@ -118,13 +132,15 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Agent, mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, activityChecker: - GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.PearlBeta5], + GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.PearlBeta5], contract: new MulticallContract( - GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta5], + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.PearlBeta5 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.PearlBeta6]: { + [STAKING_PROGRAM_IDS.PearlBeta6]: { chainId: EvmChainId.Gnosis, name: 'Pearl Beta 6', agentsSupported: [AgentType.PredictTrader], @@ -134,13 +150,15 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mechType: MechType.Agent, mech: MECHS[EvmChainId.Gnosis][MechType.Marketplace].contract, activityChecker: - GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.PearlBeta6], + GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.PearlBeta6], contract: new MulticallContract( - GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta6], + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.PearlBeta6 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.PearlBetaMechMarketplace]: { + [STAKING_PROGRAM_IDS.PearlBetaMechMarketplace]: { chainId: EvmChainId.Gnosis, name: 'Pearl Beta Mech Marketplace', agentsSupported: [AgentType.PredictTrader], @@ -151,11 +169,11 @@ export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { mech: MECHS[EvmChainId.Gnosis][MechType.Marketplace].contract, activityChecker: GNOSIS_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ - StakingProgramId.PearlBetaMechMarketplace + STAKING_PROGRAM_IDS.PearlBetaMechMarketplace ], contract: new MulticallContract( GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ - StakingProgramId.PearlBetaMechMarketplace + STAKING_PROGRAM_IDS.PearlBetaMechMarketplace ], STAKING_TOKEN_PROXY_ABI, ), diff --git a/frontend/config/stakingPrograms/index.ts b/frontend/config/stakingPrograms/index.ts index 93ba390ff..8994195e3 100644 --- a/frontend/config/stakingPrograms/index.ts +++ b/frontend/config/stakingPrograms/index.ts @@ -2,7 +2,7 @@ import { Contract as MulticallContract } from 'ethers-multicall'; import { AgentType } from '@/enums/Agent'; import { EvmChainId } from '@/enums/Chain'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { STAKING_PROGRAM_IDS, StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; import { MechType } from '../mechs'; @@ -22,6 +22,10 @@ import { MODE_STAKING_PROGRAMS, MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES, } from './mode'; +import { + OPTIMISM_STAKING_PROGRAMS, + OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, +} from './optimism'; /** * Single non-chain specific staking program configuration @@ -51,6 +55,7 @@ export const STAKING_PROGRAMS: { [EvmChainId.Base]: BASE_STAKING_PROGRAMS, [EvmChainId.Mode]: MODE_STAKING_PROGRAMS, [EvmChainId.Celo]: CELO_STAKING_PROGRAMS, + [EvmChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS, }; export const STAKING_PROGRAM_ADDRESS: { @@ -60,13 +65,15 @@ export const STAKING_PROGRAM_ADDRESS: { [EvmChainId.Base]: BASE_STAKING_PROGRAMS_CONTRACT_ADDRESSES, [EvmChainId.Mode]: MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES, [EvmChainId.Celo]: CELO_STAKING_PROGRAMS_CONTRACT_ADDRESSES, + [EvmChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, }; export const DEFAULT_STAKING_PROGRAM_IDS: { [chainId in EvmChainId]: StakingProgramId; } = { - [EvmChainId.Gnosis]: StakingProgramId.PearlBeta, - [EvmChainId.Base]: StakingProgramId.AgentsFun1, - [EvmChainId.Mode]: StakingProgramId.ModiusAlpha, - [EvmChainId.Celo]: StakingProgramId.MemeCeloAlpha2, + [EvmChainId.Gnosis]: STAKING_PROGRAM_IDS.PearlBeta, + [EvmChainId.Base]: STAKING_PROGRAM_IDS.MemeBaseAlpha2, + [EvmChainId.Mode]: STAKING_PROGRAM_IDS.ModiusAlpha, + [EvmChainId.Celo]: STAKING_PROGRAM_IDS.MemeCeloAlpha2, + [EvmChainId.Optimism]: STAKING_PROGRAM_IDS.OptimusAlpha2, }; diff --git a/frontend/config/stakingPrograms/mode.ts b/frontend/config/stakingPrograms/mode.ts index 0c265887f..219ac3f40 100644 --- a/frontend/config/stakingPrograms/mode.ts +++ b/frontend/config/stakingPrograms/mode.ts @@ -3,7 +3,7 @@ import { Contract as MulticallContract } from 'ethers-multicall'; import { STAKING_TOKEN_PROXY_ABI } from '@/abis/stakingTokenProxy'; import { AgentType } from '@/enums/Agent'; import { EvmChainId } from '@/enums/Chain'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { STAKING_PROGRAM_IDS } from '@/enums/StakingProgram'; import { TokenSymbol } from '@/enums/Token'; import { Address } from '@/types/Address'; @@ -12,21 +12,21 @@ import { StakingProgramMap } from '.'; export const MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES: Record = { - [StakingProgramId.ModiusAlpha]: + [STAKING_PROGRAM_IDS.ModiusAlpha]: '0x534C0A05B6d4d28d5f3630D6D74857B253cf8332', - [StakingProgramId.OptimusAlpha]: - '0x5fc25f50e96857373c64dc0edb1abcbed4587e91', - [StakingProgramId.ModiusAlpha2]: + [STAKING_PROGRAM_IDS.ModiusAlpha2]: '0xeC013E68FE4B5734643499887941eC197fd757D0', - [StakingProgramId.ModiusAlpha3]: + [STAKING_PROGRAM_IDS.ModiusAlpha3]: '0x9034D0413D122015710f1744A19eFb1d7c2CEB13', - [StakingProgramId.ModiusAlpha4]: + [STAKING_PROGRAM_IDS.ModiusAlpha4]: '0x8BcAdb2c291C159F9385964e5eD95a9887302862', + [STAKING_PROGRAM_IDS.OptimusAlpha]: + '0x5fc25f50e96857373c64dc0edb1abcbed4587e91', }; export const MODE_STAKING_PROGRAMS: StakingProgramMap = { // modius alpha - [StakingProgramId.ModiusAlpha]: { + [STAKING_PROGRAM_IDS.ModiusAlpha]: { chainId: EvmChainId.Mode, name: 'Modius Alpha', agentsSupported: [AgentType.Modius], @@ -34,13 +34,13 @@ export const MODE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 40, }, activityChecker: - MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.ModiusAlpha], + MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.ModiusAlpha], contract: new MulticallContract( - MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.ModiusAlpha], + MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[STAKING_PROGRAM_IDS.ModiusAlpha], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.ModiusAlpha2]: { + [STAKING_PROGRAM_IDS.ModiusAlpha2]: { chainId: EvmChainId.Mode, name: 'Modius Alpha II', agentsSupported: [AgentType.Modius], @@ -48,13 +48,15 @@ export const MODE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 100, }, activityChecker: - MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.ModiusAlpha2], + MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.ModiusAlpha2], contract: new MulticallContract( - MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.ModiusAlpha2], + MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.ModiusAlpha2 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.ModiusAlpha3]: { + [STAKING_PROGRAM_IDS.ModiusAlpha3]: { chainId: EvmChainId.Mode, name: 'Modius Alpha III', agentsSupported: [AgentType.Modius], @@ -62,13 +64,15 @@ export const MODE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 1000, }, activityChecker: - MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.ModiusAlpha3], + MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.ModiusAlpha3], contract: new MulticallContract( - MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.ModiusAlpha3], + MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.ModiusAlpha3 + ], STAKING_TOKEN_PROXY_ABI, ), }, - [StakingProgramId.ModiusAlpha4]: { + [STAKING_PROGRAM_IDS.ModiusAlpha4]: { chainId: EvmChainId.Mode, name: 'Modius Alpha IV', agentsSupported: [AgentType.Modius], @@ -76,14 +80,16 @@ export const MODE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 5000, }, activityChecker: - MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.ModiusAlpha4], + MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.ModiusAlpha4], contract: new MulticallContract( - MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.ModiusAlpha4], + MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.ModiusAlpha4 + ], STAKING_TOKEN_PROXY_ABI, ), }, - //optimus alpha - [StakingProgramId.OptimusAlpha]: { + // optimus alpha + [STAKING_PROGRAM_IDS.OptimusAlpha]: { chainId: EvmChainId.Mode, name: 'Optimus Alpha', agentsSupported: [AgentType.Modius], @@ -91,9 +97,11 @@ export const MODE_STAKING_PROGRAMS: StakingProgramMap = { [TokenSymbol.OLAS]: 40, }, activityChecker: - MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[StakingProgramId.OptimusAlpha], + MODE_STAKING_PROGRAMS_ACTIVITY_CHECKERS[STAKING_PROGRAM_IDS.OptimusAlpha], contract: new MulticallContract( - MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.OptimusAlpha], + MODE_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + STAKING_PROGRAM_IDS.OptimusAlpha + ], STAKING_TOKEN_PROXY_ABI, ), }, diff --git a/frontend/config/stakingPrograms/optimism.ts b/frontend/config/stakingPrograms/optimism.ts new file mode 100644 index 000000000..2ac601569 --- /dev/null +++ b/frontend/config/stakingPrograms/optimism.ts @@ -0,0 +1,83 @@ +import { Contract as MulticallContract } from 'ethers-multicall'; + +import { STAKING_TOKEN_PROXY_ABI } from '@/abis/stakingTokenProxy'; +import { AgentType } from '@/enums/Agent'; +import { EvmChainId } from '@/enums/Chain'; +import { + OPTIMISM_STAKING_PROGRAM_IDS, + OptimismStakingProgramId, +} from '@/enums/StakingProgram'; +import { TokenSymbol } from '@/enums/Token'; +import { Address } from '@/types/Address'; + +import { OPTIMISM_STAKING_PROGRAMS_ACTIVITY_CHECKERS } from '../activityCheckers'; +import { StakingProgramConfig } from '.'; + +export const OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES: Record< + OptimismStakingProgramId, + Address +> = { + [OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha2]: + '0xBCA056952D2A7a8dD4A002079219807CFDF9fd29', + [OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha3]: + '0x0f69f35652B1acdbD769049334f1AC580927E139', + [OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha4]: + '0x6891Cf116f9a3bDbD1e89413118eF81F69D298C3', +}; + +export const OPTIMISM_STAKING_PROGRAMS: { + [stakingProgramId in OptimismStakingProgramId]: StakingProgramConfig; +} = { + [OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha2]: { + chainId: EvmChainId.Optimism, + name: 'Optimus Alpha II', + agentsSupported: [AgentType.Optimus], + stakingRequirements: { [TokenSymbol.OLAS]: 100 }, + activityChecker: + OPTIMISM_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ + OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha2 + ], + contract: new MulticallContract( + OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha2 + ], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha3]: { + chainId: EvmChainId.Optimism, + name: 'Optimus Alpha III', + agentsSupported: [AgentType.Optimus], + stakingRequirements: { + [TokenSymbol.OLAS]: 1000, + }, + activityChecker: + OPTIMISM_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ + OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha3 + ], + contract: new MulticallContract( + OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha3 + ], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha4]: { + chainId: EvmChainId.Optimism, + name: 'Optimus Alpha IV', + agentsSupported: [AgentType.Optimus], + stakingRequirements: { + [TokenSymbol.OLAS]: 5000, + }, + activityChecker: + OPTIMISM_STAKING_PROGRAMS_ACTIVITY_CHECKERS[ + OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha4 + ], + contract: new MulticallContract( + OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + OPTIMISM_STAKING_PROGRAM_IDS.OptimusAlpha4 + ], + STAKING_TOKEN_PROXY_ABI, + ), + }, +}; diff --git a/frontend/config/tokens.ts b/frontend/config/tokens.ts index 75d222dc5..ecf8a40e5 100644 --- a/frontend/config/tokens.ts +++ b/frontend/config/tokens.ts @@ -135,6 +135,31 @@ export const MODE_TOKEN_CONFIG: ChainTokenConfig = { }, }; +export const OPTIMISM_TOKEN_CONFIG: ChainTokenConfig = { + [TokenSymbol.ETH]: { + tokenType: TokenType.NativeGas, + symbol: TokenSymbol.ETH, + decimals: 18, + }, + [TokenSymbol.OLAS]: { + tokenType: TokenType.Erc20, + symbol: TokenSymbol.OLAS, + decimals: 18, + address: '0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527', + }, + /** + * @warning USDC is a special case, it has 6 decimals, not 18. + * @link https://optimism.blockscout.com/address/0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85?tab=read_write_proxy&source_address=0xdEd3b9a8DBeDC2F9CB725B55d0E686A81E6d06dC#0x313ce567 + * @note When parsing or formatting units, use `decimals` (6) instead of the standard `ether` sizing (10^18). + */ + [TokenSymbol.USDC]: { + tokenType: TokenType.Erc20, + symbol: TokenSymbol.USDC, + decimals: 6, + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + }, +}; + /** * TODO: * 1. combine EvmChainId and AllEvmChainId into one thing to avoid confusion @@ -145,6 +170,7 @@ export const TOKEN_CONFIG: Record = { [EvmChainId.Base]: BASE_TOKEN_CONFIG, [EvmChainId.Mode]: MODE_TOKEN_CONFIG, [EvmChainId.Celo]: CELO_TOKEN_CONFIG, + [EvmChainId.Optimism]: OPTIMISM_TOKEN_CONFIG, } as const; /** diff --git a/frontend/constants/chains.ts b/frontend/constants/chains.ts new file mode 100644 index 000000000..06acb7139 --- /dev/null +++ b/frontend/constants/chains.ts @@ -0,0 +1,24 @@ +export const EvmChainId = { + Gnosis: 100, + Base: 8453, + Mode: 34443, + Celo: 42220, + Optimism: 10, +} as const; + +export const EvmChainName = { + [EvmChainId.Gnosis]: 'Gnosis', + [EvmChainId.Base]: 'Base', + [EvmChainId.Mode]: 'Mode', + [EvmChainId.Celo]: 'Celo', + [EvmChainId.Optimism]: 'Optimism', +} as const; + +export const AllEvmChainId = { + Ethereum: 1, + Gnosis: EvmChainId.Gnosis, + Base: EvmChainId.Base, + Mode: EvmChainId.Mode, + Celo: EvmChainId.Celo, + Optimism: EvmChainId.Optimism, +} as const; diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index d4452211a..fba58a39d 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -1,9 +1,9 @@ import { ethers } from 'ethers'; import { EnvProvisionType, MiddlewareChain, ServiceTemplate } from '@/client'; -import { MODE_TOKEN_CONFIG } from '@/config/tokens'; +import { MODE_TOKEN_CONFIG, OPTIMISM_TOKEN_CONFIG } from '@/config/tokens'; import { AgentType } from '@/enums/Agent'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { STAKING_PROGRAM_IDS } from '@/enums/StakingProgram'; import { TokenSymbol } from '@/enums/Token'; import { parseEther, parseUnits } from '@/utils/numberFormatters'; @@ -24,7 +24,7 @@ export const PREDICT_SERVICE_TEMPLATE: ServiceTemplate = { home_chain: MiddlewareChain.GNOSIS, configurations: { [MiddlewareChain.GNOSIS]: { - staking_program_id: StakingProgramId.PearlBeta, // default, may be overwritten + staking_program_id: STAKING_PROGRAM_IDS.PearlBeta, // default, may be overwritten nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', rpc: 'http://localhost:8545', // overwritten agent_id: 14, @@ -89,7 +89,7 @@ export const PREDICT_SERVICE_TEMPLATE: ServiceTemplate = { name: 'Tools accuracy hash', description: '', // Use the latest value from https://github.com/valory-xyz/quickstart/blob/main/configs/config_predict_trader.json#L74 - value: 'QmQKbinSRYSViRVtN77S1NqD9FtA8rE29xUqCDfQKHhJUc', + value: 'QmXqH9SeW2KcpaMLRVNUXCPCjLhXfYB1cVA7Nr2KkfcgB6', provision_type: EnvProvisionType.FIXED, }, MECH_INTERACT_ROUND_TIMEOUT_SECONDS: { @@ -105,7 +105,7 @@ const AGENTS_FUN_COMMON_TEMPLATE: Pick< ServiceTemplate, 'env_variables' | 'hash' | 'image' | 'description' | 'service_version' > = { - hash: 'bafybeiaymgtbsxf6zyoedpgocdjqd5qfnyr3ugybwo7u3iqyiseti4bzke', + hash: 'bafybeifb2s6f3ebqhj3fl7yjvcqktgwp55gdwejd7m3al35gqtytaczjwi', image: 'https://gateway.autonolas.tech/ipfs/QmQYDGMg8m91QQkTWSSmANs5tZwKrmvUCawXZfXVVWQPcu', description: `${KPI_DESC_PREFIX} Memeooorr @twitter_handle`, // NOTE: @twitter_handle to be replaced with twitter username @@ -220,7 +220,7 @@ export const AGENTS_FUN_BASE_TEMPLATE: ServiceTemplate = { home_chain: MiddlewareChain.BASE, configurations: { [MiddlewareChain.BASE]: { - staking_program_id: StakingProgramId.AgentsFun1, // default, may be overwritten + staking_program_id: STAKING_PROGRAM_IDS.AgentsFun1, // default, may be overwritten nft: 'bafybeiaakdeconw7j5z76fgghfdjmsr6tzejotxcwnvmp3nroaw3glgyve', rpc: 'http://localhost:8545', // overwritten agent_id: 43, @@ -249,7 +249,7 @@ export const AGENTS_FUN_CELO_TEMPLATE: ServiceTemplate = { home_chain: MiddlewareChain.CELO, configurations: { [MiddlewareChain.CELO]: { - staking_program_id: StakingProgramId.MemeCeloAlpha2, // default, may be overwritten + staking_program_id: STAKING_PROGRAM_IDS.MemeCeloAlpha2, // default, may be overwritten nft: 'bafybeiaakdeconw7j5z76fgghfdjmsr6tzejotxcwnvmp3nroaw3glgyve', rpc: 'http://localhost:8545', // overwritten agent_id: 43, @@ -271,7 +271,7 @@ export const AGENTS_FUN_CELO_TEMPLATE: ServiceTemplate = { export const MODIUS_SERVICE_TEMPLATE: ServiceTemplate = { agentType: AgentType.Modius, name: 'Optimus', - hash: 'bafybeidjtlrave3ck3usj3cr3wd6vjjipa7dhcoxv6manoqo6mayiyjuu4', + hash: 'bafybeidsxqb5n3lvbickiu7w63za5ezun7ramjqd5nn546feoii56mh3s4', description: `${KPI_DESC_PREFIX} Optimus`, image: 'https://gateway.autonolas.tech/ipfs/bafybeiaakdeconw7j5z76fgghfdjmsr6tzejotxcwnvmp3nroaw3glgyve', @@ -279,7 +279,7 @@ export const MODIUS_SERVICE_TEMPLATE: ServiceTemplate = { home_chain: MiddlewareChain.MODE, configurations: { [MiddlewareChain.MODE]: { - staking_program_id: StakingProgramId.ModiusAlpha, // default, may be overwritten + staking_program_id: STAKING_PROGRAM_IDS.ModiusAlpha, // default, may be overwritten nft: 'bafybeiafjcy63arqkfqbtjqpzxyeia2tscpbyradb4zlpzhgc3xymwmmtu', rpc: 'http://localhost:8545', // overwritten agent_id: 40, @@ -419,11 +419,141 @@ export const MODIUS_SERVICE_TEMPLATE: ServiceTemplate = { }, } as const; +export const OPTIMUS_SERVICE_TEMPLATE: ServiceTemplate = { + agentType: AgentType.Optimus, + name: 'Optimus - Optimism', + hash: 'bafybeidsxqb5n3lvbickiu7w63za5ezun7ramjqd5nn546feoii56mh3s4', + description: `${KPI_DESC_PREFIX} Optimus service deployment on Optimism network`, + image: + 'https://gateway.autonolas.tech/ipfs/bafybeiaakdeconw7j5z76fgghfdjmsr6tzejotxcwnvmp3nroaw3glgyve', + service_version: 'v0.3.15', + home_chain: MiddlewareChain.OPTIMISM, + configurations: { + [MiddlewareChain.OPTIMISM]: { + staking_program_id: STAKING_PROGRAM_IDS.OptimusAlpha, // default, may be overwritten + nft: 'bafybeiafjcy63arqkfqbtjqpzxyeia2tscpbyradb4zlpzhgc3xymwmmtu', + rpc: 'http://localhost:8545', // overwritten + agent_id: 40, + threshold: 1, + use_staking: true, + cost_of_bond: +parseEther(20), + monthly_gas_estimate: +parseEther(0.011), + fund_requirements: { + [ethers.constants.AddressZero]: { + agent: +parseEther(0.0007), + safe: +parseEther(0.0057), + }, + [OPTIMISM_TOKEN_CONFIG[TokenSymbol.USDC].address as string]: { + agent: 0, + safe: +parseUnits( + 16, + OPTIMISM_TOKEN_CONFIG[TokenSymbol.USDC].decimals, + ), + }, + }, + }, + }, + env_variables: { + OPTIMISM_LEDGER_RPC: { + name: 'Optimism ledger RPC', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + SAFE_CONTRACT_ADDRESSES: { + name: 'Safe contract address', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + TENDERLY_ACCESS_KEY: { + name: 'Tenderly access key', + description: '', + value: '', + provision_type: EnvProvisionType.USER, + }, + TENDERLY_ACCOUNT_SLUG: { + name: 'Tenderly account slug', + description: '', + value: '', + provision_type: EnvProvisionType.USER, + }, + TENDERLY_PROJECT_SLUG: { + name: 'Tenderly project slug', + description: '', + value: '', + provision_type: EnvProvisionType.USER, + }, + STAKING_TOKEN_CONTRACT_ADDRESS: { + name: 'Staking token contract address', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + COINGECKO_API_KEY: { + name: 'Coingecko API key', + description: '', + value: '', + provision_type: EnvProvisionType.USER, + }, + GENAI_API_KEY: { + name: 'Gemini API key', + description: '', + value: '', + provision_type: EnvProvisionType.USER, + }, + STAKING_CHAIN: { + name: 'Staking chain', + description: '', + value: 'optimism', + provision_type: EnvProvisionType.FIXED, + }, + ACTIVITY_CHECKER_CONTRACT_ADDRESS: { + name: 'Staking activity checker contract address', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + TARGET_INVESTMENT_CHAINS: { + name: 'Target investment chains', + description: '', + value: '["optimism"]', + provision_type: EnvProvisionType.FIXED, + }, + INITIAL_ASSETS: { + name: 'Initial assets', + description: '', + value: + '{"optimism":{"0x0000000000000000000000000000000000000000":"ETH","0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85":"USDC"}}', + provision_type: EnvProvisionType.FIXED, + }, + INIT_FALLBACK_GAS: { + name: 'Init fallback gas', + description: '', + value: '250000', + provision_type: EnvProvisionType.FIXED, + }, + STORE_PATH: { + name: 'Store path', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + RESET_PAUSE_DURATION: { + name: 'Reset pause duration', + description: '', + value: '300', + provision_type: EnvProvisionType.FIXED, + }, + }, +} as const; + export const SERVICE_TEMPLATES: ServiceTemplate[] = [ PREDICT_SERVICE_TEMPLATE, AGENTS_FUN_BASE_TEMPLATE, MODIUS_SERVICE_TEMPLATE, AGENTS_FUN_CELO_TEMPLATE, + OPTIMUS_SERVICE_TEMPLATE, ] as const; export const getServiceTemplates = (): ServiceTemplate[] => SERVICE_TEMPLATES; diff --git a/frontend/constants/urls.ts b/frontend/constants/urls.ts index c1ce872d8..65b6472ec 100644 --- a/frontend/constants/urls.ts +++ b/frontend/constants/urls.ts @@ -1,4 +1,4 @@ -import { MiddlewareChain } from '@/client'; +import { MiddlewareChain, SupportedMiddlewareChain } from '@/client'; import { EvmChainId } from '@/enums/Chain'; type Url = `http${'s' | ''}://${string}`; @@ -15,6 +15,8 @@ const SWAP_MODE_URL: Url = 'https://balancer.fi/swap/mode/0xd988097fb8612cc24eec14542bc03424c656005f/0xcfd1d50ce23c46d3cf6407487b2f8934e96dc8f9'; const SWAP_CELO_URL: Url = 'https://app.ubeswap.org/#/swap?inputCurrency=0x471ece3750da237f93b8e339c536989b8978a438&outputCurrency=0xacffae8e57ec6e394eb1b41939a8cf7892dbdc51'; +const SWAP_OPTIMISM_URL: Url = + 'https://balancer.fi/pools/optimism/v2/0x5bb3e58887264b667f915130fd04bbb56116c27800020000000000000000012a'; // olas.network export const PEARL_URL: Url = 'https://olas.network/pearl'; @@ -23,7 +25,10 @@ export const TERMS_AND_CONDITIONS_URL: Url = 'https://olas.network/pearl-terms'; export const DOWNLOAD_URL: Url = 'https://olas.network/pearl#update'; // thegraph -export const REWARDS_HISTORY_SUBGRAPH_URLS_BY_EVM_CHAIN = { +export const REWARDS_HISTORY_SUBGRAPH_URLS_BY_EVM_CHAIN: Record< + EvmChainId, + Url +> = { [EvmChainId.Gnosis]: 'https://gateway.thegraph.com/api/5c035877a4af18d178c96afe55ed41ae/subgraphs/id/F3iqL2iw5UTrP1qbb4S694pGEkBwzoxXp1TRikB2K4e', [EvmChainId.Base]: @@ -32,6 +37,8 @@ export const REWARDS_HISTORY_SUBGRAPH_URLS_BY_EVM_CHAIN = { 'https://gateway.thegraph.com/api/5c035877a4af18d178c96afe55ed41ae/subgraphs/id/Fe6oYUKbSGP7a16NowseTU82MVG9D2xWbBUCz4MPB4d4', [EvmChainId.Celo]: 'https://api.studio.thegraph.com/query/67875/olas-celo-staking/version/latest', + [EvmChainId.Optimism]: + 'https://gateway.thegraph.com/api/5c035877a4af18d178c96afe55ed41ae/subgraphs/id/2fe1izA4aVvBHVwbPzP1BqxLkoR9ebygWM9iHXwLCnPE', }; // discord @@ -45,11 +52,11 @@ export const GITHUB_API_LATEST_RELEASE: Url = 'https://api.github.com/repos/valory-xyz/olas-operate-app/releases/latest'; // explorers @note DO NOT END WITH `/` -// export const OPTIMISM_EXPLORER_URL: Url = 'https://optimistic.etherscan.io'; const GNOSIS_EXPLORER_URL: Url = 'https://gnosisscan.io'; const BASE_EXPLORER_URL: Url = 'https://basescan.org'; const MODE_EXPLORER_URL: Url = 'https://modescan.io'; const CELO_EXPLORER_URL: Url = 'https://celoscan.io'; +const OPTIMISM_EXPLORER_URL: Url = 'https://optimistic.etherscan.io'; // others export const TENDERLY_URL: string = 'https://tenderly.co'; @@ -59,28 +66,31 @@ export const COINGECKO_DEMO_API_KEY: string = export const GEMINI_API_URL: string = 'https://aistudio.google.com/app/apikey'; export const EXPLORER_URL_BY_MIDDLEWARE_CHAIN: Record< - string | MiddlewareChain, + SupportedMiddlewareChain, Url > = { [MiddlewareChain.GNOSIS]: GNOSIS_EXPLORER_URL, [MiddlewareChain.BASE]: BASE_EXPLORER_URL, [MiddlewareChain.MODE]: MODE_EXPLORER_URL, [MiddlewareChain.CELO]: CELO_EXPLORER_URL, + [MiddlewareChain.OPTIMISM]: OPTIMISM_EXPLORER_URL, }; export const BLOCKSCOUT_URL_BY_MIDDLEWARE_CHAIN: Record< - string | MiddlewareChain, + SupportedMiddlewareChain, Url > = { [MiddlewareChain.GNOSIS]: 'https://gnosis.blockscout.com', [MiddlewareChain.BASE]: 'https://base.blockscout.com', [MiddlewareChain.MODE]: 'https://explorer.mode.network', [MiddlewareChain.CELO]: 'https://celo.blockscout.com', + [MiddlewareChain.OPTIMISM]: 'https://optimism.blockscout.com', }; -export const SWAP_URL_BY_EVM_CHAIN: Record = { +export const SWAP_URL_BY_EVM_CHAIN: Record = { [EvmChainId.Gnosis]: COW_SWAP_GNOSIS_XDAI_OLAS_URL, [EvmChainId.Base]: SWAP_BASE_URL, [EvmChainId.Mode]: SWAP_MODE_URL, [EvmChainId.Celo]: SWAP_CELO_URL, + [EvmChainId.Optimism]: SWAP_OPTIMISM_URL, }; diff --git a/frontend/context/ElectronApiProvider.tsx b/frontend/context/ElectronApiProvider.tsx index f2cce771b..8f29d7694 100644 --- a/frontend/context/ElectronApiProvider.tsx +++ b/frontend/context/ElectronApiProvider.tsx @@ -1,7 +1,7 @@ import { get } from 'lodash'; import { createContext, PropsWithChildren } from 'react'; -import { AgentHealthCheck } from '@/types/Agent'; +import { AgentHealthCheckResponse } from '@/types/Agent'; import { ElectronStore, ElectronTrayIconStatus } from '@/types/ElectronApi'; type ElectronApiAgentActivityWindow = { @@ -43,7 +43,7 @@ type ElectronApiContextProps = { }) => Promise<{ success: true; dirPath: string } | { success?: false }>; openPath?: (filePath: string) => void; healthCheck?: () => Promise< - { response: AgentHealthCheck | null } | { error: string } + { response: AgentHealthCheckResponse | null } | { error: string } >; agentActivityWindow?: Partial; }; diff --git a/frontend/context/ServicesProvider.tsx b/frontend/context/ServicesProvider.tsx index d8d9d539d..5b4332854 100644 --- a/frontend/context/ServicesProvider.tsx +++ b/frontend/context/ServicesProvider.tsx @@ -23,7 +23,7 @@ import { AgentType } from '@/enums/Agent'; import { AgentEoa, AgentSafe, - AgentWallets, + AgentWallet, WalletOwnerType, WalletType, } from '@/enums/Wallet'; @@ -46,7 +46,7 @@ type ServicesResponse = Pick< type ServicesContextType = { services?: MiddlewareServiceResponse[]; - serviceWallets?: AgentWallets; + serviceWallets?: AgentWallet[]; selectedService?: Service; selectedServiceStatusOverride?: Maybe; isSelectedServiceDeploymentStatusLoading: boolean; @@ -161,16 +161,16 @@ export const ServicesProvider = ({ children }: PropsWithChildren) => { return config; }, [selectedAgentType]); - const serviceWallets: Optional = useMemo(() => { + const serviceWallets: Optional = useMemo(() => { if (isServicesLoading) return; if (isNilOrEmpty(services)) return []; - return services.reduce( + return services.reduce( (acc, service: MiddlewareServiceResponse) => { return [ ...acc, ...Object.keys(service.chain_configs).reduce( - (acc: AgentWallets, middlewareChain: string) => { + (acc: AgentWallet[], middlewareChain: string) => { const chainConfig = service.chain_configs[middlewareChain as MiddlewareChain]; diff --git a/frontend/context/SharedProvider/SharedProvider.tsx b/frontend/context/SharedProvider/SharedProvider.tsx index f612389cb..a96aae824 100644 --- a/frontend/context/SharedProvider/SharedProvider.tsx +++ b/frontend/context/SharedProvider/SharedProvider.tsx @@ -25,7 +25,7 @@ export const SharedContext = createContext<{ updateOnboardingStep: (step: number) => void; // agent specific checks - isMemeooorrFieldUpdateCompleted: boolean; + isMemeooorrFieldUpdateRequired: boolean; // others }>({ @@ -39,7 +39,7 @@ export const SharedContext = createContext<{ updateOnboardingStep: () => {}, // agent specific checks - isMemeooorrFieldUpdateCompleted: false, + isMemeooorrFieldUpdateRequired: false, // others }); @@ -67,14 +67,17 @@ export const SharedProvider = ({ children }: PropsWithChildren) => { // agent specific checks const { selectedAgentType, selectedService } = useServices(); - const [isMemeooorrFieldUpdateCompleted, setIsMemeooorrFieldUpdateCompleted] = - useState(true); // default to true to avoid showing the alert on first load + const [isMemeooorrFieldUpdateRequired, setIsMemeooorrFieldUpdateRequired] = + useState(false); // Users with the Memeooorr agent type are required to update their // agent configurations to run the latest version of the agent. useEffect(() => { if (!selectedAgentType) return; - if (selectedAgentType !== AgentType.Memeooorr) return; + if (selectedAgentType !== AgentType.Memeooorr) { + setIsMemeooorrFieldUpdateRequired(false); + return; + } if (!selectedService) return; const areFieldsUpdated = [ @@ -85,7 +88,7 @@ export const SharedProvider = ({ children }: PropsWithChildren) => { 'TWEEPY_ACCESS_TOKEN_SECRET', ].every((key) => selectedService.env_variables?.[key]?.value); - setIsMemeooorrFieldUpdateCompleted(areFieldsUpdated); + setIsMemeooorrFieldUpdateRequired(!areFieldsUpdated); }, [selectedAgentType, selectedService]); return ( @@ -100,7 +103,7 @@ export const SharedProvider = ({ children }: PropsWithChildren) => { updateOnboardingStep, // agent specific checks - isMemeooorrFieldUpdateCompleted, + isMemeooorrFieldUpdateRequired, }} > {children} diff --git a/frontend/context/StakingContractDetailsProvider.tsx b/frontend/context/StakingContractDetailsProvider.tsx index 95dc4be9c..bbc8236f3 100644 --- a/frontend/context/StakingContractDetailsProvider.tsx +++ b/frontend/context/StakingContractDetailsProvider.tsx @@ -102,7 +102,6 @@ const useStakingContractDetailsByStakingProgram = ({ * Request staking contract details * if service is present, request it's info and states on the staking contract */ - const promises: Promise< StakingContractDetails | ServiceStakingDetails | undefined >[] = [ diff --git a/frontend/enums/Agent.ts b/frontend/enums/Agent.ts index 19d15876a..daf798c2a 100644 --- a/frontend/enums/Agent.ts +++ b/frontend/enums/Agent.ts @@ -3,6 +3,7 @@ export const AgentType = { Memeooorr: 'memeooorr', AgentsFunCelo: 'agents-fun-celo', Modius: 'modius', + Optimus: 'optimus', } as const; export type AgentType = (typeof AgentType)[keyof typeof AgentType]; diff --git a/frontend/enums/Chain.ts b/frontend/enums/Chain.ts index e491d5aa4..e9c29a631 100644 --- a/frontend/enums/Chain.ts +++ b/frontend/enums/Chain.ts @@ -1,22 +1,12 @@ +/** + * @deprecated + * + * use `EvmChainId` from `@/types/Chain.ts` instead + */ export enum EvmChainId { Gnosis = 100, Base = 8453, Mode = 34443, Celo = 42220, -} - -export const EvmChainName = { - [EvmChainId.Gnosis]: 'Gnosis', - [EvmChainId.Base]: 'Base', - [EvmChainId.Mode]: 'Mode', - [EvmChainId.Celo]: 'Celo', -}; - -export enum AllEvmChainId { - Gnosis = EvmChainId.Gnosis, - Base = EvmChainId.Base, - Mode = EvmChainId.Mode, - Celo = EvmChainId.Celo, - Ethereum = 1, Optimism = 10, } diff --git a/frontend/enums/StakingProgram.ts b/frontend/enums/StakingProgram.ts index db2f6cc29..f291f87d8 100644 --- a/frontend/enums/StakingProgram.ts +++ b/frontend/enums/StakingProgram.ts @@ -1,23 +1,59 @@ -export enum StakingProgramId { - PearlAlpha = 'pearl_alpha', - PearlBeta = 'pearl_beta', - PearlBeta2 = 'pearl_beta_2', - PearlBeta3 = 'pearl_beta_3', - PearlBeta4 = 'pearl_beta_4', - PearlBeta5 = 'pearl_beta_5', - PearlBeta6 = 'pearl_beta_6', - PearlBetaMechMarketplace = 'pearl_beta_mech_marketplace', - OptimusAlpha = 'optimus_alpha', - MemeBaseAlpha2 = 'meme_base_alpha_2', - MemeBaseBeta = 'meme_base_beta', - MemeBaseBeta2 = 'meme_base_beta_2', - MemeBaseBeta3 = 'meme_base_beta_3', - MemeCeloAlpha2 = 'meme_celo_alpha_2', - AgentsFun1 = 'agents_fun_1', - AgentsFun2 = 'agents_fun_2', - AgentsFun3 = 'agents_fun_3', - ModiusAlpha = 'modius_alpha', - ModiusAlpha2 = 'modius_alpha_2', - ModiusAlpha3 = 'modius_alpha_3', - ModiusAlpha4 = 'modius_alpha_4', -} +import { ValueOf } from '@/types/Util'; + +const GNOSIS_STAKING_PROGRAM_IDS = { + PearlAlpha: 'pearl_alpha', + PearlBeta: 'pearl_beta', + PearlBeta2: 'pearl_beta_2', + PearlBeta3: 'pearl_beta_3', + PearlBeta4: 'pearl_beta_4', + PearlBeta5: 'pearl_beta_5', + PearlBeta6: 'pearl_beta_6', + PearlBetaMechMarketplace: 'pearl_beta_mech_marketplace', +} as const; + +const BASE_STAKING_PROGRAM_IDS = { + MemeBaseAlpha2: 'meme_base_alpha_2', + MemeBaseBeta: 'meme_base_beta', + MemeBaseBeta2: 'meme_base_beta_2', + MemeBaseBeta3: 'meme_base_beta_3', + MemeCeloAlpha2: 'meme_celo_alpha_2', + AgentsFun1: 'agents_fun_1', + AgentsFun2: 'agents_fun_2', + AgentsFun3: 'agents_fun_3', +} as const; + +const MODE_STAKING_PROGRAM_IDS = { + ModiusAlpha: 'modius_alpha', + ModiusAlpha2: 'modius_alpha_2', + ModiusAlpha3: 'modius_alpha_3', + ModiusAlpha4: 'modius_alpha_4', + OptimusAlpha: 'optimus_alpha', +} as const; + +export type ModeStakingProgramId = ValueOf; + +/** + * @note: OptimusAlpha1 is deprecated and not used in the codebase. + */ +export const OPTIMISM_STAKING_PROGRAM_IDS = { + OptimusAlpha2: 'optimus_alpha_2', + OptimusAlpha3: 'optimus_alpha_3', + OptimusAlpha4: 'optimus_alpha_4', +} as const; + +export type OptimismStakingProgramId = ValueOf< + typeof OPTIMISM_STAKING_PROGRAM_IDS +>; + +/** + * @link https://github.com/valory-xyz/olas-operate-middleware/blob/9ca362f302ae749dd99b236d062ccc5c722acabf/operate/ledger/profiles.py#L115 + * Refer the above link for the list of staking program ids. + */ +export const STAKING_PROGRAM_IDS = { + ...GNOSIS_STAKING_PROGRAM_IDS, + ...BASE_STAKING_PROGRAM_IDS, + ...MODE_STAKING_PROGRAM_IDS, + ...OPTIMISM_STAKING_PROGRAM_IDS, +} as const; + +export type StakingProgramId = ValueOf; diff --git a/frontend/enums/Wallet.ts b/frontend/enums/Wallet.ts index 056e7ff4b..bedd7fcec 100644 --- a/frontend/enums/Wallet.ts +++ b/frontend/enums/Wallet.ts @@ -37,6 +37,3 @@ export type AgentSafe = Safe & { owner: WalletOwnerType.Agent }; export type MasterWallet = MasterEoa | MasterSafe; export type AgentWallet = AgentEoa | AgentSafe; export type Wallet = MasterWallet | AgentWallet; - -/** @deprecated use AgentWallet[] instead */ -export type AgentWallets = AgentWallet[]; diff --git a/frontend/hooks/useFeatureFlag.ts b/frontend/hooks/useFeatureFlag.ts index c18b79055..fbe08549a 100644 --- a/frontend/hooks/useFeatureFlag.ts +++ b/frontend/hooks/useFeatureFlag.ts @@ -11,7 +11,6 @@ const FeatureFlagsSchema = z.enum([ 'last-transactions', 'rewards-streak', 'staking-contract-section', - 'low-funds', 'agent-activity', 'backup-via-safe', 'agent-settings', @@ -37,7 +36,6 @@ const FEATURES_CONFIG = FeaturesConfigSchema.parse({ 'last-transactions': true, 'rewards-streak': true, 'staking-contract-section': true, - 'low-funds': true, 'agent-activity': true, 'backup-via-safe': true, 'agent-settings': false, @@ -50,7 +48,6 @@ const FEATURES_CONFIG = FeaturesConfigSchema.parse({ 'last-transactions': true, 'rewards-streak': true, 'staking-contract-section': true, - 'low-funds': false, 'agent-activity': true, 'backup-via-safe': true, 'agent-settings': true, @@ -63,7 +60,6 @@ const FEATURES_CONFIG = FeaturesConfigSchema.parse({ 'last-transactions': false, 'rewards-streak': false, 'staking-contract-section': false, - 'low-funds': false, 'agent-activity': true, 'backup-via-safe': true, 'agent-settings': false, @@ -76,13 +72,24 @@ const FEATURES_CONFIG = FeaturesConfigSchema.parse({ 'last-transactions': true, 'rewards-streak': true, 'staking-contract-section': true, - 'low-funds': false, 'agent-activity': true, 'backup-via-safe': false, // temporarily hidden until mode is available on safe https://app.safe.global/new-safe/create 'agent-settings': true, 'bridge-onboarding': true, 'bridge-add-funds': false, }, + [AgentType.Optimus]: { + 'manage-wallet': true, + 'withdraw-funds': false, + 'last-transactions': true, + 'rewards-streak': true, + 'staking-contract-section': true, + 'agent-activity': true, + 'backup-via-safe': true, + 'agent-settings': true, + 'bridge-onboarding': true, + 'bridge-add-funds': false, + }, }); type FeatureFlagReturn = diff --git a/frontend/hooks/useService.ts b/frontend/hooks/useService.ts index df6467376..4e1bd5c7e 100644 --- a/frontend/hooks/useService.ts +++ b/frontend/hooks/useService.ts @@ -10,7 +10,7 @@ import { EvmChainId } from '@/enums/Chain'; import { AgentEoa, AgentSafe, - AgentWallets, + AgentWallet, WalletOwnerType, WalletType, } from '@/enums/Wallet'; @@ -53,7 +53,7 @@ export const useService = (serviceConfigId?: string) => { return service?.chain_configs?.[service?.home_chain]?.chain_data.token; }, [service?.chain_configs, service?.home_chain]); - const serviceWallets: AgentWallets = useMemo(() => { + const serviceWallets: AgentWallet[] = useMemo(() => { if (!service) return []; if (!selectedService?.home_chain) return []; if (!service.chain_configs?.[selectedService?.home_chain]) return []; diff --git a/frontend/package.json b/frontend/package.json index fefa0dc0b..ef1ef2315 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -56,7 +56,8 @@ "build": "bash -c \"GNOSIS_RPC=$GNOSIS_RPC BASE_RPC=$BASE_RPC OPTIMISM_RPC=$OPTIMISM_RPC ETHEREUM_RPC=$ETHEREUM_RPC MODE_RPC=$MODE_RPC CELO_RPC=$CELO_RPC NODE_ENV=production next build\"", "lint": "next lint", "test": "jest", - "start": "next start" + "start": "next start", + "check": "yarn run lint && tsc --noEmit --incremental false" }, "version": "0.1.0" -} \ No newline at end of file +} diff --git a/frontend/public/agent-optimus-icon.png b/frontend/public/agent-optimus-icon.png new file mode 100644 index 000000000..1e8d75766 Binary files /dev/null and b/frontend/public/agent-optimus-icon.png differ diff --git a/frontend/public/chains/optimism-chain.png b/frontend/public/chains/optimism-chain.png new file mode 100644 index 000000000..f7ef4d672 Binary files /dev/null and b/frontend/public/chains/optimism-chain.png differ diff --git a/frontend/public/setup-agent-optimus-1.png b/frontend/public/setup-agent-optimus-1.png new file mode 100644 index 000000000..5b505dfd3 Binary files /dev/null and b/frontend/public/setup-agent-optimus-1.png differ diff --git a/frontend/public/setup-agent-optimus-2.png b/frontend/public/setup-agent-optimus-2.png new file mode 100644 index 000000000..63a63e07b Binary files /dev/null and b/frontend/public/setup-agent-optimus-2.png differ diff --git a/frontend/public/setup-agent-optimus-3.png b/frontend/public/setup-agent-optimus-3.png new file mode 100644 index 000000000..274c0acdc Binary files /dev/null and b/frontend/public/setup-agent-optimus-3.png differ diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index e8d0c7d3d..d08846bb9 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -3,6 +3,7 @@ import { MiddlewareServiceResponse, ServiceConfigId, ServiceTemplate, + SupportedMiddlewareChain, } from '@/client'; import { CHAIN_CONFIG } from '@/config/chains'; import { CONTENT_TYPE_JSON_UTF8 } from '@/constants/headers'; @@ -75,7 +76,7 @@ const createService = async ({ // overwrite defaults with chain-specific configurations ...Object.entries(serviceTemplate.configurations).reduce( (acc, [middlewareChain, config]) => { - acc[middlewareChain] = { + acc[middlewareChain as SupportedMiddlewareChain] = { ...config, rpc: CHAIN_CONFIG[asEvmChainId(middlewareChain)].rpc, staking_program_id: stakingProgramId, diff --git a/frontend/service/agents/Modius.ts b/frontend/service/agents/Modius.ts index bbe2df543..04e98c790 100644 --- a/frontend/service/agents/Modius.ts +++ b/frontend/service/agents/Modius.ts @@ -5,7 +5,7 @@ import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; import { MODE_STAKING_PROGRAMS } from '@/config/stakingPrograms/mode'; import { PROVIDERS } from '@/constants/providers'; import { EvmChainId } from '@/enums/Chain'; -import { StakingProgramId } from '@/enums/StakingProgram'; +import { ModeStakingProgramId, StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; import { ServiceStakingDetails, @@ -68,22 +68,6 @@ export abstract class ModiusService extends StakedAgentService { currentMultisigNonces, ] = multicallResponse; - /** - * struct ServiceInfo { - // Service multisig address - address multisig; - // Service owner - address owner; - // Service multisig nonces - uint256[] nonces; <-- (we use this in the rewards eligibility check) - // Staking start time - uint256 tsStart; - // Accumulated service staking reward - uint256 reward; - // Accumulated inactivity that might lead to the service eviction - uint256 inactivity;} - */ - const lastMultisigNonces = serviceInfo[2]; const nowInSeconds = Math.floor(Date.now() / 1000); @@ -190,7 +174,9 @@ export abstract class ModiusService extends StakedAgentService { ): Promise => { const { multicallProvider } = PROVIDERS[chainId]; - const stakingTokenProxy = MODE_STAKING_PROGRAMS[stakingProgramId]?.contract; + const modeStakingProgram = + MODE_STAKING_PROGRAMS[stakingProgramId as ModeStakingProgramId]; + const stakingTokenProxy = modeStakingProgram?.contract; if (!stakingTokenProxy) return; const contractCalls = [ diff --git a/frontend/service/agents/Optimism.ts b/frontend/service/agents/Optimism.ts new file mode 100644 index 000000000..d6e1eaa48 --- /dev/null +++ b/frontend/service/agents/Optimism.ts @@ -0,0 +1,249 @@ +import { ethers } from 'ethers'; +import { formatEther } from 'ethers/lib/utils'; + +import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; +import { OPTIMISM_STAKING_PROGRAMS } from '@/config/stakingPrograms/optimism'; +import { PROVIDERS } from '@/constants/providers'; +import { EvmChainId } from '@/enums/Chain'; +import { + OptimismStakingProgramId, + StakingProgramId, +} from '@/enums/StakingProgram'; +import { Address } from '@/types/Address'; +import { + ServiceStakingDetails, + StakingContractDetails, + StakingRewardsInfo, +} from '@/types/Autonolas'; +import { isValidServiceId } from '@/utils/service'; + +import { + ONE_YEAR, + StakedAgentService, +} from './shared-services/StakedAgentService'; + +const REQUESTS_SAFETY_MARGIN = 1; + +const getNowInSeconds = () => Math.floor(Date.now() / 1000); + +export abstract class OptimismService extends StakedAgentService { + static getAgentStakingRewardsInfo = async ({ + agentMultisigAddress, + serviceId, + stakingProgramId, + chainId = EvmChainId.Optimism, + }: { + agentMultisigAddress: Address; + serviceId: number; + stakingProgramId: StakingProgramId; // TODO: should infer type OptimismStakingProgramId + chainId?: EvmChainId; + }): Promise => { + if (!agentMultisigAddress) return; + if (!isValidServiceId(serviceId)) return; + + const stakingProgramConfig = STAKING_PROGRAMS[chainId][stakingProgramId]; + if (!stakingProgramConfig) throw new Error('Staking program not found'); + + const { activityChecker, contract: stakingTokenProxyContract } = + stakingProgramConfig; + + const provider = PROVIDERS[chainId].multicallProvider; + const contractCalls = [ + stakingTokenProxyContract.getServiceInfo(serviceId), + stakingTokenProxyContract.livenessPeriod(), + stakingTokenProxyContract.rewardsPerSecond(), + stakingTokenProxyContract.calculateStakingReward(serviceId), + stakingTokenProxyContract.minStakingDeposit(), + stakingTokenProxyContract.tsCheckpoint(), + activityChecker.livenessRatio(), + activityChecker.getMultisigNonces(agentMultisigAddress), + ]; + const multicallResponse = await provider.all(contractCalls); + + const [ + serviceInfo, + livenessPeriod, + rewardsPerSecond, + accruedStakingReward, + minStakingDeposit, + tsCheckpoint, + livenessRatio, + currentMultisigNonces, + ] = multicallResponse; + + const lastMultisigNonces = serviceInfo[2]; + const isServiceStaked = lastMultisigNonces.length > 0; + + // Calculate the number of requests required to be eligible for rewards + const secondsSinceCheckpoint = getNowInSeconds() - tsCheckpoint; + const effectivePeriod = Math.max(livenessPeriod, secondsSinceCheckpoint); + const requiredRequests = + (Math.ceil(effectivePeriod) * livenessRatio) / 1e18 + + REQUESTS_SAFETY_MARGIN; + + // Determine how many requests the service has handled since last checkpoint + const eligibleRequests = isServiceStaked + ? currentMultisigNonces[0] - lastMultisigNonces[0] + : 0; + + // Check eligibility for rewards + const isEligibleForRewards = eligibleRequests >= requiredRequests; + + // Available rewards for the current epoch + const expectedEpochRewards = rewardsPerSecond * livenessPeriod; + const lateCheckpointRewards = rewardsPerSecond * secondsSinceCheckpoint; + const availableRewardsForEpoch = Math.max( + expectedEpochRewards, + lateCheckpointRewards, + ); + + // Minimum amount that must be staked (double the minimum deposit) + const minimumStakedAmount = + parseFloat(ethers.utils.formatEther(`${minStakingDeposit}`)) * 2; + + return { + serviceInfo, + livenessPeriod, + livenessRatio, + rewardsPerSecond, + isEligibleForRewards, + availableRewardsForEpoch, + accruedServiceStakingRewards: parseFloat( + ethers.utils.formatEther(`${accruedStakingReward}`), + ), + minimumStakedAmount, + } satisfies StakingRewardsInfo; + }; + + static getAvailableRewardsForEpoch = async ( + stakingProgramId: StakingProgramId, + chainId: EvmChainId = EvmChainId.Optimism, + ): Promise => { + const stakingTokenProxy = + STAKING_PROGRAMS[chainId][stakingProgramId]?.contract; + if (!stakingTokenProxy) return; + + const { multicallProvider } = PROVIDERS[chainId]; + const contractCalls = [ + stakingTokenProxy.rewardsPerSecond(), + stakingTokenProxy.livenessPeriod(), // epoch length + stakingTokenProxy.tsCheckpoint(), // last checkpoint timestamp + ]; + const multicallResponse = await multicallProvider.all(contractCalls); + + const [rewardsPerSecond, livenessPeriod, tsCheckpoint] = multicallResponse; + const expectedRewards = rewardsPerSecond * livenessPeriod; + const lateCheckpointRewards = + rewardsPerSecond * (getNowInSeconds() - tsCheckpoint); + + return BigInt(Math.max(expectedRewards, lateCheckpointRewards)); + }; + + /** + * Get service details by it's NftTokenId on a provided staking contract + */ + static getServiceStakingDetails = async ( + serviceNftTokenId: number, + stakingProgramId: StakingProgramId, + chainId: EvmChainId = EvmChainId.Optimism, + ): Promise => { + const { multicallProvider } = PROVIDERS[chainId]; + + const { contract: stakingTokenProxy } = + STAKING_PROGRAMS[chainId][stakingProgramId]; + + const contractCalls = [ + stakingTokenProxy.getServiceInfo(serviceNftTokenId), + stakingTokenProxy.getStakingState(serviceNftTokenId), + ]; + const multicallResponse = await multicallProvider.all(contractCalls); + const [serviceInfo, serviceStakingState] = multicallResponse; + + return { + serviceStakingStartTime: serviceInfo.tsStart.toNumber(), + serviceStakingState, + }; + }; + + /** + * Get staking contract info by staking program name + * eg. Alpha, Beta, Beta2 + */ + static getStakingContractDetails = async ( + stakingProgramId: StakingProgramId, + chainId: EvmChainId, + ): Promise => { + const { multicallProvider } = PROVIDERS[chainId]; + + const stakingTokenProxy = + OPTIMISM_STAKING_PROGRAMS[stakingProgramId as OptimismStakingProgramId] + ?.contract; + if (!stakingTokenProxy) return; + + const contractCalls = [ + stakingTokenProxy.availableRewards(), + stakingTokenProxy.maxNumServices(), + stakingTokenProxy.getServiceIds(), + stakingTokenProxy.minStakingDuration(), + stakingTokenProxy.minStakingDeposit(), + stakingTokenProxy.rewardsPerSecond(), + stakingTokenProxy.numAgentInstances(), + stakingTokenProxy.livenessPeriod(), + stakingTokenProxy.epochCounter(), + ]; + const multicallResponse = await multicallProvider.all(contractCalls); + + const [ + availableRewardsInBN, + maxNumServicesInBN, + getServiceIdsInBN, + minStakingDurationInBN, + minStakingDeposit, + rewardsPerSecond, + numAgentInstances, + livenessPeriod, + epochCounter, + ] = multicallResponse; + + const availableRewards = parseFloat( + ethers.utils.formatUnits(availableRewardsInBN, 18), + ); + const serviceIds: number[] = getServiceIdsInBN.map((id: bigint) => + Number(id), + ); + const maxNumServices: number = maxNumServicesInBN.toNumber(); + + // Calculate annual rewards (used for APY) + const rewardsPerYear = rewardsPerSecond.mul(ONE_YEAR); + + // APY + let apy = 0; + if (rewardsPerSecond.gt(0) && minStakingDeposit.gt(0)) { + const annualPercentage = rewardsPerYear.mul(100).div(minStakingDeposit); + apy = Number(annualPercentage) / (1 + numAgentInstances.toNumber()); + } + + // Required OLAS stake (min deposit per agent instance) + const stakeRequiredInWei = minStakingDeposit.add( + minStakingDeposit.mul(numAgentInstances), + ); + const olasStakeRequired = Number(formatEther(stakeRequiredInWei)); + + // Rewards earned per work period + const rewardsPerWorkPeriod = + Number(formatEther(rewardsPerSecond as bigint)) * + livenessPeriod.toNumber(); + + return { + availableRewards, + maxNumServices, + serviceIds, + minimumStakingDuration: minStakingDurationInBN.toNumber(), + minStakingDeposit: parseFloat(formatEther(minStakingDeposit)), + apy, + olasStakeRequired, + rewardsPerWorkPeriod, + epochCounter: epochCounter.toNumber(), + }; + }; +} diff --git a/frontend/types/Agent.ts b/frontend/types/Agent.ts index 7be69419f..986c8fb6b 100644 --- a/frontend/types/Agent.ts +++ b/frontend/types/Agent.ts @@ -1,20 +1,28 @@ -import { MiddlewareChain } from '@/client'; +import { SupportedMiddlewareChain } from '@/client'; import { EvmChainId } from '@/enums/Chain'; import { TokenSymbol } from '@/enums/Token'; +import { AgentsFunBaseService } from '@/service/agents/AgentsFunBase'; +import { ModiusService } from '@/service/agents/Modius'; +import { OptimismService } from '@/service/agents/Optimism'; import { PredictTraderService } from '@/service/agents/PredictTrader'; export type AgentConfig = { name: string; evmHomeChainId: EvmChainId; - middlewareHomeChainId: MiddlewareChain; + middlewareHomeChainId: SupportedMiddlewareChain; requiresAgentSafesOn: EvmChainId[]; requiresMasterSafesOn: EvmChainId[]; additionalRequirements?: Partial< Record>> >; - serviceApi: typeof PredictTraderService; + serviceApi: + | typeof PredictTraderService + | typeof ModiusService + | typeof OptimismService + | typeof AgentsFunBaseService; displayName: string; description: string; + /** Whether the agent is enabled and can be shown in the UI */ isAgentEnabled: boolean; /** If agent is enabled but not yet available to use */ isComingSoon?: boolean; @@ -25,7 +33,7 @@ export type AgentConfig = { requiresSetup: boolean; }; -export type AgentHealthCheck = { +export type AgentHealthCheckResponse = { seconds_since_last_transition: number; is_tm_healthy: boolean; period: number; diff --git a/frontend/types/Autonolas.ts b/frontend/types/Autonolas.ts index 31e89a449..5fd2a7414 100644 --- a/frontend/types/Autonolas.ts +++ b/frontend/types/Autonolas.ts @@ -8,8 +8,10 @@ const zodBigNumber = z.object({ export const StakingRewardsInfoSchema = z.object({ // mechRequestCount: z.number(), serviceInfo: z.array(z.unknown()), + /* checkpoint period (in seconds). eg. 86400 */ livenessPeriod: zodBigNumber, livenessRatio: zodBigNumber, + /* rewards per second */ rewardsPerSecond: zodBigNumber, isEligibleForRewards: z.boolean(), availableRewardsForEpoch: z.number(), diff --git a/frontend/types/Bridge.ts b/frontend/types/Bridge.ts index de57c7d4f..d11c6b324 100644 --- a/frontend/types/Bridge.ts +++ b/frontend/types/Bridge.ts @@ -82,7 +82,7 @@ export type TokenTransfer = { }; export type CrossChainTransferDetails = { - fromChain: string; - toChain: string; + fromChain: MiddlewareChain; + toChain: MiddlewareChain; transfers: TokenTransfer[]; }; diff --git a/frontend/types/ElectronApi.ts b/frontend/types/ElectronApi.ts index f32a591b9..2de1e5d7b 100644 --- a/frontend/types/ElectronApi.ts +++ b/frontend/types/ElectronApi.ts @@ -17,10 +17,13 @@ export type ElectronStore = { // Each agent has its own settings [AgentType.PredictTrader]?: AgentSettings; [AgentType.Memeooorr]?: AgentSettings; + [AgentType.AgentsFunCelo]?: AgentSettings; [AgentType.Modius]?: AgentSettings & { isProfileWarningDisplayed: boolean; }; - [AgentType.AgentsFunCelo]?: AgentSettings; + [AgentType.Optimus]?: AgentSettings & { + isProfileWarningDisplayed: boolean; + }; }; export type ElectronTrayIconStatus = diff --git a/frontend/types/Util.ts b/frontend/types/Util.ts index 31ca4bbf5..0528a979d 100644 --- a/frontend/types/Util.ts +++ b/frontend/types/Util.ts @@ -4,6 +4,8 @@ export type Optional = T | undefined; export type Maybe = Nullable>; +export type ValueOf = T[keyof T]; + /** * DeepPartial allows you to make all properties of an object optional. */ diff --git a/frontend/utils/middlewareHelpers.ts b/frontend/utils/middlewareHelpers.ts index 726bfdf77..178da8c88 100644 --- a/frontend/utils/middlewareHelpers.ts +++ b/frontend/utils/middlewareHelpers.ts @@ -17,12 +17,37 @@ export const asEvmChainId = (chain?: MiddlewareChain | string): EvmChainId => { return EvmChainId.Base; case MiddlewareChain.MODE: return EvmChainId.Mode; + case MiddlewareChain.OPTIMISM: + return EvmChainId.Optimism; case MiddlewareChain.CELO: return EvmChainId.Celo; } throw new Error(`Invalid middleware chain enum: ${chain}`); }; +export const asEvmChainDetails = ( + chain?: MiddlewareChain | string, +): { + name: string; + displayName: string; +} => { + switch (chain) { + case MiddlewareChain.ETHEREUM: + return { name: 'ethereum', displayName: 'Ethereum' }; + case MiddlewareChain.GNOSIS: + return { name: 'gnosis', displayName: 'Gnosis' }; + case MiddlewareChain.BASE: + return { name: 'base', displayName: 'Base' }; + case MiddlewareChain.CELO: + return { name: 'celo', displayName: 'Celo' }; + case MiddlewareChain.MODE: + return { name: 'mode', displayName: 'Mode' }; + case MiddlewareChain.OPTIMISM: + return { name: 'optimism', displayName: 'Optimism' }; + } + throw new Error(`Invalid middleware chain enum: ${chain}`); +}; + /** * Converts chain ids to middleware chain enums * @example asMiddlewareChain(1) => 'ethereum' @@ -35,6 +60,8 @@ export const asMiddlewareChain = (chainId?: EvmChainId | number) => { return MiddlewareChain.BASE; case EvmChainId.Mode: return MiddlewareChain.MODE; + case EvmChainId.Optimism: + return MiddlewareChain.OPTIMISM; case EvmChainId.Celo: return MiddlewareChain.CELO; } diff --git a/frontend/utils/service.ts b/frontend/utils/service.ts index d4ceec592..94e9f6fa0 100644 --- a/frontend/utils/service.ts +++ b/frontend/utils/service.ts @@ -79,22 +79,20 @@ export const updateServiceIfNeeded = async ( service.chain_configs[serviceHomeChain].chain_data.user_params .fund_requirements; const templateFundRequirements = - serviceTemplate.configurations[serviceHomeChain].fund_requirements; + serviceTemplate.configurations[serviceHomeChain]?.fund_requirements; if ( Object.entries(serviceHomeChainFundRequirements).some(([key, item]) => { return ( - templateFundRequirements[key as Address].agent !== item.agent || - templateFundRequirements[key as Address].safe !== item.safe + templateFundRequirements?.[key as Address]?.agent !== item.agent || + templateFundRequirements?.[key as Address]?.safe !== item.safe ); }) ) { // Need to pass all fund requirements from the template // even if some of them were updated partialServiceTemplate.configurations = { - [serviceHomeChain]: { - fund_requirements: templateFundRequirements, - }, + [serviceHomeChain]: { fund_requirements: templateFundRequirements }, }; } diff --git a/frontend/utils/setupMulticall.ts b/frontend/utils/setupMulticall.ts index fdbeb8b74..aa7668328 100644 --- a/frontend/utils/setupMulticall.ts +++ b/frontend/utils/setupMulticall.ts @@ -14,6 +14,7 @@ const addresses: AddressesForAllChainIds = { [EvmChainId.Gnosis]: DEFAULT_MULTICALL_ADDRESS, [EvmChainId.Mode]: DEFAULT_MULTICALL_ADDRESS, [EvmChainId.Celo]: DEFAULT_MULTICALL_ADDRESS, + [EvmChainId.Optimism]: DEFAULT_MULTICALL_ADDRESS, }; /** diff --git a/package.json b/package.json index 6b550c6cf..484bd548c 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "start:frontend": "cd frontend && yarn start", "test:frontend": "cd frontend && yarn test" }, - "version": "0.2.0-rc176", + "version": "0.2.0-rc267", "engine": { "node": ">=20", "yarn": ">=1.22.0", diff --git a/poetry.lock b/poetry.lock index bfd51dce0..0190f0f37 100644 --- a/poetry.lock +++ b/poetry.lock @@ -829,74 +829,78 @@ requests = "*" [[package]] name = "coverage" -version = "7.8.1" +version = "7.8.2" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" files = [ - {file = "coverage-7.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7af3990490982fbd2437156c69edbe82b7edf99bc60302cceeeaf79afb886b8"}, - {file = "coverage-7.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c5757a7b25fe48040fa120ba6597f5f885b01e323e0d13fe21ff95a70c0f76b7"}, - {file = "coverage-7.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8f105631835fdf191c971c4da93d27e732e028d73ecaa1a88f458d497d026cf"}, - {file = "coverage-7.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21645788c5c2afa3df2d4b607638d86207b84cb495503b71e80e16b4c6b44e80"}, - {file = "coverage-7.8.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e93f36a5c9d995f40e9c4cd9bbabd83fd78705792fa250980256c93accd07bb6"}, - {file = "coverage-7.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d591f2ddad432b794f77dc1e94334a80015a3fc7fa07fd6aed8f40362083be5b"}, - {file = "coverage-7.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:be2b1a455b3ecfee20638289bb091a95216887d44924a41c28a601efac0916e8"}, - {file = "coverage-7.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:061a3bf679dc38fe34d3822f10a9977d548de86b440010beb1e3b44ba93d20f7"}, - {file = "coverage-7.8.1-cp310-cp310-win32.whl", hash = "sha256:12950b6373dc9dfe1ce22a8506ec29c82bfc5b38146ced0a222f38cf5d99a56d"}, - {file = "coverage-7.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:11e5ea0acd8cc5d23030c34dfb2eb6638ad886328df18cc69f8eefab73d1ece5"}, - {file = "coverage-7.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc6bebc15c3b275174c66cf4e1c949a94c5c2a3edaa2f193a1225548c52c771"}, - {file = "coverage-7.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a6c35afd5b912101fabf42975d92d750cfce33c571508a82ff334a133c40d5"}, - {file = "coverage-7.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b37729ba34c116a3b2b6fb99df5c37a4ca40e96f430070488fd7a1077ad44907"}, - {file = "coverage-7.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6424c716f4c38ff8f62b602e6b94cde478dadda542a1cb3fe2fe2520cc2aae3"}, - {file = "coverage-7.8.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bcfafb2809cd01be8ffe5f962e01b0fbe4cc1d74513434c52ff2dd05b86d492"}, - {file = "coverage-7.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e3f65da9701648d226b6b24ded3e2528b72075e48d7540968cd857c3bd4c5321"}, - {file = "coverage-7.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:173e16969f990688aae4b4487717c44330bc57fd8b61a6216ce8eeb827eb5c0d"}, - {file = "coverage-7.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3763b9a4bc128f72da5dcfd7fcc7c7d6644ed28e8f2db473ce1ef0dd37a43fa9"}, - {file = "coverage-7.8.1-cp311-cp311-win32.whl", hash = "sha256:d074380f587360d2500f3b065232c67ae248aaf739267807adbcd29b88bdf864"}, - {file = "coverage-7.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:cd21de85aa0e247b79c6c41f8b5541b54285550f2da6a9448d82b53234d3611b"}, - {file = "coverage-7.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d8f844e837374a9497e11722d9eb9dfeb33b1b5d31136786c39a4c1a3073c6d"}, - {file = "coverage-7.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9cd54a762667c32112df5d6f059c5d61fa532ee06460948cc5bcbf60c502f5c9"}, - {file = "coverage-7.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:958b513e23286178b513a6b4d975fe9e7cddbcea6e5ebe8d836e4ef067577154"}, - {file = "coverage-7.8.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b31756ea647b6ef53190f6b708ad0c4c2ea879bc17799ba5b0699eee59ecf7b"}, - {file = "coverage-7.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccad4e29ac1b6f75bfeedb2cac4860fe5bd9e0a2f04c3e3218f661fa389ab101"}, - {file = "coverage-7.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:452f3831c64f5f50260e18a89e613594590d6ceac5206a9b7d76ba43586b01b3"}, - {file = "coverage-7.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9296df6a33b8539cd753765eb5b47308602263a14b124a099cbcf5f770d7cf90"}, - {file = "coverage-7.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d52d79dfd3b410b153b6d65b0e3afe834eca2b969377f55ad73c67156d35af0d"}, - {file = "coverage-7.8.1-cp312-cp312-win32.whl", hash = "sha256:ebdf212e1ed85af63fa1a76d556c0a3c7b34348ffba6e145a64b15f003ad0a2b"}, - {file = "coverage-7.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:c04a7903644ccea8fa07c3e76db43ca31c8d453f93c5c94c0f9b82efca225543"}, - {file = "coverage-7.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd5c305faa2e69334a53061b3168987847dadc2449bab95735242a9bde92fde8"}, - {file = "coverage-7.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:af6b8cdf0857fd4e6460dd6639c37c3f82163127f6112c1942b5e6a52a477676"}, - {file = "coverage-7.8.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e233a56bbf99e4cb134c4f8e63b16c77714e3987daf2c5aa10c3ba8c4232d730"}, - {file = "coverage-7.8.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dabc70012fd7b58a8040a7bc1b5f71fd0e62e2138aefdd8367d3d24bf82c349"}, - {file = "coverage-7.8.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1f8e96455907496b3e4ea16f63bb578da31e17d2805278b193525e7714f17f2"}, - {file = "coverage-7.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0034ceec8e91fdaf77350901cc48f47efd00f23c220a3f9fc1187774ddf307cb"}, - {file = "coverage-7.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82db9344a07dd9106796b9fe8805425633146a7ea7fed5ed07c65a64d0bb79e1"}, - {file = "coverage-7.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9772c9e266b2ca4999180c12b90c8efb4c5c9ad3e55f301d78bc579af6467ad9"}, - {file = "coverage-7.8.1-cp313-cp313-win32.whl", hash = "sha256:6f24a1e2c373a77afae21bc512466a91e31251685c271c5309ee3e557f6e3e03"}, - {file = "coverage-7.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:76a4e1d62505a21971968be61ae17cbdc5e0c483265a37f7ddbbc050f9c0b8ec"}, - {file = "coverage-7.8.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:35dd5d405a1d378c39f3f30f628a25b0b99f1b8e5bdd78275df2e7b0404892d7"}, - {file = "coverage-7.8.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:87b86a87f8de2e1bd0bcd45faf1b1edf54f988c8857157300e0336efcfb8ede6"}, - {file = "coverage-7.8.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce4553a573edb363d5db12be1c044826878bec039159d6d4eafe826ef773396d"}, - {file = "coverage-7.8.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db181a1896e0bad75b3bf4916c49fd3cf6751f9cc203fe0e0ecbee1fc43590fa"}, - {file = "coverage-7.8.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ce2606a171f9cf7c15a77ca61f979ffc0e0d92cd2fb18767cead58c1d19f58e"}, - {file = "coverage-7.8.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4fc4f7cff2495d6d112353c33a439230a6de0b7cd0c2578f1e8d75326f63d783"}, - {file = "coverage-7.8.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ff619c58322d9d6df0a859dc76c3532d7bdbc125cb040f7cd642141446b4f654"}, - {file = "coverage-7.8.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c0d6290a466a6f3fadf6add2dd4ec11deba4e1a6e3db2dd284edd497aadf802f"}, - {file = "coverage-7.8.1-cp313-cp313t-win32.whl", hash = "sha256:e4e893c7f7fb12271a667d5c1876710fae06d7580343afdb5f3fc4488b73209e"}, - {file = "coverage-7.8.1-cp313-cp313t-win_amd64.whl", hash = "sha256:41d142eefbc0bb3be160a77b2c0fbec76f345387676265052e224eb6c67b7af3"}, - {file = "coverage-7.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d5102e17b81158de17d4b5bc363fcffd15231a38ef3f50b8e6fa01f0c6911194"}, - {file = "coverage-7.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3bd8e3753257e95e94f38c058627aba1581d51f674e3badf226283b2bdb8f8ca"}, - {file = "coverage-7.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d616b5a543c7d4deffa25eb8d8ae3d0d95097f08ac8b131600bb7fbf967ea0e2"}, - {file = "coverage-7.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7a95b0dce364535a63fde0ec1b1ca36400037175d3b62ce04d85dbca5e33832"}, - {file = "coverage-7.8.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f82c1a1c1897d2293cb6c50f20fe8a9ea2add1a228eff479380917a1fe7bbb68"}, - {file = "coverage-7.8.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:62a13b372b65fa6e11685df9ca924bed23bab1d0f277f9b67be7536f253aaf17"}, - {file = "coverage-7.8.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe4877c24711458f7990392181be30166cc3ae72158036ecb48a73c30c99fb6f"}, - {file = "coverage-7.8.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ae5e557aa92565d72f6d3196e878e7cbd6a6380e02a15eafe0af781bd767c10d"}, - {file = "coverage-7.8.1-cp39-cp39-win32.whl", hash = "sha256:87284f272746e31919302ab6211b16b41135109822c498f6e7b40a2f828e7836"}, - {file = "coverage-7.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:07fff2f2ce465fae27447432d39ce733476fbf8478de51fb4034c201e0c5da6d"}, - {file = "coverage-7.8.1-pp39.pp310.pp311-none-any.whl", hash = "sha256:adafe9d71a940927dd3ad8d487f521f11277f133568b7da622666ebd08923191"}, - {file = "coverage-7.8.1-py3-none-any.whl", hash = "sha256:e54b80885b0e61d346accc5709daf8762471a452345521cc9281604a907162c2"}, - {file = "coverage-7.8.1.tar.gz", hash = "sha256:d41d4da5f2871b1782c6b74948d2d37aac3a5b39b43a6ba31d736b97a02ae1f1"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, ] [package.extras] @@ -1562,66 +1566,66 @@ typing-extensions = {version = ">=4,<5", markers = "python_version < \"3.10\""} [[package]] name = "grpcio" -version = "1.71.0" +version = "1.72.1" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.9" files = [ - {file = "grpcio-1.71.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:c200cb6f2393468142eb50ab19613229dcc7829b5ccee8b658a36005f6669fdd"}, - {file = "grpcio-1.71.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b2266862c5ad664a380fbbcdbdb8289d71464c42a8c29053820ee78ba0119e5d"}, - {file = "grpcio-1.71.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:0ab8b2864396663a5b0b0d6d79495657ae85fa37dcb6498a2669d067c65c11ea"}, - {file = "grpcio-1.71.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c30f393f9d5ff00a71bb56de4aa75b8fe91b161aeb61d39528db6b768d7eac69"}, - {file = "grpcio-1.71.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f250ff44843d9a0615e350c77f890082102a0318d66a99540f54769c8766ab73"}, - {file = "grpcio-1.71.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6d8de076528f7c43a2f576bc311799f89d795aa6c9b637377cc2b1616473804"}, - {file = "grpcio-1.71.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b91879d6da1605811ebc60d21ab6a7e4bae6c35f6b63a061d61eb818c8168f6"}, - {file = "grpcio-1.71.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f71574afdf944e6652203cd1badcda195b2a27d9c83e6d88dc1ce3cfb73b31a5"}, - {file = "grpcio-1.71.0-cp310-cp310-win32.whl", hash = "sha256:8997d6785e93308f277884ee6899ba63baafa0dfb4729748200fcc537858a509"}, - {file = "grpcio-1.71.0-cp310-cp310-win_amd64.whl", hash = "sha256:7d6ac9481d9d0d129224f6d5934d5832c4b1cddb96b59e7eba8416868909786a"}, - {file = "grpcio-1.71.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:d6aa986318c36508dc1d5001a3ff169a15b99b9f96ef5e98e13522c506b37eef"}, - {file = "grpcio-1.71.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:d2c170247315f2d7e5798a22358e982ad6eeb68fa20cf7a820bb74c11f0736e7"}, - {file = "grpcio-1.71.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:e6f83a583ed0a5b08c5bc7a3fe860bb3c2eac1f03f1f63e0bc2091325605d2b7"}, - {file = "grpcio-1.71.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4be74ddeeb92cc87190e0e376dbc8fc7736dbb6d3d454f2fa1f5be1dee26b9d7"}, - {file = "grpcio-1.71.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd0dfbe4d5eb1fcfec9490ca13f82b089a309dc3678e2edabc144051270a66e"}, - {file = "grpcio-1.71.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a2242d6950dc892afdf9e951ed7ff89473aaf744b7d5727ad56bdaace363722b"}, - {file = "grpcio-1.71.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0fa05ee31a20456b13ae49ad2e5d585265f71dd19fbd9ef983c28f926d45d0a7"}, - {file = "grpcio-1.71.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3d081e859fb1ebe176de33fc3adb26c7d46b8812f906042705346b314bde32c3"}, - {file = "grpcio-1.71.0-cp311-cp311-win32.whl", hash = "sha256:d6de81c9c00c8a23047136b11794b3584cdc1460ed7cbc10eada50614baa1444"}, - {file = "grpcio-1.71.0-cp311-cp311-win_amd64.whl", hash = "sha256:24e867651fc67717b6f896d5f0cac0ec863a8b5fb7d6441c2ab428f52c651c6b"}, - {file = "grpcio-1.71.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:0ff35c8d807c1c7531d3002be03221ff9ae15712b53ab46e2a0b4bb271f38537"}, - {file = "grpcio-1.71.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:b78a99cd1ece4be92ab7c07765a0b038194ded2e0a26fd654591ee136088d8d7"}, - {file = "grpcio-1.71.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc1a1231ed23caac1de9f943d031f1bc38d0f69d2a3b243ea0d664fc1fbd7fec"}, - {file = "grpcio-1.71.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6beeea5566092c5e3c4896c6d1d307fb46b1d4bdf3e70c8340b190a69198594"}, - {file = "grpcio-1.71.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5170929109450a2c031cfe87d6716f2fae39695ad5335d9106ae88cc32dc84c"}, - {file = "grpcio-1.71.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5b08d03ace7aca7b2fadd4baf291139b4a5f058805a8327bfe9aece7253b6d67"}, - {file = "grpcio-1.71.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f903017db76bf9cc2b2d8bdd37bf04b505bbccad6be8a81e1542206875d0e9db"}, - {file = "grpcio-1.71.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:469f42a0b410883185eab4689060a20488a1a0a00f8bbb3cbc1061197b4c5a79"}, - {file = "grpcio-1.71.0-cp312-cp312-win32.whl", hash = "sha256:ad9f30838550695b5eb302add33f21f7301b882937460dd24f24b3cc5a95067a"}, - {file = "grpcio-1.71.0-cp312-cp312-win_amd64.whl", hash = "sha256:652350609332de6dac4ece254e5d7e1ff834e203d6afb769601f286886f6f3a8"}, - {file = "grpcio-1.71.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:cebc1b34ba40a312ab480ccdb396ff3c529377a2fce72c45a741f7215bfe8379"}, - {file = "grpcio-1.71.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:85da336e3649a3d2171e82f696b5cad2c6231fdd5bad52616476235681bee5b3"}, - {file = "grpcio-1.71.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f9a412f55bb6e8f3bb000e020dbc1e709627dcb3a56f6431fa7076b4c1aab0db"}, - {file = "grpcio-1.71.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47be9584729534660416f6d2a3108aaeac1122f6b5bdbf9fd823e11fe6fbaa29"}, - {file = "grpcio-1.71.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9c80ac6091c916db81131d50926a93ab162a7e97e4428ffc186b6e80d6dda4"}, - {file = "grpcio-1.71.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:789d5e2a3a15419374b7b45cd680b1e83bbc1e52b9086e49308e2c0b5bbae6e3"}, - {file = "grpcio-1.71.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1be857615e26a86d7363e8a163fade914595c81fec962b3d514a4b1e8760467b"}, - {file = "grpcio-1.71.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a76d39b5fafd79ed604c4be0a869ec3581a172a707e2a8d7a4858cb05a5a7637"}, - {file = "grpcio-1.71.0-cp313-cp313-win32.whl", hash = "sha256:74258dce215cb1995083daa17b379a1a5a87d275387b7ffe137f1d5131e2cfbb"}, - {file = "grpcio-1.71.0-cp313-cp313-win_amd64.whl", hash = "sha256:22c3bc8d488c039a199f7a003a38cb7635db6656fa96437a8accde8322ce2366"}, - {file = "grpcio-1.71.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:c6a0a28450c16809f94e0b5bfe52cabff63e7e4b97b44123ebf77f448534d07d"}, - {file = "grpcio-1.71.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:a371e6b6a5379d3692cc4ea1cb92754d2a47bdddeee755d3203d1f84ae08e03e"}, - {file = "grpcio-1.71.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:39983a9245d37394fd59de71e88c4b295eb510a3555e0a847d9965088cdbd033"}, - {file = "grpcio-1.71.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9182e0063112e55e74ee7584769ec5a0b4f18252c35787f48738627e23a62b97"}, - {file = "grpcio-1.71.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693bc706c031aeb848849b9d1c6b63ae6bcc64057984bb91a542332b75aa4c3d"}, - {file = "grpcio-1.71.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:20e8f653abd5ec606be69540f57289274c9ca503ed38388481e98fa396ed0b41"}, - {file = "grpcio-1.71.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8700a2a57771cc43ea295296330daaddc0d93c088f0a35cc969292b6db959bf3"}, - {file = "grpcio-1.71.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d35a95f05a8a2cbe8e02be137740138b3b2ea5f80bd004444e4f9a1ffc511e32"}, - {file = "grpcio-1.71.0-cp39-cp39-win32.whl", hash = "sha256:f9c30c464cb2ddfbc2ddf9400287701270fdc0f14be5f08a1e3939f1e749b455"}, - {file = "grpcio-1.71.0-cp39-cp39-win_amd64.whl", hash = "sha256:63e41b91032f298b3e973b3fa4093cbbc620c875e2da7b93e249d4728b54559a"}, - {file = "grpcio-1.71.0.tar.gz", hash = "sha256:2b85f7820475ad3edec209d3d89a7909ada16caab05d3f2e08a7e8ae3200a55c"}, + {file = "grpcio-1.72.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:ce2706ff37be7a6de68fbc4c3f8dde247cab48cc70fee5fedfbc9cd923b4ee5a"}, + {file = "grpcio-1.72.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7db9e15ee7618fbea748176a67d347f3100fa92d36acccd0e7eeb741bc82f72a"}, + {file = "grpcio-1.72.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:8d6e7764181ba4a8b74aa78c98a89c9f3441068ebcee5d6f14c44578214e0be3"}, + {file = "grpcio-1.72.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:237bb619ba33594006025e6f114f62e60d9563afd6f8e89633ee384868e26687"}, + {file = "grpcio-1.72.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7f1d8a442fd242aa432c8e1b8411c79ebc409dad2c637614d726e226ce9ed0c"}, + {file = "grpcio-1.72.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f2359bd4bba85bf94fd9ab8802671b9637a6803bb673d221157a11523a52e6a8"}, + {file = "grpcio-1.72.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3269cfca37570a420a57a785f2a5d4234c5b12aced55f8843dafced2d3f8c9a6"}, + {file = "grpcio-1.72.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:06c023d86398714d6257194c21f2bc0b58a53ce45cee87dd3c54c7932c590e17"}, + {file = "grpcio-1.72.1-cp310-cp310-win32.whl", hash = "sha256:06dbe54eeea5f9dfb3e7ca2ff66c715ff5fc96b07a1feb322122fe14cb42f6aa"}, + {file = "grpcio-1.72.1-cp310-cp310-win_amd64.whl", hash = "sha256:ba593aa2cd52f4468ba29668c83f893d88c128198d6b1273ca788ef53e3ae5fe"}, + {file = "grpcio-1.72.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:4e112c083f90c330b0eaa78a633fb206d49c20c443926e827f8cac9eb9d2ea32"}, + {file = "grpcio-1.72.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c6f7e3275832adab7384193f78b8c1a98b82541562fa08d7244e8a6b4b5c78a4"}, + {file = "grpcio-1.72.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:dd03c8847c47ef7ac5455aafdfb5e553ecf84f228282bd6106762b379f27c25c"}, + {file = "grpcio-1.72.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7497dbdf220b88b66004e2630fb2b1627df5e279db970d3cc20f70d39dce978d"}, + {file = "grpcio-1.72.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c2cde3ae8ae901317c049394ed8d3c6964de6b814ae65fc68636a7337b63aa"}, + {file = "grpcio-1.72.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7a66cef4bc1db81a54108a849e95650da640c9bc1901957bf7d3b1eeb3251ee8"}, + {file = "grpcio-1.72.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fc0435ad45d540597f78978e3fd5515b448193f51f9065fb67dda566336e0f5f"}, + {file = "grpcio-1.72.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:524bad78d610fa1f9f316d47b3aab1ff89d438ba952ee34e3e335ca80a27ba96"}, + {file = "grpcio-1.72.1-cp311-cp311-win32.whl", hash = "sha256:409ee0abf7e74bbf88941046142452cf3d1f3863d34e11e8fd2b07375170c730"}, + {file = "grpcio-1.72.1-cp311-cp311-win_amd64.whl", hash = "sha256:ea483e408fac55569c11158c3e6d6d6a8c3b0f798b68f1c10db9b22c5996e19b"}, + {file = "grpcio-1.72.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:65a5ef28e5852bd281c6d01a923906e8036736e95e370acab8626fcbec041e67"}, + {file = "grpcio-1.72.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:9e5c594a6c779d674204fb9bdaa1e7b71666ff10b34a62e7769fc6868b5d7511"}, + {file = "grpcio-1.72.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:d324f4bdb990d852d79b38c59a12d24fcd47cf3b1a38f2e4d2b6d0b1031bc818"}, + {file = "grpcio-1.72.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:841db55dd29cf2f4121b853b2f89813a1b6175163fbb92c5945fb1b0ca259ef2"}, + {file = "grpcio-1.72.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00da930aa2711b955a538e835096aa365a4b7f2701bdc2ce1febb242a103f8a1"}, + {file = "grpcio-1.72.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4b657773480267fbb7ad733fa85abc103c52ab62e5bc97791faf82c53836eefc"}, + {file = "grpcio-1.72.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a08b483f17a6abca2578283a7ae3aa8d4d90347242b0de2898bdb27395c3f20b"}, + {file = "grpcio-1.72.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:299f3ea4e03c1d0548f4a174b48d612412f92c667f2100e30a079ab76fdaa813"}, + {file = "grpcio-1.72.1-cp312-cp312-win32.whl", hash = "sha256:addc721a3708ff789da1bf69876018dc730c1ec9d3d3cb6912776a00c535a5bc"}, + {file = "grpcio-1.72.1-cp312-cp312-win_amd64.whl", hash = "sha256:22ea2aa92a60dff231ba5fcd7f0220a33c2218e556009996f858eeafe294d1c2"}, + {file = "grpcio-1.72.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:294be6e9c323a197434569a41e0fb5b5aa0962fd5d55a3dc890ec5df985f611a"}, + {file = "grpcio-1.72.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:41ec164dac8df2862f67457d9cdf8d8f8b6a4ca475a3ed1ba6547fff98d93717"}, + {file = "grpcio-1.72.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:761736f75c6ddea3732d97eaabe70c616271f5f542a8be95515135fdd1a638f6"}, + {file = "grpcio-1.72.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:082003cb93618964c111c70d69b60ac0dc6566d4c254c9b2a775faa2965ba8f8"}, + {file = "grpcio-1.72.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8660f736da75424949c14f7c8b1ac60a25b2f37cabdec95181834b405373e8a7"}, + {file = "grpcio-1.72.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2ada1abe2ad122b42407b2bfd79d6706a4940d4797f44bd740f5c98ca1ecda9b"}, + {file = "grpcio-1.72.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:0db2766d0c482ee740abbe7d00a06cc4fb54f7e5a24d3cf27c3352be18a2b1e8"}, + {file = "grpcio-1.72.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4bdb404d9c2187260b34e2b22783c204fba8a9023a166cf77376190d9cf5a08"}, + {file = "grpcio-1.72.1-cp313-cp313-win32.whl", hash = "sha256:bb64722c3124c906a5b66e50a90fd36442642f653ba88a24f67d08e94bca59f3"}, + {file = "grpcio-1.72.1-cp313-cp313-win_amd64.whl", hash = "sha256:329cc6ff5b431df9614340d3825b066a1ff0a5809a01ba2e976ef48c65a0490b"}, + {file = "grpcio-1.72.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:8941b83addd503c1982090b4631804d0ff1edbbc6c85c9c20ed503b1dc65fef9"}, + {file = "grpcio-1.72.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:d29b80290c5eda561a4c291d6d5b4315a2a5095ab37061118d6e0781858aca0a"}, + {file = "grpcio-1.72.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:4ca56d955564db749c9c6d75e9c4c777854e22b2482d247fb6c5a02d5f28ea78"}, + {file = "grpcio-1.72.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b08a3ef14d2b01eef13882c6d3a2d8fb5fcd73db81bd1e3ab69d4ee75215433a"}, + {file = "grpcio-1.72.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd7df49801b3b323e4a21047979e3834cd286b32ee5ceee46f5217826274721f"}, + {file = "grpcio-1.72.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9717617ba2ff65c058ef53b0d5e50f03e8350f0c5597f93bb5c980a31db990c8"}, + {file = "grpcio-1.72.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:212db80b1e8aa7792d51269bfb32164e2333a9bb273370ace3ed2a378505cb01"}, + {file = "grpcio-1.72.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a0d19947d4480af5f363f077f221e665931f479e2604280ac4eafe6daa71f77"}, + {file = "grpcio-1.72.1-cp39-cp39-win32.whl", hash = "sha256:7622ef647dc911ed010a817d9be501df4ae83495b8e5cdd35b555bdcf3880a3e"}, + {file = "grpcio-1.72.1-cp39-cp39-win_amd64.whl", hash = "sha256:f8d8fa7cd2a7f1b4207e215dec8bc07f1202682d9a216ebe028185c15faece30"}, + {file = "grpcio-1.72.1.tar.gz", hash = "sha256:87f62c94a40947cec1a0f91f95f5ba0aa8f799f23a1d42ae5be667b6b27b959c"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.71.0)"] +protobuf = ["grpcio-tools (>=1.72.1)"] [[package]] name = "h11" @@ -2306,7 +2310,7 @@ nicer-shell = ["ipython"] [[package]] name = "olas-operate-middleware" -version = "0.4.0" +version = "0.5.0" description = "" optional = false python-versions = "<3.12,>=3.9" @@ -2351,8 +2355,8 @@ web3 = "==6.1.0" [package.source] type = "git" url = "https://github.com/valory-xyz/olas-operate-middleware.git" -reference = "920957b1871a533a3a63f1162d9c6d10625226a8" -resolved_reference = "920957b1871a533a3a63f1162d9c6d10625226a8" +reference = "7acdd8bcc906d50b99313c89c57992b9cccbc08f" +resolved_reference = "7acdd8bcc906d50b99313c89c57992b9cccbc08f" [[package]] name = "open-aea" @@ -2846,13 +2850,13 @@ files = [ [[package]] name = "pydantic" -version = "2.11.4" +version = "2.11.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, + {file = "pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7"}, + {file = "pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a"}, ] [package.dependencies] @@ -3452,13 +3456,13 @@ files = [ [[package]] name = "setuptools" -version = "80.8.0" +version = "80.9.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" files = [ - {file = "setuptools-80.8.0-py3-none-any.whl", hash = "sha256:95a60484590d24103af13b686121328cc2736bee85de8936383111e421b9edc0"}, - {file = "setuptools-80.8.0.tar.gz", hash = "sha256:49f7af965996f26d43c8ae34539c8d99c5042fbff34302ea151eaa9c207cd257"}, + {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, + {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [package.extras] @@ -3640,13 +3644,13 @@ pyotp = "*" [[package]] name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" +version = "4.14.0" +description = "Backported and Experimental Type Hints for Python 3.9+" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, + {file = "typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af"}, + {file = "typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4"}, ] [[package]] @@ -4038,13 +4042,13 @@ propcache = ">=0.2.1" [[package]] name = "zipp" -version = "3.21.0" +version = "3.22.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.9" files = [ - {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, - {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, + {file = "zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343"}, + {file = "zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5"}, ] [package.extras] @@ -4052,10 +4056,10 @@ check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "importlib_resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "ee0d3ab758d5e2dfc4e0e984b7064f301bb3dd800b9a82a39358d4375a1e3c8e" +content-hash = "2024fd89c843e182c519c141c302781626df980632e52c1e1614acb395117851" diff --git a/pyproject.toml b/pyproject.toml index 7dc50118e..54a022113 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "olas-operate-app" -version = "0.2.0-rc176" +version = "0.2.0-rc267" description = "" authors = ["David Vilela ", "Viraj Patel "] readme = "README.md" @@ -9,7 +9,7 @@ include = [] [tool.poetry.dependencies] python = ">=3.9,<3.12" -olas-operate-middleware = { git = "https://github.com/valory-xyz/olas-operate-middleware.git", rev = "920957b1871a533a3a63f1162d9c6d10625226a8"} +olas-operate-middleware = { git = "https://github.com/valory-xyz/olas-operate-middleware.git", rev = "7acdd8bcc906d50b99313c89c57992b9cccbc08f"} [build-system] requires = ["poetry-core"] diff --git a/templates/memeooorr.yaml b/templates/memeooorr.yaml deleted file mode 100644 index a8dbda662..000000000 --- a/templates/memeooorr.yaml +++ /dev/null @@ -1,79 +0,0 @@ -name: "Memeooorr" -description: "Memeooorr @twitter_handle" -hash: bafybeieqcjtgrn33q3mjevwp6ituytmudlq656ux6ofplzc7omtd5osdqy -image: https://gateway.autonolas.tech/ipfs/QmQYDGMg8m91QQkTWSSmANs5tZwKrmvUCawXZfXVVWQPcu -service_version: v0.4.2-alpha2 -home_chain: "base" -configurations: - base: - staking_program_id: meme_base_alpha_2 - nft: bafybeiaakdeconw7j5z76fgghfdjmsr6tzejotxcwnvmp3nroaw3glgyve - rpc: http://localhost:8545 # User provided - threshold: 1 # TODO: Move to service component - use_staking: true # User provided - cost_of_bond: 50000000000000000000 - monthly_gas_estimate: 50000000000000000 # 0.05 - fund_requirements: - agent: 1000000000000000 # 0.001 - safe: 2000000000000000 # 0.002 -env_variables: - BASE_LEDGER_RPC: - name: "Base ledger RPC" - description: "" - value: "" - provision_type: "computed" - CELO_LEDGER_RPC: - name: "Base ledger RPC" - description: "" - value: "" - provision_type: "computed" - TWIKIT_USERNAME: - name: "Twitter username" - description: "" - value: "" - provision_type: "user" - TWIKIT_EMAIL: - name: "Twitter email" - description: "" - value: "" - provision_type: "user" - TWIKIT_PASSWORD: - name: "Twitter password" - description: "" - value: "" - provision_type: "user" - GENAI_API_KEY: - name: "Gemini api key" - description: "" - value: "" - provision_type: "user" - PERSONA: - name: "Persona description" - description: "" - value: "" - provision_type: "user" - FEEDBACK_PERIOD_HOURS: - name: "Feedback period" - description: "" - value: "1" - provision_type: "fixed" - MIN_FEEDBACK_REPLIES: - name: "Minimum feedback replies" - description: "" - value: "10" - provision_type: "fixed" - RESET_PAUSE_DURATION: - name: "Reset pause duration" - description: "" - value: "1800" - provision_type: "fixed" - DB_PATH: - name: "DB path" - description: "" - value: "persistent_data/memeooorr.db" - provision_type: "computed" - TWIKIT_COOKIES_PATH: - name: "Twitter cookies path" - description: "" - value: "persistent_data/twikit_cookies.json" - provision_type: "computed" diff --git a/templates/optimus.yaml b/templates/optimus.yaml deleted file mode 100644 index cf387a68a..000000000 --- a/templates/optimus.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: Optimus -hash: bafybeife3l2d2vlznwwfsyx27kd2csxi6apul7ggroy377t573oltezwlm -description: Optimus -image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 -service_version: v0.3.15 -home_chain: "optimistic" -configurations: - ethereum: - staking_program_id: optimus_alpha - nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq - agent_id: 14 - threshold: 1 - use_staking: false - use_mech_marketplace: false - cost_of_bond: 1 - monthly_gas_estimate: 1000 #defaulted to 1000 as value unknown for now, needed for testing - fund_requirements: - agent: 1000 - safe: 1000 - optimistic: - staking_program_id: optimus_alpha - nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq - agent_id: 14 - threshold: 1 - use_staking: true - use_mech_marketplace: false - cost_of_bond: 1000 - monthly_gas_estimate: 1000 - fund_requirements: - agent: 1000 - safe: 1000 - base: - staking_program_id: optimus_alpha - nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq - agent_id: 14 - threshold: 1 - use_staking: false - use_mech_marketplace: false - cost_of_bond: 1 - monthly_gas_estimate: 1000 - fund_requirements: - agent: 1000 - safe: 1000 \ No newline at end of file diff --git a/templates/trader.yaml b/templates/trader.yaml deleted file mode 100644 index e39495921..000000000 --- a/templates/trader.yaml +++ /dev/null @@ -1,60 +0,0 @@ -name: "Trader Agent" -description: "A single-agent service (sovereign agent) placing bets on Omen" -hash: bafybeidjghfanh4ligtaqwjjxelebeykum23ckbaekxoxdgxrcpaxwhubm -image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 -service_version: v0.25.0 -home_chain: "gnosis" -configurations: - gnosis: - staking_program_id: pearl_beta - nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq - rpc: http://localhost:8545 # User provided - threshold: 1 # TODO: Move to service component - use_staking: false # User provided - use_mech_marketplace: false # User provided - cost_of_bond: 10000000000000000 - monthly_gas_estimate: 10000000000000000000 # TODO: Where is this used - fund_requirements: - agent: 100000000000000000 - safe: 5000000000000000000 -env_variables: - GNOSIS_LEDGER_RPC: - name: "Gnosis ledger RPC" - description: "" - value: "" - provision_type: "computed" - STAKING_CONTRACT_ADDRESS: - name: "Staking contract address" - description: "" - value: "" - provision_type: "computed" - MECH_ACTIVITY_CHECKER_CONTRACT: - name: "Mech activity checker contract" - description: "" - value: "" - provision_type: "computed" - MECH_CONTRACT_ADDRESS: - name: "Mech contract address" - description: "" - value: "" - provision_type: "computed" - MECH_REQUEST_PRICE: - name: "Mech request price" - description: "" - value: "" - provision_type: "computed" - USE_MECH_MARKETPLACE: - name: "Use Mech marketplace" - description: "" - value: "" - provision_type: "computed" - REQUESTER_STAKING_INSTANCE_ADDRESS: - name: "Requester staking instance address" - description: "" - value: "" - provision_type: "computed" - PRIORITY_MECH_ADDRESS: - name: "Priority Mech address" - description: "" - value: "" - provision_type: "computed"