Skip to content

Commit 2bf86df

Browse files
committed
feat: browser compatible BlockfrostNetworkInfoProvider
1 parent 800b2c1 commit 2bf86df

File tree

7 files changed

+56
-153
lines changed

7 files changed

+56
-153
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { BlockfrostProvider } from '../../util/BlockfrostProvider/BlockfrostProvider';
2-
import { BlockfrostToCore, blockfrostToProviderError } from '../../util';
1+
import { BlockfrostClient } from '../blockfrost/BlockfrostClient';
2+
import { BlockfrostProvider } from '../blockfrost/BlockfrostProvider';
3+
import { BlockfrostToCore } from '../blockfrost';
34
import {
45
Cardano,
56
EraSummary,
@@ -9,55 +10,59 @@ import {
910
StakeSummary,
1011
SupplySummary
1112
} from '@cardano-sdk/core';
13+
import { Logger } from 'ts-log';
14+
import { Responses } from '@blockfrost/blockfrost-js';
1215
import { Schemas } from '@blockfrost/blockfrost-js/lib/types/open-api';
13-
import { handleError } from '@blockfrost/blockfrost-js/lib/utils/errors';
1416

1517
export class BlockfrostNetworkInfoProvider extends BlockfrostProvider implements NetworkInfoProvider {
18+
constructor(client: BlockfrostClient, logger: Logger) {
19+
super(client, logger);
20+
}
21+
1622
public async stake(): Promise<StakeSummary> {
1723
try {
18-
const network = await this.blockfrost.network();
24+
const { stake } = await this.request<Responses['network']>('network');
1925
return {
20-
active: BigInt(network.stake.active),
21-
live: BigInt(network.stake.live)
26+
active: BigInt(stake.active),
27+
live: BigInt(stake.live)
2228
};
2329
} catch (error) {
24-
throw blockfrostToProviderError(error);
30+
throw this.toProviderError(error);
2531
}
2632
}
2733

2834
public async lovelaceSupply(): Promise<SupplySummary> {
2935
try {
30-
const { supply } = await this.blockfrost.network();
36+
const { supply } = await this.request<Responses['network']>('network');
3137
return {
3238
circulating: BigInt(supply.circulating),
3339
total: BigInt(supply.total)
3440
};
3541
} catch (error) {
36-
throw blockfrostToProviderError(error);
42+
throw this.toProviderError(error);
3743
}
3844
}
3945

4046
public async ledgerTip(): Promise<Cardano.Tip> {
4147
try {
42-
const block = await this.blockfrost.blocksLatest();
48+
const block = await this.request<Responses['block_content']>('blocks/latest');
4349
return BlockfrostToCore.blockToTip(block);
4450
} catch (error) {
45-
throw blockfrostToProviderError(error);
51+
throw this.toProviderError(error);
4652
}
4753
}
4854

4955
public async protocolParameters(): Promise<Cardano.ProtocolParameters> {
5056
try {
51-
const response = await this.blockfrost.epochsLatestParameters();
57+
const response = await this.request<Responses['epoch_param_content']>('epochs/latest/parameters');
5258
return BlockfrostToCore.protocolParameters(response);
5359
} catch (error) {
54-
throw blockfrostToProviderError(error);
60+
throw this.toProviderError(error);
5561
}
5662
}
5763

5864
public async genesisParameters(): Promise<Cardano.CompactGenesis> {
59-
return this.blockfrost
60-
.genesis()
65+
return this.request<Responses['genesis_content']>('genesis')
6166
.then((response) => ({
6267
activeSlotsCoefficient: response.active_slots_coefficient,
6368
epochLength: response.epoch_length,
@@ -75,18 +80,15 @@ export class BlockfrostNetworkInfoProvider extends BlockfrostProvider implements
7580
updateQuorum: response.update_quorum
7681
}))
7782
.catch((error) => {
78-
throw blockfrostToProviderError(error);
83+
throw this.toProviderError(error);
7984
});
8085
}
8186

8287
protected async fetchEraSummaries(): Promise<Schemas['network-eras']> {
8388
try {
84-
// Although Blockfrost have the endpoint, the blockfrost-js library don't have a call for it
85-
// https://github.com/blockfrost/blockfrost-js/issues/294
86-
const response = await this.blockfrost.instance<Schemas['network-eras']>('network/eras');
87-
return response.body;
89+
return await this.request<Responses['network-eras']>('network/eras');
8890
} catch (error) {
89-
throw handleError(error);
91+
throw this.toProviderError(error);
9092
}
9193
}
9294

@@ -103,7 +105,7 @@ export class BlockfrostNetworkInfoProvider extends BlockfrostProvider implements
103105
}
104106
}));
105107
} catch (error) {
106-
throw handleError(error);
108+
throw this.toProviderError(error);
107109
}
108110
}
109111

