@gzeoneth/gov-tracker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +201 -0
  3. package/dist/abis.d.ts +79 -0
  4. package/dist/abis.d.ts.map +1 -0
  5. package/dist/abis.js +159 -0
  6. package/dist/abis.js.map +1 -0
  7. package/dist/cli/lib/cli.d.ts +92 -0
  8. package/dist/cli/lib/cli.d.ts.map +1 -0
  9. package/dist/cli/lib/cli.js +562 -0
  10. package/dist/cli/lib/cli.js.map +1 -0
  11. package/dist/cli/lib/election-check.d.ts +46 -0
  12. package/dist/cli/lib/election-check.d.ts.map +1 -0
  13. package/dist/cli/lib/election-check.js +136 -0
  14. package/dist/cli/lib/election-check.js.map +1 -0
  15. package/dist/cli/lib/json-state.d.ts +100 -0
  16. package/dist/cli/lib/json-state.d.ts.map +1 -0
  17. package/dist/cli/lib/json-state.js +225 -0
  18. package/dist/cli/lib/json-state.js.map +1 -0
  19. package/dist/cli/monitor.d.ts +3 -0
  20. package/dist/cli/monitor.d.ts.map +1 -0
  21. package/dist/cli/monitor.js +442 -0
  22. package/dist/cli/monitor.js.map +1 -0
  23. package/dist/constants.d.ts +235 -0
  24. package/dist/constants.d.ts.map +1 -0
  25. package/dist/constants.js +293 -0
  26. package/dist/constants.js.map +1 -0
  27. package/dist/discovery/governor-discovery.d.ts +84 -0
  28. package/dist/discovery/governor-discovery.d.ts.map +1 -0
  29. package/dist/discovery/governor-discovery.js +310 -0
  30. package/dist/discovery/governor-discovery.js.map +1 -0
  31. package/dist/discovery/security-council.d.ts +68 -0
  32. package/dist/discovery/security-council.d.ts.map +1 -0
  33. package/dist/discovery/security-council.js +181 -0
  34. package/dist/discovery/security-council.js.map +1 -0
  35. package/dist/discovery/timelock-discovery.d.ts +99 -0
  36. package/dist/discovery/timelock-discovery.d.ts.map +1 -0
  37. package/dist/discovery/timelock-discovery.js +322 -0
  38. package/dist/discovery/timelock-discovery.js.map +1 -0
  39. package/dist/election.d.ts +172 -0
  40. package/dist/election.d.ts.map +1 -0
  41. package/dist/election.js +464 -0
  42. package/dist/election.js.map +1 -0
  43. package/dist/index.d.ts +56 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +164 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/stages/base.d.ts +127 -0
  48. package/dist/stages/base.d.ts.map +1 -0
  49. package/dist/stages/base.js +280 -0
  50. package/dist/stages/base.js.map +1 -0
  51. package/dist/stages/l2-to-l1-message.d.ts +108 -0
  52. package/dist/stages/l2-to-l1-message.d.ts.map +1 -0
  53. package/dist/stages/l2-to-l1-message.js +422 -0
  54. package/dist/stages/l2-to-l1-message.js.map +1 -0
  55. package/dist/stages/proposal-created.d.ts +20 -0
  56. package/dist/stages/proposal-created.d.ts.map +1 -0
  57. package/dist/stages/proposal-created.js +62 -0
  58. package/dist/stages/proposal-created.js.map +1 -0
  59. package/dist/stages/proposal-queued.d.ts +39 -0
  60. package/dist/stages/proposal-queued.d.ts.map +1 -0
  61. package/dist/stages/proposal-queued.js +131 -0
  62. package/dist/stages/proposal-queued.js.map +1 -0
  63. package/dist/stages/retryables.d.ts +79 -0
  64. package/dist/stages/retryables.d.ts.map +1 -0
  65. package/dist/stages/retryables.js +307 -0
  66. package/dist/stages/retryables.js.map +1 -0
  67. package/dist/stages/stage-builder.d.ts +46 -0
  68. package/dist/stages/stage-builder.d.ts.map +1 -0
  69. package/dist/stages/stage-builder.js +87 -0
  70. package/dist/stages/stage-builder.js.map +1 -0
  71. package/dist/stages/timelock.d.ts +100 -0
  72. package/dist/stages/timelock.d.ts.map +1 -0
  73. package/dist/stages/timelock.js +552 -0
  74. package/dist/stages/timelock.js.map +1 -0
  75. package/dist/stages/voting.d.ts +18 -0
  76. package/dist/stages/voting.d.ts.map +1 -0
  77. package/dist/stages/voting.js +109 -0
  78. package/dist/stages/voting.js.map +1 -0
  79. package/dist/tracker/context.d.ts +111 -0
  80. package/dist/tracker/context.d.ts.map +1 -0
  81. package/dist/tracker/context.js +264 -0
  82. package/dist/tracker/context.js.map +1 -0
  83. package/dist/tracker/discovery.d.ts +89 -0
  84. package/dist/tracker/discovery.d.ts.map +1 -0
  85. package/dist/tracker/discovery.js +228 -0
  86. package/dist/tracker/discovery.js.map +1 -0
  87. package/dist/tracker/execute.d.ts +44 -0
  88. package/dist/tracker/execute.d.ts.map +1 -0
  89. package/dist/tracker/execute.js +126 -0
  90. package/dist/tracker/execute.js.map +1 -0
  91. package/dist/tracker/index.d.ts +18 -0
  92. package/dist/tracker/index.d.ts.map +1 -0
  93. package/dist/tracker/index.js +70 -0
  94. package/dist/tracker/index.js.map +1 -0
  95. package/dist/tracker/pipeline.d.ts +47 -0
  96. package/dist/tracker/pipeline.d.ts.map +1 -0
  97. package/dist/tracker/pipeline.js +299 -0
  98. package/dist/tracker/pipeline.js.map +1 -0
  99. package/dist/tracker/query.d.ts +45 -0
  100. package/dist/tracker/query.d.ts.map +1 -0
  101. package/dist/tracker/query.js +159 -0
  102. package/dist/tracker/query.js.map +1 -0
  103. package/dist/tracker/state.d.ts +104 -0
  104. package/dist/tracker/state.d.ts.map +1 -0
  105. package/dist/tracker/state.js +287 -0
  106. package/dist/tracker/state.js.map +1 -0
  107. package/dist/tracker.d.ts +261 -0
  108. package/dist/tracker.d.ts.map +1 -0
  109. package/dist/tracker.js +556 -0
  110. package/dist/tracker.js.map +1 -0
  111. package/dist/types/config.d.ts +81 -0
  112. package/dist/types/config.d.ts.map +1 -0
  113. package/dist/types/config.js +6 -0
  114. package/dist/types/config.js.map +1 -0
  115. package/dist/types/core.d.ts +51 -0
  116. package/dist/types/core.d.ts.map +1 -0
  117. package/dist/types/core.js +6 -0
  118. package/dist/types/core.js.map +1 -0
  119. package/dist/types/cross-chain.d.ts +80 -0
  120. package/dist/types/cross-chain.d.ts.map +1 -0
  121. package/dist/types/cross-chain.js +6 -0
  122. package/dist/types/cross-chain.js.map +1 -0
  123. package/dist/types/election.d.ts +59 -0
  124. package/dist/types/election.d.ts.map +1 -0
  125. package/dist/types/election.js +6 -0
  126. package/dist/types/election.js.map +1 -0
  127. package/dist/types/governor.d.ts +71 -0
  128. package/dist/types/governor.d.ts.map +1 -0
  129. package/dist/types/governor.js +6 -0
  130. package/dist/types/governor.js.map +1 -0
  131. package/dist/types/index.d.ts +22 -0
  132. package/dist/types/index.d.ts.map +1 -0
  133. package/dist/types/index.js +21 -0
  134. package/dist/types/index.js.map +1 -0
  135. package/dist/types/stages.d.ts +189 -0
  136. package/dist/types/stages.d.ts.map +1 -0
  137. package/dist/types/stages.js +23 -0
  138. package/dist/types/stages.js.map +1 -0
  139. package/dist/types/timelock.d.ts +108 -0
  140. package/dist/types/timelock.d.ts.map +1 -0
  141. package/dist/types/timelock.js +6 -0
  142. package/dist/types/timelock.js.map +1 -0
  143. package/dist/types/tracking.d.ts +180 -0
  144. package/dist/types/tracking.d.ts.map +1 -0
  145. package/dist/types/tracking.js +6 -0
  146. package/dist/types/tracking.js.map +1 -0
  147. package/dist/types.d.ts +6 -0
  148. package/dist/types.d.ts.map +1 -0
  149. package/dist/types.js +22 -0
  150. package/dist/types.js.map +1 -0
  151. package/dist/utils/chain.d.ts +18 -0
  152. package/dist/utils/chain.d.ts.map +1 -0
  153. package/dist/utils/chain.js +34 -0
  154. package/dist/utils/chain.js.map +1 -0
  155. package/dist/utils/log-filters.d.ts +67 -0
  156. package/dist/utils/log-filters.d.ts.map +1 -0
  157. package/dist/utils/log-filters.js +116 -0
  158. package/dist/utils/log-filters.js.map +1 -0
  159. package/dist/utils/log-search.d.ts +76 -0
  160. package/dist/utils/log-search.d.ts.map +1 -0
  161. package/dist/utils/log-search.js +142 -0
  162. package/dist/utils/log-search.js.map +1 -0
  163. package/dist/utils/logger.d.ts +41 -0
  164. package/dist/utils/logger.d.ts.map +1 -0
  165. package/dist/utils/logger.js +50 -0
  166. package/dist/utils/logger.js.map +1 -0
  167. package/dist/utils/operation-id.d.ts +48 -0
  168. package/dist/utils/operation-id.d.ts.map +1 -0
  169. package/dist/utils/operation-id.js +102 -0
  170. package/dist/utils/operation-id.js.map +1 -0
  171. package/dist/utils/rpc-utils.d.ts +30 -0
  172. package/dist/utils/rpc-utils.d.ts.map +1 -0
  173. package/dist/utils/rpc-utils.js +99 -0
  174. package/dist/utils/rpc-utils.js.map +1 -0
  175. package/dist/utils/salt-computation.d.ts +78 -0
  176. package/dist/utils/salt-computation.d.ts.map +1 -0
  177. package/dist/utils/salt-computation.js +132 -0
  178. package/dist/utils/salt-computation.js.map +1 -0
  179. package/dist/utils/salt-resolver.d.ts +63 -0
  180. package/dist/utils/salt-resolver.d.ts.map +1 -0
  181. package/dist/utils/salt-resolver.js +144 -0
  182. package/dist/utils/salt-resolver.js.map +1 -0
  183. package/dist/utils/scoped-logger.d.ts +43 -0
  184. package/dist/utils/scoped-logger.d.ts.map +1 -0
  185. package/dist/utils/scoped-logger.js +72 -0
  186. package/dist/utils/scoped-logger.js.map +1 -0
  187. package/dist/utils/stage-helpers.d.ts +51 -0
  188. package/dist/utils/stage-helpers.d.ts.map +1 -0
  189. package/dist/utils/stage-helpers.js +143 -0
  190. package/dist/utils/stage-helpers.js.map +1 -0
  191. package/dist/utils/stage-metadata.d.ts +62 -0
  192. package/dist/utils/stage-metadata.d.ts.map +1 -0
  193. package/dist/utils/stage-metadata.js +140 -0
  194. package/dist/utils/stage-metadata.js.map +1 -0
  195. package/dist/utils/timing.d.ts +115 -0
  196. package/dist/utils/timing.d.ts.map +1 -0
  197. package/dist/utils/timing.js +303 -0
  198. package/dist/utils/timing.js.map +1 -0
  199. package/dist/utils/urls.d.ts +20 -0
  200. package/dist/utils/urls.d.ts.map +1 -0
  201. package/dist/utils/urls.js +51 -0
  202. package/dist/utils/urls.js.map +1 -0
  203. package/package.json +72 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * CLI Utilities for Monitor Script
