Skip to content

Commit

Permalink
Merge pull request #466 from input-output-hk/feat/ADP-2215-gracefully…
Browse files Browse the repository at this point in the history
…-handle-getNftMetadata-errors-during-getAsset

feat(cardano-services): get metadata should return undefined on errors
  • Loading branch information
rhyslbw committed Sep 28, 2022
2 parents 1b2ccd2 + 7b87d1d commit be24ba8
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ export class DbSyncNftMetadataService implements NftMetadataService {
this.#metadataService = metadataService;
}

async getNftMetadata(assetInfo: AssetPolicyIdAndName): Promise<Asset.NftMetadata | undefined> {
async getNftMetadata(assetInfo: AssetPolicyIdAndName): Promise<Asset.NftMetadata | null> {
// Perf: could query last mint tx metadata in 1 query instead of 2
const lastMintedTx = await this.#builder.queryLastMintTx(assetInfo.policyId, assetInfo.name);

if (!lastMintedTx) return;
if (!lastMintedTx) return null;

const lastMintedTxId = Cardano.TransactionId(lastMintedTx.tx_hash.toString('hex'));

Expand Down
4 changes: 2 additions & 2 deletions packages/cardano-services/src/Asset/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export interface NftMetadataService {
/**
* Get CIP-25 NFT metadata for a given asset
*
* @returns CIP-25 NFT metadata for NFTs, `undefined` for assets that are not NFTs
* @returns CIP-25 NFT metadata for NFTs, `null` for assets that are not NFTs
*/
getNftMetadata(asset: AssetPolicyIdAndName): Promise<Asset.NftMetadata | undefined>;
getNftMetadata(asset: AssetPolicyIdAndName): Promise<Asset.NftMetadata | null>;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const oneMintNft: AssetPolicyIdAndName = {
policyId: Cardano.PolicyId('50fdcdbfa3154db86a87e4b5697ae30d272e0bbcfa8122efd3e301cb')
};

export const unexistingAsset: AssetPolicyIdAndName = {
export const nonExistentAsset: AssetPolicyIdAndName = {
name: Cardano.AssetName(''),
policyId: Cardano.PolicyId('c0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a7')
};
Expand All @@ -33,12 +33,12 @@ describe('DbSyncNftMetadataService', () => {
await dbConnection.end();
});

it('returns undefined for unexisting asset', async () => {
expect(await service.getNftMetadata(unexistingAsset)).toBeUndefined();
it('returns null for non-existent asset', async () => {
expect(await service.getNftMetadata(nonExistentAsset)).toBeNull();
});

it('returns undefined for non-nft asset', async () => {
expect(await service.getNftMetadata(nonNftAsset)).toBeUndefined();
it('returns null for non-nft asset', async () => {
expect(await service.getNftMetadata(nonNftAsset)).toBeNull();
});

it('returns nft metadata when it exists', async () => {
Expand Down
15 changes: 8 additions & 7 deletions packages/core/src/Asset/util/metadatumToCip25.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,26 +72,26 @@ const getAssetMetadata = (policy: MetadatumMap, asset: Pick<AssetInfo, 'name'>)

// TODO: consider hoisting this function together with cip25 types to core or a new cip25 package
/**
* @returns {NftMetadata | undefined} CIP-0025 NFT metadata
* @returns {NftMetadata | null} CIP-0025 NFT metadata
*/
export const metadatumToCip25 = (
asset: Pick<AssetInfo, 'policyId' | 'name'>,
metadatumMap: MetadatumMap | undefined,
logger: Logger
): NftMetadata | undefined => {
): NftMetadata | null => {
const cip25Metadata = metadatumMap?.get(721n);
if (!cip25Metadata) return;
if (!cip25Metadata) return null;
const cip25MetadatumMap = asMetadatumMap(cip25Metadata);
if (!cip25MetadatumMap) return;
if (!cip25MetadatumMap) return null;
const policy = asMetadatumMap(cip25MetadatumMap.get(asset.policyId.toString())!);
if (!policy) return;
if (!policy) return null;
const assetMetadata = getAssetMetadata(policy, asset);
if (!assetMetadata) return;
if (!assetMetadata) return null;
const name = asString(assetMetadata.get('name'));
const image = asStringArray(assetMetadata.get('image'));
if (!name || !image) {
logger.warn('Invalid CIP-25 metadata', assetMetadata);
return;
return null;
}
const mediaType = asString(assetMetadata.get('mediaType'));
const files = asMetadatumArray(assetMetadata.get('files'));
Expand All @@ -108,5 +108,6 @@ export const metadatumToCip25 = (
} catch (error: unknown) {
// Any error here means metadata was invalid
logger.warn('Invalid CIP-25 metadata', assetMetadata, error);
return null;
}
};
12 changes: 6 additions & 6 deletions packages/core/test/Asset/util/metadatumToCip25.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@ describe('NftMetadata/metadatumToCip25', () => {
version: '1.0'
};

it('returns undefined for non-cip25 metadatum', () => {
it('returns null for non-cip25 metadatum', () => {
const metadatum: TxMetadata = new Map([[123n, 'metadatum']]);
expect(metadatumToCip25(asset, metadatum, logger)).toBeUndefined();
expect(metadatumToCip25(asset, metadatum, logger)).toBeNull();
});

it('returns undefined for cip25 metadatum with no metadata for given policyId', () => {
it('returns null for cip25 metadatum with no metadata for given policyId', () => {
const metadata: TxMetadata = new Map([[721n, new Map([['other_policy_id', minimalMetadata]])]]);
expect(metadatumToCip25(asset, metadata, logger)).toBeUndefined();
expect(metadatumToCip25(asset, metadata, logger)).toBeNull();
});

it('returns undefined for cip25 metadatum with no metadata for given assetId', () => {
it('returns null for cip25 metadatum with no metadata for given assetId', () => {
const metadatum: TxMetadata = new Map([
[721n, new Map([[asset.policyId.toString(), new Map([['other_asset_id', minimalMetadata]])]])]
]);
expect(metadatumToCip25(asset, metadatum, logger)).toBeUndefined();
expect(metadatumToCip25(asset, metadatum, logger)).toBeNull();
});

it('converts minimal metadata', () => {
Expand Down

0 comments on commit be24ba8

Please sign in to comment.