@zoralabs/protocol-sdk 0.2.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 (70) hide show
  1. package/.turbo/turbo-build.log +15 -0
  2. package/CHANGELOG.md +47 -0
  3. package/README.md +163 -0
  4. package/dist/anvil.d.ts +16 -0
  5. package/dist/anvil.d.ts.map +1 -0
  6. package/dist/apis/chain-constants.d.ts +21 -0
  7. package/dist/apis/chain-constants.d.ts.map +1 -0
  8. package/dist/apis/client-base.d.ts +15 -0
  9. package/dist/apis/client-base.d.ts.map +1 -0
  10. package/dist/apis/generated/discover-api-types.d.ts +2131 -0
  11. package/dist/apis/generated/discover-api-types.d.ts.map +1 -0
  12. package/dist/apis/generated/premint-api-types.d.ts +356 -0
  13. package/dist/apis/generated/premint-api-types.d.ts.map +1 -0
  14. package/dist/apis/http-api-base.d.ts +26 -0
  15. package/dist/apis/http-api-base.d.ts.map +1 -0
  16. package/dist/constants.d.ts +4 -0
  17. package/dist/constants.d.ts.map +1 -0
  18. package/dist/create/1155-create-helper.d.ts +63 -0
  19. package/dist/create/1155-create-helper.d.ts.map +1 -0
  20. package/dist/create/1155-create-helper.test.d.ts +2 -0
  21. package/dist/create/1155-create-helper.test.d.ts.map +1 -0
  22. package/dist/index.cjs +1006 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +984 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/mint/mint-api-client.d.ts +20 -0
  29. package/dist/mint/mint-api-client.d.ts.map +1 -0
  30. package/dist/mint/mint-client.d.ts +237 -0
  31. package/dist/mint/mint-client.d.ts.map +1 -0
  32. package/dist/mint/mint-client.test.d.ts +2 -0
  33. package/dist/mint/mint-client.test.d.ts.map +1 -0
  34. package/dist/premint/premint-api-client.d.ts +19 -0
  35. package/dist/premint/premint-api-client.d.ts.map +1 -0
  36. package/dist/premint/premint-client.d.ts +320 -0
  37. package/dist/premint/premint-client.d.ts.map +1 -0
  38. package/dist/premint/premint-client.test.d.ts +2 -0
  39. package/dist/premint/premint-client.test.d.ts.map +1 -0
  40. package/dist/premint/preminter.d.ts +25 -0
  41. package/dist/premint/preminter.d.ts.map +1 -0
  42. package/dist/premint/preminter.test.d.ts +2 -0
  43. package/dist/premint/preminter.test.d.ts.map +1 -0
  44. package/dist/preminter.d.ts +25 -0
  45. package/dist/preminter.d.ts.map +1 -0
  46. package/dist/preminter.test.d.ts +451 -0
  47. package/dist/preminter.test.d.ts.map +1 -0
  48. package/package.json +28 -0
  49. package/src/anvil.ts +84 -0
  50. package/src/apis/chain-constants.ts +101 -0
  51. package/src/apis/client-base.ts +29 -0
  52. package/src/apis/generated/discover-api-types.ts +2138 -0
  53. package/src/apis/generated/premint-api-types.ts +363 -0
  54. package/src/apis/http-api-base.ts +93 -0
  55. package/src/constants.ts +10 -0
  56. package/src/create/1155-create-helper.test.ts +90 -0
  57. package/src/create/1155-create-helper.ts +342 -0
  58. package/src/index.ts +9 -0
  59. package/src/mint/mint-api-client.ts +52 -0
  60. package/src/mint/mint-client.test.ts +117 -0
  61. package/src/mint/mint-client.ts +218 -0
  62. package/src/premint/premint-api-client.ts +57 -0
  63. package/src/premint/premint-client.test.ts +196 -0
  64. package/src/premint/premint-client.ts +619 -0
  65. package/src/premint/preminter.test.ts +502 -0
  66. package/src/premint/preminter.ts +72 -0
  67. package/src/preminter.test.ts +510 -0
  68. package/src/preminter.ts +72 -0
  69. package/tsconfig.json +25 -0
  70. package/tsup.config.js +10 -0