@@ -113,7 +115,7 @@ export class BlockfrostNetworkInfoProvider extends BlockfrostProvider implements
113115
const summaries = await this.fetchEraSummaries();
114116
return this.parseEraSummaries(summaries, systemStart);
115117
} catch (error) {
116-
throw blockfrostToProviderError(error);
118+
throw this.toProviderError(error);
117119
}
118120
}
119121
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
export * from './BlockfrostNetworkInfoProvider';
12
export * from './networkInfoHttpProvider';
Lines changed: 19 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
2-
/* eslint-disable max-len */
3-
import { BlockFrostAPI, Responses } from '@blockfrost/blockfrost-js';
4-
import { BlockfrostNetworkInfoProvider } from '../../../src';
1+
import { BlockfrostClient, BlockfrostNetworkInfoProvider } from '../../src';
52
import { Cardano, EraSummary, Milliseconds, StakeSummary, SupplySummary } from '@cardano-sdk/core';
3+
import { Responses } from '@blockfrost/blockfrost-js';
64
import { logger } from '@cardano-sdk/util-dev';
5+
import { mockResponses } from '../AssetInfoProvider/util';
76

87
jest.mock('@blockfrost/blockfrost-js');
98

@@ -38,74 +37,36 @@ const mockedNetworkResponse = {
3837
}
3938
} as Responses['network'];
4039

