diff --git a/clients/js/Makefile b/clients/js/Makefile index dde51401a..51dcd3b4d 100644 --- a/clients/js/Makefile +++ b/clients/js/Makefile @@ -22,6 +22,9 @@ install: build .PHONY: test test: build +# This first invocation will set up the initial config, so that the warning +# doesn't show up in the tests + node build/main.js --version > /dev/null ./run_parse_tests clean: diff --git a/clients/js/cmds/update.ts b/clients/js/cmds/update.ts new file mode 100644 index 000000000..5a89fdbdb --- /dev/null +++ b/clients/js/cmds/update.ts @@ -0,0 +1,20 @@ +import { config } from '../config'; +import { spawnSync } from 'child_process'; + +let dir = `${config.wormholeDir}/clients/js`; + +exports.command = 'update'; +exports.desc = 'Update this tool by rebuilding it'; +exports.handler = function(_argv: any) { + if (isOutdated()) { + console.log(`Building in ${dir}...`); + spawnSync(`make build -C ${dir}`, { shell: true, stdio: 'inherit' }); + } else { + console.log("'worm' is up to date"); + } +} + +export function isOutdated(): boolean { + const result = spawnSync(`make build -C ${dir} --question`, { shell: true }); + return result.status !== 0; +} diff --git a/clients/js/config.ts b/clients/js/config.ts new file mode 100644 index 000000000..32398ecdc --- /dev/null +++ b/clients/js/config.ts @@ -0,0 +1,74 @@ +const CONFIG_DIR = `${process.env.HOME}/.wormhole`; +const CONFIG_FILE = `${CONFIG_DIR}/default.json`; + +process.env["NODE_CONFIG_DIR"] = CONFIG_DIR; +process.env["SUPPRESS_NO_CONFIG_WARNING"] = "y"; +import c from 'config'; +import fs from 'fs'; + +export interface Config { + // Path to the wormhole repository + wormholeDir: string; +} + +const defaultConfig: Required = { + wormholeDir: computeRepoRootPath(), +} + +/** + * Global config object. + * Importing this module will read the config file and update it if necessary. + */ +export const config: Readonly = readAndUpdateConfig(); + +// Computes the path to the root of the wormhole repository based on the +// location of this file (well, the compiled version of this file). +function computeRepoRootPath(): string { + let rel = "/clients/js/build/config.js"; + // check if mainPath matches $DIR/clients/js/build/config.js + if (__filename.endsWith(rel)) { + // if so, grab $DIR from mainPath + return __filename.substring(0, __filename.length - rel.length); + } else { + // otherwise, throw an error + throw new Error(`Could not compute repo root path for ${__filename}`); + } +} + +function readAndUpdateConfig(): Readonly { + if (config !== undefined) { + return config; + } + let conf = defaultConfig; + // iterate through all the keys in defaultConfig + for (const key in conf) { + // if the key is not in config, set it to the default value + if (c.has(key)) { + conf[key] = c.get(key); + } + } + + let json_conf = JSON.stringify(conf, null, 2) + "\n"; + + // if the config file does not exist or does not have some of the default + // values, create/update it + let write = false; + if (!fs.existsSync(CONFIG_FILE)) { + console.error('\x1b[33m%s\x1b[0m', `NOTE: Created config file at ${CONFIG_FILE}`); + write = true; + } else if (json_conf !== fs.readFileSync(CONFIG_FILE, "utf8")) { + // ^ this will also normalise the config file, but the main thing is + // that it writes out defaults if they are missing + console.error('\x1b[33m%s\x1b[0m', `NOTE: Updated config file at ${CONFIG_FILE}`); + write = true; + } + + if (write) { + if (!fs.existsSync(CONFIG_DIR)){ + fs.mkdirSync(CONFIG_DIR, { recursive: true }); + } + fs.writeFileSync(CONFIG_FILE, json_conf); + } + + return conf; +} diff --git a/clients/js/main.ts b/clients/js/main.ts index 03f1e6418..59786fb23 100644 --- a/clients/js/main.ts +++ b/clients/js/main.ts @@ -62,9 +62,14 @@ import base58 from "bs58"; import { execute_algorand } from "./algorand"; import { execute_injective } from "./injective"; import { execute_xpla } from "./xpla"; +import { isOutdated } from "./cmds/update"; setDefaultWasm("node"); +if (isOutdated()) { + console.error("\x1b[33m%s\x1b[0m", "WARNING: 'worm' is out of date. Run 'worm update' to update."); +} + const GOVERNANCE_CHAIN = 1; const GOVERNANCE_EMITTER = "0000000000000000000000000000000000000000000000000000000000000004"; @@ -92,6 +97,8 @@ function makeVAA( } yargs(hideBin(process.argv)) + //TODO(csongor): refactor all commands into the directory structure. + .commandDir('cmds') //////////////////////////////////////////////////////////////////////////////// // Generate .command( diff --git a/clients/js/package-lock.json b/clients/js/package-lock.json index b37fb3e29..d6395aa5b 100644 --- a/clients/js/package-lock.json +++ b/clients/js/package-lock.json @@ -16,6 +16,7 @@ "@injectivelabs/tx-ts": "^1.0.22", "@solana/web3.js": "^1.22.0", "@terra-money/terra.js": "^3.1.3", + "@types/config": "^3.3.0", "@xpla/xpla.js": "^0.2.1", "algosdk": "^1.15.0", "axios": "^0.24.0", @@ -23,6 +24,7 @@ "bn.js": "^5.2.0", "bs58": "^4.0.1", "buffer-layout": "^1.2.2", + "config": "^3.3.7", "dotenv": "^10.0.0", "ethers": "^5.6.8", "js-base64": "^3.6.1", @@ -695,9 +697,9 @@ } }, "node_modules/@certusone/wormhole-sdk/node_modules/near-api-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-1.0.0.tgz", - "integrity": "sha512-OYItaQIYlKK27FG5PrqqtkTI8Vv9TEOCi7gXePYigS4o6WofXciAXNjr4sihDJ8Vzi6s7+eEkf3zTNP3042FBw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-1.1.0.tgz", + "integrity": "sha512-qYKv1mYsaDZc2uYndhS+ttDhR9+60qFc+ZjD6lWsAxr3ZskMjRwPffDGQZYhC7BRDQMe1HEbk6d5mf+TVm0Lqg==", "dependencies": { "bn.js": "5.2.1", "borsh": "^0.7.0", @@ -2551,9 +2553,9 @@ } }, "node_modules/@injectivelabs/token-metadata": { - "version": "1.0.42", - "resolved": "https://registry.npmjs.org/@injectivelabs/token-metadata/-/token-metadata-1.0.42.tgz", - "integrity": "sha512-V53w/LV8qY45OhaGUy5J3oWsRNVwpfzHQS0vJEmcVeKvZ/erjjd8CXNHLQ+kD1vVlhQitpDqs7Bb6tq6I5ywug==", + "version": "1.0.46", + "resolved": "https://registry.npmjs.org/@injectivelabs/token-metadata/-/token-metadata-1.0.46.tgz", + "integrity": "sha512-FlyUFxPnIPW5sOhrL8zUA2+Pz4+vaCIXwo13JMtxU5oH8xyhijO4XVJwJzzlO5IU6WL85o8JG5rZqMkTFPrdxw==", "hasInstallScript": true, "dependencies": { "@injectivelabs/networks": "^1.0.32", @@ -3291,6 +3293,11 @@ "base-x": "^3.0.6" } }, + "node_modules/@types/config": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@types/config/-/config-3.3.0.tgz", + "integrity": "sha512-9kZSbl3/X3TVNowLCu5HFQdQmD+4287Om55avknEYkuo6R2dDrsp/EXEHUFvfYeG7m1eJ0WYGj+cbcUIhARJAQ==" + }, "node_modules/@types/connect": { "version": "3.4.35", "license": "MIT", @@ -4421,6 +4428,17 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "node_modules/config": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.7.tgz", + "integrity": "sha512-mX/n7GKDYZMqvvkY6e6oBY49W8wxdmQt+ho/5lhwFDXqQW9gI+Ahp8EKp8VAbISPnmf2+Bv5uZK7lKXZ6pf1aA==", + "dependencies": { + "json5": "^2.1.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -7081,9 +7099,9 @@ } }, "node_modules/google-protobuf": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.0.tgz", - "integrity": "sha512-byR7MBTK4tZ5PZEb+u5ZTzpt4SfrTxv5682MjPlHN16XeqgZE2/8HOIWeiXe8JKnT9OVbtBGhbq8mtvkK8cd5g==" + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" }, "node_modules/got": { "version": "9.6.0", @@ -7800,8 +7818,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "peer": true, "dependencies": { "minimist": "^1.2.5" }, @@ -14138,9 +14154,9 @@ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "near-api-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-1.0.0.tgz", - "integrity": "sha512-OYItaQIYlKK27FG5PrqqtkTI8Vv9TEOCi7gXePYigS4o6WofXciAXNjr4sihDJ8Vzi6s7+eEkf3zTNP3042FBw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-1.1.0.tgz", + "integrity": "sha512-qYKv1mYsaDZc2uYndhS+ttDhR9+60qFc+ZjD6lWsAxr3ZskMjRwPffDGQZYhC7BRDQMe1HEbk6d5mf+TVm0Lqg==", "requires": { "bn.js": "5.2.1", "borsh": "^0.7.0", @@ -15382,9 +15398,9 @@ } }, "@injectivelabs/token-metadata": { - "version": "1.0.42", - "resolved": "https://registry.npmjs.org/@injectivelabs/token-metadata/-/token-metadata-1.0.42.tgz", - "integrity": "sha512-V53w/LV8qY45OhaGUy5J3oWsRNVwpfzHQS0vJEmcVeKvZ/erjjd8CXNHLQ+kD1vVlhQitpDqs7Bb6tq6I5ywug==", + "version": "1.0.46", + "resolved": "https://registry.npmjs.org/@injectivelabs/token-metadata/-/token-metadata-1.0.46.tgz", + "integrity": "sha512-FlyUFxPnIPW5sOhrL8zUA2+Pz4+vaCIXwo13JMtxU5oH8xyhijO4XVJwJzzlO5IU6WL85o8JG5rZqMkTFPrdxw==", "requires": { "@injectivelabs/networks": "^1.0.32", "@injectivelabs/ts-types": "^1.0.13", @@ -16060,6 +16076,11 @@ "base-x": "^3.0.6" } }, + "@types/config": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@types/config/-/config-3.3.0.tgz", + "integrity": "sha512-9kZSbl3/X3TVNowLCu5HFQdQmD+4287Om55avknEYkuo6R2dDrsp/EXEHUFvfYeG7m1eJ0WYGj+cbcUIhARJAQ==" + }, "@types/connect": { "version": "3.4.35", "requires": { @@ -16981,6 +17002,14 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "config": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.7.tgz", + "integrity": "sha512-mX/n7GKDYZMqvvkY6e6oBY49W8wxdmQt+ho/5lhwFDXqQW9gI+Ahp8EKp8VAbISPnmf2+Bv5uZK7lKXZ6pf1aA==", + "requires": { + "json5": "^2.1.1" + } + }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -18998,9 +19027,9 @@ "dev": true }, "google-protobuf": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.0.tgz", - "integrity": "sha512-byR7MBTK4tZ5PZEb+u5ZTzpt4SfrTxv5682MjPlHN16XeqgZE2/8HOIWeiXe8JKnT9OVbtBGhbq8mtvkK8cd5g==" + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" }, "got": { "version": "9.6.0", @@ -19516,8 +19545,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "peer": true, "requires": { "minimist": "^1.2.5" } diff --git a/clients/js/package.json b/clients/js/package.json index 08edd8cb1..765938b7b 100644 --- a/clients/js/package.json +++ b/clients/js/package.json @@ -10,6 +10,7 @@ "@injectivelabs/tx-ts": "^1.0.22", "@solana/web3.js": "^1.22.0", "@terra-money/terra.js": "^3.1.3", + "@types/config": "^3.3.0", "@xpla/xpla.js": "^0.2.1", "algosdk": "^1.15.0", "axios": "^0.24.0", @@ -17,6 +18,7 @@ "bn.js": "^5.2.0", "bs58": "^4.0.1", "buffer-layout": "^1.2.2", + "config": "^3.3.7", "dotenv": "^10.0.0", "ethers": "^5.6.8", "js-base64": "^3.6.1",