@aztec/sequencer-client 0.0.0-test.0 → 0.0.1-commit.0208eb9

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 (135) hide show
  1. package/dest/client/index.d.ts +1 -1
  2. package/dest/client/sequencer-client.d.ts +31 -31
  3. package/dest/client/sequencer-client.d.ts.map +1 -1
  4. package/dest/client/sequencer-client.js +82 -60
  5. package/dest/config.d.ts +15 -16
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +118 -70
  8. package/dest/global_variable_builder/global_builder.d.ts +26 -15
  9. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  10. package/dest/global_variable_builder/global_builder.js +62 -44
  11. package/dest/global_variable_builder/index.d.ts +1 -1
  12. package/dest/index.d.ts +2 -4
  13. package/dest/index.d.ts.map +1 -1
  14. package/dest/index.js +1 -3
  15. package/dest/publisher/config.d.ts +15 -12
  16. package/dest/publisher/config.d.ts.map +1 -1
  17. package/dest/publisher/config.js +32 -19
  18. package/dest/publisher/index.d.ts +3 -1
  19. package/dest/publisher/index.d.ts.map +1 -1
  20. package/dest/publisher/index.js +3 -0
  21. package/dest/publisher/sequencer-publisher-factory.d.ts +44 -0
  22. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -0
  23. package/dest/publisher/sequencer-publisher-factory.js +51 -0
  24. package/dest/publisher/sequencer-publisher-metrics.d.ts +5 -4
  25. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  26. package/dest/publisher/sequencer-publisher-metrics.js +34 -62
  27. package/dest/publisher/sequencer-publisher.d.ts +134 -88
  28. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  29. package/dest/publisher/sequencer-publisher.js +1172 -254
  30. package/dest/sequencer/checkpoint_proposal_job.d.ts +100 -0
  31. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -0
  32. package/dest/sequencer/checkpoint_proposal_job.js +1188 -0
  33. package/dest/sequencer/checkpoint_voter.d.ts +35 -0
  34. package/dest/sequencer/checkpoint_voter.d.ts.map +1 -0
  35. package/dest/sequencer/checkpoint_voter.js +109 -0
  36. package/dest/sequencer/config.d.ts +7 -1
  37. package/dest/sequencer/config.d.ts.map +1 -1
  38. package/dest/sequencer/errors.d.ts +11 -0
  39. package/dest/sequencer/errors.d.ts.map +1 -0
  40. package/dest/sequencer/errors.js +15 -0
  41. package/dest/sequencer/events.d.ts +46 -0
  42. package/dest/sequencer/events.d.ts.map +1 -0
  43. package/dest/sequencer/events.js +1 -0
  44. package/dest/sequencer/index.d.ts +4 -2
  45. package/dest/sequencer/index.d.ts.map +1 -1
  46. package/dest/sequencer/index.js +3 -1
  47. package/dest/sequencer/metrics.d.ts +48 -12
  48. package/dest/sequencer/metrics.d.ts.map +1 -1
  49. package/dest/sequencer/metrics.js +213 -68
  50. package/dest/sequencer/sequencer.d.ts +146 -137
  51. package/dest/sequencer/sequencer.d.ts.map +1 -1
  52. package/dest/sequencer/sequencer.js +971 -525
  53. package/dest/sequencer/timetable.d.ts +76 -24
  54. package/dest/sequencer/timetable.d.ts.map +1 -1
  55. package/dest/sequencer/timetable.js +177 -61
  56. package/dest/sequencer/types.d.ts +3 -0
  57. package/dest/sequencer/types.d.ts.map +1 -0
  58. package/dest/sequencer/types.js +1 -0
  59. package/dest/sequencer/utils.d.ts +20 -38
  60. package/dest/sequencer/utils.d.ts.map +1 -1
  61. package/dest/sequencer/utils.js +12 -47
  62. package/dest/test/index.d.ts +9 -1
  63. package/dest/test/index.d.ts.map +1 -1
  64. package/dest/test/index.js +0 -4
  65. package/dest/test/mock_checkpoint_builder.d.ts +95 -0
  66. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -0
  67. package/dest/test/mock_checkpoint_builder.js +220 -0
  68. package/dest/test/utils.d.ts +53 -0
  69. package/dest/test/utils.d.ts.map +1 -0
  70. package/dest/test/utils.js +103 -0
  71. package/package.json +47 -45
  72. package/src/client/sequencer-client.ts +106 -107
  73. package/src/config.ts +131 -81
  74. package/src/global_variable_builder/global_builder.ts +84 -55
  75. package/src/index.ts +1 -3
  76. package/src/publisher/config.ts +45 -32
  77. package/src/publisher/index.ts +4 -0
  78. package/src/publisher/sequencer-publisher-factory.ts +92 -0
  79. package/src/publisher/sequencer-publisher-metrics.ts +33 -63
  80. package/src/publisher/sequencer-publisher.ts +990 -302
  81. package/src/sequencer/README.md +531 -0
  82. package/src/sequencer/checkpoint_proposal_job.ts +872 -0
  83. package/src/sequencer/checkpoint_voter.ts +130 -0
  84. package/src/sequencer/config.ts +8 -0
  85. package/src/sequencer/errors.ts +21 -0
  86. package/src/sequencer/events.ts +27 -0
  87. package/src/sequencer/index.ts +3 -1
  88. package/src/sequencer/metrics.ts +288 -73
  89. package/src/sequencer/sequencer.ts +714 -588
  90. package/src/sequencer/timetable.ts +221 -62
  91. package/src/sequencer/types.ts +6 -0
  92. package/src/sequencer/utils.ts +28 -60
  93. package/src/test/index.ts +12 -4
  94. package/src/test/mock_checkpoint_builder.ts +309 -0
  95. package/src/test/utils.ts +164 -0
  96. package/dest/sequencer/allowed.d.ts +0 -3
  97. package/dest/sequencer/allowed.d.ts.map +0 -1
  98. package/dest/sequencer/allowed.js +0 -27
  99. package/dest/slasher/factory.d.ts +0 -7
  100. package/dest/slasher/factory.d.ts.map +0 -1
  101. package/dest/slasher/factory.js +0 -8
  102. package/dest/slasher/index.d.ts +0 -3
  103. package/dest/slasher/index.d.ts.map +0 -1
  104. package/dest/slasher/index.js +0 -2
  105. package/dest/slasher/slasher_client.d.ts +0 -75
  106. package/dest/slasher/slasher_client.d.ts.map +0 -1
  107. package/dest/slasher/slasher_client.js +0 -132
  108. package/dest/tx_validator/archive_cache.d.ts +0 -14
  109. package/dest/tx_validator/archive_cache.d.ts.map +0 -1
  110. package/dest/tx_validator/archive_cache.js +0 -22
  111. package/dest/tx_validator/gas_validator.d.ts +0 -14
  112. package/dest/tx_validator/gas_validator.d.ts.map +0 -1
  113. package/dest/tx_validator/gas_validator.js +0 -78
  114. package/dest/tx_validator/nullifier_cache.d.ts +0 -16
  115. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  116. package/dest/tx_validator/nullifier_cache.js +0 -24
  117. package/dest/tx_validator/phases_validator.d.ts +0 -12
  118. package/dest/tx_validator/phases_validator.d.ts.map +0 -1
  119. package/dest/tx_validator/phases_validator.js +0 -80
  120. package/dest/tx_validator/test_utils.d.ts +0 -23
  121. package/dest/tx_validator/test_utils.d.ts.map +0 -1
  122. package/dest/tx_validator/test_utils.js +0 -26
  123. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  124. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  125. package/dest/tx_validator/tx_validator_factory.js +0 -50
  126. package/src/sequencer/allowed.ts +0 -36
  127. package/src/slasher/factory.ts +0 -15
  128. package/src/slasher/index.ts +0 -2
  129. package/src/slasher/slasher_client.ts +0 -193
  130. package/src/tx_validator/archive_cache.ts +0 -28
  131. package/src/tx_validator/gas_validator.ts +0 -101
  132. package/src/tx_validator/nullifier_cache.ts +0 -30
  133. package/src/tx_validator/phases_validator.ts +0 -98
  134. package/src/tx_validator/test_utils.ts +0 -48
  135. package/src/tx_validator/tx_validator_factory.ts +0 -120
