Skip to content

Commit

Permalink
feat: options builder
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Goulding <[email protected]>
  • Loading branch information
ryandgoulding committed Dec 13, 2023
1 parent ae638ad commit 16207c2
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 0 deletions.
25 changes: 25 additions & 0 deletions packages/test-utils-evm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<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/test-utils-evm</h1>

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

Collection of internal helpers for testing LayerZero packages

## Installation

```sh
$ npm install @layerzerolabs/test-utils-evm
```
35 changes: 35 additions & 0 deletions packages/test-utils-evm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@layerzerolabs/test-utils-evm",
"version": "0.0.1",
"private": true,
"description": "Internal utilities for testing LayerZero packages",
"repository": {
"type": "git",
"url": "git+https://github.com/LayerZero-Labs/lz-utils.git",
"directory": "packages/test-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/index.*"
],
"scripts": {
"prebuild": "tsc -noEmit",
"build": "npx tsup",
"clean": "rm -rf dist",
"lint": "npx eslint '**/*.{js,ts,json}'"
},
"devDependencies": {
"@ethersproject/providers": "^5.7.0",
"ethers": "^5.7.0"
}
}
23 changes: 23 additions & 0 deletions packages/test-utils-evm/src/event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Log, TransactionReceipt } from '@ethersproject/providers'
import { utils } from 'ethers'
import { keccak256, toUtf8Bytes } from 'ethers/lib/utils'

/**
* Find matching emitted events.
* @param {TransactionReceipt} receipt
* @param {EventFragment} frag
* @param {string} contractAddress
* @returns {Log[]}
*/
export const findMatchingEvents = (
receipt: TransactionReceipt,
frag: utils.EventFragment,
contractAddress: string
): Log[] =>
receipt.logs
.filter((log) => log.topics.includes(keccak256(toUtf8Bytes(frag.format()))))
.filter(
(log) =>
log.address &&
(contractAddress === undefined || log.address.toLowerCase() === contractAddress.toLowerCase())
)
1 change: 1 addition & 0 deletions packages/test-utils-evm/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './event'
11 changes: 11 additions & 0 deletions packages/test-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"],
"compilerOptions": {
"types": ["node", "jest"],
"paths": {
"@/*": ["./src/*"]
}
}
}
12 changes: 12 additions & 0 deletions packages/test-utils-evm/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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'],
})
3 changes: 3 additions & 0 deletions packages/ua-utils-evm-hardhat-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
"@layerzerolabs/lz-evm-sdk-v1": "~1.5.72",
"@layerzerolabs/lz-evm-sdk-v2": "~1.5.72",
"@layerzerolabs/lz-utility-v2": "~1.5.72",
"@layerzerolabs/omnicounter-utils": "~0.0.1",
"@layerzerolabs/omnicounter-utils-evm": "~0.0.1",
"@layerzerolabs/protocol-utils": "~0.0.1",
"@layerzerolabs/protocol-utils-evm": "~0.0.1",
"@layerzerolabs/test-utils-evm": "~0.0.1",
"@layerzerolabs/toolbox-hardhat": "~0.0.1",
"@layerzerolabs/ua-utils": "~0.1.0",
"@layerzerolabs/ua-utils-evm": "~0.0.1",
Expand Down
113 changes: 113 additions & 0 deletions packages/ua-utils-evm-hardhat-test/test/omnicounter/options.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { findMatchingEvents } from '@layerzerolabs/test-utils-evm'
import fc from 'fast-check'
import 'hardhat'
import { EventFragment } from '@ethersproject/abi/src.ts/fragments'
import { Log, TransactionReceipt } from '@ethersproject/providers'
import { EndpointId, MainnetEndpointId } from '@layerzerolabs/lz-definitions'
import { Options } from '@layerzerolabs/lz-utility-v2'
import { createOmniCounterFactory, OmniCounter } from '@layerzerolabs/omnicounter-utils-evm'
import { createEndpointFactory } from '@layerzerolabs/protocol-utils-evm'
import { configureOApp } from '@layerzerolabs/ua-utils'
import { OmniTransaction } from '@layerzerolabs/utils'
import { omniContractToPoint } from '@layerzerolabs/utils-evm'
import {
createConnectedContractFactory,
createSignerFactory,
OmniGraphBuilderHardhat,
OmniGraphHardhat,
} from '@layerzerolabs/utils-evm-hardhat'
import { utils } from 'ethers'
import { parseEther } from 'ethers/lib/utils'
import { setupDefaultEndpoint } from '../__utils__/endpoint'
import { deployOmniCounter } from '../__utils__/omnicounter'

