Skip to content

Commit

Permalink
refactor: revert breaking type changes
Browse files Browse the repository at this point in the history
- revert to `tokenMetadata?: TokenMetadata | null` type
- return `undefined` if there is an error while fetch from token server
  • Loading branch information
Ivaylo Andonov committed Sep 8, 2022
1 parent 050fc2b commit 34273d5
Show file tree
Hide file tree
Showing 19 changed files with 101 additions and 173 deletions.
4 changes: 2 additions & 2 deletions packages/blockfrost/src/blockfrostAssetProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const blockfrostAssetProvider = (blockfrost: BlockFrostAPI): AssetProvide
};

const getNftMetadata = async (
asset: Pick<Asset.AssetInfo<unknown>, 'name' | 'policyId'>,
asset: Pick<Asset.AssetInfo, 'name' | 'policyId'>,
lastMintedTxHash: string
): Promise<Asset.NftMetadata | null> => {
const metadata = await blockfrost.txsMetadata(lastMintedTxHash);
Expand Down Expand Up @@ -93,7 +93,7 @@ export const blockfrostAssetProvider = (blockfrost: BlockFrostAPI): AssetProvide
nftMetadata: extraData?.nftMetadata ? await nftMetadata() : undefined,
policyId,
quantity,
tokenMetadata: extraData?.tokenMetadata ? { data: mapMetadata(response.metadata) } : undefined
tokenMetadata: extraData?.tokenMetadata ? mapMetadata(response.metadata) : undefined
};
};

Expand Down
54 changes: 24 additions & 30 deletions packages/blockfrost/test/blockfrostAssetProvider.test.ts

Large diffs are not rendered by default.

27 changes: 5 additions & 22 deletions packages/cardano-services/src/Asset/CardanoTokenRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Asset, Cardano, ProviderError, ProviderFailure } from '@cardano-sdk/core';
import { InMemoryCache } from '../InMemoryCache';
import { Logger } from 'ts-log';
import { MetadataSourceType, TokenMetadataService, TokenMetadataSource } from './types';
import { TokenMetadataService } from './types';
import axios, { AxiosInstance } from 'axios';

export const DEFAULT_TOKEN_METADATA_CACHE_TTL = 600;
Expand Down Expand Up @@ -41,19 +41,6 @@ const toProviderError = (error: unknown, details: string) => {
return new ProviderError(ProviderFailure.Unknown, error, `${message}${details}`);
};

const toTokenMetadataInfo = (
data: Asset.TokenMetadata | null
): {
data: Asset.TokenMetadata | null;
source: TokenMetadataSource;
} => ({
data: data ? data : null,
source: {
requestStatus: data ? 'success' : 'fail',
type: MetadataSourceType.Registry
}
});

/**
* Configuration options for CardanoTokenRegistry
*/
Expand Down Expand Up @@ -148,7 +135,7 @@ export class CardanoTokenRegistry implements TokenMetadataService {
const assetId = Cardano.AssetId(subject);
const metadata = toCoreTokenMetadata(record);

tokenMetadata[assetIds.indexOf(assetId)] = toTokenMetadataInfo(metadata);
tokenMetadata[assetIds.indexOf(assetId)] = metadata;
this.#cache.set(assetId.toString(), metadata);
} else
throw new ProviderError(
Expand All @@ -167,13 +154,11 @@ export class CardanoTokenRegistry implements TokenMetadataService {
throw error;
}

for (const assetId of assetIdsToRequest) {
tokenMetadata[assetIds.indexOf(assetId)] = toTokenMetadataInfo(null);
}
this.#logger.error(
`Failed to fetch asset metatada from token registry server.Requested asset ids: "${assetIdsToRequest}"`,
error
);
return;
}

