@artblocks/abx-sdk 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (144) hide show
  1. package/CHANGELOG.md +2203 -0
  2. package/README.md +131 -0
  3. package/dist/abi/generated.d.ts +8502 -129
  4. package/dist/abi/generated.d.ts.map +1 -1
  5. package/dist/abi/generated.js +40 -22
  6. package/dist/abi/generated.js.map +1 -1
  7. package/dist/abi/index.d.ts +2645 -168
  8. package/dist/abi/index.d.ts.map +1 -1
  9. package/dist/abi/index.js +34 -7
  10. package/dist/abi/index.js.map +1 -1
  11. package/dist/anchors.d.ts +319 -0
  12. package/dist/anchors.d.ts.map +1 -0
  13. package/dist/anchors.js +703 -0
  14. package/dist/anchors.js.map +1 -0
  15. package/dist/chains.d.ts +15 -9
  16. package/dist/chains.d.ts.map +1 -1
  17. package/dist/chains.js +19 -15
  18. package/dist/chains.js.map +1 -1
  19. package/dist/chunks.d.ts +53 -23
  20. package/dist/chunks.d.ts.map +1 -1
  21. package/dist/chunks.js +68 -6
  22. package/dist/chunks.js.map +1 -1
  23. package/dist/clients.d.ts +23 -11
  24. package/dist/clients.d.ts.map +1 -1
  25. package/dist/clients.js +17 -18
  26. package/dist/clients.js.map +1 -1
  27. package/dist/create2.d.ts +85 -1
  28. package/dist/create2.d.ts.map +1 -1
  29. package/dist/create2.js +159 -2
  30. package/dist/create2.js.map +1 -1
  31. package/dist/creator-token.d.ts +132 -0
  32. package/dist/creator-token.d.ts.map +1 -0
  33. package/dist/creator-token.js +183 -0
  34. package/dist/creator-token.js.map +1 -0
  35. package/dist/deploy.d.ts +234 -14
  36. package/dist/deploy.d.ts.map +1 -1
  37. package/dist/deploy.js +289 -111
  38. package/dist/deploy.js.map +1 -1
  39. package/dist/deployments.d.ts +63 -0
  40. package/dist/deployments.d.ts.map +1 -1
  41. package/dist/deployments.js +202 -28
  42. package/dist/deployments.js.map +1 -1
  43. package/dist/deps.d.ts +122 -5
  44. package/dist/deps.d.ts.map +1 -1
  45. package/dist/deps.js +248 -6
  46. package/dist/deps.js.map +1 -1
  47. package/dist/env.d.ts.map +1 -1
  48. package/dist/env.js +8 -0
  49. package/dist/env.js.map +1 -1
  50. package/dist/errors.d.ts +94 -0
  51. package/dist/errors.d.ts.map +1 -0
  52. package/dist/errors.js +126 -0
  53. package/dist/errors.js.map +1 -0
  54. package/dist/execute.d.ts +115 -0
  55. package/dist/execute.d.ts.map +1 -0
  56. package/dist/execute.js +142 -0
  57. package/dist/execute.js.map +1 -0
  58. package/dist/gateways.d.ts +79 -0
  59. package/dist/gateways.d.ts.map +1 -0
  60. package/dist/gateways.js +156 -0
  61. package/dist/gateways.js.map +1 -0
  62. package/dist/generator-document.d.ts +58 -0
  63. package/dist/generator-document.d.ts.map +1 -0
  64. package/dist/generator-document.js +124 -0
  65. package/dist/generator-document.js.map +1 -0
  66. package/dist/generator.d.ts +43 -1
  67. package/dist/generator.d.ts.map +1 -1
  68. package/dist/generator.js +29 -0
  69. package/dist/generator.js.map +1 -1
  70. package/dist/index.d.ts +18 -3
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +18 -3
  73. package/dist/index.js.map +1 -1
  74. package/dist/inspect.d.ts +48 -0
  75. package/dist/inspect.d.ts.map +1 -0
  76. package/dist/inspect.js +295 -0
  77. package/dist/inspect.js.map +1 -0
  78. package/dist/migrate.d.ts +41 -0
  79. package/dist/migrate.d.ts.map +1 -0
  80. package/dist/migrate.js +142 -0
  81. package/dist/migrate.js.map +1 -0
  82. package/dist/mime.d.ts +11 -0
  83. package/dist/mime.d.ts.map +1 -0
  84. package/dist/mime.js +40 -0
  85. package/dist/mime.js.map +1 -0
  86. package/dist/node.d.ts +10 -0
  87. package/dist/node.d.ts.map +1 -0
  88. package/dist/node.js +24 -0
  89. package/dist/node.js.map +1 -0
  90. package/dist/onchain-uri.d.ts +110 -0
  91. package/dist/onchain-uri.d.ts.map +1 -0
  92. package/dist/onchain-uri.js +277 -0
  93. package/dist/onchain-uri.js.map +1 -0
  94. package/dist/ops.d.ts +507 -14
  95. package/dist/ops.d.ts.map +1 -1
  96. package/dist/ops.js +848 -32
  97. package/dist/ops.js.map +1 -1
  98. package/dist/policy.d.ts +58 -0
  99. package/dist/policy.d.ts.map +1 -0
  100. package/dist/policy.js +36 -0
  101. package/dist/policy.js.map +1 -0
  102. package/dist/probe.d.ts +29 -0
  103. package/dist/probe.d.ts.map +1 -1
  104. package/dist/probe.js +104 -9
  105. package/dist/probe.js.map +1 -1
  106. package/dist/reconstruct.d.ts +94 -2
  107. package/dist/reconstruct.d.ts.map +1 -1
  108. package/dist/reconstruct.js +432 -97
  109. package/dist/reconstruct.js.map +1 -1
  110. package/dist/resume.d.ts +96 -0
  111. package/dist/resume.d.ts.map +1 -0
  112. package/dist/resume.js +95 -0
  113. package/dist/resume.js.map +1 -0
  114. package/dist/script-chunks.d.ts +24 -0
  115. package/dist/script-chunks.d.ts.map +1 -0
  116. package/dist/script-chunks.js +63 -0
  117. package/dist/script-chunks.js.map +1 -0
  118. package/dist/service.d.ts +206 -9
  119. package/dist/service.d.ts.map +1 -1
  120. package/dist/service.js +228 -18
  121. package/dist/service.js.map +1 -1
  122. package/dist/spine.d.ts +47 -4
  123. package/dist/spine.d.ts.map +1 -1
  124. package/dist/spine.js +0 -0
  125. package/dist/spine.js.map +1 -1
  126. package/dist/staging.d.ts +124 -0
  127. package/dist/staging.d.ts.map +1 -0
  128. package/dist/staging.js +134 -0
  129. package/dist/staging.js.map +1 -0
  130. package/dist/tokendata.d.ts +62 -2
  131. package/dist/tokendata.d.ts.map +1 -1
  132. package/dist/tokendata.js +79 -17
  133. package/dist/tokendata.js.map +1 -1
  134. package/dist/tokens.d.ts +120 -0
  135. package/dist/tokens.d.ts.map +1 -0
  136. package/dist/tokens.js +317 -0
  137. package/dist/tokens.js.map +1 -0
  138. package/dist/types.d.ts +108 -4
  139. package/dist/types.d.ts.map +1 -1
  140. package/dist/util.d.ts +74 -0
  141. package/dist/util.d.ts.map +1 -0
  142. package/dist/util.js +106 -0
  143. package/dist/util.js.map +1 -0
  144. package/package.json +11 -2
