Skip to content

Commit

Permalink
Create new CLI package (#2573)
Browse files Browse the repository at this point in the history
### Description

- Create new CLI package
- Upgrade prettier, typescript, and lint packages
- Update TSConfig output target to ES2020
- Migrate code from hyp-deploy repo to `typescript/cli/src`

### Related issues

Fixes #2566
Fixes #2786

### Backward compatibility

Yes

### Testing

Tested all commands locally
Tested core deployments with and without pre-existing addresses (artifacts)
Created e2e tests for deploying core, warp, and sending messages

---------

Co-authored-by: Nam Chu Hoai <[email protected]>
  • Loading branch information
jmrossy and nambrot authored Oct 14, 2023
1 parent 9b1824a commit fd48f13
Show file tree
Hide file tree
Showing 69 changed files with 3,836 additions and 493 deletions.
4 changes: 2 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@typescript-eslint/no-require-imports": ["warn"],
"@typescript-eslint/no-unused-vars": [
"error",
{
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
Expand All @@ -48,4 +48,4 @@
}
]
}
}
}
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ typescript/token @yorhodes @jmrossy @tkporter @aroralanuk
## Hello World
typescript/helloworld @yorhodes @nambrot

## CLI
typescript/cli @jmrossy @yorhodes

## Infra
typescript/infra @tkporter @nambrot
19 changes: 19 additions & 0 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,25 @@ jobs:
- name: infra
run: yarn workspace @hyperlane-xyz/infra run test

test-cli:
runs-on: ubuntu-latest
needs: [yarn-build]
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1

