execute_vaas.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import yargs from "yargs";
  2. import { hideBin } from "yargs/helpers";
  3. import { parseVaa } from "@certusone/wormhole-sdk";
  4. import { decodeGovernancePayload } from "@pythnetwork/xc-admin-common";
  5. import { COMMON_DEPLOY_OPTIONS } from "./common";
  6. import { Vault } from "../src/node/utils/governance";
  7. import { toPrivateKey } from "../src/core/base";
  8. import { SubmittedWormholeMessage } from "../src/node/utils/governance";
  9. import { executeVaa } from "../src/node/utils/executor";
  10. import { DefaultStore } from "../src/node/utils/store";
  11. const parser = yargs(hideBin(process.argv))
  12. .usage(
  13. "Tries to execute all vaas on a vault.\n" +
  14. "Useful for batch upgrades.\n" +
  15. "Usage: $0 --vault <mainnet|devnet> --private-key <private-key> (--offset <offset> | --sequence <sequence>) [--dryrun]",
  16. )
  17. .options({
  18. vault: {
  19. type: "string",
  20. default: "mainnet",
  21. choices: ["mainnet", "devnet"],
  22. desc: "Which vault to use for fetching VAAs",
  23. },
  24. "private-key": COMMON_DEPLOY_OPTIONS["private-key"],
  25. offset: {
  26. type: "number",
  27. desc: "Offset to use from the last executed sequence number",
  28. conflicts: ["sequence"],
  29. },
  30. sequence: {
  31. type: "number",
  32. desc: "Specific sequence number to execute",
  33. conflicts: ["offset"],
  34. },
  35. dryrun: {
  36. type: "boolean",
  37. default: false,
  38. desc: "Whether to execute the VAAs or just print them",
  39. },
  40. })
  41. .check((argv) => {
  42. if (!argv.offset && !argv.sequence) {
  43. throw new Error("Either --offset or --sequence must be provided");
  44. }
  45. return true;
  46. });
  47. async function main() {
  48. const argv = await parser.argv;
  49. let vault: Vault;
  50. if (argv.vault === "mainnet") {
  51. vault =
  52. DefaultStore.vaults[
  53. "mainnet-beta_FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj"
  54. ];
  55. } else {
  56. vault =
  57. DefaultStore.vaults[
  58. "devnet_6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3"
  59. ];
  60. }
  61. console.log("Executing VAAs for vault", vault.getId());
  62. console.log(
  63. "Executing VAAs for emitter",
  64. (await vault.getEmitter()).toBase58(),
  65. );
  66. let startSequenceNumber: number;
  67. let endSequenceNumber: number;
  68. if (argv.sequence !== undefined) {
  69. startSequenceNumber = argv.sequence;
  70. endSequenceNumber = argv.sequence;
  71. } else if (argv.offset !== undefined) {
  72. const lastSequenceNumber = await vault.getLastSequenceNumber();
  73. startSequenceNumber = lastSequenceNumber - argv.offset;
  74. endSequenceNumber = lastSequenceNumber;
  75. } else {
  76. // this is unreachable but it makes the typescript linter happy.
  77. throw new Error("Either --offset or --sequence must be provided");
  78. }
  79. console.log(
  80. `Going from sequence number ${startSequenceNumber} to ${endSequenceNumber}`,
  81. );
  82. for (
  83. let seqNumber = startSequenceNumber;
  84. seqNumber <= endSequenceNumber;
  85. seqNumber++
  86. ) {
  87. const submittedWormholeMessage = new SubmittedWormholeMessage(
  88. await vault.getEmitter(),
  89. seqNumber,
  90. vault.cluster,
  91. );
  92. const vaa = await submittedWormholeMessage.fetchVaa();
  93. const decodedAction = decodeGovernancePayload(parseVaa(vaa).payload);
  94. if (!decodedAction) {
  95. console.log("Skipping unknown action for vaa ", seqNumber);
  96. continue;
  97. }
  98. console.log("Executing vaa", seqNumber);
  99. console.log(decodedAction);
  100. if (!argv.dryrun) {
  101. await executeVaa(toPrivateKey(argv["private-key"]), vaa);
  102. }
  103. }
  104. }
  105. main();