Skip to main content
Glama

Stampchain MCP Server

Official
transformers.ts7.46 kB
/** * Data transformation utilities * These utilities help transform between different data formats */ import type { Stamp, Collection, Token } from '../schemas/index.js'; import type { StampResponse, CollectionResponse, TokenResponse } from '../api/types.js'; /** * Transform API stamp response to internal stamp type * (In this case they're the same, but this provides a layer of abstraction) */ export function transformStampResponse(response: StampResponse): Stamp { return response.data.stamp; } /** * Transform API collection response to internal collection type */ export function transformCollectionResponse(response: CollectionResponse): Collection { return response; } /** * Transform API token response to internal token type */ export function transformTokenResponse(response: TokenResponse): Token { return response; } /** * Group stamps by creator */ export function groupStampsByCreator(stamps: Stamp[]): Map<string, Stamp[]> { const grouped = new Map<string, Stamp[]>(); for (const stamp of stamps) { const creator = stamp.creator; if (!grouped.has(creator)) { grouped.set(creator, []); } grouped.get(creator)!.push(stamp); } return grouped; } /** * Group stamps by collection */ export function groupStampsByCollection(stamps: Stamp[]): Map<string | null, Stamp[]> { const grouped = new Map<string | null, Stamp[]>(); for (const stamp of stamps) { // Note: Individual stamps don't have collection_id in the API schema // Collections reference stamps by ID, not the other way around const collectionId = null; if (!grouped.has(collectionId)) { grouped.set(collectionId, []); } grouped.get(collectionId)!.push(stamp); } return grouped; } /** * Calculate statistics for a set of stamps */ export function calculateStampStats(stamps: Stamp[]) { if (stamps.length === 0) { return { count: 0, totalSupply: 0, averageSupply: 0, uniqueCreators: 0, uniqueCollections: 0, cursedCount: 0, btcStampCount: 0, lockedCount: 0, totalFloorValueBTC: 0, totalFloorValueUSD: 0, }; } const creators = new Set<string>(); const collections = new Set<string>(); let totalSupply = 0; let cursedCount = 0; let btcStampCount = 0; let lockedCount = 0; let totalFloorValueBTC = 0; let totalFloorValueUSD = 0; for (const stamp of stamps) { creators.add(stamp.creator); // Note: Individual stamps don't have collection_id in API schema // Collection grouping would need to be done via separate collection API calls totalSupply += stamp.supply ?? 0; if (stamp.stamp ?? 0 < 0) { cursedCount++; } else { btcStampCount++; } if (stamp.locked === 1) { lockedCount++; } if (typeof stamp.floorPrice === 'number') { totalFloorValueBTC += stamp.floorPrice * (stamp.supply ?? 0); } if (stamp.floorPriceUSD) { totalFloorValueUSD += stamp.floorPriceUSD * (stamp.supply ?? 0); } } return { count: stamps.length, totalSupply, averageSupply: totalSupply / stamps.length, uniqueCreators: creators.size, uniqueCollections: collections.size, cursedCount, btcStampCount, lockedCount, totalFloorValueBTC, totalFloorValueUSD, }; } /** * Sort stamps by various criteria */ export function sortStamps( stamps: Stamp[], sortBy: 'id' | 'created' | 'supply' | 'price' = 'id', order: 'ASC' | 'DESC' = 'DESC' ): Stamp[] { const sorted = [...stamps]; sorted.sort((a, b) => { let comparison = 0; switch (sortBy) { case 'id': comparison = (a.stamp ?? 0) - (b.stamp ?? 0); break; case 'created': comparison = a.block_index - b.block_index; break; case 'supply': comparison = (a.supply ?? 0) - (b.supply ?? 0); break; case 'price': { const priceA = typeof a.floorPrice === 'number' ? a.floorPrice : 0; const priceB = typeof b.floorPrice === 'number' ? b.floorPrice : 0; comparison = priceA - priceB; break; } } return order === 'ASC' ? comparison : -comparison; }); return sorted; } /** * Filter stamps by various criteria */ export interface StampFilters { minId?: number; maxId?: number; creator?: string; collectionId?: string; isCursed?: boolean; isLocked?: boolean; hasFloorPrice?: boolean; minSupply?: number; maxSupply?: number; mimeTypes?: string[]; } export function filterStamps(stamps: Stamp[], filters: StampFilters): Stamp[] { return stamps.filter((stamp) => { if (filters.minId !== undefined && (stamp.stamp ?? 0) < filters.minId) { return false; } if (filters.maxId !== undefined && (stamp.stamp ?? 0) > filters.maxId) { return false; } if (filters.creator && stamp.creator !== filters.creator) { return false; } // Note: collection_id filtering not supported at stamp level // Would need separate collection API call to filter by collection if (filters.collectionId) { // Skip collection filtering for now as stamps don't have collection_id return false; } if (filters.isCursed !== undefined) { const isCursed = stamp.stamp ?? 0 < 0; if (filters.isCursed !== isCursed) { return false; } } if (filters.isLocked !== undefined && (stamp.locked === 1) !== filters.isLocked) { return false; } if (filters.hasFloorPrice !== undefined) { const hasPrice = stamp.floorPrice !== null && stamp.floorPrice !== 0; if (filters.hasFloorPrice !== hasPrice) { return false; } } if (filters.minSupply !== undefined && (stamp.supply ?? 0) < filters.minSupply) { return false; } if (filters.maxSupply !== undefined && (stamp.supply ?? 0) > filters.maxSupply) { return false; } if (filters.mimeTypes && !filters.mimeTypes.includes(stamp.stamp_mimetype)) { return false; } return true; }); } /** * Convert stamp to a shareable URL format */ export function stampToShareableURL(stamp: Stamp, baseURL = 'https://stampchain.io'): string { return `${baseURL}/stamp/${stamp.stamp ?? 0}`; } /** * Extract unique values from stamps for filtering options */ export function extractFilterOptions(stamps: Stamp[]) { const creators = new Set<string>(); const collections = new Set<string>(); const mimeTypes = new Set<string>(); for (const stamp of stamps) { creators.add(stamp.creator); // Note: Individual stamps don't have collection_id in API schema // Collection grouping would need to be done via separate collection API calls mimeTypes.add(stamp.stamp_mimetype); } return { creators: Array.from(creators).sort(), collections: Array.from(collections).sort(), mimeTypes: Array.from(mimeTypes).sort(), }; } /** * Paginate an array of items */ export function paginate<T>( items: T[], page: number, pageSize: number ): { items: T[]; totalPages: number; currentPage: number; totalItems: number } { const totalItems = items.length; const totalPages = Math.ceil(totalItems / pageSize); const currentPage = Math.min(Math.max(1, page), totalPages); const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; return { items: items.slice(startIndex, endIndex), totalPages, currentPage, totalItems, }; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stampchain-io/stampchain-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server