let container;
const oneOfOnes = [
['365c7fe2007cd8eff36137f38142d2fef882d7f2121de959999aab2ecfdbc661i0', "Bearable Guy", 25],
['58b7218b03107c25566f05c720d917e3e1dba838a7aa62dca48b5cd15a0315bdi0', "Bird 1", 30],
['d9b5945836405f9561135100377c16f99d0840b7111a41c6ff353a971d55b690i0', "Bird 2", 24],
['1c1aeff53d127cc4dd237b5a43a3dafdff09673c53ace055b74d4973db7fce6di0', "Black and White", 23],
['06e7359fd120eefe9b5798c2355e6a77993eec787d4c6d05e2c01e7ff402a6b8i0', "Christmas", 23],
['a4eb37ad9fb96c8a83dc124ac9fe74885475700b8fc3fca209c1f3116861786ci0', "Gold", 23],
['c78f06a97c60f39567fe9256ba7f311cbbee80360095c50f23c7982db924701ai0', "Harry Potter", 23],
['66d8638ed3102afbc6da515ab70a34ed0a7cafe00ac5687ac5e6b9a594966f8di0', "King", 29],
['f417bbc5dc18cdafedbf3c898448421408130084563a01246090a94e930e4225i0', "Long Ear", 29],
['26386c657081287b40c3464c3109d0dbfef2685c07919482c5b5c9c3a8e36922i0', "Snow Owl", 23],
['4b61a0aad3d332f538059e7c933039bb9181713701f00654c1a50eec4397e573i0', "Steve", 23],
['3c76be763011194e8aaed09efdc844f7164be04aa06af8c1e63bf080474c0bf5i0', "USA", 23],
['929ca1c9d850c1c39d2dd61889d3b85c95f9fadd1ec48311e0e599fe65311e50i0', "Ripple 1", 23],
['8cd54503c025932887a38fb188605867a86790f17a96a180bc44dab7e4711817i0', "Ripple 2", 23],
['7bef50a6cc4ce413542a806d4506c8f00add5bb6781b4353ca2a0b6c6f62d6cei0', "Ripple 3", 23],
['379afb187ca56c3d9b07c39b18665c17c3c66784a705b0e099c875a892bb742fi0', "Ripple 4", 23],
['6e67ff1451ca44b8780f0341ba06d862b3e218f7b1fa83e0465055568f9b442ci0', "Ripple 5", 23]
];
async function loadAndModify() {
const result = await processUrl1of1();
const match = result.match;
let collectionIndex = result.collectionIndex;
// Define constants for ID mapping
const MIN_ID = 1112;
const MAX_ARRAY_INDEX = oneOfOnes.length - 1;
const MAX_ID = MIN_ID + MAX_ARRAY_INDEX;
if (match) {
// For metadata URLs, extract the exact ID from the URL to display
let displayId = collectionIndex;
const hashString = window.location.hash;
// If this is a hash metadata URL like #metadata/1120.json
if (hashString && hashString.includes("metadata")) {
const idMatch = hashString.match(/metadata\/(\d+)\.json/);
if (idMatch && idMatch[1]) {
// Use the EXACT number from the URL for display
displayId = parseInt(idMatch[1]);
}
}
// Validate collectionIndex for metadata
if (typeof collectionIndex !== 'number' || isNaN(collectionIndex) ||
collectionIndex < MIN_ID || collectionIndex > MAX_ID) {
console.error(`Invalid collectionIndex (${collectionIndex}) from URL for metadata. Expected range [${MIN_ID}-${MAX_ID}]. Halting operation.`);
return;
}
// Calculate array index from collection index (public ID)
const arrayIndex = collectionIndex - MIN_ID;
const description = `BRC333 cross-chain ${collectionName} One-of-Ones backed by Bitcoin!`;
const jsonOutput = {
"name": `${collectionName} #${displayId}`,
"image": `https://ordinals.com/content/${oneOfOnes[arrayIndex][0].trim()}`,
"collection": {
"name": `${collectionName}`,
"description": `${description}`
},
"attributes": [
{
"trait_type": "One of One",
"value": `${oneOfOnes[arrayIndex][1]}`
}
]
};
const jsonString = JSON.stringify(jsonOutput, null, 2);
displayJsonOutput(jsonString);
return;
}
// --- Canvas Display Logic ---
jsonOutputDiv.style.display = 'none';
canvas.style.display = 'block';
// Determine correct array index based on collectionIndex
// If collectionIndex is a large value (1112+), assume it's intended as a display ID and convert to array index
// Otherwise if it's small (0-17), use it directly as an array index
let arrayIndex;
if (collectionIndex >= MIN_ID) {
// Convert from display ID (1112+) to array index (0+)
arrayIndex = collectionIndex - MIN_ID;
} else {
// Use as direct array index, but ensure it's valid
arrayIndex = collectionIndex;
}
// Final validation to prevent "Cannot read properties of undefined"
if (typeof arrayIndex !== 'number' || isNaN(arrayIndex) || arrayIndex < 0 || arrayIndex > MAX_ARRAY_INDEX) {
console.warn(`Canvas: Calculated array index (${arrayIndex}) is invalid or out of bounds. Defaulting to 0.`);
arrayIndex = 0;
}
canvas.width = oneOfOnes[arrayIndex][2];
canvas.height = oneOfOnes[arrayIndex][2];
const ctx = canvas.getContext('2d');
if (!ctx) {
console.error('Failed to get 2D rendering context for the canvas');
return;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
const img = new Image();
img.src = `/content/${oneOfOnes[arrayIndex][0].trim()}`;
img.onload = () => {
if (ctx && canvas) {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
} else {
console.error('Canvas context or element became unavailable during image load.');
}
};
img.onerror = () => {
console.error(`Failed to load image for X-Owl at index ${arrayIndex}: ${img.src}`);
if (ctx) {
ctx.fillStyle = 'lightgray';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.textAlign = 'center';
ctx.font = '16px Arial';
ctx.fillText('Image failed to load', canvas.width / 2, canvas.height / 2);
}
};
setFavicon(oneOfOnes[arrayIndex][0].trim());
}
/**
* Sets the canvas as the favicon
* @param {string} id - The id of the ordinal to use as favicon
*/
async function setFavicon(id) {
const url = `/content/${id.trim()}`;
const response = await fetch(url);
const blob = await response.blob();
const faviconCanvas = document.createElement('canvas');
const ctx = faviconCanvas.getContext('2d');
const img = new Image();
img.onload = () => {
faviconCanvas.width = img.width;
faviconCanvas.height = img.height;
ctx.drawImage(img, 0, 0);
const favicon = document.createElement('link');
favicon.rel = 'icon';
favicon.href = faviconCanvas.toDataURL();
document.head.appendChild(favicon);
};
img.src = URL.createObjectURL(blob);
}
/**
* Displays JSON output in the designated HTML elements.
* @param {string} jsonString - The JSON string to be displayed.
*/
function displayJsonOutput(jsonString) {
const jsonOutputDiv = document.getElementById('jsonOutput');
const jsonTextPre = document.getElementById('jsonText');
if (jsonOutputDiv && jsonTextPre) {
jsonTextPre.textContent = jsonString;
jsonOutputDiv.style.display = 'block';
} else {
console.error('JSON output elements not found in the DOM.');
}
}
/**
* Processes the current URL to extract collection and block information.
* @param {string|null} [testingUrl=null] - Optional testing URL.
* @returns {Promise