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

🪚 OmniGraph™ #37

Merged
merged 2 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
// Intermediate deescalation to warnings
//
// FIXME Slowly remove these problems, then remove these overrides
"no-undef": "warn",
"no-undef": "off",
"no-constant-condition": "warn",

"no-unused-vars": "off",
Expand Down
2 changes: 1 addition & 1 deletion packages/create-lz-oapp/src/utilities/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { isPackageManagerAvailable } from './installation.js'
import { isDirectory } from './filesystem.js'
import { resolve } from 'path'

const handlePromptState = (state: any) => {
const handlePromptState = (state: { aborted: boolean }) => {
if (state.aborted) {
// If we don't re-enable the terminal cursor before exiting
// the program, the cursor will remain hidden
Expand Down
3 changes: 3 additions & 0 deletions packages/ua-utils/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.turbo
dist
node_modules
3 changes: 3 additions & 0 deletions packages/ua-utils/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json"
}
23 changes: 23 additions & 0 deletions packages/ua-utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<p align="center">
<a href="https://layerzero.network">
<img alt="LayerZero" style="max-width: 500px" src="https://d3a2dpnnrypp5h.cloudfront.net/bridge-app/lz.png"/>
</a>
</p>

<h1 align="center">@layerzerolabs/ua-utils</h1>

<!-- The badges section -->
<p align="center">
<!-- Shields.io NPM published package version -->
<a href="https://www.npmjs.com/package/@layerzerolabs/ua-utils"><img alt="NPM Version" src="https://img.shields.io/npm/v/@layerzerolabs/ua-utils"/></a>
<!-- Shields.io NPM downloads -->
<a href="https://www.npmjs.com/package/@layerzerolabs/ua-utils"><img alt="Downloads" src="https://img.shields.io/npm/dm/@layerzerolabs/ua-utils"/></a>
<!-- Shields.io license badge -->
<a href="https://www.npmjs.com/package/@layerzerolabs/ua-utils"><img alt="NPM License" src="https://img.shields.io/npm/l/@layerzerolabs/ua-utils"/></a>
</p>

## Installation

```sh
$ npm install @layerzerolabs/ua-utils
```
8 changes: 8 additions & 0 deletions packages/ua-utils/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
};
48 changes: 48 additions & 0 deletions packages/ua-utils/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@layerzerolabs/ua-utils",
"version": "0.1.0",
"private": true,
"description": "Utilities for working with LayerZero contracts",
"repository": {
"type": "git",
"url": "git+https://github.com/LayerZero-Labs/lz-utils.git",
"directory": "packages/ua-utils"
},
"license": "MIT",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
}
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"files": [
"dist/",
"LICENSE"
],
"scripts": {
"prebuild": "tsc -noEmit",
"build": "npx tsup",
"clean": "rm -rf dist",
"lint": "npx eslint '**/*.{js,ts,json}'",
"test": "jest"
},
"devDependencies": {
"@layerzerolabs/lz-definitions": "~1.5.58",
"@types/jest": "^29.5.10",
"fast-check": "^3.14.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"typescript": "^5.2.2",
"zod": "^3.22.4"
},
"peerDependencies": {
"@layerzerolabs/lz-definitions": "~1.5.58",
"zod": "^3.22.4"
}
}
1 change: 1 addition & 0 deletions packages/ua-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './omnigraph'
42 changes: 42 additions & 0 deletions packages/ua-utils/src/omnigraph/coordinates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { OmniVector, OmniPoint } from './types'

/**
* Compares two points by value
*
* @param a `OmniPoint`
* @param b `OmniPoint`
*
* @returns `true` if the vector point to the same point in omniverse
*/
export const arePointsEqual = (a: OmniPoint, b: OmniPoint): boolean => a.address === b.address && a.eid === b.eid

/**
* Compares two vectors by value
*
* @param a `OmniVector`
* @param b `OmniVector`
*
* @returns `true` if the vector point from and to the same point in omniverse
*/
export const areVectorsEqual = (a: OmniVector, b: OmniVector): boolean =>
arePointsEqual(a.from, b.from) && arePointsEqual(a.to, b.to)

/**
* Serializes a point. Useful for when points need to be used in Map
* where we cannot adjust the default behavior of using a reference equality
*
* @param point `OmniPoint`
*
* @returns `string`
*/
export const serializePoint = ({ address, eid }: OmniPoint): string => `${eid}|${address}`

/**
* Serializes a vector. Useful for when vectors need to be used in Map
* where we cannot adjust the default behavior of using a reference equality
*
* @param point `OmniVector`
*
* @returns `string`
*/
export const serializeVector = ({ from, to }: OmniVector): string => `${serializePoint(from)} → ${serializePoint(to)}`
3 changes: 3 additions & 0 deletions packages/ua-utils/src/omnigraph/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './coordinates'
export * from './schema'
export * from './types'
49 changes: 49 additions & 0 deletions packages/ua-utils/src/omnigraph/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { z } from 'zod'
import type { OmniPoint, OmniNode, OmniVector, OmniEdge } from './types'

