Skip to content

Commit

Permalink
feat(script): add shared utilities (#103)
Browse files Browse the repository at this point in the history
* feat: add shared utilities

* fix: correct representation of `instant finality`

* fix: also actual value

* Squashed commit of the following:

commit fad8f9e
Merge: 1639e2f eb77beb
Author: byeongsu-hong <[email protected]>
Date:   Fri Mar 1 23:21:15 2024 +0900

    Merge branch 'eddy/pick-docs' into eddy/pick-cw-hpl

commit 1639e2f
Author: byeongsu-hong <[email protected]>
Date:   Fri Mar 1 23:17:08 2024 +0900

    remove ts/sdk

commit d73647b
Author: byeongsu-hong <[email protected]>
Date:   Fri Mar 1 23:15:19 2024 +0900

    Revert "Merge branch 'main' into eddy/pick-cw-hpl"

    This reverts commit 82fc10f, reversing
    changes made to 6566e7a.

commit 82fc10f
Merge: 6566e7a be64967
Author: byeongsu-hong <[email protected]>
Date:   Fri Mar 1 23:14:05 2024 +0900

    Merge branch 'main' into eddy/pick-cw-hpl

commit be64967
Author: ByeongSu Hong <[email protected]>
Date:   Fri Mar 1 23:08:13 2024 +0900

    doc: documentation (#95)

    * wip

    * project structure & overview

    * toc

    * swap

    * fix(schema): reflect missing contracts

    * refactor(ts): migrate sdk - 1

    * refactor(script): pull back project setup to root

    * reorg script / cli

    * fix(script): make igp deployable

    * build: redeploy

    * build: stride hyperlane deployment

    * fix(hook): default gas denom

    * feat(script): add migrate command

    * chore: detailed ignore policy

    * feat(script): supprot mnemonic

    * chore(script): cleanup

    * chore: trailing comma

    * feat: add grpc endpoint as config

    * feat: generate agent config

    * feat(script): add test-dispatch

    * chore: redundant args

    * docs: owner -> <signer>

    * build: yarn berry

    * env: yarn

    * env: add cw-hpl command

    * feat: mailbox null-check

    * fix: prune imports

    * docs: wip guide & example

    * fix: rename compose file

    * fix: use localosmosis key

    * refactor: restruct guide

    * fix: remove DATA_PATH

    * fix: add `yarn install`

    * fix: handle rest endpoint not working

    * fix: use localwasmd

    * fix: hrp

    * feat: add wallet command

    * feat: wallet generator

    * fix: use osmosis testnet

    * line spacing

    * fix: xor

    * fix: split length

    * feat: more info to replace

    * fix: osmosis testnet network name

    * chore: ignore example

    * feat: add test recipient

    * fix: trouble shooting

    * docs: done

    * docs: update README.md

    * fix: line break

    * chore: remove testnet contexts

    * wip: neutron deployment

    * feat: context -> agent config

    * feat: apply review changes (#97)

    * docs: add context / example

    * fix: real instant finality

    * fix: typo

commit e8716c3
Author: ByeongSu Hong <[email protected]>
Date:   Fri Mar 1 19:57:30 2024 +0900

    review: docs (#98)

    * wip

    * project structure & overview

    * toc

    * swap

    * docs: owner -> <signer>

    * build: yarn berry

    * env: yarn

    * env: add cw-hpl command

    * docs: wip guide & example

    * fix: line break

    * fix: rename compose file

    * fix: use localosmosis key

    * refactor: restruct guide

    * fix: remove DATA_PATH

    * fix: add `yarn install`

    * fix: use localwasmd

    * fix: hrp

    * fix: use osmosis testnet

    * line spacing

    * feat: more info to replace

    * fix: osmosis testnet network name

    * chore: ignore example

    * docs: done

    * docs: update README.md

    * merge: remove conflicts

    * docs: move to root

    * docs: remove outdated docs

commit eb77beb
Author: byeongsu-hong <[email protected]>
Date:   Thu Feb 29 17:55:52 2024 +0900

    docs: remove outdated docs

commit 6a600c5
Author: byeongsu-hong <[email protected]>
Date:   Thu Feb 29 17:54:38 2024 +0900

    docs: move to root

commit 68074f0
Author: ByeongSu Hong <[email protected]>
Date:   Thu Feb 29 02:20:50 2024 +0900

    refactor: ts schema (#99)

    * fix(schema): reflect missing contracts

    * refactor(ts): migrate sdk - 1

commit 5896800
Author: byeongsu-hong <[email protected]>
Date:   Wed Feb 28 17:16:32 2024 +0900

    merge: remove conflicts

commit adb1852
Author: ByeongSu Hong <[email protected]>
Date:   Tue Feb 27 02:59:10 2024 +0900

    docs: update README.md

commit 19c6c60
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 02:57:59 2024 +0900

    docs: done

commit 5cdecaa
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 02:32:56 2024 +0900

    chore: ignore example

commit 28a5e69
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 02:21:21 2024 +0900

    fix: osmosis testnet network name

commit 57e78ea
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 02:18:23 2024 +0900

    feat: more info to replace

commit 56e2700
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 01:35:03 2024 +0900

    line spacing

commit b707b67
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 01:32:35 2024 +0900

    fix: use osmosis testnet

commit aa53d70
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 00:38:22 2024 +0900

    fix: hrp

commit bc1b84f
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 00:36:03 2024 +0900

    fix: use localwasmd

commit 7aaa751
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 00:04:08 2024 +0900

    fix: add `yarn install`

commit ca25459
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 23:56:19 2024 +0900

    fix: remove DATA_PATH

commit 82b5f59
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 23:49:25 2024 +0900

    refactor: restruct guide

commit df1a67c
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 22:32:48 2024 +0900

    fix: use localosmosis key

commit ef17165
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 22:26:51 2024 +0900

    fix: rename compose file

commit 1289770
Author: byeongsu-hong <[email protected]>
Date:   Tue Feb 27 03:00:17 2024 +0900

    fix: line break

commit 2604486
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 22:22:49 2024 +0900

    docs: wip guide & example

commit 2b4c5a1
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 21:21:24 2024 +0900

    env: add cw-hpl command

commit e43cfb3
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 21:21:14 2024 +0900

    env: yarn

commit 76313e8
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 20:49:06 2024 +0900

    build: yarn berry

commit 9dba0a4
Author: byeongsu-hong <[email protected]>
Date:   Mon Feb 26 20:44:20 2024 +0900

    docs: owner -> <signer>

commit 17200dc
Author: byeongsu-hong <[email protected]>
Date:   Wed Feb 14 18:50:16 2024 +0900

    swap

commit 50b01d7
Author: byeongsu-hong <[email protected]>
Date:   Wed Feb 14 18:42:09 2024 +0900

    toc

commit 6cde4c8
Author: byeongsu-hong <[email protected]>
Date:   Wed Feb 14 18:29:22 2024 +0900

    project structure & overview

commit cab7199
Author: byeongsu-hong <[email protected]>
Date:   Wed Feb 14 18:22:41 2024 +0900

    wip

* merge: cw-hpl (#110)

* refactor: ts schema (#99)

* fix(schema): reflect missing contracts

* refactor(ts): migrate sdk - 1

* review: docs (#98)

* wip

* project structure & overview

* toc

* swap

* docs: owner -> <signer>

* build: yarn berry

* env: yarn

* env: add cw-hpl command

* docs: wip guide & example

* fix: line break

* fix: rename compose file

* fix: use localosmosis key

* refactor: restruct guide

* fix: remove DATA_PATH

* fix: add `yarn install`

* fix: use localwasmd

* fix: hrp

* fix: use osmosis testnet

* line spacing

* feat: more info to replace

* fix: osmosis testnet network name

* chore: ignore example

* docs: done

* docs: update README.md

* merge: remove conflicts

* docs: move to root

* docs: remove outdated docs

* doc: documentation (#95)

* wip

* project structure & overview

* toc

* swap

* fix(schema): reflect missing contracts

* refactor(ts): migrate sdk - 1

* refactor(script): pull back project setup to root

* reorg script / cli

* fix(script): make igp deployable

* build: redeploy

* build: stride hyperlane deployment

* fix(hook): default gas denom

* feat(script): add migrate command

* chore: detailed ignore policy

* feat(script): supprot mnemonic

* chore(script): cleanup

* chore: trailing comma

* feat: add grpc endpoint as config

* feat: generate agent config

* feat(script): add test-dispatch

* chore: redundant args

* docs: owner -> <signer>

* build: yarn berry

* env: yarn

* env: add cw-hpl command

* feat: mailbox null-check

* fix: prune imports

* docs: wip guide & example

* fix: rename compose file

* fix: use localosmosis key

* refactor: restruct guide

* fix: remove DATA_PATH

* fix: add `yarn install`

* fix: handle rest endpoint not working

* fix: use localwasmd

* fix: hrp

* feat: add wallet command

* feat: wallet generator

* fix: use osmosis testnet

* line spacing

* fix: xor

* fix: split length

* feat: more info to replace

* fix: osmosis testnet network name

* chore: ignore example

* feat: add test recipient

* fix: trouble shooting

* docs: done

* docs: update README.md

* fix: line break

* chore: remove testnet contexts

* wip: neutron deployment

* feat: context -> agent config

* feat: apply review changes (#97)

* docs: add context / example

* fix: real instant finality

* fix: typo

* Revert "Merge branch 'main' into eddy/pick-cw-hpl"

This reverts commit 82fc10f, reversing
changes made to 6566e7a.

* remove ts/sdk

* merge: schema refactoring (#106)

* fix(schema): reflect missing contracts

* refactor(ts): migrate sdk - 1

* feat(script): initial config setup (#102)

feat: initial config setup

* merge: docs improvements (#108)

* wip

* project structure & overview

* toc

* swap

* docs: owner -> <signer>

* build: yarn berry

* env: yarn

* env: add cw-hpl command

* docs: wip guide & example

* fix: line break

* fix: rename compose file

* fix: use localosmosis key

* refactor: restruct guide

* fix: remove DATA_PATH

* fix: add `yarn install`

* fix: use localwasmd

* fix: hrp

* fix: use osmosis testnet

* line spacing

* feat: more info to replace

* fix: osmosis testnet network name

* chore: ignore example

* docs: done

* docs: update README.md

* merge: remove conflicts

* docs: move to root

* docs: remove outdated docs

* fix: apply code review
  • Loading branch information
byeongsu-hong authored Mar 8, 2024
1 parent 2f0149b commit a9fb19c
Show file tree
Hide file tree
Showing 9 changed files with 7,906 additions and 3,888 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"@cosmjs/proto-signing": "^0.32.2",
"@cosmjs/stargate": "^0.32.2",
"@cosmjs/tendermint-rpc": "^0.32.2",
"@hyperlane-xyz/sdk": "^3.7.0",
"@hyperlane-xyz/utils": "^3.7.0",
"axios": "^1.6.7",
"colors": "^1.4.0",
"commander": "^11.1.0",
Expand Down
123 changes: 123 additions & 0 deletions script/shared/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import path from "path";
import fs from "fs";
import { AgentConfig } from "@hyperlane-xyz/sdk";
import { ProtocolType } from "@hyperlane-xyz/utils";

import { Config } from "./config";
import { defaultContextPath } from "./constants";
import { Context, ContextHook } from "./context";
import { extractByte32AddrFromBech32 as fromBech32 } from "./utils";
import { getContractInfo } from "./wasm";

export async function fromContext(
network: Config["networks"][number],
context: Context
): Promise<AgentConfig> {
const { hooks, core } = context.deployments;

const mailboxAddr = core?.mailbox?.address!;
const mailboxContractInfo = await getContractInfo(network, mailboxAddr);

const igp =
findHook(hooks?.default!, "hpl_igp") ||
findHook(hooks?.required!, "hpl_igp");
if (!igp) throw new Error("no igp on this context");

const merkleTreeHook =
findHook(hooks?.default!, "hpl_hook_merkle") ||
findHook(hooks?.required!, "hpl_hook_merkle");
if (!merkleTreeHook) throw new Error("no merkle tree hook on this context");

const agent: AgentConfig = {
chains: {
[network.id.split("-").join("")]: {
name: network.id.split("-").join(""),
domainId: network.domain,
chainId: network.id,
protocol: ProtocolType.Cosmos,

rpcUrls: [{ http: network.endpoint.rpc }],
grpcUrls: [{ http: network.endpoint.grpc }],
canonicalAsset: network.gas.denom,
bech32Prefix: network.hrp,

gasPrice: {
amount: network.gas.price,
denom: network.gas.denom,
},
contractAddressBytes: 32,

index: {
from:
// sub 1 block to make sure we don't miss any block
parseInt(mailboxContractInfo.contract_info.created.block_height) -
1,
chunk: 10_000,
},
blocks: {
confirmations: 0,
reorgPeriod: 0,
},

// contract addresses
mailbox: fromBech32(core?.mailbox?.address!),
validatorAnnounce: fromBech32(core?.validator_announce?.address!),
interchainGasPaymaster: fromBech32(igp.address),
merkleTreeHook: fromBech32(merkleTreeHook.address),
},
},
};

return agent;
}

export async function saveAgentConfig(
network: Config["networks"][number],
context: Context,
{ contextPath }: { contextPath: string } = {
contextPath: defaultContextPath,
}
): Promise<AgentConfig> {
const agentConfig = await fromContext(network, context);
const fileName = path.join(contextPath, `${network.id}.config.json`);
fs.writeFileSync(fileName, JSON.stringify(agentConfig, null, 2));
return agentConfig;
}

// map filter reverse pop
function mfrpHooks(
hooks: ContextHook[],
want: ContextHook["type"]
): ContextHook | undefined {
return hooks
.map((v) => findHook(v, want))
.filter((v) => v !== undefined)
.reverse()
.pop();
}

function findHook(
hook: ContextHook,
want: ContextHook["type"]
): ContextHook | undefined {
if (hook.type === want) return hook;

switch (hook.type) {
case "hpl_hook_aggregate":
return mfrpHooks(hook.hooks, want);
case "hpl_hook_routing":
return mfrpHooks(Object.values(hook.hooks), want);
case "hpl_hook_routing_custom":
return mfrpHooks(
Object.values(hook.hooks)
.map((v) => Object.values(v))
.flat(),
want
);
case "hpl_hook_routing_fallback":
return mfrpHooks(Object.values(hook.hooks), want);

default:
return undefined;
}
}
7 changes: 7 additions & 0 deletions script/shared/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,10 @@ export const contractNames = [
"hpl_warp_cw20",
"hpl_warp_native",
];

export const REMOTE_REPO_NAME = "many-things/cw-hyperlane";
export const REMOTE_MIN_VERSION = "v0.0.6-rc8";

export const RELEASE_API_URL = `https://api.github.com/repos/${REMOTE_REPO_NAME}/releases`;
export const RELEASE_ARTIFACT_URL = (tag: string) =>
`https://github.com/${REMOTE_REPO_NAME}/releases/download/${tag}/cw-hyperlane-${tag}.zip`;
22 changes: 22 additions & 0 deletions script/shared/crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
HdPath,
Slip10,
Slip10Curve,
Bip39,
EnglishMnemonic,
Secp256k1,
} from "@cosmjs/crypto";

export const getKeyPair = async (
mnemonic: string,
hdPath: HdPath,
password?: string
) => {
const { privkey } = Slip10.derivePath(
Slip10Curve.Secp256k1,
await Bip39.mnemonicToSeed(new EnglishMnemonic(mnemonic), password),
hdPath
);
const { pubkey } = await Secp256k1.makeKeypair(privkey);
return { privkey, pubkey: Secp256k1.compressPubkey(pubkey) };
};
42 changes: 42 additions & 0 deletions script/shared/github.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as fs from "fs";
import path from "path";
import decompress from "decompress";

import { downloadFile } from "./utils";
import {
RELEASE_API_URL,
RELEASE_ARTIFACT_URL,
REMOTE_MIN_VERSION,
} from "./constants";

interface ReleaseApiResp {
tag_name: string;
}

export const getReleases = async (): Promise<Record<string, string>> => {
const apiResp = await fetch(RELEASE_API_URL);
const releases = (await apiResp.json()) as ReleaseApiResp[];

return Object.fromEntries(
releases
.map((v) => v.tag_name)
.filter((v) => v >= REMOTE_MIN_VERSION)
.map((v) => [v, RELEASE_ARTIFACT_URL(v)])
);
};

export const downloadReleases = async (
codeUrl: string,
outPath: string
): Promise<string> => {
const codeFile = path.join(outPath, "codes.zip");
const unzipPath = path.join(outPath, "codes");

if (fs.existsSync(codeFile)) fs.rmSync(codeFile);
if (fs.existsSync(unzipPath)) fs.rmSync(unzipPath, { recursive: true });

await downloadFile(codeUrl, codeFile);
await decompress(codeFile, unzipPath);

return unzipPath;
};
2 changes: 1 addition & 1 deletion script/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const withLink = (text: string, url: string) =>
export const extractByte32AddrFromBech32 = (addr: string): string => {
const { data } = fromBech32(addr);
const hexed = Buffer.from(data).toString("hex");
return hexed.length === 64 ? hexed : addPad(hexed);
return `0x${hexed.length === 64 ? hexed : addPad(hexed)}`;
};

export const downloadFile = async (url: string, dest: string) => {
Expand Down
70 changes: 70 additions & 0 deletions script/shared/wasm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import fs from "fs";
import path from "path";
import { defaultArtifactPath } from "./constants";
import { generateSha256 } from "./utils";
import { Config } from "./config";

function getWasmFilesPath(
{ artifactPath }: { artifactPath: string } = {
artifactPath: defaultArtifactPath,
}
): string[] {
try {
const files = fs.readdirSync(artifactPath);
return files
.filter((file) => file.endsWith(".wasm"))
.map((file) => path.join(artifactPath, file));
} catch (err) {
console.error(
"Cannot find wasm folder. Are you sure you compiled the wasm projects?"
);
process.exit(1);
}
}

export async function loadWasmFileDigest(
{ artifactPath }: { artifactPath: string } = {
artifactPath: defaultArtifactPath,
}
): Promise<Record<string, string>> {
return Object.fromEntries(
await Promise.all(getWasmFilesPath({ artifactPath }).map(generateSha256))
);
}

export function getWasmPath(
contractName: string,
{ artifactPath }: { artifactPath: string } = {
artifactPath: defaultArtifactPath,
}
): string {
return path.join(artifactPath, `${contractName}.wasm`);
}

export type ContractInfoResp = {
address: string;
contract_info: {
code_id: string;
creator: string;
admin?: string;
label: string;
created: {
block_height: string;
tx_index: string;
};
ibc_por_id?: string;
extension?: any;
};
};

export async function getContractInfo(
network: Config["networks"][number],
addr: string
): Promise<ContractInfoResp> {
const res = await fetch(
path.join(network.endpoint.rest, "/cosmwasm/wasm/v1/contract/", addr)
);
const body = await res.json();

return body as ContractInfoResp;
}
Loading

0 comments on commit a9fb19c

Please sign in to comment.