Skip to content

Clean up how we codegen Config - #60

Merged
DZakh merged 12 commits into
mainfrom
dz/chain-map-clean-up
Jul 9, 2024
Merged

Clean up how we codegen Config#60
DZakh merged 12 commits into
mainfrom
dz/chain-map-clean-up

Conversation

@DZakh

@DZakh DZakh commented Jul 4, 2024

Copy link
Copy Markdown
Member

@DZakh
DZakh requested a review from JonoPrest July 4, 2024 12:39
@github-actions

github-actions Bot commented Jul 4, 2024

Copy link
Copy Markdown

Here's the diff of the codegen output.🙌🧠🦜

Comment on lines +121 to +123
chainMap: networks->Js.Array2.map(n => {
(n.chain, n)
})->ChainMap.fromArray->Utils.unwrapResultExn,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does, kind of, break the reasoning for the ChainMap abstraction.

It's supposed to be that you don't create one without defining all chains. And that way you can always look it up by chain and guarantee that a value exists at that key.

Comment on lines -42 to +45
let getConfigByChainId: int => configYaml = chainId =>
RegisterHandlers.getChain(
Belt.Result.getExn(ChainMap.Chain.fromChainId(chainId)),
)->mapChainConfigToConfigYaml
let getConfigByChainId: int => configYaml = chainId => {
let config = Config.getConfig()
config.chainMap->ChainMap.get(ChainMap.Chain.fromChainId(chainId)->Belt.Result.getExn)->mapChainConfigToConfigYaml
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI this was a file that Denham added to make it possible to see values that you defined in your config.yaml from within your handlers. Maybe we can think about if there's better ways during refactor to expose these values to the user.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I even found documentation for it. I actually wanted to suggest to replace it with a chainConfig object in a handlers among side event and context.

@JonoPrest JonoPrest left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DZakh, can we discuss what you're planning to do with ChainMap?

Otherwise the properties I was looking for with it is:

  1. It should ensure that all chain values are defined.
  2. You should be able to look up by a "chain" key and guarantee the value exists
  3. It should be easy to do immutable changes

If these properties are blocking you or are suboptimal then keen to hear why and what you are thinking.

@DZakh

DZakh commented Jul 5, 2024

Copy link
Copy Markdown
Member Author

@JonoPrest A short answer is that I don't see value in It should ensure that all chain values are defined, since it can be replaced with We trust that all chains are codegened when we set config. Also, it's one step closer to having a library-like architecture.

I'll continue doing what I already started in another PR, but let's have a sync on Monday, to ensure that we are on the same page.

@JonoPrest

Copy link
Copy Markdown
Collaborator

@JonoPrest A short answer is that I don't see value in It should ensure that all chain values are defined, since it can be replaced with We trust that all chains are codegened when we set config. Also, it's one step closer to having a library-like architecture.

I'll continue doing what I already started in another PR, but let's have a sync on Monday, to ensure that we are on the same page.

The value in the abstraction is that it guarentees lookup by chain. There are a lot of places in the code where we lookup by chain. I'm happy to get rid of unneeded abstractions but this still seems useful to me.

Comment on lines +55 to +57
chain: {
id: {{chain_config.network_config.id}},
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there other fields that will exist on this chain record?

chainId->ChainMap.Chain.fromChainId->Utils.unwrapResultExn
let chain = chainId->ChainMap.Chain.evm
if !(config.chainMap->ChainMap.has(chain)) {
Js.Exn.raiseError("No chain with id " ++ chain->ChainMap.Chain.toString ++ " found in config.yaml")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started creating an error handling "framework" in ErrorHandling.res

It allows you to raise exceptions with logs etc and pass a logger with a context around. I know this is essentially a global function but maybe we can use that pattern or extend on it to make error logs/exceptions more uniform.

Comment on lines +30 to +34
let get: (t<'a>, Chain.t) => 'a = (self, chain) =>
switch Map.get(self, chain) {
| Some(v) => v
| None => Js.Exn.raiseError("No chain with id " ++ chain->Chain.toString ++ " found in config.yaml")
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we return result<'a> from this and make it a safe API?

@JonoPrest

Copy link
Copy Markdown
Collaborator

@DZakh, I think it looks good but lets keep the ChainMap api safe and return result or option type form the get method.

@DZakh DZakh left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It throws, but in the end the safety of using ChainMap should be the same as before:

  • It used to throw before, now the error message is more readable

  • There are two ways to create Chain.t

    • With ChainMap.Chain.makeUnsafe - used for initial config set up and mocks
    • With Config.getChain - which validates that the provided chainId is a part of the defined config. If it's not, it'll throw with a nice error message. Before it returned a result with exception, but we always unwrapped the exception, so the behaviour is not changed
  • ChainMap.make which allowed to safely create items for all possible cases now replaces with:

    • ChainMap.fromArray - it doesn't have any validation but it used only for initial config creation
    • ChainMap.map - all the other places use ChainMap.map, so it's guaranteed to have all chains from config

@DZakh
DZakh requested a review from JonoPrest July 8, 2024 19:28
Comment on lines +22 to +23
let fromArray: array<(Chain.t, 'a)> => t<'a> = arr => {
arr->Map.fromArray(~id=module(Chain.ChainIdCmp))
arr->Map.fromArray(~id=module(ChainIdCmp))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call this fromArrayUnsafe or something? This is where it's unsafe IMO

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll do it.

Comment on lines 10 to 13
let makeUnsafe = (~chainId) => {
id: chainId,
}

module ChainIdCmp = Belt.Id.MakeComparableU({
type t = t
let cmp = (a, b) => Pervasives.compare(a->toChainId, b->toChainId)
})
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we not just make the type directly the id? Until we need more fields?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, since it's opaque now

let convertViemDecodedEvent: Viem.decodedEvent<'a> => Viem.decodedEvent<
Types.{{contract.name.capitalized}}.{{event.name.capitalized}}.eventArgs,
> = X.magic
> = Utils.magic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually regret having a module called Utils 🤣, but it's probably a good place to put this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought it's better not to have two Utils modules :)

@DZakh
DZakh requested a review from JonoPrest July 9, 2024 08:56
@DZakh
DZakh force-pushed the dz/chain-map-clean-up branch from f518388 to 50cc6f8 Compare July 9, 2024 09:18

@JonoPrest JonoPrest left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I think its looking good 👍🏼 looks like I'll have some conflicts in the other PRs but will sort that out.

@DZakh
DZakh merged commit 6e3de26 into main Jul 9, 2024
@DZakh

DZakh commented Jul 9, 2024

Copy link
Copy Markdown
Member Author

looks like I'll have some conflicts in the other PRs but will sort that out.

Sorry 😔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants