From 5c2e9a6472604a125f619477af7a9a2335484eca Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Tue, 22 Oct 2024 17:19:32 +0200 Subject: [PATCH 01/43] feat: add mech marketplace staking contract --- frontend/constants/contractAddresses.ts | 1 + frontend/enums/StakingProgram.ts | 1 + operate/ledger/profiles.py | 1 + 3 files changed, 3 insertions(+) diff --git a/frontend/constants/contractAddresses.ts b/frontend/constants/contractAddresses.ts index f22eebd2b..c14a4f1da 100644 --- a/frontend/constants/contractAddresses.ts +++ b/frontend/constants/contractAddresses.ts @@ -24,6 +24,7 @@ export const SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES: Record< [StakingProgramId.Beta2]: '0x1c2F82413666d2a3fD8bC337b0268e62dDF67434', [StakingProgramId.Beta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', [StakingProgramId.Alpha]: '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', + [StakingProgramId.BetaMechMarketplace]: '0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA', }, }; diff --git a/frontend/enums/StakingProgram.ts b/frontend/enums/StakingProgram.ts index dc5a16da9..1ad892083 100644 --- a/frontend/enums/StakingProgram.ts +++ b/frontend/enums/StakingProgram.ts @@ -2,4 +2,5 @@ export enum StakingProgramId { Alpha = 'pearl_alpha', Beta = 'pearl_beta', Beta2 = 'pearl_beta_2', + BetaMechMarketplace = 'pearl_beta_mech_marketplace', } diff --git a/operate/ledger/profiles.py b/operate/ledger/profiles.py index 523c1fdb9..6fcfc0de8 100644 --- a/operate/ledger/profiles.py +++ b/operate/ledger/profiles.py @@ -40,6 +40,7 @@ "pearl_alpha": "0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A", "pearl_beta": "0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d", "pearl_beta_2": "0x1c2F82413666d2a3fD8bC337b0268e62dDF67434", + "pearl_beta_mech_marketplace": "0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA" } } From 8ea65dc3ad9c5f5b21f4a9b7d27a9a6ff00bf071 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Tue, 22 Oct 2024 17:26:50 +0200 Subject: [PATCH 02/43] fix: linters --- operate/ledger/profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operate/ledger/profiles.py b/operate/ledger/profiles.py index 6fcfc0de8..d0e62b272 100644 --- a/operate/ledger/profiles.py +++ b/operate/ledger/profiles.py @@ -40,7 +40,7 @@ "pearl_alpha": "0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A", "pearl_beta": "0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d", "pearl_beta_2": "0x1c2F82413666d2a3fD8bC337b0268e62dDF67434", - "pearl_beta_mech_marketplace": "0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA" + "pearl_beta_mech_marketplace": "0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA", } } From 8f14ef127b0f2aa7732915161581a85dd8d3a198 Mon Sep 17 00:00:00 2001 From: truemiller Date: Tue, 22 Oct 2024 17:00:05 +0100 Subject: [PATCH 03/43] feat: integrate mech marketplace on frontend --- frontend/abis/mechMarketplace.ts | 442 ++++++++++++++++++ frontend/abis/requesterActivityChecker.ts | 44 ++ frontend/constants/contractAddresses.ts | 26 +- frontend/constants/stakingProgramMeta.ts | 18 +- .../context/StakingContractInfoProvider.tsx | 14 +- frontend/service/Autonolas.ts | 50 +- 6 files changed, 573 insertions(+), 21 deletions(-) create mode 100644 frontend/abis/mechMarketplace.ts create mode 100644 frontend/abis/requesterActivityChecker.ts diff --git a/frontend/abis/mechMarketplace.ts b/frontend/abis/mechMarketplace.ts new file mode 100644 index 000000000..b43c9279f --- /dev/null +++ b/frontend/abis/mechMarketplace.ts @@ -0,0 +1,442 @@ +export const MECH_MARKETPLACE_ABI = [ + { + inputs: [ + { internalType: 'address', name: '_stakingFactory', type: 'address' }, + { internalType: 'address', name: '_karmaProxy', type: 'address' }, + { internalType: 'uint256', name: '_minResponseTimeout', type: 'uint256' }, + { internalType: 'uint256', name: '_maxResponseTimeout', type: 'uint256' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], + name: 'AlreadyDelivered', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'provided', type: 'uint256' }, + { internalType: 'uint256', name: 'min', type: 'uint256' }, + { internalType: 'uint256', name: 'max', type: 'uint256' }, + ], + name: 'OutOfBounds', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'provided', type: 'uint256' }, + { internalType: 'uint256', name: 'max', type: 'uint256' }, + ], + name: 'Overflow', + type: 'error', + }, + { + inputs: [ + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'address', name: 'owner', type: 'address' }, + ], + name: 'OwnerOnly', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'expected', type: 'uint256' }, + { internalType: 'uint256', name: 'current', type: 'uint256' }, + ], + name: 'PriorityMechResponseTimeout', + type: 'error', + }, + { inputs: [], name: 'ReentrancyGuard', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'stakingInstance', type: 'address' }, + { internalType: 'uint256', name: 'serviceId', type: 'uint256' }, + ], + name: 'ServiceNotStaked', + type: 'error', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'UnauthorizedAccount', + type: 'error', + }, + { inputs: [], name: 'ZeroAddress', type: 'error' }, + { inputs: [], name: 'ZeroValue', type: 'error' }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'factory', + type: 'address', + }, + ], + name: 'FactoryUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'priorityMech', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'actualMech', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'requester', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'requestId', + type: 'uint256', + }, + { indexed: false, internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'MarketplaceDeliver', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'requester', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'requestedMech', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'requestId', + type: 'uint256', + }, + { indexed: false, internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'MarketplaceRequest', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'mech', type: 'address' }, + { indexed: false, internalType: 'bool', name: 'status', type: 'bool' }, + ], + name: 'MechRegistrationStatusChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint256', + name: 'minResponseTimeout', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'maxResponseTimeout', + type: 'uint256', + }, + ], + name: 'MinMaxResponseTimeoutUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + ], + name: 'OwnerUpdated', + type: 'event', + }, + { + inputs: [], + name: 'DOMAIN_SEPARATOR_TYPE_HASH', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'VERSION', + outputs: [{ internalType: 'string', name: '', type: 'string' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'chainId', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'mech', type: 'address' }, + { internalType: 'address', name: 'mechStakingInstance', type: 'address' }, + { internalType: 'uint256', name: 'mechServiceId', type: 'uint256' }, + ], + name: 'checkMech', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'requester', type: 'address' }, + { + internalType: 'address', + name: 'requesterStakingInstance', + type: 'address', + }, + { internalType: 'uint256', name: 'requesterServiceId', type: 'uint256' }, + ], + name: 'checkRequester', + outputs: [], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'stakingInstance', type: 'address' }, + { internalType: 'uint256', name: 'serviceId', type: 'uint256' }, + ], + name: 'checkStakingInstance', + outputs: [], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'requestId', type: 'uint256' }, + { internalType: 'bytes', name: 'requestData', type: 'bytes' }, + { + internalType: 'address', + name: 'deliveryMechStakingInstance', + type: 'address', + }, + { + internalType: 'uint256', + name: 'deliveryMechServiceId', + type: 'uint256', + }, + ], + name: 'deliverMarketplace', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'domainSeparator', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'getDeliveriesCount', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getDomainSeparator', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], + name: 'getMechDeliveryInfo', + outputs: [ + { + components: [ + { internalType: 'address', name: 'priorityMech', type: 'address' }, + { internalType: 'address', name: 'deliveryMech', type: 'address' }, + { internalType: 'address', name: 'requester', type: 'address' }, + { internalType: 'uint32', name: 'responseTimeout', type: 'uint32' }, + ], + internalType: 'struct MechDelivery', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'mechService', type: 'address' }], + name: 'getMechServiceDeliveriesCount', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'account', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + ], + name: 'getRequestId', + outputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], + name: 'getRequestStatus', + outputs: [ + { + internalType: 'enum MechMarketplace.RequestStatus', + name: 'status', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'getRequestsCount', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'karmaProxy', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'mapDeliveryCounts', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'mapMechServiceDeliveryCounts', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'mapNonces', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'mapRequestCounts', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'mapRequestIdDeliveries', + outputs: [ + { internalType: 'address', name: 'priorityMech', type: 'address' }, + { internalType: 'address', name: 'deliveryMech', type: 'address' }, + { internalType: 'address', name: 'requester', type: 'address' }, + { internalType: 'uint32', name: 'responseTimeout', type: 'uint32' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'maxResponseTimeout', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'minResponseTimeout', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'numTotalRequests', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'numUndeliveredRequests', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'bytes', name: 'data', type: 'bytes' }, + { internalType: 'address', name: 'priorityMech', type: 'address' }, + { + internalType: 'address', + name: 'priorityMechStakingInstance', + type: 'address', + }, + { + internalType: 'uint256', + name: 'priorityMechServiceId', + type: 'uint256', + }, + { + internalType: 'address', + name: 'requesterStakingInstance', + type: 'address', + }, + { internalType: 'uint256', name: 'requesterServiceId', type: 'uint256' }, + { internalType: 'uint256', name: 'responseTimeout', type: 'uint256' }, + ], + name: 'request', + outputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'stakingFactory', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, +]; diff --git a/frontend/abis/requesterActivityChecker.ts b/frontend/abis/requesterActivityChecker.ts new file mode 100644 index 000000000..802a20ede --- /dev/null +++ b/frontend/abis/requesterActivityChecker.ts @@ -0,0 +1,44 @@ +export const REQUESTER_ACTIVITY_CHECKER_ABI = [ + { + inputs: [ + { internalType: 'address', name: '_mechMarketplace', type: 'address' }, + { internalType: 'uint256', name: '_livenessRatio', type: 'uint256' }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { inputs: [], name: 'ZeroAddress', type: 'error' }, + { inputs: [], name: 'ZeroValue', type: 'error' }, + { + inputs: [{ internalType: 'address', name: 'multisig', type: 'address' }], + name: 'getMultisigNonces', + outputs: [{ internalType: 'uint256[]', name: 'nonces', type: 'uint256[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256[]', name: 'curNonces', type: 'uint256[]' }, + { internalType: 'uint256[]', name: 'lastNonces', type: 'uint256[]' }, + { internalType: 'uint256', name: 'ts', type: 'uint256' }, + ], + name: 'isRatioPass', + outputs: [{ internalType: 'bool', name: 'ratioPass', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'livenessRatio', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'mechMarketplace', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, +]; diff --git a/frontend/constants/contractAddresses.ts b/frontend/constants/contractAddresses.ts index c14a4f1da..9af8f62e3 100644 --- a/frontend/constants/contractAddresses.ts +++ b/frontend/constants/contractAddresses.ts @@ -24,14 +24,38 @@ export const SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES: Record< [StakingProgramId.Beta2]: '0x1c2F82413666d2a3fD8bC337b0268e62dDF67434', [StakingProgramId.Beta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', [StakingProgramId.Alpha]: '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', - [StakingProgramId.BetaMechMarketplace]: '0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA', + [StakingProgramId.BetaMechMarketplace]: + '0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA', }, }; +/** + * Standard mech contract addresses + */ export const AGENT_MECH_CONTRACT_ADDRESS: Record = { [Chain.GNOSIS]: '0x77af31De935740567Cf4fF1986D04B2c964A786a', }; +/** + * Standard mech activity checker contract addresses + */ export const MECH_ACTIVITY_CHECKER_CONTRACT_ADDRESS: Record = { [Chain.GNOSIS]: '0x155547857680A6D51bebC5603397488988DEb1c8', }; + +/** + * Mech marketplace contract addresses + */ +export const MECH_MARKETPLACE_CONTRACT_ADDRESS: Record = { + [Chain.GNOSIS]: '0x4554fE75c1f5576c1d7F765B2A036c199Adae329', +}; + +/** + * Mech marketplace activity checker contract addresses + */ +export const REQUESTER_ACTIVITY_CHECKER_CONTRACT_ADDRESS: Record< + number, + Address +> = { + [Chain.GNOSIS]: '0x7Ec96996Cd146B91779f01419db42E67463817a0', +}; diff --git a/frontend/constants/stakingProgramMeta.ts b/frontend/constants/stakingProgramMeta.ts index 0e3ecf6de..5e49a9590 100644 --- a/frontend/constants/stakingProgramMeta.ts +++ b/frontend/constants/stakingProgramMeta.ts @@ -12,17 +12,29 @@ export const STAKING_PROGRAM_META: Record< > = { [StakingProgramId.Alpha]: { name: 'Pearl Alpha', - canMigrateTo: [StakingProgramId.Beta, StakingProgramId.Beta2], + canMigrateTo: [ + StakingProgramId.Beta, + StakingProgramId.Beta2, + StakingProgramId.BetaMechMarketplace, + ], deprecated: true, }, [StakingProgramId.Beta]: { name: 'Pearl Beta', - canMigrateTo: [StakingProgramId.Beta2], + canMigrateTo: [ + StakingProgramId.Beta2, + StakingProgramId.BetaMechMarketplace, + ], deprecated: false, }, [StakingProgramId.Beta2]: { name: 'Pearl Beta 2', - canMigrateTo: [StakingProgramId.Beta], + canMigrateTo: [StakingProgramId.Beta, StakingProgramId.BetaMechMarketplace], + deprecated: false, + }, + [StakingProgramId.BetaMechMarketplace]: { + name: 'Pearl Beta - Mech Marketplace', + canMigrateTo: [StakingProgramId.Beta, StakingProgramId.Beta2], deprecated: false, }, }; diff --git a/frontend/context/StakingContractInfoProvider.tsx b/frontend/context/StakingContractInfoProvider.tsx index a0dd6c423..115df8d0e 100644 --- a/frontend/context/StakingContractInfoProvider.tsx +++ b/frontend/context/StakingContractInfoProvider.tsx @@ -90,20 +90,22 @@ export const StakingContractInfoProvider = ({ const beta = AutonolasService.getStakingContractInfoByStakingProgram( StakingProgramId.Beta, ); - const beta_2 = AutonolasService.getStakingContractInfoByStakingProgram( + const beta2 = AutonolasService.getStakingContractInfoByStakingProgram( StakingProgramId.Beta2, ); + const betaMechMarketplace = + AutonolasService.getStakingContractInfoByStakingProgram( + StakingProgramId.BetaMechMarketplace, + ); try { - const [alphaInfo, betaInfo, beta2Info] = await Promise.all([ - alpha, - beta, - beta_2, - ]); + const [alphaInfo, betaInfo, beta2Info, betaMechMarketplaceInfo] = + await Promise.all([alpha, beta, beta2, betaMechMarketplace]); setStakingContractInfoRecord({ [StakingProgramId.Alpha]: alphaInfo, [StakingProgramId.Beta]: betaInfo, [StakingProgramId.Beta2]: beta2Info, + [StakingProgramId.BetaMechMarketplace]: betaMechMarketplaceInfo, }); setIsStakingContractInfoLoaded(true); } catch (e) { diff --git a/frontend/service/Autonolas.ts b/frontend/service/Autonolas.ts index ad5b91809..30ba16a63 100644 --- a/frontend/service/Autonolas.ts +++ b/frontend/service/Autonolas.ts @@ -4,6 +4,7 @@ import { Contract as MulticallContract } from 'ethers-multicall'; import { AGENT_MECH_ABI } from '@/abis/agentMech'; import { MECH_ACTIVITY_CHECKER_ABI } from '@/abis/mechActivityChecker'; +import { REQUESTER_ACTIVITY_CHECKER_ABI } from '@/abis/requesterActivityChecker'; import { SERVICE_REGISTRY_L2_ABI } from '@/abis/serviceRegistryL2'; import { SERVICE_REGISTRY_TOKEN_UTILITY_ABI } from '@/abis/serviceRegistryTokenUtility'; import { SERVICE_STAKING_TOKEN_MECH_USAGE_ABI } from '@/abis/serviceStakingTokenMechUsage'; @@ -11,6 +12,7 @@ import { Chain } from '@/client'; import { AGENT_MECH_CONTRACT_ADDRESS, MECH_ACTIVITY_CHECKER_CONTRACT_ADDRESS, + REQUESTER_ACTIVITY_CHECKER_CONTRACT_ADDRESS, SERVICE_REGISTRY_L2_CONTRACT_ADDRESS, SERVICE_REGISTRY_TOKEN_UTILITY_CONTRACT_ADDRESS, SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES, @@ -24,11 +26,6 @@ import { StakingContractInfo, StakingRewardsInfo } from '@/types/Autonolas'; const ONE_YEAR = 1 * 24 * 60 * 60 * 365; const REQUIRED_MECH_REQUESTS_SAFETY_MARGIN = 1; -const agentMechContract = new MulticallContract( - AGENT_MECH_CONTRACT_ADDRESS[Chain.GNOSIS], - AGENT_MECH_ABI.filter((abi) => abi.type === 'function'), // weird bug in the package where their filter doesn't work.. -); - const ServiceStakingTokenAbi = SERVICE_STAKING_TOKEN_MECH_USAGE_ABI.filter( (abi) => abi.type === 'function', ); @@ -55,21 +52,42 @@ const serviceStakingTokenMechUsageContracts: Record< ], ServiceStakingTokenAbi, ), + [StakingProgramId.BetaMechMarketplace]: new MulticallContract( + SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS][ + StakingProgramId.BetaMechMarketplace + ], + ServiceStakingTokenAbi, + ), }; const serviceRegistryTokenUtilityContract = new MulticallContract( SERVICE_REGISTRY_TOKEN_UTILITY_CONTRACT_ADDRESS[Chain.GNOSIS], - SERVICE_REGISTRY_TOKEN_UTILITY_ABI.filter((abi) => abi.type === 'function'), // same as above + SERVICE_REGISTRY_TOKEN_UTILITY_ABI.filter((abi) => abi.type === 'function'), ); const serviceRegistryL2Contract = new MulticallContract( SERVICE_REGISTRY_L2_CONTRACT_ADDRESS[Chain.GNOSIS], - SERVICE_REGISTRY_L2_ABI.filter((abi) => abi.type === 'function'), // same as above + SERVICE_REGISTRY_L2_ABI.filter((abi) => abi.type === 'function'), ); -const mechActivityCheckerContract = new MulticallContract( +const agentMechContract = new MulticallContract( + AGENT_MECH_CONTRACT_ADDRESS[Chain.GNOSIS], + AGENT_MECH_ABI.filter((abi) => abi.type === 'function'), +); + +const agentMechActivityCheckerContract = new MulticallContract( + MECH_ACTIVITY_CHECKER_CONTRACT_ADDRESS[Chain.GNOSIS], + MECH_ACTIVITY_CHECKER_ABI.filter((abi) => abi.type === 'function'), +); + +const mechMarketplaceContract = new MulticallContract( MECH_ACTIVITY_CHECKER_CONTRACT_ADDRESS[Chain.GNOSIS], - MECH_ACTIVITY_CHECKER_ABI.filter((abi) => abi.type === 'function'), // same as above + MECH_ACTIVITY_CHECKER_ABI.filter((abi) => abi.type === 'function'), +); + +const mechMarketplaceActivityCheckerContract = new MulticallContract( + REQUESTER_ACTIVITY_CHECKER_CONTRACT_ADDRESS[Chain.GNOSIS], + REQUESTER_ACTIVITY_CHECKER_ABI.filter((abi) => abi.type === 'function'), ); const getAgentStakingRewardsInfo = async ({ @@ -84,13 +102,23 @@ const getAgentStakingRewardsInfo = async ({ if (!agentMultisigAddress) return; if (!serviceId) return; + const mechContract = + stakingProgram === StakingProgramId.BetaMechMarketplace + ? mechMarketplaceContract + : agentMechContract; + + const mechActivityContract = + stakingProgram === StakingProgramId.BetaMechMarketplace + ? mechMarketplaceActivityCheckerContract + : agentMechActivityCheckerContract; + const contractCalls = [ - agentMechContract.getRequestsCount(agentMultisigAddress), + mechContract.getRequestsCount(agentMultisigAddress), serviceStakingTokenMechUsageContracts[stakingProgram].getServiceInfo( serviceId, ), serviceStakingTokenMechUsageContracts[stakingProgram].livenessPeriod(), - mechActivityCheckerContract.livenessRatio(), + mechActivityContract.livenessRatio(), serviceStakingTokenMechUsageContracts[stakingProgram].rewardsPerSecond(), serviceStakingTokenMechUsageContracts[ stakingProgram From db8c7575066a4bcac47cc8d6c8e23ef9fdca8d77 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Wed, 23 Oct 2024 14:19:43 +0200 Subject: [PATCH 04/43] chore: fix variables for deployments --- frontend/client/types.ts | 1 + frontend/constants/serviceTemplates.ts | 6 ++++-- operate/services/service.py | 25 +++++++++++++++++++++---- operate/types.py | 2 ++ templates/trader.yaml | 5 +++-- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/frontend/client/types.ts b/frontend/client/types.ts index 9b3c25ca7..70a47d697 100644 --- a/frontend/client/types.ts +++ b/frontend/client/types.ts @@ -67,6 +67,7 @@ export type ConfigurationTemplate = { agent_id: number; threshold: number; use_staking: boolean; + use_mech_marketplace: boolean; cost_of_bond: number; monthly_gas_estimate: number; fund_requirements: FundRequirementsTemplate; diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index ed9bd9b13..573a11381 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -4,20 +4,22 @@ import { StakingProgramId } from '@/enums/StakingProgram'; export const SERVICE_TEMPLATES: ServiceTemplate[] = [ { name: 'Trader Agent', - hash: 'bafybeicbfnqfc3potbfmvrmssaxepwilipe5myjbg4xh7ix2sdll4kyc6m', + hash: 'bafybeidts6y6wytfcwlhnvnacf3vhm6lkiocoe22kkmxxx2onzguez3y3q', // hash: 'bafybeibbloa4w33vj4bvdkso7pzk6tr3duvxjpecbx4mur4ix6ehnwb5uu', // temporary description: 'Trader agent for omen prediction markets', image: 'https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75', - service_version: 'v0.18.1', + service_version: 'v0.18.2', home_chain_id: '100', configurations: { 100: { staking_program_id: StakingProgramId.Beta, // default, may be overwritten nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', + rpc: 'http://localhost:8545', agent_id: 14, threshold: 1, use_staking: true, + use_mech_marketplace: true, cost_of_bond: 10000000000000000, monthly_gas_estimate: 10000000000000000000, fund_requirements: { diff --git a/operate/services/service.py b/operate/services/service.py index 186b2c675..d388c82ca 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -492,6 +492,16 @@ def _build_docker( deployment["services"][node]["environment"].append( "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=10000000000000000" ) + if ( + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE=False" + in deployment["services"][node]["environment"] + ): + deployment["services"][node]["environment"].remove( + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE=False" + ) + deployment["services"][node]["environment"].append( + f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE={str(home_chain_data.user_params.use_mech_marketplace).capitalize()}" + ) with (build / DOCKER_COMPOSE_YAML).open("w", encoding="utf-8") as stream: yaml_dump(data=deployment, stream=stream) @@ -584,10 +594,17 @@ def _build_host(self, force: bool = True, chain_id: str = "100") -> None: agent_vars[ "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE" ] = "10000000000000000" - Path(build, "agent.json").write_text( - json.dumps(agent_vars, indent=4), - encoding="utf-8", - ) + + # Mech marketplace patch. + if "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE" in agent_vars: + agent_vars[ + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE" + ] = str(chain_data.user_params.use_mech_marketplace).capitalize() + + Path(build, "agent.json").write_text( + json.dumps(agent_vars, indent=4), + encoding="utf-8", + ) self.status = DeploymentStatus.BUILT self.store() diff --git a/operate/types.py b/operate/types.py index 7360db461..81efd7218 100644 --- a/operate/types.py +++ b/operate/types.py @@ -187,6 +187,7 @@ class ConfigurationTemplate(TypedDict): rpc: str threshold: int use_staking: bool + use_mech_marketplace: bool cost_of_bond: int fund_requirements: FundRequirementsTemplate @@ -230,6 +231,7 @@ class OnChainUserParams(LocalResource): nft: str threshold: int use_staking: bool + use_mech_marketplace: bool cost_of_bond: int fund_requirements: OnChainFundRequirements diff --git a/templates/trader.yaml b/templates/trader.yaml index 85289cd3c..2e7b3b925 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -1,8 +1,8 @@ name: "Trader Agent" description: "A single-agent service (sovereign agent) placing bets on Omen" -hash: bafybeicbfnqfc3potbfmvrmssaxepwilipe5myjbg4xh7ix2sdll4kyc6m +hash: bafybeidts6y6wytfcwlhnvnacf3vhm6lkiocoe22kkmxxx2onzguez3y3q image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 -service_version: v0.18.1 +service_version: v0.18.2 home_chain_id: 100 configurations: 100: @@ -11,6 +11,7 @@ configurations: 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: From 626268fa8f70ff1756f1849fe4889e2456453f13 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 24 Oct 2024 09:47:12 +0100 Subject: [PATCH 05/43] feat: use_mech_marketplace flag added to `createService()` commented unused middleware queries --- .../MainPage/header/AgentButton.tsx | 9 +- .../StakingContractSection/MigrateButton.tsx | 2 + frontend/service/Services.ts | 126 ++++++++---------- 3 files changed, 68 insertions(+), 69 deletions(-) diff --git a/frontend/components/MainPage/header/AgentButton.tsx b/frontend/components/MainPage/header/AgentButton.tsx index 0beac0ac8..06b82c34c 100644 --- a/frontend/components/MainPage/header/AgentButton.tsx +++ b/frontend/components/MainPage/header/AgentButton.tsx @@ -4,6 +4,7 @@ import { useCallback, useMemo } from 'react'; import { Chain, DeploymentStatus } from '@/client'; import { COLOR } from '@/constants/colors'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { useBalance } from '@/hooks/useBalance'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useReward } from '@/hooks/useReward'; @@ -179,6 +180,10 @@ const AgentNotRunningButton = () => { // Mock "DEPLOYING" status (service polling will update this once resumed) setServiceStatus(DeploymentStatus.DEPLOYING); + // Get the active staking program id; default id if there's no agent yet + const stakingProgramId: StakingProgramId = + activeStakingProgramId ?? defaultStakingProgramId; + // Create master safe if it doesn't exist try { if (!masterSafeAddress) { @@ -197,9 +202,11 @@ const AgentNotRunningButton = () => { // Then create / deploy the service try { await ServicesService.createService({ - stakingProgramId: activeStakingProgramId ?? defaultStakingProgramId, // overwrite with StakingProgram.Alpha to test migration + stakingProgramId, serviceTemplate, deploy: true, + useMechMarketplace: + stakingProgramId === StakingProgramId.BetaMechMarketplace, }); } catch (error) { console.error(error); diff --git a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx index 5d1c33473..4b5eea00d 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx @@ -69,6 +69,8 @@ export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { stakingProgramId, serviceTemplate, deploy: true, + useMechMarketplace: + stakingProgramId === StakingProgramId.BetaMechMarketplace, }); await updateStakingProgram(); diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index a50959747..c9fb95a8d 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -47,10 +47,12 @@ const createService = async ({ deploy, serviceTemplate, stakingProgramId, + useMechMarketplace = false, }: { deploy: boolean; serviceTemplate: ServiceTemplate; stakingProgramId: StakingProgramId; + useMechMarketplace?: boolean; }): Promise => new Promise((resolve, reject) => fetch(`${BACKEND_URL}/services`, { @@ -63,6 +65,7 @@ const createService = async ({ ...serviceTemplate.configurations[100], staking_program_id: stakingProgramId, rpc: `${process.env.GNOSIS_RPC}`, + use_mech_marketplace: useMechMarketplace, }, }, }), @@ -77,57 +80,44 @@ const createService = async ({ }), ); -const deployOnChain = async (serviceHash: ServiceHash): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}/onchain/deploy`, { - method: 'POST', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, - }).then((response) => { - if (response.ok) { - return response.json(); - } - throw new Error('Failed to deploy service on chain'); - }); +// const deployOnChain = async (serviceHash: ServiceHash): Promise => +// fetch(`${BACKEND_URL}/services/${serviceHash}/onchain/deploy`, { +// method: 'POST', +// headers: { +// ...CONTENT_TYPE_JSON_UTF8, +// }, +// }).then((response) => { +// if (response.ok) { +// return response.json(); +// } +// throw new Error('Failed to deploy service on chain'); +// }); -const stopOnChain = async (serviceHash: ServiceHash): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}/onchain/stop`, { - method: 'POST', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, - }).then((response) => { - if (response.ok) { - return response.json(); - } - throw new Error('Failed to stop service on chain'); - }); - -const buildDeployment = async (serviceHash: ServiceHash): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/build`, { - method: 'POST', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, - }).then((response) => { - if (response.ok) { - return response.json(); - } - throw new Error('Failed to build deployment'); - }); +// const buildDeployment = async (serviceHash: ServiceHash): Promise => +// fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/build`, { +// method: 'POST', +// headers: { +// ...CONTENT_TYPE_JSON_UTF8, +// }, +// }).then((response) => { +// if (response.ok) { +// return response.json(); +// } +// throw new Error('Failed to build deployment'); +// }); -const startDeployment = async (serviceHash: ServiceHash): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/start`, { - method: 'POST', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, - }).then((response) => { - if (response.ok) { - return response.json(); - } - throw new Error('Failed to start deployment'); - }); +// const startDeployment = async (serviceHash: ServiceHash): Promise => +// fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/start`, { +// method: 'POST', +// headers: { +// ...CONTENT_TYPE_JSON_UTF8, +// }, +// }).then((response) => { +// if (response.ok) { +// return response.json(); +// } +// throw new Error('Failed to start deployment'); +// }); const stopDeployment = async (serviceHash: ServiceHash): Promise => fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/stop`, { @@ -142,20 +132,20 @@ const stopDeployment = async (serviceHash: ServiceHash): Promise => throw new Error('Failed to stop deployment'); }); -const deleteDeployment = async ( - serviceHash: ServiceHash, -): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/delete`, { - method: 'POST', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, - }).then((response) => { - if (response.ok) { - return response.json(); - } - throw new Error('Failed to delete deployment'); - }); +// const deleteDeployment = async ( +// serviceHash: ServiceHash, +// ): Promise => +// fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/delete`, { +// method: 'POST', +// headers: { +// ...CONTENT_TYPE_JSON_UTF8, +// }, +// }).then((response) => { +// if (response.ok) { +// return response.json(); +// } +// throw new Error('Failed to delete deployment'); +// }); const getDeployment = async (serviceHash: ServiceHash): Promise => fetch(`${BACKEND_URL}/services/${serviceHash}/deployment`, { @@ -175,10 +165,10 @@ export const ServicesService = { getServices, getDeployment, createService, - deployOnChain, - stopOnChain, - buildDeployment, - startDeployment, + // deployOnChain, + // stopOnChain, + // buildDeployment, + // startDeployment, stopDeployment, - deleteDeployment, + // deleteDeployment, }; From 39a8836d0afa5a5cbe521fe9b4f6fbb5c5518ea8 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 24 Oct 2024 13:12:58 +0200 Subject: [PATCH 06/43] chore: fix variables --- operate/services/service.py | 81 +++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/operate/services/service.py b/operate/services/service.py index d388c82ca..0a280425b 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -67,6 +67,7 @@ ) from operate.http.exceptions import NotAllowed from operate.keys import Keys +from operate.ledger.profiles import STAKING from operate.resource import LocalResource from operate.services.deployment_runner import run_host_deployment, stop_host_deployment from operate.services.utils import tendermint @@ -482,26 +483,34 @@ def _build_docker( for node in deployment["services"]: if "abci" in node: deployment["services"][node]["volumes"].extend(_volumes) - if ( - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=0" - in deployment["services"][node]["environment"] - ): - deployment["services"][node]["environment"].remove( - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=0" - ) - deployment["services"][node]["environment"].append( - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=10000000000000000" - ) - if ( - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE=False" - in deployment["services"][node]["environment"] - ): - deployment["services"][node]["environment"].remove( - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE=False" - ) - deployment["services"][node]["environment"].append( - f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE={str(home_chain_data.user_params.use_mech_marketplace).capitalize()}" - ) + + # Patch - update variables + + # TODO Possibly a best way to do this is within the method + # 'ServiceManager.deploy_service_locally' and set the variables + # as environment variables. Note that part of the variables of the agent + # are already set using 'os.environ' on the ServiceManager, and are + # thus set up 'by coincidence' here. + # See also method '_build_host' below. + + user_params = home_chain_data.user_params + staking_contract = STAKING[home_chain_ledger_config.chain][user_params.staking_program_id] + + env_var_updates = { + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=0": + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=10000000000000000", + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE=False": + f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE={str(home_chain_data.user_params.use_mech_marketplace).capitalize()}", + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS=0x0000000000000000000000000000000000000000": + f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS={staking_contract}", + } + + for old_value, new_value in env_var_updates.items(): + if old_value in deployment["services"][node]["environment"]: + deployment["services"][node]["environment"].remove(old_value) + deployment["services"][node]["environment"].append(new_value) + + # End patch with (build / DOCKER_COMPOSE_YAML).open("w", encoding="utf-8") as stream: yaml_dump(data=deployment, stream=stream) @@ -588,23 +597,35 @@ def _build_host(self, force: bool = True, chain_id: str = "100") -> None: shutil.rmtree(build) raise e - # Mech price patch. + # Patch - update variables + + # TODO Possibly a best way to do this is within the method + # 'ServiceManager.deploy_service_locally' and set the variables + # as environment variables. Note that part of the variables of the agent + # are already set using 'os.environ' on the ServiceManager, and are + # thus set up 'by coincidence' here. + # See also method '_build_docker' above. agent_vars = json.loads(Path(build, "agent.json").read_text(encoding="utf-8")) - if "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE" in agent_vars: - agent_vars[ - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE" - ] = "10000000000000000" - # Mech marketplace patch. - if "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE" in agent_vars: - agent_vars[ - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE" - ] = str(chain_data.user_params.use_mech_marketplace).capitalize() + user_params = chain_data.user_params + staking_contract = STAKING[ledger_config.chain][user_params.staking_program_id] + + # Mech price patch, mech marketplace patch + agent_var_updates = { + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE": "10000000000000000", + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE": str(chain_data.user_params.use_mech_marketplace).capitalize(), + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS": staking_contract + } + + for key, value in agent_var_updates.items(): + if key in agent_vars: + agent_vars[key] = value Path(build, "agent.json").write_text( json.dumps(agent_vars, indent=4), encoding="utf-8", ) + # End patch self.status = DeploymentStatus.BUILT self.store() From 32550ec3d5f0f23747b0289b50b833b33b75b104 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 24 Oct 2024 15:17:43 +0200 Subject: [PATCH 07/43] fix: linters --- operate/services/service.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/operate/services/service.py b/operate/services/service.py index 0a280425b..5811b492d 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -494,15 +494,14 @@ def _build_docker( # See also method '_build_host' below. user_params = home_chain_data.user_params - staking_contract = STAKING[home_chain_ledger_config.chain][user_params.staking_program_id] + staking_contract = STAKING[home_chain_ledger_config.chain][ + user_params.staking_program_id + ] env_var_updates = { - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=0": - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=10000000000000000", - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE=False": - f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE={str(home_chain_data.user_params.use_mech_marketplace).capitalize()}", - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS=0x0000000000000000000000000000000000000000": - f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS={staking_contract}", + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=0": "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE=10000000000000000", + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE=False": f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE={str(home_chain_data.user_params.use_mech_marketplace).capitalize()}", + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS=0x0000000000000000000000000000000000000000": f"SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS={staking_contract}", } for old_value, new_value in env_var_updates.items(): @@ -613,8 +612,10 @@ def _build_host(self, force: bool = True, chain_id: str = "100") -> None: # Mech price patch, mech marketplace patch agent_var_updates = { "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_REQUEST_PRICE": "10000000000000000", - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE": str(chain_data.user_params.use_mech_marketplace).capitalize(), - "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS": staking_contract + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_USE_MECH_MARKETPLACE": str( + chain_data.user_params.use_mech_marketplace + ).capitalize(), + "SKILL_TRADER_ABCI_MODELS_PARAMS_ARGS_MECH_MARKETPLACE_CONFIG_REQUESTER_STAKING_INSTANCE_ADDRESS": staking_contract, } for key, value in agent_var_updates.items(): From 8c644e99380365e080d2ad91d3002e835592b940 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 24 Oct 2024 15:27:20 +0200 Subject: [PATCH 08/43] fix: linters --- operate/services/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operate/services/service.py b/operate/services/service.py index 5811b492d..c82cfc9c2 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -88,7 +88,7 @@ ) -# pylint: disable=no-member,redefined-builtin,too-many-instance-attributes +# pylint: disable=no-member,redefined-builtin,too-many-instance-attributes,too-many-locals SAFE_CONTRACT_ADDRESS = "safe_contract_address" ALL_PARTICIPANTS = "all_participants" From ff1397b808a170be70e0a957eaee401dd01a2524 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 24 Oct 2024 16:19:02 +0200 Subject: [PATCH 09/43] chore: update hashes --- frontend/constants/serviceTemplates.ts | 2 +- templates/trader.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index 573a11381..17648adfa 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -4,7 +4,7 @@ import { StakingProgramId } from '@/enums/StakingProgram'; export const SERVICE_TEMPLATES: ServiceTemplate[] = [ { name: 'Trader Agent', - hash: 'bafybeidts6y6wytfcwlhnvnacf3vhm6lkiocoe22kkmxxx2onzguez3y3q', + hash: 'bafybeidycvtsy5m3nvpromqksegwdd4f4dvak4pzln3de7ozehigp72xba', // hash: 'bafybeibbloa4w33vj4bvdkso7pzk6tr3duvxjpecbx4mur4ix6ehnwb5uu', // temporary description: 'Trader agent for omen prediction markets', image: diff --git a/templates/trader.yaml b/templates/trader.yaml index 2e7b3b925..a49c3278f 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -1,6 +1,6 @@ name: "Trader Agent" description: "A single-agent service (sovereign agent) placing bets on Omen" -hash: bafybeidts6y6wytfcwlhnvnacf3vhm6lkiocoe22kkmxxx2onzguez3y3q +hash: bafybeidycvtsy5m3nvpromqksegwdd4f4dvak4pzln3de7ozehigp72xba image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 service_version: v0.18.2 home_chain_id: 100 From 174ec086582f4ec4d51cfd1a836b8238dc6b97e0 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 24 Oct 2024 17:28:56 +0200 Subject: [PATCH 10/43] chore: update hash --- frontend/constants/serviceTemplates.ts | 4 ++-- templates/trader.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index 17648adfa..0fac40ac1 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -4,12 +4,12 @@ import { StakingProgramId } from '@/enums/StakingProgram'; export const SERVICE_TEMPLATES: ServiceTemplate[] = [ { name: 'Trader Agent', - hash: 'bafybeidycvtsy5m3nvpromqksegwdd4f4dvak4pzln3de7ozehigp72xba', + hash: 'bafybeidsdziadn7hpzvmthrudvezkblq2wvotpqhla36tgxnwb4hhwrwxi', // hash: 'bafybeibbloa4w33vj4bvdkso7pzk6tr3duvxjpecbx4mur4ix6ehnwb5uu', // temporary description: 'Trader agent for omen prediction markets', image: 'https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75', - service_version: 'v0.18.2', + service_version: 'v0.18.3', home_chain_id: '100', configurations: { 100: { diff --git a/templates/trader.yaml b/templates/trader.yaml index a49c3278f..feb3d647e 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -1,8 +1,8 @@ name: "Trader Agent" description: "A single-agent service (sovereign agent) placing bets on Omen" -hash: bafybeidycvtsy5m3nvpromqksegwdd4f4dvak4pzln3de7ozehigp72xba +hash: bafybeidsdziadn7hpzvmthrudvezkblq2wvotpqhla36tgxnwb4hhwrwxi image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 -service_version: v0.18.2 +service_version: v0.18.3 home_chain_id: 100 configurations: 100: From a4174817469c95c30483a6aefe99f1d78acf58da Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 24 Oct 2024 16:42:31 +0100 Subject: [PATCH 11/43] feat: mech marketplace funding reqs --- frontend/utils/service.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/utils/service.ts b/frontend/utils/service.ts index e9720408f..cdecb71f9 100644 --- a/frontend/utils/service.ts +++ b/frontend/utils/service.ts @@ -18,5 +18,9 @@ export const getMinimumStakedAmountRequired = ( return 100; } + if (stakingProgramId === StakingProgramId.BetaMechMarketplace) { + return 40; + } + return; }; From e643111be83eacae1980711cf43aa670ce4db060 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 24 Oct 2024 16:44:10 +0100 Subject: [PATCH 12/43] chore: rename safe to masterSafe, confusing --- frontend/components/MainPage/header/AgentButton.tsx | 2 +- .../StakingContractSection/CantMigrateAlert.tsx | 2 +- .../components/SettingsPage/AddBackupWalletPage.tsx | 2 +- .../components/SetupPage/Create/SetupEoaFunding.tsx | 2 +- frontend/components/SetupPage/SetupWelcome.tsx | 2 +- frontend/components/YourWalletPage/YourWallet.tsx | 7 ++++--- frontend/context/BalanceProvider.tsx | 12 ++++++------ frontend/hooks/useNeedsFunds.ts | 2 +- 8 files changed, 16 insertions(+), 15 deletions(-) diff --git a/frontend/components/MainPage/header/AgentButton.tsx b/frontend/components/MainPage/header/AgentButton.tsx index 06b82c34c..f2f765110 100644 --- a/frontend/components/MainPage/header/AgentButton.tsx +++ b/frontend/components/MainPage/header/AgentButton.tsx @@ -133,7 +133,7 @@ const AgentNotRunningButton = () => { const { showNotification } = useElectronApi(); const { setIsPaused: setIsBalancePollingPaused, - safeBalance, + masterSafeBalance: safeBalance, isLowBalance, totalOlasStakedBalance, totalEthBalance, diff --git a/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx b/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx index 52b23737c..f848272a5 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx @@ -19,7 +19,7 @@ const AlertInsufficientMigrationFunds = ({ }: CantMigrateAlertProps) => { const { serviceTemplate } = useServiceTemplates(); const { isServiceStaked } = useStakingContractInfo(); - const { safeBalance, totalOlasStakedBalance } = useBalance(); + const { masterSafeBalance: safeBalance, totalOlasStakedBalance } = useBalance(); const totalOlasRequiredForStaking = getMinimumStakedAmountRequired( serviceTemplate, diff --git a/frontend/components/SettingsPage/AddBackupWalletPage.tsx b/frontend/components/SettingsPage/AddBackupWalletPage.tsx index 02e66d57f..de2355ba6 100644 --- a/frontend/components/SettingsPage/AddBackupWalletPage.tsx +++ b/frontend/components/SettingsPage/AddBackupWalletPage.tsx @@ -12,7 +12,7 @@ import { CardTitle } from '../Card/CardTitle'; import { CardFlex } from '../styled/CardFlex'; export const AddBackupWalletPage = () => { - const { eoaBalance } = useBalance(); + const { masterEoaBalance: eoaBalance } = useBalance(); const { goto } = useSettings(); const [form] = Form.useForm(); diff --git a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx index 3cf6eae60..244dfdcb9 100644 --- a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx +++ b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx @@ -34,7 +34,7 @@ export const SetupEoaFunding = ({ }: { isIncomplete?: boolean; }) => { - const { eoaBalance } = useBalance(); + const { masterEoaBalance: eoaBalance } = useBalance(); const { goto } = useSetup(); const isFundedMasterEoa = diff --git a/frontend/components/SetupPage/SetupWelcome.tsx b/frontend/components/SetupPage/SetupWelcome.tsx index 9d3c3b3d8..0ff6812ca 100644 --- a/frontend/components/SetupPage/SetupWelcome.tsx +++ b/frontend/components/SetupPage/SetupWelcome.tsx @@ -130,7 +130,7 @@ export const SetupWelcomeLogin = () => { const { goto: gotoPage } = usePageState(); const { masterSafeAddress, wallets } = useWallet(); - const { isBalanceLoaded, eoaBalance } = useBalance(); + const { isBalanceLoaded, masterEoaBalance: eoaBalance } = useBalance(); const [isLoggingIn, setIsLoggingIn] = useState(false); const [canNavigate, setCanNavigate] = useState(false); diff --git a/frontend/components/YourWalletPage/YourWallet.tsx b/frontend/components/YourWalletPage/YourWallet.tsx index d00583b86..9db2906e7 100644 --- a/frontend/components/YourWalletPage/YourWallet.tsx +++ b/frontend/components/YourWalletPage/YourWallet.tsx @@ -54,7 +54,8 @@ const Address = () => { }; const OlasBalance = () => { - const { safeBalance, totalOlasStakedBalance } = useBalance(); + const { masterSafeBalance: safeBalance, totalOlasStakedBalance } = + useBalance(); const olasBalances = useMemo(() => { return [ { @@ -84,7 +85,7 @@ const OlasBalance = () => { }; const XdaiBalance = () => { - const { safeBalance } = useBalance(); + const { masterSafeBalance: safeBalance } = useBalance(); return ( @@ -104,7 +105,7 @@ const XdaiBalance = () => { const Signer = () => { const { masterEoaAddress } = useWallet(); - const { eoaBalance } = useBalance(); + const { masterEoaBalance: eoaBalance } = useBalance(); return ( diff --git a/frontend/context/BalanceProvider.tsx b/frontend/context/BalanceProvider.tsx index b53985023..7e218f199 100644 --- a/frontend/context/BalanceProvider.tsx +++ b/frontend/context/BalanceProvider.tsx @@ -44,8 +44,8 @@ export const BalanceContext = createContext<{ isBalanceLoaded: boolean; olasBondBalance?: number; olasDepositBalance?: number; - eoaBalance?: ValueOf; - safeBalance?: ValueOf; + masterEoaBalance?: ValueOf; + masterSafeBalance?: ValueOf; totalEthBalance?: number; totalOlasBalance?: number; isLowBalance: boolean; @@ -62,8 +62,8 @@ export const BalanceContext = createContext<{ isBalanceLoaded: false, olasBondBalance: undefined, olasDepositBalance: undefined, - eoaBalance: undefined, - safeBalance: undefined, + masterEoaBalance: undefined, + masterSafeBalance: undefined, totalEthBalance: undefined, totalOlasBalance: undefined, isLowBalance: false, @@ -256,8 +256,8 @@ export const BalanceProvider = ({ children }: PropsWithChildren) => { isBalanceLoaded, olasBondBalance, olasDepositBalance, - eoaBalance, - safeBalance, + masterEoaBalance: eoaBalance, + masterSafeBalance: safeBalance, totalEthBalance, totalOlasBalance, isLowBalance, diff --git a/frontend/hooks/useNeedsFunds.ts b/frontend/hooks/useNeedsFunds.ts index f99e909a9..9448d9fda 100644 --- a/frontend/hooks/useNeedsFunds.ts +++ b/frontend/hooks/useNeedsFunds.ts @@ -17,7 +17,7 @@ export const useNeedsFunds = () => { ); const { storeState } = useStore(); - const { isBalanceLoaded, safeBalance, totalOlasStakedBalance } = useBalance(); + const { isBalanceLoaded, masterSafeBalance: safeBalance, totalOlasStakedBalance } = useBalance(); const serviceFundRequirements = useMemo(() => { const gasEstimate = From 694d3b7f6b9a13667b8df96deb892c160e427b60 Mon Sep 17 00:00:00 2001 From: truemiller Date: Thu, 24 Oct 2024 16:44:29 +0100 Subject: [PATCH 13/43] fix: refactor migration to support initial deployment/switch --- .../StakingContractSection/MigrateButton.tsx | 34 +++++-- .../StakingContractSection/useMigrate.tsx | 91 +++++++++++++++++-- 2 files changed, 107 insertions(+), 18 deletions(-) diff --git a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx index 4b5eea00d..3bc2a0f13 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx @@ -23,22 +23,37 @@ type MigrateButtonProps = { export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { const { goto } = usePageState(); const { serviceTemplate } = useServiceTemplates(); - const { setIsServicePollingPaused, setServiceStatus, updateServiceStatus } = - useServices(); + const { + setIsServicePollingPaused, + setServiceStatus, + updateServiceStatus, + hasInitialLoaded: isServicesLoaded, + service, + } = useServices(); const { setIsPaused: setIsBalancePollingPaused } = useBalance(); const { updateActiveStakingProgramId: updateStakingProgram } = useStakingProgram(); const { activeStakingContractInfo } = useStakingContractInfo(); const { setMigrationModalOpen } = useModals(); - const { migrateValidation } = useMigrate(stakingProgramId); + const { migrateValidation, firstDeployValidation } = + useMigrate(stakingProgramId); + + // if false, user is migrating, not running for first time + const isFirstDeploy = useMemo(() => { + if (!isServicesLoaded) return false; + if (service) return false; + + return true; + }, [isServicesLoaded, service]); + + const validation = isFirstDeploy ? firstDeployValidation : migrateValidation; const popoverContent = useMemo(() => { - if (migrateValidation.canMigrate) return null; + if (validation.canMigrate) return null; if ( - migrateValidation.reason === - CantMigrateReason.NotStakedForMinimumDuration && + validation.reason === CantMigrateReason.NotStakedForMinimumDuration && !isNil(activeStakingContractInfo) ) { return ( @@ -48,21 +63,22 @@ export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { ); } - return migrateValidation.reason; - }, [activeStakingContractInfo, migrateValidation]); + return validation.reason; + }, [activeStakingContractInfo, validation]); return (