package/dist/ops.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { type Address, type Hex } from 'viem';
2
- import type { OneOfOneInitParams, SeriesCodeInitParams, SeriesInitParams } from './deploy.js';
1
+ import { type Address, type Hex, type PublicClient } from 'viem';
2
+ import type { EditionCodeInitParams, EditionImageInitParams, OneOfOneEditionInitParams, OneOfOneInitParams, SeriesCodeInitParams, SeriesInitParams } from './deploy.js';
3
3
  /**
4
4
  * An unsigned, ready-to-sign transaction — the SDK's neutral output for every
5
5
  * write. It carries only the data needed to sign (`to`/`data`/`value`/`chainId`)
@@ -17,6 +17,20 @@ export interface PreparedTx {
17
17
  chainId: number;
18
18
  summary: string;
19
19
  fields: Record<string, string>;
20
+ /**
21
+ * A **provable** lower bound on this tx's gas — a value the real cost cannot possibly be below.
22
+ *
23
+ * This is a DETECTOR, not a substitute gas limit. It exists because `eth_estimateGas` can return a
24
+ * confidently wrong answer (an estimate taken against a target whose code isn't visible yet is
25
+ * just the calldata cost), and the only safe response to a wrong estimate is to notice and refuse
26
+ * — not to invent a replacement number. A sender treats `estimate < gasFloor` as "this estimate is
27
+ * impossible", retries, and errors out; it does NOT send `gasFloor` instead, because a bound that
28
+ * covers the provable part says nothing about the rest of the payload.
29
+ *
30
+ * Set it only from costs that are physics rather than guesswork. The one such cost here is EVM
31
+ * code deposit: storing N bytes on-chain costs exactly 200·N gas, before any other work.
32
+ */
33
+ gasFloor?: Hex;
20
34
  }
21
35
  /**
22
36
  * Batch several ops into ONE atomic transaction via the target's
@@ -46,6 +60,11 @@ export declare function prepareMulticall(args: {
46
60
  * preserved — important when a later op depends on an earlier one's effect — so a run is
47
61
  * only merged while the target stays the same. This is what turns "6 owner edits" into
48
62
  * "1 transaction" for the UX, while staying honest about what genuinely needs its own tx.
63
+ *
64
+ * A CREATE2-proxy deploy (`to === CREATE2_PROXY` — the renderer/minter/seed-source singletons)
65
+ * is creation too, even though it carries a `to`: the proxy has no `multicall`, so folding two of
66
+ * them together would silently produce a transaction that reverts on the target it's actually
67
+ * sent to. Excluded from merging for the same reason `to === null` is.
49
68
  */
50
69
  export declare function batchOps(ops: PreparedTx[]): PreparedTx[];
51
70
  /** Transfer a token to a new holder (a sale/gift settlement). Signer must be `from`. */
@@ -66,6 +85,37 @@ export declare function prepareMint(args: {
66
85
  to: Address;
67
86
  chainId: number;
68
87
  }): PreparedTx;
88
+ /**
89
+ * The token ids a mint actually created, decoded from its receipt's mint logs — `Transfer` from
90
+ * `0x0` on a 721 token, or `TransferSingle`/`TransferBatch` from `0x0` on an edition (each id
91
+ * reported once, regardless of how many copies it minted — an edition amount has nowhere to ride
92
+ * in a `string[]`, so it's a job for the sibling {@link mintedEditionAmounts}). Both event
93
+ * families are probed unconditionally (harmless — a contract only ever emits the one that
94
+ * matches its own standard, so exactly one probe ever finds anything) rather than branching on
95
+ * contract type, so this stays a single call for either kind.
96
+ *
97
+ * Authoritative by construction: the ids come from the transaction that minted them, so a
98
+ * `--count N` batch reports all N and a concurrent mint elsewhere cannot skew the answer. Returns
99
+ * `[]` rather than throwing if the receipt can't be read — a mint that landed on-chain must not be
100
+ * reported as failed because a follow-up read hiccuped.
101
+ */
102
+ export declare function mintedTokenIds(client: PublicClient, contract: Address, txHash: Hex): Promise<string[]>;
103
+ /** One id's minted copy count from a single edition mint transaction — the amount half {@link
104
+ * mintedTokenIds} can't carry (its `string[]` shape is shared with the 721 side, where a token
105
+ * is always exactly 1 unit). */
106
+ export interface MintedEditionAmount {
107
+ tokenId: string;
108
+ amount: string;
109
+ }
110
+ /**
111
+ * The `(id, amount)` pairs an edition mint actually created, decoded from its receipt's
112
+ * `TransferSingle`/`TransferBatch` (`from == 0x0`) logs — the amount-carrying sibling of {@link
113
+ * mintedTokenIds}, for callers that need "how many copies of #7 did this tx mint" rather than
114
+ * just "which ids." Amounts are summed per id (a batch could in principle mint the same id
115
+ * twice in one call), then sorted by id. Returns `[]` on a 721 receipt (no matching events) or
116
+ * any read failure, same fail-open contract as {@link mintedTokenIds}.
117
+ */
118
+ export declare function mintedEditionAmounts(client: PublicClient, contract: Address, txHash: Hex): Promise<MintedEditionAmount[]>;
69
119
  /** Re-point a token's resolver BASE (move the resolver). The per-token pointer is derived
70
120
  * on-chain as `{base}/{chainId}/{address}/{tokenId}`. Affects every token without an
71
121
  * override. Signer must be the owner. */
