@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
@@ -0,0 +1,363 @@
1
+ /**
2
+ * This file was auto-generated by openapi-typescript.
3
+ * Do not make direct changes to the file.
4
+ */
5
+
6
+
7
+ export interface paths {
8
+ "/signature": {
9
+ /** Upsert Premint Signature */
10
+ post: operations["upsert_premint_signature_signature_post"];
11
+ };
12
+ "/signature/{chain_name}/{collection_address}": {
13
+ /** Get Premint Signatures For Collection */
14
+ get: operations["get_premint_signatures_for_collection_signature__chain_name___collection_address__get"];
15
+ };
16
+ "/signature/{chain_name}/{collection_address}/next_uid": {
17
+ /** Get Next Uid */
18
+ get: operations["get_next_uid_signature__chain_name___collection_address__next_uid_get"];
19
+ };
20
+ "/signature/{chain_name}/{collection_address}/{uid}": {
21
+ /** Get Premint Signature */
22
+ get: operations["get_premint_signature_signature__chain_name___collection_address___uid__get"];
23
+ };
24
+ "/created/{chain_name}/{signer}": {
25
+ /** Get Premint Signatures By Signer */
26
+ get: operations["get_premint_signatures_by_signer_created__chain_name___signer__get"];
27
+ };
28
+ }
29
+
30
+ export type webhooks = Record<string, never>;
31
+
32
+ export interface components {
33
+ schemas: {
34
+ /**
35
+ * ChainName
36
+ * @description An enumeration.
37
+ * @enum {string}
38
+ */
39
+ ChainName: "ETHEREUM-MAINNET" | "ETHEREUM-ROPSTEN" | "ETHEREUM-RINKEBY" | "ETHEREUM-GOERLI" | "ETHEREUM-SEPOLIA" | "OPTIMISM-MAINNET" | "OPTIMISM-GOERLI" | "ZORA-GOERLI" | "ZORA-MAINNET" | "BASE-MAINNET" | "BASE-GOERLI" | "PGN-MAINNET";
40
+ /**
41
+ * CollectionCreationConfig
42
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
43
+ * (store_as, override_name), as well as provides other convinience methods.
44
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
45
+ * complex type we include on a stored entity.
46
+ *
47
+ * Example::
48
+ * >>> class Foo(ObjectBase):
49
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
50
+ * ...: other: str = "default"
51
+ */
52
+ CollectionCreationConfig: {
53
+ /** Contractadmin */
54
+ contractAdmin: string;
55
+ /** Contracturi */
56
+ contractURI: string;
57
+ /** Contractname */
58
+ contractName: string;
59
+ };
60
+ /** HTTPValidationError */
61
+ HTTPValidationError: {
62
+ /** Detail */
63
+ detail?: components["schemas"]["ValidationError"][];
64
+ };
65
+ /**
66
+ * PremintCollection
67
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
68
+ * (store_as, override_name), as well as provides other convinience methods.
69
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
70
+ * complex type we include on a stored entity.
71
+ *
72
+ * Example::
73
+ * >>> class Foo(ObjectBase):
74
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
75
+ * ...: other: str = "default"
76
+ */
77
+ PremintCollection: {
78
+ /** Contract Address */
79
+ contract_address: string;
80
+ /** Contract Admin */
81
+ contract_admin: string;
82
+ /** Contract Uri */
83
+ contract_uri: string;
84
+ /** Contract Name */
85
+ contract_name: string;
86
+ /** Premints */
87
+ premints: components["schemas"]["SignedPremintConfig"][];
88
+ };
89
+ /**
90
+ * PremintConfig
91
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
92
+ * (store_as, override_name), as well as provides other convinience methods.
93
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
94
+ * complex type we include on a stored entity.
95
+ *
96
+ * Example::
97
+ * >>> class Foo(ObjectBase):
98
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
99
+ * ...: other: str = "default"
100
+ */
101
+ PremintConfig: {
102
+ tokenConfig: components["schemas"]["TokenCreationConfig"];
103
+ /** Uid */
104
+ uid: number;
105
+ /** Version */
106
+ version: number;
107
+ /** Deleted */
108
+ deleted: boolean;
109
+ };
110
+ /**
111
+ * PremintNextUid
112
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
113
+ * (store_as, override_name), as well as provides other convinience methods.
114
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
115
+ * complex type we include on a stored entity.
116
+ *
117
+ * Example::
118
+ * >>> class Foo(ObjectBase):
119
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
120
+ * ...: other: str = "default"
121
+ */
122
+ PremintNextUid: {
123
+ /** Next Uid */
124
+ next_uid: number;
125
+ };
126
+ /**
127
+ * PremintRequest
128
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
129
+ * (store_as, override_name), as well as provides other convinience methods.
130
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
131
+ * complex type we include on a stored entity.
132
+ *
133
+ * Example::
134
+ * >>> class Foo(ObjectBase):
135
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
136
+ * ...: other: str = "default"
137
+ */
138
+ PremintRequest: {
139
+ collection: components["schemas"]["CollectionCreationConfig"];
140
+ premint: components["schemas"]["PremintConfig"];
141
+ chain_name: components["schemas"]["ChainName"];
142
+ /** Signature */
143
+ signature: string;
144
+ };
145
+ /**
146
+ * PremintSignature
147
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
148
+ * (store_as, override_name), as well as provides other convinience methods.
149
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
150
+ * complex type we include on a stored entity.
151
+ *
152
+ * Example::
153
+ * >>> class Foo(ObjectBase):
154
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
155
+ * ...: other: str = "default"
156
+ */
157
+ PremintSignature: {
158
+ collection: components["schemas"]["CollectionCreationConfig"];
159
+ premint: components["schemas"]["PremintConfig"];
160
+ chain_name: components["schemas"]["ChainName"];
161
+ /** Signature */
162
+ signature: string;
163
+ /** Collection Address */
164
+ collection_address: string;
165
+ /** Signer */
166
+ signer: string;
167
+ };
168
+ /**
169
+ * SignedPremintConfig
170
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
171
+ * (store_as, override_name), as well as provides other convinience methods.
172
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
173
+ * complex type we include on a stored entity.
174
+ *
175
+ * Example::
176
+ * >>> class Foo(ObjectBase):
177
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
178
+ * ...: other: str = "default"
179
+ */
180
+ SignedPremintConfig: {
181
+ tokenConfig: components["schemas"]["TokenCreationConfig"];
182
+ /** Uid */
183
+ uid: number;
184
+ /** Version */
185
+ version: number;
186
+ /** Deleted */
187
+ deleted: boolean;
188
+ /** Signature */
189
+ signature: string;
190
+ };
191
+ /**
192
+ * TokenCreationConfig
193
+ * @description ObjectBase extends Pydantic's BaseModel class to support extra functionality
194
+ * (store_as, override_name), as well as provides other convinience methods.
195
+ * ObjectBase allows for validation and type enforcement, and should be used inheritedfor any
196
+ * complex type we include on a stored entity.
197
+ *
198
+ * Example::
199
+ * >>> class Foo(ObjectBase):
200
+ * ...: found_at_height: int = field(override_name="address", store_as=str)
201
+ * ...: other: str = "default"
202
+ */
203
+ TokenCreationConfig: {
204
+ /** Tokenuri */
205
+ tokenURI: string;
206
+ /** Maxsupply */
207
+ maxSupply: string;
208
+ /** Maxtokensperaddress */
209
+ maxTokensPerAddress: string;
210
+ /** Pricepertoken */
211
+ pricePerToken: string;
212
+ /** Mintstart */
213
+ mintStart: string;
214
+ /** Mintduration */
215
+ mintDuration: string;
216
+ /** Royaltymintschedule */
217
+ royaltyMintSchedule: number;
218
+ /** Royaltybps */
219
+ royaltyBPS: number;
220
+ /** Royaltyrecipient */
221
+ royaltyRecipient: string;
222
+ /** Fixedpriceminter */
223
+ fixedPriceMinter: string;
224
+ };
225
+ /** ValidationError */
226
+ ValidationError: {
227
+ /** Location */
228
+ loc: (string | number)[];
229
+ /** Message */
230
+ msg: string;
231
+ /** Error Type */
232
+ type: string;
233
+ };
234
+ };
235
+ responses: never;
236
+ parameters: never;
237
+ requestBodies: never;
238
+ headers: never;
239
+ pathItems: never;
240
+ }
241
+
242
+ export type $defs = Record<string, never>;
243
+
244
+ export type external = Record<string, never>;
245
+
246
+ export interface operations {
247
+
248
+ /** Upsert Premint Signature */
249
+ upsert_premint_signature_signature_post: {
250
+ requestBody: {
251
+ content: {
252
+ "application/json": components["schemas"]["PremintRequest"];
253
+ };
254
+ };
255
+ responses: {
256
+ /** @description Successful Response */
257
+ 200: {
258
+ content: {
259
+ "application/json": components["schemas"]["PremintRequest"];
260
+ };
261
+ };
262
+ /** @description Validation Error */
263
+ 422: {
264
+ content: {
265
+ "application/json": components["schemas"]["HTTPValidationError"];
266
+ };
267
+ };
268
+ };
269
+ };
270
+ /** Get Premint Signatures For Collection */
271
+ get_premint_signatures_for_collection_signature__chain_name___collection_address__get: {
272
+ parameters: {
273
+ path: {
274
+ chain_name: components["schemas"]["ChainName"];
275
+ collection_address: string;
276
+ };
277
+ };
278
+ responses: {
279
+ /** @description Successful Response */
280
+ 200: {
281
+ content: {
282
+ "application/json": components["schemas"]["PremintCollection"];
283
+ };
284
+ };
285
+ /** @description Validation Error */
286
+ 422: {
287
+ content: {
288
+ "application/json": components["schemas"]["HTTPValidationError"];
289
+ };
290
+ };
291
+ };
292
+ };
293
+ /** Get Next Uid */
294
+ get_next_uid_signature__chain_name___collection_address__next_uid_get: {
295
+ parameters: {
296
+ path: {
297
+ chain_name: components["schemas"]["ChainName"];
298
+ collection_address: string;
299
+ };
300
+ };
301
+ responses: {
302
+ /** @description Successful Response */
303
+ 200: {
304
+ content: {
305
+ "application/json": components["schemas"]["PremintNextUid"];
306
+ };
307
+ };
308
+ /** @description Validation Error */
309
+ 422: {
310
+ content: {
311
+ "application/json": components["schemas"]["HTTPValidationError"];
312
+ };
313
+ };
314
+ };
315
+ };
316
+ /** Get Premint Signature */
317
+ get_premint_signature_signature__chain_name___collection_address___uid__get: {
318
+ parameters: {
319
+ path: {
320
+ chain_name: components["schemas"]["ChainName"];
321
+ collection_address: string;
322
+ uid: number;
323
+ };
324
+ };
325
+ responses: {
326
+ /** @description Successful Response */
327
+ 200: {
328
+ content: {
329
+ "application/json": components["schemas"]["PremintSignature"];
330
+ };
331
+ };
332
+ /** @description Validation Error */
333
+ 422: {
334
+ content: {
335
+ "application/json": components["schemas"]["HTTPValidationError"];
336
+ };
337
+ };
338
+ };
339
+ };
340
+ /** Get Premint Signatures By Signer */
341
+ get_premint_signatures_by_signer_created__chain_name___signer__get: {
342
+ parameters: {
343
+ path: {
344
+ chain_name: components["schemas"]["ChainName"];
345
+ signer: string;
346
+ };
347
+ };
348
+ responses: {
349
+ /** @description Successful Response */
350
+ 200: {
351
+ content: {
352
+ "application/json": components["schemas"]["PremintCollection"][];
353
+ };
354
+ };
355
+ /** @description Validation Error */
356
+ 422: {
357
+ content: {
358
+ "application/json": components["schemas"]["HTTPValidationError"];
359
+ };
360
+ };
361
+ };
362
+ };
363
+ }
@@ -0,0 +1,93 @@
1
+ export class BadResponseError<T = any> extends Error {
2
+ status: number;
3
+ json: T;
4
+ constructor(message: string, status: number, json: any) {
5
+ super(message);
6
+ this.name = "BadResponseError";
7
+ this.status = status;
8
+ this.json = json;
9
+ }
10
+ }
11
+
12
+ async function wait(delayMs: number) {
13
+ return new Promise((resolve) => {
14
+ setTimeout(resolve, delayMs);
15
+ });
16
+ }
17
+
18
+ /**
19
+ * A simple fetch() wrapper for HTTP gets.
20
+ * Can be overridden as needed.
21
+ *
22
+ * @param path Path to run HTTP JSON get against
23
+ * @returns JSON object response
24
+ * @throws Error when HTTP response fails
25
+ */
26
+ export const get = async <T>(url: string) => {
27
+ const response = await fetch(url, { method: "GET" });
28
+ if (response.status !== 200) {
29
+ let json;
30
+ try {
31
+ json = await response.json();
32
+ } catch (e: any) {}
33
+ throw new BadResponseError(
34
+ `Invalid response, status ${response.status}`,
35
+ response.status,
36
+ json,
37
+ );
38
+ }
39
+ return (await response.json()) as T;
40
+ };
41
+
42
+ /**
43
+ * A simple fetch() wrapper for HTTP post.
44
+ * Can be overridden as needed.
45
+ *
46
+ * @param path Path to run HTTP JSON POST against
47
+ * @param data Data to POST to the server, converted to JSON
48
+ * @returns JSON object response
49
+ * @throws Error when HTTP response fails
50
+ */
51
+ export const post = async <T>(url: string, data: any) => {
52
+ const response = await fetch(url, {
53
+ method: "POST",
54
+ headers: {
55
+ "content-type": "application/json",
56
+ accept: "application/json",
57
+ },
58
+ body: JSON.stringify(data),
59
+ });
60
+ if (response.status !== 200) {
61
+ let json;
62
+ try {
63
+ json = await response.json();
64
+ } catch (e: any) {}
65
+ throw new BadResponseError(
66
+ `Bad response: ${response.status}`,
67
+ response.status,
68
+ json,
69
+ );
70
+ }
71
+ return (await response.json()) as T;
72
+ };
73
+
74
+ export const retries = async <T>(
75
+ tryFn: () => T,
76
+ maxTries: number = 3,
77
+ atTry: number = 1,
78
+ linearBackoffMS: number = 200,
79
+ ): Promise<T> => {
80
+ try {
81
+ return await tryFn();
82
+ } catch (err: any) {
83
+ if (err instanceof BadResponseError) {
84
+ if (err.status >= 500) {
85
+ if (atTry <= maxTries) {
86
+ await wait(atTry * linearBackoffMS);
87
+ return await retries(tryFn, maxTries, atTry + 1);
88
+ }
89
+ }
90
+ }
91
+ throw err;
92
+ }
93
+ };
@@ -0,0 +1,10 @@
1
+ export const ZORA_API_BASE = "https://api.zora.co/";
2
+ export const OPEN_EDITION_MINT_SIZE = BigInt("18446744073709551615");
3
+
4
+ // Subgraph base settings
5
+ const SUBGRAPH_CONFIG_BASE =
6
+ "https://api.goldsky.com/api/public/project_clhk16b61ay9t49vm6ntn4mkz/subgraphs";
7
+
8
+ export function getSubgraph(name: string, version: string): string {
9
+ return `${SUBGRAPH_CONFIG_BASE}/${name}/${version}/gn`;
10
+ }
@@ -0,0 +1,90 @@
1
+ import { parseEther } from "viem";
2
+ import { describe, expect } from "vitest";
3
+ import {
4
+ createNew1155Token,
5
+ getTokenIdFromCreateReceipt,
6
+ } from "./1155-create-helper";
7
+ import { anvilTest } from "src/anvil";
8
+
9
+ const demoTokenMetadataURI = "ipfs://DUMMY/token.json";
10
+ const demoContractMetadataURI = "ipfs://DUMMY/contract.json";
11
+
12
+ describe("create-helper", () => {
13
+ anvilTest(
14
+ "creates a new contract given arguments",
15
+ async ({ viemClients: { testClient, publicClient, walletClient } }) => {
16
+ const addresses = await walletClient.getAddresses();
17
+ const creatorAddress = addresses[0]!;
18
+ await testClient.setBalance({
19
+ address: creatorAddress,
20
+ value: parseEther("1"),
21
+ });
22
+ const new1155TokenRequest = await createNew1155Token({
23
+ publicClient,
24
+ contract: {
25
+ name: "testContract",
26
+ uri: demoContractMetadataURI,
27
+ },
28
+ tokenMetadataURI: demoTokenMetadataURI,
29
+ account: creatorAddress,
30
+ mintToCreatorCount: 1,
31
+ });
32
+ const hash = await new1155TokenRequest.send(walletClient);
33
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
34
+ expect(receipt).not.toBeNull();
35
+ expect(receipt.to).to.equal("0x777777c338d93e2c7adf08d102d45ca7cc4ed021");
36
+ expect(getTokenIdFromCreateReceipt(receipt)).to.be.equal(1n);
37
+ },
38
+ 20 * 1000,
39
+ );
40
+ anvilTest(
41
+ "creates a new contract, than creates a new token on this existing contract",
42
+ async ({ viemClients: { publicClient, walletClient } }) => {
43
+ const addresses = await walletClient.getAddresses();
44
+ const creatorAccount = addresses[0]!;
45
+
46
+ const new1155TokenRequest = await createNew1155Token({
47
+ publicClient,
48
+ contract: {
49
+ name: "testContract2",
50
+ uri: demoContractMetadataURI,
51
+ },
52
+ tokenMetadataURI: demoTokenMetadataURI,
53
+ account: creatorAccount,
54
+ mintToCreatorCount: 1,
55
+ });
56
+ expect(new1155TokenRequest.contractAddress).to.be.equal(
57
+ "0xb1A8928dF830C21eD682949Aa8A83C1C215194d3",
58
+ );
59
+ expect(new1155TokenRequest.contractExists).to.be.false;
60
+ const hash = await new1155TokenRequest.send(walletClient);
61
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
62
+ const firstTokenId = getTokenIdFromCreateReceipt(receipt);
63
+ expect(firstTokenId).to.be.equal(1n);
64
+ expect(receipt).not.toBeNull();
65
+
66
+ const newTokenOnExistingContract = await createNew1155Token({
67
+ publicClient,
68
+ contract: {
69
+ name: "testContract2",
70
+ uri: demoContractMetadataURI,
71
+ },
72
+ tokenMetadataURI: demoTokenMetadataURI,
73
+ account: creatorAccount,
74
+ mintToCreatorCount: 1,
75
+ });
76
+ expect(newTokenOnExistingContract.contractAddress).to.be.equal(
77
+ "0xb1A8928dF830C21eD682949Aa8A83C1C215194d3",
78
+ );
79
+ expect(newTokenOnExistingContract.contractExists).to.be.true;
80
+ const newHash = await newTokenOnExistingContract.send(walletClient);
81
+ const newReceipt = await publicClient.waitForTransactionReceipt({
82
+ hash: newHash,
83
+ });
84
+ const tokenId = getTokenIdFromCreateReceipt(newReceipt);
85
+ expect(tokenId).to.be.equal(2n);
86
+ expect(newReceipt).not.toBeNull();
87
+ },
88
+ 20 * 1000,
89
+ );
90
+ });