@artblocks/abx-cli 0.1.0-alpha.17 → 0.1.0-alpha.19

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 (121) hide show
  1. package/CHANGELOG.md +218 -0
  2. package/dist/commands/deploy.d.ts +181 -0
  3. package/dist/commands/deploy.d.ts.map +1 -0
  4. package/dist/commands/deploy.js +2974 -0
  5. package/dist/commands/deploy.js.map +1 -0
  6. package/dist/commands/project.d.ts +134 -0
  7. package/dist/commands/project.d.ts.map +1 -0
  8. package/dist/commands/project.js +919 -0
  9. package/dist/commands/project.js.map +1 -0
  10. package/dist/commands/reads.d.ts +64 -0
  11. package/dist/commands/reads.d.ts.map +1 -0
  12. package/dist/commands/reads.js +635 -0
  13. package/dist/commands/reads.js.map +1 -0
  14. package/dist/commands/scaffold.d.ts +69 -0
  15. package/dist/commands/scaffold.d.ts.map +1 -0
  16. package/dist/commands/scaffold.js +508 -0
  17. package/dist/commands/scaffold.js.map +1 -0
  18. package/dist/commands/service.d.ts +41 -0
  19. package/dist/commands/service.d.ts.map +1 -0
  20. package/dist/commands/service.js +618 -0
  21. package/dist/commands/service.js.map +1 -0
  22. package/dist/commands/storage.d.ts +37 -0
  23. package/dist/commands/storage.d.ts.map +1 -0
  24. package/dist/commands/storage.js +335 -0
  25. package/dist/commands/storage.js.map +1 -0
  26. package/dist/config.d.ts +72 -2
  27. package/dist/config.d.ts.map +1 -1
  28. package/dist/config.js +201 -4
  29. package/dist/config.js.map +1 -1
  30. package/dist/conformance.d.ts +31 -0
  31. package/dist/conformance.d.ts.map +1 -0
  32. package/dist/conformance.js +371 -0
  33. package/dist/conformance.js.map +1 -0
  34. package/dist/deps.d.ts +6 -39
  35. package/dist/deps.d.ts.map +1 -1
  36. package/dist/deps.js +4 -68
  37. package/dist/deps.js.map +1 -1
  38. package/dist/errors.d.ts +20 -0
  39. package/dist/errors.d.ts.map +1 -0
  40. package/dist/errors.js +25 -0
  41. package/dist/errors.js.map +1 -0
  42. package/dist/flags.d.ts +34 -0
  43. package/dist/flags.d.ts.map +1 -1
  44. package/dist/flags.js +74 -0
  45. package/dist/flags.js.map +1 -1
  46. package/dist/main.js +220 -6905
  47. package/dist/main.js.map +1 -1
  48. package/dist/mintpage.d.ts +3 -1
  49. package/dist/mintpage.d.ts.map +1 -1
  50. package/dist/mintpage.js +48 -48
  51. package/dist/mintpage.js.map +1 -1
  52. package/dist/output.d.ts +137 -0
  53. package/dist/output.d.ts.map +1 -0
  54. package/dist/output.js +504 -0
  55. package/dist/output.js.map +1 -0
  56. package/dist/ownerops.d.ts +23 -44
  57. package/dist/ownerops.d.ts.map +1 -1
  58. package/dist/ownerops.js +151 -233
  59. package/dist/ownerops.js.map +1 -1
  60. package/dist/preview.d.ts +8 -4
  61. package/dist/preview.d.ts.map +1 -1
  62. package/dist/preview.js +8 -17
  63. package/dist/preview.js.map +1 -1
  64. package/dist/provision.d.ts.map +1 -1
  65. package/dist/provision.js +10 -7
  66. package/dist/provision.js.map +1 -1
  67. package/dist/remote.d.ts +72 -7
  68. package/dist/remote.d.ts.map +1 -1
  69. package/dist/remote.js +211 -9
  70. package/dist/remote.js.map +1 -1
  71. package/dist/riskgate.d.ts +29 -0
  72. package/dist/riskgate.d.ts.map +1 -0
  73. package/dist/riskgate.js +91 -0
  74. package/dist/riskgate.js.map +1 -0
  75. package/dist/schema.d.ts +6 -0
  76. package/dist/schema.d.ts.map +1 -1
  77. package/dist/schema.js +12 -16
  78. package/dist/schema.js.map +1 -1
  79. package/dist/served.d.ts +1 -17
  80. package/dist/served.d.ts.map +1 -1
  81. package/dist/served.js +47 -0
  82. package/dist/served.js.map +1 -1
  83. package/dist/signer.d.ts +13 -0
  84. package/dist/signer.d.ts.map +1 -1
  85. package/dist/signer.js +42 -19
  86. package/dist/signer.js.map +1 -1
  87. package/dist/update-check.d.ts +27 -0
  88. package/dist/update-check.d.ts.map +1 -1
  89. package/dist/update-check.js +30 -0
  90. package/dist/update-check.js.map +1 -1
  91. package/package.json +6 -6
  92. package/skill/SKILL.md +7 -11
  93. package/skill/reference/code-projects.md +3 -3
  94. package/skill/reference/hosting.md +6 -6
  95. package/skill/reference/operating.md +2 -5
  96. package/skill/reference/setup.md +2 -2
  97. package/skill/reference/troubleshooting.md +1 -1
  98. package/dist/gas.d.ts +0 -63
  99. package/dist/gas.d.ts.map +0 -1
  100. package/dist/gas.js +0 -76
  101. package/dist/gas.js.map +0 -1
  102. package/dist/inspect.d.ts +0 -48
  103. package/dist/inspect.d.ts.map +0 -1
  104. package/dist/inspect.js +0 -290
  105. package/dist/inspect.js.map +0 -1
  106. package/dist/migrate.d.ts +0 -65
  107. package/dist/migrate.d.ts.map +0 -1
  108. package/dist/migrate.js +0 -180
  109. package/dist/migrate.js.map +0 -1
  110. package/dist/onchain-uri.d.ts +0 -81
  111. package/dist/onchain-uri.d.ts.map +0 -1
  112. package/dist/onchain-uri.js +0 -251
  113. package/dist/onchain-uri.js.map +0 -1
  114. package/dist/resume.d.ts +0 -96
  115. package/dist/resume.d.ts.map +0 -1
  116. package/dist/resume.js +0 -95
  117. package/dist/resume.js.map +0 -1
  118. package/dist/upload.d.ts +0 -28
  119. package/dist/upload.d.ts.map +0 -1
  120. package/dist/upload.js +0 -41
  121. package/dist/upload.js.map +0 -1
