@zoralabs/protocol-sdk 0.3.5 → 0.4.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.
@@ -9,19 +9,21 @@ import {
9
9
  zoraCreator1155FactoryImplConfig,
10
10
  } from "@zoralabs/protocol-deployments";
11
11
 
12
+ import {
13
+ premintTypedDataDefinition,
14
+ isValidSignature,
15
+ recoverCreatorFromCreatorAttribution,
16
+ getPremintExecutorAddress,
17
+ } from "./preminter";
12
18
  import {
13
19
  ContractCreationConfig,
14
20
  PremintConfigV1,
15
21
  TokenCreationConfigV1,
16
- premintTypedDataDefinition,
17
- isValidSignature,
18
22
  PremintConfigVersion,
19
23
  TokenCreationConfigV2,
20
24
  PremintConfigV2,
21
25
  MintArguments,
22
- recoverCreatorFromCreatorAttribution,
23
- getPremintExecutorAddress,
24
- } from "./preminter";
26
+ } from "./contract-types";
25
27
  import { AnvilViemClientsTest, forkUrls, makeAnvilTest } from "src/anvil";
26
28
 
27
29
  // create token and contract creation config:
@@ -105,7 +107,7 @@ const ZORA_MINT_FEE = parseEther("0.000777");
105
107
  const PREMINTER_ADDRESS = getPremintExecutorAddress();
106
108
 
107
109
  const anvilTest = makeAnvilTest({
108
- forkUrl: forkUrls.zoraSepoli,
110
+ forkUrl: forkUrls.zoraSepolia,
109
111
  forkBlockNumber: 1265490,
110
112
  });
111
113
 
