import { formatUnits } from '@ethersproject/units' ; import { BigNumber } from '@ethersproject/bignumber' ; import { subgraphRequest } from '../../utils' ; export const author = 'QYuQianchen' ; export const version = '0.1.0' ; const XDAI_BLOCK_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/1hive/xdai-blocks' ; const HOPR_STAKING_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/hoprnet/hopr-staking-program' ; const LIMIT = 1000 ; async function getXdaiBlockNumber ( timestamp ) { const query = { blocks : { __args : { first : 1 , orderBy : 'number' , orderDirection : 'desc' , where : { timestamp_lte : timestamp } } , number : true , timestamp : true } } ; const data = await subgraphRequest ( XDAI_BLOCK_SUBGRAPH_URL , query ) ; return Number ( data . blocks [ 0 ] . number ) ; } async function stakingSubgraphQuery ( addresses , blockNumber ) { const query = { accounts : { __args : { first : LIMIT , block : { number : blockNumber } , where : { id_in : addresses . map ( ( adr ) => adr . toLowerCase ( ) ) } } , id : true , actualStake : true , virtualStake : true , unclaimedRewards : true } } ; const data = await subgraphRequest ( HOPR_STAKING_SUBGRAPH_URL , query ) ; const entries = data . accounts . map ( ( d ) => [ d . id , BigNumber . from ( d . actualStake ) . add ( BigNumber . from ( d . virtualStake ) . add ( BigNumber . from ( d . unclaimedRewards ) ) ) ] ) ; return Object . fromEntries ( entries ) ; } export async function strategy ( space , network , provider , addresses , options , snapshot ) { const blockTag = typeof snapshot === 'number' ? snapshot : 'latest' ; const isXdai = network === '100' ; const [ block ] = await Promise . all ( [ provider . getBlock ( blockTag ) ] ) ; const subgraphBlock = isXdai ? block . number : await getXdaiBlockNumber ( block . timestamp ) ; const addressSubsets = Array . apply ( null , Array ( Math . ceil ( addresses . length / LIMIT ) ) ) . map ( ( _e , i ) => addresses . slice ( i * LIMIT , ( i + 1 ) * LIMIT ) ) ; const returnedFromSubgraph = await Promise . all ( addressSubsets . map ( ( subset ) => stakingSubgraphQuery ( subset , subgraphBlock ) ) ) ; const subgraphBalance = Object . assign ( { } , ... returnedFromSubgraph ) ; const subgraphScore = addresses . map ( ( address ) => subgraphBalance [ address . toLowerCase ( ) ] ?? 0 ) ; return Object . fromEntries ( addresses . map ( ( adr , i ) => [ adr , parseFloat ( formatUnits ( subgraphScore [ i ] , 18 ) ) ] ) ) ; }