@marinade.finance/scoring 1.0.0 → 1.0.1
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/computing/cluster.ts +102 -0
- package/computing/eligibility.ts +163 -0
- package/computing/score.ts +164 -0
- package/computing/stake.ts +246 -0
- package/computing/validators.ts +133 -0
- package/{src/dto → dto}/bonds.dto.ts +0 -2
- package/{src/dto → dto}/cluster.dto.ts +0 -1
- package/{src/dto → dto}/eligibility.dto.ts +0 -5
- package/{src/dto → dto}/jito.dto.ts +1 -2
- package/{src/dto → dto}/marinade.dto.ts +1 -1
- package/{src/dto → dto}/rewards.dto.ts +1 -3
- package/{src/dto → dto}/scoring.dto.ts +1 -7
- package/{src/dto → dto}/snapshots.dto.ts +0 -3
- package/{src/dto → dto}/stakes.dto.ts +0 -4
- package/{src/dto → dto}/validators.dto.ts +1 -37
- package/package.json +17 -13
- package/{src/providers → providers}/api-data.provider.ts +58 -58
- package/{src/providers → providers}/file-data.provider.ts +7 -15
- package/{src/utils → utils}/csv.ts +3 -3
- package/src/cluster/cluster.module.ts +0 -8
- package/src/cluster/cluster.service.ts +0 -108
- package/src/config/config.module.ts +0 -8
- package/src/config/config.service.ts +0 -136
- package/src/eligibility/eligibility.module.ts +0 -11
- package/src/eligibility/eligibility.service.ts +0 -183
- package/src/scoring/scoring.module.ts +0 -11
- package/src/scoring/scoring.service.ts +0 -184
- package/src/stake/stake.module.ts +0 -10
- package/src/stake/stake.service.ts +0 -242
- package/src/validators/validators.module.ts +0 -48
- package/src/validators/validators.service.ts +0 -177
- /package/{src/constants → constants}/marinade.json +0 -0
- /package/{src/errors → errors}/fetching.ts +0 -0
- /package/{src/interfaces → interfaces}/data-provider.interface.ts +0 -0
- /package/{src/utils → utils}/maths.ts +0 -0
- /package/{src/utils → utils}/solana.ts +0 -0
- /package/{src/utils → utils}/zip.ts +0 -0
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { AggregatedValidator, AggregatedValidators, ValidatorDto } from '../dto/validators.dto';
|
|
2
|
-
import { IDataProvider } from '../interfaces/data-provider.interface';
|
|
3
|
-
import { JitoValidatorDto } from '../dto/jito.dto';
|
|
4
|
-
import { Inject } from '@nestjs/common';
|
|
5
|
-
import { mean, sum } from '../utils/maths';
|
|
6
|
-
import { ClusterInfo } from '../dto/cluster.dto';
|
|
7
|
-
import { Votes } from '../dto/snapshots.dto';
|
|
8
|
-
import { Bonds } from '../dto/bonds.dto';
|
|
9
|
-
import { Rewards } from '../dto/rewards.dto';
|
|
10
|
-
import { TvlStats } from '../dto/marinade.dto';
|
|
11
|
-
|
|
12
|
-
export class ValidatorsService {
|
|
13
|
-
constructor (@Inject('IDataProvider') private dataProvider: IDataProvider) { }
|
|
14
|
-
|
|
15
|
-
aggregateValidatorData (
|
|
16
|
-
validator: ValidatorDto,
|
|
17
|
-
mevRecord: JitoValidatorDto,
|
|
18
|
-
blacklist: Set<string>,
|
|
19
|
-
firstEpoch: number,
|
|
20
|
-
lastEpoch: number
|
|
21
|
-
): AggregatedValidator {
|
|
22
|
-
const currentMarinadeStake = Number(validator.epochStats[lastEpoch]?.marinade_native_stake || 0) / 1e9 + Number(validator.epochStats[lastEpoch]?.marinade_stake || 0) / 1e9;
|
|
23
|
-
const voteAccount = validator.vote_account;
|
|
24
|
-
const name = validator.info_name || 'Unknown';
|
|
25
|
-
const epochs: number[] = [];
|
|
26
|
-
const commission: number[] = [];
|
|
27
|
-
const stake: number[] = [];
|
|
28
|
-
const externalStake: number[] = [];
|
|
29
|
-
const credits: number[] = [];
|
|
30
|
-
const blocksProduced: number[] = [];
|
|
31
|
-
const leaderSlots: number[] = [];
|
|
32
|
-
const dataAvailable: boolean[] = [];
|
|
33
|
-
|
|
34
|
-
const currentStake = Number(validator.epochStats[lastEpoch]?.activated_stake || 0) / 1e9;
|
|
35
|
-
|
|
36
|
-
const blacklisted = blacklist.has(voteAccount);
|
|
37
|
-
|
|
38
|
-
for (let epoch = lastEpoch; epoch >= firstEpoch; epoch--) {
|
|
39
|
-
const epochStat = validator.epochStats?.[epoch];
|
|
40
|
-
|
|
41
|
-
epochs.push(epoch);
|
|
42
|
-
commission.push(epochStat?.commission_max_observed || epochStat?.commission_advertised || 0);
|
|
43
|
-
stake.push(Number(epochStat?.activated_stake || 0) / 1e9);
|
|
44
|
-
externalStake.push(Number(epochStat?.activated_stake || 0) / 1e9 - Number(epochStat?.marinade_stake || 0) / 1e9 - Number(epochStat?.marinade_native_stake || 0) / 1e9);
|
|
45
|
-
credits.push(epochStat?.credits || 0);
|
|
46
|
-
blocksProduced.push(epochStat?.blocks_produced || 0);
|
|
47
|
-
leaderSlots.push(epochStat?.leader_slots || 0);
|
|
48
|
-
dataAvailable.push(!!epochStat);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const mevCommission = mevRecord?.running_jito ? mevRecord.mev_commission_bps / 100 : 100;
|
|
52
|
-
return {
|
|
53
|
-
voteAccount,
|
|
54
|
-
name,
|
|
55
|
-
epochs,
|
|
56
|
-
currentMarinadeStake,
|
|
57
|
-
currentStake,
|
|
58
|
-
commission,
|
|
59
|
-
stake,
|
|
60
|
-
externalStake,
|
|
61
|
-
credits,
|
|
62
|
-
blocksProduced,
|
|
63
|
-
leaderSlots,
|
|
64
|
-
dataAvailable,
|
|
65
|
-
mevCommission,
|
|
66
|
-
country: validator.dc_country || 'Unknown',
|
|
67
|
-
city: validator.dc_full_city || 'Unknown',
|
|
68
|
-
aso: validator.dc_aso || 'Unknown',
|
|
69
|
-
blacklisted,
|
|
70
|
-
version: validator.version
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async fetchTvlStats (withSnapshot: boolean): Promise<TvlStats> {
|
|
75
|
-
return await this.dataProvider.fetchTvl(withSnapshot);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async fetchValidators (epochsToFetch: number, withSnapshot: boolean): Promise<ValidatorDto[]> {
|
|
79
|
-
return this.dataProvider.fetchValidators(epochsToFetch, withSnapshot);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async fetchMsolVotes (withSnapshot: boolean): Promise<Votes> {
|
|
83
|
-
return await this.dataProvider.fetchMSolVotes(withSnapshot);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async fetchRewards (epochs:number, withSnapshot: boolean): Promise<Rewards> {
|
|
87
|
-
return await this.dataProvider.fetchRewards(epochs, withSnapshot);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async fetchVeMndeVotes (withSnapshot: boolean): Promise<Votes> {
|
|
91
|
-
return await this.dataProvider.fetchVeMndeVotes(withSnapshot);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async fetchBonds (withSnapshot: boolean): Promise<Bonds> {
|
|
95
|
-
return this.dataProvider.fetchBonds(withSnapshot);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async aggregateValidatorsData (
|
|
99
|
-
validators: ValidatorDto[],
|
|
100
|
-
basicEligibilityEpochs: number,
|
|
101
|
-
bonusEligibilityExtraEpochs: number
|
|
102
|
-
): Promise<AggregatedValidators> {
|
|
103
|
-
const lastEpoch = this.getMaxEpoch(validators);
|
|
104
|
-
const firstEpoch = lastEpoch - basicEligibilityEpochs - bonusEligibilityExtraEpochs;
|
|
105
|
-
|
|
106
|
-
const jitoMevRecords: Record<string, JitoValidatorDto> = await this.dataProvider.fetchValidatorsJitoMEV(true);
|
|
107
|
-
const blacklist: Set<string> = await this.dataProvider.fetchBlacklist(true);
|
|
108
|
-
|
|
109
|
-
const result: { [voteAccount: string]: AggregatedValidator } = {};
|
|
110
|
-
|
|
111
|
-
for (const validator of validators) {
|
|
112
|
-
const mevRecord = jitoMevRecords[validator.vote_account] ?? {
|
|
113
|
-
vote_account: validator.vote_account,
|
|
114
|
-
mev_commission_bps: 100,
|
|
115
|
-
running_jito: false,
|
|
116
|
-
active_stake: Number(validator.activated_stake)
|
|
117
|
-
} as JitoValidatorDto;
|
|
118
|
-
|
|
119
|
-
if (mevRecord) {
|
|
120
|
-
const aggregatedData = this.aggregateValidatorData(validator, mevRecord, blacklist, firstEpoch, lastEpoch);
|
|
121
|
-
result[validator.vote_account] = aggregatedData;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return result;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
getMaxEpoch (validators: ValidatorDto[]): number {
|
|
129
|
-
return validators.reduce((maxEpoch, validator) => {
|
|
130
|
-
const validatorMaxEpoch = validator.epoch_stats.reduce((max, { epoch }) => {
|
|
131
|
-
return Math.max(epoch, max);
|
|
132
|
-
}, 0);
|
|
133
|
-
return Math.max(maxEpoch, validatorMaxEpoch);
|
|
134
|
-
}, 0);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
selectExternalStakeMin (validator: AggregatedValidator, fullEpochs: number): number {
|
|
138
|
-
if (validator.externalStake.length === 0) {
|
|
139
|
-
throw new Error('Validator has no external stake data.');
|
|
140
|
-
}
|
|
141
|
-
return Math.min(...validator.externalStake.slice(0, fullEpochs + 1));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
selectCreditsPctMean (validator: AggregatedValidator, clusterInfo: ClusterInfo, fullEpochs: number): number {
|
|
145
|
-
return mean(validator.epochs.slice(1, fullEpochs + 1).map((epoch, fullEpochIndex) =>
|
|
146
|
-
(validator.credits[fullEpochIndex + 1] ?? 0) / (clusterInfo.targetCreditsByEpoch.get(epoch) ?? 1)));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
selectBlockProductionMean (validator: AggregatedValidator, fullEpochs: number): number {
|
|
150
|
-
const leaderSlots = sum(validator.leaderSlots.slice(1, fullEpochs + 1));
|
|
151
|
-
return leaderSlots === 0 ? 1 : sum(validator.blocksProduced.slice(1, fullEpochs + 1)) / leaderSlots;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
selectCommissonInflationMax (validator: AggregatedValidator, epochs: number): number {
|
|
155
|
-
return Math.max(...validator.commission.slice(0, epochs));
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
selectCommissonMEV (validator: AggregatedValidator): number {
|
|
159
|
-
return validator.mevCommission;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
selectCountryStakeConcentration (validator: AggregatedValidator, clusterInfo: ClusterInfo): number {
|
|
163
|
-
return clusterInfo.country.get(validator.country ?? '???') ?? 0;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
selectCityStakeConcentration (validator: AggregatedValidator, clusterInfo: ClusterInfo): number {
|
|
167
|
-
return clusterInfo.city.get(validator.city ?? '???') ?? 0;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
selectASOStakeConcentration (validator: AggregatedValidator, clusterInfo: ClusterInfo): number {
|
|
171
|
-
return clusterInfo.aso.get(validator.aso ?? '???') ?? 0;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
selectNodeStake (validator: AggregatedValidator): number {
|
|
175
|
-
return validator.stake[0] ?? 0;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|