|
@@ -0,0 +1,162 @@
|
|
|
|
|
+import { LCDClient, MnemonicKey } from "@terra-money/terra.js";
|
|
|
|
|
+import {
|
|
|
|
|
+ MsgInstantiateContract,
|
|
|
|
|
+ MsgStoreCode,
|
|
|
|
|
+} from "@terra-money/terra.js";
|
|
|
|
|
+import { readFileSync } from "fs";
|
|
|
|
|
+import { Bech32, toHex } from "@cosmjs/encoding";
|
|
|
|
|
+import { zeroPad } from "ethers/lib/utils.js";
|
|
|
|
|
+import axios from "axios";
|
|
|
|
|
+import yargs from "yargs";
|
|
|
|
|
+import {hideBin} from "yargs/helpers";
|
|
|
|
|
+
|
|
|
|
|
+export const TERRA_GAS_PRICES_URL = "https://fcd.terra.dev/v1/txs/gas_prices";
|
|
|
|
|
+
|
|
|
|
|
+const argv = yargs(hideBin(process.argv))
|
|
|
|
|
+ .option('network', {
|
|
|
|
|
+ description: 'Which network to deploy to',
|
|
|
|
|
+ choices: ['mainnet', 'testnet', 'localterra'],
|
|
|
|
|
+ required: true
|
|
|
|
|
+ })
|
|
|
|
|
+ .option('artifact', {
|
|
|
|
|
+ description: 'Which WASM file to deploy',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ required: true
|
|
|
|
|
+ })
|
|
|
|
|
+ .option('mnemonic', {
|
|
|
|
|
+ description: 'Mnemonic (private key)',
|
|
|
|
|
+ type: 'string',
|
|
|
|
|
+ required: true
|
|
|
|
|
+ })
|
|
|
|
|
+ .help()
|
|
|
|
|
+ .alias('help', 'h').argv;
|
|
|
|
|
+
|
|
|
|
|
+const artifact = argv.artifact;
|
|
|
|
|
+
|
|
|
|
|
+/* Set up terra client & wallet */
|
|
|
|
|
+
|
|
|
|
|
+const terra_host =
|
|
|
|
|
+ argv.network === "mainnet"
|
|
|
|
|
+ ? {
|
|
|
|
|
+ URL: "https://lcd.terra.dev",
|
|
|
|
|
+ chainID: "columbus-5",
|
|
|
|
|
+ name: "mainnet",
|
|
|
|
|
+ }
|
|
|
|
|
+ : argv.network === "testnet"
|
|
|
|
|
+ ? {
|
|
|
|
|
+ URL: "https://bombay-lcd.terra.dev",
|
|
|
|
|
+ chainID: "bombay-12",
|
|
|
|
|
+ name: "testnet",
|
|
|
|
|
+ }
|
|
|
|
|
+ : {
|
|
|
|
|
+ URL: "http://localhost:1317",
|
|
|
|
|
+ chainID: "columbus-5",
|
|
|
|
|
+ name: "localterra",
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+const lcd = new LCDClient(terra_host);
|
|
|
|
|
+
|
|
|
|
|
+const feeDenoms = ["uluna"];
|
|
|
|
|
+
|
|
|
|
|
+const gasPrices = await axios
|
|
|
|
|
+ .get(TERRA_GAS_PRICES_URL)
|
|
|
|
|
+ .then((result) => result.data);
|
|
|
|
|
+
|
|
|
|
|
+const wallet = lcd.wallet(
|
|
|
|
|
+ new MnemonicKey({
|
|
|
|
|
+ mnemonic: argv.mnemonic
|
|
|
|
|
+ })
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+await wallet.sequence();
|
|
|
|
|
+
|
|
|
|
|
+/* Deploy artifacts */
|
|
|
|
|
+
|
|
|
|
|
+let codeId;
|
|
|
|
|
+const contract_bytes = readFileSync(artifact);
|
|
|
|
|
+console.log(`Storing WASM: ${artifact} (${contract_bytes.length} bytes)`);
|
|
|
|
|
+
|
|
|
|
|
+const store_code = new MsgStoreCode(
|
|
|
|
|
+ wallet.key.accAddress,
|
|
|
|
|
+ contract_bytes.toString("base64")
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+const feeEstimate = await lcd.tx.estimateFee(
|
|
|
|
|
+ wallet.key.accAddress,
|
|
|
|
|
+ [store_code],
|
|
|
|
|
+ {
|
|
|
|
|
+ memo: "",
|
|
|
|
|
+ feeDenoms,
|
|
|
|
|
+ gasPrices,
|
|
|
|
|
+ }
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+console.log("Deploy fee: ", feeEstimate.amount.toString());
|
|
|
|
|
+
|
|
|
|
|
+const tx = await wallet.createAndSignTx({
|
|
|
|
|
+ msgs: [store_code],
|
|
|
|
|
+ memo: "",
|
|
|
|
|
+ feeDenoms,
|
|
|
|
|
+ gasPrices,
|
|
|
|
|
+ fee: feeEstimate,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const rs = await lcd.tx.broadcast(tx);
|
|
|
|
|
+const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1];
|
|
|
|
|
+codeId = parseInt(ci);
|
|
|
|
|
+
|
|
|
|
|
+console.log("Code ID: ", codeId);
|
|
|
|
|
+
|
|
|
|
|
+/* Instantiate contracts.
|
|
|
|
|
+ *
|
|
|
|
|
+ * We instantiate the core contracts here (i.e. wormhole itself and the bridge contracts).
|
|
|
|
|
+ * The wrapped asset contracts don't need to be instantiated here, because those
|
|
|
|
|
+ * will be instantiated by the on-chain bridge contracts on demand.
|
|
|
|
|
+ * */
|
|
|
|
|
+async function instantiate(codeId, inst_msg) {
|
|
|
|
|
+ var address;
|
|
|
|
|
+ await wallet
|
|
|
|
|
+ .createAndSignTx({
|
|
|
|
|
+ msgs: [
|
|
|
|
|
+ new MsgInstantiateContract(
|
|
|
|
|
+ wallet.key.accAddress,
|
|
|
|
|
+ wallet.key.accAddress,
|
|
|
|
|
+ codeId,
|
|
|
|
|
+ inst_msg
|
|
|
|
|
+ ),
|
|
|
|
|
+ ],
|
|
|
|
|
+ memo: "",
|
|
|
|
|
+ })
|
|
|
|
|
+ .then((tx) => lcd.tx.broadcast(tx))
|
|
|
|
|
+ .then((rs) => {
|
|
|
|
|
+ address = /"contract_address","value":"([^"]+)/gm.exec(rs.raw_log)[1];
|
|
|
|
|
+ });
|
|
|
|
|
+ console.log(`Instantiated ${contract} at ${address} (${convert_terra_address_to_hex(address)})`);
|
|
|
|
|
+ return address;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// example usage of instantiate:
|
|
|
|
|
+
|
|
|
|
|
+// const contractAddress = await instantiate("wormhole.wasm", {
|
|
|
|
|
+// gov_chain: govChain,
|
|
|
|
|
+// gov_address: Buffer.from(govAddress, "hex").toString("base64"),
|
|
|
|
|
+// guardian_set_expirity: 86400,
|
|
|
|
|
+// initial_guardian_set: {
|
|
|
|
|
+// addresses: [
|
|
|
|
|
+// {
|
|
|
|
|
+// bytes: Buffer.from(
|
|
|
|
|
+// "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe",
|
|
|
|
|
+// "hex"
|
|
|
|
|
+// ).toString("base64"),
|
|
|
|
|
+// },
|
|
|
|
|
+// ],
|
|
|
|
|
+// expiration_time: 0,
|
|
|
|
|
+// },
|
|
|
|
|
+// });
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// Terra addresses are "human-readable", but for cross-chain registrations, we
|
|
|
|
|
+// want the "canonical" version
|
|
|
|
|
+function convert_terra_address_to_hex(human_addr) {
|
|
|
|
|
+ return "0x" + toHex(zeroPad(Bech32.decode(human_addr).data, 32));
|
|
|
|
|
+}
|