@artblocks/abx-sdk 0.1.0-alpha.8 → 0.1.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 (167) hide show
  1. package/CHANGELOG.md +188 -0
  2. package/README.md +130 -0
  3. package/dist/abi/generated.d.ts +7942 -142
  4. package/dist/abi/generated.d.ts.map +1 -1
  5. package/dist/abi/generated.js +41 -23
  6. package/dist/abi/generated.js.map +1 -1
  7. package/dist/abi/index.d.ts +2364 -84
  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 +325 -0
  12. package/dist/anchors.d.ts.map +1 -0
  13. package/dist/anchors.js +740 -0
  14. package/dist/anchors.js.map +1 -0
  15. package/dist/chain-support.d.ts +28 -0
  16. package/dist/chain-support.d.ts.map +1 -0
  17. package/dist/chain-support.js +65 -0
  18. package/dist/chain-support.js.map +1 -0
  19. package/dist/chain-support.json +60 -0
  20. package/dist/chains.d.ts +23 -11
  21. package/dist/chains.d.ts.map +1 -1
  22. package/dist/chains.js +51 -19
  23. package/dist/chains.js.map +1 -1
  24. package/dist/chunks.d.ts +130 -32
  25. package/dist/chunks.d.ts.map +1 -1
  26. package/dist/chunks.js +140 -15
  27. package/dist/chunks.js.map +1 -1
  28. package/dist/clients.d.ts +23 -11
  29. package/dist/clients.d.ts.map +1 -1
  30. package/dist/clients.js +17 -18
  31. package/dist/clients.js.map +1 -1
  32. package/dist/contract-generations.d.ts +58 -0
  33. package/dist/contract-generations.d.ts.map +1 -0
  34. package/dist/contract-generations.js +109 -0
  35. package/dist/contract-generations.js.map +1 -0
  36. package/dist/contract-generations.json +48 -0
  37. package/dist/create2.d.ts +88 -1
  38. package/dist/create2.d.ts.map +1 -1
  39. package/dist/create2.js +174 -4
  40. package/dist/create2.js.map +1 -1
  41. package/dist/creator-token.d.ts +75 -8
  42. package/dist/creator-token.d.ts.map +1 -1
  43. package/dist/creator-token.js +98 -8
  44. package/dist/creator-token.js.map +1 -1
  45. package/dist/creators-service.d.ts +79 -0
  46. package/dist/creators-service.d.ts.map +1 -0
  47. package/dist/creators-service.js +171 -0
  48. package/dist/creators-service.js.map +1 -0
  49. package/dist/deploy.d.ts +224 -14
  50. package/dist/deploy.d.ts.map +1 -1
  51. package/dist/deploy.js +289 -111
  52. package/dist/deploy.js.map +1 -1
  53. package/dist/deployments.d.ts +38 -5
  54. package/dist/deployments.d.ts.map +1 -1
  55. package/dist/deployments.js +157 -45
  56. package/dist/deployments.js.map +1 -1
  57. package/dist/deps.d.ts +123 -6
  58. package/dist/deps.d.ts.map +1 -1
  59. package/dist/deps.js +249 -7
  60. package/dist/deps.js.map +1 -1
  61. package/dist/env.d.ts +5 -4
  62. package/dist/env.d.ts.map +1 -1
  63. package/dist/env.js +20 -5
  64. package/dist/env.js.map +1 -1
  65. package/dist/errors.d.ts +109 -0
  66. package/dist/errors.d.ts.map +1 -0
  67. package/dist/errors.js +148 -0
  68. package/dist/errors.js.map +1 -0
  69. package/dist/execute.d.ts +118 -0
  70. package/dist/execute.d.ts.map +1 -0
  71. package/dist/execute.js +159 -0
  72. package/dist/execute.js.map +1 -0
  73. package/dist/gateways.d.ts +79 -0
  74. package/dist/gateways.d.ts.map +1 -0
  75. package/dist/gateways.js +156 -0
  76. package/dist/gateways.js.map +1 -0
  77. package/dist/generator-document.d.ts +57 -0
  78. package/dist/generator-document.d.ts.map +1 -0
  79. package/dist/generator-document.js +123 -0
  80. package/dist/generator-document.js.map +1 -0
  81. package/dist/generator.d.ts +45 -3
  82. package/dist/generator.d.ts.map +1 -1
  83. package/dist/generator.js +29 -0
  84. package/dist/generator.js.map +1 -1
  85. package/dist/index.d.ts +20 -3
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +20 -3
  88. package/dist/index.js.map +1 -1
  89. package/dist/inspect.d.ts +48 -0
  90. package/dist/inspect.d.ts.map +1 -0
  91. package/dist/inspect.js +295 -0
  92. package/dist/inspect.js.map +1 -0
  93. package/dist/migrate.d.ts +41 -0
  94. package/dist/migrate.d.ts.map +1 -0
  95. package/dist/migrate.js +142 -0
  96. package/dist/migrate.js.map +1 -0
  97. package/dist/mime.d.ts +11 -0
  98. package/dist/mime.d.ts.map +1 -0
  99. package/dist/mime.js +40 -0
  100. package/dist/mime.js.map +1 -0
  101. package/dist/node.d.ts +69 -0
  102. package/dist/node.d.ts.map +1 -0
  103. package/dist/node.js +92 -0
  104. package/dist/node.js.map +1 -0
  105. package/dist/onchain-uri.d.ts +110 -0
  106. package/dist/onchain-uri.d.ts.map +1 -0
  107. package/dist/onchain-uri.js +276 -0
  108. package/dist/onchain-uri.js.map +1 -0
  109. package/dist/ops.d.ts +437 -13
  110. package/dist/ops.d.ts.map +1 -1
  111. package/dist/ops.js +754 -34
  112. package/dist/ops.js.map +1 -1
  113. package/dist/policy.d.ts +57 -0
  114. package/dist/policy.d.ts.map +1 -0
  115. package/dist/policy.js +35 -0
  116. package/dist/policy.js.map +1 -0
  117. package/dist/probe.d.ts +58 -0
  118. package/dist/probe.d.ts.map +1 -1
  119. package/dist/probe.js +190 -9
  120. package/dist/probe.js.map +1 -1
  121. package/dist/reconstruct.d.ts +141 -3
  122. package/dist/reconstruct.d.ts.map +1 -1
  123. package/dist/reconstruct.js +479 -100
  124. package/dist/reconstruct.js.map +1 -1
  125. package/dist/resume.d.ts +147 -0
  126. package/dist/resume.d.ts.map +1 -0
  127. package/dist/resume.js +146 -0
  128. package/dist/resume.js.map +1 -0
  129. package/dist/script-chunks.d.ts +105 -0
  130. package/dist/script-chunks.d.ts.map +1 -0
  131. package/dist/script-chunks.js +158 -0
  132. package/dist/script-chunks.js.map +1 -0
  133. package/dist/service.d.ts +172 -7
  134. package/dist/service.d.ts.map +1 -1
  135. package/dist/service.js +132 -10
  136. package/dist/service.js.map +1 -1
  137. package/dist/spine.d.ts +47 -4
  138. package/dist/spine.d.ts.map +1 -1
  139. package/dist/spine.js +0 -0
  140. package/dist/spine.js.map +1 -1
  141. package/dist/staging.d.ts +139 -0
  142. package/dist/staging.d.ts.map +1 -0
  143. package/dist/staging.js +139 -0
  144. package/dist/staging.js.map +1 -0
  145. package/dist/token.d.ts +11 -1
  146. package/dist/token.d.ts.map +1 -1
  147. package/dist/token.js +32 -1
  148. package/dist/token.js.map +1 -1
  149. package/dist/tokendata.d.ts +4 -4
  150. package/dist/tokendata.d.ts.map +1 -1
  151. package/dist/tokendata.js +28 -9
  152. package/dist/tokendata.js.map +1 -1
  153. package/dist/tokens.d.ts +120 -0
  154. package/dist/tokens.d.ts.map +1 -0
  155. package/dist/tokens.js +322 -0
  156. package/dist/tokens.js.map +1 -0
  157. package/dist/types.d.ts +107 -5
  158. package/dist/types.d.ts.map +1 -1
  159. package/dist/uri-lock.d.ts +17 -0
  160. package/dist/uri-lock.d.ts.map +1 -0
  161. package/dist/uri-lock.js +33 -0
  162. package/dist/uri-lock.js.map +1 -0
  163. package/dist/util.d.ts +74 -0
  164. package/dist/util.d.ts.map +1 -0
  165. package/dist/util.js +106 -0
  166. package/dist/util.js.map +1 -0
  167. package/package.json +15 -6
