Skip to content

Commit

Permalink
Total token issuance history endpoint (#165)
Browse files Browse the repository at this point in the history
* Total issuance history endpoint

* Result type
  • Loading branch information
bobo-k2 authored Nov 27, 2024
1 parent 37aab89 commit 53b9c2d
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 11 deletions.
21 changes: 21 additions & 0 deletions public/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,27 @@
}
}
},
"/api/v1/{network}/token/supply-history/": {
"get": {
"tags": [
"Token"
],
"description": "Retreives total supply history at the beginning of a new dApp staking era for a given network and period.",
"parameters": [
{
"name": "network",
"in": "path",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/api/v1/{network}/dapps-staking/apr": {
"get": {
"tags": [
Expand Down
17 changes: 17 additions & 0 deletions src/controllers/TokenStatsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,22 @@ export class TokenStatsController extends ControllerBase implements IControllerB
*/
res.json(await this._indexerService.getHolders(req.params.network as NetworkType));
});

/**
* @description Total issuance history.
*/
app.route('/api/v1/:network/token/supply-history/').get(async (req: Request, res: Response) => {
/*
#swagger.description = 'Retreives total supply history at the beginning of a new dApp staking era for a given network and period.'
#swagger.tags = ['Token']
#swagger.parameters['network'] = {
in: 'path',
description: 'The network name. Supported networks: astar, shiden, shibuya'
required: true,
enum: ['astar', 'shiden', 'shibuya']
}
*/
res.json(await this._statsService.getTotalIssuanceHistory(req.params.network as NetworkType));
});
}
}
2 changes: 1 addition & 1 deletion src/services/DappStakingV3IndexerBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export class DappStakingV3IndexerBase extends ServiceBase {

protected getApiUrl(network: NetworkType): string {
// For local development: `http://localhost:4350/graphql`;
return `https://astar-network.squids.live/dapps-staking-indexer-${network}/v/v14/graphql`;
return `https://astar-network.squids.live/dapps-staking-indexer-${network}/v/v15/graphql`;
}
}
52 changes: 42 additions & 10 deletions src/services/StatsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,29 @@ import { NetworkType } from '../networks';
import { addressesToExclude } from './AddressesToExclude';
import { AccountData } from '../models/AccountData';
import { Guard } from '../guard';
import { DappStakingV3IndexerBase } from './DappStakingV3IndexerBase';
import axios from 'axios';

export type TotalSupply = {
block: number;
timestamp: number;
balance: bigint;
};

export interface IStatsService {
getTokenStats(network: NetworkType): Promise<TokenStats>;
getTotalSupply(network: NetworkType): Promise<number>;
getTotalIssuanceHistory(network: NetworkType): Promise<TotalSupply[]>;
}

@injectable()
/**
* Token statistics calculation service.
*/
export class StatsService implements IStatsService {
constructor(@inject(ContainerTypes.ApiFactory) private _apiFactory: IApiFactory) {}
export class StatsService extends DappStakingV3IndexerBase implements IStatsService {
constructor(@inject(ContainerTypes.ApiFactory) private _apiFactory: IApiFactory) {
super();
}

/**
* Calculates token circulation supply by substracting sum of all token holder accounts
Expand All @@ -29,7 +40,7 @@ export class StatsService implements IStatsService {
*/
public async getTokenStats(network: NetworkType): Promise<TokenStats> {
Guard.ThrowIfUndefined(network, 'network');
this.throwIfNetworkIsNotSupported(network);
this.GuardNetwork(network);

try {
const api = this._apiFactory.getApiInstance(network);
Expand All @@ -53,7 +64,7 @@ export class StatsService implements IStatsService {

public async getTotalSupply(network: NetworkType): Promise<number> {
Guard.ThrowIfUndefined(network, 'network');
this.throwIfNetworkIsNotSupported(network);
this.GuardNetwork(network);

try {
const api = this._apiFactory.getApiInstance(network);
Expand All @@ -67,6 +78,33 @@ export class StatsService implements IStatsService {
}
}

public async getTotalIssuanceHistory(network: NetworkType): Promise<TotalSupply[]> {
this.GuardNetwork(network);

try {
const result = await axios.post(this.getApiUrl(network), {
query: `query {
totalIssuances(orderBy: id_ASC) {
id
timestamp
balance
}
}`,
});

return result.data.data.totalIssuances.map((item: { id: string; timestamp: string; balance: string }) => {
return {
block: Number(item.id),
timestamp: Number(item.timestamp),
balance: BigInt(item.balance),
};
});
} catch (e) {
console.error(e);
return [];
}
}

private getTotalBalanceToExclude(balances: AccountData[]): BN {
const sum = balances
.map((balance) => {
Expand All @@ -82,10 +120,4 @@ export class StatsService implements IStatsService {

return parseInt(result.replaceAll(',', ''));
}

private throwIfNetworkIsNotSupported(network: NetworkType): void {
if (network !== 'astar' && network !== 'shiden' && network !== 'shibuya' && network !== 'rocstar') {
throw new Error(`Network ${network} is not supported.`);
}
}
}

0 comments on commit 53b9c2d

Please sign in to comment.