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

🗞️ Adding getEnforcedOptions task #369

Merged
merged 3 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions .changeset/big-zoos-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@layerzerolabs/ua-devtools-evm-hardhat-test": patch
"@layerzerolabs/ua-devtools-evm-hardhat": patch
"@layerzerolabs/ua-devtools": patch
---

Adding getEnforcedOptions task
1 change: 1 addition & 0 deletions packages/ua-devtools-evm-hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@layerzerolabs/io-devtools": "~0.1.2",
"@layerzerolabs/lz-definitions": "~2.1.4",
"@layerzerolabs/lz-evm-messagelib-v2": "~2.1.4",
"@layerzerolabs/lz-v2-utilities": "~2.1.4",
"@layerzerolabs/protocol-devtools": "~0.1.3",
"@layerzerolabs/protocol-devtools-evm": "~0.1.3",
"@layerzerolabs/ua-devtools": "~0.1.5",
Expand Down
1 change: 1 addition & 0 deletions packages/ua-devtools-evm-hardhat/src/constants/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const TASK_LZ_OAPP_CONFIG_GET_DEFAULT = 'lz:oapp:config:get:default'
export const TASK_LZ_OAPP_CONFIG_GET_EXECUTOR = 'lz:oapp:config:get:executor'
export const TASK_LZ_OAPP_CONFIG_GET = 'lz:oapp:config:get'
export const TASK_LZ_OAPP_CONFIG_CHECK = 'lz:oapp:config:check'
export const TASK_LZ_OAPP_ENFORCED_OPTIONS_GET = 'lz:oapp:enforced:options:get'
export const TASK_LZ_OAPP_CONFIG_INIT = 'lz:oapp:config:init'

export const SUBTASK_LZ_OAPP_WIRE_CONFIGURE = '::lz:oapp:wire:configure'
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { ActionType } from 'hardhat/types'
import { task } from 'hardhat/config'
import { createLogger, printCrossTable, printRecord, setDefaultLogLevel } from '@layerzerolabs/io-devtools'
import { TASK_LZ_OAPP_ENFORCED_OPTIONS_GET } from '@/constants/tasks'
import { printLogo } from '@layerzerolabs/io-devtools/swag'
import { OAppOmniGraph } from '@layerzerolabs/ua-devtools'
import { createConnectedContractFactory, types } from '@layerzerolabs/devtools-evm-hardhat'
import { createOAppFactory } from '@layerzerolabs/ua-devtools-evm'
import { checkOAppEnforcedOptions } from '@layerzerolabs/ua-devtools'
import { validateAndTransformOappConfig } from '@/utils/taskHelpers'
import { getNetworkNameForEid } from '@layerzerolabs/devtools-evm-hardhat'
import { areVectorsEqual, isZero } from '@layerzerolabs/devtools'
import { Options } from '@layerzerolabs/lz-v2-utilities'

interface TaskArgs {
oappConfig: string
logLevel?: string
}

export const enforcedOptionsGet: ActionType<TaskArgs> = async ({ oappConfig: oappConfigPath, logLevel = 'info' }) => {
printLogo()

// We'll set the global logging level to get as much info as needed
setDefaultLogLevel(logLevel)

// And we'll create a logger for ourselves
const logger = createLogger()
const graph: OAppOmniGraph = await validateAndTransformOappConfig(oappConfigPath, logger)

// need points for OApp Peer Matrix
const points = graph.contracts
.map(({ point }) => point)
.map((point) => ({
...point,
networkName: getNetworkNameForEid(point.eid),
}))

// At this point we are ready read data from the OApp
const contractFactory = createConnectedContractFactory()
const oAppFactory = createOAppFactory(contractFactory)

try {
const enforcedOptions = await checkOAppEnforcedOptions(graph, oAppFactory)
const peerNetworkMatrix = points.map((row) => {
/**
* for each point in the network (referred to as 'row'), create a row in the matrix
*/
const connectionsForCurrentRow = points.reduce((tableRow, column) => {
/**
* find a peer with a vector matching the connection from 'column' to 'row'
*/
const connection = enforcedOptions.find((peer) => {
return areVectorsEqual(peer.vector, { from: column, to: row })
})
/**
* update the row with a key-value pair indicating the connection status for the current column
*/
const enforcedOptsByMsgType = {}
if (connection?.enforcedOptions) {
connection.enforcedOptions.forEach((option) => {
let enforcedOpts = {}
if (!isZero(option.options)) {
enforcedOpts = updateEnforcedOptsFromOptions(enforcedOpts, option)
enforcedOptsByMsgType['msgType: ' + option.msgType] = enforcedOpts
}
})
}

return {
...tableRow,
[column.networkName]: printRecord(enforcedOptsByMsgType),
}
}, {})

/**
* return the row representing connections for the current 'row'
*/
return connectionsForCurrentRow
})

console.log(printCrossTable(peerNetworkMatrix, ['from → to', ...points.map(({ networkName }) => networkName)]))

return enforcedOptions
} catch (error) {
throw new Error(`An error occurred while getting the OApp configuration: ${error}`)
}
}