@@ -124,11 +174,40 @@ export declare function prepareLockContractURI(args: {
124
174
  chainId: number;
125
175
  }): PreparedTx;
126
176
  /** Set the contract-wide default royalty. Signer must be the owner. */
177
+ /**
178
+ * The on-chain royalty ceiling, mirrored from `RoyaltyExtension._maxRoyaltyBps()` (1000 bps = 10%).
179
+ *
180
+ * Client-side validation used to allow the full 0–10000 ERC-2981 range, and the CLI's own error text
181
+ * offered `10000 = 100%` as an example — so a creator asking for an ordinary 15% got a fully built,
182
+ * fully signed transaction that reverted `RoyaltyTooHigh()` on chain. On the wallet lane they approved
183
+ * it in their own wallet first and paid the gas to find out. Validate against the real cap so the
184
+ * refusal is instant, local and free.
185
+ *
186
+ * The royalty ceiling is now **per-collection**: owner-set at deploy (0–10000 bps) and reduce-only
187
+ * after. So this constant is the ABSOLUTE protocol maximum (100%); a collection's own, possibly
188
+ * lower, `maxRoyaltyBps()` is the binding cap and is enforced on chain. To refuse an over-cap
189
+ * `set-royalty` instantly rather than after a revert, pass `maxBps` (the collection's live cap, read
190
+ * from `maxRoyaltyBps()`); it defaults to the absolute max when omitted.
191
+ */
192
+ export declare const MAX_ROYALTY_BPS = 10000;
127
193
  export declare function prepareSetRoyalty(args: {
128
194
  contract: Address;
129
195
  receiver: Address;
130
196
  bps: number;
131
197
  chainId: number;
198
+ maxBps?: number;
199
+ }): PreparedTx;
200
+ /**
201
+ * Lower a collection's royalty ceiling (`RoyaltyExtension.reduceMaxRoyaltyBps`). Owner-only and
202
+ * **reduce-only**: the chain reverts `RoyaltyCapNotReduced()` if `newMaxBps` is not strictly below
203
+ * the current cap, and `RoyaltyCapBelowRoyalty()` if it would sit under the live royalty rate. This
204
+ * builder is domain-only (0–100%); the CLI reads the live cap + rate to refuse both cases before
205
+ * signing so the failure is local and free rather than a paid revert. Emits `MaxRoyaltyBpsUpdated`.
206
+ */
207
+ export declare function prepareReduceMaxRoyaltyBps(args: {
208
+ contract: Address;
209
+ newMaxBps: number;
210
+ chainId: number;
132
211
  }): PreparedTx;
133
212
  /**
134
213
  * Set/replace an on-chain metadata field for a token. `field` is what (e.g. "image",
@@ -185,11 +264,19 @@ export declare function prepareDeployOneOfOne(args: {
185
264
  chainId: number;
186
265
  clone: Address;
187
266
  }): PreparedTx;
188
- /** The unsigned form of the factory (trust-anchor) deploy — a contract creation. */
267
+ /** The unsigned form of the factory (trust-anchor) deploy — CREATE2 via the keyless proxy at the
268
+ * canonical salt, matching the forge `Deploy` script and `predictFactory()` (create2.ts). A trust
269
+ * anchor is the one address platforms allowlist, so it has to be the same on every chain and
270
+ * computable before the first tx; a plain creation (`to: null`) would make it depend on the
271
+ * deployer's nonce and could never match the recorded manifest. */
189
272
  export declare function prepareDeployFactory(args: {
190
273
  chainId: number;
191
274
  }): PreparedTx;
192
- /** The unsigned form of the canonical metadata-renderer deploy — a contract creation. */
275
+ /** The unsigned form of the canonical metadata-renderer deploy — CREATE2 via the keyless proxy +
276
+ * canonical salt, so it lands at the SAME (predictable) address on every chain, matching the forge
277
+ * `DeployRenderer` script and `predictRenderer()` (create2.ts). NOT a plain contract creation
278
+ * (`to: null`) — that would land at a nonce-dependent address, defeating the whole point of a
279
+ * canonical, cross-chain-identical singleton. */
193
280
  export declare function prepareDeployRenderer(args: {
194
281
  chainId: number;
195
282
  }): PreparedTx;
@@ -245,10 +332,111 @@ export declare function prepareDeploySeries(args: {
245
332
  chainId: number;
246
333
  clone: Address;
247
334
  }): PreparedTx;
248
- /** The unsigned form of the Series factory (trust-anchor) deploy — a contract creation. */
335
+ /** The unsigned form of the Series factory (trust-anchor) deploy — CREATE2 via the keyless proxy at
336
+ * the canonical salt, matching the forge `DeploySeries` script and `predictSeriesFactory()`. Same
337
+ * reasoning as `prepareDeployFactory` above. */
249
338
  export declare function prepareDeploySeriesFactory(args: {
250
339
  chainId: number;
251
340
  }): PreparedTx;
