deploy_single.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import { LCDClient, MnemonicKey } from "@terra-money/terra.js";
  2. import {
  3. MsgInstantiateContract,
  4. MsgStoreCode,
  5. } from "@terra-money/terra.js";
  6. import { readFileSync } from "fs";
  7. import { Bech32, toHex } from "@cosmjs/encoding";
  8. import { zeroPad } from "ethers/lib/utils.js";
  9. import axios from "axios";
  10. import yargs from "yargs";
  11. import {hideBin} from "yargs/helpers";
  12. export const TERRA_GAS_PRICES_URL = "https://fcd.terra.dev/v1/txs/gas_prices";
  13. const argv = yargs(hideBin(process.argv))
  14. .option('network', {
  15. description: 'Which network to deploy to',
  16. choices: ['mainnet', 'testnet', 'localterra'],
  17. required: true
  18. })
  19. .option('artifact', {
  20. description: 'Which WASM file to deploy',
  21. type: 'string',
  22. required: true
  23. })
  24. .option('mnemonic', {
  25. description: 'Mnemonic (private key)',
  26. type: 'string',
  27. required: true
  28. })
  29. .help()
  30. .alias('help', 'h').argv;
  31. const artifact = argv.artifact;
  32. /* Set up terra client & wallet */
  33. const terra_host =
  34. argv.network === "mainnet"
  35. ? {
  36. URL: "https://lcd.terra.dev",
  37. chainID: "columbus-5",
  38. name: "mainnet",
  39. }
  40. : argv.network === "testnet"
  41. ? {
  42. URL: "https://bombay-lcd.terra.dev",
  43. chainID: "bombay-12",
  44. name: "testnet",
  45. }
  46. : {
  47. URL: "http://localhost:1317",
  48. chainID: "columbus-5",
  49. name: "localterra",
  50. };
  51. const lcd = new LCDClient(terra_host);
  52. const feeDenoms = ["uluna"];
  53. const gasPrices = await axios
  54. .get(TERRA_GAS_PRICES_URL)
  55. .then((result) => result.data);
  56. const wallet = lcd.wallet(
  57. new MnemonicKey({
  58. mnemonic: argv.mnemonic
  59. })
  60. );
  61. await wallet.sequence();
  62. /* Deploy artifacts */
  63. let codeId;
  64. const contract_bytes = readFileSync(artifact);
  65. console.log(`Storing WASM: ${artifact} (${contract_bytes.length} bytes)`);
  66. const store_code = new MsgStoreCode(
  67. wallet.key.accAddress,
  68. contract_bytes.toString("base64")
  69. );
  70. const feeEstimate = await lcd.tx.estimateFee(
  71. wallet.key.accAddress,
  72. [store_code],
  73. {
  74. memo: "",
  75. feeDenoms,
  76. gasPrices,
  77. }
  78. );
  79. console.log("Deploy fee: ", feeEstimate.amount.toString());
  80. const tx = await wallet.createAndSignTx({
  81. msgs: [store_code],
  82. memo: "",
  83. feeDenoms,
  84. gasPrices,
  85. fee: feeEstimate,
  86. });
  87. const rs = await lcd.tx.broadcast(tx);
  88. const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1];
  89. codeId = parseInt(ci);
  90. console.log("Code ID: ", codeId);
  91. /* Instantiate contracts.
  92. *
  93. * We instantiate the core contracts here (i.e. wormhole itself and the bridge contracts).
  94. * The wrapped asset contracts don't need to be instantiated here, because those
  95. * will be instantiated by the on-chain bridge contracts on demand.
  96. * */
  97. async function instantiate(codeId, inst_msg) {
  98. var address;
  99. await wallet
  100. .createAndSignTx({
  101. msgs: [
  102. new MsgInstantiateContract(
  103. wallet.key.accAddress,
  104. wallet.key.accAddress,
  105. codeId,
  106. inst_msg
  107. ),
  108. ],
  109. memo: "",
  110. })
  111. .then((tx) => lcd.tx.broadcast(tx))
  112. .then((rs) => {
  113. address = /"contract_address","value":"([^"]+)/gm.exec(rs.raw_log)[1];
  114. });
  115. console.log(`Instantiated ${contract} at ${address} (${convert_terra_address_to_hex(address)})`);
  116. return address;
  117. }
  118. // example usage of instantiate:
  119. // const contractAddress = await instantiate("wormhole.wasm", {
  120. // gov_chain: govChain,
  121. // gov_address: Buffer.from(govAddress, "hex").toString("base64"),
  122. // guardian_set_expirity: 86400,
  123. // initial_guardian_set: {
  124. // addresses: [
  125. // {
  126. // bytes: Buffer.from(
  127. // "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe",
  128. // "hex"
  129. // ).toString("base64"),
  130. // },
  131. // ],
  132. // expiration_time: 0,
  133. // },
  134. // });
  135. // Terra addresses are "human-readable", but for cross-chain registrations, we
  136. // want the "canonical" version
  137. function convert_terra_address_to_hex(human_addr) {
  138. return "0x" + toHex(zeroPad(Bech32.decode(human_addr).data, 32));
  139. }