@artblocks/abx-cli 0.1.0-alpha.4 → 0.1.0-alpha.41
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 +161 -0
- package/assets/renderer-scaffold/README.md +41 -11
- package/assets/renderer-scaffold/foundry.toml +5 -0
- package/assets/renderer-scaffold/remappings.txt +1 -1
- package/assets/renderer-scaffold/script/DeployHooks.s.sol +24 -0
- package/assets/renderer-scaffold/script/Preview.s.sol +99 -0
- package/assets/renderer-scaffold/src/MyHooks.sol +20 -0
- package/assets/renderer-scaffold/src/MyRenderer.sol +4 -4
- package/assets/renderer-scaffold/src/MyTraits.sol +2 -2
- package/assets/renderer-scaffold/test/MyRenderer.t.sol +60 -3
- package/dist/bin.d.ts +26 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +63 -0
- package/dist/bin.js.map +1 -0
- package/dist/capabilities.d.ts +99 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +144 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/commands/auth.d.ts +54 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +447 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/deploy.d.ts +242 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +5429 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/feedback.d.ts +7 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +147 -0
- package/dist/commands/feedback.js.map +1 -0
- 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 +429 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +1720 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/reads.d.ts +85 -0
- package/dist/commands/reads.d.ts.map +1 -0
- package/dist/commands/reads.js +868 -0
- package/dist/commands/reads.js.map +1 -0
- package/dist/commands/scaffold.d.ts +89 -0
- package/dist/commands/scaffold.d.ts.map +1 -0
- package/dist/commands/scaffold.js +738 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/commands/service.d.ts +67 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +748 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/storage.d.ts +51 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +399 -0
- package/dist/commands/storage.js.map +1 -0
- package/dist/commands/submit-app.d.ts +102 -0
- package/dist/commands/submit-app.d.ts.map +1 -0
- package/dist/commands/submit-app.js +622 -0
- package/dist/commands/submit-app.js.map +1 -0
- package/dist/config.d.ts +105 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +351 -12
- package/dist/config.js.map +1 -1
- package/dist/conformance.d.ts +31 -0
- package/dist/conformance.d.ts.map +1 -0
- package/dist/conformance.js +390 -0
- package/dist/conformance.js.map +1 -0
- package/dist/contract-read-error.d.ts +5 -0
- package/dist/contract-read-error.d.ts.map +1 -0
- package/dist/contract-read-error.js +37 -0
- package/dist/contract-read-error.js.map +1 -0
- package/dist/deploy-plan.d.ts +150 -0
- package/dist/deploy-plan.d.ts.map +1 -0
- package/dist/deploy-plan.js +31 -0
- package/dist/deploy-plan.js.map +1 -0
- package/dist/deps.d.ts +6 -39
- package/dist/deps.d.ts.map +1 -1
- package/dist/deps.js +4 -68
- package/dist/deps.js.map +1 -1
- package/dist/errors.d.ts +20 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/flag-allowlists.d.ts +53 -0
- package/dist/flag-allowlists.d.ts.map +1 -0
- package/dist/flag-allowlists.js +184 -0
- package/dist/flag-allowlists.js.map +1 -0
- package/dist/flags.d.ts +47 -0
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +125 -1
- package/dist/flags.js.map +1 -1
- package/dist/jsonout.d.ts +37 -0
- package/dist/jsonout.d.ts.map +1 -0
- package/dist/jsonout.js +79 -0
- package/dist/jsonout.js.map +1 -0
- package/dist/kind.d.ts +57 -0
- package/dist/kind.d.ts.map +1 -0
- package/dist/kind.js +122 -0
- package/dist/kind.js.map +1 -0
- package/dist/main.js +786 -4838
- package/dist/main.js.map +1 -1
- package/dist/mintpage.d.ts +17 -2
- package/dist/mintpage.d.ts.map +1 -1
- package/dist/mintpage.js +241 -54
- package/dist/mintpage.js.map +1 -1
- package/dist/output.d.ts +179 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +780 -0
- package/dist/output.js.map +1 -0
- package/dist/ownerops.d.ts +381 -57
- package/dist/ownerops.d.ts.map +1 -1
- package/dist/ownerops.js +2014 -359
- package/dist/ownerops.js.map +1 -1
- package/dist/preview.d.ts +23 -5
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +95 -43
- package/dist/preview.js.map +1 -1
- package/dist/prompt.d.ts +17 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +19 -0
- package/dist/prompt.js.map +1 -0
- package/dist/provision.d.ts +3 -13
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +19 -21
- package/dist/provision.js.map +1 -1
- package/dist/remote.d.ts +157 -52
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +435 -46
- package/dist/remote.js.map +1 -1
- package/dist/riskgate.d.ts +62 -0
- package/dist/riskgate.d.ts.map +1 -0
- package/dist/riskgate.js +234 -0
- package/dist/riskgate.js.map +1 -0
- package/dist/scaffold.d.ts +12 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +56 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/schema.d.ts +36 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +121 -26
- package/dist/schema.js.map +1 -1
- package/dist/script-chunks.d.ts +8 -0
- package/dist/script-chunks.d.ts.map +1 -0
- package/dist/script-chunks.js +35 -0
- package/dist/script-chunks.js.map +1 -0
- package/dist/served.d.ts +30 -0
- package/dist/served.d.ts.map +1 -0
- package/dist/served.js +112 -0
- package/dist/served.js.map +1 -0
- package/dist/signer.d.ts +13 -0
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +84 -15
- package/dist/signer.js.map +1 -1
- package/dist/update-check.d.ts +86 -5
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +161 -20
- package/dist/update-check.js.map +1 -1
- package/package.json +13 -12
- package/skill/SKILL.md +181 -347
- package/skill/agents/openai.yaml +4 -0
- package/skill/reference/capabilities.md +188 -0
- package/skill/reference/code.md +220 -0
- package/skill/reference/creator-token.md +94 -0
- package/skill/reference/deploy.md +174 -0
- package/skill/reference/diagnose.md +178 -0
- package/skill/reference/hosting.md +186 -93
- package/skill/reference/operate.md +220 -0
- package/skill/reference/services.md +121 -0
- package/skill/reference/setup.md +154 -36
- package/assets/renderer-scaffold/src/interfaces/IAbxFieldRenderer.sol +0 -32
- package/assets/renderer-scaffold/src/interfaces/IAbxParams.sol +0 -26
- package/dist/inspect.d.ts +0 -48
- package/dist/inspect.d.ts.map +0 -1
- package/dist/inspect.js +0 -184
- package/dist/inspect.js.map +0 -1
- package/dist/migrate.d.ts +0 -65
- package/dist/migrate.d.ts.map +0 -1
- package/dist/migrate.js +0 -180
- package/dist/migrate.js.map +0 -1
- package/dist/onchain-uri.d.ts +0 -97
- package/dist/onchain-uri.d.ts.map +0 -1
- package/dist/onchain-uri.js +0 -243
- package/dist/onchain-uri.js.map +0 -1
- package/dist/upload.d.ts +0 -28
- package/dist/upload.d.ts.map +0 -1
- package/dist/upload.js +0 -41
- package/dist/upload.js.map +0 -1
- package/skill/reference/code-projects.md +0 -246
- package/skill/reference/operating.md +0 -116
- package/skill/reference/troubleshooting.md +0 -28
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# First-party services and feedback
|
|
2
|
+
|
|
3
|
+
Use this reference for the public ABX service, API-key login, hosted resolver/rendering, or feedback.
|
|
4
|
+
For provider-independent hosting and migration, also read [hosting.md](hosting.md).
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [First-party service](#first-party-service)
|
|
9
|
+
- [Feedback targets](#feedback-targets)
|
|
10
|
+
|
|
11
|
+
## First-party service
|
|
12
|
+
|
|
13
|
+
The documented endpoints are:
|
|
14
|
+
|
|
15
|
+
- documentation: `https://docs.abx.io`
|
|
16
|
+
- service: `https://services.abx.io`
|
|
17
|
+
- OAuth discovery: `https://services.abx.io/.well-known/oauth-authorization-server`
|
|
18
|
+
- manual signup fallback: `https://services.abx.io/signup`
|
|
19
|
+
|
|
20
|
+
The first-party provider has the built-in remote name `abx`:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
abx remote abx
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
It needs `ABX_SERVICES_API_KEY` in the project's ignored `.env`; it does not need
|
|
27
|
+
`ABX_REMOTE_ABX_URL`. When the key is absent, use:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
abx auth login
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The CLI starts the OAuth device flow and shows a verified browser URL plus a matching short code.
|
|
34
|
+
The human completes name, email, one-time-code verification, and approval in that browser. The CLI
|
|
35
|
+
polls at the provider-declared interval, receives the API key, and writes it directly to ignored
|
|
36
|
+
`.env` without printing it. The browser never receives the key. Do not ask the human to paste an OTP
|
|
37
|
+
or key into chat. `--no-open` leaves the browser handoff as a link; `--force` is required to replace
|
|
38
|
+
an existing local credential, but does not revoke the displaced provider key. For normal rotation,
|
|
39
|
+
run `abx auth logout` and then `abx auth login`; reserve `--force` for recovery. The CLI refuses
|
|
40
|
+
tracked or unignored `.env` files.
|
|
41
|
+
|
|
42
|
+
The issued API key is long-lived and remains valid until it is revoked. Reuse the stored key across
|
|
43
|
+
tasks and agent sessions; do not start a new login merely because a task or conversation ended. If
|
|
44
|
+
`abx remote abx` authenticates successfully, no login is needed.
|
|
45
|
+
|
|
46
|
+
In an agent runner, start `abx auth login --no-open` with a short initial yield or a resumable
|
|
47
|
+
background session. Relay the printed URL and code immediately while that same process keeps polling,
|
|
48
|
+
then resume it after human approval. Do not start another login or add an outer retry loop. If the
|
|
49
|
+
runner cannot yield control while a command waits, ask the human to run the command in their terminal.
|
|
50
|
+
|
|
51
|
+
Logout only for intentional teardown, suspected compromise, deliberate rotation, or to free an
|
|
52
|
+
active-key slot. When revoking, do not only delete the local value:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
abx auth logout # first-party service
|
|
56
|
+
abx auth logout <name> # another OAuth-capable named remote
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Logout discovers the provider's RFC 7009 endpoint, revokes the current key, and only then removes the
|
|
60
|
+
matching `.env` assignment. If the key came from a shell or another environment source, the CLI
|
|
61
|
+
revokes it and tells the human where it still needs to be unset. A repeated logout with no active
|
|
62
|
+
local credential is safe.
|
|
63
|
+
|
|
64
|
+
Use `/signup` only as the manual recovery path. It shows the raw key once, so the human—not the
|
|
65
|
+
agent—must place it in `.env`. An already verified email reuses its account and may receive another
|
|
66
|
+
key, subject to the service's active-key limit. `abx auth logout` revokes an unused current key and
|
|
67
|
+
frees its active-key slot.
|
|
68
|
+
|
|
69
|
+
Availability, pricing, and quotas are service policy rather than protocol guarantees. Confirm current
|
|
70
|
+
terms before making a durable hosting choice and keep the exit route explicit: the same remote-service
|
|
71
|
+
contract supports another provider or a creator-operated resolver/effects deployment.
|
|
72
|
+
|
|
73
|
+
Before depending on hosted behavior, inspect the live descriptor with `abx remote abx`; do not infer
|
|
74
|
+
capabilities from this file. Use `--remote abx` on commands that accept a managed remote and verify
|
|
75
|
+
the resulting public surfaces as described in [hosting.md](hosting.md).
|
|
76
|
+
|
|
77
|
+
## Feedback targets
|
|
78
|
+
|
|
79
|
+
`abx feedback` has two deliberately separate targets:
|
|
80
|
+
|
|
81
|
+
| Intent | Command | Recipient |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| ABX protocol, contracts, CLI, SDK, skill, or docs | `abx feedback` | core ABX team |
|
|
84
|
+
| A remote provider's resolver, rendering, auth, or operations | `abx feedback --remote <name>` | that provider |
|
|
85
|
+
|
|
86
|
+
For first-party hosted-service feedback use `--remote abx`. A third-party remote can advertise the
|
|
87
|
+
optional `abx-service-feedback/v1` interface and operate its own feedback store. Never send
|
|
88
|
+
provider-specific incidents through core feedback merely because both first-party targets currently
|
|
89
|
+
share infrastructure.
|
|
90
|
+
|
|
91
|
+
Discovery and report previews are public. Submission (`--yes`) and `--mine` require the same key
|
|
92
|
+
created by `abx auth login`; login once rather than creating a separate feedback credential. Run the
|
|
93
|
+
command without report flags to inspect its live schema and instructions. To report, provide the
|
|
94
|
+
required structured flags; use `--detail-file` or `--context-file` rather than fragile shell quoting
|
|
95
|
+
for longer content. The CLI shows the exact destination and payload first. Review and redact the
|
|
96
|
+
preview with the human, then repeat with `--yes` only after explicit approval.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Preview core feedback; nothing is sent.
|
|
100
|
+
abx feedback --area cli --kind bug --summary "Concise summary" --detail-file report.md
|
|
101
|
+
|
|
102
|
+
# After the human approves this exact preview.
|
|
103
|
+
abx feedback --area cli --kind bug --summary "Concise summary" --detail-file report.md --yes
|
|
104
|
+
|
|
105
|
+
# Provider-specific preview.
|
|
106
|
+
abx feedback --remote abx --component rendering --kind bug --summary "Concise summary"
|
|
107
|
+
|
|
108
|
+
# Review reports previously submitted with the current key.
|
|
109
|
+
abx feedback --mine
|
|
110
|
+
abx feedback --remote abx --mine
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Do not attach `.env`, credentials, wallet/session URLs, full transcripts, or unrelated source files.
|
|
114
|
+
Prefer the smallest reproduction and relevant version/chain/address context. The API key authenticates
|
|
115
|
+
the reporter; hosted-service entitlement is evaluated separately. It never grants transaction-signing
|
|
116
|
+
authority.
|
|
117
|
+
|
|
118
|
+
Use the CLI instead of hand-written HTTP or retry loops. The device flow already handles pending,
|
|
119
|
+
slow-down, and transient polling responses until its fixed expiry. Treat `401` as missing/invalid credentials,
|
|
120
|
+
`403` as recognized credentials without the required entitlement, and schema/interface errors as a
|
|
121
|
+
request or provider-contract mismatch. Read [diagnose.md](diagnose.md) and make one state transition.
|
package/skill/reference/setup.md
CHANGED
|
@@ -1,36 +1,154 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
|
|
36
|
-
|
|
1
|
+
# Setup and safety
|
|
2
|
+
|
|
3
|
+
Use this reference when installing ABX, selecting a binary or signer, configuring a new environment,
|
|
4
|
+
or preparing a real transaction.
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [Resolve the tool before the project](#resolve-the-tool-before-the-project)
|
|
9
|
+
- [Never expose secrets](#never-expose-secrets)
|
|
10
|
+
- [Select the chain explicitly through the environment](#select-the-chain-explicitly-through-the-environment)
|
|
11
|
+
- [Choose one signing lane](#choose-one-signing-lane)
|
|
12
|
+
- [Prepare without mutating](#prepare-without-mutating)
|
|
13
|
+
- [New environment checklist](#new-environment-checklist)
|
|
14
|
+
|
|
15
|
+
## Resolve the tool before the project
|
|
16
|
+
|
|
17
|
+
Inside the ABX source repository run `pnpm abx …`; elsewhere run the installed `abx`. A bare global
|
|
18
|
+
binary inside the repository may be older than the source. Start with:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
abx version
|
|
22
|
+
abx doctor
|
|
23
|
+
abx capabilities --json
|
|
24
|
+
abx skill install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`abx doctor` reports binary provenance, CLI/skill drift, active chain, RPC health and history reach,
|
|
28
|
+
wallet readiness, canonical factories, storage, and configured remotes without exposing credentials.
|
|
29
|
+
Treat a red check as an actionable setup state, not as permission to improvise a workaround.
|
|
30
|
+
|
|
31
|
+
The shipped skill is named `abx`. `abx skill install` installs it to `.claude/skills/abx` and
|
|
32
|
+
`.agents/skills/abx` by default; `--agent`, `--global`, and `--target` narrow the destination. During
|
|
33
|
+
the rename transition the installer moves a recognized `abx-self-host` folder to
|
|
34
|
+
`.abx-skill-backups/` before installing the new name. It preserves custom bytes rather than deleting
|
|
35
|
+
them. For a custom skills parent, run `abx skill install --target <that-parent>`; do not move or merge
|
|
36
|
+
the old folder manually. Restart the agent after installation.
|
|
37
|
+
|
|
38
|
+
ABX requires Node 22.13 or newer. Prefer a project-local npm dependency for reproducible automation;
|
|
39
|
+
use a global install for interactive machine-wide use. Avoid repeated `npx` execution when version
|
|
40
|
+
provenance matters because caches can outlive an upgrade.
|
|
41
|
+
|
|
42
|
+
## Never expose secrets
|
|
43
|
+
|
|
44
|
+
Do not open, search, quote, or print `.env`. Do not echo variables to test whether they exist. Do not
|
|
45
|
+
paste a private key into a command line, generated file, wallet page, bug report, or transcript.
|
|
46
|
+
|
|
47
|
+
Sensitive values include:
|
|
48
|
+
|
|
49
|
+
- `ABX_DEPLOYER_PK` and any wallet key;
|
|
50
|
+
- credential-bearing `ABX_RPC_URLS*` values;
|
|
51
|
+
- `PINATA_JWT`, S3/R2 keys, `ABX_SERVICES_API_KEY`, other remote-provider tokens, effects/admin
|
|
52
|
+
tokens;
|
|
53
|
+
- Arweave JWK contents and browser signing-session URLs.
|
|
54
|
+
|
|
55
|
+
Use `abx doctor`, `abx remote <name>`, `abx storage show --check`, and redacted CLI errors. If a tool
|
|
56
|
+
ever emits an unredacted credential-bearing endpoint, stop, rotate the credential, and report the
|
|
57
|
+
output bug without repeating the secret.
|
|
58
|
+
|
|
59
|
+
## Select the chain explicitly through the environment
|
|
60
|
+
|
|
61
|
+
The toolkit supports the chains printed by `abx capabilities`; today those are Base Sepolia by
|
|
62
|
+
default and Ethereum Sepolia via `ABX_CHAIN=sepolia`. There is deliberately no `--chain` flag. The
|
|
63
|
+
CLI refuses it because silently ignoring a wrong-chain request could spend on the wrong network.
|
|
64
|
+
|
|
65
|
+
Use per-chain RPC variables when operating more than one chain. `abx doctor` checks chain identity,
|
|
66
|
+
wide-range `eth_getLogs`, archival reach, and nonce coherence. Put a healthy archive endpoint first:
|
|
67
|
+
fallback transports rotate on errors, not on a successful but pruned empty log response.
|
|
68
|
+
|
|
69
|
+
The local projection and managed Arweave identity remain in `.abx-self-host/` unless
|
|
70
|
+
`ABX_DATA_DIR` overrides it. That runtime directory is separate from the renamed `abx` skill and is
|
|
71
|
+
not being renamed. Back up the managed Arweave key with `abx storage backup-key`; never print it.
|
|
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
|
+
|
|
87
|
+
## Choose one signing lane
|
|
88
|
+
|
|
89
|
+
Every write uses one of three lanes:
|
|
90
|
+
|
|
91
|
+
| Lane | Select | Use when |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Hot | `--send` or default | An environment key may sign unattended |
|
|
94
|
+
| Wallet | `--sign --for 0x…` | A human approves in their browser wallet |
|
|
95
|
+
| Cold | `--unsigned --for 0x…` | A multisig/offline signer needs prepared transactions |
|
|
96
|
+
|
|
97
|
+
Run `abx doctor --for <address>` before a wallet or cold operation. On the wallet lane, give the
|
|
98
|
+
human the locally generated signing page; never request or handle their key. On the cold lane, verify
|
|
99
|
+
chain, sender, target, calldata, value, and ordering before handing transactions over.
|
|
100
|
+
|
|
101
|
+
`--onchain-image` staging cannot use the cold lane because each chunk transaction depends on the
|
|
102
|
+
receipt of the preceding transaction. Use hot or wallet signing. Do not split staging into a homemade
|
|
103
|
+
offline sequence.
|
|
104
|
+
|
|
105
|
+
`ABX_DEPLOYER_PK` may be written with or without a `0x` prefix — the CLI and SDK normalize it. Foundry's
|
|
106
|
+
`vm.envUint` does not: a custom forge script that reads the same `.env` needs the `0x` form.
|
|
107
|
+
|
|
108
|
+
For any one EOA, run one write command at a time. ABX obtains pending and latest nonces once, takes the
|
|
109
|
+
safe maximum, increments locally, waits for newly deployed code when a following transaction targets
|
|
110
|
+
it, and throws typed reversion errors. Starting concurrent processes bypasses that serialization.
|
|
111
|
+
|
|
112
|
+
## Prepare without mutating
|
|
113
|
+
|
|
114
|
+
Use command help and dry runs, not guessed syntax:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
abx help deploy-code
|
|
118
|
+
abx deploy-code … --dry-run --json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
A dry run may read contracts, probe endpoints, analyze files, or verify an address, but it does not
|
|
122
|
+
send or store. Address prediction is meaningful only when the salt and deployer are pinned. Use
|
|
123
|
+
`abx predict` when another contract or resolver must know the collection address before deployment.
|
|
124
|
+
|
|
125
|
+
Before any real send, confirm:
|
|
126
|
+
|
|
127
|
+
- active chain and deploying/owning address;
|
|
128
|
+
- contract family and edition arithmetic;
|
|
129
|
+
- name, symbol, royalties and royalty ceiling;
|
|
130
|
+
- deploy-time options such as burnability and creator-token enrollment;
|
|
131
|
+
- custody, public resolution, image/animation/trait surfaces;
|
|
132
|
+
- mint amount, value, transaction count, and expected gas;
|
|
133
|
+
- every irreversible lock or authority transfer.
|
|
134
|
+
|
|
135
|
+
Do not make a real send merely because a dry run exited successfully. The dry run is the plan; the
|
|
136
|
+
human confirmation authorizes execution.
|
|
137
|
+
|
|
138
|
+
## New environment checklist
|
|
139
|
+
|
|
140
|
+
1. Install Node 22.13+ and the desired CLI version.
|
|
141
|
+
2. Install the co-versioned skill with `abx skill install`, then restart the agent.
|
|
142
|
+
3. Select the testnet using `ABX_CHAIN` if not using Base Sepolia.
|
|
143
|
+
4. Add RPC, signer, and storage configuration outside the transcript. For first-party hosted
|
|
144
|
+
services, run `abx auth login --no-open` in a short-yield or resumable session: immediately hand
|
|
145
|
+
its verified browser URL and matching code to the human, then resume that same polling process.
|
|
146
|
+
Let the CLI store `ABX_SERVICES_API_KEY` in ignored `.env` without printing it. Never ask for the
|
|
147
|
+
email OTP or key in chat, start duplicate login sessions, or add standing login instructions to
|
|
148
|
+
`AGENTS.md`/`CLAUDE.md`. The key is long-lived: reuse it across tasks and agent sessions. Run
|
|
149
|
+
`abx auth logout` only for intentional teardown, compromise, rotation, or an unused-key cleanup.
|
|
150
|
+
5. Run `abx doctor` and resolve every red check relevant to the chosen lane.
|
|
151
|
+
6. Run `abx storage show --check` when bytes will leave the local disk.
|
|
152
|
+
7. Run `abx remote <name>` before relying on a configured managed service.
|
|
153
|
+
8. Run command help, then a JSON dry run.
|
|
154
|
+
9. Confirm the plan and only then execute.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
/// @title IAbxFieldRenderer — the contract your in-chain art implements
|
|
5
|
-
/// @notice A field renderer returns ONE metadata field's value, COMPUTED from chain state
|
|
6
|
-
/// (the token's seed + PostParams, its owner, anything readable on-chain). The ABX
|
|
7
|
-
/// metadata renderer staticcalls it to build `tokenURI` — e.g. an `image` renderer's
|
|
8
|
-
/// SVG becomes `data:image/svg+xml;base64,…`. Deploy your renderer, then wire it with
|
|
9
|
-
/// `abx deploy-code --image-renderer <address> [--attributes-renderer <address>] --onchain-uri`.
|
|
10
|
-
///
|
|
11
|
-
/// @dev THE FIVE INVARIANTS (a reverting or malformed renderer bricks the WHOLE tokenURI —
|
|
12
|
-
/// the metadata renderer staticcalls you with NO try/catch):
|
|
13
|
-
/// 1. NEVER revert for ANY (token, tokenId, field) — including the collection surface
|
|
14
|
-
/// `tokenId == type(uint256).max` (used by `contractURI`). Return a neutral value.
|
|
15
|
-
/// 2. Return the correct `contentType` (`image/svg+xml` for an image; `application/json`
|
|
16
|
-
/// for an `attributes` array).
|
|
17
|
-
/// 3. Guard `field`: revert only a truly unsupported field (a deploy-time miswiring), but
|
|
18
|
-
/// still never revert on the fields you DO render.
|
|
19
|
-
/// 4. `view` + deterministic: same chain state → same bytes.
|
|
20
|
-
/// 5. Bounded output: keep it small (a few hundred bytes of SVG) so `tokenURI` stays a
|
|
21
|
-
/// cheap single eth_call. `forge test` the never-revert cases before you wire it.
|
|
22
|
-
interface IAbxFieldRenderer {
|
|
23
|
-
/// @param token the ABX collection contract (read its params via {IAbxParams}).
|
|
24
|
-
/// @param tokenId the token, or `type(uint256).max` for the collection surface.
|
|
25
|
-
/// @param field which field to compute (e.g. `"image"`, `"attributes"`).
|
|
26
|
-
/// @return contentType MIME of `data` (e.g. `image/svg+xml`, `application/json`).
|
|
27
|
-
/// @return data the field's finished bytes.
|
|
28
|
-
function render(address token, uint256 tokenId, bytes32 field)
|
|
29
|
-
external
|
|
30
|
-
view
|
|
31
|
-
returns (string memory contentType, bytes memory data);
|
|
32
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
/// @title IAbxParams — read the token's on-chain params (seed + collector PostParams)
|
|
5
|
-
/// @notice Your renderer reads live state through this. Each value is a `bytes32`; `isSet` tells
|
|
6
|
-
/// you whether it exists (fall back to a default if not — see invariant #1). `valueIsHash`
|
|
7
|
-
/// is true when the on-chain value is a keccak commitment to off-chain bytes (a literal
|
|
8
|
-
/// scalar param like a `seed` or a `HexColor` palette is NOT a hash — check `!valueIsHash`).
|
|
9
|
-
///
|
|
10
|
-
/// The tokenData merge rule: a token-scope value overrides the contract-scope one. The
|
|
11
|
-
/// common pattern is `tokenParam` first, then `contractParam` as a fallback (see the
|
|
12
|
-
/// `_param` helper in MyRenderer.sol).
|
|
13
|
-
interface IAbxParams {
|
|
14
|
-
/// Returns the token-scope param: its bytes32 `value`, `valueIsHash` (true if it commits to
|
|
15
|
-
/// off-chain bytes — a literal scalar like a seed/HexColor is false), and `isSet` (does it exist).
|
|
16
|
-
function tokenParam(uint256 tokenId, bytes32 key)
|
|
17
|
-
external
|
|
18
|
-
view
|
|
19
|
-
returns (bytes32 value, bool valueIsHash, bool isSet);
|
|
20
|
-
|
|
21
|
-
/// @notice The contract-scope (collection-wide) value — the fallback when a token has none.
|
|
22
|
-
function contractParam(bytes32 key)
|
|
23
|
-
external
|
|
24
|
-
view
|
|
25
|
-
returns (bytes32 value, bool valueIsHash, bool isSet);
|
|
26
|
-
}
|
package/dist/inspect.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `abx inspect <script.js>` — static analysis of a generative script, BEFORE picking a lane.
|
|
3
|
-
*
|
|
4
|
-
* The membrane fix behind this: an agent (or creator) should DERIVE the deployment lane from what
|
|
5
|
-
* the script actually needs — are there traits? are they reproducible on-chain? how big is the
|
|
6
|
-
* assembled document (does a single `tokenURI` eth_call even fit)? — instead of guessing "fully
|
|
7
|
-
* on-chain!" and walking it back. This module is the pure analysis; `cmdInspect` formats it.
|
|
8
|
-
*
|
|
9
|
-
* Static only — it never executes the script (that's the resolver/runner's job, and executing
|
|
10
|
-
* untrusted art in the CLI would be a footgun). Everything here is regex/heuristic over the source.
|
|
11
|
-
*/
|
|
12
|
-
export type TraitFeasibility = 'none' | 'exact-likely' | 'careful' | 'infeasible' | 'unknown';
|
|
13
|
-
export interface ScriptAnalysis {
|
|
14
|
-
bytes: number;
|
|
15
|
-
estChunks: number;
|
|
16
|
-
traits: {
|
|
17
|
-
present: boolean;
|
|
18
|
-
keys: string[];
|
|
19
|
-
};
|
|
20
|
-
paramHints: string[];
|
|
21
|
-
prng: {
|
|
22
|
-
seeded: boolean;
|
|
23
|
-
usesBareRandom: boolean;
|
|
24
|
-
usesMathRandom: boolean;
|
|
25
|
-
usesNoise: boolean;
|
|
26
|
-
};
|
|
27
|
-
depHints: string[];
|
|
28
|
-
looksP5: boolean;
|
|
29
|
-
feasibility: {
|
|
30
|
-
verdict: TraitFeasibility;
|
|
31
|
-
reason: string;
|
|
32
|
-
};
|
|
33
|
-
doc: {
|
|
34
|
-
estBytes: number;
|
|
35
|
-
deps: string[];
|
|
36
|
-
fitsSingleCall: boolean;
|
|
37
|
-
unknownDepSizes: boolean;
|
|
38
|
-
};
|
|
39
|
-
runtime: {
|
|
40
|
-
readsTokenData: boolean;
|
|
41
|
-
reportsTraits: boolean;
|
|
42
|
-
wrongGlobal: string | null;
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
export declare function analyzeScript(source: string, declaredDeps?: string[]): ScriptAnalysis;
|
|
46
|
-
/** A one-line lane recommendation derived from the analysis (the decision-tree output). */
|
|
47
|
-
export declare function recommendLane(a: ScriptAnalysis): string;
|
|
48
|
-
//# sourceMappingURL=inspect.d.ts.map
|
package/dist/inspect.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../src/inspect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;AAE9F,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAC,CAAC;IAC3C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAC,CAAC;IAC9F,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE;QAAC,OAAO,EAAE,gBAAgB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC;IACzD,GAAG,EAAE;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,cAAc,EAAE,OAAO,CAAC;QAAC,eAAe,EAAE,OAAO,CAAA;KAAC,CAAC;IAM3F,OAAO,EAAE;QAAC,cAAc,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,CAAC;CACxF;AAsDD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,GAAE,MAAM,EAAO,GAAG,cAAc,CAqEzF;AAED,2FAA2F;AAC3F,wBAAgB,aAAa,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CA0BvD"}
|
package/dist/inspect.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `abx inspect <script.js>` — static analysis of a generative script, BEFORE picking a lane.
|
|
3
|
-
*
|
|
4
|
-
* The membrane fix behind this: an agent (or creator) should DERIVE the deployment lane from what
|
|
5
|
-
* the script actually needs — are there traits? are they reproducible on-chain? how big is the
|
|
6
|
-
* assembled document (does a single `tokenURI` eth_call even fit)? — instead of guessing "fully
|
|
7
|
-
* on-chain!" and walking it back. This module is the pure analysis; `cmdInspect` formats it.
|
|
8
|
-
*
|
|
9
|
-
* Static only — it never executes the script (that's the resolver/runner's job, and executing
|
|
10
|
-
* untrusted art in the CLI would be a footgun). Everything here is regex/heuristic over the source.
|
|
11
|
-
*/
|
|
12
|
-
/** Approx bytes a known on-chain dependency adds to the ASSEMBLED document (gzip'd + base64'd, as it
|
|
13
|
-
* rides in the inline data-URI). Measured from real drops; used only for the RPC-size estimate. */
|
|
14
|
-
const KNOWN_DEP_DOC_BYTES = {
|
|
15
|
-
'p5@1.0.0': 200_000, // p5 1.0.0 (~623KB raw) rides ~200KB gzip+base64 in the document
|
|
16
|
-
};
|
|
17
|
-
/** The on-chain runtime the generator always inlines (abx.js + the gunzip bootstrap), base64'd. */
|
|
18
|
-
const RUNTIME_DOC_BYTES = 13_000;
|
|
19
|
-
/** A single `eth_call` returning `tokenURI` comfortably carries this much document on a default node
|
|
20
|
-
* (geth's 50M gas cap; memory expansion is ~quadratic). Past it, marketplaces that call `tokenURI`
|
|
21
|
-
* once may time out — prefer the generator's piecewise getters, directory mode, or a CDN dep. */
|
|
22
|
-
const SINGLE_CALL_DOC_CEILING = 1_500_000;
|
|
23
|
-
/** PostParam keys the script READS from tokenData — the palette-style customization inputs. A deploy
|
|
24
|
-
* that omits these from `--schema` silently drops them (the render sees `undefined` → its default),
|
|
25
|
-
* which is exactly how a real session "forgot" the palette it had itself identified. Heuristic (the
|
|
26
|
-
* script isn't executed): find identifiers aliased to `abx.tokenData`, then their property reads;
|
|
27
|
-
* plus direct `abx.tokenData.key`, destructuring, and `tokenData['key']`. `seed` is intrinsic, not a
|
|
28
|
-
* PostParam, so it's excluded. Advisory — over- or under-detection is a hint, never a hard gate. */
|
|
29
|
-
function paramKeys(source) {
|
|
30
|
-
const keys = new Set();
|
|
31
|
-
const add = (k) => { if (k && k !== 'seed')
|
|
32
|
-
keys.add(k); };
|
|
33
|
-
// Identifiers aliased to the token-data object — either `abx.tokenData` (via abx.js) or the raw
|
|
34
|
-
// injected global `window.abxTokenData` (e.g. `var td = (window.abx && abx.tokenData) || {}`).
|
|
35
|
-
const aliases = new Set();
|
|
36
|
-
// The `(?!…\.[A-Za-z_$])` guard: only alias when the RHS is the tokenData OBJECT, not a PROPERTY of
|
|
37
|
-
// it — `const seed = abx.tokenData.seed` aliases `seed` to a scalar, so its method calls
|
|
38
|
-
// (`seed.startsWith(…)`) must NOT be read as params (the false-positive that flagged startsWith/slice).
|
|
39
|
-
const aliasRe = /\b([A-Za-z_$][\w$]*)\s*=\s*[^;\n]*(?:abx\s*\??\s*\.\s*tokenData|window\s*\??\s*\.\s*abxTokenData)(?!\s*\??\s*\.\s*[A-Za-z_$])/g;
|
|
40
|
-
let m;
|
|
41
|
-
while ((m = aliasRe.exec(source)) !== null)
|
|
42
|
-
aliases.add(m[1]);
|
|
43
|
-
for (const a of aliases) {
|
|
44
|
-
// `(?!\s*\()` excludes method CALLS (`td.slice(…)`) — a param read is a bare property, never a call.
|
|
45
|
-
const dotRe = new RegExp(`\\b${a.replace(/[$]/g, '\\$')}\\s*\\??\\s*\\.\\s*([A-Za-z_$][\\w$]*)(?!\\s*\\()`, 'g');
|
|
46
|
-
let d;
|
|
47
|
-
while ((d = dotRe.exec(source)) !== null)
|
|
48
|
-
add(d[1]);
|
|
49
|
-
}
|
|
50
|
-
// Direct `abx.tokenData.key` and `abx.tokenData['key']`.
|
|
51
|
-
const directRe = /abx\s*\??\s*\.\s*tokenData\s*\??\s*(?:\.\s*([A-Za-z_$][\w$]*)|\[\s*['"]([^'"]+)['"]\s*\])/g;
|
|
52
|
-
while ((m = directRe.exec(source)) !== null)
|
|
53
|
-
add(m[1] ?? m[2]);
|
|
54
|
-
// Destructuring: `const { palette, foo } = abx.tokenData` (or an alias).
|
|
55
|
-
const destrRe = /(?:const|let|var)\s*\{([^}]*)\}\s*=\s*[^;\n]*(?:abx\s*\.\s*tokenData|\b(?:tokenData|td)\b)/g;
|
|
56
|
-
while ((m = destrRe.exec(source)) !== null) {
|
|
57
|
-
for (const part of m[1].split(','))
|
|
58
|
-
add(part.split(':')[0].trim().replace(/\.\.\./, '') || undefined);
|
|
59
|
-
}
|
|
60
|
-
return [...keys];
|
|
61
|
-
}
|
|
62
|
-
/** Extract the key names from the first `abx.traits({ ... })` object literal (flat objects only). */
|
|
63
|
-
function traitKeys(source) {
|
|
64
|
-
const m = source.match(/abx\s*\??\s*\.\s*traits\s*\(\s*\{([^}]*)\}/);
|
|
65
|
-
if (!m)
|
|
66
|
-
return [];
|
|
67
|
-
const keys = [];
|
|
68
|
-
// A key sits at the start of the object or right after a comma (so a ternary VALUE like
|
|
69
|
-
// `? 'Sparse' : 'Dense'` — a `:` not preceded by `,`/`{` — is never mistaken for a key). Allow
|
|
70
|
-
// leading whitespace after `^` so the FIRST key (preceded only by the newline after `{`) is caught.
|
|
71
|
-
// A key is EITHER a quoted string (arbitrary content — `'Plant Count'`, a spaced trait_type a
|
|
72
|
-
// marketplace shows) OR a bare identifier; a bare-identifier-only match silently dropped quoted
|
|
73
|
-
// keys, and "believe inspect" then sent authors chasing a phantom missing trait.
|
|
74
|
-
const re = /(?:^\s*|[,{]\s*)(?:(['"])([^'"]+)\1|([A-Za-z_$][\w$]*))\s*:/g;
|
|
75
|
-
let k;
|
|
76
|
-
while ((k = re.exec(m[1])) !== null)
|
|
77
|
-
keys.push(k[2] ?? k[3]);
|
|
78
|
-
return [...new Set(keys)];
|
|
79
|
-
}
|
|
80
|
-
export function analyzeScript(source, declaredDeps = []) {
|
|
81
|
-
const bytes = new TextEncoder().encode(source).length;
|
|
82
|
-
const keys = traitKeys(source);
|
|
83
|
-
const usesMathRandom = /Math\s*\.\s*random\s*\(/.test(source);
|
|
84
|
-
// p5's bare random(...) — a `random(` NOT preceded by `.` or a word char (so not Math.random / obj.random)
|
|
85
|
-
const usesBareRandom = /(^|[^.\w])random\s*\(/.test(source);
|
|
86
|
-
const seeded = /\brandomSeed\s*\(/.test(source);
|
|
87
|
-
const usesNoise = /\bnoise\s*\(/.test(source);
|
|
88
|
-
const looksP5 = /\bcreateCanvas\s*\(|function\s+setup\s*\(|function\s+draw\s*\(|\bp5\b/.test(source);
|
|
89
|
-
const depHints = [];
|
|
90
|
-
if (looksP5)
|
|
91
|
-
depHints.push('p5');
|
|
92
|
-
if (/\bTHREE\b/.test(source))
|
|
93
|
-
depHints.push('three');
|
|
94
|
-
if (/\bTone\b/.test(source))
|
|
95
|
-
depHints.push('tone');
|
|
96
|
-
// The abx.js runtime data contract — does the script read state + report traits the ONE way the
|
|
97
|
-
// toolkit injects/captures them? A near-miss global deploys fine but is silently broken.
|
|
98
|
-
// `\??\s*\.` tolerates optional chaining (`abx?.tokenData`) — a common, correct way to read it.
|
|
99
|
-
const readsTokenData = /abx\s*\??\s*\.\s*tokenData\b/.test(source) || /window\s*\??\s*\.\s*abxTokenData\b/.test(source);
|
|
100
|
-
const reportsTraits = /abx\s*\??\s*\.\s*traits\s*\(/.test(source);
|
|
101
|
-
let wrongGlobal = null;
|
|
102
|
-
if (!readsTokenData) {
|
|
103
|
-
if (/window\s*\.\s*tokenTraits\b/.test(source))
|
|
104
|
-
wrongGlobal = 'window.tokenTraits — traits are reported by CALLING abx.traits({…}), never by writing a global';
|
|
105
|
-
else if (/window\s*\.\s*tokenData\b/.test(source))
|
|
106
|
-
wrongGlobal = 'window.tokenData — abx injects window.abxTokenData (read it via abx.tokenData), not window.tokenData';
|
|
107
|
-
else if (/\btokenData\b/.test(source))
|
|
108
|
-
wrongGlobal = 'a bare `tokenData` — read abx.tokenData (via abx.js) or the raw window.abxTokenData global';
|
|
109
|
-
}
|
|
110
|
-
// Trait-reproducibility rubric (see docs/research/onchain-traits-feasibility.md).
|
|
111
|
-
let verdict;
|
|
112
|
-
let reason;
|
|
113
|
-
if (keys.length === 0) {
|
|
114
|
-
verdict = 'none';
|
|
115
|
-
reason = 'no abx.traits({…}) call → NO marketplace traits on ANY lane. A resolver captures the keys you pass to abx.traits(); it does not invent traits from internal variables or a global. Call abx.traits({…}) in the sketch if you want filterable traits.';
|
|
116
|
-
}
|
|
117
|
-
else if (usesMathRandom && !seeded) {
|
|
118
|
-
verdict = 'infeasible';
|
|
119
|
-
reason = 'traits derive from Math.random() (unseeded) — non-deterministic, reproducible nowhere. Serve attributes via a resolver, or ship without marketplace traits.';
|
|
120
|
-
}
|
|
121
|
-
else if (seeded && looksP5) {
|
|
122
|
-
verdict = 'exact-likely';
|
|
123
|
-
reason = 'seeded p5 random() is a documented LCG — integer floor/threshold/select traits port EXACTLY to Solidity. Confirm no trait keys off a raw float value. Wire with --attributes-renderer (see docs/research/onchain-traits-feasibility.md).';
|
|
124
|
-
}
|
|
125
|
-
else if (seeded) {
|
|
126
|
-
verdict = 'careful';
|
|
127
|
-
reason = "seeded, but the PRNG isn't identified as p5 — reproducible on-chain if you port that generator + the exact call order.";
|
|
128
|
-
}
|
|
129
|
-
else if (usesBareRandom) {
|
|
130
|
-
verdict = 'unknown';
|
|
131
|
-
reason = 'traits present and random() is used, but no randomSeed() was found — check the art is deterministic before attempting on-chain traits.';
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
verdict = 'exact-likely';
|
|
135
|
-
reason = 'traits look derived from the seed/params directly (no PRNG) — reproducible on-chain via an attributes field-renderer.';
|
|
136
|
-
}
|
|
137
|
-
const deps = declaredDeps;
|
|
138
|
-
let unknownDepSizes = false;
|
|
139
|
-
let depDocBytes = 0;
|
|
140
|
-
for (const d of deps) {
|
|
141
|
-
if (d in KNOWN_DEP_DOC_BYTES)
|
|
142
|
-
depDocBytes += KNOWN_DEP_DOC_BYTES[d];
|
|
143
|
-
else
|
|
144
|
-
unknownDepSizes = true;
|
|
145
|
-
}
|
|
146
|
-
const estBytes = bytes + RUNTIME_DOC_BYTES + depDocBytes;
|
|
147
|
-
return {
|
|
148
|
-
bytes,
|
|
149
|
-
estChunks: Math.max(1, Math.ceil(bytes / 22_000)),
|
|
150
|
-
traits: { present: keys.length > 0, keys },
|
|
151
|
-
paramHints: paramKeys(source),
|
|
152
|
-
prng: { seeded, usesBareRandom, usesMathRandom, usesNoise },
|
|
153
|
-
depHints,
|
|
154
|
-
looksP5,
|
|
155
|
-
feasibility: { verdict, reason },
|
|
156
|
-
doc: { estBytes, deps, fitsSingleCall: estBytes <= SINGLE_CALL_DOC_CEILING && !unknownDepSizes, unknownDepSizes },
|
|
157
|
-
runtime: { readsTokenData, reportsTraits, wrongGlobal },
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
/** A one-line lane recommendation derived from the analysis (the decision-tree output). */
|
|
161
|
-
export function recommendLane(a) {
|
|
162
|
-
const bigDoc = !a.doc.fitsSingleCall && !a.doc.unknownDepSizes;
|
|
163
|
-
if (bigDoc) {
|
|
164
|
-
return 'DIRECTORY mode (--code-dir) or a CDN dependency — the assembled document is too large for a single tokenURI eth_call to be reliable.';
|
|
165
|
-
}
|
|
166
|
-
if (a.feasibility.verdict === 'infeasible') {
|
|
167
|
-
return 'RESOLVER lane (--public-base-url) if marketplace traits matter (a server serves the JS-derived attributes), OR --onchain-uri and accept no marketplace traits (the tokenURI + animation are still fully on-chain).';
|
|
168
|
-
}
|
|
169
|
-
if (a.feasibility.verdict === 'exact-likely' || a.feasibility.verdict === 'none') {
|
|
170
|
-
const dep = a.depHints.length ? ` --dep ${a.depHints[0]}@<version>` : '';
|
|
171
|
-
const docKb = Math.round(a.doc.estBytes / 1000);
|
|
172
|
-
// Owner call (real-world experience): for a generative drop meant to sell, LEAD with the off-chain
|
|
173
|
-
// resolver — maneuverable over time + marketplaces fetch a SMALL tokenURI reliably. Fully-on-chain
|
|
174
|
-
// is the durability-max alternative, but its ~docKb tokenURI (whole doc per call) strains some
|
|
175
|
-
// marketplace/indexer reads. Traits are NOT a free flag on the on-chain lane (deployed renderer).
|
|
176
|
-
const traits = a.traits.present
|
|
177
|
-
? ` Traits (${a.traits.keys.join(', ')}): the resolver serves them from the render with no Solidity; on the on-chain lane they need a DEPLOYED --attributes-renderer (fork SeedTraitsRenderer.sol) or they're omitted.`
|
|
178
|
-
: ``;
|
|
179
|
-
return (`RECOMMENDED for a drop you'll sell — OFF-CHAIN RESOLVER (--public-base-url + an effects runner): maneuverable (metadata/serving can evolve without on-chain surgery) and marketplaces fetch a SMALL tokenURI reliably.${traits}\n` +
|
|
180
|
-
` ALTERNATIVE — FULLY ON-CHAIN (--onchain-uri${dep} --image-base <bucket>): maximal durability / no server, but the tokenURI carries the whole ~${docKb}KB document per call (some marketplace + indexer reads choke on a doc this big), stills are MANUAL, and later changes are on-chain re-points. Pick it when permanence + zero-infra outweigh maneuverability.`);
|
|
181
|
-
}
|
|
182
|
-
return (`RECOMMENDED — an OFF-CHAIN RESOLVER (--public-base-url): maneuverable, and it serves traits from the render regardless of the PRNG. --onchain-uri also works for tokenURI + animation, but first verify the script is deterministic (see the feasibility note), and note the large-tokenURI marketplace-read tradeoff; on that lane traits need a DEPLOYED --attributes-renderer or are omitted.`);
|
|
183
|
-
}
|
|
184
|
-
//# sourceMappingURL=inspect.js.map
|