207 lines
6.4 KiB
TypeScript
207 lines
6.4 KiB
TypeScript
import "dotenv/config";
|
|
import * as os from "os"
|
|
import { SigningCosmWasmClient, InstantiateResult } from "@cosmjs/cosmwasm-stargate";
|
|
import { GasPrice } from "@cosmjs/stargate"
|
|
import { Secp256k1HdWallet } from "@cosmjs/amino";
|
|
import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx";
|
|
import * as fs from "fs";
|
|
import { readdirSync, } from "fs";
|
|
import * as util from 'util'
|
|
import { toUtf8 } from "@cosmjs/encoding";
|
|
|
|
import * as devnetConsts from "./devnet-consts.json"
|
|
|
|
if (process.env.INIT_SIGNERS === "undefined") {
|
|
let msg = `.env is missing. run "make contracts-tools-deps" to fetch.`
|
|
console.error(msg)
|
|
throw msg
|
|
}
|
|
|
|
const readFileAsync = util.promisify(fs.readFile);
|
|
|
|
/*
|
|
NOTE: Only append to this array: keeping the ordering is crucial, as the
|
|
contracts must be imported in a deterministic order so their addresses remain
|
|
deterministic.
|
|
*/
|
|
type ContractName = string
|
|
const artifacts: ContractName[] = [
|
|
"cw20_base.wasm",
|
|
"wormchain_accounting.wasm",
|
|
];
|
|
|
|
const ARTIFACTS_PATH = "../artifacts/"
|
|
/* Check that the artifact folder contains all the wasm files we expect and nothing else */
|
|
|
|
try {
|
|
const actual_artifacts = readdirSync(ARTIFACTS_PATH).filter((a) =>
|
|
a.endsWith(".wasm")
|
|
);
|
|
|
|
const missing_artifacts = artifacts.filter(
|
|
(a) => !actual_artifacts.includes(a)
|
|
);
|
|
if (missing_artifacts.length) {
|
|
console.log(
|
|
"Error during wormchain deployment. The following files are expected to be in the artifacts folder:"
|
|
);
|
|
missing_artifacts.forEach((file) => console.log(` - ${file}`));
|
|
console.log(
|
|
"Hint: the deploy script needs to run after the contracts have been built."
|
|
);
|
|
console.log(
|
|
"External binary blobs need to be manually added in tools/Dockerfile."
|
|
);
|
|
process.exit(1);
|
|
}
|
|
} catch (err) {
|
|
console.error(`${ARTIFACTS_PATH} cannot be read. Do you need to run "make contracts-deploy-setup"?`)
|
|
process.exit(1)
|
|
}
|
|
|
|
|
|
|
|
async function main() {
|
|
|
|
/* Set up cosmos client & wallet */
|
|
|
|
let host = devnetConsts.chains[3104].tendermintUrlLocal
|
|
if (os.hostname().includes("wormchain-deploy")) {
|
|
// running in tilt devnet
|
|
host = devnetConsts.chains[3104].tendermintUrlTilt
|
|
}
|
|
const denom = devnetConsts.chains[3104].addresses.native.denom
|
|
const mnemonic = devnetConsts.chains[3104].accounts.wormchainNodeOfGuardian0.mnemonic
|
|
const addressPrefix = "wormhole"
|
|
|
|
const w = await Secp256k1HdWallet.fromMnemonic(mnemonic, { prefix: addressPrefix })
|
|
|
|
|
|
const gas = GasPrice.fromString(`0${denom}`)
|
|
let cwc: SigningCosmWasmClient
|
|
try {
|
|
cwc = await SigningCosmWasmClient.connectWithSigner(host, w, { prefix: addressPrefix, gasPrice: gas })
|
|
} catch (e) {
|
|
let msg = `could not connect to wormchain host: ${host}`
|
|
if (e?.message) {
|
|
console.error(e.message)
|
|
}
|
|
throw msg
|
|
}
|
|
|
|
|
|
// there are several Cosmos chains in devnet, so check the config is as expected
|
|
let id = await cwc.getChainId()
|
|
if (id !== "wormchain") {
|
|
throw new Error(`Wormchain CosmWasmClient connection produced an unexpected chainID: ${id}`)
|
|
}
|
|
|
|
const signers = await w.getAccounts()
|
|
const signer = signers[0].address
|
|
console.log("wormchain contract deployer is: ", signer)
|
|
|
|
/* Deploy artifacts */
|
|
|
|
const codeIds: { [name: ContractName]: number } = await artifacts.reduce(async (prev, file) => {
|
|
// wait for the previous to finish, to avoid the race condition of wallet sequence mismatch.
|
|
const accum = await prev
|
|
|
|
const contract_bytes = await readFileAsync(`${ARTIFACTS_PATH}${file}`);
|
|
|
|
const i = await cwc.upload(signer, contract_bytes, "auto", "")
|
|
console.log(`uploaded ${file}, codeID: ${i.codeId}, tx: ${i.transactionHash}`, i.codeId, i.transactionHash)
|
|
|
|
accum[file] = i.codeId
|
|
return accum
|
|
}, Object())
|
|
|
|
// Instantiate contracts.
|
|
|
|
async function instantiate(code_id: number, inst_msg: any, label: string) {
|
|
let inst = await cwc.instantiate(signer, code_id, inst_msg, label, "auto", {})
|
|
let addr = inst.contractAddress
|
|
let txHash = inst.transactionHash
|
|
console.log(`deployed contract ${label}, codeID: ${code_id}, address: ${addr}, txHash: ${txHash}`)
|
|
|
|
return addr
|
|
}
|
|
|
|
// Instantiate contracts.
|
|
// NOTE: Only append at the end, the ordering must be deterministic.
|
|
|
|
const addresses: { [contractName: string]: InstantiateResult["transactionHash"] } = {};
|
|
|
|
const init_guardians: string[] = JSON.parse(String(process.env.INIT_SIGNERS));
|
|
if (!init_guardians || init_guardians.length === 0) {
|
|
throw "failed to get initial guardians from .env file.";
|
|
}
|
|
|
|
addresses["mock.wasm"] = await instantiate(
|
|
codeIds["cw20_base.wasm"],
|
|
{
|
|
name: "MOCK",
|
|
symbol: "MCK",
|
|
decimals: 6,
|
|
initial_balances: [
|
|
{
|
|
address: signer,
|
|
amount: "100000000",
|
|
},
|
|
],
|
|
mint: null,
|
|
},
|
|
"mock"
|
|
);
|
|
console.log('instantiated cw20 MOCK token: ', addresses["mock.wasm"])
|
|
|
|
|
|
const registrations: { [chainName: string]: string } = {
|
|
// keys are only used for logging success/failure
|
|
"solana": String(process.env.REGISTER_SOL_TOKEN_BRIDGE_VAA),
|
|
"ethereum": String(process.env.REGISTER_ETH_TOKEN_BRIDGE_VAA),
|
|
"bsc": String(process.env.REGISTER_BSC_TOKEN_BRIDGE_VAA),
|
|
"algo": String(process.env.REGISTER_ALGO_TOKEN_BRIDGE_VAA),
|
|
"terra": String(process.env.REGISTER_TERRA_TOKEN_BRIDGE_VAA),
|
|
"near": String(process.env.REGISTER_NEAR_TOKEN_BRIDGE_VAA),
|
|
"terra2": String(process.env.REGISTER_TERRA2_TOKEN_BRIDGE_VAA),
|
|
"aptos": String(process.env.REGISTER_APTOS_TOKEN_BRIDGE_VAA),
|
|
}
|
|
|
|
|
|
const instantiateMsg = {}
|
|
addresses["wormchain_accounting.wasm"] = await instantiate(
|
|
codeIds["wormchain_accounting.wasm"],
|
|
instantiateMsg,
|
|
"wormchainAccounting"
|
|
)
|
|
console.log("instantiated accounting: ", addresses["wormchain_accounting.wasm"])
|
|
|
|
const accountingRegistrations = Object.values(registrations)
|
|
.map(r => Buffer.from(r, "hex").toString("base64"))
|
|
|
|
const msg = {
|
|
typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract",
|
|
value: MsgExecuteContract.fromPartial({
|
|
sender: signer,
|
|
contract: addresses["wormchain_accounting.wasm"],
|
|
msg: toUtf8(JSON.stringify({
|
|
submit_v_a_as: {
|
|
vaas: accountingRegistrations,
|
|
}
|
|
}))
|
|
})
|
|
}
|
|
const res = await cwc.signAndBroadcast(signer, [msg], "auto");
|
|
console.log(`sent accounting chain registrations, tx: `, res.transactionHash);
|
|
|
|
}
|
|
|
|
try {
|
|
main()
|
|
} catch (e: any) {
|
|
if (e?.message) {
|
|
console.error(e.message)
|
|
}
|
|
throw e
|
|
}
|