package/dist/index.js ADDED
@@ -0,0 +1,984 @@
1
+ // src/premint/premint-client.ts
2
+ import { decodeEventLog } from "viem";
3
+ import {
4
+ zoraCreator1155PremintExecutorImplABI,
5
+ zoraCreator1155PremintExecutorImplAddress,
6
+ zoraCreatorFixedPriceSaleStrategyAddress
7
+ } from "@zoralabs/protocol-deployments";
8
+
9
+ // src/premint/preminter.ts
10
+ var preminterTypedDataDefinition = ({
11
+ verifyingContract,
12
+ premintConfig,
13
+ chainId
14
+ }) => {
15
+ const { tokenConfig, uid, version, deleted } = premintConfig;
16
+ const types = {
17
+ CreatorAttribution: [
18
+ { name: "tokenConfig", type: "TokenCreationConfig" },
19
+ // unique id scoped to the contract and token to create.
20
+ // ensure that a signature can be replaced, as long as the replacement
21
+ // has the same uid, and a newer version.
22
+ { name: "uid", type: "uint32" },
23
+ { name: "version", type: "uint32" },
24
+ // if this update should result in the signature being deleted.
25
+ { name: "deleted", type: "bool" }
26
+ ],
27
+ TokenCreationConfig: [
28
+ { name: "tokenURI", type: "string" },
29
+ { name: "maxSupply", type: "uint256" },
30
+ { name: "maxTokensPerAddress", type: "uint64" },
31
+ { name: "pricePerToken", type: "uint96" },
32
+ { name: "mintStart", type: "uint64" },
33
+ { name: "mintDuration", type: "uint64" },
34
+ { name: "royaltyMintSchedule", type: "uint32" },
35
+ { name: "royaltyBPS", type: "uint32" },
36
+ { name: "royaltyRecipient", type: "address" },
37
+ { name: "fixedPriceMinter", type: "address" }
38
+ ]
39
+ };
40
+ const result = {
41
+ domain: {
42
+ chainId,
43
+ name: "Preminter",
44
+ version: "1",
45
+ verifyingContract
46
+ },
47
+ types,
48
+ message: {
49
+ tokenConfig,
50
+ uid,
51
+ version,
52
+ deleted
53
+ },
54
+ primaryType: "CreatorAttribution"
55
+ };
56
+ return result;
57
+ };
58
+
59
+ // src/apis/http-api-base.ts
60
+ var BadResponseError = class extends Error {
61
+ constructor(message, status, json) {
62
+ super(message);
63
+ this.name = "BadResponseError";
64
+ this.status = status;
65
+ this.json = json;
66
+ }
67
+ };
68
+ async function wait(delayMs) {
69
+ return new Promise((resolve) => {
70
+ setTimeout(resolve, delayMs);
71
+ });
72
+ }
73
+ var get = async (url) => {
74
+ const response = await fetch(url, { method: "GET" });
75
+ if (response.status !== 200) {
76
+ let json;
77
+ try {
78
+ json = await response.json();
79
+ } catch (e) {
80
+ }
81
+ throw new BadResponseError(
82
+ `Invalid response, status ${response.status}`,
83
+ response.status,
84
+ json
85
+ );
86
+ }
87
+ return await response.json();
88
+ };
89
+ var post = async (url, data) => {
90
+ const response = await fetch(url, {
91
+ method: "POST",
92
+ headers: {
93
+ "content-type": "application/json",
94
+ accept: "application/json"
95
+ },
96
+ body: JSON.stringify(data)
97
+ });
98
+ if (response.status !== 200) {
99
+ let json;
100
+ try {
101
+ json = await response.json();
102
+ } catch (e) {
103
+ }
104
+ throw new BadResponseError(
105
+ `Bad response: ${response.status}`,
106
+ response.status,
107
+ json
108
+ );
109
+ }
110
+ return await response.json();
111
+ };
112
+ var retries = async (tryFn, maxTries = 3, atTry = 1, linearBackoffMS = 200) => {
113
+ try {
114
+ return await tryFn();
115
+ } catch (err) {
116
+ if (err instanceof BadResponseError) {
117
+ if (err.status >= 500) {
118
+ if (atTry <= maxTries) {
119
+ await wait(atTry * linearBackoffMS);
120
+ return await retries(tryFn, maxTries, atTry + 1);
121
+ }
122
+ }
123
+ }
124
+ throw err;
125
+ }
126
+ };
127
+
128
+ // src/constants.ts
129
+ var ZORA_API_BASE = "https://api.zora.co/";
130
+ var OPEN_EDITION_MINT_SIZE = BigInt("18446744073709551615");
131
+ var SUBGRAPH_CONFIG_BASE = "https://api.goldsky.com/api/public/project_clhk16b61ay9t49vm6ntn4mkz/subgraphs";
132
+ function getSubgraph(name, version) {
133
+ return `${SUBGRAPH_CONFIG_BASE}/${name}/${version}/gn`;
134
+ }
135
+
136
+ // src/premint/premint-api-client.ts
137
+ var postSignature = async (data) => retries(
138
+ () => post(`${ZORA_API_BASE}premint/signature`, data)
139
+ );
140
+ var getNextUID = async (path) => retries(
141
+ () => get(
142
+ `${ZORA_API_BASE}premint/signature/${path.chain_name}/${path.collection_address}/next_uid`
143
+ )
144
+ );
145
+ var getSignature = async (path) => retries(
146
+ () => get(
147
+ `${ZORA_API_BASE}premint/signature/${path.chain_name}/${path.collection_address}/${path.uid}`
148
+ )
149
+ );
150
+ var PremintAPIClient = {
151
+ postSignature,
152
+ getSignature,
153
+ getNextUID
154
+ };
155
+
156
+ // src/apis/client-base.ts
157
+ import { createPublicClient, http } from "viem";
158
+
159
+ // src/apis/chain-constants.ts
160
+ import {
161
+ base,
162
+ baseGoerli,
163
+ foundry,
164
+ goerli,
165
+ mainnet,
166
+ optimism,
167
+ optimismGoerli,
168
+ zora,
169
+ zoraTestnet
170
+ } from "viem/chains";
171
+ import { parseEther } from "viem";
172
+ var REWARD_PER_TOKEN = parseEther("0.000777");
173
+ var BackendChainNamesLookup = {
174
+ ZORA_MAINNET: "ZORA-MAINNET",
175
+ ZORA_GOERLI: "ZORA-GOERLI",
176
+ OPTIMISM_MAINNET: "OPTIMISM-MAINNET",
177
+ OPTIMISM_GOERLI: "OPTIMISM-GOERLI",
178
+ ETHEREUM_MAINNET: "ETHEREUM-MAINNET",
179
+ ETHEREUM_GOERLI: "ETHEREUM-GOERLI",
180
+ BASE_MAINNET: "BASE-MAINNET",
181
+ BASE_GOERLI: "BASE-GOERLI"
182
+ };
183
+ var networkConfigByChain = {
184
+ [mainnet.id]: {
185
+ chainId: mainnet.id,
186
+ isTestnet: false,
187
+ zoraPathChainName: "eth",
188
+ zoraBackendChainName: BackendChainNamesLookup.ETHEREUM_MAINNET,
189
+ subgraphUrl: getSubgraph("zora-create-mainnet", "stable")
190
+ },
191
+ [goerli.id]: {
192
+ chainId: goerli.id,
193
+ isTestnet: true,
194
+ zoraPathChainName: "gor",
195
+ zoraBackendChainName: BackendChainNamesLookup.ETHEREUM_GOERLI,
196
+ subgraphUrl: getSubgraph("zora-create-goerli", "stable")
197
+ },
198
+ [zora.id]: {
199
+ chainId: zora.id,
200
+ isTestnet: false,
201
+ zoraPathChainName: "zora",
202
+ zoraBackendChainName: BackendChainNamesLookup.ZORA_MAINNET,
203
+ subgraphUrl: getSubgraph("zora-create-zora-mainnet", "stable")
204
+ },
205
+ [zoraTestnet.id]: {
206
+ chainId: zora.id,
207
+ isTestnet: true,
208
+ zoraPathChainName: "zgor",
209
+ zoraBackendChainName: BackendChainNamesLookup.ZORA_GOERLI,
210
+ subgraphUrl: getSubgraph("zora-create-zora-testnet", "stable")
211
+ },
212
+ [optimism.id]: {
213
+ chainId: optimism.id,
214
+ isTestnet: false,
215
+ zoraPathChainName: "opt",
216
+ zoraBackendChainName: BackendChainNamesLookup.OPTIMISM_MAINNET,
217
+ subgraphUrl: getSubgraph("zora-create-optimism", "stable")
218
+ },
219
+ [optimismGoerli.id]: {
220
+ chainId: optimismGoerli.id,
221
+ isTestnet: true,
222
+ zoraPathChainName: "ogor",
223
+ zoraBackendChainName: BackendChainNamesLookup.OPTIMISM_GOERLI,
224
+ subgraphUrl: getSubgraph("zora-create-optimism-goerli", "stable")
225
+ },
226
+ [base.id]: {
227
+ chainId: base.id,
228
+ isTestnet: false,
229
+ zoraPathChainName: "base",
230
+ zoraBackendChainName: BackendChainNamesLookup.BASE_MAINNET,
231
+ subgraphUrl: getSubgraph("zora-create-base-mainnet", "stable")
232
+ },
233
+ [baseGoerli.id]: {
234
+ chainId: baseGoerli.id,
235
+ isTestnet: true,
236
+ zoraPathChainName: "bgor",
237
+ zoraBackendChainName: BackendChainNamesLookup.BASE_GOERLI,
238
+ subgraphUrl: getSubgraph("zora-create-base-goerli", "stable")
239
+ },
240
+ [foundry.id]: {
241
+ chainId: foundry.id,
242
+ isTestnet: true,
243
+ zoraPathChainName: "zgor",
244
+ zoraBackendChainName: BackendChainNamesLookup.ZORA_GOERLI,
245
+ subgraphUrl: getSubgraph("zora-create-zora-testnet", "stable")
246
+ }
247
+ };
248
+
249
+ // src/apis/client-base.ts
250
+ var ClientBase = class {
251
+ constructor(chain) {
252
+ this.chain = chain;
253
+ const networkConfig = networkConfigByChain[chain.id];
254
+ if (!networkConfig) {
255
+ throw new Error(`Not configured for chain ${chain.id}`);
256
+ }
257
+ this.network = networkConfig;
258
+ }
259
+ /**
260
+ * Getter for public client that instantiates a publicClient as needed
261
+ *
262
+ * @param publicClient Optional viem public client
263
+ * @returns Existing public client or makes a new one for the given chain as needed.
264
+ */
265
+ getPublicClient(publicClient) {
266
+ if (publicClient) {
267
+ return publicClient;
268
+ }
269
+ return createPublicClient({ chain: this.chain, transport: http() });
270
+ }
271
+ };
272
+
273
+ // src/premint/premint-client.ts
274
+ var DefaultMintArguments = {
275
+ maxSupply: OPEN_EDITION_MINT_SIZE,
276
+ maxTokensPerAddress: 0n,
277
+ pricePerToken: 0n,
278
+ mintDuration: BigInt(60 * 60 * 24 * 7),
279
+ // 1 week
280
+ mintStart: 0n,
281
+ royaltyMintSchedule: 0,
282
+ royaltyBPS: 1e3
283
+ // 10%,
284
+ };
285
+ function getPremintedLogFromReceipt(receipt) {
286
+ for (const data of receipt.logs) {
287
+ try {
288
+ const decodedLog = decodeEventLog({
289
+ abi: zoraCreator1155PremintExecutorImplABI,
290
+ eventName: "Preminted",
291
+ ...data
292
+ });
293
+ if (decodedLog.eventName === "Preminted") {
294
+ return decodedLog.args;
295
+ }
296
+ } catch (err) {
297
+ }
298
+ }
299
+ }
300
+ var convertPremint = (premint) => ({
301
+ ...premint,
302
+ tokenConfig: {
303
+ ...premint.tokenConfig,
304
+ fixedPriceMinter: premint.tokenConfig.fixedPriceMinter,
305
+ royaltyRecipient: premint.tokenConfig.royaltyRecipient,
306
+ maxSupply: BigInt(premint.tokenConfig.maxSupply),
307
+ pricePerToken: BigInt(premint.tokenConfig.pricePerToken),
308
+ mintStart: BigInt(premint.tokenConfig.mintStart),
309
+ mintDuration: BigInt(premint.tokenConfig.mintDuration),
310
+ maxTokensPerAddress: BigInt(premint.tokenConfig.maxTokensPerAddress)
311
+ }
312
+ });
313
+ var convertCollection = (collection) => ({
314
+ ...collection,
315
+ contractAdmin: collection.contractAdmin
316
+ });
317
+ var encodePremintForAPI = ({
318
+ tokenConfig,
319
+ ...premint
320
+ }) => ({
321
+ ...premint,
322
+ tokenConfig: {
323
+ ...tokenConfig,
324
+ maxSupply: tokenConfig.maxSupply.toString(),
325
+ pricePerToken: tokenConfig.pricePerToken.toString(),
326
+ mintStart: tokenConfig.mintStart.toString(),
327
+ mintDuration: tokenConfig.mintDuration.toString(),
328
+ maxTokensPerAddress: tokenConfig.maxTokensPerAddress.toString()
329
+ }
330
+ });
331
+ var PremintClient = class extends ClientBase {
332
+ constructor(chain, apiClient) {
333
+ super(chain);
334
+ if (!apiClient) {
335
+ apiClient = PremintAPIClient;
336
+ }
337
+ this.apiClient = apiClient;
338
+ }
339
+ /**
340
+ * The premint executor address is deployed to the same address across all chains.
341
+ * Can be overridden as needed by making a parent class.
342
+ *
343
+ * @returns Executor address for premints
344
+ */
345
+ getExecutorAddress() {
346
+ return zoraCreator1155PremintExecutorImplAddress[999];
347
+ }
348
+ /**
349
+ * The fixed price minter address is the same across all chains for our current
350
+ * deployer strategy.
351
+ * Can be overridden as needed by making a parent class.
352
+ *
353
+ * @returns Fixed price sale strategy
354
+ */
355
+ getFixedPriceMinterAddress() {
356
+ return zoraCreatorFixedPriceSaleStrategyAddress[999];
357
+ }
358
+ /**
359
+ * Update existing premint given collection address and UID of existing premint.
360
+ *
361
+ * 1. Loads existing premint token
362
+ * 2. Updates with settings passed into function
363
+ * 3. Increments the version field
364
+ * 4. Re-signs the premint
365
+ * 5. Uploads the premint to the ZORA API
366
+ *
367
+ * Updates existing premint
368
+ * @param settings Settings for the new premint
369
+ * @param settings.account Account to sign the premint update from. Taken from walletClient if none passed in.
370
+ * @param settings.collection Collection information for the mint
371
+ * @param settings.walletClient viem wallet client to use to sign
372
+ * @param settings.uid UID
373
+ * @param settings.token Mint argument settings, optional settings are overridden with sensible defaults.
374
+ *
375
+ */
376
+ async updatePremint({
377
+ walletClient,
378
+ uid,
379
+ collection,
380
+ token,
381
+ account
382
+ }) {
383
+ const signatureResponse = await this.apiClient.getSignature({
384
+ chain_name: this.network.zoraBackendChainName,
385
+ collection_address: collection.toLowerCase(),
386
+ uid
387
+ });
388
+ const convertedPremint = convertPremint(signatureResponse.premint);
389
+ const signerData = {
390
+ ...signatureResponse,
391
+ premint: {
392
+ ...convertedPremint,
393
+ tokenConfig: {
394
+ ...convertedPremint.tokenConfig,
395
+ ...token
396
+ }
397
+ }
398
+ };
399
+ return await this.signAndSubmitPremint({
400
+ walletClient,
401
+ account,
402
+ checkSignature: false,
403
+ verifyingContract: collection,
404
+ publicClient: this.getPublicClient(),
405
+ uid,
406
+ collection: {
407
+ ...signerData.collection,
408
+ contractAdmin: signerData.collection.contractAdmin
409
+ },
410
+ premintConfig: signerData.premint
411
+ });
412
+ }
413
+ /**
414
+ * Delete premint.
415
+ *
416
+ * 1. Loads current premint from collection address with UID
417
+ * 2. Increments version and marks as deleted
418
+ * 3. Signs new premint version
419
+ * 4. Sends to ZORA Premint API
420
+ *
421
+ * Deletes existing premint
422
+ * @param settings.collection collection address
423
+ * @param settings.uid UID
424
+ * @param settings.walletClient viem wallet client to use to sign
425
+ *
426
+ */
427
+ async deletePremint({
428
+ walletClient,
429
+ uid,
430
+ account,
431
+ collection,
432
+ publicClient
433
+ }) {
434
+ const signatureResponse = await this.apiClient.getSignature({
435
+ chain_name: this.network.zoraBackendChainName,
436
+ collection_address: collection.toLowerCase(),
437
+ uid
438
+ });
439
+ const signerData = {
440
+ ...signatureResponse,
441
+ collection: convertCollection(signatureResponse.collection),
442
+ premint: {
443
+ ...convertPremint(signatureResponse.premint),
444
+ deleted: true
445
+ }
446
+ };
447
+ return await this.signAndSubmitPremint({
448
+ walletClient,
449
+ account,
450
+ checkSignature: false,
451
+ verifyingContract: collection,
452
+ publicClient: this.getPublicClient(publicClient),
453
+ uid,
454
+ collection: signerData.collection,
455
+ premintConfig: signerData.premint
456
+ });
457
+ }
458
+ /**
459
+ * Internal function to sign and submit a premint request.
460
+ *
461
+ * @param premintArguments Arguments to premint
462
+ * @returns
463
+ */
464
+ async signAndSubmitPremint({
465
+ walletClient,
466
+ publicClient,
467
+ verifyingContract,
468
+ premintConfig,
469
+ uid,
470
+ account,
471
+ checkSignature,
472
+ collection
473
+ }) {
474
+ if (!account) {
475
+ account = walletClient.account;
476
+ }
477
+ if (!account) {
478
+ throw new Error("No account provided");
479
+ }
480
+ const signature = await walletClient.signTypedData({
481
+ account,
482
+ ...preminterTypedDataDefinition({
483
+ verifyingContract,
484
+ premintConfig,
485
+ chainId: this.chain.id
486
+ })
487
+ });
488
+ if (checkSignature) {
489
+ const [isValidSignature] = await publicClient.readContract({
490
+ abi: zoraCreator1155PremintExecutorImplABI,
491
+ address: this.getExecutorAddress(),
492
+ functionName: "isValidSignature",
493
+ args: [convertCollection(collection), premintConfig, signature]
494
+ });
495
+ if (!isValidSignature) {
496
+ throw new Error("Invalid signature");
497
+ }
498
+ }
499
+ const apiData = {
500
+ collection,
501
+ premint: encodePremintForAPI(premintConfig),
502
+ chain_name: this.network.zoraBackendChainName,
503
+ signature
504
+ };
505
+ const premint = await this.apiClient.postSignature(apiData);
506
+ return {
507
+ urls: this.makeUrls({ address: verifyingContract, uid }),
508
+ uid,
509
+ verifyingContract,
510
+ premint
511
+ };
512
+ }
513
+ /**
514
+ * Create premint
515
+ *
516
+ * @param settings Settings for the new premint
517
+ * @param settings.account Account to sign the premint with. Taken from walletClient if none passed in.
518
+ * @param settings.collection Collection information for the mint
519
+ * @param settings.token Mint argument settings, optional settings are overridden with sensible defaults.
520
+ * @param settings.publicClient Public client (optional) – instantiated if not passed in with defaults.
521
+ * @param settings.walletClient Required wallet client for signing the premint message.
522
+ * @param settings.executionSettings Execution settings for premint options
523
+ * @param settings.executionSettings.deleted If this UID should be deleted. If omitted, set to false.
524
+ * @param settings.executionSettings.uid the UID to use – optional and retrieved as a fresh UID from ZORA by default.
525
+ * @param settings.checkSignature if the signature should have a pre-flight check. Not required but helpful for debugging.
526
+ * @returns premint url, uid, newContractAddress, and premint object
527
+ */
528
+ async createPremint({
529
+ account,
530
+ collection,
531
+ token,
532
+ publicClient,
533
+ walletClient,
534
+ executionSettings,
535
+ checkSignature = false
536
+ }) {
537
+ publicClient = this.getPublicClient(publicClient);
538
+ const newContractAddress = await publicClient.readContract({
539
+ address: this.getExecutorAddress(),
540
+ abi: zoraCreator1155PremintExecutorImplABI,
541
+ functionName: "getContractAddress",
542
+ args: [convertCollection(collection)]
543
+ });
544
+ const tokenConfig = {
545
+ ...DefaultMintArguments,
546
+ fixedPriceMinter: this.getFixedPriceMinterAddress(),
547
+ royaltyRecipient: account,
548
+ ...token
549
+ };
550
+ let uid = executionSettings?.uid;
551
+ if (!uid) {
552
+ const uidResponse = await this.apiClient.getNextUID({
553
+ chain_name: this.network.zoraBackendChainName,
554
+ collection_address: newContractAddress.toLowerCase()
555
+ });
556
+ uid = uidResponse.next_uid;
557
+ }
558
+ if (!uid) {
559
+ throw new Error("UID is missing but required");
560
+ }
561
+ let deleted = executionSettings?.deleted || false;
562
+ const premintConfig = {
563
+ tokenConfig,
564
+ uid,
565
+ version: 1,
566
+ deleted
567
+ };
568
+ return await this.signAndSubmitPremint({
569
+ uid,
570
+ verifyingContract: newContractAddress,
571
+ premintConfig,
572
+ checkSignature,
573
+ account,
574
+ publicClient,
575
+ walletClient,
576
+ collection
577
+ });
578
+ }
579
+ /**
580
+ * Fetches given premint data from the ZORA API.
581
+ *
582
+ * @param address Address for the premint contract
583
+ * @param uid UID for the desired premint
584
+ * @returns PremintSignatureGetResponse of premint data from the API
585
+ */
586
+ async getPremintData({
587
+ address,
588
+ uid
589
+ }) {
590
+ return await this.apiClient.getSignature({
591
+ chain_name: this.network.zoraBackendChainName,
592
+ collection_address: address,
593
+ uid
594
+ });
595
+ }
596
+ /**
597
+ * Check user signature for v1
598
+ *
599
+ * @param data Signature data from the API
600
+ * @returns isValid = signature is valid or not, contractAddress = assumed contract address, recoveredSigner = signer from contract
601
+ */
602
+ async isValidSignature({
603
+ data,
604
+ publicClient
605
+ }) {
606
+ publicClient = this.getPublicClient(publicClient);
607
+ const [isValid, contractAddress, recoveredSigner] = await publicClient.readContract({
608
+ abi: zoraCreator1155PremintExecutorImplABI,
609
+ address: this.getExecutorAddress(),
610
+ functionName: "isValidSignature",
611
+ args: [
612
+ convertCollection(data.collection),
613
+ convertPremint(data.premint),
614
+ data.signature
615
+ ]
616
+ });
617
+ return { isValid, contractAddress, recoveredSigner };
618
+ }
619
+ makeUrls({
620
+ uid,
621
+ address,
622
+ tokenId
623
+ }) {
624
+ if ((!uid || !tokenId) && !address) {
625
+ return { explorer: null, zoraCollect: null, zoraManage: null };
626
+ }
627
+ const zoraTokenPath = uid ? `premint-${uid}` : tokenId;
628
+ return {
629
+ explorer: tokenId ? `https://${this.chain.blockExplorers?.default.url}/token/${address}/instance/${tokenId}` : null,
630
+ zoraCollect: `https://${this.network.isTestnet ? "testnet." : ""}zora.co/collect/${this.network.zoraPathChainName}:${address}/${zoraTokenPath}`,
631
+ zoraManage: `https://${this.network.isTestnet ? "testnet." : ""}zora.co/collect/${this.network.zoraPathChainName}:${address}/${zoraTokenPath}`
632
+ };
633
+ }
634
+ /**
635
+ * Execute premint on-chain
636
+ *
637
+ * @param settings.data Data from the API for the mint
638
+ * @param settings.account Optional account (if omitted taken from wallet client) for the account executing the premint.
639
+ * @param settings.walletClient WalletClient to send execution from.
640
+ * @param settings.mintArguments User minting arguments.
641
+ * @param settings.mintArguments.quantityToMint Quantity to mint, optional, defaults to 1.
642
+ * @param settings.mintArguments.mintComment Optional mint comment, optional, omits when not included.
643
+ * @param settings.publicClient Optional public client for preflight checks.
644
+ * @returns receipt, log, zoraURL
645
+ */
646
+ async executePremintWithWallet({
647
+ data,
648
+ account,
649
+ walletClient,
650
+ mintArguments,
651
+ publicClient
652
+ }) {
653
+ publicClient = this.getPublicClient(publicClient);
654
+ if (mintArguments && mintArguments?.quantityToMint < 1) {
655
+ throw new Error("Quantity to mint cannot be below 1");
656
+ }
657
+ const targetAddress = this.getExecutorAddress();
658
+ const numberToMint = BigInt(mintArguments?.quantityToMint || 1);
659
+ const args = [
660
+ convertCollection(data.collection),
661
+ convertPremint(data.premint),
662
+ data.signature,
663
+ numberToMint,
664
+ mintArguments?.mintComment || ""
665
+ ];
666
+ if (!account) {
667
+ account = walletClient.account;
668
+ }
669
+ if (!account) {
670
+ throw new Error("Wallet not passed in");
671
+ }
672
+ const value = numberToMint * REWARD_PER_TOKEN;
673
+ const { request } = await publicClient.simulateContract({
674
+ account,
675
+ abi: zoraCreator1155PremintExecutorImplABI,
676
+ functionName: "premint",
677
+ value,
678
+ address: targetAddress,
679
+ args
680
+ });
681
+ const hash = await walletClient.writeContract(request);
682
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
683
+ const premintedLog = getPremintedLogFromReceipt(receipt);
684
+ return {
685
+ receipt,
686
+ premintedLog,
687
+ urls: this.makeUrls({
688
+ address: premintedLog?.contractAddress,
689
+ tokenId: premintedLog?.tokenId
690
+ })
691
+ };
692
+ }
693
+ };
694
+
695
+ // src/mint/mint-api-client.ts
696
+ function encodeQueryParameters(params) {
697
+ return new URLSearchParams(params).toString();
698
+ }
699
+ var getMintable = async (path, query) => retries(() => {
700
+ return get(
701
+ `${ZORA_API_BASE}discover/mintables/${path.chain_name}/${path.collection_address}${query?.token_id ? `?${encodeQueryParameters(query)}` : ""}`
702
+ );
703
+ });
704
+ var getSalesConfigFixedPrice = async ({
705
+ contractAddress,
706
+ tokenId,
707
+ subgraphUrl
708
+ }) => retries(async () => {
709
+ const response = await post(subgraphUrl, {
710
+ query: "query($id: ID!) {\n zoraCreateToken(id: $id) {\n id\n salesStrategies{\n fixedPrice {\n address\n }\n }\n }\n}",
711
+ variables: { id: `${contractAddress.toLowerCase()}-${tokenId}` }
712
+ });
713
+ return response.zoraCreateToken?.salesStrategies?.find(() => true)?.fixedPriceMinterAddress;
714
+ });
715
+ var MintAPIClient = {
716
+ getMintable,
717
+ getSalesConfigFixedPrice
718
+ };
719
+
720
+ // src/create/1155-create-helper.ts
721
+ import {
722
+ zoraCreator1155FactoryImplABI,
723
+ zoraCreator1155FactoryImplAddress,
724
+ zoraCreator1155ImplABI,
725
+ zoraCreatorFixedPriceSaleStrategyABI
726
+ } from "@zoralabs/protocol-deployments";
727
+ import { decodeEventLog as decodeEventLog2, encodeFunctionData, zeroAddress } from "viem";
728
+ var SALE_END_FOREVER = 18446744073709551615n;
729
+ var ROYALTY_BPS_DEFAULT = 1e3;
730
+ var DEFAULT_SALE_SETTINGS = {
731
+ fundsRecipient: zeroAddress,
732
+ // Free Mint
733
+ pricePerToken: 0n,
734
+ // Sale start time – defaults to beginning of unix time
735
+ saleStart: 0n,
736
+ // This is the end of uint64, plenty of time
737
+ saleEnd: SALE_END_FOREVER,
738
+ // 0 Here means no limit
739
+ maxTokensPerAddress: 0n
740
+ };
741
+ var PERMISSION_BIT_MINTER = 2n ** 2n;
742
+ function create1155TokenSetupArgs({
743
+ nextTokenId,
744
+ // How many NFTs upon initialization to mint to the creator
745
+ mintToCreatorCount,
746
+ tokenMetadataURI,
747
+ // Fixed price minter address – required minter
748
+ fixedPriceMinterAddress,
749
+ // Address to use as the create referral, optional.
750
+ createReferral,
751
+ // Optional max supply of the token. Default unlimited
752
+ maxSupply,
753
+ // wallet sending the transaction
754
+ account,
755
+ salesConfig,
756
+ royaltySettings
757
+ }) {
758
+ if (!maxSupply) {
759
+ maxSupply = OPEN_EDITION_MINT_SIZE;
760
+ }
761
+ maxSupply = BigInt(maxSupply);
762
+ mintToCreatorCount = BigInt(mintToCreatorCount);
763
+ const salesConfigWithDefaults = {
764
+ // Set static sales default.
765
+ ...DEFAULT_SALE_SETTINGS,
766
+ // Override with user settings.
767
+ ...salesConfig
768
+ };
769
+ const setupActions = [
770
+ encodeFunctionData({
771
+ abi: zoraCreator1155ImplABI,
772
+ functionName: "addPermission",
773
+ args: [0n, fixedPriceMinterAddress, PERMISSION_BIT_MINTER]
774
+ }),
775
+ encodeFunctionData({
776
+ abi: zoraCreator1155ImplABI,
777
+ functionName: "assumeLastTokenIdMatches",
778
+ args: [nextTokenId - 1n]
779
+ }),
780
+ createReferral ? encodeFunctionData({
781
+ abi: zoraCreator1155ImplABI,
782
+ functionName: "setupNewTokenWithCreateReferral",
783
+ args: [tokenMetadataURI, maxSupply, createReferral]
784
+ }) : encodeFunctionData({
785
+ abi: zoraCreator1155ImplABI,
786
+ functionName: "setupNewToken",
787
+ args: [tokenMetadataURI, maxSupply]
788
+ }),
789
+ encodeFunctionData({
790
+ abi: zoraCreator1155ImplABI,
791
+ functionName: "callSale",
792
+ args: [
793
+ nextTokenId,
794
+ fixedPriceMinterAddress,
795
+ encodeFunctionData({
796
+ abi: zoraCreatorFixedPriceSaleStrategyABI,
797
+ functionName: "setSale",
798
+ args: [nextTokenId, salesConfigWithDefaults]
799
+ })
800
+ ]
801
+ })
802
+ ];
803
+ if (mintToCreatorCount) {
804
+ setupActions.push(
805
+ encodeFunctionData({
806
+ abi: zoraCreator1155ImplABI,
807
+ functionName: "adminMint",
808
+ args: [account, nextTokenId, mintToCreatorCount, "0x"]
809
+ })
810
+ );
811
+ }
812
+ if (royaltySettings) {
813
+ setupActions.push(
814
+ encodeFunctionData({
815
+ abi: zoraCreator1155ImplABI,
816
+ functionName: "updateRoyaltiesForToken",
817
+ args: [
818
+ nextTokenId,
819
+ {
820
+ royaltyMintSchedule: 0,
821
+ royaltyBPS: royaltySettings?.royaltyBPS || ROYALTY_BPS_DEFAULT,
822
+ royaltyRecipient: royaltySettings?.royaltyRecipient || account
823
+ }
824
+ ]
825
+ })
826
+ );
827
+ }
828
+ return setupActions;
829
+ }
830
+ var getTokenIdFromCreateReceipt = (receipt) => {
831
+ for (const data of receipt.logs) {
832
+ try {
833
+ const decodedLog = decodeEventLog2({
834
+ abi: zoraCreator1155ImplABI,
835
+ eventName: "SetupNewToken",
836
+ ...data
837
+ });
838
+ if (decodedLog && decodedLog.eventName === "SetupNewToken") {
839
+ return decodedLog.args.tokenId;
840
+ }
841
+ } catch (err) {
842
+ }
843
+ }
844
+ };
845
+ async function getContractExists(publicClient, contract, account) {
846
+ let contractAddress;
847
+ let contractExists = false;
848
+ if (typeof contract !== "string") {
849
+ contractAddress = await publicClient.readContract({
850
+ abi: zoraCreator1155FactoryImplABI,
851
+ // Since this address is deterministic we can hardcode a chain id safely here.
852
+ address: zoraCreator1155FactoryImplAddress[999],
853
+ functionName: "deterministicContractAddress",
854
+ args: [
855
+ account,
856
+ contract.uri,
857
+ contract.name,
858
+ contract.defaultAdmin || account
859
+ ]
860
+ });
861
+ try {
862
+ await publicClient.readContract({
863
+ abi: zoraCreator1155ImplABI,
864
+ address: contractAddress,
865
+ functionName: "contractVersion"
866
+ });
867
+ contractExists = true;
868
+ } catch (e) {
869
+ }
870
+ return { contractAddress, contractExists };
871
+ }
872
+ return {
873
+ contractExists: true,
874
+ contractAddress: contract
875
+ };
876
+ }
877
+ async function createNew1155Token({
878
+ publicClient,
879
+ contract,
880
+ tokenMetadataURI,
881
+ mintToCreatorCount = 1,
882
+ salesConfig = {},
883
+ maxSupply,
884
+ account,
885
+ royaltySettings,
886
+ getAdditionalSetupActions
887
+ }) {
888
+ const { contractExists, contractAddress } = await getContractExists(
889
+ publicClient,
890
+ contract,
891
+ account
892
+ );
893
+ let nextTokenId = 1n;
894
+ if (contractExists) {
895
+ nextTokenId = await publicClient.readContract({
896
+ abi: zoraCreator1155ImplABI,
897
+ functionName: "nextTokenId",
898
+ address: contractAddress
899
+ });
900
+ }
901
+ const fixedPriceMinterAddress = await publicClient.readContract({
902
+ abi: zoraCreator1155FactoryImplABI,
903
+ address: zoraCreator1155FactoryImplAddress[999],
904
+ functionName: "fixedPriceMinter"
905
+ });
906
+ let tokenSetupActions = create1155TokenSetupArgs({
907
+ tokenMetadataURI,
908
+ nextTokenId,
909
+ salesConfig,
910
+ maxSupply,
911
+ fixedPriceMinterAddress,
912
+ account,
913
+ mintToCreatorCount,
914
+ royaltySettings
915
+ });
916
+ if (getAdditionalSetupActions) {
917
+ tokenSetupActions = [
918
+ ...getAdditionalSetupActions({ tokenId: nextTokenId, contractAddress }),
919
+ ...tokenSetupActions
920
+ ];
921
+ }
922
+ if (!contractAddress && typeof contract === "string") {
923
+ throw new Error("Invariant: contract cannot be missing and an address");
924
+ }
925
+ if (!contractExists && typeof contract !== "string") {
926
+ const { request } = await publicClient.simulateContract({
927
+ abi: zoraCreator1155FactoryImplABI,
928
+ functionName: "createContractDeterministic",
929
+ account,
930
+ address: zoraCreator1155FactoryImplAddress[999],
931
+ args: [
932
+ contract.uri,
933
+ contract.name,
934
+ {
935
+ // deprecated
936
+ royaltyMintSchedule: 0,
937
+ royaltyBPS: royaltySettings?.royaltyBPS || ROYALTY_BPS_DEFAULT,
938
+ royaltyRecipient: royaltySettings?.royaltyRecipient || account
939
+ },
940
+ contract.defaultAdmin || account,
941
+ tokenSetupActions
942
+ ]
943
+ });
944
+ return {
945
+ send: (walletClient) => walletClient.writeContract(request),
946
+ tokenSetupActions,
947
+ contractAddress,
948
+ contractExists
949
+ };
950
+ } else if (contractExists) {
951
+ const { request } = await publicClient.simulateContract({
952
+ abi: zoraCreator1155ImplABI,
953
+ functionName: "multicall",
954
+ account,
955
+ address: contractAddress,
956
+ args: [tokenSetupActions]
957
+ });
958
+ return {
959
+ send: (walletClient) => walletClient.writeContract(request),
960
+ tokenSetupActions,
961
+ contractAddress,
962
+ contractExists
963
+ };
964
+ }
965
+ throw new Error("Unsupported contract argument type");
966
+ }
967
+ export {
968
+ DEFAULT_SALE_SETTINGS,
969
+ DefaultMintArguments,
970
+ MintAPIClient,
971
+ PremintAPIClient,
972
+ PremintClient,
973
+ ZORA_API_BASE,
974
+ convertCollection,
975
+ convertPremint,
976
+ create1155TokenSetupArgs,
977
+ createNew1155Token,
978
+ encodePremintForAPI,
979
+ getPremintedLogFromReceipt,
980
+ getSalesConfigFixedPrice,
981
+ getTokenIdFromCreateReceipt,
982
+ preminterTypedDataDefinition
983
+ };
984
+ //# sourceMappingURL=index.js.map