thirdweb 5.57.0 → 5.57.1

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 (47) hide show
  1. package/dist/cjs/client/client.js +19 -15
  2. package/dist/cjs/client/client.js.map +1 -1
  3. package/dist/cjs/extensions/erc1155/drops/write/updateMetadata.js +2 -2
  4. package/dist/cjs/extensions/erc1155/drops/write/updateMetadata.js.map +1 -1
  5. package/dist/cjs/extensions/erc721/drops/write/updateMetadata.js +2 -2
  6. package/dist/cjs/extensions/erc721/drops/write/updateMetadata.js.map +1 -1
  7. package/dist/cjs/utils/fetch.js +4 -11
  8. package/dist/cjs/utils/fetch.js.map +1 -1
  9. package/dist/cjs/utils/jwt/is-jwt.js +7 -0
  10. package/dist/cjs/utils/jwt/is-jwt.js.map +1 -0
  11. package/dist/cjs/version.js +1 -1
  12. package/dist/esm/client/client.js +19 -15
  13. package/dist/esm/client/client.js.map +1 -1
  14. package/dist/esm/extensions/erc1155/drops/write/updateMetadata.js +2 -2
  15. package/dist/esm/extensions/erc1155/drops/write/updateMetadata.js.map +1 -1
  16. package/dist/esm/extensions/erc721/drops/write/updateMetadata.js +2 -2
  17. package/dist/esm/extensions/erc721/drops/write/updateMetadata.js.map +1 -1
  18. package/dist/esm/utils/fetch.js +4 -11
  19. package/dist/esm/utils/fetch.js.map +1 -1
  20. package/dist/esm/utils/jwt/is-jwt.js +4 -0
  21. package/dist/esm/utils/jwt/is-jwt.js.map +1 -0
  22. package/dist/esm/version.js +1 -1
  23. package/dist/types/client/client.d.ts +2 -2
  24. package/dist/types/client/client.d.ts.map +1 -1
  25. package/dist/types/extensions/erc1155/drops/write/updateMetadata.d.ts +1 -3
  26. package/dist/types/extensions/erc1155/drops/write/updateMetadata.d.ts.map +1 -1
  27. package/dist/types/extensions/erc721/drops/write/updateMetadata.d.ts +0 -2
  28. package/dist/types/extensions/erc721/drops/write/updateMetadata.d.ts.map +1 -1
  29. package/dist/types/utils/fetch.d.ts.map +1 -1
  30. package/dist/types/utils/jwt/is-jwt.d.ts +3 -0
  31. package/dist/types/utils/jwt/is-jwt.d.ts.map +1 -0
  32. package/dist/types/utils/jwt/types.d.ts +1 -0
  33. package/dist/types/utils/jwt/types.d.ts.map +1 -1
  34. package/dist/types/version.d.ts +1 -1
  35. package/package.json +11 -11
  36. package/src/client/client.test.ts +17 -2
  37. package/src/client/client.ts +23 -17
  38. package/src/extensions/erc1155/drops/write/updateMetadata.test.ts +0 -1
  39. package/src/extensions/erc1155/drops/write/updateMetadata.ts +4 -7
  40. package/src/extensions/erc721/drops/write/updateMetadata.test.ts +0 -2
  41. package/src/extensions/erc721/drops/write/updateMetadata.ts +2 -4
  42. package/src/extensions/marketplace/direct-listings/direct-listings.test.ts +317 -394
  43. package/src/utils/fetch.test.ts +20 -0
  44. package/src/utils/fetch.ts +6 -14
  45. package/src/utils/jwt/is-jwt.ts +5 -0
  46. package/src/utils/jwt/types.ts +2 -0
  47. package/src/version.ts +1 -1
@@ -1,25 +1,21 @@
1
- import { beforeAll, describe, expect, it } from "vitest";
1
+ import { describe, expect, it } from "vitest";
2
+ import { TEST_CONTRACT_URI } from "~test/ipfs-uris.js";
2
3
  import { ANVIL_CHAIN } from "../../../../test/src/chains.js";
3
4
  import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
4
5
  import {
5
6
  TEST_ACCOUNT_A,
6
7
  TEST_ACCOUNT_B,
8
+ TEST_ACCOUNT_C,
7
9
  } from "../../../../test/src/test-wallets.js";
