@zoralabs/protocol-sdk 0.2.0 → 0.3.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.
@@ -8,8 +8,8 @@ import type {
8
8
  Address,
9
9
  Hex,
10
10
  PublicClient,
11
+ SimulateContractParameters,
11
12
  TransactionReceipt,
12
- WalletClient,
13
13
  } from "viem";
14
14
  import { decodeEventLog, encodeFunctionData, zeroAddress } from "viem";
15
15
  import { OPEN_EDITION_MINT_SIZE } from "../constants";
@@ -101,11 +101,6 @@ export function create1155TokenSetupArgs({
101
101
  };
102
102
 
103
103
  const setupActions = [
104
- encodeFunctionData({
105
- abi: zoraCreator1155ImplABI,
106
- functionName: "addPermission",
107
- args: [0n, fixedPriceMinterAddress, PERMISSION_BIT_MINTER],
108
- }),
109
104
  encodeFunctionData({
110
105
  abi: zoraCreator1155ImplABI,
111
106
  functionName: "assumeLastTokenIdMatches",
@@ -122,6 +117,11 @@ export function create1155TokenSetupArgs({
122
117
  functionName: "setupNewToken",
123
118
  args: [tokenMetadataURI, maxSupply],
124
119
  }),
120
+ encodeFunctionData({
121
+ abi: zoraCreator1155ImplABI,
122
+ functionName: "addPermission",
123
+ args: [0n, fixedPriceMinterAddress, PERMISSION_BIT_MINTER],
124
+ }),
125
125
  encodeFunctionData({
126
126
  abi: zoraCreator1155ImplABI,
127
127
  functionName: "callSale",
@@ -226,117 +226,134 @@ async function getContractExists(
226
226
  };
227
227
  }
228
228
 
229
- // Create new 1155 token
230
- export async function createNew1155Token({
229
+ type CreateNew1155TokenReturn = {
230
+ request: SimulateContractParameters;
231
+ tokenSetupActions: Hex[];
232
+ contractAddress: Address;
233
+ contractExists: boolean;
234
+ };
235
+
236
+ export function create1155CreatorClient({
231
237
  publicClient,
232
- contract,
233
- tokenMetadataURI,
234
- mintToCreatorCount = 1,
235
- salesConfig = {},
236
- maxSupply,
237
- account,
238
- royaltySettings,
239
- getAdditionalSetupActions,
240
238
  }: {
241
239
  publicClient: PublicClient;
242
- account: Address;
243
- maxSupply?: bigint | number;
244
- royaltySettings?: RoyaltySettingsType;
245
- royaltyBPS?: number;
246
- contract: ContractType;
247
- tokenMetadataURI: string;
248
- mintToCreatorCount?: bigint | number;
249
- salesConfig?: SalesConfigParamsType;
250
- getAdditionalSetupActions?: (args: {
251
- tokenId: bigint;
252
- contractAddress: Address;
253
- }) => Hex[];
254
240
  }) {
255
- // Check if contract exists either from metadata or the static address passed in.
256
- // If a static address is passed in, this fails if that contract does not exist.
257
- const { contractExists, contractAddress } = await getContractExists(
258
- publicClient,
241
+ async function createNew1155Token({
259
242
  contract,
260
- account,
261
- );
262
-
263
- // Assume the next token id is the first token available for a new contract.
264
- let nextTokenId = 1n;
265
-
266
- if (contractExists) {
267
- nextTokenId = await publicClient.readContract({
268
- abi: zoraCreator1155ImplABI,
269
- functionName: "nextTokenId",
270
- address: contractAddress,
271
- });
272
- }
273
-
274
- // Get the fixed price minter to use within the new token to set the sales configuration.
275
- const fixedPriceMinterAddress = await publicClient.readContract({
276
- abi: zoraCreator1155FactoryImplABI,
277
- address: zoraCreator1155FactoryImplAddress[999],
278
- functionName: "fixedPriceMinter",
279
- });
280
-
281
- let tokenSetupActions = create1155TokenSetupArgs({
282
243
  tokenMetadataURI,
283
- nextTokenId,
284
- salesConfig,
244
+ mintToCreatorCount = 1,
245
+ salesConfig = {},
285
246
  maxSupply,
286
- fixedPriceMinterAddress,
287
247
  account,
288
- mintToCreatorCount,
289
248
  royaltySettings,
290
- });
291
- if (getAdditionalSetupActions) {
292
- tokenSetupActions = [
293
- ...getAdditionalSetupActions({ tokenId: nextTokenId, contractAddress }),
294
- ...tokenSetupActions,
295
- ];
296
- }
249
+ getAdditionalSetupActions,
250
+ }: {
251
+ account: Address;
252
+ maxSupply?: bigint | number;
253
+ royaltySettings?: RoyaltySettingsType;
254
+ royaltyBPS?: number;
255
+ contract: ContractType;
256
+ tokenMetadataURI: string;
257
+ mintToCreatorCount?: bigint | number;
258
+ salesConfig?: SalesConfigParamsType;
259
+ getAdditionalSetupActions?: (args: {
260
+ tokenId: bigint;
261
+ contractAddress: Address;
262
+ }) => Hex[];
263
+ }): Promise<CreateNew1155TokenReturn> {
264
+ // Check if contract exists either from metadata or the static address passed in.
265
+ // If a static address is passed in, this fails if that contract does not exist.
266
+ const { contractExists, contractAddress } = await getContractExists(
267
+ publicClient,
268
+ contract,
269
+ account,
270
+ );
297
271
 
298
- if (!contractAddress && typeof contract === "string") {
299
- throw new Error("Invariant: contract cannot be missing and an address");
300
- }
301
- if (!contractExists && typeof contract !== "string") {
302
- const { request } = await publicClient.simulateContract({
272
+ // Assume the next token id is the first token available for a new contract.
273
+ let nextTokenId = 1n;
274
+
275
+ if (contractExists) {
276
+ nextTokenId = await publicClient.readContract({
277
+ abi: zoraCreator1155ImplABI,
278
+ functionName: "nextTokenId",
279
+ address: contractAddress,
280
+ });
281
+ }
282
+
283
+ // Get the fixed price minter to use within the new token to set the sales configuration.
284
+ const fixedPriceMinterAddress = await publicClient.readContract({
303
285
  abi: zoraCreator1155FactoryImplABI,
304
- functionName: "createContractDeterministic",
305
- account,
306
286
  address: zoraCreator1155FactoryImplAddress[999],
307
- args: [
308
- contract.uri,
309
- contract.name,
310
- {
311
- // deprecated
312
- royaltyMintSchedule: 0,
313
- royaltyBPS: royaltySettings?.royaltyBPS || ROYALTY_BPS_DEFAULT,
314
- royaltyRecipient: royaltySettings?.royaltyRecipient || account,
315
- },
316
- contract.defaultAdmin || account,
317
- tokenSetupActions,
318
- ],
287
+ functionName: "fixedPriceMinter",
319
288
  });
320
- return {
321
- send: (walletClient: WalletClient) => walletClient.writeContract(request),
322
- tokenSetupActions,
323
- contractAddress,
324
- contractExists,
325
- };
326
- } else if (contractExists) {
327
- const { request } = await publicClient.simulateContract({
328
- abi: zoraCreator1155ImplABI,
329
- functionName: "multicall",
289
+
290
+ let tokenSetupActions = create1155TokenSetupArgs({
291
+ tokenMetadataURI,
292
+ nextTokenId,
293
+ salesConfig,
294
+ maxSupply,
295
+ fixedPriceMinterAddress,
330
296
  account,
331
- address: contractAddress,
332
- args: [tokenSetupActions],
297
+ mintToCreatorCount,
298
+ royaltySettings,
333
299
  });
334
- return {
335
- send: (walletClient: WalletClient) => walletClient.writeContract(request),
336
- tokenSetupActions,
337
- contractAddress,
338
- contractExists,
339
- };
300
+ if (getAdditionalSetupActions) {
301
+ tokenSetupActions = [
302
+ ...getAdditionalSetupActions({ tokenId: nextTokenId, contractAddress }),
303
+ ...tokenSetupActions,
304
+ ];
305
+ }
306
+
307
+ if (!contractAddress && typeof contract === "string") {
308
+ throw new Error("Invariant: contract cannot be missing and an address");
309
+ }
310
+ if (!contractExists && typeof contract !== "string") {
311
+ const request: SimulateContractParameters<
312
+ typeof zoraCreator1155FactoryImplABI,
313
+ "createContractDeterministic"
314
+ > = {
315
+ abi: zoraCreator1155FactoryImplABI,
316
+ functionName: "createContractDeterministic",
317
+ account,
318
+ address: zoraCreator1155FactoryImplAddress[999],
319
+ args: [
320
+ contract.uri,
321
+ contract.name,
322
+ {
323
+ // deprecated
324
+ royaltyMintSchedule: 0,
325
+ royaltyBPS: royaltySettings?.royaltyBPS || ROYALTY_BPS_DEFAULT,
326
+ royaltyRecipient: royaltySettings?.royaltyRecipient || account,
327
+ },
328
+ contract.defaultAdmin || account,
329
+ tokenSetupActions,
330
+ ],
331
+ };
332
+ return {
333
+ request,
334
+ tokenSetupActions,
335
+ contractAddress,
336
+ contractExists,
337
+ };
338
+ } else if (contractExists) {
339
+ const request: SimulateContractParameters<
340
+ typeof zoraCreator1155ImplABI,
341
+ "multicall"
342
+ > = {
343
+ abi: zoraCreator1155ImplABI,
344
+ functionName: "multicall",
345
+ account,
346
+ address: contractAddress,
347
+ args: [tokenSetupActions],
348
+ };
349
+ return {
350
+ request,
351
+ tokenSetupActions,
352
+ contractAddress,
353
+ contractExists,
354
+ };
355
+ }
356
+ throw new Error("Unsupported contract argument type");
340
357
  }
341
- throw new Error("Unsupported contract argument type");
358
+ return { createNew1155Token };
342
359
  }
@@ -1,7 +1,7 @@
1
1
  import { parseAbi, parseEther } from "viem";
2
2
  import { zora } from "viem/chains";
3
3
  import { describe, expect } from "vitest";
4
- import { MintClient } from "./mint-client";
4
+ import { createMintClient } from "./mint-client";
5
5
  import { zoraCreator1155ImplABI } from "@zoralabs/protocol-deployments";
6
6
  import { anvilTest } from "src/anvil";
7
7
 
@@ -21,7 +21,7 @@ describe("mint-helper", () => {
21
21
  });
22
22
  const targetContract = "0xa2fea3537915dc6c7c7a97a82d1236041e6feb2e";
23
23
  const targetTokenId = 1n;
24
- const minter = new MintClient(zora);
24
+ const minter = createMintClient({ chain: zora });
25
25
 
26
26
  const { simulateContractParameters: params } =
27
27
  await minter.makePrepareMintTokenParams({
@@ -73,7 +73,7 @@ describe("mint-helper", () => {
73
73
 
74
74
  const targetContract = "0x7aae7e67515A2CbB8585C707Ca6db37BDd3EA839";
75
75
  const targetTokenId = undefined;
76
- const minter = new MintClient(zora);
76
+ const minter = createMintClient({ chain: zora });
77
77
 
78
78
  const { simulateContractParameters: prepared } =
79
79
  await minter.makePrepareMintTokenParams({
@@ -42,7 +42,7 @@ const zora721Abi = parseAbi([
42
42
  "function zoraFeeForAmount(uint256 amount) public view returns (address, uint256)",
43
43
  ] as const);
44
44
 
45
- export class MintClient extends ClientBase {
45
+ class MintClient extends ClientBase {
46
46
  apiClient: typeof MintAPIClient;
47
47
 
48
48
  constructor(chain: Chain, apiClient?: typeof MintAPIClient) {
@@ -80,7 +80,7 @@ export class MintClient extends ClientBase {
80
80
  mintable: MintableGetTokenResponse;
81
81
  minterAccount: Address;
82
82
  mintArguments: MintArguments;
83
- }): Promise<{simulateContractParameters: SimulateContractParameters}> {
83
+ }): Promise<{ simulateContractParameters: SimulateContractParameters }> {
84
84
  if (!mintable) {
85
85
  throw new MintError("No mintable found");
86
86
  }
@@ -216,3 +216,13 @@ export class MintClient extends ClientBase {
216
216
  return result;
217
217
  }
218
218
  }
219
+
220
+ export function createMintClient({
221
+ chain,
222
+ mintAPIClient,
223
+ }: {
224
+ chain: Chain;
225
+ mintAPIClient?: typeof MintAPIClient;
226
+ }) {
227
+ return new MintClient(chain, mintAPIClient);
228
+ }
@@ -1,6 +1,6 @@
1
1
  import { foundry } from "viem/chains";
2
2
  import { describe, expect, vi } from "vitest";
3
- import { PremintClient } from "./premint-client";
3
+ import { createPremintClient } from "./premint-client";
4
4
  import { anvilTest } from "src/anvil";
5
5
  import { BackendChainNamesLookup } from "src/apis/chain-constants";
6
6
 
@@ -9,7 +9,7 @@ describe("ZoraCreator1155Premint", () => {
9
9
  "can sign on the forked premint contract",
10
10
  async ({ viemClients: { walletClient, publicClient } }) => {
11
11
  const [deployerAccount] = await walletClient.getAddresses();
12
- const premintClient = new PremintClient(foundry);
12
+ const premintClient = createPremintClient({ chain: foundry });
13
13
 
14
14
  premintClient.apiClient.getNextUID = vi
15
15
  .fn()
@@ -71,7 +71,7 @@ describe("ZoraCreator1155Premint", () => {
71
71
  anvilTest(
72
72
  "can validate premint on network",
73
73
  async ({ viemClients: { publicClient } }) => {
74
- const premintClient = new PremintClient(foundry);
74
+ const premintClient = createPremintClient({ chain: foundry });
75
75
 
76
76
  const premintData = {
77
77
  collection: {
@@ -116,7 +116,7 @@ describe("ZoraCreator1155Premint", () => {
116
116
  "can execute premint on network",
117
117
  async ({ viemClients: { walletClient, publicClient } }) => {
118
118
  const [deployerAccount] = await walletClient.getAddresses();
119
- const premintClient = new PremintClient(foundry);
119
+ const premintClient = createPremintClient({ chain: foundry });
120
120
 
121
121
  premintClient.apiClient.getSignature = vi.fn().mockResolvedValue({
122
122
  chain_name: "ZORA-TESTNET",
@@ -149,21 +149,34 @@ describe("ZoraCreator1155Premint", () => {
149
149
  });
150
150
  premintClient.apiClient.postSignature = vi.fn();
151
151
 
152
- const premint = await premintClient.executePremintWithWallet({
152
+ const { request } = await premintClient.executePremint({
153
+ account: deployerAccount!,
153
154
  data: await premintClient.getPremintData({
154
155
  address: "0xf8dA7f53c283d898818af7FB9d98103F559bDac2",
155
156
  uid: 3,
156
157
  }),
157
- account: deployerAccount,
158
- walletClient,
159
- publicClient,
160
158
  mintArguments: {
161
159
  quantityToMint: 1,
162
160
  mintComment: "",
163
161
  },
164
162
  });
163
+ const { request: simulateRequest } =
164
+ await publicClient.simulateContract(request);
165
+ const hash = await walletClient.writeContract(simulateRequest);
166
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
167
+ const { premintedLog, urls } =
168
+ premintClient.getDataFromPremintReceipt(receipt);
169
+
170
+ expect(urls).toEqual({
171
+ explorer:
172
+ "https://undefined/token/0xf8dA7f53c283d898818af7FB9d98103F559bDac2/instance/1",
173
+ zoraCollect:
174
+ "https://testnet.zora.co/collect/zgor:0xf8dA7f53c283d898818af7FB9d98103F559bDac2/1",
175
+ zoraManage:
176
+ "https://testnet.zora.co/collect/zgor:0xf8dA7f53c283d898818af7FB9d98103F559bDac2/1",
177
+ });
165
178
 
166
- expect(premint.premintedLog).toEqual({
179
+ expect(premintedLog).toEqual({
167
180
  contractAddress: "0xf8dA7f53c283d898818af7FB9d98103F559bDac2",
168
181
  contractConfig: {
169
182
  contractAdmin: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
@@ -5,6 +5,7 @@ import type {
5
5
  Chain,
6
6
  Hex,
7
7
  PublicClient,
8
+ SimulateContractParameters,
8
9
  TransactionReceipt,
9
10
  WalletClient,
10
11
  } from "viem";
@@ -55,12 +56,6 @@ type SignedPremintResponse = {
55
56
  premint: PremintSignatureResponse;
56
57
  };
57
58
 
58
- type ExecutedPremintResponse = {
59
- receipt: TransactionReceipt;
60
- premintedLog?: PremintedLogType;
61
- urls: URLSReturnType;
62
- };
63
-
64
59
  export const DefaultMintArguments = {
65
60
  maxSupply: OPEN_EDITION_MINT_SIZE,
66
61
  maxTokensPerAddress: 0n,
@@ -148,7 +143,7 @@ export const encodePremintForAPI = ({
148
143
  * Preminter API to access ZORA Premint functionality.
149
144
  * Currently only supports V1 premints.
150
145
  */
151
- export class PremintClient extends ClientBase {
146
+ class PremintClient extends ClientBase {
152
147
  apiClient: typeof PremintAPIClient;
153
148
 
154
149
  constructor(chain: Chain, apiClient?: typeof PremintAPIClient) {
@@ -181,6 +176,17 @@ export class PremintClient extends ClientBase {
181
176
  return zoraCreatorFixedPriceSaleStrategyAddress[999];
182
177
  }
183
178
 
179
+ getDataFromPremintReceipt(receipt: TransactionReceipt) {
180
+ const premintedLog = getPremintedLogFromReceipt(receipt);
181
+ return {
182
+ premintedLog,
183
+ urls: this.makeUrls({
184
+ address: premintedLog?.contractAddress,
185
+ tokenId: premintedLog?.tokenId,
186
+ }),
187
+ };
188
+ }
189
+
184
190
  /**
185
191
  * Update existing premint given collection address and UID of existing premint.
186
192
  *
@@ -553,24 +559,18 @@ export class PremintClient extends ClientBase {
553
559
  * @param settings.publicClient Optional public client for preflight checks.
554
560
  * @returns receipt, log, zoraURL
555
561
  */
556
- async executePremintWithWallet({
562
+ async executePremint({
557
563
  data,
558
564
  account,
559
- walletClient,
560
565
  mintArguments,
561
- publicClient,
562
566
  }: {
563
567
  data: PremintSignatureGetResponse;
564
- walletClient: WalletClient;
565
- account?: Account | Address;
568
+ account: Account | Address;
566
569
  mintArguments?: {
567
570
  quantityToMint: number;
568
571
  mintComment?: string;
569
572
  };
570
- publicClient?: PublicClient;
571
- }): Promise<ExecutedPremintResponse> {
572
- publicClient = this.getPublicClient(publicClient);
573
-
573
+ }): Promise<{request: SimulateContractParameters}> {
574
574
  if (mintArguments && mintArguments?.quantityToMint < 1) {
575
575
  throw new Error("Quantity to mint cannot be below 1");
576
576
  }
@@ -585,35 +585,33 @@ export class PremintClient extends ClientBase {
585
585
  mintArguments?.mintComment || "",
586
586
  ] as const;
587
587
 
588
- if (!account) {
589
- account = walletClient.account;
590
- }
591
-
592
588
  if (!account) {
593
589
  throw new Error("Wallet not passed in");
594
590
  }
595
591
 
596
592
  const value = numberToMint * REWARD_PER_TOKEN;
597
593
 
598
- const { request } = await publicClient.simulateContract({
594
+ const request = {
599
595
  account,
600
596
  abi: zoraCreator1155PremintExecutorImplABI,
601
597
  functionName: "premint",
602
598
  value,
603
599
  address: targetAddress,
604
600
  args,
605
- });
606
- const hash = await walletClient.writeContract(request);
607
- const receipt = await publicClient.waitForTransactionReceipt({ hash });
608
- const premintedLog = getPremintedLogFromReceipt(receipt);
601
+ };
609
602
 
610
603
  return {
611
- receipt,
612
- premintedLog,
613
- urls: this.makeUrls({
614
- address: premintedLog?.contractAddress,
615
- tokenId: premintedLog?.tokenId,
616
- }),
604
+ request,
617
605
  };
618
606
  }
619
607
  }
608
+
609
+ export function createPremintClient({
610
+ chain,
611
+ premintAPIClient,
612
+ }: {
613
+ chain: Chain;
614
+ premintAPIClient?: typeof PremintAPIClient;
615
+ }) {
616
+ return new PremintClient(chain, premintAPIClient);
617
+ }
@@ -1,25 +0,0 @@
1
- import { Address } from "abitype";
2
- import { ExtractAbiFunction, AbiParametersToPrimitiveTypes } from "abitype";
3
- import { zoraCreator1155PremintExecutorImplABI as preminterAbi } from "@zoralabs/protocol-deployments";
4
- import { TypedDataDefinition } from "viem";
5
- type PremintInputs = ExtractAbiFunction<typeof preminterAbi, "premint">["inputs"];
6
- type PreminterHashDataTypes = AbiParametersToPrimitiveTypes<PremintInputs>;
7
- export type ContractCreationConfig = PreminterHashDataTypes[0];
8
- export type PremintConfig = PreminterHashDataTypes[1];
9
- export type TokenCreationConfig = PremintConfig["tokenConfig"];
10
- export declare const preminterTypedDataDefinition: ({ verifyingContract, premintConfig, chainId, }: {
11
- verifyingContract: Address;
12
- premintConfig: PremintConfig;
13
- chainId: number;
14
- }) => TypedDataDefinition<{
15
- CreatorAttribution: {
16
- name: string;
17
- type: string;
18
- }[];
19
- TokenCreationConfig: {
20
- name: string;
21
- type: string;
22
- }[];
23
- }, "CreatorAttribution">;
24
- export {};
25
- //# sourceMappingURL=preminter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preminter.d.ts","sourceRoot":"","sources":["../src/preminter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,qCAAqC,IAAI,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACvG,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAE3C,KAAK,aAAa,GAAG,kBAAkB,CACrC,OAAO,YAAY,EACnB,SAAS,CACV,CAAC,QAAQ,CAAC,CAAC;AAEZ,KAAK,sBAAsB,GAAG,6BAA6B,CAAC,aAAa,CAAC,CAAC;AAE3E,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;AAC/D,MAAM,MAAM,aAAa,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;AAI/D,eAAO,MAAM,4BAA4B;uBAKpB,OAAO;mBACX,aAAa;aACnB,MAAM;;;;;;;;;;wBA8ChB,CAAC"}