341
+ /**
342
+ * Mint `amount` copies of `id` to `to` (`IAbxEditionMint.mint`). Owner always; the authorized
343
+ * minter only while unpaused — same auth shape as {@link prepareMint}/{@link prepareSeriesMint}.
344
+ * The edition twin of both: there is no separate "next in order" primitive here, since an
345
+ * edition mint always names its id.
346
+ */
347
+ export declare function prepareEditionMint(args: {
348
+ contract: Address;
349
+ to: Address;
350
+ tokenId: bigint | number;
351
+ amount: bigint | number;
352
+ chainId: number;
353
+ }): PreparedTx;
354
+ /** Transfer `amount` copies of `id` to a new holder (`safeTransferFrom(from,to,id,amount,"")` on
355
+ * the ERC-1155 ABI) — the edition twin of {@link prepareTransfer}. Signer must be `from` (or an
356
+ * operator it approved via the standard `setApprovalForAll`). */
357
+ export declare function prepareEditionTransfer(args: {
358
+ contract: Address;
359
+ from: Address;
360
+ to: Address;
361
+ tokenId: bigint | number;
362
+ amount: bigint | number;
363
+ chainId: number;
364
+ }): PreparedTx;
365
+ /**
366
+ * Owner overrides `id`'s supply cap (Edition Supply extension) — the edition twin of {@link
367
+ * prepareSetMaxInvocations}, one id finer. Monotonically non-increasing once used for this id,
368
+ * never below its live `totalSupply(id)` (see `IAbxEditionSupply`'s "0 = open until overridden"
369
+ * semantics — an explicit `0` permanently closes the id, it does not mean "reopen to uncapped").
370
+ * Signer must be the owner.
371
+ */
372
+ export declare function prepareSetMaxSupply(args: {
373
+ contract: Address;
374
+ tokenId: bigint | number;
375
+ cap: bigint | number;
376
+ chainId: number;
377
+ }): PreparedTx;
378
+ /**
379
+ * Permissionless, caller-chunked re-emission of the native `URI` event for the given ids —
380
+ * called after a contract-wide re-point (`setTokenURIBase`/`setTokenURIRenderer`, which emit
381
+ * only their own Register-2 config event; see `Uri1155`'s class-level dev note on why there's no
382
+ * automatic per-id loop for that case) to make marketplaces/indexers that only honor the native
383
+ * event re-index. Anyone may call it — it only re-emits already-public, current truth, so there
384
+ * is no state to protect; the caller picks the batch size.
385
+ */
386
+ export declare function preparePingURI(args: {
387
+ contract: Address;
388
+ tokenIds: Array<bigint | number>;
389
+ chainId: number;
390
+ }): PreparedTx;
391
+ /** The unsigned form of a 1/1-edition genesis deploy — `deployDeterministic(params, salt)` on
392
+ * the {@link oneOfOneEditionFactoryAbi} factory. The edition twin of {@link
393
+ * prepareDeployOneOfOne}. */
394
+ export declare function prepareDeployOneOfOneEdition(args: {
395
+ factory: Address;
396
+ params: OneOfOneEditionInitParams;
397
+ salt: Hex;
398
+ chainId: number;
399
+ clone: Address;
400
+ }): PreparedTx;
401
+ /** The unsigned form of the 1/1-edition factory (trust-anchor) deploy — CREATE2 via the keyless
402
+ * proxy + canonical salt, so it lands at the SAME (predictable) address on every chain, matching
403
+ * `predictOneOfOneEditionFactory()` (create2.ts). See {@link prepareDeployRenderer} for why this
404
+ * is `to: CREATE2_PROXY`, not a plain creation.
405
+ *
406
+ * The initcode goes out LINKED against `AbxEditionLib` (`linkOneOfOneEditionFactory()`): the
407
+ * embedded `OneOfOneEdition` implementation delegates its uri / creator-token / edition-supply
408
+ * bodies into that library, so the shipped bytecode carries a solc `__$…$__` placeholder. That
409
+ * library must already be on-chain at `predictEditionLib()` for the deployed factory to work —
410
+ * {@link deployOneOfOneEditionFactory} (deploy.ts) is the path that guarantees it. */
411
+ export declare function prepareDeployOneOfOneEditionFactory(args: {
412
+ chainId: number;
413
+ }): PreparedTx;
414
+ /** The unsigned form of an edition-image genesis deploy — `deployDeterministic(params, salt)` on
415
+ * the {@link editionImageFactoryAbi} factory. The edition twin of {@link prepareDeploySeries}. */
416
+ export declare function prepareDeployEditionImage(args: {
417
+ factory: Address;
418
+ params: EditionImageInitParams;
419
+ salt: Hex;
420
+ chainId: number;
421
+ clone: Address;
422
+ }): PreparedTx;
423
+ /** The unsigned form of the edition-image factory (trust-anchor) deploy — CREATE2 via the
424
+ * keyless proxy + canonical salt, matching `predictEditionFactory()` (create2.ts). See {@link
425
+ * prepareDeployRenderer} for why this is `to: CREATE2_PROXY`, not a plain creation, and {@link
426
+ * prepareDeployOneOfOneEditionFactory} for why the initcode is linked against `AbxEditionLib`
427
+ * (`EditionImage` delegates the same three mixins' bodies into it). */
428
+ export declare function prepareDeployEditionFactory(args: {
429
+ chainId: number;
430
+ }): PreparedTx;
431
+ /** Deterministic deploy of an {EditionCode} clone — the code-project edition factory op. The
432
+ * edition twin of {@link prepareDeploySeriesCode}. */
433
+ export declare function prepareDeployEditionCode(args: {
434
+ factory: Address;
435
+ params: EditionCodeInitParams;
436
+ salt: Hex;
437
+ chainId: number;
438
+ clone: Address;
439
+ }): PreparedTx;
252
440
  /**
253
441
  * Set/update a project's fixed-price sale on the shared minter. Signer must be the ABX
254
442
  * token's owner. `paymentToken == 0x0` prices the sale in ETH; otherwise it's that ERC-20.
@@ -264,23 +452,219 @@ export declare function prepareConfigureSale(args: {
264
452
  allocation: bigint | number;
265
453
  chainId: number;
266
454
  }): PreparedTx;
455
+ /** The sale terms a buyer is agreeing to — the input to the minter's on-chain terms guard.
456
+ * ("Terms guard", not "slippage guard": on the ETH lane it tolerates no movement at all — see
457
+ * {@link preparePurchase}.)
458
+ * A {@link SaleConfig} (or {@link SaleConfig1155}) read from the chain drops straight in, which is
459
+ * the point: the terms that go into the transaction are the terms the caller just read. */
460
+ export type PurchaseTerms = Pick<SaleConfig, 'paymentToken' | 'price'>;
267
461
  /**
268
462
  * Buy one token from the shared minter. `to` omitted → minted to the signer (`purchase`);
269
- * `to` set → minted to that address (`purchaseTo`). `value` is the ETH to attach (equal to
270
- * the sale price for an ETH sale; `0` for an ERC-20 sale, where the buyer must have approved
271
- * the minter to pull `price` beforehand). Public — no owner rights needed.
463
+ * `to` set → minted to that address (`purchaseTo`). Public — no owner rights needed.
464
+ *
465
+ * `sale` is the live terms ({@link readSaleConfig}), and they are **mandatory**: the minter takes
466
+ * `(expectedPaymentToken, maxPrice)` and reverts `SaleTermsChanged` if the sale has moved, which is
467
+ * what stops a project owner from front-running a pending purchase and spending the buyer's whole
468
+ * ERC-20 allowance (`configure` has no timelock). The ETH to attach is derived from those terms —
469
+ * `price` for an ETH sale, `0` for an ERC-20 one (where the buyer must have approved the minter to
470
+ * pull `price` beforehand) — so a caller can't desync the payment from the guard.
471
+ *
472
+ * `maxPrice` defaults to `sale.price` (accept exactly what was read). Pass it to state a wider
473
+ * ceiling. It bounds the guard only; the ETH attached still comes from `sale.price`, since the minter
474
+ * wants exact payment. There is deliberately no "no maximum" sentinel.
475
+ *
476
+ * **A wide `maxPrice` is how a caller opts out of the protection.** The minter refuses a sentinel
477
+ * precisely so that a bound has to be stated, but nothing stops a caller from stating an enormous
478
+ * one — and on the ERC-20 lane that hands back exactly the vector the guard closes: the minter pulls
479
+ * the live price from the buyer's standing allowance, so a ceiling of `2^256-1` lets a re-priced sale
480
+ * take the whole allowance. Omitting the argument is the safe path and is what every caller in this
481
+ * repo does. If you widen it, widen it by an amount you would be content to lose, and never derive it
482
+ * from a price you read in the same breath as sending — that is the same thing as no bound at all.
483
+ *
484
+ * **On the ETH lane, `maxPrice` is a terms ASSERTION, not slippage tolerance — do not sell it as
485
+ * one.** The minter requires `msg.value == price` (an equality) and V1 has no refund path, so an
486
+ * in-flight ETH purchase reverts `WrongPayment` if the price moves in *either* direction, however
487
+ * wide the ceiling. Raising `maxPrice` on an ETH sale buys the buyer nothing at all. Real tolerance
488
+ * exists only on the **ERC-20** lane, where the minter pulls the live `price` from the buyer's
489
+ * allowance and any price at or below the ceiling settles. Re-pricing a live ETH sale therefore fails
490
+ * every buy already in flight, by design — pause first for a clean cutover.
272
491
  */
