Skip to content

Commit 8cb0dac

Browse files
feat(cardano-services): blockfrost utxo provider now caches utxos locally
1 parent 4687f72 commit 8cb0dac

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

packages/cardano-services-client/src/UtxoProvider/BlockfrostUtxoProvider.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { Cardano, Serialization, UtxoByAddressesArgs, UtxoProvider } from '@card
33
import type { Responses } from '@blockfrost/blockfrost-js';
44

55
export class BlockfrostUtxoProvider extends BlockfrostProvider implements UtxoProvider {
6+
private readonly cache: Map<string, Cardano.Tx> = new Map();
7+
68
protected async fetchUtxos(addr: Cardano.PaymentAddress, paginationQueryString: string): Promise<Cardano.Utxo[]> {
79
const queryString = `addresses/${addr.toString()}/utxos?${paginationQueryString}`;
810
const utxos = await this.request<Responses['address_utxo_content']>(queryString);
@@ -27,7 +29,11 @@ export class BlockfrostUtxoProvider extends BlockfrostProvider implements UtxoPr
2729
});
2830
}
2931
protected async fetchDetailsFromCBOR(hash: string) {
30-
return this.fetchCBOR(hash)
32+
if (this.cache.has(hash)) {
33+
return this.cache.get(hash);
34+
}
35+
36+
const result = await this.fetchCBOR(hash)
3137
.then((cbor) => {
3238
const tx = Serialization.Transaction.fromCbor(Serialization.TxCBOR(cbor)).toCore();
3339
this.logger.info('Fetched details from CBOR for tx', hash);
@@ -37,7 +43,15 @@ export class BlockfrostUtxoProvider extends BlockfrostProvider implements UtxoPr
3743
this.logger.warn('Failed to fetch details from CBOR for tx', hash, error);
3844
return null;
3945
});
46+
47+
if (!result) {
48+
return null;
49+
}
50+
51+
this.cache.set(hash, result);
52+
return result;
4053
}
54+
4155
public async utxoByAddresses({ addresses }: UtxoByAddressesArgs): Promise<Cardano.Utxo[]> {
4256
try {
4357
const utxoResults = await Promise.all(

packages/cardano-services-client/test/Utxo/BlockfrostUtxoProvider.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,29 @@ describe('blockfrostUtxoProvider', () => {
7979
}
8080
});
8181
});
82+
83+
test('does not call txs/${hash}/cbor when data is cached', async () => {
84+
const txHash = '0f3abbc8fc19c2e61bab6059bf8a466e6e754833a08a62a6c56fe0e78f19d9d5';
85+
86+
mockResponses(request, [
87+
[`txs/${txHash}/cbor`, 'mockedCBORData'],
88+
[`addresses/${address.toString()}/utxos?page=1&count=100`, generateUtxoResponseMock(1)],
89+
[`addresses/${address.toString()}/utxos?page=2&count=100`, generateUtxoResponseMock(0)]
90+
]);
91+
92+
const firstResponse = await provider.utxoByAddresses({ addresses: [address] });
93+
94+
expect(firstResponse).toBeTruthy();
95+
expect(firstResponse.length).toBe(1);
96+
97+
expect(request).toHaveBeenCalled();
98+
request.mockClear();
99+
100+
const secondResponse = await provider.utxoByAddresses({ addresses: [address] });
101+
102+
expect(secondResponse).toEqual(firstResponse);
103+
104+
expect(request).not.toHaveBeenCalledWith(`txs/${txHash}/cbor`);
105+
});
82106
});
83107
});

0 commit comments

Comments
 (0)