return tokenMetadata;
Expand All @@ -182,9 +167,7 @@ export class CardanoTokenRegistry implements TokenMetadataService {
getTokenMetadataFromCache(assetIds: Cardano.AssetId[]) {
const assetIdsToRequest: Cardano.AssetId[] = [];
// eslint-disable-next-line unicorn/no-new-array
const cachedTokenMetadata: { data: Asset.TokenMetadata | null; source: TokenMetadataSource }[] = new Array(
assetIds.length
).fill(null);
const cachedTokenMetadata: (Asset.TokenMetadata | null)[] = new Array(assetIds.length).fill(null);

for (const [i, assetId] of assetIds.entries()) {
const stringAssetId = assetId.toString();
Expand All @@ -193,7 +176,7 @@ export class CardanoTokenRegistry implements TokenMetadataService {

if (cachedMetadata) {
this.#logger.debug(`Using cached asset metatada value for "${stringAssetId}"`);
cachedTokenMetadata[i] = toTokenMetadataInfo(cachedMetadata);
cachedTokenMetadata[i] = cachedMetadata;
} else assetIdsToRequest.push(assetId);
}

Expand Down
19 changes: 7 additions & 12 deletions packages/cardano-services/src/Asset/DbSyncAssetProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Asset, AssetProvider, Cardano, ProviderError, ProviderFailure } from '@
import { AssetBuilder } from './AssetBuilder';
import { DbSyncProvider } from '../DbSyncProvider';
import { Logger } from 'ts-log';
import { NftMetadataService, TokenMetadataService, TokenMetadataSource } from './types';
import { NftMetadataService, TokenMetadataService } from './types';
import { Pool } from 'pg';

/**
Expand Down Expand Up @@ -63,25 +63,20 @@ export class DbSyncAssetProvider extends DbSyncProvider implements AssetProvider
const quantity = BigInt(quantities.sum);
const mintOrBurnCount = Number(quantities.count);

const assetInfo: Asset.AssetInfo<TokenMetadataSource> = {
assetId,
fingerprint,
mintOrBurnCount,
name,
policyId,
quantity
};
const assetInfo: Asset.AssetInfo = { assetId, fingerprint, mintOrBurnCount, name, policyId, quantity };

if (extraData?.history) await this.loadHistory(assetInfo);
if (extraData?.nftMetadata)
assetInfo.nftMetadata = await this.#dependencies.ntfMetadataService.getNftMetadata(assetInfo);
if (extraData?.tokenMetadata)
assetInfo.tokenMetadata = (await this.#dependencies.tokenMetadataService.getTokenMetadata([assetId]))[0];
if (extraData?.tokenMetadata) {
const tokenMetadata = await this.#dependencies.tokenMetadataService.getTokenMetadata([assetId]);
assetInfo.tokenMetadata = tokenMetadata && tokenMetadata.length > 0 ? tokenMetadata[0] : undefined;
}

return assetInfo;
}

private async loadHistory(assetInfo: Asset.AssetInfo<TokenMetadataSource>) {
private async loadHistory(assetInfo: Asset.AssetInfo) {
assetInfo.history = (
await this.#builder.queryMultiAssetHistory(assetInfo.policyId, assetInfo.name)
).map<Asset.AssetMintOrBurn>(({ hash, quantity }) => ({
Expand Down
42 changes: 13 additions & 29 deletions packages/cardano-services/src/Asset/openApi.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,36 +63,20 @@
"AssetInfo": {
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"assetId": {
"type": "string"
},
"fingerprint": {
"type": "string"
},
"mintOrBurnCount": {
"type": "number"
},
"name": {
"type": "string"
},
"policyId": {
"type": "string"
}
}
"assetId": {
"type": "string"
},
"source": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"requestStatus": {
"type": "string"
}
}
"fingerprint": {
"type": "string"
},
"mintOrBurnCount": {
"type": "number"
},
"name": {
"type": "string"
},
"policyId": {
"type": "string"
}
}
},
Expand Down
15 changes: 2 additions & 13 deletions packages/cardano-services/src/Asset/types.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
import { Asset, Cardano } from '@cardano-sdk/core';
import { Shutdown } from '@cardano-sdk/util';

export enum MetadataSourceType {
Registry = 'registry'
}

export interface TokenMetadataSource {
type: MetadataSourceType.Registry;
requestStatus: 'success' | 'fail';
}

/**
* Cardano.AssetId as an object with `policyId` and `name`
*/
export type AssetPolicyIdAndName = Pick<Asset.AssetInfo<TokenMetadataSource>, 'name' | 'policyId'>;
export type AssetPolicyIdAndName = Pick<Asset.AssetInfo, 'name' | 'policyId'>;

/**
* Service to get CIP-25 NFT metadata for a given asset
Expand All @@ -36,9 +27,7 @@ export interface TokenMetadataService extends Shutdown {
*
* @returns CIP-38? token metadata, `null` if not found
*/
getTokenMetadata(
assetIds: Cardano.AssetId[]
): Promise<{ data: Asset.TokenMetadata | null; source: TokenMetadataSource }[]>;
getTokenMetadata(assetIds: Cardano.AssetId[]): Promise<(Asset.TokenMetadata | null)[] | undefined>;
}

export interface LastMintTxModel {
Expand Down
65 changes: 28 additions & 37 deletions packages/cardano-services/test/Asset/CardanoTokenRegistry.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Asset, Cardano, ProviderError, ProviderFailure } from '@cardano-sdk/core';
import { CardanoTokenRegistry, MetadataSourceType, TokenMetadataSource, toCoreTokenMetadata } from '../../src/Asset';
import { Cardano, ProviderError, ProviderFailure } from '@cardano-sdk/core';
import { CardanoTokenRegistry, toCoreTokenMetadata } from '../../src/Asset';
import { InMemoryCache, Key } from '../../src/InMemoryCache';
import { IncomingMessage, createServer } from 'http';
import { dummyLogger } from 'ts-log';
Expand Down Expand Up @@ -135,36 +135,30 @@ describe('CardanoTokenRegistry', () => {
});

it('returns metadata when subject exists', async () => {
const [metadata] = await tokenRegistry.getTokenMetadata([validAssetId]);

expect(metadata).not.toBeNull();

const result: { data: Asset.TokenMetadata; source: TokenMetadataSource } = {
data: {
decimals: 8,
desc: 'SingularityNET',
icon: 'testLogo',
name: 'SingularityNet AGIX Token',
ticker: 'AGIX',
url: 'https://singularitynet.io/'
},
source: {
requestStatus: 'success',
type: MetadataSourceType.Registry
}
const metadata = await tokenRegistry.getTokenMetadata([validAssetId]);

expect(metadata![0]).not.toBeNull();

const result = {
decimals: 8,
desc: 'SingularityNET',
icon: 'testLogo',
name: 'SingularityNet AGIX Token',
ticker: 'AGIX',
url: 'https://singularitynet.io/'
};

expect(metadata).toEqual(result);
expect(metadata![0]).toEqual(result);
});

it('correctly returns null or metadata for request with good and bad assetIds', async () => {
const firstResult = await tokenRegistry.getTokenMetadata([invalidAssetId, validAssetId]);
const secondResult = await tokenRegistry.getTokenMetadata([validAssetId, invalidAssetId]);

expect(firstResult[0]).toBeNull();
expect(firstResult[1]).not.toBeNull();
expect(secondResult[0]).not.toBeNull();
expect(secondResult[1]).toBeNull();
expect(firstResult![0]).toBeNull();
expect(firstResult![1]).not.toBeNull();
expect(secondResult![0]).not.toBeNull();
expect(secondResult![1]).toBeNull();
});
});

Expand Down Expand Up @@ -199,12 +193,12 @@ describe('CardanoTokenRegistry', () => {
});

it('metadata are cached', async () => {
const [firstResult] = await tokenRegistry.getTokenMetadata([validAssetId]);
const [secondResult] = await tokenRegistry.getTokenMetadata([validAssetId]);
const firstResult = await tokenRegistry.getTokenMetadata([validAssetId]);
const secondResult = await tokenRegistry.getTokenMetadata([validAssetId]);

expect(gotValues[0]).toBeUndefined();
expect(gotValues[1]).toEqual(firstResult.data);
expect(firstResult).toEqual(secondResult);
expect(gotValues[1]).toEqual(firstResult![0]);
expect(firstResult![0]).toEqual(secondResult![0]);
});
});

Expand Down Expand Up @@ -244,8 +238,8 @@ describe('CardanoTokenRegistry', () => {
});

it('internal server error', async () => {
const failedMetadata = { data: null, source: { requestStatus: 'fail', type: 'registry' } };
const succeededMetadata = { data: { name: 'test' }, source: { requestStatus: 'success', type: 'registry' } };
const failedMetadata = null;
const succeededMetadata = { name: 'test' };

let alreadyCalled = false;
const record = () => {
Expand All @@ -264,15 +258,12 @@ describe('CardanoTokenRegistry', () => {

({ closeMock, tokenMetadataServerUrl } = await mockTokenRegistry(record));
const tokenRegistry = new CardanoTokenRegistry({ logger }, { tokenMetadataServerUrl });
const result = await tokenRegistry.getTokenMetadata([invalidAssetId, validAssetId]);
const firstSucceedResult = await tokenRegistry.getTokenMetadata([invalidAssetId, validAssetId]);
const secondFailedResult = await tokenRegistry.getTokenMetadata([invalidAssetId, validAssetId]);

await expect(tokenRegistry.getTokenMetadata([invalidAssetId, validAssetId])).resolves.toEqual([
failedMetadata,
succeededMetadata
]);
expect(firstSucceedResult).toEqual([failedMetadata, succeededMetadata]);

expect(result[0]).toBeNull();
expect(result[1]).toStrictEqual(succeededMetadata);
expect(secondFailedResult).toBeUndefined();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('DbSyncAssetProvider', () => {
otherProperties: new Map([['id', 1n]]),
version: '1.0'
});
expect(asset.tokenMetadata?.data).toStrictEqual({
expect(asset.tokenMetadata).toStrictEqual({
desc: 'This is my first NFT of the macaron cake',
name: 'macaron cake token'
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,8 @@ Object {
"policyId": "50fdcdbfa3154db86a87e4b5697ae30d272e0bbcfa8122efd3e301cb",
"quantity": 1n,
"tokenMetadata": Object {
"data": Object {
"desc": "This is my first NFT of the macaron cake",
"name": "macaron cake token",
},
"source": Object {
"requestStatus": "success",
"type": "registry",
},
"desc": "This is my first NFT of the macaron cake",
"name": "macaron cake token",
},
}
`;
6 changes: 2 additions & 4 deletions packages/cardano-services/test/entrypoints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1202,8 +1202,7 @@ describe('entrypoints', () => {

const { tokenMetadata } = fromSerializableObject(res.data);
expect(tokenMetadata).toStrictEqual({
data: { name: 'test' },
source: { requestStatus: 'success', type: 'registry' }
name: 'test'
});
});

Expand All @@ -1230,8 +1229,7 @@ describe('entrypoints', () => {

const { tokenMetadata } = fromSerializableObject(res.data);
expect(tokenMetadata).toStrictEqual({
data: { name: 'test' },
source: { requestStatus: 'success', type: 'registry' }
name: 'test'
});
});
});
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/Asset/types/AssetInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface AssetMintOrBurn {
*/
quantity: bigint;
}
export interface AssetInfo<Source> {
export interface AssetInfo {
assetId: AssetId;
policyId: PolicyId;
name: AssetName;
Expand All @@ -24,7 +24,7 @@ export interface AssetInfo<Source> {
/**
* CIP-0035. `undefined` if not loaded, `null` if no metadata found
*/
tokenMetadata?: { data: TokenMetadata | null; source?: Source };
tokenMetadata?: TokenMetadata | null;
/**
* CIP-0025. `undefined` if not loaded, `null` if no metadata found
*/
Expand Down
Loading

0 comments on commit 34273d5

Please sign in to comment.