Skip to content

Commit

Permalink
Merge pull request #2092 from hirosystems/fix/stx-supply
Browse files Browse the repository at this point in the history
fix: use current circulating STX tokens for `stx_supply` endpoint
  • Loading branch information
zone117x authored Sep 27, 2024
2 parents ad4e1ca + 689ff18 commit 58cd8b2
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 25 deletions.
47 changes: 36 additions & 11 deletions src/api/routes/stx-supply.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import BigNumber from 'bignumber.js';
import { microStxToStx, STACKS_DECIMAL_PLACES, TOTAL_STACKS } from '../../helpers';
import { microStxToStx, STACKS_DECIMAL_PLACES, TOTAL_STACKS_YEAR_2050 } from '../../helpers';
import { handleChainTipCache } from '../controllers/cache-controller';

import { FastifyPluginAsync } from 'fastify';
Expand All @@ -23,18 +23,23 @@ export const StxSupplyRoutes: FastifyPluginAsync<
): Promise<{
unlockedPercent: string;
totalStx: string;
totalStxYear2050: string;
unlockedStx: string;
blockHeight: number;
}> {
const { stx: unlockedSupply, blockHeight } = await fastify.db.getUnlockedStxSupply(args);
const totalMicroStx = new BigNumber(TOTAL_STACKS).shiftedBy(STACKS_DECIMAL_PLACES);
const totalMicroStx = unlockedSupply;
const totalMicroStxYear2050 = new BigNumber(TOTAL_STACKS_YEAR_2050).shiftedBy(
STACKS_DECIMAL_PLACES
);
const unlockedPercent = new BigNumber(unlockedSupply.toString())
.div(totalMicroStx)
.div(new BigNumber(totalMicroStx.toString()))
.times(100)
.toFixed(2);
return {
unlockedPercent,
totalStx: microStxToStx(totalMicroStx),
totalStxYear2050: microStxToStx(totalMicroStxYear2050),
unlockedStx: microStxToStx(unlockedSupply),
blockHeight: blockHeight,
};
Expand All @@ -47,8 +52,7 @@ export const StxSupplyRoutes: FastifyPluginAsync<
schema: {
operationId: 'get_stx_supply',
summary: 'Get total and unlocked STX supply',
description: `Retrieves the total and unlocked STX supply. More information on Stacking can be found [here] (https://docs.stacks.co/understand-stacks/stacking).
**Note:** This uses the estimated future total supply for the year 2050.`,
description: `Retrieves the total and unlocked STX supply. More information on Stacking can be found [here] (https://docs.stacks.co/understand-stacks/stacking).`,
tags: ['Info'],
querystring: Type.Object({
height: Type.Optional(
Expand All @@ -70,7 +74,12 @@ export const StxSupplyRoutes: FastifyPluginAsync<
'String quoted decimal number of the percentage of STX that have unlocked',
}),
total_stx: Type.String({
description: 'String quoted decimal number of the total possible number of STX',
description:
'String quoted decimal number of the total circulating number of STX (at the input block height if provided, otherwise the current block height)',
}),
total_stx_year_2050: Type.String({
description:
'String quoted decimal number of total circulating STX supply in year 2050. STX supply grows approx 0.3% annually thereafter in perpetuity.',
}),
unlocked_stx: Type.String({
description:
Expand Down Expand Up @@ -98,6 +107,7 @@ export const StxSupplyRoutes: FastifyPluginAsync<
await reply.send({
unlocked_percent: supply.unlockedPercent,
total_stx: supply.totalStx,
total_stx_year_2050: supply.totalStxYear2050,
unlocked_stx: supply.unlockedStx,
block_height: supply.blockHeight,
});
Expand All @@ -109,10 +119,10 @@ export const StxSupplyRoutes: FastifyPluginAsync<
{
preHandler: handleChainTipCache,
schema: {
deprecated: true,
operationId: 'get_stx_supply_total_supply_plain',
summary: 'Get total STX supply in plain text format',
description: `Retrieves the total supply for STX tokens as plain text.
**Note:** this uses the estimated future total supply for the year 2050.`,
description: `Retrieves the total circulating STX token supply as plain text.`,
tags: ['Info'],
response: {
200: {
Expand All @@ -136,6 +146,7 @@ export const StxSupplyRoutes: FastifyPluginAsync<
{
preHandler: handleChainTipCache,
schema: {
deprecated: true,
operationId: 'get_stx_supply_circulating_plain',
summary: 'Get circulating STX supply in plain text format',
description: `Retrieves the STX tokens currently in circulation that have been unlocked as plain text.`,
Expand All @@ -162,11 +173,11 @@ export const StxSupplyRoutes: FastifyPluginAsync<
{
preHandler: handleChainTipCache,
schema: {
deprecated: true,
operationId: 'get_total_stx_supply_legacy_format',
summary:
'Get total and unlocked STX supply (results formatted the same as the legacy 1.0 API)',
description: `Retrieves total supply of STX tokens including those currently in circulation that have been unlocked.
**Note:** this uses the estimated future total supply for the year 2050.`,
description: `Retrieves total supply of STX tokens including those currently in circulation that have been unlocked.`,
tags: ['Info'],
querystring: Type.Object({
height: Type.Optional(
Expand All @@ -188,11 +199,20 @@ export const StxSupplyRoutes: FastifyPluginAsync<
'String quoted decimal number of the percentage of STX that have unlocked',
}),
totalStacks: Type.String({
description: 'String quoted decimal number of the total possible number of STX',
description:
'String quoted decimal number of the total circulating number of STX (at the input block height if provided, otherwise the current block height)',
}),
totalStacksFormatted: Type.String({
description: 'Same as `totalStacks` but formatted with comma thousands separators',
}),
totalStacksYear2050: Type.String({
description:
'String quoted decimal number of total circulating STX supply in year 2050. STX supply grows approx 0.3% annually thereafter in perpetuity.',
}),
totalStacksYear2050Formatted: Type.String({
description:
'Same as `totalStacksYear2050` but formatted with comma thousands separators',
}),
unlockedSupply: Type.String({
description:
'String quoted decimal number of the STX that have been mined or unlocked',
Expand Down Expand Up @@ -224,6 +244,11 @@ export const StxSupplyRoutes: FastifyPluginAsync<
unlockedPercent: supply.unlockedPercent,
totalStacks: supply.totalStx,
totalStacksFormatted: new BigNumber(supply.totalStx).toFormat(STACKS_DECIMAL_PLACES, 8),
totalStacksYear2050: supply.totalStxYear2050,
totalStacksYear2050Formatted: new BigNumber(supply.totalStxYear2050).toFormat(
STACKS_DECIMAL_PLACES,
8
),
unlockedSupply: supply.unlockedStx,
unlockedSupplyFormatted: new BigNumber(supply.unlockedStx).toFormat(
STACKS_DECIMAL_PLACES,
Expand Down
4 changes: 3 additions & 1 deletion src/api/routes/ws/channels/socket-io-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ export class SocketIOChannel extends WebSocketChannel {
if (!this.io && callback) {
callback();
}
this.io?.close(callback);
this.io?.close(callback).catch(err => {
logger.error(err, `Error closing socket.io`);
});
this.io = undefined;
}

Expand Down
2 changes: 1 addition & 1 deletion src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export function formatMapToObject<TKey extends string, TValue, TFormatted>(
// > 500 STX/block for following 4 yrs;
// > 250 for the 4 yrs after that; and then 125 STX/block in perpetuity after that.
// We are going to use the year 2050 projected supply because "125 STX/block in perpetuity" means the total supply is infinite.
export const TOTAL_STACKS = new BigNumber(1_818_000_000n.toString());
export const TOTAL_STACKS_YEAR_2050 = new BigNumber(1_818_000_000n.toString());

const MICROSTACKS_IN_STACKS = 1_000_000n;
export const STACKS_DECIMAL_PLACES = 6;
Expand Down
32 changes: 20 additions & 12 deletions src/tests/other-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,13 @@ describe('other tests', () => {
expect(result1.status).toBe(200);
expect(result1.type).toBe('application/json');
const expectedResp1 = {
unlocked_percent: '12.93',
total_stx: '1818000000.000000',
unlocked_stx: microStxToStx(expectedTotalStx1),
block_height: dbBlock1.block_height,
unlocked_percent: '100.00',
total_stx: '235000000.000000',
total_stx_year_2050: '1818000000.000000',
unlocked_stx: '235000000.000000',
block_height: 1,
};

expect(JSON.parse(result1.text)).toEqual(expectedResp1);

// ensure burned STX reduce the unlocked stx supply
Expand All @@ -166,9 +168,10 @@ describe('other tests', () => {
expect(result2.status).toBe(200);
expect(result2.type).toBe('application/json');
const expectedResp2 = {
unlocked_percent: '12.38',
total_stx: '1818000000.000000',
unlocked_percent: '100.00',
total_stx: microStxToStx(expectedTotalStx2),
unlocked_stx: microStxToStx(expectedTotalStx2),
total_stx_year_2050: '1818000000.000000',
block_height: dbBlock1.block_height,
};
expect(JSON.parse(result2.text)).toEqual(expectedResp2);
Expand Down Expand Up @@ -197,8 +200,9 @@ describe('other tests', () => {
expect(result3.status).toBe(200);
expect(result3.type).toBe('application/json');
const expectedResp3 = {
unlocked_percent: '13.20',
total_stx: '1818000000.000000',
unlocked_percent: '100.00',
total_stx: microStxToStx(expectedTotalStx3),
total_stx_year_2050: '1818000000.000000',
unlocked_stx: microStxToStx(expectedTotalStx3),
block_height: dbBlock1.block_height,
};
Expand All @@ -207,7 +211,7 @@ describe('other tests', () => {
const result4 = await supertest(api.server).get(`/extended/v1/stx_supply/total/plain`);
expect(result4.status).toBe(200);
expect(result4.type).toBe('text/plain');
expect(result4.text).toEqual('1818000000.000000');
expect(result4.text).toEqual('240000000.000000');

const result5 = await supertest(api.server).get(`/extended/v1/stx_supply/circulating/plain`);
expect(result5.status).toBe(200);
Expand All @@ -219,13 +223,17 @@ describe('other tests', () => {
expect(result6.status).toBe(200);
expect(result6.type).toBe('application/json');
const expectedResp6 = {
unlockedPercent: '13.20',
totalStacks: '1818000000.000000',
totalStacksFormatted: '1,818,000,000.000000',
unlockedPercent: '100.00',
totalStacks: microStxToStx(expectedTotalStx3),
totalStacksFormatted: new Intl.NumberFormat('en', {
minimumFractionDigits: STACKS_DECIMAL_PLACES,
}).format(parseInt(microStxToStx(expectedTotalStx3))),
unlockedSupply: microStxToStx(expectedTotalStx3),
unlockedSupplyFormatted: new Intl.NumberFormat('en', {
minimumFractionDigits: STACKS_DECIMAL_PLACES,
}).format(parseInt(microStxToStx(expectedTotalStx3))),
totalStacksYear2050: '1818000000.000000',
totalStacksYear2050Formatted: '1,818,000,000.000000',
blockHeight: dbBlock1.block_height.toString(),
};
expect(JSON.parse(result6.text)).toEqual(expectedResp6);
Expand Down

0 comments on commit 58cd8b2

Please sign in to comment.