Skip to content

Commit

Permalink
feat: utils-evm package with provider utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
janjakubnanista committed Nov 27, 2023
1 parent 83c56c7 commit 284cec0
Show file tree
Hide file tree
Showing 13 changed files with 207 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/utils-evm/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
node_modules
2 changes: 2 additions & 0 deletions packages/utils-evm/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist/
node_modules/
29 changes: 29 additions & 0 deletions packages/utils-evm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<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/utils-evm</h1>

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

Utilities for working with LayerZero EVM contracts.

## Installation

```bash
yarn add @layerzerolabs/utils-evm

pnpm add @layerzerolabs/utils-evm

npm install @layerzerolabs/utils-evm
```
8 changes: 8 additions & 0 deletions packages/utils-evm/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',
},
};
57 changes: 57 additions & 0 deletions packages/utils-evm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "@layerzerolabs/utils-evm",
"version": "0.0.1",
"private": true,
"description": "Utilities for LayerZero EVM projects",
"repository": {
"type": "git",
"url": "git+https://github.com/LayerZero-Labs/lz-utils.git",
"directory": "packages/utils-evm"
},
"license": "MIT",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./*": {
"types": "./dist/*.d.ts",
"require": "./dist/*.js",
"import": "./dist/*.mjs"
}
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"./dist/index.*"
],
"scripts": {
"prebuild": "npx tsc --noEmit -p tsconfig.build.json",
"build": "npx tsup",
"clean": "rm -rf dist",
"dev": "npx tsup --watch",
"lint": "npx eslint '**/*.{js,ts,json}'",
"test": "jest"
},
"dependencies": {
"p-memoize": "~4.0.1"
},
"devDependencies": {
"@ethersproject/providers": "^5.7.0",
"@layerzerolabs/lz-definitions": "~1.5.62",
"@layerzerolabs/test-utils": "~0.0.1",
"@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": "~8.0.1",
"typescript": "^5.2.2"
},
"peerDependencies": {
"@ethersproject/providers": "^5.7.0",
"@layerzerolabs/lz-definitions": "~1.5.62"
}
}
1 change: 1 addition & 0 deletions packages/utils-evm/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './provider'
6 changes: 6 additions & 0 deletions packages/utils-evm/src/provider/factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import pMemoize from 'p-memoize'
import { ProviderFactory, RpcUrlFactory } from './types'
import { JsonRpcProvider } from '@ethersproject/providers'

export const createProviderFactory = (urlFactory: RpcUrlFactory): ProviderFactory<JsonRpcProvider> =>
pMemoize(async (eid) => new JsonRpcProvider(await urlFactory(eid)))
2 changes: 2 additions & 0 deletions packages/utils-evm/src/provider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './factory'
export * from './types'
10 changes: 10 additions & 0 deletions packages/utils-evm/src/provider/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { BaseProvider } from '@ethersproject/providers'
import type { EndpointId } from '@layerzerolabs/lz-definitions'

export type Provider = BaseProvider

export type EndpointBasedFactory<TValue> = (eid: EndpointId) => TValue | Promise<TValue>

export type RpcUrlFactory = EndpointBasedFactory<string>

export type ProviderFactory<TProvider extends Provider = Provider> = EndpointBasedFactory<TProvider>
61 changes: 61 additions & 0 deletions packages/utils-evm/test/provider/factory.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import fc from 'fast-check'
import { createProviderFactory } from '@/provider/factory'
import { endpointArbitrary } from '@layerzerolabs/test-utils'
import { JsonRpcProvider } from '@ethersproject/providers'

describe('provider/factory', () => {
describe('createProviderFactory', () => {
const errorArbitrary = fc.anything()
const urlArbitrary = fc.webUrl()

it('should reject if urlFactory throws', async () => {
await fc.assert(
fc.asyncProperty(errorArbitrary, endpointArbitrary, async (error, eid) => {
const urlFactory = jest.fn().mockImplementation(() => {
throw error
})
const providerFactory = createProviderFactory(urlFactory)

await expect(providerFactory(eid)).rejects.toBe(error)
})
)
})

it('should reject if urlFactory rejects', async () => {
await fc.assert(
fc.asyncProperty(errorArbitrary, endpointArbitrary, async (error, eid) => {
const urlFactory = jest.fn().mockRejectedValue(error)
const providerFactory = createProviderFactory(urlFactory)

await expect(providerFactory(eid)).rejects.toBe(error)
})
)
})

it('should resolve with JsonRpcProvider if urlFactory returns a URL', async () => {
await fc.assert(
fc.asyncProperty(urlArbitrary, endpointArbitrary, async (url, eid) => {
const urlFactory = jest.fn().mockReturnValue(url)
const providerFactory = createProviderFactory(urlFactory)
const provider = await providerFactory(eid)

expect(provider).toBeInstanceOf(JsonRpcProvider)
expect(provider.connection.url).toBe(url)
})
)
})

it('should resolve with JsonRpcProvider if urlFactory resolves with a URL', async () => {
await fc.assert(
fc.asyncProperty(urlArbitrary, endpointArbitrary, async (url, eid) => {
const urlFactory = jest.fn().mockResolvedValue(url)
const providerFactory = createProviderFactory(urlFactory)
const provider = await providerFactory(eid)

expect(provider).toBeInstanceOf(JsonRpcProvider)
expect(provider.connection.url).toBe(url)
})
)
})
})
})
4 changes: 4 additions & 0 deletions packages/utils-evm/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["node_modules", "dist", "test"]
}
11 changes: 11 additions & 0 deletions packages/utils-evm/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"exclude": ["dist", "node_modules"],
"include": ["src", "test", "*.config.ts"],
"compilerOptions": {
"types": ["node", "jest"],
"paths": {
"@/*": ["./src/*"]
}
}
}
14 changes: 14 additions & 0 deletions packages/utils-evm/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from 'tsup'

export default defineConfig([
{
entry: ['src/index.ts'],
outDir: './dist',
clean: true,
dts: true,
sourcemap: true,
splitting: false,
treeshake: true,
format: ['esm', 'cjs'],
},
])

0 comments on commit 284cec0

Please sign in to comment.