@@ -1,78 +1,106 @@
1
- import { Attributes, Metrics, ValueType } from '@aztec/telemetry-client';
2
- import { sequencerStateToNumber } from './utils.js';
1
+ import { Attributes, Metrics, createUpDownCounterWithDefault } from '@aztec/telemetry-client';
2
+ import { formatUnits } from 'viem';
3
+ // TODO(palla/mbps): Review all metrics and add any missing ones per checkpoint
3
4
  export class SequencerMetrics {
5
+ rollup;
4
6
  tracer;
7
+ meter;
5
8
  blockCounter;
6
9
  blockBuildDuration;
7
10
  blockBuildManaPerSecond;
8
11
  stateTransitionBufferDuration;
9
- currentBlockNumber;
10
- currentBlockSize;
11
- blockBuilderInsertions;
12
+ // these are gauges because for individual sequencers building a block is not something that happens often enough to warrant a histogram
12
13
  timeToCollectAttestations;
13
- constructor(client, getState, name = 'Sequencer'){
14
- const meter = client.getMeter(name);
14
+ allowanceToCollectAttestations;
15
+ requiredAttestions;
16
+ collectedAttestions;
17
+ rewards;
18
+ slots;
19
+ filledSlots;
20
+ blockProposalFailed;
21
+ blockProposalSuccess;
22
+ blockProposalPrecheckFailed;
23
+ checkpointSuccess;
24
+ slashingAttempts;
25
+ checkpointAttestationDelay;
26
+ // Fisherman fee analysis metrics
27
+ fishermanWouldBeIncluded;
28
+ fishermanTimeBeforeBlock;
29
+ fishermanPendingBlobTxCount;
30
+ fishermanIncludedBlobTxCount;
31
+ fishermanCalculatedPriorityFee;
32
+ fishermanPriorityFeeDelta;
33
+ fishermanEstimatedCost;
34
+ fishermanEstimatedOverpayment;
35
+ fishermanMinedBlobTxPriorityFee;
36
+ fishermanMinedBlobTxTotalCost;
37
+ lastSeenSlot;
38
+ constructor(client, rollup, name = 'Sequencer'){
39
+ this.rollup = rollup;
40
+ this.meter = client.getMeter(name);
15
41
  this.tracer = client.getTracer(name);
16
- this.blockCounter = meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_COUNT);
17
- this.blockBuildDuration = meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_DURATION, {
18
- unit: 'ms',
19
- description: 'Duration to build a block',
20
- valueType: ValueType.INT
42
+ this.blockCounter = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_BLOCK_COUNT, {
43
+ [Attributes.STATUS]: [
44
+ 'failed',
45
+ 'built'
46
+ ]
21
47
  });
22
- this.blockBuildManaPerSecond = meter.createGauge(Metrics.SEQUENCER_BLOCK_BUILD_MANA_PER_SECOND, {
23
- unit: 'mana/s',
24
- description: 'Mana per second when building a block',
25
- valueType: ValueType.INT
48
+ this.blockBuildDuration = this.meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_DURATION);
49
+ this.blockBuildManaPerSecond = this.meter.createGauge(Metrics.SEQUENCER_BLOCK_BUILD_MANA_PER_SECOND);
50
+ this.stateTransitionBufferDuration = this.meter.createHistogram(Metrics.SEQUENCER_STATE_TRANSITION_BUFFER_DURATION);
51
+ this.checkpointAttestationDelay = this.meter.createHistogram(Metrics.SEQUENCER_CHECKPOINT_ATTESTATION_DELAY);
52
+ this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_REWARDS);
53
+ this.slots = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_SLOT_COUNT);
54
+ /**
55
+ * NOTE: we do not track missed slots as a separate metric. That would be difficult to determine
56
+ * Instead, use a computed metric, `slots - filledSlots` to get the number of slots a sequencer has missed.
57
+ */ this.filledSlots = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_FILLED_SLOT_COUNT);
58
+ this.timeToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_DURATION);
59
+ this.allowanceToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_TIME_ALLOWANCE);
60
+ this.requiredAttestions = this.meter.createGauge(Metrics.SEQUENCER_REQUIRED_ATTESTATIONS_COUNT);
61
+ this.collectedAttestions = this.meter.createGauge(Metrics.SEQUENCER_COLLECTED_ATTESTATIONS_COUNT);
62
+ this.blockProposalFailed = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_BLOCK_PROPOSAL_FAILED_COUNT);
63
+ this.blockProposalSuccess = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_BLOCK_PROPOSAL_SUCCESS_COUNT);
64
+ this.checkpointSuccess = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_CHECKPOINT_SUCCESS_COUNT);
65
+ this.blockProposalPrecheckFailed = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_BLOCK_PROPOSAL_PRECHECK_FAILED_COUNT, {
66
+ [Attributes.ERROR_TYPE]: [
67
+ 'slot_already_taken',
68
+ 'rollup_contract_check_failed',
69
+ 'slot_mismatch',
70
+ 'block_number_mismatch'
71
+ ]
26
72
  });
