From 754ae12b8368d8bdf4f0a93a652cce14c2e969eb Mon Sep 17 00:00:00 2001 From: Mihaela-Ioana Mot <32430018+mmioana@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:30:26 +0100 Subject: [PATCH] Feat: Add create event details to colony model Feat: Add create event details to colony model --- .../src/handlers/colonies/colonyAdded.ts | 11 +++++- .../colonies/helpers/createUniqueColony.ts | 7 ++-- apps/main-chain/src/utils/colony.ts | 37 +++++++++++++++++++ packages/blocks/src/events/eventManager.ts | 4 ++ packages/blocks/src/events/types.ts | 3 ++ packages/graphql/src/generated.ts | 24 ++++++++---- 6 files changed, 75 insertions(+), 11 deletions(-) diff --git a/apps/main-chain/src/handlers/colonies/colonyAdded.ts b/apps/main-chain/src/handlers/colonies/colonyAdded.ts index ce673e55..df65536f 100644 --- a/apps/main-chain/src/handlers/colonies/colonyAdded.ts +++ b/apps/main-chain/src/handlers/colonies/colonyAdded.ts @@ -19,6 +19,7 @@ import { getColonyContributorId } from '~utils/contributors'; import { tryFetchGraphqlQuery } from '~utils/graphql'; import { createUniqueColony } from './helpers/createUniqueColony'; import { output } from '@joincolony/utils'; +import { getCreateSaltEventFromTransaction } from '~utils/colony'; export default async (event: ContractEvent): Promise => { const { transactionHash, args, blockNumber } = event; @@ -77,6 +78,11 @@ export default async (event: ContractEvent): Promise => { args: { user: '' }, }; + const createSaltEvent = await getCreateSaltEventFromTransaction( + blockNumber, + colonyAddress, + ); + try { /* * Create the colony entry in the database @@ -86,7 +92,10 @@ export default async (event: ContractEvent): Promise => { tokenAddress: utils.getAddress(tokenAddress), transactionHash, initiatorAddress: utils.getAddress(colonyFounderAddress), - createdAtBlock: blockNumber, + colonyCreateEvent: { + blockNumber, + salt: createSaltEvent?.args?.salt, + }, }); } catch (error) { console.error(error); diff --git a/apps/main-chain/src/handlers/colonies/helpers/createUniqueColony.ts b/apps/main-chain/src/handlers/colonies/helpers/createUniqueColony.ts index ccd38b39..96e0d681 100644 --- a/apps/main-chain/src/handlers/colonies/helpers/createUniqueColony.ts +++ b/apps/main-chain/src/handlers/colonies/helpers/createUniqueColony.ts @@ -38,6 +38,7 @@ import { GetTokenFromEverywhereDocument, GetTokenFromEverywhereQuery, GetTokenFromEverywhereQueryVariables, + ColonyCreateEvent, } from '@joincolony/graphql'; import rpcProvider from '~provider'; import { getCachedColonyClient } from '~utils/clients/colony'; @@ -47,13 +48,13 @@ export const createUniqueColony = async ({ tokenAddress, transactionHash, initiatorAddress, - createdAtBlock, + colonyCreateEvent, }: { colonyAddress: string; tokenAddress: string; transactionHash: string; initiatorAddress: string; - createdAtBlock: number; + colonyCreateEvent: ColonyCreateEvent; }): Promise => { /* * Validate Colony and Token addresses @@ -217,7 +218,7 @@ export const createUniqueColony = async ({ chainMetadata: { chainId, }, - createdAtBlock, + colonyCreateEvent, version: version.toNumber(), status: { nativeToken: { diff --git a/apps/main-chain/src/utils/colony.ts b/apps/main-chain/src/utils/colony.ts index bc7de3a3..ecb3998d 100644 --- a/apps/main-chain/src/utils/colony.ts +++ b/apps/main-chain/src/utils/colony.ts @@ -5,8 +5,16 @@ import { ListColoniesWithRootPermissionHoldersQuery, ListColoniesWithRootPermissionHoldersQueryVariables, } from '@joincolony/graphql'; +import { + ContractCreateSaltEvents, + ContractEvent, + ContractEventsSignatures, +} from '@joincolony/blocks'; import { notNull } from './arrays'; import { getAllPagesOfData, GetDataFn } from './graphql'; +import { mapLogToContractEvent } from './events'; +import rpcProvider from '~provider'; +import { utils } from 'ethers'; const getColoniesData: GetDataFn< ColonyWithRootRolesFragment, @@ -29,3 +37,32 @@ export const getAllColoniesWithRootPermissionHolders = async (): Promise< return allColonies.filter(notNull); }; + +export const getCreateSaltEventFromTransaction = async ( + blockNumber: number, + colonyAddress: string, +): Promise => { + const createSaltLogs = await rpcProvider.getProviderInstance().getLogs({ + fromBlock: blockNumber, + toBlock: blockNumber, + topics: [utils.id(ContractEventsSignatures.Create3ProxyContractCreation)], + }); + + if (createSaltLogs.length === 0) { + console.error( + `Couldn't fetch colony salt creation event for colonyAddress: ${colonyAddress}`, + ); + return; + } + + const event = await mapLogToContractEvent( + createSaltLogs[0], + ContractCreateSaltEvents, + ); + + /* + * Typecasting since apparently TS doesn't realize we are actually filtering + * to ensure that the Array only contains proper events + */ + return event as ContractEvent; +}; diff --git a/packages/blocks/src/events/eventManager.ts b/packages/blocks/src/events/eventManager.ts index 1b231994..55e518e0 100644 --- a/packages/blocks/src/events/eventManager.ts +++ b/packages/blocks/src/events/eventManager.ts @@ -24,6 +24,10 @@ export const ProxyColonyEvents = new utils.Interface([ 'event LogMessagePublished(address indexed sender,uint64 sequence,uint32 nonce,bytes payload,uint8 consistencyLevel)', ]); +export const ContractCreateSaltEvents = new utils.Interface([ + `event Create3ProxyContractCreation(address indexed newContract, bytes32 indexed salt)`, +]); + export class EventManager { private listeners: EventListener[] = []; private readonly rpcProvider: RpcProvider; diff --git a/packages/blocks/src/events/types.ts b/packages/blocks/src/events/types.ts index ace81805..f1b12b1c 100644 --- a/packages/blocks/src/events/types.ts +++ b/packages/blocks/src/events/types.ts @@ -110,6 +110,9 @@ export enum ContractEventsSignatures { ProxyColonyDeployed = 'ProxyColonyDeployed(address)', LogMessagePublished = 'LogMessagePublished(address,uint64,uint32,bytes,uint8)', WormholeMessageReceived = 'WormholeMessageReceived(uint16,bytes32,uint64)', + + // Contract create events + Create3ProxyContractCreation = 'Create3ProxyContractCreation(address,bytes32)', } /* diff --git a/packages/graphql/src/generated.ts b/packages/graphql/src/generated.ts index 1c922b5d..0798d58f 100644 --- a/packages/graphql/src/generated.ts +++ b/packages/graphql/src/generated.ts @@ -301,6 +301,8 @@ export type Colony = { chainFundsClaim?: Maybe; /** Metadata related to the chain of the Colony */ chainMetadata: ChainMetadata; + /** Colony creation data */ + colonyCreateEvent?: Maybe; /** * The main member invite object * It is possible to create multiple member invites for a given colony @@ -310,8 +312,6 @@ export type Colony = { /** ID of the main member invite object */ colonyMemberInviteCode?: Maybe; createdAt: Scalars['AWSDateTime']; - /** The block number the colony was created attached */ - createdAtBlock?: Maybe; domains?: Maybe; expenditures?: Maybe; /** Global claim delay for expenditures (in seconds) */ @@ -835,6 +835,19 @@ export type ColonyContributorRolesArgs = { sortDirection?: InputMaybe; }; +export type ColonyCreateEvent = { + __typename?: 'ColonyCreateEvent'; + /** The block number the colony was created at */ + blockNumber: Scalars['Int']; + /** The address that signed the transaction */ + salt: Scalars['String']; +}; + +export type ColonyCreateEventInput = { + blockNumber: Scalars['Int']; + salt: Scalars['String']; +}; + export type ColonyDecision = { __typename?: 'ColonyDecision'; action?: Maybe; @@ -1542,8 +1555,8 @@ export type CreateColonyInput = { balances?: InputMaybe; chainFundsClaim?: InputMaybe; chainMetadata: ChainMetadataInput; + colonyCreateEvent?: InputMaybe; colonyMemberInviteCode?: InputMaybe; - createdAtBlock?: InputMaybe; expendituresGlobalClaimDelay?: InputMaybe; id?: InputMaybe; lastUpdatedContributorsWithReputation?: InputMaybe; @@ -2983,7 +2996,6 @@ export type ModelColonyActionTypeInput = { export type ModelColonyConditionInput = { and?: InputMaybe>>; colonyMemberInviteCode?: InputMaybe; - createdAtBlock?: InputMaybe; expendituresGlobalClaimDelay?: InputMaybe; lastUpdatedContributorsWithReputation?: InputMaybe; name?: InputMaybe; @@ -3110,7 +3122,6 @@ export type ModelColonyExtensionFilterInput = { export type ModelColonyFilterInput = { and?: InputMaybe>>; colonyMemberInviteCode?: InputMaybe; - createdAtBlock?: InputMaybe; expendituresGlobalClaimDelay?: InputMaybe; id?: InputMaybe; lastUpdatedContributorsWithReputation?: InputMaybe; @@ -4369,7 +4380,6 @@ export type ModelSubscriptionColonyExtensionFilterInput = { export type ModelSubscriptionColonyFilterInput = { and?: InputMaybe>>; colonyMemberInviteCode?: InputMaybe; - createdAtBlock?: InputMaybe; expendituresGlobalClaimDelay?: InputMaybe; id?: InputMaybe; lastUpdatedContributorsWithReputation?: InputMaybe; @@ -9447,8 +9457,8 @@ export type UpdateColonyInput = { balances?: InputMaybe; chainFundsClaim?: InputMaybe; chainMetadata?: InputMaybe; + colonyCreateEvent?: InputMaybe; colonyMemberInviteCode?: InputMaybe; - createdAtBlock?: InputMaybe; expendituresGlobalClaimDelay?: InputMaybe; id: Scalars['ID']; lastUpdatedContributorsWithReputation?: InputMaybe;