8
- import {
9
- type ThirdwebContract,
10
- getContract,
11
- } from "../../../contract/contract.js";
10
+ import { getContract } from "../../../contract/contract.js";
12
11
  import { parseEventLogs } from "../../../event/actions/parse-logs.js";
12
+ import { setApprovalForAll as setApprovalForAll721 } from "../../../extensions/erc721/__generated__/IERC721A/write/setApprovalForAll.js";
13
+ import { mintTo as mintToErc1155 } from "../../../extensions/erc1155/write/mintTo.js";
13
14
  import { sendAndConfirmTransaction } from "../../../transaction/actions/send-and-confirm-transaction.js";
14
15
  import { balanceOf as balanceOfErc721 } from "../../erc721/__generated__/IERC721A/read/balanceOf.js";
15
- import { approve as approveErc721 } from "../../erc721/__generated__/IERC721A/write/approve.js";
16
- import { tokensMintedEvent as tokensMintedEventErc721 } from "../../erc721/__generated__/IMintableERC721/events/TokensMinted.js";
17
16
  import { mintTo as mintToErc721 } from "../../erc721/write/mintTo.js";
18
17
  import { balanceOf as balanceOfErc1155 } from "../../erc1155/__generated__/IERC1155/read/balanceOf.js";
19
- import { setApprovalForAll } from "../../erc1155/__generated__/IERC1155/write/setApprovalForAll.js";
20
- import { claimTo } from "../../erc1155/drops/write/claimTo.js";
21
- import { setClaimConditions } from "../../erc1155/drops/write/setClaimConditions.js";
22
- import { lazyMint } from "../../erc1155/write/lazyMint.js";
18
+ import { setApprovalForAll as setApprovalForAll1155 } from "../../erc1155/__generated__/IERC1155/write/setApprovalForAll.js";
23
19
  import { deployERC721Contract } from "../../prebuilts/deploy-erc721.js";
24
20
  import { deployERC1155Contract } from "../../prebuilts/deploy-erc1155.js";
25
21
  import { deployMarketplaceContract } from "../../prebuilts/deploy-marketplace.js";
@@ -32,434 +28,361 @@ import { isListingValid } from "./utils.js";
32
28
  import { buyFromListing } from "./write/buyFromListing.js";
33
29
  import { createListing } from "./write/createListing.js";
34
30
 
