@zoralabs/protocol-sdk 0.7.1 → 0.7.2-ALLOWLIST.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 (55) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/allow-list/allow-list-client.d.ts +25 -0
  3. package/dist/allow-list/allow-list-client.d.ts.map +1 -0
  4. package/dist/allow-list/types.d.ts +14 -0
  5. package/dist/allow-list/types.d.ts.map +1 -0
  6. package/dist/apis/generated/allow-list-api-types.d.ts +288 -0
  7. package/dist/apis/generated/allow-list-api-types.d.ts.map +1 -0
  8. package/dist/apis/http-api-base.d.ts.map +1 -1
  9. package/dist/create/1155-create-helper.d.ts +1 -0
  10. package/dist/create/1155-create-helper.d.ts.map +1 -1
  11. package/dist/create/token-setup.d.ts +3 -4
  12. package/dist/create/token-setup.d.ts.map +1 -1
  13. package/dist/create/types.d.ts +24 -4
  14. package/dist/create/types.d.ts.map +1 -1
  15. package/dist/index.cjs +219 -39
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +220 -40
  20. package/dist/index.js.map +1 -1
  21. package/dist/mint/mint-queries.d.ts +3 -1
  22. package/dist/mint/mint-queries.d.ts.map +1 -1
  23. package/dist/mint/mint-transactions.d.ts +5 -3
  24. package/dist/mint/mint-transactions.d.ts.map +1 -1
  25. package/dist/mint/subgraph-mint-getter.d.ts.map +1 -1
  26. package/dist/mint/subgraph-queries.d.ts +27 -13
  27. package/dist/mint/subgraph-queries.d.ts.map +1 -1
  28. package/dist/mint/types.d.ts +22 -11
  29. package/dist/mint/types.d.ts.map +1 -1
  30. package/package.json +2 -1
  31. package/src/allow-list/allow-list-client.ts +102 -0
  32. package/src/allow-list/types.ts +15 -0
  33. package/src/apis/generated/allow-list-api-types.ts +288 -0
  34. package/src/apis/http-api-base.ts +12 -0
  35. package/src/create/1155-create-helper.ts +17 -0
  36. package/src/create/token-setup.ts +116 -19
  37. package/src/create/types.ts +32 -4
  38. package/src/index.ts +4 -0
  39. package/src/mint/mint-queries.ts +6 -0
  40. package/src/mint/mint-transactions.ts +72 -6
  41. package/src/mint/subgraph-mint-getter.ts +12 -3
  42. package/src/mint/subgraph-queries.ts +39 -17
  43. package/src/mint/types.ts +38 -12
  44. package/yarn-error.log +8602 -0
  45. package/.turbo/turbo-build.log +0 -15
  46. package/src/create/1155-create-helper.test.ts +0 -325
  47. package/src/mint/mint-client.test.ts +0 -263
  48. package/src/mints/mints-contracts.test.ts +0 -529
  49. package/src/mints/mints-eth-unwrapper-and-caller.test.ts +0 -467
  50. package/src/mints/mints-queries.test.ts +0 -105
  51. package/src/premint/premint-client.test.ts +0 -290
  52. package/src/premint/preminter.test.ts +0 -866
  53. package/test-integration/setup-test-contracts.ts +0 -96
  54. package/tsconfig.build.json +0 -10
  55. package/tsup.config.ts +0 -12
