@@ -28,6 +28,7 @@ import {
2828 prepareBottomLine ,
2929 prepareDailyLidoFees ,
3030 formatTimestamp ,
31+ formatBP ,
3132} from 'utils' ;
3233import {
3334 checkQuarantine ,
@@ -212,6 +213,171 @@ metricsRead
212213 } ) ;
213214 } ) ;
214215
216+ metricsRead
217+ . command ( 'statistic-by-reports-full' )
218+ . description ( 'get statistic data for N last reports with full data' )
219+ . argument ( '<count>' , 'count of reports' , stringToNumber )
220+ . option ( '-v, --vault <string>' , 'vault address' )
221+ . option ( '-g, --gateway' , 'ipfs gateway url' )
222+ . option ( '--no-utc' , 'do not use UTC time zone' )
223+ . action ( async ( count : number , { vault, gateway, utc } ) => {
224+ const { contract : dashboardContract , vault : vaultAddress } =
225+ await chooseVaultAndGetDashboard ( { vault } ) ;
226+
227+ await checkQuarantine ( vaultAddress ) ;
228+
229+ const lazyOracleContract = await getLazyOracleContract ( ) ;
230+ const [
231+ _vaultsDataTimestamp ,
232+ _vaultsDataRefSlot ,
233+ _vaultsDataTreeRoot ,
234+ vaultsDataReportCid ,
235+ ] = await callReadMethod ( {
236+ contract : lazyOracleContract ,
237+ methodName : 'latestReportData' ,
238+ payload : [ ] ,
239+ } ) ;
240+
241+ const { cacheUse, csv } = program . opts ( ) ;
242+ const history = await getVaultReportHistory (
243+ {
244+ vault : vaultAddress ,
245+ cid : vaultsDataReportCid ,
246+ limit : count ,
247+ direction : 'asc' ,
248+ gateway,
249+ } ,
250+ cacheUse ,
251+ ) ;
252+
253+ const blockNumbers = history . map ( ( r ) => r . blockNumber ) ;
254+ const noFeeSnapshots = await getNOFeeSnapshotsByBlockNumbers (
255+ vaultAddress ,
256+ blockNumbers ,
257+ dashboardContract ,
258+ history ,
259+ ) ;
260+
261+ const [
262+ grossStakingRewards ,
263+ nodeOperatorRewards ,
264+ netStakingRewards ,
265+ grossStakingAPR ,
266+ netStakingAPR ,
267+ carrySpread ,
268+ bottomLine ,
269+ dailyLidoFees ,
270+ ] = await Promise . all ( [
271+ prepareGrossStakingRewards ( history ) ,
272+ prepareNodeOperatorRewards ( history , noFeeSnapshots ) ,
273+ prepareNetStakingRewards ( history , noFeeSnapshots ) ,
274+ prepareGrossStakingAPR ( history ) ,
275+ prepareNetStakingAPR ( history , noFeeSnapshots ) ,
276+ prepareCarrySpread ( history , noFeeSnapshots , vaultAddress ) ,
277+ prepareBottomLine ( history , noFeeSnapshots , vaultAddress ) ,
278+ prepareDailyLidoFees ( history ) ,
279+ ] ) ;
280+
281+ const historyCutted = history . slice ( 1 ) ; // cut first report to align with metrics which calculated from 2 reports
282+ const noFeeSnapshotsCutted = noFeeSnapshots . slice ( 1 ) ; // cut first report to align with metrics which calculated from 2 reports
283+
284+ logResult ( {
285+ data : [
286+ [ 'Vault Address' , vaultAddress ] ,
287+ [
288+ 'Node Operator Accrued Fee, ETH' ,
289+ ...noFeeSnapshotsCutted . map ( ( r ) => formatEther ( BigInt ( r . accruedFee ) ) ) ,
290+ ] ,
291+ [
292+ 'Node Operator Fee Rate, %' ,
293+ ...noFeeSnapshotsCutted . map ( ( r ) => formatBP ( r . feeRate ) ) ,
294+ ] ,
295+ [
296+ 'Node Operator Settled Growth, ETH' ,
297+ ...noFeeSnapshotsCutted . map ( ( r ) =>
298+ formatEther ( BigInt ( r . settledGrowth ) ) ,
299+ ) ,
300+ ] ,
301+ [
302+ 'Total Value, ETH' ,
303+ ...historyCutted . map ( ( r ) =>
304+ formatEther ( BigInt ( r . data . totalValueWei ) ) ,
305+ ) ,
306+ ] ,
307+ [
308+ 'Fee, ETH' ,
309+ ...historyCutted . map ( ( r ) => formatEther ( BigInt ( r . data . fee ) ) ) ,
310+ ] ,
311+ [
312+ 'Liability Shares, ETH' ,
313+ ...historyCutted . map ( ( r ) =>
314+ formatEther ( BigInt ( r . data . liabilityShares ) ) ,
315+ ) ,
316+ ] ,
317+ [
318+ 'Slashing Reserve, ETH' ,
319+ ...historyCutted . map ( ( r ) =>
320+ formatEther ( BigInt ( r . data . slashingReserve ) ) ,
321+ ) ,
322+ ] ,
323+ [
324+ 'In/Out Delta, ETH' ,
325+ ...historyCutted . map ( ( r ) =>
326+ formatEther ( BigInt ( r . extraData . inOutDelta ) ) ,
327+ ) ,
328+ ] ,
329+ [
330+ 'Prev Fee, ETH' ,
331+ ...historyCutted . map ( ( r ) => formatEther ( BigInt ( r . extraData . prevFee ) ) ) ,
332+ ] ,
333+ [
334+ 'Infra Fee, ETH' ,
335+ ...historyCutted . map ( ( r ) =>
336+ formatEther ( BigInt ( r . extraData . infraFee ) ) ,
337+ ) ,
338+ ] ,
339+ [
340+ 'Liquidity Fee, ETH' ,
341+ ...historyCutted . map ( ( r ) =>
342+ formatEther ( BigInt ( r . extraData . liquidityFee ) ) ,
343+ ) ,
344+ ] ,
345+ [
346+ 'Reservation Fee, ETH' ,
347+ ...historyCutted . map ( ( r ) =>
348+ formatEther ( BigInt ( r . extraData . reservationFee ) ) ,
349+ ) ,
350+ ] ,
351+ [ 'Timestamp' , ...historyCutted . map ( ( r ) => r . timestamp ) ] ,
352+ [ 'CID' , ...historyCutted . map ( ( r ) => r . cid ) ] ,
353+ [
354+ 'Report date' ,
355+ ...historyCutted . map ( ( r ) =>
356+ formatTimestamp ( r . timestamp , 'dd.mm hh:mm' , utc ? 'UTC' : 'local' ) ,
357+ ) ,
358+ ] ,
359+ [ 'Gross Staking Rewards, ETH' , ...grossStakingRewards . values ] ,
360+ [ 'Node Operator Rewards, ETH' , ...nodeOperatorRewards . values ] ,
361+ [ 'Net Staking Rewards, ETH' , ...netStakingRewards . values ] ,
362+ [ 'Gross Staking APR, %' , ...grossStakingAPR . values . map ( formatRatio ) ] ,
363+ [ 'Net Staking APR, %' , ...netStakingAPR . values . map ( formatRatio ) ] ,
364+ [ 'Carry Spread, %' , ...carrySpread . values . map ( formatRatio ) ] ,
365+ [ 'Bottom Line, WEI' , ...bottomLine . values ] ,
366+ [ 'Daily Lido Fees, ETH' , ...dailyLidoFees . values ] ,
367+ [ 'Timestamp' , ...grossStakingRewards . timestamp ] ,
368+ ] ,
369+ params : {
370+ head : [
371+ 'Metric' ,
372+ ...grossStakingRewards . timestamp . map ( ( ts ) =>
373+ formatTimestamp ( ts , 'dd.mm hh:mm' , utc ? 'UTC' : 'local' ) ,
374+ ) ,
375+ ] ,
376+ } ,
377+ csvPath : csv ,
378+ } ) ;
379+ } ) ;
380+
215381metricsRead
216382 . command ( 'report-data' )
217383 . description ( 'get report data for Vault from N last reports' )
0 commit comments