Skip to content

Commit e1fc5c7

Browse files
committed
feat: add caching and calculation for node operator accrued fees
1 parent 46ee7cc commit e1fc5c7

File tree

9 files changed

+150
-170
lines changed

9 files changed

+150
-170
lines changed

features/metrics.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,36 @@ export const getSettledGrowthsByBlockNumbers = async (
4949

5050
return settledGrowths;
5151
};
52+
53+
export const getNodeOperatorAccruedFeeByBlockNumbers = async (
54+
vaultAddress: string,
55+
blockNumbers: number[],
56+
dashboardContract: DashboardContract,
57+
) => {
58+
// Get settled growth for each report block with caching
59+
const nodeOperatorAccruedFees: bigint[] = [];
60+
for (const blockNumber of blockNumbers) {
61+
let nodeOperatorAccruedFee = await cache.getNodeOperatorAccruedFee(
62+
vaultAddress,
63+
blockNumber,
64+
);
65+
if (nodeOperatorAccruedFee === null) {
66+
nodeOperatorAccruedFee = await callReadMethodSilent(
67+
dashboardContract,
68+
'accruedFee',
69+
{
70+
blockNumber: BigInt(blockNumber),
71+
},
72+
);
73+
await cache.setNodeOperatorAccruedFee(
74+
vaultAddress,
75+
blockNumber,
76+
nodeOperatorAccruedFee,
77+
);
78+
}
79+
80+
nodeOperatorAccruedFees.push(nodeOperatorAccruedFee);
81+
}
82+
83+
return nodeOperatorAccruedFees;
84+
};

programs/use-cases/metrics/read.ts

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ import {
3232
import {
3333
checkQuarantine,
3434
chooseVaultAndGetDashboard,
35-
getNodeOperatorFeeRatesByBlockNumbers,
36-
getSettledGrowthsByBlockNumbers,
35+
getNodeOperatorAccruedFeeByBlockNumbers,
3736
} from 'features';
3837

3938
import { metrics } from './main.js';
@@ -154,14 +153,12 @@ metricsRead
154153
);
155154

156155
const blockNumbers = history.map((r) => r.blockNumber);
157-
const [nodeOperatorFeeBPs, settledGrowths] = await Promise.all([
158-
getNodeOperatorFeeRatesByBlockNumbers(
156+
const nodeOperatorAccruedFees =
157+
await getNodeOperatorAccruedFeeByBlockNumbers(
159158
vault,
160159
blockNumbers,
161160
dashboardContract,
162-
),
163-
getSettledGrowthsByBlockNumbers(vault, blockNumbers, dashboardContract),
164-
]);
161+
);
165162

166163
const [
167164
grossStakingRewards,
@@ -174,22 +171,12 @@ metricsRead
174171
dailyLidoFees,
175172
] = await Promise.all([
176173
prepareGrossStakingRewards(history),
177-
prepareNodeOperatorRewards(history, nodeOperatorFeeBPs, settledGrowths),
178-
prepareNetStakingRewards(history, nodeOperatorFeeBPs, settledGrowths),
174+
prepareNodeOperatorRewards(history, nodeOperatorAccruedFees),
175+
prepareNetStakingRewards(history, nodeOperatorAccruedFees),
179176
prepareGrossStakingAPR(history),
180-
prepareNetStakingAPR(history, nodeOperatorFeeBPs, settledGrowths),
181-
prepareCarrySpread(
182-
history,
183-
nodeOperatorFeeBPs,
184-
vaultAddress,
185-
settledGrowths,
186-
),
187-
prepareBottomLine(
188-
history,
189-
nodeOperatorFeeBPs,
190-
vaultAddress,
191-
settledGrowths,
192-
),
177+
prepareNetStakingAPR(history, nodeOperatorAccruedFees),
178+
prepareCarrySpread(history, nodeOperatorAccruedFees, vaultAddress),
179+
prepareBottomLine(history, nodeOperatorAccruedFees, vaultAddress),
193180
prepareDailyLidoFees(history),
194181
]);
195182

utils/cache.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ const getSettledGrowthCacheFile = (vaultAddress: string) =>
3434
path.resolve('cache', `settled-growth-cache-${vaultAddress}.json`);
3535
const getIndexedEventsCacheFile = (poolAddress: string) =>
3636
path.resolve('cache', `indexed-events-cache-${poolAddress}.json`);
37+
const getNodeOperatorAccruedFeeCacheFile = (vaultAddress: string) =>
38+
path.resolve('cache', `node-operator-accrued-fee-cache-${vaultAddress}.json`);
3739

