1

Say I have this code:

            private async void LaunchEventRetrievalLoop()
            {
                try
                {
                    Debug.Log("Creating event filter");
                    Event<Erc20TransferEvent> transferEvent = web3DirectClient.Eth.GetEvent<Erc20TransferEvent>(ContractAddress);
                    NewFilterInput filterInput = transferEvent.CreateFilterInput();
                    HexBigInteger filterId = await transferEvent.CreateFilterAsync(filterInput);
                    Debug.Log("Starting event lifecycle");
                    while (gameObject)
                    {
                        Debug.Log("Testing log");
                        List<EventLog<Erc20TransferEvent>> events = await transferEvent.GetFilterChangesAsync(filterId);
                        Debug.Log($"Iterating log ({events.Count})");
                        foreach (EventLog<Erc20TransferEvent> @event in events)
                        {
                            string eventLine = $"\n{@event.Log.BlockNumber} {@event.Log.Type} - " +
                                               $"{@event.Event.From}->{@event.Event.To} : {@event.Event.Value}";
                            if (string.IsNullOrEmpty(eventsBox.text))
                            {
                                eventsBox.text = eventLine;
                            }
                            else
                            {
                                eventsBox.text += $"\n{eventLine}";
                            }
                        }

                        float time = 0;
                        while (time < 5f)
                        {
                            await Tasks.Blink();
                            time += Time.deltaTime;
                        }
                    }
                    Debug.Log("Destroying everything");
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }

Most of the code is adapted from what the tutorial says for retrieving almost real-time events. This code is run inside a Unity synchronization context (this method is async, but in the context of Unity).

As you can see, there are many logs but, inside the while loop, two logs are recurrent:

Testing log
Iterating log (0)
# these lines repeat over and over in intervals of 5 seconds - no Unity time scaling.

Which stands for: I did not receive any events at all.

This routine is part of a sample UI which, in fact, can connect to a sample Ganache GUI local server (at http://my.local.network.address:8545/) and issue queries (CALL) and transactions (SEND) over a dumb contract which is, essentially, an ERC-20 contract I created just to have one view method, one non-view method and one event to test.

Save for the events, everything works well. The Erc20TransferEvent model I have looks like this:

            [Event("Transfer")]
            public class Erc20TransferEvent : IEventDTO
            {
                [Parameter("address", "_from", 1)]
                public string From { get; set; }
        
                [Parameter("address", "_to", 2)]        
                public string To { get; set; }
        
                [Parameter("uint256", "_value", 3)]        
                public System.Numerics.BigInteger Value { get; set; }
            }

Which intends to be the same as the tutorial (assume IEventDTO and Event are appropriately imported).

Assuming an up-to-date version of the Ganache GUI repository and also assuming a valid value in ContractAddress being an OpenZeppelin's ERC-20 implementation (it only has an extra implementation in the constructor to mint a default token supply for the creator of the contract) in which I can use the same Web3 web3DirectClient instance to issue SEND and CALL commands on the contract's methods...

...What am I missing here? Why I cannot log any single event? Even when Ganache GUI is instantaneous for the transactions, I don't see any log no matter how much I wait.

1 Answer 1

0

Okay, I'm adding a temporary answer, which is correct to my needed extent, but not in the way I wanted. I'm open to new answers and perhaps to serve as basis of other answers in the process.

The answer is composed of two parts.

The first one is that, actually, I commited a mistake in the Event DTO definition: I forgot to add the flags for indexed parameters. Indexed parameters are quite important since the search for up to 3 topics in an event is useful (e.g. to get events of a certain sender, a certain receiver, or both, in an ERC-20 quickly) but they are also required to be specified on the corresponding DTO paramters according to the event definition to perform the lookups. So, the definition must include a 4th argument in the Parameter definition for the indexed arguments (two, in the case of the ERC-20's Transfer event):

            [Event("Transfer")]
            public class Erc20TransferEvent : IEventDTO
            {
                [Parameter("address", "_from", 1, true)]
                public string From { get; set; }
        
                [Parameter("address", "_to", 2, true)]
                public string To { get; set; }
        
                [Parameter("uint256", "_value", 3)]
                public System.Numerics.BigInteger Value { get; set; }
            }

(notice the true flags, added as 4th arguments in both 1st and 2nd event parameters)

The second part... I'm not actually sure. Perhaps there's something I don't understand of the library or a bug on it (the versions I'm using are actually versions extracted from the Moralis.io SDK). However, I solved it in a way I dislike: Changing the paradigm / using another available call: A GetAllChangesAsync-based approach (instead of a GetFilterChangesAsync-based approach), where I have to control the block range explicitly:

            private async void LaunchEventRetrievalLoop()
            {
                try
                {
                    Debug.Log("Creating event filter");
                    Event<Erc20TransferEvent> transferEvent = web3DirectClient.Eth.GetEvent<Erc20TransferEvent>(ContractAddress);
                    BlockParameter fromBlock = null;
                    Debug.Log("Starting event lifecycle");
                    while (gameObject)
                    {
                        NewFilterInput filterInput = transferEvent.CreateFilterInput(fromBlock, null);
                        Debug.Log("Testing log");
                        List<EventLog<Erc20TransferEvent>> events = await transferEvent.GetAllChangesAsync(filterInput);
                        Debug.Log($"Iterating log ({events.Count})");
                        foreach (EventLog<Erc20TransferEvent> @event in events)
                        {
                            string eventLine = $"\n{@event.Log.BlockNumber} {@event.Log.Type} - " +
                                               $"{@event.Event.From}->{@event.Event.To} : {@event.Event.Value}";
                            if (string.IsNullOrEmpty(eventsBox.text))
                            {
                                eventsBox.text = eventLine;
                            }
                            else
                            {
                                eventsBox.text += $"\n{eventLine}";
                            }

                            fromBlock = new BlockParameter(new HexBigInteger(@event.Log.BlockNumber.Value + 1));
                        }

                        float time = 0;
                        while (time < 5f)
                        {
                            await Tasks.Blink();
                            time += Time.deltaTime;
                        }
                    }
                    Debug.Log("Destroying everything");
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }

Please note: I'm not sure whether this is due to a bug of the version(s) I'm using or what -- At least the index flag thing is for sure required, but I'm not sure, yet open to change or accept any edition if it happens to be true in someone else's try, about the GetFilterChangesAsync-approach in another code version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.