3
+ *
4
+ * NOTE: This is CLI application code that demonstrates SDK usage, not library code.
5
+ * Developers should treat this as part of the CLI application, not as part of the SDK API.
6
+ *
7
+ * Provides RPC option parsing, provider creation, transaction execution,
8
+ * and the core monitoring cycle. This is monitor-specific code, not part of the SDK.
9
+ */
10
+ import { Command, Option } from "commander";
11
+ import { ethers } from "ethers";
12
+ import { ProposalStageTracker, TrackedStage, TrackingResult, TrackingCheckpoint, PreparedTransaction, PrepareResult, isElectionGovernor, DiscoveredProposal, DiscoveredTimelockOp, DiscoveryWatermarks } from "../../index";
13
+ export { isElectionGovernor };
14
+ /** Default block lag to prevent reorg issues */
15
+ export declare const DEFAULT_BLOCK_LAG = 12;
16
+ /** Default max age in days for re-tracking incomplete proposals */
17
+ export declare const DEFAULT_MAX_AGE_DAYS = 60;
18
+ /** Maximum consecutive errors before skipping an item */
19
+ export declare const MAX_CONSECUTIVE_ERRORS = 5;
20
+ export declare const rpcOptions: Option[];
21
+ export declare function addOptions(cmd: Command, opts: Option[]): void;
22
+ export interface ProviderBundle {
23
+ l2Provider: ethers.providers.JsonRpcProvider;
24
+ l1Provider: ethers.providers.JsonRpcProvider;
25
+ novaProvider: ethers.providers.JsonRpcProvider;
26
+ }
27
+ export declare function createProvidersFromOptions(opts: {
28
+ l2Rpc?: string;
29
+ l1Rpc?: string;
30
+ novaRpc?: string;
31
+ }): ProviderBundle;
32
+ export declare function requirePrivateKeyForWrite(opts: {
33
+ write?: boolean;
34
+ privateKey?: string;
35
+ }): void;
36
+ export declare function createSigner(privateKey: string): ethers.Wallet;
37
+ export declare function executeTransaction(prepared: PreparedTransaction, signer: ethers.Wallet, providers: ProviderBundle): Promise<{
38
+ success: boolean;
39
+ txHash?: string;
40
+ error?: string;
41
+ }>;
42
+ export declare function formatDryRun(prepared: PreparedTransaction): string;
43
+ export declare function formatTrackingResult(result: TrackingResult, label?: string): string;
44
+ export declare function formatStagesBrief(stages: TrackedStage[]): string;
45
+ export declare function formatCacheStatus(checkpoints: Map<string, TrackingCheckpoint>): string;
46
+ export declare function runWithLoop(cycleFn: () => Promise<void>, options: {
47
+ loop: boolean;
48
+ intervalMs: number;
49
+ healthCheckUrl?: string;
50
+ }): Promise<void>;
51
+ export interface TrackCallbackResult {
52
+ key: string;
53
+ result: TrackingResult | null;
54
+ prepared?: PreparedTransaction;
55
+ error?: string;
56
+ }
57
+ export interface TrackCallbackReturn {
58
+ shouldRetrack?: boolean;
59
+ }
60
+ export interface MonitorRunOptions {
61
+ prepare?: boolean;
62
+ force?: boolean;
63
+ preparePending?: boolean;
64
+ onTrack?: (result: TrackCallbackResult) => Promise<TrackCallbackReturn | void> | void;
65
+ startBlock?: number;
66
+ blockLag?: number;
67
+ maxChainDepth?: number;
68
+ maxAgeDays?: number;
69
+ /** Number of concurrent tracking operations (default: 1 = sequential) */
70
+ concurrency?: number;
71
+ }
72
+ export interface MonitorRunResult {
73
+ tracked: number;
74
+ prepared: number;
75
+ errors: number;
76
+ retracked: number;
77
+ }
78
+ export declare function runMonitorCycle(tracker: ProposalStageTracker, l2Provider: ethers.providers.Provider, options?: MonitorRunOptions): Promise<{
79
+ result: MonitorRunResult;
80
+ proposals: DiscoveredProposal[];
81
+ timelockOps: DiscoveredTimelockOp[];
82
+ watermarks: DiscoveryWatermarks;
83
+ }>;
84
+ export declare function trackAndPrepare(tracker: ProposalStageTracker, txHash: string, options?: {
85
+ prepare?: boolean;
86
+ force?: boolean;
87
+ preparePending?: boolean;
88
+ }): Promise<{
89
+ results: TrackingResult[];
90
+ preparations: PrepareResult[];
91
+ }>;
92
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,562 @@
1
+ "use strict";
2
+ /**
3
+ * CLI Utilities for Monitor Script
4
+ *
5
+ * NOTE: This is CLI application code that demonstrates SDK usage, not library code.
6
+ * Developers should treat this as part of the CLI application, not as part of the SDK API.
7
+ *
8
+ * Provides RPC option parsing, provider creation, transaction execution,
9
+ * and the core monitoring cycle. This is monitor-specific code, not part of the SDK.
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.rpcOptions = exports.MAX_CONSECUTIVE_ERRORS = exports.DEFAULT_MAX_AGE_DAYS = exports.DEFAULT_BLOCK_LAG = exports.isElectionGovernor = void 0;
16
+ exports.addOptions = addOptions;
17
+ exports.createProvidersFromOptions = createProvidersFromOptions;
18
+ exports.requirePrivateKeyForWrite = requirePrivateKeyForWrite;
19
+ exports.createSigner = createSigner;
20
+ exports.executeTransaction = executeTransaction;
21
+ exports.formatDryRun = formatDryRun;
22
+ exports.formatTrackingResult = formatTrackingResult;
23
+ exports.formatStagesBrief = formatStagesBrief;
24
+ exports.formatCacheStatus = formatCacheStatus;
25
+ exports.runWithLoop = runWithLoop;
26
+ exports.runMonitorCycle = runMonitorCycle;
27
+ exports.trackAndPrepare = trackAndPrepare;
28
+ const commander_1 = require("commander");
29
+ const ethers_1 = require("ethers");
30
+ const p_limit_1 = __importDefault(require("p-limit"));
31
+ const index_1 = require("../../index");
32
+ Object.defineProperty(exports, "isElectionGovernor", { enumerable: true, get: function () { return index_1.isElectionGovernor; } });
33
+ const logger_1 = require("../../utils/logger");
34
+ // ============================================================================
35
+ // Constants
36
+ // ============================================================================
37
+ /** Default block lag to prevent reorg issues */
38
+ exports.DEFAULT_BLOCK_LAG = 12;
39
+ /** Default max age in days for re-tracking incomplete proposals */
40
+ exports.DEFAULT_MAX_AGE_DAYS = 60;
41
+ /** Maximum consecutive errors before skipping an item */
42
+ exports.MAX_CONSECUTIVE_ERRORS = 5;
43
+ // ============================================================================
44
+ // RPC Configuration
45
+ // ============================================================================
46
+ exports.rpcOptions = [
47
+ new commander_1.Option("--l2-rpc <url>", "L2 RPC URL").env("ARB1_RPC"),
48
+ new commander_1.Option("--l1-rpc <url>", "L1 RPC URL").env("ETH_RPC"),
49
+ new commander_1.Option("--nova-rpc <url>", "Nova RPC URL").env("NOVA_RPC"),
50
+ ];
51
+ function addOptions(cmd, opts) {
52
+ opts.forEach((o) => cmd.addOption(o));
53
+ }
54
+ function createProvidersFromOptions(opts) {
55
+ const l2Rpc = opts.l2Rpc || process.env.ARB1_RPC || index_1.DEFAULT_RPC_URLS.ARB_ONE;
56
+ const l1Rpc = opts.l1Rpc || process.env.ETH_RPC;
57
+ const novaRpc = opts.novaRpc || process.env.NOVA_RPC || index_1.DEFAULT_RPC_URLS.NOVA;
58
+ if (!l1Rpc) {
59
+ throw new Error("L1 RPC URL required (--l1-rpc or ETH_RPC env var)");
60
+ }
61
+ return {
62
+ l2Provider: new ethers_1.ethers.providers.JsonRpcProvider(l2Rpc),
63
+ l1Provider: new ethers_1.ethers.providers.JsonRpcProvider(l1Rpc),
64
+ novaProvider: new ethers_1.ethers.providers.JsonRpcProvider(novaRpc),
65
+ };
66
+ }
67
+ // ============================================================================
68
+ // Signer Creation
69
+ // ============================================================================
70
+ function requirePrivateKeyForWrite(opts) {
71
+ if (opts.write && !opts.privateKey) {
72
+ console.error("Error: --write requires --private-key or PRIVATE_KEY env var");
73
+ process.exit(1);
74
+ }
75
+ }
76
+ function createSigner(privateKey) {
77
+ return new ethers_1.ethers.Wallet(privateKey.startsWith("0x") ? privateKey : "0x" + privateKey);
78
+ }
79
+ // ============================================================================
80
+ // Transaction Execution
81
+ // ============================================================================
82
+ const RETRYABLE_MAX_RETRIES = 10;
83
+ const RETRYABLE_RETRY_DELAY_MS = 5000;
84
+ async function executeTransaction(prepared, signer, providers) {
85
+ const isRetryable = prepared.description?.toLowerCase().includes("retryable") ?? false;
86
+ for (let attempt = 1; attempt <= (isRetryable ? RETRYABLE_MAX_RETRIES : 1); attempt++) {
87
+ try {
88
+ const provider = prepared.chain === "L1"
89
+ ? providers.l1Provider
90
+ : prepared.chain === "NOVA"
91
+ ? providers.novaProvider
92
+ : providers.l2Provider;
93
+ const connectedSigner = signer.connect(provider);
94
+ console.log(`\nExecuting on ${prepared.chain}: ${prepared.description}`);
95
+ console.log(` To: ${prepared.to}`);
96
+ if (prepared.value !== "0")
97
+ console.log(` Value: ${prepared.value}`);
98
+ const tx = await connectedSigner.sendTransaction({
99
+ to: prepared.to,
100
+ data: prepared.data,
101
+ value: prepared.value,
102
+ });
103
+ console.log(` Tx sent: ${tx.hash}`);
104
+ const receipt = await tx.wait();
105
+ console.log(` Confirmed in block ${receipt.blockNumber}`);
106
+ return { success: true, txHash: tx.hash };
107
+ }
108
+ catch (error) {
109
+ const message = error instanceof Error ? error.message : String(error);
110
+ // For retryables, check if already redeemed
111
+ if (isRetryable &&
112
+ (message.includes("REDEEMED") ||
113
+ message.includes("already redeemed") ||
114
+ message.includes("NoTicketWithID"))) {
115
+ console.log(` Retryable already redeemed, treating as success`);
116
+ return { success: true };
117
+ }
118
+ if (!isRetryable || attempt >= RETRYABLE_MAX_RETRIES) {
119
+ return { success: false, error: message };
120
+ }
121
+ console.log(` Retry ${attempt}/${RETRYABLE_MAX_RETRIES} failed: ${message}`);
122
+ console.log(` Retrying in ${RETRYABLE_RETRY_DELAY_MS / 1000}s...`);
123
+ await new Promise((resolve) => setTimeout(resolve, RETRYABLE_RETRY_DELAY_MS));
124
+ }
125
+ }
126
+ return { success: false, error: "Unexpected retry loop exit" };
127
+ }
128
+ // ============================================================================
129
+ // Output Formatting
130
+ // ============================================================================
131
+ function formatDryRun(prepared) {
132
+ const lines = [
133
+ `[DRY RUN] ${prepared.description}`,
134
+ ` Chain: ${prepared.chain}`,
135
+ ` To: ${prepared.to}`,
136
+ ];
137
+ if (prepared.operationId)
138
+ lines.push(` OperationId: ${prepared.operationId}`);
139
+ if (prepared.value !== "0")
140
+ lines.push(` Value: ${prepared.value}`);
141
+ lines.push(` Data: ${prepared.data}`);
142
+ if (prepared.hashValidation) {
143
+ lines.push(prepared.hashValidation.isValid
144
+ ? ` Hash Valid: YES`
145
+ : ` WARNING: Hash validation failed - ${prepared.hashValidation.error}`);
146
+ }
147
+ return lines.join("\n");
148
+ }
149
+ function formatTrackingResult(result, label) {
150
+ const lines = [];
151
+ if (label)
152
+ lines.push(`--- ${label} ---`);
153
+ const timelockStage = result.stages.find((s) => s.type === "L2_TIMELOCK");
154
+ const operationId = timelockStage?.data.operationId;
155
+ const isSecurityCouncil = timelockStage?.data.isSecurityCouncilOperation === true;
156
+ const scNonce = timelockStage?.data.securityCouncilNonce;
157
+ if (operationId)
158
+ lines.push(`OperationId: ${operationId}`);
159
+ if (isSecurityCouncil && scNonce)
160
+ lines.push(`Security Council Nonce: ${scNonce}`);
161
+ if (result.isElection)
162
+ lines.push(`Type: createElection`);
163
+ lines.push(`Complete: ${result.isComplete}`);
164
+ lines.push(`Stages: ${result.stages.length}\n`);
165
+ for (let i = 0; i < result.stages.length; i++) {
166
+ const stage = result.stages[i];
167
+ const title = (0, index_1.formatStageTitle)(stage.type);
168
+ // Transaction links
169
+ const txLines = [];
170
+ for (const tx of stage.transactions) {
171
+ const desc = tx.description ?? "tx";
172
+ txLines.push(` ${desc}: ${tx.hash}\n ${(0, index_1.getStageTransactionUrl)(tx)}`);
173
+ }
174
+ // ETA info
175
+ let etaInfo = "";
176
+ if (stage.timing?.eta) {
177
+ etaInfo = ` | ETA: ${new Date(stage.timing.eta * 1000).toISOString()}`;
178
+ }
179
+ else if (stage.status === "NOT_STARTED") {
180
+ const expectedEta = (0, index_1.calculateExpectedEta)(result.stages, i);
181
+ if (expectedEta) {
182
+ etaInfo = ` | Expected: ~${new Date(expectedEta * 1000).toISOString()}`;
183
+ }
184
+ }
185
+ // Retryable info
186
+ let retryableInfo = "";
187
+ if (stage.type === "RETRYABLE_EXECUTED") {
188
+ const ticketCount = stage.data.ticketCount;
189
+ const creationDetails = stage.data.creationDetails;
190
+ const redeemedCount = stage.data.redeemedCount;
191
+ const pendingCount = stage.data.pendingCount;
192
+ if (ticketCount && ticketCount > 0) {
193
+ const arb1Count = creationDetails?.filter((d) => d.targetChain === "Arb1").length ?? 0;
194
+ const novaCount = creationDetails?.filter((d) => d.targetChain === "Nova").length ?? 0;
195
+ const chains = [arb1Count > 0 && `${arb1Count} Arb1`, novaCount > 0 && `${novaCount} Nova`]
196
+ .filter(Boolean)
197
+ .join(", ");
198
+ retryableInfo = ` [${ticketCount} ticket${ticketCount !== 1 ? "s" : ""}: ${chains}`;
199
+ if (stage.status === "COMPLETED") {
200
+ retryableInfo += ` - all redeemed]`;
201
+ }
202
+ else if (pendingCount && pendingCount > 0) {
203
+ retryableInfo += ` - ${redeemedCount ?? 0} redeemed, ${pendingCount} pending]`;
204
+ }
205
+ else {
206
+ retryableInfo += `]`;
207
+ }
208
+ }
209
+ }
210
+ lines.push(` ${title}: ${stage.status}${retryableInfo}${etaInfo}`);
211
+ lines.push(...txLines);
212
+ }
213
+ return lines.join("\n").concat("\n");
214
+ }
215
+ function formatStagesBrief(stages) {
216
+ const summary = (0, index_1.getTrackingStatusSummary)(stages);
217
+ const current = (0, index_1.getCurrentStage)(stages);
218
+ const title = current ? (0, index_1.formatStageTitle)(current.type) : "Complete";
219
+ return `${title}: ${current?.status ?? "DONE"} (${summary.completed}/${summary.total})`;
220
+ }
221
+ function formatCacheStatus(checkpoints) {
222
+ let proposalTotal = 0, proposalComplete = 0, proposalActive = 0, proposalFailed = 0;
223
+ let timelockTotal = 0, timelockComplete = 0, timelockActive = 0, timelockFailed = 0;
224
+ let electionTotal = 0, electionComplete = 0;
225
+ for (const [, checkpoint] of checkpoints) {
226
+ const stages = checkpoint.cachedData?.completedStages ?? [];
227
+ const isComplete = stages.length > 0 && (0, index_1.areAllStagesComplete)(stages);
228
+ const errorCount = checkpoint.metadata?.errorCount ?? 0;
229
+ const isFailed = errorCount >= exports.MAX_CONSECUTIVE_ERRORS;
230
+ const input = checkpoint.input;
231
+ if (input.type === "governor") {
232
+ if ((0, index_1.isElectionGovernor)(input.governorAddress)) {
233
+ electionTotal++;
234
+ if (isComplete)
235
+ electionComplete++;
236
+ }
237
+ else {
238
+ proposalTotal++;
239
+ if (isComplete)
240
+ proposalComplete++;
241
+ else if (isFailed)
242
+ proposalFailed++;
243
+ else
244
+ proposalActive++;
245
+ }
246
+ }
247
+ else if (input.type === "timelock") {
248
+ timelockTotal++;
249
+ if (isComplete)
250
+ timelockComplete++;
251
+ else if (isFailed)
252
+ timelockFailed++;
253
+ else
254
+ timelockActive++;
255
+ }
256
+ }
257
+ const lines = [
258
+ `Total cached: ${checkpoints.size}`,
259
+ ``,
260
+ `Proposals: ${proposalTotal}`,
261
+ ` Complete: ${proposalComplete}`,
262
+ ` Active: ${proposalActive}`,
263
+ ];
264
+ if (proposalFailed > 0)
265
+ lines.push(` Failed: ${proposalFailed}`);
266
+ lines.push(``, `Timelock Ops: ${timelockTotal}`, ` Complete: ${timelockComplete}`, ` Active: ${timelockActive}`);
267
+ if (timelockFailed > 0)
268
+ lines.push(` Failed: ${timelockFailed}`);
269
+ if (electionTotal > 0)
270
+ lines.push(``, `Elections: ${electionTotal} (${electionComplete} complete)`);
271
+ return lines.join("\n");
272
+ }
273
+ // ============================================================================
274
+ // Loop Runner
275
+ // ============================================================================
276
+ async function waitWithChunks(ms) {
277
+ const MAX_CHUNK = 60 * 60 * 1000; // 1 hour max per chunk
278
+ let remaining = ms;
279
+ while (remaining > 0) {
280
+ await new Promise((resolve) => setTimeout(resolve, Math.min(remaining, MAX_CHUNK)));
281
+ remaining -= MAX_CHUNK;
282
+ }
283
+ }
284
+ async function runWithLoop(cycleFn, options) {
285
+ if (!options.loop) {
286
+ await cycleFn();
287
+ return;
288
+ }
289
+ let consecutiveErrors = 0;
290
+ let running = true;
291
+ process.on("SIGINT", () => {
292
+ running = false;
293
+ console.log("\nGracefully shutting down...");
294
+ });
295
+ while (running) {
296
+ try {
297
+ await cycleFn();
298
+ consecutiveErrors = 0;
299
+ }
300
+ catch (error) {
301
+ console.error("Cycle error:", error.message);
302
+ consecutiveErrors = Math.min(consecutiveErrors + 1, 10);
303
+ const backoffMs = Math.min(5000 * Math.pow(2, consecutiveErrors - 1), 300000);
304
+ console.log(`Backing off for ${backoffMs / 1000}s after ${consecutiveErrors} consecutive errors`);
305
+ await waitWithChunks(backoffMs);
306
+ }
307
+ if (options.healthCheckUrl) {
308
+ try {
309
+ await fetch(options.healthCheckUrl, { method: "GET" });
310
+ }
311
+ catch {
312
+ // Silently ignore health check errors
313
+ }
314
+ }
315
+ if (running)
316
+ await waitWithChunks(options.intervalMs);
317
+ }
318
+ }
319
+ // ============================================================================
320
+ // Stage Preparation
321
+ // ============================================================================
322
+ const PREPARABLE_STAGE_TYPES = [
323
+ "L2_TIMELOCK",
324
+ "L1_TIMELOCK",
325
+ "L2_TO_L1_MESSAGE",
326
+ "RETRYABLE_EXECUTED",
327
+ ];
328
+ async function prepareStagesForResult(tracker, stages, options) {
329
+ const preparations = [];
330
+ let prepared;
331
+ let count = 0;
332
+ if (!options.prepare)
333
+ return { preparations, count };
334
+ if (options.force) {
335
+ // Historical validation: prepare COMPLETED timelock stages
336
+ for (const stage of stages) {
337
+ if (stage.status === "COMPLETED" && (0, index_1.isTimelockStage)(stage.type)) {
338
+ const prepResult = await tracker.prepareTransaction(stage, { force: true });
339
+ preparations.push(prepResult);
340
+ if (prepResult.success) {
341
+ count++;
342
+ prepared = prepResult.prepared;
343
+ }
344
+ }
345
+ }
346
+ }
347
+ else if (options.preparePending) {
348
+ // Pre-execution: prepare PENDING stages
349
+ for (const stage of stages) {
350
+ const isPreparable = PREPARABLE_STAGE_TYPES.includes(stage.type);
351
+ if (isPreparable && stage.status === "PENDING") {
352
+ const prepResult = await tracker.prepareTransaction(stage, { force: true });
353
+ preparations.push(prepResult);
354
+ if (prepResult.success) {
355
+ count++;
356
+ prepared = prepResult.prepared;
357
+ }
358
+ }
359
+ }
360
+ }
361
+ else {
362
+ // Normal: prepare only READY stages
363
+ const ready = (0, index_1.findExecutableStage)(stages);
364
+ if (ready) {
365
+ const prepResult = await tracker.prepareTransaction(ready, {});
366
+ preparations.push(prepResult);
367
+ if (prepResult.success) {
368
+ count++;
369
+ prepared = prepResult.prepared;
370
+ }
371
+ }
372
+ }
373
+ return { prepared, preparations, count };
374
+ }
375
+ // ============================================================================
376
+ // Monitor Cycle
377
+ // ============================================================================
378
+ /** Create a short scope name from a tracking key */
379
+ function shortScope(key) {
380
+ // "tx:0x1234...abcd" -> "0x1234..abcd"
381
+ if (key.startsWith("tx:0x")) {
382
+ const hash = key.slice(3);
383
+ return hash.slice(0, 6) + ".." + hash.slice(-4);
384
+ }
385
+ return key.slice(0, 12);
386
+ }
387
+ async function runMonitorCycle(tracker, l2Provider, options = {}) {
388
+ const tipBlock = await l2Provider.getBlockNumber();
389
+ const blockLag = options.blockLag ?? exports.DEFAULT_BLOCK_LAG;
390
+ const currentBlock = Math.max(0, tipBlock - blockLag);
391
+ const concurrency = options.concurrency ?? 1;
392
+ const limit = (0, p_limit_1.default)(concurrency);
393
+ // Optional startBlock override (watermarks are exclusive, so subtract 1)
394
+ const startBlockWatermarks = options.startBlock
395
+ ? {
396
+ constitutionalGovernor: options.startBlock - 1,
397
+ nonConstitutionalGovernor: options.startBlock - 1,
398
+ electionNomineeGovernor: options.startBlock - 1,
399
+ electionMemberGovernor: options.startBlock - 1,
400
+ l2ConstitutionalTimelock: options.startBlock - 1,
401
+ l2NonConstitutionalTimelock: options.startBlock - 1,
402
+ }
403
+ : undefined;
404
+ const targets = (0, index_1.buildDefaultTargets)();
405
+ const discoveryResult = await tracker.discoverAll(targets, currentBlock, startBlockWatermarks);
406
+ const result = { tracked: 0, prepared: 0, errors: 0, retracked: 0 };
407
+ const trackedKeys = new Set();
408
+ const trackedOperationIds = new Set();
409
+ async function track(key, trackFn) {
410
+ if (trackedKeys.has(key))
411
+ return;
412
+ trackedKeys.add(key);
413
+ // Wrap tracking in scope for debug logging
414
+ await (0, logger_1.withScope)(shortScope(key), async () => {
415
+ try {
416
+ const trackResult = await trackFn();
417
+ result.tracked++;
418
+ if (trackResult.timelockLink?.operationId) {
419
+ trackedOperationIds.add(trackResult.timelockLink.operationId.toLowerCase());
420
+ }
421
+ const prepResult = await prepareStagesForResult(tracker, trackResult.stages, options);
422
+ result.prepared += prepResult.count;
423
+ const callbackResult = await options.onTrack?.({
424
+ key,
425
+ result: trackResult,
426
+ prepared: prepResult.prepared,
427
+ });
428
+ if (callbackResult?.shouldRetrack) {
429
+ trackedKeys.delete(key);
430
+ await track(key, trackFn);
431
+ }
432
+ }
433
+ catch (error) {
434
+ result.errors++;
435
+ // Wrap error callback in try-catch to prevent nested errors from propagating
436
+ try {
437
+ await options.onTrack?.({
438
+ key,
439
+ result: null,
440
+ error: error instanceof Error ? error.message : String(error),
441
+ });
442
+ }
443
+ catch (callbackError) {
444
+ // Log the callback error but don't let it mask the original error
445
+ console.error(`Error in onTrack callback for ${key}:`, callbackError instanceof Error ? callbackError.message : String(callbackError));
446
+ }
447
+ }
448
+ });
449
+ }
450
+ // Query incomplete checkpoints first to avoid duplicate tracking
451
+ const maxAgeDays = options.maxAgeDays ?? exports.DEFAULT_MAX_AGE_DAYS;
452
+ const incompleteCheckpoints = await tracker.queryIncompleteCheckpoints({
453
+ maxAgeDays,
454
+ maxErrorCount: exports.MAX_CONSECUTIVE_ERRORS,
455
+ });
456
+ // Extract operationIds from governor checkpoints
457
+ const governorOperationIds = new Set();
458
+ for (const { checkpoint } of incompleteCheckpoints) {
459
+ if (checkpoint.input.type === "governor") {
460
+ const stages = checkpoint.cachedData.completedStages ?? [];
461
+ const opId = (0, index_1.extractOperationId)(stages);
462
+ if (opId)
463
+ governorOperationIds.add(opId.toLowerCase());
464
+ }
465
+ }
466
+ // Phase 1: Track proposals and incomplete governor checkpoints first
467
+ // This populates trackedOperationIds so we can filter TLOs correctly
468
+ const proposalTasks = [];
469
+ // 1a. Newly discovered proposals
470
+ for (const p of discoveryResult.proposals) {
471
+ const key = `tx:${p.creationTxHash.toLowerCase()}`;
472
+ proposalTasks.push({
473
+ key,
474
+ fn: async () => {
475
+ const results = await tracker.trackByTxHash(p.creationTxHash);
476
+ if (results.length === 0)
477
+ throw new Error(`No proposal found in tx ${p.creationTxHash}`);
478
+ return results[0];
479
+ },
480
+ });
481
+ }
482
+ // 1b. Incomplete governor checkpoints to re-track (excluding elections)
483
+ const nonElectionCheckpoints = incompleteCheckpoints.filter(({ checkpoint }) => {
484
+ if (checkpoint.input.type === "governor")
485
+ return !(0, index_1.isElectionGovernor)(checkpoint.input.governorAddress);
486
+ return true;
487
+ });
488
+ result.retracked = nonElectionCheckpoints.length;
489
+ for (const { key, checkpoint } of nonElectionCheckpoints) {
490
+ if (checkpoint.input.type === "governor") {
491
+ proposalTasks.push({
492
+ key,
493
+ fn: () => tracker.trackFromCheckpoint(checkpoint),
494
+ });
495
+ }
496
+ }
497
+ // Run proposal tasks first to populate trackedOperationIds
498
+ await Promise.all(proposalTasks.map((task) => limit(() => track(task.key, task.fn))));
499
+ // Phase 2: Track TLOs (filter out those already tracked via proposals)
500
+ const timelockTasks = [];
501
+ // 2a. Newly discovered timelock operations (filter duplicates)
502
+ for (const op of discoveryResult.timelockOps) {
503
+ const opIdLower = op.operationId.toLowerCase();
504
+ // Skip if already tracked via proposal (either from cache or just tracked)
505
+ if (governorOperationIds.has(opIdLower))
506
+ continue;
507
+ if (trackedOperationIds.has(opIdLower))
508
+ continue;
509
+ const key = `tx:${op.scheduledTxHash.toLowerCase()}`;
510
+ timelockTasks.push({
511
+ key,
512
+ fn: async () => {
513
+ const results = await tracker.trackByTxHash(op.scheduledTxHash);
514
+ if (results.length === 0)
515
+ throw new Error(`No timelock operation found in tx ${op.scheduledTxHash}`);
516
+ const matchingResult = results.find((r) => {
517
+ if (r.input.type === "timelock")
518
+ return r.input.operationId.toLowerCase() === opIdLower;
519
+ return r.timelockLink?.operationId?.toLowerCase() === opIdLower;
520
+ });
521
+ trackedOperationIds.add(opIdLower);
522
+ return matchingResult ?? results[0];
523
+ },
524
+ });
525
+ }
526
+ // 2b. Incomplete timelock checkpoints to re-track
527
+ for (const { key, checkpoint } of nonElectionCheckpoints) {
528
+ if (checkpoint.input.type === "timelock") {
529
+ const operationId = checkpoint.input.operationId;
530
+ // Skip if already tracked via proposal
531
+ if (operationId && governorOperationIds.has(operationId.toLowerCase()))
532
+ continue;
533
+ if (operationId && trackedOperationIds.has(operationId.toLowerCase()))
534
+ continue;
535
+ timelockTasks.push({
536
+ key,
537
+ fn: () => tracker.trackFromCheckpoint(checkpoint),
538
+ });
539
+ }
540
+ }
541
+ // Run timelock tasks
542
+ await Promise.all(timelockTasks.map((task) => limit(() => track(task.key, task.fn))));
543
+ return {
544
+ result,
545
+ proposals: discoveryResult.proposals,
546
+ timelockOps: discoveryResult.timelockOps,
547
+ watermarks: discoveryResult.watermarks,
548
+ };
549
+ }
550
+ // ============================================================================
551
+ // Track and Prepare (for single-item tracking)
552
+ // ============================================================================
553
+ async function trackAndPrepare(tracker, txHash, options = {}) {
554
+ const results = await tracker.trackByTxHash(txHash);
555
+ const preparations = [];
556
+ for (const result of results) {
557
+ const prepResult = await prepareStagesForResult(tracker, result.stages, options);
558
+ preparations.push(...prepResult.preparations);
559
+ }
560
+ return { results, preparations };
561
+ }
562
+ //# sourceMappingURL=cli.js.map