juno icon indicating copy to clipboard operation
juno copied to clipboard

Refactor `feeder` and `gateway` packages and extract common types

Open IronGauntlets opened this issue 2 years ago • 3 comments

The clients/feeder and clients/gateway packages belong to the Frameworks & Drivers layer of clean architecture, therefore any layer inside of Frameworks & Drivers can only use clients/feeder and clients/gateway through an interface. This is known as The Dependency Inversion Rule, the overarching principle of clean architecture.

Defining an interface to access an outer layer has the benefit of having multiple concrete implementations which are accessed through a single interface. This helps with minimising sweeping changes across the codebase when a breaking change is introduced. However, the Dependency Inversion rule can introduce unnecessary complexity early on in the project, as declaring an interface for a single concrete implementation doesn't always make sense.

At the beginning of the project, we declared StarknetData as an interface used to fetch Starknet's data which could be implemented by either the feeder gateway or the p2p layer (Interface Adapter layer).

To add different transactions we introduced a gateway package, accessed through a Gateway interface in the rpc package, however, we still use the feeder package directly in the starknet data package and rpc package which violates the dependency inversion rule. Therefore we need to introduce a Feeder interface which is used by both the rpc package and the StarknetData package.

feeder and gateway are under the same parent client package where each package creates its own client with the only difference of post and get methods. As @omerfirmak suggested we should merge these packages together to have a single client with both a post and get methods. This client is then composed into feeder and gateway structs (which are responsible for building the query URL for fetching Starknet data from the sequencer). Another benefit of merging these packages together is that they share the same types, therefore, merging them would reduce duplication.

Crossing layers in the clean architecture requires adapter functions: input from rpc to core types should have its own adapter and input from feeder and gateway also should have their own adapters to core types (and vice versa). However, due to the commonality between all of the adapters and to reduce duplication, we created feeder2core. These functions can be moved to the utils package with a more generic name.

Also, the feeder, gateway and rpc packages have very similar types (namely Transaction and TransactionReceipts nested types) all of whom can also be moved to the utils to reduce duplication.

In summary, this issue has the following parts:

  • Merge the clients/feeder and clients/gateway packages into the clients package
    • A single Client struct (with private post and get) would implement the Feeder (needs to be defined) and Gateway (needs to be moved from rpc package to the clients package) interface.
  • Further, generalise the feeder2core adapter by renaming it and moving it to the utils package.
  • Extract common types from the feeder package and rpc package to the utils package to reduce duplication.

IronGauntlets avatar Aug 04 '23 11:08 IronGauntlets

I'd like to work on this

rianhughes avatar Aug 23 '23 11:08 rianhughes

I've broken this PR into three sub-PRs:

  • [ ] https://github.com/NethermindEth/juno/issues/1146
  • [ ] https://github.com/NethermindEth/juno/issues/1147
  • [ ] https://github.com/NethermindEth/juno/issues/1148

rianhughes avatar Aug 23 '23 11:08 rianhughes

Love the idea of merging feeder and gateway.

Therefore we need to introduce a Feeder interface which is used by both the rpc package and the StarknetData package.

Why not add an AddTransaction method to the StarknetData interface and use StarknetData in rpc? cc @rianhughes @IronGauntlets

joshklop avatar Sep 04 '23 13:09 joshklop

Done

rodrigo-pino avatar Feb 03 '25 14:02 rodrigo-pino