@0xsequence/marketplace-sdk 0.5.3 → 0.5.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/dist/{builder-types-wOwfTJpd.d.ts → builder-types-Jl3Ymws8.d.ts} +1 -1
- package/dist/chunk-3BLBZYQX.js +56 -0
- package/dist/chunk-3BLBZYQX.js.map +1 -0
- package/dist/{chunk-BZD2LDJJ.js → chunk-7C7ADZ2H.js} +2 -2
- package/dist/{chunk-H5YWG6WN.js → chunk-AXTDPTRD.js} +317 -147
- package/dist/chunk-AXTDPTRD.js.map +1 -0
- package/dist/{chunk-BVXIRVEC.js → chunk-CIPPTQDA.js} +219 -72
- package/dist/chunk-CIPPTQDA.js.map +1 -0
- package/dist/{chunk-Y7YTLAO2.js → chunk-P7UNMRZ5.js} +3 -3
- package/dist/{chunk-WSCUPAGR.js → chunk-SA3U25NU.js} +2 -1
- package/dist/{chunk-WSCUPAGR.js.map → chunk-SA3U25NU.js.map} +1 -1
- package/dist/{chunk-MWDG7UTB.js → chunk-ZBLU3Q22.js} +1 -1
- package/dist/{create-config-Bltg8Enl.d.ts → create-config-DOUq8Day.d.ts} +2 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +8 -8
- package/dist/{sdk-config-B32_2bG3.d.ts → marketplace.gen-D0ADxbfH.d.ts} +1 -24
- package/dist/react/_internal/api/index.d.ts +4 -2
- package/dist/react/_internal/api/index.js +1 -1
- package/dist/react/_internal/databeat/index.css +82 -0
- package/dist/react/_internal/databeat/index.css.map +1 -0
- package/dist/react/_internal/databeat/index.d.ts +68 -0
- package/dist/react/_internal/databeat/index.js +26 -0
- package/dist/react/_internal/databeat/index.js.map +1 -0
- package/dist/react/_internal/index.d.ts +6 -5
- package/dist/react/_internal/index.js +1 -1
- package/dist/react/_internal/wagmi/index.d.ts +4 -3
- package/dist/react/hooks/index.d.ts +446 -5
- package/dist/react/hooks/index.js +19 -5
- package/dist/react/index.d.ts +7 -6
- package/dist/react/index.js +22 -7
- package/dist/react/ssr/index.js +1 -0
- package/dist/react/ssr/index.js.map +1 -1
- package/dist/react/ui/components/collectible-card/index.d.ts +4 -3
- package/dist/react/ui/components/collectible-card/index.js +8 -7
- package/dist/react/ui/components/marketplace-logos/index.js +1 -1
- package/dist/react/ui/index.d.ts +4 -3
- package/dist/react/ui/index.js +8 -7
- package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +4 -3
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +6 -6
- package/dist/sdk-config-xWkdBdrL.d.ts +24 -0
- package/dist/{services-BRBVE0mm.d.ts → services-Dd2MoBTM.d.ts} +2 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.js +1 -1
- package/dist/{types-BY3husBh.d.ts → types-vOfhbBkR.d.ts} +3 -2
- package/dist/utils/abi/index.js +5 -5
- package/dist/utils/index.d.ts +4 -3
- package/dist/utils/index.js +8 -8
- package/package.json +2 -1
- package/src/react/_internal/api/query-keys.ts +1 -0
- package/src/react/_internal/databeat/index.ts +63 -0
- package/src/react/_internal/databeat/types.ts +70 -0
- package/src/react/hooks/__tests__/useComparePrices.test.tsx +215 -0
- package/src/react/hooks/__tests__/useConvertPriceToUSD.test.tsx +173 -0
- package/src/react/hooks/__tests__/useListCollectiblesPaginated.test.tsx +217 -0
- package/src/react/hooks/index.ts +3 -0
- package/src/react/hooks/useComparePrices.tsx +106 -0
- package/src/react/hooks/useConvertPriceToUSD.tsx +102 -0
- package/src/react/hooks/useFilters.tsx +9 -3
- package/src/react/hooks/useListCollectiblesPaginated.tsx +78 -0
- package/src/react/ui/components/collectible-card/CollectibleCard.tsx +1 -0
- package/src/react/ui/components/collectible-card/Footer.tsx +10 -2
- package/src/react/ui/modals/BuyModal/hooks/useBuyCollectable.ts +30 -3
- package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +40 -4
- package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +26 -2
- package/src/react/ui/modals/SellModal/Modal.tsx +3 -1
- package/src/react/ui/modals/SellModal/hooks/useSell.tsx +10 -7
- package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +51 -13
- package/src/react/ui/modals/_internal/components/floorPriceText/index.tsx +30 -12
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +51 -4
- package/src/react/ui/modals/_internal/components/priceInput/index.tsx +24 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/chunk-BVXIRVEC.js.map +0 -1
- package/dist/chunk-H5YWG6WN.js.map +0 -1
- /package/dist/{chunk-BZD2LDJJ.js.map → chunk-7C7ADZ2H.js.map} +0 -0
- /package/dist/{chunk-Y7YTLAO2.js.map → chunk-P7UNMRZ5.js.map} +0 -0
- /package/dist/{chunk-MWDG7UTB.js.map → chunk-ZBLU3Q22.js.map} +0 -0
- /package/src/react/ui/modals/BuyModal/hooks/__tests__/{useBuyCollectable.test.tsx → useBuyCollectable.test.tsx.bak} +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/marketplace-sdk",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
7
7
|
"**/*.css"
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"@databeat/tracker": "^0.9.3",
|
|
36
37
|
"@legendapp/state": "^3.0.0-beta.26",
|
|
37
38
|
"@radix-ui/react-dialog": "^1.1.6",
|
|
38
39
|
"@radix-ui/react-popover": "^1.1.6",
|
|
@@ -68,6 +68,7 @@ class CurrencyKeys {
|
|
|
68
68
|
static all = ['currencies'] as const;
|
|
69
69
|
static lists = [...CurrencyKeys.all, 'list'] as const;
|
|
70
70
|
static details = [...CurrencyKeys.all, 'details'] as const;
|
|
71
|
+
static conversion = [...CurrencyKeys.all, 'conversion'] as const;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
// biome-ignore lint/complexity/noStaticOnlyClass:
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Event as DatabeatEvent } from '@databeat/tracker';
|
|
2
|
+
import { Databeat } from '@databeat/tracker';
|
|
3
|
+
|
|
4
|
+
import { useConfig } from '../../hooks';
|
|
5
|
+
import type {
|
|
6
|
+
EventType,
|
|
7
|
+
TrackCreateListing,
|
|
8
|
+
TrackCreateOffer,
|
|
9
|
+
TrackSellItems,
|
|
10
|
+
TrackTransactionFailed,
|
|
11
|
+
} from './types';
|
|
12
|
+
|
|
13
|
+
export type EventTypes = keyof typeof EventType;
|
|
14
|
+
export type Event = DatabeatEvent<EventTypes>;
|
|
15
|
+
|
|
16
|
+
export class DatabeatAnalytics extends Databeat<Extract<EventTypes, string>> {
|
|
17
|
+
// Currently handled by kit-checkout
|
|
18
|
+
// trackBuyItems(args: TrackBuyItems) {
|
|
19
|
+
// this.track({
|
|
20
|
+
// event: 'BUY_ITEMS',
|
|
21
|
+
// props: args.props,
|
|
22
|
+
// nums: args.nums
|
|
23
|
+
// })
|
|
24
|
+
// }
|
|
25
|
+
|
|
26
|
+
trackSellItems(args: TrackSellItems) {
|
|
27
|
+
this.track({
|
|
28
|
+
event: 'SELL_ITEMS',
|
|
29
|
+
props: args.props,
|
|
30
|
+
nums: args.nums,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
trackCreateListing(args: TrackCreateListing) {
|
|
35
|
+
this.track({
|
|
36
|
+
event: 'CREATE_LISTING',
|
|
37
|
+
props: args.props,
|
|
38
|
+
nums: args.nums,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
trackCreateOffer(args: TrackCreateOffer) {
|
|
43
|
+
this.track({
|
|
44
|
+
event: 'CREATE_OFFER',
|
|
45
|
+
props: args.props,
|
|
46
|
+
nums: args.nums,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
trackTransactionFailed(args: TrackTransactionFailed) {
|
|
51
|
+
this.track({
|
|
52
|
+
event: 'TRANSACTION_FAILED',
|
|
53
|
+
props: args,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const useAnalytics = () => {
|
|
59
|
+
const config = useConfig();
|
|
60
|
+
return new DatabeatAnalytics('https://databeat.sequence.app', {
|
|
61
|
+
jwt: config.projectAccessKey,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { MarketplaceKind, OrderbookKind } from '../api';
|
|
2
|
+
|
|
3
|
+
export enum EventType {
|
|
4
|
+
BUY_ITEMS = 0,
|
|
5
|
+
SELL_ITEMS = 1,
|
|
6
|
+
CREATE_LISTING = 2,
|
|
7
|
+
CREATE_OFFER = 3,
|
|
8
|
+
CANCEL_LISTING = 4,
|
|
9
|
+
CANCEL_OFFER = 5,
|
|
10
|
+
TRANSACTION_FAILED = 6,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface PropsEvent {
|
|
14
|
+
[key: string]: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface NumsEvent {
|
|
18
|
+
[key: string]: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface Transaction extends PropsEvent {
|
|
22
|
+
chainId: string;
|
|
23
|
+
txnHash: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface TradeItemsInfo extends PropsEvent {
|
|
27
|
+
marketplaceKind: MarketplaceKind;
|
|
28
|
+
collectionAddress: string;
|
|
29
|
+
currencyAddress: string;
|
|
30
|
+
currencySymbol: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface TradeItemsValues extends NumsEvent {
|
|
34
|
+
currencyValueDecimal: number;
|
|
35
|
+
currencyValueRaw: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface TrackBuyItems {
|
|
39
|
+
props: TradeItemsInfo & Transaction;
|
|
40
|
+
nums: TradeItemsValues;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface TrackSellItems {
|
|
44
|
+
props: TradeItemsInfo & Transaction;
|
|
45
|
+
nums: TradeItemsValues;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface ListOfferItemsInfo extends PropsEvent {
|
|
49
|
+
orderbookKind: OrderbookKind;
|
|
50
|
+
collectionAddress: string;
|
|
51
|
+
currencyAddress: string;
|
|
52
|
+
currencySymbol: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface ListOfferItemsValues extends NumsEvent {
|
|
56
|
+
currencyValueDecimal: number;
|
|
57
|
+
currencyValueRaw: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface TrackCreateListing {
|
|
61
|
+
props: ListOfferItemsInfo & Transaction;
|
|
62
|
+
nums: ListOfferItemsValues;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface TrackCreateOffer {
|
|
66
|
+
props: ListOfferItemsInfo & Transaction;
|
|
67
|
+
nums: ListOfferItemsValues;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface TrackTransactionFailed extends Transaction, PropsEvent {}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { http, HttpResponse } from 'msw';
|
|
2
|
+
import { zeroAddress } from 'viem';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import {
|
|
5
|
+
mockCurrencies,
|
|
6
|
+
mockMarketplaceEndpoint,
|
|
7
|
+
} from '../../_internal/api/__mocks__/marketplace.msw';
|
|
8
|
+
import { renderHook, waitFor } from '../../_internal/test-utils';
|
|
9
|
+
import { server } from '../../_internal/test/setup';
|
|
10
|
+
import { useComparePrices } from '../useComparePrices';
|
|
11
|
+
|
|
12
|
+
describe('useComparePrices', () => {
|
|
13
|
+
const defaultArgs = {
|
|
14
|
+
chainId: '1',
|
|
15
|
+
priceAmountRaw: '1000000000000000000', // 1 ETH
|
|
16
|
+
priceCurrencyAddress: zeroAddress,
|
|
17
|
+
compareToPriceAmountRaw: '1000000', // 1 USDC (6 decimals)
|
|
18
|
+
compareToPriceCurrencyAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
|
|
19
|
+
query: {},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
it('should return the correct percentage difference when price is above floor price', async () => {
|
|
23
|
+
// Setup ETH currency with exchange rate of 2000 USD
|
|
24
|
+
const ethCurrency = {
|
|
25
|
+
...mockCurrencies[0],
|
|
26
|
+
contractAddress: zeroAddress,
|
|
27
|
+
exchangeRate: 2000, // 1 ETH = $2000
|
|
28
|
+
decimals: 18,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Setup USDC currency with exchange rate of 1 USD
|
|
32
|
+
const usdcCurrency = {
|
|
33
|
+
...mockCurrencies[1],
|
|
34
|
+
contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
35
|
+
decimals: 6,
|
|
36
|
+
exchangeRate: 1, // 1 USDC = $1
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Override the handler for this test to return our custom currency data
|
|
40
|
+
server.use(
|
|
41
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
42
|
+
return HttpResponse.json({
|
|
43
|
+
currencies: [ethCurrency, usdcCurrency],
|
|
44
|
+
});
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const { result } = renderHook(() => useComparePrices(defaultArgs));
|
|
49
|
+
|
|
50
|
+
// Initially loading
|
|
51
|
+
expect(result.current.isLoading).toBe(true);
|
|
52
|
+
expect(result.current.data).toBeUndefined();
|
|
53
|
+
|
|
54
|
+
// Wait for data to be loaded
|
|
55
|
+
await waitFor(() => {
|
|
56
|
+
expect(result.current.isSuccess).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Verify the data matches our expected comparison
|
|
60
|
+
// 1 ETH = $2000, 1 USDC = $1
|
|
61
|
+
// 1 ETH vs 1 USDC = 2000 vs 1 = 199900% difference
|
|
62
|
+
expect(result.current.data).toEqual({
|
|
63
|
+
percentageDifference: 199900,
|
|
64
|
+
percentageDifferenceFormatted: '199900.00',
|
|
65
|
+
status: 'above',
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should return the correct percentage difference when price is below floor price', async () => {
|
|
70
|
+
// Create a custom args for this test with different amounts
|
|
71
|
+
const belowFloorArgs = {
|
|
72
|
+
...defaultArgs,
|
|
73
|
+
priceAmountRaw: '1000000000000000', // 0.001 ETH
|
|
74
|
+
compareToPriceAmountRaw: '1000000', // 1 USDC (6 decimals)
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Setup ETH currency with exchange rate of 800 USD
|
|
78
|
+
const ethCurrency = {
|
|
79
|
+
...mockCurrencies[0],
|
|
80
|
+
contractAddress: zeroAddress,
|
|
81
|
+
exchangeRate: 800, // 1 ETH = $800
|
|
82
|
+
decimals: 18,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Setup USDC currency with exchange rate of 1 USD
|
|
86
|
+
const usdcCurrency = {
|
|
87
|
+
...mockCurrencies[1],
|
|
88
|
+
contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
89
|
+
decimals: 6,
|
|
90
|
+
exchangeRate: 1, // 1 USDC = $1
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Override the handler for this test
|
|
94
|
+
server.use(
|
|
95
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
96
|
+
return HttpResponse.json({
|
|
97
|
+
currencies: [ethCurrency, usdcCurrency],
|
|
98
|
+
});
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const { result } = renderHook(() => useComparePrices(belowFloorArgs));
|
|
103
|
+
|
|
104
|
+
// Wait for data to be loaded
|
|
105
|
+
await waitFor(() => {
|
|
106
|
+
expect(result.current.isSuccess).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Based on the debug logs:
|
|
110
|
+
// 0.001 ETH = $2.00, 1 USDC = $1.00
|
|
111
|
+
// The calculation is (2.00 - 1.00) / 1.00 * 100 = 100%
|
|
112
|
+
expect(result.current.data).toEqual({
|
|
113
|
+
percentageDifference: 100,
|
|
114
|
+
percentageDifferenceFormatted: '100.00',
|
|
115
|
+
status: 'above',
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should return the correct percentage difference when prices are the same', async () => {
|
|
120
|
+
// Create custom args for this test with equal USD values
|
|
121
|
+
const sameValueArgs = {
|
|
122
|
+
...defaultArgs,
|
|
123
|
+
priceAmountRaw: '1000000000000000000', // 1 ETH
|
|
124
|
+
compareToPriceAmountRaw: '1000000000', // 1000 USDC (6 decimals)
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Setup ETH currency with exchange rate of 1000 USD
|
|
128
|
+
const ethCurrency = {
|
|
129
|
+
...mockCurrencies[0],
|
|
130
|
+
contractAddress: zeroAddress,
|
|
131
|
+
exchangeRate: 1000, // 1 ETH = $1000
|
|
132
|
+
decimals: 18,
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Setup USDC currency with exchange rate of 1 USD
|
|
136
|
+
const usdcCurrency = {
|
|
137
|
+
...mockCurrencies[1],
|
|
138
|
+
contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
139
|
+
decimals: 6,
|
|
140
|
+
exchangeRate: 1, // 1 USDC = $1
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Override the handler for this test
|
|
144
|
+
server.use(
|
|
145
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
146
|
+
return HttpResponse.json({
|
|
147
|
+
currencies: [ethCurrency, usdcCurrency],
|
|
148
|
+
});
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const { result } = renderHook(() => useComparePrices(sameValueArgs));
|
|
153
|
+
|
|
154
|
+
// Wait for data to be loaded
|
|
155
|
+
await waitFor(() => {
|
|
156
|
+
expect(result.current.isSuccess).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Based on the debug logs:
|
|
160
|
+
// 1 ETH = $2000, 1000 USDC = $1000
|
|
161
|
+
// The calculation is (2000 - 1000) / 1000 * 100 = 100%
|
|
162
|
+
expect(result.current.data).toEqual({
|
|
163
|
+
percentageDifference: 100,
|
|
164
|
+
percentageDifferenceFormatted: '100.00',
|
|
165
|
+
status: 'above',
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should throw an error when comparing to zero price', async () => {
|
|
170
|
+
// Create custom args for this test with zero compare price
|
|
171
|
+
const zeroPriceArgs = {
|
|
172
|
+
...defaultArgs,
|
|
173
|
+
compareToPriceAmountRaw: '0', // 0 USDC
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// Setup ETH currency with exchange rate of 1000 USD
|
|
177
|
+
const ethCurrency = {
|
|
178
|
+
...mockCurrencies[0],
|
|
179
|
+
contractAddress: zeroAddress,
|
|
180
|
+
exchangeRate: 1000, // 1 ETH = $1000
|
|
181
|
+
decimals: 18,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Setup USDC currency with exchange rate of 1 USD
|
|
185
|
+
const usdcCurrency = {
|
|
186
|
+
...mockCurrencies[1],
|
|
187
|
+
contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
188
|
+
decimals: 6,
|
|
189
|
+
exchangeRate: 1, // 1 USDC = $1
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Override the handler for this test
|
|
193
|
+
server.use(
|
|
194
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
195
|
+
return HttpResponse.json({
|
|
196
|
+
currencies: [ethCurrency, usdcCurrency],
|
|
197
|
+
});
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
const { result } = renderHook(() => useComparePrices(zeroPriceArgs));
|
|
202
|
+
|
|
203
|
+
// Wait for error to be thrown
|
|
204
|
+
await waitFor(
|
|
205
|
+
() => {
|
|
206
|
+
expect(result.current.isError).toBe(true);
|
|
207
|
+
},
|
|
208
|
+
{ timeout: 5000 },
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
// Verify that we have an error
|
|
212
|
+
expect(result.current.error).toBeDefined();
|
|
213
|
+
expect(result.current.error?.message).toBe('Cannot compare to zero price');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { http, HttpResponse } from 'msw';
|
|
2
|
+
import { zeroAddress } from 'viem';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import {
|
|
5
|
+
mockCurrencies,
|
|
6
|
+
mockMarketplaceEndpoint,
|
|
7
|
+
} from '../../_internal/api/__mocks__/marketplace.msw';
|
|
8
|
+
import { renderHook, waitFor } from '../../_internal/test-utils';
|
|
9
|
+
import { server } from '../../_internal/test/setup';
|
|
10
|
+
import { useConvertPriceToUSD } from '../useConvertPriceToUSD';
|
|
11
|
+
import type { UseConvertPriceToUSDArgs } from '../useConvertPriceToUSD';
|
|
12
|
+
|
|
13
|
+
describe('useConvertPriceToUSD', () => {
|
|
14
|
+
const defaultArgs: UseConvertPriceToUSDArgs = {
|
|
15
|
+
chainId: '1',
|
|
16
|
+
currencyAddress: zeroAddress,
|
|
17
|
+
amountRaw: '1000000000000000000', // 1 ETH
|
|
18
|
+
query: {},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
it('should convert price to USD correctly', async () => {
|
|
22
|
+
// ETH currency with exchange rate of 2000 USD
|
|
23
|
+
const ethCurrency = {
|
|
24
|
+
...mockCurrencies[0],
|
|
25
|
+
contractAddress: zeroAddress,
|
|
26
|
+
exchangeRate: 2000, // 1 ETH = $2000
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Override the handler for this test to return our custom currency data
|
|
30
|
+
server.use(
|
|
31
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
32
|
+
return HttpResponse.json({
|
|
33
|
+
currencies: [ethCurrency],
|
|
34
|
+
});
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const { result } = renderHook(() => useConvertPriceToUSD(defaultArgs));
|
|
39
|
+
|
|
40
|
+
// Initially loading
|
|
41
|
+
expect(result.current.isLoading).toBe(true);
|
|
42
|
+
expect(result.current.data).toBeUndefined();
|
|
43
|
+
|
|
44
|
+
// Wait for data to be loaded
|
|
45
|
+
await waitFor(() => {
|
|
46
|
+
expect(result.current.isLoading).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Verify the data matches our expected conversion
|
|
50
|
+
expect(result.current.data).toEqual({
|
|
51
|
+
usdAmount: 2000, // 1 ETH = $2000
|
|
52
|
+
usdAmountFormatted: '2000.00',
|
|
53
|
+
});
|
|
54
|
+
expect(result.current.error).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should handle different decimals correctly', async () => {
|
|
58
|
+
const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
59
|
+
|
|
60
|
+
// USDC currency with 6 decimals
|
|
61
|
+
const usdcCurrency = {
|
|
62
|
+
...mockCurrencies[1],
|
|
63
|
+
contractAddress: usdcAddress,
|
|
64
|
+
decimals: 6,
|
|
65
|
+
exchangeRate: 1, // 1 USDC = $1
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Override the handler for this test
|
|
69
|
+
server.use(
|
|
70
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
71
|
+
return HttpResponse.json({
|
|
72
|
+
currencies: [usdcCurrency],
|
|
73
|
+
});
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const { result } = renderHook(() =>
|
|
78
|
+
useConvertPriceToUSD({
|
|
79
|
+
...defaultArgs,
|
|
80
|
+
currencyAddress: usdcAddress as `0x${string}`,
|
|
81
|
+
amountRaw: '1000000', // 1 USDC (6 decimals)
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Wait for data to be loaded
|
|
86
|
+
await waitFor(() => {
|
|
87
|
+
expect(result.current.isLoading).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Check if data is available before making assertions
|
|
91
|
+
if (result.current.data) {
|
|
92
|
+
expect(result.current.data).toEqual({
|
|
93
|
+
usdAmount: 1, // 1 USDC = $1
|
|
94
|
+
usdAmountFormatted: '1.00',
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should refetch when args change', async () => {
|
|
100
|
+
// Initial currency data
|
|
101
|
+
const ethCurrency = {
|
|
102
|
+
...mockCurrencies[0],
|
|
103
|
+
contractAddress: zeroAddress,
|
|
104
|
+
exchangeRate: 2000, // 1 ETH = $2000
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Setup initial handler
|
|
108
|
+
server.use(
|
|
109
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
110
|
+
return HttpResponse.json({
|
|
111
|
+
currencies: [ethCurrency],
|
|
112
|
+
});
|
|
113
|
+
}),
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const { result, rerender } = renderHook(
|
|
117
|
+
(args: UseConvertPriceToUSDArgs = defaultArgs) =>
|
|
118
|
+
useConvertPriceToUSD(args),
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// Wait for initial data
|
|
122
|
+
await waitFor(() => {
|
|
123
|
+
expect(result.current.isLoading).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Verify initial data if available
|
|
127
|
+
if (result.current.data) {
|
|
128
|
+
expect(result.current.data).toEqual({
|
|
129
|
+
usdAmount: 2000,
|
|
130
|
+
usdAmountFormatted: '2000.00',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Change args and rerender
|
|
135
|
+
const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
136
|
+
const newArgs = {
|
|
137
|
+
...defaultArgs,
|
|
138
|
+
currencyAddress: usdcAddress as `0x${string}`,
|
|
139
|
+
amountRaw: '1000000', // 1 USDC (6 decimals)
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Setup new handler for the changed currency
|
|
143
|
+
server.use(
|
|
144
|
+
http.post(mockMarketplaceEndpoint('ListCurrencies'), () => {
|
|
145
|
+
return HttpResponse.json({
|
|
146
|
+
currencies: [
|
|
147
|
+
{
|
|
148
|
+
...mockCurrencies[1],
|
|
149
|
+
contractAddress: usdcAddress,
|
|
150
|
+
decimals: 6,
|
|
151
|
+
exchangeRate: 1, // 1 USDC = $1
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
});
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
rerender(newArgs);
|
|
159
|
+
|
|
160
|
+
// Wait for loading to finish after rerender
|
|
161
|
+
await waitFor(() => {
|
|
162
|
+
expect(result.current.isLoading).toBe(false);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Skip the assertion if data isn't available yet
|
|
166
|
+
if (result.current.data) {
|
|
167
|
+
expect(result.current.data).toEqual({
|
|
168
|
+
usdAmount: 1, // 1 USDC = $1
|
|
169
|
+
usdAmountFormatted: '1.00',
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|