@marinade.finance/scoring 1.0.1 → 1.0.3

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 (101) hide show
  1. package/dist/computing/cluster.d.ts +10 -0
  2. package/dist/computing/cluster.js +95 -0
  3. package/dist/computing/cluster.js.map +1 -0
  4. package/dist/computing/eligibility.d.ts +19 -0
  5. package/dist/computing/eligibility.js +166 -0
  6. package/dist/computing/eligibility.js.map +1 -0
  7. package/dist/computing/score.d.ts +20 -0
  8. package/dist/computing/score.js +174 -0
  9. package/dist/computing/score.js.map +1 -0
  10. package/dist/computing/stake.d.ts +26 -0
  11. package/dist/computing/stake.js +197 -0
  12. package/dist/computing/stake.js.map +1 -0
  13. package/dist/computing/validators.d.ts +16 -0
  14. package/dist/computing/validators.js +123 -0
  15. package/dist/computing/validators.js.map +1 -0
  16. package/dist/constants/marinade.json +38 -0
  17. package/dist/dto/bonds.dto.d.ts +16 -0
  18. package/dist/dto/bonds.dto.js +3 -0
  19. package/dist/dto/bonds.dto.js.map +1 -0
  20. package/dist/dto/cluster.dto.d.ts +12 -0
  21. package/dist/dto/cluster.dto.js +3 -0
  22. package/dist/dto/cluster.dto.js.map +1 -0
  23. package/{dto/eligibility.dto.ts → dist/dto/eligibility.dto.d.ts} +15 -15
  24. package/dist/dto/eligibility.dto.js +3 -0
  25. package/dist/dto/eligibility.dto.js.map +1 -0
  26. package/dist/dto/jito.dto.d.ts +9 -0
  27. package/dist/dto/jito.dto.js +10 -0
  28. package/dist/dto/jito.dto.js.map +1 -0
  29. package/dist/dto/marinade.dto.d.ts +18 -0
  30. package/dist/dto/marinade.dto.js +3 -0
  31. package/dist/dto/marinade.dto.js.map +1 -0
  32. package/dist/dto/rewards.dto.d.ts +17 -0
  33. package/dist/dto/rewards.dto.js +18 -0
  34. package/dist/dto/rewards.dto.js.map +1 -0
  35. package/dist/dto/scoring.dto.d.ts +101 -0
  36. package/dist/dto/scoring.dto.js +3 -0
  37. package/dist/dto/scoring.dto.js.map +1 -0
  38. package/dist/dto/snapshots.dto.d.ts +15 -0
  39. package/dist/dto/snapshots.dto.js +13 -0
  40. package/dist/dto/snapshots.dto.js.map +1 -0
  41. package/dist/dto/stakes.dto.d.ts +30 -0
  42. package/dist/dto/stakes.dto.js +3 -0
  43. package/dist/dto/stakes.dto.js.map +1 -0
  44. package/dist/dto/validators.dto.d.ts +110 -0
  45. package/dist/dto/validators.dto.js +19 -0
  46. package/dist/dto/validators.dto.js.map +1 -0
  47. package/dist/errors/fetching.d.ts +22 -0
  48. package/dist/errors/fetching.js +30 -0
  49. package/dist/errors/fetching.js.map +1 -0
  50. package/dist/index.d.ts +24 -0
  51. package/dist/index.js +41 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/interfaces/data-provider.interface.d.ts +16 -0
  54. package/dist/interfaces/data-provider.interface.js +3 -0
  55. package/dist/interfaces/data-provider.interface.js.map +1 -0
  56. package/dist/logging/logger.d.ts +3 -0
  57. package/dist/logging/logger.js +72 -0
  58. package/dist/logging/logger.js.map +1 -0
  59. package/dist/providers/api-data.provider.d.ts +30 -0
  60. package/dist/providers/api-data.provider.js +227 -0
  61. package/dist/providers/api-data.provider.js.map +1 -0
  62. package/dist/providers/file-data.provider.d.ts +29 -0
  63. package/dist/providers/file-data.provider.js +96 -0
  64. package/dist/providers/file-data.provider.js.map +1 -0
  65. package/dist/tsconfig.tsbuildinfo +1 -0
  66. package/dist/utils/csv.d.ts +2 -0
  67. package/dist/utils/csv.js +52 -0
  68. package/dist/utils/csv.js.map +1 -0
  69. package/dist/utils/maths.d.ts +8 -0
  70. package/dist/utils/maths.js +56 -0
  71. package/dist/utils/maths.js.map +1 -0
  72. package/dist/utils/solana.d.ts +1 -0
  73. package/dist/utils/solana.js +9 -0
  74. package/dist/utils/solana.js.map +1 -0
  75. package/dist/utils/zip.d.ts +2 -0
  76. package/dist/utils/zip.js +15 -0
  77. package/dist/utils/zip.js.map +1 -0
  78. package/package.json +7 -13
  79. package/computing/cluster.ts +0 -102
  80. package/computing/eligibility.ts +0 -163
  81. package/computing/score.ts +0 -164
  82. package/computing/stake.ts +0 -246
  83. package/computing/validators.ts +0 -133
  84. package/constants/marinade.json +0 -38
  85. package/dto/bonds.dto.ts +0 -12
  86. package/dto/cluster.dto.ts +0 -12
  87. package/dto/jito.dto.ts +0 -9
  88. package/dto/marinade.dto.ts +0 -18
  89. package/dto/rewards.dto.ts +0 -19
  90. package/dto/scoring.dto.ts +0 -103
  91. package/dto/snapshots.dto.ts +0 -16
  92. package/dto/stakes.dto.ts +0 -31
  93. package/dto/validators.dto.ts +0 -110
  94. package/errors/fetching.ts +0 -25
  95. package/interfaces/data-provider.interface.ts +0 -17
  96. package/providers/api-data.provider.ts +0 -261
  97. package/providers/file-data.provider.ts +0 -117
  98. package/utils/csv.ts +0 -30
  99. package/utils/maths.ts +0 -75
  100. package/utils/solana.ts +0 -9
  101. package/utils/zip.ts +0 -12