export const AddressSchema = z.string()

export const EndpointIdSchema: z.ZodSchema<EndpointId, z.ZodTypeDef, unknown> = z
.nativeEnum(EndpointId)
.pipe(z.number())

export const OmniPointSchema: z.ZodSchema<OmniPoint, z.ZodTypeDef, unknown> = z.object({
address: AddressSchema,
eid: EndpointIdSchema,
})

export const OmniVectorSchema: z.ZodSchema<OmniVector, z.ZodTypeDef, unknown> = z.object({
from: OmniPointSchema,
to: OmniPointSchema,
})

/**
* Factory for OmniNode schemas
*
* @param configSchema Schema of the config contained in the node
*
* @returns `z.ZodSchema<OmniNode<TConfig>>` schema for a node with the particular config type
*/
export const createOmniNodeSchema = <TConfig = unknown>(
configSchema: z.ZodSchema<TConfig, z.ZodTypeDef, unknown>
): z.ZodSchema<OmniNode<TConfig>, z.ZodTypeDef, unknown> =>
z.object({
point: OmniPointSchema,
config: configSchema,
}) as z.ZodSchema<OmniNode<TConfig>, z.ZodTypeDef, unknown>

/**
* Factory for OmniEdge schemas
*
* @param configSchema `z.ZodSchema<TConfig>` Schema of the config contained in the edge
*
* @returns `z.ZodSchema<OmniEdge<TConfig>>` schema for an edge with the particular config type
*/
export const createOmniEdgeSchema = <TConfig = unknown>(
configSchema: z.ZodSchema<TConfig, z.ZodTypeDef, unknown>
): z.ZodSchema<OmniEdge<TConfig>, z.ZodTypeDef, unknown> =>
z.object({
vector: OmniVectorSchema,
config: configSchema,
}) as z.ZodSchema<OmniEdge<TConfig>, z.ZodTypeDef, unknown>
53 changes: 53 additions & 0 deletions packages/ua-utils/src/omnigraph/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { EndpointId } from '@layerzerolabs/lz-definitions'

export type Address = string

/**
* OmniPoint identifies a point in omniverse, an omnichain universe.
*
* In layman terms this is a contract deployed on a particular network (represented by an endpoint).
*/
export interface OmniPoint {
eid: EndpointId
address: Address
}

/**
* OmniVector identifies a vector in omniverse, an omnichain universe.
*
* In layman terms this is a directional connection between two contracts - two points of the omniverse
*/
export interface OmniVector {
from: OmniPoint
to: OmniPoint
}

/**
* OmniNode represents a point in omniverse
* with an additional piece of information attached
*/
export interface OmniNode<TConfig = unknown> {
point: OmniPoint
config: TConfig
}

/**
* OmniEdge represents a connection between two points in omniverse
* with an additional piece of information attached
*/
export interface OmniEdge<TConfig = unknown> {
vector: OmniVector
config: TConfig
}

/**
* OmniGraph is a collection of nodes and edges of omniverse
* that together represent an omnichain app a.k.a. OApp.
*
* For purposes of readability and to avoid overabstraction on the user end,
* the names are set to be `contracts` rather than `nodes` and `connections` rather than `edges`
*/
export interface OmniGraph<TNodeConfig = unknown, TEdgeConfig = unknown> {
contracts: OmniNode<TNodeConfig>[]
connections: OmniEdge<TEdgeConfig>[]
}
18 changes: 18 additions & 0 deletions packages/ua-utils/test/__utils__/arbitraries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import fc from 'fast-check'
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { ENDPOINT_IDS } from './constants'
import { OmniPoint, OmniVector } from '@/omnigraph/types'

export const addressArbitrary = fc.string()

export const endpointArbitrary: fc.Arbitrary<EndpointId> = fc.constantFrom(...ENDPOINT_IDS)

export const pointArbitrary: fc.Arbitrary<OmniPoint> = fc.record({
eid: endpointArbitrary,
address: addressArbitrary,
})

export const vectorArbitrary: fc.Arbitrary<OmniVector> = fc.record({
from: pointArbitrary,
to: pointArbitrary,
})
6 changes: 6 additions & 0 deletions packages/ua-utils/test/__utils__/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { EndpointId } from '@layerzerolabs/lz-definitions'
import { EndpointIdSchema } from '../../src/omnigraph/schema'

export const ENDPOINT_IDS = Object.values(EndpointId).filter(
(value): value is EndpointId => EndpointIdSchema.safeParse(value).success
)
Loading