Skip to content

Commit

Permalink
chore: follow up from Jan's feedback
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Goulding <goulding@layerzerolabs.org>
  • Loading branch information
ryandgoulding committed Jan 26, 2024
1 parent 2ae50e2 commit e515462
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 238 deletions.
2 changes: 1 addition & 1 deletion packages/build-lz-options/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

## Create LayerZero OApp Options <img alt="Static Badge" src="https://img.shields.io/badge/status-work_in_progress-yellow">

The easiest way to get started with LayerZero smart contract development. This CLI tool enables you to quickly start building on top of LayerZero omnichain interoperability protocol. To get started, use the following command:
This package provides a convenient way to build and serialize Options for LayerZero OApps.

```bash
npx build-lz-options@latest
Expand Down
1 change: 1 addition & 0 deletions packages/build-lz-options/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "build-lz-options",
"version": "0.0.1",
"private": true,
"description": "Build LayerZero options with one command",
"keywords": [
"LayerZero",
Expand Down
16 changes: 12 additions & 4 deletions packages/build-lz-options/src/components/config.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import React from "react";
import { Box, Text } from "ink";
import { OptionType1, OptionConfig, OptionType2 } from "@/types";
import {
OptionType1Summary,
OptionTypeInput,
OptionType2Summary,
} from "@/types";

interface Props {
value: OptionConfig;
value: OptionTypeInput;
}

interface OptionType1Props {
props: OptionType1;
props: OptionType1Summary;
}

interface OptionType2Props extends OptionType1Props {
props: OptionType2;
props: OptionType2Summary;
}

export const ConfigSummary: React.FC<Props> = ({ value }) => {
Expand Down Expand Up @@ -39,7 +43,11 @@ export const Option2Summary: React.FC<OptionType2Props> = ({ props }) => {
<Box flexDirection="column" marginTop={1} marginBottom={1}>
<Text>
Gas Limit: <Text bold>{props.gasLimit}</Text>
</Text>
<Text>
Native Drop Amount: <Text bold>{props.nativeDropAmount}</Text>
</Text>
<Text>
Native Drop Address: <Text bold>{props.nativeDropAddress}</Text>
</Text>
</Box>
Expand Down
80 changes: 19 additions & 61 deletions packages/build-lz-options/src/components/outputOptions.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,24 @@
import { makeBytes32 } from "@layerzerolabs/devtools-evm";
import React, { useEffect } from "react";
import type { OptionType1, OptionType2, OptionType3 } from "@/types";
import { Box } from "ink";
import { useTask } from "@/utilities/tasks";
import { optionsType1, optionsType2 } from "@layerzerolabs/lz-utility-v2";
import React from "react";
import type { OptionOutput } from "@/types";
import { Box, Text } from "ink";

interface Props {
props: OptionType1;
interface OptionOutputProps {
props: OptionOutput;
}

export const outputOptionsType1 = async (gasLimit: OptionType1) => {
console.log(optionsType1(gasLimit.gasLimit));
};

export const OutputOptionsType1: React.FC<Props> = ({ props }) => {
const output = useTask(() => outputOptionsType1(props));

useEffect(() => {
output.run().catch(() => {});
}, [output.run]);

return <Box flexDirection="column"></Box>;
};

interface OptionsType2Props {
props: OptionType2;
}

const outputOptionsType2 = async (options: OptionType2) => {
console.log(
optionsType2(
options.gasLimit,
options.nativeDropAmount,
makeBytes32(options.nativeDropAddress),
),
/**
* Render the options output to the user.
* @param {OptionOutputProps} props
* @constructor
*/
export const OutputOptions: React.FC<OptionOutputProps> = ({
props,
}: OptionOutputProps) => {
return (
<Box flexDirection="column">
<Text>
Result: <Text color={"green"}>{props.hex}</Text>
</Text>
</Box>
);
};

export const OutputOptionsType2: React.FC<OptionsType2Props> = ({ props }) => {
const output = useTask(() => outputOptionsType2(props));

useEffect(() => {
output.run().catch(() => {});
}, [output.run]);

return <Box flexDirection="column"></Box>;
};

interface OptionsType3Props {
props: OptionType3;
}

const outputOptionsType3 = async (options: OptionType3) => {
console.log(options.output);
};

export const OutputOptionsType3: React.FC<OptionsType3Props> = ({ props }) => {
const output = useTask(() => outputOptionsType3(props));

useEffect(() => {
output.run().catch(() => {});
}, [output.run]);

return <Box flexDirection="column"></Box>;
};
6 changes: 3 additions & 3 deletions packages/build-lz-options/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import { ExecutorOptionType, WorkerId } from '@layerzerolabs/lz-utility-v2'
*/
export const OPTION_TYPES: OptionType[] = [
{
// TODO: use OptionType.TYPE_1 once exported from lz-utility-v2
// TODO: use OptionType.TYPE_1 once exported from lz-v2-utility
id: '1',
label: '1: gas for remote execution',
},
{
// TODO: use OptionType.TYPE_2 once exported from lz-utility-v2
// TODO: use OptionType.TYPE_2 once exported from lz-v2-utility
id: '2',
label: '2: gas for remote execution and native drop',
},
{
// TODO: use OptionType.TYPE_3 once exported from lz-utility-v2
// TODO: use OptionType.TYPE_3 once exported from lz-v2-utility
id: '3',
label: '3: options builder (EndpointV2 only)',
},
Expand Down
41 changes: 13 additions & 28 deletions packages/build-lz-options/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { makeBytes32 } from "@layerzerolabs/devtools-evm";
import { optionsType1, optionsType2 } from "@layerzerolabs/lz-utility-v2";
import React from "react";
import { render } from "ink";
import { Command } from "commander";
Expand All @@ -12,22 +14,19 @@ import {
Option1Summary,
Option2Summary,
} from "@/components/config";
import {
OutputOptionsType1,
OutputOptionsType2,
OutputOptionsType3,
} from "@/components/outputOptions";
import { OutputOptions } from "@/components/outputOptions";
import { printLogo } from "@layerzerolabs/io-devtools/swag";

new Command("build-lz-options")
.description("Create LayerZero OApp options with one command")
.action(async () => {
printLogo();

// First we get the config from the user
const config = await promptForOptionType();
render(<ConfigSummary value={config} />).unmount();

let output: string = "";

switch (config.type.id) {
case "1": {
const options = await promptForOptionType1();
Expand All @@ -38,13 +37,7 @@ new Command("build-lz-options")
}}
/>,
).unmount();
render(
<OutputOptionsType1
props={{
gasLimit: options.gasLimit,
}}
/>,
);
output = optionsType1(options.gasLimit);
break;
}
case "2": {
Expand All @@ -58,27 +51,19 @@ new Command("build-lz-options")
}}
/>,
).unmount();
render(
<OutputOptionsType2
props={{
gasLimit: options.gasLimit,
nativeDropAmount: options.nativeDropAmount,
nativeDropAddress: options.nativeDropAddress,
}}
/>,
output = optionsType2(
options.gasLimit,
options.nativeDropAmount,
makeBytes32(options.nativeDropAddress),
);
break;
}
case "3": {
const options = await promptForOptionType3();
render(
<OutputOptionsType3
props={{
output: options.toHex(),
}}
/>,
);
output = options.toHex();
break;
}
}
render(<OutputOptions props={{ hex: output }} />);
})
.parseAsync();
35 changes: 25 additions & 10 deletions packages/build-lz-options/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
export interface OptionConfig {
type: OptionType
}

/**
* Used to render OptionType input from the user.
*/
export interface OptionType {
id: string
label: string
}

export interface OptionType1 {
/**
* Input OptionType selection.
*/
export interface OptionTypeInput {
type: OptionType
}

/**
* The result of building an Option.
*/
export interface OptionOutput {
hex: string
}

/**
* Summary of OptionType.TYPE_1.
*/
export interface OptionType1Summary {
gasLimit: string
}

export interface OptionType2 extends OptionType1 {
/**
* Summary of OptionType.TYPE_2.
*/
export interface OptionType2Summary extends OptionType1Summary {
nativeDropAmount: string
nativeDropAddress: string
}

export interface OptionType3 {
output: string
}
60 changes: 36 additions & 24 deletions packages/build-lz-options/src/utilities/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { EXECUTOR_OPTION_TYPE, OPTION_TYPES, WORKER_TYPE } from '@/config'
import { OptionType1, OptionType2 } from '@/types'
import { OptionType1Summary, OptionType2Summary } from '@/types'
import { makeBytes32 } from '@layerzerolabs/devtools-evm'
import { ExecutorOptionType, Options, WorkerId } from '@layerzerolabs/lz-utility-v2'
import prompts, { PromptObject } from 'prompts'
import { handlePromptState, promptToContinue } from '@layerzerolabs/io-devtools'

// Max value of a Uint128 using a BigInt container.
const MAX_UINT_128 = BigInt(2) ** BigInt(128) - BigInt(1)
// Max value of a Uint8 using a number container.
const MAX_UINT_8 = 0xffff
// Default initial text number.
const DEFAULT_INITIAL_TEXT_NUMBER = BigInt('200000')

/**
Expand Down Expand Up @@ -140,23 +143,22 @@ const promptForExecutorOption = async (options: Options): Promise<Options> => {
const executorOptionType = await promptForExecutorOptionType()
switch (executorOptionType.type?.id) {
case ExecutorOptionType.LZ_RECEIVE: {
options = await promptExecutorLzReceiveOption(options)
break
return promptExecutorLzReceiveOption(options)
}
case ExecutorOptionType.NATIVE_DROP: {
options = await promptExecutorNativeDropOption(options)
break
return await promptExecutorNativeDropOption(options)
}
case ExecutorOptionType.COMPOSE: {
options = await promptExecutorComposeOption(options)
break
return await promptExecutorComposeOption(options)
}
case ExecutorOptionType.ORDERED: {
options = options.addExecutorOrderedExecutionOption()
break
return options.addExecutorOrderedExecutionOption()
}
default: {
// unreachable in normal operations
throw new Error(`Unsupported executor option type: ${executorOptionType.type?.id}`)
}
}
return options
}

const promptVerifierPrecrimeOption = async (options: Options): Promise<Options> => {
Expand All @@ -167,31 +169,41 @@ const promptVerifierPrecrimeOption = async (options: Options): Promise<Options>
/**
* Helper function to prompt for OptionType.TYPE_1.
*/
export const promptForOptionType1 = () => prompts([promptForGasLimit]) as never as Promise<OptionType1>
export const promptForOptionType1 = () => prompts([promptForGasLimit]) as never as Promise<OptionType1Summary>

/**
* Helper function to prompt for OptionType.TYPE_2.
*/
export const promptForOptionType2 = (): Promise<OptionType2> =>
prompts([promptForGasLimit, promptForNativeDropAmount, promptForNativeDropAddress]) as never as Promise<OptionType2>
export const promptForOptionType2 = (): Promise<OptionType2Summary> =>
prompts([
promptForGasLimit,
promptForNativeDropAmount,
promptForNativeDropAddress,
]) as never as Promise<OptionType2Summary>

const determineWorkerType = async (options: Options): Promise<Options> => {
const workerType = await promptForWorkerType()
switch (workerType.type?.id) {
case WorkerId.EXECUTOR: {
return promptForExecutorOption(options)
}
case WorkerId.VERIFIER: {
return promptVerifierPrecrimeOption(options)
}
default: {
// unreachable in normal operations
throw new Error(`Unsupported worker type: ${workerType.type?.id}`)
}
}
}

/**
* Helper function to prompt for OptionType.TYPE_3.
*/
export const promptForOptionType3 = async (): Promise<Options> => {
let options = Options.newOptions()
do {
const workerType = await promptForWorkerType()
switch (workerType.type.id) {
case WorkerId.EXECUTOR: {
options = await promptForExecutorOption(options)
break
}
case WorkerId.VERIFIER: {
options = await promptVerifierPrecrimeOption(options)
break
}
}
options = await determineWorkerType(options)
} while (await promptToContinue())
return options
}
Loading

0 comments on commit e515462

Please sign in to comment.