Sub-Adapters 1
Preview and test each sub adapter.
Ethereum Beacon Chain (eth-beacon-chain)
Metadata
- ID
- eth-beacon-chain
- name
"Ethereum Beacon Chain"
- icon
Queries
Adapter Code
Check the entire code written for the Adapter.
Source code
Showing TS source.
1export const name = 'Ethereum Beacon Chain';
2export const version = '0.0.2';
3export const license = 'MIT';
4
5///
6// Code copied from Eth2 Launchpad
7// https://github.com/ethereum/staking-launchpad/blob/d25870fabccdc9b896fa6d061bdfbc2f87990ec1/src/utils/calculateEth2Rewards.ts
8///
9
10export interface CalculateEth2RewardsParams {
11 slotTimeInSec?: number;
12 slotsInEpoch?: number;
13 baseRewardFactor?: number;
14 totalAtStake?: number;
15 baseRewardsPerEpoch?: number;
16 baseRewardsPropotionalValidators?: number;
17 averageNetworkPctOnline?: number;
18 oneSlotLatePenalty?: number;
19 vaildatorUptime?: number;
20 validatorDeposit?: number;
21}
22
23const calculateEth2Rewards = ({
24 slotTimeInSec = 12,
25 slotsInEpoch = 32,
26 baseRewardFactor = 64,
27 totalAtStake = 1_000_000,
28 baseRewardsPerEpoch = 4,
29 baseRewardsPropotionalValidators = 3,
30 averageNetworkPctOnline = 0.95,
31 oneSlotLatePenalty = 0.0156,
32 vaildatorUptime = 0.99,
33 validatorDeposit = 32,
34}: CalculateEth2RewardsParams): number => {
35 // Calculate number of epochs per year
36 const avgSecInYear = 31556908.8; // 60 * 60 * 24 * 365.242
37 const epochPerYear = avgSecInYear / (slotTimeInSec * slotsInEpoch);
38
39 // Calculate base reward for full validator (in gwei)
40 const baseGweiRewardFullValidator =
41 (32 * 10e8 * baseRewardFactor) /
42 (totalAtStake * 10e8) ** 0.5 /
43 baseRewardsPerEpoch;
44
45 // Calculate offline per-validator penalty per epoch (in gwei)
46 const offlineEpochGweiPentalty = baseGweiRewardFullValidator * 4;
47
48 // Calculate online per-validator reward per epoch (in gwei)
49 const fullUptimeValidatorRewards =
50 baseGweiRewardFullValidator *
51 baseRewardsPropotionalValidators *
52 averageNetworkPctOnline;
53 const oneEighthReward =
54 0.125 * baseGweiRewardFullValidator * averageNetworkPctOnline;
55 const rewardAdjModifier =
56 averageNetworkPctOnline +
57 averageNetworkPctOnline *
58 (1 - averageNetworkPctOnline) *
59 (1 - oneSlotLatePenalty) +
60 averageNetworkPctOnline *
61 (1 - averageNetworkPctOnline) ** 2 *
62 (1 - 2 * oneSlotLatePenalty);
63 const sevenEighthsReward =
64 0.875 * baseGweiRewardFullValidator * rewardAdjModifier;
65 const onlineEpochGweiReward =
66 fullUptimeValidatorRewards + oneEighthReward + sevenEighthsReward;
67
68 // Calculate net yearly staking reward (in gwei)
69 const reward = onlineEpochGweiReward * vaildatorUptime;
70 const penalty = offlineEpochGweiPentalty * (1 - vaildatorUptime);
71 const netRewardPerYear = epochPerYear * (reward - penalty);
72
73 // Return net yearly staking reward percentage
74 return netRewardPerYear / 10e8 / validatorDeposit;
75};
76
77
78export function setup(sdk: Context) {
79 let latestEpochPromise: any = null;
80 // Prevents duplicate requests to the same URL
81 const getLatestEpoch = () => {
82 if (!latestEpochPromise) {
83 latestEpochPromise = sdk.http.get('https://mainnet.beaconcha.in/api/v1/epoch/latest');
84 }
85 return latestEpochPromise;
86 }
87
88 const getBeaconStats = async () => {
89 const response = await getLatestEpoch();
90 return {
91 validatorCount: response.data.validatorscount,
92 amountEth: response.data.totalvalidatorbalance * 1e-9,
93 };
94 }
95
96 const getInterestRate = async (assetAddress?: string): Promise<number> => {
97 if (assetAddress && assetAddress !== '0x0000000000000000000000000000000000000000') {
98 return 0;
99 }
100 const { amountEth } = await getBeaconStats();
101 const apr = calculateEth2Rewards({ totalAtStake: amountEth });
102 return apr;
103 }
104
105 const getTotalRewards = async () => {
106 const latest = await getLatestEpoch();
107 const previous = await sdk.http.get(`https://mainnet.beaconcha.in/api/v1/epoch/${latest.data.epoch - 1}`);
108 return (previous.data.totalvalidatorbalance - previous.data.eligibleether) / 1e9;
109 }
110
111 const getEligibleETH = async () => {
112 const latest = await getLatestEpoch();
113 const previous = await sdk.http.get(`https://mainnet.beaconcha.in/api/v1/epoch/${latest.data.epoch - 1}`);
114
115 return previous.data.eligibleether / 1e9;
116 }
117
118 sdk.register({
119 id: 'eth-beacon-chain',
120 queries: {
121 currentAPY: getInterestRate,
122 tvlUSDCurrent: async () => {
123 const { amountEth } = await getBeaconStats();
124 const ethPrice = await sdk.coinGecko.getCurrentPrice('ethereum');
125 return amountEth * ethPrice;
126 },
127 tvlETHCurrent: async () => {
128 const { amountEth } = await getBeaconStats();
129 return amountEth;
130 },
131 totalRewards: getTotalRewards,
132 totalStakedETH: getEligibleETH,
133 },
134 metadata: {
135 name: 'Ethereum Beacon Chain',
136 icon: sdk.ipfs.getDataURILoader('QmedJLPy6R7x3dDEy2cfMd8gXbZm9e3vxvgBLXp3YZEHCy', 'image/svg+xml'),
137 },
138 });
139}
140
It's something off?
Report it to the discussion board on Discord, we will take care of it.