Skip to content

Commit

Permalink
Display number of stakers (#1121)
Browse files Browse the repository at this point in the history
* Fetch and display number of stakers

* Mutations refactoring

* Cleanup
  • Loading branch information
bobo-k2 authored Jan 11, 2024
1 parent 26faed9 commit 2c4ec83
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/i18n/en-US/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ export default {
withdraw: 'Withdraw',
relock: 'Re-lock',
currentTier: 'Current Tier',
numberOfStakers: 'Number of Stakers',
numberOfStakers: 'Number of stakers',
totalEarned: 'Total Earned',
yourDashboard: 'Your Dashboard',
edit: 'Edit',
Expand Down
1 change: 1 addition & 0 deletions src/staking-v3/components/Dapps.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
</div>
<div class="card__bottom">
<div>T{{ getDappTier(dapp.chain.id) ?? '-' }}</div>
<div>{{ dapp.dappDetails?.stakersCount ?? '--' }}</div>
<div>
<token-balance-native :balance="dapp.chain.totalStake?.toString() ?? '0'" />
</div>
Expand Down
4 changes: 0 additions & 4 deletions src/staking-v3/components/dapp/DappBackground.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<template>
<div class="wrapper--dapp-background">
aaa
<img class="image--dapp-icon" :src="dapp.basic.iconUrl" :alt="dapp.basic.name" />
</div>
</template>
Expand All @@ -15,9 +14,6 @@ export default defineComponent({
required: true,
},
},
setup() {
return {};
},
});
</script>

Expand Down
8 changes: 3 additions & 5 deletions src/staking-v3/components/dapp/DappStatistics.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@
<kpi-card v-if="!small" :title="$t('dappStaking.dappPage.totalStaked')">
<token-balance-native :balance="dapp.chain.totalStake?.toString() || '0'" />
</kpi-card>

<!-- <kpi-card :title="$t('dappStaking.dappPage.totalStaker')">
<span>{{ $n(dapp.stakerInfo.stakersCount) }}</span>
</kpi-card> -->

<kpi-card v-if="!small" :title="$t('stakingV3.currentTier')">
<span>{{ getDappTier(dapp.chain.id) ?? '--' }}</span>
</kpi-card>
<kpi-card v-if="!small" :title="$t('stakingV3.numberOfStakers')">
<span>{{ dapp.dappDetails?.stakersCount ?? '--' }}</span>
</kpi-card>

<!-- <kpi-card :title="$t('stakingV3.totalEarned')">
<span>{{ $t('amountToken', { amount: 10, token: nativeTokenSymbol }) }}</span>
Expand Down
28 changes: 27 additions & 1 deletion src/staking-v3/hooks/useDappStaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,10 @@ export function useDappStaking() {
const staker = await stakingService.getStakerRewards(currentAccount.value);
const bonus = await stakingService.getBonusRewards(currentAccount.value);
store.commit('stakingV3/setRewards', { ...rewards.value, staker, bonus });
fetchStakerInfoToStore();
getCurrentEraInfo();
fetchStakeAmountsToStore();
await fetchStakerInfoToStore();
updateStakersCount([dapp.chain.address], -1);
};

