@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
|
@@ -1,182 +1,200 @@
|
|
|
1
|
-
# Hosting
|
|
1
|
+
# Hosting, storage, and remote operation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use this reference when a project needs public resolution, managed remote service, creator-operated
|
|
4
|
+
resolver/effects, storage configuration, render publication, lifecycle monitoring, or migration.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## Contents
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- [First decide whether a host exists](#first-decide-whether-a-host-exists)
|
|
9
|
+
- [Choose managed or creator-operated resolution](#choose-managed-or-creator-operated-resolution)
|
|
10
|
+
- [Choose storage independently](#choose-storage-independently)
|
|
11
|
+
- [Operate resolver and effects services](#operate-resolver-and-effects-services)
|
|
12
|
+
- [Use lifecycle states](#use-lifecycle-states)
|
|
13
|
+
- [Migrate without losing canonicity](#migrate-without-losing-canonicity)
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
|---|---|---|---|
|
|
11
|
-
| **`fs`** (default) | Operator-held, local disk | — | — |
|
|
12
|
-
| **`cloud`** | S3-compatible: AWS S3 / R2 / B2 / MinIO | `--backend cloud --endpoint <url> --bucket <b> --region <r>` (or `ABX_S3_ENDPOINT`/`ABX_S3_BUCKET`/`ABX_S3_REGION`) | `ABX_S3_ACCESS_KEY_ID`, `ABX_S3_SECRET_ACCESS_KEY` |
|
|
13
|
-
| **`ipfs`** | Decentralized (CID) | kubo: `--backend ipfs --mode kubo --api-url http://127.0.0.1:5001 --gateway http://127.0.0.1:8080` · pinata: `--backend ipfs --mode pinata --gateway https://<you>.mypinata.cloud` | `PINATA_JWT` (pinata mode) |
|
|
14
|
-
| **`arweave`** | Pay-once permanent | `--backend arweave` (Turbo default; or `ABX_STORAGE_BACKEND=arweave`) | the Turbo key (auto-managed) |
|
|
15
|
+
## First decide whether a host exists
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
Do not ask “where should we host?” until the public surfaces require a host.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|---|---|
|
|
20
|
-
| `ipfs` | `https://ipfs.io/ipfs/` |
|
|
21
|
-
| `arweave` | `https://arweave.net/` |
|
|
19
|
+
No ABX resolver is required when:
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
- static bytes and metadata resolve on-chain;
|
|
22
|
+
- on-chain JSON points at public Arweave/IPFS/cloud media;
|
|
23
|
+
- Solidity field renderers compute every required metadata surface on-chain.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
A resolver is useful or required when:
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
- metadata must remain operationally editable;
|
|
28
|
+
- a JavaScript/build project needs a hosted live document;
|
|
29
|
+
- marketplace stills/traits are produced by an effects runner;
|
|
30
|
+
- attached artifacts must be enumerated and fetched;
|
|
31
|
+
- large on-chain content needs an HTTP reader in front of endpoint-dependent `eth_call` execution;
|
|
32
|
+
- a project needs indexed status/dashboard/API surfaces.
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
Storage can be on-chain while resolution is hosted, or external while metadata resolution is
|
|
35
|
+
on-chain. Keep those axes separate.
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
- **`arweave`** — pay once, permanent. Arweave's storage endowment funds retention for centuries (~200 years at current economics); the bytes resolve as long as the network and any gateway are up. Nothing to renew, nothing to re-pin. The strongest "never lapses" custody.
|
|
33
|
-
- **`ipfs`** — **only as durable as the pin.** The token's `image` resolves through the creator's Pinata (or kubo) gateway; if the pin is dropped — account lapses, billing fails, node goes offline — the bytes can become unretrievable and the image breaks. IPFS is *content-addressed* (the CID proves integrity) but **not self-storing** (someone must keep hosting the bytes). Tell the creator plainly: with IPFS they've taken on an ongoing pinning responsibility. Mitigate by pinning to a durable service and not letting it lapse — or prefer `arweave` and be done.
|
|
34
|
-
- **`cloud`/`fs`** — durable only while the creator maintains the bucket/disk; centralized, mutable.
|
|
35
|
-
- **Backends are swappable** — the on-chain keccak is the anchor, so bytes are portable: re-upload to the new backend and re-point the `image` field (`abx set-field <addr> --field image …`), then `abx verify` confirms the served bytes still match the on-chain hash. For a hosted-resolver project, `abx migrate` re-pins node-custody images to a durable backend as part of the move (see [operating.md](operating.md)). Re-pointing is an owner-signed tx, so keep the owner wallet secure. Starting on `fs`/`ipfs` and moving to `arweave` later is fine; just don't let an interim backend lapse before the move.
|
|
37
|
+
## Choose managed or creator-operated resolution
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
Both routes implement the same public resolver contract. The token holds a base URI; the operator
|
|
40
|
+
reconstructs canonical state from chain and serves metadata/live/data surfaces.
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
### Managed remote
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
- **`--storage-signer eth`** — reuse the **`.env` EVM signing key** (`ABX_DEPLOYER_PK`) as the Turbo identity. Its ETH address holds the credits, so credits funded on that wallet's Turbo balance are spendable. Hot lane (key in `.env`).
|
|
44
|
-
- **`--storage-signer eth` + `--sign`** — the **browser wallet** signs each upload data-item via `personal_sign` (no gas, no funds move; the upload is paid from the wallet's Turbo credits), in the same sign session as the deploy tx. The key never leaves the wallet. *(New; the mechanism matches arbundles' `InjectedEthereumSigner` and is unit-tested at the CLI↔page contract, but the live MetaMask↔Turbo path wants a manual smoke test. If a live upload misbehaves, fall back to `--storage-signer eth` with a key, or fund the managed key.)*
|
|
45
|
-
- **Under 100 KB → free**, permanent, zero setup. The CLI prints this from the file size (in `--dry-run` too).
|
|
46
|
-
- **Over 100 KB → prepaid credits, one-time.** `abx storage balance` shows the funded address + credits; `abx storage topup --usd <n>` returns a Stripe checkout link. A **pre-upload balance guard** stops *before* the deploy if credits are short — printing the address + fund options — so a shortfall never fails mid-deploy after txs already landed. One-time payment, no recurring fee, nothing to re-pin (contrast `cloud`/`ipfs`). Credits are non-refundable.
|
|
47
|
-
- **Credits attach to the IDENTITY, not "you".** With the default `arweave` lane, a top-up funds the CLI-managed Arweave address (derived from the key file) — a *different* identity from the ETH wallet used to sign deploys. So a fresh managed key shows **0 credits even if the creator "funded Turbo before"**: those old credits sit on whatever identity they funded. If they funded their **ETH wallet's** Turbo balance, reach it with `--storage-signer eth` (key) or `--storage-signer eth --sign` (browser). If they hold a funded **Arweave** key, import it via `ARWEAVE_JWK`/`ABX_ARWEAVE_KEY_FILE`.
|
|
48
|
-
- **If the Stripe link fails**, fall back to Turbo's hosted top-up (`https://turbo-topup.com`) and fund the **exact address `abx storage topup` prints** (it accepts a recipient address, so credits still land on the intended identity). Not ideal, but it beats abandoning Arweave for IPFS on a link glitch.
|
|
44
|
+
Use a named remote already configured in the environment rather than standing up duplicate
|
|
45
|
+
infrastructure. Start with:
|
|
49
46
|
|
|
50
|
-
|
|
47
|
+
```bash
|
|
48
|
+
abx remote <name>
|
|
49
|
+
```
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
This reports the service descriptor, supported chains, rendering policy, and authentication status.
|
|
52
|
+
Do not infer provider capability from its hostname or marketing page.
|
|
53
53
|
|
|
54
|
-
-
|
|
55
|
-
- **"…has already been uploaded to this service!" is SUCCESS, not failure.** Turbo deduplicates identical bytes (same signer + bytes → same data-item id), so re-uploads (a retry, a redeploy, two identical images) return that sentence instead of JSON. The CLI treats it as the existing txid and continues. If you ever see it surface as an error, the toolkit is stale — don't work around it.
|
|
56
|
-
- **Check BOTH balances before concluding "needs funding."** `abx storage balance --backend arweave` prints the managed key's balance **and** the deployer wallet's Turbo balance (Turbo exposes balance-by-address publicly — no key needed). The managed key showing 0 does NOT mean "top up": if the **wallet** has credits, use them (`--storage-signer eth`, or `+ --sign` for a browser wallet). The pre-upload funds guard does this check for you and recommends the wallet lane when it applies — checking only the managed key's 0 and pushing a top-up is the classic wrong turn.
|
|
57
|
-
- **Don't reflexively push a $5 top-up or "switch to IPFS."** Both throw away what the creator chose (their funded wallet credits; permanence). Only top up if *neither* the managed key nor the wallet can cover the bytes — and **back up the managed key first** (`abx storage backup-key --out <path>`), since it will hold the credits you buy. Only suggest IPFS if they ask or Arweave is truly unavailable.
|
|
58
|
-
- **A blind retry re-signs the same bytes → same dedup reply.** Retry only after you've identified and fixed the actual cause.
|
|
59
|
-
- **Gateway swappable, integrity independent.** The on-chain keccak256 (or the CID itself) is the anchor; `arweave.net` is the default gateway (`--gateway` at upload, `abx set-gateway` for serving). A gateway issue is a re-point, never a lost asset.
|
|
60
|
-
- **Provider swappable.** `--provider http-bundler --upload-url <bundler>` uses a dep-free token-authed endpoint you run (secret `ARWEAVE_UPLOAD_TOKEN`); funding then means "fund the wallet directly" (only Turbo tracks credits). Default to Turbo unless asked.
|
|
54
|
+
Interpret control-plane failures precisely:
|
|
61
55
|
|
|
62
|
-
|
|
56
|
+
- `401` means the supplied token is missing, stale, or invalid; replace the credential.
|
|
57
|
+
- `403` means the credential is recognized but lacks permission for this chain/project; fix provider
|
|
58
|
+
scope rather than rotating keys blindly.
|
|
59
|
+
- a conformance failure means the service contract is incomplete or incompatible; do not register a
|
|
60
|
+
production launch until the failing assertion is understood.
|
|
63
61
|
|
|
64
|
-
|
|
62
|
+
Register or operate a project using `--remote <name>` and monitor with `abx status --remote <name>`.
|
|
63
|
+
If the provider advertises managed rendering, confirm it for the active chain/project. Otherwise the
|
|
64
|
+
creator still owns the effects and storage path.
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- **`cloud` (S3/R2/CDN)** works the same, but the signed-API host (`--endpoint`/`ABX_S3_ENDPOINT`, where uploads go) and the public read host (`--public-base`/`ABX_S3_PUBLIC_BASE`, also what `deploy-code --image-base` takes) are **different hosts by design** — one auth-only, one public (R2's own API endpoint is never public; its public URL is a separate `pub-<hash>.r2.dev` or custom domain you enable). **`abx storage show --check` proves the two agree** — a real PUT through the API + an unsigned GET through the public base (`abx doctor` runs the same probe). Files upload under a content-derived prefix → `<publicBase>/<prefix>/{id}.png`. **Caveat:** S3 is centralized, mutable, not content-addressed (no CID/txid root). Good if the creator already runs a bucket/CDN; IPFS/Arweave are the trustless/permanent options.
|
|
69
|
-
- **Integrity** (IPFS/Arweave) comes from the content-addressed root (CID / manifest txid), not a per-token keccak. The gateway host is baked on-chain → moving gateways is a `set-field` (bytes stay put). Prefer a **dedicated** gateway.
|
|
70
|
-
- **`url-template`** is a first-class representation ([spec](../../../../specs/protocol/onchain-metadata.md)); set by hand with `abx set-field <addr> --collection --field image --representation url-template --text "<gateway>/ipfs/<cid>/{id}.png"` then `abx set-renderer <addr>`.
|
|
66
|
+
Never invent a provider, signup flow, price, quota, or key source. If no configured provider exists,
|
|
67
|
+
offer the fully supported creator-operated route.
|
|
71
68
|
|
|
72
|
-
|
|
69
|
+
### Creator-operated resolver
|
|
73
70
|
|
|
74
|
-
|
|
71
|
+
Use `abx deploy-resolver --provider …` to generate hosting artifacts for the selected platform. The
|
|
72
|
+
creator owns the cloud account, domain, secrets, monitoring, and upgrades. Review the generated
|
|
73
|
+
configuration before deploying it; do not copy repository `.env` wholesale.
|
|
75
74
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
- **The API key is the human's step — a membrane ask, never a chat paste.** Say: *"This provider covers your chain and manages rendering. You'll need an API key from `<signupUrl>` — put it in `.env` as `ABX_REMOTE_<NAME>_TOKEN` (never paste it in chat) and I'll do the rest."* Then verify with `abx remote <name>`: it lists the projects visible to the key. **401** = the key is missing/wrong (check the var, rotate at the provider). **403** = the key is valid but not authorized for this contract/chain — provider-side scoping, not a typo; don't retry-loop, check the provider dashboard.
|
|
80
|
-
- **The exit is guaranteed by the interface**, not by the provider's goodwill: registration is never load-bearing for resolution, and `abx migrate --from <provider> --to <anywhere>` reads only the provider's *public* endpoints — leaving is one config change plus (for a provider-hostname base) one on-chain re-point.
|
|
81
|
-
- **Honesty:** no default provider is baked into the CLI, the SDK, or this skill, and the provider market is only starting to form. A creator with a provider key (or a named remote already in `.env`) should use it; otherwise **self-hosting (next section) is the fully-supported path today** and what the rest of this file assumes.
|
|
75
|
+
The host needs read-only RPC access, storage access where applicable, and a stable public URL. Keep
|
|
76
|
+
signing keys off the resolver. Use the project/state API and on-chain reconstruction instead of a
|
|
77
|
+
private source-of-truth database.
|
|
82
78
|
|
|
83
|
-
|
|
79
|
+
Prefer a creator-controlled domain in the on-chain base URI. Provider-specific hostnames work, but a
|
|
80
|
+
custom domain makes migration a DNS operation rather than a contract operation. Tunnels and localhost
|
|
81
|
+
are preview-only and must never be baked into a launch.
|
|
84
82
|
|
|
85
|
-
|
|
83
|
+
After provisioning:
|
|
86
84
|
|
|
87
|
-
|
|
85
|
+
1. Run health/conformance checks.
|
|
86
|
+
2. Register the contract with its deploy block when known.
|
|
87
|
+
3. Wait for indexing readiness.
|
|
88
|
+
4. Fetch contract and token metadata through the public URL.
|
|
89
|
+
5. Verify byte commitments with `abx verify`.
|
|
90
|
+
6. Mint only after required token-specific surfaces can become ready.
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
## Choose storage independently
|
|
90
93
|
|
|
91
|
-
|
|
94
|
+
Storage is stateless configuration selected per command or through environment defaults. Inspect the
|
|
95
|
+
resolved choice with:
|
|
92
96
|
|
|
93
|
-
|
|
97
|
+
```bash
|
|
98
|
+
abx storage show --check
|
|
99
|
+
```
|
|
94
100
|
|
|
95
|
-
|
|
101
|
+
| Backend | Good for | Operator responsibility |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `fs` | local development | disk durability and no public reach by default |
|
|
104
|
+
| `cloud` | mutable/fast public assets | bucket, auth endpoint, public read base/CDN, retention |
|
|
105
|
+
| `ipfs` | content-addressed distribution | pinning and public gateway availability |
|
|
106
|
+
| `arweave` | permanent external custody | upload identity/credits and propagation |
|
|
96
107
|
|
|
97
|
-
|
|
108
|
+
Never silently fall back to `fs` when a selected backend is incomplete. Fix the missing configuration
|
|
109
|
+
or change the plan explicitly.
|
|
98
110
|
|
|
99
|
-
|
|
111
|
+
### Cloud
|
|
100
112
|
|
|
101
|
-
|
|
102
|
-
|
|
113
|
+
Separate the authenticated S3/R2 API endpoint used for writes from the public HTTP base used by
|
|
114
|
+
collectors. An R2 S3 endpoint is not a marketplace image URL. `--check` performs a real write/read
|
|
115
|
+
round trip through the public base; require it to pass.
|
|
103
116
|
|
|
104
|
-
|
|
117
|
+
### IPFS
|
|
105
118
|
|
|
106
|
-
|
|
119
|
+
Pinning success and gateway retrieval are distinct. Use a durable pinning service and public gateway
|
|
120
|
+
for launches. A local kubo node is suitable for development only. The on-chain field may hold the
|
|
121
|
+
bare CID while a collection gateway preference chooses the serving prefix; `abx set-gateway` can
|
|
122
|
+
change that prefix without changing the content.
|
|
107
123
|
|
|
108
|
-
|
|
109
|
-
- **Local resolver** (`abx serve` here): a local `deploy`/`add` already indexed it — done.
|
|
110
|
-
- **Remote resolver** (baked URL is remote): after deploy run **`abx add <clone> --remote [name|url]`** to register + index it on the node (bare `--remote` defaults to `ABX_PUBLIC_BASE_URL` + `ABX_REMOTE_SELF_TOKEN`; a named remote uses its own `ABX_REMOTE_<NAME>_TOKEN`). Also **bridges** what the node can't derive: the durable `ipfs://`/`ar://` locator and off-chain traits. Post-deploy nudge (after a deferred mint) is **`abx index <clone> --remote`** (idempotent). Remove with **`abx forget <clone> --remote`**. Every remote command prints `REMOTE → <url>`.
|
|
124
|
+
### Arweave
|
|
111
125
|
|
|
112
|
-
|
|
126
|
+
The accepted upload and a retrievable gateway object are separate lifecycle states. Use
|
|
127
|
+
`abx storage status <locator> --json`; wait for `ready` instead of uploading duplicates during
|
|
128
|
+
propagation. Upload deduplication is success, not an instruction to top up or switch backends.
|
|
113
129
|
|
|
114
|
-
|
|
130
|
+
Turbo credits attach to the signing identity. `abx storage balance` reports the managed identity and
|
|
131
|
+
wallet-related lanes; choose the intended payer before funding. Back up the managed key using the
|
|
132
|
+
dedicated command and never expose the JWK.
|
|
115
133
|
|
|
116
|
-
|
|
134
|
+
### Publication bridge
|
|
117
135
|
|
|
118
|
-
|
|
136
|
+
An effects runner stores rendered bytes, then publishes their locator to the resolver. The resolver
|
|
137
|
+
usually redirects to that public object rather than proxying it. Therefore the storage backend must be
|
|
138
|
+
reachable from both the runner and collectors. A local `fs` output from one machine is orphaned when
|
|
139
|
+
the public resolver runs elsewhere.
|
|
119
140
|
|
|
120
|
-
|
|
121
|
-
| --- | --- | --- |
|
|
122
|
-
| `queued` / `backfilling` | accepted, catching up (registration is already durable) | **wait** — poll, don't re-add |
|
|
123
|
-
| `live` | caught up, tracking head | done |
|
|
124
|
-
| `stale` | was live, now lagging — **still serving** old state | usually the service's RPC; investigate if it sticks |
|
|
125
|
-
| `failed` | catch-up errored; retried with backoff | read the **class** (below); the registration survived |
|
|
141
|
+
## Operate resolver and effects services
|
|
126
142
|
|
|
127
|
-
|
|
143
|
+
The resolver handles indexed state and public metadata/live/data routes. The effects service executes
|
|
144
|
+
programs and publishes stills/traits. Deploy them separately so heavy browser work does not destabilize
|
|
145
|
+
metadata reads.
|
|
128
146
|
|
|
129
|
-
|
|
147
|
+
For an active JavaScript sale, run continuous effects. For a fixed supply or repair, a one-shot render
|
|
148
|
+
may be sufficient. With an on-chain Solidity image renderer, no effects service is needed for the
|
|
149
|
+
image; do not deploy infrastructure merely because the collection is a code contract.
|
|
130
150
|
|
|
131
|
-
|
|
151
|
+
Protect public effects endpoints with the generated token. An unauthenticated force-render endpoint
|
|
152
|
+
can burn compute and storage. Keep resolver admin/effects credentials separate from wallet signing.
|
|
132
153
|
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
abx predict # 1. prints predicted address + reserved --salt (+ exact deploy cmd)
|
|
136
|
-
abx add <predicted> --remote --from-block <now> # 2. resolver starts WATCHING that address (nothing there yet)
|
|
137
|
-
ABX_PUBLIC_BASE_URL=https://meta.you.xyz abx deploy --image ./art.png --name "Aurora" --salt <salt> # 3. deploy + MINT in one tx (same salt!)
|
|
138
|
-
abx add <predicted> --remote # 4. one nudge → pulls the deploy events + bridges the image locator
|
|
139
|
-
abx refresh <predicted> # 5. marketplaces (already resolvable → they cache the real thing)
|
|
140
|
-
```
|
|
141
|
-
Use the **exact `--salt` that `predict` printed** in step 3 (a plain `deploy` reserves a *different* salt → a different address than the resolver is watching). `--from-block <now>` = current block (`cast block-number`, or just `0` on a quiet testnet).
|
|
154
|
+
Verify the operational graph:
|
|
142
155
|
|
|
143
|
-
|
|
156
|
+
1. Resolver can reconstruct chain state from its configured RPC.
|
|
157
|
+
2. Effects can load the exact live document for a minted id.
|
|
158
|
+
3. Effects storage produces a publicly retrievable locator.
|
|
159
|
+
4. Resolver publishes or redirects to that locator.
|
|
160
|
+
5. Token metadata exposes the resulting image/attributes.
|
|
161
|
+
6. A PostParam change reaches the watcher and creates the next inputs-hash render.
|
|
144
162
|
|
|
145
|
-
|
|
163
|
+
## Use lifecycle states
|
|
146
164
|
|
|
147
|
-
|
|
165
|
+
Prefer status over retries. Typical nonterminal states include deployment accepted, indexing,
|
|
166
|
+
storage propagating, render queued/running, and remote registration pending. Typical terminal faults
|
|
167
|
+
include authentication/authorization failure, invalid contract/chain, interface mismatch, failed
|
|
168
|
+
transaction, integrity mismatch, and unsupported configuration.
|
|
169
|
+
|
|
170
|
+
Use:
|
|
148
171
|
|
|
149
172
|
```bash
|
|
150
|
-
abx
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
abx
|
|
154
|
-
abx mint <address> # 5. issue token #0 once metadata is live
|
|
155
|
-
abx refresh <address> # 6. nudge marketplaces to index it
|
|
173
|
+
abx status [address] --watch
|
|
174
|
+
abx status <address> --remote <name> --watch
|
|
175
|
+
abx storage status <locator> --json
|
|
176
|
+
abx verify <address> --json
|
|
156
177
|
```
|
|
157
|
-
Drop `--no-mint` (steps 5–6 collapse) for the express path. Add `--sign` to step 3/5 for the wallet lane. Confirm integrity with `abx verify <address>` (re-hashes served bytes vs the on-chain commitment — no server needed; the `/verify` HTTP route is the same check while serving). `abx index <address>` re-reconstructs from chain; `abx status` lists projects + the active backend.
|
|
158
|
-
|
|
159
|
-
## Token API (the resolver)
|
|
160
|
-
|
|
161
|
-
⚠ **Read this list; never infer a route from another one — and prefer not needing it at all.** The contract commits its own metadata URL on-chain, so **`abx tokenuri <addr>`** and **`abx contracturi <addr>`** (ERC-7572 collection metadata: reads `contractURI()`, follows it, decodes the JSON) answer "where does this resolve, and what does it say" without you assembling a URL. Guessing has a specific trap: **`/t/<chainId>/<address>` is NOT collection metadata** — collection metadata is `/c/<chainId>/<address>`. A miss now names which of three things happened, in a machine `code`: **400 `invalid_request`** (your path shape — the body names the right template and may carry `didYouMean`) · **404 `unknown_route`** (this node serves no such path; body lists what it does serve) · **404 `not_registered`** (path fine, this node doesn't index that contract → `abx add <addr> --remote`) · **400 `unsupported_chain`** (body carries the `chains` it serves) · **410 `burned`** (that token existed and was destroyed — permanent; stop asking, and drop it from any listing. An *edition* id with zero live copies is NOT this: it still serves, and can mint again). None of those mean the service is down — don't report an outage off a URL you built.
|
|
162
178
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
- For IPFS/Arweave the served `image` is the **gateway HTTPS URL** (`https://<gateway>/ipfs/<cid>` / `<gateway>/<txid>`), the form wallets/marketplaces render (raw `ipfs://` doesn't). The on-chain commitment is the **keccak256** (backend-neutral anchor, survives a gateway migration); the CID/txid is just the locator. The locator lives in the **deployer's** local index, so a **remote** resolver emits the gateway URL only once it's bridged (`abx add <clone> --remote`), else `image` falls back to the resolver's own `/…/image` route.
|
|
167
|
-
- `GET /.well-known/abx-service` — the **service descriptor** (public): what the node supports — `interfaces`, `chains`, `auth` (incl. `signupUrl` for humans), `render.attached` (managed rendering). Read it before registering with any remote service.
|
|
168
|
-
- `POST /v1/projects` `{chainId, address, fromBlock?, factory?, description?, externalUrl?, attributes?, contentLocators?}` · `GET /v1/projects` (the projects visible to the token, each with `status`) · `DELETE /v1/projects/<chainId>/<address>` · `POST /v1/projects/<chainId>/<address>/reindex` · `GET /v1/projects/<chainId>/<address>/status` (`status` + `fromBlock`/`toBlock`/`headBlock` + `error.class`) — the **control plane** ([spec](../../../../specs/self-host-toolkit/remote-services.md)): register/forget which contracts the node indexes, bridge off-chain traits + locators; a remote `add`/`forget`. Bearer-gated (`Authorization: Bearer <token>`), 404 code `disabled` when no token is configured. Errors carry a machine `code` (`unauthorized` 401 · `forbidden` 403 · `unsupported_chain` · `not_registered`). Register answers **200** (caught up, with counts) or **202** (accepted, still catching up — poll status); the registration is durable either way. Indexing control only — never signing.
|
|
169
|
-
- `GET /api/project/<address>/verify` — bearer-gated too (it triggers outbound fetches). Run from the CLI: `abx verify <addr>` / `abx index <addr> --remote`.
|
|
179
|
+
Wait on nonterminal states using the command's watcher/backoff. Do not wrap the CLI in a second tight
|
|
180
|
+
poller. Do not retry terminal 4xx responses or reverted transactions unchanged. Read
|
|
181
|
+
[diagnose.md](diagnose.md) for the one-transition recovery model.
|
|
170
182
|
|
|
171
|
-
|
|
183
|
+
## Migrate without losing canonicity
|
|
172
184
|
|
|
173
|
-
|
|
185
|
+
Migration changes a public projection, not canonical on-chain history. Use `abx migrate` to copy and
|
|
186
|
+
compare resolver state without cutting over prematurely.
|
|
174
187
|
|
|
175
|
-
|
|
188
|
+
1. Resolve the source and destination descriptors and credentials.
|
|
189
|
+
2. Confirm both support the active chain and contract type.
|
|
190
|
+
3. Reconstruct/register the destination from chain using the deploy block.
|
|
191
|
+
4. Copy only off-chain operator state and published artifact locators that are not derivable from chain.
|
|
192
|
+
5. Verify contract metadata, representative token metadata, fields, attachments, renders, and byte
|
|
193
|
+
commitments on both sides.
|
|
194
|
+
6. Cut over via DNS when using a stable creator domain, or change the on-chain URI pointer only after
|
|
195
|
+
parity is proven.
|
|
196
|
+
7. Re-emit URI/refresh signals as required, then monitor the destination.
|
|
197
|
+
8. Keep the old service until marketplace and collector paths have converged.
|
|
176
198
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
cd deploy/vps
|
|
180
|
-
docker compose up -d --build # builds the emitted Dockerfile, serves on :8787
|
|
181
|
-
```
|
|
182
|
-
One small container (`node:24-slim`, SQLite projection on a volume — no DB service, no native modules). State persists in the `abx-data` volume. Set `ABX_RPC_URLS` / `ABX_PUBLIC_BASE_URL` / secrets via the `.env` the setup writes (sourced, never inlined); Caddy fronts it with automatic TLS. Sizing → [`specs/self-host-toolkit/deployment.md`](../../../../specs/self-host-toolkit/deployment.md).
|
|
199
|
+
Never describe resolver migration as moving the NFT. Ownership, parameters, commitments, and canonical
|
|
200
|
+
events remain on-chain; only the serving/indexing projection changes.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Operating an existing ABX project
|
|
2
|
+
|
|
3
|
+
Use this reference for inspection, minting and sales, transfers, fields, gateways, URI pointers,
|
|
4
|
+
royalties, supply, attachments, refreshes, ownership transfer, and locks.
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [Read before writing](#read-before-writing)
|
|
9
|
+
- [Mint and run primary sales](#mint-and-run-primary-sales)
|
|
10
|
+
- [Transfer tokens and authority](#transfer-tokens-and-authority)
|
|
11
|
+
- [Operate metadata and data](#operate-metadata-and-data)
|
|
12
|
+
- [Manage economics and supply](#manage-economics-and-supply)
|
|
13
|
+
- [Lock precisely](#lock-precisely)
|
|
14
|
+
|
|
15
|
+
## Read before writing
|
|
16
|
+
|
|
17
|
+
Never infer contract type or current authority from the original launch notes. Read the contract:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
abx state <address>
|
|
21
|
+
abx tokens <address> --json
|
|
22
|
+
abx contracturi <address>
|
|
23
|
+
abx tokenuri <address> --token <id>
|
|
24
|
+
abx verify <address> --json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use `abx status` or its remote form for projection/render lifecycle. Record active chain, detected
|
|
28
|
+
family, owner/admin, supply and pause state, minter/payee, royalty/cap, URI renderer/pointers, code
|
|
29
|
+
dependencies, schemas/hooks, and lock state.
|
|
30
|
+
|
|
31
|
+
Before every write, run its help and dry-run form when available. Confirm sender, target, value,
|
|
32
|
+
token/id/amount, and permanence. Let the CLI validate contract type; do not send raw ABI calls to make
|
|
33
|
+
an operation fit the wrong family.
|
|
34
|
+
|
|
35
|
+
## Mint and run primary sales
|
|
36
|
+
|
|
37
|
+
`abx mint` follows the detected family:
|
|
38
|
+
|
|
39
|
+
- A 1/1 issues its single token.
|
|
40
|
+
- A Series mints the next id in order; `--count` can mint multiple sequential ids.
|
|
41
|
+
- An edition requires `--token-id` except where the contract has only the single 1/1-edition id, and
|
|
42
|
+
uses `--amount` for copies. `--count` is not an edition synonym.
|
|
43
|
+
|
|
44
|
+
Confirm the recipient. Minting may trigger a transfer hook; a hook that vetoes mint will revert the
|
|
45
|
+
whole transaction.
|
|
46
|
+
|
|
47
|
+
### Shared fixed-price minter
|
|
48
|
+
|
|
49
|
+
Use the shared minter commands for ordinary ETH primary sales:
|
|
50
|
+
|
|
51
|
+
1. `abx minter configure <token> …` sets price and allocation. Editions require a token id and use a
|
|
52
|
+
per-id sale configuration.
|
|
53
|
+
2. `abx set-minter <token> --minter <address>` authorizes the minter.
|
|
54
|
+
3. `abx set-primary-payee <token> --payee <address>` declares payout.
|
|
55
|
+
4. `abx unpause <token>` opens minting when the family supports the pause gate.
|
|
56
|
+
5. `abx minter show <token> …` verifies the public sale state.
|
|
57
|
+
6. `abx minter buy <token> …` is the public purchase path; editions use quantity and token id.
|
|
58
|
+
|
|
59
|
+
Do not call a sale live until price units, allocation, payee, minter address, pause state, and a
|
|
60
|
+
representative purchase are verified. `abx mint-page` scaffolds a client for the shared minter; it does
|
|
61
|
+
not configure the on-chain sale for you.
|
|
62
|
+
|
|
63
|
+
Use a custom minter for auctions, allowlists, raffles, free claims, ERC-20 pricing, or other issuance
|
|
64
|
+
rules. The custom contract calls the canonical token's mint authority; the token itself remains a
|
|
65
|
+
factory clone. Read [capabilities.md](capabilities.md).
|
|
66
|
+
|
|
67
|
+
## Transfer tokens and authority
|
|
68
|
+
|
|
69
|
+
`abx transfer` moves token ownership/copies, not contract administration.
|
|
70
|
+
|
|
71
|
+
- A 721 transfer names token id and destination.
|
|
72
|
+
- An edition transfer names token id, amount, destination, and source holder because an id can have
|
|
73
|
+
multiple holders.
|
|
74
|
+
- Creator-token validation or a transfer hook may reject the move. Diagnose the actual revert; do not
|
|
75
|
+
bypass or clear an enforcement mechanism without the owner's explicit intent.
|
|
76
|
+
|
|
77
|
+
`abx set-admin --to <address>` transfers contract authority. Treat it as a high-risk, potentially
|
|
78
|
+
irrecoverable handoff:
|
|
79
|
+
|
|
80
|
+
1. Verify the recipient is correct for the active chain.
|
|
81
|
+
2. Inventory unfinished operations and unlocked surfaces.
|
|
82
|
+
3. State which powers move and which external controllers remain separate.
|
|
83
|
+
4. Receive exact human confirmation.
|
|
84
|
+
5. Execute once, then read state from chain to prove the new owner.
|
|
85
|
+
|
|
86
|
+
Never interpret a token transfer as a sale listing. ABX has no secondary order book; a marketplace or
|
|
87
|
+
manual transfer handles secondary exchange.
|
|
88
|
+
|
|
89
|
+
## Operate metadata and data
|
|
90
|
+
|
|
91
|
+
### URI pointers and renderers
|
|
92
|
+
|
|
93
|
+
Use `set-token-uri`, `set-contract-uri`, and `set-renderer` only after reading the current configuration
|
|
94
|
+
and verifying the destination. Switching `set-renderer --off` can place an HTTP resolver in front of
|
|
95
|
+
content that remains stored on-chain. Switching to the canonical renderer makes configured on-chain
|
|
96
|
+
fields self-resolving when the contract supports them.
|
|
97
|
+
|
|
98
|
+
Never hand-build a resolver path. Read `tokenURI`/`contractURI`, decode it, and follow what the
|
|
99
|
+
contract actually returns. A correct-looking URL constructed from memory is not evidence.
|
|
100
|
+
|
|
101
|
+
### Fields
|
|
102
|
+
|
|
103
|
+
`abx set-field` writes one metadata field representation at token or collection scope. Representations
|
|
104
|
+
include inline data, reader/chunk pointers, hashes, public locators, and renderer pointers as supported
|
|
105
|
+
by the contract. Collection-scope values act as shared defaults; token-scope values override them.
|
|
106
|
+
|
|
107
|
+
Use reserved fields such as description, attributes, creator, license, display notes, and links
|
|
108
|
+
according to command help. Verify the resulting provenance in decoded metadata. On-chain-wins means a
|
|
109
|
+
new on-chain value can intentionally supersede a resolver projection.
|
|
110
|
+
|
|
111
|
+
### Gateways
|
|
112
|
+
|
|
113
|
+
`abx set-gateway` changes the serving prefix for IPFS/Arweave locator representations without moving
|
|
114
|
+
the content. Verify a representative locator through the new gateway before changing it. A gateway
|
|
115
|
+
repoint is not a re-upload and does not change the committed CID/transaction id.
|
|
116
|
+
|
|
117
|
+
### Attachments versus parameters
|
|
118
|
+
|
|
119
|
+
`abx attach <addr> <key> <locator>` records a named artifact. The resolver exposes the complete
|
|
120
|
+
artifacts list and `/data/<key>` retrieval. Bare on-chain metadata cannot enumerate arbitrary field
|
|
121
|
+
keys, so consumers need a resolver to discover all attachments even when each locator is durable and
|
|
122
|
+
hash-anchored.
|
|
123
|
+
|
|
124
|
+
PostParams are different: the parameter store enumerates schemas and values on-chain. Read schemas
|
|
125
|
+
with `state` and values with `tokens --json`. Parameters do not require a resolver merely to be
|
|
126
|
+
canonical or enumerable.
|
|
127
|
+
|
|
128
|
+
### Refresh and URI events
|
|
129
|
+
|
|
130
|
+
`abx refresh` asks external marketplaces to fetch metadata again; it does not fix the metadata or
|
|
131
|
+
mutate canonical state. First prove that the current URI resolves and returns the intended document.
|
|
132
|
+
For editions, `ping-uri` re-emits native URI events for selected ids after a repoint. Use the smallest
|
|
133
|
+
id set needed and verify the new path before signalling indexers.
|
|
134
|
+
|
|
135
|
+
## Manage economics and supply
|
|
136
|
+
|
|
137
|
+
Use `set-royalty` to change receiver/rate within the collection's permanent royalty ceiling. Use
|
|
138
|
+
`set-royalty-cap` only to lower that ceiling. State the old and new values and confirm the irreversible
|
|
139
|
+
loss of future headroom.
|
|
140
|
+
|
|
141
|
+
Series supply caps and edition per-id caps are monotonic downward. Read current minted supply before
|
|
142
|
+
lowering a cap; never propose a value below already minted supply. For editions, name the id and
|
|
143
|
+
distinguish its per-id cap from aggregate collection supply.
|
|
144
|
+
|
|
145
|
+
Pause/unpause controls the supported mint gate, not transfers or every external minter behavior.
|
|
146
|
+
Read state after changing it.
|
|
147
|
+
|
|
148
|
+
Primary payee declares sale proceeds; royalty receiver handles secondary royalty reporting. Keep them
|
|
149
|
+
separate. Changing one does not update the other.
|
|
150
|
+
|
|
151
|
+
## Lock precisely
|
|
152
|
+
|
|
153
|
+
Lock last, after production-path verification. Every lock freezes a different surface:
|
|
154
|
+
|
|
155
|
+
| Lock | Freezes | Does not necessarily freeze |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `lock-field` | one token/collection field representation | other fields, URI pointer, program, params |
|
|
158
|
+
| `lock-uri` | URI configuration/pointer at selected scope | program/dependencies/params/hooks |
|
|
159
|
+
| `lock-script` | code-project script chunks | dependencies, metadata, params, external renderer code |
|
|
160
|
+
| `lock-dependencies` | dependency list and registry pointer | bytes returned later by a live registry entry |
|
|
161
|
+
| `lock-param-hooks` | configure/transfer/augment addresses | behavior behind an upgradeable address |
|
|
162
|
+
| governed schema/value lock | writes governed by that schema/key | unrelated or ungoverned params; some inherited defaults |
|
|
163
|
+
| ownership transfer | future owner-only authority at this contract | powers held by external minters/hooks/providers |
|
|
164
|
+
|
|
165
|
+
For a code project, metadata locks alone do not freeze the program. A strong freeze normally requires
|
|
166
|
+
script, dependency, relevant field/URI, hook, and governed-parameter decisions, plus immutable external
|
|
167
|
+
renderer/hook/dependency deployments.
|
|
168
|
+
|
|
169
|
+
Important qualifications:
|
|
170
|
+
|
|
171
|
+
- An ungoverned parameter remains writable despite metadata locks.
|
|
172
|
+
- A schema-welded token value is stronger than a collection default inherited by many tokens; the
|
|
173
|
+
recovery path may still allow a poisoned collection default to be cleared.
|
|
174
|
+
- A registry dependency may return different bytes behind a frozen reference.
|
|
175
|
+
- A locked pointer to an upgradeable proxy fixes the address, not its behavior.
|
|
176
|
+
- A transfer-hook address represents a standing ability to veto mints/transfers. Freezing an empty
|
|
177
|
+
hook set is the proof that this power cannot later be added.
|
|
178
|
+
|
|
179
|
+
Use `abx verify` and direct state reads to enumerate what remains mutable. Describe the guarantee as
|
|
180
|
+
specific stored values and addresses that can no longer change; do not promise immutable output unless
|
|
181
|
+
every live input and external implementation has actually been bounded.
|