@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.
- package/LICENSE +21 -0
- package/dist/abxjs.d.ts +13 -0
- package/dist/abxjs.d.ts.map +1 -0
- package/dist/abxjs.js +49 -0
- package/dist/abxjs.js.map +1 -0
- package/dist/art.d.ts +26 -0
- package/dist/art.d.ts.map +1 -0
- package/dist/art.js +85 -0
- package/dist/art.js.map +1 -0
- package/dist/code.d.ts +73 -0
- package/dist/code.d.ts.map +1 -0
- package/dist/code.js +216 -0
- package/dist/code.js.map +1 -0
- package/dist/dashboard.d.ts +12 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +231 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/deps.d.ts +146 -0
- package/dist/deps.d.ts.map +1 -0
- package/dist/deps.js +297 -0
- package/dist/deps.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/inline.d.ts +19 -0
- package/dist/inline.d.ts.map +1 -0
- package/dist/inline.js +23 -0
- package/dist/inline.js.map +1 -0
- package/dist/metadata.d.ts +89 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +673 -0
- package/dist/metadata.js.map +1 -0
- package/dist/resolve.d.ts +74 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +107 -0
- package/dist/resolve.js.map +1 -0
- package/dist/server.d.ts +91 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +940 -0
- package/dist/server.js.map +1 -0
- package/dist/watcher.d.ts +56 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +179 -0
- package/dist/watcher.js.map +1 -0
- 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.
|
package/dist/abxjs.d.ts
ADDED
|
@@ -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
|
package/dist/art.js.map
ADDED
|
@@ -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
|
package/dist/code.js.map
ADDED
|
@@ -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"}
|