package/dist/inspect.js DELETED
@@ -1,290 +0,0 @@
1
- /**
2
- * `abx inspect <script.js>` — static analysis of a generative script, BEFORE picking a lane.
3
- *
4
- * The membrane fix behind this: an agent (or creator) should DERIVE the deployment lane from what
5
- * the script actually needs — are there traits? are they reproducible on-chain? how big is the
6
- * assembled document (does a single `tokenURI` eth_call even fit)? — instead of guessing "fully
7
- * on-chain!" and walking it back. This module is the pure analysis; `cmdInspect` formats it.
8
- *
9
- * Static only — it never executes the script (that's the resolver/runner's job, and executing
10
- * untrusted art in the CLI would be a footgun). Everything here is regex/heuristic over the source.
11
- */
12
- /** Approx bytes a known on-chain dependency adds to the ASSEMBLED document (gzip'd + base64'd, as it
13
- * rides in the inline data-URI). Measured from real drops; used only for the RPC-size estimate. */
14
- const KNOWN_DEP_DOC_BYTES = {
15
- 'p5@1.0.0': 200_000, // p5 1.0.0 (~623KB raw) rides ~200KB gzip+base64 in the document
16
- };
17
- /** The on-chain runtime the generator always inlines (abx.js + the gunzip bootstrap), base64'd. */
18
- const RUNTIME_DOC_BYTES = 13_000;
19
- /** A single `eth_call` returning `tokenURI` comfortably carries this much document on a default node
20
- * (geth's 50M gas cap; memory expansion is ~quadratic). Past it, marketplaces that call `tokenURI`
21
- * once may time out — prefer the generator's piecewise getters, directory mode, or a CDN dep. */
22
- const SINGLE_CALL_DOC_CEILING = 1_500_000;
23
- /**
24
- * Two views of the source, so a regex heuristic can never fire on prose.
25
- *
26
- * Every detector here is a regex over the file, and a comment or a string is not code: a
27
- * dependency-free sketch whose header reads `// vanilla canvas, no p5` was reported as
28
- * `libraries: p5` and then RECOMMENDED `--dep p5@<version>` — advice the agent adopts verbatim,
29
- * which bloats the stored document and can drag a drop onto the wrong chain (on-chain deps need a
30
- * dependency registry ⇒ Sepolia, not Base Sepolia). One tokenizer pass fixes that whole class.
31
- *
32
- * - `code`: comments removed, string/template contents blanked (quotes kept, so syntax survives).
33
- * For flags that must reflect real code — library globals, PRNG use, the runtime data contract.
34
- * - `noComments`: comments removed, strings INTACT. For extractors that read literal content —
35
- * trait keys (`'Plant Count':`) and bracket-accessed param keys (`tokenData['collapse.index']`).
36
- */
37
- function sourceViews(source) {
38
- const code = [];
39
- const noComments = [];
40
- const n = source.length;
41
- let i = 0;
42
- const push = (ch, inString) => {
43
- noComments.push(ch);
44
- code.push(inString ? ' ' : ch);
45
- };
46
- while (i < n) {
47
- const ch = source[i];
48
- const next = source[i + 1];
49
- // Comments — dropped from both views (newlines kept so line-anchored regexes still work).
50
- if (ch === '/' && next === '/') {
51
- while (i < n && source[i] !== '\n')
52
- i++;
53
- continue;
54
- }
55
- if (ch === '/' && next === '*') {
56
- i += 2;
57
- while (i < n && !(source[i] === '*' && source[i + 1] === '/')) {
58
- if (source[i] === '\n')
59
- push('\n', false);
60
- i++;
61
- }
62
- i += 2;
63
- continue;
64
- }
65
- // Strings + template literals — kept in `noComments`, blanked in `code`.
66
- if (ch === '"' || ch === "'" || ch === '`') {
67
- const quote = ch;
68
- push(quote, false);
69
- i++;
70
- while (i < n && source[i] !== quote) {
71
- if (source[i] === '\\') {
72
- push(source[i], true);
73
- i++;
74
- if (i < n) {
75
- push(source[i], true);
76
- i++;
77
- }
78
- continue;
79
- }
80
- push(source[i] === '\n' ? '\n' : source[i], source[i] !== '\n');
81
- i++;
82
- }
83
- if (i < n) {
84
- push(quote, false);
85
- i++;
86
- }
87
- continue;
88
- }
89
- push(ch, false);
90
- i++;
91
- }
92
- return { code: code.join(''), noComments: noComments.join('') };
93
- }
94
- /**
95
- * Coordinates the runtime injects into `tokenData` on every render. They are NOT PostParams: they
96
- * arrive automatically, and `--schema tokenId:…` is advice that must never be followed (a reserved
97
- * key can't be declared). Excluded from {@link paramKeys} so the "declare EACH or it's dropped"
98
- * warning only ever names keys a creator can actually declare.
99
- */
100
- const RESERVED_TOKEN_DATA_KEYS = new Set(['seed', 'tokenId', 'chainId', 'contractAddress']);
101
- /** PostParam keys the script READS from tokenData — the palette-style customization inputs. A deploy
102
- * that omits these from `--schema` silently drops them (the render sees `undefined` → its default),
103
- * which is exactly how a real session "forgot" the palette it had itself identified. Heuristic (the
104
- * script isn't executed): find identifiers aliased to `abx.tokenData`, then their property reads;
105
- * plus direct `abx.tokenData.key`, destructuring, and `tokenData['key']`. `seed` is intrinsic, not a
106
- * PostParam, so it's excluded. Advisory — over- or under-detection is a hint, never a hard gate. */
107
- function paramKeys(source) {
108
- const keys = new Set();
109
- const add = (k) => { if (k && !RESERVED_TOKEN_DATA_KEYS.has(k))
110
- keys.add(k); };
111
- // Identifiers aliased to the token-data object — either `abx.tokenData` (via abx.js) or the raw
112
- // injected global `window.abxTokenData` (e.g. `var td = (window.abx && abx.tokenData) || {}`).
113
- const aliases = new Set();
114
- // The `(?!…\.[A-Za-z_$])` guard: only alias when the RHS is the tokenData OBJECT, not a PROPERTY of
115
- // it — `const seed = abx.tokenData.seed` aliases `seed` to a scalar, so its method calls
116
- // (`seed.startsWith(…)`) must NOT be read as params (the false-positive that flagged startsWith/slice).
117
- const aliasRe = /\b([A-Za-z_$][\w$]*)\s*=\s*[^;\n]*(?:abx\s*\??\s*\.\s*tokenData|window\s*\??\s*\.\s*abxTokenData)(?!\s*\??\s*\.\s*[A-Za-z_$])/g;
118
- let m;
119
- while ((m = aliasRe.exec(source)) !== null)
120
- aliases.add(m[1]);
121
- for (const a of aliases) {
122
- // `(?!\s*\()` excludes method CALLS (`td.slice(…)`) — a param read is a bare property, never a call.
123
- const dotRe = new RegExp(`\\b${a.replace(/[$]/g, '\\$')}\\s*\\??\\s*\\.\\s*([A-Za-z_$][\\w$]*)(?!\\s*\\()`, 'g');
124
- let d;
125
- while ((d = dotRe.exec(source)) !== null)
126
- add(d[1]);
127
- // …and bracket reads through the same alias. A DOTTED key (`collapse.index`) is only readable
128
- // as `d['collapse.index']`, and ABX's own output-naming convention is dotted
129
- // (`effect.render.image`) — so alias+bracket is the documented idiom, not an edge case. Missing
130
- // it produced a false "declare EACH or it's dropped at render" warning on a correct program.
131
- const brkRe = new RegExp(`\\b${a.replace(/[$]/g, '\\$')}\\s*\\??\\s*\\[\\s*['"]([^'"]+)['"]\\s*\\]`, 'g');
132
- while ((d = brkRe.exec(source)) !== null)
133
- add(d[1]);
134
- }
135
- // Direct `abx.tokenData.key` and `abx.tokenData['key']`.
136
- const directRe = /abx\s*\??\s*\.\s*tokenData\s*\??\s*(?:\.\s*([A-Za-z_$][\w$]*)|\[\s*['"]([^'"]+)['"]\s*\])/g;
137
- while ((m = directRe.exec(source)) !== null)
138
- add(m[1] ?? m[2]);
139
- // Destructuring: `const { palette, foo } = abx.tokenData` (or an alias).
140
- const destrRe = /(?:const|let|var)\s*\{([^}]*)\}\s*=\s*[^;\n]*(?:abx\s*\.\s*tokenData|\b(?:tokenData|td)\b)/g;
141
- while ((m = destrRe.exec(source)) !== null) {
142
- for (const part of m[1].split(','))
143
- add(part.split(':')[0].trim().replace(/\.\.\./, '') || undefined);
144
- }
145
- return [...keys];
146
- }
147
- /** Extract the key names from the first `abx.traits({ ... })` object literal (flat objects only). */
148
- function traitKeys(source) {
149
- const m = source.match(/abx\s*\??\s*\.\s*traits\s*\(\s*\{([^}]*)\}/);
150
- if (!m)
151
- return [];
152
- const keys = [];
153
- // A key sits at the start of the object or right after a comma (so a ternary VALUE like
154
- // `? 'Sparse' : 'Dense'` — a `:` not preceded by `,`/`{` — is never mistaken for a key). Allow
155
- // leading whitespace after `^` so the FIRST key (preceded only by the newline after `{`) is caught.
156
- // A key is EITHER a quoted string (arbitrary content — `'Plant Count'`, a spaced trait_type a
157
- // marketplace shows) OR a bare identifier; a bare-identifier-only match silently dropped quoted
158
- // keys, and "believe inspect" then sent authors chasing a phantom missing trait.
159
- const re = /(?:^\s*|[,{]\s*)(?:(['"])([^'"]+)\1|([A-Za-z_$][\w$]*))\s*:/g;
160
- let k;
161
- while ((k = re.exec(m[1])) !== null)
162
- keys.push(k[2] ?? k[3]);
163
- return [...new Set(keys)];
164
- }
165
- export function analyzeScript(source, declaredDeps = []) {
166
- const bytes = new TextEncoder().encode(source).length;
167
- // `code` for flags that must reflect real code, `noComments` for literal-content extraction.
168
- // Never run a detector against the raw source — a comment mentioning p5 is not a p5 dependency.
169
- const { code, noComments } = sourceViews(source);
170
- const keys = traitKeys(noComments);
171
- const usesMathRandom = /Math\s*\.\s*random\s*\(/.test(code);
172
- // p5's bare random(...) — a `random(` NOT preceded by `.` or a word char (so not Math.random / obj.random)
173
- const usesBareRandom = /(^|[^.\w])random\s*\(/.test(code);
174
- const seeded = /\brandomSeed\s*\(/.test(code);
175
- const usesNoise = /\bnoise\s*\(/.test(code);
176
- const looksP5 = /\bcreateCanvas\s*\(|function\s+setup\s*\(|function\s+draw\s*\(|\bp5\b/.test(code);
177
- // A generator the author wrote themselves — the dominant shape for dependency-free work, and
178
- // invisible to `seeded` (which only knows p5's `randomSeed(`). Matches the arithmetic fingerprints
179
- // of the usual suspects: LCG multipliers/moduli, xorshift, and the uint32 coercions they need.
180
- // Deliberately loose: a false positive costs only the more cautious verdict, a false negative
181
- // promises on-chain reproducibility that a Solidity port may not actually deliver.
182
- const handRolledPrng = /\bMath\s*\.\s*imul\s*\(|>>>\s*0\b|\^=\s*[A-Za-z_$][\w$]*\s*<<|\b(?:1664525|1013904223|1103515245|2147483647|4294967296|69069|22695477)\b/.test(code);
183
- const depHints = [];
184
- if (looksP5)
185
- depHints.push('p5');
186
- if (/\bTHREE\b/.test(code))
187
- depHints.push('three');
188
- if (/\bTone\b/.test(code))
189
- depHints.push('tone');
190
- // The abx.js runtime data contract — does the script read state + report traits the ONE way the
191
- // toolkit injects/captures them? A near-miss global deploys fine but is silently broken.
192
- // `\??\s*\.` tolerates optional chaining (`abx?.tokenData`) — a common, correct way to read it.
193
- const readsTokenData = /abx\s*\??\s*\.\s*tokenData\b/.test(code) || /window\s*\??\s*\.\s*abxTokenData\b/.test(code);
194
- const reportsTraits = /abx\s*\??\s*\.\s*traits\s*\(/.test(code);
195
- let wrongGlobal = null;
196
- if (!readsTokenData) {
197
- if (/window\s*\.\s*tokenTraits\b/.test(code))
198
- wrongGlobal = 'window.tokenTraits — traits are reported by CALLING abx.traits({…}), never by writing a global';
199
- else if (/window\s*\.\s*tokenData\b/.test(code))
200
- wrongGlobal = 'window.tokenData — abx injects window.abxTokenData (read it via abx.tokenData), not window.tokenData';
201
- else if (/\btokenData\b/.test(code))
202
- wrongGlobal = 'a bare `tokenData` — read abx.tokenData (via abx.js) or the raw window.abxTokenData global';
203
- }
204
- // Trait-reproducibility rubric (see docs/research/onchain-traits-feasibility.md).
205
- let verdict;
206
- let reason;
207
- if (keys.length === 0) {
208
- verdict = 'none';
209
- reason = 'no abx.traits({…}) call → NO marketplace traits on ANY lane. A resolver captures the keys you pass to abx.traits(); it does not invent traits from internal variables or a global. Call abx.traits({…}) in the sketch if you want filterable traits.';
210
- }
211
- else if (usesMathRandom && !seeded) {
212
- verdict = 'infeasible';
213
- reason = 'traits derive from Math.random() (unseeded) — non-deterministic, reproducible nowhere. Serve attributes via a resolver, or ship without marketplace traits.';
214
- }
215
- else if (seeded && looksP5) {
216
- verdict = 'exact-likely';
217
- reason = 'seeded p5 random() is a documented LCG — integer floor/threshold/select traits port EXACTLY to Solidity. Confirm no trait keys off a raw float value. Wire with --attributes-renderer (see docs/research/onchain-traits-feasibility.md).';
218
- }
219
- else if (seeded) {
220
- verdict = 'careful';
221
- reason = "seeded, but the PRNG isn't identified as p5 — reproducible on-chain if you port that generator + the exact call order.";
222
- }
223
- else if (usesBareRandom) {
224
- verdict = 'unknown';
225
- reason = 'traits present and random() is used, but no randomSeed() was found — check the art is deterministic before attempting on-chain traits.';
226
- }
227
- else if (handRolledPrng) {
228
- // `seeded` only recognizes p5's `randomSeed(`, so a hand-written generator used to land in the
229
- // branch below and be told "no PRNG" — with the STRONGER verdict attached. That is backwards, and
230
- // it is the common case, not an edge one: the skill's own canonical vanilla example hand-rolls an
231
- // LCG. Porting a bespoke generator to Solidity means reproducing its arithmetic AND its exact call
232
- // order, which is the `careful` bar, not the field-renderer-and-done bar.
233
- verdict = 'careful';
234
- reason =
235
- 'traits derive from a HAND-WRITTEN PRNG seeded off the token seed — deterministic, so reproducible on-chain, ' +
236
- 'but only if you port that exact generator (same arithmetic, same call order) into Solidity. Verify with identical ' +
237
- 'seeds on both sides before committing to on-chain traits; the off-chain resolver lane needs no port.';
238
- }
239
- else {
240
- verdict = 'exact-likely';
241
- reason = 'traits look derived from the seed/params directly (no PRNG) — reproducible on-chain via an attributes field-renderer.';
242
- }
243
- const deps = declaredDeps;
244
- let unknownDepSizes = false;
245
- let depDocBytes = 0;
246
- for (const d of deps) {
247
- if (d in KNOWN_DEP_DOC_BYTES)
248
- depDocBytes += KNOWN_DEP_DOC_BYTES[d];
249
- else
250
- unknownDepSizes = true;
251
- }
252
- const estBytes = bytes + RUNTIME_DOC_BYTES + depDocBytes;
253
- return {
254
- bytes,
255
- estChunks: Math.max(1, Math.ceil(bytes / 22_000)),
256
- traits: { present: keys.length > 0, keys },
257
- paramHints: paramKeys(noComments),
258
- prng: { seeded, usesBareRandom, usesMathRandom, usesNoise },
259
- depHints,
260
- looksP5,
261
- feasibility: { verdict, reason },
262
- doc: { estBytes, deps, fitsSingleCall: estBytes <= SINGLE_CALL_DOC_CEILING && !unknownDepSizes, unknownDepSizes },
263
- runtime: { readsTokenData, reportsTraits, wrongGlobal },
264
- };
265
- }
266
- /** A one-line lane recommendation derived from the analysis (the decision-tree output). */
267
- export function recommendLane(a) {
268
- const bigDoc = !a.doc.fitsSingleCall && !a.doc.unknownDepSizes;
269
- if (bigDoc) {
270
- return 'DIRECTORY mode (--code-dir) or a CDN dependency — the assembled document is too large for a single tokenURI eth_call to be reliable.';
271
- }
272
- if (a.feasibility.verdict === 'infeasible') {
273
- return 'RESOLVER lane (--public-base-url) if marketplace traits matter (a server serves the JS-derived attributes), OR --onchain-uri and accept no marketplace traits (the tokenURI + animation are still fully on-chain).';
274
- }
275
- if (a.feasibility.verdict === 'exact-likely' || a.feasibility.verdict === 'none') {
276
- const dep = a.depHints.length ? ` --dep ${a.depHints[0]}@<version>` : '';
277
- const docKb = Math.round(a.doc.estBytes / 1000);
278
- // Owner call (real-world experience): for a generative drop meant to sell, LEAD with the off-chain
279
- // resolver — maneuverable over time + marketplaces fetch a SMALL tokenURI reliably. Fully-on-chain
280
- // is the durability-max alternative, but its ~docKb tokenURI (whole doc per call) strains some
281
- // marketplace/indexer reads. Traits are NOT a free flag on the on-chain lane (deployed renderer).
282
- const traits = a.traits.present
283
- ? ` Traits (${a.traits.keys.join(', ')}): the resolver serves them from the render with no Solidity; on the on-chain lane they need a DEPLOYED --attributes-renderer (fork SeedTraitsRenderer.sol) or they're omitted.`
284
- : ``;
285
- return (`RECOMMENDED for a drop you'll sell — OFF-CHAIN RESOLVER (--public-base-url + an effects runner): maneuverable (metadata/serving can evolve without on-chain surgery) and marketplaces fetch a SMALL tokenURI reliably.${traits}\n` +
286
- ` ALTERNATIVE — FULLY ON-CHAIN (--onchain-uri${dep} --image-base <bucket>): maximal durability / no server, but the tokenURI carries the whole ~${docKb}KB document per call (some marketplace + indexer reads choke on a doc this big), stills are MANUAL, and later changes are on-chain re-points. Pick it when permanence + zero-infra outweigh maneuverability.`);
287
- }
288
- return (`RECOMMENDED — an OFF-CHAIN RESOLVER (--public-base-url): maneuverable, and it serves traits from the render regardless of the PRNG. --onchain-uri also works for tokenURI + animation, but first verify the script is deterministic (see the feasibility note), and note the large-tokenURI marketplace-read tradeoff; on that lane traits need a DEPLOYED --attributes-renderer or are omitted.`);
289
- }
290
- //# sourceMappingURL=inspect.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../src/inspect.ts"],"names":[],"mappings":"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"}
package/dist/migrate.d.ts DELETED
@@ -1,65 +0,0 @@
1
- import type { OpenSeaAttribute, ProjectState } from '@artblocks/abx-sdk';
2
- import { type StorageBackend } from '@artblocks/abx-storage';
3
- /** An image that lives ONLY on the source host (committed by hash, never pinned to a durable
4
- * backend) — there's no portable URL to copy, so its bytes must be re-pinned before cutover. */
5
- export interface NodeCustodyImage {
6
- tokenId: string;
7
- /** On-chain content hash (the `keccak256`/`sha256` commitment) — what we verify re-pinned bytes against. */
8
- hash: string;
9
- /** The source's served image URL — the old host's own `/…/image` route; where we fetch the bytes. */
10
- imageUrl: string;
11
- }
12
- /** The off-chain state to bridge to the destination resolver + what couldn't be carried cleanly. */
13
- export interface MigrationPlan {
14
- description?: string;
15
- externalUrl?: string;
16
- attributes?: OpenSeaAttribute[];
17
- /** `{ "0x<keccak>": "https://gw/ipfs/<cid>" }` — durable image locators recovered from the source. */
18
- contentLocators: Record<string, string>;
19
- /** Images served only by the source host (no durable locator) — re-pin before cutover. */
20
- nodeCustody: NodeCustodyImage[];
21
- /** Tokens whose served JSON we read to build this plan. */
22
- tokensRead: number;
23
- }
24
- export declare const tokenApiUrl: (base: string, chainId: number, addr: string, id: string) => string;
25
- export declare const contractApiUrl: (base: string, chainId: number, addr: string) => string;
26
- /**
27
- * Build the migration plan by reading the SOURCE resolver's public API, using the locally
28
- * reconstructed on-chain state (`local`) for the hash KEYS the served JSON doesn't expose.
29
- */
30
- export declare function buildMigrationPlan(sourceBase: string, chainId: number, local: ProjectState): Promise<MigrationPlan>;
31
- /**
32
- * Re-pin node-custody images to a DURABLE backend so the destination never depends on the
33
- * (soon-to-be-decommissioned) source host. For each image: fetch the bytes from the source,
34
- * **verify** them against the on-chain hash (trustless — we trust the chain, not the old node),
35
- * then `put` them to the destination operator's own backend and read back a portable locator.
36
- *
37
- * If the configured backend isn't durable (no `locator` — fs/cloud serve only through their own
38
- * node, so re-pinning there just moves the single-host dependency), we re-pin NOTHING and report
39
- * every image as `needsDurableBackend`: the right move is to configure IPFS/Arweave and re-run,
40
- * never to bridge a URL that points back at the dying host.
41
- */
42
- export interface RepinResult {
43
- /** hash → new durable locator, ready to bridge to the destination. */
44
- repinned: Record<string, string>;
45
- /** Re-pinned token ids (for reporting). */
46
- repinnedTokens: string[];
47
- /** Bytes fetched but their hash didn't match the on-chain commitment — NOT trusted, NOT pinned. */
48
- mismatched: NodeCustodyImage[];
49
- /** Couldn't fetch the bytes from the source (host down, 404). */
50
- unreachable: NodeCustodyImage[];
51
- /** Skipped because no durable backend is configured — these need IPFS/Arweave + a re-run. */
52
- needsDurableBackend: NodeCustodyImage[];
53
- }
54
- export declare function repinNodeCustody(images: NodeCustodyImage[], backend: StorageBackend): Promise<RepinResult>;
55
- /** A parity check after bridging: does the destination now serve the same image/description/traits? */
56
- export interface ParityResult {
57
- tokenId: string;
58
- imageMatch: boolean;
59
- descriptionMatch: boolean;
60
- attributesMatch: boolean;
61
- sourceImage?: string;
62
- destImage?: string;
63
- }
64
- export declare function verifyParity(sourceBase: string, destBase: string, chainId: number, addr: string, tokenId: string): Promise<ParityResult>;
65
- //# sourceMappingURL=migrate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAqB,gBAAgB,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAc,KAAK,cAAc,EAAC,MAAM,wBAAwB,CAAC;AA4BxE;iGACiG;AACjG,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,4GAA4G;IAC5G,IAAI,EAAE,MAAM,CAAC;IACb,qGAAqG;IACrG,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,oGAAoG;AACpG,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAChC,sGAAsG;IACtG,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,0FAA0F;IAC1F,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;CACpB;AAGD,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE,MAAM,MAAM,EAAE,IAAI,MAAM,KAAG,MAC5B,CAAC;AAC3D,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE,MAAM,MAAM,KAAG,MACzB,CAAC;AA+BrD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,aAAa,CAAC,CAsDxB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,2CAA2C;IAC3C,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,mGAAmG;IACnG,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,iEAAiE;IACjE,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,6FAA6F;IAC7F,mBAAmB,EAAE,gBAAgB,EAAE,CAAC;CACzC;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAyChH;AAED,uGAAuG;AACvG,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CAavB"}
package/dist/migrate.js DELETED
@@ -1,180 +0,0 @@
1
- /**
2
- * Migrate a contract's OFF-CHAIN operator state from one resolver to another — the
3
- * toolkit's portability guarantee, made operational.
4
- *
5
- * Everything on-chain a new resolver gets for free: it replays the event spine from any
6
- * RPC (that's what the control plane's `POST /v1/projects` already does). The only
7
- * thing it can't reconstruct from chain is the operator's off-chain state — the four fields
8
- * on the registration row: `description`, `externalUrl`, off-chain `attributes`, and the
9
- * `keccak → gateway-URL` content locators.
10
- *
11
- * The key property: each resolver's served JSON is **self-describing** via `abx_provenance`,
12
- * which makes it self-MIGRATING. By reading the SOURCE resolver's public token/contract API
13
- * (plus the chain, for the locator KEYS — the on-chain hashes, which aren't in any served
14
- * JSON), we reconstruct exactly that off-chain state and bridge it to the destination through
15
- * the same control plane. The two resolvers never talk to each other; the operator's CLI
16
- * orchestrates from public endpoints alone — no shared database, no private channel.
17
- *
18
- * Two cases this can't paper over, both surfaced honestly:
19
- * - **Stitched attributes** — an off-chain trait shadowed by an on-chain one of the same
20
- * `trait_type` was never *served*, so it can't be recovered. We migrate the off-chain
21
- * remainder (served traits whose `trait_type` has no on-chain entry), which is byte-exact
22
- * for everything that was ever visible.
23
- * - **Node-custody images** — an image committed by hash but never pinned to a durable
24
- * backend is served from the source node's own `/image` route. There's no portable URL to
25
- * copy; the bytes live only on the old host. We list these so the operator re-pins them
26
- * (fetch → verify against the on-chain hash → re-upload) BEFORE tearing the old host down.
27
- */
28
- import { fieldOf, inlineText, normalizeAttributes, METADATA_REPRESENTATION as R } from '@artblocks/abx-sdk';
29
- import { hashContent } from '@artblocks/abx-storage';
30
- const trim = (base) => base.replace(/\/+$/, '');
31
- export const tokenApiUrl = (base, chainId, addr, id) => `${trim(base)}/t/${chainId}/${addr.toLowerCase()}/${id}`;
32
- export const contractApiUrl = (base, chainId, addr) => `${trim(base)}/c/${chainId}/${addr.toLowerCase()}`;
33
- async function getJson(url) {
34
- let resp;
35
- try {
36
- resp = await fetch(url);
37
- }
38
- catch (err) {
39
- throw new Error(`couldn't reach the source resolver at ${url}: ${err.message}`);
40
- }
41
- if (resp.status === 404)
42
- return null; // unknown project / unminted token — not fatal per-token
43
- if (!resp.ok)
44
- throw new Error(`source resolver ${url} → ${resp.status} ${resp.statusText}`);
45
- return (await resp.json());
46
- }
47
- const provOf = (json, field) => json?.abx_provenance?.find((p) => p.field === field);
48
- /** Off-chain attribute trait_types present on-chain (case-insensitive) — these are NOT migrated as
49
- * off-chain (the destination re-derives them from chain and they win the stitch). */
50
- function onChainTraitTypes(fields) {
51
- const entry = fieldOf(fields, 'attributes');
52
- if (!entry || entry.representation !== R.inline)
53
- return new Set();
54
- try {
55
- const parsed = JSON.parse(inlineText(entry));
56
- if (!Array.isArray(parsed))
57
- return new Set();
58
- return new Set(parsed.map((a) => String(a.trait_type).toLowerCase()));
59
- }
60
- catch {
61
- return new Set();
62
- }
63
- }
64
- /**
65
- * Build the migration plan by reading the SOURCE resolver's public API, using the locally
66
- * reconstructed on-chain state (`local`) for the hash KEYS the served JSON doesn't expose.
67
- */
68
- export async function buildMigrationPlan(sourceBase, chainId, local) {
69
- const addr = local.address;
70
- const plan = { contentLocators: {}, nodeCustody: [], tokensRead: 0 };
71
- // ── operator-level fields (one registration row applies across the collection) ──
72
- // Prefer the contract API; fall back to token #0. Take a value only when its provenance
73
- // says it's off-chain (a plain operator value) — on-chain values are re-derived by replay.
74
- const contractJson = await getJson(contractApiUrl(sourceBase, chainId, addr));
75
- const firstToken = local.tokens.find((t) => t.minted) ?? local.tokens[0];
76
- const tokenZeroJson = firstToken
77
- ? await getJson(tokenApiUrl(sourceBase, chainId, addr, firstToken.tokenId))
78
- : null;
79
- const offChainText = (json, field, value) => (value != null && provOf(json, field)?.status === 'off-chain' ? value : undefined);
80
- plan.description =
81
- offChainText(tokenZeroJson, 'description', tokenZeroJson?.description) ??
82
- offChainText(contractJson, 'description', contractJson?.description);
83
- plan.externalUrl =
84
- offChainText(tokenZeroJson, 'external_url', tokenZeroJson?.external_url) ??
85
- offChainText(contractJson, 'external_link', contractJson?.external_link);
86
- // attributes: the off-chain remainder = served traits whose trait_type has NO on-chain entry.
87
- if (tokenZeroJson?.attributes?.length && provOf(tokenZeroJson, 'attributes')?.status !== 'on-chain') {
88
- const onChain = onChainTraitTypes(firstToken?.fields ?? []);
89
- const offChain = tokenZeroJson.attributes.filter((a) => !onChain.has(String(a.trait_type).toLowerCase()));
90
- if (offChain.length)
91
- plan.attributes = normalizeAttributes(offChain);
92
- }
93
- // ── per-token content locators (image bytes that live off-chain by hash) ──
94
- for (const token of local.tokens) {
95
- const image = fieldOf(token.fields, 'image');
96
- if (!image || (image.representation !== R.keccak256 && image.representation !== R.sha256)) {
97
- continue; // on-chain content or an on-chain locator — the destination derives it from chain
98
- }
99
- const json = await getJson(tokenApiUrl(sourceBase, chainId, addr, token.tokenId));
100
- if (!json)
101
- continue; // unminted / not served
102
- plan.tokensRead++;
103
- const prov = provOf(json, 'image');
104
- const hash = image.value.toLowerCase();
105
- // A durable locator: the resolver served a portable URL (ipfs/arweave/url source). Node-custody:
106
- // the source served the bytes from its own host (source === the hash kind), so there's nothing to copy.
107
- if (json.image && prov && prov.onChain === false && (prov.source === 'ipfs' || prov.source === 'arweave' || prov.source === 'url')) {
108
- plan.contentLocators[hash] = json.image;
109
- }
110
- else if (json.image) {
111
- plan.nodeCustody.push({ tokenId: token.tokenId, hash, imageUrl: json.image });
112
- }
113
- }
114
- return plan;
115
- }
116
- export async function repinNodeCustody(images, backend) {
117
- const result = { repinned: {}, repinnedTokens: [], mismatched: [], unreachable: [], needsDurableBackend: [] };
118
- if (!images.length)
119
- return result;
120
- // A backend is "durable" for migration iff it can hand back a node-independent locator.
121
- if (!backend.locator) {
122
- result.needsDurableBackend = [...images];
123
- return result;
124
- }
125
- for (const img of images) {
126
- let bytes;
127
- let contentType;
128
- try {
129
- const resp = await fetch(img.imageUrl);
130
- if (!resp.ok) {
131
- result.unreachable.push(img);
132
- continue;
133
- }
134
- bytes = new Uint8Array(await resp.arrayBuffer());
135
- contentType = resp.headers.get('content-type') ?? 'application/octet-stream';
136
- }
137
- catch {
138
- result.unreachable.push(img);
139
- continue;
140
- }
141
- // Trustless: re-hash the fetched bytes and compare to the ON-CHAIN commitment.
142
- if (hashContent(bytes).toLowerCase() !== img.hash.toLowerCase()) {
143
- result.mismatched.push(img);
144
- continue;
145
- }
146
- await backend.put(img.hash, { bytes, contentType });
147
- const loc = await backend.locator(img.hash);
148
- if (loc) {
149
- result.repinned[img.hash.toLowerCase()] = loc;
150
- result.repinnedTokens.push(img.tokenId);
151
- }
152
- else {
153
- // Stored, but the backend still can't produce a portable locator — treat as not durable.
154
- result.needsDurableBackend.push(img);
155
- }
156
- }
157
- return result;
158
- }
159
- const sameAttrs = (a = [], b = []) => {
160
- const key = (xs) => xs
161
- .map((x) => `${String(x.trait_type).toLowerCase()}=${String(x.value)}`)
162
- .sort()
163
- .join('|');
164
- return key(a) === key(b);
165
- };
166
- export async function verifyParity(sourceBase, destBase, chainId, addr, tokenId) {
167
- const [src, dst] = await Promise.all([
168
- getJson(tokenApiUrl(sourceBase, chainId, addr, tokenId)),
169
- getJson(tokenApiUrl(destBase, chainId, addr, tokenId)),
170
- ]);
171
- return {
172
- tokenId,
173
- imageMatch: !!src && !!dst && src.image === dst.image,
174
- descriptionMatch: (src?.description ?? null) === (dst?.description ?? null),
175
- attributesMatch: sameAttrs(src?.attributes, dst?.attributes),
176
- sourceImage: src?.image,
177
- destImage: dst?.image,
178
- };
179
- }
180
- //# sourceMappingURL=migrate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}