Skip to content

Commit

Permalink
Merge pull request #301 from input-output-hk/refactor/remodel-network…
Browse files Browse the repository at this point in the history
…info-provider-to-remove-networkinfo

refactor: Remodel NetworkInfoProvider to remove NetworkInfo
  • Loading branch information
rhyslbw committed Jun 29, 2022
2 parents fbe855e + d63d3fb commit ec593cf
Show file tree
Hide file tree
Showing 33 changed files with 617 additions and 373 deletions.
35 changes: 17 additions & 18 deletions packages/blockfrost/src/blockfrostNetworkInfoProvider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BlockFrostAPI } from '@blockfrost/blockfrost-js';
import { BlockfrostToCore } from './BlockfrostToCore';
import { Cardano, NetworkInfoProvider, ProviderError, ProviderFailure, testnetTimeSettings } from '@cardano-sdk/core';
import { NetworkInfoProvider, ProviderError, ProviderFailure } from '@cardano-sdk/core';
import { networkMagicToIdMap, timeSettings } from './util';

/**
* Connect to the [Blockfrost service](https://docs.blockfrost.io/)
Expand All @@ -13,23 +14,20 @@ export const blockfrostNetworkInfoProvider = (blockfrost: BlockFrostAPI): Networ
if (!blockfrost.apiUrl.includes('testnet')) {
throw new ProviderError(ProviderFailure.NotImplemented);
}
const networkInfo: NetworkInfoProvider['networkInfo'] = async () => {
const { stake, supply } = await blockfrost.network();

const stake: NetworkInfoProvider['stake'] = async () => {
const network = await blockfrost.network();
return {
active: BigInt(network.stake.active),
live: BigInt(network.stake.live)
};
};

const lovelaceSupply: NetworkInfoProvider['lovelaceSupply'] = async () => {
const { supply } = await blockfrost.network();
return {
lovelaceSupply: {
circulating: BigInt(supply.circulating),
max: BigInt(supply.max),
total: BigInt(supply.total)
},
network: {
id: Cardano.NetworkId.testnet,
magic: 1_097_911_063,
timeSettings: testnetTimeSettings
},
stake: {
active: BigInt(stake.active),
live: BigInt(stake.live)
}
circulating: BigInt(supply.circulating),
total: BigInt(supply.total)
};
};

Expand All @@ -53,6 +51,7 @@ export const blockfrostNetworkInfoProvider = (blockfrost: BlockFrostAPI): Networ
epochLength: response.epoch_length,
maxKesEvolutions: response.max_kes_evolutions,
maxLovelaceSupply: BigInt(response.max_lovelace_supply),
networkId: networkMagicToIdMap[response.network_magic],
networkMagic: response.network_magic,
securityParameter: response.security_param,
slotLength: response.slot_length,
Expand All @@ -62,5 +61,5 @@ export const blockfrostNetworkInfoProvider = (blockfrost: BlockFrostAPI): Networ
};
};

return { currentWalletProtocolParameters, genesisParameters, ledgerTip, networkInfo };
return { currentWalletProtocolParameters, genesisParameters, ledgerTip, lovelaceSupply, stake, timeSettings };
};
17 changes: 16 additions & 1 deletion packages/blockfrost/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Error as BlockfrostError } from '@blockfrost/blockfrost-js';
import { Cardano, InvalidStringError, ProviderError, ProviderFailure, ProviderUtil } from '@cardano-sdk/core';
import {
Cardano,
InvalidStringError,
NetworkInfoProvider,
ProviderError,
ProviderFailure,
ProviderUtil,
testnetTimeSettings
} from '@cardano-sdk/core';
import { PaginationOptions } from '@blockfrost/blockfrost-js/lib/types';

export const formatBlockfrostError = (error: unknown) => {
Expand Down Expand Up @@ -118,3 +126,10 @@ export const fetchByAddressSequentially = async <Item, Response>(props: {
? (response, arg) => props.responseTranslator!(arg, response)
: undefined
});

export const networkMagicToIdMap: { [key in number]: Cardano.NetworkId } = {
[Cardano.CardanoNetworkMagic.Mainnet]: Cardano.NetworkId.mainnet,
[Cardano.CardanoNetworkMagic.Testnet]: Cardano.NetworkId.testnet
};

export const timeSettings: NetworkInfoProvider['timeSettings'] = async () => testnetTimeSettings;
79 changes: 45 additions & 34 deletions packages/blockfrost/test/blockfrostNetworkInfoProvider.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable max-len */
import { BlockFrostAPI, Responses } from '@blockfrost/blockfrost-js';
import { Cardano, NetworkInfo, testnetTimeSettings } from '@cardano-sdk/core';
import { Cardano, StakeSummary, SupplySummary, TimeSettings, testnetTimeSettings } from '@cardano-sdk/core';
import { blockfrostNetworkInfoProvider } from '../src';

