this service is a REST API microservice that serves Solana token metadata. its designed to abstract away how that metadata is handled and service a common interface regardless of if traditional metaplex, token metadata extensions, or metaplex core is used.
metadata-service/
├── dist/ # compiled javascript files (output)
├── src/ # typescript source code
│ ├── api/ # express routes and controllers
│ │ └── metadata.ts # logic for the /metadata endpoint
│ ├── services/ # core business logic
│ │ └── solana.ts # the token metadata fetching logic
│ └── index.ts # entry point of the application (express server setup)
├── .env # environment variables (e.g., rpc_url)
├── .gitignore # to ignore node_modules, dist, .env, etc.
├── package.json # project dependencies and scripts
└── tsconfig.json # typescript compiler options
a single GET endpoint exists:
- endpoint:
/metadata/:mintAddress - method:
GET - description: Retrieves metadata for a given Solana token mint address.
- success Response (200 OK):
{ "name": "Wrapped SOL", "symbol": "SOL", "uri": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png", "program": "METAPLEX" } - error eesponse (404 Not Found):
{ "error": "metadata not found for mint address: [mintAddress]" } - error response (400 Bad Request):
{ "error": "invalid mint address provided" }
example success response:
{
"name": "Pump",
"symbol": "PUMP",
"uri": "https://ipfs.io/ipfs/QmaLStp4G2a8iCMM22p4co57nL37m3s237229aMWpD2mXg",
"program": "TOKEN_2022"
}here is an example of how you can call the API from a ts application.
interface TokenMetadata {
name: string;
symbol: string;
uri: string;
program: 'METAPLEX' | 'TOKEN_2022' | 'CORE';
}
async function fetchMetadata(mintAddress: string): Promise<TokenMetadata | null> {
try {
const response = await fetch(`http://localhost:3000/metadata/${mintAddress}`);
if (!response.ok) {
console.error(`Error: ${response.status} - ${response.statusText}`);
return null;
}
const metadata: TokenMetadata = await response.json();
return metadata;
} catch (error) {
console.error('Failed to fetch metadata:', error);
return null;
}
}
// usage:
const mintAddress = 'pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn';
fetchMetadata(mintAddress).then(metadata => {
if (metadata) {
console.log('Successfully fetched metadata:', metadata);
}
});