@@ -1,110 +0,0 @@
1
- export class WarningDto {
2
- warning: string;
3
- }
4
- export class EpochStatDto {
5
- epoch: number;
6
- epoch_start_at: string;
7
- epoch_end_at?: string;
8
- commission_max_observed?: number | null;
9
- commission_min_observed?: number | null;
10
- commission_advertised: number;
11
- commission_effective?: number | null;
12
- version: string;
13
- activated_stake: string;
14
- marinade_stake: string;
15
- foundation_stake: string;
16
- marinade_native_stake: string;
17
- self_stake: string;
18
- superminority: boolean;
19
- stake_to_become_superminority: string;
20
- credits: number;
21
- leader_slots: number;
22
- blocks_produced: number;
23
- skip_rate: number;
24
- uptime_pct?: number | null;
25
- uptime?: number | null;
26
- downtime?: number | null;
27
- apr?: number | null;
28
- apy?: number | null;
29
- score: number;
30
- rank_score: number;
31
- rank_activated_stake: number;
32
- rank_apy: number;
33
- }
34
- export class ValidatorDto {
35
- identity: string;
36
- vote_account: string;
37
- start_epoch: number;
38
- start_date: string;
39
- info_name: string;
40
- info_url: string;
41
- info_keybase: string;
42
- node_ip: string;
43
- dc_coordinates_lat: number;
44
- dc_coordinates_lon: number;
45
- dc_continent: string;
46
- dc_country_iso: string;
47
- dc_country: string;
48
- dc_city: string;
49
- dc_full_city: string;
50
- dc_asn: number;
51
- dc_aso: string;
52
- dcc_full_city: number;
53
- dcc_asn: number;
54
- dcc_aso: number;
55
- commission_max_observed?: number | null;
56
- commission_min_observed?: number | null;
57
- commission_advertised: number;
58
- commission_effective?: number | null;
59
- commission_aggregated?: number | null;
60
- rugged_commission_occurrences: number;
61
- rugged_commission: boolean;
62
- rugged_commission_info: string[];
63
- version: string;
64
- activated_stake: string;
65
- marinade_stake: string;
66
- foundation_stake: string;
67
- marinade_native_stake: string;
68
- self_stake: string;
69
- superminority: boolean;
70
- credits: number;
71
- score: number;
72
- warnings: WarningDto[];
73
- epoch_stats: EpochStatDto[];
74
- epochStats: Record<number, EpochStatDto>;
75
- epochs_count: number;
76
- has_last_epoch_stats: boolean;
77
- avg_uptime_pct: number;
78
- avg_apy: number;
79
- }
80
- export class ValidatorAggregatedDto {
81
- epoch: number;
82
- epoch_start_date: string;
83
- avg_marinade_score?: number | null;
84
- avg_apy?: number | null;
85
- }
86
- export class ValidatorsResponseDto {
87
- validators: ValidatorDto[];
88
- validators_aggregated: ValidatorAggregatedDto[];
89
- }
90
- export type AggregatedValidator = {
91
- voteAccount: string;
92
- name: string;
93
- epochs: number[];
94
- currentStake: number;
95
- currentMarinadeStake: number;
96
- commission: number[];
97
- stake: number[];
98
- externalStake: number[];
99
- credits: number[];
100
- blocksProduced: number[];
101
- leaderSlots: number[];
102
- dataAvailable: boolean[];
103
- mevCommission: number;
104
- country: string;
105
- city: string;
106
- aso: string;
107
- blacklisted: boolean;
108
- version: string;
109
- };
110
- export type AggregatedValidators = Record<string, AggregatedValidator>
@@ -1,25 +0,0 @@
1
- export class FetchError extends Error {
2
- constructor (message: string, public statusCode: number) {
3
- super(message);
4
- this.name = 'FetchError';
5
- }
6
- }
7
-
8
- export const FETCHING_ERROR_MESSAGES = {
9
- generalValidatorsFetchFailed: 'An error occured while fetching validators data',
10
- generalTvlFetchFailed: 'An error occured while fetching validators data',
11
- generalBondsFetchFailed: 'An error occured while fetching bonds data',
12
- generalRewardsFetchFailed: 'An error occured while fetching rewards',
13
- generalVemndeFetchFailed: 'An error occured while fetching veMNDE votes',
14
- generalMsolFetchFailed: 'An error occured while fetching mSOL votes',
15
- generalJitoMEVFetchFailed: 'An error occured while fetching Jito MEV',
16
- generalBlacklistFetchFailed: 'An error occured while fetching blacklist',
17
- validatorsFetchFailed: 'Failed to fetch validators data',
18
- tvlFetchFailed: 'Failed to fetch tvl data',
19
- bondsFetchFailed: 'Failed to fetch bonds data',
20
- vemndeFetchFailed: 'Failed to fetch veMNDE votes',
21
- msolFetchFailed: 'Failed to fetch mSOL votes',
22
- rewardsFetchFailed: 'Failed to fetch rewards',
23
- jitoMevFetchFailed: 'Failed to fetch Jito MEV',
24
- blacklistFetchFailed: 'Failed to fetch blacklist'
25
- };
@@ -1,17 +0,0 @@
1
- import { ValidatorDto } from '../dto/validators.dto';
2
- import { Rewards } from '../dto/rewards.dto';
3
- import { Votes } from '../dto/snapshots.dto';
4
- import { JitoValidatorDto } from '../dto/jito.dto';
5
- import { Bonds } from '../dto/bonds.dto';
6
- import { TvlStats } from '../dto/marinade.dto';
7
-
8
- export interface IDataProvider {
9
- fetchValidators(epochsToFetch: number, withSnapshot: boolean): Promise<ValidatorDto[]>;
10
- fetchBlacklist(withSnapshot: boolean): Promise<Set<string>>;
11
- fetchVeMndeVotes(withSnapshot: boolean): Promise<Votes>;
12
- fetchMSolVotes(withSnapshot: boolean): Promise<Votes>;
13
- fetchRewards(epochs: number, withSnapshot: boolean): Promise<Rewards>;
14
- fetchValidatorsJitoMEV(withSnapshot: boolean): Promise<Record<string, JitoValidatorDto>>;
15
- fetchBonds(withSnapshot: boolean): Promise<Bonds>;
16
- fetchTvl(withSnapshot: boolean): Promise<TvlStats>;
17
- }
@@ -1,261 +0,0 @@
1
- import { Rewards, RewardsResponseDto } from '../dto/rewards.dto';
2
- import { Votes, mSolSnapshotDto, veMNDESnapshotDto } from '../dto/snapshots.dto';
3
- import { EpochStatDto, ValidatorDto, ValidatorsResponseDto } from '../dto/validators.dto';
4
- import { IDataProvider } from '../interfaces/data-provider.interface';
5
- import { sum } from '../utils/maths';
6
- import { FETCHING_ERROR_MESSAGES } from '../errors/fetching';
7
- import { JitoValidatorDto, JitoValidatorsResponseDto } from '../dto/jito.dto';
8
- import { writeFile } from 'fs/promises';
9
- import { Bonds, BondsDto } from '../dto/bonds.dto';
10
- import { TvlStats } from '../dto/marinade.dto';
11
- import axios, { AxiosError } from 'axios';
12
- import { error } from '../logger';
13
-
14
- export class URLs {
15
- validatorsURL: string;
16
- blacklistURL: string;
17
- vemndeVotesURL: string;
18
- msolVotesURL: string;
19
- rewardsURL: string;
20
- jitoMevURL: string;
21
- bondsURL: string;
22
- marinadeTvlURL: string;
23
- }
24
-
25
- export class ApiDataProvider implements IDataProvider {
26
- constructor (private urls: URLs, private snapshotsBasePath?: string) { }
27
-
28
- async fetchValidators (epochsToFetch: number, withSnapshot = false): Promise<ValidatorDto[]> {
29
- try {
30
- const response = await axios.get(`${this.urls.validatorsURL}?limit=9999&epochs=${epochsToFetch + 1}`);
31
-
32
- const rawData = response.data as ValidatorsResponseDto;
33
-
34
- rawData.validators.forEach(validator => {
35
- validator.epochStats = validator.epoch_stats.reduce((acc, epochStat) => {
36
- acc[epochStat.epoch] = epochStat;
37
- return acc;
38
- }, {} as Record<number, EpochStatDto>);
39
- });
40
-
41
- if (withSnapshot) {
42
- await writeFile('./snapshot/validators.json', JSON.stringify(rawData, null, 2));
43
- }
44
-
45
- return rawData.validators;
46
- } catch (err) {
47
- if (axios.isAxiosError(error)) {
48
- const axiosError = error as AxiosError;
49
- if (axiosError.response) {
50
- error(FETCHING_ERROR_MESSAGES.validatorsFetchFailed, axiosError.response.status);
51
- } else if (axiosError.request) {
52
- error(FETCHING_ERROR_MESSAGES.generalValidatorsFetchFailed, axiosError.request);
53
- }
54
- }
55
- throw err;
56
- }
57
- }
58
-
59
- async fetchTvl (withSnapshot: boolean): Promise<TvlStats> {
60
- try {
61
- const response = await axios.get(this.urls.marinadeTvlURL);
62
-
63
- const data: TvlStats = response.data;
64
-
65
- if (withSnapshot) {
66
- await writeFile(`${this.snapshotsBasePath}/tvl.json`, JSON.stringify(data, null, 2));
67
- }
68
-
69
- return data;
70
- } catch (err) {
71
- if (axios.isAxiosError(error)) {
72
- const axiosError = error as AxiosError;
73
- if (axiosError.response) {
74
- error(FETCHING_ERROR_MESSAGES.tvlFetchFailed, axiosError.response.status);
75
- } else if (axiosError.request) {
76
- error(FETCHING_ERROR_MESSAGES.generalTvlFetchFailed, axiosError.request);
77
- }
78
- }
79
- throw err;
80
- }
81
- }
82
-
83
- async fetchBonds (withSnapshot: boolean): Promise<Bonds> {
84
- try {
85
- const response = await axios.get<BondsDto>(this.urls.bondsURL);
86
- const data: BondsDto = response.data;
87
-
88
- const bonds: Bonds = data.bonds.reduce<Bonds>((acc, bond) => {
89
- acc[bond.vote_account] = bond.cpmpe;
90
- return acc;
91
- }, {} as Bonds);
92
-
93
- if (withSnapshot) {
94
- await writeFile(`${this.snapshotsBasePath}/bonds.json`, JSON.stringify(data, null, 2));
95
- }
96
-
97
- return bonds;
98
- } catch (err) {
99
- if (axios.isAxiosError(err)) {
100
- const axiosError = err as AxiosError;
101
- if (axiosError.response) {
102
- error(FETCHING_ERROR_MESSAGES.bondsFetchFailed, axiosError.response.status);
103
- } else if (axiosError.request) {
104
- error(FETCHING_ERROR_MESSAGES.generalBondsFetchFailed, axiosError.request);
105
- }
106
- }
107
-
108
- throw err;
109
- }
110
- }
111
-
112
- async fetchBlacklist (withSnapshot = false): Promise<Set<string>> {
113
- try {
114
- const response = await axios.get<string>(this.urls.blacklistURL, {
115
- responseType: 'text'
116
- });
117
-
118
- const csv: string = response.data;
119
-
120
- if (withSnapshot) {
121
- await writeFile(`${this.snapshotsBasePath}/blacklist.csv`, csv);
122
- }
123
-
124
- const blacklistSet = new Set(
125
- csv
126
- .split('\n')
127
- .map((line) => line.trim().split(',')[0])
128
- .filter((value): value is string => !!value)
129
- );
130
-
131
- return blacklistSet;
132
- } catch (err) {
133
- if (axios.isAxiosError(err)) {
134
- if (err.response) {
135
- error(FETCHING_ERROR_MESSAGES.blacklistFetchFailed, err.response.status);
136
- } else if (err.request) {
137
- error(FETCHING_ERROR_MESSAGES.generalBlacklistFetchFailed, err.request);
138
- }
139
- }
140
-
141
- throw err;
142
- }
143
- }
144
-
145
- async fetchVeMndeVotes (withSnapshot = false): Promise<Votes> {
146
- try {
147
- const response = await axios.get<veMNDESnapshotDto>(this.urls.vemndeVotesURL);
148
- const data: veMNDESnapshotDto = response.data;
149
-
150
- if (withSnapshot) {
151
- await writeFile(`${this.snapshotsBasePath}/vemnde-votes.json`, JSON.stringify(data, null, 2));
152
- }
153
-
154
- const result: Votes = {};
155
- for (const { amount, validatorVoteAccount } of data.records) {
156
- const parsedAmount = Number(amount);
157
- if (!isNaN(parsedAmount) && parsedAmount > 0) {
158
- result[validatorVoteAccount] = (result[validatorVoteAccount] ?? 0) + parsedAmount;
159
- }
160
- }
161
-
162
- return result;
163
- } catch (err) {
164
- if (axios.isAxiosError(err)) {
165
- if (err.response) {
166
- error(FETCHING_ERROR_MESSAGES.vemndeFetchFailed, err.response.status);
167
- } else if (err.request) {
168
- error(FETCHING_ERROR_MESSAGES.generalVemndeFetchFailed, err.request);
169
- }
170
- }
171
-
172
- throw err;
173
- }
174
- }
175
-
176
- async fetchMSolVotes (withSnapshot = false): Promise<Votes> {
177
- try {
178
- const response = await axios.get<mSolSnapshotDto>(this.urls.msolVotesURL);
179
- const data: mSolSnapshotDto = response.data;
180
-
181
- if (withSnapshot) {
182
- await writeFile(`${this.snapshotsBasePath}/msol-votes.json`, JSON.stringify(data, null, 2));
183
- }
184
-
185
- const result: Votes = {};
186
- for (const { amount, validatorVoteAccount } of data.records) {
187
- const parsedAmount = Number(amount);
188
- if (!isNaN(parsedAmount) && parsedAmount > 0) {
189
- result[validatorVoteAccount] = (result[validatorVoteAccount] ?? 0) + parsedAmount;
190
- }
191
- }
192
-
193
- return result;
194
- } catch (err) {
195
- if (axios.isAxiosError(err)) {
196
- if (err.response) {
197
- error(FETCHING_ERROR_MESSAGES.msolFetchFailed, err.response.status);
198
- } else if (err.request) {
199
- error(FETCHING_ERROR_MESSAGES.generalMsolFetchFailed, err.request);
200
- }
201
- }
202
-
203
- throw err;
204
- }
205
- }
206
-
207
- async fetchRewards (epochs: number, withSnapshot = false): Promise<Rewards> {
208
- try {
209
- const response = await axios.get<{ rewards_mev: [number, number][], rewards_inflation_est: [number, number][] }>(
210
- `${this.urls.rewardsURL}?epochs=${epochs}`
211
- );
212
-
213
- const jsonResponse = response.data;
214
- const data = new RewardsResponseDto(jsonResponse);
215
-
216
- if (withSnapshot) {
217
- await writeFile(`${this.snapshotsBasePath}/rewards.json`, JSON.stringify(jsonResponse, null, 2));
218
- }
219
-
220
- const mev = sum(data.rewards_mev.map(dto => dto.amount));
221
- const inflation = sum(data.rewards_inflation_est.map(dto => dto.amount));
222
-
223
- return { inflation, mev };
224
- } catch (err) {
225
- if (axios.isAxiosError(err)) {
226
- if (err.response) {
227
- error(FETCHING_ERROR_MESSAGES.rewardsFetchFailed, err.response.status);
228
- } else if (err.request) {
229
- error(FETCHING_ERROR_MESSAGES.generalRewardsFetchFailed, err.request);
230
- }
231
- }
232
-
233
- throw err;
234
- }
235
- }
236
-
237
- async fetchValidatorsJitoMEV (withSnapshot = false): Promise<Record<string, JitoValidatorDto>> {
238
- try {
239
- const response = await axios.get<JitoValidatorsResponseDto>(this.urls.jitoMevURL);
240
- const jitoMevRecords: JitoValidatorsResponseDto = response.data;
241
-
242
- if (withSnapshot) {
243
- await writeFile(`${this.snapshotsBasePath}/jito-mev-records.json`, JSON.stringify(jitoMevRecords, null, 2));
244
- }
245
-
246
- return Object.fromEntries(
247
- jitoMevRecords.validators.map((validator) => [validator.vote_account, validator])
248
- );
249
- } catch (err) {
250
- if (axios.isAxiosError(err)) {
251
- if (err.response) {
252
- error(FETCHING_ERROR_MESSAGES.jitoMevFetchFailed, err.response.status);
253
- } else if (err.request) {
254
- error(FETCHING_ERROR_MESSAGES.generalJitoMEVFetchFailed, err.request);
255
- }
256
- }
257
-
258
- throw err;
259
- }
260
- }
261
- }
@@ -1,117 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { TvlStats } from '../dto/marinade.dto';
3
- import { Bonds, BondsDto } from '../dto/bonds.dto';
4
- import { JitoValidatorDto, JitoValidatorsResponseDto } from '../dto/jito.dto';
5
- import { Rewards, RewardsResponseDto } from '../dto/rewards.dto';
6
- import { EpochStatDto, ValidatorDto, ValidatorsResponseDto } from '../dto/validators.dto';
7
- import { IDataProvider } from '../interfaces/data-provider.interface';
8
- import { readFile } from 'fs/promises';
9
- import { FETCHING_ERROR_MESSAGES } from '../errors/fetching';
10
- import { sum } from '../utils/maths';
11
- import { Votes, mSolSnapshotDto } from '../dto/snapshots.dto';
12
- import { error } from 'logger';
13
-
14
- class Paths {
15
- validatorsPath: string;
16
- blacklistPath: string;
17
- vemndeVotesPath: string;
18
- msolVotesPath: string;
19
- rewardsPath: string;
20
- jitoMevPath: string;
21
- bondsPath: string;
22
- marinadeTvlPath: string;
23
- }
24
-
25
- export class FileDataProvider implements IDataProvider {
26
- constructor (private paths: Paths) { }
27
-
28
- async fetchValidators (epochsToFetch: number): Promise<ValidatorDto[]> {
29
- try {
30
- const validatorsFile = await readFile(this.paths.validatorsPath, 'utf8');
31
- const validatorsData: ValidatorsResponseDto = JSON.parse(validatorsFile);
32
-
33
- validatorsData.validators.forEach(validator => {
34
- validator.epochStats = validator.epoch_stats.reduce((acc, epochStat) => {
35
- acc[epochStat.epoch] = epochStat;
36
- return acc;
37
- }, {} as Record<number, EpochStatDto>);
38
- });
39
-
40
- return validatorsData.validators;
41
- } catch (err) {
42
- error(FETCHING_ERROR_MESSAGES.generalValidatorsFetchFailed, err);
43
- throw err;
44
- }
45
- }
46
- async fetchTvl (withSnapshot: boolean): Promise<TvlStats> {
47
- const tvlFile = await readFile(this.paths.marinadeTvlPath, 'utf8');
48
- const tvlData: TvlStats = JSON.parse(tvlFile);
49
- return tvlData;
50
- }
51
- async fetchBlacklist (): Promise<Set<string>> {
52
- const blacklistFile = await readFile(this.paths.blacklistPath, 'utf8');
53
- const blacklistSet = new Set(blacklistFile.split('\n').map((line) => line.split(',')[0]).filter((value): value is string => !!value));
54
- return blacklistSet;
55
- }
56
- async fetchBonds (): Promise<Bonds> {
57
- const bondsFile = await readFile(this.paths.bondsPath, 'utf8');
58
- const bondsData: BondsDto = JSON.parse(bondsFile);
59
-
60
- const bonds: Bonds = bondsData.bonds.reduce<Bonds>((acc, bond) => {
61
- acc[bond.vote_account] = bond.cpmpe;
62
- return acc;
63
- }, {} as Bonds);
64
-
65
- return bonds;
66
- }
67
- async fetchVeMndeVotes (): Promise<Record<string, number>> {
68
- const vemndeVotesFile = await readFile(this.paths.vemndeVotesPath, 'utf8');
69
- const vemndeVotesData = JSON.parse(vemndeVotesFile) as mSolSnapshotDto;
70
- const result: Votes = {};
71
- for (const { amount, validatorVoteAccount } of vemndeVotesData.records) {
72
- const parsedAmount = Number(amount);
73
- if (!isNaN(parsedAmount) && parsedAmount > 0) {
74
- result[validatorVoteAccount] = (result[validatorVoteAccount] ?? 0) + parsedAmount;
75
- }
76
- }
77
-
78
- return result;
79
- }
80
- async fetchMSolVotes (): Promise<Record<string, number>> {
81
- const msolVotesFile = await readFile(this.paths.msolVotesPath, 'utf8');
82
- const msolVotesData = JSON.parse(msolVotesFile) as mSolSnapshotDto;
83
- const result: Votes = {};
84
- for (const { amount, validatorVoteAccount } of msolVotesData.records) {
85
- const parsedAmount = Number(amount);
86
- if (!isNaN(parsedAmount) && parsedAmount > 0) {
87
- result[validatorVoteAccount] = (result[validatorVoteAccount] ?? 0) + parsedAmount;
88
- }
89
- }
90
-
91
- return result;
92
- }
93
- async fetchRewards (epochs: number): Promise<Rewards> {
94
- const rewardsFile = await readFile(this.paths.rewardsPath, 'utf8');
95
- const rewardsData = JSON.parse(rewardsFile) as { rewards_mev: [number, number][], rewards_inflation_est: [number, number][] };
96
-
97
- const data = new RewardsResponseDto(rewardsData);
98
-
99
- const mev = sum(data.rewards_mev.map(dto => dto.amount));
100
- const inflation = sum(data.rewards_inflation_est.map(dto => dto.amount));
101
-
102
- return { inflation, mev };
103
- }
104
- async fetchValidatorsJitoMEV (): Promise<Record<string, JitoValidatorDto>> {
105
- try {
106
- const jitoMevFile = await readFile(this.paths.jitoMevPath, 'utf8');
107
- const jitoMevData: JitoValidatorsResponseDto = JSON.parse(jitoMevFile);
108
-
109
- return Object.fromEntries(
110
- jitoMevData.validators.map((validator) => [validator.vote_account, validator])
111
- );
112
- } catch (err) {
113
- error(FETCHING_ERROR_MESSAGES.generalJitoMEVFetchFailed, err);
114
- throw err;
115
- }
116
- }
117
- }
package/utils/csv.ts DELETED
@@ -1,30 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
- import * as fs from 'fs';
3
- import { Score } from '../dto/scoring.dto';
4
- import { error } from 'logger';
5
-
6
- export function writeScoresToCsv(filePath: string, data: Score[]): void {
7
- if (data.length === 0) {
8
- console.error('Data array is empty, no CSV will be written.');
9
- return;
10
- }
11
- const headers = Object.keys(data[0]!);
12
- let csvString = headers.join(',') + '\n';
13
-
14
- data.forEach(score => {
15
- const rowData = headers.map(header => {
16
- const value = score[header as keyof Score];
17
- if (typeof value === 'string' && (value.includes(',') || value.includes('\n') || value.includes('"'))) {
18
- return `"${value.replace(/"/g, '""')}"`;
19
- }
20
- return `"${value}"`;
21
- }).join(',');
22
- csvString += rowData + '\n';
23
- });
24
-
25
- fs.writeFile(filePath, csvString, (err) => {
26
- if (err) {
27
- error('Error writing CSV file:', err);
28
- }
29
- });
30
- }
package/utils/maths.ts DELETED
@@ -1,75 +0,0 @@
1
- import { Value } from 'expr-eval';
2
-
3
- /**
4
- * Calculates the sum of an array of numbers.
5
- * @param {number[]} amounts - The array of numbers to sum.
6
- * @return {number} The sum of the numbers in the array.
7
- */
8
- export function sum (amounts: number[]): number {
9
- if (!Array.isArray(amounts) || amounts.some(amount => typeof amount !== 'number')) {
10
- throw new TypeError('Input must be an array of numbers');
11
- }
12
- return amounts.reduce((acc, amount) => acc + amount, 0);
13
- }
14
-
15
- /**
16
- * Calculates the mean (average) of an array of numbers.
17
- * @param {number[]} data - The array of numbers for which to calculate the mean.
18
- * @return {number} The mean of the numbers in the array. Throws an error if the array is empty.
19
- */
20
- export function mean (data: number[]): number {
21
- if (data.length === 0) {
22
- throw new Error('Cannot calculate mean for empty data');
23
- }
24
-
25
- return sum(data) / data.length;
26
- }
27
-
28
- /**
29
- * Calculates the standard deviation of an array of numbers.
30
- * Standard deviation is a measure of the amount of variation or dispersion of a set of values.
31
- * @param {number[]} data - The array of numbers for which to calculate the standard deviation.
32
- * @return {number} The standard deviation of the numbers in the array. Throws an error if the array is empty.
33
- */
34
- export function stdDev (data: number[]): number {
35
- if (data.length === 0) {
36
- throw new Error('Cannot calculate std. dev. for empty data');
37
- }
38
-
39
- const dataMean = mean(data);
40
- return Math.sqrt(data.reduce((sum, value) => sum + Math.pow(value - dataMean, 2), 0) / data.length);
41
- }
42
-
43
- export function piecewise (...args: Value[]): Value {
44
- if (args.length === 0) {
45
- throw new Error('At least one argument must be provided!');
46
- }
47
-
48
- for (let conditionIndex = 0, valueIndex = 1; valueIndex < args.length; conditionIndex += 2, valueIndex += 2) {
49
- const condition = args[conditionIndex];
50
- const value = args[valueIndex];
51
-
52
- if (typeof condition !== 'boolean') {
53
- throw new Error(`Argument at position ${conditionIndex} must be a boolean!`);
54
- }
55
-
56
- if (condition) {
57
- if (value === undefined) {
58
- throw new Error(`Expected a value corresponding to the condition at position ${conditionIndex}, but got undefined.`);
59
- }
60
- return value;
61
- }
62
- }
63
-
64
- const defaultValue = args[args.length - 1];
65
- if (defaultValue === undefined) {
66
- throw new Error('Unexpected error: Default value is undefined.');
67
- }
68
- return defaultValue;
69
- }
70
-
71
- export function mathUtilityFunctions () {
72
- return {
73
- piecewise
74
- };
75
- }
package/utils/solana.ts DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * Converts a lamport value (as a string) to its equivalent in SOL, adding a decimal point before the last 9 digits.
3
- * @param {string} lamports - The lamport value to convert, represented as a string.
4
- * @return {string} The equivalent value in SOL, as a string.
5
- */
6
- export function lamportsToSol (lamports: string): string {
7
- const paddedLamports = lamports.padStart(10, '0');
8
- return paddedLamports.replace(/(.{9})$/, '.$1');
9
- }
package/utils/zip.ts DELETED
@@ -1,12 +0,0 @@
1
- export function zip<T1, T2, T3> (...iterables: [Iterable<T1>, Iterable<T2>, Iterable<T3>]): Generator<[T1, T2, T3]>
2
- export function zip<T1, T2> (...iterables: [Iterable<T1>, Iterable<T2>]): Generator<[T1, T2]>
3
- export function* zip<T1, T2> (...iterables: Iterable<T1 | T2>[]): Generator<(T1 | T2)[]> {
4
- const iterators = iterables.map((iterable) => iterable[Symbol.iterator]());
5
- while (true) {
6
- const results = iterators.map((iter) => iter.next());
7
- if (results.some((result) => result.done)) {
8
- return;
9
- }
10
- yield results.map((result) => result.value);
11
- }
12
- }