273
492
  export declare function preparePurchase(args: {
274
493
  minter: Address;
275
494
  token: Address;
495
+ sale: PurchaseTerms;
276
496
  to?: Address;
277
- value?: bigint | number;
497
+ maxPrice?: bigint | number;
498
+ chainId: number;
499
+ }): PreparedTx;
500
+ /** A project's fixed-price sale state on the shared minter (`sales(token)`): whether a sale is
501
+ * configured, the payment token (`zeroAddress` = ETH), the per-unit price, the minter's own
502
+ * sell-through budget (`allocation`, distinct from the token's `maxInvocations` cap), and units
503
+ * sold so far. The read half of {@link prepareConfigureSale}/{@link preparePurchase} — every
504
+ * caller that needs to know a sale's live terms (show it, gate a purchase) reads through here. */
505
+ export interface SaleConfig {
506
+ configured: boolean;
507
+ paymentToken: Address;
508
+ price: bigint;
509
+ allocation: bigint;
510
+ sold: bigint;
511
+ }
512
+ export declare function readSaleConfig(client: PublicClient, minter: Address, token: Address): Promise<SaleConfig>;
513
+ /** The unsigned form of the shared fixed-price minter deploy — CREATE2 via the keyless proxy +
514
+ * canonical salt (same address on every chain), matching `predictFixedPriceMinter()`. See
515
+ * {@link prepareDeployRenderer} for why this is `to: CREATE2_PROXY`, not a plain creation. */
516
+ export declare function prepareDeployFixedPriceMinter(args: {
278
517
  chainId: number;
279
518
  }): PreparedTx;