@@ -238,7 +240,7 @@ describe("ZoraCreator1155Preminter", () => {
238
240
  20 * 1000,
239
241
  );
240
242
  makeAnvilTest({
241
- forkUrl: forkUrls.zoraSepoli,
243
+ forkUrl: forkUrls.zoraSepolia,
242
244
  forkBlockNumber: 1262991,
243
245
  })(
244
246
  "can sign and recover a v2 premint config signature",
@@ -1,5 +1,4 @@
1
1
  import { Address } from "abitype";
2
- import { ExtractAbiFunction, AbiParametersToPrimitiveTypes } from "abitype";
3
2
  import {
4
3
  zoraCreator1155PremintExecutorImplABI as preminterAbi,
5
4
  zoraCreator1155ImplABI,
@@ -18,102 +17,19 @@ import {
18
17
  recoverAddress,
19
18
  GetEventArgs,
20
19
  } from "viem";
21
-
22
- type PremintV1Inputs = ExtractAbiFunction<
23
- typeof preminterAbi,
24
- "premintV1"
25
- >["inputs"];
26
-
27
- type PremintV1HashDataTypes = AbiParametersToPrimitiveTypes<PremintV1Inputs>;
28
-
29
- export type ContractCreationConfig = PremintV1HashDataTypes[0];
30
-
31
- export type PremintConfigV1 = PremintV1HashDataTypes[1];
32
- export type TokenCreationConfigV1 = PremintConfigV1["tokenConfig"];
33
-
34
- export type MintArguments = PremintV1HashDataTypes[4];
35
-
36
- type PremintV2Inputs = ExtractAbiFunction<
37
- typeof preminterAbi,
38
- "premintV2"
39
- >["inputs"];
40
-
41
- type PremintV2HashDataTypes = AbiParametersToPrimitiveTypes<PremintV2Inputs>;
42
-
43
- export type PremintConfigV2 = PremintV2HashDataTypes[1];
44
- export type TokenCreationConfigV2 = PremintConfigV2["tokenConfig"];
45
-
46
- const v1Types = {
47
- CreatorAttribution: [
48
- { name: "tokenConfig", type: "TokenCreationConfig" },
49
- // unique id scoped to the contract and token to create.
50
- // ensure that a signature can be replaced, as long as the replacement
51
- // has the same uid, and a newer version.
52
- { name: "uid", type: "uint32" },
53
- { name: "version", type: "uint32" },
54
- // if this update should result in the signature being deleted.
55
- { name: "deleted", type: "bool" },
56
- ],
57
- TokenCreationConfig: [
58
- { name: "tokenURI", type: "string" },
59
- { name: "maxSupply", type: "uint256" },
60
- { name: "maxTokensPerAddress", type: "uint64" },
61
- { name: "pricePerToken", type: "uint96" },
62
- { name: "mintStart", type: "uint64" },
63
- { name: "mintDuration", type: "uint64" },
64
- { name: "royaltyMintSchedule", type: "uint32" },
65
- { name: "royaltyBPS", type: "uint32" },
66
- { name: "royaltyRecipient", type: "address" },
67
- { name: "fixedPriceMinter", type: "address" },
68
- ],
69
- } as const;
70
-
71
- const v2Types = {
72
- CreatorAttribution: [
73
- { name: "tokenConfig", type: "TokenCreationConfig" },
74
- // unique id scoped to the contract and token to create.
75
- // ensure that a signature can be replaced, as long as the replacement
76
- // has the same uid, and a newer version.
77
- { name: "uid", type: "uint32" },
78
- { name: "version", type: "uint32" },
79
- // if this update should result in the signature being deleted.
80
- { name: "deleted", type: "bool" },
81
- ],
82
- TokenCreationConfig: [
83
- { name: "tokenURI", type: "string" },
84
- { name: "maxSupply", type: "uint256" },
85
- { name: "maxTokensPerAddress", type: "uint64" },
86
- { name: "pricePerToken", type: "uint96" },
87
- { name: "mintStart", type: "uint64" },
88
- { name: "mintDuration", type: "uint64" },
89
- { name: "royaltyBPS", type: "uint32" },
90
- { name: "payoutRecipient", type: "address" },
91
- { name: "fixedPriceMinter", type: "address" },
92
- { name: "createReferral", type: "address" },
93
- ],
94
- } as const;
95
-
96
- export const PreminterDomain = "Preminter";
97
-
98
- type PremintConfigVersion = "1" | "2";
99
-
100
- export const PremintConfigVersion = {
101
- V1: "1",
102
- V2: "2",
103
- } as const;
104
-
105
- type PremintConfigForVersion<T extends PremintConfigVersion> = T extends "1"
106
- ? PremintConfigV1
107
- : PremintConfigV2;
108
-
109
- type PremintConfigWithVersion<T extends PremintConfigVersion> = {
110
- premintConfig: PremintConfigForVersion<T>;
111
- premintConfigVersion: T;
112
- };
113
-
114
- export type PremintConfigAndVersion =
115
- | PremintConfigWithVersion<"1">
116
- | PremintConfigWithVersion<"2">;
20
+ import {
21
+ ContractCreationConfig,
22
+ PremintConfig,
23
+ PremintConfigForTokenCreationConfig,
24
+ PremintConfigV1,
25
+ PremintConfigV2,
26
+ PremintConfigVersion,
27
+ PremintConfigWithVersion,
28
+ PreminterDomain,
29
+ TokenCreationConfig,
30
+ v1Types,
31
+ v2Types,
32
+ } from "./contract-types";
117
33
 
118
34
  export const getPremintExecutorAddress = () =>
119
35
  zoraCreator1155PremintExecutorImplAddress[999];
@@ -127,7 +43,7 @@ export const getPremintExecutorAddress = () =>
127
43
  * @param params.premintConfig the premint config
128
44
  * @returns
129
45
  */
130
- export const premintTypedDataDefinition = ({
46
+ export const premintTypedDataDefinition = <T extends PremintConfigVersion>({
131
47
  verifyingContract,
132
48
  chainId,
133
49
  premintConfigVersion: version,
@@ -135,7 +51,7 @@ export const premintTypedDataDefinition = ({
135
51
  }: {
136
52
  verifyingContract: Address;
137
53
  chainId: number;
138
- } & PremintConfigAndVersion): TypedDataDefinition => {
54
+ } & PremintConfigWithVersion<T>): TypedDataDefinition => {
139
55
  const domain = {
140
56
  chainId,
141
57
  name: PreminterDomain,
@@ -147,14 +63,14 @@ export const premintTypedDataDefinition = ({
147
63
  return {
148
64
  domain,
149
65
  types: v1Types,
150
- message: premintConfig,
66
+ message: premintConfig as PremintConfigV1,
151
67
  primaryType: "CreatorAttribution",
152
68
  } satisfies TypedDataDefinition<typeof v1Types, "CreatorAttribution">;
153
69
  if (version === PremintConfigVersion.V2) {
154
70
  return {
155
71
  domain,
156
72
  types: v2Types,
157
- message: premintConfig,
73
+ message: premintConfig as PremintConfigV2,
158
74
  primaryType: "CreatorAttribution",
159
75
  } satisfies TypedDataDefinition<typeof v2Types, "CreatorAttribution">;
160
76
  }
@@ -167,7 +83,9 @@ export type IsValidSignatureReturn = {
167
83
  recoveredAddress?: Address;
168
84
  };
169
85
 
170
- export async function isAuthorizedToCreatePremint({
86
+ export async function isAuthorizedToCreatePremint<
87
+ T extends PremintConfigVersion,
88
+ >({
171
89
  collection,
172
90
  collectionAddress,
173
91
  publicClient,
@@ -181,7 +99,7 @@ export async function isAuthorizedToCreatePremint({
181
99
  publicClient: PublicClient;
182
100
  signature: Hex;
183
101
  signer: Address;
184
- } & PremintConfigAndVersion) {
102
+ } & PremintConfigWithVersion<T>) {
185
103
  // if we are using legacy version of premint config, we can use the function
186
104
  // "isValidSignature" which we know exists on the premint executor contract
187
105
  if (premintConfigVersion === PremintConfigVersion.V1) {
@@ -189,7 +107,7 @@ export async function isAuthorizedToCreatePremint({
189
107
  abi: zoraCreator1155PremintExecutorImplABI,
190
108
  address: getPremintExecutorAddress(),
191
109
  functionName: "isValidSignature",
192
- args: [collection, premintConfig, signature],
110
+ args: [collection, premintConfig as PremintConfigV1, signature],
193
111
  });
194
112
 
195
113
  return isValidSignature;
@@ -204,14 +122,14 @@ export async function isAuthorizedToCreatePremint({
204
122
  });
205
123
  }
206
124
 
207
- export async function recoverPremintSigner({
125
+ export async function recoverPremintSigner<T extends PremintConfigVersion>({
208
126
  signature,
209
127
  ...rest
210
128
  }: {
211
129
  signature: Hex;
212
130
  chainId: number;
213
131
  verifyingContract: Address;
214
- } & PremintConfigAndVersion): Promise<Address> {
132
+ } & PremintConfigWithVersion<T>): Promise<Address> {
215
133
  const typedData = premintTypedDataDefinition(rest);
216
134
  return await recoverTypedDataAddress({
217
135
  ...typedData,
@@ -241,7 +159,7 @@ export async function tryRecoverPremintSigner(
241
159
  * @param params.tokenContract the address of the 1155 contract
242
160
  * @returns
243
161
  */
244
- export async function isValidSignature({
162
+ export async function isValidSignature<T extends PremintConfigVersion>({
245
163
  signature,
246
164
  publicClient,
247
165
  collection,
@@ -252,7 +170,7 @@ export async function isValidSignature({
252
170
  signature: Hex;
253
171
  chainId: number;
254
172
  publicClient: PublicClient;
255
- } & PremintConfigAndVersion): Promise<IsValidSignatureReturn> {
173
+ } & PremintConfigWithVersion<T>): Promise<IsValidSignatureReturn> {
256
174
  const tokenContract = await getPremintCollectionAddress({
257
175
  collection,
258
176
  publicClient,
@@ -375,22 +293,41 @@ export const recoverCreatorFromCreatorAttribution = async ({
375
293
  });
376
294
  };
377
295
 
296
+ export const supportedPremintVersions = async ({
297
+ tokenContract,
298
+ publicClient,
299
+ }: {
300
+ tokenContract: Address;
301
+ publicClient: PublicClient;
302
+ }): Promise<readonly string[]> => {
303
+ try {
304
+ return await publicClient.readContract({
305
+ abi: preminterAbi,
306
+ address: getPremintExecutorAddress(),
307
+ functionName: "supportedPremintSignatureVersions",
308
+ args: [tokenContract],
309
+ });
310
+ } catch (e) {
311
+ console.error(e);
312
+ // if the premint executor contract doesn't support the function, it must be v1
313
+ return ["1"];
314
+ }
315
+ };
378
316
  /**
379
317
  * Checks if the 1155 contract at that address supports the given version of the premint config.
380
318
  */
381
- export const supportsPremintVersion = async (
382
- version: PremintConfigVersion,
383
- tokenContract: Address,
384
- publicClient: PublicClient,
385
- ): Promise<boolean> => {
386
- const supportedPremintSignatureVersions = await publicClient.readContract({
387
- abi: preminterAbi,
388
- address: getPremintExecutorAddress(),
389
- functionName: "supportedPremintSignatureVersions",
390
- args: [tokenContract],
391
- });
392
-
393
- return supportedPremintSignatureVersions.includes(version);
319
+ export const supportsPremintVersion = async ({
320
+ version,
321
+ tokenContract,
322
+ publicClient,
323
+ }: {
324
+ version: PremintConfigVersion;
325
+ tokenContract: Address;
326
+ publicClient: PublicClient;
327
+ }): Promise<boolean> => {
328
+ return (
329
+ await supportedPremintVersions({ tokenContract, publicClient })
330
+ ).includes(version);
394
331
  };
395
332
 
396
333
  export async function getPremintCollectionAddress({
@@ -407,3 +344,52 @@ export async function getPremintCollectionAddress({
407
344
  args: [collection],
408
345
  });
409
346
  }
347
+
348
+ export function markPremintDeleted<T extends PremintConfig>(
349
+ premintConfig: T,
350
+ ): T {
351
+ return {
352
+ ...premintConfig,
353
+ version: premintConfig.version + 1,
354
+ deleted: true,
355
+ };
356
+ }
357
+
358
+ export function applyUpdateToPremint({
359
+ uid,
360
+ version,
361
+ tokenConfig,
362
+ tokenConfigUpdates,
363
+ }: {
364
+ tokenConfig: TokenCreationConfig;
365
+ tokenConfigUpdates: Partial<TokenCreationConfig>;
366
+ } & Pick<PremintConfig, "uid" | "version">): PremintConfig {
367
+ const updatedTokenConfig: TokenCreationConfig = {
368
+ ...tokenConfig,
369
+ ...tokenConfigUpdates,
370
+ } as const;
371
+
372
+ const result = {
373
+ deleted: false,
374
+ uid,
375
+ version: version + 1,
376
+ tokenConfig: updatedTokenConfig,
377
+ } as PremintConfig;
378
+
379
+ return result;
380
+ }
381
+
382
+ export function makeNewPremint<T extends TokenCreationConfig>({
383
+ tokenConfig,
384
+ uid,
385
+ }: {
386
+ tokenConfig: T;
387
+ uid: number;
388
+ }): PremintConfigForTokenCreationConfig<T> {
389
+ return {
390
+ deleted: false,
391
+ uid,
392
+ version: 0,
393
+ tokenConfig,
394
+ } as PremintConfigForTokenCreationConfig<T>;
395
+ }