@artblocks/abx-cli 0.1.0-alpha.0

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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/assets/renderer-scaffold/README.md +59 -0
  3. package/assets/renderer-scaffold/foundry.toml +15 -0
  4. package/assets/renderer-scaffold/remappings.txt +3 -0
  5. package/assets/renderer-scaffold/script/Deploy.s.sol +23 -0
  6. package/assets/renderer-scaffold/src/MyRenderer.sol +123 -0
  7. package/assets/renderer-scaffold/src/MyTraits.sol +75 -0
  8. package/assets/renderer-scaffold/src/interfaces/IAbxFieldRenderer.sol +32 -0
  9. package/assets/renderer-scaffold/src/interfaces/IAbxParams.sol +26 -0
  10. package/assets/renderer-scaffold/test/MyRenderer.t.sol +110 -0
  11. package/dist/config.d.ts +69 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +184 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/deps.d.ts +46 -0
  16. package/dist/deps.d.ts.map +1 -0
  17. package/dist/deps.js +90 -0
  18. package/dist/deps.js.map +1 -0
  19. package/dist/flags.d.ts +25 -0
  20. package/dist/flags.d.ts.map +1 -0
  21. package/dist/flags.js +34 -0
  22. package/dist/flags.js.map +1 -0
  23. package/dist/inspect.d.ts +48 -0
  24. package/dist/inspect.d.ts.map +1 -0
  25. package/dist/inspect.js +184 -0
  26. package/dist/inspect.js.map +1 -0
  27. package/dist/main.d.ts +3 -0
  28. package/dist/main.d.ts.map +1 -0
  29. package/dist/main.js +5102 -0
  30. package/dist/main.js.map +1 -0
  31. package/dist/migrate.d.ts +65 -0
  32. package/dist/migrate.d.ts.map +1 -0
  33. package/dist/migrate.js +180 -0
  34. package/dist/migrate.js.map +1 -0
  35. package/dist/mintpage.d.ts +46 -0
  36. package/dist/mintpage.d.ts.map +1 -0
  37. package/dist/mintpage.js +461 -0
  38. package/dist/mintpage.js.map +1 -0
  39. package/dist/onchain-uri.d.ts +97 -0
  40. package/dist/onchain-uri.d.ts.map +1 -0
  41. package/dist/onchain-uri.js +243 -0
  42. package/dist/onchain-uri.js.map +1 -0
  43. package/dist/ownerops.d.ts +195 -0
  44. package/dist/ownerops.d.ts.map +1 -0
  45. package/dist/ownerops.js +1270 -0
  46. package/dist/ownerops.js.map +1 -0
  47. package/dist/provision.d.ts +86 -0
  48. package/dist/provision.d.ts.map +1 -0
  49. package/dist/provision.js +372 -0
  50. package/dist/provision.js.map +1 -0
  51. package/dist/remote.d.ts +58 -0
  52. package/dist/remote.d.ts.map +1 -0
  53. package/dist/remote.js +54 -0
  54. package/dist/remote.js.map +1 -0
  55. package/dist/schema.d.ts +15 -0
  56. package/dist/schema.d.ts.map +1 -0
  57. package/dist/schema.js +125 -0
  58. package/dist/schema.js.map +1 -0
  59. package/dist/series-traits.d.ts +30 -0
  60. package/dist/series-traits.d.ts.map +1 -0
  61. package/dist/series-traits.js +103 -0
  62. package/dist/series-traits.js.map +1 -0
  63. package/dist/signer.d.ts +80 -0
  64. package/dist/signer.d.ts.map +1 -0
  65. package/dist/signer.js +520 -0
  66. package/dist/signer.js.map +1 -0
  67. package/dist/upload.d.ts +28 -0
  68. package/dist/upload.d.ts.map +1 -0
  69. package/dist/upload.js +41 -0
  70. package/dist/upload.js.map +1 -0
  71. package/package.json +55 -0
  72. package/skill/SKILL.md +304 -0
  73. package/skill/reference/code-projects.md +211 -0
  74. package/skill/reference/hosting.md +138 -0
  75. package/skill/reference/operating.md +116 -0
  76. package/skill/reference/setup.md +36 -0
  77. package/skill/reference/troubleshooting.md +28 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Talk to a REMOTE resolver's admin control plane — the HTTP form of `abx add` /