41-
const mockedError = {
42-
error: 'Forbidden',
43-
message: 'Invalid project token.',
44-
status_code: 403,
45-
url: 'test'
46-
};
40+
describe('BlockfrostNetworkInfoProvider', () => {
41+
let request: jest.Mock;
42+
let provider: BlockfrostNetworkInfoProvider;
4743

48-
const mockedErrorMethod = jest.fn().mockRejectedValue(mockedError);
49-
// const mockedProviderError = new ProviderError(ProviderFailure.Unknown, {}, 'testing');
50-
const apiKey = 'someapikey';
51-
const apiUrl = 'http://testnet.endpoint';
52-
53-
describe('blockfrostNetworkInfoProvider', () => {
5444
beforeEach(async () => {
55-
mockedErrorMethod.mockClear();
45+
request = jest.fn();
46+
const client = { request } as unknown as BlockfrostClient;
47+
provider = new BlockfrostNetworkInfoProvider(client, logger);
5648
});
57-
test('stake', async () => {
58-
BlockFrostAPI.prototype.network = jest.fn().mockResolvedValue(mockedNetworkResponse);
59-
BlockFrostAPI.prototype.apiUrl = apiUrl;
6049

61-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
62-
const client = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
63-
const response = await client.stake();
50+
test('stake', async () => {
51+
mockResponses(request, [['network', mockedNetworkResponse]]);
52+
const response = await provider.stake();
6453

6554
expect(response).toMatchObject<StakeSummary>({
6655
active: 1_060_378_314_781_343n,
6756
live: 15_001_884_895_856_815n
6857
});
6958
});
7059

71-
test('stake throws', async () => {
72-
BlockFrostAPI.prototype.network = mockedErrorMethod;
73-
74-
BlockFrostAPI.prototype.apiUrl = apiUrl;
75-
76-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
77-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
78-
79-
await expect(() => provider.stake()).rejects.toThrow();
80-
expect(mockedErrorMethod).toBeCalledTimes(1);
81-
});
82-
8360
test('lovelaceSupply', async () => {
84-
BlockFrostAPI.prototype.network = jest.fn().mockResolvedValue(mockedNetworkResponse);
85-
BlockFrostAPI.prototype.apiUrl = apiUrl;
86-
87-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
88-
const client = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
89-
const response = await client.lovelaceSupply();
61+
mockResponses(request, [['network', mockedNetworkResponse]]);
62+
const response = await provider.lovelaceSupply();
9063

9164
expect(response).toMatchObject<SupplySummary>({
9265
circulating: 42_064_399_450_423_723n,
9366
total: 40_267_211_394_073_980n
9467
});
9568
});
9669

97-
test('lovelace throws', async () => {
98-
BlockFrostAPI.prototype.network = mockedErrorMethod;
99-
100-
BlockFrostAPI.prototype.apiUrl = apiUrl;
101-
102-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
103-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
104-
105-
await expect(() => provider.lovelaceSupply()).rejects.toThrow();
106-
expect(mockedErrorMethod).toBeCalledTimes(1);
107-
});
108-
10970
test('eraSummaries', async () => {
11071
const genesis = {
11172
activeSlotsCoefficient: 0.05,
@@ -286,30 +247,13 @@ describe('blockfrostNetworkInfoProvider', () => {
286247
}
287248
];
288249

289-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
290-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
291-
250+
mockResponses(request, [['network/eras', blockfrostResponseBody]]);
251+
// mockResponses(request, [['genesis', genesis]])
292252
provider.genesisParameters = jest.fn().mockResolvedValue(genesis);
293-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
294-
// @ts-ignore
295-
provider.fetchEraSummaries = jest.fn().mockResolvedValue(blockfrostResponseBody);
296-
297253
const response = await provider.eraSummaries();
298-
299254
expect(response).toMatchObject<EraSummary[]>(expected);
300255
});
301256

302-
test('eraSummaries throws', async () => {
303-
BlockFrostAPI.prototype.apiUrl = apiUrl;
304-
305-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
306-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
307-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
308-
// @ts-ignore
309-
provider.fetchEraSummaries = mockedErrorMethod;
310-
await expect(() => provider.eraSummaries()).rejects.toThrow();
311-
});
312-
313257
test('genesisParameters', async () => {
314258
const mockedResponse = {
315259
active_slots_coefficient: 0.05,
@@ -323,10 +267,7 @@ describe('blockfrostNetworkInfoProvider', () => {
323267
system_start: 1_506_203_091,
324268
update_quorum: 5
325269
};
326-
BlockFrostAPI.prototype.genesis = jest.fn().mockResolvedValue(mockedResponse);
327-
328-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
329-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
270+
mockResponses(request, [['genesis', mockedResponse]]);
330271
const response = await provider.genesisParameters();
331272

332273
expect(response).toMatchObject({
@@ -343,18 +284,6 @@ describe('blockfrostNetworkInfoProvider', () => {
343284
} as Cardano.CompactGenesis);
344285
});
345286

346-
test('genesisParameters throws', async () => {
347-
BlockFrostAPI.prototype.genesis = mockedErrorMethod;
348-
349-
BlockFrostAPI.prototype.apiUrl = apiUrl;
350-
351-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
352-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
353-
354-
await expect(() => provider.genesisParameters()).rejects.toThrow();
355-
expect(mockedErrorMethod).toBeCalledTimes(1);
356-
});
357-
358287
test('protocolParameters', async () => {
359288
const mockedResponse = {
360289
a0: 0.3,
@@ -383,12 +312,7 @@ describe('blockfrostNetworkInfoProvider', () => {
383312
rho: 0.003,
384313
tau: 0.2
385314
};
386-
BlockFrostAPI.prototype.epochsLatestParameters = jest.fn().mockResolvedValue(mockedResponse) as any;
387-
388-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
389-
BlockFrostAPI.prototype.apiUrl = apiUrl;
390-
391-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
315+
mockResponses(request, [['epochs/latest/parameters', mockedResponse]]);
392316
const response = await provider.protocolParameters();
393317

394318
expect(response).toMatchObject({
@@ -405,23 +329,8 @@ describe('blockfrostNetworkInfoProvider', () => {
405329
});
406330
});
407331

408-
test('protocolParameters throws', async () => {
409-
BlockFrostAPI.prototype.epochsLatestParameters = mockedErrorMethod;
410-
411-
BlockFrostAPI.prototype.apiUrl = apiUrl;
412-
413-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
414-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
415-
416-
await expect(() => provider.protocolParameters()).rejects.toThrow();
417-
expect(mockedErrorMethod).toBeCalledTimes(1);
418-
});
419-
420332
test('ledgerTip', async () => {
421-
BlockFrostAPI.prototype.blocksLatest = jest.fn().mockResolvedValue(blockResponse);
422-
423-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
424-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
333+
mockResponses(request, [['blocks/latest', blockResponse]]);
425334
const response = await provider.ledgerTip();
426335

427336
expect(response).toMatchObject({
@@ -430,16 +339,4 @@ describe('blockfrostNetworkInfoProvider', () => {
430339
slot: 37_767_194
431340
});
432341
});
433-
434-
test('ledgerTip throws', async () => {
435-
BlockFrostAPI.prototype.blocksLatest = mockedErrorMethod;
436-
437-
BlockFrostAPI.prototype.apiUrl = apiUrl;
438-
439-
const blockfrost = new BlockFrostAPI({ network: 'preprod', projectId: apiKey });
440-
const provider = new BlockfrostNetworkInfoProvider({ blockfrost, logger });
441-
442-
await expect(() => provider.ledgerTip()).rejects.toThrow();
443-
expect(mockedErrorMethod).toBeCalledTimes(1);
444-
});
445342
});

packages/cardano-services/src/NetworkInfo/BlockfrostNetworkInfoProvider/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
export * from './BlockfrostNetworkInfoProvider';
21
export * from './DbSyncNetworkInfoProvider';
32
export * from './NetworkInfoHttpService';

packages/cardano-services/src/Program/programs/providerServer.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ import {
1414
StakePoolProvider,
1515
UtxoProvider
1616
} from '@cardano-sdk/core';
17-
import { BlockfrostAssetProvider, CardanoWsClient, TxSubmitApiProvider } from '@cardano-sdk/cardano-services-client';
17+
import {
18+
BlockfrostAssetProvider,
19+
BlockfrostNetworkInfoProvider,
20+
CardanoWsClient,
21+
TxSubmitApiProvider
22+
} from '@cardano-sdk/cardano-services-client';
1823
import { Logger } from 'ts-log';
1924
import { Observable } from 'rxjs';
2025
import { OgmiosCardanoNode } from '@cardano-sdk/ogmios';
@@ -38,7 +43,6 @@ import {
3843
ChainHistoryHttpService,
3944
DbSyncChainHistoryProvider
4045
} from '../../ChainHistory';
41-
import { BlockfrostNetworkInfoProvider, DbSyncNetworkInfoProvider, NetworkInfoHttpService } from '../../NetworkInfo';
4246
import { BlockfrostRewardsProvider, DbSyncRewardsProvider, RewardsHttpService } from '../../Rewards';
4347
import { BlockfrostTxSubmitProvider, NodeTxSubmitProvider, TxSubmitHttpService } from '../../TxSubmit';
4448
import { BlockfrostUtxoProvider, DbSyncUtxoProvider, UtxoHttpService } from '../../Utxo';
@@ -52,6 +56,7 @@ import {
5256
suffixType2Cli
5357
} from '../options';
5458
import { DbPools, DbSyncEpochPollService, TypeormProvider, getBlockfrostApi, getBlockfrostClient } from '../../util';
59+
import { DbSyncNetworkInfoProvider, NetworkInfoHttpService } from '../../NetworkInfo';
5560
import {
5661
DbSyncStakePoolProvider,
5762
StakePoolHttpService,
@@ -308,8 +313,7 @@ const serviceMapFactory = (options: ServiceMapFactoryOptions) => {
308313
ServiceNames.Utxo
309314
);
310315

311-
const getBlockfrostNetworkInfoProvider = () =>
312-
new BlockfrostNetworkInfoProvider({ blockfrost: getBlockfrostApi(), logger });
316+
const getBlockfrostNetworkInfoProvider = () => new BlockfrostNetworkInfoProvider(getBlockfrostClient(), logger);
313317

314318
const getDbSyncNetworkInfoProvider = withDbSyncProvider((dbPools, cardanoNode) => {
315319
if (args.useWebSocketApi) return getWebSocketClient().networkInfoProvider;

0 commit comments

Comments
 (0)