diff --git a/.github/workflows/gate.yml b/.github/workflows/gate.yml index 89ade8e..117543a 100644 --- a/.github/workflows/gate.yml +++ b/.github/workflows/gate.yml @@ -23,7 +23,7 @@ jobs: bun-version: '1.3.14' - run: npm install --no-package-lock --no-save playwright@1.56.1 - - run: npx playwright install --with-deps chromium + - run: npx playwright install --with-deps chromium firefox webkit # Unit tests, minification, unit tests against the minified artifact, the # byte budget, and a real Chromium loading the library through diff --git a/README.md b/README.md index f018eb6..d81d8d5 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,93 @@ This example outlines the basic structure for utilizing OrdJS within an asynchro - The pinned CBOR decoder still loses precision on 64-bit integers and collapses distinct map keys. Fixing that needs a separate audited decoder inscription. +## Endpoint coverage (0.1.3-beta) + +Every route below was checked against mainnet `ordinals.com` before being wrapped. + +| Method | Route | Notes | +|---|---|---| +| `getBlockhash(height?)` | `/r/blockhash[/]` | | +| `getBlockheight()` | `/r/blockheight` | | +| `getBlocktime()` | `/r/blocktime` | | +| `getBlockInfo(query)` | `/r/blockinfo/` | `latest` is **not** accepted: ord answers 400. A block hash is an art seed, not secure randomness | +| `getInscription(id)` | `/r/inscription/` | type, length, delegate, sat, location; location is mutable | +| `getMetadata(id)` | `/r/metadata/` | hex CBOR | +| `getDecodedMetadata(id)` | `/r/metadata/` | decodes via the CBOR inscription, loaded lazily | +| `getChildren(id, page?)` | `/r/children/[/]` | IDs only | +| `getChildrenInscriptions(id, page?)` | `/r/children//inscriptions[/]` | full details; paginates with `page` | +| `getParents(id, page?)` | `/r/parents/[/]` | paginates with `page_index`, not `page` | +| `getSatInscriptions(sat, page?, index?)` | `/r/sat/[/][/at/]` | page and index are mutually exclusive | +| `getSatLastInscription(sat)` | `/r/sat//at/-1` | may answer `{"id": null}` | +| `getSatLastInscriptionContent(sat)` | above, then `/content/` | resolves `null` for an empty sat | +| `getInscriptionContent(id)` | `/content/` | follows a delegate; returns `{mime, base64}` | +| `getUndelegatedContent(id)` | `/r/undelegated-content/` | the inscription's own bytes, delegate not followed | +| `getSatInscriptionContent(sat, index?)` | `/r/sat//at//content` | one request instead of two; needs the sat index; defaults to `-1` | + +`request(endpoint)` remains available for any JSON route without a wrapper. + +### Errors + +Every failing request throws `OrdJS : ` with a +`status` property, for example +`OrdJS 404 /r/sat/1/at/0/content: inscription on sat 1 not found`. Branch on +`error.status`, not on message text. Note that a 404 from +`getSatInscriptionContent` means either an empty sat **or** a server running +without the sat index; ord's message distinguishes them, so it is preserved rather +than collapsed into "not found". + +## The metadata decoder + +`getDecodedMetadata` loads the inscribed decoder lazily, once. The current one +(`a9f6a9b0…308566i0`, cbor-js) **decodes some metadata incorrectly**: + +| Input | Inscribed decoder | Consequence | +|---|---|---| +| `9007199254740993` | `9007199254740992` | integers above 2^53 silently round: nanosecond timestamps, 18-decimal token amounts, snowflake IDs | +| map with key `1` and key `"1"` | `{"1": …}` | one entry silently disappears | +| map with key `__proto__` | no own keys, prototype changed | the value stops being data | +| ~1 MiB CBOR text | `RangeError` | large metadata cannot be decoded at all | + +### The replacement candidate + +`vendor/cbor2-decoder.js` is the proposed replacement, built by +`node scripts/build-decoder.mjs` from `cbor2@2.3.0` (MIT, notice retained in the +artifact). `vendor/cbor2-decoder.json` records its bytes and sha256, and the gate +verifies the file still matches them. **It is not inscribed yet**, so +`inscription_id` is `null`. + +The library asks for its decoder at a fixed `/content/` path — no configuration +hook is inscribed for this. To try the candidate, serve it at that path, which is +what `scripts/decoder-smoke.mjs` does. + +That script decodes the vendored RFC 8949 Appendix A fixture in Chromium through +the real recursive loader: **59 of 59 decodable vectors correct**. Upstream +Appendix A has 82 entries; 23 are diagnostic-only and carry no expected value, so +they are not in the fixture and **59/59 is not full Appendix A conformance**. The +same run against the currently inscribed decoder reports 55/59 with eight problems, +so the check discriminates rather than decorates. + +### Migration cost, measured + +More than the broken cases change shape. The decoder smoke prints this table on +every run; these are all cases the current decoder handles *acceptably*, so they +are migration cost rather than fixes: + +| CBOR | Inscribed decoder | Candidate | +|---|---|---| +| `{a:1, b:2}` string keys | plain object | plain object — unchanged | +| `{1:2, 3:4}` integer keys | plain object, `meta[1]` works | **`Map`**, `meta[1]` is `undefined` | +| tag 0 / tag 1 date | string / number | **`Date`** | +| tag 32 URI | string | **`URL`** (adds a trailing slash) | +| tags 23 / 24 | `Uint8Array` | **`Tag` wrapper** | +| integers > 2^53 | rounded number | **`BigInt`** | + +So: ordinary string-keyed metadata keeps working as `meta.foo`, but a consumer +using integer keys, tags, or raw byte strings must be updated. That is the real +cost of the swap, and it is why the decision is a migration rather than a drop-in. + + + ## Tests and the release gate `test/` runs on Node's built-in runner with no dependencies: @@ -87,21 +174,28 @@ node --test test/ordjs.test.mjs Before inscribing, run the full gate. It runs the tests, minifies with a pinned configuration, re-runs the tests against the **minified** artifact, enforces a byte -budget against the size of the live inscription, drives a real Chromium that loads -the library through `/content/` exactly as an inscription does, and prints the -byte counts, hash and dependency inscription IDs a release record needs: +budget against the size of the live inscription, drives Chromium, Firefox and +WebKit through the real `/content/` recursive load, checks the decoder +candidate against the RFC 8949 fixture and against its own manifest, computes the +commit/reveal fee from the serialised transaction, and prints the byte counts, hash +and dependency inscription IDs a release record needs: ```sh -bun install # playwright, dev-only -npx playwright install chromium -node scripts/gate.mjs # --no-browser skips only the Chromium stage +bun install # playwright, dev-only +npx playwright install chromium firefox webkit +node scripts/gate.mjs # --no-browser drops every browser stage ``` +`--no-browser` skips all three engines **and** the decoder conformance stage, so a +run with that flag is not release evidence. + CI runs the same gate on every push and pull request. The gate does not cover, and a release still requires: a real ord server with the -sat index both enabled and disabled, Firefox and WebKit, and a commit/reveal fee -dry-run at the chosen rate. +sat index both enabled and disabled, and a wallet dry-run of the actual +commit/reveal transaction. The fee stage serialises the envelope, tapscript and +witness exactly, but it assumes a standard commit shape (1 P2TR input, 2 P2TR +outputs) rather than your wallet's real input selection. Tests, examples, tooling and this README are repository files only; inscribing the library uses a minified `src/content/OrdJS.js` and nothing else. diff --git a/scripts/browser-smoke.mjs b/scripts/browser-smoke.mjs index f54500c..c451ca0 100644 --- a/scripts/browser-smoke.mjs +++ b/scripts/browser-smoke.mjs @@ -6,12 +6,12 @@ // recursive script load, the real fetch/btoa/document, and the decoder inscription // being pulled in lazily by a second `); + return; + } + if (req.url === `/content/${LIB_ID}`) { + res.writeHead(200, { 'content-type': 'text/javascript' }); + res.end(library); + return; + } + if (req.url === DECODER_PATH) { + res.writeHead(200, { 'content-type': 'text/javascript' }); + res.end(decoder); + return; + } + const metadata = req.url.match(/^\/r\/metadata\/([0-9a-f]+)$/); + if (metadata) { + res.writeHead(200, { 'content-type': 'application/json' }); + res.end(JSON.stringify(metadata[1])); + return; + } + res.writeHead(404, { 'content-type': 'text/plain' }); + res.end('not found'); +}); + +await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); +const origin = `http://127.0.0.1:${server.address().port}`; + +const browser = await chromium.launch(); +let report; +try { + const page = await browser.newPage(); + await page.goto(`${origin}/`, { waitUntil: 'load' }); + + report = await page.evaluate(async ({ decoderPath, suite }) => { + const ord = new OrdJS(''); + + // JSON cannot express the exact expectation for 64-bit vectors, so those are + // compared against decimal strings instead of lossy numbers. + const canon = (value) => { + if (typeof value === 'bigint') return value.toString(); + if (value instanceof Uint8Array) return 'bytes:' + [...value].map((b) => b.toString(16).padStart(2, '0')).join(''); + if (value instanceof Date) return value.toISOString(); + if (value instanceof Map) return canon(Object.fromEntries([...value].map(([k, v]) => [String(canon(k)), v]))); + if (Array.isArray(value)) return value.map(canon); + if (value && typeof value === 'object') { + const out = {}; + for (const key of Object.keys(value)) out[key] = canon(value[key]); + return out; + } + if (typeof value === 'number' && !Number.isFinite(value)) return String(value); + return value; + }; + + const failures = []; + let passed = 0; + for (const vector of suite.vectors) { + const override = suite.exact_overrides[vector.hex]; + let got; + try { + got = await ord.getDecodedMetadata(vector.hex); + } catch (error) { + failures.push({ hex: vector.hex, got: `THROW ${error.message}` }); + continue; + } + const want = JSON.stringify(override ?? canon(vector.decoded)); + const actual = JSON.stringify(canon(got)); + if (actual === want) passed += 1; + else failures.push({ hex: vector.hex, want, got: actual }); + } + + // The behaviours the current inscribed decoder gets wrong. + const regressions = { + // 9007199254740993 must not round to ...992 + bigint: String(canon(await ord.getDecodedMetadata('1b0020000000000001'))), + // Map with numeric key 1 and string key "1": both must survive. canon() is + // deliberately not used here — it stringifies keys, which would collapse the + // two exactly like the defect under test and make this check pass on a broken + // decoder. + mixedKeys: await ord.getDecodedMetadata('a201616161316162').then((m) => (m instanceof Map + ? `Map(${m.size}) ${[...m].map(([k, v]) => `${typeof k}:${String(k)}=${v}`).join('|')}` + : `not-a-map ${JSON.stringify(m)}`)), + // __proto__ as a data key must not reach the prototype + protoIsOwnKey: Object.keys(await ord.getDecodedMetadata('a1695f5f70726f746f5f5fa1617801')).join(','), + protoClean: Object.getPrototypeOf(await ord.getDecodedMetadata('a1695f5f70726f746f5f5fa1617801')) === Object.prototype, + // ordinary string-keyed metadata must still decode to a plain object + plainObject: JSON.stringify(await ord.getDecodedMetadata('a26161016162 02'.replace(' ', ''))) + }; + + // Shape changes a consumer of the CURRENT decoder would absorb. These are not + // failures — the candidate is correct here — but they are migration cost, and + // the RFC fixture cannot show them because upstream lists these vectors as + // diagnostic-only. Recorded so the README cannot understate the migration. + const describe = (value) => { + if (value instanceof Map) return `Map(${value.size})`; + if (value instanceof Date) return 'Date'; + if (value instanceof URL) return 'URL'; + if (value instanceof Uint8Array) return 'Uint8Array'; + if (value && typeof value === 'object') { + // The library under test may be minified, so a constructor name is not a + // stable label. Describe the shape instead. + const keys = Object.keys(value); + if (keys.includes('tag') || keys.includes('contents')) return `tag wrapper {${keys.join(',')}}`; + return `object {${keys.join(',')}}`; + } + return typeof value; + }; + // Shape alone is not enough: a decoder that returns Invalid Date for every + // date, or rewrites a URI to an attacker's host, has the RIGHT SHAPE and the + // wrong value. Each probe therefore records what the value actually is. + const value = (decoded) => { + if (decoded instanceof Date) return `Date(${decoded.toISOString?.() ?? 'Invalid'})`; + if (decoded instanceof URL) return `URL(${decoded.href})`; + if (decoded instanceof Uint8Array) return `bytes(${[...decoded].join(',')})`; + if (decoded instanceof Map) return `Map(${[...decoded].map(([k, v]) => `${typeof k}:${String(k)}=${JSON.stringify(v)}`).join('|')})`; + if (decoded && typeof decoded === 'object') return `object(${JSON.stringify(decoded, (k, v) => (v instanceof Uint8Array ? [...v] : v))})`; + return JSON.stringify(decoded); + }; + const migration = {}; + for (const [label, hex] of [ + ['integer-keyed map {1:2,3:4}', 'a201020304'], + ['tag 0 date string', 'c074323031332d30332d32315432303a30343a30305a'], + ['tag 1 epoch', 'c11a514b67b0'], + ['tag 23 expected-base16', 'd74401020304'], + ['tag 24 encoded-cbor', 'd818456449455446'], + ['tag 32 URI', 'd82076687474703a2f2f7777772e6578616d706c652e636f6d'], + ['byte string', '4401020304'], + ['string-keyed map {a:1,b:2}', 'a2616101616202'] + ]) { + try { + const decoded = await ord.getDecodedMetadata(hex); + migration[label] = `${describe(decoded)} = ${value(decoded)}`; + } catch (error) { + migration[label] = `THROW ${error.message}`; + } + } + + return { total: suite.vectors.length, passed, failures, regressions, migration, decoderLoads: document.querySelectorAll(`script[src="${decoderPath}"]`).length }; + }, { decoderPath: DECODER_PATH, suite }); +} finally { + await browser.close(); + server.close(); +} + +const problems = [...report.failures.map((f) => `vector ${f.hex}: want ${f.want}, got ${f.got}`)]; +const r = report.regressions; +if (r.bigint !== '9007199254740993') problems.push(`uint64 precision: ${r.bigint}`); +if (r.mixedKeys !== 'Map(2) number:1=a|string:1=b') problems.push(`mixed keys lost: ${r.mixedKeys}`); +if (r.protoIsOwnKey !== '__proto__') problems.push(`__proto__ not an own key: ${r.protoIsOwnKey}`); +if (r.protoClean !== true) problems.push('prototype was mutated by a __proto__ key'); +if (r.plainObject !== '{"a":1,"b":2}') problems.push(`string-keyed map is not a plain object: ${r.plainObject}`); +if (report.decoderLoads !== 1) problems.push(`decoder loaded ${report.decoderLoads} times`); + +// The migration probes are also correctness probes: a decoder can hold the right +// SHAPE and the wrong VALUE. An Invalid Date, or a URI silently rewritten to +// another host, would otherwise be published as an acceptable migration. +const expectedValues = { + 'integer-keyed map {1:2,3:4}': 'Map(2) = Map(number:1=2|number:3=4)', + 'tag 0 date string': 'Date = Date(2013-03-21T20:04:00.000Z)', + 'tag 1 epoch': 'Date = Date(2013-03-21T20:04:00.000Z)', + 'tag 32 URI': 'URL = URL(http://www.example.com/)', + 'byte string': 'Uint8Array = bytes(1,2,3,4)', + 'string-keyed map {a:1,b:2}': 'object {a,b} = object({"a":1,"b":2})' +}; +for (const [label, expected] of Object.entries(expectedValues)) { + if (report.migration[label] !== expected) { + problems.push(`migration ${label}: expected ${expected}, got ${report.migration[label]}`); + } +} + +console.log(`RFC 8949 Appendix A: ${report.passed}/${report.total} vectors decoded correctly in Chromium`); +console.log(` (${report.total} of the 82 upstream entries carry a decoded value; the other 23 are diagnostic-only`); +console.log(' and include the tag and integer-keyed-map cases listed under migration below)'); +console.log(`regressions fixed vs the inscribed decoder: ${JSON.stringify(r, null, 2)}`); +console.log(`migration shape changes vs the inscribed decoder: ${JSON.stringify(report.migration, null, 2)}`); +if (problems.length > 0) { + console.error('decoder smoke FAILED'); + for (const problem of problems) console.error(` - ${problem}`); + process.exit(1); +} +console.log(`decoder smoke ok (${decoderPath})`); diff --git a/scripts/fee-estimate.mjs b/scripts/fee-estimate.mjs new file mode 100644 index 0000000..a125b59 --- /dev/null +++ b/scripts/fee-estimate.mjs @@ -0,0 +1,224 @@ +// Fee estimate built from the ACTUAL inscription structure, not a bytes/4 guess. +// +// It assembles the real ord envelope for a given artifact — OP_FALSE OP_IF "ord" +// OP_1 OP_0 OP_ENDIF — measures the +// tapscript, builds the reveal witness (signature, script, control block) and a +// standard commit transaction, then computes weight and virtual size the way a +// node does. +// +// node scripts/fee-estimate.mjs [--rate 1] [--rate 5] [file ...] +// +// This is exact arithmetic over the real serialised structures. It is still NOT a +// wallet dry-run: a real `ord wallet inscribe` picks specific inputs, change and +// postage, which move the commit side. Treat the reveal figure as tight and the +// commit figure as a standard-shape approximation. + +import { readFileSync, existsSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; + +const args = process.argv.slice(2); +const rates = []; +const files = []; +for (let i = 0; i < args.length; i += 1) { + if (args[i] === '--rate') { rates.push(Number(args[i + 1])); i += 1; continue; } + files.push(args[i]); +} +if (rates.length === 0) rates.push(1, 5, 10); + +const root = fileURLToPath(new URL('..', import.meta.url)); +const targets = files.length > 0 ? files : [ + `${root}/vendor/cbor2-decoder.js` +]; + +// Bitcoin script push encoding: this is where "bytes ÷ 4" quietly loses accuracy. +function pushSize(dataLength) { + if (dataLength === 0) return 1; // OP_0 + if (dataLength <= 75) return 1 + dataLength; // direct push + if (dataLength <= 255) return 2 + dataLength; // OP_PUSHDATA1 + if (dataLength <= 65535) return 3 + dataLength; // OP_PUSHDATA2 + return 5 + dataLength; // OP_PUSHDATA4 +} + +function varIntSize(n) { + if (n < 0xfd) return 1; + if (n <= 0xffff) return 3; + if (n <= 0xffffffff) return 5; + return 9; +} + +// ord envelope, per the inscription spec: body is split into pushes of at most +// 520 bytes because that is the maximum a single push can carry. +// +// Both tags are DATA PUSHES, not opcodes: ord's Tag::append calls +// push_slice(tag.bytes()), so the content-type tag [1] serialises as 0x01 0x01 +// (2 bytes) while the body tag is a zero-length slice and serialises as OP_0 +// (1 byte). Counting the content-type tag as a single OP_1 understates the +// envelope, which is exactly the kind of error a "bytes / 4" estimate hides. +function envelopeSize(bodyBytes, contentType) { + const CHUNK = 520; + let size = 0; + size += 1; // OP_FALSE + size += 1; // OP_IF + size += pushSize(3); // "ord" + size += pushSize(1); // content-type tag, pushed as data + size += pushSize(Buffer.byteLength(contentType)); + size += pushSize(0); // body tag: empty slice -> OP_0 + for (let offset = 0; offset < bodyBytes; offset += CHUNK) { + size += pushSize(Math.min(CHUNK, bodyBytes - offset)); + } + size += 1; // OP_ENDIF + return size; +} + +function revealTransaction(bodyBytes, contentType) { + // Tapscript: <32-byte internal key> OP_CHECKSIG, then the envelope. + const script = pushSize(32) + 1 + envelopeSize(bodyBytes, contentType); + + // Non-witness part: version, input count, outpoint+empty scriptSig+sequence, + // output count, one P2TR output, locktime. + const base = 4 + 1 + (32 + 4 + 1 + 4) + 1 + (8 + 1 + 34) + 4; + + // Witness: item count, 64-byte Schnorr signature, the script, a control block + // for a single-leaf tree (1 + 32). + const witness = 1 + + varIntSize(64) + 64 + + varIntSize(script) + script + + varIntSize(33) + 33; + + // Segwit marker and flag are witness-weighted. + const weight = base * 4 + (2 + witness); + return { script, base, witness, weight, vsize: Math.ceil(weight / 4) }; +} + +function commitTransaction() { + // One P2TR input, two P2TR outputs (reveal address + change): the ordinary + // shape a wallet produces. Key-path spend, so the witness is one signature. + const base = 4 + 1 + (32 + 4 + 1 + 4) + 1 + 2 * (8 + 1 + 34) + 4; + const witness = 1 + varIntSize(64) + 64; + const weight = base * 4 + (2 + witness); + return { weight, vsize: Math.ceil(weight / 4) }; +} + +const commit = commitTransaction(); +const rows = []; +for (const file of targets) { + if (!existsSync(file)) { + console.error(`skipped, not found: ${file}`); + continue; + } + const body = readFileSync(file); + // ord's media table maps js/mjs to "text/javascript" with no charset parameter; + // the live sibling inscription reports exactly that content type. + const contentType = file.endsWith('.js') ? 'text/javascript' : 'application/octet-stream'; + const reveal = revealTransaction(body.length, contentType); + const totalVB = reveal.vsize + commit.vsize; + rows.push({ + file: file.replace(root, ''), + body_bytes: body.length, + content_type: contentType, + tapscript_bytes: reveal.script, + reveal_weight: reveal.weight, + reveal_vB: reveal.vsize, + commit_vB: commit.vsize, + total_vB: totalVB, + sats: Object.fromEntries(rates.map((rate) => [`${rate}_sat_vB`, totalVB * rate])) + }); +} + +// A stage that only prints cannot fail, and a fee figure nobody can falsify is +// worse than no figure. These invariants are derived independently of the +// functions above, so a corrupted pushSize or envelope walk is caught rather +// than published as a smaller number. +const violations = []; +for (const row of rows) { + const body = row.body_bytes; + const chunks = Math.ceil(body / 520); + // Independent lower bound: the body itself, its push prefixes (3 bytes per + // 520-byte chunk), the 34-byte key-path prefix and the smallest possible + // envelope header. + const floor = body + chunks * 3 + 34 + 8; + if (row.tapscript_bytes < floor) { + violations.push(`${row.file}: tapscript ${row.tapscript_bytes} B is below the ${floor} B floor for a ${body} B body`); + } + // The witness is weight 1 per byte, so the reveal can never be cheaper than a + // quarter of the script it carries. + if (row.reveal_vB < Math.ceil(row.tapscript_bytes / 4)) { + violations.push(`${row.file}: reveal ${row.reveal_vB} vB is below tapscript/4`); + } + // BIP 141: vsize is weight/4 rounded up. Recomputed here from the reported + // weight rather than restated, so a corrupted weight or vsize is caught. + if (row.reveal_vB !== Math.ceil(row.reveal_weight / 4)) { + violations.push(`${row.file}: reveal ${row.reveal_vB} vB is not ceil(${row.reveal_weight} weight / 4)`); + } + // The witness carries the whole body at 1 weight unit per byte, and the + // non-witness part is weighted x4, so the reveal weight has a hard floor. + if (row.reveal_weight < body + 4 * 60) { + violations.push(`${row.file}: reveal weight ${row.reveal_weight} is below the floor for a ${body} B body`); + } + if (row.total_vB !== row.reveal_vB + row.commit_vB) { + violations.push(`${row.file}: total is not reveal + commit`); + } + // ord's own media table decides this string, and its length lands in the + // envelope. A charset parameter nobody inscribes would silently inflate every + // figure, so the mapping is pinned rather than trusted. + if (row.file.endsWith('.js') && row.content_type !== 'text/javascript') { + violations.push(`${row.file}: modelled as ${row.content_type}, but ord inscribes .js as text/javascript`); + } +} +// Known-answer check on the push encoder itself, independent of any artifact. +for (const [length, expected] of [[0, 1], [1, 2], [75, 76], [76, 78], [255, 257], [256, 259], [520, 523]]) { + if (pushSize(length) !== expected) { + violations.push(`pushSize(${length}) = ${pushSize(length)}, expected ${expected}`); + } +} + +// GROUND TRUTH. A floor can only catch a large error; these numbers come from the +// real reveal transaction of the live OrdJS v0.1.2 inscription +// (4123e324aa3508ae7021a43a1dfc2d9d83fc35029d092877c57234f729068526i0, reveal txid +// 4123e324..., witness items 64 / 3995 / 33 bytes, weight 4476), whose body is +// 3911 bytes of text/javascript. If this model of the envelope drifts by even one +// byte — a mis-sized tag, a wrong chunk size, a charset added to the content type +// — these equalities fail. That is what makes the stage falsifiable rather than +// merely bounded. +const LIVE = { body: 3911, contentType: 'text/javascript', tapscript: 3995, weight: 4476, vsize: 1119 }; +const modelled = revealTransaction(LIVE.body, LIVE.contentType); +if (modelled.script !== LIVE.tapscript) { + violations.push(`known answer: tapscript for the live v0.1.2 body is ${modelled.script} B, on-chain it is ${LIVE.tapscript} B`); +} +if (modelled.weight !== LIVE.weight) { + violations.push(`known answer: reveal weight for the live v0.1.2 body is ${modelled.weight}, on-chain it is ${LIVE.weight}`); +} +if (modelled.vsize !== LIVE.vsize) { + violations.push(`known answer: reveal vsize for the live v0.1.2 body is ${modelled.vsize}, expected ${LIVE.vsize}`); +} +// The commit side was previously unconstrained: a collapsed commit understated the +// total by 10% and every stage still passed. Pin its exact serialised size. +if (commit.vsize !== 154 || commit.weight !== 616) { + violations.push(`commit tx is ${commit.vsize} vB / ${commit.weight} wu, expected 154 vB / 616 wu for 1 P2TR in, 2 P2TR out`); +} + +// Body chunking: the 521st byte must start a SECOND push, costing its own +// 1-byte prefix plus the byte itself, i.e. exactly pushSize(1) = 2 more bytes. +// A single oversized push (CHUNK raised above 520) makes this 1. +const oneChunk = envelopeSize(520, 'text/plain'); +const twoChunks = envelopeSize(521, 'text/plain'); +if (twoChunks - oneChunk !== 2) { + violations.push(`chunking: crossing 520 bytes changed the envelope by ${twoChunks - oneChunk} B, expected 2 (a second push: 1-byte prefix + 1 byte)`); +} + +console.log(JSON.stringify({ + method: 'exact serialisation of the ord envelope, tapscript, reveal witness and a standard commit tx', + not_included: ['wallet input selection', 'change and postage values', 'parent/child or metadata fields', 'sat selection'], + commit_assumption: '1 P2TR input, 2 P2TR outputs, key-path spend', + results: rows +}, null, 2)); + +if (violations.length > 0) { + console.error('fee estimate FAILED its own invariants'); + for (const violation of violations) console.error(` - ${violation}`); + process.exit(1); +} +if (rows.length === 0) { + console.error('fee estimate FAILED: no artifact was measured'); + process.exit(1); +} diff --git a/scripts/gate.mjs b/scripts/gate.mjs index 7452cc7..3c1eae4 100644 --- a/scripts/gate.mjs +++ b/scripts/gate.mjs @@ -5,15 +5,18 @@ // record needs. // // node scripts/gate.mjs full gate (needs bun + playwright chromium) -// node scripts/gate.mjs --no-browser skip only the real-browser stage +// node scripts/gate.mjs --no-browser skip only the browser-dependent stages // // Stages: // 1. unit tests against the readable source // 2. minify with a pinned, recorded configuration // 3. unit tests again against the MINIFIED artifact (the thing that ships) // 4. byte budget: the artifact must not exceed the live inscription body -// 5. real browser: recursive /content/ load, 1 MiB round-trip, lazy decoder -// 6. release record: sizes, hashes, dependency inscription IDs +// 5. decoder manifest: recorded bytes/sha256/notice still match the artifact +// 6. real browsers: chromium, firefox and webkit through /content/ +// 7. decoder conformance: RFC 8949 Appendix A through the recursive loader +// 8. fee estimate: envelope/tapscript/witness serialisation with known answers +// 9. release record: sizes, hashes, dependency inscription IDs import { spawnSync } from 'node:child_process'; import { createHash } from 'node:crypto'; @@ -70,12 +73,43 @@ if (minifiedOk && existsSync(minified)) { process.stdout.write(`\n=== byte budget\n${bytes} B minified, budget ${BUDGET_BYTES} B, ` + `${withinBudget ? `${BUDGET_BYTES - bytes} B of headroom` : `${bytes - BUDGET_BYTES} B OVER`}\n`); + // The manifest check reads two files and needs no browser, so it runs even + // under --no-browser: artifact/manifest drift is an integrity failure, not a + // browser-dependent one. + // + // A MISSING candidate is not a silent pass. Deleting the artifact used to make + // both decoder stages disappear from the summary while the gate still reported + // success, so the manifest deciding the candidate exists is what is checked. + const manifestPresent = existsSync(join(root, 'vendor/cbor2-decoder.json')); + const artifactPresent = existsSync(join(root, 'vendor/cbor2-decoder.js')); + if (manifestPresent !== artifactPresent) { + steps.push({ + name: `decoder candidate is complete (manifest ${manifestPresent ? 'present' : 'missing'}, artifact ${artifactPresent ? 'present' : 'missing'})`, + ok: false + }); + process.stdout.write('\n=== decoder candidate\nFAIL: the manifest and the artifact must exist together\n'); + } + if (artifactPresent && manifestPresent) { + run('decoder manifest matches artifact', 'node', ['scripts/check-manifest.mjs']); + } + if (withBrowser) { - run('browser smoke (minified artifact)', 'node', ['scripts/browser-smoke.mjs', minified]); + run('browser smoke (minified artifact, chromium/firefox/webkit)', 'node', + ['scripts/browser-smoke.mjs', minified, '--engine', 'all']); + // The decoder candidate is a separate inscription, so it is gated separately: + // RFC 8949 Appendix A decoded in Chromium through the recursive loader, and + // against the MINIFIED library, because that is what would ship. + if (artifactPresent && manifestPresent) { + run('decoder candidate conformance', 'node', ['scripts/decoder-smoke.mjs', '--library', minified]); + } } else { - process.stdout.write('\n=== browser smoke\nSKIPPED (--no-browser): the inscription path is unverified\n'); + process.stdout.write('\n=== browser smoke\n' + + 'SKIPPED (--no-browser): the inscription path, all three engines AND the decoder\n' + + 'candidate conformance are unverified in this run\n'); } + run('fee estimate', 'node', ['scripts/fee-estimate.mjs', '--rate', '1', '--rate', '5', minified]); + const sha256 = createHash('sha256').update(artifact).digest('hex'); const commit = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8' }).stdout?.trim(); const dependencies = [...readFileSync(source, 'utf8').matchAll(/[0-9a-f]{64}i\d+/g)].map((m) => m[0]); @@ -91,7 +125,9 @@ if (minifiedOk && existsSync(minified)) { live_inscription_body_bytes: BUDGET_BYTES }, null, 2) + '\n'); process.stdout.write('\nNot covered by this gate, and required before inscribing: a real ord server ' + - '(indexed and non-indexed), Firefox and WebKit, and a commit/reveal fee dry-run at the chosen rate.\n'); + '(sat index enabled AND disabled), and a wallet dry-run of the real commit/reveal transaction. ' + + 'The fee stage serialises the envelope, tapscript and witness exactly but assumes a standard ' + + 'commit shape (1 P2TR input, 2 P2TR outputs).\n'); } const failed = steps.filter((step) => !step.ok); diff --git a/src/content/OrdJS.js b/src/content/OrdJS.js index cb1b88e..50efaf5 100644 --- a/src/content/OrdJS.js +++ b/src/content/OrdJS.js @@ -18,12 +18,16 @@ class OrdJS { this.decoderPromise = null; } + // Kept for compatibility: nothing needs initialising and no method waits on + // it, but the flag is still set so an existing caller that awaits init() and + // reads it sees true. async init() { this.isInitialized = true; } // The CBOR decoder is inscribed on Bitcoin mainnet and loaded only when - // decoded metadata is requested. Concurrent callers share one load. + // decoded metadata is requested. Concurrent callers share one load, and a + // failed load is retried rather than cached. loadAndUseDependency() { if (!this.decoderPromise) { this.decoderPromise = this.loadScript('/content/a9f6a9b050af3de1a4ce714978c1f2231ba731f1f46731a16d0e411f89308566i0') @@ -43,7 +47,7 @@ class OrdJS { async request(endpoint) { const response = await fetch(this.baseURL + endpoint); if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); + throw await OrdJS.httpError(endpoint, response); } return response.json(); } @@ -70,6 +74,29 @@ class OrdJS { return this.request(`/r/metadata/${inscriptionId}`); } + // Inscription details: content type, length, delegate, sat, location. Fields + // may be null, and location/address are mutable even though the ID is not. + getInscription(inscriptionId) { + return this.request(`/r/inscription/${inscriptionId}`); + } + + // Parent IDs. This endpoint paginates with page_index, unlike children's page. + getParents(inscriptionId, page = '') { + return this.request(`/r/parents/${inscriptionId}${OrdJS.given(page) ? `/${page}` : ''}`); + } + + // Child details rather than bare IDs: one request instead of N getInscription + // calls. Paginates with page. + getChildrenInscriptions(inscriptionId, page = '') { + return this.request(`/r/children/${inscriptionId}/inscriptions${OrdJS.given(page) ? `/${page}` : ''}`); + } + + // Block statistics for a height or a 64-character block hash. ord parses this + // segment as a height or hash only: 'latest' is rejected with 400. + getBlockInfo(query) { + return this.request(`/r/blockinfo/${query}`); + } + // page lists inscriptions on the sat; index selects a single one. They are // separate routes, so supplying both is rejected instead of building an // undocumented URL. Numeric 0 is a valid page and a valid index. @@ -83,10 +110,33 @@ class OrdJS { return this.request(endpoint); } - async getInscriptionContent(inscriptionId) { - const response = await fetch(this.baseURL + `/content/${inscriptionId}`); + getInscriptionContent(inscriptionId) { + return this.fetchContent(`/content/${inscriptionId}`); + } + + // The inscription's OWN bytes. /content/ follows a delegate; this does not, + // so a delegating inscription returns its own body here. + getUndelegatedContent(inscriptionId) { + return this.fetchContent(`/r/undelegated-content/${inscriptionId}`); + } + + // One request instead of resolving the ID and then fetching it. Index -1 is the + // latest inscription on the sat. Requires an ord with the sat index; an empty + // sat and a server without that index both answer 404, and the thrown error + // carries ord's own explanation of which it was. + // + // NOTE the deliberate difference from getSatLastInscriptionContent, which + // resolves null for an empty sat because /r/sat//at/-1 answers 200 with + // {"id": null}. Switching to this cheaper method converts that null into a + // thrown 404. + getSatInscriptionContent(satNumber, index = -1) { + return this.fetchContent(`/r/sat/${satNumber}/at/${index}/content`); + } + + async fetchContent(endpoint) { + const response = await fetch(this.baseURL + endpoint); if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); + throw await OrdJS.httpError(endpoint, response); } const contentType = response.headers.get('Content-Type'); const bytes = new Uint8Array(await response.arrayBuffer()); @@ -96,6 +146,17 @@ class OrdJS { }; } + // ord explains its own failures in the response body ("inscription on sat 1 not + // found", "...metadata not found"). Carrying that text turns an opaque status + // into an actionable message; the status and endpoint stay in the message so a + // caller can still branch on them. + static async httpError(endpoint, response) { + const detail = await response.text().catch(() => ''); + const error = new Error(`OrdJS ${response.status} ${endpoint}: ${detail.trim().slice(0, 200)}`); + error.status = response.status; + return error; + } + async getSatLastInscription(satNumber) { return this.request(`/r/sat/${satNumber}/at/-1`); } diff --git a/test/fixtures/rfc8949-appendix-a.json b/test/fixtures/rfc8949-appendix-a.json new file mode 100644 index 0000000..3a765c0 --- /dev/null +++ b/test/fixtures/rfc8949-appendix-a.json @@ -0,0 +1,385 @@ +{ + "source": "https://github.com/cbor/test-vectors appendix_a.json (RFC 8949 Appendix A)", + "note": "Only vectors carrying a decoded value. JSON cannot hold 64-bit integers exactly, so vectors whose value exceeds Number.MAX_SAFE_INTEGER are listed in exact_overrides as strings.", + "exact_overrides": { + "1bffffffffffffffff": "18446744073709551615", + "c249010000000000000000": "18446744073709551616", + "3bffffffffffffffff": "-18446744073709551616", + "c349010000000000000000": "-18446744073709551617" + }, + "vectors": [ + { + "hex": "00", + "decoded": 0 + }, + { + "hex": "01", + "decoded": 1 + }, + { + "hex": "0a", + "decoded": 10 + }, + { + "hex": "17", + "decoded": 23 + }, + { + "hex": "1818", + "decoded": 24 + }, + { + "hex": "1819", + "decoded": 25 + }, + { + "hex": "1864", + "decoded": 100 + }, + { + "hex": "1903e8", + "decoded": 1000 + }, + { + "hex": "1a000f4240", + "decoded": 1000000 + }, + { + "hex": "1b000000e8d4a51000", + "decoded": 1000000000000 + }, + { + "hex": "1bffffffffffffffff", + "decoded": 18446744073709552000 + }, + { + "hex": "c249010000000000000000", + "decoded": 18446744073709552000 + }, + { + "hex": "3bffffffffffffffff", + "decoded": -18446744073709552000 + }, + { + "hex": "c349010000000000000000", + "decoded": -18446744073709552000 + }, + { + "hex": "20", + "decoded": -1 + }, + { + "hex": "29", + "decoded": -10 + }, + { + "hex": "3863", + "decoded": -100 + }, + { + "hex": "3903e7", + "decoded": -1000 + }, + { + "hex": "f90000", + "decoded": 0 + }, + { + "hex": "f98000", + "decoded": 0 + }, + { + "hex": "f93c00", + "decoded": 1 + }, + { + "hex": "fb3ff199999999999a", + "decoded": 1.1 + }, + { + "hex": "f93e00", + "decoded": 1.5 + }, + { + "hex": "f97bff", + "decoded": 65504 + }, + { + "hex": "fa47c35000", + "decoded": 100000 + }, + { + "hex": "fa7f7fffff", + "decoded": 3.4028234663852886e+38 + }, + { + "hex": "fb7e37e43c8800759c", + "decoded": 1e+300 + }, + { + "hex": "f90001", + "decoded": 5.960464477539063e-8 + }, + { + "hex": "f90400", + "decoded": 0.00006103515625 + }, + { + "hex": "f9c400", + "decoded": -4 + }, + { + "hex": "fbc010666666666666", + "decoded": -4.1 + }, + { + "hex": "f4", + "decoded": false + }, + { + "hex": "f5", + "decoded": true + }, + { + "hex": "f6", + "decoded": null + }, + { + "hex": "60", + "decoded": "" + }, + { + "hex": "6161", + "decoded": "a" + }, + { + "hex": "6449455446", + "decoded": "IETF" + }, + { + "hex": "62225c", + "decoded": "\"\\" + }, + { + "hex": "62c3bc", + "decoded": "ü" + }, + { + "hex": "63e6b0b4", + "decoded": "水" + }, + { + "hex": "64f0908591", + "decoded": "𐅑" + }, + { + "hex": "80", + "decoded": [] + }, + { + "hex": "83010203", + "decoded": [ + 1, + 2, + 3 + ] + }, + { + "hex": "8301820203820405", + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "hex": "98190102030405060708090a0b0c0d0e0f101112131415161718181819", + "decoded": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + { + "hex": "a0", + "decoded": {} + }, + { + "hex": "a26161016162820203", + "decoded": { + "a": 1, + "b": [ + 2, + 3 + ] + } + }, + { + "hex": "826161a161626163", + "decoded": [ + "a", + { + "b": "c" + } + ] + }, + { + "hex": "a56161614161626142616361436164614461656145", + "decoded": { + "a": "A", + "b": "B", + "c": "C", + "d": "D", + "e": "E" + } + }, + { + "hex": "7f657374726561646d696e67ff", + "decoded": "streaming" + }, + { + "hex": "9fff", + "decoded": [] + }, + { + "hex": "9f018202039f0405ffff", + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "hex": "9f01820203820405ff", + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "hex": "83018202039f0405ff", + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "hex": "83019f0203ff820405", + "decoded": [ + 1, + [ + 2, + 3 + ], + [ + 4, + 5 + ] + ] + }, + { + "hex": "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff", + "decoded": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ] + }, + { + "hex": "bf61610161629f0203ffff", + "decoded": { + "a": 1, + "b": [ + 2, + 3 + ] + } + }, + { + "hex": "826161bf61626163ff", + "decoded": [ + "a", + { + "b": "c" + } + ] + }, + { + "hex": "bf6346756ef563416d7421ff", + "decoded": { + "Fun": true, + "Amt": -2 + } + } + ] +} \ No newline at end of file diff --git a/test/ordjs.test.mjs b/test/ordjs.test.mjs index 682bede..a548191 100644 --- a/test/ordjs.test.mjs +++ b/test/ordjs.test.mjs @@ -59,6 +59,14 @@ const binary = (bytes) => async () => ({ arrayBuffer: async () => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) }); +// ord answers a failure with a plain-text explanation, e.g. +// "inscription on sat 1 not found" (verified against mainnet ordinals.com). +const failure = (status, message) => async () => ({ + ok: false, + status, + text: async () => message +}); + test('numeric index and page select their exact sat routes', async () => { const { OrdJS, calls } = load({ body: json({ ok: true }) }); const ord = new OrdJS(''); @@ -161,3 +169,92 @@ test('NaN path segments fall back instead of reaching the server', async () => { assert.deepEqual(calls, ['/r/sat/9', '/r/sat/9', '/r/children/abci0']); }); + +// Routes verified against mainnet ordinals.com before these wrappers were added: +// /r/inscription/, /r/parents/[/] (paginates with page_index), +// /r/children//inscriptions[/] (paginates with page), +// /r/undelegated-content/, /r/blockinfo/. +// +// This test can only prove string construction; it cannot prove a route exists. +// 'latest' was documented here until a live probe returned 400 ("invalid digit +// found in string"), so the height and hash forms are what is pinned. +test('endpoint wrappers build their documented routes', async () => { + const { OrdJS, calls } = load({ body: json({ ok: true }) }); + const ord = new OrdJS(''); + const hash = '0000000000000000000320283a032748cef8227873ff4872689bf23f1cda83a5'; // real block 840000 hash, 64 hex chars + + await ord.getInscription('abci0'); + await ord.getParents('abci0'); + await ord.getParents('abci0', 0); + await ord.getChildrenInscriptions('abci0'); + await ord.getChildrenInscriptions('abci0', 2); + await ord.getBlockInfo(840000); + await ord.getBlockInfo(hash); + + assert.deepEqual(calls, [ + '/r/inscription/abci0', + '/r/parents/abci0', + '/r/parents/abci0/0', + '/r/children/abci0/inscriptions', + '/r/children/abci0/inscriptions/2', + '/r/blockinfo/840000', + `/r/blockinfo/${hash}` + ]); +}); + +test('undelegated content returns own bytes and does not follow the delegate', async () => { + const own = Uint8Array.from([9, 8, 7]); + const delegated = Uint8Array.from([1, 1, 1]); + const { OrdJS, calls } = load({ + body: (url) => (url.startsWith('/r/undelegated-content/') ? binary(own)() : binary(delegated)()) + }); + const ord = new OrdJS(''); + + const undelegated = await ord.getUndelegatedContent('abci0'); + const followed = await ord.getInscriptionContent('abci0'); + + assert.equal(undelegated.base64, Buffer.from(own).toString('base64')); + assert.equal(followed.base64, Buffer.from(delegated).toString('base64')); + assert.deepEqual(calls, ['/r/undelegated-content/abci0', '/content/abci0']); +}); + +test('indexed sat content is fetched in one request', async () => { + const bytes = Uint8Array.from([4, 5, 6]); + const { OrdJS, calls } = load({ body: binary(bytes) }); + const ord = new OrdJS(''); + + const latest = await ord.getSatInscriptionContent(1469077634181728); + const first = await ord.getSatInscriptionContent(1469077634181728, 0); + + assert.equal(latest.base64, Buffer.from(bytes).toString('base64')); + assert.equal(first.base64, Buffer.from(bytes).toString('base64')); + assert.deepEqual(calls, [ + '/r/sat/1469077634181728/at/-1/content', + '/r/sat/1469077634181728/at/0/content' + ]); +}); + +test("a failure carries ord's own explanation, the status and the endpoint", async () => { + const { OrdJS } = load({ body: failure(404, 'inscription on sat 1 not found\n') }); + const ord = new OrdJS(''); + + const error = await ord.getSatInscriptionContent(1, 0).then(() => null, (e) => e); + assert.match(error.message, /404/); + assert.match(error.message, /\/r\/sat\/1\/at\/0\/content/); + assert.match(error.message, /inscription on sat 1 not found/); + assert.equal(error.status, 404); + + const jsonError = await ord.getMetadata('abci0').then(() => null, (e) => e); + assert.match(jsonError.message, /OrdJS 404 \/r\/metadata\/abci0: inscription on sat 1 not found/); + assert.equal(jsonError.status, 404); +}); + +test('an unreadable error body still produces a usable error', async () => { + const { OrdJS } = load({ + body: async () => ({ ok: false, status: 500, text: async () => { throw new Error('stream closed'); } }) + }); + + const error = await new OrdJS('').getBlockheight().then(() => null, (e) => e); + assert.match(error.message, /OrdJS 500 \/r\/blockheight/); + assert.equal(error.status, 500); +}); diff --git a/vendor/cbor2-decoder.js b/vendor/cbor2-decoder.js new file mode 100644 index 0000000..2acf8b1 --- /dev/null +++ b/vendor/cbor2-decoder.js @@ -0,0 +1,38 @@ +/*! + * CBOR decoder for OrdJS — bundled from cbor2@2.3.0 (decode only). + * Exposes globalThis.CBOR.decode(ArrayBuffer). + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Joe Hildebrand + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +var f={POS_INT:0,NEG_INT:1,BYTE_STRING:2,UTF8_STRING:3,ARRAY:4,MAP:5,TAG:6,SIMPLE_FLOAT:7},T={DATE_STRING:0,DATE_EPOCH:1,POS_BIGINT:2,NEG_BIGINT:3,DECIMAL_FRAC:4,BIGFLOAT:5,BASE64URL_EXPECTED:21,BASE64_EXPECTED:22,BASE16_EXPECTED:23,CBOR:24,URI:32,BASE64URL:33,BASE64:34,MIME:36,DATE_EPOCH_DAYS:100,SET:258,JSON:262,WTF8:273,SYMBOL:280,DATE_FULL:1004,REGEXP:21066,SELF_DESCRIBED:55799,INVALID_16:65535,INVALID_32:4294967295,INVALID_64:0xffffffffffffffffn},I={ZERO:0,ONE:24,TWO:25,FOUR:26,EIGHT:27,INDEFINITE:31},o={FALSE:20,TRUE:21,NULL:22,UNDEFINED:23};class A{static BREAK=Symbol.for("github.com/hildjj/cbor2/break");static ENCODED=Symbol.for("github.com/hildjj/cbor2/cbor-encoded");static LENGTH=Symbol.for("github.com/hildjj/cbor2/length")}var S={MIN:-(2n**63n),MAX:2n**64n-1n};class o2{static#e=new Map;tag;contents;constructor(e,t=void 0){this.tag=e,this.contents=t}get noChildren(){return!!o2.#e.get(this.tag)?.noChildren}static registerDecoder(e,t,n){let i=this.#e.get(e);return this.#e.set(e,t),i&&(("comment"in t)||(t.comment=i.comment),("noChildren"in t)||(t.noChildren=i.noChildren)),n&&!t.comment&&(t.comment=()=>`(${n})`),i}static clearDecoder(e){let t=this.#e.get(e);return this.#e.delete(e),t}static getDecoder(e){return this.#e.get(e)}static getAllDecoders(){return new Map(this.#e)}*[Symbol.iterator](){yield this.contents}push(e){return this.contents=e,1}decode(e){let t=e?.tags?.get(this.tag)??(e?.ignoreGlobalTags?void 0:o2.#e.get(this.tag));return t?t(this,e):this}comment(e,t){let n=e?.tags?.get(this.tag)??(e?.ignoreGlobalTags?void 0:o2.#e.get(this.tag));if(n?.comment)return n.comment(this,e,t)}toCBOR(){return[this.tag,this.contents]}[Symbol.for("nodejs.util.inspect.custom")](e,t,n){return`${this.tag}(${n(this.contents,t)})`}}function f2(n){if(n!=null&&typeof n=="object")return n[A.ENCODED]}function s(n){if(n!=null&&typeof n=="object")return n[A.LENGTH]}function u(n,e){Object.defineProperty(n,A.ENCODED,{configurable:!0,enumerable:!1,value:e})}function d(n,e){let r=Object(n);return u(r,e),r}var g=Symbol("CBOR_RANGES");function c(r,n){Object.defineProperty(r,g,{configurable:!1,enumerable:!1,writable:!1,value:n})}function f3(r){return r[g]}function l(r){return f3(r)!==void 0}function R(r,n=0,t=r.length-1){let o3=r.subarray(n,t),a=f3(r);if(a){let s2=[];for(let e of a)if(e[0]>=n&&e[0]+e[1]<=t){let i=[...e];i[0]-=n,s2.push(i)}s2.length&&c(o3,s2)}return o3}function b(r){let n=Math.ceil(r.length/2),t=new Uint8Array(n);n--;for(let o3=r.length,a=o3-2;o3>=0;o3=a,a-=2,n--)t[n]=parseInt(r.substring(a,o3),16);return t}function A2(r){return r.reduce((n,t)=>n+t.toString(16).padStart(2,"0"),"")}function d2(r){let n=r.reduce((e,i)=>e+i.length,0),t=r.some((e)=>l(e)),o3=[],a=new Uint8Array(n),s2=0;for(let e of r){if(!(e instanceof Uint8Array))throw TypeError(`Invalid array: ${e}`);if(a.set(e,s2),t){let i=e[g]??[[0,e.length]];for(let u2 of i)u2[0]+=s2;o3.push(...i)}s2+=e.length}return t&&c(a,o3),a}function y(r){let n=atob(r);return Uint8Array.from(n,(t)=>t.codePointAt(0))}var p={"-":"+",_:"/"};function x(r){let n=r.replace(/[_-]/g,(t)=>p[t]);return y(n.padEnd(Math.ceil(n.length/4)*4,"="))}function h(){let r=new Uint8Array(4),n=new Uint32Array(r.buffer);return!((n[0]=1)&r[0])}function U(r){let n="";for(let t of r){let o3=t.codePointAt(0)?.toString(16).padStart(4,"0");n&&(n+=", "),n+=`U+${o3}`}return n}class s2{#e=new Map;registerEncoder(e,t){let n=this.#e.get(e);return this.#e.set(e,t),n}get(e){return this.#e.get(e)}delete(e){return this.#e.delete(e)}clear(){this.#e.clear()}}function f4(c2,d3){let[u2,a,n]=c2,[l2,s3,t]=d3,r=Math.min(n.length,t.length);for(let o3=0;o3= 8, got ${this.#r.chunkSize}`);this.#n()}get length(){return this.#a}read(){this.#o();let t=new Uint8Array(this.#a),i=0;for(let s3 of this.#i)t.set(s3,i),i+=s3.length;return this.#n(),t}write(t){let i=t.length;i>this.#l()?(this.#o(),i>this.#r.chunkSize?(this.#i.push(t),this.#n()):(this.#n(),this.#i[this.#i.length-1].set(t),this.#t=i)):(this.#i[this.#i.length-1].set(t,this.#t),this.#t+=i),this.#a+=i}writeUint8(t){this.#e(1),this.#s.setUint8(this.#t,t),this.#h(1)}writeUint16(t,i=!1){this.#e(2),this.#s.setUint16(this.#t,t,i),this.#h(2)}writeUint32(t,i=!1){this.#e(4),this.#s.setUint32(this.#t,t,i),this.#h(4)}writeBigUint64(t,i=!1){this.#e(8),this.#s.setBigUint64(this.#t,t,i),this.#h(8)}writeInt16(t,i=!1){this.#e(2),this.#s.setInt16(this.#t,t,i),this.#h(2)}writeInt32(t,i=!1){this.#e(4),this.#s.setInt32(this.#t,t,i),this.#h(4)}writeBigInt64(t,i=!1){this.#e(8),this.#s.setBigInt64(this.#t,t,i),this.#h(8)}writeFloat32(t,i=!1){this.#e(4),this.#s.setFloat32(this.#t,t,i),this.#h(4)}writeFloat64(t,i=!1){this.#e(8),this.#s.setFloat64(this.#t,t,i),this.#h(8)}clear(){this.#a=0,this.#i=[],this.#n()}#n(){let t=new Uint8Array(this.#r.chunkSize);this.#i.push(t),this.#t=0,this.#s=new DataView(t.buffer,t.byteOffset,t.byteLength)}#o(){if(this.#t===0){this.#i.pop();return}let t=this.#i.length-1;this.#i[t]=this.#i[t].subarray(0,this.#t),this.#t=0,this.#s=null}#l(){let t=this.#i.length-1;return this.#i[t].length-this.#t}#e(t){this.#l()(t[t.NATURAL=-2]="NATURAL",t[t.UNKNOWN=-1]="UNKNOWN",t[t.F16=2]="F16",t[t.F32=4]="F32",t[t.F64=8]="F64",t))(x2||{});function U2(i,n,e2,r){let o3="nan'";return i.quiet||(o3+="!"),i.sign===-1&&(o3+="-"),o3+=r(Math.abs(i.payload),e2),o3+="'",o3+=i.encodingIndicator,o3}class O extends Number{#n;#t=-1;constructor(n,e2=!0,r=-1){super(NaN);let o3=n;if(typeof n=="number"){if(!Number.isSafeInteger(n))throw Error(`Invalid NAN payload: ${n}`);n=BigInt(n);let t=0n;if(n<0&&(t=N,n=-n),n>=c2)throw Error(`Payload too large: ${o3}`);let s3=e2?c2:0n;switch(this.#n=t|a|s3|n,r){case-2:throw Error("NAN_SIZE.NATURAL only valid for bigint constructor");case-1:r=this.preferredSize;break;case 2:if(this.#n&_)throw Error("Invalid size for payload");break;case 4:if(this.#n&S2)throw Error("Invalid size for payload");break;case 8:break;default:throw Error(`Invalid size: ${r}`)}this.#t=r}else if(typeof n=="bigint"){let t=-1;if((n&a)===a)this.#n=n,t=8;else if((n&l2)===l2){let s3=(n&g2)<<32n;this.#n=s3|a|(n&p2)<<29n,t=4}else if((n&f5)===f5){let s3=(n&w)<<48n;this.#n=s3|a|(n&I2)<<42n,t=2}else throw Error(`Invalid raw NaN value: ${n}`);if(r===-1)this.#t=this.preferredSize;else if(r===-2)this.#t=t;else{if(r>42n;e2.setUint16(1,Number(o3),!1);break}case 4:{e2.setUint8(0,250);let o3=(this.#n&N?g2:0n)|l2|(this.#n&F)>>29n;e2.setUint32(1,Number(o3),!1);break}case 8:e2.setUint8(0,251),e2.setBigUint64(1,this.#n);break}return new Uint8Array(n)}get quiet(){return!!(this.#n&c2)}get sign(){return this.#n&N?-1:1}get payload(){return Number(this.#n&u2)*this.sign}get raw(){return this.#n}get encodingIndicator(){switch(this.#t){case 2:return"_1";case 4:return"_2"}return"_3"}get size(){return this.#t}get preferredSize(){return(this.#n&_)===0n?2:(this.#n&S2)===0n?4:8}get isShortestEncoding(){return this.preferredSize===this.#t}toCBOR(n){n.write(this.bytes)}toString(n=10){return U2(this,1,{},(e2)=>(m[n]??"")+e2.toString(n))}[Symbol.for("nodejs.util.inspect.custom")](n,e2,r){return U2(this,n,e2,r)}}function v(i,n=0,e2=!1){let r=i[n]&128?-1:1,o3=(i[n]&124)>>2,t=(i[n]&3)<<8|i[n+1];if(o3===0){if(e2&&t!==0)throw Error(`Unwanted subnormal: ${r*0.00000005960464477539063*t}`);return r*0.00000005960464477539063*t}else if(o3===31)return t?NaN:r*(1/0);return r*2**(o3-25)*(1024+t)}function Z(i){let n=new DataView(new ArrayBuffer(4));n.setFloat32(0,i,!1);let e2=n.getUint32(0,!1);if((e2&8191)!==0)return null;let r=e2>>16&32768,o3=e2>>23&255,t=e2&8388607;if(!(o3===0&&t===0))if(o3>=113&&o3<=142)r+=(o3-112<<10)+(t>>13);else if(o3>=103&&o3<113){if(t&(1<<126-o3)-1)return null;r+=t+8388608>>126-o3}else if(o3===255)r|=31744,r|=t>>13;else return null;return r}function k(i){if(i!==0){let n=new ArrayBuffer(8),e2=new DataView(n);e2.setFloat64(0,i,!1);let r=e2.getBigUint64(0,!1);if((r&0x7ff0000000000000n)===0n)return r&0x8000000000000000n?-0:0}return i}function B(i){switch(i.length){case 2:v(i,0,!0);break;case 4:{let n=new DataView(i.buffer,i.byteOffset,i.byteLength),e2=n.getUint32(0,!1);if((e2&2139095040)===0&&e2&8388607)throw Error(`Unwanted subnormal: ${n.getFloat32(0,!1)}`);break}case 8:{let n=new DataView(i.buffer,i.byteOffset,i.byteLength),e2=n.getBigUint64(0,!1);if((e2&0x7ff0000000000000n)===0n&&e2&0x000fffffffffffn)throw Error(`Unwanted subnormal: ${n.getFloat64(0,!1)}`);break}default:throw TypeError(`Bad input to isSubnormal: ${i}`)}}class DecodeError extends TypeError{code="ERR_ENCODING_INVALID_ENCODED_DATA";constructor(){super("The encoded data was not valid for encoding wtf-8")}}class InvalidEncodingError extends RangeError{code="ERR_ENCODING_NOT_SUPPORTED";constructor(label){super(`Invalid encoding: "${label}"`)}}var BOM=65279,EMPTY=new Uint8Array(0),MAX_HIGH_SURROGATE=56319;var MIN_HIGH_SURROGATE=55296,MIN_LOW_SURROGATE=56320,REPLACEMENT=65533,WTF8="wtf-8";function isArrayBufferView(input){return input&&typeof input==="object"&&!(input instanceof ArrayBuffer)&&!(input instanceof SharedArrayBuffer)&&input.buffer instanceof ArrayBuffer}function getUint8(input){if(!input)return EMPTY;if(input instanceof Uint8Array)return input;if(isArrayBufferView(input))return new Uint8Array(input.buffer,input.byteOffset,input.byteLength);return new Uint8Array(input)}var REMAINDER=[0,0,0,0,0,0,0,0,-1,-1,-1,-1,1,1,2,3];class Wtf8Decoder{static DEFAULT_BUFFERSIZE=4096;encoding=WTF8;fatal;ignoreBOM;bufferSize;#left=0;#cur=0;#pending=0;#first=!0;#buf;constructor(label="wtf8",options=void 0){if(label.toLowerCase().replace("-","")!=="wtf8")throw new InvalidEncodingError(label);if(this.fatal=Boolean(options?.fatal),this.ignoreBOM=Boolean(options?.ignoreBOM),this.bufferSize=Math.floor(options?.bufferSize??Wtf8Decoder.DEFAULT_BUFFERSIZE),isNaN(this.bufferSize)||this.bufferSize<1)throw RangeError(`Invalid buffer size: ${options?.bufferSize}`);this.#buf=new Uint16Array(this.bufferSize)}decode(input,options){let streaming=Boolean(options?.stream),bytes=getUint8(input),res=[],out=this.#buf,maxSize=this.bufferSize-3,pos=0,fatal=()=>{if(this.#cur=0,this.#left=0,this.#pending=0,this.fatal)throw new DecodeError;out[pos++]=REPLACEMENT},fatals=()=>{let p3=this.#pending;for(let i=0;i{if(this.#left===0)switch(REMAINDER[b3>>4]){case-1:fatal();break;case 0:out[pos++]=b3;break;case 1:if(this.#cur=b3&31,(this.#cur&30)===0)fatal();else this.#left=1,this.#pending=1;break;case 2:this.#cur=b3&15,this.#left=2,this.#pending=1;break;case 3:if(b3&8)fatal();else this.#cur=b3&7,this.#left=3,this.#pending=1;break}else{if((b3&192)!==128)return fatals(),oneByte(b3);if(this.#pending===1&&this.#left===2&&this.#cur===0&&(b3&32)===0)return fatals(),oneByte(b3);if(this.#left===3&&this.#cur===0&&(b3&48)===0)return fatals(),oneByte(b3);if(this.#cur=this.#cur<<6|b3&63,this.#pending++,--this.#left===0){if(this.ignoreBOM||!this.#first||this.#cur!==BOM)if(this.#cur<65536)out[pos++]=this.#cur;else{let cp=this.#cur-65536;out[pos++]=cp>>>10&1023|MIN_HIGH_SURROGATE,out[pos++]=cp&1023|MIN_LOW_SURROGATE}this.#cur=0,this.#pending=0,this.#first=!1}}};for(let b3 of bytes){if(pos>=maxSize)res.push(String.fromCharCode.apply(null,out.subarray(0,pos))),pos=0;oneByte(b3)}if(!streaming){if(this.#first=!0,this.#cur||this.#left)fatals()}if(pos>0)res.push(String.fromCharCode.apply(null,out.subarray(0,pos)));return res.join("")}}function utf8length(str){let len=0;for(let s3 of str){let cp=s3.codePointAt(0);if(cp<128)len++;else if(cp<2048)len+=2;else if(cp<65536)len+=3;else len+=4}return len}class Wtf8Encoder{encoding=WTF8;encode(input){if(!input)return EMPTY;let buf=new Uint8Array(utf8length(String(input)));return this.encodeInto(input,buf),buf}encodeInto(source,destination){let str=String(source),len=str.length,outLen=destination.length,written=0,read=0;for(read=0;read=outLen)break;destination[written++]=c3}else if(c3<2048){if(written>=outLen-1)break;destination[written++]=192|c3>>6,destination[written++]=128|c3&63}else if(c3<65536){if(written>=outLen-2)break;destination[written++]=224|c3>>12,destination[written++]=128|c3>>6&63,destination[written++]=128|c3&63}else{if(written>=outLen-3)break;destination[written++]=240|c3>>18,destination[written++]=128|c3>>12&63,destination[written++]=128|c3>>6&63,destination[written++]=128|c3&63,read++}}return{read,written}}}class Wtf8DecoderStream{#handle;#transform;constructor(encoding="wtf-8",options=void 0){let dec=new Wtf8Decoder(encoding,options);this.#handle=dec,this.#transform=new TransformStream({transform(chunk,controller){let value=dec.decode(chunk,{stream:!0});if(value)controller.enqueue(value)},flush(controller){let value=dec.decode();if(value)controller.enqueue(value);controller.terminate()}})}get encoding(){return this.#handle.encoding}get fatal(){return this.#handle.fatal}get ignoreBOM(){return this.#handle.ignoreBOM}get readable(){return this.#transform.readable}get writable(){return this.#transform.writable}}function isHighSurrogate(n){return MIN_HIGH_SURROGATE<=n&&n<=MAX_HIGH_SURROGATE}class Wtf8EncoderStream{#pendingHighSurrogate=null;#handle;#transform;constructor(){this.#handle=new Wtf8Encoder,this.#transform=new TransformStream({transform:(chunk,controller)=>{if(chunk=String(chunk),this.#pendingHighSurrogate!=null)chunk=this.#pendingHighSurrogate+chunk,this.#pendingHighSurrogate=null;if(isHighSurrogate(chunk.charCodeAt(chunk.length-1)))this.#pendingHighSurrogate=chunk[chunk.length-1],chunk=chunk.slice(0,-1);if(chunk){let value=this.#handle.encode(chunk);if(value.length)controller.enqueue(value)}},flush:(controller)=>{if(this.#pendingHighSurrogate!==null)controller.enqueue(this.#handle.encode(this.#pendingHighSurrogate)),this.#pendingHighSurrogate=null}})}get encoding(){return this.#handle.encoding}get readable(){return this.#transform.readable}get writable(){return this.#transform.writable}}var U3=f.SIMPLE_FLOAT<<5|I.TWO,h2=f.SIMPLE_FLOAT<<5|I.FOUR,B2=f.SIMPLE_FLOAT<<5|I.EIGHT,j=f.SIMPLE_FLOAT<<5|o.TRUE,q=f.SIMPLE_FLOAT<<5|o.FALSE,$=f.SIMPLE_FLOAT<<5|o.UNDEFINED,z=f.SIMPLE_FLOAT<<5|o.NULL,H=new TextEncoder,K=new Wtf8Encoder,k2={...e.defaultOptions,avoidInts:!1,cde:!1,collapseBigInts:!0,dateTag:T.DATE_EPOCH,dcbor:!1,float64:!1,flushToZero:!1,forceEndian:null,ignoreOriginalEncoding:!1,largeNegativeAsBigInt:!1,reduceUnsafeNumbers:!1,rejectBigInts:!1,rejectCustomSimples:!1,rejectDuplicateKeys:!1,rejectFloats:!1,rejectUndefined:!1,simplifyNegativeZero:!1,sortKeys:null,stringNormalization:null,types:null,wtf8:!1,ignoreGlobalTags:!1},F2={cde:!0,ignoreOriginalEncoding:!0,sortKeys:f4},Y={...F2,dcbor:!0,largeNegativeAsBigInt:!0,reduceUnsafeNumbers:!0,rejectCustomSimples:!0,rejectDuplicateKeys:!0,rejectUndefined:!0,simplifyNegativeZero:!0,stringNormalization:"NFC"};function y2(e2){let n=e2<0;return typeof e2=="bigint"?[n?-e2-1n:e2,n]:[n?-e2-1:e2,n]}function N2(e2,n,i){if(i.rejectFloats)throw Error(`Attempt to encode an unwanted floating point number: ${e2}`);if(isNaN(e2))n.writeUint8(U3),n.writeUint16(32256);else if(!i.float64&&Math.fround(e2)===e2){let r=Z(e2);r===null?(n.writeUint8(h2),n.writeFloat32(e2)):(n.writeUint8(U3),n.writeUint16(r))}else n.writeUint8(B2),n.writeFloat64(e2)}function a2(e2,n,i){let[r,t]=y2(e2);if(t&&i)throw TypeError(`Negative size: ${e2}`);i??=t?f.NEG_INT:f.POS_INT,i<<=5,r<24?n.writeUint8(i|r):r<=255?(n.writeUint8(i|I.ONE),n.writeUint8(r)):r<=65535?(n.writeUint8(i|I.TWO),n.writeUint16(r)):r<=4294967295?(n.writeUint8(i|I.FOUR),n.writeUint32(r)):(n.writeUint8(i|I.EIGHT),n.writeBigUint64(BigInt(r)))}function m2(e2,n,i){typeof e2=="number"?a2(e2,n,f.TAG):typeof e2=="object"&&!i.ignoreOriginalEncoding&&(A.ENCODED in e2)?n.write(e2[A.ENCODED]):e2<=Number.MAX_SAFE_INTEGER?a2(Number(e2),n,f.TAG):(n.writeUint8(f.TAG<<5|I.EIGHT),n.writeBigUint64(BigInt(e2)))}function O2(e2,n,i){let[r,t]=y2(e2);if(i.collapseBigInts&&(!i.largeNegativeAsBigInt||e2>=-0x8000000000000000n)){if(r<=0xffffffffn){a2(Number(e2),n);return}if(r<=0xffffffffffffffffn){let l3=(t?f.NEG_INT:f.POS_INT)<<5;n.writeUint8(l3|I.EIGHT),n.writeBigUint64(r);return}}if(i.rejectBigInts)throw Error(`Attempt to encode unwanted bigint: ${e2}`);let o3=t?T.NEG_BIGINT:T.POS_BIGINT,c3=r.toString(16),s3=c3.length%2?"0":"";m2(o3,n,i);let u3=b(s3+c3);a2(u3.length,n,f.BYTE_STRING),n.write(u3)}function Z2(e2,n,i){i.flushToZero&&(e2=k(e2)),Object.is(e2,-0)?i.simplifyNegativeZero?i.avoidInts?N2(0,n,i):a2(0,n):N2(e2,n,i):!i.avoidInts&&Number.isSafeInteger(e2)?a2(e2,n):i.reduceUnsafeNumbers&&Math.floor(e2)===e2&&e2>=S.MIN&&e2<=S.MAX?O2(BigInt(e2),n,i):N2(e2,n,i)}function R2(e2,n,i){let r=i.stringNormalization?e2.normalize(i.stringNormalization):e2;if(i.wtf8&&!e2.isWellFormed()){let t=K.encode(r);m2(T.WTF8,n,i),a2(t.length,n,f.BYTE_STRING),n.write(t)}else{let t=H.encode(r);a2(t.length,n,f.UTF8_STRING),n.write(t)}}function J(e2,n,i){let r=e2;L(r,r.length,f.ARRAY,n,i);for(let t of r)g3(t,n,i)}function V(e2,n){a2(e2.length,n,f.BYTE_STRING),n.write(e2)}var b3=new s2;b3.registerEncoder(Array,J),b3.registerEncoder(Uint8Array,V);function ue(e2,n){return b3.registerEncoder(e2,n)}function L(e2,n,i,r,t){let o3=s(e2);o3&&!t.ignoreOriginalEncoding?r.write(o3):a2(n,r,i)}function X(e2,n,i){if(e2===null){n.writeUint8(z);return}if(!i.ignoreOriginalEncoding&&A.ENCODED in e2){n.write(e2[A.ENCODED]);return}let r=e2.constructor;if(r){let o3=i.types?.get(r)??(i.ignoreGlobalTags?void 0:b3.get(r));if(o3){let c3=o3(e2,n,i);if(c3!==void 0){if(!Array.isArray(c3)||c3.length!==2)throw Error("Invalid encoder return value");(typeof c3[0]=="bigint"||isFinite(Number(c3[0])))&&m2(c3[0],n,i),g3(c3[1],n,i)}return}}if(typeof e2.toCBOR=="function"){let o3=e2.toCBOR(n,i);o3&&((typeof o3[0]=="bigint"||isFinite(Number(o3[0])))&&m2(o3[0],n,i),g3(o3[1],n,i));return}if(typeof e2.toJSON=="function"){g3(e2.toJSON(),n,i);return}let t=Object.entries(e2).map((o3)=>[o3[0],o3[1],v2(o3[0],i)]);i.sortKeys&&t.sort(i.sortKeys),L(e2,t.length,f.MAP,n,i);for(let[o3,c3,s3]of t)n.write(s3),g3(c3,n,i)}function Q(e2,n,i){if(!e2.description||e2!==Symbol.for(e2.description))throw TypeError(`Private or empty symbol: ${e2.toString()}`);m2(280,n,i),R2(e2.description,n,i)}function g3(e2,n,i){switch(typeof e2){case"number":Z2(e2,n,i);break;case"bigint":O2(e2,n,i);break;case"string":R2(e2,n,i);break;case"boolean":n.writeUint8(e2?j:q);break;case"undefined":if(i.rejectUndefined)throw Error("Attempt to encode unwanted undefined.");n.writeUint8($);break;case"object":X(e2,n,i);break;case"symbol":Q(e2,n,i);break;default:throw TypeError(`Unknown type: ${typeof e2}, ${String(e2)}`)}}function v2(e2,n={}){let i={...k2};n.dcbor?Object.assign(i,Y):n.cde&&Object.assign(i,F2),Object.assign(i,n);let r=new e(i);return g3(e2,r,i),r.read()}var o3=((e2)=>(e2[e2.NEVER=-1]="NEVER",e2[e2.PREFERRED=0]="PREFERRED",e2[e2.ALWAYS=1]="ALWAYS",e2))(o3||{});class t{static KnownSimple=new Map([[o.FALSE,!1],[o.TRUE,!0],[o.NULL,null],[o.UNDEFINED,void 0]]);value;constructor(e2){this.value=e2}static create(e2){return t.KnownSimple.has(e2)?t.KnownSimple.get(e2):new t(e2)}toCBOR(e2,i){if(i.rejectCustomSimples)throw Error(`Cannot encode non-standard Simple value: ${this.value}`);a2(this.value,e2,f.SIMPLE_FLOAT)}toString(){return`simple(${this.value})`}decode(){return t.KnownSimple.has(this.value)?t.KnownSimple.get(this.value):this}[Symbol.for("nodejs.util.inspect.custom")](e2,i,r){return`simple(${r(this.value,i)})`}}var p3=new TextDecoder("utf8",{fatal:!0,ignoreBOM:!0});class y3{static defaultOptions={maxDepth:1024,encoding:"hex",requirePreferred:!1};#t;#r;#e=0;#i;constructor(t2,r){if(this.#i={...y3.defaultOptions,...r},typeof t2=="string")switch(this.#i.encoding){case"hex":this.#t=b(t2);break;case"base64":this.#t=y(t2);break;default:throw TypeError(`Encoding not implemented: "${this.#i.encoding}"`)}else this.#t=t2;this.#r=new DataView(this.#t.buffer,this.#t.byteOffset,this.#t.byteLength)}toHere(t2){return R(this.#t,t2,this.#e)}*[Symbol.iterator](){if(yield*this.#n(0),this.#e!==this.#t.length)throw Error("Extra data in input")}*seq(){for(;this.#ethis.#i.maxDepth)throw Error(`Maximum depth ${this.#i.maxDepth} exceeded`);let r=this.#e,c3=this.#r.getUint8(this.#e++),i=c3>>5,n=c3&31,e2=n,f6=!1,a3=0;switch(n){case I.ONE:if(a3=1,e2=this.#r.getUint8(this.#e),i===f.SIMPLE_FLOAT){if(e2<32)throw Error(`Invalid simple encoding in extra byte: ${e2}`);f6=!0}else if(this.#i.requirePreferred&&e2<24)throw Error(`Unexpectedly long integer encoding (1) for ${e2}`);break;case I.TWO:if(a3=2,i===f.SIMPLE_FLOAT)e2=v(this.#t,this.#e);else if(e2=this.#r.getUint16(this.#e,!1),this.#i.requirePreferred&&e2<=255)throw Error(`Unexpectedly long integer encoding (2) for ${e2}`);break;case I.FOUR:if(a3=4,i===f.SIMPLE_FLOAT)e2=this.#r.getFloat32(this.#e,!1);else if(e2=this.#r.getUint32(this.#e,!1),this.#i.requirePreferred&&e2<=65535)throw Error(`Unexpectedly long integer encoding (4) for ${e2}`);break;case I.EIGHT:{if(a3=8,i===f.SIMPLE_FLOAT)e2=this.#r.getFloat64(this.#e,!1);else if(e2=this.#r.getBigUint64(this.#e,!1),e2<=Number.MAX_SAFE_INTEGER&&(e2=Number(e2)),this.#i.requirePreferred&&e2<=4294967295)throw Error(`Unexpectedly long integer encoding (8) for ${e2}`);break}case 28:case 29:case 30:throw Error(`Additional info not implemented: ${n}`);case I.INDEFINITE:switch(i){case f.POS_INT:case f.NEG_INT:case f.TAG:throw Error(`Invalid indefinite encoding for MT ${i}`);case f.SIMPLE_FLOAT:yield[i,n,A.BREAK,r,0];return}e2=1/0;break;default:f6=!0}switch(this.#e+=a3,i){case f.POS_INT:yield[i,n,e2,r,a3];break;case f.NEG_INT:yield[i,n,typeof e2=="bigint"?-1n-e2:-1-Number(e2),r,a3];break;case f.BYTE_STRING:e2===1/0?yield*this.#s(i,t2,r):yield[i,n,this.#a(e2),r,e2];break;case f.UTF8_STRING:e2===1/0?yield*this.#s(i,t2,r):yield[i,n,p3.decode(this.#a(e2)),r,e2];break;case f.ARRAY:if(e2===1/0)yield*this.#s(i,t2,r,!1);else{let o4=Number(e2);yield[i,n,o4,r,a3];for(let h3=0;h3typeof i=="string")?Object.fromEntries(h3):new Map(h3)}class y4{static defaultDecodeOptions={...y3.defaultOptions,ParentType:y4,boxed:!1,cde:!1,dcbor:!1,diagnosticSizes:o3.PREFERRED,collapseBigInts:!1,convertUnsafeIntsToFloat:!1,createObject:F3,keepNanPayloads:!1,pretty:!1,preferBigInt:!1,preferMap:!1,rejectLargeNegatives:!1,rejectBigInts:!1,rejectDuplicateKeys:!1,rejectFloats:!1,rejectInts:!1,rejectLongLoundNaN:!1,rejectLongFloats:!1,rejectNegativeZero:!1,rejectSimple:!1,rejectStreaming:!1,rejectStringsNotNormalizedAs:null,rejectSubnormals:!1,rejectUndefined:!1,rejectUnsafeFloatInts:!1,saveOriginal:!1,sortKeys:null,tags:null,ignoreGlobalTags:!1};static cdeDecodeOptions={cde:!0,rejectStreaming:!0,requirePreferred:!0,sortKeys:f4};static dcborDecodeOptions={...this.cdeDecodeOptions,dcbor:!0,convertUnsafeIntsToFloat:!0,rejectDuplicateKeys:!0,rejectLargeNegatives:!0,rejectLongLoundNaN:!0,rejectLongFloats:!0,rejectNegativeZero:!0,rejectSimple:!0,rejectUndefined:!0,rejectUnsafeFloatInts:!0,rejectStringsNotNormalizedAs:"NFC"};parent;mt;ai;left;offset;count=0;children=[];depth=0;#e;#t=null;constructor(r,i,e2,t2){if([this.mt,this.ai,,this.offset]=r,this.left=i,this.parent=e2,this.#e=t2,e2&&(this.depth=e2.depth+1),this.mt===f.MAP&&(this.#e.sortKeys||this.#e.rejectDuplicateKeys)&&(this.#t=[]),this.#e.rejectStreaming&&this.ai===I.INDEFINITE)throw Error("Streaming not supported")}get isStreaming(){return this.left===1/0}get done(){return this.left===0}static create(r,i,e2,t2){let[s3,u3,n,c3]=r;switch(s3){case f.POS_INT:case f.NEG_INT:{if(e2.rejectInts)throw Error(`Unexpected integer: ${n}`);if(e2.rejectLargeNegatives&&n<-0x8000000000000000n)throw Error(`Invalid 65bit negative number: ${n}`);let o4=n;return e2.preferBigInt?o4=BigInt(o4):e2.convertUnsafeIntsToFloat&&o4>=S.MIN&&o4<=S.MAX&&(o4=Number(n)),e2.boxed?d(o4,t2.toHere(c3)):o4}case f.SIMPLE_FLOAT:if(u3>I.ONE){if(typeof n=="symbol")return n;if(e2.rejectFloats)throw Error(`Decoding unwanted floating point number: ${n}`);if(e2.rejectNegativeZero&&Object.is(n,-0))throw Error("Decoding negative zero");if(isNaN(n)){let o4=t2.toHere(c3),f6=new O(o4);if(e2.rejectLongLoundNaN){if(f6.payload||o4.length>3)throw Error(`Invalid NaN encoding: "${A2(o4)}"`)}else if(e2.keepNanPayloads&&(f6.payload||f6.sign===-1)){if(e2.rejectLongFloats&&!f6.isShortestEncoding)throw Error(`NaN should have been encoded shorter: ${n}`);return f6}}if(e2.rejectSubnormals&&B(t2.toHere(c3+1)),e2.rejectLongFloats){let o4=v2(n,{chunkSize:9,reduceUnsafeNumbers:e2.rejectUnsafeFloatInts});if(o4[0]>>5!==s3)throw Error(`Should have been encoded as int, not float: ${n}`);if(o4.length=0)throw Error(`Duplicate or out of order key: "0x${s3[2]}"`);t2=s3}}else if(this.#e.rejectDuplicateKeys){let t2=new Set;for(let[s3,u3,n]of e2){let c3=A2(n);if(t2.has(c3))throw Error(`Duplicate key: "0x${c3}"`);t2.add(c3)}}i=this.#e.createObject(e2,this.#e);break}case f.BYTE_STRING:return d2(this.children);case f.UTF8_STRING:{let e2=this.children.join("");i=this.#e.boxed?d(e2,r.toHere(this.offset)):e2;break}case f.TAG:i=this.children.decode(this.#e);break;default:throw TypeError(`Invalid mt on convert: ${this.mt}`)}return this.#e.saveOriginal&&i&&typeof i=="object"&&u(i,r.toHere(this.offset)),i}#r(){let r=this.children,i=r.length;if(i%2)throw Error("Missing map value");let e2=Array(i/2);if(this.#t)for(let t2=0;t2>1]=[r[t2],r[t2+1],this.#t[t2]];else for(let t2=0;t2>1]=[r[t2],r[t2+1],R3];return e2}}var O3=" ",y5=new TextEncoder;class g4 extends y4{close="";quote='"';get isEmptyStream(){return(this.mt===f.UTF8_STRING||this.mt===f.BYTE_STRING)&&this.count===0}}function a3(m3,l3,n,p4){let t2="";if(l3===I.INDEFINITE)t2+="_";else{if(p4.diagnosticSizes===o3.NEVER)return"";{let r=p4.diagnosticSizes===o3.ALWAYS;if(!r){let e2=I.ZERO;if(Object.is(n,-0))e2=I.TWO;else if(m3===f.POS_INT||m3===f.NEG_INT){let T2=n<0,u3=typeof n=="bigint"?1n:1,o4=T2?-n-u3:n;o4<=23?e2=Number(o4):o4<=255?e2=I.ONE:o4<=65535?e2=I.TWO:o4<=4294967295?e2=I.FOUR:e2=I.EIGHT}else isFinite(n)?Math.fround(n)===n?Z(n)==null?e2=I.FOUR:e2=I.TWO:e2=I.EIGHT:e2=I.TWO;r=e2!==l3}r&&(t2+="_",l30&&i!==A.BREAK&&(t2.mt===f.MAP&&t2.count%2?e2+=": ":(e2+=",",n.pretty||(e2+=" "))),n.pretty&&(t2.mt!==f.MAP||t2.count%2===0)&&(e2+=` +${O3.repeat(t2.depth+1)}`)),r=y4.create(T2,t2,n,p4),u3){case f.POS_INT:case f.NEG_INT:e2+=String(i),e2+=a3(u3,o4,i,n);break;case f.SIMPLE_FLOAT:if(i!==A.BREAK)if(typeof i=="number"){let c3=Object.is(i,-0)?"-0.0":String(i);e2+=c3,isFinite(i)&&!/[.e]/.test(c3)&&(e2+=".0"),e2+=a3(u3,o4,i,n)}else i instanceof t?(e2+="simple(",e2+=String(i.value),e2+=a3(f.POS_INT,o4,i.value,n),e2+=")"):e2+=String(i);break;case f.BYTE_STRING:i===1/0?(e2+="(_ ",r.close=")",r.quote="'"):(e2+="h'",e2+=A2(i),e2+="'",e2+=a3(f.POS_INT,o4,i.length,n));break;case f.UTF8_STRING:i===1/0?(e2+="(_ ",r.close=")"):(e2+=JSON.stringify(i),e2+=a3(f.POS_INT,o4,y5.encode(i).length,n));break;case f.ARRAY:{e2+="[";let c3=a3(f.POS_INT,o4,i,n);e2+=c3,c3&&(e2+=" "),n.pretty&&i?r.close=` +${O3.repeat(r.depth)}]`:r.close="]";break}case f.MAP:{e2+="{";let c3=a3(f.POS_INT,o4,i,n);e2+=c3,c3&&(e2+=" "),n.pretty&&i?r.close=` +${O3.repeat(r.depth)}}`:r.close="}";break}case f.TAG:e2+=String(i),e2+=a3(f.POS_INT,o4,i,n),e2+="(",r.close=")";break}if(r===A.BREAK)if(t2?.isStreaming)t2.left=0;else throw Error("Unexpected BREAK");else t2&&(t2.count++,t2.left--);for(r instanceof g4&&(t2=r);t2?.done;){if(t2.isEmptyStream)e2=e2.slice(0,-3),e2+=`${t2.quote}${t2.quote}_`;else{if(t2.mt===f.MAP&&t2.count%2!==0)throw Error(`Odd streaming map size: ${t2.count}`);e2+=t2.close}t2=t2.parent}}return e2}var H2=new TextDecoder;class A5 extends y4{depth=0;leaf=!1;value;length;[A.ENCODED];constructor(a4,f6,e2,n){super(a4,f6,e2,n),this.parent?this.depth=this.parent.depth+1:this.depth=n.initialDepth,[,,this.value,,this.length]=a4}numBytes(){switch(this.ai){case I.ONE:return 1;case I.TWO:return 2;case I.FOUR:return 4;case I.EIGHT:return 8}return 0}}function k3(t2){return t2 instanceof A5}function O4(t2,a4){return t2===1/0?"Indefinite":a4?`${t2} ${a4}${t2!==1&&t2!==1n?"s":""}`:String(t2)}function y6(t2){return"".padStart(t2," ")}function x3(t2,a4,f6){let e2="";e2+=y6(t2.depth*2);let n=f2(t2);e2+=A2(n.subarray(0,1));let r=t2.numBytes();r&&(e2+=" ",e2+=A2(n.subarray(1,r+1))),e2=e2.padEnd(a4.minCol+1," "),e2+="-- ",f6!==void 0&&(e2+=y6(t2.depth*2),f6!==""&&(e2+=`[${f6}] `));let p4=!1,[s3]=t2.children;switch(t2.mt){case f.POS_INT:e2+=`Unsigned: ${s3}`,typeof s3=="bigint"&&(e2+="n");break;case f.NEG_INT:e2+=`Negative: ${s3}`,typeof s3=="bigint"&&(e2+="n");break;case f.BYTE_STRING:e2+=`Bytes (Length: ${O4(t2.length)})`;break;case f.UTF8_STRING:e2+=`UTF8 (Length: ${O4(t2.length)})`,t2.length!==1/0&&(e2+=`: ${JSON.stringify(s3)}`);break;case f.ARRAY:e2+=`Array (Length: ${O4(t2.value,"item")})`;break;case f.MAP:e2+=`Map (Length: ${O4(t2.value,"pair")})`;break;case f.TAG:{e2+=`Tag #${t2.value}`;let o4=t2.children,[m3]=o4.contents.children,i=new o2(o4.tag,m3);u(i,n);let l3=i.comment(a4,t2.depth);l3&&(e2+=": ",e2+=l3),p4||=i.noChildren;break}case f.SIMPLE_FLOAT:s3===A.BREAK?e2+="BREAK":t2.ai>I.ONE?Object.is(s3,-0)?e2+="Float: -0":e2+=`Float: ${s3}`:(e2+="Simple: ",s3 instanceof t?e2+=s3.value:e2+=s3);break}if(!p4)if(t2.leaf){if(e2+=` +`,n.length>r+1){let o4=y6((t2.depth+1)*2),m3=f3(n);if(m3?.length){m3.sort((l3,c3)=>{return l3[0]-c3[0]||c3[1]-l3[1]});let i=0;for(let[l3,c3,g5]of m3)if(!(l3w2===0&&D===c3&&v3==="<<");$2>=0&&h3.splice($2,1)}e2+=M(d4),e2+=` >> +`,e2+=L2(d4,{initialDepth:t2.depth+1,minCol:a4.minCol,noPrefixHex:!0});continue}else g5==="'"&&(e2+=y6(a4.minCol+1),e2+="--",e2+=o4,e2+="'",e2+=H2.decode(n.subarray(l3,l3+c3)),e2+=`' +`);if(l3>r)for(let d4=l3;d4{let i=[...e2.entries()].map((a4)=>[a4[0],a4[1],v2(a4[0],n)]);if(n.rejectDuplicateKeys){let a4=new Set;for(let[d4,u3,g5]of i){let y7=A2(g5);if(a4.has(y7))throw Error(`Duplicate map key: 0x${y7}`);a4.add(y7)}}n.sortKeys&&i.sort(n.sortKeys),L(e2,e2.size,f.MAP,r,n);for(let[a4,d4,u3]of i)r.write(u3),g3(d4,r,n)});function w2(e2){return f6(e2.contents),new Date(e2.contents)}w2.comment=(e2)=>{f6(e2.contents);let r=new Date(e2.contents);return`(String ${e2.tag===T.DATE_FULL?"Full ":""}Date) ${r.toISOString()}`},o2.registerDecoder(T.DATE_STRING,w2),o2.registerDecoder(T.DATE_FULL,w2);function N3(e2){return I3(e2.contents),new Date(e2.contents*1000)}N3.comment=(e2)=>(I3(e2.contents),`(Epoch Date) ${new Date(e2.contents*1000).toISOString()}`),o2.registerDecoder(T.DATE_EPOCH,N3);var S3=86400000;function $2(e2){return I3(e2.contents),new Date(e2.contents*S3)}$2.comment=(e2)=>(I3(e2.contents),`(Epoch Date) ${new Date(e2.contents*S3).toISOString()}`),o2.registerDecoder(T.DATE_EPOCH_DAYS,$2),ue(Date,(e2,r,n)=>{switch(n.dateTag){case T.DATE_EPOCH:return[n.dateTag,e2.valueOf()/1000];case T.DATE_STRING:return[n.dateTag,e2.toISOString().replace(/\.000Z$/,"Z")];case T.DATE_EPOCH_DAYS:return[n.dateTag,Math.floor(e2.valueOf()/S3)];case T.DATE_FULL:return[n.dateTag,e2.toISOString().split("T")[0]];default:throw Error(`Unsupported date tag: ${n.dateTag}`)}});function m3(e2,r,n){if(E2(r.contents),n.rejectBigInts)throw Error(`Decoding unwanted big integer: ${r}(h'${A2(r.contents)}')`);if(n.requirePreferred&&r.contents[0]===0)throw Error(`Decoding overly-large bigint: ${r.tag}(h'${A2(r.contents)})`);let i=r.contents.reduce((d4,u3)=>d4<<8n|BigInt(u3),0n);e2&&(i=-1n-i);let a4=i>=Number.MIN_SAFE_INTEGER&&i<=Number.MAX_SAFE_INTEGER;if(n.requirePreferred&&a4)throw Error(`Decoding bigint that could have been int: ${i}n`);return n.collapseBigInts&&a4&&(i=Number(i)),n.boxed?d(i,r.contents):i}var L3=m3.bind(null,!1),x4=m3.bind(null,!0);L3.comment=(e2,r)=>`(Positive BigInt) ${m3(!1,e2,r)}n`,x4.comment=(e2,r)=>`(Negative BigInt) ${m3(!0,e2,r)}n`,o2.registerDecoder(T.POS_BIGINT,L3),o2.registerDecoder(T.NEG_BIGINT,x4);function R4(e2,r){return E2(e2.contents),e2}R4.comment=(e2,r,n)=>{E2(e2.contents);let i={...r,initialDepth:n+2,noPrefixHex:!0},a4=f2(e2),u3=2**((a4[0]&31)-24)+1,g5=a4[u3]&31,y7=A2(a4.subarray(u3,++u3));g5>=24&&(y7+=" ",y7+=A2(a4.subarray(u3,u3+2**(g5-24)))),i.minCol=Math.max(i.minCol,(n+1)*2+y7.length);let D=L2(e2.contents,i),T2=`Embedded CBOR +`;return T2+=`${"".padStart((n+1)*2," ")}${y7}`.padEnd(i.minCol+1," "),T2+=`-- Bytes (Length: ${e2.contents.length}) +`,T2+=D,T2},R4.noChildren=!0,o2.registerDecoder(T.CBOR,R4),o2.registerDecoder(T.URI,(e2)=>(f6(e2.contents),new URL(e2.contents)),"URI"),ue(URL,(e2)=>[T.URI,e2.toString()]),o2.registerDecoder(T.BASE64URL,(e2)=>(f6(e2.contents),x(e2.contents)),"Base64url-encoded"),o2.registerDecoder(T.BASE64,(e2)=>(f6(e2.contents),y(e2.contents)),"Base64-encoded"),o2.registerDecoder(35,(e2)=>(f6(e2.contents),new RegExp(e2.contents)),"RegExp"),o2.registerDecoder(21065,(e2)=>{f6(e2.contents);let r=`^(?:${e2.contents})$`;return new RegExp(r,"u")},"I-RegExp"),o2.registerDecoder(T.REGEXP,(e2)=>{if(_2(e2.contents),e2.contents.length<1||e2.contents.length>2)throw Error(`Invalid RegExp Array: ${e2.contents}`);return new RegExp(e2.contents[0],e2.contents[1])},"RegExp"),ue(RegExp,(e2)=>[T.REGEXP,[e2.source,e2.flags]]),o2.registerDecoder(64,(e2)=>(E2(e2.contents),e2.contents),"uint8 Typed Array");function c3(e2,r,n){E2(e2.contents);let i=e2.contents.length;if(i%r.BYTES_PER_ELEMENT!==0)throw Error(`Number of bytes must be divisible by ${r.BYTES_PER_ELEMENT}, got: ${i}`);i/=r.BYTES_PER_ELEMENT;let a4=new r(i),d4=new DataView(e2.contents.buffer,e2.contents.byteOffset,e2.contents.byteLength),u3=d4[`get${r.name.replace(/Array/,"")}`].bind(d4);for(let g5=0;g5c3(e2,Uint16Array,!1),"uint16, big endian, Typed Array"),o2.registerDecoder(66,(e2)=>c3(e2,Uint32Array,!1),"uint32, big endian, Typed Array"),o2.registerDecoder(67,(e2)=>c3(e2,BigUint64Array,!1),"uint64, big endian, Typed Array"),o2.registerDecoder(68,(e2)=>(E2(e2.contents),new Uint8ClampedArray(e2.contents)),"uint8 Typed Array, clamped arithmetic"),ue(Uint8ClampedArray,(e2)=>[68,new Uint8Array(e2.buffer,e2.byteOffset,e2.byteLength)]),o2.registerDecoder(69,(e2)=>c3(e2,Uint16Array,!0),"uint16, little endian, Typed Array"),ue(Uint16Array,(e2,r,n)=>l3(r,69,65,e2,n)),o2.registerDecoder(70,(e2)=>c3(e2,Uint32Array,!0),"uint32, little endian, Typed Array"),ue(Uint32Array,(e2,r,n)=>l3(r,70,66,e2,n)),o2.registerDecoder(71,(e2)=>c3(e2,BigUint64Array,!0),"uint64, little endian, Typed Array"),ue(BigUint64Array,(e2,r,n)=>l3(r,71,67,e2,n)),o2.registerDecoder(72,(e2)=>(E2(e2.contents),new Int8Array(e2.contents)),"sint8 Typed Array"),ue(Int8Array,(e2)=>[72,new Uint8Array(e2.buffer,e2.byteOffset,e2.byteLength)]),o2.registerDecoder(73,(e2)=>c3(e2,Int16Array,!1),"sint16, big endian, Typed Array"),o2.registerDecoder(74,(e2)=>c3(e2,Int32Array,!1),"sint32, big endian, Typed Array"),o2.registerDecoder(75,(e2)=>c3(e2,BigInt64Array,!1),"sint64, big endian, Typed Array"),o2.registerDecoder(77,(e2)=>c3(e2,Int16Array,!0),"sint16, little endian, Typed Array"),ue(Int16Array,(e2,r,n)=>l3(r,77,73,e2,n)),o2.registerDecoder(78,(e2)=>c3(e2,Int32Array,!0),"sint32, little endian, Typed Array"),ue(Int32Array,(e2,r,n)=>l3(r,78,74,e2,n)),o2.registerDecoder(79,(e2)=>c3(e2,BigInt64Array,!0),"sint64, little endian, Typed Array"),ue(BigInt64Array,(e2,r,n)=>l3(r,79,75,e2,n)),o2.registerDecoder(81,(e2)=>c3(e2,Float32Array,!1),"IEEE 754 binary32, big endian, Typed Array"),o2.registerDecoder(82,(e2)=>c3(e2,Float64Array,!1),"IEEE 754 binary64, big endian, Typed Array"),o2.registerDecoder(85,(e2)=>c3(e2,Float32Array,!0),"IEEE 754 binary32, little endian, Typed Array"),ue(Float32Array,(e2,r,n)=>l3(r,85,81,e2,n)),o2.registerDecoder(86,(e2)=>c3(e2,Float64Array,!0),"IEEE 754 binary64, big endian, Typed Array"),ue(Float64Array,(e2,r,n)=>l3(r,86,82,e2,n)),o2.registerDecoder(T.SET,(e2,r)=>{if(_2(e2.contents),r.sortKeys){let n=y4.decodeToEncodeOpts(r),i=null;for(let a4 of e2.contents){let d4=[a4,void 0,v2(a4,n)];if(i&&r.sortKeys(i,d4)>=0)throw Error(`Set items out of order in tag #${T.SET}`);i=d4}}return new Set(e2.contents)},"Set"),ue(Set,(e2,r,n)=>{let i=[...e2];if(n.sortKeys){let a4=i.map((d4)=>[d4,void 0,v2(d4,n)]);a4.sort(n.sortKeys),i=a4.map(([d4])=>d4)}return[T.SET,i]}),o2.registerDecoder(T.JSON,(e2)=>(f6(e2.contents),JSON.parse(e2.contents)),"JSON-encoded");function C(e2){return E2(e2.contents),new Wtf8Decoder().decode(e2.contents)}C.comment=(e2)=>{E2(e2.contents);let r=new Wtf8Decoder;return`(WTF8 string): ${JSON.stringify(r.decode(e2.contents))}`},o2.registerDecoder(T.WTF8,C),o2.registerDecoder(T.SELF_DESCRIBED,(e2)=>e2.contents,"Self-Described"),o2.registerDecoder(T.INVALID_16,()=>{throw Error(`Tag always invalid: ${T.INVALID_16}`)},"Invalid"),o2.registerDecoder(T.INVALID_32,()=>{throw Error(`Tag always invalid: ${T.INVALID_32}`)},"Invalid"),o2.registerDecoder(T.INVALID_64,()=>{throw Error(`Tag always invalid: ${T.INVALID_64}`)},"Invalid"),o2.registerDecoder(T.SYMBOL,(e2)=>{let r=e2.contents;if(Array.isArray(e2.contents)){if(e2.contents.length!==1)throw Error(`Expected Array of size 1: ${e2.contents}`);[r]=e2.contents}if(f6(r),!r.length)throw Error(`Expected non-empty string: ${e2.contents}`);return Symbol.for(r)},"Symbol");function h3(e2){throw Error(`Encoding ${e2.constructor.name} intentionally unimplmented. It is not concrete enough to interoperate. Convert to Uint8Array first.`)}ue(ArrayBuffer,h3),ue(DataView,h3),typeof SharedArrayBuffer<"u"&&ue(SharedArrayBuffer,h3);function p4(e2){return[NaN,e2.valueOf()]}ue(Boolean,p4),ue(Number,p4),ue(String,p4),ue(BigInt,p4);function c4(i){let e2={...y4.defaultDecodeOptions};if(i.dcbor?Object.assign(e2,y4.dcborDecodeOptions):i.cde&&Object.assign(e2,y4.cdeDecodeOptions),Object.assign(e2,i),Object.hasOwn(e2,"rejectLongNumbers"))throw TypeError("rejectLongNumbers has changed to requirePreferred");return e2.boxed&&(e2.saveOriginal=!0),e2}class d4{parent=void 0;ret=void 0;step(e2,n,t2){if(this.ret=y4.create(e2,this.parent,n,t2),e2[2]===A.BREAK)if(this.parent?.isStreaming)this.parent.left=0;else throw Error("Unexpected BREAK");else this.parent&&this.parent.push(this.ret,t2,e2[3]);for(this.ret instanceof y4&&(this.parent=this.ret);this.parent?.done;){this.ret=this.parent.convert(t2);let r=this.parent.parent;r?.replaceLast(this.ret,this.parent,t2),this.parent=r}}}function l4(i,e2={}){let n=c4(e2),t2=new y3(i,n),r=new d4;for(let o4 of t2)r.step(o4,n,t2);return r.ret}class O5{#t;#e;constructor(e2,n={}){let t2=new y3(e2,c4(n));this.#t=t2.seq()}peek(){return this.#e||(this.#e=this.#n()),this.#e}read(){let e2=this.#e??this.#n();return this.#e=void 0,e2}*[Symbol.iterator](){for(;;){let e2=this.read();if(!e2)return;yield e2}}#n(){let{value:e2,done:n}=this.#t.next();if(!n)return e2}}globalThis.CBOR={decode(buffer,options){return l4(new Uint8Array(buffer),options)}}; diff --git a/vendor/cbor2-decoder.json b/vendor/cbor2-decoder.json new file mode 100644 index 0000000..0e4071e --- /dev/null +++ b/vendor/cbor2-decoder.json @@ -0,0 +1,11 @@ +{ + "source": "cbor2@2.3.0", + "license": "MIT", + "homepage": "https://github.com/hildjj/cbor2", + "global": "CBOR.decode(ArrayBuffer)", + "bytes": 46085, + "sha256": "1a1268a12cce7040ec879c5e3bf07f9ab1f7846690c37e959c473bf83f7438c5", + "builder": "bun 1.3.14 build --minify-syntax --minify-whitespace --target=browser", + "inscription_id": null, + "note": "Not inscribed. The library loads its decoder from the fixed /content/ path with no configuration hook, so to try this candidate serve it at that path, as scripts/decoder-smoke.mjs does." +}