3
+ * `abx index` / `abx forget`, pointed at a hosted node (fly/render/vps) instead of
4
+ * this machine's local projection. This is the bridge the toolkit was missing: a
5
+ * contract you deploy here is registered with the *local* store; the resolver baked
6
+ * into your on-chain tokenURI is a *different* store and must be told separately, or
7
+ * it answers "unknown project". These helpers do the telling.
8
+ *
9
+ * The admin token authorizes indexing control only — never on-chain signing — so the
10
+ * "no signing key on the host" rule is intact. It lives in `.env` as
11
+ * ABX_RESOLVER_ADMIN_TOKEN and must match the token set on the resolver.
12
+ */
13
+ export interface RemoteAddBody {
14
+ address: string;
15
+ /** Scan floor — the deploy block. Omit on a re-POST (the nudge) to keep the stored floor + reindex incrementally. */
16
+ fromBlock?: string;
17
+ factory?: string;
18
+ label?: string;
19
+ description?: string;
20
+ externalUrl?: string;
21
+ /** Off-chain operator traits (OpenSea attribute array) — stitched UNDER any on-chain `attributes`. */
22
+ attributes?: Array<{
23
+ trait_type: string;
24
+ value: string | number;
25
+ display_type?: string;
26
+ }>;
27
+ /** Off-chain PER-TOKEN operator traits, `{ "<tokenId>": OpenSeaAttribute[] }` — a Series' editable
28
+ * traits (a token's entry wins over the collection-scope `attributes`; on-chain wins over both). */
29
+ tokenAttributes?: Record<string, Array<{
30
+ trait_type: string;
31
+ value: string | number;
32
+ display_type?: string;
33
+ }>>;
34
+ /** Durable locators keyed by on-chain hash, `{ "0x<keccak>": "ipfs://<cid>" }` — lets the resolver
35
+ * point `image` at IPFS/Arweave without holding the bytes. Merged over any already stored. */
36
+ contentLocators?: Record<string, string>;
37
+ /** Force a full replay even on a re-POST. */
38
+ full?: boolean;
39
+ }
40
+ export interface RemoteAddResult {
41
+ ok: boolean;
42
+ mode: 'full' | 'incremental';
43
+ elapsedMs: number;
44
+ project: {
45
+ address: string;
46
+ name: string | null;
47
+ eventCount: number;
48
+ tokenCount: number;
49
+ mintedCount: number;
50
+ };
51
+ }
52
+ /** Normalize a resolver base URL to its `/admin/projects` control-plane endpoint. */
53
+ export declare function adminProjectsUrl(base: string): string;
54
+ /** Register + index a project with a remote resolver (remote `abx add`/`index`). */
55
+ export declare function remoteAddProject(base: string, token: string, body: RemoteAddBody): Promise<RemoteAddResult>;
56
+ /** Stop a remote resolver from indexing a project (remote `abx forget`). */
57
+ export declare function remoteRemoveProject(base: string, token: string, address: string): Promise<void>;
58
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,qHAAqH;IACrH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sGAAsG;IACtG,UAAU,CAAC,EAAE,KAAK,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACxF;yGACqG;IACrG,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC,CAAC;IAC7G;mGAC+F;IAC/F,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,6CAA6C;IAC7C,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAAC;CAC9G;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAuBD,oFAAoF;AACpF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAQjH;AAED,4EAA4E;AAC5E,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrG"}
package/dist/remote.js ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Talk to a REMOTE resolver's admin control plane — the HTTP form of `abx add` /
3
+ * `abx index` / `abx forget`, pointed at a hosted node (fly/render/vps) instead of
4
+ * this machine's local projection. This is the bridge the toolkit was missing: a
5
+ * contract you deploy here is registered with the *local* store; the resolver baked
6
+ * into your on-chain tokenURI is a *different* store and must be told separately, or
7
+ * it answers "unknown project". These helpers do the telling.
8
+ *
9
+ * The admin token authorizes indexing control only — never on-chain signing — so the
10
+ * "no signing key on the host" rule is intact. It lives in `.env` as
11
+ * ABX_RESOLVER_ADMIN_TOKEN and must match the token set on the resolver.
12
+ */
13
+ /** Normalize a resolver base URL to its `/admin/projects` control-plane endpoint. */
14
+ export function adminProjectsUrl(base) {
15
+ return base.replace(/\/+$/, '') + '/admin/projects';
16
+ }
17
+ function authHeaders(token) {
18
+ return { authorization: `Bearer ${token}`, 'content-type': 'application/json' };
19
+ }
20
+ /** Map a non-2xx admin response into a useful Error (surfaces the server's message). */
21
+ async function asError(label, resp) {
22
+ let detail = '';
23
+ try {
24
+ detail = (await resp.json()).error ?? '';
25
+ }
26
+ catch {
27
+ /* non-JSON body */
28
+ }
29
+ if (resp.status === 401) {
30
+ return new Error(`${label}: 401 unauthorized — ABX_RESOLVER_ADMIN_TOKEN doesn't match the token on the resolver.`);
31
+ }
32
+ if (resp.status === 404 && detail.includes('disabled')) {
33
+ return new Error(`${label}: the resolver has no admin token set — it can't accept remote add/remove. ${detail}`);
34
+ }
35
+ return new Error(`${label}: ${resp.status} ${detail || resp.statusText}`);
36
+ }
37
+ /** Register + index a project with a remote resolver (remote `abx add`/`index`). */
38
+ export async function remoteAddProject(base, token, body) {
39
+ const resp = await fetch(adminProjectsUrl(base), {
40
+ method: 'POST',
41
+ headers: authHeaders(token),
42
+ body: JSON.stringify(body),
43
+ });
44
+ if (!resp.ok)
45
+ throw await asError('remote add', resp);
46
+ return (await resp.json());
47
+ }
48
+ /** Stop a remote resolver from indexing a project (remote `abx forget`). */
49
+ export async function remoteRemoveProject(base, token, address) {
50
+ const resp = await fetch(`${adminProjectsUrl(base)}/${address}`, { method: 'DELETE', headers: authHeaders(token) });
51
+ if (!resp.ok && resp.status !== 404)
52
+ throw await asError('remote remove', resp);
53
+ }
54
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA6BH,qFAAqF;AACrF,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,iBAAiB,CAAC;AACtD,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,EAAC,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAC,CAAC;AAChF,CAAC;AAED,wFAAwF;AACxF,KAAK,UAAU,OAAO,CAAC,KAAa,EAAE,IAAc;IAClD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAsB,CAAC,KAAK,IAAI,EAAE,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB;IACrB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACxB,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,wFAAwF,CAAC,CAAC;IACrH,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACvD,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,8EAA8E,MAAM,EAAE,CAAC,CAAC;IACnH,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,MAAM,IAAI,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,KAAa,EAAE,IAAmB;IACrF,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE;QAC/C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;QAC3B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,MAAM,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACtD,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAoB,CAAC;AAChD,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAY,EAAE,KAAa,EAAE,OAAe;IACpF,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,OAAO,EAAE,EAAE,EAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAAC,CAAC,CAAC;IAClH,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG;QAAE,MAAM,MAAM,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;AAClF,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Hex } from 'viem';
2
+ export interface ParsedSchema {
3
+ key: string;
4
+ paramType: number;
5
+ auth: number;
6
+ min: Hex;
7
+ max: Hex;
8
+ selectOptions: string[];
9
+ }
10
+ export declare function parseSchemaSpec(spec: string): ParsedSchema;
11
+ /** Parse a full `--schema` value: comma-separated specs. */
12
+ export declare function parseSchemaSpecs(raw: string | undefined): ParsedSchema[];
13
+ /** A human one-line rendering of a parsed schema (for the confirm readout). */
14
+ export declare function describeSchema(s: ParsedSchema): string;
15
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,MAAM,CAAC;AAO9B,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,GAAG,CAAC;IACT,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAQD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAyD1D;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,EAAE,CAMxE;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAWtD"}
package/dist/schema.js ADDED
@@ -0,0 +1,125 @@
1
+ /**
2
+ * `--schema` spec parsing for `deploy-code` PostParams.
3
+ *
4
+ * The on-chain `setParamSchema(key, paramType, auth, authAddress, lockAfter, min, max, selectOptions)`
5
+ * carries more than the old CLI format (`key:Type:Auth`) could express — a `Select` REQUIRES its
6
+ * option list (the contract reverts `InvalidParamSchema` without it), and the Range types carry
7
+ * `min`/`max` bounds. This parser extends the format with an optional bracket suffix on the Type
8
+ * token so a single, backwards-compatible string expresses all of it:
9
+ *
10
+ * key:HexColor:TokenOwner simple type (unchanged)
11
+ * key:Select[Spring|Summer|Autumn|Winter]:Auth Select — options, pipe-delimited (REQUIRED)
12
+ * key:Uint256Range[0..100]:Auth Range — inclusive min..max bounds (optional)
13
+ * key:Int256Range[-50..50]:Auth
14
+ * key:DecimalRange[0..1]:Auth decimals, ≤10 places (÷1e10 fixed-point)
15
+ * key:Timestamp[2026-01-01..2026-12-31]:Auth unix seconds OR ISO dates
16
+ *
17
+ * Delimiters can't collide: params are comma-separated, fields colon-separated, options
18
+ * pipe-separated, bounds `..`-separated — and options/bounds live inside `[...]`, so none of the
19
+ * outer delimiters appear there. Omit the bracket on a Range → unbounded (min=max=0, the prior
20
+ * behavior). A Select with no bracket, or a bracket on a type that takes none, is a clear error.
21
+ */
22
+ import { PARAM_TYPES, AUTH_OPTIONS, encodeScalarParam } from '@artblocks/abx-sdk';
23
+ const ZERO32 = `0x${'0'.repeat(64)}`;
24
+ /** The types that accept a `[min..max]` bound (the contract's min/max fields are meaningful here). */
25
+ const BOUNDED_TYPES = new Set(['Uint256Range', 'Int256Range', 'DecimalRange', 'Timestamp']);
26
+ /** min ≤ max in the type's own ordering (mirrors AbxParamsLib's on-chain check, but earlier + clearer). */
27
+ function orderedBounds(typeName, min, max) {
28
+ if (typeName === 'Int256Range')
29
+ return BigInt.asIntN(256, BigInt(min)) <= BigInt.asIntN(256, BigInt(max));
30
+ return BigInt(min) <= BigInt(max);
31
+ }
32
+ export function parseSchemaSpec(spec) {
33
+ const parts = spec.split(':');
34
+ if (parts.length !== 3) {
35
+ throw new Error(`--schema "${spec}" — expected key:Type:Auth (a Select adds options: key:Select[A|B|C]:Auth; a Range adds bounds: key:Uint256Range[0..100]:Auth).`);
36
+ }
37
+ const [key, typeToken, authName] = parts;
38
+ const m = typeToken.match(/^([A-Za-z0-9]+)(?:\[(.*)\])?$/);
39
+ if (!key || !m)
40
+ throw new Error(`--schema "${spec}" — malformed type "${typeToken}".`);
41
+ const typeName = m[1];
42
+ const bracket = m[2]; // undefined when there is no [...]
43
+ const paramType = PARAM_TYPES.indexOf(typeName);
44
+ const auth = AUTH_OPTIONS.indexOf(authName);
45
+ if (paramType < 0 || auth < 0) {
46
+ throw new Error(`--schema "${spec}" — Type ∈ {${PARAM_TYPES.join('|')}}, Auth ∈ {${AUTH_OPTIONS.join('|')}}.`);
47
+ }
48
+ if (AUTH_OPTIONS[auth].includes('Address')) {
49
+ throw new Error(`--schema "${spec}" — Address-auth legs need an authAddress; set that schema post-deploy via the contract.`);
50
+ }
51
+ let min = ZERO32;
52
+ let max = ZERO32;
53
+ let selectOptions = [];
54
+ if (typeName === 'Select') {
55
+ if (bracket === undefined) {
56
+ throw new Error(`--schema "${spec}" — a Select needs its options: ${key}:Select[Option A|Option B|Option C]:${authName}.`);
57
+ }
58
+ selectOptions = bracket.split('|').map((o) => o.trim());
59
+ if (selectOptions.length === 0 || selectOptions.some((o) => o === '')) {
60
+ throw new Error(`--schema "${spec}" — Select options must be non-empty, e.g. ${key}:Select[A|B|C]:${authName}.`);
61
+ }
62
+ if (new Set(selectOptions).size !== selectOptions.length) {
63
+ throw new Error(`--schema "${spec}" — duplicate Select option in [${selectOptions.join('|')}].`);
64
+ }
65
+ for (const o of selectOptions) {
66
+ if (/[,:\]]/.test(o))
67
+ throw new Error(`--schema "${spec}" — a Select option can't contain , : or ] (got "${o}"). Use simpler labels.`);
68
+ }
69
+ }
70
+ else if (bracket !== undefined) {
71
+ if (!BOUNDED_TYPES.has(typeName)) {
72
+ throw new Error(`--schema "${spec}" — ${typeName} takes no [...]; only ${[...BOUNDED_TYPES].join('/')} take [min..max], and Select takes [options].`);
73
+ }
74
+ const mm = bracket.split('..');
75
+ if (mm.length !== 2)
76
+ throw new Error(`--schema "${spec}" — bounds are [min..max], e.g. ${key}:${typeName}[0..100]:${authName}.`);
77
+ try {
78
+ min = encodeScalarParam(typeName, mm[0].trim(), []).value;
79
+ max = encodeScalarParam(typeName, mm[1].trim(), []).value;
80
+ }
81
+ catch (e) {
82
+ throw new Error(`--schema "${spec}" — bad bound: ${e.message}`);
83
+ }
84
+ if (!orderedBounds(typeName, min, max)) {
85
+ throw new Error(`--schema "${spec}" — min must be ≤ max (got ${mm[0].trim()}..${mm[1].trim()}).`);
86
+ }
87
+ }
88
+ return { key, paramType, auth, min, max, selectOptions };
89
+ }
90
+ /** Parse a full `--schema` value: comma-separated specs. */
91
+ export function parseSchemaSpecs(raw) {
92
+ return String(raw ?? '')
93
+ .split(',')
94
+ .map((s) => s.trim())
95
+ .filter(Boolean)
96
+ .map(parseSchemaSpec);
97
+ }
98
+ /** A human one-line rendering of a parsed schema (for the confirm readout). */
99
+ export function describeSchema(s) {
100
+ const type = PARAM_TYPES[s.paramType];
101
+ const auth = AUTH_OPTIONS[s.auth];
102
+ let detail = '';
103
+ if (type === 'Select')
104
+ detail = `[${s.selectOptions.join(' | ')}]`;
105
+ else if (s.min !== ZERO32 || s.max !== ZERO32) {
106
+ const lo = decodeBound(type, s.min);
107
+ const hi = decodeBound(type, s.max);
108
+ detail = `[${lo}..${hi}]`;
109
+ }
110
+ return `${s.key}:${type}${detail}:${auth}`;
111
+ }
112
+ function decodeBound(typeName, v) {
113
+ // Cheap display-only decode (the SDK's decodeScalarParam is the canonical one, but this keeps the
114
+ // readout dependency-light for the two Range cases that matter in a bound).
115
+ if (typeName === 'Int256Range')
116
+ return BigInt.asIntN(256, BigInt(v)).toString();
117
+ if (typeName === 'DecimalRange') {
118
+ const scaled = BigInt(v);
119
+ const whole = scaled / 10000000000n;
120
+ const frac = (scaled % 10000000000n).toString().padStart(10, '0').replace(/0+$/, '');
121
+ return frac ? `${whole}.${frac}` : `${whole}`;
122
+ }
123
+ return BigInt(v).toString();
124
+ }
125
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Per-token marketplace traits for a Series (`deploy-series --attributes <file.json>`).
3
+ *
4
+ * The contract already carries per-token `attributes` fields (`SeriesImage.InitParams.tokenFields`,
5
+ * keyed by tokenId) — exactly like the per-token `image` fields deploy-series already writes. This is
6
+ * purely the CLI ergonomics of supplying them for a folder of media, so it's extracted here (main.ts
7
+ * runs the CLI on import, so its helpers aren't unit-testable). The manifest is EITHER:
8
+ * • an ARRAY indexed by token id — `[[{trait_type,value}…], …]` (element i = token i); OR
9
+ * • an OBJECT keyed by the media FILENAME (with or without extension) or the token-id string.
10
+ * Each value is an OpenSea attributes array OR a `{name: value}` map (normalized either way).
11
+ */
12
+ import { type OpenSeaAttribute } from '@artblocks/abx-sdk';
13
+ /** Parse the `--attributes` manifest CONTENT (not a path) into a sparse tokenId → attributes map. */
14
+ export declare function parseSeriesTraits(rawJson: string | undefined, slots: string[]): Map<number, OpenSeaAttribute[]>;
15
+ /**
16
+ * True when a `--attributes` payload is the Series PER-TOKEN shape — an array whose elements are
17
+ * themselves attribute arrays/maps (element i = token i), or an object whose VALUES are attribute
18
+ * arrays/maps (keyed by token id / filename) — as opposed to a flat 1/1 payload (an OpenSea attributes
19
+ * array `[{trait_type,value}…]` or a single `{name: value}` map). Ambiguity defaults to flat, so a
20
+ * 1/1's `--attributes` at `abx add` is never mis-read as per-token. Content, not a path.
21
+ */
22
+ export declare function looksPerTokenAttributes(rawJson: string): boolean;
23
+ /**
24
+ * Parse a PER-TOKEN `--attributes` payload for an EDIT at `abx add` — no media folder is present, so
25
+ * only token-id keys resolve (an array indexes by token id; an object's numeric keys are token ids;
26
+ * filename-only keys can't be mapped and are dropped). Returns a `{ "<tokenId>": OpenSeaAttribute[] }`
27
+ * map ready for the `tokenAttributes` column. Content, not a path.
28
+ */
29
+ export declare function parseSeriesTraitsById(rawJson: string): Record<string, OpenSeaAttribute[]>;
30
+ //# sourceMappingURL=series-traits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"series-traits.d.ts","sourceRoot":"","sources":["../src/series-traits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAsB,KAAK,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAE9E,qGAAqG;AACrG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CA0B/G;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAmBhE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAgBzF"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Per-token marketplace traits for a Series (`deploy-series --attributes <file.json>`).
3
+ *
4
+ * The contract already carries per-token `attributes` fields (`SeriesImage.InitParams.tokenFields`,
5
+ * keyed by tokenId) — exactly like the per-token `image` fields deploy-series already writes. This is
6
+ * purely the CLI ergonomics of supplying them for a folder of media, so it's extracted here (main.ts
7
+ * runs the CLI on import, so its helpers aren't unit-testable). The manifest is EITHER:
8
+ * • an ARRAY indexed by token id — `[[{trait_type,value}…], …]` (element i = token i); OR
9
+ * • an OBJECT keyed by the media FILENAME (with or without extension) or the token-id string.
10
+ * Each value is an OpenSea attributes array OR a `{name: value}` map (normalized either way).
11
+ */
12
+ import { normalizeAttributes } from '@artblocks/abx-sdk';
13
+ /** Parse the `--attributes` manifest CONTENT (not a path) into a sparse tokenId → attributes map. */
14
+ export function parseSeriesTraits(rawJson, slots) {
15
+ const out = new Map();
16
+ if (!rawJson)
17
+ return out;
18
+ let parsed;
19
+ try {
20
+ parsed = JSON.parse(rawJson);
21
+ }
22
+ catch (e) {
23
+ throw new Error(`--attributes: not valid JSON (${e.message})`);
24
+ }
25
+ const put = (i, v) => {
26
+ if (v == null)
27
+ return;
28
+ const attrs = normalizeAttributes(v);
29
+ if (attrs.length)
30
+ out.set(i, attrs);
31
+ };
32
+ if (Array.isArray(parsed)) {
33
+ parsed.forEach((v, i) => { if (i < slots.length)
34
+ put(i, v); });
35
+ }
36
+ else if (parsed && typeof parsed === 'object') {
37
+ const obj = parsed;
38
+ slots.forEach((name, i) => {
39
+ const base = name.replace(/\.[^.]+$/, '');
40
+ put(i, obj[name] ?? obj[base] ?? obj[String(i)]);
41
+ });
42
+ }
43
+ else {
44
+ throw new Error('--attributes for a Series expects a JSON array (indexed by token id) or an object keyed by filename / token id — each value an attributes array or a {name: value} map.');
45
+ }
46
+ return out;
47
+ }
48
+ /**
49
+ * True when a `--attributes` payload is the Series PER-TOKEN shape — an array whose elements are
50
+ * themselves attribute arrays/maps (element i = token i), or an object whose VALUES are attribute
51
+ * arrays/maps (keyed by token id / filename) — as opposed to a flat 1/1 payload (an OpenSea attributes
52
+ * array `[{trait_type,value}…]` or a single `{name: value}` map). Ambiguity defaults to flat, so a
53
+ * 1/1's `--attributes` at `abx add` is never mis-read as per-token. Content, not a path.
54
+ */
55
+ export function looksPerTokenAttributes(rawJson) {
56
+ let parsed;
57
+ try {
58
+ parsed = JSON.parse(rawJson);
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ const isAttr = (v) => v != null && typeof v === 'object' && !Array.isArray(v) && 'trait_type' in v;
64
+ const isScalar = (v) => v == null || typeof v !== 'object';
65
+ if (Array.isArray(parsed)) {
66
+ // Flat = array of {trait_type,value}; per-token = array of arrays/maps (no top-level trait_type).
67
+ return parsed.length > 0 && parsed.every((v) => Array.isArray(v) || (v != null && typeof v === 'object' && !isAttr(v)));
68
+ }
69
+ if (parsed && typeof parsed === 'object') {
70
+ const vals = Object.values(parsed);
71
+ // Flat `{name: value}` map = scalar values; per-token = every value is an array/map of traits.
72
+ return vals.length > 0 && vals.every((v) => !isScalar(v));
73
+ }
74
+ return false;
75
+ }
76
+ /**
77
+ * Parse a PER-TOKEN `--attributes` payload for an EDIT at `abx add` — no media folder is present, so
78
+ * only token-id keys resolve (an array indexes by token id; an object's numeric keys are token ids;
79
+ * filename-only keys can't be mapped and are dropped). Returns a `{ "<tokenId>": OpenSeaAttribute[] }`
80
+ * map ready for the `tokenAttributes` column. Content, not a path.
81
+ */
82
+ export function parseSeriesTraitsById(rawJson) {
83
+ const parsed = JSON.parse(rawJson);
84
+ const out = {};
85
+ const put = (id, v) => {
86
+ if (v == null)
87
+ return;
88
+ const attrs = normalizeAttributes(v);
89
+ if (attrs.length)
90
+ out[id] = attrs;
91
+ };
92
+ if (Array.isArray(parsed)) {
93
+ parsed.forEach((v, i) => put(String(i), v));
94
+ }
95
+ else if (parsed && typeof parsed === 'object') {
96
+ for (const [k, v] of Object.entries(parsed)) {
97
+ if (/^\d+$/.test(k))
98
+ put(k, v); // token-id keys only — filenames need the deploy's --dir
99
+ }
100
+ }
101
+ return out;
102
+ }
103
+ //# sourceMappingURL=series-traits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"series-traits.js","sourceRoot":"","sources":["../src/series-traits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { type Address, type Hex, type PreparedTx } from '@artblocks/abx-sdk';
2
+ import type { TransactionReceipt } from 'viem';
3
+ /**
4
+ * The signing harness — the one place a write transaction turns into a signature.
5
+ *
6
+ * The CLI builds an unsigned {@link PreparedTx}; this picks the *lane* that signs it:
7
+ *
8
+ * • send (hot) — sign with the env key and broadcast. Autonomous agents, testnet, low stakes.
9
+ * • sign (wallet) — serve a one-shot, operation-aware localhost page; a human approves in their
10
+ * own wallet (the key never touches this process). Real value, mainnet.
11
+ * • unsigned (cold)— print the tx data to sign elsewhere (a multisig / offline signer).
12
+ *
13
+ * The agent picks the lane; the CLI owns the mechanics. Signing is the only step
14
+ * that ever differs — everything up to the prepared tx, and the re-index after,
15
+ * is identical across lanes.
16
+ */
17
+ export type Lane = 'send' | 'sign' | 'unsigned';
18
+ /** A prepared tx, or — when the signer's address is needed to build it (deploy) — a builder of one. */
19
+ export type TxProvider = PreparedTx | ((signer: Address) => PreparedTx | Promise<PreparedTx>);
20
+ export interface SignOptions {
21
+ lane: Lane;
22
+ chainKey: string;
23
+ /** The address that must sign (onlyOwner / token holder). Shown to the human; guards the hot lane. */
24
+ expectedSigner?: Address;
25
+ /** Allow the hot lane on a non-testnet chain (a deliberate mainnet spend). */
26
+ yes?: boolean;
27
+ /** Port for the wallet-lane sign page. */
28
+ port?: number;
29
+ /** Write the sign-page URL to this file the instant the server is ready — a deterministic,
30
+ * race-free way for an agent driving this in the background to capture + relay the URL. */
31
+ signUrlFile?: string;
32
+ }
33
+ export interface SignResult {
34
+ txHash: Hex;
35
+ prepared: PreparedTx;
36
+ blockNumber: bigint;
37
+ }
38
+ /**
39
+ * Sign and (for hot/wallet) broadcast a prepared tx via the chosen lane. Returns
40
+ * the broadcast tx hash, or `null` for the cold lane (nothing is sent — the
41
+ * caller hands the printed tx to an external signer).
42
+ */
43
+ export declare function signTx(provider: TxProvider, opts: SignOptions): Promise<SignResult | null>;
44
+ /**
45
+ * The one sign-page implementation behind the whole wallet lane — single owner ops AND
46
+ * multi-tx staged deploys both run through it ({@link signWallet} just opens one with
47
+ * `total: 1`). It keeps a single page open: the human connects once, then approves each tx as
48
+ * the CLI produces it (`Transaction 1 of N`, …). Each tx's receipt can feed the next (a
49
+ * chunk's pointers determine the manifest), so the CLI drives the sequence and the page just
50
+ * follows. Every signature is gated on the right NETWORK and the right SIGNING WALLET, checked
51
+ * live in the page (and re-checked at sign time) and enforced server-side on `/connect`, so a
52
+ * wrong-chain or wrong-wallet tx can never be queued. The key never touches this process.
53
+ */
54
+ export interface SignedReceipt {
55
+ txHash: Hex;
56
+ receipt: TransactionReceipt;
57
+ }
58
+ export interface WalletSession {
59
+ /** Resolves once the human connects a wallet in the browser; yields the connected address. */
60
+ connect(): Promise<Address>;
61
+ /** Show + sign the next tx through the open page; resolves with its hash + mined receipt. */
62
+ send(tx: PreparedTx): Promise<SignedReceipt>;
63
+ /** Show + `personal_sign` a message through the open page; resolves with the `0x` signature. Used
64
+ * to sign Arweave/Turbo upload data-items with the connected wallet (its credits then pay). */
65
+ signMessage(message: Uint8Array, summary?: string): Promise<Hex>;
66
+ /** No more items — the page shows "all done", then the server closes. */
67
+ close(): void;
68
+ }
69
+ export interface WalletSessionOptions {
70
+ chainKey: string;
71
+ /** The address that should sign (owner / deployer). Shown to the human; mismatch warns. */
72
+ expectedSigner?: Address;
73
+ port?: number;
74
+ /** Total tx count if known up front — rendered as "Transaction N of total". */
75
+ total?: number;
76
+ /** Write the sign-page URL to this file the instant the server is ready (agent capture). */
77
+ signUrlFile?: string;
78
+ }
79
+ export declare function openWalletSession(opts: WalletSessionOptions): Promise<WalletSession>;
80
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,GAAG,EACR,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,MAAM,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAEhD,uGAAuG;AACvG,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;AAE9F,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,sGAAsG;IACtG,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;gGAC4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAiBD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,UAAU,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAqED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAShG;AAyFD;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,GAAG,CAAC;IACZ,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,6FAA6F;IAC7F,IAAI,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC7C;oGACgG;IAChG,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACjE,yEAAyE;IACzE,KAAK,IAAI,IAAI,CAAC;CACf;AASD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,2FAA2F;IAC3F,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CA8I1F"}