package/dist/create2.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { concat, getContractAddress, keccak256, toBytes } from 'viem';
2
- import { abxChunkStoreBytecode, abxFixedPriceMinterBytecode, abxMetadataRendererBytecode, abxSeedSourceBytecode, } from './abi/index.js';
2
+ import { abxChunkStoreBytecode, abxCodeLibBytecode, abxEditionLibBytecode, abxMetadataLibBytecode, abxFixedPriceMinterBytecode, abxFixedPriceMinter1155Bytecode, abxMetadataRendererBytecode, abxParamsLibBytecode, abxSeedSourceBytecode, editionCodeFactoryBytecode, editionImageFactoryBytecode, oneOfOneEditionFactoryBytecode, oneOfOneImageFactoryBytecode, seriesCodeFactoryBytecode, seriesImageFactoryBytecode, } from './abi/index.js';
3
3
  /**
4
4
  * Keyless CREATE2 deployment — the TS twin of `contracts/script/AbxSalts.sol`.
5
5
  *
@@ -12,7 +12,9 @@ import { abxChunkStoreBytecode, abxFixedPriceMinterBytecode, abxMetadataRenderer
12
12
  /** The keyless CREATE2 proxy (Arachnid deterministic-deployment-proxy). Same address on every chain. */
13
13
  export const CREATE2_PROXY = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