- uses: actions/cache@v3
with:
path: ./*
key: ${{ github.sha }}

- name: test
run: ./typescript/cli/ci-test.sh

test-env:
runs-on: ubuntu-latest
needs: [yarn-build]
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ COPY typescript/utils/package.json ./typescript/utils/
COPY typescript/sdk/package.json ./typescript/sdk/
COPY typescript/helloworld/package.json ./typescript/helloworld/
COPY typescript/token/package.json ./typescript/token/
COPY typescript/cli/package.json ./typescript/cli/
COPY typescript/infra/package.json ./typescript/infra/
COPY solidity/package.json ./solidity/

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
[codecov-badge]: https://img.shields.io/codecov/c/github/hyperlane-xyz/hyperlane-monorepo
[foundry]: https://getfoundry.sh/
[foundry-badge]: https://img.shields.io/badge/Built%20with-Foundry-FFDB1C.svg
[license]: https://opensource.org/licenses/MIT
[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg
[license]: https://www.apache.org/licenses/LICENSE-2.0
[license-badge]: https://img.shields.io/badge/License-Apache-blue.svg

## Versioning

Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
"description": "A yarn workspace of core Hyperlane packages",
"version": "0.0.0",
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^3.2.0",
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"eslint": "^8.16.0",
"eslint-config-prettier": "^8.5.0",
"eslint": "^8.43.0",
"eslint-config-prettier": "^8.8.0",
"husky": "^8.0.0",
"lint-staged": "^12.4.3",
"prettier": "^2.4.1"
"prettier": "^2.8.8"
},
"packageManager": "[email protected]",
"private": true,
Expand All @@ -37,6 +37,7 @@
"lodash": "^4.17.21",
"recursive-readdir": "^2.2.3",
"underscore": "^1.13",
"undici": "^5.11"
"undici": "^5.11",
"@trivago/prettier-plugin-sort-imports/@babel/parser": "^7.22.7"
}
}
9 changes: 5 additions & 4 deletions solidity/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "@hyperlane-xyz/core",
"description": "Core solidity contracts for Hyperlane",
"version": "1.5.1",
"version": "1.5.4-beta0",
"dependencies": {
"@eth-optimism/contracts": "^0.6.0",
"@hyperlane-xyz/utils": "1.5.1",
"@hyperlane-xyz/utils": "1.5.4-beta0",
"@openzeppelin/contracts": "^4.8.0",
"@openzeppelin/contracts-upgradeable": "^4.8.0"
},
Expand All @@ -18,7 +18,7 @@
"ethers": "^5.7.2",
"hardhat": "^2.16.1",
"hardhat-gas-reporter": "^1.0.9",
"prettier": "^2.4.1",
"prettier": "^2.8.8",
"prettier-plugin-solidity": "^1.0.0-beta.5",
"solhint": "^3.3.2",
"solhint-plugin-prettier": "^0.0.5",
Expand Down Expand Up @@ -56,5 +56,6 @@
"gas-ci": "yarn gas --check --tolerance 2 || (echo 'Manually update gas snapshot' && exit 1)",
"slither": "slither ."
},
"types": "dist/index.d.ts"
"types": "dist/index.d.ts",
"stableVersion": "1.5.3"
}
2 changes: 2 additions & 0 deletions typescript/cli/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
5 changes: 5 additions & 0 deletions typescript/cli/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"no-console": ["off"]
}
}
5 changes: 5 additions & 0 deletions typescript/cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.env*
/dist
/cache
/configs
/artifacts
57 changes: 57 additions & 0 deletions typescript/cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Hyperlane CLI

The Hyperlane CLI is a command-line tool written in Typescript that facilitates common operations on Hyperlane, such as deploying the core contracts and/or warp routes to new chains.

## Hyperlane overview

Hyperlane is an interchain messaging protocol that allows applications to communicate between blockchains.

Developers can use Hyperlane to share state between blockchains, allowing them to build interchain applications that live natively across multiple chains.

To read more about interchain applications, how the protocol works, and how to integrate with Hyperlane, please see the [documentation](https://docs.hyperlane.xyz).

## Setup

Node 16 or newer is required.

**Option 1: Global install:**

```bash
# Install with NPM
npm install -g @hyperlane-xyz/cli
# Or uninstall old versions
npm uninstall -g @hyperlane-xyz/cli
```

**Option 2: Temp install:**

```bash
# Run via NPM's npx command
npx @hyperlane-xyz/cli
# Or via Yarn's dlx command
yarn dlx @hyperlane-xyz/cli
```

**Option 3: Run from source:**

```bash
git clone https://github.com/hyperlane-xyz/hyperlane-monorepo.git
cd hyperlane-monorepo
yarn install && yarn build
cd typescript/cli
yarn hyperlane
```

## Common commands

View help: `hyperlane --help`

Create a core deployment config: `hyperlane config create`

Run hyperlane core deployments: `hyperlane deploy core`

Run warp route deployments: `hyperlane deploy warp`

View SDK contract addresses: `hyperlane chains addresses`

Send test message: `hyperlane send message`
164 changes: 164 additions & 0 deletions typescript/cli/ci-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
#!/usr/bin/env bash

# Optional cleanup for previous runs, useful when running locally
pkill -f anvil
docker ps -aq | xargs docker stop | xargs docker rm
rm -rf /tmp/anvil*
rm -rf /tmp/relayer

# Setup directories for anvil chains
for CHAIN in anvil1 anvil2
do
mkdir -p /tmp/$CHAIN /tmp/$CHAIN/state /tmp/$CHAIN/validator /tmp/relayer
chmod -R 777 /tmp/relayer /tmp/$CHAIN
done

# Optional: remove the --block-time 1 to speedup tests for local runs
anvil --chain-id 31337 -p 8545 --state /tmp/anvil1/state --block-time 1 > /dev/null &
anvil --chain-id 31338 -p 8555 --state /tmp/anvil2/state --block-time 1 > /dev/null &
sleep 1

set -e

echo "{}" > /tmp/empty-artifacts.json

echo "Deploying contracts to anvil1"
yarn workspace @hyperlane-xyz/cli run hyperlane deploy core \
--chains ./examples/anvil-chains.yaml \
--artifacts /tmp/empty-artifacts.json \
--out /tmp \
--ism ./examples/multisig-ism.yaml \
--origin anvil1 --remotes anvil2 \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--yes

CORE_ARTIFACTS_PATH=`find /tmp/core-deployment* -type f -exec ls -t1 {} + | head -1`

echo "Deploying contracts to anvil2"
yarn workspace @hyperlane-xyz/cli run hyperlane deploy core \
--chains ./examples/anvil-chains.yaml \
--artifacts $CORE_ARTIFACTS_PATH \
--out /tmp \
--ism ./examples/multisig-ism.yaml \
--origin anvil2 --remotes anvil1 \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--yes

CORE_ARTIFACTS_PATH=`find /tmp/core-deployment* -type f -exec ls -t1 {} + | head -1`
echo "Core artifacts:"
cat $CORE_ARTIFACTS_PATH

AGENT_CONFIG_FILENAME=`ls -t1 /tmp | grep agent-config | head -1`

echo "Deploying warp routes"
yarn workspace @hyperlane-xyz/cli run hyperlane deploy warp \
--chains ./examples/anvil-chains.yaml \
--core $CORE_ARTIFACTS_PATH \
--config ./examples/warp-tokens.yaml \
--out /tmp \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--yes

echo "Sending test message"
yarn workspace @hyperlane-xyz/cli run hyperlane send message \
--origin anvil1 \
--destination anvil2 \
--chains ./examples/anvil-chains.yaml \
--core $CORE_ARTIFACTS_PATH \
--quick \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
| tee /tmp/message1

MESSAGE1_ID=`cat /tmp/message1 | grep "Message ID" | grep -E -o '0x[0-9a-f]+'`
echo "Message 1 ID: $MESSAGE1_ID"

WARP_ARTIFACTS_FILE=`find /tmp/warp-deployment* -type f -exec ls -t1 {} + | head -1`
ANVIL1_ROUTER=`cat $WARP_ARTIFACTS_FILE | jq -r ".anvil1.router"`

echo "Sending test warp transfer"
yarn workspace @hyperlane-xyz/cli run hyperlane send transfer \
--origin anvil1 \
--destination anvil2 \
--chains ./examples/anvil-chains.yaml \
--core $CORE_ARTIFACTS_PATH \
--router $ANVIL1_ROUTER \
--type native \
--quick \
--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
| tee /tmp/message2

MESSAGE2_ID=`cat /tmp/message2 | grep "Message ID" | grep -E -o '0x[0-9a-f]+'`
echo "Message 2 ID: $MESSAGE2_ID"

if [[ $OSTYPE == 'darwin'* ]]; then
# Required because the -net=host driver only works on linux
DOCKER_CONNECTION_URL="http://host.docker.internal"
else
DOCKER_CONNECTION_URL="http://127.0.0.1"
fi

for i in "anvil1 8545 ANVIL1" "anvil2 8555 ANVIL2"
do
set -- $i
echo "Running validator on $1"
docker run \
--mount type=bind,source="/tmp",target=/data --net=host \
-e CONFIG_FILES=/data/${AGENT_CONFIG_FILENAME} -e HYP_VALIDATOR_ORIGINCHAINNAME=$1 \
-e HYP_VALIDATOR_REORGPERIOD=0 -e HYP_VALIDATOR_INTERVAL=1 \
-e HYP_BASE_CHAINS_${3}_CONNECTION_URL=${DOCKER_CONNECTION_URL}:${2} \
-e HYP_VALIDATOR_VALIDATOR_TYPE=hexKey \
-e HYP_VALIDATOR_VALIDATOR_KEY=0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 \
-e HYP_VALIDATOR_CHECKPOINTSYNCER_TYPE=localStorage \
-e HYP_VALIDATOR_CHECKPOINTSYNCER_PATH=/data/${1}/validator \
-e HYP_BASE_TRACING_LEVEL=debug -e HYP_BASE_TRACING_FMT=compact \
gcr.io/abacus-labs-dev/hyperlane-agent:main ./validator > /tmp/${1}/validator-logs.txt &
done

echo "Validator running, sleeping to let it sync"
sleep 15
echo "Done sleeping"

echo "Validator Announcement:"
cat /tmp/anvil1/validator/announcement.json

echo "Running relayer"
# Won't work on anything but linux due to -net=host
# Replace CONNECTION_URL with host.docker.internal on mac
docker run \
--mount type=bind,source="/tmp",target=/data --net=host \
-e CONFIG_FILES=/data/${AGENT_CONFIG_FILENAME} \
-e HYP_BASE_CHAINS_ANVIL1_CONNECTION_URL=${DOCKER_CONNECTION_URL}:8545 \
-e HYP_BASE_CHAINS_ANVIL2_CONNECTION_URL=${DOCKER_CONNECTION_URL}:8555 \
-e HYP_BASE_TRACING_LEVEL=debug -e HYP_BASE_TRACING_FMT=compact \
-e HYP_RELAYER_RELAYCHAINS=anvil1,anvil2 \
-e HYP_RELAYER_ALLOWLOCALCHECKPOINTSYNCERS=true -e HYP_RELAYER_DB=/data/relayer \
-e HYP_RELAYER_GASPAYMENTENFORCEMENT='[{"type":"none"}]' \
-e HYP_BASE_CHAINS_ANVIL1_SIGNER_TYPE=hexKey \
-e HYP_BASE_CHAINS_ANVIL1_SIGNER_KEY=0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 \
-e HYP_BASE_CHAINS_ANVIL2_SIGNER_TYPE=hexKey \
-e HYP_BASE_CHAINS_ANVIL2_SIGNER_KEY=0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97 \
gcr.io/abacus-labs-dev/hyperlane-agent:main ./relayer > /tmp/relayer/relayer-logs.txt &

sleep 5
echo "Done running relayer, checking message delivery statuses"

for i in "1 $MESSAGE1_ID" "2 $MESSAGE2_ID"
do
set -- $i
echo "Checking delivery status of $1: $2"
yarn workspace @hyperlane-xyz/cli run hyperlane status \
--id $2 \
--destination anvil2 \
--chains ./examples/anvil-chains.yaml \
--core $CORE_ARTIFACTS_PATH \
| tee /tmp/message-status-$1
if ! grep -q "$2 was delivered" /tmp/message-status-$1; then
echo "ERROR: Message $1 was not delivered"
exit 1
else
echo "Message $1 was delivered!"
fi
done

docker ps -aq | xargs docker stop | xargs docker rm
pkill -f anvil
Loading

0 comments on commit fd48f13

Please sign in to comment.