task(TASK_LZ_OAPP_ENFORCED_OPTIONS_GET, 'Outputs table of OApp enforced options using layerzero.config')
.addParam('oappConfig', 'Path to your LayerZero OApp config', './layerzero.config.js', types.string)
sirarthurmoney marked this conversation as resolved.
Show resolved Hide resolved
.addParam('logLevel', 'Logging level. One of: error, warn, info, verbose, debug, silly', 'info', types.logLevel)
.setAction(enforcedOptionsGet)

/**
* Updates the enforced options object based on the provided encoded enforced options.
* @param enforcedOpts - The enforced options object to update.
* @param option - The encoded enforced options that needs to be decoded to extract enforced options.
* @returns The updated enforced options object.
*/
function updateEnforcedOptsFromOptions(enforcedOpts, option) {
const fromOptions = Options.fromOptions(option.options)
const lzReceiveOption = fromOptions.decodeExecutorLzReceiveOption()
const lzNativeDropOption = fromOptions.decodeExecutorNativeDropOption()
const lzComposeOption = fromOptions.decodeExecutorComposeOption()
const lzOrderedExecutionOption = fromOptions.decodeExecutorOrderedExecutionOption()

enforcedOpts = {
...enforcedOpts,
...(lzReceiveOption ? { lzReceiveOption } : {}),
...updateEnforcedOpts(enforcedOpts, 'lzNativeDropOption', lzNativeDropOption),
...updateEnforcedOpts(enforcedOpts, 'lzComposeOption', lzComposeOption),
...(lzOrderedExecutionOption ? { lzOrderedExecutionOption } : {}),
}

return enforcedOpts
}

/**
* Updates the enforced options for better readability.
* @param enforcedOpts - The enforced options object to update.
* @param optionName - The name of the option to update.
* @param optionValue - The value of the option to update.
* @returns The updated enforced options object.
*/
function updateEnforcedOpts(enforcedOpts, optionName, optionValue) {
if (optionValue && optionValue.length === 1) {
// If the option value is defined and has length 1, pop from array and keep as object
return { ...enforcedOpts, [optionName]: optionValue.pop() }
} else if (optionValue && optionValue.length > 1) {
// If the option value exists and has length greater than 1, keep it as an array
return { ...enforcedOpts, [optionName]: [...(enforcedOpts[optionName] || []), ...optionValue] }
} else {
// If the option value is not defined or has length 0, return the original enforcedOpts
return enforcedOpts
}
}
1 change: 1 addition & 0 deletions packages/ua-devtools-evm-hardhat/src/tasks/oapp/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import './config.check'
import './config.get.default'
import './config.get.executor'
import './config.get'
import './enforced.options.get'
import './config.init'
34 changes: 31 additions & 3 deletions packages/ua-devtools/src/oapp/check.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { OAppFactory, OAppOmniGraph, OAppPeers } from '@/oapp/types'
import { EncodedOption, OAppEnforcedOptions, OAppFactory, OAppOmniGraph, OAppPeers } from '@/oapp/types'
import { ExecutorOptionType } from '@layerzerolabs/lz-v2-utilities'

export type OAppRead = (graph: OAppOmniGraph, createSdk: OAppFactory) => Promise<OAppPeers[]>
export type OAppReadPeers = (graph: OAppOmniGraph, createSdk: OAppFactory) => Promise<OAppPeers[]>
export type OAppReadEnforcedOptions = (graph: OAppOmniGraph, createSdk: OAppFactory) => Promise<OAppEnforcedOptions[]>

export const checkOAppPeers: OAppRead = async (graph, createSdk): Promise<OAppPeers[]> => {
const EnforcedOptions: ExecutorOptionType[] = [
ExecutorOptionType.LZ_RECEIVE,
ExecutorOptionType.NATIVE_DROP,
ExecutorOptionType.COMPOSE,
ExecutorOptionType.ORDERED,
]

export const checkOAppPeers: OAppReadPeers = async (graph, createSdk): Promise<OAppPeers[]> => {
return await Promise.all(
graph.connections.map(async ({ vector }): Promise<OAppPeers> => {
const sdk = await createSdk(vector.from)
Expand All @@ -11,3 +20,22 @@ export const checkOAppPeers: OAppRead = async (graph, createSdk): Promise<OAppPe
})
)
}

export const checkOAppEnforcedOptions: OAppReadEnforcedOptions = async (
graph,
createSdk
): Promise<OAppEnforcedOptions[]> => {
return await Promise.all(
graph.connections.map(async ({ vector }): Promise<OAppEnforcedOptions> => {
const enforcedOptionsRead: EncodedOption[] = []
const oappSdk = await createSdk(vector.from)
for (const enforcedOption of EnforcedOptions) {
enforcedOptionsRead.push({
msgType: enforcedOption,
options: await oappSdk.getEnforcedOptions(vector.to.eid, enforcedOption),
})
}
return { vector: vector, enforcedOptions: enforcedOptionsRead }
})
)
}
6 changes: 5 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading