Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDK: Add core/base files and unit tests #3504

Closed
wants to merge 8 commits into from
Closed

Conversation

barnjamin
Copy link
Contributor

Initial PR to start bringing the connect-sdk into Wormhole monorepo

See the DESIGN.md file for an overview of the intended structure.

The core/base module provides constants and a convenient way to access them as well as utilities for higher level packages.

SEJeff
SEJeff previously approved these changes Dec 12, 2023
Copy link
Collaborator

@SEJeff SEJeff left a comment

Choose a reason for hiding this comment

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

All nits, very very nice. Feel free to ignore all of them :)

I did not review the typescript bits indepth or the tests at all. The docs are super nice and the sdk is obviously really nice given the magic behind the scenes that connect gives you.

sdk/js-connect/DESIGN.md Outdated Show resolved Hide resolved
sdk/js-connect/DESIGN.md Show resolved Hide resolved
sdk/js-connect/DESIGN.md Outdated Show resolved Hide resolved
sdk/js-connect/DESIGN.md Outdated Show resolved Hide resolved
sdk/js-connect/DESIGN.md Outdated Show resolved Hide resolved
sdk/js-connect/README.md Show resolved Hide resolved
sdk/js-connect/README.md Outdated Show resolved Hide resolved
["Kujira", 4002],
// holy cow, how ugly of a hack is that?! - a chainId that's exclusive to a testnet!
["Sepolia", 10002],
] as const satisfies MapLevel<string, number>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this mean we are going to have yet another place to maintain this list?

Thinking outloud, does it make sense to have a clearly namespaced singular wormhole typescript lib that is solely the constants that can be imported by this new sdk and the "legacy" sdk, or is the legacy one going to be fully deprecated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm hopeful we end up deriving the "legacy" config/consts from this one so we only have to update it/reference it from one spot.

If we do have a single Wormhole ts lib, this one is its own module so should be importable to access the config

Copy link
Contributor

Choose a reason for hiding this comment

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

the plan is that this SDK is the one to rule them all. the legacy one in the monorepo, as well as the sdk directory inside wormhole-connect, will both be replaced by this.

Comment on lines +3 to +4
RUN apt-get update && apt-get -y install \
git python3 make curl netcat
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
RUN apt-get update && apt-get -y install \
git python3 make curl netcat
RUN apt-get update && apt-get -y install --no-install-recommends \
git python3 make curl netcat && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

Put those images on a diet since you're not using a multi-stage build! Feel free to confirm the before and after with this trick:

docker image ls --format "{{ .Size }}" $IMAGE_NAME

testing/connectsdk.sh Outdated Show resolved Hide resolved
@barnjamin barnjamin force-pushed the connect-sdk/base branch 2 times, most recently from a3b8268 to 13225f7 Compare January 4, 2024 17:11
@@ -0,0 +1,59 @@
export type Extends<T, U> = [T] extends [U] ? true : false;

export type Function<P extends any[] = any[], R = any> = (...args: P) => R;
Copy link
Contributor

Choose a reason for hiding this comment

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

doesn't typescript already have a Function built-in?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

@nonergodic nonergodic Jan 4, 2024

Choose a reason for hiding this comment

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

As the documentation says:

This is an untyped function call and is generally best avoided because of the unsafe any return type.

I.e. another thing that TypeScript has and says "oh, it's there but, you shouldn't really use it. Think of it like a rake that we put in tall grass so you can accidentally step on it and have it smack you in the face. We put it there because we thought it was funny."

Ultimately, both Function and Extends, just like e.g. RoArray, are simply there to make stuff more readable (in my book - reasonable people can disagree here I think 🤷‍♂️ )

The fact that Extends compares clothed types might be surprising, so I'm less sure about that one and to what extent it is really mostly a leftover from my very early Typescript days, so that one is perhaps less justified than Function.

Overall, I don't have a strong opinion here.


export const relayerContracts = [[
"Mainnet", [
["Ethereum", "0x27428DD2d3DD32A4D7f7C497eAaa23130d894911"],
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm guessing you copy pastad all this and they don't need to be individually verified?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes copy/pasta'd but probably makes sense to check a few

@artursapek
Copy link
Contributor

I would change the js-connect directory name to typescript or js-v2 or something like that. make it clear this is more than just a Connect SDK.

@kev1n-peters
Copy link
Contributor

kev1n-peters commented Jan 4, 2024

I think that we should add a .prettierrc file in the root directory and potentially a CI job that enforces TypeScript formatting

@nonergodic
Copy link
Collaborator

nonergodic commented Jan 4, 2024

I strongly object to the prettier. What's currently not pretty? I can point to loads of places that will be less readable, once a "prettier" is done with disfiguring the code that I wrote.

@nonergodic
Copy link
Collaborator

nonergodic commented Jan 4, 2024

The compromise that Ben and I originally came up with was that "my" part of the code would be exempt (i.e. get a prettier ignore entry). This way, whoever has the most skin in the games in various parts of the code gets to call the shots, rather than having some external "authority" come up with "sensible regulations". Uniformity and standardization is necessary when you run a fast-food franchise, but you'll not get a five star restaurant that way.

@barnjamin
Copy link
Contributor Author

barnjamin commented Jan 4, 2024

The compromise that Ben and I originally came up with was that "my" part of the code would be exempt (i.e. get a prettier ignore entry). This way, whoever has the most skin in the games in various parts of the code gets to call the shots, rather than having some external "authority" come up with "sensible regulations". Uniformity and standardization is necessary when you run a fast-food franchise, but you'll not get a five star restaurant that way.

fwiw I think I borked the formatting again, will have to make it pretty once again. Can we use the formatting everywhere but cordon off certain things like const declarations with an ignore directive https://prettier.io/docs/en/ignore.html#javascript

@nonergodic
Copy link
Collaborator

fwiw I think I borked the formatting again, will have to make it pretty once again. Can we use the formatting everywhere but cordon off certain things like const declarations with an ignore directive https://prettier.io/docs/en/ignore.html#javascript

Making my point for me.

Example taken from mapping.ts:
Before "prettier":

type TransformMapping<M extends MappingEntries, S extends Shape | void = void> =
  //check that M has a valid structure for mapping entries
  CartesianRightRecursive<M> extends infer CRR extends RoArray2D
  ? IsRectangular<CRR> extends true
    //ensure CRR is not empty  
    ? CRR extends readonly [RoArray, ...RoArray2D]
      ? S extends Shape
        ? SplitAndReorderKeyValueColumns<CRR, S> extends [
            infer KC extends CartesianSet<MappableKey>,
            infer VC extends CartesianSet
          ]
          ? KC["length"] extends Depth[number]
            ? CombineValueColumnsToLeafValues<VC> extends infer VR extends RoArray<LeafValue>
              ? ProcessNextKeyColmn<KC, VR> extends infer TM extends MappingEntries
                ? [MaybeUnwrapValuesIfAllAreSingletons<TM, KC["length"]>, KC["length"]]
                : never
              : never
            : never
          : never
        //if we don't have an explicit shape, take the first row and subtract 1 (for the value
        //  column) to determine the count of key columns
        : CRR[0] extends readonly [...infer KC extends RoArray, unknown]
        ? KC["length"] extends Depth[number]
          ? [M, KC["length"]]
          : never
        : never
      : never
    : never
  : never;

After "prettier":

type TransformMapping<M extends MappingEntries, S extends Shape | void = void> =
  //check that M has a valid structure for mapping entries
  CartesianRightRecursive<M> extends infer CRR extends RoArray2D
  ? IsRectangular<CRR> extends true
  //ensure CRR is not empty  
  ? CRR extends readonly [RoArray, ...RoArray2D]
  ? S extends Shape
  ? SplitAndReorderKeyValueColumns<CRR, S> extends [
    infer KC extends CartesianSet<MappableKey>,
    infer VC extends CartesianSet
  ]
  ? KC["length"] extends Depth[number]
  ? CombineValueColumnsToLeafValues<VC> extends infer VR extends RoArray<LeafValue>
  ? ProcessNextKeyColmn<KC, VR> extends infer TM extends MappingEntries
  ? [MaybeUnwrapValuesIfAllAreSingletons<TM, KC["length"]>, KC["length"]]
  : never
  : never
  : never
  : never
  //if we don't have an explicit shape, take the first row and subtract 1 (for the value
  //  column) to determine the count of key columns
  : CRR[0] extends readonly [...infer KC extends RoArray, unknown]
  ? KC["length"] extends Depth[number]
  ? [M, KC["length"]]
  : never
  : never
  : never
  : never
  : never;

I rest my case.

@kev1n-peters
Copy link
Contributor

Ah, prettier does make the code pretty unreadable in that case. Maybe we could compromise like previously suggested and ignore formatting in cases where it hurts readability.

@artursapek
Copy link
Contributor

it's worth trying this prettier option: https://prettier.io/docs/en/options.html#experimental-ternaries

and just generally seeing if we can configure it to suit your fancy. it's highly configurable.

@nonergodic
Copy link
Collaborator

it's worth trying this prettier option: https://prettier.io/docs/en/options.html#experimental-ternaries

and just generally seeing if we can configure it to suit your fancy. it's highly configurable.

We have a fundamental, philosophical difference here.

You can't nail down what makes readable code, just like you can't nail down virtue and what it means to be virtuous.

Sure, you can give guidelines (be honest, be charitable, and so on) but you can't put this "into code". Trying to replace wisdom with intelligence is exactly the sort of trap that intelligent nerds fall into (I used to be one of them). I now reject this entire line of thinking.

You can define some approximation that you keep refining over time, but I don't see the purpose.

Be a virtuous person. Write readable code.

@artursapek
Copy link
Contributor

artursapek commented Jan 5, 2024

I don't really see how it's a matter of intelligence or wisdom. I think people who use formatters usually do it to be more efficient. I don't like spending my time formatting my code. it's one of many chores in my life which I prefer to automate as much as I can.

In larger orgs, it's a PITA to make sure everyone has the same tab settings, etc. and diffs become very noisy if you don't. this was why Golang shipped with gofmt from the very beginning; Google was trying to make a good systems language for massive development projects with many contributors.

@@ -0,0 +1,36 @@
export {
Copy link
Contributor

Choose a reason for hiding this comment

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

this utils/layout is quite a piece of work. I don't see unit tests in this directory. is this unit tested somehow elsewhere in this large diff?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@artursapek artursapek left a comment

Choose a reason for hiding this comment

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

@artursapek artursapek closed this Feb 22, 2024
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.

5 participants