@artblocks/abx-cli 0.1.0-alpha.13 → 0.1.0-alpha.15
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/config.d.ts.map +1 -1
- package/dist/config.js +8 -8
- package/dist/config.js.map +1 -1
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +1 -1
- package/dist/flags.js.map +1 -1
- package/dist/main.js +271 -78
- package/dist/main.js.map +1 -1
- package/dist/onchain-uri.d.ts +23 -39
- package/dist/onchain-uri.d.ts.map +1 -1
- package/dist/onchain-uri.js +94 -86
- package/dist/onchain-uri.js.map +1 -1
- package/dist/ownerops.d.ts +29 -13
- package/dist/ownerops.d.ts.map +1 -1
- package/dist/ownerops.js +270 -127
- package/dist/ownerops.js.map +1 -1
- package/dist/preview.d.ts +8 -0
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +27 -2
- package/dist/preview.js.map +1 -1
- package/package.json +6 -6
- package/skill/SKILL.md +4 -2
- package/skill/reference/code-projects.md +5 -3
- package/skill/reference/creator-token.md +71 -0
- package/skill/reference/decisions.md +2 -2
- package/skill/reference/operating.md +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Royalty enforcement — opt-in ERC-721C (creator token)
|
|
2
|
+
|
|
3
|
+
[← back to SKILL.md](../SKILL.md)
|
|
4
|
+
|
|
5
|
+
**Read this ONLY because the creator brought it up** (royalty enforcement, "make OpenSea pay my
|
|
6
|
+
royalties", ERC-721C, transfer restrictions, a transfer validator). If they didn't, this file has no
|
|
7
|
+
business in the conversation: **plain ERC-721 is the default and the recommendation**, every deploy
|
|
8
|
+
flow already does the right thing with zero 721C flags, and offering enforcement unprompted reads as
|
|
9
|
+
a nudge toward a restricted asset. Never present `--721c` as a checklist item, a "should we also…",
|
|
10
|
+
or a row in the deploy readout for a creator who never asked.
|
|
11
|
+
|
|
12
|
+
## The stance (how to frame it when asked)
|
|
13
|
+
|
|
14
|
+
- **Plain ERC-721 (the default) is the more sovereign asset**: no third-party contract on the
|
|
15
|
+
transfer path, tradeable everywhere, nothing anyone — creator included — can later switch off.
|
|
16
|
+
ABX royalties are already on-chain via ERC-2981 (`abx set-royalty`); marketplaces *choose* whether
|
|
17
|
+
to honor them.
|
|
18
|
+
- **ERC-721C is enforcement for creators who specifically want it**: transfers are checked by a
|
|
19
|
+
validator contract, and sales that don't route through an authorized venue revert. It is a real
|
|
20
|
+
trade-off, decided at deploy, **permanently** — present it transparently, recommend it only when
|
|
21
|
+
the creator's stated goal is enforcement, and get an explicit yes before enrolling.
|
|
22
|
+
- **The honest market picture (2026) — say it, don't oversell**: enforcement via 721C effectively
|
|
23
|
+
means **OpenSea** plus venues on Limit Break's Payment Processor. OpenSea's own help docs say
|
|
24
|
+
enforcement limits sales to those venues; Magic Eden's EVM marketplace shut down March 2026, and
|
|
25
|
+
Blur never honored 721C. The trade: enforced royalties on OpenSea, in exchange for not trading on
|
|
26
|
+
venues the validator doesn't authorize.
|
|
27
|
+
|
|
28
|
+
## What enrolling does (the facts to relay)
|
|
29
|
+
|
|
30
|
+
- **Deploy-time, permanent, both directions.** A plain ABX 721 can **never** grow transfer
|
|
31
|
+
restrictions later (that's a feature — collectors of unenrolled tokens keep that promise forever),
|
|
32
|
+
and an enrolled one never sheds the standard. No retrofit exists; the only path to enrollment for
|
|
33
|
+
a live plain collection is a redeploy.
|
|
34
|
+
- **Suspend ≠ un-enroll.** The owner can re-point the validator or set it to zero (enforcement off,
|
|
35
|
+
token **stays** enrolled — the owner can re-enable any time). Collectors can see enrollment via
|
|
36
|
+
ERC-165, suspended or not.
|
|
37
|
+
- **Mints and burns are NEVER validated** — no validator policy can brick minting, the shared
|
|
38
|
+
fixed-price minter, or a delegated minter.
|
|
39
|
+
- **The recommended validator** (`--721c recommended`, or bare `--721c`) is OpenSea's
|
|
40
|
+
StrictAuthorizedTransferSecurityRegistry — under it, owner-initiated wallet-to-wallet transfers
|
|
41
|
+
pass; non-authorized operators revert. One decision, done.
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Enroll at deploy — all three deploy commands take the flag (absent = plain ERC-721, forever):
|
|
47
|
+
abx deploy|deploy-series|deploy-code … --721c [recommended|0x<validator>]
|
|
48
|
+
|
|
49
|
+
# Operate an ENROLLED collection (owner-only, any signing lane, --dry-run works):
|
|
50
|
+
abx set-transfer-validator <addr> 0x<validator> # re-point enforcement
|
|
51
|
+
abx set-transfer-validator <addr> none # suspend (stays enrolled)
|
|
52
|
+
abx set-transfer-validator <addr> recommended # the chain's recommended validator
|
|
53
|
+
|
|
54
|
+
abx state <addr> # shows a "721C validator" row ONLY when enrolled ("suspended" when zero)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Enrolling prints one plain statement of what enforcement means — relay it, don't embellish. An
|
|
58
|
+
un-enrolled deploy prints nothing about 721C.
|
|
59
|
+
|
|
60
|
+
## Refusals the CLI enforces (don't fight them; relay the reason)
|
|
61
|
+
|
|
62
|
+
- **`--721c none`/zero at deploy** — refused: a zero validator never enrolls, and "enrolled but
|
|
63
|
+
suspended" is not a deploy-time state. Plain ERC-721 is already the default; drop the flag.
|
|
64
|
+
- **`--721c recommended` on a chain with no known validator** — refused, naming the chains that have
|
|
65
|
+
one. Pass an explicit deployed validator address instead; never guess one.
|
|
66
|
+
- **A codeless validator address** — refused before any gas at deploy AND at re-point (the contract
|
|
67
|
+
would revert `InvalidTransferValidator()`); a mixed-case address must pass its EIP-55 checksum.
|
|
68
|
+
A real deploy also refuses to enroll blind when the RPC can't verify code (a dry-run defers it).
|
|
69
|
+
- **`set-transfer-validator` on a plain ERC-721** — refused up front: enrollment is a deploy-time
|
|
70
|
+
decision and this collection didn't enroll. Do not retry with different flags; if the creator
|
|
71
|
+
truly needs enforcement, that's a redeploy conversation.
|
|
@@ -26,13 +26,13 @@ placeholder. If you remember that limitation, it is gone.)
|
|
|
26
26
|
|
|
27
27
|
**Picking IPFS (or Arweave) does NOT mean running a server.** The `--onchain-uri --backend ipfs|arweave` path (pattern 2) bakes the image's public **gateway** URL into on-chain JSON — a pinning service's read endpoint (a *dedicated* Pinata gateway for IPFS), not a resolver you host. So when a creator chooses IPFS, **default to this no-server path** — image on IPFS, JSON on-chain, nothing to keep running (just keep the pin alive). You only need a **resolver** (pattern 3 — managed or self-hosted) if they want *freely editable* metadata. Never present IPFS as blocked on "a public URL" or "a server always online": the gateway belongs to the pinning service and the JSON lives on-chain. (The one real input IPFS needs is `PINATA_JWT` in `.env` for pinning — that's an API upload, not a host.)
|
|
28
28
|
|
|
29
|
-
**No-server tradeoff (patterns 1, 2, 4):** with the on-chain renderer only the *image* is off-chain — any **description / traits / animation_url live on-chain** (gas to write, permanent, lockable), vs a hosted resolver where they're free to edit. Cheap (a shared value is **one collection-scope field**, not one per token — the renderer falls back token→collection), but the creator should choose "no server" knowing their text metadata is on-chain.
|
|
29
|
+
**No-server tradeoff (patterns 1, 2, 4):** with the on-chain renderer only the *image* is off-chain — any **description / traits / animation_url, and every configured PostParam (served as `abx_params`), live on-chain** (gas to write, permanent, lockable), vs a hosted resolver where they're free to edit. Cheap (a shared value is **one collection-scope field**, not one per token — the renderer falls back token→collection), but the creator should choose "no server" knowing their text metadata is on-chain.
|
|
30
30
|
|
|
31
31
|
Get decisions 1–2 right before deploy (image commitment + resolver URL are written then; re-pointable, but):
|
|
32
32
|
|
|
33
33
|
**1. Storage permanence** — where bytes live. Not irreversible: bytes are content-addressed by their on-chain keccak, so start on one backend and move later (`abx verify` confirms the hash). Don't let it block a first deploy.
|
|
34
34
|
- `arweave` = pay-once permanent, no recurring fee. `cloud` (S3/R2) = durable, you maintain it. `ipfs` = decentralized, you pin it. `fs` = zero-config start, dies with the disk → move before it matters.
|
|
35
|
-
- **`arweave` is nearly as easy as `fs` for small art** — Turbo default: **under 100 KB free, no setup** (a managed `.abx-self-host/arweave-key.json` minted on first upload; back it up with `abx storage backup-key`). Choose per command with `--backend` (stateless, no config file)
|
|
35
|
+
- **`arweave` is nearly as easy as `fs` for small art** — Turbo default: **under 100 KB free, no setup** (a managed `.abx-self-host/arweave-key.json` minted on first upload; back it up with `abx storage backup-key`). Choose per command with `--backend` (stateless, no config file). **A backend missing its secret does NOT fall back to `fs`** — it fails: `cloud` refuses up front naming the missing values, and `ipfs` without `PINATA_JWT` resolves to **kubo mode against a local node** (`http://127.0.0.1:5001`), which fails at upload time if you aren't running one. Check with `abx storage show` (it prints the resolved backend *and* mode) before a real upload.
|
|
36
36
|
- **Who pays is a lane (`--storage-signer`)** — Turbo credits attach to an identity (managed key · `.env` key · browser wallet). **Before any top-up, check BOTH balances** (`abx storage balance --backend arweave` shows the managed key AND the wallet — spend the wallet's credits if present). On an upload error surface it verbatim — `…already been uploaded…` is *success* (dedup); don't reflexively top-up or switch to IPFS. Full lanes + failure playbook → [hosting.md](reference/hosting.md#arweave-via-turbo--the-easy-permanent-path-read-before-quoting-setup).
|
|
37
37
|
|
|
38
38
|
**2. Public host URL — and who runs the resolver** (**off-chain custody only**). Baked into `tokenURI` at deploy, so the CLI **refuses an off-chain deploy without a public URL** (`ABX_PUBLIC_BASE_URL` or `--public-base-url https://…`) and **never bakes localhost** (that token resolves for no one). No exceptions.
|
|
@@ -49,7 +49,7 @@ A token anchors **named, typed files**; the served JSON's **`artifacts`** array
|
|
|
49
49
|
- scope: `--token <id>` (default 0) or `--collection`; any lane; `--dry-run` previews the tx.
|
|
50
50
|
- **`artifacts` and `abx_provenance` are COMPUTED** — the resolver/renderer assembles them from your fields. `set-field`/`attach` refuse them: you never set the manifest, you attach the files it lists.
|
|
51
51
|
- **Verify** — a resolver serves the complete listing: `curl <resolver>/t/<chainId>/<addr>/<id>` shows the `artifacts` array, and `/t/<chainId>/<addr>/<id>/data/<key>` fetches (or 302-redirects to) each file. The attached bytes are stored on-chain + keccak-anchored either way.
|
|
52
|
-
- **On-chain vs resolver reach.** The complete listing (arbitrary attached keys) is a **resolver** surface — the EVM can't enumerate an open set of
|
|
52
|
+
- **On-chain vs resolver reach.** The complete listing (arbitrary attached keys) is a **resolver** surface — the EVM can't enumerate an open set of FIELD keys, so the bare on-chain `tokenURI` (on-chain renderer) emits **reserved fields only**. Attaching is durable + anchored regardless, but to *surface* extra files to consumers today, the project is served by a resolver. **PostParams are the exception**: the params store enumerates its own keys on-chain, so a bare `tokenURI` emits every set param under **`abx_params`** with no resolver in the picture. Say it to a creator as one line — *attachments always need a resolver; params never do.*
|
|
53
53
|
|
|
54
54
|
### Series-only owner ops
|
|
55
55
|
|