/**
* Parse event logs.
* @param {Log} log
* @param {utils.Interface} context
*/
const parseArgs = (log: Log, context: utils.Interface): utils.Result => context.parseLog(log).args

describe('oapp/options', () => {
const ethContract = { eid: EndpointId.ETHEREUM_MAINNET, contractName: 'OmniCounter' }
const avaxContract = { eid: EndpointId.AVALANCHE_MAINNET, contractName: 'OmniCounter' }

const config: OmniGraphHardhat = {
contracts: [
{
contract: ethContract,
},
{
contract: avaxContract,
},
],
connections: [
{
from: ethContract,
to: avaxContract,
},
{
from: avaxContract,
to: ethContract,
},
],
}

beforeEach(async () => {
await deployOmniCounter()
await setupDefaultEndpoint()
})

it('lzReceive option', async () => {
const contractFactory = createConnectedContractFactory()
const builder = await OmniGraphBuilderHardhat.fromConfig(config)
const sdkFactory = createOmniCounterFactory(contractFactory)
const signerFactory = createSignerFactory()

const ethPoint = omniContractToPoint(await contractFactory(ethContract))
const ethSdk: OmniCounter = await sdkFactory(ethPoint)
const ethSigner = await signerFactory(ethContract.eid)

const avaxPoint = omniContractToPoint(await contractFactory(avaxContract))
const avaxSdk = await sdkFactory(avaxPoint)
const avaxSigner = await signerFactory(avaxContract.eid)

const transactions = await configureOApp(builder.graph, sdkFactory)
for (const transaction of transactions) {
const signer = transaction.point.eid === MainnetEndpointId.ETHEREUM_MAINNET ? ethSigner : avaxSigner
const txResponse = await signer.signAndSend(transaction)
const txReceipt: TransactionReceipt = await txResponse.wait()
expect(txReceipt.status).toBe(1)
}

expect(await ethSdk.hasPeer(avaxPoint.eid, avaxPoint.address)).toBe(true)
expect(await avaxSdk.hasPeer(ethPoint.eid, ethPoint.address)).toBe(true)

await fc.assert(
fc.asyncProperty(fc.integer({ min: 200000, max: 100000000000 }), async (p) => {
const options = Options.newOptions().addExecutorLzReceiveOption(p)
const incrementTx: OmniTransaction = {
...(await ethSdk.increment(avaxPoint.eid, 2, options.toHex())),
gasLimit: 500000,
value: parseEther('0').toString(),
}
const incrementTxResponse = await ethSigner.signAndSend(incrementTx)
const incrementTxReceipt: TransactionReceipt = await incrementTxResponse.wait()
expect(incrementTxReceipt.status).toEqual(1)

const ethEndpointContract = { eid: MainnetEndpointId.ETHEREUM_MAINNET, contractName: 'EndpointV2' }
const ethEndpointPoint = omniContractToPoint(await contractFactory(ethEndpointContract))
const endpointSdkFactory = createEndpointFactory(contractFactory)
const ethEndpointSdk = await endpointSdkFactory(ethEndpointPoint)
const packetReceived = Object.values(
ethEndpointSdk.contract.contract.interface.events as any as EventFragment[]

Check warning on line 103 in packages/ua-utils-evm-hardhat-test/test/omnicounter/options.test.ts

View workflow job for this annotation

GitHub Actions / Check code / Build, Lint & Test

Unexpected any. Specify a different type
).find((frag: EventFragment) => frag.name === 'PacketSent') as EventFragment
const logs = findMatchingEvents(incrementTxReceipt, packetReceived, ethEndpointPoint.address)
if (logs && logs.length > 0) {
const eventArgs = parseArgs(logs[0]!, ethEndpointSdk.contract.contract.interface)
expect(eventArgs.options.toLowerCase() === options.toHex().toLowerCase())
}
})
)
})
})

0 comments on commit 16207c2

Please sign in to comment.