Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

feat: derive Serialize and Deserialize for Event, {}Filter, Call, and Errors in contract bindings #2599

Closed
Autoparallel opened this issue Sep 14, 2023 · 6 comments · Fixed by #2606

Comments

@Autoparallel
Copy link
Contributor

Is your feature request related to a problem? Please describe.
When working with contract bindings, it would be nice to be able to use serde to manage these structs/enums. For instance, if I was doing something like this:

let mut stream = event.stream().await.unwrap();
                while let Some(Ok(event)) = stream.next().await {
                    println!("Event: {:?}", serde_json::to_string(&event));
                }

it would be great to be able to do this serialization so I can, for example, output this all to a CSV nicely.

Describe the solution you'd like
For instance, we can just add Serialize in the output for the bindings such as here:

fn expand_events_enum(&self) -> TokenStream {
        let variants = self
            .abi
            .events
            .values()
            .flatten()
            .map(|e| {
                event_struct_name(&e.name, self.event_aliases.get(&e.abi_signature()).cloned())
            })
            .collect::<Vec<_>>();

        let enum_name = self.expand_event_enum_name();

        let mut derives = self.expand_extra_derives();
        let params =
            self.abi.events.values().flatten().flat_map(|err| &err.inputs).map(|param| &param.kind);
        util::derive_builtin_traits(params, &mut derives, false, true);

        let ethers_core = ethers_core_crate();
        let ethers_contract = ethers_contract_crate();

        quote! {
            #[doc = "Container type for all of the contract's events"]
            #[derive(Clone, #ethers_contract::EthAbiType, #derives)]
            pub enum #enum_name {
                #( #variants(#variants), )*
            }
            \\ ~ snip

we can just replace #[derive(Clone, #ethers_contract::EthAbiType, #derives)] with #[derive(Clone, Serialize, Deserialize, #ethers_contract::EthAbiType, #derives)]. Note that this is located here.

Additional context
Though I just showed the potential solution for Events, this could be applied to Calls, Errors, and {}Filter objects as well.

@Autoparallel Autoparallel changed the title feat: derive Serialize and Deserialize for Event, [_]Filter, Call, and Errors in contract bindings feat: derive Serialize and Deserialize for Event, {}Filter, Call, and Errors in contract bindings Sep 14, 2023
@mattsse
Copy link
Collaborator

mattsse commented Sep 14, 2023

I think this is reasonable, perhaps this should reuse the attributes supplies to abigen!

@Autoparallel
Copy link
Contributor Author

I think this is reasonable, perhaps this should reuse the attributes supplies to abigen!

Does this mean the #derives? I'm a bit new to macros. I was searching for where the easiest entrypoint would be for the most minimal changes. Is there anywhere in the codebase that Serialize and Deserialize are re-exported, or would we supply that derives would read:

#[derive(Clone, ::serde::Serialize, ::serde::Deserialize, ..)]

@mattsse
Copy link
Collaborator

mattsse commented Sep 14, 2023

see

/// Expands `self.extra_derives` into a comma separated list to be inserted in a
/// `#[derive(...)]` attribute.
pub(crate) fn expand_extra_derives(&self) -> TokenStream {
let extra_derives = &self.extra_derives;
quote!(#( #extra_derives, )*)
}

and structs for example:

let mut derives = self.expand_extra_derives();
util::derive_builtin_traits_struct(&self.internal_structs, sol_struct, types, &mut derives);
let ethers_contract = ethers_contract_crate();
Ok(quote! {
#[doc = #doc_str]
#[derive(Clone, #ethers_contract::EthAbiType, #ethers_contract::EthAbiCodec, #derives)]
pub #struct_def
})

@Autoparallel
Copy link
Contributor Author

Let me give this a shot.

Do you have a suggestion for testing this? Coming from forge bind, maybe it is just best to rebuild foundry and point to my ethers branch?

@mattsse
Copy link
Collaborator

mattsse commented Sep 14, 2023

like this

#[test]
fn can_generate_internal_structs() {
abigen!(
VerifierContract,
"ethers-contract/tests/solidity-contracts/verifier_abi.json",
derives(serde::Deserialize, serde::Serialize)
);
assert_struct::<VerifyingKey>();
assert_struct::<G1Point>();
assert_struct::<G2Point>();
}

and assert Serialize+Deserialize

@Autoparallel
Copy link
Contributor Author

Okay fair enough!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants