Skip to content

Commit

Permalink
feat: support json token uri
Browse files Browse the repository at this point in the history
  • Loading branch information
phamphong9981 committed Sep 11, 2024
1 parent ec4280d commit 047cc78
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 10 deletions.
36 changes: 29 additions & 7 deletions src/services/evm/erc721_media_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import { S3Service } from '../../common/utils/s3';
const SUPPORT_DECODED_TOKEN_URI = {
BASE64: 'data:application/json;base64',
};
const TOKEN_URI_FORMAT = {
IPFS: 'IPFS',
BASE64: 'BASE64',
JSON: 'JSON',
};
export interface ITokenMediaInfo {
erc721_token_id: number;
address: string;
Expand Down Expand Up @@ -172,12 +177,31 @@ export async function getMetadata(token_uri: string): Promise<{
image?: string;
animation_url?: string;
}> {
const tokenUriType = detechTokenUriFormat(token_uri);
switch (tokenUriType) {
case TOKEN_URI_FORMAT.BASE64: {
const base64Metadata = token_uri.split(',')[1];
return JSON.parse(fromUtf8(fromBase64(base64Metadata)));
}
case TOKEN_URI_FORMAT.JSON:
return JSON.parse(token_uri);
default: {
const metadata = await downloadAttachment(parseIPFSUri(token_uri));
return JSON.parse(metadata.toString());
}
}
}
function detechTokenUriFormat(token_uri: string) {
if (token_uri.split(',')[0] === SUPPORT_DECODED_TOKEN_URI.BASE64) {
const base64Metadata = token_uri.split(',')[1];
return JSON.parse(fromUtf8(fromBase64(base64Metadata)));
return TOKEN_URI_FORMAT.BASE64;
}
try {
JSON.parse(token_uri);
return TOKEN_URI_FORMAT.JSON;
} catch {
// do nothing
}
const metadata = await downloadAttachment(parseIPFSUri(token_uri));
return JSON.parse(metadata.toString());
return TOKEN_URI_FORMAT.IPFS;
}

// dowload image/animation from url
Expand Down Expand Up @@ -214,9 +238,7 @@ export function parseFilename(media_uri: string) {
}
return parsed.path.substring(1); // http://ipfs.io/ipfs/QmWov9DpE1vYZtTH7JLKXb7b8bJycN91rEPJEmXRXdmh2G/nerd_access_pass.gif
}
if (media_uri.includes('//github.com')) {
return parsed.path.substring(1); // https://github.com/storyprotocol/protocol-core/blob/main/assets/license-image.gif
}
return parsed.path.substring(1); // https://github.com/storyprotocol/protocol-core/blob/main/assets/license-image.gif
}
if (media_uri.startsWith('/ipfs/')) {
return media_uri.substring(1); // /ipfs/QmPAGifcMvxDBgYr1XmEz9gZiC3DEkfYeinFdVSe364uQp/689.png
Expand Down
41 changes: 38 additions & 3 deletions test/unit/services/erc721/erc721-media.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { toBase64, toUtf8 } from '@cosmjs/encoding';
import {
AfterAll,
AfterEach,
BeforeAll,
Describe,
Test,
} from '@jest-decorated/core';
import axios from 'axios';
import { ServiceBroker } from 'moleculer';
import { Config } from '../../../../src/common';
import knex from '../../../../src/common/utils/db_connection';
Expand Down Expand Up @@ -143,9 +145,6 @@ export default class TestErc721MediaService {
expect(parsedNativeUrl).toEqual(`ipfs/${path}`);
expect(parsedIpfsPath).toEqual(`ipfs/${path}`);
expect(parsedHttpPath).toEqual(`ipfs/${path}`);
const httpWrongPath =
'http://ipfs.dev.aura.network:8080/ipfs/Qme33YMXArHQzDdgRxQuL6m7JDJNDKeAUyJXDQU3wnL7s/1000_F_260918513_EtP8xFDBIj4SvHIuXPGdFIyEXyBCmTEq.jpg';
expect(Erc721MediaHanlder.parseFilename(httpWrongPath)).toBeNull();
const subDomain =
'bafybeie5gq4jxvzmsym6hjlwxej4rwdoxt7wadqvmmwbqi7r27fclha2va.ipfs.dweb.link';
const httpSubDomain = `https://${subDomain}`;
Expand Down Expand Up @@ -183,4 +182,40 @@ export default class TestErc721MediaService {
this.mockInitContract_2.tokens.length
);
}

@Test('test getMetadata')
async testGetMetadata() {
const imageUrl =
'ipfs://QmPfi9CcTafv4C1sBZ5HxUs4PbvBi22nkjgqbypMhqaPLp/The_Immersion_Into_Aura_Odyssey.png';
// Case token_uri: ipfs format
const ipfsTokenUri = 'ipfs://QmPf5LawLS1ZVqFTSs7JhFD6yteKQLXxYMEYoc1PcKkhVj/109';
jest.spyOn(axios, 'get').mockImplementation(async () =>
Buffer.from(`{
name: 'Immersion 109',
description:
'The Immersion: Into Aura Odyssey Collection is a collaboration between Micro3 and Aura Network, marking the debut of Aura EVM NFT.',
image: ${imageUrl},
}`)
);
const ipfsMetadata = await Erc721MediaHanlder.getMetadata(ipfsTokenUri);
expect(ipfsMetadata.image).toEqual(imageUrl);
// Case token_uri: json
const jsonTokenUri = `{"name": "Mahojin NFT #20", "description": "Mahojin NFT!", "image": "${imageUrl}"}`;
const jsonMetadata = await Erc721MediaHanlder.getMetadata(jsonTokenUri);
expect(jsonMetadata.image).toEqual(imageUrl);
// Case token_uri: base64
const metadata = {
name: 'Color Commemorative Launch NFT #999999',
description:
'Color Commemorative NFT to celebrate the launch of Story Testnet',
external_url: 'https://colormp.com/',
image: imageUrl,
attributes: [{ trait_type: 'Serial Number', value: '999999' }],
};
const base64TokenUri = `data:application/json;base64,${toBase64(
toUtf8(JSON.stringify(metadata))
)}`;
const base64Metadata = await Erc721MediaHanlder.getMetadata(base64TokenUri);
expect(base64Metadata.image).toEqual(imageUrl);
}
}

0 comments on commit 047cc78

Please sign in to comment.