2 6 e 2 8 3 f 6 e f
e 8 1 ░▓9▓▓ 0 1 8 0 4 c 8 f 7 0
5 3 0 ░█4██░ 0 9 8 d b b 4 1 0 8
9 8 a 2▒█░ f 3 c 5 c 6 a d 7 3
4 c 8 6▒█░ 5 4 d b e a 2 a 1 c
▓█ 4 ▒█ a ▓███▓3 b▒█░ a ░██c██▒ b ▓███▓░9 ▓█░█f▓ ▓██ 1 ▓███c d 8 0
▓█ 3 ▓█ 7 ██▓▒▒█9 e▒█░ 2 ▓██▒9▒▓▒ 4██▒▒▒██0 ▓██▒d██▓▓█▒ 8 ██▓▒▒0█ 6 d b
▒█░ 3 ██ 8▒█▒ ░5▓ e▒█░ 5 ░█▓ 8 7█░ ░█a ▓█▓ a██ █▓ 7 ▒█▒ 0█▓ a 1 b
░█▒ ░e▒ █▓ 8██ 6█ d▒█░ 8 ██ c ░3█ ▓5░ ▓█ 1█▒ █▓ 1 ██ 6██ 2 6 b
█▒ ▓e█ █▒ b██▓▓▓▓▓c█░ a▒█░ 8 ██ 1 ▒2▒ ░d▒ ▓█ 7█▒ █▓ 2 ██▓▓▓▓1██░ 6 0 8
█▓ █7█▒░█▒ 3██▓▓▓▓▓b▓ d▒█░ f ██ 5 ▒2▒ ░e▒ ▓█ 8█▒ █▓ c░██▓▓▓▓f▓▓ 4 8 6
█▓▒█8▓█░█░ 8██ 2 9▒█░ 6 ██ c ▒1▒ ░5▒ ▓█ 2█▒ █▓ 9 ██ e 7 0 c
▓██▓f ███ 5██ a d▒█░ f ██░ 9 ░2█ ▓d░ ▓█ 6█▒ █▓ 3 ██ 2 4 c a
▒██ a ▓██ b▒█▓ 8 6▒█░ d ▒██ 0 3█░ ░█b ▓█ e█▒ █▓ a ▒█▓ 0 3 f d
▒█▓ 1 ░██ f ▓██▒░▒6▒ f▒█▓▒▒ 9 ▓██▒8░▒▒ 3██▒░▒██a ▓█ d█▒ █▓ e ▓██▒░7▓▒ c 5 8
░█░ 2 █▓ 4 ▒████7▒ 7▒████ 6 ▒██d██▓ c░▓████░b ▓█ 2█▒ █▓ c ▒███7█▒ a d 0
4 e 9 1 f 1 e a a 0 d 8 c d
0 0 6 1 e b b 9 c b 3 e 3 e
a 0 1 b d 8 4 3
2 5 e 2 7 2 d 6 0 3
▒▓ 8 ▓▓ e ▓▓▓▓▓▓f░ ▓3 1 ▓░ 9 6 ▒███▒ a 2 0 8 5░ e d
██ 1 ██ 4░██████d▒ ░█c f ░█▒ c 4███▓███4 7 f 5 9█░ 8 9
██ e ██ d░█▒ 8 ░█6 6 ░█▒ d a█▓ ▒█a c c 0 a▓█ 9 3
██ 0 ██ 8░█▒ e ░█f 2 ░█▒ 6 a█ █f c 7 e 1 ██ 2 8
██ 0 ██ 5░█▒ 5 ░█6 6 ░█▒ 2 ░3▓ ▒6▒ 3█▒ b e c ▒█▒ 0 5
██ 2 ██ 5░█▒ 9 ░█2 2 ░█▒ d ▒3▒ ░e▒ f██ e 1 d ██ 7 5
████e████ 4░██▓▓▓▓0░ ░█2 d ░█▒ 8 ▓f▒ ░1▓ 4▒ 4 6 8 ▓█ b f
██▓▓2▓▓██ e░██████c░ ░█a 8 ░█▒ 4 ▓9░ ░1▓ 9 f 1 0 ▓█░ 4 0
██ 5 ██ 9░█▒ f ░█a 3 ░█▒ a ▓0░ ░5▓ 4 6 ▒▓▓▓▓5▒ c ▒█▒ c a
██ b ██ 1░█▒ 6 ░█1 0 ░█▒ d ▓2▒ ░a▓ 1 3 ▓████4▓ 8 ▒█▒ 9 3
██ c ██ e░█▒ d ░█7 4 ░█▒ a ▒a▓ ▒e▒ b d c 3 ▓█░ 7 3
██ c ██ c░█▒ a ░█5 3 ░█▒ 8 0█ █1░ 8 4 d 9 ▓█ c 6
██ f ██ 8░█▒ f ░█a f ░█▒ 0 1█▒ ░█5 f▒ f 0 4 ██ 2 b
██ 2 ██ 4░██▓▓▓▓8▒ ░█3▓▓▓▓▓▓ 5 ░██▓▓8▓▓▓ 1██▓▒▓██8 9██ 2 7 a ▒█▒ b c
▓█ f ██ d░██████a▒ ░█0██████ 1 ░████4███ 9░▓████░f f█▒ d 8 f ██ 7 7
c 8 5 3 b 0 c 9 6 4 6 2▓█ e b
8 0 6 0 f 1 1 9 3 3 6 4█░ 6 e
2 e a a a 3 9 f ▓░
2 b a c b c 2 9 e 2
▒▓▓▓b▓▓▓▓ 2▒▓ 9▒▓ ▓0▓▓▓▓▓▒ 7 ▒▓ e ▓▓ ▓c▓▓▓▓▓▓▓d▓ ▒▓ 0 ▓▓ 6 ▒▓▓▓▓▓8 b▓▓▓▓▓▓░c 2
▓███f████ f██ 8█▓ ░█2█████▓ d ██ 0 ██ █0███████3█ ██ 9 ██ c ██████a█ ░6██████▒5 b
b ▒█▓ 7██ ▒e▓ ░█d 2 ██ 4 ██ 4 ░█▒ 8 ██ 6 ██ a ██ d██ ░9▒ 4 a
9 ██ 0██ ▒█6 ░█8 6 ██ c ██ 4 ░█▒ c ██ 6 ██ 2 ██ f██ ░2▒ 1 f
e▒█░ 9██ ▒█▓c ░█d 0 ██ 6 ██ e ░█▒ c ██ 9 ██ e ██ 8██ ░3▒ c a
6█▓ 1██ ░██ e ░█b 3 ██ 5 ██ c ░█▒ 3 ██ b ██ f ██ 8██ ░0▒ c e
b█░ 3██▒██ 8 ░█d▒▒▒▒▒ e ██ f ██ a ░█▒ b ██ 9 ██ 4 ██░░░▒d█░ ░e█▓▓▓▓▓░0 4
▒9▓ b█████▓ 6 ░█2█████░ c ██ f ██ 1 ░█▒ c ██ 3 ██ 8 ██████5░ ░8██████░4 f
█c e███░██░d ░█1 f ██ c ██ 2 ░█▒ 6 ██ f ██ d ██▒░██9 ░9▒ d 5
▓█8 c██░ ░██5 ░█5 3 ██ 9 ██ 7 ░█▒ b ██ c ██ 4 ██ ░█c ░0▒ b e
█▓9 9██ ▒█c ░█2 a ██ 4 ██ a ░█▒ d ██ 0 ██ b ██ ▓e▒ ░b▒ 6 1
▓█ b 8██ █8▒ ░█b 9 ▓█░ b ██ 2 ░█▒ 5 ▓█░2 ██ d ██ 5█░ ░8▒ 1 1
▒█▒ 0 7██ c█░ ░█d a ▒█▒ 0▒█▓ c ░█▒ 6 ▒█▒2 ▒█▓ a ██ b██ ░1▒ a d
██▓▓1▓▓▓▓ a██ b██ ░█8 0 ██▓▒4██░ 2 ░█▒ 2 ██e▒▒██░ 9 ██ 7▓█▓ ░3█▓▓▓▓▓▒9 3
████f████ b▓█ 3▓█ ░█0 3 ▓██6█░ 4 ░█▒ 6 ▓7███░ 9 ▓█ 2 ██ ░6██████▒e 7
0 3 7 c 7 8 6 7 7 2 2 3 a 7
2 5 d 5 3 4 e 1 a 6 6 5 d 8
c c 4 1 3 7 b a
DecentralizedOperatingSystemCaller is not escrow contractBoth slots must be claimedInvalid escrow addressSlot already claimedSlot already takenSoulBound : Transfer failedDude has no secret wordPUPPPPPPPPPPPPV[`0123456789abcdefhttps://ethereum-rpc.publicnode.comwss://ethereum-rpc.publicnode.com
Only CypherDudesOffer must be > 0Can't offer on own tokennew Offer must be higher than th`DMarketplace not approvedMarketplace not approvedPrice must be > 0ReentrancyGuard: reentrant callRoyalty transfer failedETH transfer failedETH transfer failed
Titles have to be uniqueArchive already storedYou're not the curatorCuration not foundMust be future dateMust be exactly 12:00 UTCSlot already bookedAllowance exceeded for this mont`D0123456789abcdef
DecentralizedOperatingSystemCaller is not escrow contractBoth slots must be claimedInvalid escrow addressSlot already claimedSlot already takenSoulBound : Transfer failedDude has no secret word[PPPP[PPPPPPPPPPPV[`0123456789abcdefhttps://ethereum-rpc.publicnode.comwss://ethereum-rpc.publicnode.com
"h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h\O04040404040404040404040404040404040404040404040404040404040404jehckhhd04040404040404040404040404040404040404040404040404040404040404jeh$bh`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`hbh`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h'14040404040404040404040404040404040404040404040404040404040404jehch`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`hah`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`hch`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h04040404040404040404040404040404040404040404040404040404040404jvah`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h`h14040404040404040404040404040404040404040404040404040404040404jeht+04040404040404040404040404040404040404040404040404040404040404jeht
DOS_loader
var base = Math.min(20000, 500 * Math.pow(2, attempt || 0));
ep.cooldownUntil = Date.now() + base / 2 + Math.random() * (base / 2);
}
};
var rpcPool = window.rpcPool;
window.rpcSleep = function (ms) { return new Promise(function (r) { setTimeout(r, ms); }); };
var rpcSleep = window.rpcSleep;
// First working RPC from the RPCs array: first endpoint not cooling down
// (i.e. not recently failed / rate-limited), else the first configured one.
// Use this wherever a single endpoint is needed (e.g. callContract).
window.firstWorkingRpc = function () {
var eps = window.rpcPool.endpoints();
var now = Date.now();
for (var i = 0; i < eps.length; i++) if (eps[i].cooldownUntil <= now) return eps[i].url;
return eps.length ? eps[0].url : "";
};
// Run fn(item, rpcUrl) over items with one worker per endpoint (recompose's
// worker-pool U()). Failed items retry on another endpoint up to `retries`.
window.parallelRpcMap = async function (items, fn, opts) {
var retries = (opts && opts.retries != null) ? opts.retries : 3;
var eps = rpcPool.endpoints();
if (!eps.length) { // no pool — degrade to sequential on the first rpc
for (var k = 0; k < items.length; k++) {
try { await fn(items[k], window.firstWorkingRpc()); }
catch (e) { console.warn('parallelRpcMap:', items[k], e); }
}
return;
}
var next = 0;
var workers = Array.from({ length: Math.min(eps.length, items.length) }, async function () {
while (next < items.length) {
var i = next++;
for (var a = 0; ; a++) {
var picked = rpcPool.pick();
if (picked.waitMs > 0) await rpcSleep(picked.waitMs);
try { await fn(items[i], picked.ep.url); break; }
catch (e) {
rpcPool.cooldown(picked.ep, a);
if (a >= retries) { console.warn('parallelRpcMap: item failed', items[i], e); break; }
}
}
}
});
await Promise.all(workers);
};
/* --------------------------------------------- scripty getContent (eth_call) */
// Self-contained minimal ABI encode/decode: the loader runs BEFORE
// COS_ethCalls.js (which is itself in the script list above).
// ABI-encode getContent(string name, bytes data) with data == empty bytes (0x).
// Head: two offset words; tail: string (len + padded utf8), then bytes (len 0).
function encodeGetContent(name) {
function word(n) { return n.toString(16).padStart(64, "0"); }
var utf8 = new TextEncoder().encode(name);
var hex = "";
for (var i = 0; i < utf8.length; i++) hex += utf8[i].toString(16).padStart(2, "0");
var padded = hex.padEnd(Math.max(64, Math.ceil(hex.length / 64) * 64), "0");
var strTail = word(utf8.length) + padded; // string: len + data
return GETCONTENT_SELECTOR +
word(0x40) + // offset of string
word(0x40 + strTail.length / 2) + // offset of bytes
strTail +
word(0); // bytes: len 0 (== '0x')
}
// Decode a single ABI `bytes` return into a 0x-prefixed hex blob.
function decodeBytesReturn(result) {
if (!result || result === "0x") throw new Error("empty result");
var h = result.slice(2);
var off = parseInt(h.slice(0, 64), 16) * 2;
var len = parseInt(h.slice(off, off + 64), 16) * 2;
if (!len) throw new Error("content not stored");
return "0x" + h.slice(off + 64, off + 64 + len);
}
// One eth_call: ScriptyStorageV2.getContent(name, 0x) on a given endpoint.
async function ethGetContent(name, rpcUrl) {
var payload = {
jsonrpc: "2.0",
method: "eth_call",
params: [{ to: SCRIPTY_ADDRESS, data: encodeGetContent(name) }, "latest"],
id: 1
};
var r = await fetch(rpcUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
if (!r.ok) throw new Error("HTTP " + r.status);
var json = await r.json();
if (json.error) throw new Error("RPC Error: " + json.error.message);
return decodeBytesReturn(json.result);
}
/* ------------------------------------------------- parallel prefetch pool */
// Same principle as recompose.min.js / the world's slot loader: all
// getContent calls are dispatched up-front through the RPC pool (one worker
// per endpoint, paced, retried across endpoints with cooldown), while
// INJECTION stays strictly sequential — script order matters for execution,
// but the network wait is fully overlapped.
function prefetchAll(scripts) {
var RETRIES = 3;
var resolvers = scripts.map(function () { return {}; });
var promises = scripts.map(function (_, i) {
return new Promise(function (res, rej) { resolvers[i].res = res; resolvers[i].rej = rej; });
});
async function fetchOne(sc) {
var lastErr = null;
var hasPool = rpcPool.endpoints().length > 0;
for (var a = 0; hasPool && a <= RETRIES; a++) {
var picked = rpcPool.pick();
if (picked.waitMs > 0) await rpcSleep(picked.waitMs);
try {
return await ethGetContent(sc.data, picked.ep.url);
} catch (e) {
lastErr = e;
rpcPool.cooldown(picked.ep, a);
}
}
// Local-dev fallback: `data` may be a plain URL/path (e.g. a .txt or .gz
// served next to the page). Try a direct fetch before giving up.
try {
var r = await fetch(sc.data);
if (!r.ok) throw new Error("HTTP " + r.status);
return await r.text();
} catch (e) {
throw lastErr || e;
}
}
var next = 0;
function worker() {
if (next >= scripts.length) return Promise.resolve();
var i = next++;
return fetchOne(scripts[i])
.then(function (txt) { resolvers[i].res(txt); })
.catch(function (err) { resolvers[i].rej(err); })
.then(worker);
}
var workers = [];
var n = Math.max(1, Math.min(rpcPool.endpoints().length || 1, scripts.length));
for (var w = 0; w < n; w++) workers.push(worker());
return promises;
}
/* -------------------------------------------------------------------- finish */
var finished = false;
function finish() {
if (finished) return;
finished = true;
markDone(curLine);
setProgress(1);
if (!el.root) return;
el.root.classList.add("dos-hide");
setTimeout(function () {
if (el.root && el.root.parentNode) el.root.parentNode.removeChild(el.root);
}, 900);
}
// Wait for the world to signal readiness (window.__WORLD_READY, set at the end
// of init() once the scene is built and the render loop has started).
//
// The modules finish injecting well before the world is actually painted (the
// world spends a few seconds fetching slot data + building geometry). Rather
// than fade on a timer and expose a white screen, we keep the splash up and
// show a "World reconstruction" phase: the radar keeps sweeping and the counter
// shows the elapsed reconstruction time, until __WORLD_READY (or the hard cap).
function awaitWorld() {
if (window.__WORLD_READY) return finish();
// Stop the progress easing so it doesn't fight the reconstruction spin.
if (raf) { cancelAnimationFrame(raf); raf = 0; }
addLine("World reconstruction");
var start = Date.now();
var spinRaf = 0;
(function spin() {
var elapsed = (Date.now() - start) / 1000;
// ~0.55 turn/sec continuous sweep (indeterminate — we can't know the total).
if (el.radar) el.radar.setAttribute("transform", "rotate(" + ((elapsed * 200) % 360).toFixed(2) + " 256 256)");
if (el.pct) el.pct.textContent = elapsed.toFixed(1) + "s";
spinRaf = requestAnimationFrame(spin);
})();
(function poll() {
if (window.__WORLD_READY || Date.now() - start > READY_TIMEOUT_MS) {
if (spinRaf) cancelAnimationFrame(spinRaf);
return finish();
}
setTimeout(poll, 120);
})();
}
/* ---------------------------------------------------------------------- boot */
async function boot() {
// Run-once guard: modules are injected as classic <script>s into the shared
// global scope, so a second boot would re-declare their top-level consts
// (e.g. `fonts` from CypherDudesFonts) and throw "already declared". This can
// happen when the same window is reused (e.g. a document.write preview that
// reopens the document and re-fires DOMContentLoaded).
if (window.__DOS_BOOTED) return;
window.__DOS_BOOTED = true;
build();
window.addEventListener("resize", layout);
window.addEventListener("load", layout);
if (document.fonts && document.fonts.ready) document.fonts.ready.then(layout);
layout();
var n = SCRIPTS.length;
// All network fetches start NOW, in parallel; the loop below only waits
// for each script's bytes to arrive before injecting them in order.
var prefetched = prefetchAll(SCRIPTS);
for (var i = 0; i < n; i++) {
addLine(SCRIPTS[i].label); // new name on the first line, previous pushed down
setProgress(i / n);
try {
var txt = await prefetched[i];
await injectOne(txt, SCRIPTS[i]);
} catch (err) {
console.error("[DOSLoader] failed:", SCRIPTS[i].data, err);
markError();
}
setProgress((i + 1) / n);
// MonoPixel changes the title metrics -> re-fit once it has loaded
if (/fonts/i.test(SCRIPTS[i].data)) layout();
}
markDone(curLine);
// Everything is injected — DOS_animate's init() is building the world NOW.
// Signal listeners (the recompose zk-preload prelude) to start their
// BACKGROUND downloads (crypto/snarkjs/wasm/zkey) without having competed
// with the boot fetches above.
try { window.dispatchEvent(new Event("dos:world-ready")); } catch (e) {}
awaitWorld();
}
// Public API
window.DOSLoader = {
setProgress: setProgress,
addLine: addLine,
layout: layout,
finish: finish,
boot: boot
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", boot);
} else {
boot();
}
})();