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.3';
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      stakedAssetsUSD: async () => {
134        const [{ amountEth }, ethPrice] = await Promise.all([
135          getBeaconStats(),
136          sdk.coinGecko.getCurrentPrice('ethereum'),
137        ]);
138        return amountEth * ethPrice;
139      },
140    },
141    metadata: {
142      name: 'Ethereum Beacon Chain',
143      icon: sdk.ipfs.getDataURILoader('QmedJLPy6R7x3dDEy2cfMd8gXbZm9e3vxvgBLXp3YZEHCy', 'image/svg+xml'),
144    },
145  });
146}
147

It's something off?

Report it to the discussion board on Discord, we will take care of it.

Adapter Info

Version

0.0.3

License

MIT

IPFS CID

QmVdY24XYYa8K6LvxijQ3cVhBd4TXi4fSCpYmmLkGquVYN

CID (source)

QmZJxmdH8AL7j2XtjUXu9LEDk8hhavR6hxDLzPiBPSQvyE

Author

mihal.eth