27
- this.stateTransitionBufferDuration = meter.createHistogram(Metrics.SEQUENCER_STATE_TRANSITION_BUFFER_DURATION, {
28
- unit: 'ms',
29
- description: 'The time difference between when the sequencer needed to transition to a new state and when it actually did.',
30
- valueType: ValueType.INT
73
+ this.slashingAttempts = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_SLASHING_ATTEMPTS_COUNT);
74
+ // Fisherman fee analysis metrics
75
+ this.fishermanWouldBeIncluded = createUpDownCounterWithDefault(this.meter, Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED, {
76
+ [Attributes.OK]: [
77
+ true,
78
+ false
79
+ ]
31
80
  });
32
- const currentState = meter.createObservableGauge(Metrics.SEQUENCER_CURRENT_STATE, {
33
- description: 'Current state of the sequencer'
34
- });
35
- currentState.addCallback((observer)=>{
36
- observer.observe(sequencerStateToNumber(getState()));
37
- });
38
- this.currentBlockNumber = meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_NUMBER, {
39
- description: 'Current block number',
40
- valueType: ValueType.INT
41
- });
42
- this.currentBlockSize = meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_SIZE, {
43
- description: 'Current block size',
44
- valueType: ValueType.INT
45
- });
46
- this.timeToCollectAttestations = meter.createGauge(Metrics.SEQUENCER_TIME_TO_COLLECT_ATTESTATIONS, {
47
- description: 'The time spent collecting attestations from committee members',
48
- valueType: ValueType.INT
49
- });
50
- this.blockBuilderInsertions = meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_INSERTION_TIME, {
51
- description: 'Timer for tree insertions performed by the block builder',
52
- unit: 'us',
53
- valueType: ValueType.INT
54
- });
55
- this.setCurrentBlock(0, 0);
81
+ this.fishermanTimeBeforeBlock = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK);
82
+ this.fishermanPendingBlobTxCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT);
83
+ this.fishermanIncludedBlobTxCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_INCLUDED_BLOB_TX_COUNT);
84
+ this.fishermanCalculatedPriorityFee = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_CALCULATED_PRIORITY_FEE);
85
+ this.fishermanPriorityFeeDelta = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PRIORITY_FEE_DELTA);
86
+ this.fishermanEstimatedCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_COST);
87
+ this.fishermanEstimatedOverpayment = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_OVERPAYMENT);
88
+ this.fishermanMinedBlobTxPriorityFee = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_PRIORITY_FEE);
89
+ this.fishermanMinedBlobTxTotalCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_TOTAL_COST);
56
90
  }
