Skip to content

Commit

Permalink
Merge pull request #15 from PeerMeHQ/staking-updates
Browse files Browse the repository at this point in the history
Staking app updates
  • Loading branch information
michavie authored Nov 29, 2023
2 parents a210662 + 55344a8 commit b8ba17b
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 79 deletions.
11 changes: 5 additions & 6 deletions src/extensions/staking/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import { Config } from './config'
import React, { useEffect, useState } from 'react'
import { useApp } from '../../../shared/hooks/useApp'
import { DelegateSection } from './delegation/DelegateSection'
import { OverviewSection } from './delegation/OverviewSection'
import { DelegationInfo, DelegationProvider } from './types'
import { ApiNetworkProvider } from '@multiversx/sdk-network-providers'
import { DelegationsSection } from './delegation/DelegationsSection'
import { getDelegationInfoRequest, getDelegationProvidersRequest } from './api'

export const App = () => {
const app = useApp()
const delegationNetworkProvider = new ApiNetworkProvider(Config.Urls.Delegation(app.config.network))
const [providers, setProviders] = useState<DelegationProvider[]>([])
const [delegations, setDelegations] = useState<DelegationInfo[]>([])

useEffect(() => {
getDelegationProvidersRequest(delegationNetworkProvider).then((p) => setProviders(p))
getDelegationInfoRequest(delegationNetworkProvider, app.config.entity.address).then((d) => setDelegations(d))
getDelegationProvidersRequest(app.networkProvider).then((p) => setProviders(p))
getDelegationInfoRequest(app.networkProvider, app.config.entity.address).then((d) => setDelegations(d))
}, [])

return (
<>
<OverviewSection delegations={delegations} className="mb-4" />
<DelegationsSection providers={providers} delegations={delegations} className="mb-4" />
{delegations.length > 0 && (
<DelegationsSection providers={providers} delegations={delegations} className="mb-4" />
)}
<DelegateSection providers={providers} className="mb-4" />
</>
)
Expand Down
15 changes: 8 additions & 7 deletions src/extensions/staking/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@ import { DelegationInfo, DelegationProvider } from './types'
import { ApiNetworkProvider } from '@multiversx/sdk-network-providers'

export const getDelegationProvidersRequest = async (provider: ApiNetworkProvider): Promise<DelegationProvider[]> => {
const res = await provider.doGetGeneric('providers?size=10000')

return res.map(
const res = await provider.doGetGeneric('providers?withIdentityInfo=true&size=10000')
const providers: DelegationProvider[] = res.map(
(r: any) =>
({
...r,
totalActiveStake: new BigNumber(res.totalActiveStake || 0),
maxDelegationCap: new BigNumber(res.maxDelegationCap || 0),
maxDelegateAmountAllowed: new BigNumber(res.maxDelegateAmountAllowed || 0),
contract: r.provider,
stake: new BigNumber(res.stake || 0),
delegationCap: new BigNumber(res.delegationCap || 0),
} as DelegationProvider)
)

return providers.filter((p) => !!p.identityInfo)
}

export const getDelegationInfoRequest = async (
provider: ApiNetworkProvider,
address: string
): Promise<DelegationInfo[]> => {
const res = await provider.doGetGeneric(`accounts/${address}/delegations?size=10000`)
const res = await provider.doGetGeneric(`accounts/${address}/delegation?size=10000`)

return res.map(
(r: any) =>
Expand Down
10 changes: 0 additions & 10 deletions src/extensions/staking/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
import { Network } from '../../../shared/types'

export const Config = {
Endpoints: {
ClaimRewards: 'claimRewards',
Delegate: 'delegate',
ReDelegateRewards: 'reDelegateRewards',
UnDelegate: 'unDelegate',
},

Urls: {
Delegation: (network: Network) => {
if (network === 'devnet') return 'https://devnet-delegation-api.multiversx.com'
if (network === 'testnet') return 'https://testnet-delegation-api.multiversx.com'
return 'https://delegation-api.multiversx.com'
},
},
}
6 changes: 3 additions & 3 deletions src/extensions/staking/src/delegation/DelegateSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const DelegateSection = (props: Props) => {

const filterProviders = (providers: DelegationProvider[], query: string) =>
providers
.filter((p) => p.identity.name && p.identity.url)
.filter((p) => p.identity.name.toLowerCase().includes(query.toLowerCase()))
.sort((a, b) => (a.identity.name > b.identity.name ? 1 : -1))
.filter((p) => p.identityInfo.name && p.identityInfo.website)
.filter((p) => p.identityInfo.name.toLowerCase().includes(query.toLowerCase()))
.sort((a, b) => (a.identityInfo.name > b.identityInfo.name ? 1 : -1))
.sort((a, b) => (a.featured ? -1 : 1))
19 changes: 6 additions & 13 deletions src/extensions/staking/src/delegation/_DelegateProviderList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,26 @@ export const _DelegateProviderList = (props: Props) => (
<td className="flex-grow flex px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
<div className="flex items-center">
<img
src={provider.identity.avatar}
alt={provider.identity.name + ' Staking Provider Avatar'}
src={provider.identityInfo.avatar}
alt={provider.identityInfo.name + ' Staking Provider Avatar'}
className="w-8 h-8 sm:w-10 sm:h-10 rounded-full mr-4"
/>
</div>
<div className="text-left">
<h3 className="text-lg text-black dark:text-white">{provider.identity.name}</h3>
<span className="text-sm text-gray-500">{provider.identity.url}</span>
<h3 className="text-lg text-black dark:text-white">{provider.identityInfo.name}</h3>
<span className="text-sm text-gray-500">{provider.identityInfo.website}</span>
</div>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{provider.apr}%</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{+provider.serviceFee / 100}%</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{provider.maxDelegationCap.isZero()
? 'Uncapped'
: calculateProviderFilledPercentage(provider).toFixed(2) + '%'}
{provider.delegationCap.isZero() ? 'Uncapped' : provider.identityInfo.stakePercent + '%'}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{provider.maxDelegateAmountAllowed.isZero()
? 'Uncapped'
: toEgldDisplayAmount(provider.maxDelegateAmountAllowed)}
{provider.stake.isZero() ? 'Uncapped' : toEgldDisplayAmount(provider.stake)}
</td>
</tr>
))}
</tbody>
</table>
)

const calculateProviderFilledPercentage = (provider: DelegationProvider) =>
provider.totalActiveStake.div(provider.maxDelegationCap).times(100)
6 changes: 3 additions & 3 deletions src/extensions/staking/src/delegation/_DelegationsRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ export const _DelegationsRow = (props: Props) => {
<div className="flex">
<div className="flex items-center">
<img
src={props.provider.identity.avatar}
alt={props.provider.identity.name + ' Staking Provider Avatar'}
src={props.provider.identityInfo.avatar}
alt={props.provider.identityInfo.name + ' Staking Provider Avatar'}
className="w-8 h-8 sm:w-10 sm:h-10 rounded-full mr-4"
/>
</div>
<div className="flex-grow text-left">
<h3 className="text-lg text-black dark:text-white">{props.provider.identity.name}</h3>
<h3 className="text-lg text-black dark:text-white">{props.provider.identityInfo.name}</h3>
<span className="text-sm text-gray-500">APR: {props.provider.apr}%</span>
</div>
</div>
Expand Down
12 changes: 6 additions & 6 deletions src/extensions/staking/src/delegation/_Delegator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,23 @@ export const _Delegator = (props: Props) => {

return (
<div className="relative pt-2">
<h2 className="sr-only">Stake with {props.provider.identity.name}</h2>
<h2 className="sr-only">Stake with {props.provider.identityInfo.name}</h2>
<a
href={props.provider.identity.url}
href={props.provider.identityInfo.website}
target="_blank"
rel="noopener"
className="flex px-6 py-3 bg-gray-200 dark:bg-gray-900 rounded-xl mb-4"
>
<div className="flex items-center">
<img
src={props.provider.identity.avatar}
alt={props.provider.identity.name + ' Staking Provider Avatar'}
src={props.provider.identityInfo.avatar}
alt={props.provider.identityInfo.name + ' Staking Provider Avatar'}
className="w-8 h-8 sm:w-10 sm:h-10 rounded-full mr-4"
/>
</div>
<div className="flex-grow text-left">
<h3 className="text-lg text-black dark:text-white">{props.provider.identity.name}</h3>
<span className="text-sm text-gray-500">{props.provider.identity.url}</span>
<h3 className="text-lg text-black dark:text-white">{props.provider.identityInfo.name}</h3>
<span className="text-sm text-gray-500">{props.provider.identityInfo.website}</span>
</div>
</a>
<label htmlFor="amount" className="pl-1 text-xl mb-2 text-gray-800 dark:text-gray-200">
Expand Down
10 changes: 5 additions & 5 deletions src/extensions/staking/src/delegation/_Withdrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ export const _Withdrawer = (props: Props) => {
<div className="relative pt-2">
<h2 className="sr-only">Withdraw from</h2>
<a
href={props.provider.identity.url}
href={props.provider.identityInfo.website}
target="_blank"
rel="noopener"
className="flex px-6 py-3 bg-gray-200 dark:bg-gray-900 rounded-xl mb-4"
>
<div className="flex items-center">
<img
src={props.provider.identity.avatar}
alt={props.provider.identity.name + ' Staking Provider Avatar'}
src={props.provider.identityInfo.avatar}
alt={props.provider.identityInfo.name + ' Staking Provider Avatar'}
className="w-8 h-8 sm:w-10 sm:h-10 rounded-full mr-4"
/>
</div>
<div className="flex-grow text-left">
<h3 className="text-lg text-black dark:text-white">{props.provider.identity.name}</h3>
<span className="text-sm text-gray-500">{props.provider.identity.url}</span>
<h3 className="text-lg text-black dark:text-white">{props.provider.identityInfo.name}</h3>
<span className="text-sm text-gray-500">{props.provider.identityInfo.website}</span>
</div>
</a>
<label htmlFor="amount" className="pl-1 text-xl mb-2 text-gray-800 dark:text-gray-200">
Expand Down
62 changes: 36 additions & 26 deletions src/extensions/staking/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
import { BigNumber } from 'bignumber.js'

export type DelegationProvider = {
identity: {
key: string
name: string
avatar: string
description: string
location: string
url: string
}
numNodes: number
stake: BigNumber
topUp: string
locked: string
contract: string
explorerURL: string
featured: boolean
owner: string
serviceFee: string
maxDelegationCap: BigNumber
initialOwnerFunds: string
featured: boolean
serviceFee: number
delegationCap: BigNumber
apr: number
numUsers: number
cumulatedRewards: string
identity: string
automaticActivation: boolean
withDelegationCap: boolean
changeableServiceFee: boolean
checkCapOnRedelegate: boolean
createdNonce: number
unBondPeriod: number
apr: string
aprValue: number
totalActiveStake: BigNumber
totalUnStaked: string
totalCumulatedRewards: string
numUsers: number
numNodes: number
maxDelegateAmountAllowed: BigNumber
ownerBelowRequiredBalanceThreshold: boolean
githubProfileValidated: boolean
githubProfileValidatedAt: string
githubKeysValidated: boolean
githubKeysValidatedAt: string
identityInfo: ProviderIdentity
}

type ProviderIdentity = {
identity: string
locked: string
distribution: { [key: string]: number }
avatar: string
description: string
name: string
website: string
twitter: string
location: string
score: number
validators: number
stake: string
topUp: string
providers: string[]
stakePercent: number
apr: number
rank: number
}

export type DelegationInfo = {
Expand Down

0 comments on commit b8ba17b

Please sign in to comment.