jest.mock('@blockfrost/blockfrost-js');
Expand All @@ -24,48 +24,59 @@ const blockResponse = {
tx_count: 3
} as Responses['block_content'];

const mockedNetworkResponse = {
stake: {
active: '1060378314781343',
live: '15001884895856815'
},
supply: {
circulating: '42064399450423723',
locked: '6161981104458',
max: '45000000000000000',
total: '40267211394073980'
}
} as Responses['network'];

const apiKey = 'someapikey';
const apiUrl = 'http://testnet.endpoint';

describe('blockfrostNetworkInfoProvider', () => {
const apiKey = 'someapikey';

test('networkInfo', async () => {
const mockedNetworkResponse = {
stake: {
active: '1060378314781343',
live: '15001884895856815'
},
supply: {
circulating: '42064399450423723',
locked: '6161981104458',
max: '45000000000000000',
total: '40267211394073980'
}
} as Responses['network'];
test('stake', async () => {
BlockFrostAPI.prototype.network = jest.fn().mockResolvedValue(mockedNetworkResponse);
BlockFrostAPI.prototype.apiUrl = apiUrl;

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostNetworkInfoProvider(blockfrost);
const response = await client.stake();

expect(response).toMatchObject<StakeSummary>({
active: 1_060_378_314_781_343n,
live: 15_001_884_895_856_815n
});
});

test('lovelaceSupply', async () => {
BlockFrostAPI.prototype.network = jest.fn().mockResolvedValue(mockedNetworkResponse);
BlockFrostAPI.prototype.apiUrl = 'http://testnet.endpoint';
BlockFrostAPI.prototype.apiUrl = apiUrl;

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostNetworkInfoProvider(blockfrost);
const response = await client.networkInfo();

expect(response).toMatchObject<NetworkInfo>({
lovelaceSupply: {
circulating: 42_064_399_450_423_723n,
max: 45_000_000_000_000_000n,
total: 40_267_211_394_073_980n
},
network: {
id: Cardano.NetworkId.testnet,
magic: 1_097_911_063,
timeSettings: testnetTimeSettings
},
stake: {
active: 1_060_378_314_781_343n,
live: 15_001_884_895_856_815n
}
const response = await client.lovelaceSupply();

expect(response).toMatchObject<SupplySummary>({
circulating: 42_064_399_450_423_723n,
total: 40_267_211_394_073_980n
});
});

test('timeSettings', async () => {
const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostNetworkInfoProvider(blockfrost);
const response = await client.timeSettings();

expect(response).toMatchObject<TimeSettings[]>(testnetTimeSettings);
});

test('genesisParameters', async () => {
const mockedResponse = {
active_slots_coefficient: 0.05,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ export const defaultNetworkInfoProviderPaths: HttpProviderConfigPaths<NetworkInf
currentWalletProtocolParameters: '/current-wallet-protocol-parameters',
genesisParameters: '/genesis-parameters',
ledgerTip: '/ledger-tip',
networkInfo: '/network'
lovelaceSupply: '/lovelace-supply',
stake: '/stake',
timeSettings: '/time-settings'
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,22 @@ describe('networkInfoHttpProvider', () => {
axiosMock.restore();
});

test('networkInfo does not throw', async () => {
test('stake does not throw', async () => {
axiosMock.onPost().replyOnce(200, {});
const provider = networkInfoHttpProvider(url);
await expect(provider.networkInfo()).resolves.toEqual({});
await expect(provider.stake()).resolves.toEqual({});
});

test('lovelace does not throw', async () => {
axiosMock.onPost().replyOnce(200, {});
const provider = networkInfoHttpProvider(url);
await expect(provider.lovelaceSupply()).resolves.toEqual({});
});

test('timeSettings does not throw', async () => {
axiosMock.onPost().replyOnce(200, {});
const provider = networkInfoHttpProvider(url);
await expect(provider.timeSettings()).resolves.toEqual({});
});

test('ledgerTip does not throw', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {
Cardano,
NetworkInfo,
NetworkInfoProvider,
ProtocolParametersRequiredByWallet,
StakeSummary,
SupplySummary,
TimeSettings,
timeSettingsConfig
} from '@cardano-sdk/core';
import { DbSyncProvider } from '../../DbSyncProvider';
Expand All @@ -13,7 +15,7 @@ import { NetworkInfoBuilder } from './NetworkInfoBuilder';
import { NetworkInfoCacheKey } from '.';
import { Pool } from 'pg';
import { Shutdown } from '@cardano-sdk/util';
import { loadGenesisData, toGenesisParams, toLedgerTip, toNetworkInfo, toWalletProtocolParams } from './mappers';
import { loadGenesisData, toGenesisParams, toLedgerTip, toStake, toSupply, toWalletProtocolParams } from './mappers';
import { pollDbSync } from './utils';

export interface NetworkInfoProviderProps {
Expand Down Expand Up @@ -45,48 +47,53 @@ export class DbSyncNetworkInfoProvider extends DbSyncProvider implements Network
this.#dbPollInterval = dbPollInterval;
}

public async networkInfo(): Promise<NetworkInfo> {
const { networkMagic, networkId, maxLovelaceSupply } = await this.#genesisDataReady;
const timeSettings = timeSettingsConfig[networkMagic];
public async ledgerTip(): Promise<Cardano.Tip> {
const tip = await this.#builder.queryLedgerTip();
return toLedgerTip(tip);
}

public async currentWalletProtocolParameters(): Promise<ProtocolParametersRequiredByWallet> {
const currentProtocolParams = await this.#builder.queryCurrentWalletProtocolParams();
return toWalletProtocolParams(currentProtocolParams);
}

public async genesisParameters(): Promise<Cardano.CompactGenesis> {
const genesisData = await this.#genesisDataReady;
return toGenesisParams(genesisData);
}

this.#logger.debug('About to query network info data');
public async lovelaceSupply(): Promise<SupplySummary> {
const { maxLovelaceSupply } = await this.#genesisDataReady;

const [liveStake, circulatingSupply, activeStake, totalSupply] = await Promise.all([
this.#cache.get(NetworkInfoCacheKey.LIVE_STAKE, () => this.#builder.queryLiveStake()),
const [circulatingSupply, totalSupply] = await Promise.all([
this.#cache.get(NetworkInfoCacheKey.CIRCULATING_SUPPLY, () => this.#builder.queryCirculatingSupply()),
this.#cache.get(NetworkInfoCacheKey.ACTIVE_STAKE, () => this.#builder.queryActiveStake(), UNLIMITED_CACHE_TTL),
this.#cache.get(
NetworkInfoCacheKey.TOTAL_SUPPLY,
() => this.#builder.queryTotalSupply(maxLovelaceSupply),
UNLIMITED_CACHE_TTL
)
]);

return toNetworkInfo({
activeStake,
circulatingSupply,
liveStake,
maxLovelaceSupply,
networkId,
networkMagic,
timeSettings,
totalSupply
});
return toSupply({ circulatingSupply, totalSupply });
}

public async ledgerTip(): Promise<Cardano.Tip> {
const tip = await this.#builder.queryLedgerTip();
return toLedgerTip(tip);
}
public async stake(): Promise<StakeSummary> {
this.#logger.debug('About to query stake data');

public async currentWalletProtocolParameters(): Promise<ProtocolParametersRequiredByWallet> {
const currentProtocolParams = await this.#builder.queryCurrentWalletProtocolParams();
return toWalletProtocolParams(currentProtocolParams);
const [liveStake, activeStake] = await Promise.all([
this.#cache.get(NetworkInfoCacheKey.LIVE_STAKE, () => this.#builder.queryLiveStake()),
this.#cache.get(NetworkInfoCacheKey.ACTIVE_STAKE, () => this.#builder.queryActiveStake(), UNLIMITED_CACHE_TTL)
]);

return toStake({
activeStake,
liveStake
});
}

public async genesisParameters(): Promise<Cardano.CompactGenesis> {
const genesisData = await this.#genesisDataReady;
return toGenesisParams(genesisData);
public async timeSettings(): Promise<TimeSettings[]> {
const { networkMagic } = await this.#genesisDataReady;
return timeSettingsConfig[networkMagic];
}

async start(): Promise<void> {
Expand Down

0 comments on commit ec593cf

Please sign in to comment.