@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.
- package/LICENSE +191 -0
- package/README.md +201 -0
- package/dist/abis.d.ts +79 -0
- package/dist/abis.d.ts.map +1 -0
- package/dist/abis.js +159 -0
- package/dist/abis.js.map +1 -0
- package/dist/cli/lib/cli.d.ts +92 -0
- package/dist/cli/lib/cli.d.ts.map +1 -0
- package/dist/cli/lib/cli.js +562 -0
- package/dist/cli/lib/cli.js.map +1 -0
- package/dist/cli/lib/election-check.d.ts +46 -0
- package/dist/cli/lib/election-check.d.ts.map +1 -0
- package/dist/cli/lib/election-check.js +136 -0
- package/dist/cli/lib/election-check.js.map +1 -0
- package/dist/cli/lib/json-state.d.ts +100 -0
- package/dist/cli/lib/json-state.d.ts.map +1 -0
- package/dist/cli/lib/json-state.js +225 -0
- package/dist/cli/lib/json-state.js.map +1 -0
- package/dist/cli/monitor.d.ts +3 -0
- package/dist/cli/monitor.d.ts.map +1 -0
- package/dist/cli/monitor.js +442 -0
- package/dist/cli/monitor.js.map +1 -0
- package/dist/constants.d.ts +235 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +293 -0
- package/dist/constants.js.map +1 -0
- package/dist/discovery/governor-discovery.d.ts +84 -0
- package/dist/discovery/governor-discovery.d.ts.map +1 -0
- package/dist/discovery/governor-discovery.js +310 -0
- package/dist/discovery/governor-discovery.js.map +1 -0
- package/dist/discovery/security-council.d.ts +68 -0
- package/dist/discovery/security-council.d.ts.map +1 -0
- package/dist/discovery/security-council.js +181 -0
- package/dist/discovery/security-council.js.map +1 -0
- package/dist/discovery/timelock-discovery.d.ts +99 -0
- package/dist/discovery/timelock-discovery.d.ts.map +1 -0
- package/dist/discovery/timelock-discovery.js +322 -0
- package/dist/discovery/timelock-discovery.js.map +1 -0
- package/dist/election.d.ts +172 -0
- package/dist/election.d.ts.map +1 -0
- package/dist/election.js +464 -0
- package/dist/election.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +164 -0
- package/dist/index.js.map +1 -0
- package/dist/stages/base.d.ts +127 -0
- package/dist/stages/base.d.ts.map +1 -0
- package/dist/stages/base.js +280 -0
- package/dist/stages/base.js.map +1 -0
- package/dist/stages/l2-to-l1-message.d.ts +108 -0
- package/dist/stages/l2-to-l1-message.d.ts.map +1 -0
- package/dist/stages/l2-to-l1-message.js +422 -0
- package/dist/stages/l2-to-l1-message.js.map +1 -0
- package/dist/stages/proposal-created.d.ts +20 -0
- package/dist/stages/proposal-created.d.ts.map +1 -0
- package/dist/stages/proposal-created.js +62 -0
- package/dist/stages/proposal-created.js.map +1 -0
- package/dist/stages/proposal-queued.d.ts +39 -0
- package/dist/stages/proposal-queued.d.ts.map +1 -0
- package/dist/stages/proposal-queued.js +131 -0
- package/dist/stages/proposal-queued.js.map +1 -0
- package/dist/stages/retryables.d.ts +79 -0
- package/dist/stages/retryables.d.ts.map +1 -0
- package/dist/stages/retryables.js +307 -0
- package/dist/stages/retryables.js.map +1 -0
- package/dist/stages/stage-builder.d.ts +46 -0
- package/dist/stages/stage-builder.d.ts.map +1 -0
- package/dist/stages/stage-builder.js +87 -0
- package/dist/stages/stage-builder.js.map +1 -0
- package/dist/stages/timelock.d.ts +100 -0
- package/dist/stages/timelock.d.ts.map +1 -0
- package/dist/stages/timelock.js +552 -0
- package/dist/stages/timelock.js.map +1 -0
- package/dist/stages/voting.d.ts +18 -0
- package/dist/stages/voting.d.ts.map +1 -0
- package/dist/stages/voting.js +109 -0
- package/dist/stages/voting.js.map +1 -0
- package/dist/tracker/context.d.ts +111 -0
- package/dist/tracker/context.d.ts.map +1 -0
- package/dist/tracker/context.js +264 -0
- package/dist/tracker/context.js.map +1 -0
- package/dist/tracker/discovery.d.ts +89 -0
- package/dist/tracker/discovery.d.ts.map +1 -0
- package/dist/tracker/discovery.js +228 -0
- package/dist/tracker/discovery.js.map +1 -0
- package/dist/tracker/execute.d.ts +44 -0
- package/dist/tracker/execute.d.ts.map +1 -0
- package/dist/tracker/execute.js +126 -0
- package/dist/tracker/execute.js.map +1 -0
- package/dist/tracker/index.d.ts +18 -0
- package/dist/tracker/index.d.ts.map +1 -0
- package/dist/tracker/index.js +70 -0
- package/dist/tracker/index.js.map +1 -0
- package/dist/tracker/pipeline.d.ts +47 -0
- package/dist/tracker/pipeline.d.ts.map +1 -0
- package/dist/tracker/pipeline.js +299 -0
- package/dist/tracker/pipeline.js.map +1 -0
- package/dist/tracker/query.d.ts +45 -0
- package/dist/tracker/query.d.ts.map +1 -0
- package/dist/tracker/query.js +159 -0
- package/dist/tracker/query.js.map +1 -0
- package/dist/tracker/state.d.ts +104 -0
- package/dist/tracker/state.d.ts.map +1 -0
- package/dist/tracker/state.js +287 -0
- package/dist/tracker/state.js.map +1 -0
- package/dist/tracker.d.ts +261 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +556 -0
- package/dist/tracker.js.map +1 -0
- package/dist/types/config.d.ts +81 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +6 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/core.d.ts +51 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +6 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/cross-chain.d.ts +80 -0
- package/dist/types/cross-chain.d.ts.map +1 -0
- package/dist/types/cross-chain.js +6 -0
- package/dist/types/cross-chain.js.map +1 -0
- package/dist/types/election.d.ts +59 -0
- package/dist/types/election.d.ts.map +1 -0
- package/dist/types/election.js +6 -0
- package/dist/types/election.js.map +1 -0
- package/dist/types/governor.d.ts +71 -0
- package/dist/types/governor.d.ts.map +1 -0
- package/dist/types/governor.js +6 -0
- package/dist/types/governor.js.map +1 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/stages.d.ts +189 -0
- package/dist/types/stages.d.ts.map +1 -0
- package/dist/types/stages.js +23 -0
- package/dist/types/stages.js.map +1 -0
- package/dist/types/timelock.d.ts +108 -0
- package/dist/types/timelock.d.ts.map +1 -0
- package/dist/types/timelock.js +6 -0
- package/dist/types/timelock.js.map +1 -0
- package/dist/types/tracking.d.ts +180 -0
- package/dist/types/tracking.d.ts.map +1 -0
- package/dist/types/tracking.js +6 -0
- package/dist/types/tracking.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/chain.d.ts +18 -0
- package/dist/utils/chain.d.ts.map +1 -0
- package/dist/utils/chain.js +34 -0
- package/dist/utils/chain.js.map +1 -0
- package/dist/utils/log-filters.d.ts +67 -0
- package/dist/utils/log-filters.d.ts.map +1 -0
- package/dist/utils/log-filters.js +116 -0
- package/dist/utils/log-filters.js.map +1 -0
- package/dist/utils/log-search.d.ts +76 -0
- package/dist/utils/log-search.d.ts.map +1 -0
- package/dist/utils/log-search.js +142 -0
- package/dist/utils/log-search.js.map +1 -0
- package/dist/utils/logger.d.ts +41 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +50 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/operation-id.d.ts +48 -0
- package/dist/utils/operation-id.d.ts.map +1 -0
- package/dist/utils/operation-id.js +102 -0
- package/dist/utils/operation-id.js.map +1 -0
- package/dist/utils/rpc-utils.d.ts +30 -0
- package/dist/utils/rpc-utils.d.ts.map +1 -0
- package/dist/utils/rpc-utils.js +99 -0
- package/dist/utils/rpc-utils.js.map +1 -0
- package/dist/utils/salt-computation.d.ts +78 -0
- package/dist/utils/salt-computation.d.ts.map +1 -0
- package/dist/utils/salt-computation.js +132 -0
- package/dist/utils/salt-computation.js.map +1 -0
- package/dist/utils/salt-resolver.d.ts +63 -0
- package/dist/utils/salt-resolver.d.ts.map +1 -0
- package/dist/utils/salt-resolver.js +144 -0
- package/dist/utils/salt-resolver.js.map +1 -0
- package/dist/utils/scoped-logger.d.ts +43 -0
- package/dist/utils/scoped-logger.d.ts.map +1 -0
- package/dist/utils/scoped-logger.js +72 -0
- package/dist/utils/scoped-logger.js.map +1 -0
- package/dist/utils/stage-helpers.d.ts +51 -0
- package/dist/utils/stage-helpers.d.ts.map +1 -0
- package/dist/utils/stage-helpers.js +143 -0
- package/dist/utils/stage-helpers.js.map +1 -0
- package/dist/utils/stage-metadata.d.ts +62 -0
- package/dist/utils/stage-metadata.d.ts.map +1 -0
- package/dist/utils/stage-metadata.js +140 -0
- package/dist/utils/stage-metadata.js.map +1 -0
- package/dist/utils/timing.d.ts +115 -0
- package/dist/utils/timing.d.ts.map +1 -0
- package/dist/utils/timing.js +303 -0
- package/dist/utils/timing.js.map +1 -0
- package/dist/utils/urls.d.ts +20 -0
- package/dist/utils/urls.d.ts.map +1 -0
- package/dist/utils/urls.js +51 -0
- package/dist/utils/urls.js.map +1 -0
- 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
|
+
}
|