280
- /** The unsigned form of the shared fixed-price minter deploy — a contract creation. */
281
- export declare function prepareDeployFixedPriceMinter(args: {
519
+ /**
520
+ * Set/update a project's fixed-price sale for one id on the shared edition minter. The id-keyed
521
+ * twin of {@link prepareConfigureSale}. Signer must be the ABX token's owner.
522
+ */
523
+ export declare function prepareConfigureSale1155(args: {
524
+ minter: Address;
525
+ token: Address;
526
+ tokenId: bigint | number;
527
+ paymentToken?: Address;
528
+ price: bigint | number;
529
+ allocation: bigint | number;
530
+ chainId: number;
531
+ }): PreparedTx;
532
+ /**
533
+ * Buy `quantity` copies of `id` from the shared edition minter. The id/quantity-keyed twin of
534
+ * {@link preparePurchase}. `to` omitted → minted to the signer (`purchase`); `to` set → minted to
535
+ * that address (`purchaseTo`). Public — no owner rights needed.
536
+ *
537
+ * `sale` is the live terms ({@link readSaleConfig1155}) and is mandatory, same terms guard as the 721
538
+ * lane — except the minter bounds the **total** (`price × quantity`), which is what actually leaves
539
+ * the buyer's balance. `price × quantity` is computed here (once), for both the attached ETH and the
540
+ * bound; `maxTotalPrice` defaults to it, and passing it states a wider ceiling.
541
+ *
542
+ * The ETH-lane caveat on {@link preparePurchase} applies here identically: `msg.value` must equal the
543
+ * total exactly, so `maxTotalPrice` is an assertion about the terms, **not** slippage tolerance. Only
544
+ * an ERC-20 edition sale gets real tolerance.
545
+ */
546
+ export declare function preparePurchase1155(args: {
547
+ minter: Address;
548
+ token: Address;
549
+ tokenId: bigint | number;
550
+ quantity: bigint | number;
551
+ sale: PurchaseTerms;
552
+ to?: Address;
553
+ maxTotalPrice?: bigint | number;
554
+ chainId: number;
555
+ }): PreparedTx;
556
+ /** A project's fixed-price sale state for one id on the shared edition minter (`sales(token,
557
+ * id)`) — the id-keyed twin of {@link SaleConfig}. */
558
+ export interface SaleConfig1155 {
559
+ configured: boolean;
560
+ paymentToken: Address;
561
+ price: bigint;
562
+ allocation: bigint;
563
+ sold: bigint;
564
+ }
565
+ /** The id-keyed twin of {@link readSaleConfig}. */
566
+ export declare function readSaleConfig1155(client: PublicClient, minter: Address, token: Address, tokenId: bigint | number): Promise<SaleConfig1155>;
567
+ /** The unsigned form of the shared edition minter deploy — CREATE2 via the keyless proxy +
568
+ * canonical salt (same address on every chain), matching `predictFixedPriceMinter1155()`. See
569
+ * {@link prepareDeployRenderer} for why this is `to: CREATE2_PROXY`, not a plain creation. */
570
+ export declare function prepareDeployFixedPriceMinter1155(args: {
282
571
  chainId: number;
283
572
  }): PreparedTx;
573
+ /** The unsigned form of the canonical seed source deploy — CREATE2 via the keyless proxy +
574
+ * canonical salt (same address on every chain), matching `predictSeedSource()`. See
575
+ * {@link prepareDeployRenderer} for why this is `to: CREATE2_PROXY`, not a plain creation. */
576
+ export declare function prepareDeploySeedSource(args: {
577
+ chainId: number;
578
+ }): PreparedTx;
579
+ /**
580
+ * Set (or clear, with `0x0`) the seed source a code project draws mint seeds from. Signer must be
581
+ * the owner. **Future mints only** — a seed is settled once assigned, so re-pointing never rewrites
582
+ * a token that already has one.
583
+ *
584
+ * Pass an address that {@link probeSeedSource} says is usable. The chain does NOT validate the
585
+ * source (`SeedSourceExtension.setSeedSource` stores whatever it's handed), and the failure mode of
586
+ * a bad one is the worst kind: `seedSource()` reads back exactly what you set, the `SeedSourceSet`
587
+ * event fires, everything looks configured — and then every mint reverts in the ABI decode of the
588
+ * source's (empty or short) return. Callers should probe first and refuse before gas.
589
+ */
590
+ export declare function prepareSetSeedSource(args: {
591
+ contract: Address;
592
+ seedSource: Address;
593
+ chainId: number;
594
+ }): PreparedTx;
595
+ /**
596
+ * The seed source a token currently draws from — `zeroAddress` for "no mint-time seed", and
597
+ * `undefined` when the getter isn't there at all (a 1/1 or an image Series never composed the
598
+ * extension). Those two are NOT the same fact and must not be collapsed: one is a code project
599
+ * that opted out, the other is a token that has no such knob to set.
600
+ */
601
+ export declare function readSeedSource(client: PublicClient, contract: Address): Promise<Address | undefined>;
602
+ /**
603
+ * Why a candidate seed source is unusable — or `ok`. Structured rather than a sentence: the SDK
604
+ * doesn't know a UX's flag names (see `AnchorUnavailableError`'s note), so the caller composes the
605
+ * guidance and this only says which shape it hit.
606
+ *
607
+ * - `no-code` — nothing deployed there. A Solidity call to a codeless address SUCCEEDS with
608
+ * zero returndata, so the token's `abi.decode` to `bytes32` is what reverts.
609
+ * - `empty-return` — has code, answered, returned nothing. The permissive-fallback shape: a
610
+ * **Safe** (`FallbackManager.fallback()` returns empty for an unset handler),
611
+ * an uninitialised proxy, an EIP-7702-delegated EOA. Same mint revert.
612
+ * - `short-return` — answered with fewer than 32 bytes; not a `bytes32` no matter what it is.
613
+ * - `reverted` — has code and refused the call. Either the wrong address entirely (a token,
614
+ * a renderer — no such selector, no fallback) or a real source that is gating
615
+ * callers / not yet armed. Both are refusals: `seed()` is called
616
+ * **synchronously inside the mint** and its revert bubbles, so a source that
617
+ * cannot answer now cannot answer at mint either.
618
+ * - `unreachable` — the RPC didn't answer. Says nothing about the address; retry, don't refuse
619
+ * on the merits (a preview may choose to defer the check and say so).
620
+ */
621
+ export type SeedSourceVerdict = 'ok' | 'no-code' | 'empty-return' | 'short-return' | 'reverted' | 'unreachable';
622
+ /** The result of {@link probeSeedSource} — the verdict plus what was observed, for a message. */
623
+ export interface SeedSourceProbe {
624
+ verdict: SeedSourceVerdict;
625
+ /** The address probed. */
626
+ address: Address;
627
+ /** Bytes of returndata, when the call answered at all (`ok`/`empty-return`/`short-return`). */
628
+ returnedBytes?: number;
629
+ /** First line of the revert/transport error, for `reverted` / `unreachable`. */
630
+ error?: string;
631
+ }
632
+ /**
633
+ * Ask a candidate seed source the exact question the token will ask it, and report whether it
634
+ * answers with 32 bytes.
635
+ *
636
+ * **`code.length > 0` is not enough**, which is the whole reason this exists. Three separate shapes
637
+ * pass a has-code check, read back correctly from `seedSource()`, emit `SeedSourceSet`, and then
638
+ * revert **every mint of the collection**: no code, a permissive fallback that returns empty (a
639
+ * Safe, an uninitialised proxy, a 7702-delegated EOA — the same footgun the transfer-validator
640
+ * probe in `CreatorToken.sol` was written for), and anything answering with fewer than 32 bytes.
641
+ * A misconfigured seed source is silent until the first buyer, so the check belongs at configure
642
+ * time, loudly.
643
+ *
644
+ * `IAbxSeedSource.seed` is **non-`view`** (sources may keep state — commit-reveal, oracle-fed), but
645
+ * an `eth_call` simulates a state-changing function perfectly well and the canonical implementation
646
+ * is itself `view`, so one `eth_call` probes both kinds without sending anything.
647
+ *
648
+ * The call is made **as the token** (`from` = `opts.as`, when given): `msg.sender` namespaces the
649
+ * canonical seed and is exactly what a caller-gating custom source checks, so probing from a
650
+ * random address would false-negative a legitimate source. Same reason the transfer-validator
651
+ * research used `cast call --from <collection>`.
652
+ *
653
+ * Never throws for an on-chain reason — every failure is a verdict.
654
+ */
655
+ export declare function probeSeedSource(client: PublicClient, source: Address, opts?: {
656
+ as?: Address;
657
+ tokenId?: bigint;
658
+ }): Promise<SeedSourceProbe>;
659
+ /**
660
+ * {@link probeSeedSource}, as a guard: throws {@link SeedSourceUnusableError} unless the verdict is
661
+ * `ok`. For an SDK caller that just wants "refuse a bad source" without composing prose; the CLI
662
+ * uses the probe directly so it can name its own flags in the refusal.
663
+ */
664
+ export declare function assertSeedSourceUsable(client: PublicClient, source: Address, opts?: {
665
+ as?: Address;
666
+ tokenId?: bigint;
667
+ }): Promise<void>;
284
668
  /** Deterministic deploy of a {SeriesCode} clone — the code-project factory op. */
285
669
  export declare function prepareDeploySeriesCode(args: {
286
670
  factory: Address;
@@ -298,6 +682,8 @@ export declare function prepareCodeSetup(args: {
298
682
  chainId: number;
299
683
  chunkCount: number;
300
684
  schemaKeys: string[];
685
+ /** Byte length of each script chunk this multicall stores. Used only to compute `gasFloor`. */
686
+ chunkBytes?: number[];
301
687
  deps?: string[];
302
688
  onchainUri?: boolean;
303
689
  }): PreparedTx;
@@ -329,10 +715,21 @@ export declare function prepareLockDependencies(args: {
329
715
  contract: Address;
330
716
  chainId: number;
331
717
  }): PreparedTx;
718
+ /** Freeze the on-chain program (script chunks) forever — `setScriptChunk`/`removeLastScriptChunk`
719
+ * revert after this. Irreversible, owner-only. This is the lock that actually freezes the WORK
720
+ * of a code project; `lock-field`/`lock-uri` only freeze the metadata, and `lock-dependencies` only
721
+ * the library set. All of them together freeze everything the CONTRACT stores — which is not the
722
+ * same as a frozen output: params have no lock and the renderer serves them, and a `Registry`
723
+ * dependency resolves from the registry at read time. */
724
+ export declare function prepareLockScript(args: {
725
+ contract: Address;
726
+ chainId: number;
727
+ }): PreparedTx;
332
728
  /** Set a CONTRACT-scope param to a literal `bytes32` (the raw owner setter — Params base).
333
729
  * Only for schema-less keys (a schema'd key closes the raw path: `SchemaGoverned`). This is
334
- * the write behind well-known contract params like `params.keys` / `display.gateway`.
335
- * Signer must be the owner. */
730
+ * the write behind well-known contract params like `display.animation`. The key joins the
731
+ * contract's on-chain key list automatically (`contractParamKeys`), so it is enumerated by
732
+ * the generator and the renderer with no separate declaration. Signer must be the owner. */
336
733
  export declare function prepareSetContractParam(args: {
337
734
  contract: Address;
338
735
  key: string;
@@ -351,7 +748,15 @@ export declare function prepareSetContractParamData(args: {
351
748
  /** Wire the three param-lifecycle hook addresses (configure/augment/transfer) in ONE owner call.
352
749
  * The contract has no per-hook setter — `setParamHooks` writes all three at once — so a caller
353
750
  * changing one hook must pass the CURRENT values for the other two (read them via `paramHooks()`),
354
- * else it silently clears them. `zeroAddress` for any role means "no hook". SeriesCode only. */
751
+ * else it silently clears them. `zeroAddress` for any role means "no hook". SeriesCode/EditionCode
752
+ * only.
753
+ *
754
+ * Note what the `transferHook` slot is: a **veto**. Its revert bubbles and fails the transfer, and
755
+ * a mint is a transfer from `0x0`, so a reverting hook stops minting for the project too. Setting
756
+ * one is therefore a standing power over a collector's ability to sell — disclose it, and offer
757
+ * {@link prepareLockParamHooks} to a project that wants to prove it will never arm one.
758
+ *
759
+ * Reverts `ParamHooksLocked()` once {@link prepareLockParamHooks} has been sent. */
355
760
  export declare function prepareSetParamHooks(args: {
356
761
  contract: Address;
357
762
  configureHook: Address;
@@ -359,6 +764,42 @@ export declare function prepareSetParamHooks(args: {
359
764
  transferHook: Address;
360
765
  chainId: number;
361
766
  }): PreparedTx;
767
+ /**
768
+ * Is the param hook set frozen (`lockParamHooks()` already sent)?
769
+ *
770
+ * One `eth_call` to `paramHooksLocked()`. This used to simulate `setParamHooks` as the owner and
771
+ * watch for a `ParamHooksLocked()` revert, on the stated grounds that no getter existed — it does
772
+ * now (`IAbxConfigurableParams`), and the simulation cost two extra reads (`paramHooks` + `owner`)
773
+ * to infer what one read states.
774
+ *
775
+ * The other honest read is the `ParamHooksFrozen` event, which is what `reconstructProject` folds
776
+ * (`ProjectState.paramHooks.locked`). Prefer the fold when you already have the logs; use this when
777
+ * you have an address and one RPC round trip, which is `abx state`'s situation.
778
+ *
779
+ * Returns `undefined` — never throws for an on-chain reason — when the answer can't be established:
780
+ * not a ConfigurableParams project, or the node refused the call. A caller must render that as
781
+ * "unknown", never as "unlocked".
782
+ */
783
+ export declare function readParamHooksLocked(client: PublicClient, contract: Address): Promise<boolean | undefined>;
784
+ /**
785
+ * Freeze the param-lifecycle hook set forever — `setParamHooks` reverts `ParamHooksLocked()` after
786
+ * this. Irreversible, owner-only. The sibling of `lock-script`/`lock-dependencies`/`lock-uri`, and
787
+ * the one aimed at a **buyer** rather than at the metadata: the `transferHook` is a veto (its revert
788
+ * fails a transfer, and a mint is a transfer from `0x0`), so while the hooks are unwritten-in-stone a
789
+ * project retains a standing power over whether a collector can ever sell. Sending this gives up
790
+ * three abilities permanently — arming a transfer veto, arming a write-time configure veto, and
791
+ * re-pointing or clearing the read-time augment hook — and it cannot be undone, re-opened, or
792
+ * time-limited. A project that never wants the power sends it before the sale; a buyer reads
793
+ * `paramHooks()` plus the `ParamHooksFrozen` event (`abx state`) to check.
794
+ *
795
+ * It does NOT freeze anything else: schemas, values, script, dependencies, and URIs all keep their
796
+ * own locks, and a hook already set keeps running exactly as before — freezing the SET is not
797
+ * disarming the hooks in it.
798
+ */
799
+ export declare function prepareLockParamHooks(args: {
800
+ contract: Address;
801
+ chainId: number;
802
+ }): PreparedTx;
362
803
  /** Set a schema-governed PostParam (literal scalar) — signer must satisfy the schema's auth. */
363
804
  export declare function prepareConfigureTokenParam(args: {
364
805
  contract: Address;
@@ -376,4 +817,56 @@ export declare function prepareConfigureTokenParamData(args: {
376
817
  data: Hex;
377
818
  chainId: number;
378
819
  }): PreparedTx;
820
+ /** Attach or replace one key's schema. Owner-only.
821
+ *
822
+ * A replacement does NOT re-validate values already stored under the key — narrow a bound, drop a
823
+ * `Select` option or change the type and existing tokens keep values that now violate their own
824
+ * schema. Callers that are editing (rather than creating) should read the current schema first and
825
+ * carry forward every field they don't mean to change; this is a full-row write, not a patch. */
826
+ export declare function prepareSetParamSchema(args: {
827
+ contract: Address;
828
+ key: string;
829
+ paramType: number;
830
+ auth: number;
831
+ authAddress?: Address;
832
+ lockAfter?: number;
833
+ min: Hex;
834
+ max: Hex;
835
+ selectOptions?: string[];
836
+ chainId: number;
837
+ /** Human rendering for the sign page (the CLI's `describeSchema`). */
838
+ display?: string;
839
+ }): PreparedTx;
840
+ /** The decoded on-chain schema for one key (`paramSchema(bytes32)`). `exists: false` ⇒ ungoverned. */
841
+ export interface OnChainParamSchema {
842
+ exists: boolean;
843
+ paramType: number;
844
+ auth: number;
845
+ authAddress: Address;
846
+ lockAfter: number;
847
+ min: Hex;
848
+ max: Hex;
849
+ selectOptions: string[];
850
+ }
851
+ /** Read one key's schema from chain. The read half of the upsert — anything editing a live schema
852
+ * MUST start here, or it silently rewrites the fields it didn't mention. */
853
+ export declare function readParamSchema(client: PublicClient, contract: Address, key: string): Promise<OnChainParamSchema>;
854
+ /**
855
+ * Retire a parameter: keep every field of its existing schema and set only `lockAfter` to a past
856
+ * timestamp, so all further writes revert `ParamLockExpired`. This is the closest thing the protocol
857
+ * has to deleting a parameter, and it is the read-modify-write case the upsert makes dangerous —
858
+ * hence the caller passes the schema it just READ, rather than a schema it composed.
859
+ *
860
+ * What retiring does NOT do: erase a value already stored. That value keeps being served in token
861
+ * data. It cannot be removed, deliberately — a value written under a `TokenOwner` or `Address` leg
862
+ * came from a collector, and the creator should not be able to delete someone else's contribution.
863
+ */
864
+ export declare function prepareRetireParam(args: {
865
+ contract: Address;
866
+ key: string;
867
+ current: OnChainParamSchema;
868
+ chainId: number;
869
+ /** Unix seconds; defaults to "one second ago" (already expired ⇒ permanent). */
870
+ at?: number;
871
+ }): PreparedTx;
379
872
  //# sourceMappingURL=ops.d.ts.map