@artblocks/abx-cli 0.1.0-alpha.40 → 0.1.0-alpha.42
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 +222 -0
- package/assets/renderer-scaffold/README.md +12 -0
- package/assets/renderer-scaffold/foundry.toml +4 -0
- package/assets/renderer-scaffold/script/Preview.s.sol +99 -0
- package/dist/capabilities.d.ts +9 -4
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +13 -4
- package/dist/capabilities.js.map +1 -1
- package/dist/commands/deploy.d.ts +51 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +1008 -172
- package/dist/commands/deploy.js.map +1 -1
- 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 +175 -3
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +359 -29
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/reads.d.ts +21 -0
- package/dist/commands/reads.d.ts.map +1 -1
- package/dist/commands/reads.js +171 -4
- package/dist/commands/reads.js.map +1 -1
- package/dist/commands/scaffold.d.ts.map +1 -1
- package/dist/commands/scaffold.js +5 -0
- package/dist/commands/scaffold.js.map +1 -1
- package/dist/commands/service.d.ts.map +1 -1
- package/dist/commands/service.js +7 -0
- package/dist/commands/service.js.map +1 -1
- package/dist/commands/storage.d.ts.map +1 -1
- package/dist/commands/storage.js +32 -3
- package/dist/commands/storage.js.map +1 -1
- package/dist/commands/submit-app.d.ts +43 -0
- package/dist/commands/submit-app.d.ts.map +1 -1
- package/dist/commands/submit-app.js +115 -6
- package/dist/commands/submit-app.js.map +1 -1
- package/dist/config.d.ts +16 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +73 -7
- package/dist/config.js.map +1 -1
- package/dist/deploy-plan.d.ts +221 -0
- package/dist/deploy-plan.d.ts.map +1 -0
- package/dist/deploy-plan.js +20 -0
- package/dist/deploy-plan.js.map +1 -0
- package/dist/flag-allowlists.d.ts.map +1 -1
- package/dist/flag-allowlists.js +5 -1
- package/dist/flag-allowlists.js.map +1 -1
- package/dist/flags.d.ts +6 -0
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +14 -0
- package/dist/flags.js.map +1 -1
- package/dist/jsonout.d.ts.map +1 -1
- package/dist/jsonout.js +11 -0
- package/dist/jsonout.js.map +1 -1
- package/dist/main.js +62 -13
- package/dist/main.js.map +1 -1
- package/dist/ownerops.d.ts +139 -1
- package/dist/ownerops.d.ts.map +1 -1
- package/dist/ownerops.js +382 -19
- package/dist/ownerops.js.map +1 -1
- package/dist/riskgate.d.ts +36 -0
- package/dist/riskgate.d.ts.map +1 -1
- package/dist/riskgate.js +91 -17
- package/dist/riskgate.js.map +1 -1
- package/dist/script-chunks.d.ts +1 -1
- package/dist/script-chunks.d.ts.map +1 -1
- package/dist/script-chunks.js +2 -2
- package/dist/script-chunks.js.map +1 -1
- package/package.json +6 -6
- package/skill/SKILL.md +6 -4
- package/skill/reference/code.md +31 -8
- package/skill/reference/deploy.md +9 -2
- package/skill/reference/diagnose.md +15 -2
- package/skill/reference/hosting.md +26 -0
- package/skill/reference/operate.md +55 -4
- package/skill/reference/setup.md +14 -0
package/dist/riskgate.js
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
* free just by routing through here — there is no owner-op-specific reason they lacked it; it was
|
|
16
16
|
* simply never wired.
|
|
17
17
|
*/
|
|
18
|
-
import { decodeErrorResult, zeroAddress } from 'viem';
|
|
18
|
+
import { decodeErrorResult, formatEther, zeroAddress } from 'viem';
|
|
19
19
|
import { createInterface } from 'node:readline';
|
|
20
|
-
import { assertChainId, envSigningKey, makePublicClient, seriesCodeAbi } from '@artblocks/abx-sdk';
|
|
20
|
+
import { assertChainId, envSigningKey, makePublicClient, pinGas, seriesCodeAbi, GasEstimateBelowFloorError, } from '@artblocks/abx-sdk';
|
|
21
21
|
import { signTx } from './signer.js';
|
|
22
22
|
import { isDryRun } from './flags.js';
|
|
23
23
|
// ── tiny ANSI (kept local — every module here stands alone; see signer.ts/ownerops.ts) ───────
|
|
@@ -134,18 +134,36 @@ export function revertReason(err) {
|
|
|
134
134
|
return short;
|
|
135
135
|
}
|
|
136
136
|
/**
|
|
137
|
-
*
|
|
137
|
+
* Simulate the prepared transaction against current state, and say what would happen — honestly.
|
|
138
138
|
*
|
|
139
139
|
* This is what makes `--dry-run` an *answer* rather than an echo of its own input. It matters most
|
|
140
140
|
* for a **multicall** — `attach`'s batched pairs, `deploy-code`'s setup — because a multicall is one
|
|
141
141
|
* transaction, so simulating it exercises the whole sequence atomically against real state, with no
|
|
142
142
|
* fork and no new surface.
|
|
143
143
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
144
|
+
* A dry run that reports `would-succeed` for a send whose real gas turned out to need 49% more than
|
|
145
|
+
* this function used to check, then failed for real, is a preview asserting an outcome it never
|
|
146
|
+
* established — the same class of bug fixed for `verify --remote --json` (see `cmdVerifyRemote`'s
|
|
147
|
+
* fail-closed comment in commands/project.ts): a payload must not claim success it hasn't earned.
|
|
148
|
+
* Two things had to be true before this could say "would succeed", and neither was checked:
|
|
149
|
+
* 1. The call executes without reverting — the ORIGINAL check (an `eth_call`, now folded into
|
|
150
|
+
* {@link pinGas} below instead of a separate unconstrained call, so the preview shares the
|
|
151
|
+
* real send's own gas math, not a second copy of it that could quietly disagree).
|
|
152
|
+
* 2. The signer can actually PAY for it. `estimateGas` succeeding proves the call is valid; it says
|
|
153
|
+
* nothing about whether the account sending it has the ETH to cover `gas × gasPrice (+ value)`.
|
|
154
|
+
* A preview that skips this is not "optimistic", it is wrong — the failure this fixes.
|
|
155
|
+
*
|
|
156
|
+
* Reports **unknown**, never a false green, whenever it cannot actually prove EITHER of those: no
|
|
157
|
+
* signer to simulate as, a contract deploy, a target that does not exist yet, an unreachable node, or
|
|
158
|
+
* a gas estimate that comes back below the transaction's provable floor even after retrying (the
|
|
159
|
+
* exact same refusal a real send makes — see {@link GasEstimateBelowFloorError}). `unknown` is never
|
|
160
|
+
* collapsed into `would-succeed` (an optimistic guess) or `would-revert` (a false alarm) — it says
|
|
161
|
+
* plainly that the question could not be answered, and why.
|
|
162
|
+
*
|
|
163
|
+
* `clientOverride` exists for tests: production callers always omit it and get a real client built
|
|
164
|
+
* from `chainKey`, exactly as before.
|
|
147
165
|
*/
|
|
148
|
-
async function simulateDryRun(prepared, chainKey, expectedSigner, narrate = true) {
|
|
166
|
+
async function simulateDryRun(prepared, chainKey, expectedSigner, narrate = true, clientOverride) {
|
|
149
167
|
const label = 'simulation'.padEnd(12);
|
|
150
168
|
const unknown = (why) => {
|
|
151
169
|
if (narrate)
|
|
@@ -162,24 +180,47 @@ async function simulateDryRun(prepared, chainKey, expectedSigner, narrate = true
|
|
|
162
180
|
// preview is the product; the simulation is a bonus). So even constructing the client is guarded —
|
|
163
181
|
// `resolveChain` throws on a chain key it doesn't know, and that must degrade to `unknown`, never
|
|
164
182
|
// turn a preview into a failure.
|
|
183
|
+
let client;
|
|
184
|
+
try {
|
|
185
|
+
client = clientOverride ?? makePublicClient({ chainKey });
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
return unknown(`could not run the simulation (${revertReason(err)})`);
|
|
189
|
+
}
|
|
165
190
|
try {
|
|
166
|
-
const client = makePublicClient({ chainKey });
|
|
167
191
|
const code = await client.getCode({ address: prepared.to });
|
|
168
192
|
if (!code || code === '0x')
|
|
169
193
|
return unknown(`${prepared.to} has no code yet on this chain`);
|
|
170
|
-
|
|
171
|
-
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
return unknown(`could not run the simulation (${revertReason(err)})`);
|
|
197
|
+
}
|
|
198
|
+
// Reuse the REAL send's own gas selection (`pinGas`, execute.ts — the exact function
|
|
199
|
+
// `makeHotSender` calls at send time) instead of a second, separately-written `eth_call`. Two
|
|
200
|
+
// benefits: (a) the preview can never independently drift from what the send would actually do,
|
|
201
|
+
// and (b) a transaction whose real send would REFUSE (every estimate attempt below the provable
|
|
202
|
+
// floor) is reported as such here too, rather than "succeeding" against an unconstrained call.
|
|
203
|
+
let gas;
|
|
204
|
+
try {
|
|
205
|
+
gas = await pinGas(client, {
|
|
206
|
+
from: expectedSigner,
|
|
172
207
|
to: prepared.to,
|
|
173
208
|
data: prepared.data,
|
|
174
|
-
|
|
209
|
+
value: prepared.value,
|
|
210
|
+
gasFloor: prepared.gasFloor,
|
|
175
211
|
});
|
|
176
|
-
if (narrate)
|
|
177
|
-
console.log(` ${dim(label)} ${C.green}✓${C.reset} would succeed ${dim('(eth_call against current state)')}`);
|
|
178
|
-
return { status: 'would-succeed' };
|
|
179
212
|
}
|
|
180
213
|
catch (err) {
|
|
181
|
-
|
|
214
|
+
if (err instanceof GasEstimateBelowFloorError) {
|
|
215
|
+
// Not a contract-logic revert and not a network hiccup — this is "cannot be determined safe",
|
|
216
|
+
// the same refusal a real send makes. Reported as `unknown`, never folded into `would-revert`
|
|
217
|
+
// (nothing was proven to revert) or `would-succeed` (nothing was proven safe either).
|
|
218
|
+
return unknown(`the gas estimate (${err.estimate}) came back below the ${err.floor} this transaction provably needs, ` +
|
|
219
|
+
`even after retrying — the same reason a real send would refuse rather than risk an under-funded ` +
|
|
220
|
+
`transaction. Retry in a few seconds, or against a different RPC.`);
|
|
221
|
+
}
|
|
182
222
|
const reason = revertReason(err);
|
|
223
|
+
// A node that cannot answer is not a failing transaction — do not report one as the other.
|
|
183
224
|
if (/fetch|network|timeout|ECONN|unknown chain/i.test(reason))
|
|
184
225
|
return unknown(`could not run the simulation (${reason})`);
|
|
185
226
|
if (narrate) {
|
|
@@ -188,6 +229,36 @@ async function simulateDryRun(prepared, chainKey, expectedSigner, narrate = true
|
|
|
188
229
|
}
|
|
189
230
|
return { status: 'would-revert', reason };
|
|
190
231
|
}
|
|
232
|
+
// The call is provably executable at `gas` — what's left is whether the signer can actually PAY
|
|
233
|
+
// for it. This is the check that was missing entirely: a preview that never compares cost against
|
|
234
|
+
// balance is asserting an outcome it has not earned.
|
|
235
|
+
let gasPrice;
|
|
236
|
+
let balance;
|
|
237
|
+
try {
|
|
238
|
+
[gasPrice, balance] = await Promise.all([client.getGasPrice(), client.getBalance({ address: expectedSigner })]);
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
// We proved the call itself would succeed; we just can't price it. Say so — do NOT fall back to
|
|
242
|
+
// a bare "would succeed" that quietly drops the affordability question it was just asked.
|
|
243
|
+
return unknown(`the call would succeed, but the cost to send it could not be priced (${revertReason(err)})`);
|
|
244
|
+
}
|
|
245
|
+
const value = prepared.value && prepared.value !== '0x0' ? BigInt(prepared.value) : 0n;
|
|
246
|
+
const cost = gas * gasPrice + value;
|
|
247
|
+
const priced = { estimatedGas: gas.toString(), estimatedCostWei: cost.toString(), balanceWei: balance.toString() };
|
|
248
|
+
if (balance < cost) {
|
|
249
|
+
const reason = `insufficient funds — this send needs ≈${formatEther(cost)} ETH (${gas} gas × ${formatEther(gasPrice)} ` +
|
|
250
|
+
`ETH/gas${value > 0n ? ` + ${formatEther(value)} ETH value` : ''}) but ${expectedSigner} has only ` +
|
|
251
|
+
`${formatEther(balance)} ETH — short by ${formatEther(cost - balance)} ETH.`;
|
|
252
|
+
if (narrate) {
|
|
253
|
+
console.log(` ${dim(label)} ${C.orange}✗ would FAIL${C.reset} — ${reason}`);
|
|
254
|
+
console.log(` ${dim(''.padEnd(12))} ${dim('sending this now would run out of funds before it lands.')}`);
|
|
255
|
+
}
|
|
256
|
+
return { status: 'would-revert', reason, ...priced };
|
|
257
|
+
}
|
|
258
|
+
if (narrate) {
|
|
259
|
+
console.log(` ${dim(label)} ${C.green}✓${C.reset} would succeed ${dim(`(≈${gas} gas, ≈${formatEther(cost)} ETH — signer holds ${formatEther(balance)} ETH)`)}`);
|
|
260
|
+
}
|
|
261
|
+
return { status: 'would-succeed', ...priced };
|
|
191
262
|
}
|
|
192
263
|
/**
|
|
193
264
|
* The one send choke point for a SINGLE already-prepared write: `--dry-run` preview (nothing sent,
|
|
@@ -202,19 +273,22 @@ export async function gatedSend(provider, flags, opts) {
|
|
|
202
273
|
if (isDryRun(flags)) {
|
|
203
274
|
const prepared = await resolveProvider(provider, opts.expectedSigner ?? zeroAddress);
|
|
204
275
|
if (flags.json !== undefined) {
|
|
205
|
-
const simulation = await simulateDryRun(prepared, opts.chainKey, opts.expectedSigner, false);
|
|
276
|
+
const simulation = await simulateDryRun(prepared, opts.chainKey, opts.expectedSigner, false, opts.client);
|
|
206
277
|
console.log(JSON.stringify({
|
|
207
278
|
dryRun: true,
|
|
208
279
|
sent: false,
|
|
209
280
|
lane: laneFromFlags(flags),
|
|
210
281
|
expectedSigner: opts.expectedSigner ?? null,
|
|
211
282
|
transaction: prepared,
|
|
283
|
+
// `transaction.gasFloor` (when present) is a PROVEN MINIMUM used to detect an implausible
|
|
284
|
+
// gas estimate — not a prediction of total cost. `simulation.estimatedGas`/`estimatedCostWei`
|
|
285
|
+
// are the real numbers, from the same gas selection the send itself uses; trust those.
|
|
212
286
|
simulation,
|
|
213
287
|
}, null, 2));
|
|
214
288
|
}
|
|
215
289
|
else {
|
|
216
290
|
printDryRunPreview(prepared, opts.expectedSigner);
|
|
217
|
-
await simulateDryRun(prepared, opts.chainKey, opts.expectedSigner);
|
|
291
|
+
await simulateDryRun(prepared, opts.chainKey, opts.expectedSigner, true, opts.client);
|
|
218
292
|
console.log(dim(`\n Re-run without --dry-run to send (lane: ${laneFromFlags(flags)}).\n`));
|
|
219
293
|
}
|
|
220
294
|
return null;
|
package/dist/riskgate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"riskgate.js","sourceRoot":"","sources":["../src/riskgate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAC,iBAAiB,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"riskgate.js","sourceRoot":"","sources":["../src/riskgate.ts"],"names":[],"mappings":"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"}
|
package/dist/script-chunks.d.ts
CHANGED
|
@@ -4,5 +4,5 @@ import { type Hex } from 'viem';
|
|
|
4
4
|
* {@link splitScriptChunks} splits so that join is byte-identical to `source`. A program that does
|
|
5
5
|
* not parse — before OR after that join — is refused here, because `abx verify` does not parse it.
|
|
6
6
|
*/
|
|
7
|
-
export declare function planOnChainScript(source: string): Hex[];
|
|
7
|
+
export declare function planOnChainScript(source: string, chunkSize?: number): Hex[];
|
|
8
8
|
//# sourceMappingURL=script-chunks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-chunks.d.ts","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"AAKA,OAAO,EAAQ,KAAK,GAAG,EAAC,MAAM,MAAM,CAAC;AAGrC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"script-chunks.d.ts","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"AAKA,OAAO,EAAQ,KAAK,GAAG,EAAC,MAAM,MAAM,CAAC;AAGrC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE,CAW3E"}
|
package/dist/script-chunks.js
CHANGED
|
@@ -10,9 +10,9 @@ import { joinScriptChunks, splitScriptChunks } from '@artblocks/abx-sdk';
|
|
|
10
10
|
* {@link splitScriptChunks} splits so that join is byte-identical to `source`. A program that does
|
|
11
11
|
* not parse — before OR after that join — is refused here, because `abx verify` does not parse it.
|
|
12
12
|
*/
|
|
13
|
-
export function planOnChainScript(source) {
|
|
13
|
+
export function planOnChainScript(source, chunkSize) {
|
|
14
14
|
assertScriptParses(source, 'the script on disk');
|
|
15
|
-
const parts = splitScriptChunks(source);
|
|
15
|
+
const parts = chunkSize === undefined ? splitScriptChunks(source) : splitScriptChunks(source, chunkSize);
|
|
16
16
|
const joined = joinScriptChunks(parts);
|
|
17
17
|
if (joined !== source) {
|
|
18
18
|
throw new Error('internal: script chunks do not reassemble to the source. The on-chain generator joins ' +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-chunks.js","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAC,KAAK,EAAW,MAAM,MAAM,CAAC;AACrC,OAAO,EAAC,gBAAgB,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAEvE;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;
|
|
1
|
+
{"version":3,"file":"script-chunks.js","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAC,KAAK,EAAW,MAAM,MAAM,CAAC;AACrC,OAAO,EAAC,gBAAgB,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAEvE;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,SAAkB;IAClE,kBAAkB,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACzG,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,wFAAwF;YACtF,6EAA6E,CAChF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc,EAAE,IAAY;IACtD,IAAI,CAAC;QACH,gGAAgG;QAChG,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAC,QAAQ,EAAE,WAAW,EAAC,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,kCAAkC,GAAG,iDAAiD;YAC3F,sFAAsF;YACtF,wDAAwD,CAC3D,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artblocks/abx-cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.42",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Command-line interface for deploying, operating, indexing, and serving ABX projects.",
|
|
6
6
|
"type": "module",
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"viem": "^2.56.0",
|
|
42
|
-
"@artblocks/abx-sdk": "0.1.0-alpha.
|
|
43
|
-
"@artblocks/abx-indexer": "0.1.0-alpha.
|
|
44
|
-
"@artblocks/abx-
|
|
45
|
-
"@artblocks/abx-
|
|
42
|
+
"@artblocks/abx-sdk": "0.1.0-alpha.32",
|
|
43
|
+
"@artblocks/abx-indexer": "0.1.0-alpha.33",
|
|
44
|
+
"@artblocks/abx-token-api": "0.1.0-alpha.35",
|
|
45
|
+
"@artblocks/abx-storage": "0.1.0-alpha.32"
|
|
46
46
|
},
|
|
47
47
|
"optionalDependencies": {
|
|
48
|
-
"@artblocks/abx-effects": "0.1.0-alpha.
|
|
48
|
+
"@artblocks/abx-effects": "0.1.0-alpha.32"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"playwright": "1.62.1"
|
package/skill/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
change an ABX collection, or to determine whether ABX supports a mechanic.
|
|
10
10
|
compatibility: Drives @artblocks/abx-cli on Node 22.13+. Co-versioned with the CLI; install or refresh with `abx skill install`.
|
|
11
11
|
metadata:
|
|
12
|
-
version: "0.1.0-alpha.
|
|
12
|
+
version: "0.1.0-alpha.42"
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
# ABX
|
|
@@ -106,8 +106,10 @@ Run `abx capabilities --json` for the current matrix, then load [deploy.md](refe
|
|
|
106
106
|
|
|
107
107
|
Important boundaries:
|
|
108
108
|
|
|
109
|
-
- `deploy-code --copies` supports `--script`, dependencies,
|
|
110
|
-
|
|
109
|
+
- `deploy-code --copies` supports `--script`, `--code-dir`, dependencies, Solidity image/attributes
|
|
110
|
+
renderers, `--image-base` (a deterministic per-id off-chain still, mutually exclusive with
|
|
111
|
+
`--image-renderer`), and `--resume` (a per-id mint diff — pass the same content flags plus
|
|
112
|
+
`--mint-amount` if the original deploy premint ids).
|
|
111
113
|
- `--onchain-image` works for static 721s and editions in hot or wallet-signing lanes. It cannot be
|
|
112
114
|
prepared as one cold `--unsigned` bundle because staged transactions depend on prior receipts.
|
|
113
115
|
- A code project may need no public host when its image/traits are computed by Solidity renderers.
|
|
@@ -129,7 +131,7 @@ Before deploying, write down the promised value for each applicable row:
|
|
|
129
131
|
| Animation/live view | the decoded `animation_url`, loaded with a real minted token |
|
|
130
132
|
| Marketplace traits | decoded `attributes`, not merely console output from the program |
|
|
131
133
|
| Parameters and values | `abx state` for schemas; `abx tokens --json` for token values |
|
|
132
|
-
| Attached artifacts |
|
|
134
|
+
| Attached artifacts | `abx artifacts <addr> --token <id>` (entries + current/stale effect rows); attachments are not enumerable in bare on-chain metadata |
|
|
133
135
|
| Byte integrity | `abx verify <addr>` |
|
|
134
136
|
| Hosted lifecycle | `abx status --remote <name> --watch` or provider status |
|
|
135
137
|
|
package/skill/reference/code.md
CHANGED
|
@@ -26,10 +26,27 @@ renderers, marketplace stills and traits, seeds, dependencies, parameters, and c
|
|
|
26
26
|
| Solidity-computed fields | `--image-renderer` and/or `--attributes-renderer` | on-chain SVG image and/or traits |
|
|
27
27
|
| Hybrid | script plus field renderers | program animation plus Solidity image/traits |
|
|
28
28
|
|
|
29
|
+
`--script` splits the source into on-chain chunks automatically (default ~22 KB per chunk, the
|
|
30
|
+
practical SSTORE2/EIP-170 limit). Pass `--chunk-size <bytes>` to override the split size — smaller
|
|
31
|
+
values force a multi-chunk program cheaply, which is the fast way to exercise multi-chunk behavior on
|
|
32
|
+
a tiny test script rather than needing a large real one. `abx replace-script`
|
|
33
|
+
([operate.md](operate.md#replacing-an-unlocked-script)) accepts the same flag.
|
|
34
|
+
|
|
35
|
+
There is no fixed supported script-size ceiling. Post-deploy setup (chunks, PostParam schemas,
|
|
36
|
+
dependency declarations, on-chain-URI legs, reserve mints) rides one combined transaction when it
|
|
37
|
+
fits; a large script splits it into several gas-bounded transactions instead — chunks first, then the
|
|
38
|
+
remaining config, mints strictly last. The dry run's `transactions`/`approvals` reports the real
|
|
39
|
+
count for the whole plan; if any single one is interrupted mid-sequence, `--resume` finishes it (see
|
|
40
|
+
[diagnose.md](diagnose.md#incomplete-deployments)) — every non-mint leg is idempotent, so re-running
|
|
41
|
+
resume is always safe.
|
|
42
|
+
|
|
29
43
|
Without `--copies`, the contract is SeriesCode (ERC-721). With `--copies <n|open>`, it is EditionCode
|
|
30
44
|
(ERC-1155): N generated ids, each with multiple copies. EditionCode currently supports scripts,
|
|
31
|
-
dependencies,
|
|
32
|
-
|
|
45
|
+
directory builds (`--code-dir`), dependencies, field renderers, deterministic per-id off-chain stills
|
|
46
|
+
(`--image-base`), and `--resume` for an incomplete deployment (see
|
|
47
|
+
[diagnose.md](diagnose.md#incomplete-deployments) — the mint leg diffs per id, with a new
|
|
48
|
+
`--mint-amount` naming each premint id's intended copy count). Run `abx capabilities --json`
|
|
49
|
+
immediately before planning.
|
|
33
50
|
|
|
34
51
|
For one generated work with 100 copies, use `--max 1 --copies 100`. Omitting `--max 1` leaves the
|
|
35
52
|
default multi-id space, producing multiple generated ids with 100 copies available for each id.
|
|
@@ -105,16 +122,22 @@ a still published to a deterministic public `--image-base` is a manual/backfill
|
|
|
105
122
|
after relevant parameter changes. An on-chain animation plus automatically updating off-chain still
|
|
106
123
|
requires an operator watching state.
|
|
107
124
|
|
|
108
|
-
EditionCode
|
|
109
|
-
|
|
110
|
-
|
|
125
|
+
EditionCode now accepts `--image-base` too: the same `{base}/{id}.png` url-template, one id space
|
|
126
|
+
finer — `{id}` is the EditionCode id, and every copy of that id shares the one image (there is no
|
|
127
|
+
per-copy addressing). The effect runner never renders an id with zero live copies (no mint-time seed
|
|
128
|
+
has been drawn yet for it), so an unminted premint id is skipped, not errored — it renders once the
|
|
129
|
+
first copy mints. `--image-base` stays mutually exclusive with `--image-renderer` on both lanes.
|
|
111
130
|
|
|
112
131
|
### Build directory
|
|
113
132
|
|
|
114
133
|
Use `--code-dir` for an application bundle whose files are uploaded and addressed as a code artifact.
|
|
115
|
-
It requires external storage and public resolution
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
It requires external storage and public resolution — a backend without directory upload (`fs`, the
|
|
135
|
+
local default) is refused; pick `--backend ipfs` or `--backend arweave`. Inspect the built output, not
|
|
136
|
+
only the source tree, and verify that every referenced asset is included. The live view 302s through
|
|
137
|
+
the gateway, so the gateway must serve HTML (the shared Pinata public gateway does not — use a
|
|
138
|
+
dedicated gateway or Arweave). `--code-dir` works with `--copies` too (EditionCode): the same upload,
|
|
139
|
+
the same on-chain `code` field, the same gateway rules — `--script` and `--code-dir` remain mutually
|
|
140
|
+
exclusive on both lanes.
|
|
118
141
|
|
|
119
142
|
## Plan Solidity field renderers
|
|
120
143
|
|
|
@@ -51,7 +51,9 @@ Use `--onchain-uri --backend arweave|ipfs|cloud`. The CLI uploads media, bakes i
|
|
|
51
51
|
on-chain JSON, and does not require an ABX resolver. This is often the simplest durable path for
|
|
52
52
|
static collections:
|
|
53
53
|
|
|
54
|
-
- Arweave provides pay-once permanent custody through the configured uploader
|
|
54
|
+
- Arweave provides pay-once permanent custody through the configured uploader, but needs the
|
|
55
|
+
optional `@artblocks/abx-storage-arweave` package installed alongside the CLI first (see
|
|
56
|
+
[hosting.md](hosting.md#arweave)) — it is not part of the default install.
|
|
55
57
|
- IPFS requires maintained pinning and a public gateway; a local kubo gateway is development-only.
|
|
56
58
|
- Cloud requires an authenticated upload endpoint and a distinct public read base/CDN URL.
|
|
57
59
|
|
|
@@ -154,7 +156,12 @@ Do not import code-edition limits into static editions or vice versa. Use the ca
|
|
|
154
156
|
1. Run `abx doctor`, storage/remote checks needed by the selected path, and command help.
|
|
155
157
|
2. Run the exact command with `--dry-run --json` and a known `--for` address when needed.
|
|
156
158
|
3. Read back contract family, id/copy arithmetic, custody, resolution, public URLs, signer lane,
|
|
157
|
-
initial mint, transaction count, cost/reach warnings, and irreversible options.
|
|
159
|
+
initial mint, transaction count, cost/reach warnings, and irreversible options. The JSON payload's
|
|
160
|
+
`plan` object (every `deploy`/`deploy-series`/`deploy-code` emit, including `--resume`) carries
|
|
161
|
+
most of this pre-structured — `transactions`, `roles`, `royalty`, `custody`, `mint`, `estimate`,
|
|
162
|
+
`warnings`, and (code lanes) `surfaces`/`dependencies` — versioned via `plan.schemaVersion`. Prefer
|
|
163
|
+
it over parsing the human prose for anything it covers; a field it has no answer for is `null`, not
|
|
164
|
+
absent.
|
|
158
165
|
4. Receive explicit confirmation.
|
|
159
166
|
5. Run the same normalized command without `--dry-run`; do not start another write using the EOA.
|
|
160
167
|
6. Capture the chain, contract address, deploy block, owner, storage locators, and resolver/remote.
|
|
@@ -76,8 +76,15 @@ Before resume:
|
|
|
76
76
|
- read the resume dry run and confirm every proposed transaction;
|
|
77
77
|
- ensure no second writer is operating the same EOA.
|
|
78
78
|
|
|
79
|
-
EditionCode
|
|
80
|
-
|
|
79
|
+
EditionCode (`--copies`) targets are supported too — pass the exact same content flags the original
|
|
80
|
+
deploy used, minus `--copies` itself (the standard was fixed at creation and is read from chain, not
|
|
81
|
+
re-specified). The one difference from a 721 resume: name the intended premint plan with
|
|
82
|
+
`--mint-count`/`--mint-amount` if the original deploy premint any ids — the mint leg diffs **per id**
|
|
83
|
+
against that id's own on-chain copy count, not a single whole-contract total, and each shortfall sends
|
|
84
|
+
as one transaction regardless of how many copies are missing. Getting `--mint-count`/`--mint-amount`
|
|
85
|
+
wrong under-reports (an id you meant to premint stays at zero) rather than over-mints (a token cannot
|
|
86
|
+
be un-minted, so the diff only ever tops up a shortfall) — but confirm the intended plan with the
|
|
87
|
+
human before sending if there is any doubt about what the original deploy meant to premint.
|
|
81
88
|
|
|
82
89
|
## RPC and chain failures
|
|
83
90
|
|
|
@@ -154,6 +161,12 @@ idempotently skip an existing current artifact. A PostParam change produces a ne
|
|
|
154
161
|
the watcher or run the explicit one-shot path. Solidity image renderers have no effects job—diagnose
|
|
155
162
|
their on-chain call instead.
|
|
156
163
|
|
|
164
|
+
`abx artifacts <addr> --token <id> --json` is the direct check for steps 5–7: it reports every
|
|
165
|
+
registered effect row (current and stale) against the token's active `inputsHash`, without fetching
|
|
166
|
+
and parsing the whole served document. A row present but labeled `stale` means a param changed since
|
|
167
|
+
it rendered — re-render, don't assume it's missing. Add `--remote <name|url>` for a hosted project;
|
|
168
|
+
the real artifact set lives on the resolver that serves it, not in this node's local projection.
|
|
169
|
+
|
|
157
170
|
## Secret-safe reporting
|
|
158
171
|
|
|
159
172
|
Include command name, CLI version, chain key, redacted host labels, contract address, transaction hash,
|
|
@@ -128,6 +128,13 @@ change that prefix without changing the content.
|
|
|
128
128
|
|
|
129
129
|
### Arweave
|
|
130
130
|
|
|
131
|
+
`--backend arweave` (the default `turbo` provider) needs the optional
|
|
132
|
+
`@artblocks/abx-storage-arweave` package installed alongside the CLI — it is not part of the
|
|
133
|
+
default install, deliberately, so a default `abx` install stays free of Turbo's browser
|
|
134
|
+
wallet-connector dependency tree. If it is missing, the CLI names the exact install command
|
|
135
|
+
(`npm install @artblocks/abx-storage-arweave`) rather than failing unhelpfully; run that command
|
|
136
|
+
once, then retry. `--provider http-bundler` needs neither this package nor any of its dependencies.
|
|
137
|
+
|
|
131
138
|
The accepted upload and a retrievable gateway object are separate lifecycle states. Use
|
|
132
139
|
`abx storage status <locator> --json`; wait for `ready` instead of uploading duplicates during
|
|
133
140
|
propagation. Upload deduplication is success, not an instruction to top up or switch backends.
|
|
@@ -165,6 +172,25 @@ Verify the operational graph:
|
|
|
165
172
|
5. Token metadata exposes the resulting image/attributes.
|
|
166
173
|
6. A PostParam change reaches the watcher and creates the next inputs-hash render.
|
|
167
174
|
|
|
175
|
+
### SQLite maintenance for a long-running node
|
|
176
|
+
|
|
177
|
+
The self-hosted store is one SQLite file. `abx serve` already reclaims freed pages automatically in
|
|
178
|
+
small bounded passes between chain-watch ticks — never inline with a request, so it never adds
|
|
179
|
+
latency to a metadata read. Nothing to schedule for that half.
|
|
180
|
+
|
|
181
|
+
The other half is explicit and never automatic: a store created before this maintenance shipped
|
|
182
|
+
needs a one-time conversion.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
abx vacuum # status: auto_vacuum mode, page count, freelist size
|
|
186
|
+
abx vacuum convert # one-time full VACUUM — only when abx vacuum says the store needs it
|
|
187
|
+
abx vacuum incremental [--pages n] # one bounded reclaim pass on demand (not running abx serve? use this)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Run `abx vacuum convert` deliberately, not on a schedule: it rewrites the entire file and can briefly
|
|
191
|
+
need up to ~2x its on-disk size. Check `abx vacuum` first; if it already reports `auto_vacuum:
|
|
192
|
+
incremental`, there is nothing to convert.
|
|
193
|
+
|
|
168
194
|
## Use lifecycle states
|
|
169
195
|
|
|
170
196
|
Prefer status over retries. Typical nonterminal states include deployment accepted, indexing,
|
|
@@ -22,8 +22,17 @@ abx tokens <address> --json
|
|
|
22
22
|
abx contracturi <address>
|
|
23
23
|
abx tokenuri <address> --token <id>
|
|
24
24
|
abx verify <address> --json
|
|
25
|
+
abx artifacts <address> --token <id> --json
|
|
25
26
|
```
|
|
26
27
|
|
|
28
|
+
`abx artifacts` reads a token's `artifacts` manifest directly, without fetching and parsing the whole
|
|
29
|
+
served document — entries plus every registered effect row (current and stale, labeled against the
|
|
30
|
+
token's active `inputsHash`). Report which surface answered: this node's local projection, or (with
|
|
31
|
+
`--remote <name|url>`) the hosted resolver that actually owns a hosted project's real artifact set.
|
|
32
|
+
Neither "not registered here" nor "not registered on that remote" is an error — both return a stable
|
|
33
|
+
`{surface, registered, available, reason, entries, effects}` shape. Nothing it reports is onchain data
|
|
34
|
+
itself; every entry is a resolver-published projection.
|
|
35
|
+
|
|
27
36
|
Use `abx status` or its remote form for projection/render lifecycle. Record active chain, detected
|
|
28
37
|
family, owner/admin, supply and pause state, minter/payee, royalty/cap, URI renderer/pointers, code
|
|
29
38
|
dependencies, schemas/hooks, and lock state.
|
|
@@ -116,15 +125,35 @@ repoint is not a re-upload and does not change the committed CID/transaction id.
|
|
|
116
125
|
|
|
117
126
|
### Attachments versus parameters
|
|
118
127
|
|
|
119
|
-
`abx attach <addr> <key> <locator>` records a named artifact.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
128
|
+
`abx attach <addr> <key> <locator>` records a named artifact. It prints the CANONICAL fetch URL for
|
|
129
|
+
every key (`{base}/{chainId}/{address}[/<id>]/data/<key>`) directly — never hand-build that route.
|
|
130
|
+
It also distinguishes the on-chain field write from off-chain SERVING: an on-chain write can succeed
|
|
131
|
+
while nothing can serve it. With no resolver base baked in at all, it warns there is no serving path
|
|
132
|
+
whatsoever. With one baked in, it probes whether a resolver actually answers for this token right
|
|
133
|
+
now (before the write, since the key itself doesn't exist yet) and warns if not — "the on-chain
|
|
134
|
+
document carries reserved fields only" is a real gap creators hit; the write landing is not proof
|
|
135
|
+
anything can serve it. Bare on-chain metadata cannot enumerate arbitrary field keys, so consumers
|
|
136
|
+
need a resolver to discover all attachments even when each locator is durable and hash-anchored.
|
|
123
137
|
|
|
124
138
|
PostParams are different: the parameter store enumerates schemas and values on-chain. Read schemas
|
|
125
139
|
with `state` and values with `tokens --json`. Parameters do not require a resolver merely to be
|
|
126
140
|
canonical or enumerable.
|
|
127
141
|
|
|
142
|
+
### Replacing an unlocked script
|
|
143
|
+
|
|
144
|
+
`abx replace-script <addr> --script <file>` ships a fix to a code project's on-chain program any
|
|
145
|
+
time before `abx lock-script`. It refuses outright — never warns and proceeds — on a locked script
|
|
146
|
+
or a target that isn't SeriesCode/EditionCode. It diffs by content against what's on-chain (an index
|
|
147
|
+
that already matches is never re-sent), folds every write and remove into ONE atomic transaction (so
|
|
148
|
+
a revert can never leave a half-applied script), and reads the completed script back to verify exact
|
|
149
|
+
reassembly before reporting success. Prefer this over hand-encoding `setScriptChunk` calls.
|
|
150
|
+
|
|
151
|
+
`--chunk-size <bytes>` overrides the default on-chain split size (~22 KB) — the same flag
|
|
152
|
+
`deploy-code` accepts (see [code.md](code.md#choose-the-runtime-lane)). A small value forces a
|
|
153
|
+
multi-chunk layout, which is the cheap way to exercise growing/shrinking a program across several
|
|
154
|
+
chunks (including the on-chain removal of surplus chunks when shrinking) without needing a large
|
|
155
|
+
real program.
|
|
156
|
+
|
|
128
157
|
### Refresh and URI events
|
|
129
158
|
|
|
130
159
|
`abx refresh` asks external marketplaces to fetch metadata again; it does not fix the metadata or
|
|
@@ -175,7 +204,29 @@ Important qualifications:
|
|
|
175
204
|
- A locked pointer to an upgradeable proxy fixes the address, not its behavior.
|
|
176
205
|
- A transfer-hook address represents a standing ability to veto mints/transfers. Freezing an empty
|
|
177
206
|
hook set is the proof that this power cannot later be added.
|
|
207
|
+
- `lock-field` targets one scope (token, or `--collection`); a token-scope value wins over a
|
|
208
|
+
collection-scope one when both are set. Locking a scope that ISN'T actually serving the value
|
|
209
|
+
freezes an empty or overridden slot, not what a viewer sees — the CLI refuses this by default and
|
|
210
|
+
names the correct command; only `--force-field` proceeds (with a loud warning, never silently).
|
|
211
|
+
Check `abx tokenuri --token <id>`'s `abx_provenance` (or just try the lock without `--force-field`)
|
|
212
|
+
before assuming a scope holds the value.
|
|
178
213
|
|
|
179
214
|
Use `abx verify` and direct state reads to enumerate what remains mutable. Describe the guarantee as
|
|
180
215
|
specific stored values and addresses that can no longer change; do not promise immutable output unless
|
|
181
216
|
every live input and external implementation has actually been bounded.
|
|
217
|
+
|
|
218
|
+
`abx state <address> --json` reports every lock above in one `locks` object — token/contract URI,
|
|
219
|
+
script, dependencies, param hooks, and the standard `METADATA_FIELD` set — each as `true` (frozen),
|
|
220
|
+
`false` (open), or `null` (unread; never report an unread lock as off). A project's own custom field
|
|
221
|
+
keys are real and independently lockable but are not enumerable from a bare head read; say so rather
|
|
222
|
+
than implying the field scan is exhaustive. Every lock is independent: never infer one lock's state
|
|
223
|
+
from another's.
|
|
224
|
+
|
|
225
|
+
`abx verify --json` separates two verdicts that must not be conflated: `ok`/`contentIntegrity` is
|
|
226
|
+
content-integrity ONLY (a hash mismatch, or none to check) and is the only field the exit code
|
|
227
|
+
reflects; `availability` is a sibling verdict for render/serve readiness (`available` / `partial` /
|
|
228
|
+
`unavailable` / `unknown`) that a missing render or an un-refetched `ipfs`/`arweave`/`url` locator
|
|
229
|
+
moves, while `ok` stays unaffected by design. Report both, never collapse one into the other.
|
|
230
|
+
`abx verify` also flags whether the project's stored `tokenURIRenderer`/generator pointers are the
|
|
231
|
+
CURRENT canonical singletons — a `false` here means an older-but-working deployment (or a fully
|
|
232
|
+
custom one), never "broken".
|
package/skill/reference/setup.md
CHANGED
|
@@ -70,6 +70,20 @@ The local projection and managed Arweave identity remain in `.abx-self-host/` un
|
|
|
70
70
|
`ABX_DATA_DIR` overrides it. That runtime directory is separate from the renamed `abx` skill and is
|
|
71
71
|
not being renamed. Back up the managed Arweave key with `abx storage backup-key`; never print it.
|
|
72
72
|
|
|
73
|
+
Every WRITE command (`deploy*`, `add`, `index`, `mint`, `set-*`, …) resolves `.abx-self-host`
|
|
74
|
+
strictly relative to the current directory — it never searches upward, so it never creates a
|
|
75
|
+
project's state somewhere unexpected. A handful of READ commands (`status`, `state`, `verify`,
|
|
76
|
+
`doctor`, `capabilities`, `tokens`, `tokenuri`, `contracturi`, `inspect`, `minter show`) DO search
|
|
77
|
+
upward, git-style, for an already-existing `.abx-self-host` if the current directory doesn't have
|
|
78
|
+
one of its own — bounded at the home directory, a `.git` root, or the filesystem root. Practical
|
|
79
|
+
consequence: `cd`-ing into a project's `contracts/` subdirectory before `abx status` still finds
|
|
80
|
+
that project; the same `cd` before `abx add`/`abx deploy*` creates a NEW, empty node right there
|
|
81
|
+
instead. If a status/verify/etc. answer looks emptier than expected, or a write seems to have
|
|
82
|
+
landed in the wrong place, run bare `abx status` — its `data: <path>` line names the exact
|
|
83
|
+
directory that answered, including a note when it was found by searching upward — or set
|
|
84
|
+
`ABX_DATA_DIR` explicitly rather than guessing. See [Local data
|
|
85
|
+
directory](https://docs.abx.io/docs/using-abx/self-hosting#local-data-directory) for the full rule.
|
|
86
|
+
|
|
73
87
|
## Choose one signing lane
|
|
74
88
|
|
|
75
89
|
Every write uses one of three lanes:
|