@artblocks/abx-cli 0.1.0-alpha.10 → 0.1.0-alpha.11
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/main.js +107 -1
- package/dist/main.js.map +1 -1
- package/package.json +6 -6
- package/skill/SKILL.md +2 -1
- package/skill/reference/hosting.md +2 -0
- package/skill/reference/troubleshooting.md +1 -1
package/dist/main.js
CHANGED
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
* abx remote [<name|url>] inspect a remote service (descriptor · chains · managed rendering · your projects there)
|
|
22
22
|
* abx index [<address>] re-index a project from chain (replay; --remote to nudge a remote resolver)
|
|
23
23
|
* abx verify <address> re-hash served bytes vs the on-chain commitment (no server)
|
|
24
|
+
* abx tokenuri <address> read tokenURI(id) from the contract + decode · contracturi: the ERC-7572 collection JSON
|
|
25
|
+
* (the contract holds the URL — never hand-build a resolver path)
|
|
24
26
|
* abx configure-param <addr> <id> <key> <value> set a governed PostParam (typed encode; any lane)
|
|
25
27
|
* abx set-param-hooks <addr> wire/clear a SeriesCode's configure/augment/transfer param hooks
|
|
26
28
|
* abx render <addr> [id…] effect-runner repair lane: render missing stills/traits
|
|
@@ -177,6 +179,7 @@ async function main() {
|
|
|
177
179
|
case 'render': return cmdRender(rest[0], rest.slice(1), flags);
|
|
178
180
|
case 'effects': return cmdEffects(flags);
|
|
179
181
|
case 'tokenuri': return cmdTokenUri(rest[0], flags);
|
|
182
|
+
case 'contracturi': return cmdContractUri(rest[0], flags);
|
|
180
183
|
case 'serve': return cmdServe(flags);
|
|
181
184
|
// owner operations — write + sign (hot/wallet/cold lane), then re-index
|
|
182
185
|
case 'mint': return cmdMint(rest[0], flags);
|
|
@@ -4397,6 +4400,101 @@ async function cmdTokenUri(address, flags) {
|
|
|
4397
4400
|
console.log(` ${uri.slice(0, 240)}${uri.length > 240 ? dim(`… (${uri.length} chars)`) : ''}\n`);
|
|
4398
4401
|
}
|
|
4399
4402
|
}
|
|
4403
|
+
// ── contracturi ──────────────────────────────────────────────────────────────
|
|
4404
|
+
/**
|
|
4405
|
+
* `abx contracturi <address>` — the collection-level counterpart of `tokenuri`: read
|
|
4406
|
+
* `contractURI()` (ERC-7572) STRAIGHT FROM THE CONTRACT, then FOLLOW it and decode the JSON.
|
|
4407
|
+
*
|
|
4408
|
+
* Why this exists, and why it follows the URL: the resolver's route grammar is committed
|
|
4409
|
+
* on-chain at deploy (`contractURIBase` = `<baseUrl>/c`), so the contract — not a doc, not a
|
|
4410
|
+
* service descriptor — is the source of truth for where a collection's metadata lives. Without
|
|
4411
|
+
* this command the only way to look was to hand-build the URL from memory of the grammar, and a
|
|
4412
|
+
* guessed path that 404s reads exactly like a broken service. Ask the chain instead.
|
|
4413
|
+
*/
|
|
4414
|
+
async function cmdContractUri(address, _flags) {
|
|
4415
|
+
if (!address || address.startsWith('--')) {
|
|
4416
|
+
console.error('usage: abx contracturi <address>\n');
|
|
4417
|
+
process.exit(1);
|
|
4418
|
+
}
|
|
4419
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
|
|
4420
|
+
console.error(`abx contracturi: '${address}' isn't a 0x contract address.\n`);
|
|
4421
|
+
process.exit(1);
|
|
4422
|
+
}
|
|
4423
|
+
const publicClient = makePublicClient({ chainKey: CHAIN });
|
|
4424
|
+
let uri;
|
|
4425
|
+
try {
|
|
4426
|
+
uri = (await publicClient.readContract({
|
|
4427
|
+
address,
|
|
4428
|
+
abi: oneOfOneImageAbi,
|
|
4429
|
+
functionName: 'contractURI',
|
|
4430
|
+
args: [],
|
|
4431
|
+
}));
|
|
4432
|
+
}
|
|
4433
|
+
catch {
|
|
4434
|
+
const code = await publicClient.getCode({ address }).catch(() => undefined);
|
|
4435
|
+
if (!code || code === '0x') {
|
|
4436
|
+
// Name the endpoint we actually asked — "no contract here" and "you're pointed at the wrong
|
|
4437
|
+
// node" are indistinguishable otherwise (same reasoning as `tokenuri`).
|
|
4438
|
+
console.error(`abx contracturi: no contract at ${address} on ${CHAIN} (asked ${redactRpcUrl(resolveRpcUrl(CHAIN))}) — ` +
|
|
4439
|
+
`double-check the address, and that this endpoint is the network you deployed to. ` +
|
|
4440
|
+
`If you JUST deployed, give the tx a block or two to mine.\n`);
|
|
4441
|
+
}
|
|
4442
|
+
else {
|
|
4443
|
+
console.error(`abx contracturi: ${address} didn't return a contractURI — it may not be an ABX/ERC-7572 contract, or ` +
|
|
4444
|
+
`— on a large on-chain contractURI — an unauthenticated RPC read hit its gas cap (try a wallet-connected / high-gas RPC).\n`);
|
|
4445
|
+
}
|
|
4446
|
+
process.exit(1);
|
|
4447
|
+
}
|
|
4448
|
+
console.log(`\n ${bold('contractURI()')} ${dim(`— read directly from ${address} on ${CHAIN}`)}`);
|
|
4449
|
+
if (!uri) {
|
|
4450
|
+
console.error(`\n ${bold('empty')} — this contract has no contractURI set: no collection-level metadata to resolve. ` +
|
|
4451
|
+
`Set one with ${bold(`abx set-contract-uri ${address} --uri <base>`)}, or point it at the canonical renderer for the on-chain lane.\n`);
|
|
4452
|
+
process.exit(1);
|
|
4453
|
+
}
|
|
4454
|
+
const onChain = decodeOnChainJson(uri);
|
|
4455
|
+
if (onChain) {
|
|
4456
|
+
info('resolution: ON-CHAIN (data: URI from the renderer — no server in the path)');
|
|
4457
|
+
console.log(onChain.split('\n').map((l) => ' ' + l).join('\n') + '\n');
|
|
4458
|
+
return;
|
|
4459
|
+
}
|
|
4460
|
+
console.log(` ${dim('resolves to')} ${uri}`);
|
|
4461
|
+
if (!/^https?:\/\//i.test(uri)) {
|
|
4462
|
+
// ipfs:// / ar:// — a locator, not something we can fetch without choosing a gateway. Print it
|
|
4463
|
+
// rather than silently picking one; the creator's gateway choice is theirs.
|
|
4464
|
+
info(`not an http(s) URL — a ${uri.split(':')[0]}: locator needs a gateway to fetch. Nothing more to read from here.`);
|
|
4465
|
+
console.log('');
|
|
4466
|
+
return;
|
|
4467
|
+
}
|
|
4468
|
+
let body;
|
|
4469
|
+
try {
|
|
4470
|
+
const res = await fetch(uri, { headers: { accept: 'application/json' } });
|
|
4471
|
+
body = await res.text();
|
|
4472
|
+
if (!res.ok) {
|
|
4473
|
+
// The URL came FROM THE CHAIN, so a bad status here is genuinely about the service (or the
|
|
4474
|
+
// contract pointing somewhere stale) — never a mistyped path. Say which, so nobody re-guesses.
|
|
4475
|
+
console.error(`\n ${bold(`HTTP ${res.status}`)} from the contract's own contractURI — the URL is correct by construction (it came from ` +
|
|
4476
|
+
`${address} on-chain), so this is the SERVICE, not the path. Likely: the project isn't registered on that resolver ` +
|
|
4477
|
+
`(${bold('abx add ' + address + ' --remote')}), the node serves a different chain, or it's down. ` +
|
|
4478
|
+
`Response: ${body.slice(0, 200)}\n`);
|
|
4479
|
+
process.exit(1);
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4482
|
+
catch (e) {
|
|
4483
|
+
console.error(`\n couldn't reach ${uri} — ${e.message}. The URL is what the contract commits to, so check that the ` +
|
|
4484
|
+
`host is up and publicly reachable (a localhost base URL resolves for no one but this machine).\n`);
|
|
4485
|
+
process.exit(1);
|
|
4486
|
+
}
|
|
4487
|
+
info('resolution: OFF-CHAIN (fetched from the URL the contract commits to)');
|
|
4488
|
+
try {
|
|
4489
|
+
console.log(JSON.stringify(JSON.parse(body), null, 2)
|
|
4490
|
+
.split('\n')
|
|
4491
|
+
.map((l) => ' ' + l)
|
|
4492
|
+
.join('\n') + '\n');
|
|
4493
|
+
}
|
|
4494
|
+
catch {
|
|
4495
|
+
console.log(` ${dim('(not JSON)')} ${body.slice(0, 400)}\n`);
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4400
4498
|
// ── serve ──────────────────────────────────────────────────────────────────--
|
|
4401
4499
|
async function cmdServe(flags) {
|
|
4402
4500
|
const port = Number(flags.port ?? process.env.ABX_PORT ?? DEFAULT_PORT);
|
|
@@ -5951,7 +6049,14 @@ const COMMAND_HELP = {
|
|
|
5951
6049
|
${dim(`${g('onChainStatus')} (branch · chain-complete · unresolved refs · URL budget) and decodes ${g('tokenURI')} straight from the contract.`)}`,
|
|
5952
6050
|
tokenuri: `
|
|
5953
6051
|
${bold('abx tokenuri')} <address> [--token <id>] ${dim('— read tokenURI(id) straight from the contract on-chain + decode the JSON (read-only; no server).')}
|
|
5954
|
-
${dim('The proof a fully on-chain token self-resolves: any RPC returns the renderer-assembled metadata. Default token 0.')}
|
|
6052
|
+
${dim('The proof a fully on-chain token self-resolves: any RPC returns the renderer-assembled metadata. Default token 0.')}
|
|
6053
|
+
${dim('Collection-level (ERC-7572) counterpart:')} ${g('abx contracturi <address>')}`,
|
|
6054
|
+
contracturi: `
|
|
6055
|
+
${bold('abx contracturi')} <address> ${dim('— read contractURI() (ERC-7572 collection metadata) from the contract, FOLLOW it, and decode (read-only).')}
|
|
6056
|
+
${dim('The collection-level counterpart of')} ${g('tokenuri')}${dim('. On-chain lane: decodes the data: URI. Off-chain lane: fetches the')}
|
|
6057
|
+
${dim('URL the contract itself commits to and prints the JSON.')}
|
|
6058
|
+
${bold('Never hand-build a resolver URL to check this')} ${dim('— the contract holds the answer, so a URL from here is right by')}
|
|
6059
|
+
${dim('construction. A bad status is then about the SERVICE (unregistered project · wrong chain · down), never a mistyped path.')}`,
|
|
5955
6060
|
forget: `
|
|
5956
6061
|
${bold('abx forget')} <address> ${dim('— drop a project’s local registration + projection. On-chain data is untouched.')}
|
|
5957
6062
|
${g('--remote [name|url]')} deregister on a REMOTE resolver instead (it stops serving the project; re-add any time)`,
|
|
@@ -6022,6 +6127,7 @@ function help() {
|
|
|
6022
6127
|
${g('abx index')} [<address>] re-index from chain (incremental by default; ${g('--full')} forces a replay from deploy)
|
|
6023
6128
|
${g('abx verify')} <addr> re-hash served bytes vs the on-chain commitment (no server needed)
|
|
6024
6129
|
${g('abx tokenuri')} <addr> read tokenURI(0) on-chain + decode the JSON (proof a self-resolving token works)
|
|
6130
|
+
${g('abx contracturi')} <addr> read contractURI() (ERC-7572 collection metadata) on-chain, follow it, decode — never hand-build the URL
|
|
6025
6131
|
${g('abx state')} <addr> one-glance on-chain snapshot: owner · supply · paused · minter · payee · royalty · renderer
|
|
6026
6132
|
${g('abx serve')} [--port ..] serve the token API + dashboard — and WATCH the chain: auto-index every registered
|
|
6027
6133
|
project + notify the effects layer on change (${g('ABX_WATCH_INTERVAL_MS')}; 0 = off)
|