@artblocks/abx-token-api 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/dist/abxjs.d.ts +13 -0
  3. package/dist/abxjs.d.ts.map +1 -0
  4. package/dist/abxjs.js +49 -0
  5. package/dist/abxjs.js.map +1 -0
  6. package/dist/art.d.ts +26 -0
  7. package/dist/art.d.ts.map +1 -0
  8. package/dist/art.js +85 -0
  9. package/dist/art.js.map +1 -0
  10. package/dist/code.d.ts +73 -0
  11. package/dist/code.d.ts.map +1 -0
  12. package/dist/code.js +216 -0
  13. package/dist/code.js.map +1 -0
  14. package/dist/dashboard.d.ts +12 -0
  15. package/dist/dashboard.d.ts.map +1 -0
  16. package/dist/dashboard.js +231 -0
  17. package/dist/dashboard.js.map +1 -0
  18. package/dist/deps.d.ts +146 -0
  19. package/dist/deps.d.ts.map +1 -0
  20. package/dist/deps.js +297 -0
  21. package/dist/deps.js.map +1 -0
  22. package/dist/index.d.ts +15 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +15 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/inline.d.ts +19 -0
  27. package/dist/inline.d.ts.map +1 -0
  28. package/dist/inline.js +23 -0
  29. package/dist/inline.js.map +1 -0
  30. package/dist/metadata.d.ts +89 -0
  31. package/dist/metadata.d.ts.map +1 -0
  32. package/dist/metadata.js +673 -0
  33. package/dist/metadata.js.map +1 -0
  34. package/dist/resolve.d.ts +74 -0
  35. package/dist/resolve.d.ts.map +1 -0
  36. package/dist/resolve.js +107 -0
  37. package/dist/resolve.js.map +1 -0
  38. package/dist/server.d.ts +91 -0
  39. package/dist/server.d.ts.map +1 -0
  40. package/dist/server.js +940 -0
  41. package/dist/server.js.map +1 -0
  42. package/dist/watcher.d.ts +56 -0
  43. package/dist/watcher.d.ts.map +1 -0
  44. package/dist/watcher.js +179 -0
  45. package/dist/watcher.js.map +1 -0
  46. package/package.json +50 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Art Blocks, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `abx.js` — the runtime companion (the hl-gen.js analog), served at `/abx.js` and
