@0xsequence/marketplace-sdk 0.8.3 → 0.8.5
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.
- package/CHANGELOG.md +16 -1
- package/dist/{chunk-25CAMYCG.js → chunk-BB2PTJHI.js} +22 -20
- package/dist/chunk-BB2PTJHI.js.map +1 -0
- package/dist/{chunk-5ATGT5S4.js → chunk-EZFCQZHU.js} +14 -6
- package/dist/chunk-EZFCQZHU.js.map +1 -0
- package/dist/{chunk-DFI52A2E.js → chunk-KCLMSSPS.js} +364 -242
- package/dist/chunk-KCLMSSPS.js.map +1 -0
- package/dist/{chunk-XUNDLCEH.js → chunk-LDZZUYG7.js} +2 -2
- package/dist/{chunk-QTV77W42.js → chunk-SFSFIGHM.js} +45 -35
- package/dist/chunk-SFSFIGHM.js.map +1 -0
- package/dist/{chunk-FSJKN4YN.js → chunk-ZSCZLHKX.js} +194 -2
- package/dist/chunk-ZSCZLHKX.js.map +1 -0
- package/dist/{chunk-FH4TZRDV.js → chunk-ZVTG6US2.js} +2 -2
- package/dist/index.css +4 -4
- package/dist/index.css.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{lowestListing-DUZ_nYml.d.ts → lowestListing-W7P4EkC3.d.ts} +34 -11
- package/dist/react/_internal/databeat/index.js +5 -5
- package/dist/react/_internal/index.d.ts +1 -1
- package/dist/react/_internal/index.js +3 -1
- package/dist/react/_internal/wagmi/index.d.ts +3 -2
- package/dist/react/_internal/wagmi/index.js +3 -1
- package/dist/react/hooks/index.d.ts +8 -5
- package/dist/react/hooks/index.js +6 -4
- package/dist/react/hooks/options/index.js +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +9 -7
- package/dist/react/queries/index.d.ts +1 -1
- package/dist/react/queries/index.js +6 -2
- package/dist/react/ssr/index.js +1 -1
- package/dist/react/ui/components/collectible-card/index.d.ts +3 -2
- package/dist/react/ui/components/collectible-card/index.js +7 -7
- package/dist/react/ui/icons/index.js +1 -1
- package/dist/react/ui/index.js +7 -7
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +5 -5
- package/dist/types/index.js +1 -1
- package/dist/utils/index.js +1 -1
- package/package.json +19 -19
- package/src/react/_internal/api/__mocks__/marketplace.msw.ts +35 -21
- package/src/react/_internal/wagmi/__tests__/create-config.test.ts +1 -11
- package/src/react/_internal/wagmi/get-connectors.ts +27 -24
- package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +4 -9
- package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +5 -4
- package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +14 -10
- package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +115 -65
- package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +10 -7
- package/src/react/hooks/__tests__/useInventory.test.tsx +294 -0
- package/src/react/hooks/index.ts +1 -0
- package/src/react/hooks/useAutoSelectFeeOption.tsx +10 -3
- package/src/react/hooks/useCancelOrder.tsx +1 -0
- package/src/react/hooks/useCancelTransactionSteps.tsx +18 -4
- package/src/react/hooks/useGenerateOfferTransaction.tsx +11 -1
- package/src/react/hooks/useInventory.tsx +15 -0
- package/src/react/hooks/util/optimisticCancelUpdates.ts +115 -0
- package/src/react/queries/index.ts +1 -0
- package/src/react/queries/inventory.ts +303 -0
- package/src/react/queries/listBalances.ts +1 -8
- package/src/react/queries/listCollectibles.ts +12 -3
- package/src/react/ui/components/_internals/action-button/__tests__/ActionButtonBody.test.tsx +27 -94
- package/src/react/ui/components/_internals/action-button/__tests__/NonOwnerActions.test.tsx +59 -0
- package/src/react/ui/components/_internals/action-button/__tests__/OwnerActions.test.tsx +73 -0
- package/src/react/ui/components/_internals/action-button/__tests__/useActionButtonLogic.test.tsx +77 -0
- package/src/react/ui/components/_internals/action-button/components/ActionButtonBody.tsx +3 -2
- package/src/react/ui/components/_internals/action-button/hooks/useActionButtonLogic.ts +4 -3
- package/src/react/ui/components/collectible-card/CollectibleAsset.tsx +1 -0
- package/src/react/ui/components/collectible-card/CollectibleCard.tsx +18 -12
- package/src/react/ui/components/collectible-card/__tests__/CollectibleAsset.test.tsx +200 -0
- package/src/react/ui/components/collectible-card/__tests__/CollectibleCard.test.tsx +92 -123
- package/src/react/ui/components/collectible-card/__tests__/Footer.test.tsx +136 -0
- package/src/react/ui/modals/BuyModal/__tests__/Modal.test.tsx +2 -8
- package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +74 -104
- package/src/react/ui/modals/MakeOfferModal/__tests__/Modal.test.tsx +108 -78
- package/src/react/ui/modals/SellModal/__tests__/Modal.test.tsx +72 -135
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.test.tsx +286 -0
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +16 -4
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +35 -132
- package/src/react/ui/modals/_internal/components/floorPriceText/__tests__/FloorPriceText.test.tsx +199 -0
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/PriceInput.test.tsx +55 -0
- package/src/react/ui/modals/_internal/components/priceInput/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/__tests__/ActionButtons.test.tsx +72 -0
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/__tests__/BalanceIndicator.test.tsx +50 -0
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/__tests__/SelectWaasFeeOptions.test.tsx +193 -0
- package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +2 -2
- package/test/const.ts +24 -0
- package/test/test-utils.tsx +85 -47
- package/.changeset/flat-parks-clean.md +0 -8
- package/.changeset/red-buckets-deny.md +0 -6
- package/.changeset/seven-doors-taste.md +0 -5
- package/dist/chunk-25CAMYCG.js.map +0 -1
- package/dist/chunk-5ATGT5S4.js.map +0 -1
- package/dist/chunk-DFI52A2E.js.map +0 -1
- package/dist/chunk-FSJKN4YN.js.map +0 -1
- package/dist/chunk-QTV77W42.js.map +0 -1
- package/src/react/ui/components/_internals/action-button/__tests__/ActionButton.test.tsx +0 -107
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +0 -164
- /package/dist/{chunk-XUNDLCEH.js.map → chunk-LDZZUYG7.js.map} +0 -0
- /package/dist/{chunk-FH4TZRDV.js.map → chunk-ZVTG6US2.js.map} +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { renderHook, server, waitFor } from '@test';
|
|
2
|
+
import { http, HttpResponse } from 'msw';
|
|
3
|
+
import { zeroAddress } from 'viem';
|
|
4
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import {
|
|
6
|
+
mockIndexerEndpoint,
|
|
7
|
+
mockTokenBalance,
|
|
8
|
+
} from '../../_internal/api/__mocks__/indexer.msw';
|
|
9
|
+
import {
|
|
10
|
+
mockCollectibleOrder,
|
|
11
|
+
mockMarketplaceEndpoint,
|
|
12
|
+
} from '../../_internal/api/__mocks__/marketplace.msw';
|
|
13
|
+
import type { UseInventoryArgs } from '../../queries/inventory';
|
|
14
|
+
import { mockConfig } from '../options/__mocks__/marketplaceConfig.msw';
|
|
15
|
+
import { useInventory } from '../useInventory';
|
|
16
|
+
|
|
17
|
+
// Make sure mockCollectibleOrder has a tokenId of "1" for tests
|
|
18
|
+
mockCollectibleOrder.metadata.tokenId = '1';
|
|
19
|
+
|
|
20
|
+
describe('useInventory', () => {
|
|
21
|
+
const defaultArgs: UseInventoryArgs = {
|
|
22
|
+
accountAddress:
|
|
23
|
+
'0x1234567890123456789012345678901234567890' as `0x${string}`,
|
|
24
|
+
chainId: 1,
|
|
25
|
+
collectionAddress: zeroAddress,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
// Reset MSW handlers before each test to ensure a clean state
|
|
30
|
+
server.resetHandlers();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should fetch inventory data successfully', async () => {
|
|
34
|
+
const { result } = renderHook(() => useInventory(defaultArgs));
|
|
35
|
+
|
|
36
|
+
// Initially loading
|
|
37
|
+
expect(result.current.isLoading).toBe(true);
|
|
38
|
+
expect(result.current.data).toBeUndefined();
|
|
39
|
+
|
|
40
|
+
// Wait for data to be loaded
|
|
41
|
+
await waitFor(() => {
|
|
42
|
+
expect(result.current.isLoading).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Verify the data is defined and has pages
|
|
46
|
+
expect(result.current.data).toBeDefined();
|
|
47
|
+
expect(result.current.data?.pages).toBeDefined();
|
|
48
|
+
expect(result.current.error).toBeNull();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should handle error gracefully', async () => {
|
|
52
|
+
// Mock both API endpoints to return errors
|
|
53
|
+
server.use(
|
|
54
|
+
http.post(mockMarketplaceEndpoint('ListCollectibles'), () => {
|
|
55
|
+
return new HttpResponse(null, { status: 500 });
|
|
56
|
+
}),
|
|
57
|
+
http.post(mockIndexerEndpoint('GetTokenBalances'), () => {
|
|
58
|
+
return new HttpResponse(null, { status: 500 });
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const { result } = renderHook(() =>
|
|
63
|
+
useInventory({
|
|
64
|
+
...defaultArgs,
|
|
65
|
+
// Add a unique key to avoid caching
|
|
66
|
+
collectionAddress:
|
|
67
|
+
'0xdeadbeef0000000000000000000000000000dead' as `0x${string}`,
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Wait for the query to finish loading and show error
|
|
72
|
+
await waitFor(
|
|
73
|
+
() => {
|
|
74
|
+
expect(result.current.isLoading).toBe(false);
|
|
75
|
+
},
|
|
76
|
+
{ timeout: 3000 },
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Verify error state
|
|
80
|
+
expect(result.current.status).toBe('error');
|
|
81
|
+
expect(result.current.isError).toBe(true);
|
|
82
|
+
expect(result.current.error).not.toBeNull();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should refetch when args change', async () => {
|
|
86
|
+
const { result, rerender } = renderHook(() => useInventory(defaultArgs));
|
|
87
|
+
|
|
88
|
+
// Wait for initial data
|
|
89
|
+
await waitFor(() => {
|
|
90
|
+
expect(result.current.isLoading).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Change args and rerender with a new hook
|
|
94
|
+
const newArgs = {
|
|
95
|
+
...defaultArgs,
|
|
96
|
+
collectionAddress:
|
|
97
|
+
'0x1234567890123456789012345678901234567890' as `0x${string}`,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
rerender(() => useInventory(newArgs));
|
|
101
|
+
|
|
102
|
+
// Wait for new data
|
|
103
|
+
await waitFor(() => {
|
|
104
|
+
expect(result.current.data).toBeDefined();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Verify that the query was refetched with new args
|
|
108
|
+
expect(result.current.data).toBeDefined();
|
|
109
|
+
expect(result.current.isSuccess).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should handle disabled queries', async () => {
|
|
113
|
+
const disabledArgs: UseInventoryArgs = {
|
|
114
|
+
...defaultArgs,
|
|
115
|
+
query: {
|
|
116
|
+
enabled: false,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const { result } = renderHook(() => useInventory(disabledArgs));
|
|
121
|
+
|
|
122
|
+
// Should not be loading or have data
|
|
123
|
+
expect(result.current.isLoading).toBe(false);
|
|
124
|
+
expect(result.current.data).toBeUndefined();
|
|
125
|
+
expect(result.current.isFetched).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should use isLaos721 flag from marketplaceConfig', async () => {
|
|
129
|
+
// Setup config with LAOS collection
|
|
130
|
+
const laosCollectionAddress = '0x1234567890123456789012345678901234567890';
|
|
131
|
+
server.use(
|
|
132
|
+
http.get('*/marketplace/*/settings.json', () => {
|
|
133
|
+
const configWithLaos = {
|
|
134
|
+
...mockConfig,
|
|
135
|
+
collections: [
|
|
136
|
+
{
|
|
137
|
+
...mockConfig.collections[0],
|
|
138
|
+
address: laosCollectionAddress,
|
|
139
|
+
isLAOSERC721: true,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
return HttpResponse.json(configWithLaos);
|
|
144
|
+
}),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const laosArgs: UseInventoryArgs = {
|
|
148
|
+
...defaultArgs,
|
|
149
|
+
collectionAddress: laosCollectionAddress as `0x${string}`,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const { result } = renderHook(() => useInventory(laosArgs));
|
|
153
|
+
|
|
154
|
+
await waitFor(() => {
|
|
155
|
+
expect(result.current.isLoading).toBe(false);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect(result.current.data).toBeDefined();
|
|
159
|
+
expect(result.current.isSuccess).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should fetch data from indexer when marketplace API has no more results', async () => {
|
|
163
|
+
// Mock marketplace API with empty results
|
|
164
|
+
server.use(
|
|
165
|
+
http.post(mockMarketplaceEndpoint('ListCollectibles'), () => {
|
|
166
|
+
return HttpResponse.json({
|
|
167
|
+
collectibles: [],
|
|
168
|
+
page: {
|
|
169
|
+
page: 1,
|
|
170
|
+
pageSize: 50,
|
|
171
|
+
more: false,
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
}),
|
|
175
|
+
// Mock indexer with data
|
|
176
|
+
http.post(mockIndexerEndpoint('GetTokenBalances'), () => {
|
|
177
|
+
return HttpResponse.json({
|
|
178
|
+
balances: [mockTokenBalance],
|
|
179
|
+
page: {
|
|
180
|
+
page: 1,
|
|
181
|
+
pageSize: 50,
|
|
182
|
+
more: false,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const { result } = renderHook(() => useInventory(defaultArgs));
|
|
189
|
+
|
|
190
|
+
await waitFor(() => {
|
|
191
|
+
expect(result.current.isLoading).toBe(false);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(result.current.data).toBeDefined();
|
|
195
|
+
expect(result.current.data?.pages[0].collectibles).toBeDefined();
|
|
196
|
+
expect(result.current.isSuccess).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('should support pagination with fetchNextPage', async () => {
|
|
200
|
+
// Simplified test for pagination
|
|
201
|
+
// Set up mock data for first and second pages
|
|
202
|
+
const page1Data = {
|
|
203
|
+
collectibles: [
|
|
204
|
+
{
|
|
205
|
+
...mockCollectibleOrder,
|
|
206
|
+
metadata: {
|
|
207
|
+
...mockCollectibleOrder.metadata,
|
|
208
|
+
tokenId: '1',
|
|
209
|
+
name: 'Token 1',
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
page: {
|
|
214
|
+
page: 1,
|
|
215
|
+
pageSize: 10,
|
|
216
|
+
more: true, // indicate there's a next page
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// Mock API to return data for the first page
|
|
221
|
+
server.use(
|
|
222
|
+
http.post(
|
|
223
|
+
mockMarketplaceEndpoint('ListCollectibles'),
|
|
224
|
+
async ({ request }) => {
|
|
225
|
+
const body = (await request.json()) as { page?: number };
|
|
226
|
+
const pageNumber = body?.page || 1;
|
|
227
|
+
|
|
228
|
+
// Return first page data
|
|
229
|
+
if (pageNumber === 1) {
|
|
230
|
+
return HttpResponse.json(page1Data);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// For second page, return empty collectibles but with more=false
|
|
234
|
+
return HttpResponse.json({
|
|
235
|
+
collectibles: [],
|
|
236
|
+
page: {
|
|
237
|
+
page: 2,
|
|
238
|
+
pageSize: 10,
|
|
239
|
+
more: false,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
},
|
|
243
|
+
),
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
// Use unique test args to avoid caching issues
|
|
247
|
+
const testArgs = {
|
|
248
|
+
...defaultArgs,
|
|
249
|
+
accountAddress:
|
|
250
|
+
'0xabcdef1234567890abcdef1234567890abcdef12' as `0x${string}`,
|
|
251
|
+
collectionAddress:
|
|
252
|
+
'0xabcdef1234567890abcdef1234567890abcdef12' as `0x${string}`,
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const { result } = renderHook(() => useInventory(testArgs));
|
|
256
|
+
|
|
257
|
+
// Wait for the first page to load
|
|
258
|
+
await waitFor(
|
|
259
|
+
() => {
|
|
260
|
+
expect(result.current.isLoading).toBe(false);
|
|
261
|
+
expect(result.current.data?.pages).toBeDefined();
|
|
262
|
+
},
|
|
263
|
+
{ timeout: 5000 },
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
// Verify first page data loaded correctly
|
|
267
|
+
expect(result.current.data?.pages[0].collectibles).toBeDefined();
|
|
268
|
+
expect(result.current.data?.pages[0].collectibles.length).toBeGreaterThan(
|
|
269
|
+
0,
|
|
270
|
+
);
|
|
271
|
+
// Check that at least one item has the expected tokenId
|
|
272
|
+
expect(
|
|
273
|
+
result.current.data?.pages[0].collectibles.some(
|
|
274
|
+
(c) => c.metadata.tokenId === '1',
|
|
275
|
+
),
|
|
276
|
+
).toBe(true);
|
|
277
|
+
expect(result.current.hasNextPage).toBe(true);
|
|
278
|
+
|
|
279
|
+
// Fetch the next page
|
|
280
|
+
await result.current.fetchNextPage();
|
|
281
|
+
|
|
282
|
+
// Wait for second page to load
|
|
283
|
+
await waitFor(
|
|
284
|
+
() => {
|
|
285
|
+
expect(result.current.data?.pages.length).toBe(2);
|
|
286
|
+
},
|
|
287
|
+
{ timeout: 5000 },
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
// For an empty second page we just verify it exists
|
|
291
|
+
expect(result.current.data?.pages[1]).toBeDefined();
|
|
292
|
+
expect(result.current.hasNextPage).toBe(false); // No more pages
|
|
293
|
+
});
|
|
294
|
+
});
|
package/src/react/hooks/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from './useCurrency';
|
|
|
12
12
|
export * from './useFilters';
|
|
13
13
|
export * from './useFloorOrder';
|
|
14
14
|
export * from './useHighestOffer';
|
|
15
|
+
export * from './useInventory';
|
|
15
16
|
export * from './useListBalances';
|
|
16
17
|
export * from './useListCollectibleActivities';
|
|
17
18
|
export * from './useListCollectibles';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Address, zeroAddress } from 'viem';
|
|
2
2
|
|
|
3
3
|
import { useChain } from '@0xsequence/connect';
|
|
4
|
-
import { useCallback } from 'react';
|
|
4
|
+
import { useCallback, useEffect } from 'react';
|
|
5
5
|
import { useAccount } from 'wagmi';
|
|
6
6
|
import type { FeeOption } from '../../types/waas-types';
|
|
7
7
|
import { useCollectionBalanceDetails } from './useCollectionBalanceDetails';
|
|
@@ -19,6 +19,7 @@ type UseAutoSelectFeeOptionArgs = {
|
|
|
19
19
|
options: FeeOption[] | undefined;
|
|
20
20
|
chainId: number;
|
|
21
21
|
};
|
|
22
|
+
enabled?: boolean;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -87,6 +88,7 @@ type UseAutoSelectFeeOptionArgs = {
|
|
|
87
88
|
*/
|
|
88
89
|
export function useAutoSelectFeeOption({
|
|
89
90
|
pendingFeeOptionConfirmation,
|
|
91
|
+
enabled,
|
|
90
92
|
}: UseAutoSelectFeeOptionArgs) {
|
|
91
93
|
const { address: userAddress } = useAccount();
|
|
92
94
|
|
|
@@ -110,7 +112,8 @@ export function useAutoSelectFeeOption({
|
|
|
110
112
|
omitNativeBalances: false,
|
|
111
113
|
},
|
|
112
114
|
query: {
|
|
113
|
-
enabled:
|
|
115
|
+
enabled:
|
|
116
|
+
!!pendingFeeOptionConfirmation.options && !!userAddress && enabled,
|
|
114
117
|
},
|
|
115
118
|
});
|
|
116
119
|
const chain = useChain(pendingFeeOptionConfirmation.chainId);
|
|
@@ -131,7 +134,11 @@ export function useAutoSelectFeeOption({
|
|
|
131
134
|
})),
|
|
132
135
|
];
|
|
133
136
|
|
|
134
|
-
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
if (combinedBalances) {
|
|
139
|
+
console.debug('currency balances', combinedBalances);
|
|
140
|
+
}
|
|
141
|
+
}, [combinedBalances]);
|
|
135
142
|
|
|
136
143
|
const autoSelectedOption = useCallback(async () => {
|
|
137
144
|
if (!userAddress) {
|
|
@@ -20,6 +20,10 @@ import type { ModalCallbacks } from '../ui/modals/_internal/types';
|
|
|
20
20
|
import type { TransactionStep } from './useCancelOrder';
|
|
21
21
|
import { useConfig } from './useConfig';
|
|
22
22
|
import { useGenerateCancelTransaction } from './useGenerateCancelTransaction';
|
|
23
|
+
import {
|
|
24
|
+
invalidateQueriesOnCancel,
|
|
25
|
+
updateQueriesOnCancel,
|
|
26
|
+
} from './util/optimisticCancelUpdates';
|
|
23
27
|
|
|
24
28
|
interface UseCancelTransactionStepsArgs {
|
|
25
29
|
collectionAddress: string;
|
|
@@ -156,9 +160,12 @@ export const useCancelTransactionSteps = ({
|
|
|
156
160
|
|
|
157
161
|
if (onSuccess && typeof onSuccess === 'function') {
|
|
158
162
|
onSuccess({ hash });
|
|
159
|
-
}
|
|
160
163
|
|
|
161
|
-
|
|
164
|
+
updateQueriesOnCancel({
|
|
165
|
+
orderId,
|
|
166
|
+
queryClient,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
162
169
|
|
|
163
170
|
setSteps((prev) => ({
|
|
164
171
|
...prev,
|
|
@@ -172,9 +179,12 @@ export const useCancelTransactionSteps = ({
|
|
|
172
179
|
|
|
173
180
|
if (onSuccess && typeof onSuccess === 'function') {
|
|
174
181
|
onSuccess({ orderId: reservoirOrderId });
|
|
175
|
-
}
|
|
176
182
|
|
|
177
|
-
|
|
183
|
+
updateQueriesOnCancel({
|
|
184
|
+
orderId: reservoirOrderId,
|
|
185
|
+
queryClient,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
178
188
|
|
|
179
189
|
setSteps((prev) => ({
|
|
180
190
|
...prev,
|
|
@@ -182,6 +192,10 @@ export const useCancelTransactionSteps = ({
|
|
|
182
192
|
}));
|
|
183
193
|
}
|
|
184
194
|
} catch (error) {
|
|
195
|
+
invalidateQueriesOnCancel({
|
|
196
|
+
queryClient,
|
|
197
|
+
});
|
|
198
|
+
|
|
185
199
|
setSteps((prev) => ({
|
|
186
200
|
...prev,
|
|
187
201
|
isExecuting: false,
|
|
@@ -5,8 +5,10 @@ import {
|
|
|
5
5
|
type CreateReq,
|
|
6
6
|
type GenerateOfferTransactionArgs,
|
|
7
7
|
type Step,
|
|
8
|
+
type WalletKind,
|
|
8
9
|
getMarketplaceClient,
|
|
9
10
|
} from '../_internal';
|
|
11
|
+
import { useWallet } from '../_internal/wallet/useWallet';
|
|
10
12
|
import { useConfig } from './useConfig';
|
|
11
13
|
|
|
12
14
|
export type UseGenerateOfferTransactionArgs = {
|
|
@@ -29,10 +31,12 @@ export const generateOfferTransaction = async (
|
|
|
29
31
|
params: GenerateOfferTransactionProps,
|
|
30
32
|
config: SdkConfig,
|
|
31
33
|
chainId: number,
|
|
34
|
+
walletKind?: WalletKind,
|
|
32
35
|
) => {
|
|
33
36
|
const args = {
|
|
34
37
|
...params,
|
|
35
38
|
offer: { ...params.offer, expiry: dateToUnixTime(params.offer.expiry) },
|
|
39
|
+
walletType: walletKind,
|
|
36
40
|
} satisfies GenerateOfferTransactionArgs;
|
|
37
41
|
const marketplaceClient = getMarketplaceClient(chainId, config);
|
|
38
42
|
return (await marketplaceClient.generateOfferTransaction(args)).steps;
|
|
@@ -42,11 +46,17 @@ export const useGenerateOfferTransaction = (
|
|
|
42
46
|
params: UseGenerateOfferTransactionArgs,
|
|
43
47
|
) => {
|
|
44
48
|
const config = useConfig();
|
|
49
|
+
const { wallet } = useWallet();
|
|
45
50
|
|
|
46
51
|
const { mutate, mutateAsync, ...result } = useMutation({
|
|
47
52
|
onSuccess: params.onSuccess,
|
|
48
53
|
mutationFn: (args: GenerateOfferTransactionProps) =>
|
|
49
|
-
generateOfferTransaction(
|
|
54
|
+
generateOfferTransaction(
|
|
55
|
+
args,
|
|
56
|
+
config,
|
|
57
|
+
params.chainId,
|
|
58
|
+
wallet?.walletKind,
|
|
59
|
+
),
|
|
50
60
|
});
|
|
51
61
|
|
|
52
62
|
return {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useInfiniteQuery } from '@tanstack/react-query';
|
|
2
|
+
import { type UseInventoryArgs, inventoryOptions } from '../queries/inventory';
|
|
3
|
+
import { useConfig } from './useConfig';
|
|
4
|
+
import { useMarketplaceConfig } from './useMarketplaceConfig';
|
|
5
|
+
|
|
6
|
+
export function useInventory(args: UseInventoryArgs) {
|
|
7
|
+
const config = useConfig();
|
|
8
|
+
const marketplaceConfig = useMarketplaceConfig();
|
|
9
|
+
const isLaos721 =
|
|
10
|
+
marketplaceConfig.data?.collections.find(
|
|
11
|
+
(c) => c.address === args.collectionAddress,
|
|
12
|
+
)?.isLAOSERC721 ?? false;
|
|
13
|
+
|
|
14
|
+
return useInfiniteQuery(inventoryOptions({ ...args, isLaos721 }, config));
|
|
15
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import {
|
|
3
|
+
type GetCountOfListingsForCollectibleReturn,
|
|
4
|
+
type GetCountOfOffersForCollectibleReturn,
|
|
5
|
+
type ListListingsForCollectibleReturn,
|
|
6
|
+
type ListOffersForCollectibleReturn,
|
|
7
|
+
collectableKeys,
|
|
8
|
+
} from '../../_internal';
|
|
9
|
+
|
|
10
|
+
const SECOND = 1000;
|
|
11
|
+
|
|
12
|
+
interface OptimisticCancelUpdatesParams {
|
|
13
|
+
orderId: string;
|
|
14
|
+
queryClient: QueryClient;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const updateQueriesOnCancel = ({
|
|
18
|
+
orderId,
|
|
19
|
+
queryClient,
|
|
20
|
+
}: OptimisticCancelUpdatesParams) => {
|
|
21
|
+
queryClient.setQueriesData(
|
|
22
|
+
{ queryKey: collectableKeys.offersCount, exact: false },
|
|
23
|
+
(oldData: GetCountOfOffersForCollectibleReturn | undefined) => {
|
|
24
|
+
if (!oldData) return { count: 0 };
|
|
25
|
+
return { count: Math.max(0, oldData.count - 1) };
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
console.log('query client ', queryClient, 'orderId', orderId);
|
|
30
|
+
|
|
31
|
+
// remove the offer with matching orderId
|
|
32
|
+
queryClient.setQueriesData(
|
|
33
|
+
{ queryKey: collectableKeys.offers, exact: false },
|
|
34
|
+
(oldData: ListOffersForCollectibleReturn | undefined) => {
|
|
35
|
+
if (!oldData || !oldData.offers) return oldData;
|
|
36
|
+
return {
|
|
37
|
+
...oldData,
|
|
38
|
+
offers: oldData.offers.filter((offer) => offer.orderId !== orderId),
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// 2 seconds is enough time for new data to be fetched
|
|
44
|
+
setTimeout(() => {
|
|
45
|
+
queryClient.invalidateQueries({
|
|
46
|
+
queryKey: collectableKeys.highestOffers,
|
|
47
|
+
exact: false,
|
|
48
|
+
});
|
|
49
|
+
}, 2 * SECOND);
|
|
50
|
+
|
|
51
|
+
queryClient.setQueriesData(
|
|
52
|
+
{ queryKey: collectableKeys.listingsCount, exact: false },
|
|
53
|
+
(oldData: GetCountOfListingsForCollectibleReturn | undefined) => {
|
|
54
|
+
if (!oldData) return { count: 0 };
|
|
55
|
+
return { count: Math.max(0, oldData.count - 1) };
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
queryClient.setQueriesData(
|
|
60
|
+
{ queryKey: collectableKeys.listings, exact: false },
|
|
61
|
+
(oldData: ListListingsForCollectibleReturn | undefined) => {
|
|
62
|
+
if (!oldData || !oldData.listings) return oldData;
|
|
63
|
+
return {
|
|
64
|
+
...oldData,
|
|
65
|
+
listings: oldData.listings.filter(
|
|
66
|
+
(listing) => listing.orderId !== orderId,
|
|
67
|
+
),
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// 2 seconds is enough time for new data to be fetched
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
queryClient.invalidateQueries({
|
|
75
|
+
queryKey: collectableKeys.lowestListings,
|
|
76
|
+
exact: false,
|
|
77
|
+
});
|
|
78
|
+
}, 2 * SECOND);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const invalidateQueriesOnCancel = ({
|
|
82
|
+
queryClient,
|
|
83
|
+
}: {
|
|
84
|
+
queryClient: QueryClient;
|
|
85
|
+
}) => {
|
|
86
|
+
queryClient.invalidateQueries({
|
|
87
|
+
queryKey: collectableKeys.offers,
|
|
88
|
+
exact: false,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
queryClient.invalidateQueries({
|
|
92
|
+
queryKey: collectableKeys.offersCount,
|
|
93
|
+
exact: false,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
queryClient.invalidateQueries({
|
|
97
|
+
queryKey: collectableKeys.listings,
|
|
98
|
+
exact: false,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
queryClient.invalidateQueries({
|
|
102
|
+
queryKey: collectableKeys.listingsCount,
|
|
103
|
+
exact: false,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
queryClient.invalidateQueries({
|
|
107
|
+
queryKey: collectableKeys.highestOffers,
|
|
108
|
+
exact: false,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
queryClient.invalidateQueries({
|
|
112
|
+
queryKey: collectableKeys.lowestListings,
|
|
113
|
+
exact: false,
|
|
114
|
+
});
|
|
115
|
+
};
|