FuelLabs / fuels-rs

Fuel Network Rust SDK
https://fuellabs.github.io/fuels-rs
Apache License 2.0
44.25k stars 1.34k forks source link

Interface to query and filter user owned events #598

Open digorithm opened 1 year ago

digorithm commented 1 year ago

Once https://github.com/FuelLabs/fuels-rs/pull/582 is merged, it will enable us to offer some nice querying/filtering functionalities around logging and events.

One of these functionalities that requires no change to the client would be: given an owner (a public Bech32Address), return all (or a paginated amount) events (logs) triggered by this owner.

We have to expose client.receipts(txId) through the Provider. Then, the design space is fairly large. But the SDK has to filter Logs out of the Receipts.

The underlying implementation would encapsulate something like this:


    let response = contract_instance.log_my_event(event).call().await?;

    let w = contract_instance._get_wallet();

    let request = PaginationRequest::<String> {
        cursor: None,
        results: 9999,
        direction: PageDirection::Forward,
    };

    let txs = w
        .get_provider()
        .unwrap()
        .get_transactions_by_owner(w.address(), request)
        .await
        .unwrap();

    for tx in txs.results {
        let receipt = w
            .get_provider()
            .unwrap()
            .client
            .receipts(&tx.transaction.id().to_string())
            .await
            .unwrap();

        dbg!(&receipt); // Filter out only the logs, parse them, etc., and at the end, return a nice `Vec<T>` with all events.
    }

We could, later on, add a whole simple querying language on top of this to enable better filtering. But that would be outside of this initial scope. For now, just being able to query all events from a user should be good starting point.

segfault-magnet commented 1 year ago

In order to know the original type of some logged data, we need the log->type mapping from the JSON ABI of the contract which logged it.

So if you call get_transactions_by_owner and then call receipts with those transaction ids, you can theoretically get logs from contracts for which you might not have the appropriate JSON ABIs (in #582 that data is stored inside the contract_instance, so you would need those).

This means that:

  1. The API for getting decoded logs would need to be given one or more contract instances so that it may use them to decode logs.
  2. We would need to decide if it is an error to be given a log whose original type we cannot deduce from the contract instances given to us. We could skip that log for example, but it might be surprising to the user.

I'll go ahead and implement a draft of something along these lines and we can wiggle toward what is best from there.

FYI @digorithm

nfurfaro commented 1 year ago

This might need a separate issue, but would we be able to handle failing require statements in a more user-friendly way? Currently, a require in sway logs a custom error type (often an enum variant, but not always), and then reverts with the value 42. The idea was always that the SDK would see the Revert(42) and then know to look at the preceding log/logd receipt as the reason for the failure. This log/logd would need to be decoded to be human-readable. I'm guessing that this is probably? doable now with the current state of things? cc @digorithm