57
- startCollectingAttestationsTimer() {
58
- const startTime = Date.now();
59
- const stop = ()=>{
60
- const duration = Date.now() - startTime;
61
- this.recordTimeToCollectAttestations(duration);
62
- };
63
- return stop.bind(this);
91
+ recordRequiredAttestations(requiredAttestationsCount, allowanceMs) {
92
+ this.requiredAttestions.record(requiredAttestationsCount);
93
+ this.allowanceToCollectAttestations.record(Math.ceil(allowanceMs));
94
+ // reset
95
+ this.collectedAttestions.record(0);
96
+ this.timeToCollectAttestations.record(0);
64
97
  }
65
- recordTimeToCollectAttestations(time) {
66
- this.timeToCollectAttestations.record(time);
98
+ recordCheckpointAttestationDelay(duration) {
99
+ this.checkpointAttestationDelay.record(duration);
67
100
  }
68
- recordBlockBuilderTreeInsertions(timeUs) {
69
- this.blockBuilderInsertions.record(Math.ceil(timeUs));
70
- }
71
- recordCancelledBlock() {
72
- this.blockCounter.add(1, {
73
- [Attributes.STATUS]: 'cancelled'
74
- });
75
- this.setCurrentBlock(0, 0);
101
+ recordCollectedAttestations(count, durationMs) {
102
+ this.collectedAttestions.record(count);
103
+ this.timeToCollectAttestations.record(Math.ceil(durationMs));
76
104
  }
77
105
  recordBuiltBlock(buildDurationMs, totalMana) {
78
106
  this.blockCounter.add(1, {
@@ -85,18 +113,135 @@ export class SequencerMetrics {
85
113
  this.blockCounter.add(1, {
86
114
  [Attributes.STATUS]: 'failed'
87
115
  });
88
- this.setCurrentBlock(0, 0);
89
- }
90
- recordNewBlock(blockNumber, txCount) {
91
- this.setCurrentBlock(blockNumber, txCount);
92
116
  }
93
117
  recordStateTransitionBufferMs(durationMs, state) {
94
118
  this.stateTransitionBufferDuration.record(durationMs, {
95
119
  [Attributes.SEQUENCER_STATE]: state
96
120
  });
97
121
  }
98
- setCurrentBlock(blockNumber, txCount) {
99
- this.currentBlockNumber.record(blockNumber);
100
- this.currentBlockSize.record(txCount);
122
+ incOpenSlot(slot, proposer) {
123
+ // sequencer went through the loop a second time. Noop
124
+ if (slot === this.lastSeenSlot) {
125
+ return;
126
+ }
127
+ this.slots.add(1, {
128
+ [Attributes.BLOCK_PROPOSER]: proposer
129
+ });
130
+ this.lastSeenSlot = slot;
131
+ }
132
+ async incFilledSlot(proposer, coinbase) {
133
+ this.filledSlots.add(1, {
134
+ [Attributes.BLOCK_PROPOSER]: proposer
135
+ });
136
+ this.lastSeenSlot = undefined;
137
+ if (coinbase) {
138
+ try {
139
+ const rewards = await this.rollup.getSequencerRewards(coinbase);
140
+ const fmt = parseFloat(formatUnits(rewards, 18));
141
+ this.rewards.record(fmt, {
142
+ [Attributes.COINBASE]: coinbase.toString()
143
+ });
144
+ } catch {
145
+ // no-op
146
+ }
147
+ }
148
+ }
149
+ recordCheckpointSuccess() {
150
+ this.checkpointSuccess.add(1);
151
+ }
152
+ recordBlockProposalFailed(reason) {
153
+ this.blockProposalFailed.add(1, {
154
+ ...reason && {
155
+ [Attributes.ERROR_TYPE]: reason
156
+ }
157
+ });
158
+ }
159
+ recordBlockProposalSuccess() {
160
+ this.blockProposalSuccess.add(1);
161
+ }
162
+ recordBlockProposalPrecheckFailed(checkType) {
163
+ this.blockProposalPrecheckFailed.add(1, {
164
+ [Attributes.ERROR_TYPE]: checkType
165
+ });
166
+ }
167
+ recordSlashingAttempt(actionCount) {
168
+ this.slashingAttempts.add(actionCount);
169
+ }
170
+ /**
171
+ * Records metrics for a completed fisherman fee analysis
172
+ * @param analysis - The completed fee analysis result
173
+ */ recordFishermanFeeAnalysis(analysis) {
174
+ // In fisherman mode, we should always have strategy results
175
+ if (!analysis.computedPrices.strategyResults || analysis.computedPrices.strategyResults.length === 0) {
176
+ // This should never happen in fisherman mode - log an error
177
+ // We don't record metrics without strategy IDs as that defeats the purpose
178
+ throw new Error(`No strategy results found in fisherman fee analysis ${analysis.id}. This indicates a bug in the fee analysis.`);
179
+ }
180
+ // Record metrics for each strategy separately
181
+ for (const strategyResult of analysis.computedPrices.strategyResults){
182
+ const strategyAttributes = {
183
+ [Attributes.FISHERMAN_FEE_STRATEGY_ID]: strategyResult.strategyId
184
+ };
185
+ // Record pending block snapshot data (once per strategy for comparison)
186
+ this.fishermanPendingBlobTxCount.record(analysis.pendingSnapshot.pendingBlobTxCount, strategyAttributes);
187
+ // Record mined block data if available
188
+ if (analysis.minedBlock) {
189
+ this.fishermanIncludedBlobTxCount.record(analysis.minedBlock.includedBlobTxCount, strategyAttributes);
190
+ // Record actual fees from blob transactions in the mined block
191
+ for (const blobTx of analysis.minedBlock.includedBlobTxs){
192
+ // Record priority fee per gas in Gwei
193
+ const priorityFeeGwei = Number(blobTx.maxPriorityFeePerGas) / 1e9;
194
+ this.fishermanMinedBlobTxPriorityFee.record(priorityFeeGwei, strategyAttributes);
195
+ // Calculate total cost in ETH
196
+ // Cost = (gas * (baseFee + priorityFee)) + (blobCount * blobGasPerBlob * blobBaseFee)
197
+ const baseFee = analysis.minedBlock.baseFeePerGas;
198
+ const effectiveGasPrice = baseFee + blobTx.maxPriorityFeePerGas;
199
+ // Calculate execution cost using actual gas limit from the transaction
200
+ const executionCost = blobTx.gas * effectiveGasPrice;
201
+ // Calculate blob cost using maxFeePerBlobGas * blobCount * GAS_PER_BLOB
202
+ const blobCost = blobTx.maxFeePerBlobGas * BigInt(blobTx.blobCount) * 131072n; // 128KB per blob
203
+ const totalCostWei = executionCost + blobCost;
204
+ const totalCostEth = Number(totalCostWei) / 1e18;
205
+ this.fishermanMinedBlobTxTotalCost.record(totalCostEth, strategyAttributes);
206
+ }
207
+ }
208
+ // Record the calculated priority fee for this strategy
209
+ const calculatedPriorityFeeGwei = Number(strategyResult.calculatedPriorityFee) / 1e9;
210
+ this.fishermanCalculatedPriorityFee.record(calculatedPriorityFeeGwei, strategyAttributes);
211
+ // Record analysis results if available
212
+ if (analysis.analysis) {
213
+ this.fishermanTimeBeforeBlock.record(Math.ceil(analysis.analysis.timeBeforeBlockMs), strategyAttributes);
214
+ // Record strategy-specific inclusion result
215
+ if (strategyResult.wouldBeIncluded !== undefined) {
216
+ if (strategyResult.wouldBeIncluded) {
217
+ this.fishermanWouldBeIncluded.add(1, {
218
+ ...strategyAttributes,
219
+ [Attributes.OK]: true
220
+ });
221
+ } else {
222
+ this.fishermanWouldBeIncluded.add(1, {
223
+ ...strategyAttributes,
224
+ [Attributes.OK]: false,
225
+ ...strategyResult.exclusionReason && {
226
+ [Attributes.ERROR_TYPE]: strategyResult.exclusionReason
227
+ }
228
+ });
229
+ }
230
+ }
231
+ // Record strategy-specific priority fee delta
232
+ if (strategyResult.priorityFeeDelta !== undefined) {
233
+ const priorityFeeDeltaGwei = Number(strategyResult.priorityFeeDelta) / 1e9;
234
+ this.fishermanPriorityFeeDelta.record(priorityFeeDeltaGwei, strategyAttributes);
235
+ }
236
+ // Record estimated cost if available
237
+ if (strategyResult.estimatedCostEth !== undefined) {
238
+ this.fishermanEstimatedCost.record(strategyResult.estimatedCostEth, strategyAttributes);
239
+ }
240
+ // Record estimated overpayment if available
241
+ if (strategyResult.estimatedOverpaymentEth !== undefined) {
242
+ this.fishermanEstimatedOverpayment.record(strategyResult.estimatedOverpaymentEth, strategyAttributes);
243
+ }
244
+ }
245
+ }
101
246
  }
102
247
  }