const unstakeFromUnregistered = async (dappAddress: string, dappName: string): Promise<void> => {
Expand Down Expand Up @@ -231,6 +232,10 @@ export function useDappStaking() {
unstakeAmount,
t('stakingV3.voteSuccess', { number: stakeInfo.length })
);
updateStakersCount(
stakeInfo.map((x) => x.address),
1
);
await Promise.all([
getAllRewards(),
fetchStakerInfoToStore(),
Expand Down Expand Up @@ -492,6 +497,27 @@ export function useDappStaking() {
return;
};

/**
* Updates number of stakers for dApps in Vuex store. Stakers count comes from an indexer through Token API
* and it doesn't make sense to reload from there because most likely the new stakers count won't be indexed
* at the time of the call.
* @param stakedContracts List of contract addresses for which stakers count should be updated.
* @param amount expected value +1 in case of staking and -1 when unstaking.
*/
const updateStakersCount = (stakedContracts: string[], amount: number): void => {
for (const contract of stakedContracts) {
const alreadyStaked = stakerInfo.value.get(contract);
if (!alreadyStaked) {
const dapp = getDapp(contract);
if (dapp && dapp.dappDetails) {
const detailsClone = { ...dapp.dappDetails };
detailsClone.stakersCount += amount;
store.commit('stakingV3/updateDappDetails', detailsClone);
}
}
}
};

return {
protocolState,
ledger,
Expand Down
2 changes: 1 addition & 1 deletion src/staking-v3/hooks/useDapps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function useDapps() {
};

const getDapp = (dappAddress: string): CombinedDappInfo | undefined =>
allDapps.value.find((d) => d.chain.address === dappAddress);
allDapps.value.find((d) => d.chain.address.toLowerCase() === dappAddress?.toLowerCase());

return {
registeredDapps,
Expand Down
2 changes: 1 addition & 1 deletion src/staking-v3/hooks/useLeaderboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function useLeaderboard() {
});
};

const getDailyReward = (tier: number): bigint => dAppTiers.value.rewards[tier - 1];
const getDailyReward = (tier: number): bigint => dAppTiers.value.rewards[tier - 1] ?? BigInt(0);

watch(
registeredDapps,
Expand Down
10 changes: 10 additions & 0 deletions src/staking-v3/logic/models/DappStaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface CombinedDappInfo {
basic: DappBase;
extended?: Dapp;
chain: DappInfo;
dappDetails?: ProviderDappData;
}

export interface Developer {
Expand Down Expand Up @@ -188,3 +189,12 @@ export enum TvlAmountType {
FixedTvlAmount,
DynamicTvlAmount,
}

export interface ProviderDappData {
contractAddress: string;
stakersCount: number;
registeredAt: number;
registrationBlockNumber: number;
unregisteredAt?: number;
unregistrationBlockNumber?: number;
}
8 changes: 8 additions & 0 deletions src/staking-v3/logic/repositories/IDataProviderRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ProviderDappData } from '../models';

/**
* Interface for provider to fetch dapp staking v3 data from other sources
*/
export interface IDataProviderRepository {
getDapps(network: string): Promise<ProviderDappData[]>;
}
28 changes: 28 additions & 0 deletions src/staking-v3/logic/repositories/TokenApiProviderRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { injectable } from 'inversify';
import { IDataProviderRepository } from './IDataProviderRepository';
import { ProviderDappData } from '../models';
import { TOKEN_API_URL } from '@astar-network/astar-sdk-core';
import { Guard } from 'src/v2/common';
import axios from 'axios';

@injectable()
export class TokenApiProviderRepository implements IDataProviderRepository {
private readonly _baseUrl: string;

constructor() {
this._baseUrl = 'https://api.astar.network/api/v3/shibuya/dapps-staking/';
}
async getDapps(network: string): Promise<ProviderDappData[]> {
Guard.ThrowIfUndefined(network, 'network');

const dappsUrl = `${TOKEN_API_URL}/v3/${network.toLowerCase()}/dapps-staking/chaindapps`;
try {
const dapps = await axios.get<ProviderDappData[]>(dappsUrl);
return dapps.data;
} catch (error) {
console.error(error);
}

return [];
}
}
2 changes: 2 additions & 0 deletions src/staking-v3/logic/repositories/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './DappStakingRepository';
export * from './IDappStakingRepository';
export * from './IDataProviderRepository';
export * from './TokenApiProviderRepository';
11 changes: 9 additions & 2 deletions src/staking-v3/logic/services/DappStakingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { inject, injectable } from 'inversify';
import { CombinedDappInfo, DappStakeInfo, SingularStakingInfo, StakeAmount } from '../models';
import { IDappStakingService } from './IDappStakingService';
import { Symbols } from 'src/v2/symbols';
import { IDappStakingRepository } from '../repositories';
import { IDappStakingRepository, IDataProviderRepository } from '../repositories';
import { Guard } from 'src/v2/common';
import { IWalletService } from 'src/v2/services';
import { ExtrinsicPayload } from '@astar-network/astar-sdk-core';
Expand All @@ -13,16 +13,19 @@ export class DappStakingService implements IDappStakingService {
constructor(
@inject(Symbols.DappStakingRepositoryV3)
protected dappStakingRepository: IDappStakingRepository,
@inject(Symbols.TokenApiProviderRepository)
protected tokenApiRepository: IDataProviderRepository,
@inject(Symbols.WalletFactory) private walletFactory: () => IWalletService
) {}

// @inheritdoc
public async getDapps(network: string): Promise<CombinedDappInfo[]> {
Guard.ThrowIfUndefined(network, 'network');

const [storeDapps, chainDapps] = await Promise.all([
const [storeDapps, chainDapps, tokenApiDapps] = await Promise.all([
this.dappStakingRepository.getDapps(network.toLowerCase()),
this.dappStakingRepository.getChainDapps(),
this.tokenApiRepository.getDapps(network.toLowerCase()),
]);

// Map on chain and in store dApps
Expand All @@ -31,10 +34,14 @@ export class DappStakingService implements IDappStakingService {
const storeDapp = storeDapps.find(
(x) => x.address.toLowerCase() === chainDapp.address.toLowerCase()
);
const dappDetails = tokenApiDapps.find(
(x) => x.contractAddress.toLowerCase() === chainDapp.address.toLowerCase()
);
if (storeDapp) {
dApps.push({
basic: storeDapp,
chain: chainDapp,
dappDetails,
});
}
});
Expand Down
5 changes: 3 additions & 2 deletions src/staking-v3/logic/services/DappStakingServiceEvm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { IDappStakingService } from './IDappStakingService';
import { DappStakingService } from './DappStakingService';
import { DappStakeInfo, SingularStakingInfo } from '../models';
import { IWalletService } from '../../../v2/services/IWalletService';
import { IDappStakingRepository } from '../repositories';
import { IDappStakingRepository, IDataProviderRepository } from '../repositories';
import { Symbols } from 'src/v2/symbols';
import { evmPrecompiledContract } from 'src/modules/precompiled';
import { IAccountUnificationRepository } from 'src/v2/repositories';
Expand All @@ -17,11 +17,12 @@ export class DappStakingServiceEvm extends DappStakingService implements IDappSt

constructor(
@inject(Symbols.DappStakingRepositoryV3) dappStakingRepository: IDappStakingRepository,
@inject(Symbols.TokenApiProviderRepository) tokenApiRepository: IDataProviderRepository,
@inject(Symbols.WalletFactory) walletFactory: () => IWalletService,
@inject(Symbols.AccountUnificationRepository)
private accountUnificationRepository: IAccountUnificationRepository
) {
super(dappStakingRepository, walletFactory);
super(dappStakingRepository, tokenApiRepository, walletFactory);
this.wallet = walletFactory();
}

Expand Down
41 changes: 17 additions & 24 deletions src/staking-v3/store/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import {
DappInfo,
TiersConfiguration,
EraLengths,
ProviderDappData,
} from '../logic';

export interface DappStakingMutations<S = DappStakingState> {
addDapps(state: DappStakingState, dapps: CombinedDappInfo[]): void;
addDapp(state: DappStakingState, dapp: CombinedDappInfo): void;
updateDappExtended(state: DappStakingState, dapp: Dapp): void;
updateDappChain(state: DappStakingState, dapp: DappInfo): void;
updateDappDetails(state: DappStakingState, dapp: ProviderDappData): void;
setProtocolState(state: DappStakingState, protocolState: ProtocolState): void;
setLedger(state: DappStakingState, ledger: AccountLedger): void;
setStakerInfo(state: DappStakingState, stakerInfo: Map<string, SingularStakingInfo>): void;
Expand All @@ -31,18 +33,22 @@ export interface DappStakingMutations<S = DappStakingState> {
setEraLengths(state: DappStakingState, eraLengths: EraLengths): void;
}

const updateDapp = (
const updateDapp = <T>(
state: DappStakingState,
dapp: CombinedDappInfo,
propertyToUpdate: 'basic' | 'extended' | 'chain'
dappAddress: string,
data: T,
propertyToUpdate: 'basic' | 'extended' | 'chain' | 'dappDetails'
): void => {
const dappToUpdate = state.dapps.find((x) => x.basic.address === dapp.chain.address);
// TODO see how to figure out type of T, so we can remove propertyToUpdate parameter.
const dappToUpdate = state.dapps.find(
(x) => x.basic.address.toLowerCase() === dappAddress.toLowerCase()
);

if (dappToUpdate) {
const index = state.dapps.indexOf(dappToUpdate);
state.dapps.splice(index, 1, { ...dappToUpdate, [propertyToUpdate]: dapp[propertyToUpdate] });
state.dapps.splice(index, 1, { ...dappToUpdate, [propertyToUpdate]: data });
} else {
console.warn(`Dapp with address ${dapp.chain.address} not found in the store.`);
console.warn(`Dapp with address ${dappAddress} not found in the store.`);
}
};

Expand All @@ -54,26 +60,13 @@ const mutations: MutationTree<DappStakingState> & DappStakingMutations = {
state.dapps.push(dapp);
},
updateDappExtended(state, dapp) {
const dappToUpdate = state.dapps.find((x) => x.basic.address === dapp.address);

if (dappToUpdate) {
const index = state.dapps.indexOf(dappToUpdate);
state.dapps.splice(index, 1, { ...dappToUpdate, extended: dapp });
} else {
console.warn(`Dapp with address ${dapp.address} not found in the store.`);
}
updateDapp(state, dapp.address, dapp, 'extended');
},
updateDappChain(state: DappStakingState, dapp: DappInfo): void {
const dappToUpdate = state.dapps.find(
(x) => x.basic.address.toLowerCase() === dapp.address.toLowerCase()
);

if (dappToUpdate) {
const index = state.dapps.indexOf(dappToUpdate);
state.dapps.splice(index, 1, { ...dappToUpdate, chain: dapp });
} else {
console.warn(`Dapp with address ${dapp.address} not found in the store.`);
}
updateDapp(state, dapp.address, dapp, 'chain');
},
updateDappDetails(state: DappStakingState, dapp: ProviderDappData): void {
updateDapp(state, dapp.contractAddress, dapp, 'dappDetails');
},
setProtocolState(state, protocolState) {
state.protocolState = protocolState;
Expand Down
5 changes: 5 additions & 0 deletions src/v2/app.container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import { xcmToken, XcmTokenInformation } from 'src/modules/xcm';
import { XvmRepository } from 'src/v2/repositories/implementations/XvmRepository';
import { XvmService } from 'src/v2/services/implementations/XvmService';
import { IdentityRepository } from './repositories/implementations/IdentityRepository';
import { IDataProviderRepository, TokenApiProviderRepository } from '../staking-v3/logic';

let currentWalletType = WalletType.Polkadot;
let currentWalletName = '';
Expand Down Expand Up @@ -198,6 +199,10 @@ export default function buildDependencyContainer(network: endpointKey): void {
DappStakingRepositoryV3,
Symbols.DappStakingRepositoryV3
);
container.addSingleton<IDataProviderRepository>(
TokenApiProviderRepository,
Symbols.TokenApiProviderRepository
);
container.addSingleton<IDappStakingServiceV3>(DappStakingServiceV3, Symbols.DappStakingServiceV3);
container.addSingleton<IDappStakingServiceV3>(
DappStakingServiceEvmV3,
Expand Down
1 change: 1 addition & 0 deletions src/v2/symbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ export const Symbols = {
DappStakingServiceV3: Symbol.for('DappStakingServiceV3'),
DappStakingServiceEvmV3: Symbol.for('DappStakingServiceEvmV3'),
DappStakingServiceFactoryV3: Symbol.for('DappStakingServiceFactoryV3'),
TokenApiProviderRepository: Symbol.for('TokenApiProviderRepository'),
};

0 comments on commit 2c4ec83

Please sign in to comment.