3
+ * inlined into template-mode documents. Convention, not protocol: a directory build
4
+ * includes it; the generator injects the same surface.
5
+ *
6
+ * tokenData resolution order (the durability chain): the injected `window.abxTokenData`
7
+ * global (template mode) → the `?abx=` query param (base64url canonical JSON — the
8
+ * live-view route) → the `?chainId&contract&tokenId` coordinate floor (a build opened
9
+ * bare from a gateway still knows which token it is; full param reads from RPC are the
10
+ * render-node's job, not this shim's).
11
+ */
12
+ export declare const ABX_JS = "(function () {\n var abx = (window.abx = window.abx || {});\n function fromQuery() {\n try {\n var q = new URLSearchParams(location.search);\n var packed = q.get('abx');\n if (packed) {\n var b64 = packed.replace(/-/g, '+').replace(/_/g, '/');\n return JSON.parse(new TextDecoder().decode(Uint8Array.from(atob(b64), function (c) { return c.charCodeAt(0); })));\n }\n // coordinate floor: enough for a deterministic piece opened bare from a gateway\n if (q.get('contract') && q.get('tokenId')) {\n return {\n chainId: Number(q.get('chainId') || 1),\n contractAddress: String(q.get('contract')).toLowerCase(),\n tokenId: String(q.get('tokenId')),\n };\n }\n } catch (e) {}\n return null;\n }\n abx.tokenData = window.abxTokenData || fromQuery();\n abx.__traits = null;\n abx.__done = false;\n /** The script reports its computed traits (script-defined features; captured at render). */\n abx.traits = function (t) {\n abx.__traits = t;\n try { document.dispatchEvent(new CustomEvent('abx:traits', {detail: t})); } catch (e) {}\n return t;\n };\n /** Output-complete \u2014 the capture point for the render effect. Optional (timeout fallback). */\n abx.done = function () {\n abx.__done = true;\n try { document.dispatchEvent(new CustomEvent('abx:done')); } catch (e) {}\n };\n})();\n";
13
+ //# sourceMappingURL=abxjs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abxjs.d.ts","sourceRoot":"","sources":["../src/abxjs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,o4CAoClB,CAAC"}
package/dist/abxjs.js ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * `abx.js` — the runtime companion (the hl-gen.js analog), served at `/abx.js` and
3
+ * inlined into template-mode documents. Convention, not protocol: a directory build
4
+ * includes it; the generator injects the same surface.
5
+ *
6
+ * tokenData resolution order (the durability chain): the injected `window.abxTokenData`
7
+ * global (template mode) → the `?abx=` query param (base64url canonical JSON — the
8
+ * live-view route) → the `?chainId&contract&tokenId` coordinate floor (a build opened
9
+ * bare from a gateway still knows which token it is; full param reads from RPC are the
10
+ * render-node's job, not this shim's).
11
+ */
12
+ export const ABX_JS = `(function () {
13
+ var abx = (window.abx = window.abx || {});
14
+ function fromQuery() {
15
+ try {
16
+ var q = new URLSearchParams(location.search);
17
+ var packed = q.get('abx');
18
+ if (packed) {
19
+ var b64 = packed.replace(/-/g, '+').replace(/_/g, '/');
20
+ return JSON.parse(new TextDecoder().decode(Uint8Array.from(atob(b64), function (c) { return c.charCodeAt(0); })));
21
+ }
22
+ // coordinate floor: enough for a deterministic piece opened bare from a gateway
23
+ if (q.get('contract') && q.get('tokenId')) {
24
+ return {
25
+ chainId: Number(q.get('chainId') || 1),
26
+ contractAddress: String(q.get('contract')).toLowerCase(),
27
+ tokenId: String(q.get('tokenId')),
28
+ };
29
+ }
30
+ } catch (e) {}
31
+ return null;
32
+ }
33
+ abx.tokenData = window.abxTokenData || fromQuery();
34
+ abx.__traits = null;
35
+ abx.__done = false;
36
+ /** The script reports its computed traits (script-defined features; captured at render). */
37
+ abx.traits = function (t) {
38
+ abx.__traits = t;
39
+ try { document.dispatchEvent(new CustomEvent('abx:traits', {detail: t})); } catch (e) {}
40
+ return t;
41
+ };
42
+ /** Output-complete — the capture point for the render effect. Optional (timeout fallback). */
43
+ abx.done = function () {
44
+ abx.__done = true;
45
+ try { document.dispatchEvent(new CustomEvent('abx:done')); } catch (e) {}
46
+ };
47
+ })();
48
+ `;
49
+ //# sourceMappingURL=abxjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abxjs.js","sourceRoot":"","sources":["../src/abxjs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCrB,CAAC"}
package/dist/art.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { type Hex } from 'viem';
2
+ /**
3
+ * The demo's reference content. A 1/1 needs *bytes* — here they're generated
4
+ * deterministically from the contract address (the seed), so "byte custody" is
5
+ * satisfied by reproducible regeneration plus an on-chain hash commitment: the
6
+ * server can always re-derive the exact image, and anyone can verify it matches
7
+ * what the contract committed. A real custody node stores arbitrary bytes; the
8
+ * verification + serving path is identical.
9
+ *
10
+ * (Generative-from-seed is also a fitting nod to where this protocol comes from.)
11
+ */
12
+ export declare const IMAGE_MEDIA_TYPE = "image/svg+xml";
13
+ /** Deterministic generative SVG for a contract address. Pure: address → bytes. */
14
+ export declare function generateArt(address: string): string;
15
+ /** keccak256 of the generated art's UTF-8 bytes — the value committed on-chain (image `keccak256` field). */
16
+ export declare function artContentHash(address: string): Hex;
17
+ /**
18
+ * The required-field *fallback* image — a simple, deterministic placeholder used when a
19
+ * token has no resolvable `image` (unset, or a representation the surface can't load).
20
+ * Deliberately trivial so it is **byte-identical** to the on-chain renderer's
21
+ * `_fallbackImage` (`AbxMetadataRenderer`): background = the address's first 3 bytes,
22
+ * label = `#tokenId`. Distinct from {generateArt} (the demo's *chosen* content) — this is
23
+ * the "nothing was set" placeholder both the on-chain and off-chain resolvers agree on.
24
+ */
25
+ export declare function fallbackImageSvg(address: string, tokenId: string | number | bigint): string;
26
+ //# sourceMappingURL=art.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"art.d.ts","sourceRoot":"","sources":["../src/art.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,GAAG,EAAC,MAAM,MAAM,CAAC;AAExD;;;;;;;;;GASG;AAEH,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAahD,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA6CnD;AAED,6GAA6G;AAC7G,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAEnD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAQ3F"}
package/dist/art.js ADDED
@@ -0,0 +1,85 @@
1
+ import { keccak256, stringToBytes } from 'viem';
2
+ /**
3
+ * The demo's reference content. A 1/1 needs *bytes* — here they're generated
4
+ * deterministically from the contract address (the seed), so "byte custody" is
5
+ * satisfied by reproducible regeneration plus an on-chain hash commitment: the
6
+ * server can always re-derive the exact image, and anyone can verify it matches
7
+ * what the contract committed. A real custody node stores arbitrary bytes; the
8
+ * verification + serving path is identical.
9
+ *
10
+ * (Generative-from-seed is also a fitting nod to where this protocol comes from.)
11
+ */
12
+ export const IMAGE_MEDIA_TYPE = 'image/svg+xml';
13
+ function mulberry32(seed) {
14
+ let a = seed >>> 0;
15
+ return () => {
16
+ a |= 0;
17
+ a = (a + 0x6d2b79f5) | 0;
18
+ let t = Math.imul(a ^ (a >>> 15), 1 | a);
19
+ t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
20
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
21
+ };
22
+ }
23
+ /** Deterministic generative SVG for a contract address. Pure: address → bytes. */
24
+ export function generateArt(address) {
25
+ const clean = address.toLowerCase().replace(/^0x/, '').padEnd(40, '0');
26
+ const seed = parseInt(clean.slice(0, 8), 16) ^ parseInt(clean.slice(8, 16), 16);
27
+ const rnd = mulberry32(seed);
28
+ const hue = Math.floor(rnd() * 360);
29
+ const bg = `hsl(${hue}, 60%, 8%)`;
30
+ const size = 500;
31
+ const cells = 5 + Math.floor(rnd() * 4); // 5–8
32
+ const step = size / cells;
33
+ const shapes = [];
34
+ for (let y = 0; y < cells; y++) {
35
+ for (let x = 0; x < cells; x++) {
36
+ if (rnd() < 0.18)
37
+ continue; // negative space
38
+ const h = (hue + Math.floor(rnd() * 80) - 40 + 360) % 360;
39
+ const light = 45 + Math.floor(rnd() * 40);
40
+ const fill = `hsl(${h}, ${55 + Math.floor(rnd() * 35)}%, ${light}%)`;
41
+ const cx = x * step + step / 2;
42
+ const cy = y * step + step / 2;
43
+ const r = (step / 2) * (0.35 + rnd() * 0.6);
44
+ const kind = rnd();
45
+ if (kind < 0.45) {
46
+ shapes.push(`<circle cx="${cx.toFixed(1)}" cy="${cy.toFixed(1)}" r="${r.toFixed(1)}" fill="${fill}"/>`);
47
+ }
48
+ else if (kind < 0.8) {
49
+ const s = (r * 1.6).toFixed(1);
50
+ shapes.push(`<rect x="${(cx - r).toFixed(1)}" y="${(cy - r).toFixed(1)}" width="${s}" height="${s}" rx="${(r * 0.2).toFixed(1)}" fill="${fill}" transform="rotate(${Math.floor(rnd() * 90)} ${cx.toFixed(1)} ${cy.toFixed(1)})"/>`);
51
+ }
52
+ else {
53
+ const x2 = (cx + (rnd() - 0.5) * step).toFixed(1);
54
+ const y2 = (cy + (rnd() - 0.5) * step).toFixed(1);
55
+ shapes.push(`<line x1="${cx.toFixed(1)}" y1="${cy.toFixed(1)}" x2="${x2}" y2="${y2}" stroke="${fill}" stroke-width="${(r * 0.4).toFixed(1)}" stroke-linecap="round"/>`);
56
+ }
57
+ }
58
+ }
59
+ return [
60
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">`,
61
+ `<rect width="${size}" height="${size}" fill="${bg}"/>`,
62
+ shapes.join(''),
63
+ `</svg>`,
64
+ ].join('');
65
+ }
66
+ /** keccak256 of the generated art's UTF-8 bytes — the value committed on-chain (image `keccak256` field). */
67
+ export function artContentHash(address) {
68
+ return keccak256(stringToBytes(generateArt(address)));
69
+ }
70
+ /**
71
+ * The required-field *fallback* image — a simple, deterministic placeholder used when a
72
+ * token has no resolvable `image` (unset, or a representation the surface can't load).
73
+ * Deliberately trivial so it is **byte-identical** to the on-chain renderer's
74
+ * `_fallbackImage` (`AbxMetadataRenderer`): background = the address's first 3 bytes,
75
+ * label = `#tokenId`. Distinct from {generateArt} (the demo's *chosen* content) — this is
76
+ * the "nothing was set" placeholder both the on-chain and off-chain resolvers agree on.
77
+ */
78
+ export function fallbackImageSvg(address, tokenId) {
79
+ const color = address.toLowerCase().replace(/^0x/, '').slice(0, 6);
80
+ return (`<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 500 500">` +
81
+ `<rect width="500" height="500" fill="#${color}"/>` +
82
+ `<text x="250" y="264" font-family="monospace" font-size="42" fill="#ffffff" text-anchor="middle">#${tokenId}</text>` +
83
+ `</svg>`);
84
+ }
85
+ //# sourceMappingURL=art.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"art.js","sourceRoot":"","sources":["../src/art.ts"],"names":[],"mappings":"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"}
package/dist/code.d.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { isCodeProject, type Hex, type ProjectState, type PublicClient, type TokenState } from '@artblocks/abx-sdk';
2
+ import type { StorageBackend } from '@artblocks/abx-storage';
3
+ /**
4
+ * The live view + the render-effect consumption seam.
5
+ *
6
+ * The live view is the document a collector (and any render node) loads: directory mode
7
+ * serves the build's entry document from the resolver with `window.abxTokenData` injected
8
+ * (+ a `<base>` at the code root so relative assets still ride the gateway) — abx.js reads
9
+ * the injected global FIRST, so no tokenData ever rides a URL on this path; the `?abx=`
10
+ * 302 redirect survives only as the fallback when the entry document can't be fetched.
11
+ * Template mode assembles the generator document from chain (dependencies in order →
12
+ * `window.abxTokenData` → the script chunks). The seam: `image` resolution consults byte
13
+ * custody at the canonical effect address for the CURRENT `inputsHash` — a param change
14
+ * re-addresses output, so a stale render is never served (a miss falls back to the
15
+ * placeholder until re-rendered).
16
+ */
17
+ export declare function liveViewUrl(baseUrl: string, chainId: number, address: string, tokenId: string): string;
18
+ /** Whether the derived live view should fill `animation_url` (code present, not suppressed). */
19
+ export declare function liveViewEnabled(state: ProjectState): boolean;
20
+ export { isCodeProject };
21
+ /**
22
+ * A render-artifact locator (`ipfs://<cid>`, `ar://<txid>`, or an absolute `https://…`) → a fetchable
23
+ * URL, applying the IPFS/Arweave gateway at SERVE time (overridable via env). Mirrors `codeLocatorUrl`'s
24
+ * gateway handling; an already-absolute URL is returned verbatim (never re-prefixed).
25
+ */
26
+ export declare function resolveLocatorUrl(locator: string): string;
27
+ /**
28
+ * The token's CURRENT settled inputsHash — the effect-run identity every artifact address is
29
+ * keyed by. SETTLED tokenData (augment: false) — must mirror the producer's addressing
30
+ * (EffectRunner.runToken): artifacts are keyed on event-derived state only, never live augment
31
+ * data (live data animates the live view; a capture snapshots it without re-addressing every
32
+ * block). Computed once per metadata build and shared across the image seam, the traits stitch,
33
+ * and the `artifacts` manifest. Uses the default environmentId ('web:any') — a runner with a
34
+ * custom ABX_ENVIRONMENT_ID must match the resolver's (pre-existing constraint).
35
+ */
36
+ export declare function currentSettledInputsHash(client: PublicClient, state: ProjectState, token: TokenState): Promise<Hex>;
37
+ /** The current artifact address for one (effect, output) of a token — and whether a conforming
38
+ * producer has stored it in THIS node's byte custody. A locator-bridge artifact lives in the
39
+ * effect_artifacts registry instead (checked by the caller), so `storage` may be absent here. */
40
+ export declare function currentRenderArtifact(client: PublicClient, state: ProjectState, token: TokenState, storage?: StorageBackend, outputKey?: string, opts?: {
41
+ hash?: Hex;
42
+ effectKey?: string;
43
+ }): Promise<{
44
+ key: Hex;
45
+ found: boolean;
46
+ hash: Hex;
47
+ }>;
48
+ export type LiveView = {
49
+ kind: 'redirect';
50
+ location: string;
51
+ } | {
52
+ kind: 'html';
53
+ html: string;
54
+ } | null;
55
+ /** Resolve the live view for a token: a served document (directory inline-injection or
56
+ * template assembly) or the directory 302 fallback. The live view carries FULL tokenData
57
+ * (settled + the augment hook's live entries) — the one place live data belongs. The hook's
58
+ * presence on-chain IS the live-data opt-in: no hook, no live read, zero per-view cost.
59
+ * ABX_DISABLE_AUGMENT=1 is a resolver-operator kill-switch (cost/abuse control on a public
60
+ * node) that degrades gracefully to settled params. */
61
+ export declare function resolveLiveView(client: PublicClient, state: ProjectState, token: TokenState, fetchFn?: typeof fetch): Promise<LiveView>;
62
+ /** Reset the in-process entry-document cache — for tests. */
63
+ export declare function resetEntryDocumentCache(): void;
64
+ /**
65
+ * Inject `window.abxTokenData` (and, when the document doesn't already carry one, a
66
+ * `<base href="{code root}/">` so relative asset paths keep riding the gateway) at the
67
+ * very top of `<head>` — before any build script can execute; abx.js resolves the global
68
+ * first. String-level and deliberately robust rather than a full HTML parse: no `<head>`
69
+ * → inject right after `<html …>`; neither → prepend. First `<base>` wins in HTML, so an
70
+ * existing one is never doubled.
71
+ */
72
+ export declare function injectTokenDataIntoHtml(html: string, tokenDataJson: string, codeRoot: string): string;
73
+ //# sourceMappingURL=code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../src/code.ts"],"names":[],"mappings":"AACA,OAAO,EAML,aAAa,EAEb,KAAK,GAAG,EACR,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,wBAAwB,CAAC;AAK3D;;;;;;;;;;;;;GAaG;AAEH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtG;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAE5D;AAED,OAAO,EAAC,aAAa,EAAC,CAAC;AAEvB;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAWzD;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,GAAG,CAAC,CAGd;AAED;;kGAEkG;AAClG,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE,cAAc,EACxB,SAAS,GAAE,MAAgB,EAC3B,IAAI,GAAE;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAM,GAC1C,OAAO,CAAC;IAAC,GAAG,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAC,CAAC,CAIhD;AAED,MAAM,MAAM,QAAQ,GAAG;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,GAAG;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAAG,IAAI,CAAC;AAElG;;;;;wDAKwD;AACxD,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAmCnB;AAYD,6DAA6D;AAC7D,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAkBD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAcrG"}
package/dist/code.js ADDED
@@ -0,0 +1,216 @@
1
+ import { hexToString } from 'viem';
2
+ import { buildTokenData, codeField, contentDigestOf, contractParamString, inputsHash, isCodeProject, renderArtifactKey, } from '@artblocks/abx-sdk';
3
+ import { seriesCodeAbi } from '@artblocks/abx-sdk';
4
+ import { ABX_JS } from './abxjs.js';
5
+ import { checkUrlBudget, dependencyScriptTags, recordDirectoryServe } from './deps.js';
6
+ import { escapeInlineJson, escapeInlineScript } from './inline.js';
7
+ /**
8
+ * The live view + the render-effect consumption seam.
9
+ *
10
+ * The live view is the document a collector (and any render node) loads: directory mode
11
+ * serves the build's entry document from the resolver with `window.abxTokenData` injected
12
+ * (+ a `<base>` at the code root so relative assets still ride the gateway) — abx.js reads
13
+ * the injected global FIRST, so no tokenData ever rides a URL on this path; the `?abx=`
14
+ * 302 redirect survives only as the fallback when the entry document can't be fetched.
15
+ * Template mode assembles the generator document from chain (dependencies in order →
16
+ * `window.abxTokenData` → the script chunks). The seam: `image` resolution consults byte
17
+ * custody at the canonical effect address for the CURRENT `inputsHash` — a param change
18
+ * re-addresses output, so a stale render is never served (a miss falls back to the
19
+ * placeholder until re-rendered).
20
+ */
21
+ export function liveViewUrl(baseUrl, chainId, address, tokenId) {
22
+ return `${baseUrl}/a/${chainId}/${address}/${tokenId}`;
23
+ }
24
+ /** Whether the derived live view should fill `animation_url` (code present, not suppressed). */
25
+ export function liveViewEnabled(state) {
26
+ return isCodeProject(state) && contractParamString(state, 'display.animation') !== 'none';
27
+ }
28
+ export { isCodeProject };
29
+ /**
30
+ * A render-artifact locator (`ipfs://<cid>`, `ar://<txid>`, or an absolute `https://…`) → a fetchable
31
+ * URL, applying the IPFS/Arweave gateway at SERVE time (overridable via env). Mirrors `codeLocatorUrl`'s
32
+ * gateway handling; an already-absolute URL is returned verbatim (never re-prefixed).
33
+ */
34
+ export function resolveLocatorUrl(locator) {
35
+ if (/^https?:\/\//i.test(locator))
36
+ return locator;
37
+ if (locator.startsWith('ipfs://')) {
38
+ const gw = process.env.ABX_IPFS_GATEWAY ?? 'https://ipfs.io';
39
+ return `${gw.replace(/\/$/, '')}/ipfs/${locator.slice('ipfs://'.length)}`;
40
+ }
41
+ if (locator.startsWith('ar://')) {
42
+ const gw = process.env.ABX_ARWEAVE_GATEWAY ?? 'https://arweave.net';
43
+ return `${gw.replace(/\/$/, '')}/${locator.slice('ar://'.length)}`;
44
+ }
45
+ return locator;
46
+ }
47
+ /**
48
+ * The token's CURRENT settled inputsHash — the effect-run identity every artifact address is
49
+ * keyed by. SETTLED tokenData (augment: false) — must mirror the producer's addressing
50
+ * (EffectRunner.runToken): artifacts are keyed on event-derived state only, never live augment
51
+ * data (live data animates the live view; a capture snapshots it without re-addressing every
52
+ * block). Computed once per metadata build and shared across the image seam, the traits stitch,
53
+ * and the `artifacts` manifest. Uses the default environmentId ('web:any') — a runner with a
54
+ * custom ABX_ENVIRONMENT_ID must match the resolver's (pre-existing constraint).
55
+ */
56
+ export async function currentSettledInputsHash(client, state, token) {
57
+ const { json } = await buildTokenData(client, state, token, { augment: false });
58
+ return inputsHash(contentDigestOf(state), json);
59
+ }
60
+ /** The current artifact address for one (effect, output) of a token — and whether a conforming
61
+ * producer has stored it in THIS node's byte custody. A locator-bridge artifact lives in the
62
+ * effect_artifacts registry instead (checked by the caller), so `storage` may be absent here. */
63
+ export async function currentRenderArtifact(client, state, token, storage, outputKey = 'image', opts = {}) {
64
+ const hash = opts.hash ?? (await currentSettledInputsHash(client, state, token));
65
+ const key = renderArtifactKey(state.chainId, state.address, token.tokenId, hash, outputKey, opts.effectKey ?? 'render');
66
+ return { key, found: storage ? await storage.has(key) : false, hash };
67
+ }
68
+ /** Resolve the live view for a token: a served document (directory inline-injection or
69
+ * template assembly) or the directory 302 fallback. The live view carries FULL tokenData
70
+ * (settled + the augment hook's live entries) — the one place live data belongs. The hook's
71
+ * presence on-chain IS the live-data opt-in: no hook, no live read, zero per-view cost.
72
+ * ABX_DISABLE_AUGMENT=1 is a resolver-operator kill-switch (cost/abuse control on a public
73
+ * node) that degrades gracefully to settled params. */
74
+ export async function resolveLiveView(client, state, token, fetchFn = fetch) {
75
+ const { json } = await buildTokenData(client, state, token, { augment: process.env.ABX_DISABLE_AUGMENT !== '1' });
76
+ const code = codeField(state);
77
+ if (code) {
78
+ const base = codeLocatorUrl(code.representation, code.value);
79
+ if (!base)
80
+ return null;
81
+ const entry = base.endsWith('.html') ? base : `${base.replace(/\/$/, '')}/index.html`;
82
+ // PRIMARY: serve the entry document from the resolver with `window.abxTokenData`
83
+ // injected at the very top of <head> (abx.js reads the global before the ?abx= query
84
+ // param) + a <base> at the code root so the build's relative assets still ride the
85
+ // gateway. tokenData never touches a URL on this path — no query-string budget.
86
+ try {
87
+ const doc = await fetchEntryDocument(code.representation, entry, fetchFn);
88
+ recordDirectoryServe(state.address, 'inline-injection');
89
+ const codeRoot = entry.slice(0, entry.lastIndexOf('/') + 1);
90
+ return { kind: 'html', html: injectTokenDataIntoHtml(doc, json, codeRoot) };
91
+ }
92
+ catch (err) {
93
+ // FALLBACK: the ?abx= redirect the old path survived on — never a hard failure.
94
+ console.warn(`[code] entry-document fetch failed for ${state.address} (${entry}): ${err.message} — falling back to the ?abx= redirect`);
95
+ recordDirectoryServe(state.address, 'redirect-fallback');
96
+ }
97
+ const packed = Buffer.from(json, 'utf8').toString('base64url');
98
+ const location = `${entry}?abx=${packed}`;
99
+ // The spec's query-string budget applies to URL-carried tokenData only (this fallback):
100
+ // gateway request lines cap near 8KB. The FULL URL is always served (params are never
101
+ // dropped) — a breach warns loudly, once per project.
102
+ checkUrlBudget(state.address, token.tokenId, location);
103
+ return { kind: 'redirect', location };
104
+ }
105
+ if ((state.script?.chunkCount ?? 0) > 0) {
106
+ return { kind: 'html', html: await assembleGeneratorDocument(client, state, json) };
107
+ }
108
+ return null;
109
+ }
110
+ // ── directory-mode inline injection (the primary serving path) ────────────────────
111
+ // Fetched entry documents cache in-process keyed by the resolved entry URL. A
112
+ // content-addressed root (ipfs/arweave) can never change under its locator — cache
113
+ // indefinitely (bounded by entry count); a mutable `url` root gets a short TTL.
114
+ const ENTRY_DOC_CACHE_MAX = 32;
115
+ const ENTRY_DOC_URL_TTL_MS = 5 * 60 * 1000;
116
+ const ENTRY_DOC_FETCH_TIMEOUT_MS = 10_000;
117
+ const entryDocCache = new Map();
118
+ /** Reset the in-process entry-document cache — for tests. */
119
+ export function resetEntryDocumentCache() {
120
+ entryDocCache.clear();
121
+ }
122
+ /** Fetch (and cache) a directory build's entry document text. Throws on any failure —
123
+ * the caller falls back to the ?abx= redirect. */
124
+ async function fetchEntryDocument(representation, url, fetchFn) {
125
+ const hit = entryDocCache.get(url);
126
+ if (hit && hit.expiresAt > Date.now())
127
+ return hit.html;
128
+ const res = await fetchFn(url, { signal: AbortSignal.timeout(ENTRY_DOC_FETCH_TIMEOUT_MS) });
129
+ if (!res.ok)
130
+ throw new Error(`HTTP ${res.status}`);
131
+ const html = await res.text();
132
+ const ttl = representation === 'ipfs' || representation === 'arweave' ? Number.POSITIVE_INFINITY : ENTRY_DOC_URL_TTL_MS;
133
+ if (entryDocCache.size >= ENTRY_DOC_CACHE_MAX) {
134
+ entryDocCache.delete(entryDocCache.keys().next().value); // oldest insert
135
+ }
136
+ entryDocCache.set(url, { html, expiresAt: Date.now() + ttl });
137
+ return html;
138
+ }
139
+ /**
140
+ * Inject `window.abxTokenData` (and, when the document doesn't already carry one, a
141
+ * `<base href="{code root}/">` so relative asset paths keep riding the gateway) at the
142
+ * very top of `<head>` — before any build script can execute; abx.js resolves the global
143
+ * first. String-level and deliberately robust rather than a full HTML parse: no `<head>`
144
+ * → inject right after `<html …>`; neither → prepend. First `<base>` wins in HTML, so an
145
+ * existing one is never doubled.
146
+ */
147
+ export function injectTokenDataIntoHtml(html, tokenDataJson, codeRoot) {
148
+ const baseTag = /<base[\s/>]/i.test(html) ? '' : `<base href="${codeRoot}">`;
149
+ const injection = `${baseTag}<script>window.abxTokenData=${escapeInlineJson(tokenDataJson)};</script>`;
150
+ const head = /<head(\s[^>]*)?>/i.exec(html);
151
+ if (head) {
152
+ const at = head.index + head[0].length;
153
+ return html.slice(0, at) + injection + html.slice(at);
154
+ }
155
+ const htmlTag = /<html(\s[^>]*)?>/i.exec(html);
156
+ if (htmlTag) {
157
+ const at = htmlTag.index + htmlTag[0].length;
158
+ return html.slice(0, at) + injection + html.slice(at);
159
+ }
160
+ return injection + html;
161
+ }
162
+ /** A `code` field locator → a fetchable https URL (gateways overridable via env). */
163
+ function codeLocatorUrl(representation, value) {
164
+ const text = hexToString(value);
165
+ // A stored locator can already be an absolute URL (e.g. a gateway URL saved verbatim by an older
166
+ // deploy) — serve it directly rather than prefixing a gateway again (which double-prefixes to a
167
+ // broken `https://arweave.net/https://arweave.net/…`). Applies to any representation.
168
+ if (/^https?:\/\//i.test(text))
169
+ return text;
170
+ if (representation === 'url')
171
+ return text;
172
+ if (representation === 'ipfs') {
173
+ const gw = process.env.ABX_IPFS_GATEWAY ?? 'https://ipfs.io';
174
+ return `${gw.replace(/\/$/, '')}/ipfs/${text.replace(/^ipfs:\/\//, '')}`;
175
+ }
176
+ if (representation === 'arweave') {
177
+ const gw = process.env.ABX_ARWEAVE_GATEWAY ?? 'https://arweave.net';
178
+ return `${gw.replace(/\/$/, '')}/${text.replace(/^ar:\/\//, '')}`;
179
+ }
180
+ return null; // `code` is locators-only by the registry; anything else is unserveable
181
+ }
182
+ /**
183
+ * Template mode: the reference generator convention — dependencies in order (index 0 =
184
+ * the runtime), `abx.js` + the injected tokenData, then the script chunks from chain.
185
+ */
186
+ async function assembleGeneratorDocument(client, state, tokenDataJson) {
187
+ const n = state.script?.chunkCount ?? 0;
188
+ const reads = (await client.multicall({
189
+ contracts: Array.from({ length: n }, (_, i) => ({
190
+ address: state.address,
191
+ abi: seriesCodeAbi,
192
+ functionName: 'scriptChunk',
193
+ args: [BigInt(i)],
194
+ })),
195
+ allowFailure: true,
196
+ }));
197
+ const script = reads
198
+ .map((r) => (r.status === 'success' ? hexToString(r.result) : ''))
199
+ .join('\n');
200
+ // Dependencies resolve per the registry order (specs/protocol/dependency-registry.md
201
+ // "Consumers"): the collection's registry pointer (on-chain bytes → preferredCDN) → the
202
+ // built-in CDN map. Resolution never throws — the document always assembles.
203
+ const depTags = await dependencyScriptTags(client, state);
204
+ return [
205
+ '<!doctype html>',
206
+ '<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">',
207
+ '<style>html,body{margin:0;padding:0;overflow:hidden}canvas{display:block}</style>',
208
+ `<script>window.abxTokenData=${escapeInlineJson(tokenDataJson)};</script>`,
209
+ `<script>${ABX_JS}</script>`,
210
+ ...depTags,
211
+ '</head><body>',
212
+ `<script>\n${escapeInlineScript(script)}\n</script>`,
213
+ '</body></html>',
214
+ ].join('\n');
215
+ }
216
+ //# sourceMappingURL=code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.js","sourceRoot":"","sources":["../src/code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { ProjectState } from '@artblocks/abx-sdk';
2
+ /**
3
+ * The per-contract dashboard, served at `/d/<chainId>/<address>`. **Read-only by design**: it
4
+ * renders reconstructed state but takes NO actions. Re-indexing and verification are mutating /
5
+ * load-bearing operations gated behind the admin token (from the CLI: `abx index <addr> --remote`),
6
+ * never public buttons — a public host should never let a stranger trigger a full chain replay.
7
+ */
8
+ export declare function renderDashboard(project: ProjectState, baseUrl: string, chainId: number): string;
9
+ /** The node index at `/`, served read-only: which contracts this resolver serves, each linking to
10
+ * its per-contract dashboard. No actions — operate via the CLI (admin-token gated). */
11
+ export declare function renderIndex(projects: ProjectState[], baseUrl: string, chainId: number): string;
12
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAwBrD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ/F;AAED;wFACwF;AACxF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAe9F"}