@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,303 @@
1
+ "use strict";
2
+ /**
3
+ * Timing utilities for ETA calculations
4
+ *
5
+ * Handles block-based timing across L1 and L2
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.estimateTimestampFromBlock = estimateTimestampFromBlock;
9
+ exports.calculateEta = calculateEta;
10
+ exports.calculateRemainingSeconds = calculateRemainingSeconds;
11
+ exports.getCurrentBlockInfo = getCurrentBlockInfo;
12
+ exports.getL1BlockNumberFromL2 = getL1BlockNumberFromL2;
13
+ exports.getL1BlockForL2Block = getL1BlockForL2Block;
14
+ exports.getFirstL2BlockForL1Block = getFirstL2BlockForL1Block;
15
+ exports.blockAfterDelay = blockAfterDelay;
16
+ exports.calculateExpectedEta = calculateExpectedEta;
17
+ const ethers_1 = require("ethers");
18
+ const lib_1 = require("@arbitrum/sdk/dist/lib/utils/lib");
19
+ const constants_1 = require("../constants");
20
+ const rpc_utils_1 = require("./rpc-utils");
21
+ const logger_1 = require("./logger");
22
+ const log = logger_1.loggers.rpc;
23
+ /**
24
+ * Get the completion timestamp from a stage's transactions.
25
+ *
26
+ * For stages with multiple transactions (e.g., timelock stages with both
27
+ * "queued" and "executed" txs), this finds the tx with description "executed"
28
+ * or falls back to the last transaction in the array.
29
+ */
30
+ function getCompletionTimestamp(stage) {
31
+ if (!stage.transactions?.length)
32
+ return undefined;
33
+ // Find tx with description "executed", or use last tx
34
+ const execTx = stage.transactions.find((tx) => tx.description === "executed") ??
35
+ stage.transactions[stage.transactions.length - 1];
36
+ return execTx?.timestamp;
37
+ }
38
+ /**
39
+ * Convert block number to estimated timestamp
40
+ */
41
+ function estimateTimestampFromBlock(blockNumber, currentBlock, currentTimestamp, blockTime = constants_1.BLOCK_TIMES.L2) {
42
+ const blockDiff = blockNumber - currentBlock;
43
+ const timeDiff = blockDiff * blockTime;
44
+ return Math.floor(currentTimestamp + timeDiff);
45
+ }
46
+ /**
47
+ * Calculate ETA for a future block
48
+ */
49
+ function calculateEta(targetBlock, currentBlock, currentTimestamp, blockTime = constants_1.BLOCK_TIMES.L2) {
50
+ if (targetBlock <= currentBlock) {
51
+ return null; // Already passed
52
+ }
53
+ return estimateTimestampFromBlock(targetBlock, currentBlock, currentTimestamp, blockTime);
54
+ }
55
+ /**
56
+ * Calculate remaining time in seconds
57
+ */
58
+ function calculateRemainingSeconds(targetBlock, currentBlock, blockTime = constants_1.BLOCK_TIMES.L2) {
59
+ const blockDiff = targetBlock - currentBlock;
60
+ if (blockDiff <= 0) {
61
+ return 0;
62
+ }
63
+ return Math.floor(blockDiff * blockTime);
64
+ }
65
+ // Short-lived cache for getCurrentBlockInfo (2 seconds TTL)
66
+ // Uses WeakMap to avoid memory leaks when providers are garbage collected
67
+ const blockInfoCache = new WeakMap();
68
+ const BLOCK_INFO_CACHE_TTL_MS = 2000; // 2 seconds - short enough for L2's fast blocks
69
+ /**
70
+ * Get current block info from a provider
71
+ *
72
+ * Results are cached for 2 seconds to reduce redundant RPC calls during a single
73
+ * tracking operation. The cache is per-provider.
74
+ */
75
+ async function getCurrentBlockInfo(provider) {
76
+ const cached = blockInfoCache.get(provider);
77
+ const now = Date.now();
78
+ if (cached && now - cached.fetchedAt < BLOCK_INFO_CACHE_TTL_MS) {
79
+ log("getBlock(latest): block=%d (cached)", cached.blockNumber);
80
+ return { blockNumber: cached.blockNumber, timestamp: cached.timestamp };
81
+ }
82
+ const start = now;
83
+ const block = await (0, rpc_utils_1.queryWithRetry)(() => provider.getBlock("latest"));
84
+ log("getBlock(latest): block=%d (%dms)", block.number, Date.now() - start);
85
+ const result = {
86
+ blockNumber: block.number,
87
+ timestamp: block.timestamp,
88
+ fetchedAt: now,
89
+ };
90
+ blockInfoCache.set(provider, result);
91
+ return { blockNumber: result.blockNumber, timestamp: result.timestamp };
92
+ }
93
+ /**
94
+ * Get current L1 block number as seen from L2
95
+ *
96
+ * Arbitrum L2 blocks include the L1 block number in their metadata.
97
+ * This returns the L1 block number from the latest L2 block.
98
+ *
99
+ * IMPORTANT: This returns the actual L1 block number, not the L2 block number.
100
+ * Use this for comparing against vetting deadlines which are in L1 blocks.
101
+ */
102
+ async function getL1BlockNumberFromL2(l2Provider) {
103
+ const jsonRpcProvider = l2Provider;
104
+ if (typeof jsonRpcProvider.send !== "function") {
105
+ throw new Error("Provider does not support direct RPC calls (send method required)");
106
+ }
107
+ const start = Date.now();
108
+ const rawBlock = await (0, rpc_utils_1.queryWithRetry)(() => jsonRpcProvider.send("eth_getBlockByNumber", ["latest", false]));
109
+ if (!rawBlock || !rawBlock.l1BlockNumber) {
110
+ throw new Error("Could not get L1 block number from latest L2 block");
111
+ }
112
+ const l1Block = ethers_1.BigNumber.from(rawBlock.l1BlockNumber);
113
+ log("getL1BlockNumberFromL2: l1Block=%s (%dms)", l1Block.toString(), Date.now() - start);
114
+ return l1Block;
115
+ }
116
+ /**
117
+ * Get the corresponding L1 block number for an L2 block.
118
+ *
119
+ * Arbitrum L2 blocks include the L1 block number at the time they were created.
120
+ * This is exposed via the `l1BlockNumber` field in the raw block data.
121
+ *
122
+ * This is useful for determining search ranges when looking for L1 events
123
+ * that correspond to L2 actions.
124
+ *
125
+ * Note: This relies on Arbitrum-specific block metadata and requires a
126
+ * JsonRpcProvider that supports the `send` method for raw RPC calls.
127
+ */
128
+ async function getL1BlockForL2Block(l2Provider, l2BlockNumber) {
129
+ const jsonRpcProvider = l2Provider;
130
+ if (typeof jsonRpcProvider.send !== "function") {
131
+ throw new Error("Provider does not support direct RPC calls (send method required)");
132
+ }
133
+ const rawBlock = await (0, rpc_utils_1.queryWithRetry)(() => jsonRpcProvider.send("eth_getBlockByNumber", ["0x" + l2BlockNumber.toString(16), false]));
134
+ if (!rawBlock || !rawBlock.l1BlockNumber) {
135
+ throw new Error(`Could not get L1 block number for L2 block ${l2BlockNumber}`);
136
+ }
137
+ // Use BigNumber.from for consistent parsing (handles both hex and decimal)
138
+ // This matches getL1BlockNumberFromL2's approach
139
+ const l1Block = ethers_1.BigNumber.from(rawBlock.l1BlockNumber);
140
+ return l1Block.toNumber();
141
+ }
142
+ /**
143
+ * Get the first L2 block for a given L1 block number using Arbitrum SDK.
144
+ *
145
+ * Arbitrum governors use L1 block numbers for voting deadlines. This function
146
+ * finds the corresponding L2 block for searching L2 logs.
147
+ *
148
+ * Uses binary search via the SDK's getFirstBlockForL1Block which queries
149
+ * NodeInterface.l2BlockRangeForL1() internally.
150
+ *
151
+ * @param l2Provider - L2 provider (must be JsonRpcProvider)
152
+ * @param targetL1Block - Target L1 block number
153
+ * @param options.minL2Block - Minimum L2 block to search from (speeds up binary search)
154
+ * @param options.maxL2Block - Maximum L2 block to search to (speeds up binary search)
155
+ * @returns First L2 block for the given L1 block, or undefined if not found
156
+ */
157
+ async function getFirstL2BlockForL1Block(l2Provider, targetL1Block, options = {}) {
158
+ const jsonRpcProvider = l2Provider;
159
+ const result = await (0, lib_1.getFirstBlockForL1Block)({
160
+ arbitrumProvider: jsonRpcProvider,
161
+ forL1Block: targetL1Block,
162
+ allowGreater: true, // Allow finding block even if L1 block is slightly in the future
163
+ minArbitrumBlock: options.minL2Block,
164
+ maxArbitrumBlock: options.maxL2Block,
165
+ });
166
+ if (result !== undefined) {
167
+ log("getFirstL2BlockForL1Block: L1=%d -> L2=%d (bounds: %s-%s)", targetL1Block, result, options.minL2Block ?? "start", options.maxL2Block ?? "latest");
168
+ }
169
+ return result;
170
+ }
171
+ /**
172
+ * Find a block number shortly after a delay expires.
173
+ *
174
+ * Instead of using a hardcoded block time which can overshoot or undershoot,
175
+ * this function checks actual block timestamps and adjusts iteratively.
176
+ *
177
+ * IMPORTANT: This function errs on the side of being EARLY rather than late.
178
+ * When searching for events, it's better to start searching a bit before the
179
+ * target time than to miss the event by starting too late.
180
+ *
181
+ * @param provider - Provider to fetch block data
182
+ * @param startBlock - The block number where the delay started
183
+ * @param delaySeconds - The delay duration in seconds
184
+ * @param estimatedBlockTime - Estimated seconds per block (default: 12 for L1)
185
+ * @returns A block number at or shortly before timestamp >= startTimestamp + delaySeconds
186
+ */
187
+ async function blockAfterDelay(provider, startBlock, delaySeconds, estimatedBlockTime = constants_1.BLOCK_TIMES.L1) {
188
+ const start = Date.now();
189
+ // Get the start block timestamp
190
+ const startBlockData = await (0, rpc_utils_1.queryWithRetry)(() => provider.getBlock(startBlock));
191
+ if (!startBlockData) {
192
+ throw new Error(`Could not fetch block ${startBlock}`);
193
+ }
194
+ const targetTimestamp = startBlockData.timestamp + delaySeconds;
195
+ // Get current block for upper bound
196
+ const { blockNumber: currentBlock, timestamp: currentTimestamp } = await getCurrentBlockInfo(provider);
197
+ // If current time hasn't passed the target, return startBlock (too early to have executed)
198
+ if (currentTimestamp < targetTimestamp) {
199
+ log("blockAfterDelay: delay not yet passed, returning startBlock=%d (%dms)", startBlock, Date.now() - start);
200
+ return startBlock;
201
+ }
202
+ // Initial estimate
203
+ let resultBlock = startBlock + Math.floor(delaySeconds / estimatedBlockTime);
204
+ // Clamp to valid range
205
+ resultBlock = Math.min(resultBlock, currentBlock);
206
+ resultBlock = Math.max(resultBlock, startBlock + 1);
207
+ // Safety margin: 100 blocks on L1 (~20 min), ensures we start before target
208
+ const safetyMargin = 100;
209
+ // Iteratively refine until we're before the target timestamp
210
+ const maxIterations = 10;
211
+ for (let i = 0; i < maxIterations; i++) {
212
+ const block = await (0, rpc_utils_1.queryWithRetry)(() => provider.getBlock(resultBlock));
213
+ if (!block) {
214
+ log("blockAfterDelay: could not fetch block %d, using estimate", resultBlock);
215
+ break;
216
+ }
217
+ const diff = block.timestamp - targetTimestamp;
218
+ if (diff < 0) {
219
+ // We're before the target - perfect, this is where we want to be
220
+ log("blockAfterDelay: found block=%d (diff=%ds before target) in %d iterations (%dms)", resultBlock, -diff, i + 1, Date.now() - start);
221
+ return resultBlock;
222
+ }
223
+ // We're at or after the target - backtrack
224
+ // Backtrack by the overshoot amount plus safety margin
225
+ const blocksToBacktrack = Math.ceil(diff / estimatedBlockTime) + safetyMargin;
226
+ const previousBlock = resultBlock;
227
+ resultBlock = Math.max(startBlock + 1, resultBlock - blocksToBacktrack);
228
+ log("blockAfterDelay: block %d is +%ds after target, backtracking %d blocks to %d", previousBlock, diff, blocksToBacktrack, resultBlock);
229
+ // Prevent infinite loop if we can't go back further
230
+ if (resultBlock === startBlock + 1) {
231
+ log("blockAfterDelay: can't backtrack further, using startBlock+1=%d", resultBlock);
232
+ return resultBlock;
233
+ }
234
+ }
235
+ log("blockAfterDelay: returning block=%d after max iterations (%dms)", resultBlock, Date.now() - start);
236
+ return resultBlock;
237
+ }
238
+ // Simple ETA Calculation for Individual Stages
239
+ /**
240
+ * Stage duration mapping for ETA calculations (in days)
241
+ */
242
+ const STAGE_DURATION_DAYS = {
243
+ VOTING_ACTIVE: constants_1.GOVERNANCE_STAGE_DURATION_DAYS.VOTING,
244
+ L2_TIMELOCK: constants_1.GOVERNANCE_STAGE_DURATION_DAYS.L2_CONSTITUTIONAL_TIMELOCK,
245
+ L2_TO_L1_MESSAGE: constants_1.GOVERNANCE_STAGE_DURATION_DAYS.CHALLENGE_PERIOD,
246
+ L1_TIMELOCK: constants_1.GOVERNANCE_STAGE_DURATION_DAYS.L1_TIMELOCK,
247
+ };
248
+ /**
249
+ * Calculate expected ETA for a stage that hasn't started yet
250
+ *
251
+ * Estimates when a future stage will complete based on:
252
+ * 1. Finding a reference point (completed stage timestamp or existing ETA)
253
+ * 2. Calculating cumulative delays from that reference to the target stage
254
+ *
255
+ * @param stages - Array of tracked stages from a TrackingResult
256
+ * @param stageIndex - Index of the stage to calculate ETA for
257
+ * @returns Estimated completion timestamp in seconds, or undefined if cannot calculate
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * const result = await tracker.trackFromGovernor(governor, proposalId);
262
+ * for (let i = 0; i < result.stages.length; i++) {
263
+ * const stage = result.stages[i];
264
+ * if (stage.status === "NOT_STARTED") {
265
+ * const eta = calculateExpectedEta(result.stages, i);
266
+ * if (eta) {
267
+ * console.log(`${stage.type}: Expected ~${new Date(eta * 1000).toISOString()}`);
268
+ * }
269
+ * }
270
+ * }
271
+ * ```
272
+ */
273
+ function calculateExpectedEta(stages, stageIndex) {
274
+ let baseEta;
275
+ let baseIndex = -1;
276
+ for (let i = stageIndex - 1; i >= 0; i--) {
277
+ const stage = stages[i];
278
+ if (stage.timing?.eta) {
279
+ baseEta = stage.timing.eta;
280
+ baseIndex = i;
281
+ break;
282
+ }
283
+ if (stage.status === "COMPLETED") {
284
+ const completionTs = getCompletionTimestamp(stage);
285
+ if (completionTs !== undefined) {
286
+ baseEta = completionTs;
287
+ baseIndex = i;
288
+ break;
289
+ }
290
+ }
291
+ }
292
+ if (baseEta === undefined) {
293
+ return undefined;
294
+ }
295
+ let cumulativeDelayDays = 0;
296
+ for (let i = baseIndex + 1; i <= stageIndex; i++) {
297
+ const stageType = stages[i].type;
298
+ cumulativeDelayDays += STAGE_DURATION_DAYS[stageType] ?? 0;
299
+ }
300
+ const delaySeconds = cumulativeDelayDays * 24 * 60 * 60;
301
+ return baseEta + delaySeconds;
302
+ }
303
+ //# sourceMappingURL=timing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.js","sourceRoot":"","sources":["../../src/utils/timing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ChainType, StageTransaction } from "../types";
2
+ /**
3
+ * Map ChainType to numeric chain ID
4
+ */
5
+ export declare function chainTypeToId(chain: ChainType): number;
6
+ export declare function getExplorerUrl(chainId: number, type: "tx" | "address", hash: string): string;
7
+ export declare function getTxUrl(chainId: number, txHash: string): string;
8
+ /**
9
+ * Get block explorer URL for a stage transaction
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const stage = result.stages[0];
14
+ * for (const tx of stage.transactions) {
15
+ * console.log(`${tx.hash}: ${getStageTransactionUrl(tx)}`);
16
+ * }
17
+ * ```
18
+ */
19
+ export declare function getStageTransactionUrl(tx: StageTransaction): string;
20
+ //# sourceMappingURL=urls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../src/utils/urls.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5D;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAStD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5F;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,gBAAgB,GAAG,MAAM,CAGnE"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.chainTypeToId = chainTypeToId;
4
+ exports.getExplorerUrl = getExplorerUrl;
5
+ exports.getTxUrl = getTxUrl;
6
+ exports.getStageTransactionUrl = getStageTransactionUrl;
7
+ const constants_1 = require("../constants");
8
+ /**
9
+ * Map ChainType to numeric chain ID
10
+ */
11
+ function chainTypeToId(chain) {
12
+ switch (chain) {
13
+ case "L1":
14
+ return constants_1.CHAIN_IDS.ETHEREUM;
15
+ case "L2":
16
+ return constants_1.CHAIN_IDS.ARB_ONE;
17
+ case "NOVA":
18
+ return constants_1.CHAIN_IDS.NOVA;
19
+ }
20
+ }
21
+ function getExplorerUrl(chainId, type, hash) {
22
+ switch (chainId) {
23
+ case 1: // Ethereum
24
+ return `https://etherscan.io/${type}/${hash}`;
25
+ case constants_1.CHAIN_IDS.ARB_ONE:
26
+ return `https://arbiscan.io/${type}/${hash}`;
27
+ case constants_1.CHAIN_IDS.NOVA:
28
+ return `https://nova.arbiscan.io/${type}/${hash}`;
29
+ default:
30
+ return `https://etherscan.io/${type}/${hash}`;
31
+ }
32
+ }
33
+ function getTxUrl(chainId, txHash) {
34
+ return getExplorerUrl(chainId, "tx", txHash);
35
+ }
36
+ /**
37
+ * Get block explorer URL for a stage transaction
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * const stage = result.stages[0];
42
+ * for (const tx of stage.transactions) {
43
+ * console.log(`${tx.hash}: ${getStageTransactionUrl(tx)}`);
44
+ * }
45
+ * ```
46
+ */
47
+ function getStageTransactionUrl(tx) {
48
+ const chainId = chainTypeToId(tx.chain);
49
+ return getTxUrl(chainId, tx.hash);
50
+ }
51
+ //# sourceMappingURL=urls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/utils/urls.ts"],"names":[],"mappings":";;AAMA,sCASC;AAED,wCAWC;AAED,4BAEC;AAaD,wDAGC;AAhDD,4CAAyC;AAGzC;;GAEG;AACH,SAAgB,aAAa,CAAC,KAAgB;IAC5C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,IAAI;YACP,OAAO,qBAAS,CAAC,QAAQ,CAAC;QAC5B,KAAK,IAAI;YACP,OAAO,qBAAS,CAAC,OAAO,CAAC;QAC3B,KAAK,MAAM;YACT,OAAO,qBAAS,CAAC,IAAI,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,OAAe,EAAE,IAAsB,EAAE,IAAY;IAClF,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,CAAC,EAAE,WAAW;YACjB,OAAO,wBAAwB,IAAI,IAAI,IAAI,EAAE,CAAC;QAChD,KAAK,qBAAS,CAAC,OAAO;YACpB,OAAO,uBAAuB,IAAI,IAAI,IAAI,EAAE,CAAC;QAC/C,KAAK,qBAAS,CAAC,IAAI;YACjB,OAAO,4BAA4B,IAAI,IAAI,IAAI,EAAE,CAAC;QACpD;YACE,OAAO,wBAAwB,IAAI,IAAI,IAAI,EAAE,CAAC;IAClD,CAAC;AACH,CAAC;AAED,SAAgB,QAAQ,CAAC,OAAe,EAAE,MAAc;IACtD,OAAO,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,sBAAsB,CAAC,EAAoB;IACzD,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@gzeoneth/gov-tracker",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight, high-performance library for tracking Arbitrum DAO governance proposal lifecycle stages",
5
+ "license": "Apache-2.0",
6
+ "author": "gzeoneth",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/gzeoneth/gov-tracker.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/gzeoneth/gov-tracker/issues"
13
+ },
14
+ "main": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "bin": {
17
+ "gov-tracker": "dist/cli/monitor.js"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "test": "NO_RPC=1 vitest run",
25
+ "test:monitor": "vitest run test/monitor.test.ts",
26
+ "test:integration": "vitest run test/integration.test.ts test/tracker.test.ts test/retryables.test.ts",
27
+ "test:fork": "vitest run --config vitest.config.fork.mts",
28
+ "test:all": "vitest run",
29
+ "lint": "eslint src test --quiet",
30
+ "lint:fix": "eslint src test --fix",
31
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
32
+ "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
33
+ "prepublishOnly": "yarn lint && yarn format:check && yarn build",
34
+ "prepare": "husky",
35
+ "monitor": "ts-node src/cli/monitor.ts",
36
+ "monitor:run": "ts-node src/cli/monitor.ts run",
37
+ "monitor:status": "ts-node src/cli/monitor.ts status",
38
+ "monitor:track": "ts-node src/cli/monitor.ts track"
39
+ },
40
+ "lint-staged": {
41
+ "*.ts": [
42
+ "eslint --fix",
43
+ "prettier --write"
44
+ ]
45
+ },
46
+ "dependencies": {
47
+ "@arbitrum/sdk": "^4.0.0",
48
+ "commander": "^14.0.2",
49
+ "debug": "^4.3.4",
50
+ "dotenv": "^17.2.3",
51
+ "ethers": "^5.7.2",
52
+ "p-limit": "3"
53
+ },
54
+ "devDependencies": {
55
+ "@types/debug": "^4.1.12",
56
+ "@types/node": "^20.0.0",
57
+ "@typescript-eslint/eslint-plugin": "^8.51.0",
58
+ "@typescript-eslint/parser": "^8.51.0",
59
+ "@vitest/coverage-v8": "^1.6.0",
60
+ "eslint": "^9.39.2",
61
+ "husky": "^9.1.7",
62
+ "jiti": "^2.6.1",
63
+ "lint-staged": "^16.2.7",
64
+ "prettier": "^3.7.4",
65
+ "ts-node": "^10.9.2",
66
+ "typescript": "^5.0.0",
67
+ "vitest": "^4.0.16"
68
+ },
69
+ "engines": {
70
+ "node": ">=18.0.0"
71
+ }
72
+ }