execute_vaas.ts 3.6 KB

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