@artblocks/abx-cli 0.1.0-alpha.31 → 0.1.0-alpha.33
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 +196 -0
- package/dist/capabilities.d.ts +94 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +135 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +25 -29
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/scaffold.d.ts +9 -1
- package/dist/commands/scaffold.d.ts.map +1 -1
- package/dist/commands/scaffold.js +59 -12
- package/dist/commands/scaffold.js.map +1 -1
- package/dist/flag-allowlists.d.ts.map +1 -1
- package/dist/flag-allowlists.js +2 -1
- package/dist/flag-allowlists.js.map +1 -1
- package/dist/flags.d.ts +0 -4
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +0 -6
- package/dist/flags.js.map +1 -1
- package/dist/main.js +36 -20
- package/dist/main.js.map +1 -1
- package/dist/ownerops.d.ts +33 -26
- package/dist/ownerops.d.ts.map +1 -1
- package/dist/ownerops.js +85 -56
- package/dist/ownerops.js.map +1 -1
- package/dist/update-check.d.ts +6 -1
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +40 -17
- package/dist/update-check.js.map +1 -1
- package/package.json +6 -6
- package/skill/SKILL.md +164 -499
- package/skill/agents/openai.yaml +4 -0
- package/skill/reference/capabilities.md +187 -0
- package/skill/reference/code.md +210 -0
- package/skill/reference/creator-token.md +90 -95
- package/skill/reference/deploy.md +167 -0
- package/skill/reference/diagnose.md +165 -0
- package/skill/reference/hosting.md +144 -126
- package/skill/reference/operate.md +181 -0
- package/skill/reference/setup.md +105 -62
- package/skill/reference/code-projects.md +0 -368
- package/skill/reference/decisions.md +0 -174
- package/skill/reference/operating.md +0 -220
- package/skill/reference/troubleshooting.md +0 -65
package/dist/ownerops.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* served state reflects the change. The agent picks the lane; the human only
|
|
7
7
|
* approves (wallet lane) or it's the env key (hot lane).
|
|
8
8
|
*/
|
|
9
|
-
import { MAX_ROYALTY_BPS, assertChainId, ensureChunkStore as sdkEnsureChunkStore, predictFixedPriceMinter, predictFixedPriceMinter1155, makeHotSender, makePublicClient, makeWalletClient, oneOfOneImageAbi, oneOfOneEditionAbi, seriesImageAbi, deployFixedPriceMinter, deployFixedPriceMinter1155, prepareConfigureSale, prepareConfigureSale1155, preparePurchase, preparePurchase1155, readSaleConfig, readSaleConfig1155, prepareEditionMint, prepareEditionTransfer, prepareSetMaxSupply, preparePingURI, prepareLockContractField, prepareLockContractURI, prepareLockTokenField, prepareLockTokenURI, prepareMint, mintedTokenIds, prepareSeriesMintMany, prepareSetMinter, prepareSetMaxInvocations, prepareSetPrimaryPayee, prepareSetPaused, prepareSetContractField, prepareSetContractURIBase, prepareSetContractURIOverride, prepareSetContractURIRenderer, prepareSetParamHooks, prepareSetParamSchema, prepareRetireParam, readParamSchema, PARAM_TYPES, prepareSetRoyalty, prepareReduceMaxRoyaltyBps, prepareSetTokenField, batchOps, prepareSetTokenURIBase, prepareSetTokenURIOverride, prepareSetTokenURIRenderer, prepareSetTransferValidator, prepareSetSeedSource, probeSeedSource, readSeedSource, predictSeedSource, getDeployment, prepareTransfer, prepareTransferOwnership, probeTransferValidator, readCreatorTokenStatus, resolveRecommendedTransferValidator, RECOMMENDED_TRANSFER_VALIDATOR, KNOWN_CHAIN_KEYS, resolveChain, resolveRpcUrl, redactRpcUrl, encodeTag, METADATA_FIELD as F, METADATA_REPRESENTATION as R, stageFieldContent, planStagedContent, exceedsOnchainSoftLimit, classifyOnchainReadSize, tokenUriGasEstimate, ONCHAIN_IMAGE_SOFT_LIMIT, ONCHAIN_PROJECT_SOFT_LIMIT, ONCHAIN_READ_WARN_BYTES,
|
|
9
|
+
import { MAX_ROYALTY_BPS, assertChainId, ensureChunkStore as sdkEnsureChunkStore, predictFixedPriceMinter, predictFixedPriceMinter1155, makeHotSender, makePublicClient, makeWalletClient, oneOfOneImageAbi, oneOfOneEditionAbi, seriesImageAbi, deployFixedPriceMinter, deployFixedPriceMinter1155, prepareConfigureSale, prepareConfigureSale1155, preparePurchase, preparePurchase1155, readSaleConfig, readSaleConfig1155, prepareEditionMint, prepareEditionTransfer, prepareSetMaxSupply, preparePingURI, prepareLockContractField, prepareLockContractURI, prepareLockTokenField, prepareLockTokenURI, prepareMint, mintedTokenIds, prepareSeriesMintMany, prepareSetMinter, prepareSetMaxInvocations, prepareSetPrimaryPayee, prepareSetPaused, prepareSetContractField, prepareSetContractURIBase, prepareSetContractURIOverride, prepareSetContractURIRenderer, prepareSetParamHooks, prepareSetParamSchema, prepareRetireParam, readParamSchema, PARAM_TYPES, prepareSetRoyalty, prepareReduceMaxRoyaltyBps, prepareSetTokenField, batchOps, prepareSetTokenURIBase, prepareSetTokenURIOverride, prepareSetTokenURIRenderer, prepareSetTransferValidator, prepareSetSeedSource, probeSeedSource, readSeedSource, predictSeedSource, getDeployment, prepareTransfer, prepareTransferOwnership, probeTransferValidator, readCreatorTokenStatus, resolveRecommendedTransferValidator, RECOMMENDED_TRANSFER_VALIDATOR, KNOWN_CHAIN_KEYS, resolveChain, resolveRpcUrl, redactRpcUrl, encodeTag, METADATA_FIELD as F, METADATA_REPRESENTATION as R, stageFieldContent, planStagedContent, exceedsOnchainSoftLimit, classifyOnchainReadSize, tokenUriGasEstimate, ONCHAIN_IMAGE_SOFT_LIMIT, ONCHAIN_PROJECT_SOFT_LIMIT, ONCHAIN_READ_WARN_BYTES, ETH_CALL_GAS_FLOOR, readableBytesAtGas, probeBestEthCallGasCap, } from '@artblocks/abx-sdk';
|
|
10
10
|
import { encodeScalarParam, encodeTag as encodeTagSdk, isAccepted, prepareConfigureTokenParam, prepareConfigureTokenParamData, prepareSetContractParam, prepareSetContractParamData, seriesCodeAbi, tryReadContract, } from '@artblocks/abx-sdk';
|
|
11
11
|
import { hasParamEnumeration, GATEWAY_FIELD, GATEWAY_FLOOR, gatewayPrefixFrom, readCollectionPolicy, readEnv } from '@artblocks/abx-sdk';
|
|
12
12
|
import { decodeFieldRenderer, encodeFieldRenderer, resolveGenerator, DEP_RESOLUTION, parseDependencyRef, prepareLockDependencies, prepareLockParamHooks, prepareLockScript, prepareRemoveLastDependency, prepareSetDependency, prepareSetDependencyRegistry, } from '@artblocks/abx-sdk';
|
|
@@ -23,12 +23,12 @@ import { openWalletSession } from './signer.js';
|
|
|
23
23
|
import { gatedSend, laneFromFlags } from './riskgate.js';
|
|
24
24
|
import { withJson } from './jsonout.js';
|
|
25
25
|
import { resolveRemote, serviceClient } from './remote.js';
|
|
26
|
-
import {
|
|
26
|
+
import { isDryRun, positionalArgs, unknownFlags, warnStrayFlags } from './flags.js';
|
|
27
27
|
import { parseSchemaSpecs, describeSchema } from './schema.js';
|
|
28
28
|
// Re-exported for main.ts (the on-chain-vs-off-chain cost model + the compression-mode type now
|
|
29
29
|
// live in the SDK's staging.ts, layered on planChunks/planContentTxs — see the comment at their
|
|
30
30
|
// definition below).
|
|
31
|
-
export { ONCHAIN_PROJECT_SOFT_LIMIT, ONCHAIN_READ_WARN_BYTES,
|
|
31
|
+
export { ONCHAIN_PROJECT_SOFT_LIMIT, ONCHAIN_READ_WARN_BYTES, ETH_CALL_GAS_FLOOR, tokenUriGasEstimate, readableBytesAtGas };
|
|
32
32
|
// ── ANSI (local) ─────────────────────────────────────────────────────────────
|
|
33
33
|
const C = { reset: '\x1b[0m', dim: '\x1b[2m', bold: '\x1b[1m', green: '\x1b[38;5;115m', yellow: '\x1b[38;5;221m' };
|
|
34
34
|
const dim = (s) => `${C.dim}${s}${C.reset}`;
|
|
@@ -382,11 +382,11 @@ export function parseHookAddress(role, v) {
|
|
|
382
382
|
}
|
|
383
383
|
/**
|
|
384
384
|
* `abx set-param-hooks <address> [--configure 0x|none] [--augment 0x|none] [--transfer 0x|none] [--clear]`
|
|
385
|
-
* — wire (or clear) a SeriesCode project's three param-lifecycle hooks. The contract has NO per-hook
|
|
385
|
+
* — wire (or clear) a SeriesCode/EditionCode project's three param-lifecycle hooks. The contract has NO per-hook
|
|
386
386
|
* setter (`setParamHooks` writes all three at once), so this READS the current trio (`paramHooks()`)
|
|
387
387
|
* and re-sends it with your changes applied: omit a role to KEEP it, pass an address to set it, or
|
|
388
|
-
* `none` to clear it (`--clear` clears all three). Owner-only, any lane, guards `--dry-run`.
|
|
389
|
-
* only —
|
|
388
|
+
* `none` to clear it (`--clear` clears all three). Owner-only, any lane, guards `--dry-run`. Code kinds
|
|
389
|
+
* only — static 1/1, Series, and edition kinds have no configurable params to hook. Bare (no flags) prints the current
|
|
390
390
|
* hooks and does nothing.
|
|
391
391
|
*/
|
|
392
392
|
export async function cmdSetParamHooks(address, flags) {
|
|
@@ -398,8 +398,8 @@ export async function cmdSetParamHooks(address, flags) {
|
|
|
398
398
|
// Refuse the contradictory combo rather than silently pick one (enforce, don't warn).
|
|
399
399
|
throw new Error(`--clear clears ALL three hooks; don't combine it with --${roleFlags.join('/--')}. Use either --clear, or per-role flags.`);
|
|
400
400
|
}
|
|
401
|
-
// Read the current trio FIRST — this doubles as the SeriesCode guard (paramHooks()
|
|
402
|
-
// the ConfigurableParams extension; a
|
|
401
|
+
// Read the current trio FIRST — this doubles as the SeriesCode/EditionCode guard (paramHooks()
|
|
402
|
+
// exists only on the ConfigurableParams extension; a static kind reverts "no data").
|
|
403
403
|
const publicClient = makePublicClient({ chainKey: CHAIN });
|
|
404
404
|
let current;
|
|
405
405
|
try {
|
|
@@ -1485,51 +1485,81 @@ export function sessionStagingSender(session) {
|
|
|
1485
1485
|
}
|
|
1486
1486
|
const kb = (n) => `${n < 10 * 1024 ? (n / 1024).toFixed(1) : Math.round(n / 1024)}KB`;
|
|
1487
1487
|
const mgas = (n) => `~${(n / 1_000_000).toFixed(0)}M gas`;
|
|
1488
|
-
/** The flag that overrides {@link guardOnChainSize}'s refusal — a creator who genuinely wants a
|
|
1489
|
-
* project no default RPC can read. Named for what accepting it means, not for the check it skips. */
|
|
1490
|
-
export const ALLOW_UNREADABLE_FLAG = 'allow-unreadable-onchain';
|
|
1491
1488
|
/**
|
|
1492
|
-
* The
|
|
1493
|
-
*
|
|
1494
|
-
*
|
|
1495
|
-
*
|
|
1496
|
-
* building, not the storage mechanism) — so the readable envelope is much tighter than the cost-sane one.
|
|
1489
|
+
* The measured `eth_call` gas allowance of the best configured endpoint, cached for the process.
|
|
1490
|
+
* `null` = could not be measured (an endpoint that rejects state overrides, or is unreachable),
|
|
1491
|
+
* which is a normal outcome and never blocks anything — the report degrades to the conservative
|
|
1492
|
+
* {@link ETH_CALL_GAS_FLOOR} instead.
|
|
1497
1493
|
*
|
|
1498
|
-
*
|
|
1499
|
-
*
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1494
|
+
* Measured once per run because it is a property of the endpoint, not of the content: a 40-file
|
|
1495
|
+
* Series should not fire 40 probes.
|
|
1496
|
+
*/
|
|
1497
|
+
let cachedGasCap;
|
|
1498
|
+
/** Measure (once) what the configured RPCs will actually serve an `eth_call`. Never throws. */
|
|
1499
|
+
export async function ensureRpcGasCap() {
|
|
1500
|
+
if (cachedGasCap === undefined) {
|
|
1501
|
+
try {
|
|
1502
|
+
cachedGasCap = await probeBestEthCallGasCap();
|
|
1503
|
+
}
|
|
1504
|
+
catch {
|
|
1505
|
+
cachedGasCap = { gasCap: null, label: null };
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return cachedGasCap;
|
|
1509
|
+
}
|
|
1510
|
+
/** Test seam: force the cached cap (or clear it with `undefined`). */
|
|
1511
|
+
export function __setRpcGasCapForTest(v) {
|
|
1512
|
+
cachedGasCap = v;
|
|
1513
|
+
}
|
|
1514
|
+
/**
|
|
1515
|
+
* Report what putting `bytesLen` of content on-chain costs, on both axes that matter — and REFUSE
|
|
1516
|
+
* NOTHING at any size.
|
|
1517
|
+
*
|
|
1518
|
+
* This used to throw past 100 KB. The threshold was reasoned from geth's `--rpc.gascap` default of
|
|
1519
|
+
* 50M minus a margin, on the theory that hosted providers commonly cap lower. Measured 2026-08-24,
|
|
1520
|
+
* they do not: 50M is the floor (publicnode, drpc), and `sepolia.base.org` — the default endpoint of
|
|
1521
|
+
* our default chain — serves 600M, good for ~729 KB. The refusal sat below every endpoint we could
|
|
1522
|
+
* find, so it blocked content all of them could read, on the chain we ship as the default.
|
|
1504
1523
|
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1524
|
+
* Two axes, and they fail differently:
|
|
1525
|
+
* • WRITE is chunked (22,000-byte SSTORE2 chunks across separate transactions), so no block gas
|
|
1526
|
+
* limit ever binds it. It is purely a money question at ~200 gas/byte.
|
|
1527
|
+
* • READ is one `eth_call`, and whether it succeeds is a property of WHOSE endpoint is asking.
|
|
1528
|
+
* Ours is measurable; a marketplace's is not, and that distinction survives into the output.
|
|
1529
|
+
*
|
|
1530
|
+
* Returns true if it printed anything.
|
|
1508
1531
|
*/
|
|
1509
|
-
export function guardOnChainSize(bytesLen, label
|
|
1510
|
-
const
|
|
1511
|
-
const
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1532
|
+
export async function guardOnChainSize(bytesLen, label) {
|
|
1533
|
+
const { gasCap, label: rpcLabel } = await ensureRpcGasCap();
|
|
1534
|
+
const verdict = classifyOnchainReadSize(bytesLen, gasCap);
|
|
1535
|
+
const readGas = tokenUriGasEstimate(bytesLen);
|
|
1536
|
+
const writeGas = bytesLen * 200;
|
|
1537
|
+
const floorKb = kb(readableBytesAtGas(ETH_CALL_GAS_FLOOR));
|
|
1538
|
+
const uncapped = gasCap === Number.POSITIVE_INFINITY;
|
|
1539
|
+
const capText = uncapped ? 'no eth_call cap at all' : `${mgas(gasCap ?? 0)}`;
|
|
1540
|
+
const servesText = uncapped ? 'any size this toolkit can write' : `~${kb(readableBytesAtGas(gasCap ?? 0))}`;
|
|
1541
|
+
// The route that dissolves the reach problem entirely, and the reason none of this is a refusal:
|
|
1542
|
+
// a resolver reads the on-chain bytes with ITS rpc and serves them as ordinary HTTP, so the
|
|
1543
|
+
// marketplace never makes the big eth_call. The bytes stay on-chain and permanent either way.
|
|
1544
|
+
const resolverRoute = ' Reach is fixable after the fact and the bytes are permanent regardless: a resolver reads on-chain content and serves it over plain HTTP' +
|
|
1545
|
+
' (abx deploy-resolver, or a hosted one), so marketplaces fetch a URL instead of making this call — point tokenURI at it with `abx set-renderer <addr> --off`.' +
|
|
1546
|
+
' On-chain storage is preservation; serving is a separate, swappable choice.';
|
|
1547
|
+
if (verdict === 'beyond-local-rpc') {
|
|
1548
|
+
console.log(yellow(` ⚠ ${label} is ${kb(bytesLen)} on-chain — reading tokenURI in ONE call costs ${mgas(readGas)}, past what your own RPC serves (${capText}${rpcLabel ? `, ${rpcLabel}` : ''}).`));
|
|
1549
|
+
console.log(dim(` Writing is unaffected — ${mgas(writeGas)}, chunked, and the bytes are permanent the moment they land.${resolverRoute}`));
|
|
1550
|
+
return true;
|
|
1551
|
+
}
|
|
1552
|
+
if (verdict === 'endpoint-dependent') {
|
|
1553
|
+
console.log(yellow(` ⚠ ${label} is ${kb(bytesLen)} on-chain — reading tokenURI in ONE call costs ${mgas(readGas)}, past the ${mgas(ETH_CALL_GAS_FLOOR)} floor every endpoint serves.`));
|
|
1554
|
+
console.log(dim(` ${gasCap != null ? `Measured just now, your RPC allows ${capText}${rpcLabel ? ` (${rpcLabel})` : ''} — it serves ${servesText}.` : `Your RPC's cap could not be measured, so the floor below is the reference.`} We can measure yours; we CANNOT know a marketplace's or an indexer's, and those are the ones that decide whether your token displays. On a 50M-capped provider the ceiling is ~${floorKb}, and past it they see a revert. Writing is unaffected: ${mgas(writeGas)}, chunked.${resolverRoute}`));
|
|
1524
1555
|
return true;
|
|
1525
1556
|
}
|
|
1526
|
-
if (
|
|
1527
|
-
console.log(
|
|
1528
|
-
console.log(dim(` That is served by a high-gas RPC but not by every hosted one, and it is past what another contract can spend inside a transaction. Under ~${kb(ONCHAIN_READ_WARN_BYTES)} of on-chain content per token is the routinely-readable range; off-chain custody (--backend arweave|ipfs|cloud) keeps the JSON on-chain and the read small.`));
|
|
1557
|
+
if (bytesLen >= ONCHAIN_READ_WARN_BYTES) {
|
|
1558
|
+
console.log(dim(` ${label} is ${kb(bytesLen)} on-chain — ${mgas(writeGas)} to write (chunked), ${mgas(readGas)} to read. Under the ${mgas(ETH_CALL_GAS_FLOOR)} every endpoint serves, so it renders anywhere.`));
|
|
1529
1559
|
return true;
|
|
1530
1560
|
}
|
|
1531
1561
|
if (exceedsOnchainSoftLimit(bytesLen)) {
|
|
1532
|
-
console.log(dim(` ${label} is ${kb(bytesLen)} — past ~${kb(ONCHAIN_IMAGE_SOFT_LIMIT)}/file on-chain costs more to write than off-chain (~200 gas/byte), so pick it for self-resolution, not for price. Reading tokenURI: ${
|
|
1562
|
+
console.log(dim(` ${label} is ${kb(bytesLen)} — past ~${kb(ONCHAIN_IMAGE_SOFT_LIMIT)}/file on-chain costs more to write than off-chain (~200 gas/byte), so pick it for self-resolution, not for price. Reading tokenURI: ${mgas(readGas)}.`));
|
|
1533
1563
|
return true;
|
|
1534
1564
|
}
|
|
1535
1565
|
return false;
|
|
@@ -1579,9 +1609,8 @@ function planTxLine(p, finalLabel) {
|
|
|
1579
1609
|
* These store writes use the env key (the data contracts are ownerless); the owner only
|
|
1580
1610
|
* signs the field set that references the manifest.
|
|
1581
1611
|
*/
|
|
1582
|
-
async function putContentOnChain(bytes, compress, field, send, finalLabel = '1 owner field-set', store
|
|
1583
|
-
|
|
1584
|
-
guardOnChainSize(bytes.length, `'${field}'`, allowUnreadable);
|
|
1612
|
+
async function putContentOnChain(bytes, compress, field, send, finalLabel = '1 owner field-set', store) {
|
|
1613
|
+
await guardOnChainSize(bytes.length, `'${field}'`);
|
|
1585
1614
|
const content = compress === 'gzip' ? new Uint8Array(gzipSync(bytes)) : new Uint8Array(bytes);
|
|
1586
1615
|
const publicClient = makePublicClient({ chainKey: CHAIN });
|
|
1587
1616
|
return stageFieldContent({
|
|
@@ -1618,13 +1647,13 @@ export function refusePrewrappedImage(bytes, label) {
|
|
|
1618
1647
|
* true count instead of leaving the agent to guess). The final tx here is the deploy that
|
|
1619
1648
|
* bakes in the reader field, so the count is staging tx(s) + the deploy.
|
|
1620
1649
|
*/
|
|
1621
|
-
export function previewImageStaging(imagePath, compress
|
|
1650
|
+
export async function previewImageStaging(imagePath, compress) {
|
|
1622
1651
|
const bytes = readFileSync(resolvePath(imagePath));
|
|
1623
1652
|
refusePrewrappedImage(bytes, basename(resolvePath(imagePath)));
|
|
1624
1653
|
const p = computeContentPlan(bytes, compress);
|
|
1625
1654
|
// The gate runs on the dry-run too: a refusal a creator only meets after the first staging tx has
|
|
1626
1655
|
// landed is a refusal that already cost them gas.
|
|
1627
|
-
guardOnChainSize(bytes.length, basename(resolvePath(imagePath))
|
|
1656
|
+
await guardOnChainSize(bytes.length, basename(resolvePath(imagePath)));
|
|
1628
1657
|
return (`would stage ${basename(resolvePath(imagePath))} on-chain (chunk store): ` +
|
|
1629
1658
|
`${planSizeLine(bytes.length, p, compress)} as ${p.representation}; ` +
|
|
1630
1659
|
`${planTxLine(p, '1 deploy (bakes the reader field + mints)')}`);
|
|
@@ -1636,10 +1665,10 @@ export function previewImageStaging(imagePath, compress, allowUnreadable = false
|
|
|
1636
1665
|
* image" is just those staging tx(s) + the single deploy — no post-deploy `set-field`.
|
|
1637
1666
|
* The manifest is deployer-independent, so this is computed once and reused for any signer.
|
|
1638
1667
|
*/
|
|
1639
|
-
export async function stageImageField(imagePath, compress, send
|
|
1668
|
+
export async function stageImageField(imagePath, compress, send) {
|
|
1640
1669
|
const bytes = readFileSync(resolvePath(imagePath));
|
|
1641
1670
|
refusePrewrappedImage(bytes, basename(resolvePath(imagePath)));
|
|
1642
|
-
const { value, representation } = await putContentOnChain(bytes, compress, 'image', send, '1 deploy (bakes the reader field + mints)'
|
|
1671
|
+
const { value, representation } = await putContentOnChain(bytes, compress, 'image', send, '1 deploy (bakes the reader field + mints)');
|
|
1643
1672
|
return {
|
|
1644
1673
|
field: { field: encodeTag(F.image), representation: encodeTag(representation), value },
|
|
1645
1674
|
note: `image: ${bytes.length}B staged ON-CHAIN via reader (${representation}) — baked into the deploy`,
|
|
@@ -1652,12 +1681,12 @@ export async function stageImageField(imagePath, compress, send, allowUnreadable
|
|
|
1652
1681
|
* Each field still points at its own manifest, so each token's work is independent; they just
|
|
1653
1682
|
* share the store contract. Returns the fields in input order (token order).
|
|
1654
1683
|
*/
|
|
1655
|
-
export async function stageImageFieldsBatch(imagePaths, compress, send, storeOverride
|
|
1684
|
+
export async function stageImageFieldsBatch(imagePaths, compress, send, storeOverride) {
|
|
1656
1685
|
const store = await ensureChunkStore(send, storeOverride);
|
|
1657
1686
|
const fields = [];
|
|
1658
1687
|
for (const imagePath of imagePaths) {
|
|
1659
1688
|
const bytes = readFileSync(resolvePath(imagePath));
|
|
1660
|
-
const { value, representation } = await putContentOnChain(bytes, compress, 'image', send, '1 deploy (bakes the reader fields + mints)', store
|
|
1689
|
+
const { value, representation } = await putContentOnChain(bytes, compress, 'image', send, '1 deploy (bakes the reader fields + mints)', store);
|
|
1661
1690
|
fields.push({ field: encodeTag(F.image), representation: encodeTag(representation), value });
|
|
1662
1691
|
}
|
|
1663
1692
|
return { fields, store };
|
|
@@ -1831,7 +1860,7 @@ export async function cmdSetField(address, flags) {
|
|
|
1831
1860
|
const bytes = readFileSync(resolvePath(flags.file));
|
|
1832
1861
|
const p = computeContentPlan(bytes, parseCompress(flags.compress));
|
|
1833
1862
|
// Same render-gas gate the real path applies, so a refusal costs a dry run rather than gas.
|
|
1834
|
-
guardOnChainSize(bytes.length, `'${field}'
|
|
1863
|
+
await guardOnChainSize(bytes.length, `'${field}'`);
|
|
1835
1864
|
console.log(`\n ${bold('◆ set-field ' + field)} ${dim('(dry run — nothing staged or sent)')}`);
|
|
1836
1865
|
console.log(` ${dim('scope'.padEnd(12))} ${collection ? 'collection' : `token #${flags.token ?? '0'}`}`);
|
|
1837
1866
|
console.log(` ${planSizeLine(bytes.length, p, parseCompress(flags.compress))}`);
|
|
@@ -1863,7 +1892,7 @@ export async function cmdSetField(address, flags) {
|
|
|
1863
1892
|
});
|
|
1864
1893
|
try {
|
|
1865
1894
|
await session.connect();
|
|
1866
|
-
const { value, representation } = await putContentOnChain(bytes, compress, field, sessionStagingSender(session)
|
|
1895
|
+
const { value, representation } = await putContentOnChain(bytes, compress, field, sessionStagingSender(session));
|
|
1867
1896
|
await session.send(buildTx(value, representation));
|
|
1868
1897
|
}
|
|
1869
1898
|
finally {
|
|
@@ -1877,7 +1906,7 @@ export async function cmdSetField(address, flags) {
|
|
|
1877
1906
|
let representation;
|
|
1878
1907
|
if (staging) {
|
|
1879
1908
|
const compress = parseCompress(flags.compress);
|
|
1880
|
-
({ value, representation } = await putContentOnChain(readFileSync(resolvePath(flags.file)), compress, field, envStagingSender()
|
|
1909
|
+
({ value, representation } = await putContentOnChain(readFileSync(resolvePath(flags.file)), compress, field, envStagingSender()));
|
|
1881
1910
|
}
|
|
1882
1911
|
else if (flags.text && flags.text !== 'true') {
|
|
1883
1912
|
if (field === 'image')
|