@artblocks/abx-token-api 0.1.0-alpha.2 → 0.1.0-alpha.20
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/dist/code.d.ts +33 -12
- package/dist/code.d.ts.map +1 -1
- package/dist/code.js +45 -55
- package/dist/code.js.map +1 -1
- package/dist/{art.d.ts → content.d.ts} +5 -5
- package/dist/content.d.ts.map +1 -0
- package/dist/{art.js → content.js} +6 -6
- package/dist/content.js.map +1 -0
- package/dist/control-plane.d.ts +85 -0
- package/dist/control-plane.d.ts.map +1 -0
- package/dist/control-plane.js +721 -0
- package/dist/control-plane.js.map +1 -0
- package/dist/dashboard.d.ts +1 -1
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +39 -16
- package/dist/dashboard.js.map +1 -1
- package/dist/deps.d.ts +28 -110
- package/dist/deps.d.ts.map +1 -1
- package/dist/deps.js +34 -184
- package/dist/deps.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -10
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +29 -2
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +298 -104
- package/dist/metadata.js.map +1 -1
- package/dist/resolve.d.ts +0 -2
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +0 -5
- package/dist/resolve.js.map +1 -1
- package/dist/server.d.ts +4 -27
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +251 -418
- package/dist/server.js.map +1 -1
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +137 -8
- package/dist/watcher.js.map +1 -1
- package/package.json +4 -4
- package/dist/abxjs.d.ts +0 -13
- package/dist/abxjs.d.ts.map +0 -1
- package/dist/abxjs.js +0 -49
- package/dist/abxjs.js.map +0 -1
- package/dist/art.d.ts.map +0 -1
- package/dist/art.js.map +0 -1
- package/dist/inline.d.ts +0 -19
- package/dist/inline.d.ts.map +0 -1
- package/dist/inline.js +0 -23
- package/dist/inline.js.map +0 -1
package/dist/code.d.ts
CHANGED
|
@@ -18,12 +18,42 @@ export declare function liveViewUrl(baseUrl: string, chainId: number, address: s
|
|
|
18
18
|
/** Whether the derived live view should fill `animation_url` (code present, not suppressed). */
|
|
19
19
|
export declare function liveViewEnabled(state: ProjectState): boolean;
|
|
20
20
|
export { isCodeProject };
|
|
21
|
+
/**
|
|
22
|
+
* Whether the live view can be served — and, when it can't, WHICH KIND of "can't" it is.
|
|
23
|
+
*
|
|
24
|
+
* The `/a/` route used to collapse every negative into one confident verdict about the *contract*
|
|
25
|
+
* ("not a code project"), when at least one of them is a statement about the *index*. `chunkCount`
|
|
26
|
+
* is a head read, so a template-mode project whose chunks have not been folded in yet reads as
|
|
27
|
+
* zero — not-yet-a-code-project to the check, and forever-not-a-code-project to the reader. A
|
|
28
|
+
* tester lost a day to that wording: they got `live · caught up · 127 events · 32 tokens` from the
|
|
29
|
+
* node and this 404 from `/a/`, concluded the resolver did not recognise the SeriesCode factory,
|
|
30
|
+
* and a `--full` re-index did not clear it.
|
|
31
|
+
*
|
|
32
|
+
* `contractType` is folded from the deployed extensions, so it knows this is a code project before
|
|
33
|
+
* any code lands — which is exactly the distinction the route needs.
|
|
34
|
+
*
|
|
35
|
+
* - `ready` — there is executable content; go serve it.
|
|
36
|
+
* - `indexing` — this IS a code contract, but its code hasn't been folded in yet. Retry-able.
|
|
37
|
+
* - `not-a-code-project` — no executable content and nothing says there should be. Terminal.
|
|
38
|
+
*
|
|
39
|
+
* Pure, and deliberately so: this is a projection-only decision that needs no RPC (a contract with
|
|
40
|
+
* no executable content does not acquire some when a chain client appears), which is why the route
|
|
41
|
+
* answers it before touching one.
|
|
42
|
+
*/
|
|
43
|
+
export type LiveViewAvailability = 'ready' | 'indexing' | 'not-a-code-project';
|
|
44
|
+
export declare function liveViewAvailability(state: ProjectState): LiveViewAvailability;
|
|
21
45
|
/**
|
|
22
46
|
* A render-artifact locator (`ipfs://<cid>`, `ar://<txid>`, or an absolute `https://…`) → a fetchable
|
|
23
|
-
* URL, applying the
|
|
24
|
-
*
|
|
47
|
+
* URL, applying the gateway at SERVE time. Same source of truth as `codeLocatorUrl` and the metadata
|
|
48
|
+
* planes: the collection's `abx_gateway_*` preference first, this host's env as the floor. An
|
|
49
|
+
* already-absolute URL is returned verbatim (never re-prefixed).
|
|
50
|
+
*
|
|
51
|
+
* `state` is required rather than optional because these locators are the SAME project's content
|
|
52
|
+
* reached by a different route (an effect artifact, a computed `text/uri-list`), and a redirect that
|
|
53
|
+
* ignored the project's stated gateway while `image` honoured it would be a difference nobody could
|
|
54
|
+
* explain from the chain.
|
|
25
55
|
*/
|
|
26
|
-
export declare function resolveLocatorUrl(locator: string): string;
|
|
56
|
+
export declare function resolveLocatorUrl(state: ProjectState, locator: string): string;
|
|
27
57
|
/**
|
|
28
58
|
* The token's CURRENT settled inputsHash — the effect-run identity every artifact address is
|
|
29
59
|
* keyed by. SETTLED tokenData (augment: false) — must mirror the producer's addressing
|
|
@@ -61,13 +91,4 @@ export type LiveView = {
|
|
|
61
91
|
export declare function resolveLiveView(client: PublicClient, state: ProjectState, token: TokenState, fetchFn?: typeof fetch): Promise<LiveView>;
|
|
62
92
|
/** Reset the in-process entry-document cache — for tests. */
|
|
63
93
|
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
94
|
//# sourceMappingURL=code.d.ts.map
|
package/dist/code.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../src/code.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../src/code.ts"],"names":[],"mappings":"AACA,OAAO,EAWL,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;AAG3D;;;;;;;;;;;;;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;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,UAAU,GAAG,oBAAoB,CAAC;AAE/E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,oBAAoB,CAG9E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAc9E;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"}
|
package/dist/code.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { hexToString } from 'viem';
|
|
2
|
-
import { buildTokenData, codeField, contentDigestOf, contractParamString, inputsHash, isCodeProject, renderArtifactKey, } from '@artblocks/abx-sdk';
|
|
2
|
+
import { buildGeneratorDocument, buildTokenData, codeField, contentDigestOf, contractParamString, gatewayConfigFromEnv, projectGatewayPrefix, projectGatewayUrl, injectTokenDataIntoHtml, inputsHash, isCodeProject, renderArtifactKey, } from '@artblocks/abx-sdk';
|
|
3
3
|
import { seriesCodeAbi } from '@artblocks/abx-sdk';
|
|
4
|
-
import { ABX_JS } from './abxjs.js';
|
|
5
4
|
import { checkUrlBudget, dependencyScriptTags, recordDirectoryServe } from './deps.js';
|
|
6
|
-
import { escapeInlineJson, escapeInlineScript } from './inline.js';
|
|
7
5
|
/**
|
|
8
6
|
* The live view + the render-effect consumption seam.
|
|
9
7
|
*
|
|
@@ -26,21 +24,36 @@ export function liveViewEnabled(state) {
|
|
|
26
24
|
return isCodeProject(state) && contractParamString(state, 'display.animation') !== 'none';
|
|
27
25
|
}
|
|
28
26
|
export { isCodeProject };
|
|
27
|
+
export function liveViewAvailability(state) {
|
|
28
|
+
if (isCodeProject(state))
|
|
29
|
+
return 'ready';
|
|
30
|
+
return state.contractType === 'code' ? 'indexing' : 'not-a-code-project';
|
|
31
|
+
}
|
|
29
32
|
/**
|
|
30
33
|
* A render-artifact locator (`ipfs://<cid>`, `ar://<txid>`, or an absolute `https://…`) → a fetchable
|
|
31
|
-
* URL, applying the
|
|
32
|
-
*
|
|
34
|
+
* URL, applying the gateway at SERVE time. Same source of truth as `codeLocatorUrl` and the metadata
|
|
35
|
+
* planes: the collection's `abx_gateway_*` preference first, this host's env as the floor. An
|
|
36
|
+
* already-absolute URL is returned verbatim (never re-prefixed).
|
|
37
|
+
*
|
|
38
|
+
* `state` is required rather than optional because these locators are the SAME project's content
|
|
39
|
+
* reached by a different route (an effect artifact, a computed `text/uri-list`), and a redirect that
|
|
40
|
+
* ignored the project's stated gateway while `image` honoured it would be a difference nobody could
|
|
41
|
+
* explain from the chain.
|
|
33
42
|
*/
|
|
34
|
-
export function resolveLocatorUrl(locator) {
|
|
43
|
+
export function resolveLocatorUrl(state, locator) {
|
|
35
44
|
if (/^https?:\/\//i.test(locator))
|
|
36
45
|
return locator;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
46
|
+
// Explicit compose (the on-chain preference + the SDK's env helper) rather than a single call, so
|
|
47
|
+
// the env read (`ABX_IPFS_GATEWAY`/`ABX_ARWEAVE_GATEWAY`) is visibly host-side here, at the
|
|
48
|
+
// one place this resolver actually reads it.
|
|
49
|
+
const gateways = gatewayConfigFromEnv();
|
|
50
|
+
for (const network of ['ipfs', 'arweave']) {
|
|
51
|
+
const scheme = network === 'ipfs' ? 'ipfs://' : 'ar://';
|
|
52
|
+
if (locator.startsWith(scheme)) {
|
|
53
|
+
const wrapped = projectGatewayUrl(network, locator, projectGatewayPrefix(state, network, gateways));
|
|
54
|
+
if (wrapped !== null)
|
|
55
|
+
return wrapped;
|
|
56
|
+
}
|
|
44
57
|
}
|
|
45
58
|
return locator;
|
|
46
59
|
}
|
|
@@ -75,7 +88,7 @@ export async function resolveLiveView(client, state, token, fetchFn = fetch) {
|
|
|
75
88
|
const { json } = await buildTokenData(client, state, token, { augment: process.env.ABX_DISABLE_AUGMENT !== '1' });
|
|
76
89
|
const code = codeField(state);
|
|
77
90
|
if (code) {
|
|
78
|
-
const base = codeLocatorUrl(code.representation, code.value);
|
|
91
|
+
const base = codeLocatorUrl(state, code.representation, code.value);
|
|
79
92
|
if (!base)
|
|
80
93
|
return null;
|
|
81
94
|
const entry = base.endsWith('.html') ? base : `${base.replace(/\/$/, '')}/index.html`;
|
|
@@ -136,31 +149,18 @@ async function fetchEntryDocument(representation, url, fetchFn) {
|
|
|
136
149
|
entryDocCache.set(url, { html, expiresAt: Date.now() + ttl });
|
|
137
150
|
return html;
|
|
138
151
|
}
|
|
152
|
+
// `injectTokenDataIntoHtml` moved to `@artblocks/abx-sdk` (src/generator-document.ts) — the
|
|
153
|
+
// abx-services integrator ask. Imported above; used at its call site just below.
|
|
139
154
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
155
|
+
* A `code` field locator → a fetchable https URL.
|
|
156
|
+
*
|
|
157
|
+
* The twin of `AbxGenerator._directoryUrl`'s gateway handling, and it reads the SAME source the
|
|
158
|
+
* generator does: the collection's reserved `abx_gateway_ipfs` / `abx_gateway_arweave` field, with
|
|
159
|
+
* this host's env as the floor beneath it. That is the whole point of `state` being a parameter
|
|
160
|
+
* here — the two lanes serve the same project, so they must agree on the code root's URL, and this
|
|
161
|
+
* used to consult env alone while the generator consulted a contract param.
|
|
146
162
|
*/
|
|
147
|
-
|
|
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) {
|
|
163
|
+
function codeLocatorUrl(state, representation, value) {
|
|
164
164
|
const text = hexToString(value);
|
|
165
165
|
// A stored locator can already be an absolute URL (e.g. a gateway URL saved verbatim by an older
|
|
166
166
|
// deploy) — serve it directly rather than prefixing a gateway again (which double-prefixes to a
|
|
@@ -169,13 +169,11 @@ function codeLocatorUrl(representation, value) {
|
|
|
169
169
|
return text;
|
|
170
170
|
if (representation === 'url')
|
|
171
171
|
return text;
|
|
172
|
-
if (representation === 'ipfs') {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const gw = process.env.ABX_ARWEAVE_GATEWAY ?? 'https://arweave.net';
|
|
178
|
-
return `${gw.replace(/\/$/, '')}/${text.replace(/^ar:\/\//, '')}`;
|
|
172
|
+
if (representation === 'ipfs' || representation === 'arweave') {
|
|
173
|
+
// Explicit compose (the on-chain preference + this host's env floor) — the env read stays
|
|
174
|
+
// visibly host-side here, at the one place this resolver actually reaches for it.
|
|
175
|
+
const prefix = projectGatewayPrefix(state, representation, gatewayConfigFromEnv());
|
|
176
|
+
return projectGatewayUrl(representation, text, prefix);
|
|
179
177
|
}
|
|
180
178
|
return null; // `code` is locators-only by the registry; anything else is unserveable
|
|
181
179
|
}
|
|
@@ -201,16 +199,8 @@ async function assembleGeneratorDocument(client, state, tokenDataJson) {
|
|
|
201
199
|
// "Consumers"): the collection's registry pointer (on-chain bytes → preferredCDN) → the
|
|
202
200
|
// built-in CDN map. Resolution never throws — the document always assembles.
|
|
203
201
|
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');
|
|
202
|
+
return buildGeneratorDocument(script, tokenDataJson, depTags);
|
|
215
203
|
}
|
|
204
|
+
// `buildGeneratorDocument` moved to `@artblocks/abx-sdk` (src/generator-document.ts) — the
|
|
205
|
+
// abx-services integrator ask. Imported above; used at its call site just above.
|
|
216
206
|
//# sourceMappingURL=code.js.map
|
package/dist/code.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.js","sourceRoot":"","sources":["../src/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,MAAM,CAAC;AACjC,OAAO,EACL,cAAc,EACd,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,aAAa,EACb,iBAAiB,GAKlB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../src/code.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,16 +11,16 @@ import { type Hex } from 'viem';
|
|
|
11
11
|
*/
|
|
12
12
|
export declare const IMAGE_MEDIA_TYPE = "image/svg+xml";
|
|
13
13
|
/** Deterministic generative SVG for a contract address. Pure: address → bytes. */
|
|
14
|
-
export declare function
|
|
15
|
-
/** keccak256 of the generated
|
|
16
|
-
export declare function
|
|
14
|
+
export declare function generateContent(address: string): string;
|
|
15
|
+
/** keccak256 of the generated content's UTF-8 bytes — the value committed on-chain (image `keccak256` field). */
|
|
16
|
+
export declare function contentHash(address: string): Hex;
|
|
17
17
|
/**
|
|
18
18
|
* The required-field *fallback* image — a simple, deterministic placeholder used when a
|
|
19
19
|
* token has no resolvable `image` (unset, or a representation the surface can't load).
|
|
20
20
|
* Deliberately trivial so it is **byte-identical** to the on-chain renderer's
|
|
21
21
|
* `_fallbackImage` (`AbxMetadataRenderer`): background = the address's first 3 bytes,
|
|
22
|
-
* label = `#tokenId`. Distinct from {
|
|
22
|
+
* label = `#tokenId`. Distinct from {generateContent} (the demo's *chosen* content) — this is
|
|
23
23
|
* the "nothing was set" placeholder both the on-chain and off-chain resolvers agree on.
|
|
24
24
|
*/
|
|
25
25
|
export declare function fallbackImageSvg(address: string, tokenId: string | number | bigint): string;
|
|
26
|
-
//# sourceMappingURL=
|
|
26
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,GAAG,EAAC,MAAM,MAAM,CAAC;AAExD;;;;;;;;;GASG;AAEH,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAahD,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA6CvD;AAED,iHAAiH;AACjH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAEhD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAQ3F"}
|
|
@@ -21,7 +21,7 @@ function mulberry32(seed) {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
/** Deterministic generative SVG for a contract address. Pure: address → bytes. */
|
|
24
|
-
export function
|
|
24
|
+
export function generateContent(address) {
|
|
25
25
|
const clean = address.toLowerCase().replace(/^0x/, '').padEnd(40, '0');
|
|
26
26
|
const seed = parseInt(clean.slice(0, 8), 16) ^ parseInt(clean.slice(8, 16), 16);
|
|
27
27
|
const rnd = mulberry32(seed);
|
|
@@ -63,16 +63,16 @@ export function generateArt(address) {
|
|
|
63
63
|
`</svg>`,
|
|
64
64
|
].join('');
|
|
65
65
|
}
|
|
66
|
-
/** keccak256 of the generated
|
|
67
|
-
export function
|
|
68
|
-
return keccak256(stringToBytes(
|
|
66
|
+
/** keccak256 of the generated content's UTF-8 bytes — the value committed on-chain (image `keccak256` field). */
|
|
67
|
+
export function contentHash(address) {
|
|
68
|
+
return keccak256(stringToBytes(generateContent(address)));
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
71
|
* The required-field *fallback* image — a simple, deterministic placeholder used when a
|
|
72
72
|
* token has no resolvable `image` (unset, or a representation the surface can't load).
|
|
73
73
|
* Deliberately trivial so it is **byte-identical** to the on-chain renderer's
|
|
74
74
|
* `_fallbackImage` (`AbxMetadataRenderer`): background = the address's first 3 bytes,
|
|
75
|
-
* label = `#tokenId`. Distinct from {
|
|
75
|
+
* label = `#tokenId`. Distinct from {generateContent} (the demo's *chosen* content) — this is
|
|
76
76
|
* the "nothing was set" placeholder both the on-chain and off-chain resolvers agree on.
|
|
77
77
|
*/
|
|
78
78
|
export function fallbackImageSvg(address, tokenId) {
|
|
@@ -82,4 +82,4 @@ export function fallbackImageSvg(address, tokenId) {
|
|
|
82
82
|
`<text x="250" y="264" font-family="monospace" font-size="42" fill="#ffffff" text-anchor="middle">#${tokenId}</text>` +
|
|
83
83
|
`</svg>`);
|
|
84
84
|
}
|
|
85
|
-
//# sourceMappingURL=
|
|
85
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The /v1 control plane + the service descriptor — the resolver's ONE write surface, speaking the
|
|
3
|
+
* provider-neutral interface pinned by specs/self-host-toolkit/remote-services.md. Everything here
|
|
4
|
+
* is index/metadata control (register, list, deregister, reindex, status, artifact registration): the
|
|
5
|
+
* bearer token never signs anything on-chain, so the "no signing key on the host" rule is intact.
|
|
6
|
+
*
|
|
7
|
+
* This module never imports server.ts (one-way dependency), which is why the shared HTTP helpers
|
|
8
|
+
* (sendJson, the bearer guard) live here and the read plane imports them.
|
|
9
|
+
*/
|
|
10
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
11
|
+
import { type ProjectState, type ServiceDescriptor, type ServiceErrorCode } from '@artblocks/abx-sdk';
|
|
12
|
+
import type { SelfHostIndexer } from '@artblocks/abx-indexer';
|
|
13
|
+
import type { StorageBackend } from '@artblocks/abx-storage';
|
|
14
|
+
export interface ControlPlaneContext {
|
|
15
|
+
indexer: SelfHostIndexer;
|
|
16
|
+
storage: StorageBackend;
|
|
17
|
+
/** The chain this node serves — every control-plane call names a chainId and is checked against it. */
|
|
18
|
+
chainId: number;
|
|
19
|
+
/** The chain KEY ('sepolia', …) the indexer registers projects under — the string form of chainId. */
|
|
20
|
+
chainKey: string;
|
|
21
|
+
/** The public base this node believes it serves — echoed in the descriptor. */
|
|
22
|
+
baseUrl: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
|
|
25
|
+
/** Every non-2xx control-plane response: `{error: <human>, code: <machine>}` — clients key off
|
|
26
|
+
* `code`, never off prose (specs/self-host-toolkit/remote-services.md → Errors). */
|
|
27
|
+
export declare function sendError(res: ServerResponse, status: number, code: ServiceErrorCode, message: string, extra?: Record<string, unknown>): void;
|
|
28
|
+
/**
|
|
29
|
+
* The ONE bearer guard for every gated route: 404 code `disabled` when no token is configured on
|
|
30
|
+
* the host (the write surface honestly doesn't exist — the descriptor omits the control-plane
|
|
31
|
+
* interface too), 401 code `unauthorized` on a missing/bad bearer. Returns false if it handled
|
|
32
|
+
* the response (caller must stop), true when the request may proceed. 403 (`forbidden`) is
|
|
33
|
+
* spec-defined for multi-tenant providers; this single-token reference never emits it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function requireBearer(req: IncomingMessage, res: ServerResponse): boolean;
|
|
36
|
+
/** The one-line project summary shared by `GET /api/projects` and the register/reindex responses. */
|
|
37
|
+
export declare function summarize(s: ProjectState): {
|
|
38
|
+
reconstructedAt: string;
|
|
39
|
+
copies?: string | undefined;
|
|
40
|
+
address: `0x${string}`;
|
|
41
|
+
name: string | null;
|
|
42
|
+
symbol: string | null;
|
|
43
|
+
owner: `0x${string}` | null;
|
|
44
|
+
abxVersion: number | null;
|
|
45
|
+
isCanonical: boolean | null;
|
|
46
|
+
extensions: string[];
|
|
47
|
+
eventCount: number;
|
|
48
|
+
tokenCount: number;
|
|
49
|
+
mintedCount: number;
|
|
50
|
+
};
|
|
51
|
+
/** Parse a stored content-locators JSON column → `{hash: locator}` (lowercased keys, never throws). */
|
|
52
|
+
export declare function safeLocators(json: string): Record<string, string> | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Decide the scan floor + whether a full replay is needed when registering a project via the
|
|
55
|
+
* control plane. Pure (the discovery/refusal fallback for the null case is the caller's):
|
|
56
|
+
* - explicit `bodyFromBlock` wins; else the `existingFromBlock` already stored.
|
|
57
|
+
* - `null` ⇒ NEITHER supplied nor stored — the caller must derive the deploy block or refuse
|
|
58
|
+
* (never default to genesis: a range-capped RPC would sweep millions of blocks).
|
|
59
|
+
* - `full` is true only when forced, on a first registration (no existing floor), or when the
|
|
60
|
+
* floor actually CHANGED — so re-sending the SAME floor (the CLI now always forwards the deploy
|
|
61
|
+
* block, even on a nudge) stays incremental: registering twice ≠ two full scans.
|
|
62
|
+
*/
|
|
63
|
+
export declare function planRegistrationFloor(bodyFromBlock: string | undefined, existingFromBlock: string | undefined, forceFull?: boolean): {
|
|
64
|
+
fromBlock: string;
|
|
65
|
+
full: boolean;
|
|
66
|
+
} | null;
|
|
67
|
+
/**
|
|
68
|
+
* `GET /.well-known/abx-service` — what this node supports, agent-readably (public, no auth).
|
|
69
|
+
* The control-plane interface (and `auth`) appears iff the bearer token is configured: a token-less
|
|
70
|
+
* self-host node honestly advertises no remote control surface — which is how a client tells
|
|
71
|
+
* "disabled" from "wrong URL". The artifact-registry routes ride `abx-control-plane/v1` rather than
|
|
72
|
+
* an id of their own: once referenced output is locator-only, accepting a registration is a database
|
|
73
|
+
* insert, so there is no infrastructure a node could lack that would justify a separate capability
|
|
74
|
+
* flag. `render` appears when a runner rides behind this resolver (ABX_EFFECTS_URL); its declared
|
|
75
|
+
* effects come from a best-effort `/health` probe. Provider identity (name, signup/docs URLs) is
|
|
76
|
+
* deployment env — no provider ships in this code.
|
|
77
|
+
*/
|
|
78
|
+
export declare function serviceDescriptor(ctx: ControlPlaneContext): Promise<ServiceDescriptor>;
|
|
79
|
+
/**
|
|
80
|
+
* Dispatch a `/v1/*` request (`parts` excludes the leading `v1`). Every route is bearer-gated;
|
|
81
|
+
* `chainId` is explicit everywhere (body on collection POSTs, path elsewhere) and validated, so a
|
|
82
|
+
* project can never silently register against the wrong chain. Wrong method on a known path ⇒ 405.
|
|
83
|
+
*/
|
|
84
|
+
export declare function routeControlPlane(req: IncomingMessage, res: ServerResponse, ctx: ControlPlaneContext, parts: string[]): Promise<void>;
|
|
85
|
+
//# sourceMappingURL=control-plane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-plane.d.ts","sourceRoot":"","sources":["../src/control-plane.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAC,eAAe,EAAE,cAAc,EAAC,MAAM,WAAW,CAAC;AAC/D,OAAO,EAeL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,wBAAwB,CAAC;AAG3D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,uGAAuG;IACvG,OAAO,EAAE,MAAM,CAAC;IAChB,sGAAsG;IACtG,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAGjF;AAED;qFACqF;AACrF,wBAAgB,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE7I;AAuDD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAUhF;AAgDD,qGAAqG;AACrG,wBAAgB,SAAS,CAAC,CAAC,EAAE,YAAY;;;;;;;;;;;;;EAgBxC;AAED,uGAAuG;AACvG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAS7E;AAcD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,iBAAiB,EAAE,MAAM,GAAG,SAAS,EACrC,SAAS,UAAQ,GAChB;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,GAAG,IAAI,CAK3C;AAuCD;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqB5F;AAID;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,mBAAmB,EACxB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
|