From 6e28df412797974b8ce6f6deb0c3346ff5938a05 Mon Sep 17 00:00:00 2001 From: Mircea Hasegan Date: Thu, 13 Apr 2023 16:24:42 +0200 Subject: [PATCH] refactor!: rename AssetInfo 'quantity' to 'supply' --- .../assetInfoHttpProvider.ts | 29 +++++++++++++++++-- .../src/HttpProvider.ts | 17 +++++++++-- .../assetInfoHttpProvider.test.ts | 21 ++++++++++++++ .../DbSyncAssetProvider.ts | 4 +-- .../cardano-services/src/Asset/openApi.json | 16 ++++++++++ .../test/Asset/DbSyncAssetProvider.test.ts | 2 +- packages/core/src/Asset/types/AssetInfo.ts | 2 +- .../wallet/SingleAddressWallet/nft.test.ts | 8 ++--- .../wallet/test/mocks/mockAssetProvider.ts | 2 +- 9 files changed, 86 insertions(+), 15 deletions(-) diff --git a/packages/cardano-services-client/src/AssetInfoProvider/assetInfoHttpProvider.ts b/packages/cardano-services-client/src/AssetInfoProvider/assetInfoHttpProvider.ts index d9c932f4d1c..e706c24a30a 100644 --- a/packages/cardano-services-client/src/AssetInfoProvider/assetInfoHttpProvider.ts +++ b/packages/cardano-services-client/src/AssetInfoProvider/assetInfoHttpProvider.ts @@ -1,5 +1,10 @@ -import { AssetProvider } from '@cardano-sdk/core'; -import { CreateHttpProviderConfig, HttpProviderConfigPaths, createHttpProvider } from '../HttpProvider'; +import { Asset, AssetProvider } from '@cardano-sdk/core'; +import { + CreateHttpProviderConfig, + HttpProviderConfig, + HttpProviderConfigPaths, + createHttpProvider +} from '../HttpProvider'; /** * The AssetProvider endpoint paths. @@ -10,6 +15,23 @@ const paths: HttpProviderConfigPaths = { healthCheck: '/health' }; +const isAssetInfo = (assetInfo: unknown): assetInfo is Asset.AssetInfo => !!(assetInfo as Asset.AssetInfo)?.assetId; + +const transformQuantityToSupply = (assetInfo: Asset.AssetInfo | unknown): Asset.AssetInfo | unknown => { + if (isAssetInfo(assetInfo) && assetInfo.supply === undefined) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const { quantity, ...assetInfoReduced } = assetInfo as any; + return { ...assetInfoReduced, supply: quantity } as Asset.AssetInfo; + } + return assetInfo; +}; + +const responseTransformers: HttpProviderConfig['responseTransformers'] = { + getAsset: (data: unknown): unknown => transformQuantityToSupply(data), + getAssets: (data: unknown): unknown => + Array.isArray(data) ? data.map((assetInfo) => transformQuantityToSupply(assetInfo)) : data +}; + /** * Connect to a Cardano Services HttpServer instance with the service available * @@ -18,5 +40,6 @@ const paths: HttpProviderConfigPaths = { export const assetInfoHttpProvider = (config: CreateHttpProviderConfig): AssetProvider => createHttpProvider({ ...config, - paths + paths, + responseTransformers }); diff --git a/packages/cardano-services-client/src/HttpProvider.ts b/packages/cardano-services-client/src/HttpProvider.ts index 68457567f16..0fd3f0976df 100644 --- a/packages/cardano-services-client/src/HttpProvider.ts +++ b/packages/cardano-services-client/src/HttpProvider.ts @@ -2,11 +2,12 @@ import { Logger } from 'ts-log'; import { ProviderError, ProviderFailure } from '@cardano-sdk/core'; import { fromSerializableObject, toSerializableObject } from '@cardano-sdk/util'; -import axios, { AxiosAdapter, AxiosRequestConfig } from 'axios'; +import axios, { AxiosAdapter, AxiosRequestConfig, AxiosResponseTransformer } from 'axios'; const isEmptyResponse = (response: any) => response === ''; export type HttpProviderConfigPaths = { [methodName in keyof T]: string }; +type ResponseTransformers = { [K in keyof T]?: AxiosResponseTransformer }; export interface HttpProviderConfig { /** @@ -41,6 +42,11 @@ export interface HttpProviderConfig { * Logger strategy. */ logger: Logger; + + /** + * Transform responses + */ + responseTransformers?: ResponseTransformers; } /** @@ -65,7 +71,8 @@ export const createHttpProvider = ({ mapError, paths, adapter, - logger + logger, + responseTransformers }: HttpProviderConfig): T => new Proxy({} as T, { // eslint-disable-next-line sonarjs/cognitive-complexity @@ -73,6 +80,8 @@ export const createHttpProvider = ({ if (prop === 'then') return; const method = prop as keyof T; const path = paths[method]; + const transformResponse = + responseTransformers && responseTransformers[method] ? responseTransformers[method]! : (v: unknown) => v; if (!path) throw new ProviderError(ProviderFailure.NotImplemented, `HttpProvider missing path for '${prop.toString()}'`); return async (...args: any[]) => { @@ -97,7 +106,9 @@ export const createHttpProvider = ({ }); axiosInstance.interceptors.response.use((value) => ({ ...value, - data: fromSerializableObject(value.data, { getErrorPrototype: () => ProviderError.prototype }) + data: transformResponse( + fromSerializableObject(value.data, { getErrorPrototype: () => ProviderError.prototype }) + ) })); const response = (await axiosInstance.request(req)).data; return !isEmptyResponse(response) ? response : undefined; diff --git a/packages/cardano-services-client/test/AssetInfoProvider/assetInfoHttpProvider.test.ts b/packages/cardano-services-client/test/AssetInfoProvider/assetInfoHttpProvider.test.ts index da6a63e97c8..1dba361f372 100644 --- a/packages/cardano-services-client/test/AssetInfoProvider/assetInfoHttpProvider.test.ts +++ b/packages/cardano-services-client/test/AssetInfoProvider/assetInfoHttpProvider.test.ts @@ -1,6 +1,7 @@ import { Cardano } from '@cardano-sdk/core'; import { assetInfoHttpProvider } from '../../src'; import { logger } from '@cardano-sdk/util-dev'; +import { toSerializableObject } from '@cardano-sdk/util'; import MockAdapter from 'axios-mock-adapter'; import axios from 'axios'; @@ -41,5 +42,25 @@ describe('assetInfoHttpProvider', () => { }) ).resolves.toEqual({}); }); + + test('getAsset maps legacy assetInfo `quantity` as `supply`', async () => { + axiosMock.onPost().replyOnce(200, toSerializableObject({ assetId: 'dummy', quantity: 2n })); + const provider = assetInfoHttpProvider(config); + await expect( + provider.getAsset({ + assetId: Cardano.AssetId('f43a62fdc3965df486de8a0d32fe800963589c41b38946602a0dc53541474958') + }) + ).resolves.toEqual({ assetId: 'dummy', supply: 2n }); + }); + + test('getAssets maps legacy assetInfo `quantity` as `supply`', async () => { + axiosMock.onPost().replyOnce(200, toSerializableObject([{ assetId: 'dummy', quantity: 2n }])); + const provider = assetInfoHttpProvider(config); + await expect( + provider.getAssets({ + assetIds: [Cardano.AssetId('f43a62fdc3965df486de8a0d32fe800963589c41b38946602a0dc53541474958')] + }) + ).resolves.toEqual([{ assetId: 'dummy', supply: 2n }]); + }); }); }); diff --git a/packages/cardano-services/src/Asset/DbSyncAssetProvider/DbSyncAssetProvider.ts b/packages/cardano-services/src/Asset/DbSyncAssetProvider/DbSyncAssetProvider.ts index a911efc3446..1d29e096280 100644 --- a/packages/cardano-services/src/Asset/DbSyncAssetProvider/DbSyncAssetProvider.ts +++ b/packages/cardano-services/src/Asset/DbSyncAssetProvider/DbSyncAssetProvider.ts @@ -132,9 +132,9 @@ export class DbSyncAssetProvider extends DbSyncProvider() implements AssetProvid const fingerprint = multiAsset.fingerprint as unknown as Cardano.AssetFingerprint; const quantities = await this.#builder.queryMultiAssetQuantities(multiAsset.id); - const quantity = BigInt(quantities.sum); + const supply = BigInt(quantities.sum); const mintOrBurnCount = Number(quantities.count); - return { assetId, fingerprint, mintOrBurnCount, name, policyId, quantity }; + return { assetId, fingerprint, mintOrBurnCount, name, policyId, supply }; } } diff --git a/packages/cardano-services/src/Asset/openApi.json b/packages/cardano-services/src/Asset/openApi.json index d65163df4af..7447c76f84d 100644 --- a/packages/cardano-services/src/Asset/openApi.json +++ b/packages/cardano-services/src/Asset/openApi.json @@ -126,6 +126,22 @@ }, "policyId": { "type": "string" + }, + "supply": { + "$ref": "#/components/schemas/BigInt" + } + } + }, + "BigInt": { + "required": ["value", "__type"], + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "__type": { + "type": "string", + "enum": ["bigint"] } } }, diff --git a/packages/cardano-services/test/Asset/DbSyncAssetProvider.test.ts b/packages/cardano-services/test/Asset/DbSyncAssetProvider.test.ts index 91a724553d8..d41ff65a6ee 100644 --- a/packages/cardano-services/test/Asset/DbSyncAssetProvider.test.ts +++ b/packages/cardano-services/test/Asset/DbSyncAssetProvider.test.ts @@ -84,7 +84,7 @@ describe('DbSyncAssetProvider', () => { mintOrBurnCount: 1, name: '6d616361726f6e2d63616b65', policyId: '50fdcdbfa3154db86a87e4b5697ae30d272e0bbcfa8122efd3e301cb', - quantity: 1n + supply: 1n }); }); it('returns an AssetInfo with extra data', async () => { diff --git a/packages/core/src/Asset/types/AssetInfo.ts b/packages/core/src/Asset/types/AssetInfo.ts index 9af21fb0797..49bd54197cd 100644 --- a/packages/core/src/Asset/types/AssetInfo.ts +++ b/packages/core/src/Asset/types/AssetInfo.ts @@ -16,7 +16,7 @@ export interface AssetInfo { policyId: PolicyId; name: AssetName; fingerprint: AssetFingerprint; - quantity: bigint; + supply: bigint; mintOrBurnCount: number; /** * Sorted by slot diff --git a/packages/e2e/test/wallet/SingleAddressWallet/nft.test.ts b/packages/e2e/test/wallet/SingleAddressWallet/nft.test.ts index dcf11501d63..955de2fba7c 100644 --- a/packages/e2e/test/wallet/SingleAddressWallet/nft.test.ts +++ b/packages/e2e/test/wallet/SingleAddressWallet/nft.test.ts @@ -203,9 +203,9 @@ describe('SingleAddressWallet.assets/nft', () => { version: '1.0' }, policyId, - // in case of repeated tests on the same network, total asset quantity is not updated due to + // in case of repeated tests on the same network, total asset supply is not updated due to // the limitation that asset info is not refreshed on wallet balance changes - quantity: expect.anything(), + supply: expect.anything(), tokenMetadata: null }); expect(nfts.find((nft) => nft.assetId === assetIds[TOKEN_METADATA_1_INDEX])).toBeDefined(); @@ -251,7 +251,7 @@ describe('SingleAddressWallet.assets/nft', () => { version: '1.0' }, policyId, - quantity: expect.anything(), + supply: expect.anything(), tokenMetadata: null }); }); @@ -385,7 +385,7 @@ describe('SingleAddressWallet.assets/nft', () => { version: '1.0' }, policyId, - quantity: expect.anything(), + supply: expect.anything(), tokenMetadata: null }); }); diff --git a/packages/wallet/test/mocks/mockAssetProvider.ts b/packages/wallet/test/mocks/mockAssetProvider.ts index 61f85d7ddc5..b266e041208 100644 --- a/packages/wallet/test/mocks/mockAssetProvider.ts +++ b/packages/wallet/test/mocks/mockAssetProvider.ts @@ -12,7 +12,7 @@ export const asset = { name: Cardano.AssetName('54534c41'), nftMetadata: null, policyId: Cardano.PolicyId('7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373'), - quantity: 1000n, + supply: 1000n, tokenMetadata: null } as Asset.AssetInfo;