@artblocks/abx-cli 0.1.0-alpha.7 → 0.1.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -70,7 +70,7 @@ const SCHEMA_CATALOG = 'Types: Bool·Select·Uint256Range·Int256Range·DecimalR
70
70
  'Select needs options — key:Select[A|B|C]:Auth; a Range takes bounds — key:Uint256Range[0..100]:Auth. ' +
71
71
  'A palette collectors set = palette:HexColor:TokenOwner';
72
72
  import { uploadAndLocate } from './upload.js';
73
- import { assertChainId, discoverDeployBlock, deployFactory, deploySeriesFactory, deploySeries, deployOneOfOne, deployRenderer, predictRenderer, predictSeedSource, encodeTag, encodeFieldRenderer, isCodeProject, loadDotEnv, makePublicClient, makeWalletClient, oneOfOneImageAbi, oneOfOneImageFactoryAbi, seriesImageAbi, seriesImageFactoryAbi, abxMetadataRendererAbi, predictClone, probeRpcEndpoints, prepareDeployOneOfOne, prepareDeploySeries, reconstructProject, saltFor, saltGuard, resolveChain, DEFAULT_CHAIN_KEY, normalizeAttributes, parseTraitPairs, METADATA_FIELD as F, METADATA_REPRESENTATION as R, } from '@artblocks/abx-sdk';
73
+ import { assertChainId, discoverDeployBlock, deployFactory, deploySeriesFactory, deploySeries, deployOneOfOne, deployRenderer, predictRenderer, predictSeedSource, encodeTag, encodeFieldRenderer, isCodeProject, loadDotEnv, makePublicClient, makeWalletClient, oneOfOneImageAbi, oneOfOneImageFactoryAbi, seriesImageAbi, seriesImageFactoryAbi, abxMetadataRendererAbi, predictClone, probeRpcEndpoints, prepareDeployOneOfOne, prepareDeploySeries, reconstructProject, saltFor, saltGuard, resolveChain, explorerUrl, DEFAULT_CHAIN_KEY, normalizeAttributes, parseTraitPairs, METADATA_FIELD as F, METADATA_REPRESENTATION as R, } from '@artblocks/abx-sdk';
74
74
  import { SelfHostIndexer, SqliteStore } from '@artblocks/abx-indexer';
75
75
  import { artContentHash, currentRenderArtifact, generateArt, resolveBaseUrl, startChainWatcher, startTokenApiServer, verifyProject, watchIntervalMs, DEFAULT_PORT, } from '@artblocks/abx-token-api';
76
76
  import { ARWEAVE_FREE_UPLOAD_LIMIT, arweaveAddress, arweaveFunding, contentTypeFromPath, hashContent, resolveBackend, turboBalanceForAddress, turboUploadCostUsd, turboUploadWinc } from '@artblocks/abx-storage';
@@ -80,12 +80,10 @@ import { remoteAddProject, remoteRemoveProject } from './remote.js';
80
80
  import { buildMigrationPlan, repinNodeCustody, verifyParity } from './migrate.js';
81
81
  import { activeBackendId, arweaveKeyFilePath, backendResolution, ensureArweaveJwk, factoryAddress, seriesFactoryAddress, fixedPriceMinterAddress, loadArweaveJwk, loopbackBaseUrl, faucetHint, rendererAddress, storageOptions, storageSignerChoice, } from './config.js';
82
82
  const CHAIN = process.env.ABX_CHAIN ?? DEFAULT_CHAIN_KEY;
83
- // Block explorer base per chain (keyed by EIP-155 chainId), for the tx/address links the CLI prints.
84
- const EXPLORERS = {
85
- 11155111: 'https://sepolia.etherscan.io', // Sepolia
86
- 84532: 'https://sepolia.basescan.org', // Base Sepolia
87
- };
88
- const EXPLORER = EXPLORERS[resolveChain(CHAIN).id] ?? 'https://sepolia.etherscan.io';
83
+ // Block explorer base for the tx/address links the CLI prints. Derived from viem's chain metadata via
84
+ // the SDK (see explorerUrl) rather than a local table — this used to be a hand-maintained map, which is
85
+ // the same shape of bug that had the token-api dashboard sending every Base Sepolia link to Etherscan.
86
+ const EXPLORER = explorerUrl(resolveChain(CHAIN).id);
89
87
  // Product dimensions — what you can launch. One concrete contract exists today
90
88
  // (the 1/1 image); this table is the seam future implementations slot into, so
91
89
  // `abx deploy --type <dimension>` is stable while the contracts grow under it.
@@ -449,7 +447,7 @@ function refuseMissingFactory(kind, envVar, reason) {
449
447
  ` To deploy your OWN trust anchor instead (private chains, sandboxes — platforms won't recognize its clones), ` +
450
448
  `re-run with --bootstrap-factory.`);
