@artblocks/abx-cli 0.1.0-alpha.4 → 0.1.0-alpha.41
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/CHANGELOG.md +161 -0
- package/assets/renderer-scaffold/README.md +41 -11
- package/assets/renderer-scaffold/foundry.toml +5 -0
- package/assets/renderer-scaffold/remappings.txt +1 -1
- package/assets/renderer-scaffold/script/DeployHooks.s.sol +24 -0
- package/assets/renderer-scaffold/script/Preview.s.sol +99 -0
- package/assets/renderer-scaffold/src/MyHooks.sol +20 -0
- package/assets/renderer-scaffold/src/MyRenderer.sol +4 -4
- package/assets/renderer-scaffold/src/MyTraits.sol +2 -2
- package/assets/renderer-scaffold/test/MyRenderer.t.sol +60 -3
- package/dist/bin.d.ts +26 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +63 -0
- package/dist/bin.js.map +1 -0
- package/dist/capabilities.d.ts +99 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +144 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/commands/auth.d.ts +54 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +447 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/deploy.d.ts +242 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +5429 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/feedback.d.ts +7 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +147 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/maintenance.d.ts +4 -0
- package/dist/commands/maintenance.d.ts.map +1 -0
- package/dist/commands/maintenance.js +114 -0
- package/dist/commands/maintenance.js.map +1 -0
- package/dist/commands/project.d.ts +429 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +1720 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/reads.d.ts +85 -0
- package/dist/commands/reads.d.ts.map +1 -0
- package/dist/commands/reads.js +868 -0
- package/dist/commands/reads.js.map +1 -0
- package/dist/commands/scaffold.d.ts +89 -0
- package/dist/commands/scaffold.d.ts.map +1 -0
- package/dist/commands/scaffold.js +738 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/commands/service.d.ts +67 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +748 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/storage.d.ts +51 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +399 -0
- package/dist/commands/storage.js.map +1 -0
- package/dist/commands/submit-app.d.ts +102 -0
- package/dist/commands/submit-app.d.ts.map +1 -0
- package/dist/commands/submit-app.js +622 -0
- package/dist/commands/submit-app.js.map +1 -0
- package/dist/config.d.ts +105 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +351 -12
- package/dist/config.js.map +1 -1
- package/dist/conformance.d.ts +31 -0
- package/dist/conformance.d.ts.map +1 -0
- package/dist/conformance.js +390 -0
- package/dist/conformance.js.map +1 -0
- package/dist/contract-read-error.d.ts +5 -0
- package/dist/contract-read-error.d.ts.map +1 -0
- package/dist/contract-read-error.js +37 -0
- package/dist/contract-read-error.js.map +1 -0
- package/dist/deploy-plan.d.ts +150 -0
- package/dist/deploy-plan.d.ts.map +1 -0
- package/dist/deploy-plan.js +31 -0
- package/dist/deploy-plan.js.map +1 -0
- package/dist/deps.d.ts +6 -39
- package/dist/deps.d.ts.map +1 -1
- package/dist/deps.js +4 -68
- package/dist/deps.js.map +1 -1
- package/dist/errors.d.ts +20 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/flag-allowlists.d.ts +53 -0
- package/dist/flag-allowlists.d.ts.map +1 -0
- package/dist/flag-allowlists.js +184 -0
- package/dist/flag-allowlists.js.map +1 -0
- package/dist/flags.d.ts +47 -0
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +125 -1
- package/dist/flags.js.map +1 -1
- package/dist/jsonout.d.ts +37 -0
- package/dist/jsonout.d.ts.map +1 -0
- package/dist/jsonout.js +79 -0
- package/dist/jsonout.js.map +1 -0
- package/dist/kind.d.ts +57 -0
- package/dist/kind.d.ts.map +1 -0
- package/dist/kind.js +122 -0
- package/dist/kind.js.map +1 -0
- package/dist/main.js +786 -4838
- package/dist/main.js.map +1 -1
- package/dist/mintpage.d.ts +17 -2
- package/dist/mintpage.d.ts.map +1 -1
- package/dist/mintpage.js +241 -54
- package/dist/mintpage.js.map +1 -1
- package/dist/output.d.ts +179 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +780 -0
- package/dist/output.js.map +1 -0
- package/dist/ownerops.d.ts +381 -57
- package/dist/ownerops.d.ts.map +1 -1
- package/dist/ownerops.js +2014 -359
- package/dist/ownerops.js.map +1 -1
- package/dist/preview.d.ts +23 -5
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +95 -43
- package/dist/preview.js.map +1 -1
- package/dist/prompt.d.ts +17 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +19 -0
- package/dist/prompt.js.map +1 -0
- package/dist/provision.d.ts +3 -13
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +19 -21
- package/dist/provision.js.map +1 -1
- package/dist/remote.d.ts +157 -52
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +435 -46
- package/dist/remote.js.map +1 -1
- package/dist/riskgate.d.ts +62 -0
- package/dist/riskgate.d.ts.map +1 -0
- package/dist/riskgate.js +234 -0
- package/dist/riskgate.js.map +1 -0
- package/dist/scaffold.d.ts +12 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +56 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/schema.d.ts +36 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +121 -26
- package/dist/schema.js.map +1 -1
- package/dist/script-chunks.d.ts +8 -0
- package/dist/script-chunks.d.ts.map +1 -0
- package/dist/script-chunks.js +35 -0
- package/dist/script-chunks.js.map +1 -0
- package/dist/served.d.ts +30 -0
- package/dist/served.d.ts.map +1 -0
- package/dist/served.js +112 -0
- package/dist/served.js.map +1 -0
- package/dist/signer.d.ts +13 -0
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +84 -15
- package/dist/signer.js.map +1 -1
- package/dist/update-check.d.ts +86 -5
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +161 -20
- package/dist/update-check.js.map +1 -1
- package/package.json +13 -12
- package/skill/SKILL.md +181 -347
- package/skill/agents/openai.yaml +4 -0
- package/skill/reference/capabilities.md +188 -0
- package/skill/reference/code.md +220 -0
- package/skill/reference/creator-token.md +94 -0
- package/skill/reference/deploy.md +174 -0
- package/skill/reference/diagnose.md +178 -0
- package/skill/reference/hosting.md +186 -93
- package/skill/reference/operate.md +220 -0
- package/skill/reference/services.md +121 -0
- package/skill/reference/setup.md +154 -36
- package/assets/renderer-scaffold/src/interfaces/IAbxFieldRenderer.sol +0 -32
- package/assets/renderer-scaffold/src/interfaces/IAbxParams.sol +0 -26
- package/dist/inspect.d.ts +0 -48
- package/dist/inspect.d.ts.map +0 -1
- package/dist/inspect.js +0 -184
- package/dist/inspect.js.map +0 -1
- package/dist/migrate.d.ts +0 -65
- package/dist/migrate.d.ts.map +0 -1
- package/dist/migrate.js +0 -180
- package/dist/migrate.js.map +0 -1
- package/dist/onchain-uri.d.ts +0 -97
- package/dist/onchain-uri.d.ts.map +0 -1
- package/dist/onchain-uri.js +0 -243
- package/dist/onchain-uri.js.map +0 -1
- package/dist/upload.d.ts +0 -28
- package/dist/upload.d.ts.map +0 -1
- package/dist/upload.js +0 -41
- package/dist/upload.js.map +0 -1
- package/skill/reference/code-projects.md +0 -246
- package/skill/reference/operating.md +0 -116
- package/skill/reference/troubleshooting.md +0 -28
package/dist/flags.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
+
import { bold, info, warn } from './output.js';
|
|
1
2
|
/** Flags where every occurrence counts (values comma-join, in argv order). */
|
|
2
|
-
export const REPEATABLE_FLAGS = new Set(['dep', 'schema']);
|
|
3
|
+
export const REPEATABLE_FLAGS = new Set(['dep', 'schema', 'param']);
|
|
3
4
|
/**
|
|
4
5
|
* Flags valid on ANY command (handled centrally in main, not by a command handler), so
|
|
5
6
|
* {@link unknownFlags} never flags them as unrecognized regardless of the per-command allowlist.
|
|
6
7
|
* `no-update-check` opts out of the startup update nudge (see update-check.ts).
|
|
7
8
|
*/
|
|
8
9
|
export const GLOBAL_FLAGS = new Set(['no-update-check']);
|
|
10
|
+
/** Whether `--dry-run` was passed. The one place that truthiness is decided — every write command
|
|
11
|
+
* (owner-op or deploy) reads it through here rather than hand-rolling `!!flags['dry-run']`, so a
|
|
12
|
+
* fresh command can't ship with a *slightly* different spelling of the same check (or skip it). */
|
|
13
|
+
export function isDryRun(flags) {
|
|
14
|
+
return !!flags['dry-run'];
|
|
15
|
+
}
|
|
9
16
|
export function parseFlags(args) {
|
|
10
17
|
const out = {};
|
|
11
18
|
const set = (k, v) => {
|
|
@@ -25,6 +32,25 @@ export function parseFlags(args) {
|
|
|
25
32
|
}
|
|
26
33
|
return out;
|
|
27
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* The bare (non-flag) arguments, with flag VALUES removed — the mirror of {@link parseFlags}, and
|
|
37
|
+
* deliberately next to it: the two must consume argv by the same rule or a flag's value looks like a
|
|
38
|
+
* positional. (Hand-rolling `args.filter(a => !a.startsWith('-'))` reads `--token 0` as a stray
|
|
39
|
+
* positional `0`, which is exactly the bug a stray-positional check is meant to catch.)
|
|
40
|
+
*/
|
|
41
|
+
export function positionalArgs(args) {
|
|
42
|
+
const out = [];
|
|
43
|
+
for (let i = 0; i < args.length; i++) {
|
|
44
|
+
const a = args[i];
|
|
45
|
+
if (a.startsWith('--')) {
|
|
46
|
+
if (a.indexOf('=') === -1 && args[i + 1] && !args[i + 1].startsWith('--'))
|
|
47
|
+
i++; // this flag consumes the next token
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
out.push(a);
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
28
54
|
/**
|
|
29
55
|
* The flag keys in `flags` that are NOT in `allowed` — for a non-fatal "unrecognized flag"
|
|
30
56
|
* notice at a command's entry. {@link parseFlags} keeps any `--k` it sees, so a typo'd or
|
|
@@ -37,4 +63,102 @@ export function unknownFlags(flags, allowed) {
|
|
|
37
63
|
const ok = new Set(allowed);
|
|
38
64
|
return Object.keys(flags).filter((k) => !ok.has(k) && !GLOBAL_FLAGS.has(k));
|
|
39
65
|
}
|
|
66
|
+
/** Warn (never throw) on a flag the command doesn't recognize — a typo'd or unsupported flag
|
|
67
|
+
* otherwise no-ops INVISIBLY (the worst failure mode for a write-adjacent value like a mistyped
|
|
68
|
+
* --royalty-bps). Non-fatal, per the owner's scriptability line ([[cli-ux-decisions]]). */
|
|
69
|
+
// Targeted "did you mean" hints for the flags creators most often invent (seen across agent sessions).
|
|
70
|
+
// A stray flag is otherwise silently ignored, so a wrong-but-plausible one (a price/supply flag that
|
|
71
|
+
// doesn't exist) reads as "it worked." Command-aware so a flag valid elsewhere isn't mis-hinted.
|
|
72
|
+
export const FLAG_HINTS = {
|
|
73
|
+
count: (cmd) => (cmd === 'deploy-code' ? 'did you mean --max <N> (the supply cap)?' : undefined),
|
|
74
|
+
price: () => 'a sale price is NOT set at deploy — configure it after with `abx minter configure <addr> --price <eth>`.',
|
|
75
|
+
supply: () => 'did you mean --max <N> (the supply cap)?',
|
|
76
|
+
amount: () => 'a sale price/amount is set post-deploy via `abx minter configure`.',
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Unknown flags on a command that can SEND: refuse, don't warn.
|
|
80
|
+
*
|
|
81
|
+
* This used to warn and carry on, and `--chain sepolia` proved why that isn't enough — the warning was
|
|
82
|
+
* accurate, it scrolled past, and the deploy ran on the DEFAULT chain. On a dry run that costs a
|
|
83
|
+
* confused minute; on a funded send it is a wrong-chain deploy. "Prose that was ignored once will be
|
|
84
|
+
* ignored again" is the standing rule here, so the tx-sending commands stop instead.
|
|
85
|
+
*
|
|
86
|
+
* Safe to refuse rather than warn because a flag absent from the allowlist is, by construction, one
|
|
87
|
+
* the command never reads — verified per command by comparing every `flags.x` read in its body against
|
|
88
|
+
* its allowlist. So refusal cannot break a working flag; it only makes an already-ignored one loud.
|
|
89
|
+
*
|
|
90
|
+
* `--dry-run` refuses identically. A preview that accepts what the real send rejects is its own trap:
|
|
91
|
+
* you'd validate a command in preview and have it fail at the moment it matters.
|
|
92
|
+
*/
|
|
93
|
+
export function refuseStrayFlags(flags, allowed, cmd) {
|
|
94
|
+
const stray = unknownFlags(flags, allowed);
|
|
95
|
+
if (!stray.length)
|
|
96
|
+
return;
|
|
97
|
+
const hints = stray.map((f) => FLAG_HINTS[f]?.(cmd)).filter(Boolean);
|
|
98
|
+
throw new Error(`unrecognized flag(s): ${stray.map((f) => '--' + f).join(', ')} — this command would have ignored them silently, so it is refusing instead.\n` +
|
|
99
|
+
hints.map((h, i) => ` ↳ --${stray[i]}: ${h}`).join('\n') +
|
|
100
|
+
(hints.length ? '\n' : '') +
|
|
101
|
+
` see \`abx help ${cmd}\` for the flags it accepts.`);
|
|
102
|
+
}
|
|
103
|
+
/** Unknown flags on a READ-ONLY command: warn, don't refuse. Nothing can be mis-sent, and a stray
|
|
104
|
+
* flag on `preview`/`inspect` shouldn't stop a creator mid-iteration. */
|
|
105
|
+
export function warnStrayFlags(flags, allowed, cmd) {
|
|
106
|
+
const stray = unknownFlags(flags, allowed);
|
|
107
|
+
if (stray.length) {
|
|
108
|
+
warn(`unrecognized flag(s), ignored: ${stray.map((f) => bold('--' + f)).join(', ')} — see \`abx help ${cmd}\`. (A misspelled or unsupported flag silently does nothing.)`);
|
|
109
|
+
for (const f of stray) {
|
|
110
|
+
const hint = FLAG_HINTS[f]?.(cmd);
|
|
111
|
+
if (hint)
|
|
112
|
+
info(` ↳ --${f}: ${hint}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** The wallet-lane owner-pinning guard: on `--sign` with no `--for`, whichever wallet connects
|
|
117
|
+
* becomes owner + royalty receiver + mint recipient (the launch-readiness "random wallet owns the
|
|
118
|
+
* collection" trap). Fires uniformly on deploy / deploy-series / deploy-code. */
|
|
119
|
+
export function warnSignWithoutFor(flags) {
|
|
120
|
+
if (flags.sign !== undefined && !flags.for) {
|
|
121
|
+
warn(`--sign without --for: whichever wallet connects becomes ${bold('owner + royalty receiver + mint recipient')}. Pass ${bold('--for <your address>')} to PIN it — the sign page then refuses a mismatched wallet (the intended safety on the wallet lane).`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** Validate `--to-block` for the index lane: only the two REORG-SAFE tags, never a raw block number.
|
|
125
|
+
* A number is deliberately refused — `abx index` is incremental and picks its own scan window, so a
|
|
126
|
+
* hand-pinned height would silently freeze the watermark somewhere the next run can't reason about;
|
|
127
|
+
* the tags are the only values that stay meaningful across runs. Undefined when absent. */
|
|
128
|
+
export function parseBlockTagFlag(raw) {
|
|
129
|
+
if (raw === undefined || raw === 'true')
|
|
130
|
+
return undefined;
|
|
131
|
+
if (raw !== 'safe' && raw !== 'finalized') {
|
|
132
|
+
throw new Error(`--to-block takes 'safe' or 'finalized' (got '${raw}'). These stop the scan at a boundary the chain won't ` +
|
|
133
|
+
`reorg away; omit the flag for the default 'latest' head. A raw block number isn't accepted here — ` +
|
|
134
|
+
`use the SDK's reconstruct options if you need to pin an exact height.`);
|
|
135
|
+
}
|
|
136
|
+
return raw;
|
|
137
|
+
}
|
|
138
|
+
/** Validate an explicit --salt (a 32-byte hex). Undefined when absent. */
|
|
139
|
+
export function parseSaltFlag(raw) {
|
|
140
|
+
if (!raw || raw === 'true')
|
|
141
|
+
return undefined;
|
|
142
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(raw)) {
|
|
143
|
+
throw new Error(`--salt must be a 32-byte hex (0x + 64 hex chars); got '${raw}'`);
|
|
144
|
+
}
|
|
145
|
+
// Warn here, at the one place every command parses the flag, rather than at the five places a
|
|
146
|
+
// deploy derives an address from it.
|
|
147
|
+
//
|
|
148
|
+
// The factory reads a salt's leading 20 bytes as an access guard: the caller's own address means
|
|
149
|
+
// only that signer may deploy with it; all-zero means anyone may. Omitting --salt gives you the
|
|
150
|
+
// former. Only `abx predict` ever explained this, while the deploy commands took an explicit
|
|
151
|
+
// --salt verbatim and said nothing — so a creator pinning a vanity salt with a zero prefix and
|
|
152
|
+
// announcing the predicted address was handing it to whoever deployed there first, and the
|
|
153
|
+
// front-runner becomes `owner()` (ownership is set by `initialize`, not by the prediction).
|
|
154
|
+
// Warn rather than refuse: a zero prefix is the
|
|
155
|
+
// correct choice for a deliberately shared, caller-independent deployment.
|
|
156
|
+
if (/^0{40}$/.test(raw.slice(2, 42))) {
|
|
157
|
+
warn('--salt has an all-zero guard prefix, so ANYONE may deploy to the address it predicts. ' +
|
|
158
|
+
'Publish that address before you deploy and someone else can take it — and own it. ' +
|
|
159
|
+
'Drop --salt for a salt pinned to your signer, or keep this only if a shared, ' +
|
|
160
|
+
'caller-independent address is the point.');
|
|
161
|
+
}
|
|
162
|
+
return raw;
|
|
163
|
+
}
|
|
40
164
|
//# sourceMappingURL=flags.js.map
|
package/dist/flags.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAaA,8EAA8E;AAC9E,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Flags } from './flags.js';
|
|
2
|
+
/**
|
|
3
|
+
* `--json`: make **stdout a machine channel**.
|
|
4
|
+
*
|
|
5
|
+
* The rule this enforces, from an integrator who drove the CLI from a server: *a value a program
|
|
6
|
+
* needs must be obtainable without parsing prose.* They had to regex-scrape ANSI-coloured stdout for
|
|
7
|
+
* every value — and an escape code ended up inside a locator, was written into a stored player URL,
|
|
8
|
+
* and 404'd in production. The cause was found only by inspecting stored bytes.
|
|
9
|
+
*
|
|
10
|
+
* So under `--json`, stdout carries exactly one JSON document and nothing else. Every narration line
|
|
11
|
+
* the command would print for a human goes to **stderr** instead — not suppressed, because a human
|
|
12
|
+
* watching a deploy still wants to see it, and a program redirecting stdout still gets a clean parse.
|
|
13
|
+
* The update-check already wrote to stderr for precisely this reason; this carries that instinct
|
|
14
|
+
* through to the values themselves.
|
|
15
|
+
*
|
|
16
|
+
* It works by swapping `console.log` for the duration rather than threading a `quiet` flag through
|
|
17
|
+
* every command body. That is deliberate: the alternative is touching dozens of call sites, where the
|
|
18
|
+
* one that gets missed is a stray line that corrupts a parse — the exact failure mode being fixed.
|
|
19
|
+
* `console.error`/`console.warn` are untouched (already stderr), and the payload is written through a
|
|
20
|
+
* captured reference to the real `console.log`, so nothing can intercept it back.
|
|
21
|
+
*/
|
|
22
|
+
export declare function jsonMode(flags: Flags): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Run `body` and, under `--json`, print whatever it returns as the sole contents of stdout.
|
|
25
|
+
*
|
|
26
|
+
* `body` receives an `emit` it may call to contribute the payload incrementally — for a command that
|
|
27
|
+
* discovers its value midway (a deploy learning its address) and would otherwise have to restructure
|
|
28
|
+
* to return it at the end. The last `emit` wins; a returned value overrides both.
|
|
29
|
+
*
|
|
30
|
+
* Without `--json` this is a plain pass-through: zero behaviour change on the human path.
|
|
31
|
+
*/
|
|
32
|
+
export declare function withJson<T extends Record<string, unknown>>(flags: Flags, body: (emit: (payload: T) => void) => Promise<T | void>): Promise<void>;
|
|
33
|
+
/** BigInt-safe JSON: bigints become decimal strings rather than throwing. Every on-chain number a
|
|
34
|
+
* payload carries (supply, a token id, a block) arrives as a bigint, and `JSON.stringify` refuses
|
|
35
|
+
* them outright — so a payload builder that forgets one would fail at the last line of a deploy. */
|
|
36
|
+
export declare function jsonSafe<T>(value: T): T;
|
|
37
|
+
//# sourceMappingURL=jsonout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonout.d.ts","sourceRoot":"","sources":["../src/jsonout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE9C;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GACtD,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED;;qGAEqG;AACrG,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAEvC"}
|
package/dist/jsonout.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `--json`: make **stdout a machine channel**.
|
|
3
|
+
*
|
|
4
|
+
* The rule this enforces, from an integrator who drove the CLI from a server: *a value a program
|
|
5
|
+
* needs must be obtainable without parsing prose.* They had to regex-scrape ANSI-coloured stdout for
|
|
6
|
+
* every value — and an escape code ended up inside a locator, was written into a stored player URL,
|
|
7
|
+
* and 404'd in production. The cause was found only by inspecting stored bytes.
|
|
8
|
+
*
|
|
9
|
+
* So under `--json`, stdout carries exactly one JSON document and nothing else. Every narration line
|
|
10
|
+
* the command would print for a human goes to **stderr** instead — not suppressed, because a human
|
|
11
|
+
* watching a deploy still wants to see it, and a program redirecting stdout still gets a clean parse.
|
|
12
|
+
* The update-check already wrote to stderr for precisely this reason; this carries that instinct
|
|
13
|
+
* through to the values themselves.
|
|
14
|
+
*
|
|
15
|
+
* It works by swapping `console.log` for the duration rather than threading a `quiet` flag through
|
|
16
|
+
* every command body. That is deliberate: the alternative is touching dozens of call sites, where the
|
|
17
|
+
* one that gets missed is a stray line that corrupts a parse — the exact failure mode being fixed.
|
|
18
|
+
* `console.error`/`console.warn` are untouched (already stderr), and the payload is written through a
|
|
19
|
+
* captured reference to the real `console.log`, so nothing can intercept it back.
|
|
20
|
+
*/
|
|
21
|
+
export function jsonMode(flags) {
|
|
22
|
+
return flags.json !== undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Run `body` and, under `--json`, print whatever it returns as the sole contents of stdout.
|
|
26
|
+
*
|
|
27
|
+
* `body` receives an `emit` it may call to contribute the payload incrementally — for a command that
|
|
28
|
+
* discovers its value midway (a deploy learning its address) and would otherwise have to restructure
|
|
29
|
+
* to return it at the end. The last `emit` wins; a returned value overrides both.
|
|
30
|
+
*
|
|
31
|
+
* Without `--json` this is a plain pass-through: zero behaviour change on the human path.
|
|
32
|
+
*/
|
|
33
|
+
export async function withJson(flags, body) {
|
|
34
|
+
let payload;
|
|
35
|
+
const emit = (p) => {
|
|
36
|
+
payload = p;
|
|
37
|
+
};
|
|
38
|
+
if (!jsonMode(flags)) {
|
|
39
|
+
await body(emit);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const realLog = console.log;
|
|
43
|
+
// Route human narration to stderr. Mirrors console.log's own formatting closely enough for
|
|
44
|
+
// progress text; nothing structured goes through here.
|
|
45
|
+
console.log = (...args) => process.stderr.write(args.map((a) => String(a)).join(' ') + '\n');
|
|
46
|
+
try {
|
|
47
|
+
const returned = await body(emit);
|
|
48
|
+
const out = returned ?? payload;
|
|
49
|
+
// A command that emitted nothing is a bug in that command, not a silent empty object — say so on
|
|
50
|
+
// stderr and leave stdout empty rather than writing `{}` that a caller would trust.
|
|
51
|
+
if (out === undefined) {
|
|
52
|
+
process.stderr.write('abx: --json produced no payload for this command (please report it)\n');
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
realLog(JSON.stringify(out, null, 2));
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
// A command that already called `emit()` for a fact it established (a minted token id) before a
|
|
60
|
+
// LATER step throws must not leave a `--json` caller with NOTHING on stdout — that fact is real
|
|
61
|
+
// and the caller may have no other way to recover it (e.g. the id assigned by a mint the command
|
|
62
|
+
// cannot safely repeat). Print whatever was emitted, then rethrow unchanged: main.ts's top-level
|
|
63
|
+
// catch still reports the error on stderr and sets the exit code exactly as it does today — this
|
|
64
|
+
// only ADDS a partial payload to stdout, it never swallows or reshapes the failure.
|
|
65
|
+
if (payload !== undefined)
|
|
66
|
+
realLog(JSON.stringify(payload, null, 2));
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
console.log = realLog;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** BigInt-safe JSON: bigints become decimal strings rather than throwing. Every on-chain number a
|
|
74
|
+
* payload carries (supply, a token id, a block) arrives as a bigint, and `JSON.stringify` refuses
|
|
75
|
+
* them outright — so a payload builder that forgets one would fail at the last line of a deploy. */
|
|
76
|
+
export function jsonSafe(value) {
|
|
77
|
+
return JSON.parse(JSON.stringify(value, (_k, v) => (typeof v === 'bigint' ? v.toString() : v)));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=jsonout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonout.js","sourceRoot":"","sources":["../src/jsonout.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAY;IACnC,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAY,EACZ,IAAuD;IAEvD,IAAI,OAAsB,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,CAAI,EAAE,EAAE;QACpB,OAAO,GAAG,CAAC,CAAC;IACd,CAAC,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC;IAC5B,2FAA2F;IAC3F,uDAAuD;IACvD,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACxG,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,GAAG,GAAI,QAA0B,IAAI,OAAO,CAAC;QACnD,iGAAiG;QACjG,oFAAoF;QACpF,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;YAC9F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gGAAgG;QAChG,gGAAgG;QAChG,iGAAiG;QACjG,iGAAiG;QACjG,iGAAiG;QACjG,oFAAoF;QACpF,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;qGAEqG;AACrG,MAAM,UAAU,QAAQ,CAAI,KAAQ;IAClC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAM,CAAC;AACvG,CAAC"}
|
package/dist/kind.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized token-kind detection — one shared probe for the six concrete ABX token types, from
|
|
3
|
+
* three plain `eth_call`s (no events, no local index). Before this existed, the same "is this a
|
|
4
|
+
* 721 or an edition, and which concrete type" question was answered by ad-hoc, slightly different
|
|
5
|
+
* probes scattered across `commands/project.ts` (`state`), `commands/scaffold.ts`
|
|
6
|
+
* (`assertMintableSeries`), and `ownerops.ts` (the `set-param-hooks` guard) — this gives it one
|
|
7
|
+
* name and one place to live, so a new call site (mint/transfer/minter kind-awareness) doesn't
|
|
8
|
+
* grow a fourth copy.
|
|
9
|
+
*
|
|
10
|
+
* The discriminator mirrors the SDK's `ProjectState.contractType` union (reconstruct.ts) exactly,
|
|
11
|
+
* but this is a LIVE probe, not an event fold: `state`, `mint-page`, and the owner-op guards need a
|
|
12
|
+
* snapshot with no local index and no getLogs scan.
|
|
13
|
+
*
|
|
14
|
+
* ERC-165 0xd9b67a26 (ERC-1155) → the edition family (OneOfOneEdition / EditionImage / EditionCode)
|
|
15
|
+
* maxInvocations() → present on the multi-id twins (Series/SeriesCode, EditionImage/Code)
|
|
16
|
+
* the Params/ConfigurableParams surface (`paramHooks()`) → present only on the two code twins
|
|
17
|
+
*
|
|
18
|
+
* Every probe treats a genuine revert/no-data response as "getter absent", but propagates RPC and
|
|
19
|
+
* transport failures. Conflating those cases silently downgraded a Series to `1of1` whenever a
|
|
20
|
+
* public endpoint transiently failed `maxInvocations()`. A no-code address still makes every getter
|
|
21
|
+
* truthfully absent, so the existence check lives HERE, once, ahead of the probes — every call site
|
|
22
|
+
* inherits it and cannot forget it.
|
|
23
|
+
*/
|
|
24
|
+
import type { Address, PublicClient } from 'viem';
|
|
25
|
+
/** Mirrors the SDK's `ProjectState.contractType` (reconstruct.ts) — the 721 ladder and its
|
|
26
|
+
* ERC-1155 edition twin, one rung apart. */
|
|
27
|
+
export type TokenKind = '1of1' | 'series' | 'code' | '1of1-edition' | 'edition' | 'edition-code';
|
|
28
|
+
export interface TokenKindInfo {
|
|
29
|
+
kind: TokenKind;
|
|
30
|
+
/** The single fact most call sites actually branch on — true for the three ERC-1155 twins. */
|
|
31
|
+
isEdition: boolean;
|
|
32
|
+
/** The concrete contract name, for a readout ("EditionImage (edition) state"). */
|
|
33
|
+
label: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Which of the six concrete ABX token types `address` is — the shared discriminator every command
|
|
37
|
+
* that branches on kind should call instead of re-deriving its own probe. Three live `eth_call`s,
|
|
38
|
+
* in the order that lets each short-circuit the next: ERC-165 first (edition family or not), then
|
|
39
|
+
* `maxInvocations()` (multi-id or not), then the Params surface (code or not).
|
|
40
|
+
*/
|
|
41
|
+
export declare function detectTokenKind(client: PublicClient, address: Address): Promise<TokenKindInfo>;
|
|
42
|
+
/** Convenience for a call site that only needs the one boolean (is this an ERC-1155 edition, at
|
|
43
|
+
* all) — the cheapest single probe, so a guard that doesn't need the full breakdown doesn't pay
|
|
44
|
+
* for the other two calls. */
|
|
45
|
+
export declare function isEditionContract(client: PublicClient, address: Address): Promise<boolean>;
|
|
46
|
+
/** Human, one-line description of a kind — `"EditionImage (edition)"`, `"SeriesImage (series)"` —
|
|
47
|
+
* the shared phrasing for a readout header (`state`, `tokens`). */
|
|
48
|
+
export declare function describeKind(info: TokenKindInfo): string;
|
|
49
|
+
/** The ConfigurableParams / PostParams surface — SeriesCode and EditionCode only. */
|
|
50
|
+
export declare function hasParamsSurface(info: TokenKindInfo): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Refuse a PostParams command (set-schema / configure-param / retire-param) against a contract
|
|
53
|
+
* that does not compose ConfigurableParams — before any signing prompt, and as a capability
|
|
54
|
+
* mismatch rather than a raw viem revert. Same probe `set-param-hooks` already ran.
|
|
55
|
+
*/
|
|
56
|
+
export declare function assertHasParamsSurface(client: PublicClient, address: Address, what: string): Promise<TokenKindInfo>;
|
|
57
|
+
//# sourceMappingURL=kind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kind.d.ts","sourceRoot":"","sources":["../src/kind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAC,OAAO,EAAE,YAAY,EAAC,MAAM,MAAM,CAAC;AAGhD;6CAC6C;AAC7C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,cAAc,CAAC;AAEjG,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,8FAA8F;IAC9F,SAAS,EAAE,OAAO,CAAC;IACnB,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;CACf;AA+ED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAYpG;AAED;;+BAE+B;AAC/B,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAEhG;AAED;oEACoE;AACpE,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAExD;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE7D;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,CAAC,CASxB"}
|
package/dist/kind.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { isMissingContractCapability, isRpcReadFailure } from './contract-read-error.js';
|
|
2
|
+
/** ERC-165 id of ERC-1155 itself — what sorts a clone into the edition family (anchors.ts's
|
|
3
|
+
* `ERC1155_INTERFACE_ID`, restated here rather than imported: it's a fixed standard id, not SDK
|
|
4
|
+
* surface). */
|
|
5
|
+
const ERC1155_INTERFACE_ID = '0xd9b67a26';
|
|
6
|
+
const KIND_PROBE_ABI = [
|
|
7
|
+
{ type: 'function', name: 'supportsInterface', stateMutability: 'view', inputs: [{ type: 'bytes4' }], outputs: [{ type: 'bool' }] },
|
|
8
|
+
{ type: 'function', name: 'maxInvocations', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
|
|
9
|
+
{ type: 'function', name: 'paramHooks', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }, { type: 'address' }, { type: 'address' }] },
|
|
10
|
+
];
|
|
11
|
+
function capabilityMissOrThrow(client, address, error) {
|
|
12
|
+
if (isMissingContractCapability(error))
|
|
13
|
+
return false;
|
|
14
|
+
if (isRpcReadFailure(error)) {
|
|
15
|
+
const chain = client.chain?.name ?? 'the active chain';
|
|
16
|
+
throw new Error(`could not detect the token type for ${address} on ${chain} — the RPC answered block/code requests but failed eth_call ` +
|
|
17
|
+
`(rate-limited or backend unhealthy). This is not a contract verdict; check the configured RPC URLs.`, { cause: error });
|
|
18
|
+
}
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Refuse to infer a kind for an address that holds no contract. Without this the three negative
|
|
23
|
+
* probes below are indistinguishable from "nothing deployed here", and the ladder's `1of1` default
|
|
24
|
+
* becomes a confident lie about a specific contract type (see the file docstring).
|
|
25
|
+
*
|
|
26
|
+
* Deliberately silent when the check itself can't run (an RPC hiccup → `getCode` throws): a network
|
|
27
|
+
* blip must not become a "no contract" claim, so we fall through to the probes exactly as before and
|
|
28
|
+
* let whatever the caller was doing surface its own error. Same stance as `assertContractExists`.
|
|
29
|
+
*/
|
|
30
|
+
async function assertHasCode(client, address) {
|
|
31
|
+
let code;
|
|
32
|
+
try {
|
|
33
|
+
code = await client.getCode({ address });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return; // can't tell — don't manufacture a verdict
|
|
37
|
+
}
|
|
38
|
+
if (code && code !== '0x')
|
|
39
|
+
return;
|
|
40
|
+
const chain = client.chain?.name ?? 'the active chain';
|
|
41
|
+
throw new Error(`no contract at ${address} on ${chain} — so there is no token type to read. ` +
|
|
42
|
+
`Check the address, and check the network: a contract that lives on another chain reads as empty here ` +
|
|
43
|
+
`(the chain is picked with ABX_CHAIN; base-sepolia is the default). Owner ops run AFTER deploy.`);
|
|
44
|
+
}
|
|
45
|
+
async function supportsErc1155(client, address) {
|
|
46
|
+
try {
|
|
47
|
+
return (await client.readContract({ address, abi: KIND_PROBE_ABI, functionName: 'supportsInterface', args: [ERC1155_INTERFACE_ID] }));
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return capabilityMissOrThrow(client, address, error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function hasMaxInvocations(client, address) {
|
|
54
|
+
try {
|
|
55
|
+
await client.readContract({ address, abi: KIND_PROBE_ABI, functionName: 'maxInvocations' });
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return capabilityMissOrThrow(client, address, error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** The Params/ConfigurableParams surface probe — `paramHooks()` exists only on SeriesCode/
|
|
63
|
+
* EditionCode (mirrors the exact check `ownerops.ts`'s `cmdSetParamHooks` already ran ad-hoc). */
|
|
64
|
+
async function hasConfigurableParams(client, address) {
|
|
65
|
+
try {
|
|
66
|
+
await client.readContract({ address, abi: KIND_PROBE_ABI, functionName: 'paramHooks' });
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return capabilityMissOrThrow(client, address, error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Which of the six concrete ABX token types `address` is — the shared discriminator every command
|
|
75
|
+
* that branches on kind should call instead of re-deriving its own probe. Three live `eth_call`s,
|
|
76
|
+
* in the order that lets each short-circuit the next: ERC-165 first (edition family or not), then
|
|
77
|
+
* `maxInvocations()` (multi-id or not), then the Params surface (code or not).
|
|
78
|
+
*/
|
|
79
|
+
export async function detectTokenKind(client, address) {
|
|
80
|
+
await assertHasCode(client, address);
|
|
81
|
+
const isEdition = await supportsErc1155(client, address);
|
|
82
|
+
const capped = await hasMaxInvocations(client, address);
|
|
83
|
+
if (isEdition) {
|
|
84
|
+
if (!capped)
|
|
85
|
+
return { kind: '1of1-edition', isEdition: true, label: 'OneOfOneEdition' };
|
|
86
|
+
const code = await hasConfigurableParams(client, address);
|
|
87
|
+
return code ? { kind: 'edition-code', isEdition: true, label: 'EditionCode' } : { kind: 'edition', isEdition: true, label: 'EditionImage' };
|
|
88
|
+
}
|
|
89
|
+
if (!capped)
|
|
90
|
+
return { kind: '1of1', isEdition: false, label: 'OneOfOneImage' };
|
|
91
|
+
const code = await hasConfigurableParams(client, address);
|
|
92
|
+
return code ? { kind: 'code', isEdition: false, label: 'SeriesCode' } : { kind: 'series', isEdition: false, label: 'SeriesImage' };
|
|
93
|
+
}
|
|
94
|
+
/** Convenience for a call site that only needs the one boolean (is this an ERC-1155 edition, at
|
|
95
|
+
* all) — the cheapest single probe, so a guard that doesn't need the full breakdown doesn't pay
|
|
96
|
+
* for the other two calls. */
|
|
97
|
+
export async function isEditionContract(client, address) {
|
|
98
|
+
return supportsErc1155(client, address);
|
|
99
|
+
}
|
|
100
|
+
/** Human, one-line description of a kind — `"EditionImage (edition)"`, `"SeriesImage (series)"` —
|
|
101
|
+
* the shared phrasing for a readout header (`state`, `tokens`). */
|
|
102
|
+
export function describeKind(info) {
|
|
103
|
+
return `${info.label} (${info.kind === '1of1' ? '1/1' : info.kind === '1of1-edition' ? 'edition' : info.kind})`;
|
|
104
|
+
}
|
|
105
|
+
/** The ConfigurableParams / PostParams surface — SeriesCode and EditionCode only. */
|
|
106
|
+
export function hasParamsSurface(info) {
|
|
107
|
+
return info.kind === 'code' || info.kind === 'edition-code';
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Refuse a PostParams command (set-schema / configure-param / retire-param) against a contract
|
|
111
|
+
* that does not compose ConfigurableParams — before any signing prompt, and as a capability
|
|
112
|
+
* mismatch rather than a raw viem revert. Same probe `set-param-hooks` already ran.
|
|
113
|
+
*/
|
|
114
|
+
export async function assertHasParamsSurface(client, address, what) {
|
|
115
|
+
const kind = await detectTokenKind(client, address);
|
|
116
|
+
if (!hasParamsSurface(kind)) {
|
|
117
|
+
throw new Error(`${address} exposes no PostParams — ${what} is a SeriesCode/EditionCode feature. ` +
|
|
118
|
+
`${kind.label} has no configurable params.`);
|
|
119
|
+
}
|
|
120
|
+
return kind;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=kind.js.map
|
package/dist/kind.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kind.js","sourceRoot":"","sources":["../src/kind.ts"],"names":[],"mappings":"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"}
|