Skip to content

Commit

Permalink
refactor(wallet): add utxoProvider dependeny to blockfrost
Browse files Browse the repository at this point in the history
  • Loading branch information
Juan Cruz committed May 13, 2022
1 parent 769b6b5 commit 2c4ef11
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 14 deletions.
14 changes: 12 additions & 2 deletions packages/blockfrost/src/blockfrostWalletProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ProviderError,
ProviderFailure,
ProviderUtil,
UtxoProvider,
WalletProvider
} from '@cardano-sdk/core';
import { PaginationOptions } from '@blockfrost/blockfrost-js/lib/types';
Expand Down Expand Up @@ -41,10 +42,15 @@ const fetchByAddressSequentially = async <Item, Response>(props: {
* Connect to the [Blockfrost service](https://docs.blockfrost.io/)
*
* @param {BlockFrostAPI} blockfrost BlockFrostAPI instance
* @param {UtxoProvider} utxoProvider utxo provider
* @returns {WalletProvider} WalletProvider
* @throws {ProviderFailure}
*/
export const blockfrostWalletProvider = (blockfrost: BlockFrostAPI, logger = dummyLogger): WalletProvider => {
export const blockfrostWalletProvider = (
blockfrost: BlockFrostAPI,
utxoProvider: UtxoProvider,
logger = dummyLogger
): WalletProvider => {
const ledgerTip: WalletProvider['ledgerTip'] = async () => {
const block = await blockfrost.blocksLatest();
return BlockfrostToCore.blockToTip(block);
Expand Down Expand Up @@ -72,6 +78,9 @@ export const blockfrostWalletProvider = (blockfrost: BlockFrostAPI, logger = dum
};
};

const utxoByAddresses: WalletProvider['utxoByAddresses'] = async (addresses) =>
utxoProvider.utxoByAddresses(addresses);

const rewards: WalletProvider['rewardAccountBalance'] = async (rewardAccount: Cardano.RewardAccount) => {
try {
const accountResponse = await blockfrost.accounts(rewardAccount.toString());
Expand Down Expand Up @@ -397,7 +406,8 @@ export const blockfrostWalletProvider = (blockfrost: BlockFrostAPI, logger = dum
rewardsHistory,
stakePoolStats,
transactionsByAddresses,
transactionsByHashes
transactionsByHashes,
utxoByAddresses
};

return ProviderUtil.withProviderErrors(providerFunctions, toProviderError);
Expand Down
41 changes: 29 additions & 12 deletions packages/blockfrost/test/blockfrostWalletProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
import { BlockFrostAPI, Responses } from '@blockfrost/blockfrost-js';
import { Cardano, StakePoolStats, WalletProvider } from '@cardano-sdk/core';
import { blockfrostWalletProvider } from '../src';
import { utxoHttpProvider } from '@cardano-sdk/cardano-services-client';

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

const url = 'http://some-hostname:3000/utxo';

const generatePoolsResponseMock = (qty: number) =>
[...Array.from({ length: qty }).keys()].map((num) => String(Math.random() * num)) as Responses['pool_list'];

Expand Down Expand Up @@ -70,7 +74,8 @@ describe('blockfrostWalletProvider', () => {
.mockReturnValueOnce(generatePoolsResponseMock(77));

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.stakePoolStats!();

expect(response).toMatchObject<StakePoolStats>({
Expand All @@ -91,7 +96,9 @@ describe('blockfrostWalletProvider', () => {
.mockResolvedValueOnce(generateUtxoResponseMock(0));

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);

const response = await client.utxoByAddresses(
[
'addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp'
Expand Down Expand Up @@ -149,7 +156,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.addressesUtxos = jest.fn().mockRejectedValue(notFoundBody);

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.utxoByAddresses(
[
'addr_test1qz44wna7xvs8n2ukxw0qat3vktymndgk8nerey6mlxr97s47n48hk78hcuyku03lj7qplmfqscm87j9wv3amxqaur2hs055pjt'
Expand Down Expand Up @@ -177,7 +185,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.accounts = jest.fn().mockResolvedValue(accountsMockResponse);

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.rewardAccountBalance(
Cardano.RewardAccount('stake_test1uqfu74w3wh4gfzu8m6e7j987h4lq9r3t7ef5gaw497uu85qsqfy27')
);
Expand All @@ -194,7 +203,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.accounts = jest.fn().mockRejectedValue(notFoundBody);

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.rewardAccountBalance(
Cardano.RewardAccount('stake_test1up7pvfq8zn4quy45r2g572290p9vf99mr9tn7r9xrgy2l2qdsf58d')
);
Expand Down Expand Up @@ -316,7 +326,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.txs = jest.fn().mockResolvedValue(mockedTxResponse);
BlockFrostAPI.prototype.txsMetadata = jest.fn().mockResolvedValue(mockedMetadataResponse);
const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.transactionsByHashes(
['4123d70f66414cc921f6ffc29a899aafc7137a99a0fd453d6b200863ef5702d6'].map(Cardano.TransactionId)
);
Expand Down Expand Up @@ -429,7 +440,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.genesis = jest.fn().mockResolvedValue(mockedResponse);

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.genesisParameters();

expect(response).toMatchObject({
Expand Down Expand Up @@ -465,7 +477,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.axiosInstance = jest.fn().mockResolvedValue(mockedResponse) as any;

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.currentWalletProtocolParameters();

expect(response).toMatchObject({
Expand All @@ -486,7 +499,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.blocksLatest = jest.fn().mockResolvedValue(blockResponse);

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.ledgerTip();

expect(response).toMatchObject({
Expand All @@ -500,7 +514,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.blocks = jest.fn().mockResolvedValue(blockResponse);

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.blocksByHashes([
Cardano.BlockId('0dbe461fb5f981c0d01615332b8666340eb1a692b3034f46bcb5f5ea4172b2ed')
]);
Expand Down Expand Up @@ -533,7 +548,8 @@ describe('blockfrostWalletProvider', () => {
BlockFrostAPI.prototype.blocks = jest.fn().mockResolvedValue({ ...blockResponse, slot_leader: slotLeader });

const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
const client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
const client = blockfrostWalletProvider(blockfrost, utxoProvider);
const response = await client.blocksByHashes([
Cardano.BlockId('0dbe461fb5f981c0d01615332b8666340eb1a692b3034f46bcb5f5ea4172b2ed')
]);
Expand All @@ -557,7 +573,8 @@ describe('blockfrostWalletProvider', () => {

beforeEach(() => {
const blockfrost = new BlockFrostAPI({ isTestnet: true, projectId: apiKey });
client = blockfrostWalletProvider(blockfrost);
const utxoProvider = utxoHttpProvider(url);
client = blockfrostWalletProvider(blockfrost, utxoProvider);
});

test('epoch bounds & query per stake address', async () => {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/Provider/WalletProvider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface WalletProvider {
// move stakePoolStats out to other provider type, since it's not required for wallet operation.
// Perhaps generalize StakePoolSearchProvider?
stakePoolStats?: () => Promise<StakePoolStats>;
utxoByAddresses: (addresses: Cardano.Address[]) => Promise<Cardano.Utxo[]>;
/**
* @param {Cardano.BlockNo} sinceBlock inclusive
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class TrackedWalletProvider extends ProviderTracker implements WalletProv
readonly currentWalletProtocolParameters: WalletProvider['currentWalletProtocolParameters'];
readonly genesisParameters: WalletProvider['genesisParameters'];
readonly rewardsHistory: WalletProvider['rewardsHistory'];
readonly utxoByAddresses: WalletProvider['utxoByAddresses'];

constructor(walletProvider: WalletProvider) {
super();
Expand All @@ -64,6 +65,7 @@ export class TrackedWalletProvider extends ProviderTracker implements WalletProv
? () => this.trackedCall(walletProvider.stakePoolStats!, this.stats.stakePoolStats$)
: undefined;
this.ledgerTip = () => this.trackedCall(walletProvider.ledgerTip, this.stats.ledgerTip$);
this.utxoByAddresses = (addresses) => this.utxoByAddresses(addresses);
this.rewardAccountBalance = (rewardAccount) =>
this.trackedCall(() => walletProvider.rewardAccountBalance(rewardAccount), this.stats.rewardAccountBalance$);
this.transactionsByAddresses = (addresses) =>
Expand Down

0 comments on commit 2c4ef11

Please sign in to comment.