@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,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Governor discovery module
|
|
4
|
+
*
|
|
5
|
+
* Find proposals, detect governor type, parse ProposalCreated events.
|
|
6
|
+
* Also includes proposal discovery functions for block range scanning.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.detectProposalType = detectProposalType;
|
|
10
|
+
exports.isElectionProposal = isElectionProposal;
|
|
11
|
+
exports.detectGovernorCapabilities = detectGovernorCapabilities;
|
|
12
|
+
exports.getTimelockAddress = getTimelockAddress;
|
|
13
|
+
exports.getProposalState = getProposalState;
|
|
14
|
+
exports.parseProposalCreatedEvent = parseProposalCreatedEvent;
|
|
15
|
+
exports.findProposalCreatedEvent = findProposalCreatedEvent;
|
|
16
|
+
exports.findProposalByTxHash = findProposalByTxHash;
|
|
17
|
+
exports.getVotingData = getVotingData;
|
|
18
|
+
exports.findProposalQueuedEvent = findProposalQueuedEvent;
|
|
19
|
+
exports.discoverProposals = discoverProposals;
|
|
20
|
+
exports.discoverProposalByTxHash = discoverProposalByTxHash;
|
|
21
|
+
const ethers_1 = require("ethers");
|
|
22
|
+
const constants_1 = require("../constants");
|
|
23
|
+
const log_search_1 = require("../utils/log-search");
|
|
24
|
+
const log_filters_1 = require("../utils/log-filters");
|
|
25
|
+
const rpc_utils_1 = require("../utils/rpc-utils");
|
|
26
|
+
const timing_1 = require("../utils/timing");
|
|
27
|
+
const abis_1 = require("../abis");
|
|
28
|
+
const election_1 = require("../election");
|
|
29
|
+
const chain_1 = require("../utils/chain");
|
|
30
|
+
/**
|
|
31
|
+
* Detect governor type from address
|
|
32
|
+
*/
|
|
33
|
+
function detectProposalType(governorAddress) {
|
|
34
|
+
if ((0, chain_1.addressEquals)(governorAddress, constants_1.ADDRESSES.CONSTITUTIONAL_GOVERNOR))
|
|
35
|
+
return "CONSTITUTIONAL";
|
|
36
|
+
if ((0, chain_1.addressEquals)(governorAddress, constants_1.ADDRESSES.NON_CONSTITUTIONAL_GOVERNOR))
|
|
37
|
+
return "NON_CONSTITUTIONAL";
|
|
38
|
+
if ((0, chain_1.addressEquals)(governorAddress, constants_1.ADDRESSES.ELECTION_NOMINEE_GOVERNOR))
|
|
39
|
+
return "ELECTION_NOMINEE";
|
|
40
|
+
if ((0, chain_1.addressEquals)(governorAddress, constants_1.ADDRESSES.ELECTION_MEMBER_GOVERNOR))
|
|
41
|
+
return "ELECTION_MEMBER";
|
|
42
|
+
return "UNKNOWN";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if a governor type is a Security Council election governor
|
|
46
|
+
*/
|
|
47
|
+
function isElectionProposal(proposalType) {
|
|
48
|
+
return proposalType === "ELECTION_NOMINEE" || proposalType === "ELECTION_MEMBER";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if a governor has a timelock() function
|
|
52
|
+
*
|
|
53
|
+
* Governors with timelock route proposals through L2 timelock before execution.
|
|
54
|
+
*/
|
|
55
|
+
async function hasTimelock(governorAddress, provider) {
|
|
56
|
+
const governor = new ethers_1.ethers.Contract(governorAddress, abis_1.GOVERNOR_ABI, provider);
|
|
57
|
+
try {
|
|
58
|
+
await governor.timelock();
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Detect governor capabilities by probing the contract
|
|
67
|
+
*
|
|
68
|
+
* This function determines the execution path for proposals:
|
|
69
|
+
* - WITH_TIMELOCK: Governor -> L2Timelock -> (optional L1 round-trip)
|
|
70
|
+
* - WITH_VETTING: Same as WITH_TIMELOCK but with vetting period
|
|
71
|
+
* - NO_TIMELOCK: Direct governor.execute() without timelock
|
|
72
|
+
*
|
|
73
|
+
* The detection order matters:
|
|
74
|
+
* 1. Check for timelock() first - most governors have this
|
|
75
|
+
* 2. Check for nomineeVetter() - only Security Council Nominee Election Governor
|
|
76
|
+
* 3. Default to NO_TIMELOCK - Security Council Member Election Governor
|
|
77
|
+
*/
|
|
78
|
+
async function detectGovernorCapabilities(governorAddress, provider) {
|
|
79
|
+
// Check for timelock first (most common case)
|
|
80
|
+
if (await hasTimelock(governorAddress, provider)) {
|
|
81
|
+
return "WITH_TIMELOCK";
|
|
82
|
+
}
|
|
83
|
+
// Check for vetting period (Security Council Nominee Election)
|
|
84
|
+
if (await (0, election_1.hasVettingPeriod)(governorAddress, provider)) {
|
|
85
|
+
return "WITH_VETTING";
|
|
86
|
+
}
|
|
87
|
+
// No timelock and no vetting - direct execution
|
|
88
|
+
return "NO_TIMELOCK";
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the timelock address for a governor
|
|
92
|
+
*/
|
|
93
|
+
async function getTimelockAddress(governorAddress, provider) {
|
|
94
|
+
const governor = new ethers_1.ethers.Contract(governorAddress, abis_1.GOVERNOR_ABI, provider);
|
|
95
|
+
return (0, rpc_utils_1.queryWithRetry)(() => governor.timelock());
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get proposal state from governor contract
|
|
99
|
+
*/
|
|
100
|
+
async function getProposalState(governorAddress, proposalId, provider) {
|
|
101
|
+
const governor = new ethers_1.ethers.Contract(governorAddress, abis_1.GOVERNOR_ABI, provider);
|
|
102
|
+
const stateNum = (await (0, rpc_utils_1.queryWithRetry)(() => governor.state(ethers_1.BigNumber.from(proposalId))));
|
|
103
|
+
const stateNumber = typeof stateNum === "number" ? stateNum : stateNum.toNumber();
|
|
104
|
+
const state = constants_1.PROPOSAL_STATE_MAP[stateNumber];
|
|
105
|
+
if (!state) {
|
|
106
|
+
throw new Error(`Unknown proposal state number: ${stateNumber}`);
|
|
107
|
+
}
|
|
108
|
+
return state;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Parse ProposalCreated event data
|
|
112
|
+
*/
|
|
113
|
+
function parseProposalCreatedEvent(log) {
|
|
114
|
+
try {
|
|
115
|
+
const parsed = abis_1.proposalCreatedInterface.parseLog(log);
|
|
116
|
+
// Cast through unknown required due to ethers' Result type structure
|
|
117
|
+
const args = parsed.args;
|
|
118
|
+
return {
|
|
119
|
+
proposalId: args.proposalId.toString(),
|
|
120
|
+
proposer: args.proposer,
|
|
121
|
+
targets: args.targets,
|
|
122
|
+
values: args.values,
|
|
123
|
+
signatures: args.signatures,
|
|
124
|
+
calldatas: args.calldatas,
|
|
125
|
+
startBlock: args.startBlock,
|
|
126
|
+
endBlock: args.endBlock,
|
|
127
|
+
description: args.description,
|
|
128
|
+
creationBlock: log.blockNumber,
|
|
129
|
+
creationTxHash: log.transactionHash,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Find ProposalCreated event by proposal ID
|
|
138
|
+
*
|
|
139
|
+
* @param hint - Search optimization hint. Default is backward search from current block.
|
|
140
|
+
*/
|
|
141
|
+
async function findProposalCreatedEvent(governorAddress, proposalId, provider, hint) {
|
|
142
|
+
const { blockNumber: currentBlock } = await (0, timing_1.getCurrentBlockInfo)(provider);
|
|
143
|
+
// Apply search hint (default: search backward from current block)
|
|
144
|
+
const fromBlock = hint?.startBlock ?? constants_1.GOVERNANCE_START_BLOCKS.L2;
|
|
145
|
+
const toBlock = hint?.endBlock ?? currentBlock;
|
|
146
|
+
const reverseDirection = hint?.direction === "backward" || !hint?.direction;
|
|
147
|
+
// Note: ProposalCreated event does NOT have indexed proposalId
|
|
148
|
+
// We filter by event topic only and use predicate for exact matching
|
|
149
|
+
return (0, log_search_1.findAndParseEvent)(provider, { address: governorAddress, topics: [constants_1.EVENT_TOPICS.PROPOSAL_CREATED], fromBlock, toBlock }, (l) => parseProposalCreatedEvent(l)?.proposalId === proposalId, parseProposalCreatedEvent, { chunkSize: 10000000, reverseDirection });
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Find ProposalCreated event by transaction hash
|
|
153
|
+
*/
|
|
154
|
+
async function findProposalByTxHash(txHash, provider) {
|
|
155
|
+
const receipt = await (0, rpc_utils_1.queryWithRetry)(() => provider.getTransactionReceipt(txHash));
|
|
156
|
+
if (!receipt) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
return (0, log_filters_1.findFirstLog)(receipt.logs, { topic: constants_1.EVENT_TOPICS.PROPOSAL_CREATED }, parseProposalCreatedEvent);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get voting information for a proposal
|
|
163
|
+
*/
|
|
164
|
+
async function getVotingData(governorAddress, proposalId, provider) {
|
|
165
|
+
const governor = new ethers_1.ethers.Contract(governorAddress, abis_1.GOVERNOR_ABI, provider);
|
|
166
|
+
const proposalIdBN = ethers_1.BigNumber.from(proposalId);
|
|
167
|
+
// Fetch all voting data in parallel
|
|
168
|
+
const [startBlock, deadline, votes, { blockNumber: currentBlock }] = await Promise.all([
|
|
169
|
+
(0, rpc_utils_1.queryWithRetry)(() => governor.proposalSnapshot(proposalIdBN)),
|
|
170
|
+
(0, rpc_utils_1.queryWithRetry)(() => governor.proposalDeadline(proposalIdBN)),
|
|
171
|
+
(0, rpc_utils_1.queryWithRetry)(() => governor.proposalVotes(proposalIdBN)),
|
|
172
|
+
(0, timing_1.getCurrentBlockInfo)(provider),
|
|
173
|
+
]);
|
|
174
|
+
// Get quorum at start block
|
|
175
|
+
const quorum = (await (0, rpc_utils_1.queryWithRetry)(() => governor.quorum(startBlock)));
|
|
176
|
+
// Check for extended deadline (late quorum)
|
|
177
|
+
let extendedDeadline;
|
|
178
|
+
try {
|
|
179
|
+
const extended = await governor.proposalExtendedDeadline(proposalIdBN);
|
|
180
|
+
if (extended.gt(0)) {
|
|
181
|
+
extendedDeadline = extended;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// Function not available on this governor
|
|
186
|
+
}
|
|
187
|
+
// Check for vetting deadline (Security Council)
|
|
188
|
+
// IMPORTANT: Vetting deadline is an L1 block number, not L2
|
|
189
|
+
let vettingDeadline;
|
|
190
|
+
let isVettingPeriod = false;
|
|
191
|
+
try {
|
|
192
|
+
const vetting = await governor.proposalVettingDeadline(proposalIdBN);
|
|
193
|
+
if (vetting.gt(0)) {
|
|
194
|
+
vettingDeadline = vetting;
|
|
195
|
+
// Use L1 block number for comparison since vetting deadline is L1-based
|
|
196
|
+
const l1Block = await (0, timing_1.getL1BlockNumberFromL2)(provider);
|
|
197
|
+
isVettingPeriod = l1Block.lte(vetting);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// Function not available on this governor
|
|
202
|
+
}
|
|
203
|
+
const effectiveDeadline = extendedDeadline ?? deadline;
|
|
204
|
+
const hasReachedQuorum = votes.forVotes.gte(quorum);
|
|
205
|
+
const isVotingPeriodOver = ethers_1.BigNumber.from(currentBlock).gt(effectiveDeadline);
|
|
206
|
+
return {
|
|
207
|
+
startBlock,
|
|
208
|
+
endBlock: deadline,
|
|
209
|
+
deadline: effectiveDeadline,
|
|
210
|
+
forVotes: votes.forVotes,
|
|
211
|
+
againstVotes: votes.againstVotes,
|
|
212
|
+
abstainVotes: votes.abstainVotes,
|
|
213
|
+
quorum,
|
|
214
|
+
hasReachedQuorum,
|
|
215
|
+
isVotingPeriodOver,
|
|
216
|
+
extendedDeadline,
|
|
217
|
+
vettingDeadline,
|
|
218
|
+
isVettingPeriod,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Find ProposalQueued event for a proposal
|
|
223
|
+
*
|
|
224
|
+
* Note: ProposalQueued(uint256 proposalId, uint256 eta) has NON-INDEXED parameters,
|
|
225
|
+
* so we cannot filter by proposalId in topics. We must search for all ProposalQueued
|
|
226
|
+
* events and decode the data to find the matching proposalId.
|
|
227
|
+
*
|
|
228
|
+
* @param hint - Search optimization hint. Default is backward search from current block.
|
|
229
|
+
*/
|
|
230
|
+
async function findProposalQueuedEvent(governorAddress, proposalId, provider, hint) {
|
|
231
|
+
const { blockNumber: currentBlock } = await (0, timing_1.getCurrentBlockInfo)(provider);
|
|
232
|
+
// Apply search hint (default: search backward from current block)
|
|
233
|
+
const fromBlock = hint?.startBlock ?? constants_1.GOVERNANCE_START_BLOCKS.L2;
|
|
234
|
+
const toBlock = hint?.endBlock ?? currentBlock;
|
|
235
|
+
const reverseDirection = hint?.direction === "backward" || !hint?.direction;
|
|
236
|
+
const targetProposalId = ethers_1.BigNumber.from(proposalId);
|
|
237
|
+
// ProposalQueued has non-indexed parameters, so we search by event signature only
|
|
238
|
+
// and decode the data to match the proposalId
|
|
239
|
+
const log = await (0, log_search_1.findLog)(provider, {
|
|
240
|
+
address: governorAddress,
|
|
241
|
+
topics: [constants_1.EVENT_TOPICS.PROPOSAL_QUEUED],
|
|
242
|
+
fromBlock,
|
|
243
|
+
toBlock,
|
|
244
|
+
}, (logEntry) => {
|
|
245
|
+
try {
|
|
246
|
+
const parsed = abis_1.proposalQueuedInterface.parseLog(logEntry);
|
|
247
|
+
return parsed.args.proposalId.eq(targetProposalId);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}, { chunkSize: 10000000, reverseDirection });
|
|
253
|
+
if (!log) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
const parsed = abis_1.proposalQueuedInterface.parseLog(log);
|
|
258
|
+
return {
|
|
259
|
+
blockNumber: log.blockNumber,
|
|
260
|
+
txHash: log.transactionHash,
|
|
261
|
+
eta: parsed.args.eta,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
// Discovery Functions (merged from monitor-discovery.ts)
|
|
269
|
+
/** Discover proposals from a governor in a block range */
|
|
270
|
+
async function discoverProposals(governorAddress, fromBlock, toBlock, provider, options = {}) {
|
|
271
|
+
if (fromBlock >= toBlock)
|
|
272
|
+
return [];
|
|
273
|
+
const { logs } = await (0, log_search_1.searchLogsInChunks)(provider, { address: governorAddress, topics: [constants_1.EVENT_TOPICS.PROPOSAL_CREATED], fromBlock, toBlock }, { chunkSize: options.chunkSize ?? constants_1.CHUNK_SIZES.L2 });
|
|
274
|
+
const seen = new Set();
|
|
275
|
+
return logs.flatMap((log) => {
|
|
276
|
+
if (seen.has(log.transactionHash))
|
|
277
|
+
return [];
|
|
278
|
+
seen.add(log.transactionHash);
|
|
279
|
+
const parsed = parseProposalCreatedEvent(log);
|
|
280
|
+
return parsed
|
|
281
|
+
? [
|
|
282
|
+
{
|
|
283
|
+
governorAddress,
|
|
284
|
+
proposalId: parsed.proposalId,
|
|
285
|
+
creationTxHash: log.transactionHash,
|
|
286
|
+
creationBlock: log.blockNumber,
|
|
287
|
+
},
|
|
288
|
+
]
|
|
289
|
+
: [];
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
/** Discover a proposal by transaction hash */
|
|
293
|
+
async function discoverProposalByTxHash(txHash, provider) {
|
|
294
|
+
const receipt = await (0, rpc_utils_1.queryWithRetry)(() => provider.getTransactionReceipt(txHash));
|
|
295
|
+
if (!receipt)
|
|
296
|
+
return null;
|
|
297
|
+
const log = receipt.logs.find((l) => l.topics[0] === constants_1.EVENT_TOPICS.PROPOSAL_CREATED);
|
|
298
|
+
if (!log)
|
|
299
|
+
return null;
|
|
300
|
+
const parsed = parseProposalCreatedEvent(log);
|
|
301
|
+
return parsed
|
|
302
|
+
? {
|
|
303
|
+
governorAddress: log.address,
|
|
304
|
+
proposalId: parsed.proposalId,
|
|
305
|
+
creationTxHash: txHash,
|
|
306
|
+
creationBlock: receipt.blockNumber,
|
|
307
|
+
}
|
|
308
|
+
: null;
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=governor-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governor-discovery.js","sourceRoot":"","sources":["../../src/discovery/governor-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Council special handling
|
|
3
|
+
*
|
|
4
|
+
* Detect Security Council updates, handle vetting periods, generate salts
|
|
5
|
+
*/
|
|
6
|
+
import { BigNumber, ethers } from "ethers";
|
|
7
|
+
/**
|
|
8
|
+
* Check vetting period for a Security Council nominee election
|
|
9
|
+
*
|
|
10
|
+
* IMPORTANT: The vetting deadline is an L1 block number, not an L2 block number.
|
|
11
|
+
* We must compare against the L1 block number (via ArbSys) to determine if
|
|
12
|
+
* vetting is still active. This is consistent with how voting deadlines work.
|
|
13
|
+
*/
|
|
14
|
+
export declare function checkVettingPeriod(governorAddress: string, proposalId: string, provider: ethers.providers.Provider): Promise<{
|
|
15
|
+
hasVettingPeriod: boolean;
|
|
16
|
+
vettingDeadline: BigNumber | null;
|
|
17
|
+
isVettingActive: boolean;
|
|
18
|
+
vetterAddress: string | null;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Detect if a proposal is a Security Council election
|
|
22
|
+
*/
|
|
23
|
+
export declare function isSecurityCouncilElectionProposal(targets: string[]): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Extracted Security Council operation parameters
|
|
26
|
+
*/
|
|
27
|
+
export interface SecurityCouncilOperationParams {
|
|
28
|
+
members: string[];
|
|
29
|
+
nonce: BigNumber;
|
|
30
|
+
timelockAddress: string;
|
|
31
|
+
/** Operation ID for this specific operation */
|
|
32
|
+
operationId?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* All Security Council operations in a batch transaction
|
|
36
|
+
*/
|
|
37
|
+
export interface SecurityCouncilBatchParams {
|
|
38
|
+
/** All operations with their individual params */
|
|
39
|
+
operations: SecurityCouncilOperationParams[];
|
|
40
|
+
/** Common timelock address */
|
|
41
|
+
timelockAddress: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a transaction receipt is a Security Council operation
|
|
45
|
+
*/
|
|
46
|
+
export declare function isSecurityCouncilOperation(receipt: ethers.providers.TransactionReceipt): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Extract Security Council params for ALL operations from a CallScheduled receipt
|
|
49
|
+
*
|
|
50
|
+
* SC rotations create MULTIPLE operations in a single transaction, each with
|
|
51
|
+
* its own incrementing nonce. This function returns params for every operation.
|
|
52
|
+
*/
|
|
53
|
+
export declare function extractAllSecurityCouncilParams(receipt: ethers.providers.TransactionReceipt): SecurityCouncilBatchParams | null;
|
|
54
|
+
/**
|
|
55
|
+
* Extract Security Council params for a specific operation by operationId
|
|
56
|
+
*
|
|
57
|
+
* Use this when you need the salt for a specific operation in a multi-operation
|
|
58
|
+
* SC rotation batch. Each operation has its own nonce and therefore its own salt.
|
|
59
|
+
*/
|
|
60
|
+
export declare function extractSecurityCouncilParamsForOperation(receipt: ethers.providers.TransactionReceipt, targetOperationId: string): SecurityCouncilOperationParams | null;
|
|
61
|
+
/**
|
|
62
|
+
* Extract Security Council params for the last operation in a batch
|
|
63
|
+
*
|
|
64
|
+
* Returns the last operation. Use extractSecurityCouncilParamsForOperation
|
|
65
|
+
* for specific operation lookups.
|
|
66
|
+
*/
|
|
67
|
+
export declare function extractSecurityCouncilParams(receipt: ethers.providers.TransactionReceipt): SecurityCouncilOperationParams | null;
|
|
68
|
+
//# sourceMappingURL=security-council.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-council.d.ts","sourceRoot":"","sources":["../../src/discovery/security-council.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAa3C;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,QAAQ,GAClC,OAAO,CAAC;IACT,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,SAAS,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC,CAwCD;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAE5E;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,kDAAkD;IAClD,UAAU,EAAE,8BAA8B,EAAE,CAAC;IAC7C,8BAA8B;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAAG,OAAO,CAEhG;AA0CD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAC3C,0BAA0B,GAAG,IAAI,CAkDnC;AAED;;;;;GAKG;AACH,wBAAgB,wCAAwC,CACtD,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,EAC5C,iBAAiB,EAAE,MAAM,GACxB,8BAA8B,GAAG,IAAI,CAWvC;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAC3C,8BAA8B,GAAG,IAAI,CAMvC"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security Council special handling
|
|
4
|
+
*
|
|
5
|
+
* Detect Security Council updates, handle vetting periods, generate salts
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.checkVettingPeriod = checkVettingPeriod;
|
|
9
|
+
exports.isSecurityCouncilElectionProposal = isSecurityCouncilElectionProposal;
|
|
10
|
+
exports.isSecurityCouncilOperation = isSecurityCouncilOperation;
|
|
11
|
+
exports.extractAllSecurityCouncilParams = extractAllSecurityCouncilParams;
|
|
12
|
+
exports.extractSecurityCouncilParamsForOperation = extractSecurityCouncilParamsForOperation;
|
|
13
|
+
exports.extractSecurityCouncilParams = extractSecurityCouncilParams;
|
|
14
|
+
const ethers_1 = require("ethers");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
16
|
+
const rpc_utils_1 = require("../utils/rpc-utils");
|
|
17
|
+
const timing_1 = require("../utils/timing");
|
|
18
|
+
const chain_1 = require("../utils/chain");
|
|
19
|
+
const abis_1 = require("../abis");
|
|
20
|
+
/**
|
|
21
|
+
* Check vetting period for a Security Council nominee election
|
|
22
|
+
*
|
|
23
|
+
* IMPORTANT: The vetting deadline is an L1 block number, not an L2 block number.
|
|
24
|
+
* We must compare against the L1 block number (via ArbSys) to determine if
|
|
25
|
+
* vetting is still active. This is consistent with how voting deadlines work.
|
|
26
|
+
*/
|
|
27
|
+
async function checkVettingPeriod(governorAddress, proposalId, provider) {
|
|
28
|
+
const governor = new ethers_1.ethers.Contract(governorAddress, abis_1.GOVERNOR_WITH_VETTER_ABI, provider);
|
|
29
|
+
try {
|
|
30
|
+
// First check if this governor has vetting functionality
|
|
31
|
+
const [vettingDeadline, vetterAddress] = await Promise.all([
|
|
32
|
+
(0, rpc_utils_1.queryWithRetry)(() => governor.proposalVettingDeadline(proposalId)),
|
|
33
|
+
(0, rpc_utils_1.queryWithRetry)(() => governor.vetter()),
|
|
34
|
+
]);
|
|
35
|
+
// If no vetting deadline set, no vetting period
|
|
36
|
+
if (!vettingDeadline.gt(0)) {
|
|
37
|
+
return {
|
|
38
|
+
hasVettingPeriod: false,
|
|
39
|
+
vettingDeadline: null,
|
|
40
|
+
isVettingActive: false,
|
|
41
|
+
vetterAddress,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// CRITICAL: The vetting deadline is an L1 block number.
|
|
45
|
+
// We need to get the current L1 block number via Multicall3.
|
|
46
|
+
const currentL1Block = await (0, timing_1.getL1BlockNumberFromL2)(provider);
|
|
47
|
+
const isVettingActive = currentL1Block.lte(vettingDeadline);
|
|
48
|
+
return {
|
|
49
|
+
hasVettingPeriod: true,
|
|
50
|
+
vettingDeadline,
|
|
51
|
+
isVettingActive,
|
|
52
|
+
vetterAddress,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Governor doesn't have vetting functionality
|
|
57
|
+
return {
|
|
58
|
+
hasVettingPeriod: false,
|
|
59
|
+
vettingDeadline: null,
|
|
60
|
+
isVettingActive: false,
|
|
61
|
+
vetterAddress: null,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Detect if a proposal is a Security Council election
|
|
67
|
+
*/
|
|
68
|
+
function isSecurityCouncilElectionProposal(targets) {
|
|
69
|
+
return targets.some((target) => (0, chain_1.addressEquals)(target, constants_1.ADDRESSES.SECURITY_COUNCIL_MANAGER));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if a transaction receipt is a Security Council operation
|
|
73
|
+
*/
|
|
74
|
+
function isSecurityCouncilOperation(receipt) {
|
|
75
|
+
return receipt.logs.some((log) => (0, chain_1.addressEquals)(log.address, constants_1.ADDRESSES.SECURITY_COUNCIL_MANAGER));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Extract members and nonce from CallScheduled event data
|
|
79
|
+
*
|
|
80
|
+
* The extraction follows this data nesting:
|
|
81
|
+
* 1. CallScheduled event contains data for ArbSys.sendTxToL1
|
|
82
|
+
* 2. sendTxToL1 contains data for L1Timelock.scheduleBatch
|
|
83
|
+
* 3. scheduleBatch's first payload contains UpgradeExecutor.execute
|
|
84
|
+
* 4. execute contains SecurityCouncilMemberSyncAction.perform(council, members, nonce)
|
|
85
|
+
*/
|
|
86
|
+
function extractMembersAndNonceFromCallData(data) {
|
|
87
|
+
try {
|
|
88
|
+
// Step 1: Decode ArbSys.sendTxToL1(destination, data)
|
|
89
|
+
const sendTxToL1Data = abis_1.arbSysInterface.decodeFunctionData("sendTxToL1", data);
|
|
90
|
+
const l1TimelockData = sendTxToL1Data[1];
|
|
91
|
+
// Step 2: Decode L1Timelock.scheduleBatch(...)
|
|
92
|
+
const scheduleBatchData = abis_1.timelockInterface.decodeFunctionData("scheduleBatch", l1TimelockData);
|
|
93
|
+
const payloads = scheduleBatchData[2];
|
|
94
|
+
if (payloads.length === 0) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
// Step 3: Decode UpgradeExecutor.execute(upgrade, data)
|
|
98
|
+
const executeData = abis_1.upgradeExecutorInterface.decodeFunctionData("execute", payloads[0]);
|
|
99
|
+
const actionData = executeData[1];
|
|
100
|
+
// Step 4: Decode SecurityCouncilMemberSyncAction.perform(council, members, nonce)
|
|
101
|
+
const performData = abis_1.memberSyncActionInterface.decodeFunctionData("perform", actionData);
|
|
102
|
+
const members = performData[1];
|
|
103
|
+
const nonce = performData[2];
|
|
104
|
+
return { members, nonce };
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Extract Security Council params for ALL operations from a CallScheduled receipt
|
|
112
|
+
*
|
|
113
|
+
* SC rotations create MULTIPLE operations in a single transaction, each with
|
|
114
|
+
* its own incrementing nonce. This function returns params for every operation.
|
|
115
|
+
*/
|
|
116
|
+
function extractAllSecurityCouncilParams(receipt) {
|
|
117
|
+
if (!isSecurityCouncilOperation(receipt)) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const callScheduledLogs = receipt.logs.filter((log) => log.topics[0] === constants_1.EVENT_TOPICS.CALL_SCHEDULED);
|
|
121
|
+
if (callScheduledLogs.length === 0) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
// Validate all CallScheduled logs come from the same timelock
|
|
125
|
+
// SC operations should all target the same L2 timelock
|
|
126
|
+
const timelockAddress = callScheduledLogs[0].address;
|
|
127
|
+
const hasMultipleTimelocks = callScheduledLogs.some((log) => !(0, chain_1.addressEquals)(log.address, timelockAddress));
|
|
128
|
+
if (hasMultipleTimelocks) {
|
|
129
|
+
// This shouldn't happen for SC operations, but guard against it
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const operations = [];
|
|
133
|
+
for (const log of callScheduledLogs) {
|
|
134
|
+
const parsed = abis_1.timelockInterface.parseLog(log);
|
|
135
|
+
const operationId = parsed.args.id;
|
|
136
|
+
const callData = parsed.args.data;
|
|
137
|
+
const extracted = extractMembersAndNonceFromCallData(callData);
|
|
138
|
+
if (extracted) {
|
|
139
|
+
operations.push({
|
|
140
|
+
members: extracted.members,
|
|
141
|
+
nonce: extracted.nonce,
|
|
142
|
+
timelockAddress: log.address,
|
|
143
|
+
operationId,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (operations.length === 0) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
operations,
|
|
152
|
+
timelockAddress,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Extract Security Council params for a specific operation by operationId
|
|
157
|
+
*
|
|
158
|
+
* Use this when you need the salt for a specific operation in a multi-operation
|
|
159
|
+
* SC rotation batch. Each operation has its own nonce and therefore its own salt.
|
|
160
|
+
*/
|
|
161
|
+
function extractSecurityCouncilParamsForOperation(receipt, targetOperationId) {
|
|
162
|
+
const batch = extractAllSecurityCouncilParams(receipt);
|
|
163
|
+
if (!batch) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return (batch.operations.find((op) => op.operationId && (0, chain_1.addressEquals)(op.operationId, targetOperationId)) ?? null);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Extract Security Council params for the last operation in a batch
|
|
170
|
+
*
|
|
171
|
+
* Returns the last operation. Use extractSecurityCouncilParamsForOperation
|
|
172
|
+
* for specific operation lookups.
|
|
173
|
+
*/
|
|
174
|
+
function extractSecurityCouncilParams(receipt) {
|
|
175
|
+
const batch = extractAllSecurityCouncilParams(receipt);
|
|
176
|
+
if (!batch || batch.operations.length === 0) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
return batch.operations[batch.operations.length - 1];
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=security-council.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-council.js","sourceRoot":"","sources":["../../src/discovery/security-council.ts"],"names":[],"mappings":"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"}
|