451
449
  }
452
- async function ensureFactory(override, allowBootstrap = false) {
450
+ async function ensureFactory(override, allowBootstrap = false, quiet = false) {
453
451
  // Resolve the canonical factory from the shipped manifest (flag → env → manifest); on a chain
454
452
  // with no entry, deploy a fresh trust anchor and tell the operator how to reuse it.
455
453
  const known = factoryAddress(override);
@@ -459,7 +457,10 @@ async function ensureFactory(override, allowBootstrap = false) {
459
457
  const code = await publicClient.getCode({ address: known });
460
458
  if (code && code !== '0x') {
461
459
  if (await isCurrentFactory(publicClient, known)) {
462
- info(`using canonical factory ${EXPLORER}/address/${known}`);
460
+ // `quiet` suppresses only this happy-path line (the demo resolves the factory without making a
461
+ // teaching moment of it). Bootstrap/mismatch messages below always print — those matter.
462
+ if (!quiet)
463
+ info(`using canonical factory ${EXPLORER}/address/${known}`);
463
464
  return known;
464
465
  }
465
466
  if (!allowBootstrap)
@@ -1038,7 +1039,13 @@ async function cmdDeploy(flags, serveAfter) {
1038
1039
  if (signer)
1039
1040
  await warnUnfunded(publicClient, signer);
1040
1041
  }
1041
- step(serveAfter ? 'Who vouches for this token?' : 'Trust anchor');
1042
+ // `deploy` surfaces the trust anchor as a step; the demo does NOT. It briefly opened on "only this
1043
+ // factory can make a token that IS an ABX token", which is simply false — anything that follows the
1044
+ // protocol's event spine is an ABX token, and the factory is one way to get there, not the
1045
+ // definition of the thing. Rather than restate it more carefully, the demo skips it: a first-timer
1046
+ // does not need a provenance lecture before they have made anything.
1047
+ if (!serveAfter)
1048
+ step('Trust anchor');
1042
1049
  let factory;
1043
1050
  if (dryRun) {
1044
1051
  const existing = factoryAddress(flags.factory);
@@ -1051,16 +1058,7 @@ async function cmdDeploy(flags, serveAfter) {
1051
1058
  info(`would reuse canonical factory ${factory}`);
1052
1059
  }
1053
1060
  else {
1054
- factory = await ensureFactory(flags.factory, !!flags['bootstrap-factory']);
1055
- }
1056
- // The demo explains what it just did; `deploy` stays terse. The authenticity point is the least
1057
- // obvious thing about ABX and the easiest to get wrong, so it's worth spelling out — but in plain
1058
- // language, with the actual term parked in a dim aside for whoever wants to look it up.
1059
- if (serveAfter) {
1060
- console.log(` ${g('✦')} anyone can write a contract that ${bold('claims')} to be an ABX token`);
1061
- console.log(` ${g('✦')} only this one factory can make a token that ${bold('is')} one`);
1062
- info(dim('so "is this real?" is a yes/no question anyone can ask the chain — not a matter of trusting us'));
1063
- info(dim(`the factory answers it on-chain: isAbxClone(yourToken) · ${EXPLORER}/address/${factory}`));
1061
+ factory = await ensureFactory(flags.factory, !!flags['bootstrap-factory'], serveAfter);
1064
1062
  }
1065
1063
  // --onchain-uri: resolve tokenURI/contractURI fully on-chain via the canonical renderer
1066
1064
  // (the JSON is assembled from on-chain fields → no resolver needed, ever). The off-chain
@@ -1437,7 +1435,10 @@ async function cmdDeploy(flags, serveAfter) {
1437
1435
  if (serveAfter) {
1438
1436
  if (state.eventCount > 0)
1439
1437
  ok(`read ${bold(String(state.eventCount))} events straight off ${CHAIN} in ${elapsedMs}ms — no API key, no company's server`);
1440
- info(`it says: "${state.name}" · owned by ${state.owner} · ${state.isCanonical ? `${g('verified real')} ${dim('(that factory vouched for it)')}` : `${c.orange}unverified${c.reset}`}`);
1438
+ // "verified real" overstated it in the same way the removed trust-anchor step did factory
1439
+ // provenance is a fact about how this contract was made, not a verdict on whether a token counts
1440
+ // as ABX. Report the fact.
1441
+ info(`it says: "${state.name}" · owned by ${state.owner} · ${state.isCanonical ? g('made by the canonical factory') : dim('not factory-made')}`);
1441
1442
  info(dim(`optional features switched on: ${state.extensions.map((e) => e.name.replace(/^abx\.extension\./, '')).join(' · ') || 'none'}`));
1442
1443
  walkthroughSpine(state);
1443
1444
  }