35
- describe.skip("Marketplace: Direct Listings", () => {
36
- describe("ERC721", () => {
37
- let nftTokenId: bigint;
38
- let marketplaceContract: ThirdwebContract;
39
- let erc721Contract: ThirdwebContract;
40
- beforeAll(async () => {
41
- marketplaceContract = getContract({
42
- address: await deployMarketplaceContract({
43
- account: TEST_ACCOUNT_A,
44
- chain: ANVIL_CHAIN,
45
- client: TEST_CLIENT,
46
- params: {
47
- name: "TestMarketPlace",
48
- },
49
- }),
50
- client: TEST_CLIENT,
51
- chain: ANVIL_CHAIN,
52
- });
53
-
54
- // also deploy an ERC721 contract
55
- erc721Contract = getContract({
56
- address: await deployERC721Contract({
57
- type: "TokenERC721",
58
- account: TEST_ACCOUNT_A,
59
- chain: ANVIL_CHAIN,
60
- client: TEST_CLIENT,
61
- params: {
62
- name: "TestERC721",
63
- },
64
- }),
65
- client: TEST_CLIENT,
66
- chain: ANVIL_CHAIN,
67
- });
31
+ const chain = ANVIL_CHAIN;
32
+ const client = TEST_CLIENT;
33
+
34
+ describe.runIf(process.env.TW_SECRET_KEY)("Marketplace Direct Listings", () => {
35
+ it("should work with ERC721 and ERC1155", async () => {
36
+ const marketplaceAddress = await deployMarketplaceContract({
37
+ account: TEST_ACCOUNT_A,
38
+ chain,
39
+ client,
40
+ params: {
41
+ name: "TestMarketPlace",
42
+ contractURI: TEST_CONTRACT_URI,
43
+ },
44
+ });
45
+ const erc721Address = await deployERC721Contract({
46
+ type: "TokenERC721",
47
+ account: TEST_ACCOUNT_B,
48
+ chain,
49
+ client,
50
+ params: {
51
+ name: "TestERC721",
52
+ contractURI: TEST_CONTRACT_URI,
53
+ },
54
+ });
55
+ const erc1155Address = await deployERC1155Contract({
56
+ type: "TokenERC1155",
57
+ account: TEST_ACCOUNT_C,
58
+ chain,
59
+ client,
60
+ params: {
61
+ name: "TestERC1155",
62
+ contractURI: TEST_CONTRACT_URI,
63
+ },
64
+ });
65
+
66
+ const marketplaceContract = getContract({
67
+ address: marketplaceAddress,
68
+ chain,
69
+ client,
70
+ });
71
+ const erc721Contract = getContract({
72
+ address: erc721Address,
73
+ chain,
74
+ client,
75
+ });
76
+ const erc1155Contract = getContract({
77
+ address: erc1155Address,
78
+ chain,
79
+ client,
80
+ });
68
81
 
69
- const receipt = await sendAndConfirmTransaction({
82
+ // Mint some NFTs in parallel
83
+ await Promise.all([
84
+ sendAndConfirmTransaction({
85
+ account: TEST_ACCOUNT_B,
70
86
  transaction: mintToErc721({
71
87
  contract: erc721Contract,
72
- to: TEST_ACCOUNT_A.address,
73
- nft: { name: "Test:ERC721:DirectListing" },
88
+ nft: { name: "erc721 #0" },
89
+ to: TEST_ACCOUNT_B.address,
74
90
  }),
75
- account: TEST_ACCOUNT_A,
76
- });
77
-
78
- const mintEvents = parseEventLogs({
79
- events: [tokensMintedEventErc721()],
80
- logs: receipt.logs,
81
- });
91
+ }),
92
+ sendAndConfirmTransaction({
93
+ account: TEST_ACCOUNT_C,
94
+ transaction: mintToErc1155({
95
+ contract: erc1155Contract,
96
+ nft: { name: "erc1155 #0" },
97
+ to: TEST_ACCOUNT_C.address,
98
+ supply: 100n,
99
+ }),
100
+ }),
101
+ ]);
82
102
 
83
- expect(mintEvents.length).toBe(1);
84
- expect(mintEvents[0]?.args.tokenIdMinted).toBeDefined();
103
+ // Set NFT approvals
104
+ await Promise.all([
105
+ sendAndConfirmTransaction({
106
+ account: TEST_ACCOUNT_B,
107
+ transaction: setApprovalForAll721({
108
+ contract: erc721Contract,
109
+ approved: true,
110
+ operator: marketplaceAddress,
111
+ }),
112
+ }),
113
+ sendAndConfirmTransaction({
114
+ account: TEST_ACCOUNT_C,
115
+ transaction: setApprovalForAll1155({
116
+ contract: erc1155Contract,
117
+ approved: true,
118
+ operator: marketplaceAddress,
119
+ }),
120
+ }),
121
+ ]);
85
122
 
86
- nftTokenId = mintEvents[0]?.args.tokenIdMinted as bigint;
87
- // does a lot of stuff, this may take a while
88
- }, 120_000);
123
+ // ---- set up completed ---- //
89
124
 
90
- it("should work for basic listings (Native Currency)", async () => {
91
- // listings should be 0 length to start
92
- const listings = await getAllListings({
125
+ // listings should be 0 length to start
126
+ const [allListings, totalListingCount] = await Promise.all([
127
+ getAllListings({
93
128
  contract: marketplaceContract,
94
- });
95
- expect(listings.length).toBe(0);
96
- // oh and so should totalListings
97
- expect(await totalListings({ contract: marketplaceContract })).toBe(0n);
98
-
99
- // approve first
100
- const approveTx = approveErc721({
101
- contract: erc721Contract,
102
- to: marketplaceContract.address,
103
- tokenId: nftTokenId,
104
- });
105
-
106
- await sendAndConfirmTransaction({
107
- transaction: approveTx,
108
- account: TEST_ACCOUNT_A,
109
- });
110
-
111
- const transaction = createListing({
129
+ }),
130
+ totalListings({ contract: marketplaceContract }),
131
+ ]);
132
+ expect(allListings.length).toBe(0);
133
+ // oh and so should totalListings
134
+ expect(totalListingCount).toBe(0n);
135
+
136
+ const receipt = await sendAndConfirmTransaction({
137
+ transaction: createListing({
112
138
  contract: marketplaceContract,
113
139
  assetContractAddress: erc721Contract.address,
114
- tokenId: nftTokenId,
140
+ tokenId: 0n,
115
141
  pricePerToken: "1",
116
- });
117
- const receipt = await sendAndConfirmTransaction({
118
- transaction,
119
- account: TEST_ACCOUNT_A,
120
- });
142
+ }),
143
+ account: TEST_ACCOUNT_B,
144
+ });
121
145
 
122
- const listingEvents = parseEventLogs({
123
- events: [newListingEvent()],
124
- logs: receipt.logs,
125
- });
146
+ const listingEvents = parseEventLogs({
147
+ events: [newListingEvent()],
148
+ logs: receipt.logs,
149
+ });
126
150
 
127
- expect(listingEvents.length).toBe(1);
151
+ expect(listingEvents.length).toBe(1);
128
152
 
129
- // biome-ignore lint/style/noNonNullAssertion: OK in tests
130
- const listingEvent = listingEvents[0]!;
153
+ // biome-ignore lint/style/noNonNullAssertion: OK in tests
154
+ const listingEvent = listingEvents[0]!;
131
155
 
132
- expect(listingEvent.args.listingCreator).toBe(TEST_ACCOUNT_A.address);
133
- expect(listingEvent.args.assetContract).toBe(erc721Contract.address);
156
+ expect(listingEvent.args.listingCreator).toBe(TEST_ACCOUNT_B.address);
157
+ expect(listingEvent.args.assetContract).toBe(erc721Contract.address);
134
158
 
135
- // at this point listings should be 1
136
- const listingsAfter = await getAllListings({
159
+ const [
160
+ listingsAfter,
161
+ validListings,
162
+ totalListingCount2,
163
+ firstListing,
164
+ nftBalanceOfAccountABeforePurchase,
165
+ ] = await Promise.all([
166
+ getAllListings({
137
167
  contract: marketplaceContract,
138
- });
139
- expect(listingsAfter.length).toBe(1);
140
- // valid listings should also be 1!
141
- const validListings = await getAllValidListings({
168
+ }),
169
+ getAllValidListings({
142
170
  contract: marketplaceContract,
143
- });
144
- expect(validListings.length).toBe(1);
145
- // and totalListings should be 1
146
- expect(await totalListings({ contract: marketplaceContract })).toBe(1n);
147
-
148
- // explicitly retrieve the listing!
149
- const listing = await getListing({
171
+ }),
172
+ totalListings({ contract: marketplaceContract }),
173
+ getListing({
150
174
  contract: marketplaceContract,
151
175
  listingId: listingEvent.args.listingId,
152
- });
153
-
154
- expect(listing).toBeDefined();
155
- expect(listing.status).toBe("ACTIVE");
156
- expect(listing.creatorAddress).toBe(TEST_ACCOUNT_A.address);
157
- expect(listing.assetContractAddress).toBe(erc721Contract.address);
158
- expect(listing.tokenId).toBe(nftTokenId);
159
- expect(listing.currencyValuePerToken).toMatchInlineSnapshot(`
160
- {
161
- "decimals": 18,
162
- "displayValue": "1",
163
- "name": "Anvil Ether",
164
- "symbol": "ETH",
165
- "value": 1000000000000000000n,
166
- }
167
- `);
168
- expect(listing.asset).toMatchInlineSnapshot(`
169
- {
170
- "id": 0n,
171
- "metadata": {
172
- "name": "Test:ERC721:DirectListing",
173
- },
174
- "owner": null,
175
- "tokenURI": "ipfs://QmewoGwuooC1Vno1ZTnmKmEUaimDygraR1fEEHdTeraF34/0",
176
- "type": "ERC721",
177
- }
178
- `);
179
-
180
- // check the listing is valid
181
- const listingValidity = await isListingValid({
182
- listing,
183
- contract: marketplaceContract,
184
- quantity: 1n,
185
- });
176
+ }),
177
+ balanceOfErc721({
178
+ contract: erc721Contract,
179
+ owner: TEST_ACCOUNT_A.address,
180
+ }),
181
+ ]);
182
+
183
+ // at this point listings should be 1
184
+ expect(listingsAfter.length).toBe(1);
185
+ // valid listings should also be 1!
186
+ expect(validListings.length).toBe(1);
187
+ // and totalListings should be 1
188
+ expect(totalListingCount2).toBe(1n);
189
+ expect(firstListing).toBeDefined();
190
+ expect(firstListing.status).toBe("ACTIVE");
191
+ expect(firstListing.creatorAddress).toBe(TEST_ACCOUNT_B.address);
192
+ expect(firstListing.assetContractAddress).toBe(erc721Contract.address);
193
+ expect(firstListing.tokenId).toBe(0n);
194
+ expect(firstListing.currencyValuePerToken).toMatchInlineSnapshot(`
195
+ {
196
+ "decimals": 18,
197
+ "displayValue": "1",
198
+ "name": "Anvil Ether",
199
+ "symbol": "ETH",
200
+ "value": 1000000000000000000n,
201
+ }
202
+ `);
203
+ expect(firstListing.asset.metadata.name).toBe("erc721 #0");
204
+ expect(firstListing.asset.id).toBe(0n);
205
+ expect(firstListing.asset.owner).toBe(null);
206
+ // check the listing is valid
207
+ const firstListingValidity = await isListingValid({
208
+ listing: firstListing,
209
+ contract: marketplaceContract,
210
+ quantity: 1n,
211
+ });
186
212
 
187
- expect(listingValidity).toMatchInlineSnapshot(`
188
- {
189
- "valid": true,
190
- }
213
+ expect(firstListingValidity).toMatchInlineSnapshot(`
214
+ {
215
+ "valid": true,
216
+ }
191
217
  `);
218
+ expect(nftBalanceOfAccountABeforePurchase).toBe(0n);
192
219
 
193
- // expect the buyer to have an initial balance of 0
194
- await expect(
195
- balanceOfErc721({
196
- contract: erc721Contract,
197
- owner: TEST_ACCOUNT_B.address,
198
- }),
199
- ).resolves.toBe(0n);
200
-
201
- const buyTx = buyFromListing({
220
+ await sendAndConfirmTransaction({
221
+ transaction: buyFromListing({
202
222
  contract: marketplaceContract,
203
223
  listingId: listingEvent.args.listingId,
204
- recipient: TEST_ACCOUNT_B.address,
224
+ recipient: TEST_ACCOUNT_A.address,
205
225
  quantity: 1n,
206
- });
207
-
208
- await sendAndConfirmTransaction({
209
- transaction: buyTx,
210
- account: TEST_ACCOUNT_B,
211
- });
212
-
213
- // expect the buyer to have a new balance of 1
214
- await expect(
215
- balanceOfErc721({
216
- contract: erc721Contract,
217
- owner: TEST_ACCOUNT_B.address,
218
- }),
219
- ).resolves.toBe(1n);
220
- // expect the seller to no longer have the token
221
- await expect(
222
- balanceOfErc721({
223
- contract: erc721Contract,
224
- owner: TEST_ACCOUNT_A.address,
225
- }),
226
- ).resolves.toBe(0n);
226
+ }),
227
+ account: TEST_ACCOUNT_A,
227
228
  });
228
- });
229
-
230
- describe("ERC1155 Drop", () => {
231
- let nftTokenId: bigint;
232
- let marketplaceContract: ThirdwebContract;
233
- let erc1155Contract: ThirdwebContract;
234
- beforeAll(async () => {
235
- marketplaceContract = getContract({
236
- address: await deployMarketplaceContract({
237
- account: TEST_ACCOUNT_A,
238
- chain: ANVIL_CHAIN,
239
- client: TEST_CLIENT,
240
- params: {
241
- name: "TestMarketPlace",
242
- },
243
- }),
244
- client: TEST_CLIENT,
245
- chain: ANVIL_CHAIN,
246
- });
247
-
248
- // also deploy an ERC721 contract
249
- erc1155Contract = getContract({
250
- address: await deployERC1155Contract({
251
- type: "DropERC1155",
252
- account: TEST_ACCOUNT_A,
253
- chain: ANVIL_CHAIN,
254
- client: TEST_CLIENT,
255
- params: {
256
- name: "TestERC1155",
257
- },
258
- }),
259
- client: TEST_CLIENT,
260
- chain: ANVIL_CHAIN,
261
- });
262
-
263
- // lazy mint 10 tokens
264
- await expect(
265
- sendAndConfirmTransaction({
266
- transaction: lazyMint({
267
- contract: erc1155Contract,
268
- nfts: [{ name: "Test:ERC1155:DirectListing" }],
269
- }),
270
- account: TEST_ACCOUNT_A,
271
- }),
272
- ).resolves.toBeDefined();
273
-
274
- // set claim condition (just public is fine)
275
- await expect(
276
- sendAndConfirmTransaction({
277
- transaction: setClaimConditions({
278
- contract: erc1155Contract,
279
- tokenId: 0n,
280
- phases: [{}],
281
- }),
282
- account: TEST_ACCOUNT_A,
283
- }),
284
- ).resolves.toBeDefined();
285
-
286
- // claim 10 tokens
287
- await expect(
288
- sendAndConfirmTransaction({
289
- transaction: claimTo({
290
- contract: erc1155Contract,
291
- tokenId: 0n,
292
- to: TEST_ACCOUNT_A.address,
293
- quantity: 10n,
294
- }),
295
- account: TEST_ACCOUNT_A,
296
- }),
297
- ).resolves.toBeDefined();
298
-
299
- nftTokenId = 0n;
300
- // does a lot of stuff, this may take a while
301
- }, 120_000);
302
-
303
- it("should work for basic listings (Native Currency)", async () => {
304
- // listings should be 0 length to start
305
- const listings = await getAllListings({
306
- contract: marketplaceContract,
307
- });
308
- expect(listings.length).toBe(0);
309
- // oh and so should totalListings
310
- expect(await totalListings({ contract: marketplaceContract })).toBe(0n);
311
229
 
312
- // approve first
313
-
314
- await sendAndConfirmTransaction({
315
- transaction: setApprovalForAll({
316
- contract: erc1155Contract,
317
- operator: marketplaceContract.address,
318
- approved: true,
319
- }),
320
- account: TEST_ACCOUNT_A,
321
- });
322
-
323
- // this should fail because we're listing more than we have
324
- await expect(
325
- sendAndConfirmTransaction({
326
- transaction: createListing({
327
- contract: marketplaceContract,
328
- assetContractAddress: erc1155Contract.address,
329
- tokenId: nftTokenId,
330
- pricePerToken: "1",
331
- quantity: 20n,
332
- }),
333
- account: TEST_ACCOUNT_A,
334
- }),
335
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
336
- [TransactionError: Error - Marketplace: not owner or approved tokens.
337
-
338
- contract: ${marketplaceContract.address}
339
- chainId: 31337]
340
- `);
341
-
342
- // this should work because we're listing the correct amount
343
- const receipt = await sendAndConfirmTransaction({
230
+ const [
231
+ nftBalanceOfAccountAAfterPurchase,
232
+ nftBalanceOfAccountBAfterPurchase,
233
+ ] = await Promise.all([
234
+ balanceOfErc721({
235
+ contract: erc721Contract,
236
+ owner: TEST_ACCOUNT_A.address,
237
+ }),
238
+ balanceOfErc721({
239
+ contract: erc721Contract,
240
+ owner: TEST_ACCOUNT_B.address,
241
+ }),
242
+ ]);
243
+ // expect the buyer to have a new balance of 1
244
+ expect(nftBalanceOfAccountAAfterPurchase).toBe(1n);
245
+ // expect the seller to no longer have the nft
246
+ expect(nftBalanceOfAccountBAfterPurchase).toBe(0n);
247
+
248
+ /**
249
+ * ============ now do the same tests but for ERC1155 =============
250
+ */
251
+
252
+ // this should fail because we're listing more than we have
253
+ await expect(
254
+ sendAndConfirmTransaction({
344
255
  transaction: createListing({
345
256
  contract: marketplaceContract,
346
257
  assetContractAddress: erc1155Contract.address,
347
- tokenId: nftTokenId,
348
- pricePerToken: "0.01",
349
- quantity: 1n,
258
+ tokenId: 0n,
259
+ pricePerToken: "1",
260
+ quantity: 101n,
350
261
  }),
351
- account: TEST_ACCOUNT_A,
352
- });
262
+ account: TEST_ACCOUNT_C,
263
+ }),
264
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
265
+ [TransactionError: Error - Marketplace: not owner or approved tokens.
353
266
 
354
- const listingEvents = parseEventLogs({
355
- events: [newListingEvent()],
356
- logs: receipt.logs,
357
- });
267
+ contract: ${marketplaceContract.address}
268
+ chainId: 31337]
269
+ `);
358
270
 
359
- expect(listingEvents.length).toBe(1);
271
+ const receipt1155 = await sendAndConfirmTransaction({
272
+ transaction: createListing({
273
+ contract: marketplaceContract,
274
+ assetContractAddress: erc1155Contract.address,
275
+ tokenId: 0n,
276
+ pricePerToken: "0.01",
277
+ quantity: 1n,
278
+ }),
279
+ account: TEST_ACCOUNT_C,
280
+ });
360
281
 
361
- // biome-ignore lint/style/noNonNullAssertion: OK in tests
362
- const listingEvent = listingEvents[0]!;
282
+ const listingEvents1155 = parseEventLogs({
283
+ events: [newListingEvent()],
284
+ logs: receipt1155.logs,
285
+ });
363
286
 
364
- expect(listingEvent.args.listingCreator).toBe(TEST_ACCOUNT_A.address);
365
- expect(listingEvent.args.assetContract).toBe(erc1155Contract.address);
287
+ expect(listingEvents.length).toBe(1);
366
288
 
367
- // at this point listings should be 1
368
- const listingsAfter = await getAllListings({
369
- contract: marketplaceContract,
370
- });
371
- expect(listingsAfter.length).toBe(1);
372
- // valid listings should also be 1!
373
- const validListings = await getAllValidListings({
374
- contract: marketplaceContract,
375
- });
376
- expect(validListings.length).toBe(1);
377
- // and totalListings should be 1
378
- expect(await totalListings({ contract: marketplaceContract })).toBe(1n);
289
+ // biome-ignore lint/style/noNonNullAssertion: OK in tests
290
+ const listingEvent1155 = listingEvents1155[0]!;
379
291
 
380
- // explicitly retrieve the listing!
381
- const listing = await getListing({
292
+ expect(listingEvent1155.args.listingCreator).toBe(TEST_ACCOUNT_C.address);
293
+ expect(listingEvent1155.args.assetContract).toBe(erc1155Contract.address);
294
+
295
+ const [
296
+ listings1155After,
297
+ validListings1155,
298
+ totalListingCountAfter1155,
299
+ secondListing,
300
+ nft1155BalanceOfAccountABeforePurchase,
301
+ ] = await Promise.all([
302
+ getAllListings({
382
303
  contract: marketplaceContract,
383
- listingId: listingEvent.args.listingId,
384
- });
385
-
386
- expect(listing).toBeDefined();
387
- expect(listing.status).toBe("ACTIVE");
388
- expect(listing.creatorAddress).toBe(TEST_ACCOUNT_A.address);
389
- expect(listing.assetContractAddress).toBe(erc1155Contract.address);
390
- expect(listing.tokenId).toBe(nftTokenId);
391
- expect(listing.currencyValuePerToken).toMatchInlineSnapshot(`
392
- {
393
- "decimals": 18,
394
- "displayValue": "0.01",
395
- "name": "Anvil Ether",
396
- "symbol": "ETH",
397
- "value": 10000000000000000n,
398
- }
399
- `);
400
- expect(listing.asset).toMatchInlineSnapshot(`
401
- {
402
- "id": 0n,
403
- "metadata": {
404
- "name": "Test:ERC1155:DirectListing",
405
- },
406
- "owner": null,
407
- "supply": 10n,
408
- "tokenURI": "ipfs://QmdwzcoSGSzoRSMBk2efkHjGVRsyUaR2Lm79YTuL324NtM/0",
409
- "type": "ERC1155",
410
- }
411
- `);
412
-
413
- // check the listing is valid
414
- const listingValidity = await isListingValid({
415
- listing,
304
+ }),
305
+ getAllValidListings({
416
306
  contract: marketplaceContract,
417
- quantity: 1n,
418
- });
307
+ }),
308
+ totalListings({ contract: marketplaceContract }),
309
+ getListing({
310
+ contract: marketplaceContract,
311
+ listingId: listingEvent1155.args.listingId,
312
+ }),
313
+ balanceOfErc1155({
314
+ contract: erc1155Contract,
315
+ owner: TEST_ACCOUNT_A.address,
316
+ tokenId: 0n,
317
+ }),
318
+ ]);
319
+
320
+ // at this point listings should be 2
321
+ expect(listings1155After.length).toBe(2);
322
+ // valid listings should be 1 still because the first listing has been bought
323
+ expect(validListings1155.length).toBe(1);
324
+ // and totalListings should be 2
325
+ expect(totalListingCountAfter1155).toBe(2n);
326
+ expect(secondListing).toBeDefined();
327
+ expect(secondListing.status).toBe("ACTIVE");
328
+ expect(secondListing.creatorAddress).toBe(TEST_ACCOUNT_C.address);
329
+ expect(secondListing.assetContractAddress).toBe(erc1155Contract.address);
330
+ expect(secondListing.tokenId).toBe(0n);
331
+ expect(secondListing.currencyValuePerToken).toMatchInlineSnapshot(`
332
+ {
333
+ "decimals": 18,
334
+ "displayValue": "0.01",
335
+ "name": "Anvil Ether",
336
+ "symbol": "ETH",
337
+ "value": 10000000000000000n,
338
+ }
339
+ `);
340
+ expect(secondListing.asset.metadata.name).toBe("erc1155 #0");
341
+ expect(secondListing.asset.id).toBe(0n);
342
+
343
+ // check the listing is valid
344
+ const listingValidity = await isListingValid({
345
+ listing: secondListing,
346
+ contract: marketplaceContract,
347
+ quantity: 1n,
348
+ });
419
349
 
420
- expect(listingValidity).toMatchInlineSnapshot(`
421
- {
422
- "valid": true,
423
- }
424
- `);
350
+ expect(listingValidity).toMatchInlineSnapshot(`
351
+ {
352
+ "valid": true,
353
+ }
354
+ `);
425
355
 
426
- // expect the buyer to have an initial balance of 0
427
- await expect(
428
- balanceOfErc1155({
429
- contract: erc1155Contract,
430
- owner: TEST_ACCOUNT_B.address,
431
- tokenId: nftTokenId,
432
- }),
433
- ).resolves.toBe(0n);
356
+ expect(nft1155BalanceOfAccountABeforePurchase).toBe(0n);
434
357
 
435
- const buyTx = buyFromListing({
358
+ await sendAndConfirmTransaction({
359
+ transaction: buyFromListing({
436
360
  contract: marketplaceContract,
437
- listingId: listingEvent.args.listingId,
438
- recipient: TEST_ACCOUNT_B.address,
361
+ listingId: listingEvent1155.args.listingId,
362
+ recipient: TEST_ACCOUNT_A.address,
439
363
  quantity: 1n,
440
- });
441
-
442
- await sendAndConfirmTransaction({
443
- transaction: buyTx,
444
- account: TEST_ACCOUNT_B,
445
- });
446
-
447
- // expect the buyer to have a new balance of 1
448
- await expect(
449
- balanceOfErc1155({
450
- contract: erc1155Contract,
451
- owner: TEST_ACCOUNT_B.address,
452
- tokenId: nftTokenId,
453
- }),
454
- ).resolves.toBe(1n);
455
- // expect the seller to only have 9 of the tokens
456
- await expect(
457
- balanceOfErc1155({
458
- contract: erc1155Contract,
459
- owner: TEST_ACCOUNT_A.address,
460
- tokenId: nftTokenId,
461
- }),
462
- ).resolves.toBe(9n);
364
+ }),
365
+ account: TEST_ACCOUNT_A,
463
366
  });
367
+
368
+ const [
369
+ nft1155BalanceOfAccountAAfterPurchase,
370
+ nft1155BalanceOfAccountCAfterPurchase,
371
+ ] = await Promise.all([
372
+ balanceOfErc1155({
373
+ contract: erc1155Contract,
374
+ owner: TEST_ACCOUNT_A.address,
375
+ tokenId: 0n,
376
+ }),
377
+ balanceOfErc1155({
378
+ contract: erc1155Contract,
379
+ owner: TEST_ACCOUNT_C.address,
380
+ tokenId: 0n,
381
+ }),
382
+ ]);
383
+ // expect the buyer to have a new balance of 1
384
+ expect(nft1155BalanceOfAccountAAfterPurchase).toBe(1n);
385
+ // expect the seller to have one less 1155 token
386
+ expect(nft1155BalanceOfAccountCAfterPurchase).toBe(99n);
464
387
  });
465
388
  });