Dynamically Create Contract Event Sync

I have a factory contract that instantiates other contracts. Since the address of the newly created contract is not know ahead of time, I can’t setup a “Sync and Watch Contract Events” using the Moralis admin panel. My question is: could this be done dynamically after the contract is created?

I was looking at the cloud functions and came across the “watchContractEvent” cloud function. Would it possible to create a cloud function that is passed the address of the new contract and then this cloud function would call “watchContractEvent” to setup the sync? I have not seen examples in the documentation with one cloud function calling another.

My thought is that once the factory is called and the new contract is created, we take its address and then call the custom cloud function passing the address as a parameter.

Looking for validation of this approach. If it is not feasible, what other approach can be taken to achieve this?

Thanks.

Hey @DeveloperMarwan

If your factory contract has an Event for new contracts created you can listen to it.

You can do this programmatically directly from your cloud code https://docs.moralis.io/moralis-server/automatic-transaction-sync/smart-contract-events#watch-new-smart-contract-event

All you need is to setup afterSave trigger in factory table events which will be triggered after “new contract created”

Hope this helps! Happy BUIDLing :man_mechanic:

1 Like

Thank you @Yomoo for your reply.

I have an event sync already setup on the factory contract so that when a new contract is instantiated, the event is emitted. This is working as expected.

I then setup a trigger as per your suggestion on the event table from the above. Below is the code I did for this in “Cloud Functions”:

Moralis.Cloud.afterSave("GovernorCreatedEvents", (request) => {
  const logger = Moralis.Cloud.getLogger();
  logger.info("----> GovernorCreatedEvents.afterSave - START");
  const govAddress = request.object.get("govAddress");
  logger.info("----> govAddress: " + govAddress);
  
  let options = {
    "chainId": "0xA869",
    "address": govAddress,
    "topic": "ProposalCreated(address, uint256, address, address[], uint[], string[], bytes[], uint256, uint256, string)",
    "abi":   {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "govAddress",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "proposalId",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "proposer",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address[]",
          "name": "targets",
          "type": "address[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "values",
          "type": "uint256[]"
        },
        {
          "indexed": false,
          "internalType": "string[]",
          "name": "signatures",
          "type": "string[]"
        },
        {
          "indexed": false,
          "internalType": "bytes[]",
          "name": "calldatas",
          "type": "bytes[]"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "startTime",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "endTime",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "string",
          "name": "description",
          "type": "string"
        }
      ],
      "name": "ProposalCreated",
      "type": "event"
    },
    "tableName": "ProposalCreated",
    "sync_historical": true
  };
  Moralis.Cloud.run("watchContractEvent", options, {useMasterKey:true});
  logger.info("----> GovernorCreatedEvents.afterSave - FINISH");
});

I ran a test and I can see the following entries in the log:

It looks like the trigger code ran twice. I suspect this is because of the confirmed (true/false) so maybe I need to check for that flag and only run the code if confirmed = true. Is that right?

When I go to the Dashboard, I do see the ProposalCreated table. However, I do not see any of the columns for the event fields. Please see the screen shot below:

So I have two questions:

  1. How can I see the event fields such as proposalId and proposer, etc.
  2. If another contract instance is created, the trigger will call “watchContractEvent” with the new contract’s address, will that interfere with the other contract? i.e. does “watchContractEvent” work if it is called with the same tableName but different address values?

Thanks!

It may not work to call it with an exiting table name

@DeveloperMarwan were you able to resolve your issue? I’m running into something similar.

@dancemonk No I have not been able to resolve it. Based on cryptokid’s response and based on the fact that I could not get all fields of the event to show up in the generated sync, I decided not to pursue it further.

All the best.

I think that you didn’t have the right topic there, you can try with the topic in hex form