3840
export const cache = {
3941
async getShareRate(blockNumber: number): Promise<bigint | null> {
@@ -184,6 +186,54 @@ export const cache = {
184186
);
185187
},
186188

189+
async getNodeOperatorAccruedFee(
190+
vaultAddress: string,
191+
blockNumber: number,
192+
): Promise<bigint | null> {
193+
try {
194+
const data = JSON.parse(
195+
await fs.readFile(
196+
getNodeOperatorAccruedFeeCacheFile(vaultAddress),
197+
'utf-8',
198+
),
199+
);
200+
if (data[blockNumber] !== undefined) return BigInt(data[blockNumber]);
201+
} catch {
202+
/* ignore */
203+
}
204+
return null;
205+
},
206+
207+
async setNodeOperatorAccruedFee(
208+
vaultAddress: string,
209+
blockNumber: number,
210+
value: bigint,
211+
) {
212+
let data: Record<string, string> = {};
213+
try {
214+
data = JSON.parse(
215+
await fs.readFile(
216+
getNodeOperatorAccruedFeeCacheFile(vaultAddress),
217+
'utf-8',
218+
),
219+
);
220+
} catch {
221+
/* ignore */
222+
}
223+
data[blockNumber] = value.toString();
224+
await fs.mkdir(
225+
path.dirname(getNodeOperatorAccruedFeeCacheFile(vaultAddress)),
226+
{
227+
recursive: true,
228+
},
229+
);
230+
await fs.writeFile(
231+
getNodeOperatorAccruedFeeCacheFile(vaultAddress),
232+
JSON.stringify(data),
233+
'utf-8',
234+
);
235+
},
236+
187237
async getIndexedEventsByBlock(
188238
poolAddress: string,
189239
blockNumber: bigint,

utils/charts/blessed/charts-apr.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import { Address } from 'viem';
44

55
import { callReadMethodSilent, getVaultReportHistory } from 'utils';
66
import { getDashboardContract } from 'contracts';
7-
import {
8-
getNodeOperatorFeeRatesByBlockNumbers,
9-
getSettledGrowthsByBlockNumbers,
10-
} from 'features';
7+
import { getNodeOperatorAccruedFeeByBlockNumbers } from 'features';
118

129
import { lineOpts, getMinMax } from './utils.js';
1310
import { LIMIT } from './constants.js';
@@ -55,32 +52,23 @@ export const fetchAprChartsData = async ({
5552
if (!history || history.length < 2) throw new Error('Not enough data');
5653

5754
const blockNumbers = history.map((r) => r.blockNumber);
58-
const [nodeOperatorFeeBPs, settledGrowths] = await Promise.all([
59-
getNodeOperatorFeeRatesByBlockNumbers(
60-
vault,
61-
blockNumbers,
62-
dashboardContract,
63-
),
64-
getSettledGrowthsByBlockNumbers(vault, blockNumbers, dashboardContract),
65-
]);
55+
const nodeOperatorAccruedFees = await getNodeOperatorAccruedFeeByBlockNumbers(
56+
vault,
57+
blockNumbers,
58+
dashboardContract,
59+
);
6660

6761
const grossStakingAPR = prepareGrossStakingAPR(history);
68-
const netStakingAPR = prepareNetStakingAPR(
69-
history,
70-
nodeOperatorFeeBPs,
71-
settledGrowths,
72-
);
62+
const netStakingAPR = prepareNetStakingAPR(history, nodeOperatorAccruedFees);
7363
const carrySpread = await prepareCarrySpread(
7464
history,
75-
nodeOperatorFeeBPs,
65+
nodeOperatorAccruedFees,
7666
vault,
77-
settledGrowths,
7867
);
7968
const bottomLine = await prepareBottomLine(
8069
history,
81-
nodeOperatorFeeBPs,
70+
nodeOperatorAccruedFees,
8271
vault,
83-
settledGrowths,
8472
);
8573
const lidoAPR = await prepareLidoAPR(history);
8674

utils/charts/blessed/charts-rewards.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import contrib from 'blessed-contrib';
44
import { Address } from 'viem';
55
import { callReadMethodSilent, getVaultReportHistory } from 'utils';
66
import { getDashboardContract } from 'contracts';
7-
import {
8-
getNodeOperatorFeeRatesByBlockNumbers,
9-
getSettledGrowthsByBlockNumbers,
10-
} from 'features';
7+
import { getNodeOperatorAccruedFeeByBlockNumbers } from 'features';
118

129
import { lineOpts } from './utils.js';
1310
import { LIMIT } from './constants.js';
@@ -48,25 +45,20 @@ export const fetchRewardsChartsData = async ({
4845

4946
// Get nodeOperatorFeeBP for each report block with caching
5047
const blockNumbers = history.map((r) => r.blockNumber);
51-
const [nodeOperatorFeeBPs, settledGrowths] = await Promise.all([
52-
getNodeOperatorFeeRatesByBlockNumbers(
53-
vault,
54-
blockNumbers,
55-
dashboardContract,
56-
),
57-
getSettledGrowthsByBlockNumbers(vault, blockNumbers, dashboardContract),
58-
]);
48+
const nodeOperatorAccruedFees = await getNodeOperatorAccruedFeeByBlockNumbers(
49+
vault,
50+
blockNumbers,
51+
dashboardContract,
52+
);
5953

6054
const grossStakingRewards = prepareGrossStakingRewards(history);
6155
const nodeOperatorRewards = prepareNodeOperatorRewards(
6256
history,
63-
nodeOperatorFeeBPs,
64-
settledGrowths,
57+
nodeOperatorAccruedFees,
6558
);
6659
const netStakingRewards = prepareNetStakingRewards(
6760
history,
68-
nodeOperatorFeeBPs,
69-
settledGrowths,
61+
nodeOperatorAccruedFees,
7062
);
7163

7264
const grossStakingRewardsChart =

utils/charts/blessed/datasets/prepare-metrics.ts

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
getCarrySpread,
99
calculateLidoAPR,
1010
getGrossStakingRewards,
11-
getNodeOperatorRewards,
1211
getNetStakingRewards,
1312
getDailyLidoFees,
1413
} from 'utils';
@@ -17,9 +16,8 @@ import { getRebaseRewardFromCache, getShareRateFromCache } from 'utils';
1716

1817
export const prepareBottomLine = async (
1918
history: VaultReport[],
20-
nodeOperatorFeeBPs: bigint[],
19+
nodeOperatorAccruedFees: bigint[],
2120
vaultAddress: string,
22-
settledGrowth: bigint[],
2321
) => {
2422
const bottomLine = [];
2523
const timestamp = [];
@@ -40,9 +38,8 @@ export const prepareBottomLine = async (
4038
const bottomLineValue = getBottomLine(
4139
current,
4240
previous,
43-
nodeOperatorFeeBPs[i] ?? 0n,
41+
nodeOperatorAccruedFees[i] ?? 0n,
4442
stEthLiabilityRebaseRewards,
45-
settledGrowth[i] ?? 0n,
4643
);
4744

4845
bottomLine.push(String(bottomLineValue));
@@ -70,8 +67,7 @@ export const prepareGrossStakingAPR = (history: VaultReport[]) => {
7067

7168
export const prepareNetStakingAPR = (
7269
history: VaultReport[],
73-
nodeOperatorFeeBPs: bigint[],
74-
settledGrowth: bigint[],
70+
nodeOperatorAccruedFees: bigint[],
7571
) => {
7672
const netStakingAPRPercent = [];
7773
const timestamp = [];
@@ -85,8 +81,7 @@ export const prepareNetStakingAPR = (
8581
const value = getNetStakingAPR(
8682
current,
8783
previous,
88-
nodeOperatorFeeBPs[i] ?? 0n,
89-
settledGrowth[i] ?? 0n,
84+
nodeOperatorAccruedFees[i] ?? 0n,
9085
);
9186

9287
netStakingAPRPercent.push(value.apr_percent);
@@ -97,9 +92,8 @@ export const prepareNetStakingAPR = (
9792

9893
export const prepareCarrySpread = async (
9994
history: VaultReport[],
100-
nodeOperatorFeeBPs: bigint[],
95+
nodeOperatorAccruedFees: bigint[],
10196
vaultAddress: string,
102-
settledGrowth: bigint[],
10397
) => {
10498
const carrySpreadPercent = [];
10599
const timestamp = [];
@@ -120,9 +114,8 @@ export const prepareCarrySpread = async (
120114
const value = getCarrySpread(
121115
current,
122116
previous,
123-
nodeOperatorFeeBPs[i] ?? 0n,
117+
nodeOperatorAccruedFees[i] ?? 0n,
124118
stEthLiabilityRebaseRewards,
125-
settledGrowth[i] ?? 0n,
126119
);
127120

128121
carrySpreadPercent.push(value.apr_percent);
@@ -175,8 +168,7 @@ export const prepareGrossStakingRewards = (history: VaultReport[]) => {
175168

176169
export const prepareNodeOperatorRewards = (
177170
history: VaultReport[],
178-
nodeOperatorFeeBPs: bigint[],
179-
settledGrowth: bigint[],
171+
nodeOperatorAccruedFees: bigint[],
180172
) => {
181173
const nodeOperatorRewards = [];
182174
const timestamp = [];
@@ -186,12 +178,7 @@ export const prepareNodeOperatorRewards = (
186178
const previous = history[i - 1];
187179
if (!current || !previous) continue;
188180

189-
const value = getNodeOperatorRewards(
190-
current,
191-
previous,
192-
nodeOperatorFeeBPs[i] ?? 0n,
193-
settledGrowth[i] ?? 0n,
194-
);
181+
const value = nodeOperatorAccruedFees[i] ?? 0n;
195182

196183
nodeOperatorRewards.push(String(formatEther(value)));
197184
timestamp.push(current.timestamp);
@@ -201,8 +188,7 @@ export const prepareNodeOperatorRewards = (
201188

202189
export const prepareNetStakingRewards = (
203190
history: VaultReport[],
204-
nodeOperatorFeeBPs: bigint[],
205-
settledGrowth: bigint[],
191+
nodeOperatorAccruedFees: bigint[],
206192
) => {
207193
const netStakingRewards = [];
208194
const timestamp = [];
@@ -215,8 +201,7 @@ export const prepareNetStakingRewards = (
215201
const value = getNetStakingRewards(
216202
current,
217203
previous,
218-
nodeOperatorFeeBPs[i] ?? 0n,
219-
settledGrowth[i] ?? 0n,
204+
nodeOperatorAccruedFees[i] ?? 0n,
220205
);
221206

222207
netStakingRewards.push(String(formatEther(value)));

0 commit comments

Comments
 (0)