14
14
  /** Canonical salt strings — MUST stay byte-identical to `contracts/script/AbxSalts.sol`, since the
15
- * deterministic address is `keccak256(0xff ++ proxy ++ keccak256(salt) ++ keccak256(initcode))`. */
15
+ * deterministic address is `keccak256(0xff ++ proxy ++ keccak256(salt) ++ keccak256(initcode))`.
16
+ * `test/create2-salts.test.ts` diffs this table against that file, both ways, so drift can't be
17
+ * quiet: the two halves have to be one fact. */
16
18
  export const ABX_SALT = {
17
19
  oneOfOneFactory: 'abx.factory.one-of-one.v1',
18
20
  seriesFactory: 'abx.factory.series.v1',
@@ -22,17 +24,42 @@ export const ABX_SALT = {
22
24
  fixedPriceMinter: 'abx.minter.fixed-price.v1',
23
25
  seedSource: 'abx.seed-source.v1',
24
26
  generator: 'abx.generator.v1',
27
+ // ERC-1155 editions (twins of the above; naming follows the parity plan verbatim).
28
+ oneOfOneEditionFactory: 'abx.one-of-one-edition-factory.v1',
29
+ editionFactory: 'abx.edition-factory.v1',
30
+ editionCodeFactory: 'abx.edition-code-factory.v1',
31
+ fixedPriceMinter1155: 'abx.fixed-price-minter-1155.v1',
32
+ // Delegatecalled write-path libraries — CREATE2 like everything else here (see the
33
+ // "delegatecalled write-path libraries" note below, and `DeployLibraries.s.sol`).
34
+ paramsLib: 'abx.lib.params.v1',
35
+ codeLib: 'abx.lib.code.v1',
36
+ editionLib: 'abx.lib.edition.v1',
37
+ metadataLib: 'abx.lib.metadata.v1',
25
38
  };
26
39
  /** The 32-byte salt a CREATE2 deploy uses (`keccak256` of the canonical string). */
27
40
  export const saltHash = (salt) => keccak256(toBytes(salt));
41
+ function exactCreate2Salt(salt) {
42
+ if (!/^0x[0-9a-fA-F]{64}$/.test(salt)) {
43
+ throw new Error('CREATE2 salt must be exactly 32 bytes (0x + 64 hex characters).');
44
+ }
45
+ return salt.toLowerCase();
46
+ }
47
+ /** The deterministic address for an already-hashed/raw 32-byte CREATE2 salt. */
48
+ export function predictCreate2AddressFromSalt(salt, bytecode) {
49
+ return getContractAddress({ opcode: 'CREATE2', from: CREATE2_PROXY, salt: exactCreate2Salt(salt), bytecode });
50
+ }
51
+ /** Proxy calldata for an already-hashed/raw 32-byte CREATE2 salt. */
52
+ export function create2CalldataFromSalt(salt, bytecode) {
53
+ return concat([exactCreate2Salt(salt), bytecode]);
54
+ }
28
55
  /** The deterministic address `bytecode` deploys to under `salt` via the keyless proxy — identical
29
56
  * on every chain. Pure: no chain access. */
30
57
  export function predictCreate2Address(salt, bytecode) {
31
- return getContractAddress({ opcode: 'CREATE2', from: CREATE2_PROXY, salt: saltHash(salt), bytecode });
58
+ return predictCreate2AddressFromSalt(saltHash(salt), bytecode);
32
59
  }
33
60
  /** The calldata a CREATE2-proxy deploy sends: 32-byte salt ++ initcode (the proxy CREATE2-deploys it). */
34
61
  export function create2Calldata(salt, bytecode) {
35
- return concat([saltHash(salt), bytecode]);
62
+ return create2CalldataFromSalt(saltHash(salt), bytecode);
36
63
  }
37
64
  /** The canonical (cross-chain-identical) AbxChunkStore address for the current bytecode. */
38
65
  export const predictChunkStore = () => predictCreate2Address(ABX_SALT.chunkStore, abxChunkStoreBytecode);
@@ -44,4 +71,147 @@ export const predictFixedPriceMinter = () => predictCreate2Address(ABX_SALT.fixe
44
71
  * (`DeploySeedSource.s.sol`) so it compiles at the default profile — bundling it with the
45
72
  * SeriesCode factory's `clone-impl` unit yields a different, non-canonical bytecode + address. */
46
73
  export const predictSeedSource = () => predictCreate2Address(ABX_SALT.seedSource, abxSeedSourceBytecode);
74
+ // ── ERC-1155 editions ──────────────────────────────────────────────────────────
75
+ //
76
+ // `DeployOneOfOneEdition.s.sol` / `DeployEdition.s.sol` / `DeployMinter1155.s.sol` each deploy
77
+ // their contract with a fixed `AbxSalts` salt and NO constructor args, so the salt + this build's
78
+ // bytecode fix the address before any deploy. `AbxFixedPriceMinter1155` is a plain singleton and is
79
+ // predicted right below; the two edition IMAGE factories are not — `OneOfOneEdition`/`EditionImage`
80
+ // both delegate bodies into `AbxEditionLib`, so their factories carry a link placeholder and their
81
+ // predictions live with the library-linked factories in the write-path-library section below
82
+ // (`predictOneOfOneEditionFactory`/`predictEditionFactory`), next to the two code factories.
83
+ /** The canonical (cross-chain-identical) `OneOfOneImageFactory` address for the current bytecode —
84
+ * the 721 1/1 trust anchor. */
85
+ export const predictFactory = () => predictCreate2Address(ABX_SALT.oneOfOneFactory, linkFactory());
86
+ /** The canonical (cross-chain-identical) `SeriesImageFactory` address for the current bytecode —
87
+ * the 721 multi-token trust anchor. */
88
+ export const predictSeriesFactory = () => predictCreate2Address(ABX_SALT.seriesFactory, linkSeriesFactory());
89
+ /** The canonical (cross-chain-identical) `AbxFixedPriceMinter1155` address for the current
90
+ * bytecode — the shared, ownerless edition sale singleton. */
91
+ export const predictFixedPriceMinter1155 = () => predictCreate2Address(ABX_SALT.fixedPriceMinter1155, abxFixedPriceMinter1155Bytecode);
92
+ // ── delegatecalled write-path libraries ────────────────────────────────────────
93
+ //
94
+ // A `public` library function is compiled as a `delegatecall` to a SEPARATELY deployed copy of the
95
+ // library, and solc leaves a `__$<id>$__` placeholder in the caller's bytecode where that copy's
96
+ // address goes. Linking is the substitution of an address into that placeholder.
97
+ //
98
+ // **Linking does not cost determinism.** These libraries are deployed through the same keyless
99
+ // CREATE2 proxy at the canonical salts above (`DeployLibraries.s.sol` is the forge twin), so a
100
+ // library's address is `f(proxy, salt, creation bytecode)` and nothing else — the deployer's nonce
101
+ // is not an input to a CREATE2 address (it is an input to plain `CREATE`, which is where the
102
+ // confusion came from). Predict the libraries, substitute them, and the linked factory's initcode
103
+ // is fixed too — hence the FOUR `predict*Factory` helpers at the bottom of this section.
104
+ //
105
+ // Worth stating plainly, because the opposite belief was load-bearing: two ERC-1155 token types
106
+ // (`OneOfOneEdition`/`EditionImage`) were held library-free and an EIP-170 size floor was relaxed to
107
+ // avoid "losing" a factory's deterministic address. What was actually true was narrower and
108
+ // self-inflicted — the SDK deployed its libraries with a plain EOA `CREATE` (`to: null`) by its own
109
+ // choice, so *it* could not predict them, and that local limitation was written up as a property of
110
+ // libraries in general. It isn't one. The broadcast artifacts always said so: every recorded library
111
+ // deploy went through the keyless proxy, and `AbxParamsLib` landed at ONE address on Sepolia and
112
+ // Base Sepolia from deployer nonces 215 apart. Both of those token types now delegate into
113
+ // `AbxEditionLib` exactly as `EditionCode` does, so FOUR factories here are library-linked, not two.
114
+ //
115
+ // **Losing track of that is a bug class, not a footnote.** Three separate times a contract became
116
+ // library-linked and this file went on hashing its UNLINKED bytecode, and the failure is silent:
117
+ // viem does not reject a `__$…$__` placeholder, it UTF-8-encodes it — so the prediction is a
118
+ // real-looking address that is the hash of ASCII garbage, for the addresses platforms allowlist, and
119
+ // the same bytes would go out as initcode. `link.test.ts`'s "nothing deployable carries a
120
+ // placeholder" guard derives its subject set from the exported bytecodes rather than a list of
121
+ // names, precisely so the next contract to become library-linked cannot escape the same way.
122
+ //
123
+ // **The real trap is compile-time linking, not linking.** Substituting into the placeholder happens
124
+ // AFTER compilation, so it cannot change the library's own creation bytecode. Handing solc the
125
+ // addresses at build time instead (`forge build/script --libraries src/…:Lib:0x…`) writes the
126
+ // library map into `settings.libraries` in every artifact's metadata, and the metadata hash is
127
+ // appended to the creation bytecode — so the library's own address moves, and so does the linked
128
+ // factory's. Optimizer settings do the same (the code tokens compile at `optimizer_runs = 200`,
129
+ // everything else at 1,000,000). One canonical bytecode per library, therefore: the one
130
+ // `sync-abis` reads from a plain `forge build`, which is what these predictions use.
131
+ /** Fully-qualified library names (solc's link keys — path-sensitive, so they must match how the
132
+ * contracts are compiled: `src/libraries/…` as `foundry.toml` sees them). */
133
+ export const LIB_FQN = {
134
+ paramsLib: 'src/libraries/AbxParamsLib.sol:AbxParamsLib',
135
+ codeLib: 'src/libraries/AbxCodeLib.sol:AbxCodeLib',
136
+ editionLib: 'src/libraries/AbxEditionLib.sol:AbxEditionLib',
137
+ metadataLib: 'src/libraries/AbxMetadataLib.sol:AbxMetadataLib',
138
+ };
139
+ /** The solc link placeholder for a fully-qualified library name: `__$<keccak(fqn)[0:34]>$__`. */
140
+ export const libPlaceholder = (fullyQualified) => `__$${keccak256(toBytes(fullyQualified)).slice(2, 36)}$__`;
141
+ /**
142
+ * Link `bytecode` against deployed libraries — the post-compile placeholder substitution `forge`
143
+ * does at build time, done here so a sandbox / fresh chain needs no forge. Throws if any
144
+ * placeholder is left over, since an unlinked `__$…$__` is not valid hex and the RPC would reject
145
+ * the transaction with an opaque `Invalid byte sequence`.
146
+ */
147
+ export function linkLibraries(bytecode, links) {
148
+ let out = bytecode;
149
+ for (const [fqn, address] of links)
150
+ out = out.split(libPlaceholder(fqn)).join(address.slice(2).toLowerCase());
151
+ if (out.includes('__$'))
152
+ throw new Error(`unlinked library placeholder remains: ${/__\$[0-9a-f]{34}\$__/.exec(out)?.[0]}`);
153
+ return out;
154
+ }
155
+ /** The canonical (cross-chain-identical) `AbxParamsLib` address — the params write path both code
156
+ * token types delegatecall. */
157
+ export const predictParamsLib = () => predictCreate2Address(ABX_SALT.paramsLib, abxParamsLibBytecode);
158
+ /** The canonical (cross-chain-identical) `AbxCodeLib` address — the script/code write path. */
159
+ export const predictCodeLib = () => predictCreate2Address(ABX_SALT.codeLib, abxCodeLibBytecode);
160
+ /** The canonical (cross-chain-identical) `AbxEditionLib` address — the 1155 uri / creator-token /
161
+ * edition-supply write path that **all three** edition token types (`OneOfOneEdition`,
162
+ * `EditionImage`, `EditionCode`) delegatecall.
163
+ * `AbxEditionLib` itself delegatecalls `AbxParamsLib`, so it is linked before it is deployed: the
164
+ * one library here whose own initcode depends on another library's address. */
165
+ export const predictEditionLib = () => predictCreate2Address(ABX_SALT.editionLib, linkEditionLib());
166
+ /** The canonical `AbxMetadataLib` address. Linked by ALL SIX token types to preserve EIP-170
167
+ * headroom; externalizing the metadata field store makes even the plainest 721 factory
168
+ * library-linked. It links nothing itself, so it is deployed first. */
169
+ export const predictMetadataLib = () => predictCreate2Address(ABX_SALT.metadataLib, abxMetadataLibBytecode);
170
+ /** `AbxEditionLib`'s canonical initcode: its shipped bytecode linked against `AbxParamsLib`. */
171
+ export const linkEditionLib = () => linkLibraries(abxEditionLibBytecode, [[LIB_FQN.paramsLib, predictParamsLib()]]);
172
+ /** `OneOfOneEditionFactory`'s canonical initcode: linked against `AbxEditionLib` (the only library
173
+ * its embedded `OneOfOneEdition` implementation delegates into). `AbxEditionLib`'s own address
174
+ * already accounts for its `AbxParamsLib` link — see {@link predictEditionLib}. */
175
+ export const linkOneOfOneEditionFactory = () => linkLibraries(oneOfOneEditionFactoryBytecode, [
176
+ [LIB_FQN.editionLib, predictEditionLib()],
177
+ [LIB_FQN.metadataLib, predictMetadataLib()],
178
+ ]);
179
+ /** `EditionImageFactory`'s canonical initcode: linked against `AbxEditionLib`, the sibling of
180
+ * {@link linkOneOfOneEditionFactory}. */
181
+ export const linkEditionFactory = () => linkLibraries(editionImageFactoryBytecode, [
182
+ [LIB_FQN.editionLib, predictEditionLib()],
183
+ [LIB_FQN.metadataLib, predictMetadataLib()],
184
+ ]);
185
+ /** `SeriesCodeFactory`'s canonical initcode: linked against the two write-path libraries. */
186
+ export const linkSeriesCodeFactory = () => linkLibraries(seriesCodeFactoryBytecode, [
187
+ [LIB_FQN.paramsLib, predictParamsLib()],
188
+ [LIB_FQN.codeLib, predictCodeLib()],
189
+ [LIB_FQN.metadataLib, predictMetadataLib()],
190
+ ]);
191
+ /** `EditionCodeFactory`'s canonical initcode: linked against all three write-path libraries. */
192
+ export const linkEditionCodeFactory = () => linkLibraries(editionCodeFactoryBytecode, [
193
+ [LIB_FQN.paramsLib, predictParamsLib()],
194
+ [LIB_FQN.codeLib, predictCodeLib()],
195
+ [LIB_FQN.editionLib, predictEditionLib()],
196
+ [LIB_FQN.metadataLib, predictMetadataLib()],
197
+ ]);
198
+ /** The two ERC-721 image factories' canonical initcode. They linked NOTHING until the metadata
199
+ * field store was externalized; now every token type is library-linked. */
200
+ export const linkFactory = () => linkLibraries(oneOfOneImageFactoryBytecode, [[LIB_FQN.metadataLib, predictMetadataLib()]]);
201
+ export const linkSeriesFactory = () => linkLibraries(seriesImageFactoryBytecode, [[LIB_FQN.metadataLib, predictMetadataLib()]]);
202
+ /** The canonical (cross-chain-identical) `SeriesCodeFactory` address — the code-project trust
203
+ * anchor. Predictable because its libraries are (see the section note above). */
204
+ export const predictSeriesCodeFactory = () => predictCreate2Address(ABX_SALT.seriesCodeFactory, linkSeriesCodeFactory());
205
+ /** The canonical (cross-chain-identical) `EditionCodeFactory` address — the code-project EDITION
206
+ * trust anchor. */
207
+ export const predictEditionCodeFactory = () => predictCreate2Address(ABX_SALT.editionCodeFactory, linkEditionCodeFactory());
208
+ /** The canonical (cross-chain-identical) `OneOfOneEditionFactory` address — the 1/1-edition trust
209
+ * anchor. Predicted from LINKED initcode: `OneOfOneEdition` delegates its uri / creator-token /
210
+ * edition-supply bodies into `AbxEditionLib`, so the shipped factory bytecode carries a link
211
+ * placeholder (hashing it unlinked yields a plausible-looking address for a trust anchor that
212
+ * nothing can ever be deployed to — see the section note). */
213
+ export const predictOneOfOneEditionFactory = () => predictCreate2Address(ABX_SALT.oneOfOneEditionFactory, linkOneOfOneEditionFactory());
214
+ /** The canonical (cross-chain-identical) `EditionImageFactory` address — the multi-work edition
215
+ * trust anchor, the sibling of {@link predictOneOfOneEditionFactory} (same single library link). */
216
+ export const predictEditionFactory = () => predictCreate2Address(ABX_SALT.editionFactory, linkEditionFactory());
47
217
  //# sourceMappingURL=create2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create2.js","sourceRoot":"","sources":["../src/create2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,EAAyB,MAAM,MAAM,CAAC;AAC5F,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;GAQG;AAEH,wGAAwG;AACxG,MAAM,CAAC,MAAM,aAAa,GAAY,4CAA4C,CAAC;AAEnF;qGACqG;AACrG,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,eAAe,EAAE,2BAA2B;IAC5C,aAAa,EAAE,uBAAuB;IACtC,iBAAiB,EAAE,4BAA4B;IAC/C,QAAQ,EAAE,iBAAiB;IAC3B,UAAU,EAAE,oBAAoB;IAChC,gBAAgB,EAAE,2BAA2B;IAC7C,UAAU,EAAE,oBAAoB;IAChC,SAAS,EAAE,kBAAkB;CACrB,CAAC;AAEX,oFAAoF;AACpF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAO,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAExE;6CAC6C;AAC7C,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,QAAa;IAC/D,OAAO,kBAAkB,CAAC,EAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAC,CAAC,CAAC;AACtG,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,QAAa;IACzD,OAAO,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAY,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;AAElH,kGAAkG;AAClG,MAAM,CAAC,MAAM,eAAe,GAAG,GAAY,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC;AAEpH,kGAAkG;AAClG,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAY,EAAE,CACnD,qBAAqB,CAAC,QAAQ,CAAC,gBAAgB,EAAE,2BAA2B,CAAC,CAAC;AAEhF;;mGAEmG;AACnG,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAY,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"create2.js","sourceRoot":"","sources":["../src/create2.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,15 @@
8
8
  * zero — never un-enrolls. Every transfer that isn't a mint/burn (or the validator's own)
9
9
  * staticcalls `validateTransfer(caller, from, to, tokenId)` on the validator; a policy
10
10
  * violation reverts and bubbles.
11
+ *
12
+ * **`setTransferValidator` is owner-only only while the collection has an owner.** Once
13
+ * `owner() == address(0)` the contract opens one asymmetric door: **anyone** may suspend
14
+ * enforcement by passing `zeroAddress`, and nobody — including that caller — may ever arm a
15
+ * validator again. That is the dead-man release for the worst reachable state (a validator that
16
+ * reverts every transfer on a collection with nobody left to re-point it, which would otherwise
17
+ * strand every collector's token forever). An integrator building for collectors should expose
18
+ * that suspension path on a renounced collection rather than gating it behind an owner check that
19
+ * can no longer be satisfied — see {@link prepareSetTransferValidator}.
11
20
  */
12
21
  import { type Address, type PublicClient } from 'viem';
13
22
  import type { PreparedTx } from './ops.js';
@@ -20,10 +29,10 @@ export declare const CREATOR_TOKEN_EXTENSION_ID: "0x0839e7ed7fc1f5db3f253851d61b
20
29
  /**
21
30
  * The recommended transfer validator per chain — OpenSea's
22
31
  * **StrictAuthorizedTransferSecurityRegistry**, the validator their creator-fee-enforcement
23
- * doc recommends for enforcement eligibility (docs.opensea.io "Creator Fee Enforcement",
24
- * checked 2026-08; the named alternative is Limit Break's CreatorTokenTransferValidator
25
- * 0x721C0078c2328597Ca70F5451ffF5A7B38D4E947). Verified empirically against the LIVE
26
- * contracts on 2026-08-04 (`cast call --from <collection>` on the 4-arg
32
+ * doc recommends for enforcement eligibility (docs.opensea.io "Creator Fee Enforcement"; the named
33
+ * alternative is Limit Break's CreatorTokenTransferValidator
34
+ * 0x721C0078c2328597Ca70F5451ffF5A7B38D4E947). Verified empirically against the live contracts with
35
+ * `cast call --from <collection>` on the 4-arg
27
36
  * `validateTransfer(address,address,address,uint256)` overload, both chains):
28
37
  * an owner-initiated (OTC) transfer succeeds; an unauthorized operator reverts
29
38
  * `StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer()`.
@@ -50,12 +59,70 @@ export interface CreatorTokenStatus {
50
59
  * must read as `{enrolled: false, validator: zeroAddress}`, not as an error.
51
60
  */
52
61
  export declare function readCreatorTokenStatus(client: PublicClient, contract: Address): Promise<CreatorTokenStatus>;
62
+ /** What {@link probeTransferValidator} found. Only `ok` may be written to a live collection.
63
+ *
64
+ * - `ok` — the address has code and refuses a selector no validator implements,
65
+ * which is what every live validator does (see the probe's doc).
66
+ * - `no-code` — nothing deployed at this address on this chain. Enforcement would read
67
+ * as ON everywhere and check nothing.
68
+ * - `permissive-fallback` — it has code, but it answers an unknown selector *successfully*. A
69
+ * Safe, an uninitialised proxy, or a 7702-delegated EOA does this, and
70
+ * because `validateTransfer` returns nothing there is no ABI decode to
71
+ * fail — so every transfer would silently pass validation.
72
+ * - `unreachable` — the RPC didn't answer. Says nothing about the address; retry.
73
+ */
74
+ export type TransferValidatorVerdict = 'ok' | 'no-code' | 'permissive-fallback' | 'unreachable';
75
+ /** The result of {@link probeTransferValidator} — verdict plus what was observed, for a message. */
76
+ export interface TransferValidatorProbe {
77
+ verdict: TransferValidatorVerdict;
78
+ address: Address;
79
+ /** First line of the revert/transport error, when there was one. */
80
+ error?: string;
81
+ }
82
+ /**
83
+ * Ask a candidate transfer validator a question no validator can answer, and require it to FAIL.
84
+ *
85
+ * **`code.length > 0` is not enough**, which is why this exists and why the on-chain guard was
86
+ * rewritten to match. Two shapes enforce nothing while every read surface — ERC-165,
87
+ * `getTransferValidator()`, the extension beacon — reports enforcement as on: no code at all, and a
88
+ * *permissive fallback* that succeeds for any selector. `validateTransfer` returns nothing, so
89
+ * there is no ABI decode to fail; a Safe (its `FallbackManager.fallback()` returns empty when no
90
+ * handler is set), an uninitialised proxy, and an EIP-7702-delegated EOA all pass a has-code check
91
+ * and then wave every transfer through. A creator pasting their own Safe is the likely real case.
92
+ *
93
+ * So the probe inverts the question: a real validator **reverts** here (verified against OpenSea's
94
+ * SATSR and three Limit Break deployments on mainnet and Sepolia), and a permissive one returns
95
+ * empty success. This mirrors the contract exactly — the same selector, the same "must fail" rule —
96
+ * so an address that passes here is an address the token will accept, and the CLI stops reporting
97
+ * "no code on this chain" for an address that plainly has code.
98
+ *
99
+ * An ERC-165 gate was measured and rejected: none of those four live validators advertises
100
+ * `ITransferValidator`/`ITransferValidator1155`, so requiring an id would refuse the entire
101
+ * ecosystem, including the validator ABX itself recommends.
102
+ *
103
+ * **A misconfiguration guard, not a security boundary** — a contract can always be written to pass
104
+ * this and enforce nothing. It catches the honest mistake. Never throws for an on-chain reason:
105
+ * every failure is a verdict (mirrors `probeSeedSource`).
106
+ */
107
+ export declare function probeTransferValidator(client: PublicClient, validator: Address,
108
+ /** The enrolling/enrolled token, when known — the probe is made as the token, because that is
109
+ * the `msg.sender` the contract's own staticcall presents. */
110
+ opts?: {
111
+ as?: Address;
112
+ }): Promise<TransferValidatorProbe>;
53
113
  /**
54
114
  * Re-point an enrolled token's transfer validator, or suspend enforcement with
55
- * `zeroAddress` (the token stays enrolled). Signer must be the owner. Reverts
56
- * `NotCreatorToken()` on a token that didn't enroll at deploy — enrollment can never be
57
- * added later — and `InvalidTransferValidator()` on a non-zero validator with no code;
58
- * callers should read {@link readCreatorTokenStatus} first and refuse those before gas.
115
+ * `zeroAddress` (the token stays enrolled). Reverts `NotCreatorToken()` on a token that didn't
116
+ * enroll at deploy — enrollment can never be added later — and `InvalidTransferValidator()` on a
117
+ * validator the chain's own probe refuses (no code on this chain, **or** a permissive fallback that
118
+ * would enforce nothing); call {@link probeTransferValidator} first and refuse those before gas.
119
+ *
120
+ * **Who may sign:** the owner, while there is one. On a collection whose `owner()` is
121
+ * `address(0)`, **any** signer may send this with `validator = zeroAddress` to suspend enforcement
122
+ * permanently — the dead-man release described in this module's header. Arming a validator is still
123
+ * owner-only, so an ownerless collection can only move toward transferability, never back. A UX for
124
+ * collectors should offer that suspension when it sees a renounced, enforcing collection; gating it
125
+ * on `owner()` would hide the one recovery a stranded holder has.
59
126
  */
60
127
  export declare function prepareSetTransferValidator(args: {
61
128
  contract: Address;
@@ -1 +1 @@
1
- {"version":3,"file":"creator-token.d.ts","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAkC,KAAK,OAAO,EAAE,KAAK,YAAY,EAAC,MAAM,MAAM,CAAC;AAEtF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AAEzC,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,EAAG,YAAqB,CAAC;AAChE,qFAAqF;AACrF,eAAO,MAAM,iCAAiC,EAAG,YAAqB,CAAC;AACvE,iGAAiG;AACjG,eAAO,MAAM,0BAA0B,EACrC,oEAA6E,CAAC;AAEhF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAKlE,CAAC;AAEF,4FAA4F;AAC5F,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAExF;AAED,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,UAAU,CAiBb"}
1
+ {"version":3,"file":"creator-token.d.ts","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAkC,KAAK,OAAO,EAAY,KAAK,YAAY,EAAC,MAAM,MAAM,CAAC;AAEhG,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AAEzC,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,EAAG,YAAqB,CAAC;AAChE,qFAAqF;AACrF,eAAO,MAAM,iCAAiC,EAAG,YAAqB,CAAC;AACvE,iGAAiG;AACjG,eAAO,MAAM,0BAA0B,EACrC,oEAA6E,CAAC;AAEhF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAKlE,CAAC;AAEF,4FAA4F;AAC5F,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAExF;AAED,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,wBAAwB,GAAG,IAAI,GAAG,SAAS,GAAG,qBAAqB,GAAG,aAAa,CAAC;AAEhG,oGAAoG;AACpG,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,wBAAwB,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,OAAO;AAClB;+DAC+D;AAC/D,IAAI,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GACxB,OAAO,CAAC,sBAAsB,CAAC,CAsBjC;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,UAAU,CAiBb"}
@@ -8,6 +8,15 @@
8
8
  * zero — never un-enrolls. Every transfer that isn't a mint/burn (or the validator's own)
9
9
  * staticcalls `validateTransfer(caller, from, to, tokenId)` on the validator; a policy
10
10
  * violation reverts and bubbles.
11
+ *
12
+ * **`setTransferValidator` is owner-only only while the collection has an owner.** Once
13
+ * `owner() == address(0)` the contract opens one asymmetric door: **anyone** may suspend
14
+ * enforcement by passing `zeroAddress`, and nobody — including that caller — may ever arm a
15
+ * validator again. That is the dead-man release for the worst reachable state (a validator that
16
+ * reverts every transfer on a collection with nobody left to re-point it, which would otherwise
17
+ * strand every collector's token forever). An integrator building for collectors should expose
18
+ * that suspension path on a renounced collection rather than gating it behind an owner check that
19
+ * can no longer be satisfied — see {@link prepareSetTransferValidator}.
11
20
  */
12
21
  import { encodeFunctionData, zeroAddress } from 'viem';
13
22
  import { oneOfOneImageAbi } from './abi/index.js';
@@ -20,10 +29,10 @@ export const CREATOR_TOKEN_EXTENSION_ID = '0x0839e7ed7fc1f5db3f253851d61b10f8520
20
29
  /**
21
30
  * The recommended transfer validator per chain — OpenSea's
22
31
  * **StrictAuthorizedTransferSecurityRegistry**, the validator their creator-fee-enforcement
23
- * doc recommends for enforcement eligibility (docs.opensea.io "Creator Fee Enforcement",
24
- * checked 2026-08; the named alternative is Limit Break's CreatorTokenTransferValidator
25
- * 0x721C0078c2328597Ca70F5451ffF5A7B38D4E947). Verified empirically against the LIVE
26
- * contracts on 2026-08-04 (`cast call --from <collection>` on the 4-arg
32
+ * doc recommends for enforcement eligibility (docs.opensea.io "Creator Fee Enforcement"; the named
33
+ * alternative is Limit Break's CreatorTokenTransferValidator
34
+ * 0x721C0078c2328597Ca70F5451ffF5A7B38D4E947). Verified empirically against the live contracts with
35
+ * `cast call --from <collection>` on the 4-arg
27
36
  * `validateTransfer(address,address,address,uint256)` overload, both chains):
28
37
  * an owner-initiated (OTC) transfer succeeds; an unauthorized operator reverts
29
38
  * `StrictAuthorizedTransferSecurityRegistry__UnauthorizedTransfer()`.
@@ -65,12 +74,93 @@ export async function readCreatorTokenStatus(client, contract) {
65
74
  ]);
66
75
  return { enrolled, validator };
67
76
  }
77
+ /**
78
+ * A selector no transfer validator implements — the probe question. Same constant the contract's
79
+ * own `_requireHasCode` uses, so the SDK and the chain agree about which addresses are refused.
80
+ */
81
+ const NOT_A_VALIDATOR_SELECTOR = '0xa9b1c2d3';
82
+ /**
83
+ * Ask a candidate transfer validator a question no validator can answer, and require it to FAIL.
84
+ *
85
+ * **`code.length > 0` is not enough**, which is why this exists and why the on-chain guard was
86
+ * rewritten to match. Two shapes enforce nothing while every read surface — ERC-165,
87
+ * `getTransferValidator()`, the extension beacon — reports enforcement as on: no code at all, and a
88
+ * *permissive fallback* that succeeds for any selector. `validateTransfer` returns nothing, so
89
+ * there is no ABI decode to fail; a Safe (its `FallbackManager.fallback()` returns empty when no
90
+ * handler is set), an uninitialised proxy, and an EIP-7702-delegated EOA all pass a has-code check
91
+ * and then wave every transfer through. A creator pasting their own Safe is the likely real case.
92
+ *
93
+ * So the probe inverts the question: a real validator **reverts** here (verified against OpenSea's
94
+ * SATSR and three Limit Break deployments on mainnet and Sepolia), and a permissive one returns
95
+ * empty success. This mirrors the contract exactly — the same selector, the same "must fail" rule —
96
+ * so an address that passes here is an address the token will accept, and the CLI stops reporting
97
+ * "no code on this chain" for an address that plainly has code.
98
+ *
99
+ * An ERC-165 gate was measured and rejected: none of those four live validators advertises
100
+ * `ITransferValidator`/`ITransferValidator1155`, so requiring an id would refuse the entire
101
+ * ecosystem, including the validator ABX itself recommends.
102
+ *
103
+ * **A misconfiguration guard, not a security boundary** — a contract can always be written to pass
104
+ * this and enforce nothing. It catches the honest mistake. Never throws for an on-chain reason:
105
+ * every failure is a verdict (mirrors `probeSeedSource`).
106
+ */
107
+ export async function probeTransferValidator(client, validator,
108
+ /** The enrolling/enrolled token, when known — the probe is made as the token, because that is
109
+ * the `msg.sender` the contract's own staticcall presents. */
110
+ opts = {}) {
111
+ let code;
112
+ try {
113
+ code = await client.getCode({ address: validator });
114
+ }
115
+ catch (err) {
116
+ return { verdict: 'unreachable', address: validator, error: firstLine(err) };
117
+ }
118
+ if (!code || code === '0x')
119
+ return { verdict: 'no-code', address: validator };
120
+ try {
121
+ await client.call({
122
+ to: validator,
123
+ data: NOT_A_VALIDATOR_SELECTOR,
124
+ ...(opts.as ? { account: opts.as } : {}),
125
+ });
126
+ }
127
+ catch (err) {
128
+ // A revert is the PASS: this is what a real validator does with an unknown selector. A
129
+ // transport failure lands here too, so classify it rather than calling a broken RPC "ok".
130
+ return isTransportFailure(err)
131
+ ? { verdict: 'unreachable', address: validator, error: firstLine(err) }
132
+ : { verdict: 'ok', address: validator };
133
+ }
134
+ return { verdict: 'permissive-fallback', address: validator };
135
+ }
136
+ /** First line of an error message — a revert reason is readable; viem's full dump is not. */
137
+ function firstLine(err) {
138
+ return String(err?.message ?? err).split('\n')[0].trim();
139
+ }
140
+ /** Distinguish "the node said this call reverted" (a verdict) from "the node didn't answer" (retry).
141
+ * viem reports a revert as an execution error carrying revert data or the word itself; anything
142
+ * that never reached execution (timeout, socket, HTTP status, rate limit) must not read as a pass. */
143
+ function isTransportFailure(err) {
144
+ const name = err?.name ?? '';
145
+ const msg = String(err?.message ?? err);
146
+ if (/execution reverted|reverted with|revert reason|InvalidTransferValidator/i.test(msg))
147
+ return false;
148
+ return (/Timeout|Socket|Network|HttpRequest|Connection|RateLimit|InternalRpc|LimitExceeded/i.test(name) ||
149
+ /timed? out|timeout|socket hang up|ECONN|fetch failed|status code|too many requests|rate limit/i.test(msg));
150
+ }
68
151
  /**
69
152
  * Re-point an enrolled token's transfer validator, or suspend enforcement with
70
- * `zeroAddress` (the token stays enrolled). Signer must be the owner. Reverts
71
- * `NotCreatorToken()` on a token that didn't enroll at deploy — enrollment can never be
72
- * added later — and `InvalidTransferValidator()` on a non-zero validator with no code;
73
- * callers should read {@link readCreatorTokenStatus} first and refuse those before gas.
153
+ * `zeroAddress` (the token stays enrolled). Reverts `NotCreatorToken()` on a token that didn't
154
+ * enroll at deploy — enrollment can never be added later — and `InvalidTransferValidator()` on a
155
+ * validator the chain's own probe refuses (no code on this chain, **or** a permissive fallback that
156
+ * would enforce nothing); call {@link probeTransferValidator} first and refuse those before gas.
157
+ *
158
+ * **Who may sign:** the owner, while there is one. On a collection whose `owner()` is
159
+ * `address(0)`, **any** signer may send this with `validator = zeroAddress` to suspend enforcement
160
+ * permanently — the dead-man release described in this module's header. Arming a validator is still
161
+ * owner-only, so an ownerless collection can only move toward transferability, never back. A UX for
162
+ * collectors should offer that suspension when it sees a renounced, enforcing collection; gating it
163
+ * on `owner()` would hide the one recovery a stranded holder has.
74
164
  */
75
165
  export function prepareSetTransferValidator(args) {
76
166
  const suspending = args.validator === zeroAddress;
@@ -1 +1 @@
1
- {"version":3,"file":"creator-token.js","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAkC,MAAM,MAAM,CAAC;AACtF,OAAO,EAAC,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AAGhD,0FAA0F;AAC1F,MAAM,CAAC,MAAM,0BAA0B,GAAG,YAAqB,CAAC;AAChE,qFAAqF;AACrF,MAAM,CAAC,MAAM,iCAAiC,GAAG,YAAqB,CAAC;AACvE,iGAAiG;AACjG,MAAM,CAAC,MAAM,0BAA0B,GACrC,oEAA6E,CAAC;AAEhF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAA4B;IACrE,oBAAoB;IACpB,QAAQ,EAAE,4CAA4C;IACtD,yBAAyB;IACzB,KAAK,EAAE,4CAA4C;CACpD,CAAC;AAEF,4FAA4F;AAC5F,MAAM,UAAU,mCAAmC,CAAC,OAAe;IACjE,OAAO,8BAA8B,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC;AAUD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAoB,EACpB,QAAiB;IAEjB,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9C,MAAM;aACH,YAAY,CAAC;YACZ,OAAO,EAAE,QAAQ;YACjB,GAAG,EAAE,gBAAgB;YACrB,YAAY,EAAE,mBAAmB;YACjC,IAAI,EAAE,CAAC,0BAA0B,CAAC;SACnC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAqB;QACzC,MAAM;aACH,YAAY,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,gBAAgB,EAAE,YAAY,EAAE,sBAAsB,EAAC,CAAC;aAC9F,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,CAAqB;KAChD,CAAC,CAAC;IACH,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAC,CAAC;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAI3C;IACC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,KAAK,WAAW,CAAC;IAClD,OAAO;QACL,EAAE,EAAE,wBAAwB;QAC5B,EAAE,EAAE,IAAI,CAAC,QAAQ;QACjB,IAAI,EAAE,kBAAkB,CAAC;YACvB,GAAG,EAAE,gBAAgB;YACrB,YAAY,EAAE,sBAAsB;YACpC,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;SACvB,CAAC;QACF,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO,EAAE,UAAU;YACjB,CAAC,CAAC,mFAAmF;YACrF,CAAC,CAAC,qCAAqC,IAAI,CAAC,SAAS,EAAE;QACzD,MAAM,EAAE,EAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAC;KAC7D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"creator-token.js","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import type { Address, Hex } from 'viem';
2
+ export type CreatorOperationState = 'prepared' | 'submitting' | 'pending' | 'confirmed' | 'failed' | 'unknown';
3
+ export interface CreatorWallet {
4
+ address: Address;
5
+ provider: 'privy';
6
+ /** Public Privy application identifier used for the creator's device authorization. */
7
+ providerAppId: string;
8
+ }
9
+ export interface CreatorAccount {
10
+ accountId: string;
11
+ emailVerified: boolean;
12
+ wallet: CreatorWallet | null;
13
+ capabilities: {
14
+ wallet: boolean;
15
+ sponsorship: boolean;
16
+ sponsoredChains: number[];
17
+ };
18
+ }
19
+ export interface CreatorOperation {
20
+ operationId: string;
21
+ chainId: number;
22
+ walletId: string;
23
+ state: CreatorOperationState;
24
+ providerTransactionId: string | null;
25
+ transactionHash: Hex | null;
26
+ userOperationHash: Hex | null;
27
+ errorCode: string | null;
28
+ updatedAt: string;
29
+ }
30
+ export interface CreatorSigningRequest {
31
+ walletId: string;
32
+ idempotencyKey: string;
33
+ requestExpiry: string;
34
+ body: Record<string, unknown>;
35
+ }
36
+ export interface CreatorPreparedOperation {
37
+ operation: CreatorOperation;
38
+ signingRequest: CreatorSigningRequest;
39
+ }
40
+ export interface CreatorApiClientOptions {
41
+ /** Explicit provider endpoint, normally resolved from `abx-creator-wallet/v1` in its remote descriptor. */
42
+ baseUrl: string;
43
+ token: string;
44
+ fetchImpl?: typeof fetch;
45
+ timeoutMs?: number;
46
+ }
47
+ export declare class CreatorApiError extends Error {
48
+ readonly code: string;
49
+ readonly status: number;
50
+ constructor(code: string, status: number);
51
+ }
52
+ /** Account/wallet API client. It never receives a wallet key or authorization token. */
53
+ export declare class CreatorApiClient {
54
+ #private;
55
+ constructor(options: CreatorApiClientOptions);
56
+ account(): Promise<CreatorAccount>;
57
+ provisionWallet(): Promise<CreatorWallet & {
58
+ created: boolean;
59
+ }>;
60
+ prepare(input: {
61
+ operationId: string;
62
+ chainId: number;
63
+ /** Sponsored operations are calls; custom-contract deployment targets the CREATE2 proxy. */
64
+ to: Address;
65
+ value: Hex;
66
+ data: Hex;
67
+ gasLimit: number;
68
+ }): Promise<CreatorPreparedOperation>;
69
+ submit(operationId: string, input: {
70
+ requestExpiry: string;
71
+ data: Hex;
72
+ signed: {
73
+ url: string;
74
+ headers: Record<string, string>;
75
+ };
76
+ }): Promise<CreatorOperation>;
77
+ getOperation(operationId: string): Promise<CreatorOperation>;
78
+ }
79
+ //# sourceMappingURL=creators-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"creators-service.d.ts","sourceRoot":"","sources":["../src/creators-service.ts"],"names":[],"mappings":"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"}