@@ -49,6 +49,15 @@ export const get = async <T>(url: string) => {
49
49
  * @throws Error when HTTP response fails
50
50
  */
51
51
  export const post = async <T>(url: string, data: any) => {
52
+ const controller = new AbortController();
53
+ const { signal } = controller;
54
+
55
+ // 30 minute timeout:
56
+ const timeout = 30 * 60 * 1000;
57
+
58
+ // Set a timeout to automatically abort the request
59
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
60
+
52
61
  const response = await fetch(url, {
53
62
  method: "POST",
54
63
  headers: {
@@ -56,7 +65,10 @@ export const post = async <T>(url: string, data: any) => {
56
65
  accept: "application/json",
57
66
  },
58
67
  body: JSON.stringify(data),
68
+ signal,
59
69
  });
70
+
71
+ clearTimeout(timeoutId);
60
72
  if (response.status !== 200) {
61
73
  let json;
62
74
  try {
@@ -37,6 +37,23 @@ export const getTokenIdFromCreateReceipt = (
37
37
  }
38
38
  };
39
39
 
40
+ export const getContractAddressFromCreateReceipt = (
41
+ receipt: TransactionReceipt,
42
+ ): Address | undefined => {
43
+ for (const data of receipt.logs) {
44
+ try {
45
+ const decodedLog = decodeEventLog({
46
+ abi: zoraCreator1155FactoryImplABI,
47
+ eventName: "SetupNewContract",
48
+ ...data,
49
+ });
50
+ if (decodedLog && decodedLog.eventName === "SetupNewContract") {
51
+ return decodedLog.args.newContract;
52
+ }
53
+ } catch (err: any) {}
54
+ }
55
+ };
56
+
40
57
  type CreateNew1155TokenReturn = {
41
58
  parameters: SimulateContractParameters<
42
59
  any,
@@ -4,13 +4,17 @@ import {
4
4
  zoraCreator1155ImplABI,
5
5
  zoraCreatorFixedPriceSaleStrategyABI,
6
6
  zoraCreatorFixedPriceSaleStrategyAddress,
7
+ zoraCreatorMerkleMinterStrategyABI,
8
+ zoraCreatorMerkleMinterStrategyAddress,
7
9
  } from "@zoralabs/protocol-deployments";
8
10
  import { Address, encodeFunctionData, zeroAddress, Hex } from "viem";
9
11
  import * as semver from "semver";
10
12
  import {
13
+ AllowlistData,
11
14
  ContractProps,
12
15
  CreateNew1155TokenProps,
13
16
  New1155Token,
17
+ SalesConfigOrAllowList,
14
18
  SalesConfigParamsType,
15
19
  } from "./types";
16
20
  import { OPEN_EDITION_MINT_SIZE } from "src/constants";
@@ -24,16 +28,15 @@ type SetupMintersProps = {
24
28
  tokenId: bigint;
25
29
  chainId: number;
26
30
  fundsRecipient: Address;
27
- salesConfig: Concrete<SalesConfigParamsType>;
31
+ salesConfigOrAllowList: SalesConfigOrAllowList;
28
32
  };
29
33
 
30
34
  // Sales end forever amount (uint64 max)
35
+ const SALE_END_FOREVER = 18446744073709551615n;
31
36
 
32
37
  const saleSettingsOrDefault = (
33
38
  saleSettings?: SalesConfigParamsType,
34
39
  ): Concrete<SalesConfigParamsType> => {
35
- const SALE_END_FOREVER = 18446744073709551615n;
36
-
37
40
  const DEFAULT_SALE_SETTINGS: Concrete<SalesConfigParamsType> = {
38
41
  currency: zeroAddress,
39
42
  // Free Mint
@@ -51,6 +54,36 @@ const saleSettingsOrDefault = (
51
54
  };
52
55
  };
53
56
 
57
+ const allowListWithDefaults = (allowlist: AllowlistData) => {
58
+ const defaultAllowListSettings: Concrete<
59
+ Omit<AllowlistData, "presaleMerkleRoot">
60
+ > = {
61
+ // Sale start time – defaults to beginning of unix time
62
+ saleStart: 0n,
63
+ // This is the end of uint64, plenty of time
64
+ saleEnd: SALE_END_FOREVER,
65
+ };
66
+
67
+ return {
68
+ ...defaultAllowListSettings,
69
+ ...allowlist,
70
+ };
71
+ };
72
+
73
+ const getSalesConfigOrAllowListWithDefaults = ({
74
+ salesConfig,
75
+ allowlist,
76
+ }: Pick<CreateNew1155TokenProps, "salesConfig" | "allowlist">) => {
77
+ if (!allowlist) {
78
+ return {
79
+ salesConfig: saleSettingsOrDefault(salesConfig),
80
+ };
81
+ }
82
+ return {
83
+ allowlist: allowListWithDefaults(allowlist),
84
+ };
85
+ };
86
+
54
87
  function applyNew1155Defaults(
55
88
  props: CreateNew1155TokenProps,
56
89
  ownerAddress: Address,
@@ -68,8 +101,11 @@ function applyNew1155Defaults(
68
101
  ? OPEN_EDITION_MINT_SIZE
69
102
  : BigInt(props.maxSupply),
70
103
  royaltyBPS: props.royaltyBPS || 1000,
71
- salesConfig: saleSettingsOrDefault(props.salesConfig),
72
104
  tokenMetadataURI: props.tokenMetadataURI,
105
+ salesConfigOrAllowList: getSalesConfigOrAllowListWithDefaults({
106
+ salesConfig: props.salesConfig,
107
+ allowlist: props.allowlist,
108
+ }),
73
109
  };
74
110
  }
75
111
 
@@ -187,24 +223,84 @@ function setupFixedPriceMinter({
187
223
  };
188
224
  }
189
225
 
190
- export function setupMinters({ salesConfig, ...rest }: SetupMintersProps): {
226
+ function setupAllowListMinter({
227
+ chainId,
228
+ tokenId: nextTokenId,
229
+ allowlist,
230
+ fundsRecipient,
231
+ }: {
232
+ chainId: number;
233
+ tokenId: bigint;
234
+ allowlist: Concrete<AllowlistData>;
235
+ fundsRecipient: Address;
236
+ }) {
237
+ const merkleSaleStrategyAddress =
238
+ zoraCreatorMerkleMinterStrategyAddress[
239
+ chainId as keyof typeof zoraCreatorMerkleMinterStrategyAddress
240
+ ];
241
+
242
+ const merkleApproval = encodeFunctionData({
243
+ abi: zoraCreator1155ImplABI,
244
+ functionName: "addPermission",
245
+ args: [nextTokenId, merkleSaleStrategyAddress, PERMISSION_BITS.MINTER],
246
+ });
247
+
248
+ const merkleRoot = allowlist.presaleMerkleRoot.startsWith("0x")
249
+ ? allowlist.presaleMerkleRoot
250
+ : (`0x${allowlist.presaleMerkleRoot}` as Hex);
251
+
252
+ const saleData = encodeFunctionData({
253
+ abi: zoraCreatorMerkleMinterStrategyABI,
254
+ functionName: "setSale",
255
+ args: [
256
+ BigInt(nextTokenId),
257
+ {
258
+ presaleStart: allowlist.saleStart,
259
+ presaleEnd: allowlist.saleEnd,
260
+ merkleRoot,
261
+ fundsRecipient: fundsRecipient,
262
+ },
263
+ ],
264
+ });
265
+
266
+ const callSaleMerkle = encodeFunctionData({
267
+ abi: zoraCreator1155ImplABI,
268
+ functionName: "callSale",
269
+ args: [BigInt(nextTokenId), merkleSaleStrategyAddress, saleData],
270
+ });
271
+
272
+ return {
273
+ minter: merkleSaleStrategyAddress,
274
+ setupActions: [merkleApproval, callSaleMerkle],
275
+ };
276
+ }
277
+
278
+ export function setupMinters({
279
+ salesConfigOrAllowList: { salesConfig, allowlist },
280
+ ...rest
281
+ }: SetupMintersProps): {
191
282
  minter: Address;
192
283
  setupActions: Hex[];
193
284
  } {
194
- if (!salesConfig) throw new Error("No sales config for token");
195
- const { currency: currencyAddress } = salesConfig;
196
-
197
- if (currencyAddress === zeroAddress) {
198
- return setupFixedPriceMinter({
199
- ...salesConfig,
200
- ...rest,
201
- });
202
- } else {
203
- return setupErc20Minter({
204
- ...salesConfig,
205
- ...rest,
206
- });
285
+ if (salesConfig) {
286
+ const { currency: currencyAddress } = salesConfig;
287
+
288
+ if (currencyAddress === zeroAddress) {
289
+ return setupFixedPriceMinter({
290
+ ...salesConfig,
291
+ ...rest,
292
+ });
293
+ } else {
294
+ return setupErc20Minter({
295
+ ...salesConfig,
296
+ ...rest,
297
+ });
298
+ }
207
299
  }
300
+ return setupAllowListMinter({
301
+ allowlist: allowlist as Concrete<AllowlistData>,
302
+ ...rest,
303
+ });
208
304
  }
209
305
 
210
306
  function buildSetupNewToken({
@@ -335,7 +431,8 @@ export function constructCreate1155TokenCalls(
335
431
  tokenId: nextTokenId,
336
432
  chainId,
337
433
  fundsRecipient: new1155TokenPropsWithDefaults.payoutRecipient,
338
- salesConfig: new1155TokenPropsWithDefaults.salesConfig,
434
+ salesConfigOrAllowList:
435
+ new1155TokenPropsWithDefaults.salesConfigOrAllowList,
339
436
  });
340
437
 
341
438
  const adminMintCall = makeAdminMintCall({
@@ -32,26 +32,54 @@ export type CreateNew1155Params = {
32
32
  token: CreateNew1155TokenProps;
33
33
  };
34
34
 
35
- export interface CreateNew1155TokenProps {
35
+ export type AllowlistData = {
36
+ saleStart?: bigint;
37
+ saleEnd?: bigint;
38
+ presaleMerkleRoot: `0x${string}`;
39
+ };
40
+
41
+ export type CreateNew1155TokenProps = {
36
42
  maxSupply?: bigint | number;
37
43
  tokenMetadataURI: string;
38
44
  royaltyBPS?: number;
39
- salesConfig?: SalesConfigParamsType;
40
45
  createReferral?: Address;
41
46
  mintToCreatorCount?: number;
42
47
  payoutRecipient?: Address;
43
- }
48
+ } & (
49
+ | {
50
+ salesConfig: SalesConfigParamsType;
51
+ allowlist?: undefined;
52
+ }
53
+ | {
54
+ salesConfig?: undefined;
55
+ allowlist: AllowlistData;
56
+ }
57
+ | {
58
+ salesConfig?: undefined;
59
+ allowlist?: undefined;
60
+ }
61
+ );
44
62
 
45
63
  export interface ContractProps {
46
64
  nextTokenId: bigint;
47
65
  contractVersion: string;
48
66
  }
49
67
 
68
+ export type SalesConfigOrAllowList =
69
+ | {
70
+ salesConfig: Concrete<SalesConfigParamsType>;
71
+ allowlist?: undefined;
72
+ }
73
+ | {
74
+ salesConfig: undefined;
75
+ allowlist: Concrete<AllowlistData>;
76
+ };
77
+
50
78
  export type New1155Token = {
51
79
  payoutRecipient: Address;
52
80
  createReferral: Address;
53
81
  maxSupply: bigint;
54
82
  royaltyBPS: number;
55
- salesConfig: Concrete<SalesConfigParamsType>;
56
83
  tokenMetadataURI: string;
84
+ salesConfigOrAllowList: SalesConfigOrAllowList;
57
85
  };
package/src/index.ts CHANGED
@@ -31,3 +31,7 @@ export * from "./create/types";
31
31
  export * from "./sdk";
32
32
 
33
33
  export * from "./ipfs";
34
+
35
+ export { createAllowList } from "./allow-list/allow-list-client";
36
+
37
+ export * from "./allow-list/types";
@@ -27,6 +27,7 @@ import {
27
27
  import { makeOnchainMintCall, parseMintCosts } from "./mint-transactions";
28
28
  import { buildPremintMintCall } from "src/premint/premint-client";
29
29
  import { IPublicClient } from "src/types";
30
+ import { AllowListEntry } from "src/allow-list/types";
30
31
 
31
32
  export async function getMint({
32
33
  params,
@@ -129,11 +130,13 @@ export async function getMintsOfContract({
129
130
 
130
131
  export async function getMintCosts({
131
132
  params,
133
+ allowListEntry,
132
134
  mintGetter,
133
135
  premintGetter,
134
136
  publicClient,
135
137
  }: {
136
138
  params: GetMintCostsParameters;
139
+ allowListEntry?: Pick<AllowListEntry, "price">;
137
140
  mintGetter: IOnchainMintGetter;
138
141
  premintGetter: IPremintGetter;
139
142
  publicClient: IPublicClient;
@@ -150,6 +153,7 @@ export async function getMintCosts({
150
153
  mintFeePerQuantity: salesConfigAndTokenInfo.mintFeePerQuantity,
151
154
  salesConfig: salesConfigAndTokenInfo.salesConfig,
152
155
  quantityToMint: BigInt(quantityToMint),
156
+ allowListEntry,
153
157
  });
154
158
  }
155
159
 
@@ -258,6 +262,7 @@ const makeOnchainPrepareMint =
258
262
  salesConfig: result.salesConfig,
259
263
  quantityToMint: BigInt(params.quantityToMint),
260
264
  mintFeePerQuantity: result.mintFeePerQuantity,
265
+ allowListEntry: params.allowListEntry,
261
266
  }),
262
267
  });
263
268
 
@@ -286,6 +291,7 @@ const makePremintPrepareMint =
286
291
  mintFeePerQuantity: mintFee,
287
292
  quantityToMint: BigInt(params.quantityToMint),
288
293
  salesConfig: mintable.salesConfig,
294
+ allowListEntry: params.allowListEntry,
289
295
  }),
290
296
  });
291
297
 
@@ -5,6 +5,7 @@ import {
5
5
  zeroAddress,
6
6
  Account,
7
7
  SimulateContractParameters,
8
+ Hex,
8
9
  } from "viem";
9
10
  import {
10
11
  erc20MinterABI,
@@ -21,6 +22,7 @@ import { MakeMintParametersArgumentsBase } from "./types";
21
22
 
22
23
  import { contractSupportsNewMintFunction } from "./utils";
23
24
  import { OnchainSalesConfigAndTokenInfo } from "./types";
25
+ import { AllowListEntry } from "src/allow-list/types";
24
26
 
25
27
  export function makeOnchainMintCall({
26
28
  token,
@@ -59,6 +61,7 @@ export function makePrepareMint1155TokenParams({
59
61
  mintReferral,
60
62
  mintRecipient,
61
63
  quantityToMint,
64
+ allowListEntry,
62
65
  }: {
63
66
  salesConfigAndTokenInfo: MintableParameters;
64
67
  tokenId: GenericTokenIdTypes;
@@ -70,6 +73,7 @@ export function makePrepareMint1155TokenParams({
70
73
  | "mintReferral"
71
74
  | "quantityToMint"
72
75
  | "mintRecipient"
76
+ | "allowListEntry"
73
77
  >): SimulateContractParameters<any, any, any, any, any, Address | Account> {
74
78
  const mintQuantity = BigInt(quantityToMint || 1);
75
79
 
@@ -77,7 +81,7 @@ export function makePrepareMint1155TokenParams({
77
81
 
78
82
  const saleType = salesConfigAndTokenInfo.salesConfig.saleType;
79
83
 
80
- if (saleType === "fixedPrice") {
84
+ if (saleType === "fixedPrice" || saleType === "allowlist") {
81
85
  return makeEthMintCall({
82
86
  mintComment,
83
87
  minterAccount,
@@ -87,6 +91,7 @@ export function makePrepareMint1155TokenParams({
87
91
  salesConfigAndTokenInfo,
88
92
  tokenContract,
89
93
  tokenId,
94
+ allowListEntry,
90
95
  });
91
96
  }
92
97
 
@@ -137,6 +142,7 @@ function makePrepareMint721TokenParams({
137
142
  mintFeePerQuantity: salesConfigAndTokenInfo.mintFeePerQuantity,
138
143
  salesConfig: salesConfigAndTokenInfo.salesConfig,
139
144
  quantityToMint: actualQuantityToMint,
145
+ allowListEntry: undefined,
140
146
  }).totalCostEth;
141
147
 
142
148
  return makeContractParameters({
@@ -154,6 +160,37 @@ function makePrepareMint721TokenParams({
154
160
  });
155
161
  }
156
162
 
163
+ function makeFixedPriceMinterArguments({
164
+ mintTo,
165
+ mintComment,
166
+ }: {
167
+ mintTo: Address;
168
+ mintComment?: string;
169
+ }) {
170
+ return encodeAbiParameters(parseAbiParameters("address, string"), [
171
+ mintTo,
172
+ mintComment || "",
173
+ ]);
174
+ }
175
+
176
+ function makeAllowListMinterArguments({
177
+ mintTo,
178
+ allowListEntry,
179
+ }: {
180
+ mintTo: Address;
181
+ allowListEntry: AllowListEntry;
182
+ }) {
183
+ return encodeAbiParameters(
184
+ parseAbiParameters("address, uint256, uint256, bytes32[]"),
185
+ [
186
+ mintTo,
187
+ BigInt(allowListEntry.maxCanMint),
188
+ allowListEntry.price,
189
+ allowListEntry.proof,
190
+ ],
191
+ );
192
+ }
193
+
157
194
  function makeEthMintCall({
158
195
  tokenContract,
159
196
  tokenId,
@@ -163,6 +200,7 @@ function makeEthMintCall({
163
200
  mintReferral,
164
201
  mintQuantity,
165
202
  mintTo,
203
+ allowListEntry,
166
204
  }: {
167
205
  minterAccount: Account | Address;
168
206
  tokenContract: Address;
@@ -172,17 +210,26 @@ function makeEthMintCall({
172
210
  mintQuantity: bigint;
173
211
  mintComment?: string;
174
212
  mintReferral?: Address;
213
+ allowListEntry?: AllowListEntry;
175
214
  }): SimulateContractParametersWithAccount {
176
215
  const mintValue = parseMintCosts({
177
216
  mintFeePerQuantity: salesConfigAndTokenInfo.mintFeePerQuantity,
178
217
  salesConfig: salesConfigAndTokenInfo.salesConfig,
179
218
  quantityToMint: mintQuantity,
219
+ allowListEntry,
180
220
  }).totalCostEth;
181
221
 
182
- const minterArguments = encodeAbiParameters(
183
- parseAbiParameters("address, string"),
184
- [mintTo, mintComment || ""],
185
- );
222
+ const saleType = salesConfigAndTokenInfo.salesConfig.saleType;
223
+ let minterArguments: Hex;
224
+
225
+ if (saleType === "fixedPrice") {
226
+ minterArguments = makeFixedPriceMinterArguments({ mintTo, mintComment });
227
+ } else if (saleType === "allowlist") {
228
+ if (!allowListEntry) throw new Error("Missing allowListEntry");
229
+ minterArguments = makeAllowListMinterArguments({ mintTo, allowListEntry });
230
+ } else {
231
+ throw new Error("Unsupported sale type");
232
+ }
186
233
 
187
234
  // if based on contract version it has the new mint function,
188
235
  // call the new mint function.
@@ -223,18 +270,37 @@ function makeEthMintCall({
223
270
  });
224
271
  }
225
272
 
273
+ function paidMintCost(
274
+ salesConfig: SaleStrategies,
275
+ allowListEntry?: Pick<AllowListEntry, "price">,
276
+ ) {
277
+ if (
278
+ salesConfig.saleType === "erc20" ||
279
+ salesConfig.saleType === "fixedPrice"
280
+ ) {
281
+ return salesConfig.pricePerToken;
282
+ }
283
+
284
+ if (allowListEntry) return allowListEntry.price;
285
+
286
+ return 0n;
287
+ }
288
+
226
289
  export function parseMintCosts({
227
290
  salesConfig,
228
291
  mintFeePerQuantity,
229
292
  quantityToMint,
293
+ allowListEntry,
230
294
  }: {
231
295
  salesConfig: SaleStrategies;
232
296
  mintFeePerQuantity: bigint;
233
297
  quantityToMint: bigint;
298
+ allowListEntry: Pick<AllowListEntry, "price"> | undefined;
234
299
  }): MintCosts {
235
300
  const mintFeeForTokens = mintFeePerQuantity * quantityToMint;
236
301
 
237
- const tokenPurchaseCost = BigInt(salesConfig.pricePerToken) * quantityToMint;
302
+ const tokenPurchaseCost =
303
+ paidMintCost(salesConfig, allowListEntry) * quantityToMint;
238
304
 
239
305
  const totalPurchaseCostCurrency = isErc20SaleStrategy(salesConfig)
240
306
  ? salesConfig.currency
@@ -53,14 +53,23 @@ function parseSalesConfig(
53
53
  pricePerToken: BigInt(targetStrategy.erc20Minter.pricePerToken),
54
54
  };
55
55
  }
56
+ if (targetStrategy.type === "PRESALE") {
57
+ return {
58
+ saleType: "allowlist",
59
+ address: targetStrategy.presale.address,
60
+ merkleRoot: targetStrategy.presale.merkleRoot,
61
+ saleStart: targetStrategy.presale.presaleStart,
62
+ saleEnd: targetStrategy.presale.presaleEnd,
63
+ };
64
+ }
56
65
 
57
66
  throw new Error("Unknown saleType");
58
67
  }
59
68
 
60
69
  function getSaleEnd(a: SalesStrategyResult) {
61
- return BigInt(
62
- a.type === "ERC_20_MINTER" ? a.erc20Minter.saleEnd : a.fixedPrice.saleEnd,
63
- );
70
+ if (a.type === "FIXED_PRICE") return BigInt(a.fixedPrice.saleEnd);
71
+ if (a.type === "ERC_20_MINTER") return BigInt(a.erc20Minter.saleEnd);
72
+ return BigInt(a.presale.presaleEnd);
64
73
  }
65
74
 
66
75
  function getTargetStrategy({
@@ -2,26 +2,42 @@ import { GenericTokenIdTypes } from "src/types";
2
2
  import { Address } from "viem";
3
3
 
4
4
  export type FixedPriceSaleStrategyResult = {
5
- address: Address;
6
- pricePerToken: string;
7
- saleEnd: string;
8
- saleStart: string;
9
- maxTokensPerAddress: string;
5
+ type: "FIXED_PRICE";
6
+ fixedPrice: {
7
+ address: Address;
8
+ pricePerToken: string;
9
+ saleEnd: string;
10
+ saleStart: string;
11
+ maxTokensPerAddress: string;
12
+ };
10
13
  };
11
14
 
12
- export type ERC20SaleStrategyResult = FixedPriceSaleStrategyResult & {
13
- currency: Address;
15
+ export type ERC20SaleStrategyResult = {
16
+ type: "ERC_20_MINTER";
17
+ erc20Minter: {
18
+ address: Address;
19
+ pricePerToken: string;
20
+ saleEnd: string;
21
+ saleStart: string;
22
+ maxTokensPerAddress: string;
23
+ currency: Address;
24
+ };
25
+ };
26
+
27
+ export type PresaleSalesStrategyResult = {
28
+ type: "PRESALE";
29
+ presale: {
30
+ address: Address;
31
+ presaleStart: string;
32
+ presaleEnd: string;
33
+ merkleRoot: string;
34
+ };
14
35
  };
15
36
 
16
37
  export type SalesStrategyResult =
17
- | {
18
- type: "FIXED_PRICE";
19
- fixedPrice: FixedPriceSaleStrategyResult;
20
- }
21
- | {
22
- type: "ERC_20_MINTER";
23
- erc20Minter: ERC20SaleStrategyResult;
24
- };
38
+ | FixedPriceSaleStrategyResult
39
+ | ERC20SaleStrategyResult
40
+ | PresaleSalesStrategyResult;
25
41
 
26
42
  export type TokenQueryResult = {
27
43
  tokenId?: string;
@@ -59,6 +75,12 @@ fragment SaleStrategy on SalesStrategyConfig {
59
75
  saleStart
60
76
  maxTokensPerAddress
61
77
  }
78
+ presale {
79
+ address
80
+ presaleStart
81
+ presaleEnd
82
+ merkleRoot
83
+ }
62
84
  }`;
63
85
 
64
86
  const TOKEN_FRAGMENT = `
@@ -69,7 +91,7 @@ fragment Token on ZoraCreateToken {
69
91
  totalMinted
70
92
  maxSupply
71
93
  tokenStandard
72
- salesStrategies(where: {type_in: ["FIXED_PRICE", "ERC_20_MINTER"]}) {
94
+ salesStrategies(where: {type_in: ["FIXED_PRICE", "ERC_20_MINTER", "PRESALE"]}) {
73
95
  ...SaleStrategy
74
96
  }
75
97
  contract {
@@ -78,7 +100,7 @@ fragment Token on ZoraCreateToken {
78
100
  contractVersion
79
101
  contractURI
80
102
  name
81
- salesStrategies(where: {type_in: ["FIXED_PRICE", "ERC_20_MINTER"]}) {
103
+ salesStrategies(where: {type_in: ["FIXED_PRICE", "ERC_20_MINTER", "PRESALE"]}) {
82
104
  ...SaleStrategy
83
105
  }
84
106
  }