Skip to content

Instantly share code, notes, and snippets.

@ordengine
Created June 1, 2025 15:50
Show Gist options
  • Select an option

  • Save ordengine/78d40c0e3f54d17a96d16aa9efcded26 to your computer and use it in GitHub Desktop.

Select an option

Save ordengine/78d40c0e3f54d17a96d16aa9efcded26 to your computer and use it in GitHub Desktop.
import express from 'express';
import { createServer } from 'http';
import cors from 'cors'
const app = express();
const server = createServer(app);
app.use(cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'upgrade-insecure-requests'],
credentials: false,
}));
/// set with your API key
const headers = { "Authorization": "Bearer MaGiCeDeN-aPi-KeY" };
async function fetchOwnedBitmaps(address) {
const fetch = await import('node-fetch');
let offset = 0;
let done = false;
const bitmaps = [];
try {
while (!done) {
console.log(`Fetching owned bitmaps for ${address}, offset ${offset}`);
const response = await fetch.default(
`https://api-mainnet.magiceden.dev/v2/ord/btc/tokens?collectionSymbol=bitmap&ownerAddress=${address}&limit=100&offset=${offset}&showAll=true`,
{ headers }
);
if (!response.ok) {
throw new Error(`API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
if (!data.tokens || data.tokens.length === 0) {
console.log(`No more owned bitmaps found for ${address}`);
done = true;
continue;
}
console.log(`Got ${data.tokens.length} owned bitmaps for ${address}`);
data.tokens.forEach(d => bitmaps.push(parseInt(d.meta.name.split('.')[0])));
offset += 100;
done = data.tokens.length < 100;
}
console.log(`Completed fetching ${bitmaps.length} owned bitmaps for ${address}`);
return bitmaps;
} catch (error) {
console.error(`Error fetching owned bitmaps for ${address}:`, error);
return bitmaps;
}
}
let ownedBitmapsCache = {};
const fetchingOwnedStatus = new Map();
const lastForceUpdate = new Map();
async function getOwnedBitmaps(address, forceUpdate = false) {
if (address === 'bc1qptgujmlkez7e6744yctzjgztu0st372mxs6702') {
// large merlin address, serve from cache to prevent lag
return [];
}
if (!forceUpdate && ownedBitmapsCache[address]) {
console.log(`Returning cached owned bitmaps for ${address}`);
return ownedBitmapsCache[address];
}
if (forceUpdate) {
const lastUpdate = lastForceUpdate.get(address);
const now = Date.now();
const min10 = 10 * 60 * 1000;
if (lastUpdate && (now - lastUpdate < min10)) {
console.log(`Force update skipped for ${address}, too soon, serving cached data`);
return ownedBitmapsCache[address] || [];
}
}
if (fetchingOwnedStatus.get(address)) {
console.log(`Fetch in progress for ${address}, returning cached data`);
return ownedBitmapsCache[address] || [];
}
fetchingOwnedStatus.set(address, true);
console.log(`Starting fetch for ${address}, active fetches: ${fetchingOwnedStatus.size}`);
try {
const bitmaps = await fetchOwnedBitmaps(address);
if (bitmaps.length > 0) {
ownedBitmapsCache[address] = bitmaps;
if (forceUpdate) lastForceUpdate.set(address, Date.now());
console.log(`Caching ${bitmaps.length} owned bitmaps for ${address}`);
}
return bitmaps;
} finally {
fetchingOwnedStatus.delete(address);
console.log(`Finished fetch for ${address}, active fetches: ${fetchingOwnedStatus.size}`);
}
}
app.get('/owned/:address', async (req, res) => {
const bitmaps = await getOwnedBitmaps(req.params.address);
res.json(bitmaps);
});
app.get('/owned/:address/force', async (req, res) => {
const bitmaps = await getOwnedBitmaps(req.params.address, true);
res.json(bitmaps);
});
const port = process.env.PORT || 3000
app.listen(port, () => console.log(`Server running on port ${port}`))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment