@0xsequence/marketplace-sdk 0.8.12 → 0.10.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.
- package/.storybook/main.ts +63 -0
- package/.storybook/preview.ts +24 -0
- package/.storybook/vitest.setup.ts +6 -0
- package/CHANGELOG.md +158 -21
- package/dist/{CartIcon-Bll1rbxv.js → CalendarIcon-CqsuAuCm.js} +30 -77
- package/dist/CalendarIcon-CqsuAuCm.js.map +1 -0
- package/dist/{types-BIJOaL4j.d.ts → CollectibleCard-Dd-CG6dE.d.ts} +11 -7
- package/dist/InfoIcon-v0w_Lu7t.js +53 -0
- package/dist/InfoIcon-v0w_Lu7t.js.map +1 -0
- package/dist/_internal-C75gOSNo.js +14 -0
- package/dist/_internal-C75gOSNo.js.map +1 -0
- package/dist/actionModal-CMUeVsFX.js +116 -0
- package/dist/actionModal-CMUeVsFX.js.map +1 -0
- package/dist/{alien_swap-B_76IMma.js → alien_swap-CYv6YlOF.js} +1 -1
- package/dist/{alien_swap-B_76IMma.js.map → alien_swap-CYv6YlOF.js.map} +1 -1
- package/dist/{api-1KFxYh7o.js → api-BiMGqWdz.js} +79 -87
- package/dist/api-BiMGqWdz.js.map +1 -0
- package/dist/{aqua-xyz-CMN_TFY5.js → aqua-xyz-Bzn5baeH.js} +1 -1
- package/dist/{aqua-xyz-CMN_TFY5.js.map → aqua-xyz-Bzn5baeH.js.map} +1 -1
- package/dist/{aura-Cye_TuHj.js → aura-DzIWh8WT.js} +1 -1
- package/dist/{aura-Cye_TuHj.js.map → aura-DzIWh8WT.js.map} +1 -1
- package/dist/base-DqaJPvfN.js +22 -0
- package/dist/base-DqaJPvfN.js.map +1 -0
- package/dist/{blur-DWDMyMpK.js → blur-DSH-Cbpj.js} +1 -1
- package/dist/{blur-DWDMyMpK.js.map → blur-DSH-Cbpj.js.map} +1 -1
- package/dist/{builder-api-BQvzykoU.js → builder-api-BFuZNOaN.js} +2 -2
- package/dist/{builder-api-BQvzykoU.js.map → builder-api-BFuZNOaN.js.map} +1 -1
- package/dist/{builder.gen-CxP9NT1p.js → builder.gen-B9wR2nvF.js} +1 -1
- package/dist/builder.gen-B9wR2nvF.js.map +1 -0
- package/dist/{coinbase-ByA_XRB0.js → coinbase-Df8URNxq.js} +1 -1
- package/dist/{coinbase-ByA_XRB0.js.map → coinbase-Df8URNxq.js.map} +1 -1
- package/dist/{sdk-config-DJzxVPld.d.ts → create-config-DKJ-F0jc.d.ts} +458 -86
- package/dist/{wagmi-DRctYEk6.js → create-config-fQ-jbJD1.js} +33 -16
- package/dist/create-config-fQ-jbJD1.js.map +1 -0
- package/dist/{element-b77CyXIZ.js → element-Cx6uJu5N.js} +1 -1
- package/dist/{element-b77CyXIZ.js.map → element-Cx6uJu5N.js.map} +1 -1
- package/dist/{foundation-DbOrKP9Y.js → foundation-D6U4aRLN.js} +1 -1
- package/dist/{foundation-DbOrKP9Y.js.map → foundation-D6U4aRLN.js.map} +1 -1
- package/dist/get-provider-CYYHfrlg.js +10 -0
- package/dist/get-provider-CYYHfrlg.js.map +1 -0
- package/dist/get-query-client-D19vvfJo.js +23 -0
- package/dist/get-query-client-D19vvfJo.js.map +1 -0
- package/dist/hooks-4pxIbLbM.js +4044 -0
- package/dist/hooks-4pxIbLbM.js.map +1 -0
- package/dist/{index-1bezgsFq.d.ts → index-136YrWDH.d.ts} +929 -255
- package/dist/{index-D5v5iluA.d.ts → index-BAhaEfqY.d.ts} +1 -1
- package/dist/index-BKBin-rq.d.ts +979 -0
- package/dist/index-BUWB_RXp.d.ts +3144 -0
- package/dist/{index-Cl7PQOGu.d.ts → index-BhVFc2rX.d.ts} +28 -25
- package/dist/{index-DXMfTZ1F.d.ts → index-C5aqo8xu.d.ts} +1 -1
- package/dist/{index-BIMIpDiI.d.ts → index-CKrYP7ot.d.ts} +74 -103
- package/dist/{index-BEYefG1G.d.ts → index-CUwMH7Ht.d.ts} +5 -5
- package/dist/{index-BjIwVzc4.d.ts → index-Cu70Lw-w.d.ts} +238 -238
- package/dist/index.css +427 -1
- package/dist/index.d.ts +8 -10
- package/dist/index.js +15 -11
- package/dist/{looks-rare-C1VqNcSM.js → looks-rare-ChBRBY-p.js} +1 -1
- package/dist/{looks-rare-C1VqNcSM.js.map → looks-rare-ChBRBY-p.js.map} +1 -1
- package/dist/{magic-eden-ea_AGCZr.js → magic-eden-D5U7N1xL.js} +1 -1
- package/dist/{magic-eden-ea_AGCZr.js.map → magic-eden-D5U7N1xL.js.map} +1 -1
- package/dist/{manifold-8y8J2sjT.js → manifold-CtLF52zU.js} +1 -1
- package/dist/{manifold-8y8J2sjT.js.map → manifold-CtLF52zU.js.map} +1 -1
- package/dist/{marketplace-nwnZv9Cb.js → marketplace-DmFiyBoS.js} +1 -1
- package/dist/{marketplace-nwnZv9Cb.js.map → marketplace-DmFiyBoS.js.map} +1 -1
- package/dist/{marketplace-logos-CSeGcPW4.js → marketplace-logos-Cd6W-qOq.js} +21 -21
- package/dist/{marketplace-logos-CSeGcPW4.js.map → marketplace-logos-Cd6W-qOq.js.map} +1 -1
- package/dist/{marketplace.gen-Dqk8vRmD.js → marketplace.gen-HpnpL5xU.js} +12 -3
- package/dist/marketplace.gen-HpnpL5xU.js.map +1 -0
- package/dist/{marketplaceConfig-D2MYFqll.js → marketplaceConfig-GQTTmihy.js} +3 -3
- package/dist/marketplaceConfig-GQTTmihy.js.map +1 -0
- package/dist/{mintify-LA68TzWg.js → mintify-Bi3Bce68.js} +1 -1
- package/dist/{mintify-LA68TzWg.js.map → mintify-Bi3Bce68.js.map} +1 -1
- package/dist/network-CGD0oKtS.js +15 -0
- package/dist/network-CGD0oKtS.js.map +1 -0
- package/dist/{nftx-D3Tc8nzd.js → nftx-BDQZjtkX.js} +1 -1
- package/dist/{nftx-D3Tc8nzd.js.map → nftx-BDQZjtkX.js.map} +1 -1
- package/dist/{okx-hbqg6oIJ.js → okx-D4meadLe.js} +1 -1
- package/dist/{okx-hbqg6oIJ.js.map → okx-D4meadLe.js.map} +1 -1
- package/dist/{open-sea-BccuK8-t.js → open-sea-DN0hgfVw.js} +1 -1
- package/dist/{open-sea-BccuK8-t.js.map → open-sea-DN0hgfVw.js.map} +1 -1
- package/dist/options-BBBR8u_4.js +0 -0
- package/dist/{primary-sale-Cw95phYC.js → primary-sale-CmWxSfFQ.js} +279 -279
- package/dist/primary-sale-CmWxSfFQ.js.map +1 -0
- package/dist/provider-DPGUA10G.js +125 -0
- package/dist/provider-DPGUA10G.js.map +1 -0
- package/dist/queries-Ce_2othB.js +757 -0
- package/dist/queries-Ce_2othB.js.map +1 -0
- package/dist/{rarible-BgTwwj9g.js → rarible-B0xlD88A.js} +1 -1
- package/dist/{rarible-BgTwwj9g.js.map → rarible-B0xlD88A.js.map} +1 -1
- package/dist/react/_internal/api/index.d.ts +2 -4
- package/dist/react/_internal/api/index.js +9 -6
- package/dist/react/_internal/databeat/index.d.ts +2 -73
- package/dist/react/_internal/databeat/index.js +4 -21
- package/dist/react/_internal/index.d.ts +2 -7
- package/dist/react/_internal/index.js +13 -8
- package/dist/react/_internal/wagmi/index.d.ts +2 -4
- package/dist/react/_internal/wagmi/index.js +6 -4
- package/dist/react/hooks/index.d.ts +13 -17
- package/dist/react/hooks/index.js +25 -21
- package/dist/react/hooks/options/index.d.ts +3 -5
- package/dist/react/hooks/options/index.js +15 -10
- package/dist/react/index.d.ts +13 -40
- package/dist/react/index.js +30 -21
- package/dist/react/queries/index.d.ts +9 -8
- package/dist/react/queries/index.js +22 -17
- package/dist/react/ssr/index.d.ts +7 -9
- package/dist/react/ssr/index.js +13 -8
- package/dist/react/ssr/index.js.map +1 -1
- package/dist/react/ui/components/marketplace-collectible-card/index.d.ts +3 -9
- package/dist/react/ui/components/marketplace-collectible-card/index.js +29 -20
- package/dist/react/ui/components/marketplace-collectible-card/utils/index.d.ts +2 -7
- package/dist/react/ui/components/marketplace-collectible-card/utils/index.js +13 -8
- package/dist/react/ui/components/marketplace-logos/index.d.ts +21 -21
- package/dist/react/ui/components/marketplace-logos/index.js +1 -1
- package/dist/react/ui/icons/index.js +14 -10
- package/dist/react/ui/index.d.ts +3 -9
- package/dist/react/ui/index.js +29 -20
- package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +5 -5
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +25 -20
- package/dist/{react-BG7o4PId.js → react-DP0M2Wfm.js} +4919 -7839
- package/dist/react-DP0M2Wfm.js.map +1 -0
- package/dist/{react-BbHBl6gg.css → react-DeDyTgo7.css} +1 -1
- package/dist/{react-BbHBl6gg.css.map → react-DeDyTgo7.css.map} +1 -1
- package/dist/{sequence-Do3kzb4J.js → sequence-BIrOVRXO.js} +1 -1
- package/dist/{sequence-Do3kzb4J.js.map → sequence-BIrOVRXO.js.map} +1 -1
- package/dist/{sudo-swap-B6vPKxBz.js → sudo-swap-BPMon-M5.js} +1 -1
- package/dist/{sudo-swap-B6vPKxBz.js.map → sudo-swap-BPMon-M5.js.map} +1 -1
- package/dist/{super-rare-eCm1SE6O.js → super-rare-kPN6Ua8i.js} +1 -1
- package/dist/{super-rare-eCm1SE6O.js.map → super-rare-kPN6Ua8i.js.map} +1 -1
- package/dist/{token-CO5llIla.js → token-CHSBPYVG.js} +1540 -761
- package/dist/token-CHSBPYVG.js.map +1 -0
- package/dist/{transaction-CcVViHEL.js → transaction-CnctdNzS.js} +3 -21
- package/dist/transaction-CnctdNzS.js.map +1 -0
- package/dist/types/index.d.ts +2 -3
- package/dist/types/index.js +3 -3
- package/dist/{types-DwWE6xOF.js → types-Yw2ywj6j.js} +1 -1
- package/dist/types-Yw2ywj6j.js.map +1 -0
- package/dist/utils/abi/index.d.ts +5 -5
- package/dist/utils/abi/index.js +5 -5
- package/dist/utils/abi/marketplace/index.d.ts +1 -1
- package/dist/utils/abi/marketplace/index.js +1 -1
- package/dist/utils/abi/primary-sale/index.d.ts +1 -1
- package/dist/utils/abi/primary-sale/index.js +1 -1
- package/dist/utils/abi/token/index.d.ts +2 -2
- package/dist/utils/abi/token/index.js +2 -2
- package/dist/utils/index.d.ts +7 -8
- package/dist/utils/index.js +13 -10
- package/dist/{utils-BFdxaToy.js → utils-9RXDgcBl.js} +86 -93
- package/dist/utils-9RXDgcBl.js.map +1 -0
- package/dist/{utils-Cat9_pef.js → utils-DjVJ9tov.js} +5 -6
- package/dist/utils-DjVJ9tov.js.map +1 -0
- package/dist/wagmi-Do_KW5ke.js +0 -0
- package/dist/{x2y2-DD17tT91.js → x2y2-BLz-_Q2O.js} +1 -1
- package/dist/{x2y2-DD17tT91.js.map → x2y2-BLz-_Q2O.js.map} +1 -1
- package/dist/{zora-BpSG9UzS.js → zora-UGhKs-aL.js} +1 -1
- package/dist/{zora-BpSG9UzS.js.map → zora-UGhKs-aL.js.map} +1 -1
- package/eslint/use-client.js +0 -6
- package/eslint.config.mjs +4 -0
- package/package.json +47 -35
- package/postcss.config.mjs +6 -0
- package/src/index.css +5 -4
- package/src/index.ts +2 -1
- package/src/react/__tests__/provider.test.tsx +4 -3
- package/src/react/_internal/api/__mocks__/builder.msw.ts +5 -3
- package/src/react/_internal/api/__mocks__/indexer.msw.ts +24 -8
- package/src/react/_internal/api/__mocks__/laos.msw.ts +387 -0
- package/src/react/_internal/api/__mocks__/marketplace.msw.ts +6 -6
- package/src/react/_internal/api/__mocks__/metadata.msw.ts +1 -1
- package/src/react/_internal/api/__tests__/laos-api.test.ts +756 -0
- package/src/react/_internal/api/builder.gen.ts +6 -6
- package/src/react/_internal/api/get-query-client.ts +2 -2
- package/src/react/_internal/api/index.ts +2 -2
- package/src/react/_internal/api/laos-api.ts +3 -0
- package/src/react/_internal/api/marketplace.gen.ts +43 -3
- package/src/react/_internal/api/query-keys.ts +21 -6
- package/src/react/_internal/api/services.ts +30 -45
- package/src/react/_internal/databeat/index.ts +15 -14
- package/src/react/_internal/databeat/types.ts +22 -0
- package/src/react/_internal/databeat/utils.ts +26 -0
- package/src/react/_internal/index.ts +1 -1
- package/src/react/_internal/types.ts +10 -23
- package/src/react/_internal/utils.ts +4 -5
- package/src/react/_internal/wagmi/create-config.ts +43 -19
- package/src/react/_internal/wagmi/get-connectors.ts +9 -7
- package/src/react/_internal/wallet/__tests__/wallet.test.ts +1 -1
- package/src/react/_internal/wallet/wallet.ts +22 -22
- package/src/react/hooks/__tests__/__snapshots__/useListCollections.test.tsx.snap +20 -0
- package/src/react/hooks/__tests__/__snapshots__/useMarketplaceConfig.test.tsx.snap +12 -2
- package/src/react/hooks/__tests__/useAutoSelectFeeOption.test.tsx +1 -1
- package/src/react/hooks/__tests__/useBalanceOfCollectible.laos.test.tsx +367 -0
- package/src/react/hooks/__tests__/useBalanceOfCollectible.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCancelOrder.test.tsx +4 -4
- package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCheckoutOptions.test.tsx +158 -0
- package/src/react/hooks/__tests__/useCheckoutOptionsSalesContract.test.tsx +42 -65
- package/src/react/hooks/__tests__/useCollectible.test.tsx +14 -16
- package/src/react/hooks/__tests__/useCollection.test.tsx +4 -4
- package/src/react/hooks/__tests__/useCollectionBalanceDetails.test.tsx +16 -25
- package/src/react/hooks/__tests__/useCollectionDetails.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCollectionDetailsPolling.test.tsx +12 -4
- package/src/react/hooks/__tests__/useComparePrices.test.tsx +7 -6
- package/src/react/hooks/__tests__/useConvertPriceToUSD.test.tsx +4 -4
- package/src/react/hooks/__tests__/useCountListingsForCollectible.test.tsx +2 -2
- package/src/react/hooks/__tests__/useCountOfCollectables.test.tsx +5 -5
- package/src/react/hooks/__tests__/useCountOffersForCollectible.test.tsx +2 -2
- package/src/react/hooks/__tests__/useCurrency.test.tsx +5 -3
- package/src/react/hooks/__tests__/useCurrencyBalance.test.tsx +7 -3
- package/src/react/hooks/__tests__/useFilters.test.tsx +3 -3
- package/src/react/hooks/__tests__/useFloorOrder.test.tsx +4 -4
- package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +3 -3
- package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +1 -1
- package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +1 -1
- package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +1 -1
- package/src/react/hooks/__tests__/useGetTokenRanges.test.tsx +111 -0
- package/src/react/hooks/__tests__/useHighestOffer.test.tsx +4 -4
- package/src/react/hooks/__tests__/useInventory.test.tsx +1 -1
- package/src/react/hooks/__tests__/useListCollectibleActivities.test.tsx +11 -13
- package/src/react/hooks/__tests__/useListCollectibles.test.tsx +5 -5
- package/src/react/hooks/__tests__/useListCollectiblesPaginated.test.tsx +10 -15
- package/src/react/hooks/__tests__/useListCollectionActivities.test.tsx +13 -15
- package/src/react/hooks/__tests__/useListCollections.test.tsx +3 -3
- package/src/react/hooks/__tests__/useListListingsForCollectible.test.tsx +3 -2
- package/src/react/hooks/__tests__/useListMarketCardData.test.tsx +301 -0
- package/src/react/hooks/__tests__/useListOffersForCollectible.test.tsx +1 -1
- package/src/react/hooks/__tests__/useListTokenMetadata.test.tsx +137 -0
- package/src/react/hooks/__tests__/useLowestListing.test.tsx +1 -1
- package/src/react/hooks/__tests__/useMarketCurrencies.test.tsx +1 -1
- package/src/react/hooks/__tests__/useRoyalty.test.tsx +0 -23
- package/src/react/hooks/__tests__/useTransferTokens.test.tsx +469 -0
- package/src/react/hooks/index.ts +29 -24
- package/src/react/hooks/options/index.ts +0 -1
- package/src/react/hooks/useAutoSelectFeeOption.tsx +1 -1
- package/src/react/hooks/useBalanceOfCollectible.tsx +1 -1
- package/src/react/hooks/useCancelTransactionSteps.tsx +2 -2
- package/src/react/hooks/useCheckoutOptions.tsx +84 -54
- package/src/react/hooks/useCheckoutOptionsSalesContract.tsx +98 -57
- package/src/react/hooks/useCollectible.tsx +64 -49
- package/src/react/hooks/useCollection.tsx +60 -11
- package/src/react/hooks/useCollectionBalanceDetails.tsx +93 -73
- package/src/react/hooks/useCollectionDetails.ts +69 -0
- package/src/react/hooks/useCollectionDetailsPolling.tsx +7 -3
- package/src/react/hooks/useComparePrices.tsx +91 -86
- package/src/react/hooks/useConvertPriceToUSD.tsx +83 -86
- package/src/react/hooks/useCountListingsForCollectible.tsx +64 -53
- package/src/react/hooks/useCountOfCollectables.tsx +60 -69
- package/src/react/hooks/useCountOfPrimarySaleItems.tsx +13 -0
- package/src/react/hooks/useCountOffersForCollectible.tsx +64 -53
- package/src/react/hooks/useCurrency.tsx +56 -64
- package/src/react/hooks/useCurrencyBalance.tsx +132 -46
- package/src/react/hooks/useERC721SaleMintedTokens.tsx +8 -5
- package/src/react/hooks/useFilterState.tsx +1 -2
- package/src/react/hooks/useFilters.tsx +154 -111
- package/src/react/hooks/useFloorOrder.tsx +65 -40
- package/src/react/hooks/useGenerateCancelTransaction.tsx +5 -10
- package/src/react/hooks/useGenerateListingTransaction.tsx +1 -1
- package/src/react/hooks/useGenerateOfferTransaction.tsx +1 -1
- package/src/react/hooks/useGenerateSellTransaction.tsx +5 -10
- package/src/react/hooks/useGetCountOfPrimarySaleItems.tsx +48 -0
- package/src/react/hooks/useGetReceiptFromHash.tsx +32 -3
- package/src/react/hooks/useGetTokenRanges.tsx +92 -0
- package/src/react/hooks/useHighestOffer.tsx +68 -4
- package/src/react/hooks/useInventory.tsx +1 -1
- package/src/react/hooks/useList1155ShopCardData.tsx +57 -82
- package/src/react/hooks/useList721ShopCardData.tsx +98 -63
- package/src/react/hooks/useListBalances.tsx +1 -1
- package/src/react/hooks/useListCollectibleActivities.tsx +89 -50
- package/src/react/hooks/useListCollectibles.tsx +81 -16
- package/src/react/hooks/useListCollectiblesPaginated.tsx +96 -66
- package/src/react/hooks/useListCollectionActivities.tsx +84 -50
- package/src/react/hooks/useListCollections.tsx +71 -17
- package/src/react/hooks/useListListingsForCollectible.tsx +90 -50
- package/src/react/hooks/useListMarketCardData.tsx +3 -2
- package/src/react/hooks/useListOffersForCollectible.tsx +9 -14
- package/src/react/hooks/useListPrimarySaleItems.tsx +66 -0
- package/src/react/hooks/useListShopCardData.tsx +70 -0
- package/src/react/hooks/useListTokenMetadata.ts +64 -12
- package/src/react/hooks/useListTokenMetadata.tsx +73 -0
- package/src/react/hooks/useLowestListing.tsx +68 -4
- package/src/react/hooks/useMarketCurrencies.tsx +62 -5
- package/src/react/hooks/useOpenConnectModal.tsx +9 -0
- package/src/react/hooks/useRoyalty.tsx +57 -13
- package/src/react/hooks/useShopCollectibleSaleData.tsx +349 -0
- package/src/react/hooks/useTokenSaleDetailsBatch.tsx +3 -7
- package/src/react/hooks/useTokenSupplies.ts +81 -0
- package/src/react/hooks/useTransferTokens.tsx +2 -2
- package/src/react/hooks/util/optimisticCancelUpdates.ts +5 -7
- package/src/react/index.ts +5 -3
- package/src/react/provider.tsx +73 -9
- package/src/react/queries/__tests__/balanceOfCollectible.laos.test.ts +123 -0
- package/src/react/queries/__tests__/inventory.laos.test.ts +496 -0
- package/src/react/queries/balanceOfCollectible.ts +8 -5
- package/src/react/queries/checkoutOptions.ts +85 -0
- package/src/react/queries/checkoutOptionsSalesContract.ts +89 -0
- package/src/react/queries/collectible.ts +66 -0
- package/src/react/queries/collection.ts +55 -0
- package/src/react/queries/collectionBalanceDetails.ts +92 -0
- package/src/react/queries/collectionDetails.ts +64 -0
- package/src/react/queries/comparePrices.ts +108 -0
- package/src/react/queries/convertPriceToUSD.ts +92 -0
- package/src/react/queries/countListingsForCollectible.ts +73 -0
- package/src/react/queries/countOfCollectables.ts +83 -0
- package/src/react/queries/countOfPrimarySaleItems.ts +48 -0
- package/src/react/queries/countOffersForCollectible.ts +73 -0
- package/src/react/queries/currency.ts +83 -0
- package/src/react/queries/filters.ts +138 -0
- package/src/react/queries/floorOrder.ts +63 -0
- package/src/react/queries/getTokenRanges.ts +62 -0
- package/src/react/queries/highestOffer.ts +46 -40
- package/src/react/queries/index.ts +10 -4
- package/src/react/queries/inventory.ts +10 -4
- package/src/react/queries/listBalances.ts +5 -4
- package/src/react/queries/listCollectibleActivities.ts +97 -0
- package/src/react/queries/listCollectibles.ts +67 -50
- package/src/react/queries/listCollectiblesPaginated.ts +87 -0
- package/src/react/queries/listCollectionActivities.ts +95 -0
- package/src/react/queries/listCollections.ts +53 -10
- package/src/react/queries/listListingsForCollectible.ts +82 -0
- package/src/react/queries/listTokenMetadata.ts +47 -23
- package/src/react/queries/lowestListing.ts +46 -31
- package/src/react/queries/marketCurrencies.ts +42 -29
- package/src/react/queries/marketplaceConfig.ts +4 -4
- package/src/react/queries/primarySaleItems.ts +85 -0
- package/src/react/queries/primarySaleItemsCount.ts +64 -0
- package/src/react/queries/tokenSupplies.ts +93 -0
- package/src/react/ssr/__tests__/__snapshots__/create-ssr-client.test.ts.snap +12 -2
- package/src/react/ssr/create-ssr-client.ts +1 -1
- package/src/react/types/query.ts +34 -0
- package/src/react/ui/components/ModelViewer.tsx +1 -1
- package/src/react/ui/components/_internals/action-button/ActionButton.tsx +66 -66
- package/src/react/ui/components/_internals/action-button/__tests__/ActionButtonBody.test.tsx +22 -4
- package/src/react/ui/components/_internals/action-button/__tests__/useActionButtonLogic.test.tsx +14 -8
- package/src/react/ui/components/_internals/action-button/components/ActionButtonBody.tsx +5 -4
- package/src/react/ui/components/_internals/action-button/components/NonOwnerActions.tsx +3 -0
- package/src/react/ui/components/_internals/action-button/components/OwnerActions.tsx +4 -4
- package/src/react/ui/components/_internals/action-button/hooks/useActionButtonLogic.ts +20 -18
- package/src/react/ui/components/_internals/action-button/store.ts +72 -34
- package/src/react/ui/components/_internals/custom-select/CustomSelect.stories.tsx +582 -0
- package/src/react/ui/components/_internals/pill/Pill.stories.tsx +83 -0
- package/src/react/ui/components/marketplace-collectible-card/CollectibleCard.tsx +1 -1
- package/src/react/ui/components/marketplace-collectible-card/Footer.tsx +12 -5
- package/src/react/ui/components/marketplace-collectible-card/components/ActionButtonWrapper.tsx +7 -4
- package/src/react/ui/components/marketplace-collectible-card/components/BaseCard.tsx +3 -0
- package/src/react/ui/components/marketplace-collectible-card/index.ts +1 -1
- package/src/react/ui/components/marketplace-collectible-card/types.ts +11 -7
- package/src/react/ui/components/marketplace-collectible-card/utils/supplyStatus.ts +4 -7
- package/src/react/ui/components/marketplace-collectible-card/variants/MarketCard.tsx +3 -2
- package/src/react/ui/components/marketplace-collectible-card/variants/ShopCard.tsx +7 -6
- package/src/react/ui/components/marketplace-logos/marketplace-logos.stories.tsx +199 -0
- package/src/react/ui/components/marketplace-logos/marketplace-logos.tsx +1 -1
- package/src/react/ui/components/media/Media.stories.tsx +642 -0
- package/src/react/ui/components/media/Media.tsx +29 -20
- package/src/react/ui/components/media/types.ts +6 -0
- package/src/react/ui/index.ts +8 -10
- package/src/react/ui/modals/BuyModal/__tests__/BuyModalRouter.test.tsx +15 -0
- package/src/react/ui/modals/BuyModal/__tests__/ERC1155ShopModal.test.tsx +100 -87
- package/src/react/ui/modals/BuyModal/__tests__/Modal1155.test.tsx +11 -5
- package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +10 -2
- package/src/react/ui/modals/BuyModal/components/ERC1155QuantityModal.tsx +17 -11
- package/src/react/ui/modals/BuyModal/components/ERC1155ShopModal.tsx +4 -1
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +1 -1
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useERC1155Checkout.test.tsx +30 -27
- package/src/react/ui/modals/BuyModal/hooks/useCheckoutOptions.ts +3 -3
- package/src/react/ui/modals/BuyModal/hooks/useERC1155Checkout.ts +11 -2
- package/src/react/ui/modals/BuyModal/hooks/useERC721SalePaymentParams.ts +2 -2
- package/src/react/ui/modals/BuyModal/hooks/usePaymentModalParams.ts +10 -3
- package/src/react/ui/modals/BuyModal/index.tsx +9 -1
- package/src/react/ui/modals/BuyModal/store.ts +26 -0
- package/src/react/ui/modals/CreateListingModal/Modal.tsx +28 -11
- package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +2 -2
- package/src/react/ui/modals/CreateListingModal/hooks/useCreateListing.tsx +0 -1
- package/src/react/ui/modals/CreateListingModal/hooks/useGetTokenApproval.ts +2 -2
- package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +7 -6
- package/src/react/ui/modals/CreateListingModal/index.tsx +1 -1
- package/src/react/ui/modals/CreateListingModal/store.ts +3 -3
- package/src/react/ui/modals/MakeOfferModal/Modal.tsx +31 -14
- package/src/react/ui/modals/MakeOfferModal/__tests__/Modal.test.tsx +1 -1
- package/src/react/ui/modals/MakeOfferModal/hooks/useGetTokenApproval.tsx +1 -1
- package/src/react/ui/modals/MakeOfferModal/hooks/useMakeOffer.tsx +0 -1
- package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +7 -7
- package/src/react/ui/modals/MakeOfferModal/index.tsx +1 -1
- package/src/react/ui/modals/MakeOfferModal/store.ts +3 -3
- package/src/react/ui/modals/SellModal/Modal.tsx +14 -11
- package/src/react/ui/modals/SellModal/__tests__/Modal.test.tsx +6 -4
- package/src/react/ui/modals/SellModal/hooks/useGetTokenApproval.tsx +1 -1
- package/src/react/ui/modals/SellModal/hooks/useSell.tsx +0 -1
- package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +6 -6
- package/src/react/ui/modals/SellModal/store.ts +3 -3
- package/src/react/ui/modals/SuccessfulPurchaseModal/__tests__/Modal.test.tsx +1 -1
- package/src/react/ui/modals/TransferModal/__tests__/__snapshots__/store.test.ts.snap +17 -0
- package/src/react/ui/modals/TransferModal/__tests__/store.test.ts +366 -0
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/__tests__/useHandleTransfer.test.tsx +402 -0
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TokenQuantityInput.tsx +52 -50
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TransferButton.tsx +39 -47
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/WalletAddressInput.tsx +9 -8
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +33 -37
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +19 -10
- package/src/react/ui/modals/TransferModal/index.tsx +28 -31
- package/src/react/ui/modals/TransferModal/messages.ts +1 -1
- package/src/react/ui/modals/TransferModal/store.ts +122 -0
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.test.tsx +1 -1
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +2 -4
- package/src/react/ui/modals/_internal/components/calendar/index.tsx +0 -1
- package/src/react/ui/modals/_internal/components/currencyImage/index.tsx +10 -14
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +6 -3
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +23 -18
- package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +10 -10
- package/src/react/ui/modals/_internal/components/floorPriceText/__tests__/FloorPriceText.test.tsx +6 -6
- package/src/react/ui/modals/_internal/components/floorPriceText/index.tsx +4 -4
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/PriceInput.test.tsx +13 -5
- package/src/react/ui/modals/_internal/components/priceInput/index.tsx +41 -26
- package/src/react/ui/modals/_internal/components/quantityInput/__tests__/index.test.tsx +68 -59
- package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +23 -17
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/__tests__/SelectWaasFeeOptions.test.tsx +340 -41
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/_components/BalanceIndicator.tsx +1 -2
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/index.tsx +95 -101
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/store.ts +72 -14
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/useWaasFeeOptionManager.tsx +29 -14
- package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +2 -2
- package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +2 -2
- package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +88 -89
- package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +37 -11
- package/src/react/ui/modals/_internal/components/transactionStatusModal/hooks/useTransactionStatus.ts +0 -1
- package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +32 -20
- package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +92 -63
- package/src/react/ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect.tsx +44 -45
- package/src/react/ui/modals/_internal/types.ts +2 -2
- package/src/react/ui/modals/modal-provider.tsx +2 -3
- package/src/types/api-types.ts +36 -36
- package/src/types/buyModalErrors.ts +1 -1
- package/src/types/index.ts +5 -5
- package/src/types/new-marketplace-types.ts +1 -1
- package/src/types/sdk-config.ts +8 -2
- package/src/types/types.ts +1 -0
- package/src/types/waas-types.ts +1 -1
- package/src/utils/abi/index.ts +1 -1
- package/src/utils/abi/primary-sale/index.ts +1 -1
- package/src/utils/abi/token/index.ts +2 -1
- package/src/utils/decode/erc20.ts +1 -1
- package/src/utils/index.ts +3 -3
- package/src/utils/network.ts +15 -0
- package/test/const.ts +3 -1
- package/test/mocks/wallet.ts +1 -1
- package/test/test-utils.tsx +5 -4
- package/vitest.shims.d.ts +2 -0
- package/vitest.storybook.config.js +33 -0
- package/.changeset/fluffy-jokes-lay.md +0 -5
- package/.changeset/wise-bugs-boil.md +0 -8
- package/dist/CartIcon-Bll1rbxv.js.map +0 -1
- package/dist/CollectibleCard-CLQTl0_6.d.ts +0 -8
- package/dist/_internal-69NEWNUE.js +0 -34
- package/dist/_internal-69NEWNUE.js.map +0 -1
- package/dist/api-1KFxYh7o.js.map +0 -1
- package/dist/builder-api-DoK3907S.d.ts +0 -12
- package/dist/builder.gen-CxP9NT1p.js.map +0 -1
- package/dist/index-4-kfOFdx.d.ts +0 -22
- package/dist/index-BHiSG-Yi.d.ts +0 -312
- package/dist/index-BQW0PUkQ.d.ts +0 -3973
- package/dist/index-BfH21xmk.d.ts +0 -117
- package/dist/index-CN8puQQJ.d.ts +0 -24
- package/dist/index-DafWjEb4.d.ts +0 -65
- package/dist/marketplace.gen-Dqk8vRmD.js.map +0 -1
- package/dist/marketplaceConfig-D2MYFqll.js.map +0 -1
- package/dist/options-DCi6_23w.js +0 -34
- package/dist/options-DCi6_23w.js.map +0 -1
- package/dist/primary-sale-Cw95phYC.js.map +0 -1
- package/dist/queries-DPvwtnO7.js +0 -486
- package/dist/queries-DPvwtnO7.js.map +0 -1
- package/dist/react-BG7o4PId.js.map +0 -1
- package/dist/token-CO5llIla.js.map +0 -1
- package/dist/transaction-CcVViHEL.js.map +0 -1
- package/dist/types-DwWE6xOF.js.map +0 -1
- package/dist/useCollection-C-mclKU0.d.ts +0 -66
- package/dist/utils-BFdxaToy.js.map +0 -1
- package/dist/utils-Cat9_pef.js.map +0 -1
- package/dist/wagmi-DRctYEk6.js.map +0 -1
- package/src/react/_internal/api/zod-schema.ts +0 -678
- package/src/react/hooks/options/collectionOptions.ts +0 -41
- package/src/react/hooks/useCollectionDetails.tsx +0 -50
- package/src/react/hooks/useGetTokenSuppliesMap.ts +0 -33
- package/src/react/hooks/useListPrimarySaleItems.ts +0 -42
- package/src/react/queries/getTokenSupplies.ts +0 -38
- package/src/react/ui/modals/TransferModal/_store.ts +0 -72
- package/src/react/ui/modals/_internal/stores/accountModal.ts +0 -3
- package/tsconfig.tsbuildinfo +0 -1
- /package/dist/{abi-BKyRjVcZ.js → abi-BMvgNbKQ.js} +0 -0
- /package/dist/{index-C39K_8SG.d.ts → index-CD2bj_xW.d.ts} +0 -0
- /package/dist/{index-ij9f8GAA.d.ts → index-DvpBZgor.d.ts} +0 -0
|
@@ -0,0 +1,4044 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { SEQUENCE_MARKET_V1_ADDRESS, SEQUENCE_MARKET_V2_ADDRESS } from "./src-Dz2CfBL0.js";
|
|
3
|
+
import { FilterCondition } from "./builder.gen-B9wR2nvF.js";
|
|
4
|
+
import { BaseError } from "./base-DqaJPvfN.js";
|
|
5
|
+
import { ChainSwitchError, ChainSwitchUserRejectedError, NoWalletConnectedError, TransactionConfirmationError, TransactionExecutionError, TransactionSignatureError, UserRejectedRequestError, WalletInstanceNotFoundError } from "./transaction-CnctdNzS.js";
|
|
6
|
+
import { getQueryClient } from "./get-query-client-D19vvfJo.js";
|
|
7
|
+
import { collectableKeys, collectionKeys, getIndexerClient, getMarketplaceClient, getMetadataClient } from "./api-BiMGqWdz.js";
|
|
8
|
+
import { CollectionStatus, ContractType, ExecuteType, OrderSide, PropertyType, StepType, WalletKind } from "./marketplace.gen-HpnpL5xU.js";
|
|
9
|
+
import { getPresentableChainName } from "./network-CGD0oKtS.js";
|
|
10
|
+
import { EIP2981_ABI } from "./marketplace-DmFiyBoS.js";
|
|
11
|
+
import { ERC1155_SALES_CONTRACT_ABI, ERC721_SALE_ABI } from "./primary-sale-CmWxSfFQ.js";
|
|
12
|
+
import { ERC1155_ABI, ERC721_ABI, SEQUENCE_1155_ITEMS_ABI } from "./token-CHSBPYVG.js";
|
|
13
|
+
import { compareAddress } from "./utils-9RXDgcBl.js";
|
|
14
|
+
import { MarketplaceSdkContext } from "./provider-DPGUA10G.js";
|
|
15
|
+
import { balanceOfCollectibleOptions, collectibleQueryOptions, collectionDetailsQueryOptions, countOfPrimarySaleItemsOptions, currencyQueryOptions, floorOrderQueryOptions, highestOfferQueryOptions, inventoryOptions, listBalancesOptions, listCollectiblesQueryOptions, listCollectionsQueryOptions, listTokenMetadataQueryOptions, lowestListingQueryOptions, marketCurrenciesQueryOptions, tokenSuppliesQueryOptions } from "./queries-Ce_2othB.js";
|
|
16
|
+
import { marketplaceConfigOptions } from "./marketplaceConfig-GQTTmihy.js";
|
|
17
|
+
import { InfoIcon_default } from "./InfoIcon-v0w_Lu7t.js";
|
|
18
|
+
import { useChain, useWaasFeeOptions } from "@0xsequence/connect";
|
|
19
|
+
import { useAccount, useChainId, usePublicClient, useReadContract, useSwitchChain, useWalletClient, useWriteContract } from "wagmi";
|
|
20
|
+
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
21
|
+
import { infiniteQueryOptions, queryOptions, skipToken, useInfiniteQuery, useMutation, useQuery } from "@tanstack/react-query";
|
|
22
|
+
import { Button, Modal, Spinner, Text, WarningIcon } from "@0xsequence/design-system";
|
|
23
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
24
|
+
import { BaseError as BaseError$1, TransactionReceiptNotFoundError, UserRejectedRequestError as UserRejectedRequestError$1, WaitForTransactionReceiptTimeoutError, custom, erc20Abi, erc721Abi, formatUnits, hexToBigInt, isHex, zeroAddress } from "viem";
|
|
25
|
+
import { createStore } from "@xstate/store";
|
|
26
|
+
import { useSelector } from "@xstate/store/react";
|
|
27
|
+
import { createSerializer, parseAsBoolean, parseAsJson, parseAsString, useQueryState } from "nuqs";
|
|
28
|
+
import { observable } from "@legendapp/state";
|
|
29
|
+
|
|
30
|
+
//#region src/react/queries/collectionBalanceDetails.ts
|
|
31
|
+
/**
|
|
32
|
+
* Fetches detailed balance information for multiple accounts from the Indexer API
|
|
33
|
+
*/
|
|
34
|
+
async function fetchCollectionBalanceDetails(params) {
|
|
35
|
+
const { chainId, filter, config } = params;
|
|
36
|
+
const indexerClient = getIndexerClient(chainId, config);
|
|
37
|
+
const promises = filter.accountAddresses.map((accountAddress) => indexerClient.getTokenBalancesDetails({ filter: {
|
|
38
|
+
accountAddresses: [accountAddress],
|
|
39
|
+
contractWhitelist: filter.contractWhitelist,
|
|
40
|
+
omitNativeBalances: filter.omitNativeBalances
|
|
41
|
+
} }));
|
|
42
|
+
const responses = await Promise.all(promises);
|
|
43
|
+
const mergedResponse = responses.reduce((acc, curr) => {
|
|
44
|
+
if (!curr) return acc;
|
|
45
|
+
return {
|
|
46
|
+
page: curr.page,
|
|
47
|
+
nativeBalances: [...acc.nativeBalances || [], ...curr.nativeBalances || []],
|
|
48
|
+
balances: [...acc.balances || [], ...curr.balances || []]
|
|
49
|
+
};
|
|
50
|
+
}, {
|
|
51
|
+
page: {},
|
|
52
|
+
nativeBalances: [],
|
|
53
|
+
balances: []
|
|
54
|
+
});
|
|
55
|
+
if (!mergedResponse) throw new Error("Failed to fetch collection balance details");
|
|
56
|
+
return mergedResponse;
|
|
57
|
+
}
|
|
58
|
+
function collectionBalanceDetailsQueryOptions(params) {
|
|
59
|
+
const enabled = Boolean(params.chainId && params.filter?.accountAddresses?.length && params.config && (params.query?.enabled ?? true));
|
|
60
|
+
return queryOptions({
|
|
61
|
+
queryKey: [
|
|
62
|
+
"balances",
|
|
63
|
+
"collectionBalanceDetails",
|
|
64
|
+
params
|
|
65
|
+
],
|
|
66
|
+
queryFn: () => fetchCollectionBalanceDetails({
|
|
67
|
+
chainId: params.chainId,
|
|
68
|
+
filter: params.filter,
|
|
69
|
+
config: params.config
|
|
70
|
+
}),
|
|
71
|
+
...params.query,
|
|
72
|
+
enabled
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/utils/_internal/error/context.ts
|
|
78
|
+
var MarketplaceSdkProviderNotFoundError = class extends BaseError {
|
|
79
|
+
name = "MarketplaceSDKProviderNotFoundError";
|
|
80
|
+
constructor() {
|
|
81
|
+
super("`useConfig` must be used within `MarketplaceSdkProvider`.");
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/react/hooks/useConfig.tsx
|
|
87
|
+
function useConfig() {
|
|
88
|
+
const context = useContext(MarketplaceSdkContext);
|
|
89
|
+
if (!context) throw new MarketplaceSdkProviderNotFoundError();
|
|
90
|
+
return context;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/react/hooks/useCollectionBalanceDetails.tsx
|
|
95
|
+
/**
|
|
96
|
+
* Hook to fetch detailed balance information for multiple accounts
|
|
97
|
+
*
|
|
98
|
+
* Retrieves token balances and native balances for multiple account addresses,
|
|
99
|
+
* with support for contract whitelisting and optional native balance exclusion.
|
|
100
|
+
* Aggregates results from multiple account addresses into a single response.
|
|
101
|
+
*
|
|
102
|
+
* @param params - Configuration parameters
|
|
103
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
104
|
+
* @param params.filter - Filter configuration for balance queries
|
|
105
|
+
* @param params.filter.accountAddresses - Array of account addresses to query balances for
|
|
106
|
+
* @param params.filter.contractWhitelist - Optional array of contract addresses to filter by
|
|
107
|
+
* @param params.filter.omitNativeBalances - Whether to exclude native token balances
|
|
108
|
+
* @param params.query - Optional React Query configuration
|
|
109
|
+
*
|
|
110
|
+
* @returns Query result containing aggregated balance details for all accounts
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* Basic usage:
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const { data: balanceDetails, isLoading } = useCollectionBalanceDetails({
|
|
116
|
+
* chainId: 137,
|
|
117
|
+
* filter: {
|
|
118
|
+
* accountAddresses: ['0x1234...', '0x5678...'],
|
|
119
|
+
* omitNativeBalances: false
|
|
120
|
+
* }
|
|
121
|
+
* })
|
|
122
|
+
*
|
|
123
|
+
* if (data) {
|
|
124
|
+
* console.log(`Found ${data.balances.length} token balances`);
|
|
125
|
+
* console.log(`Found ${data.nativeBalances.length} native balances`);
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* With contract whitelist:
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const { data: balanceDetails } = useCollectionBalanceDetails({
|
|
133
|
+
* chainId: 1,
|
|
134
|
+
* filter: {
|
|
135
|
+
* accountAddresses: [userAddress],
|
|
136
|
+
* contractWhitelist: ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'], // USDC only
|
|
137
|
+
* omitNativeBalances: true
|
|
138
|
+
* },
|
|
139
|
+
* query: {
|
|
140
|
+
* enabled: Boolean(userAddress),
|
|
141
|
+
* refetchInterval: 60000 // Refresh every minute
|
|
142
|
+
* }
|
|
143
|
+
* })
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
function useCollectionBalanceDetails(params) {
|
|
147
|
+
const defaultConfig = useConfig();
|
|
148
|
+
const { config = defaultConfig,...rest } = params;
|
|
149
|
+
const queryOptions$1 = collectionBalanceDetailsQueryOptions({
|
|
150
|
+
config,
|
|
151
|
+
...rest
|
|
152
|
+
});
|
|
153
|
+
return useQuery({ ...queryOptions$1 });
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/react/hooks/useAutoSelectFeeOption.tsx
|
|
158
|
+
var AutoSelectFeeOptionError = /* @__PURE__ */ function(AutoSelectFeeOptionError$1) {
|
|
159
|
+
AutoSelectFeeOptionError$1["UserNotConnected"] = "User not connected";
|
|
160
|
+
AutoSelectFeeOptionError$1["NoOptionsProvided"] = "No options provided";
|
|
161
|
+
AutoSelectFeeOptionError$1["FailedToCheckBalances"] = "Failed to check balances";
|
|
162
|
+
AutoSelectFeeOptionError$1["InsufficientBalanceForAnyFeeOption"] = "Insufficient balance for any fee option";
|
|
163
|
+
return AutoSelectFeeOptionError$1;
|
|
164
|
+
}(AutoSelectFeeOptionError || {});
|
|
165
|
+
/**
|
|
166
|
+
* A React hook that automatically selects the first fee option for which the user has sufficient balance.
|
|
167
|
+
*
|
|
168
|
+
* @param {Object} params.pendingFeeOptionConfirmation - Configuration for fee option selection
|
|
169
|
+
*
|
|
170
|
+
* @returns {Promise<{
|
|
171
|
+
* selectedOption: FeeOption | null,
|
|
172
|
+
* error: AutoSelectFeeOptionError | null,
|
|
173
|
+
* isLoading?: boolean
|
|
174
|
+
* }>} A promise that resolves to an object containing:
|
|
175
|
+
* - selectedOption: The first fee option with sufficient balance, or null if none found
|
|
176
|
+
* - error: Error message if selection fails, null otherwise
|
|
177
|
+
* - isLoading: True while checking balances
|
|
178
|
+
*
|
|
179
|
+
* @throws {AutoSelectFeeOptionError} Possible errors:
|
|
180
|
+
* - UserNotConnected: When no wallet is connected
|
|
181
|
+
* - NoOptionsProvided: When fee options array is undefined
|
|
182
|
+
* - FailedToCheckBalances: When balance checking fails
|
|
183
|
+
* - InsufficientBalanceForAnyFeeOption: When user has insufficient balance for all options
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```tsx
|
|
187
|
+
* function MyComponent() {
|
|
188
|
+
* const [pendingFeeOptionConfirmation, confirmPendingFeeOption] = useWaasFeeOptions();
|
|
189
|
+
*
|
|
190
|
+
* const autoSelectOptionPromise = useAutoSelectFeeOption({
|
|
191
|
+
* pendingFeeOptionConfirmation: pendingFeeOptionConfirmation
|
|
192
|
+
* ? {
|
|
193
|
+
* id: pendingFeeOptionConfirmation.id,
|
|
194
|
+
* options: pendingFeeOptionConfirmation.options,
|
|
195
|
+
* chainId: 1
|
|
196
|
+
* }
|
|
197
|
+
* : {
|
|
198
|
+
* id: '',
|
|
199
|
+
* options: undefined,
|
|
200
|
+
* chainId: 1
|
|
201
|
+
* }
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* useEffect(() => {
|
|
205
|
+
* autoSelectOptionPromise.then((result) => {
|
|
206
|
+
* if (result.isLoading) {
|
|
207
|
+
* console.log('Checking balances...');
|
|
208
|
+
* return;
|
|
209
|
+
* }
|
|
210
|
+
*
|
|
211
|
+
* if (result.error) {
|
|
212
|
+
* console.error('Failed to select fee option:', result.error);
|
|
213
|
+
* return;
|
|
214
|
+
* }
|
|
215
|
+
*
|
|
216
|
+
* if (pendingFeeOptionConfirmation?.id && result.selectedOption) {
|
|
217
|
+
* confirmPendingFeeOption(
|
|
218
|
+
* pendingFeeOptionConfirmation.id,
|
|
219
|
+
* result.selectedOption.token.contractAddress
|
|
220
|
+
* );
|
|
221
|
+
* }
|
|
222
|
+
* });
|
|
223
|
+
* }, [autoSelectOptionPromise, confirmPendingFeeOption, pendingFeeOptionConfirmation]);
|
|
224
|
+
*
|
|
225
|
+
* return <div>...</div>;
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
function useAutoSelectFeeOption({ pendingFeeOptionConfirmation, enabled }) {
|
|
230
|
+
const { address: userAddress } = useAccount();
|
|
231
|
+
const contractWhitelist = pendingFeeOptionConfirmation.options?.map((option) => option.token.contractAddress === null ? zeroAddress : option.token.contractAddress);
|
|
232
|
+
const { data: balanceDetails, isLoading: isBalanceDetailsLoading, isError: isBalanceDetailsError } = useCollectionBalanceDetails({
|
|
233
|
+
chainId: pendingFeeOptionConfirmation.chainId,
|
|
234
|
+
filter: {
|
|
235
|
+
accountAddresses: userAddress ? [userAddress] : [],
|
|
236
|
+
contractWhitelist,
|
|
237
|
+
omitNativeBalances: false
|
|
238
|
+
},
|
|
239
|
+
query: { enabled: !!pendingFeeOptionConfirmation.options && !!userAddress && enabled }
|
|
240
|
+
});
|
|
241
|
+
const chain = useChain(pendingFeeOptionConfirmation.chainId);
|
|
242
|
+
const combinedBalances = balanceDetails && [...balanceDetails.nativeBalances.map((b) => ({
|
|
243
|
+
chainId: pendingFeeOptionConfirmation.chainId,
|
|
244
|
+
balance: b.balance,
|
|
245
|
+
symbol: chain?.nativeCurrency.symbol,
|
|
246
|
+
contractAddress: zeroAddress
|
|
247
|
+
})), ...balanceDetails.balances.map((b) => ({
|
|
248
|
+
chainId: b.chainId,
|
|
249
|
+
balance: b.balance,
|
|
250
|
+
symbol: b.contractInfo?.symbol,
|
|
251
|
+
contractAddress: b.contractAddress
|
|
252
|
+
}))];
|
|
253
|
+
useEffect(() => {
|
|
254
|
+
if (combinedBalances) console.debug("currency balances", combinedBalances);
|
|
255
|
+
}, [combinedBalances]);
|
|
256
|
+
const autoSelectedOption = useCallback(async () => {
|
|
257
|
+
if (!userAddress) return {
|
|
258
|
+
selectedOption: null,
|
|
259
|
+
error: AutoSelectFeeOptionError.UserNotConnected
|
|
260
|
+
};
|
|
261
|
+
if (!pendingFeeOptionConfirmation.options) return {
|
|
262
|
+
selectedOption: null,
|
|
263
|
+
error: AutoSelectFeeOptionError.NoOptionsProvided
|
|
264
|
+
};
|
|
265
|
+
if (isBalanceDetailsLoading) return {
|
|
266
|
+
selectedOption: null,
|
|
267
|
+
error: null,
|
|
268
|
+
isLoading: true
|
|
269
|
+
};
|
|
270
|
+
if (isBalanceDetailsError || !combinedBalances) return {
|
|
271
|
+
selectedOption: null,
|
|
272
|
+
error: AutoSelectFeeOptionError.FailedToCheckBalances
|
|
273
|
+
};
|
|
274
|
+
const selectedOption = pendingFeeOptionConfirmation.options.find((option) => {
|
|
275
|
+
const tokenBalance = combinedBalances.find((balance) => balance.contractAddress.toLowerCase() === (option.token.contractAddress === null ? zeroAddress : option.token.contractAddress).toLowerCase());
|
|
276
|
+
if (!tokenBalance) return false;
|
|
277
|
+
return BigInt(tokenBalance.balance) >= BigInt(option.value);
|
|
278
|
+
});
|
|
279
|
+
if (!selectedOption) return {
|
|
280
|
+
selectedOption: null,
|
|
281
|
+
error: AutoSelectFeeOptionError.InsufficientBalanceForAnyFeeOption
|
|
282
|
+
};
|
|
283
|
+
console.debug("auto selected option", selectedOption);
|
|
284
|
+
return {
|
|
285
|
+
selectedOption,
|
|
286
|
+
error: null
|
|
287
|
+
};
|
|
288
|
+
}, [
|
|
289
|
+
userAddress,
|
|
290
|
+
pendingFeeOptionConfirmation.options,
|
|
291
|
+
isBalanceDetailsLoading,
|
|
292
|
+
isBalanceDetailsError,
|
|
293
|
+
combinedBalances
|
|
294
|
+
]);
|
|
295
|
+
return autoSelectedOption();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/react/hooks/useMarketplaceConfig.tsx
|
|
300
|
+
const useMarketplaceConfig = () => {
|
|
301
|
+
const config = useConfig();
|
|
302
|
+
return useQuery(marketplaceConfigOptions(config));
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
//#endregion
|
|
306
|
+
//#region src/react/hooks/useBalanceOfCollectible.tsx
|
|
307
|
+
/**
|
|
308
|
+
* Hook to fetch the balance of a specific collectible for a user
|
|
309
|
+
*
|
|
310
|
+
* @param args - The arguments for fetching the balance
|
|
311
|
+
* @returns Query result containing the balance data
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```tsx
|
|
315
|
+
* const { data, isLoading, error } = useBalanceOfCollectible({
|
|
316
|
+
* collectionAddress: '0x123...',
|
|
317
|
+
* collectableId: '1',
|
|
318
|
+
* userAddress: '0x456...',
|
|
319
|
+
* chainId: 1,
|
|
320
|
+
* query: {
|
|
321
|
+
* enabled: true,
|
|
322
|
+
* refetchInterval: 10000,
|
|
323
|
+
* }
|
|
324
|
+
* });
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
function useBalanceOfCollectible(args) {
|
|
328
|
+
const config = useConfig();
|
|
329
|
+
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
330
|
+
const collection = marketplaceConfig?.market.collections.find((collection$1) => collection$1.itemsAddress === args.collectionAddress);
|
|
331
|
+
const isLaos721 = collection?.contractType === ContractType.LAOS_ERC_721;
|
|
332
|
+
return useQuery(balanceOfCollectibleOptions({
|
|
333
|
+
...args,
|
|
334
|
+
isLaos721
|
|
335
|
+
}, config));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/react/_internal/logger.ts
|
|
340
|
+
var TransactionLogger = class {
|
|
341
|
+
constructor(context, enabled = true) {
|
|
342
|
+
this.context = context;
|
|
343
|
+
this.enabled = enabled;
|
|
344
|
+
}
|
|
345
|
+
formatData(data) {
|
|
346
|
+
if (data instanceof Error) return {
|
|
347
|
+
name: data.name,
|
|
348
|
+
message: data.message,
|
|
349
|
+
cause: data.cause instanceof Error ? this.formatData(data.cause) : data.cause,
|
|
350
|
+
stack: data.stack?.split("\n").slice(0, 3)
|
|
351
|
+
};
|
|
352
|
+
if (Array.isArray(data)) return data.map((item) => this.formatData(item));
|
|
353
|
+
if (typeof data === "object" && data !== null) return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, this.formatData(value)]));
|
|
354
|
+
return data;
|
|
355
|
+
}
|
|
356
|
+
log(level, message, data) {
|
|
357
|
+
if (!this.enabled) return;
|
|
358
|
+
console[level](`[${this.context}] ${message}`, data ? this.formatData(data) : "");
|
|
359
|
+
}
|
|
360
|
+
debug(message, data) {
|
|
361
|
+
this.log("debug", message, data);
|
|
362
|
+
}
|
|
363
|
+
error(message, error) {
|
|
364
|
+
this.log("error", message, error);
|
|
365
|
+
}
|
|
366
|
+
info(message, data) {
|
|
367
|
+
this.log("info", message, data);
|
|
368
|
+
}
|
|
369
|
+
state(from, to) {
|
|
370
|
+
this.info(`State transition: ${from} -> ${to}`);
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
const createLogger = (context, enabled = true) => new TransactionLogger(context, enabled);
|
|
374
|
+
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/react/_internal/wallet/wallet.ts
|
|
377
|
+
const isSequenceWallet = (connector) => connector.id === "sequence" || connector.id === "sequence-waas";
|
|
378
|
+
const wallet = ({ wallet: wallet$1, chains, connector, sdkConfig, publicClient }) => {
|
|
379
|
+
const logger = createLogger("Wallet");
|
|
380
|
+
const walletInstance = {
|
|
381
|
+
transport: custom(wallet$1.transport),
|
|
382
|
+
isWaaS: connector.id.endsWith("waas"),
|
|
383
|
+
walletKind: isSequenceWallet(connector) ? WalletKind.sequence : WalletKind.unknown,
|
|
384
|
+
getChainId: wallet$1.getChainId,
|
|
385
|
+
address: async () => {
|
|
386
|
+
let address = wallet$1.account?.address;
|
|
387
|
+
if (!address) [address] = await wallet$1.getAddresses();
|
|
388
|
+
return address;
|
|
389
|
+
},
|
|
390
|
+
switchChain: async (chainId) => {
|
|
391
|
+
logger.debug("Switching chain", { targetChainId: chainId });
|
|
392
|
+
try {
|
|
393
|
+
await wallet$1.switchChain({ id: chainId });
|
|
394
|
+
logger.info("Chain switch successful", { chainId });
|
|
395
|
+
return;
|
|
396
|
+
} catch (e) {
|
|
397
|
+
const error = e;
|
|
398
|
+
logger.error("Chain switch failed", error);
|
|
399
|
+
switch (error.name) {
|
|
400
|
+
case "SwitchChainNotSupportedError": throw new ChainSwitchError(await wallet$1.getChainId(), chainId);
|
|
401
|
+
case "UserRejectedRequestError": throw new UserRejectedRequestError();
|
|
402
|
+
case "ChainNotConfiguredError": return;
|
|
403
|
+
default: throw new ChainSwitchError(await wallet$1.getChainId(), chainId);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
handleSignMessageStep: async (stepItem) => {
|
|
408
|
+
try {
|
|
409
|
+
if (stepItem.id === StepType.signEIP191) {
|
|
410
|
+
logger.debug("Signing with EIP-191", { data: stepItem.data });
|
|
411
|
+
const message = isHex(stepItem.data) ? { raw: stepItem.data } : stepItem.data;
|
|
412
|
+
return await wallet$1.signMessage({
|
|
413
|
+
account: wallet$1.account,
|
|
414
|
+
message
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
if (stepItem.id === StepType.signEIP712) {
|
|
418
|
+
logger.debug("Signing with EIP-712", {
|
|
419
|
+
domain: stepItem.domain,
|
|
420
|
+
types: stepItem.signature?.types
|
|
421
|
+
});
|
|
422
|
+
return await wallet$1.signTypedData({
|
|
423
|
+
account: wallet$1.account,
|
|
424
|
+
domain: stepItem.signature.domain,
|
|
425
|
+
types: stepItem.signature.types,
|
|
426
|
+
primaryType: stepItem.signature.primaryType,
|
|
427
|
+
message: stepItem.signature.value
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
} catch (e) {
|
|
431
|
+
const error = e;
|
|
432
|
+
logger.error("Signature failed", error);
|
|
433
|
+
if (error.cause instanceof BaseError$1) {
|
|
434
|
+
const viemError = error.cause;
|
|
435
|
+
if (viemError instanceof UserRejectedRequestError$1) throw new UserRejectedRequestError();
|
|
436
|
+
}
|
|
437
|
+
throw new TransactionSignatureError(stepItem.id, error);
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
handleSendTransactionStep: async (chainId, stepItem) => {
|
|
441
|
+
logger.debug("Sending transaction", {
|
|
442
|
+
chainId,
|
|
443
|
+
to: stepItem.to,
|
|
444
|
+
value: stepItem.value
|
|
445
|
+
});
|
|
446
|
+
const chain = chains.find((chain$1) => chain$1.id === chainId);
|
|
447
|
+
try {
|
|
448
|
+
return await wallet$1.sendTransaction({
|
|
449
|
+
chain,
|
|
450
|
+
data: stepItem.data,
|
|
451
|
+
account: wallet$1.account,
|
|
452
|
+
to: stepItem.to,
|
|
453
|
+
value: hexToBigInt(stepItem.value || "0x0"),
|
|
454
|
+
...stepItem.maxFeePerGas && { maxFeePerGas: hexToBigInt(stepItem.maxFeePerGas) },
|
|
455
|
+
...stepItem.maxPriorityFeePerGas && { maxPriorityFeePerGas: hexToBigInt(stepItem.maxPriorityFeePerGas) },
|
|
456
|
+
...stepItem.gas && { gas: hexToBigInt(stepItem.gas) }
|
|
457
|
+
});
|
|
458
|
+
} catch (e) {
|
|
459
|
+
const error = e;
|
|
460
|
+
logger.error("Transaction failed", error);
|
|
461
|
+
if (error.cause instanceof BaseError$1) {
|
|
462
|
+
const viemError = error.cause;
|
|
463
|
+
if (viemError instanceof UserRejectedRequestError$1) throw new UserRejectedRequestError();
|
|
464
|
+
}
|
|
465
|
+
throw new TransactionExecutionError(stepItem.id, error);
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
handleConfirmTransactionStep: async (txHash, chainId) => {
|
|
469
|
+
logger.debug("Confirming transaction", {
|
|
470
|
+
txHash,
|
|
471
|
+
chainId
|
|
472
|
+
});
|
|
473
|
+
try {
|
|
474
|
+
const receipt = await awaitTransactionReceipt({
|
|
475
|
+
txHash,
|
|
476
|
+
chainId,
|
|
477
|
+
sdkConfig
|
|
478
|
+
});
|
|
479
|
+
logger.info("Transaction confirmed", {
|
|
480
|
+
txHash,
|
|
481
|
+
receipt
|
|
482
|
+
});
|
|
483
|
+
return receipt;
|
|
484
|
+
} catch (error) {
|
|
485
|
+
logger.error("Transaction confirmation failed", error);
|
|
486
|
+
throw new TransactionConfirmationError(txHash, error);
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
hasTokenApproval: async ({ tokenType, contractAddress, spender }) => {
|
|
490
|
+
const walletAddress = await walletInstance.address();
|
|
491
|
+
const spenderAddress = spender === "sequenceMarketV1" ? SEQUENCE_MARKET_V1_ADDRESS : spender === "sequenceMarketV2" ? SEQUENCE_MARKET_V2_ADDRESS : spender;
|
|
492
|
+
switch (tokenType) {
|
|
493
|
+
case "ERC20": return await publicClient.readContract({
|
|
494
|
+
address: contractAddress,
|
|
495
|
+
abi: erc20Abi,
|
|
496
|
+
functionName: "allowance",
|
|
497
|
+
args: [walletAddress, spenderAddress]
|
|
498
|
+
});
|
|
499
|
+
case "ERC721": return await publicClient.readContract({
|
|
500
|
+
address: contractAddress,
|
|
501
|
+
abi: erc721Abi,
|
|
502
|
+
functionName: "isApprovedForAll",
|
|
503
|
+
args: [walletAddress, spenderAddress]
|
|
504
|
+
});
|
|
505
|
+
case "ERC1155": return await publicClient.readContract({
|
|
506
|
+
address: contractAddress,
|
|
507
|
+
abi: ERC1155_ABI,
|
|
508
|
+
functionName: "isApprovedForAll",
|
|
509
|
+
args: [walletAddress, spenderAddress]
|
|
510
|
+
});
|
|
511
|
+
default: throw new Error("Unsupported contract type for approval checking");
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
publicClient
|
|
515
|
+
};
|
|
516
|
+
return walletInstance;
|
|
517
|
+
};
|
|
518
|
+
const ONE_MIN = 60 * 1e3;
|
|
519
|
+
const THREE_MIN = 3 * ONE_MIN;
|
|
520
|
+
const awaitTransactionReceipt = async ({ txHash, chainId, sdkConfig, timeout = THREE_MIN }) => {
|
|
521
|
+
const indexer = getIndexerClient(chainId, sdkConfig);
|
|
522
|
+
return Promise.race([new Promise((resolve, reject) => {
|
|
523
|
+
indexer.subscribeReceipts({ filter: { txnHash: txHash } }, {
|
|
524
|
+
onMessage: ({ receipt }) => {
|
|
525
|
+
resolve(receipt);
|
|
526
|
+
},
|
|
527
|
+
onError: () => {
|
|
528
|
+
reject(TransactionReceiptNotFoundError);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
}), new Promise((_, reject) => {
|
|
532
|
+
setTimeout(() => {
|
|
533
|
+
reject(WaitForTransactionReceiptTimeoutError);
|
|
534
|
+
}, timeout);
|
|
535
|
+
})]);
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
//#endregion
|
|
539
|
+
//#region src/react/_internal/wallet/useWallet.ts
|
|
540
|
+
const useWallet = () => {
|
|
541
|
+
const { chains } = useSwitchChain();
|
|
542
|
+
const { data: walletClient, isLoading: wagmiWalletIsLoading, isError: wagmiWalletIsError } = useWalletClient();
|
|
543
|
+
const { connector, isConnected, isConnecting } = useAccount();
|
|
544
|
+
const sdkConfig = useConfig();
|
|
545
|
+
const chainId = useChainId();
|
|
546
|
+
const publicClient = usePublicClient();
|
|
547
|
+
const { data, isLoading, isError } = useQuery({
|
|
548
|
+
queryKey: [
|
|
549
|
+
"wallet",
|
|
550
|
+
chainId,
|
|
551
|
+
connector?.uid
|
|
552
|
+
],
|
|
553
|
+
queryFn: walletClient && connector && isConnected && publicClient ? () => {
|
|
554
|
+
return wallet({
|
|
555
|
+
wallet: walletClient,
|
|
556
|
+
chains,
|
|
557
|
+
connector,
|
|
558
|
+
sdkConfig,
|
|
559
|
+
publicClient
|
|
560
|
+
});
|
|
561
|
+
} : skipToken,
|
|
562
|
+
staleTime: Number.POSITIVE_INFINITY
|
|
563
|
+
});
|
|
564
|
+
return {
|
|
565
|
+
wallet: data,
|
|
566
|
+
isLoading: isLoading || isConnecting || wagmiWalletIsLoading,
|
|
567
|
+
isError: isError || wagmiWalletIsError
|
|
568
|
+
};
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region src/react/ui/modals/_internal/components/alertMessage/index.tsx
|
|
573
|
+
function AlertMessage({ message, type }) {
|
|
574
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
575
|
+
className: `flex items-center justify-between gap-3 rounded-xl p-4 ${type === "warning" ? "bg-[hsla(39,71%,40%,0.3)]" : "bg-[hsla(247,100%,75%,0.3)]"}`,
|
|
576
|
+
children: [
|
|
577
|
+
/* @__PURE__ */ jsx(Text, {
|
|
578
|
+
className: "font-body text-sm",
|
|
579
|
+
color: "white",
|
|
580
|
+
fontWeight: "medium",
|
|
581
|
+
children: message
|
|
582
|
+
}),
|
|
583
|
+
type === "warning" && /* @__PURE__ */ jsx(WarningIcon, {
|
|
584
|
+
size: "sm",
|
|
585
|
+
color: "white"
|
|
586
|
+
}),
|
|
587
|
+
type === "info" && /* @__PURE__ */ jsx(InfoIcon_default, {
|
|
588
|
+
size: "sm",
|
|
589
|
+
color: "white"
|
|
590
|
+
})
|
|
591
|
+
]
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
//#endregion
|
|
596
|
+
//#region src/react/ui/modals/_internal/components/consts.ts
|
|
597
|
+
const MODAL_WIDTH = "360px";
|
|
598
|
+
const MODAL_OVERLAY_PROPS = { style: { background: "hsla(0, 0%, 15%, 0.9)" } };
|
|
599
|
+
const MODAL_CONTENT_PROPS = { style: {
|
|
600
|
+
width: MODAL_WIDTH,
|
|
601
|
+
height: "auto"
|
|
602
|
+
} };
|
|
603
|
+
|
|
604
|
+
//#endregion
|
|
605
|
+
//#region src/react/ui/modals/_internal/components/switchChainModal/store.ts
|
|
606
|
+
const initialContext = {
|
|
607
|
+
isOpen: false,
|
|
608
|
+
chainIdToSwitchTo: void 0,
|
|
609
|
+
isSwitching: false,
|
|
610
|
+
onSuccess: void 0,
|
|
611
|
+
onError: void 0,
|
|
612
|
+
onClose: void 0
|
|
613
|
+
};
|
|
614
|
+
const switchChainModalStore = createStore({
|
|
615
|
+
context: initialContext,
|
|
616
|
+
on: {
|
|
617
|
+
open: (context, event) => ({
|
|
618
|
+
...context,
|
|
619
|
+
isOpen: true,
|
|
620
|
+
chainIdToSwitchTo: event.chainIdToSwitchTo,
|
|
621
|
+
onSuccess: event.onSuccess,
|
|
622
|
+
onError: event.onError,
|
|
623
|
+
onClose: event.onClose
|
|
624
|
+
}),
|
|
625
|
+
close: (context) => ({
|
|
626
|
+
...context,
|
|
627
|
+
isOpen: false,
|
|
628
|
+
chainIdToSwitchTo: void 0,
|
|
629
|
+
isSwitching: false,
|
|
630
|
+
onSuccess: void 0,
|
|
631
|
+
onError: void 0,
|
|
632
|
+
onClose: void 0
|
|
633
|
+
}),
|
|
634
|
+
setSwitching: (context, event) => ({
|
|
635
|
+
...context,
|
|
636
|
+
isSwitching: event.isSwitching
|
|
637
|
+
})
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
const useIsOpen = () => useSelector(switchChainModalStore, (state) => state.context.isOpen);
|
|
641
|
+
const useChainIdToSwitchTo = () => useSelector(switchChainModalStore, (state) => state.context.chainIdToSwitchTo);
|
|
642
|
+
const useIsSwitching = () => useSelector(switchChainModalStore, (state) => state.context.isSwitching);
|
|
643
|
+
const useOnSuccess = () => useSelector(switchChainModalStore, (state) => state.context.onSuccess);
|
|
644
|
+
const useOnError = () => useSelector(switchChainModalStore, (state) => state.context.onError);
|
|
645
|
+
const useOnClose = () => useSelector(switchChainModalStore, (state) => state.context.onClose);
|
|
646
|
+
|
|
647
|
+
//#endregion
|
|
648
|
+
//#region src/react/ui/modals/_internal/components/switchChainModal/index.tsx
|
|
649
|
+
const useSwitchChainModal = () => {
|
|
650
|
+
return {
|
|
651
|
+
show: (args) => switchChainModalStore.send({
|
|
652
|
+
type: "open",
|
|
653
|
+
...args
|
|
654
|
+
}),
|
|
655
|
+
close: () => switchChainModalStore.send({ type: "close" })
|
|
656
|
+
};
|
|
657
|
+
};
|
|
658
|
+
const SwitchChainModal = () => {
|
|
659
|
+
const isOpen = useIsOpen();
|
|
660
|
+
const chainIdToSwitchTo = useChainIdToSwitchTo();
|
|
661
|
+
const isSwitching = useIsSwitching();
|
|
662
|
+
const onSuccess = useOnSuccess();
|
|
663
|
+
const onError = useOnError();
|
|
664
|
+
const onClose = useOnClose();
|
|
665
|
+
const chainName = chainIdToSwitchTo ? getPresentableChainName(chainIdToSwitchTo) : "";
|
|
666
|
+
const { switchChainAsync } = useSwitchChain();
|
|
667
|
+
async function handleSwitchChain() {
|
|
668
|
+
switchChainModalStore.send({
|
|
669
|
+
type: "setSwitching",
|
|
670
|
+
isSwitching: true
|
|
671
|
+
});
|
|
672
|
+
try {
|
|
673
|
+
if (!chainIdToSwitchTo) return;
|
|
674
|
+
await switchChainAsync({ chainId: Number(chainIdToSwitchTo) });
|
|
675
|
+
if (onSuccess && typeof onSuccess === "function") onSuccess();
|
|
676
|
+
switchChainModalStore.send({ type: "close" });
|
|
677
|
+
} catch (error) {
|
|
678
|
+
if (error instanceof Error && onError && typeof onError === "function") onError(error);
|
|
679
|
+
} finally {
|
|
680
|
+
switchChainModalStore.send({
|
|
681
|
+
type: "setSwitching",
|
|
682
|
+
isSwitching: false
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
const handleClose = () => {
|
|
687
|
+
if (onClose && typeof onClose === "function") onClose();
|
|
688
|
+
switchChainModalStore.send({ type: "close" });
|
|
689
|
+
};
|
|
690
|
+
if (!isOpen || !chainIdToSwitchTo) return null;
|
|
691
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
692
|
+
isDismissible: true,
|
|
693
|
+
onClose: handleClose,
|
|
694
|
+
disableAnimation: true,
|
|
695
|
+
size: "sm",
|
|
696
|
+
overlayProps: MODAL_OVERLAY_PROPS,
|
|
697
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
698
|
+
className: "grid flex-col gap-6 p-7",
|
|
699
|
+
children: [
|
|
700
|
+
/* @__PURE__ */ jsx(Text, {
|
|
701
|
+
className: "text-xl",
|
|
702
|
+
fontWeight: "bold",
|
|
703
|
+
color: "text100",
|
|
704
|
+
children: "Wrong network"
|
|
705
|
+
}),
|
|
706
|
+
/* @__PURE__ */ jsx(AlertMessage, {
|
|
707
|
+
type: "warning",
|
|
708
|
+
message: `You need to switch to ${chainName} network before completing the transaction`
|
|
709
|
+
}),
|
|
710
|
+
/* @__PURE__ */ jsx(Button, {
|
|
711
|
+
className: `${isSwitching ? "flex w-[147px] items-center justify-center [&>div]:justify-center" : "w-[147px]"} flex justify-self-end`,
|
|
712
|
+
name: "switch-chain",
|
|
713
|
+
id: "switch-chain-button",
|
|
714
|
+
size: "sm",
|
|
715
|
+
label: isSwitching ? /* @__PURE__ */ jsx("div", {
|
|
716
|
+
"data-testid": "switch-chain-spinner",
|
|
717
|
+
children: /* @__PURE__ */ jsx(Spinner, { className: "spinner" })
|
|
718
|
+
}) : "Switch Network",
|
|
719
|
+
variant: "primary",
|
|
720
|
+
pending: isSwitching,
|
|
721
|
+
shape: "square",
|
|
722
|
+
onClick: handleSwitchChain,
|
|
723
|
+
"data-testid": "switch-chain-button"
|
|
724
|
+
})
|
|
725
|
+
]
|
|
726
|
+
})
|
|
727
|
+
});
|
|
728
|
+
};
|
|
729
|
+
var switchChainModal_default = SwitchChainModal;
|
|
730
|
+
|
|
731
|
+
//#endregion
|
|
732
|
+
//#region src/react/hooks/useGenerateCancelTransaction.tsx
|
|
733
|
+
const generateCancelTransaction = async (args, config) => {
|
|
734
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
735
|
+
return marketplaceClient.generateCancelTransaction({
|
|
736
|
+
...args,
|
|
737
|
+
chainId: String(args.chainId)
|
|
738
|
+
}).then((data) => data.steps);
|
|
739
|
+
};
|
|
740
|
+
const useGenerateCancelTransaction = (params) => {
|
|
741
|
+
const config = useConfig();
|
|
742
|
+
const { mutate, mutateAsync,...result } = useMutation({
|
|
743
|
+
onSuccess: params.onSuccess,
|
|
744
|
+
mutationFn: (args) => generateCancelTransaction(args, config)
|
|
745
|
+
});
|
|
746
|
+
return {
|
|
747
|
+
...result,
|
|
748
|
+
generateCancelTransaction: mutate,
|
|
749
|
+
generateCancelTransactionAsync: mutateAsync
|
|
750
|
+
};
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
//#endregion
|
|
754
|
+
//#region src/react/hooks/util/optimisticCancelUpdates.ts
|
|
755
|
+
const SECOND = 1e3;
|
|
756
|
+
const updateQueriesOnCancel = ({ orderId, queryClient }) => {
|
|
757
|
+
queryClient.setQueriesData({
|
|
758
|
+
queryKey: collectableKeys.offersCount,
|
|
759
|
+
exact: false
|
|
760
|
+
}, (oldData) => {
|
|
761
|
+
if (!oldData) return 0;
|
|
762
|
+
return Math.max(0, oldData.count - 1);
|
|
763
|
+
});
|
|
764
|
+
queryClient.setQueriesData({
|
|
765
|
+
queryKey: collectableKeys.offers,
|
|
766
|
+
exact: false
|
|
767
|
+
}, (oldData) => {
|
|
768
|
+
if (!oldData || !oldData.offers) return oldData;
|
|
769
|
+
return {
|
|
770
|
+
...oldData,
|
|
771
|
+
offers: oldData.offers.filter((offer) => offer.orderId !== orderId)
|
|
772
|
+
};
|
|
773
|
+
});
|
|
774
|
+
setTimeout(() => {
|
|
775
|
+
queryClient.invalidateQueries({
|
|
776
|
+
queryKey: collectableKeys.highestOffers,
|
|
777
|
+
exact: false
|
|
778
|
+
});
|
|
779
|
+
}, 2 * SECOND);
|
|
780
|
+
queryClient.setQueriesData({
|
|
781
|
+
queryKey: collectableKeys.listingsCount,
|
|
782
|
+
exact: false
|
|
783
|
+
}, (oldData) => {
|
|
784
|
+
if (!oldData) return 0;
|
|
785
|
+
return Math.max(0, oldData.count - 1);
|
|
786
|
+
});
|
|
787
|
+
queryClient.setQueriesData({
|
|
788
|
+
queryKey: collectableKeys.listings,
|
|
789
|
+
exact: false
|
|
790
|
+
}, (oldData) => {
|
|
791
|
+
if (!oldData || !oldData.listings) return oldData;
|
|
792
|
+
return {
|
|
793
|
+
...oldData,
|
|
794
|
+
listings: oldData.listings.filter((listing) => listing.orderId !== orderId)
|
|
795
|
+
};
|
|
796
|
+
});
|
|
797
|
+
setTimeout(() => {
|
|
798
|
+
queryClient.invalidateQueries({
|
|
799
|
+
queryKey: collectableKeys.lowestListings,
|
|
800
|
+
exact: false
|
|
801
|
+
});
|
|
802
|
+
}, 2 * SECOND);
|
|
803
|
+
};
|
|
804
|
+
const invalidateQueriesOnCancel = ({ queryClient }) => {
|
|
805
|
+
queryClient.invalidateQueries({
|
|
806
|
+
queryKey: collectableKeys.offers,
|
|
807
|
+
exact: false
|
|
808
|
+
});
|
|
809
|
+
queryClient.invalidateQueries({
|
|
810
|
+
queryKey: collectableKeys.offersCount,
|
|
811
|
+
exact: false
|
|
812
|
+
});
|
|
813
|
+
queryClient.invalidateQueries({
|
|
814
|
+
queryKey: collectableKeys.listings,
|
|
815
|
+
exact: false
|
|
816
|
+
});
|
|
817
|
+
queryClient.invalidateQueries({
|
|
818
|
+
queryKey: collectableKeys.listingsCount,
|
|
819
|
+
exact: false
|
|
820
|
+
});
|
|
821
|
+
queryClient.invalidateQueries({
|
|
822
|
+
queryKey: collectableKeys.highestOffers,
|
|
823
|
+
exact: false
|
|
824
|
+
});
|
|
825
|
+
queryClient.invalidateQueries({
|
|
826
|
+
queryKey: collectableKeys.lowestListings,
|
|
827
|
+
exact: false
|
|
828
|
+
});
|
|
829
|
+
};
|
|
830
|
+
|
|
831
|
+
//#endregion
|
|
832
|
+
//#region src/react/hooks/useCancelTransactionSteps.tsx
|
|
833
|
+
const useCancelTransactionSteps = ({ collectionAddress, chainId, callbacks, setSteps, onSuccess, onError }) => {
|
|
834
|
+
const { show: showSwitchChainModal } = useSwitchChainModal();
|
|
835
|
+
const { wallet: wallet$1, isLoading, isError } = useWallet();
|
|
836
|
+
const walletIsInitialized = wallet$1 && !isLoading && !isError;
|
|
837
|
+
const sdkConfig = useConfig();
|
|
838
|
+
const marketplaceClient = getMarketplaceClient(sdkConfig);
|
|
839
|
+
const { generateCancelTransactionAsync } = useGenerateCancelTransaction({ chainId });
|
|
840
|
+
const getWalletChainId = async () => {
|
|
841
|
+
return await wallet$1?.getChainId();
|
|
842
|
+
};
|
|
843
|
+
const switchChain = async () => {
|
|
844
|
+
await wallet$1?.switchChain(Number(chainId));
|
|
845
|
+
};
|
|
846
|
+
const checkAndSwitchChain = async () => {
|
|
847
|
+
const walletChainId = await getWalletChainId();
|
|
848
|
+
const isWaaS = wallet$1?.isWaaS;
|
|
849
|
+
const chainIdMismatch = walletChainId !== Number(chainId);
|
|
850
|
+
return new Promise((resolve, reject) => {
|
|
851
|
+
if (chainIdMismatch) if (isWaaS) switchChain().then(resolve).catch(reject);
|
|
852
|
+
else showSwitchChainModal({
|
|
853
|
+
chainIdToSwitchTo: chainId,
|
|
854
|
+
onSuccess: () => resolve({ chainId }),
|
|
855
|
+
onError: (error) => reject(error),
|
|
856
|
+
onClose: () => reject(new ChainSwitchUserRejectedError())
|
|
857
|
+
});
|
|
858
|
+
else resolve({ chainId });
|
|
859
|
+
});
|
|
860
|
+
};
|
|
861
|
+
const getCancelSteps = async ({ orderId, marketplace }) => {
|
|
862
|
+
try {
|
|
863
|
+
const address = await wallet$1?.address();
|
|
864
|
+
if (!address) throw new Error("Wallet address not found");
|
|
865
|
+
const steps = await generateCancelTransactionAsync({
|
|
866
|
+
chainId,
|
|
867
|
+
collectionAddress,
|
|
868
|
+
maker: address,
|
|
869
|
+
marketplace,
|
|
870
|
+
orderId
|
|
871
|
+
});
|
|
872
|
+
return steps;
|
|
873
|
+
} catch (error) {
|
|
874
|
+
if (callbacks?.onError) callbacks.onError(error);
|
|
875
|
+
else console.debug("onError callback not provided:", error);
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
const cancelOrder = async ({ orderId, marketplace }) => {
|
|
879
|
+
const queryClient = getQueryClient();
|
|
880
|
+
if (!walletIsInitialized) throw new WalletInstanceNotFoundError();
|
|
881
|
+
try {
|
|
882
|
+
await checkAndSwitchChain();
|
|
883
|
+
setSteps((prev) => ({
|
|
884
|
+
...prev,
|
|
885
|
+
isExecuting: true
|
|
886
|
+
}));
|
|
887
|
+
const cancelSteps = await getCancelSteps({
|
|
888
|
+
orderId,
|
|
889
|
+
marketplace
|
|
890
|
+
});
|
|
891
|
+
const transactionStep = cancelSteps?.find((step) => step.id === StepType.cancel);
|
|
892
|
+
const signatureStep = cancelSteps?.find((step) => step.id === StepType.signEIP712);
|
|
893
|
+
console.debug("transactionStep", transactionStep);
|
|
894
|
+
console.debug("signatureStep", signatureStep);
|
|
895
|
+
if (!transactionStep && !signatureStep) throw new Error("No transaction or signature step found");
|
|
896
|
+
let hash;
|
|
897
|
+
let reservoirOrderId;
|
|
898
|
+
if (transactionStep && wallet$1) {
|
|
899
|
+
hash = await executeTransaction({ transactionStep });
|
|
900
|
+
if (hash) {
|
|
901
|
+
await wallet$1.handleConfirmTransactionStep(hash, Number(chainId));
|
|
902
|
+
if (onSuccess && typeof onSuccess === "function") {
|
|
903
|
+
onSuccess({ hash });
|
|
904
|
+
updateQueriesOnCancel({
|
|
905
|
+
orderId,
|
|
906
|
+
queryClient
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
setSteps((prev) => ({
|
|
910
|
+
...prev,
|
|
911
|
+
isExecuting: false
|
|
912
|
+
}));
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
if (signatureStep) {
|
|
916
|
+
reservoirOrderId = await executeSignature({ signatureStep });
|
|
917
|
+
if (onSuccess && typeof onSuccess === "function") {
|
|
918
|
+
onSuccess({ orderId: reservoirOrderId });
|
|
919
|
+
updateQueriesOnCancel({
|
|
920
|
+
orderId: reservoirOrderId,
|
|
921
|
+
queryClient
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
setSteps((prev) => ({
|
|
925
|
+
...prev,
|
|
926
|
+
isExecuting: false
|
|
927
|
+
}));
|
|
928
|
+
}
|
|
929
|
+
} catch (error) {
|
|
930
|
+
invalidateQueriesOnCancel({ queryClient });
|
|
931
|
+
setSteps((prev) => ({
|
|
932
|
+
...prev,
|
|
933
|
+
isExecuting: false
|
|
934
|
+
}));
|
|
935
|
+
if (onError && typeof onError === "function") onError(error);
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
const executeTransaction = async ({ transactionStep }) => {
|
|
939
|
+
const hash = await wallet$1?.handleSendTransactionStep(Number(chainId), transactionStep);
|
|
940
|
+
return hash;
|
|
941
|
+
};
|
|
942
|
+
const executeSignature = async ({ signatureStep }) => {
|
|
943
|
+
const signature = await wallet$1?.handleSignMessageStep(signatureStep);
|
|
944
|
+
const result = await marketplaceClient.execute({
|
|
945
|
+
chainId: String(chainId),
|
|
946
|
+
signature,
|
|
947
|
+
method: signatureStep.post?.method,
|
|
948
|
+
endpoint: signatureStep.post?.endpoint,
|
|
949
|
+
body: signatureStep.post?.body,
|
|
950
|
+
executeType: ExecuteType.order
|
|
951
|
+
});
|
|
952
|
+
return result.orderId;
|
|
953
|
+
};
|
|
954
|
+
return { cancelOrder };
|
|
955
|
+
};
|
|
956
|
+
|
|
957
|
+
//#endregion
|
|
958
|
+
//#region src/react/hooks/useCancelOrder.tsx
|
|
959
|
+
const useCancelOrder = ({ collectionAddress, chainId, onSuccess, onError }) => {
|
|
960
|
+
const [steps, setSteps] = useState({
|
|
961
|
+
exist: false,
|
|
962
|
+
isExecuting: false,
|
|
963
|
+
execute: () => Promise.resolve()
|
|
964
|
+
});
|
|
965
|
+
const [cancellingOrderId, setCancellingOrderId] = useState(null);
|
|
966
|
+
const [pendingFeeOptionConfirmation, confirmPendingFeeOption] = useWaasFeeOptions();
|
|
967
|
+
const autoSelectOptionPromise = useAutoSelectFeeOption({
|
|
968
|
+
pendingFeeOptionConfirmation: pendingFeeOptionConfirmation ? {
|
|
969
|
+
id: pendingFeeOptionConfirmation.id,
|
|
970
|
+
options: pendingFeeOptionConfirmation.options?.map((opt) => ({
|
|
971
|
+
...opt,
|
|
972
|
+
token: {
|
|
973
|
+
...opt.token,
|
|
974
|
+
contractAddress: opt.token.contractAddress || null,
|
|
975
|
+
decimals: opt.token.decimals || 0,
|
|
976
|
+
tokenID: opt.token.tokenID || null
|
|
977
|
+
}
|
|
978
|
+
})),
|
|
979
|
+
chainId
|
|
980
|
+
} : {
|
|
981
|
+
id: "",
|
|
982
|
+
options: void 0,
|
|
983
|
+
chainId
|
|
984
|
+
},
|
|
985
|
+
enabled: !!pendingFeeOptionConfirmation
|
|
986
|
+
});
|
|
987
|
+
useEffect(() => {
|
|
988
|
+
autoSelectOptionPromise.then((res) => {
|
|
989
|
+
if (pendingFeeOptionConfirmation?.id && res.selectedOption) confirmPendingFeeOption(pendingFeeOptionConfirmation.id, res.selectedOption.token.contractAddress);
|
|
990
|
+
});
|
|
991
|
+
}, [
|
|
992
|
+
autoSelectOptionPromise,
|
|
993
|
+
confirmPendingFeeOption,
|
|
994
|
+
pendingFeeOptionConfirmation
|
|
995
|
+
]);
|
|
996
|
+
const { cancelOrder: cancelOrderBase } = useCancelTransactionSteps({
|
|
997
|
+
collectionAddress,
|
|
998
|
+
chainId,
|
|
999
|
+
onSuccess: (result) => {
|
|
1000
|
+
setCancellingOrderId(null);
|
|
1001
|
+
onSuccess?.(result);
|
|
1002
|
+
},
|
|
1003
|
+
onError: (error) => {
|
|
1004
|
+
setCancellingOrderId(null);
|
|
1005
|
+
onError?.(error);
|
|
1006
|
+
},
|
|
1007
|
+
setSteps
|
|
1008
|
+
});
|
|
1009
|
+
const cancelOrder = async (params) => {
|
|
1010
|
+
setCancellingOrderId(params.orderId);
|
|
1011
|
+
return cancelOrderBase(params);
|
|
1012
|
+
};
|
|
1013
|
+
return {
|
|
1014
|
+
cancelOrder,
|
|
1015
|
+
isExecuting: steps.isExecuting,
|
|
1016
|
+
cancellingOrderId
|
|
1017
|
+
};
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
//#endregion
|
|
1021
|
+
//#region src/react/queries/checkoutOptionsSalesContract.ts
|
|
1022
|
+
/**
|
|
1023
|
+
* Fetches checkout options for sales contract from the Marketplace API
|
|
1024
|
+
*/
|
|
1025
|
+
async function fetchCheckoutOptionsSalesContract(params) {
|
|
1026
|
+
const { chainId, walletAddress, contractAddress, collectionAddress, items, config } = params;
|
|
1027
|
+
const client = getMarketplaceClient(config);
|
|
1028
|
+
const apiArgs = {
|
|
1029
|
+
chainId: String(chainId),
|
|
1030
|
+
wallet: walletAddress,
|
|
1031
|
+
contractAddress,
|
|
1032
|
+
collectionAddress,
|
|
1033
|
+
items
|
|
1034
|
+
};
|
|
1035
|
+
const result = await client.checkoutOptionsSalesContract(apiArgs);
|
|
1036
|
+
return result;
|
|
1037
|
+
}
|
|
1038
|
+
function checkoutOptionsSalesContractQueryOptions(params) {
|
|
1039
|
+
const enabled = Boolean(params.chainId && params.walletAddress && params.contractAddress && params.collectionAddress && params.items?.length && params.config && (params.query?.enabled ?? true));
|
|
1040
|
+
return queryOptions({
|
|
1041
|
+
queryKey: [
|
|
1042
|
+
"checkout",
|
|
1043
|
+
"options",
|
|
1044
|
+
"salesContract",
|
|
1045
|
+
params
|
|
1046
|
+
],
|
|
1047
|
+
queryFn: () => fetchCheckoutOptionsSalesContract({
|
|
1048
|
+
chainId: params.chainId,
|
|
1049
|
+
walletAddress: params.walletAddress,
|
|
1050
|
+
contractAddress: params.contractAddress,
|
|
1051
|
+
collectionAddress: params.collectionAddress,
|
|
1052
|
+
items: params.items,
|
|
1053
|
+
config: params.config
|
|
1054
|
+
}),
|
|
1055
|
+
...params.query,
|
|
1056
|
+
enabled
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
//#endregion
|
|
1061
|
+
//#region src/react/hooks/useCheckoutOptionsSalesContract.tsx
|
|
1062
|
+
/**
|
|
1063
|
+
* Hook to fetch checkout options for sales contract items
|
|
1064
|
+
*
|
|
1065
|
+
* Retrieves checkout options including available payment methods, fees, and transaction details
|
|
1066
|
+
* for items from a sales contract. Requires a connected wallet to calculate wallet-specific options.
|
|
1067
|
+
*
|
|
1068
|
+
* @param params - Configuration parameters or skipToken to skip the query
|
|
1069
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1070
|
+
* @param params.contractAddress - The sales contract address
|
|
1071
|
+
* @param params.collectionAddress - The collection contract address
|
|
1072
|
+
* @param params.items - Array of items to purchase with tokenId and quantity
|
|
1073
|
+
* @param params.query - Optional React Query configuration
|
|
1074
|
+
*
|
|
1075
|
+
* @returns Query result containing checkout options with payment methods and fees
|
|
1076
|
+
*
|
|
1077
|
+
* @example
|
|
1078
|
+
* Basic usage:
|
|
1079
|
+
* ```typescript
|
|
1080
|
+
* const { data: checkoutOptions, isLoading } = useCheckoutOptionsSalesContract({
|
|
1081
|
+
* chainId: 137,
|
|
1082
|
+
* contractAddress: '0x1234...',
|
|
1083
|
+
* collectionAddress: '0x5678...',
|
|
1084
|
+
* items: [{
|
|
1085
|
+
* tokenId: '1',
|
|
1086
|
+
* quantity: '1'
|
|
1087
|
+
* }]
|
|
1088
|
+
* })
|
|
1089
|
+
* ```
|
|
1090
|
+
*
|
|
1091
|
+
* @example
|
|
1092
|
+
* With skipToken to conditionally skip:
|
|
1093
|
+
* ```typescript
|
|
1094
|
+
* const { data: checkoutOptions } = useCheckoutOptionsSalesContract(
|
|
1095
|
+
* items.length > 0 ? {
|
|
1096
|
+
* chainId: 1,
|
|
1097
|
+
* contractAddress: contractAddress,
|
|
1098
|
+
* collectionAddress: collectionAddress,
|
|
1099
|
+
* items: items
|
|
1100
|
+
* } : skipToken
|
|
1101
|
+
* )
|
|
1102
|
+
* ```
|
|
1103
|
+
*/
|
|
1104
|
+
function useCheckoutOptionsSalesContract(params) {
|
|
1105
|
+
const { address } = useAccount();
|
|
1106
|
+
const defaultConfig = useConfig();
|
|
1107
|
+
const queryOptions$1 = checkoutOptionsSalesContractQueryOptions(params === skipToken ? {
|
|
1108
|
+
config: defaultConfig,
|
|
1109
|
+
walletAddress: address,
|
|
1110
|
+
chainId: 0,
|
|
1111
|
+
contractAddress: "",
|
|
1112
|
+
collectionAddress: "",
|
|
1113
|
+
items: [],
|
|
1114
|
+
query: { enabled: false }
|
|
1115
|
+
} : {
|
|
1116
|
+
config: defaultConfig,
|
|
1117
|
+
walletAddress: address,
|
|
1118
|
+
...params
|
|
1119
|
+
});
|
|
1120
|
+
return useQuery({ ...queryOptions$1 });
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/react/hooks/useCollectible.tsx
|
|
1125
|
+
/**
|
|
1126
|
+
* Hook to fetch metadata for a specific collectible
|
|
1127
|
+
*
|
|
1128
|
+
* This hook retrieves metadata for an individual NFT from a collection,
|
|
1129
|
+
* including properties like name, description, image, attributes, etc.
|
|
1130
|
+
*
|
|
1131
|
+
* @param params - Configuration parameters
|
|
1132
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1133
|
+
* @param params.collectionAddress - The collection contract address
|
|
1134
|
+
* @param params.collectibleId - The token ID of the collectible
|
|
1135
|
+
* @param params.query - Optional React Query configuration
|
|
1136
|
+
*
|
|
1137
|
+
* @returns Query result containing the collectible metadata
|
|
1138
|
+
*
|
|
1139
|
+
* @example
|
|
1140
|
+
* Basic usage:
|
|
1141
|
+
* ```typescript
|
|
1142
|
+
* const { data: collectible, isLoading } = useCollectible({
|
|
1143
|
+
* chainId: 137,
|
|
1144
|
+
* collectionAddress: '0x631998e91476da5b870d741192fc5cbc55f5a52e',
|
|
1145
|
+
* collectibleId: '12345'
|
|
1146
|
+
* })
|
|
1147
|
+
* ```
|
|
1148
|
+
*
|
|
1149
|
+
* @example
|
|
1150
|
+
* With custom query options:
|
|
1151
|
+
* ```typescript
|
|
1152
|
+
* const { data } = useCollectible({
|
|
1153
|
+
* chainId: 137,
|
|
1154
|
+
* collectionAddress: '0x631998e91476da5b870d741192fc5cbc55f5a52e',
|
|
1155
|
+
* collectibleId: '12345',
|
|
1156
|
+
* query: {
|
|
1157
|
+
* enabled: Boolean(collectionAddress && tokenId),
|
|
1158
|
+
* staleTime: 30_000
|
|
1159
|
+
* }
|
|
1160
|
+
* })
|
|
1161
|
+
* ```
|
|
1162
|
+
*/
|
|
1163
|
+
function useCollectible(params) {
|
|
1164
|
+
const defaultConfig = useConfig();
|
|
1165
|
+
const { config = defaultConfig,...rest } = params;
|
|
1166
|
+
const queryOptions$1 = collectibleQueryOptions({
|
|
1167
|
+
config,
|
|
1168
|
+
...rest
|
|
1169
|
+
});
|
|
1170
|
+
return useQuery({ ...queryOptions$1 });
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
//#endregion
|
|
1174
|
+
//#region src/react/queries/collection.ts
|
|
1175
|
+
/**
|
|
1176
|
+
* Fetches collection information from the metadata API
|
|
1177
|
+
*/
|
|
1178
|
+
async function fetchCollection(params) {
|
|
1179
|
+
const { collectionAddress, chainId, config } = params;
|
|
1180
|
+
const metadataClient = getMetadataClient(config);
|
|
1181
|
+
const result = await metadataClient.getContractInfo({
|
|
1182
|
+
chainID: chainId.toString(),
|
|
1183
|
+
contractAddress: collectionAddress
|
|
1184
|
+
});
|
|
1185
|
+
return result.contractInfo;
|
|
1186
|
+
}
|
|
1187
|
+
function collectionQueryOptions(params) {
|
|
1188
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.config && (params.query?.enabled ?? true));
|
|
1189
|
+
return queryOptions({
|
|
1190
|
+
queryKey: [...collectionKeys.detail, params],
|
|
1191
|
+
queryFn: () => fetchCollection({
|
|
1192
|
+
chainId: params.chainId,
|
|
1193
|
+
collectionAddress: params.collectionAddress,
|
|
1194
|
+
config: params.config
|
|
1195
|
+
}),
|
|
1196
|
+
...params.query,
|
|
1197
|
+
enabled
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
//#endregion
|
|
1202
|
+
//#region src/react/hooks/useCollection.tsx
|
|
1203
|
+
/**
|
|
1204
|
+
* Hook to fetch collection information from the metadata API
|
|
1205
|
+
*
|
|
1206
|
+
* Retrieves basic contract information including name, symbol, type,
|
|
1207
|
+
* and extension data for a given collection contract.
|
|
1208
|
+
*
|
|
1209
|
+
* @param params - Configuration parameters
|
|
1210
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1211
|
+
* @param params.collectionAddress - The collection contract address
|
|
1212
|
+
* @param params.query - Optional React Query configuration
|
|
1213
|
+
*
|
|
1214
|
+
* @returns Query result containing contract information
|
|
1215
|
+
*
|
|
1216
|
+
* @example
|
|
1217
|
+
* Basic usage:
|
|
1218
|
+
* ```typescript
|
|
1219
|
+
* const { data, isLoading } = useCollection({
|
|
1220
|
+
* chainId: 137,
|
|
1221
|
+
* collectionAddress: '0x...'
|
|
1222
|
+
* })
|
|
1223
|
+
* ```
|
|
1224
|
+
*
|
|
1225
|
+
* @example
|
|
1226
|
+
* With custom query options:
|
|
1227
|
+
* ```typescript
|
|
1228
|
+
* const { data, isLoading } = useCollection({
|
|
1229
|
+
* chainId: 1,
|
|
1230
|
+
* collectionAddress: '0x...',
|
|
1231
|
+
* query: {
|
|
1232
|
+
* refetchInterval: 30000,
|
|
1233
|
+
* enabled: userWantsToFetch
|
|
1234
|
+
* }
|
|
1235
|
+
* })
|
|
1236
|
+
* ```
|
|
1237
|
+
*/
|
|
1238
|
+
function useCollection(params) {
|
|
1239
|
+
const defaultConfig = useConfig();
|
|
1240
|
+
const { config = defaultConfig,...rest } = params;
|
|
1241
|
+
const queryOptions$1 = collectionQueryOptions({
|
|
1242
|
+
config,
|
|
1243
|
+
...rest
|
|
1244
|
+
});
|
|
1245
|
+
return useQuery({ ...queryOptions$1 });
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
//#endregion
|
|
1249
|
+
//#region src/react/hooks/useCollectionDetails.ts
|
|
1250
|
+
/**
|
|
1251
|
+
* Hook to fetch detailed information about a collection
|
|
1252
|
+
*
|
|
1253
|
+
* This hook retrieves comprehensive metadata and details for an NFT collection,
|
|
1254
|
+
* including collection name, description, banner, avatar, social links, stats, etc.
|
|
1255
|
+
*
|
|
1256
|
+
* @param params - Configuration parameters
|
|
1257
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1258
|
+
* @param params.collectionAddress - The collection contract address
|
|
1259
|
+
* @param params.query - Optional React Query configuration
|
|
1260
|
+
*
|
|
1261
|
+
* @returns Query result containing the collection details
|
|
1262
|
+
*
|
|
1263
|
+
* @example
|
|
1264
|
+
* Basic usage:
|
|
1265
|
+
* ```typescript
|
|
1266
|
+
* const { data: collection, isLoading } = useCollectionDetails({
|
|
1267
|
+
* chainId: 137,
|
|
1268
|
+
* collectionAddress: '0x631998e91476da5b870d741192fc5cbc55f5a52e'
|
|
1269
|
+
* })
|
|
1270
|
+
* ```
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* With custom query options:
|
|
1274
|
+
* ```typescript
|
|
1275
|
+
* const { data } = useCollectionDetails({
|
|
1276
|
+
* chainId: 137,
|
|
1277
|
+
* collectionAddress: '0x631998e91476da5b870d741192fc5cbc55f5a52e',
|
|
1278
|
+
* query: {
|
|
1279
|
+
* enabled: Boolean(collectionAddress),
|
|
1280
|
+
* staleTime: 60_000
|
|
1281
|
+
* }
|
|
1282
|
+
* })
|
|
1283
|
+
* ```
|
|
1284
|
+
*/
|
|
1285
|
+
function useCollectionDetails(params) {
|
|
1286
|
+
const defaultConfig = useConfig();
|
|
1287
|
+
const { config = defaultConfig,...rest } = params;
|
|
1288
|
+
const queryOptions$1 = collectionDetailsQueryOptions({
|
|
1289
|
+
config,
|
|
1290
|
+
...rest
|
|
1291
|
+
});
|
|
1292
|
+
return useQuery({ ...queryOptions$1 });
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
//#endregion
|
|
1296
|
+
//#region src/react/hooks/useCollectionDetailsPolling.tsx
|
|
1297
|
+
const INITIAL_POLLING_INTERVAL = 2e3;
|
|
1298
|
+
const MAX_POLLING_INTERVAL = 3e4;
|
|
1299
|
+
const MAX_ATTEMPTS = 30;
|
|
1300
|
+
const isTerminalState = (status) => {
|
|
1301
|
+
return [
|
|
1302
|
+
CollectionStatus.active,
|
|
1303
|
+
CollectionStatus.failed,
|
|
1304
|
+
CollectionStatus.inactive,
|
|
1305
|
+
CollectionStatus.incompatible_type
|
|
1306
|
+
].includes(status);
|
|
1307
|
+
};
|
|
1308
|
+
const collectionDetailsPollingOptions = (args, config) => {
|
|
1309
|
+
return queryOptions({
|
|
1310
|
+
...collectionDetailsQueryOptions({
|
|
1311
|
+
...args,
|
|
1312
|
+
config
|
|
1313
|
+
}),
|
|
1314
|
+
refetchInterval: (query) => {
|
|
1315
|
+
const data = query.state.data;
|
|
1316
|
+
if (data && isTerminalState(data.status)) return false;
|
|
1317
|
+
const currentAttempt = (query.state.dataUpdateCount || 0) + 1;
|
|
1318
|
+
if (currentAttempt >= MAX_ATTEMPTS) return false;
|
|
1319
|
+
const interval = Math.min(INITIAL_POLLING_INTERVAL * 1.5 ** currentAttempt, MAX_POLLING_INTERVAL);
|
|
1320
|
+
return interval;
|
|
1321
|
+
},
|
|
1322
|
+
refetchOnWindowFocus: false,
|
|
1323
|
+
retry: false,
|
|
1324
|
+
enabled: args.query?.enabled ?? true
|
|
1325
|
+
});
|
|
1326
|
+
};
|
|
1327
|
+
const useCollectionDetailsPolling = (args) => {
|
|
1328
|
+
const config = useConfig();
|
|
1329
|
+
return useQuery(collectionDetailsPollingOptions(args, config));
|
|
1330
|
+
};
|
|
1331
|
+
|
|
1332
|
+
//#endregion
|
|
1333
|
+
//#region src/react/queries/convertPriceToUSD.ts
|
|
1334
|
+
/**
|
|
1335
|
+
* Converts a price amount from a specific currency to USD using exchange rates
|
|
1336
|
+
*/
|
|
1337
|
+
async function fetchConvertPriceToUSD(params) {
|
|
1338
|
+
const { chainId, currencyAddress, amountRaw, config } = params;
|
|
1339
|
+
const queryClient = getQueryClient();
|
|
1340
|
+
const currencies = await queryClient.fetchQuery(marketCurrenciesQueryOptions({
|
|
1341
|
+
chainId,
|
|
1342
|
+
config
|
|
1343
|
+
}));
|
|
1344
|
+
const currencyDetails = currencies.find((c) => c.contractAddress.toLowerCase() === currencyAddress.toLowerCase());
|
|
1345
|
+
if (!currencyDetails) throw new Error("Currency not found");
|
|
1346
|
+
const amountDecimal = Number(formatUnits(BigInt(amountRaw), currencyDetails.decimals));
|
|
1347
|
+
const usdAmount = amountDecimal * currencyDetails.exchangeRate;
|
|
1348
|
+
return {
|
|
1349
|
+
usdAmount,
|
|
1350
|
+
usdAmountFormatted: usdAmount.toFixed(2)
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
function convertPriceToUSDQueryOptions(params) {
|
|
1354
|
+
const enabled = Boolean(params.chainId && params.currencyAddress && params.amountRaw && params.config && (params.query?.enabled ?? true));
|
|
1355
|
+
return queryOptions({
|
|
1356
|
+
queryKey: [
|
|
1357
|
+
"currency",
|
|
1358
|
+
"convertPriceToUSD",
|
|
1359
|
+
params
|
|
1360
|
+
],
|
|
1361
|
+
queryFn: () => fetchConvertPriceToUSD({
|
|
1362
|
+
chainId: params.chainId,
|
|
1363
|
+
currencyAddress: params.currencyAddress,
|
|
1364
|
+
amountRaw: params.amountRaw,
|
|
1365
|
+
config: params.config
|
|
1366
|
+
}),
|
|
1367
|
+
...params.query,
|
|
1368
|
+
enabled
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
//#endregion
|
|
1373
|
+
//#region src/react/queries/comparePrices.ts
|
|
1374
|
+
/**
|
|
1375
|
+
* Compares prices between different currencies by converting both to USD
|
|
1376
|
+
*/
|
|
1377
|
+
async function fetchComparePrices(params) {
|
|
1378
|
+
const { chainId, priceAmountRaw, priceCurrencyAddress, compareToPriceAmountRaw, compareToPriceCurrencyAddress, config } = params;
|
|
1379
|
+
const [priceUSD, compareToPriceUSD] = await Promise.all([fetchConvertPriceToUSD({
|
|
1380
|
+
chainId,
|
|
1381
|
+
currencyAddress: priceCurrencyAddress,
|
|
1382
|
+
amountRaw: priceAmountRaw,
|
|
1383
|
+
config
|
|
1384
|
+
}), fetchConvertPriceToUSD({
|
|
1385
|
+
chainId,
|
|
1386
|
+
currencyAddress: compareToPriceCurrencyAddress,
|
|
1387
|
+
amountRaw: compareToPriceAmountRaw,
|
|
1388
|
+
config
|
|
1389
|
+
})]);
|
|
1390
|
+
const difference = priceUSD.usdAmount - compareToPriceUSD.usdAmount;
|
|
1391
|
+
if (compareToPriceUSD.usdAmount === 0) throw new Error("Cannot compare to zero price");
|
|
1392
|
+
const percentageDifference = difference / compareToPriceUSD.usdAmount * 100;
|
|
1393
|
+
const isAbove = percentageDifference > 0;
|
|
1394
|
+
const isSame = percentageDifference === 0;
|
|
1395
|
+
return {
|
|
1396
|
+
percentageDifference,
|
|
1397
|
+
percentageDifferenceFormatted: Math.abs(percentageDifference).toFixed(2),
|
|
1398
|
+
status: isAbove ? "above" : isSame ? "same" : "below"
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
function comparePricesQueryOptions(params) {
|
|
1402
|
+
const enabled = Boolean(params.chainId && params.priceAmountRaw && params.priceCurrencyAddress && params.compareToPriceAmountRaw && params.compareToPriceCurrencyAddress && params.config && (params.query?.enabled ?? true));
|
|
1403
|
+
return queryOptions({
|
|
1404
|
+
queryKey: [
|
|
1405
|
+
"currency",
|
|
1406
|
+
"conversion",
|
|
1407
|
+
"compare",
|
|
1408
|
+
params
|
|
1409
|
+
],
|
|
1410
|
+
queryFn: () => fetchComparePrices({
|
|
1411
|
+
chainId: params.chainId,
|
|
1412
|
+
priceAmountRaw: params.priceAmountRaw,
|
|
1413
|
+
priceCurrencyAddress: params.priceCurrencyAddress,
|
|
1414
|
+
compareToPriceAmountRaw: params.compareToPriceAmountRaw,
|
|
1415
|
+
compareToPriceCurrencyAddress: params.compareToPriceCurrencyAddress,
|
|
1416
|
+
config: params.config
|
|
1417
|
+
}),
|
|
1418
|
+
...params.query,
|
|
1419
|
+
enabled
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
//#endregion
|
|
1424
|
+
//#region src/react/hooks/useComparePrices.tsx
|
|
1425
|
+
/**
|
|
1426
|
+
* Hook to compare prices between different currencies by converting both to USD
|
|
1427
|
+
*
|
|
1428
|
+
* Compares two prices by converting both to USD using real-time exchange rates
|
|
1429
|
+
* and returns the percentage difference with comparison status.
|
|
1430
|
+
*
|
|
1431
|
+
* @param params - Configuration parameters
|
|
1432
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1433
|
+
* @param params.priceAmountRaw - The raw amount of the first price (wei format)
|
|
1434
|
+
* @param params.priceCurrencyAddress - The currency address of the first price
|
|
1435
|
+
* @param params.compareToPriceAmountRaw - The raw amount of the second price to compare against (wei format)
|
|
1436
|
+
* @param params.compareToPriceCurrencyAddress - The currency address of the second price
|
|
1437
|
+
* @param params.query - Optional React Query configuration
|
|
1438
|
+
*
|
|
1439
|
+
* @returns Query result containing percentage difference and comparison status
|
|
1440
|
+
*
|
|
1441
|
+
* @example
|
|
1442
|
+
* Basic usage:
|
|
1443
|
+
* ```typescript
|
|
1444
|
+
* const { data: comparison, isLoading } = useComparePrices({
|
|
1445
|
+
* chainId: 1,
|
|
1446
|
+
* priceAmountRaw: '1000000000000000000', // 1 ETH in wei
|
|
1447
|
+
* priceCurrencyAddress: '0x0000000000000000000000000000000000000000', // ETH
|
|
1448
|
+
* compareToPriceAmountRaw: '2000000000', // 2000 USDC in wei (6 decimals)
|
|
1449
|
+
* compareToPriceCurrencyAddress: '0xA0b86a33E6B8DbF5E71Eaa9bfD3F6fD8e8Be3F69' // USDC
|
|
1450
|
+
* })
|
|
1451
|
+
*
|
|
1452
|
+
* if (data) {
|
|
1453
|
+
* console.log(`${data.percentageDifferenceFormatted}% ${data.status}`);
|
|
1454
|
+
* // e.g., "25.50% above" or "10.25% below"
|
|
1455
|
+
* }
|
|
1456
|
+
* ```
|
|
1457
|
+
*
|
|
1458
|
+
* @example
|
|
1459
|
+
* With custom query options:
|
|
1460
|
+
* ```typescript
|
|
1461
|
+
* const { data: comparison } = useComparePrices({
|
|
1462
|
+
* chainId: 137,
|
|
1463
|
+
* priceAmountRaw: price1,
|
|
1464
|
+
* priceCurrencyAddress: currency1Address,
|
|
1465
|
+
* compareToPriceAmountRaw: price2,
|
|
1466
|
+
* compareToPriceCurrencyAddress: currency2Address,
|
|
1467
|
+
* query: {
|
|
1468
|
+
* enabled: Boolean(price1 && price2),
|
|
1469
|
+
* refetchInterval: 30000 // Refresh every 30 seconds
|
|
1470
|
+
* }
|
|
1471
|
+
* })
|
|
1472
|
+
* ```
|
|
1473
|
+
*/
|
|
1474
|
+
function useComparePrices(params) {
|
|
1475
|
+
const defaultConfig = useConfig();
|
|
1476
|
+
const { config = defaultConfig,...rest } = params;
|
|
1477
|
+
const queryOptions$1 = comparePricesQueryOptions({
|
|
1478
|
+
config,
|
|
1479
|
+
...rest
|
|
1480
|
+
});
|
|
1481
|
+
return useQuery({ ...queryOptions$1 });
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
//#endregion
|
|
1485
|
+
//#region src/react/hooks/useConvertPriceToUSD.tsx
|
|
1486
|
+
/**
|
|
1487
|
+
* Hook to convert a price amount from a specific currency to USD
|
|
1488
|
+
*
|
|
1489
|
+
* Converts cryptocurrency amounts to their USD equivalent using current exchange rates.
|
|
1490
|
+
* Fetches currency data and calculates the USD value based on the provided amount
|
|
1491
|
+
* and currency address.
|
|
1492
|
+
*
|
|
1493
|
+
* @param params - Configuration parameters
|
|
1494
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1495
|
+
* @param params.currencyAddress - The currency contract address to convert from
|
|
1496
|
+
* @param params.amountRaw - The raw amount in smallest units (e.g., wei for ETH)
|
|
1497
|
+
* @param params.query - Optional React Query configuration
|
|
1498
|
+
*
|
|
1499
|
+
* @returns Query result containing USD amount and formatted USD amount
|
|
1500
|
+
*
|
|
1501
|
+
* @example
|
|
1502
|
+
* Basic ETH to USD conversion:
|
|
1503
|
+
* ```typescript
|
|
1504
|
+
* const { data: conversion, isLoading } = useConvertPriceToUSD({
|
|
1505
|
+
* chainId: 1,
|
|
1506
|
+
* currencyAddress: '0x0000000000000000000000000000000000000000', // ETH
|
|
1507
|
+
* amountRaw: '1000000000000000000' // 1 ETH in wei
|
|
1508
|
+
* })
|
|
1509
|
+
*
|
|
1510
|
+
* if (data) {
|
|
1511
|
+
* console.log(`$${data.usdAmountFormatted}`); // e.g., "$2000.00"
|
|
1512
|
+
* console.log(data.usdAmount); // e.g., 2000
|
|
1513
|
+
* }
|
|
1514
|
+
* ```
|
|
1515
|
+
*
|
|
1516
|
+
* @example
|
|
1517
|
+
* ERC-20 token conversion with conditional enabling:
|
|
1518
|
+
* ```typescript
|
|
1519
|
+
* const { data: conversion } = useConvertPriceToUSD({
|
|
1520
|
+
* chainId: 137,
|
|
1521
|
+
* currencyAddress: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', // USDC on Polygon
|
|
1522
|
+
* amountRaw: '1000000', // 1 USDC (6 decimals)
|
|
1523
|
+
* query: {
|
|
1524
|
+
* enabled: Boolean(userHasTokens),
|
|
1525
|
+
* refetchInterval: 30000 // Update price every 30 seconds
|
|
1526
|
+
* }
|
|
1527
|
+
* })
|
|
1528
|
+
* ```
|
|
1529
|
+
*/
|
|
1530
|
+
function useConvertPriceToUSD(params) {
|
|
1531
|
+
const defaultConfig = useConfig();
|
|
1532
|
+
const { config = defaultConfig,...rest } = params;
|
|
1533
|
+
const queryOptions$1 = convertPriceToUSDQueryOptions({
|
|
1534
|
+
config,
|
|
1535
|
+
...rest
|
|
1536
|
+
});
|
|
1537
|
+
return useQuery({ ...queryOptions$1 });
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
//#endregion
|
|
1541
|
+
//#region src/react/queries/countListingsForCollectible.ts
|
|
1542
|
+
/**
|
|
1543
|
+
* Fetches count of listings for a collectible from the marketplace API
|
|
1544
|
+
*/
|
|
1545
|
+
async function fetchCountListingsForCollectible(params) {
|
|
1546
|
+
const { collectionAddress, chainId, collectibleId, config, filter } = params;
|
|
1547
|
+
const client = getMarketplaceClient(config);
|
|
1548
|
+
const apiArgs = {
|
|
1549
|
+
contractAddress: collectionAddress,
|
|
1550
|
+
chainId: String(chainId),
|
|
1551
|
+
tokenId: collectibleId,
|
|
1552
|
+
filter
|
|
1553
|
+
};
|
|
1554
|
+
const result = await client.getCountOfListingsForCollectible(apiArgs);
|
|
1555
|
+
return result.count;
|
|
1556
|
+
}
|
|
1557
|
+
function countListingsForCollectibleQueryOptions(params) {
|
|
1558
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.collectibleId && params.config && (params.query?.enabled ?? true));
|
|
1559
|
+
return queryOptions({
|
|
1560
|
+
queryKey: [...collectableKeys.listingsCount, params],
|
|
1561
|
+
queryFn: () => fetchCountListingsForCollectible({
|
|
1562
|
+
chainId: params.chainId,
|
|
1563
|
+
collectionAddress: params.collectionAddress,
|
|
1564
|
+
collectibleId: params.collectibleId,
|
|
1565
|
+
config: params.config,
|
|
1566
|
+
filter: params.filter
|
|
1567
|
+
}),
|
|
1568
|
+
...params.query,
|
|
1569
|
+
enabled
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
//#endregion
|
|
1574
|
+
//#region src/react/hooks/useCountListingsForCollectible.tsx
|
|
1575
|
+
/**
|
|
1576
|
+
* Hook to get the count of listings for a specific collectible
|
|
1577
|
+
*
|
|
1578
|
+
* Counts the number of active listings for a given collectible in the marketplace.
|
|
1579
|
+
* Useful for displaying listing counts in UI components.
|
|
1580
|
+
*
|
|
1581
|
+
* @param params - Configuration parameters
|
|
1582
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1583
|
+
* @param params.collectionAddress - The collection contract address
|
|
1584
|
+
* @param params.collectibleId - The specific collectible/token ID
|
|
1585
|
+
* @param params.filter - Optional filter criteria for listings
|
|
1586
|
+
* @param params.query - Optional React Query configuration
|
|
1587
|
+
*
|
|
1588
|
+
* @returns Query result containing the count of listings
|
|
1589
|
+
*
|
|
1590
|
+
* @example
|
|
1591
|
+
* Basic usage:
|
|
1592
|
+
* ```typescript
|
|
1593
|
+
* const { data: listingCount, isLoading } = useCountListingsForCollectible({
|
|
1594
|
+
* chainId: 137,
|
|
1595
|
+
* collectionAddress: '0x...',
|
|
1596
|
+
* collectibleId: '123'
|
|
1597
|
+
* })
|
|
1598
|
+
* ```
|
|
1599
|
+
*
|
|
1600
|
+
* @example
|
|
1601
|
+
* With filter:
|
|
1602
|
+
* ```typescript
|
|
1603
|
+
* const { data: filteredCount } = useCountListingsForCollectible({
|
|
1604
|
+
* chainId: 137,
|
|
1605
|
+
* collectionAddress: '0x...',
|
|
1606
|
+
* collectibleId: '123',
|
|
1607
|
+
* filter: { priceRange: { min: '1000000000000000000' } }
|
|
1608
|
+
* })
|
|
1609
|
+
* ```
|
|
1610
|
+
*/
|
|
1611
|
+
function useCountListingsForCollectible(params) {
|
|
1612
|
+
const defaultConfig = useConfig();
|
|
1613
|
+
const { config = defaultConfig,...rest } = params;
|
|
1614
|
+
const queryOptions$1 = countListingsForCollectibleQueryOptions({
|
|
1615
|
+
config,
|
|
1616
|
+
...rest
|
|
1617
|
+
});
|
|
1618
|
+
return useQuery({ ...queryOptions$1 });
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
//#endregion
|
|
1622
|
+
//#region src/react/queries/countOfCollectables.ts
|
|
1623
|
+
/**
|
|
1624
|
+
* Fetches count of collectibles from the marketplace API
|
|
1625
|
+
*/
|
|
1626
|
+
async function fetchCountOfCollectables(params) {
|
|
1627
|
+
const { collectionAddress, chainId, config, filter, side } = params;
|
|
1628
|
+
const client = getMarketplaceClient(config);
|
|
1629
|
+
if (filter && side) {
|
|
1630
|
+
const apiArgs$1 = {
|
|
1631
|
+
contractAddress: collectionAddress,
|
|
1632
|
+
chainId: String(chainId),
|
|
1633
|
+
filter,
|
|
1634
|
+
side
|
|
1635
|
+
};
|
|
1636
|
+
const result$1 = await client.getCountOfFilteredCollectibles(apiArgs$1);
|
|
1637
|
+
return result$1.count;
|
|
1638
|
+
}
|
|
1639
|
+
const apiArgs = {
|
|
1640
|
+
contractAddress: collectionAddress,
|
|
1641
|
+
chainId: String(chainId)
|
|
1642
|
+
};
|
|
1643
|
+
const result = await client.getCountOfAllCollectibles(apiArgs);
|
|
1644
|
+
return result.count;
|
|
1645
|
+
}
|
|
1646
|
+
function countOfCollectablesQueryOptions(params) {
|
|
1647
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.config && (params.query?.enabled ?? true));
|
|
1648
|
+
return queryOptions({
|
|
1649
|
+
queryKey: [...collectableKeys.counts, params],
|
|
1650
|
+
queryFn: () => fetchCountOfCollectables({
|
|
1651
|
+
chainId: params.chainId,
|
|
1652
|
+
collectionAddress: params.collectionAddress,
|
|
1653
|
+
config: params.config,
|
|
1654
|
+
filter: params.filter,
|
|
1655
|
+
side: params.side
|
|
1656
|
+
}),
|
|
1657
|
+
...params.query,
|
|
1658
|
+
enabled
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
//#endregion
|
|
1663
|
+
//#region src/react/hooks/useCountOfCollectables.tsx
|
|
1664
|
+
/**
|
|
1665
|
+
* Hook to get the count of collectibles in a market collection
|
|
1666
|
+
*
|
|
1667
|
+
* Counts either all collectibles or filtered collectibles based on provided parameters.
|
|
1668
|
+
* When filter and side parameters are provided, returns count of filtered collectibles.
|
|
1669
|
+
* Otherwise returns count of all collectibles in the collection.
|
|
1670
|
+
*
|
|
1671
|
+
* @param params - Configuration parameters
|
|
1672
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1673
|
+
* @param params.collectionAddress - The collection contract address
|
|
1674
|
+
* @param params.filter - Optional filter criteria for collectibles
|
|
1675
|
+
* @param params.side - Optional order side (BUY/SELL) when using filters
|
|
1676
|
+
* @param params.query - Optional React Query configuration
|
|
1677
|
+
*
|
|
1678
|
+
* @returns Query result containing the count of collectibles
|
|
1679
|
+
*
|
|
1680
|
+
* @example
|
|
1681
|
+
* Basic usage (count all collectibles):
|
|
1682
|
+
* ```typescript
|
|
1683
|
+
* const { data: totalCount, isLoading } = useCountOfCollectables({
|
|
1684
|
+
* chainId: 137,
|
|
1685
|
+
* collectionAddress: '0x...'
|
|
1686
|
+
* })
|
|
1687
|
+
* ```
|
|
1688
|
+
*
|
|
1689
|
+
* @example
|
|
1690
|
+
* With filters (count filtered collectibles):
|
|
1691
|
+
* ```typescript
|
|
1692
|
+
* const { data: filteredCount } = useCountOfCollectables({
|
|
1693
|
+
* chainId: 137,
|
|
1694
|
+
* collectionAddress: '0x...',
|
|
1695
|
+
* filter: { priceRange: { min: '1000000000000000000' } },
|
|
1696
|
+
* side: OrderSide.SELL
|
|
1697
|
+
* })
|
|
1698
|
+
* ```
|
|
1699
|
+
*/
|
|
1700
|
+
function useCountOfCollectables(params) {
|
|
1701
|
+
const defaultConfig = useConfig();
|
|
1702
|
+
const { config = defaultConfig,...rest } = params;
|
|
1703
|
+
const queryOptions$1 = countOfCollectablesQueryOptions({
|
|
1704
|
+
config,
|
|
1705
|
+
...rest
|
|
1706
|
+
});
|
|
1707
|
+
return useQuery({ ...queryOptions$1 });
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
//#endregion
|
|
1711
|
+
//#region src/react/queries/countOffersForCollectible.ts
|
|
1712
|
+
/**
|
|
1713
|
+
* Fetches count of offers for a collectible from the marketplace API
|
|
1714
|
+
*/
|
|
1715
|
+
async function fetchCountOffersForCollectible(params) {
|
|
1716
|
+
const { collectionAddress, chainId, collectibleId, config, filter } = params;
|
|
1717
|
+
const client = getMarketplaceClient(config);
|
|
1718
|
+
const apiArgs = {
|
|
1719
|
+
contractAddress: collectionAddress,
|
|
1720
|
+
chainId: String(chainId),
|
|
1721
|
+
tokenId: collectibleId,
|
|
1722
|
+
filter
|
|
1723
|
+
};
|
|
1724
|
+
const result = await client.getCountOfOffersForCollectible(apiArgs);
|
|
1725
|
+
return result.count;
|
|
1726
|
+
}
|
|
1727
|
+
function countOffersForCollectibleQueryOptions(params) {
|
|
1728
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.collectibleId && params.config && (params.query?.enabled ?? true));
|
|
1729
|
+
return queryOptions({
|
|
1730
|
+
queryKey: [...collectableKeys.offersCount, params],
|
|
1731
|
+
queryFn: () => fetchCountOffersForCollectible({
|
|
1732
|
+
chainId: params.chainId,
|
|
1733
|
+
collectionAddress: params.collectionAddress,
|
|
1734
|
+
collectibleId: params.collectibleId,
|
|
1735
|
+
config: params.config,
|
|
1736
|
+
filter: params.filter
|
|
1737
|
+
}),
|
|
1738
|
+
...params.query,
|
|
1739
|
+
enabled
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
//#endregion
|
|
1744
|
+
//#region src/react/hooks/useCountOffersForCollectible.tsx
|
|
1745
|
+
/**
|
|
1746
|
+
* Hook to get the count of offers for a specific collectible
|
|
1747
|
+
*
|
|
1748
|
+
* Counts the number of active offers for a given collectible in the marketplace.
|
|
1749
|
+
* Useful for displaying offer counts in UI components.
|
|
1750
|
+
*
|
|
1751
|
+
* @param params - Configuration parameters
|
|
1752
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1753
|
+
* @param params.collectionAddress - The collection contract address
|
|
1754
|
+
* @param params.collectibleId - The specific collectible/token ID
|
|
1755
|
+
* @param params.filter - Optional filter criteria for offers
|
|
1756
|
+
* @param params.query - Optional React Query configuration
|
|
1757
|
+
*
|
|
1758
|
+
* @returns Query result containing the count of offers
|
|
1759
|
+
*
|
|
1760
|
+
* @example
|
|
1761
|
+
* Basic usage:
|
|
1762
|
+
* ```typescript
|
|
1763
|
+
* const { data: offerCount, isLoading } = useCountOffersForCollectible({
|
|
1764
|
+
* chainId: 137,
|
|
1765
|
+
* collectionAddress: '0x...',
|
|
1766
|
+
* collectibleId: '123'
|
|
1767
|
+
* })
|
|
1768
|
+
* ```
|
|
1769
|
+
*
|
|
1770
|
+
* @example
|
|
1771
|
+
* With filter:
|
|
1772
|
+
* ```typescript
|
|
1773
|
+
* const { data: filteredCount } = useCountOffersForCollectible({
|
|
1774
|
+
* chainId: 137,
|
|
1775
|
+
* collectionAddress: '0x...',
|
|
1776
|
+
* collectibleId: '123',
|
|
1777
|
+
* filter: { priceRange: { min: '1000000000000000000' } }
|
|
1778
|
+
* })
|
|
1779
|
+
* ```
|
|
1780
|
+
*/
|
|
1781
|
+
function useCountOffersForCollectible(params) {
|
|
1782
|
+
const defaultConfig = useConfig();
|
|
1783
|
+
const { config = defaultConfig,...rest } = params;
|
|
1784
|
+
const queryOptions$1 = countOffersForCollectibleQueryOptions({
|
|
1785
|
+
config,
|
|
1786
|
+
...rest
|
|
1787
|
+
});
|
|
1788
|
+
return useQuery({ ...queryOptions$1 });
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
//#endregion
|
|
1792
|
+
//#region src/react/hooks/useCountOfPrimarySaleItems.tsx
|
|
1793
|
+
function useCountOfPrimarySaleItems(args) {
|
|
1794
|
+
const config = useConfig();
|
|
1795
|
+
return useQuery(countOfPrimarySaleItemsOptions(args, config));
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
//#endregion
|
|
1799
|
+
//#region src/react/hooks/useCurrency.tsx
|
|
1800
|
+
/**
|
|
1801
|
+
* Hook to fetch currency details from the marketplace
|
|
1802
|
+
*
|
|
1803
|
+
* Retrieves detailed information about a specific currency by its contract address.
|
|
1804
|
+
* The currency data is cached from previous currency list calls when possible.
|
|
1805
|
+
*
|
|
1806
|
+
* @param params - Configuration parameters
|
|
1807
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1808
|
+
* @param params.currencyAddress - The currency contract address
|
|
1809
|
+
* @param params.query - Optional React Query configuration
|
|
1810
|
+
*
|
|
1811
|
+
* @returns Query result containing currency details
|
|
1812
|
+
*
|
|
1813
|
+
* @example
|
|
1814
|
+
* Basic usage:
|
|
1815
|
+
* ```typescript
|
|
1816
|
+
* const { data, isLoading } = useCurrency({
|
|
1817
|
+
* chainId: 137,
|
|
1818
|
+
* currencyAddress: '0x...'
|
|
1819
|
+
* })
|
|
1820
|
+
* ```
|
|
1821
|
+
*
|
|
1822
|
+
* @example
|
|
1823
|
+
* With custom query options:
|
|
1824
|
+
* ```typescript
|
|
1825
|
+
* const { data, isLoading } = useCurrency({
|
|
1826
|
+
* chainId: 1,
|
|
1827
|
+
* currencyAddress: '0x...',
|
|
1828
|
+
* query: {
|
|
1829
|
+
* enabled: Boolean(selectedCurrency)
|
|
1830
|
+
* }
|
|
1831
|
+
* })
|
|
1832
|
+
* ```
|
|
1833
|
+
*/
|
|
1834
|
+
function useCurrency(params) {
|
|
1835
|
+
const defaultConfig = useConfig();
|
|
1836
|
+
const { config = defaultConfig,...rest } = params;
|
|
1837
|
+
const queryOptions$1 = currencyQueryOptions({
|
|
1838
|
+
config,
|
|
1839
|
+
...rest
|
|
1840
|
+
});
|
|
1841
|
+
return useQuery({ ...queryOptions$1 });
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
//#endregion
|
|
1845
|
+
//#region src/react/hooks/useTokenSupplies.ts
|
|
1846
|
+
/**
|
|
1847
|
+
* Hook to fetch token supplies from the indexer or LAOS API
|
|
1848
|
+
*
|
|
1849
|
+
* Retrieves supply information for tokens from a specific collection.
|
|
1850
|
+
* Automatically chooses between indexer and LAOS APIs based on the isLaos721 flag.
|
|
1851
|
+
*
|
|
1852
|
+
* @param params - Configuration parameters
|
|
1853
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
1854
|
+
* @param params.collectionAddress - The collection contract address
|
|
1855
|
+
* @param params.isLaos721 - Whether to use LAOS API instead of indexer
|
|
1856
|
+
* @param params.includeMetadata - Whether to include token metadata
|
|
1857
|
+
* @param params.page - Pagination options
|
|
1858
|
+
* @param params.query - Optional React Query configuration
|
|
1859
|
+
*
|
|
1860
|
+
* @returns Query result containing token supplies
|
|
1861
|
+
*
|
|
1862
|
+
* @example
|
|
1863
|
+
* Basic usage:
|
|
1864
|
+
* ```typescript
|
|
1865
|
+
* const { data, isLoading } = useTokenSupplies({
|
|
1866
|
+
* chainId: 137,
|
|
1867
|
+
* collectionAddress: '0x...'
|
|
1868
|
+
* })
|
|
1869
|
+
* ```
|
|
1870
|
+
*
|
|
1871
|
+
* @example
|
|
1872
|
+
* With LAOS API:
|
|
1873
|
+
* ```typescript
|
|
1874
|
+
* const { data, isLoading } = useTokenSupplies({
|
|
1875
|
+
* chainId: 1,
|
|
1876
|
+
* collectionAddress: '0x...',
|
|
1877
|
+
* isLaos721: true
|
|
1878
|
+
* })
|
|
1879
|
+
* ```
|
|
1880
|
+
*
|
|
1881
|
+
* @example
|
|
1882
|
+
* With conditional fetching:
|
|
1883
|
+
* ```typescript
|
|
1884
|
+
* const { data, isLoading } = useTokenSupplies({
|
|
1885
|
+
* chainId: 1,
|
|
1886
|
+
* collectionAddress: selectedCollection,
|
|
1887
|
+
* query: {
|
|
1888
|
+
* enabled: !!selectedCollection
|
|
1889
|
+
* }
|
|
1890
|
+
* })
|
|
1891
|
+
* ```
|
|
1892
|
+
*/
|
|
1893
|
+
function useTokenSupplies(params) {
|
|
1894
|
+
const defaultConfig = useConfig();
|
|
1895
|
+
const { config = defaultConfig,...rest } = params;
|
|
1896
|
+
const queryOptions$1 = tokenSuppliesQueryOptions({
|
|
1897
|
+
config,
|
|
1898
|
+
...rest
|
|
1899
|
+
});
|
|
1900
|
+
return useQuery({ ...queryOptions$1 });
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
//#endregion
|
|
1904
|
+
//#region src/react/hooks/useERC721SaleMintedTokens.tsx
|
|
1905
|
+
function useERC721SaleMintedTokens({ chainId, contractAddress, salesContractAddress, tokenIds, enabled = true }) {
|
|
1906
|
+
const { data: saleDetails, isLoading: saleDetailsLoading, error: saleDetailsError } = useReadContract({
|
|
1907
|
+
chainId,
|
|
1908
|
+
address: salesContractAddress,
|
|
1909
|
+
abi: ERC721_SALE_ABI,
|
|
1910
|
+
functionName: "saleDetails",
|
|
1911
|
+
query: { enabled }
|
|
1912
|
+
});
|
|
1913
|
+
const { data: tokenSupplies, isLoading: tokenSuppliesLoading } = useTokenSupplies({
|
|
1914
|
+
chainId,
|
|
1915
|
+
collectionAddress: contractAddress
|
|
1916
|
+
});
|
|
1917
|
+
const isLoading = saleDetailsLoading || tokenSuppliesLoading;
|
|
1918
|
+
const ownedCount = tokenIds.reduce((count, tokenId) => {
|
|
1919
|
+
let supply;
|
|
1920
|
+
if (tokenSupplies) supply = tokenSupplies.tokenIDs.find((s) => s.tokenID === tokenId);
|
|
1921
|
+
const hasOwner = supply ? BigInt(supply.supply) > 0n : false;
|
|
1922
|
+
return count + (hasOwner ? 1 : 0);
|
|
1923
|
+
}, 0);
|
|
1924
|
+
const totalSupplyCap = saleDetails?.supplyCap ? Number(saleDetails.supplyCap) : 0;
|
|
1925
|
+
const remainingCount = Math.max(0, totalSupplyCap - ownedCount);
|
|
1926
|
+
return {
|
|
1927
|
+
ownedCount,
|
|
1928
|
+
totalSupplyCap,
|
|
1929
|
+
remainingCount,
|
|
1930
|
+
isLoading,
|
|
1931
|
+
error: saleDetailsError,
|
|
1932
|
+
saleDetails
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
//#endregion
|
|
1937
|
+
//#region src/react/hooks/useFilterState.tsx
|
|
1938
|
+
const validateFilters = (value) => {
|
|
1939
|
+
if (!Array.isArray(value)) return [];
|
|
1940
|
+
return value.filter((f) => typeof f === "object" && typeof f.name === "string" && Object.values(PropertyType).includes(f.type));
|
|
1941
|
+
};
|
|
1942
|
+
const filtersParser = parseAsJson(validateFilters).withDefault([]);
|
|
1943
|
+
const searchParser = parseAsString.withDefault("");
|
|
1944
|
+
const listedOnlyParser = parseAsBoolean.withDefault(false);
|
|
1945
|
+
const serialize = createSerializer({
|
|
1946
|
+
filters: filtersParser,
|
|
1947
|
+
search: searchParser,
|
|
1948
|
+
listedOnly: listedOnlyParser
|
|
1949
|
+
}, { urlKeys: {
|
|
1950
|
+
filters: "f",
|
|
1951
|
+
search: "q",
|
|
1952
|
+
listedOnly: "l"
|
|
1953
|
+
} });
|
|
1954
|
+
function useFilterState() {
|
|
1955
|
+
const [filterOptions, setFilterOptions] = useQueryState("filters", filtersParser);
|
|
1956
|
+
const [searchText, setSearchText] = useQueryState("search", searchParser);
|
|
1957
|
+
const [showListedOnly, setShowListedOnly] = useQueryState("listedOnly", listedOnlyParser);
|
|
1958
|
+
const helpers = useMemo(() => ({
|
|
1959
|
+
getFilter: (name) => {
|
|
1960
|
+
return filterOptions?.find((f) => f.name === name);
|
|
1961
|
+
},
|
|
1962
|
+
getFilterValues: (name) => {
|
|
1963
|
+
const filter = filterOptions?.find((f) => f.name === name);
|
|
1964
|
+
if (!filter) return void 0;
|
|
1965
|
+
if (filter.type === PropertyType.INT) return {
|
|
1966
|
+
type: PropertyType.INT,
|
|
1967
|
+
min: filter.min ?? 0,
|
|
1968
|
+
max: filter.max ?? 0
|
|
1969
|
+
};
|
|
1970
|
+
return {
|
|
1971
|
+
type: PropertyType.STRING,
|
|
1972
|
+
values: filter.values ?? []
|
|
1973
|
+
};
|
|
1974
|
+
},
|
|
1975
|
+
isFilterActive: (name) => {
|
|
1976
|
+
return !!filterOptions?.find((f) => f.name === name);
|
|
1977
|
+
},
|
|
1978
|
+
isStringValueSelected: (name, value) => {
|
|
1979
|
+
const filter = filterOptions?.find((f) => f.name === name);
|
|
1980
|
+
if (!filter || filter.type !== PropertyType.STRING) return false;
|
|
1981
|
+
return filter.values?.includes(value) ?? false;
|
|
1982
|
+
},
|
|
1983
|
+
isIntFilterActive: (name) => {
|
|
1984
|
+
const filter = filterOptions?.find((f) => f.name === name);
|
|
1985
|
+
return !!filter && filter.type === PropertyType.INT;
|
|
1986
|
+
},
|
|
1987
|
+
getIntFilterRange: (name) => {
|
|
1988
|
+
const filter = filterOptions?.find((f) => f.name === name);
|
|
1989
|
+
if (!filter || filter.type !== PropertyType.INT) return void 0;
|
|
1990
|
+
return [filter.min ?? 0, filter.max ?? 0];
|
|
1991
|
+
},
|
|
1992
|
+
deleteFilter: (name) => {
|
|
1993
|
+
const otherFilters = filterOptions?.filter((f) => !(f.name === name)) ?? [];
|
|
1994
|
+
setFilterOptions(otherFilters);
|
|
1995
|
+
},
|
|
1996
|
+
toggleStringFilterValue: (name, value) => {
|
|
1997
|
+
const otherFilters = filterOptions?.filter((f) => !(f.name === name)) ?? [];
|
|
1998
|
+
const filter = filterOptions?.find((f) => f.name === name);
|
|
1999
|
+
const existingValues = filter?.type === PropertyType.STRING ? filter.values ?? [] : [];
|
|
2000
|
+
if (existingValues.includes(value)) {
|
|
2001
|
+
const newValues = existingValues.filter((v) => v !== value);
|
|
2002
|
+
if (newValues.length === 0) {
|
|
2003
|
+
setFilterOptions(otherFilters);
|
|
2004
|
+
return;
|
|
2005
|
+
}
|
|
2006
|
+
setFilterOptions([...otherFilters, {
|
|
2007
|
+
name,
|
|
2008
|
+
type: PropertyType.STRING,
|
|
2009
|
+
values: newValues
|
|
2010
|
+
}]);
|
|
2011
|
+
} else setFilterOptions([...otherFilters, {
|
|
2012
|
+
name,
|
|
2013
|
+
type: PropertyType.STRING,
|
|
2014
|
+
values: [...existingValues, value]
|
|
2015
|
+
}]);
|
|
2016
|
+
},
|
|
2017
|
+
setIntFilterValue: (name, min, max) => {
|
|
2018
|
+
if (min === max && min === 0) {
|
|
2019
|
+
const otherFilters$1 = filterOptions?.filter((f) => !(f.name === name)) ?? [];
|
|
2020
|
+
setFilterOptions(otherFilters$1);
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
const otherFilters = filterOptions?.filter((f) => !(f.name === name)) ?? [];
|
|
2024
|
+
setFilterOptions([...otherFilters, {
|
|
2025
|
+
name,
|
|
2026
|
+
type: PropertyType.INT,
|
|
2027
|
+
min,
|
|
2028
|
+
max
|
|
2029
|
+
}]);
|
|
2030
|
+
},
|
|
2031
|
+
clearAllFilters: () => {
|
|
2032
|
+
setShowListedOnly(false);
|
|
2033
|
+
setFilterOptions([]);
|
|
2034
|
+
setSearchText("");
|
|
2035
|
+
}
|
|
2036
|
+
}), [
|
|
2037
|
+
filterOptions,
|
|
2038
|
+
setFilterOptions,
|
|
2039
|
+
setShowListedOnly,
|
|
2040
|
+
setSearchText
|
|
2041
|
+
]);
|
|
2042
|
+
return {
|
|
2043
|
+
filterOptions,
|
|
2044
|
+
searchText,
|
|
2045
|
+
showListedOnly,
|
|
2046
|
+
setFilterOptions,
|
|
2047
|
+
setSearchText,
|
|
2048
|
+
setShowListedOnly,
|
|
2049
|
+
...helpers,
|
|
2050
|
+
serialize
|
|
2051
|
+
};
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
//#endregion
|
|
2055
|
+
//#region src/react/queries/filters.ts
|
|
2056
|
+
/**
|
|
2057
|
+
* Fetches collection filters from the Metadata API with optional marketplace filtering
|
|
2058
|
+
*/
|
|
2059
|
+
async function fetchFilters(params) {
|
|
2060
|
+
const { chainId, collectionAddress, showAllFilters, excludePropertyValues, config } = params;
|
|
2061
|
+
const metadataClient = getMetadataClient(config);
|
|
2062
|
+
const filters = await metadataClient.getTokenMetadataPropertyFilters({
|
|
2063
|
+
chainID: chainId.toString(),
|
|
2064
|
+
contractAddress: collectionAddress,
|
|
2065
|
+
excludeProperties: [],
|
|
2066
|
+
excludePropertyValues
|
|
2067
|
+
}).then((resp) => resp.filters);
|
|
2068
|
+
if (showAllFilters) return filters;
|
|
2069
|
+
const queryClient = getQueryClient();
|
|
2070
|
+
const marketplaceConfig = await queryClient.fetchQuery(marketplaceConfigOptions(config));
|
|
2071
|
+
const collectionFilters = marketplaceConfig.market.collections.find((c) => compareAddress(c.itemsAddress, collectionAddress))?.filterSettings;
|
|
2072
|
+
if (!collectionFilters?.exclusions || collectionFilters.exclusions.length === 0 || !collectionFilters.filterOrder || collectionFilters.filterOrder.length === 0) return filters;
|
|
2073
|
+
const { filterOrder, exclusions } = collectionFilters;
|
|
2074
|
+
const sortedFilters = filters.toSorted((a, b) => {
|
|
2075
|
+
const aIndex = filterOrder.indexOf(a.name) > -1 ? filterOrder.indexOf(a.name) : filterOrder.length;
|
|
2076
|
+
const bIndex = filterOrder.indexOf(b.name) > -1 ? filterOrder.indexOf(b.name) : filterOrder.length;
|
|
2077
|
+
return aIndex - bIndex;
|
|
2078
|
+
});
|
|
2079
|
+
const filteredResults = sortedFilters.reduce((acc, filter) => {
|
|
2080
|
+
const exclusionRule = exclusions.find((rule) => rule.key === filter.name);
|
|
2081
|
+
if (!exclusionRule) {
|
|
2082
|
+
acc.push(filter);
|
|
2083
|
+
return acc;
|
|
2084
|
+
}
|
|
2085
|
+
if (exclusionRule.condition === FilterCondition.ENTIRE_KEY) return acc;
|
|
2086
|
+
if (exclusionRule.condition === FilterCondition.SPECIFIC_VALUE && exclusionRule.value) {
|
|
2087
|
+
const filteredValues = filter.values?.filter((value) => value !== exclusionRule.value) || [];
|
|
2088
|
+
if (filteredValues.length > 0) acc.push({
|
|
2089
|
+
...filter,
|
|
2090
|
+
values: filteredValues
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
return acc;
|
|
2094
|
+
}, []);
|
|
2095
|
+
return filteredResults;
|
|
2096
|
+
}
|
|
2097
|
+
function filtersQueryOptions(params) {
|
|
2098
|
+
const enabled = Boolean(params.chainId && params.collectionAddress && params.config && (params.query?.enabled ?? true));
|
|
2099
|
+
return queryOptions({
|
|
2100
|
+
queryKey: ["filters", params],
|
|
2101
|
+
queryFn: () => fetchFilters({
|
|
2102
|
+
chainId: params.chainId,
|
|
2103
|
+
collectionAddress: params.collectionAddress,
|
|
2104
|
+
showAllFilters: params.showAllFilters,
|
|
2105
|
+
excludePropertyValues: params.excludePropertyValues,
|
|
2106
|
+
config: params.config
|
|
2107
|
+
}),
|
|
2108
|
+
...params.query,
|
|
2109
|
+
enabled
|
|
2110
|
+
});
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
//#endregion
|
|
2114
|
+
//#region src/react/hooks/useFilters.tsx
|
|
2115
|
+
/**
|
|
2116
|
+
* Hook to fetch metadata filters for a collection
|
|
2117
|
+
*
|
|
2118
|
+
* Retrieves property filters for a collection from the metadata service,
|
|
2119
|
+
* with support for marketplace-specific filter configuration including
|
|
2120
|
+
* exclusion rules and custom ordering.
|
|
2121
|
+
*
|
|
2122
|
+
* @param params - Configuration parameters
|
|
2123
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2124
|
+
* @param params.collectionAddress - The collection contract address to fetch filters for
|
|
2125
|
+
* @param params.showAllFilters - Whether to show all filters or apply marketplace filtering
|
|
2126
|
+
* @param params.excludePropertyValues - Whether to exclude property values from the response
|
|
2127
|
+
* @param params.query - Optional React Query configuration
|
|
2128
|
+
*
|
|
2129
|
+
* @returns Query result containing property filters for the collection
|
|
2130
|
+
*
|
|
2131
|
+
* @example
|
|
2132
|
+
* Basic usage:
|
|
2133
|
+
* ```typescript
|
|
2134
|
+
* const { data: filters, isLoading } = useFilters({
|
|
2135
|
+
* chainId: 137,
|
|
2136
|
+
* collectionAddress: '0x1234...'
|
|
2137
|
+
* })
|
|
2138
|
+
*
|
|
2139
|
+
* if (data) {
|
|
2140
|
+
* console.log(`Found ${data.length} filters`);
|
|
2141
|
+
* data.forEach(filter => {
|
|
2142
|
+
* console.log(`${filter.name}: ${filter.values?.join(', ')}`);
|
|
2143
|
+
* });
|
|
2144
|
+
* }
|
|
2145
|
+
* ```
|
|
2146
|
+
*
|
|
2147
|
+
* @example
|
|
2148
|
+
* With marketplace filtering disabled:
|
|
2149
|
+
* ```typescript
|
|
2150
|
+
* const { data: allFilters } = useFilters({
|
|
2151
|
+
* chainId: 1,
|
|
2152
|
+
* collectionAddress: '0x5678...',
|
|
2153
|
+
* showAllFilters: true, // Bypass marketplace filter rules
|
|
2154
|
+
* query: {
|
|
2155
|
+
* enabled: Boolean(selectedCollection),
|
|
2156
|
+
* staleTime: 300000 // Cache for 5 minutes
|
|
2157
|
+
* }
|
|
2158
|
+
* })
|
|
2159
|
+
* ```
|
|
2160
|
+
*
|
|
2161
|
+
* @example
|
|
2162
|
+
* Exclude property values for faster loading:
|
|
2163
|
+
* ```typescript
|
|
2164
|
+
* const { data: filterNames } = useFilters({
|
|
2165
|
+
* chainId: 137,
|
|
2166
|
+
* collectionAddress: collectionAddress,
|
|
2167
|
+
* excludePropertyValues: true, // Only get filter names, not values
|
|
2168
|
+
* query: {
|
|
2169
|
+
* enabled: Boolean(collectionAddress)
|
|
2170
|
+
* }
|
|
2171
|
+
* })
|
|
2172
|
+
* ```
|
|
2173
|
+
*/
|
|
2174
|
+
function useFilters(params) {
|
|
2175
|
+
const defaultConfig = useConfig();
|
|
2176
|
+
const { config = defaultConfig,...rest } = params;
|
|
2177
|
+
const queryOptions$1 = filtersQueryOptions({
|
|
2178
|
+
config,
|
|
2179
|
+
...rest
|
|
2180
|
+
});
|
|
2181
|
+
return useQuery({ ...queryOptions$1 });
|
|
2182
|
+
}
|
|
2183
|
+
/**
|
|
2184
|
+
* Hook to progressively load collection filters
|
|
2185
|
+
*
|
|
2186
|
+
* First loads filter names only for fast initial display, then loads full filter
|
|
2187
|
+
* data with values. Uses placeholder data to provide immediate feedback while
|
|
2188
|
+
* full data loads in the background.
|
|
2189
|
+
*
|
|
2190
|
+
* @param params - Configuration parameters (same as useFilters)
|
|
2191
|
+
*
|
|
2192
|
+
* @returns Query result with additional loading states
|
|
2193
|
+
* @returns result.isLoadingNames - Whether filter names are still loading
|
|
2194
|
+
* @returns result.isFetchingValues - Whether filter values are being fetched
|
|
2195
|
+
*
|
|
2196
|
+
* @example
|
|
2197
|
+
* Progressive filter loading:
|
|
2198
|
+
* ```typescript
|
|
2199
|
+
* const {
|
|
2200
|
+
* data: filters,
|
|
2201
|
+
* isLoadingNames,
|
|
2202
|
+
* isFetchingValues,
|
|
2203
|
+
* isLoading
|
|
2204
|
+
* } = useFiltersProgressive({
|
|
2205
|
+
* chainId: 137,
|
|
2206
|
+
* collectionAddress: '0x1234...'
|
|
2207
|
+
* })
|
|
2208
|
+
*
|
|
2209
|
+
* if (isLoadingNames) {
|
|
2210
|
+
* return <div>Loading filters...</div>;
|
|
2211
|
+
* }
|
|
2212
|
+
*
|
|
2213
|
+
* return (
|
|
2214
|
+
* <div>
|
|
2215
|
+
* {filters?.map(filter => (
|
|
2216
|
+
* <FilterComponent
|
|
2217
|
+
* key={filter.name}
|
|
2218
|
+
* filter={filter}
|
|
2219
|
+
* isLoadingValues={isFetchingValues}
|
|
2220
|
+
* />
|
|
2221
|
+
* ))}
|
|
2222
|
+
* </div>
|
|
2223
|
+
* );
|
|
2224
|
+
* ```
|
|
2225
|
+
*/
|
|
2226
|
+
function useFiltersProgressive(params) {
|
|
2227
|
+
const defaultConfig = useConfig();
|
|
2228
|
+
const { config = defaultConfig,...rest } = params;
|
|
2229
|
+
const namesQuery = useQuery(filtersQueryOptions({
|
|
2230
|
+
config,
|
|
2231
|
+
...rest,
|
|
2232
|
+
excludePropertyValues: true
|
|
2233
|
+
}));
|
|
2234
|
+
const fullQuery = useQuery({
|
|
2235
|
+
...filtersQueryOptions({
|
|
2236
|
+
config,
|
|
2237
|
+
...rest
|
|
2238
|
+
}),
|
|
2239
|
+
placeholderData: namesQuery.data
|
|
2240
|
+
});
|
|
2241
|
+
const isLoadingNames = namesQuery.isLoading;
|
|
2242
|
+
const isFetchingValues = fullQuery.isPlaceholderData && fullQuery.isFetching;
|
|
2243
|
+
return {
|
|
2244
|
+
...fullQuery,
|
|
2245
|
+
isFetchingValues,
|
|
2246
|
+
isLoadingNames
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
//#endregion
|
|
2251
|
+
//#region src/react/hooks/useFloorOrder.tsx
|
|
2252
|
+
/**
|
|
2253
|
+
* Hook to fetch the floor order for a collection
|
|
2254
|
+
*
|
|
2255
|
+
* Retrieves the lowest priced order (listing) currently available for any token
|
|
2256
|
+
* in the specified collection from the marketplace.
|
|
2257
|
+
*
|
|
2258
|
+
* @param params - Configuration parameters
|
|
2259
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2260
|
+
* @param params.collectionAddress - The collection contract address
|
|
2261
|
+
* @param params.filter - Optional filter criteria for collectibles
|
|
2262
|
+
* @param params.query - Optional React Query configuration
|
|
2263
|
+
*
|
|
2264
|
+
* @returns Query result containing the floor order data for the collection
|
|
2265
|
+
*
|
|
2266
|
+
* @example
|
|
2267
|
+
* Basic usage:
|
|
2268
|
+
* ```typescript
|
|
2269
|
+
* const { data, isLoading } = useFloorOrder({
|
|
2270
|
+
* chainId: 137,
|
|
2271
|
+
* collectionAddress: '0x...'
|
|
2272
|
+
* })
|
|
2273
|
+
* ```
|
|
2274
|
+
*
|
|
2275
|
+
* @example
|
|
2276
|
+
* With filters and custom query options:
|
|
2277
|
+
* ```typescript
|
|
2278
|
+
* const { data, isLoading } = useFloorOrder({
|
|
2279
|
+
* chainId: 1,
|
|
2280
|
+
* collectionAddress: '0x...',
|
|
2281
|
+
* filter: {
|
|
2282
|
+
* minPrice: '1000000000000000000' // 1 ETH in wei
|
|
2283
|
+
* },
|
|
2284
|
+
* query: {
|
|
2285
|
+
* refetchInterval: 30000,
|
|
2286
|
+
* enabled: hasCollectionAddress
|
|
2287
|
+
* }
|
|
2288
|
+
* })
|
|
2289
|
+
* ```
|
|
2290
|
+
*/
|
|
2291
|
+
function useFloorOrder(params) {
|
|
2292
|
+
const defaultConfig = useConfig();
|
|
2293
|
+
const { config = defaultConfig,...rest } = params;
|
|
2294
|
+
const queryOptions$1 = floorOrderQueryOptions({
|
|
2295
|
+
config,
|
|
2296
|
+
...rest
|
|
2297
|
+
});
|
|
2298
|
+
return useQuery({ ...queryOptions$1 });
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
//#endregion
|
|
2302
|
+
//#region src/utils/date.ts
|
|
2303
|
+
const dateToUnixTime = (date) => Math.floor(date.getTime() / 1e3).toString();
|
|
2304
|
+
|
|
2305
|
+
//#endregion
|
|
2306
|
+
//#region src/react/hooks/useGenerateListingTransaction.tsx
|
|
2307
|
+
const generateListingTransaction = async (params, config) => {
|
|
2308
|
+
const args = {
|
|
2309
|
+
...params,
|
|
2310
|
+
chainId: String(params.chainId),
|
|
2311
|
+
listing: {
|
|
2312
|
+
...params.listing,
|
|
2313
|
+
expiry: dateToUnixTime(params.listing.expiry)
|
|
2314
|
+
}
|
|
2315
|
+
};
|
|
2316
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
2317
|
+
return (await marketplaceClient.generateListingTransaction(args)).steps;
|
|
2318
|
+
};
|
|
2319
|
+
const useGenerateListingTransaction = (params) => {
|
|
2320
|
+
const config = useConfig();
|
|
2321
|
+
const { mutate, mutateAsync,...result } = useMutation({
|
|
2322
|
+
onSuccess: params.onSuccess,
|
|
2323
|
+
mutationFn: (args) => generateListingTransaction({
|
|
2324
|
+
...args,
|
|
2325
|
+
chainId: params.chainId
|
|
2326
|
+
}, config)
|
|
2327
|
+
});
|
|
2328
|
+
return {
|
|
2329
|
+
...result,
|
|
2330
|
+
generateListingTransaction: mutate,
|
|
2331
|
+
generateListingTransactionAsync: mutateAsync
|
|
2332
|
+
};
|
|
2333
|
+
};
|
|
2334
|
+
|
|
2335
|
+
//#endregion
|
|
2336
|
+
//#region src/react/hooks/useGenerateOfferTransaction.tsx
|
|
2337
|
+
const generateOfferTransaction = async (params, config, walletKind) => {
|
|
2338
|
+
const args = {
|
|
2339
|
+
...params,
|
|
2340
|
+
chainId: String(params.chainId),
|
|
2341
|
+
offer: {
|
|
2342
|
+
...params.offer,
|
|
2343
|
+
expiry: dateToUnixTime(params.offer.expiry)
|
|
2344
|
+
},
|
|
2345
|
+
walletType: walletKind
|
|
2346
|
+
};
|
|
2347
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
2348
|
+
return (await marketplaceClient.generateOfferTransaction(args)).steps;
|
|
2349
|
+
};
|
|
2350
|
+
const useGenerateOfferTransaction = (params) => {
|
|
2351
|
+
const config = useConfig();
|
|
2352
|
+
const { wallet: wallet$1 } = useWallet();
|
|
2353
|
+
const { mutate, mutateAsync,...result } = useMutation({
|
|
2354
|
+
onSuccess: params.onSuccess,
|
|
2355
|
+
mutationFn: (args) => generateOfferTransaction({
|
|
2356
|
+
...args,
|
|
2357
|
+
chainId: params.chainId
|
|
2358
|
+
}, config, wallet$1?.walletKind)
|
|
2359
|
+
});
|
|
2360
|
+
return {
|
|
2361
|
+
...result,
|
|
2362
|
+
generateOfferTransaction: mutate,
|
|
2363
|
+
generateOfferTransactionAsync: mutateAsync
|
|
2364
|
+
};
|
|
2365
|
+
};
|
|
2366
|
+
|
|
2367
|
+
//#endregion
|
|
2368
|
+
//#region src/react/hooks/useGenerateSellTransaction.tsx
|
|
2369
|
+
const generateSellTransaction = async (args, config) => {
|
|
2370
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
2371
|
+
const argsWithStringChainId = {
|
|
2372
|
+
...args,
|
|
2373
|
+
chainId: String(args.chainId)
|
|
2374
|
+
};
|
|
2375
|
+
return marketplaceClient.generateSellTransaction(argsWithStringChainId).then((data) => data.steps);
|
|
2376
|
+
};
|
|
2377
|
+
const useGenerateSellTransaction = (params) => {
|
|
2378
|
+
const config = useConfig();
|
|
2379
|
+
const { mutate, mutateAsync,...result } = useMutation({
|
|
2380
|
+
onSuccess: params.onSuccess,
|
|
2381
|
+
mutationFn: (args) => generateSellTransaction({
|
|
2382
|
+
...args,
|
|
2383
|
+
chainId: params.chainId
|
|
2384
|
+
}, config)
|
|
2385
|
+
});
|
|
2386
|
+
return {
|
|
2387
|
+
...result,
|
|
2388
|
+
generateSellTransaction: mutate,
|
|
2389
|
+
generateSellTransactionAsync: mutateAsync
|
|
2390
|
+
};
|
|
2391
|
+
};
|
|
2392
|
+
|
|
2393
|
+
//#endregion
|
|
2394
|
+
//#region src/react/queries/primarySaleItemsCount.ts
|
|
2395
|
+
/**
|
|
2396
|
+
* Fetches the count of primary sale items from the marketplace API
|
|
2397
|
+
*/
|
|
2398
|
+
async function fetchPrimarySaleItemsCount(params) {
|
|
2399
|
+
const { chainId, primarySaleContractAddress, filter, config } = params;
|
|
2400
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
2401
|
+
return marketplaceClient.getCountOfPrimarySaleItems({
|
|
2402
|
+
chainId: String(chainId),
|
|
2403
|
+
primarySaleContractAddress,
|
|
2404
|
+
filter
|
|
2405
|
+
});
|
|
2406
|
+
}
|
|
2407
|
+
const primarySaleItemsCountQueryOptions = (args) => {
|
|
2408
|
+
const enabled = Boolean(args.primarySaleContractAddress && args.chainId && args.config && (args.query?.enabled ?? true));
|
|
2409
|
+
return queryOptions({
|
|
2410
|
+
queryKey: ["primarySaleItemsCount", args],
|
|
2411
|
+
queryFn: () => fetchPrimarySaleItemsCount({
|
|
2412
|
+
chainId: args.chainId,
|
|
2413
|
+
primarySaleContractAddress: args.primarySaleContractAddress,
|
|
2414
|
+
filter: args.filter,
|
|
2415
|
+
config: args.config
|
|
2416
|
+
}),
|
|
2417
|
+
...args.query,
|
|
2418
|
+
enabled
|
|
2419
|
+
});
|
|
2420
|
+
};
|
|
2421
|
+
|
|
2422
|
+
//#endregion
|
|
2423
|
+
//#region src/react/hooks/useGetCountOfPrimarySaleItems.tsx
|
|
2424
|
+
/**
|
|
2425
|
+
* Hook to get the total count of primary sale items
|
|
2426
|
+
*
|
|
2427
|
+
* Retrieves the total count of primary sale items for a specific contract address
|
|
2428
|
+
* from the marketplace.
|
|
2429
|
+
*
|
|
2430
|
+
* @param params - Configuration parameters
|
|
2431
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2432
|
+
* @param params.primarySaleContractAddress - The primary sale contract address
|
|
2433
|
+
* @param params.filter - Optional filter parameters for the query
|
|
2434
|
+
* @param params.query - Optional React Query configuration
|
|
2435
|
+
*
|
|
2436
|
+
* @returns Query result containing the count of primary sale items
|
|
2437
|
+
*
|
|
2438
|
+
* @example
|
|
2439
|
+
* ```typescript
|
|
2440
|
+
* const { data: count, isLoading } = useGetCountOfPrimarySaleItems({
|
|
2441
|
+
* chainId: 137,
|
|
2442
|
+
* primarySaleContractAddress: '0x...',
|
|
2443
|
+
* })
|
|
2444
|
+
* ```
|
|
2445
|
+
*/
|
|
2446
|
+
function useGetCountOfPrimarySaleItems(params) {
|
|
2447
|
+
const defaultConfig = useConfig();
|
|
2448
|
+
const { config = defaultConfig,...rest } = params;
|
|
2449
|
+
const queryOptions$1 = primarySaleItemsCountQueryOptions({
|
|
2450
|
+
config,
|
|
2451
|
+
...rest
|
|
2452
|
+
});
|
|
2453
|
+
return useQuery(queryOptions$1);
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
//#endregion
|
|
2457
|
+
//#region src/react/queries/getTokenRanges.ts
|
|
2458
|
+
/**
|
|
2459
|
+
* Fetches token ID ranges for a collection from the Indexer API
|
|
2460
|
+
*/
|
|
2461
|
+
async function fetchGetTokenRanges(params) {
|
|
2462
|
+
const { chainId, collectionAddress, config } = params;
|
|
2463
|
+
const indexerClient = getIndexerClient(chainId, config);
|
|
2464
|
+
const response = await indexerClient.getTokenIDRanges({ contractAddress: collectionAddress });
|
|
2465
|
+
if (!response) throw new Error("Failed to fetch token ranges");
|
|
2466
|
+
return response;
|
|
2467
|
+
}
|
|
2468
|
+
function getTokenRangesQueryOptions(params) {
|
|
2469
|
+
const enabled = Boolean(params.chainId && params.collectionAddress && params.config && (params.query?.enabled ?? true));
|
|
2470
|
+
return queryOptions({
|
|
2471
|
+
queryKey: [
|
|
2472
|
+
"indexer",
|
|
2473
|
+
"tokenRanges",
|
|
2474
|
+
params
|
|
2475
|
+
],
|
|
2476
|
+
queryFn: () => fetchGetTokenRanges({
|
|
2477
|
+
chainId: params.chainId,
|
|
2478
|
+
collectionAddress: params.collectionAddress,
|
|
2479
|
+
config: params.config
|
|
2480
|
+
}),
|
|
2481
|
+
...params.query,
|
|
2482
|
+
enabled
|
|
2483
|
+
});
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
//#endregion
|
|
2487
|
+
//#region src/react/hooks/useGetTokenRanges.tsx
|
|
2488
|
+
/**
|
|
2489
|
+
* Hook to fetch token ID ranges for a collection
|
|
2490
|
+
*
|
|
2491
|
+
* Retrieves the available token ID ranges for a specific collection,
|
|
2492
|
+
* which is useful for understanding the token distribution and
|
|
2493
|
+
* available tokens within a collection.
|
|
2494
|
+
*
|
|
2495
|
+
* @param params - Configuration parameters
|
|
2496
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2497
|
+
* @param params.collectionAddress - The collection contract address to fetch ranges for
|
|
2498
|
+
* @param params.query - Optional React Query configuration
|
|
2499
|
+
*
|
|
2500
|
+
* @returns Query result containing token ID ranges for the collection
|
|
2501
|
+
*
|
|
2502
|
+
* @example
|
|
2503
|
+
* Basic usage:
|
|
2504
|
+
* ```typescript
|
|
2505
|
+
* const { data: tokenRanges, isLoading } = useGetTokenRanges({
|
|
2506
|
+
* chainId: 137,
|
|
2507
|
+
* collectionAddress: '0x1234...'
|
|
2508
|
+
* })
|
|
2509
|
+
*
|
|
2510
|
+
* if (data) {
|
|
2511
|
+
* console.log(`Token ranges: ${JSON.stringify(data.tokenIDRanges)}`);
|
|
2512
|
+
* data.tokenIDRanges?.forEach(range => {
|
|
2513
|
+
* console.log(`Range: ${range.start} - ${range.end}`);
|
|
2514
|
+
* });
|
|
2515
|
+
* }
|
|
2516
|
+
* ```
|
|
2517
|
+
*
|
|
2518
|
+
* @example
|
|
2519
|
+
* With conditional enabling:
|
|
2520
|
+
* ```typescript
|
|
2521
|
+
* const { data: tokenRanges } = useGetTokenRanges({
|
|
2522
|
+
* chainId: 1,
|
|
2523
|
+
* collectionAddress: selectedCollection?.address,
|
|
2524
|
+
* query: {
|
|
2525
|
+
* enabled: Boolean(selectedCollection?.address),
|
|
2526
|
+
* staleTime: 300000, // Cache for 5 minutes
|
|
2527
|
+
* refetchInterval: 60000 // Refresh every minute
|
|
2528
|
+
* }
|
|
2529
|
+
* })
|
|
2530
|
+
* ```
|
|
2531
|
+
*/
|
|
2532
|
+
function useGetTokenRanges(params) {
|
|
2533
|
+
const defaultConfig = useConfig();
|
|
2534
|
+
const { config = defaultConfig,...rest } = params;
|
|
2535
|
+
const queryOptions$1 = getTokenRangesQueryOptions({
|
|
2536
|
+
config,
|
|
2537
|
+
...rest
|
|
2538
|
+
});
|
|
2539
|
+
return useQuery({ ...queryOptions$1 });
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
//#endregion
|
|
2543
|
+
//#region src/react/hooks/useHighestOffer.tsx
|
|
2544
|
+
/**
|
|
2545
|
+
* Hook to fetch the highest offer for a collectible
|
|
2546
|
+
*
|
|
2547
|
+
* Retrieves the highest offer currently available for a specific token
|
|
2548
|
+
* in a collection from the marketplace.
|
|
2549
|
+
*
|
|
2550
|
+
* @param params - Configuration parameters
|
|
2551
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2552
|
+
* @param params.collectionAddress - The collection contract address
|
|
2553
|
+
* @param params.tokenId - The token ID within the collection
|
|
2554
|
+
* @param params.query - Optional React Query configuration
|
|
2555
|
+
*
|
|
2556
|
+
* @returns Query result containing the highest offer data or null if no offers exist
|
|
2557
|
+
*
|
|
2558
|
+
* @example
|
|
2559
|
+
* Basic usage:
|
|
2560
|
+
* ```typescript
|
|
2561
|
+
* const { data, isLoading } = useHighestOffer({
|
|
2562
|
+
* chainId: 137,
|
|
2563
|
+
* collectionAddress: '0x...',
|
|
2564
|
+
* tokenId: '1'
|
|
2565
|
+
* })
|
|
2566
|
+
* ```
|
|
2567
|
+
*
|
|
2568
|
+
* @example
|
|
2569
|
+
* With custom query options:
|
|
2570
|
+
* ```typescript
|
|
2571
|
+
* const { data, isLoading } = useHighestOffer({
|
|
2572
|
+
* chainId: 1,
|
|
2573
|
+
* collectionAddress: '0x...',
|
|
2574
|
+
* tokenId: '42',
|
|
2575
|
+
* query: {
|
|
2576
|
+
* refetchInterval: 15000,
|
|
2577
|
+
* enabled: hasTokenId
|
|
2578
|
+
* }
|
|
2579
|
+
* })
|
|
2580
|
+
* ```
|
|
2581
|
+
*/
|
|
2582
|
+
function useHighestOffer(params) {
|
|
2583
|
+
const defaultConfig = useConfig();
|
|
2584
|
+
const { config = defaultConfig,...rest } = params;
|
|
2585
|
+
const queryOptions$1 = highestOfferQueryOptions({
|
|
2586
|
+
config,
|
|
2587
|
+
...rest
|
|
2588
|
+
});
|
|
2589
|
+
return useQuery({ ...queryOptions$1 });
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
//#endregion
|
|
2593
|
+
//#region src/react/hooks/useInventory.tsx
|
|
2594
|
+
function useInventory(args) {
|
|
2595
|
+
const config = useConfig();
|
|
2596
|
+
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
2597
|
+
const isLaos721 = marketplaceConfig?.market?.collections?.find((c) => c.itemsAddress === args.collectionAddress && c.chainId === args.chainId)?.contractType === ContractType.LAOS_ERC_721;
|
|
2598
|
+
return useInfiniteQuery(inventoryOptions({
|
|
2599
|
+
...args,
|
|
2600
|
+
isLaos721
|
|
2601
|
+
}, config));
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
//#endregion
|
|
2605
|
+
//#region src/react/hooks/useListCollectibles.tsx
|
|
2606
|
+
/**
|
|
2607
|
+
* Hook to fetch a list of collectibles with infinite pagination support
|
|
2608
|
+
*
|
|
2609
|
+
* Fetches collectibles from the marketplace with support for filtering, pagination,
|
|
2610
|
+
* and special handling for shop marketplace types and LAOS721 contracts.
|
|
2611
|
+
*
|
|
2612
|
+
* @param params - Configuration parameters
|
|
2613
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2614
|
+
* @param params.collectionAddress - The collection contract address
|
|
2615
|
+
* @param params.side - Order side (listing or bid)
|
|
2616
|
+
* @param params.filter - Optional filtering parameters
|
|
2617
|
+
* @param params.isLaos721 - Whether the collection is a LAOS721 contract
|
|
2618
|
+
* @param params.marketplaceType - Type of marketplace (shop, etc.)
|
|
2619
|
+
* @param params.query - Optional React Query configuration
|
|
2620
|
+
*
|
|
2621
|
+
* @returns Infinite query result containing collectibles data with pagination
|
|
2622
|
+
*
|
|
2623
|
+
* @example
|
|
2624
|
+
* Basic usage:
|
|
2625
|
+
* ```typescript
|
|
2626
|
+
* const { data, isLoading, fetchNextPage, hasNextPage } = useListCollectibles({
|
|
2627
|
+
* chainId: 137,
|
|
2628
|
+
* collectionAddress: '0x...',
|
|
2629
|
+
* side: OrderSide.listing
|
|
2630
|
+
* })
|
|
2631
|
+
* ```
|
|
2632
|
+
*
|
|
2633
|
+
* @example
|
|
2634
|
+
* With filtering:
|
|
2635
|
+
* ```typescript
|
|
2636
|
+
* const { data, fetchNextPage } = useListCollectibles({
|
|
2637
|
+
* chainId: 1,
|
|
2638
|
+
* collectionAddress: '0x...',
|
|
2639
|
+
* side: OrderSide.listing,
|
|
2640
|
+
* filter: {
|
|
2641
|
+
* searchText: 'dragon',
|
|
2642
|
+
* includeEmpty: false,
|
|
2643
|
+
* marketplaces: [MarketplaceKind.sequence_marketplace_v2]
|
|
2644
|
+
* }
|
|
2645
|
+
* })
|
|
2646
|
+
* ```
|
|
2647
|
+
*
|
|
2648
|
+
* @example
|
|
2649
|
+
* For LAOS721 collections:
|
|
2650
|
+
* ```typescript
|
|
2651
|
+
* const { data } = useListCollectibles({
|
|
2652
|
+
* chainId: 137,
|
|
2653
|
+
* collectionAddress: '0x...',
|
|
2654
|
+
* side: OrderSide.listing,
|
|
2655
|
+
* isLaos721: true,
|
|
2656
|
+
* filter: {
|
|
2657
|
+
* inAccounts: ['0x...']
|
|
2658
|
+
* }
|
|
2659
|
+
* })
|
|
2660
|
+
* ```
|
|
2661
|
+
*/
|
|
2662
|
+
function useListCollectibles(params) {
|
|
2663
|
+
const defaultConfig = useConfig();
|
|
2664
|
+
const { config = defaultConfig,...rest } = params;
|
|
2665
|
+
const queryOptions$1 = listCollectiblesQueryOptions({
|
|
2666
|
+
config,
|
|
2667
|
+
...rest
|
|
2668
|
+
});
|
|
2669
|
+
return useInfiniteQuery({ ...queryOptions$1 });
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
//#endregion
|
|
2673
|
+
//#region src/react/queries/primarySaleItems.ts
|
|
2674
|
+
/**
|
|
2675
|
+
* Fetches primary sale items from the marketplace API
|
|
2676
|
+
*/
|
|
2677
|
+
async function fetchPrimarySaleItems(params) {
|
|
2678
|
+
const { chainId, primarySaleContractAddress, filter, page, config } = params;
|
|
2679
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
2680
|
+
return marketplaceClient.listPrimarySaleItems({
|
|
2681
|
+
chainId: String(chainId),
|
|
2682
|
+
primarySaleContractAddress,
|
|
2683
|
+
filter,
|
|
2684
|
+
page
|
|
2685
|
+
});
|
|
2686
|
+
}
|
|
2687
|
+
const listPrimarySaleItemsQueryOptions = (params) => {
|
|
2688
|
+
const enabled = Boolean(params.primarySaleContractAddress && params.chainId && params.config && (params.query?.enabled ?? true));
|
|
2689
|
+
const initialPage = {
|
|
2690
|
+
page: 1,
|
|
2691
|
+
pageSize: 30
|
|
2692
|
+
};
|
|
2693
|
+
return infiniteQueryOptions({
|
|
2694
|
+
queryKey: ["listPrimarySaleItems", params],
|
|
2695
|
+
queryFn: async ({ pageParam }) => {
|
|
2696
|
+
return fetchPrimarySaleItems({
|
|
2697
|
+
chainId: params.chainId,
|
|
2698
|
+
primarySaleContractAddress: params.primarySaleContractAddress,
|
|
2699
|
+
filter: params.filter,
|
|
2700
|
+
page: pageParam,
|
|
2701
|
+
config: params.config
|
|
2702
|
+
});
|
|
2703
|
+
},
|
|
2704
|
+
initialPageParam: initialPage,
|
|
2705
|
+
getNextPageParam: (lastPage) => lastPage.page?.more ? {
|
|
2706
|
+
page: (lastPage.page?.page || 1) + 1,
|
|
2707
|
+
pageSize: lastPage.page?.pageSize || 30
|
|
2708
|
+
} : void 0,
|
|
2709
|
+
...params.query,
|
|
2710
|
+
enabled
|
|
2711
|
+
});
|
|
2712
|
+
};
|
|
2713
|
+
|
|
2714
|
+
//#endregion
|
|
2715
|
+
//#region src/react/hooks/useListPrimarySaleItems.tsx
|
|
2716
|
+
/**
|
|
2717
|
+
* Hook to fetch primary sale items with pagination support
|
|
2718
|
+
*
|
|
2719
|
+
* Retrieves a paginated list of primary sale items for a specific contract address
|
|
2720
|
+
* from the marketplace.
|
|
2721
|
+
*
|
|
2722
|
+
* @param params - Configuration parameters
|
|
2723
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2724
|
+
* @param params.primarySaleContractAddress - The primary sale contract address
|
|
2725
|
+
* @param params.filter - Optional filter parameters for the query
|
|
2726
|
+
* @param params.page - Optional pagination parameters
|
|
2727
|
+
* @param params.query - Optional React Query configuration
|
|
2728
|
+
*
|
|
2729
|
+
* @returns Infinite query result containing the primary sale items data
|
|
2730
|
+
*
|
|
2731
|
+
* @example
|
|
2732
|
+
* Basic usage:
|
|
2733
|
+
* ```typescript
|
|
2734
|
+
* const { data, isLoading } = useListPrimarySaleItems({
|
|
2735
|
+
* chainId: 137,
|
|
2736
|
+
* primarySaleContractAddress: '0x...',
|
|
2737
|
+
* })
|
|
2738
|
+
* ```
|
|
2739
|
+
*
|
|
2740
|
+
* @example
|
|
2741
|
+
* With filters and pagination:
|
|
2742
|
+
* ```typescript
|
|
2743
|
+
* const { data, isLoading } = useListPrimarySaleItems({
|
|
2744
|
+
* chainId: 1,
|
|
2745
|
+
* primarySaleContractAddress: '0x...',
|
|
2746
|
+
* filter: { status: 'active' },
|
|
2747
|
+
* page: { page: 1, pageSize: 20 },
|
|
2748
|
+
* query: {
|
|
2749
|
+
* enabled: isReady
|
|
2750
|
+
* }
|
|
2751
|
+
* })
|
|
2752
|
+
* ```
|
|
2753
|
+
*/
|
|
2754
|
+
function useListPrimarySaleItems(params) {
|
|
2755
|
+
const defaultConfig = useConfig();
|
|
2756
|
+
const { config = defaultConfig,...rest } = params;
|
|
2757
|
+
const queryOptions$1 = listPrimarySaleItemsQueryOptions({
|
|
2758
|
+
config,
|
|
2759
|
+
...rest
|
|
2760
|
+
});
|
|
2761
|
+
return useInfiniteQuery(queryOptions$1);
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
//#endregion
|
|
2765
|
+
//#region src/react/hooks/useList721ShopCardData.tsx
|
|
2766
|
+
function useList721ShopCardData({ tokenIds, chainId, contractAddress, salesContractAddress, enabled = true }) {
|
|
2767
|
+
const { showListedOnly } = useFilterState();
|
|
2768
|
+
const { data: primarySaleItems, isLoading: primarySaleItemsLoading, error: primarySaleItemsError } = useListPrimarySaleItems({
|
|
2769
|
+
chainId,
|
|
2770
|
+
primarySaleContractAddress: salesContractAddress,
|
|
2771
|
+
filter: { includeEmpty: !showListedOnly }
|
|
2772
|
+
});
|
|
2773
|
+
const firstAvailableTokenId = primarySaleItems?.pages[0]?.primarySaleItems[0]?.primarySaleItem.tokenId?.toString();
|
|
2774
|
+
const hasMintedTokens = Boolean(firstAvailableTokenId) && Number(firstAvailableTokenId) > 0;
|
|
2775
|
+
const { data: mintedTokensMetadata, isLoading: mintedTokensMetadataLoading } = useListCollectibles({
|
|
2776
|
+
chainId,
|
|
2777
|
+
collectionAddress: contractAddress,
|
|
2778
|
+
side: OrderSide.listing,
|
|
2779
|
+
filter: { includeEmpty: true },
|
|
2780
|
+
query: { enabled: enabled && hasMintedTokens }
|
|
2781
|
+
});
|
|
2782
|
+
const { data: saleDetails, isLoading: saleDetailsLoading, error: saleDetailsError } = useReadContract({
|
|
2783
|
+
chainId,
|
|
2784
|
+
address: salesContractAddress,
|
|
2785
|
+
abi: ERC721_SALE_ABI,
|
|
2786
|
+
functionName: "saleDetails",
|
|
2787
|
+
query: { enabled }
|
|
2788
|
+
});
|
|
2789
|
+
const isLoading = saleDetailsLoading || primarySaleItemsLoading || mintedTokensMetadataLoading;
|
|
2790
|
+
const mintedTokensMetadataMap = /* @__PURE__ */ new Map();
|
|
2791
|
+
for (const page of mintedTokensMetadata?.pages ?? []) for (const collectible of page.collectibles) mintedTokensMetadataMap.set(collectible.metadata.tokenId, collectible.metadata);
|
|
2792
|
+
const collectibleCards = tokenIds.map((tokenId) => {
|
|
2793
|
+
const minted = hasMintedTokens && Number(tokenId) < Number(firstAvailableTokenId);
|
|
2794
|
+
const matchingPrimarySaleItem = primarySaleItems?.pages.find((item) => item.primarySaleItems.find((primarySaleItem) => primarySaleItem.primarySaleItem.tokenId?.toString() === tokenId))?.primarySaleItems.find((primarySaleItem) => primarySaleItem.primarySaleItem.tokenId?.toString() === tokenId);
|
|
2795
|
+
const saleData = matchingPrimarySaleItem?.primarySaleItem;
|
|
2796
|
+
let tokenMetadata = matchingPrimarySaleItem?.metadata;
|
|
2797
|
+
if (minted && mintedTokensMetadataMap.has(tokenId)) tokenMetadata = mintedTokensMetadataMap.get(tokenId);
|
|
2798
|
+
tokenMetadata = tokenMetadata || {};
|
|
2799
|
+
const salePrice = saleData ? {
|
|
2800
|
+
amount: saleData.priceAmount?.toString() || "",
|
|
2801
|
+
currencyAddress: saleData.currencyAddress
|
|
2802
|
+
} : {
|
|
2803
|
+
amount: saleDetails?.cost?.toString() || "",
|
|
2804
|
+
currencyAddress: saleDetails?.paymentToken ?? "0x"
|
|
2805
|
+
};
|
|
2806
|
+
const quantityInitial = saleData?.supply?.toString() ?? (saleDetails?.supplyCap ? saleDetails.supplyCap.toString() : void 0);
|
|
2807
|
+
const quantityRemaining = minted ? void 0 : "1";
|
|
2808
|
+
const saleStartsAt = saleData?.startDate?.toString() ?? saleDetails?.startTime?.toString();
|
|
2809
|
+
const saleEndsAt = saleData?.endDate?.toString() ?? saleDetails?.endTime?.toString();
|
|
2810
|
+
return {
|
|
2811
|
+
collectibleId: tokenId,
|
|
2812
|
+
chainId,
|
|
2813
|
+
collectionAddress: contractAddress,
|
|
2814
|
+
collectionType: ContractType.ERC721,
|
|
2815
|
+
tokenMetadata,
|
|
2816
|
+
cardLoading: isLoading,
|
|
2817
|
+
salesContractAddress,
|
|
2818
|
+
salePrice,
|
|
2819
|
+
quantityInitial,
|
|
2820
|
+
quantityRemaining,
|
|
2821
|
+
quantityDecimals: 0,
|
|
2822
|
+
saleStartsAt,
|
|
2823
|
+
saleEndsAt,
|
|
2824
|
+
marketplaceType: "shop"
|
|
2825
|
+
};
|
|
2826
|
+
});
|
|
2827
|
+
return {
|
|
2828
|
+
salePrice: collectibleCards[0]?.salePrice,
|
|
2829
|
+
collectibleCards,
|
|
2830
|
+
saleDetailsError,
|
|
2831
|
+
primarySaleItemsError,
|
|
2832
|
+
saleDetails,
|
|
2833
|
+
primarySaleItems,
|
|
2834
|
+
isLoading
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2838
|
+
//#endregion
|
|
2839
|
+
//#region src/react/hooks/useList1155ShopCardData.tsx
|
|
2840
|
+
function useList1155ShopCardData({ tokenIds, chainId, contractAddress, salesContractAddress, enabled = true }) {
|
|
2841
|
+
const { showListedOnly } = useFilterState();
|
|
2842
|
+
const { data: primarySaleItems, isLoading: primarySaleItemsLoading, error: primarySaleItemsError } = useListPrimarySaleItems({
|
|
2843
|
+
chainId,
|
|
2844
|
+
primarySaleContractAddress: salesContractAddress,
|
|
2845
|
+
filter: { includeEmpty: !showListedOnly }
|
|
2846
|
+
});
|
|
2847
|
+
const { data: collection, isLoading: collectionLoading } = useCollection({
|
|
2848
|
+
chainId,
|
|
2849
|
+
collectionAddress: contractAddress
|
|
2850
|
+
});
|
|
2851
|
+
const { data: paymentToken, isLoading: paymentTokenLoading } = useReadContract({
|
|
2852
|
+
chainId,
|
|
2853
|
+
address: salesContractAddress,
|
|
2854
|
+
abi: ERC1155_SALES_CONTRACT_ABI,
|
|
2855
|
+
functionName: "paymentToken",
|
|
2856
|
+
query: { enabled }
|
|
2857
|
+
});
|
|
2858
|
+
const isLoading = primarySaleItemsLoading || collectionLoading || paymentTokenLoading;
|
|
2859
|
+
const allPrimarySaleItems = primarySaleItems?.pages.flatMap((page) => page.primarySaleItems) ?? [];
|
|
2860
|
+
const collectibleCards = tokenIds.map((tokenId) => {
|
|
2861
|
+
const matchingPrimarySaleItem = allPrimarySaleItems.find((item) => item.primarySaleItem.tokenId?.toString() === tokenId);
|
|
2862
|
+
const saleData = matchingPrimarySaleItem?.primarySaleItem;
|
|
2863
|
+
const tokenMetadata = matchingPrimarySaleItem?.metadata || {};
|
|
2864
|
+
const salePrice = {
|
|
2865
|
+
amount: saleData?.priceAmount?.toString() || "",
|
|
2866
|
+
currencyAddress: saleData?.currencyAddress || paymentToken || "0x"
|
|
2867
|
+
};
|
|
2868
|
+
const supply = saleData?.supply?.toString();
|
|
2869
|
+
const unlimitedSupply = saleData?.unlimitedSupply;
|
|
2870
|
+
return {
|
|
2871
|
+
collectibleId: tokenId,
|
|
2872
|
+
chainId,
|
|
2873
|
+
collectionAddress: contractAddress,
|
|
2874
|
+
collectionType: ContractType.ERC1155,
|
|
2875
|
+
tokenMetadata,
|
|
2876
|
+
cardLoading: isLoading,
|
|
2877
|
+
salesContractAddress,
|
|
2878
|
+
salePrice,
|
|
2879
|
+
quantityInitial: supply,
|
|
2880
|
+
quantityDecimals: collection?.decimals || 0,
|
|
2881
|
+
quantityRemaining: supply,
|
|
2882
|
+
unlimitedSupply,
|
|
2883
|
+
saleStartsAt: saleData?.startDate?.toString(),
|
|
2884
|
+
saleEndsAt: saleData?.endDate?.toString(),
|
|
2885
|
+
marketplaceType: "shop"
|
|
2886
|
+
};
|
|
2887
|
+
});
|
|
2888
|
+
return {
|
|
2889
|
+
collectibleCards,
|
|
2890
|
+
tokenMetadataError: primarySaleItemsError,
|
|
2891
|
+
tokenSaleDetailsError: null,
|
|
2892
|
+
isLoading
|
|
2893
|
+
};
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
//#endregion
|
|
2897
|
+
//#region src/react/hooks/useListBalances.tsx
|
|
2898
|
+
/**
|
|
2899
|
+
* Hook to fetch a list of token balances with pagination support
|
|
2900
|
+
*
|
|
2901
|
+
* @param args - The arguments for fetching the balances
|
|
2902
|
+
* @returns Infinite query result containing the balances data
|
|
2903
|
+
*
|
|
2904
|
+
* @example
|
|
2905
|
+
* ```tsx
|
|
2906
|
+
* const { data, isLoading, error, fetchNextPage } = useListBalances({
|
|
2907
|
+
* chainId: 1,
|
|
2908
|
+
* accountAddress: '0x123...',
|
|
2909
|
+
* includeMetadata: true,
|
|
2910
|
+
* query: {
|
|
2911
|
+
* enabled: true,
|
|
2912
|
+
* refetchInterval: 10000,
|
|
2913
|
+
* }
|
|
2914
|
+
* });
|
|
2915
|
+
* ```
|
|
2916
|
+
*/
|
|
2917
|
+
function useListBalances(args) {
|
|
2918
|
+
const config = useConfig();
|
|
2919
|
+
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
2920
|
+
const isLaos721 = marketplaceConfig?.market?.collections?.find((c) => c.itemsAddress === args.contractAddress && c.chainId === args.chainId)?.contractType === ContractType.LAOS_ERC_721;
|
|
2921
|
+
return useInfiniteQuery(listBalancesOptions({
|
|
2922
|
+
...args,
|
|
2923
|
+
isLaos721
|
|
2924
|
+
}, config));
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
//#endregion
|
|
2928
|
+
//#region src/react/queries/listCollectibleActivities.ts
|
|
2929
|
+
/**
|
|
2930
|
+
* Fetches collectible activities from the Marketplace API
|
|
2931
|
+
*/
|
|
2932
|
+
async function fetchListCollectibleActivities(params) {
|
|
2933
|
+
const { collectionAddress, chainId, config, page, pageSize, sort,...additionalApiParams } = params;
|
|
2934
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
2935
|
+
const pageParams = page || pageSize || sort ? {
|
|
2936
|
+
page: page ?? 1,
|
|
2937
|
+
pageSize: pageSize ?? 10,
|
|
2938
|
+
sort
|
|
2939
|
+
} : void 0;
|
|
2940
|
+
const apiArgs = {
|
|
2941
|
+
contractAddress: collectionAddress,
|
|
2942
|
+
chainId: String(chainId),
|
|
2943
|
+
page: pageParams,
|
|
2944
|
+
...additionalApiParams
|
|
2945
|
+
};
|
|
2946
|
+
return await marketplaceClient.listCollectibleActivities(apiArgs);
|
|
2947
|
+
}
|
|
2948
|
+
function listCollectibleActivitiesQueryOptions(params) {
|
|
2949
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.tokenId && params.config && (params.query?.enabled ?? true));
|
|
2950
|
+
return queryOptions({
|
|
2951
|
+
queryKey: [...collectableKeys.collectibleActivities, params],
|
|
2952
|
+
queryFn: () => fetchListCollectibleActivities({
|
|
2953
|
+
chainId: params.chainId,
|
|
2954
|
+
collectionAddress: params.collectionAddress,
|
|
2955
|
+
config: params.config,
|
|
2956
|
+
tokenId: params.tokenId,
|
|
2957
|
+
page: params.page,
|
|
2958
|
+
pageSize: params.pageSize,
|
|
2959
|
+
sort: params.sort
|
|
2960
|
+
}),
|
|
2961
|
+
...params.query,
|
|
2962
|
+
enabled
|
|
2963
|
+
});
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
//#endregion
|
|
2967
|
+
//#region src/react/hooks/useListCollectibleActivities.tsx
|
|
2968
|
+
/**
|
|
2969
|
+
* Hook to fetch a list of activities for a specific collectible
|
|
2970
|
+
*
|
|
2971
|
+
* Fetches activities (transfers, sales, offers, etc.) for a specific token
|
|
2972
|
+
* from the marketplace with support for pagination and sorting.
|
|
2973
|
+
*
|
|
2974
|
+
* @param params - Configuration parameters
|
|
2975
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
2976
|
+
* @param params.collectionAddress - The collection contract address
|
|
2977
|
+
* @param params.tokenId - The specific token ID to fetch activities for
|
|
2978
|
+
* @param params.page - Page number to fetch (default: 1)
|
|
2979
|
+
* @param params.pageSize - Number of activities per page (default: 10)
|
|
2980
|
+
* @param params.sort - Sort order for activities
|
|
2981
|
+
* @param params.query - Optional React Query configuration
|
|
2982
|
+
*
|
|
2983
|
+
* @returns Query result containing activities data
|
|
2984
|
+
*
|
|
2985
|
+
* @example
|
|
2986
|
+
* Basic usage:
|
|
2987
|
+
* ```typescript
|
|
2988
|
+
* const { data, isLoading } = useListCollectibleActivities({
|
|
2989
|
+
* chainId: 137,
|
|
2990
|
+
* collectionAddress: '0x...',
|
|
2991
|
+
* tokenId: '123'
|
|
2992
|
+
* })
|
|
2993
|
+
* ```
|
|
2994
|
+
*
|
|
2995
|
+
* @example
|
|
2996
|
+
* With pagination:
|
|
2997
|
+
* ```typescript
|
|
2998
|
+
* const { data } = useListCollectibleActivities({
|
|
2999
|
+
* chainId: 1,
|
|
3000
|
+
* collectionAddress: '0x...',
|
|
3001
|
+
* tokenId: '456',
|
|
3002
|
+
* page: 2,
|
|
3003
|
+
* pageSize: 20
|
|
3004
|
+
* })
|
|
3005
|
+
* ```
|
|
3006
|
+
*
|
|
3007
|
+
* @example
|
|
3008
|
+
* With sorting:
|
|
3009
|
+
* ```typescript
|
|
3010
|
+
* const { data } = useListCollectibleActivities({
|
|
3011
|
+
* chainId: 137,
|
|
3012
|
+
* collectionAddress: '0x...',
|
|
3013
|
+
* tokenId: '789',
|
|
3014
|
+
* sort: 'timestamp_desc',
|
|
3015
|
+
* pageSize: 50
|
|
3016
|
+
* })
|
|
3017
|
+
* ```
|
|
3018
|
+
*/
|
|
3019
|
+
function useListCollectibleActivities(params) {
|
|
3020
|
+
const defaultConfig = useConfig();
|
|
3021
|
+
const { config = defaultConfig,...rest } = params;
|
|
3022
|
+
const queryOptions$1 = listCollectibleActivitiesQueryOptions({
|
|
3023
|
+
config,
|
|
3024
|
+
...rest
|
|
3025
|
+
});
|
|
3026
|
+
return useQuery({ ...queryOptions$1 });
|
|
3027
|
+
}
|
|
3028
|
+
|
|
3029
|
+
//#endregion
|
|
3030
|
+
//#region src/react/queries/listCollectiblesPaginated.ts
|
|
3031
|
+
/**
|
|
3032
|
+
* Fetches a list of collectibles with pagination support from the Marketplace API
|
|
3033
|
+
*/
|
|
3034
|
+
async function fetchListCollectiblesPaginated(params) {
|
|
3035
|
+
const { collectionAddress, chainId, config, page = 1, pageSize = 30,...additionalApiParams } = params;
|
|
3036
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
3037
|
+
const pageParams = {
|
|
3038
|
+
page,
|
|
3039
|
+
pageSize
|
|
3040
|
+
};
|
|
3041
|
+
const apiArgs = {
|
|
3042
|
+
contractAddress: collectionAddress,
|
|
3043
|
+
chainId: String(chainId),
|
|
3044
|
+
page: pageParams,
|
|
3045
|
+
...additionalApiParams
|
|
3046
|
+
};
|
|
3047
|
+
return await marketplaceClient.listCollectibles(apiArgs);
|
|
3048
|
+
}
|
|
3049
|
+
function listCollectiblesPaginatedQueryOptions(params) {
|
|
3050
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.side && params.config && (params.query?.enabled ?? true));
|
|
3051
|
+
return queryOptions({
|
|
3052
|
+
queryKey: [
|
|
3053
|
+
...collectableKeys.lists,
|
|
3054
|
+
"paginated",
|
|
3055
|
+
params
|
|
3056
|
+
],
|
|
3057
|
+
queryFn: () => fetchListCollectiblesPaginated({
|
|
3058
|
+
chainId: params.chainId,
|
|
3059
|
+
collectionAddress: params.collectionAddress,
|
|
3060
|
+
config: params.config,
|
|
3061
|
+
side: params.side,
|
|
3062
|
+
filter: params.filter,
|
|
3063
|
+
page: params.page,
|
|
3064
|
+
pageSize: params.pageSize
|
|
3065
|
+
}),
|
|
3066
|
+
...params.query,
|
|
3067
|
+
enabled
|
|
3068
|
+
});
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
//#endregion
|
|
3072
|
+
//#region src/react/hooks/useListCollectiblesPaginated.tsx
|
|
3073
|
+
/**
|
|
3074
|
+
* Hook to fetch a list of collectibles with pagination support
|
|
3075
|
+
*
|
|
3076
|
+
* Fetches collectibles from the marketplace with support for filtering and pagination.
|
|
3077
|
+
* Unlike the infinite query version, this hook fetches a specific page of results.
|
|
3078
|
+
*
|
|
3079
|
+
* @param params - Configuration parameters
|
|
3080
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
3081
|
+
* @param params.collectionAddress - The collection contract address
|
|
3082
|
+
* @param params.side - Order side (listing or bid)
|
|
3083
|
+
* @param params.filter - Optional filtering parameters
|
|
3084
|
+
* @param params.page - Page number to fetch (default: 1)
|
|
3085
|
+
* @param params.pageSize - Number of items per page (default: 30)
|
|
3086
|
+
* @param params.query - Optional React Query configuration
|
|
3087
|
+
*
|
|
3088
|
+
* @returns Query result containing collectibles data for the specific page
|
|
3089
|
+
*
|
|
3090
|
+
* @example
|
|
3091
|
+
* Basic usage:
|
|
3092
|
+
* ```typescript
|
|
3093
|
+
* const { data, isLoading } = useListCollectiblesPaginated({
|
|
3094
|
+
* chainId: 137,
|
|
3095
|
+
* collectionAddress: '0x...',
|
|
3096
|
+
* side: OrderSide.listing,
|
|
3097
|
+
* page: 1,
|
|
3098
|
+
* pageSize: 20
|
|
3099
|
+
* })
|
|
3100
|
+
* ```
|
|
3101
|
+
*
|
|
3102
|
+
* @example
|
|
3103
|
+
* With filtering:
|
|
3104
|
+
* ```typescript
|
|
3105
|
+
* const { data } = useListCollectiblesPaginated({
|
|
3106
|
+
* chainId: 1,
|
|
3107
|
+
* collectionAddress: '0x...',
|
|
3108
|
+
* side: OrderSide.listing,
|
|
3109
|
+
* page: 2,
|
|
3110
|
+
* pageSize: 50,
|
|
3111
|
+
* filter: {
|
|
3112
|
+
* searchText: 'rare',
|
|
3113
|
+
* includeEmpty: false
|
|
3114
|
+
* }
|
|
3115
|
+
* })
|
|
3116
|
+
* ```
|
|
3117
|
+
*
|
|
3118
|
+
* @example
|
|
3119
|
+
* Controlled pagination:
|
|
3120
|
+
* ```typescript
|
|
3121
|
+
* const [currentPage, setCurrentPage] = useState(1);
|
|
3122
|
+
* const { data, isLoading } = useListCollectiblesPaginated({
|
|
3123
|
+
* chainId: 137,
|
|
3124
|
+
* collectionAddress: '0x...',
|
|
3125
|
+
* side: OrderSide.listing,
|
|
3126
|
+
* page: currentPage,
|
|
3127
|
+
* pageSize: 25
|
|
3128
|
+
* });
|
|
3129
|
+
*
|
|
3130
|
+
* const hasMorePages = data?.page?.more;
|
|
3131
|
+
* ```
|
|
3132
|
+
*/
|
|
3133
|
+
function useListCollectiblesPaginated(params) {
|
|
3134
|
+
const defaultConfig = useConfig();
|
|
3135
|
+
const { config = defaultConfig,...rest } = params;
|
|
3136
|
+
const queryOptions$1 = listCollectiblesPaginatedQueryOptions({
|
|
3137
|
+
config,
|
|
3138
|
+
...rest
|
|
3139
|
+
});
|
|
3140
|
+
return useQuery({ ...queryOptions$1 });
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
//#endregion
|
|
3144
|
+
//#region src/react/queries/listCollectionActivities.ts
|
|
3145
|
+
/**
|
|
3146
|
+
* Fetches collection activities from the Marketplace API
|
|
3147
|
+
*/
|
|
3148
|
+
async function fetchListCollectionActivities(params) {
|
|
3149
|
+
const { collectionAddress, chainId, config, page, pageSize, sort,...additionalApiParams } = params;
|
|
3150
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
3151
|
+
const pageParams = page || pageSize || sort ? {
|
|
3152
|
+
page: page ?? 1,
|
|
3153
|
+
pageSize: pageSize ?? 10,
|
|
3154
|
+
sort
|
|
3155
|
+
} : void 0;
|
|
3156
|
+
const apiArgs = {
|
|
3157
|
+
contractAddress: collectionAddress,
|
|
3158
|
+
chainId: String(chainId),
|
|
3159
|
+
page: pageParams,
|
|
3160
|
+
...additionalApiParams
|
|
3161
|
+
};
|
|
3162
|
+
return await marketplaceClient.listCollectionActivities(apiArgs);
|
|
3163
|
+
}
|
|
3164
|
+
function listCollectionActivitiesQueryOptions(params) {
|
|
3165
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.config && (params.query?.enabled ?? true));
|
|
3166
|
+
return queryOptions({
|
|
3167
|
+
queryKey: [...collectionKeys.collectionActivities, params],
|
|
3168
|
+
queryFn: () => fetchListCollectionActivities({
|
|
3169
|
+
chainId: params.chainId,
|
|
3170
|
+
collectionAddress: params.collectionAddress,
|
|
3171
|
+
config: params.config,
|
|
3172
|
+
page: params.page,
|
|
3173
|
+
pageSize: params.pageSize,
|
|
3174
|
+
sort: params.sort
|
|
3175
|
+
}),
|
|
3176
|
+
...params.query,
|
|
3177
|
+
enabled
|
|
3178
|
+
});
|
|
3179
|
+
}
|
|
3180
|
+
|
|
3181
|
+
//#endregion
|
|
3182
|
+
//#region src/react/hooks/useListCollectionActivities.tsx
|
|
3183
|
+
/**
|
|
3184
|
+
* Hook to fetch a list of activities for an entire collection
|
|
3185
|
+
*
|
|
3186
|
+
* Fetches activities (transfers, sales, offers, etc.) for all tokens
|
|
3187
|
+
* in a collection from the marketplace with support for pagination and sorting.
|
|
3188
|
+
*
|
|
3189
|
+
* @param params - Configuration parameters
|
|
3190
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
3191
|
+
* @param params.collectionAddress - The collection contract address
|
|
3192
|
+
* @param params.page - Page number to fetch (default: 1)
|
|
3193
|
+
* @param params.pageSize - Number of activities per page (default: 10)
|
|
3194
|
+
* @param params.sort - Sort order for activities
|
|
3195
|
+
* @param params.query - Optional React Query configuration
|
|
3196
|
+
*
|
|
3197
|
+
* @returns Query result containing activities data for the collection
|
|
3198
|
+
*
|
|
3199
|
+
* @example
|
|
3200
|
+
* Basic usage:
|
|
3201
|
+
* ```typescript
|
|
3202
|
+
* const { data, isLoading } = useListCollectionActivities({
|
|
3203
|
+
* chainId: 137,
|
|
3204
|
+
* collectionAddress: '0x...'
|
|
3205
|
+
* })
|
|
3206
|
+
* ```
|
|
3207
|
+
*
|
|
3208
|
+
* @example
|
|
3209
|
+
* With pagination:
|
|
3210
|
+
* ```typescript
|
|
3211
|
+
* const { data } = useListCollectionActivities({
|
|
3212
|
+
* chainId: 1,
|
|
3213
|
+
* collectionAddress: '0x...',
|
|
3214
|
+
* page: 2,
|
|
3215
|
+
* pageSize: 20
|
|
3216
|
+
* })
|
|
3217
|
+
* ```
|
|
3218
|
+
*
|
|
3219
|
+
* @example
|
|
3220
|
+
* With sorting:
|
|
3221
|
+
* ```typescript
|
|
3222
|
+
* const { data } = useListCollectionActivities({
|
|
3223
|
+
* chainId: 137,
|
|
3224
|
+
* collectionAddress: '0x...',
|
|
3225
|
+
* sort: [{ column: 'createdAt', order: SortOrder.DESC }],
|
|
3226
|
+
* pageSize: 50
|
|
3227
|
+
* })
|
|
3228
|
+
* ```
|
|
3229
|
+
*/
|
|
3230
|
+
function useListCollectionActivities(params) {
|
|
3231
|
+
const defaultConfig = useConfig();
|
|
3232
|
+
const { config = defaultConfig,...rest } = params;
|
|
3233
|
+
const queryOptions$1 = listCollectionActivitiesQueryOptions({
|
|
3234
|
+
config,
|
|
3235
|
+
...rest
|
|
3236
|
+
});
|
|
3237
|
+
return useQuery({ ...queryOptions$1 });
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
//#endregion
|
|
3241
|
+
//#region src/react/hooks/useListCollections.tsx
|
|
3242
|
+
/**
|
|
3243
|
+
* Hook to fetch collections from marketplace configuration
|
|
3244
|
+
*
|
|
3245
|
+
* Retrieves all collections configured in the marketplace, with optional filtering
|
|
3246
|
+
* by marketplace type. Combines metadata from the metadata API with marketplace
|
|
3247
|
+
* configuration to provide complete collection information.
|
|
3248
|
+
*
|
|
3249
|
+
* @param params - Configuration parameters
|
|
3250
|
+
* @param params.marketplaceType - Optional filter by marketplace type
|
|
3251
|
+
* @param params.query - Optional React Query configuration
|
|
3252
|
+
*
|
|
3253
|
+
* @returns Query result containing array of collections with metadata
|
|
3254
|
+
*
|
|
3255
|
+
* @example
|
|
3256
|
+
* Basic usage:
|
|
3257
|
+
* ```typescript
|
|
3258
|
+
* const { data: collections, isLoading } = useListCollections();
|
|
3259
|
+
*
|
|
3260
|
+
* if (isLoading) return <div>Loading collections...</div>;
|
|
3261
|
+
*
|
|
3262
|
+
* return (
|
|
3263
|
+
* <div>
|
|
3264
|
+
* {collections?.map(collection => (
|
|
3265
|
+
* <div key={collection.itemsAddress}>
|
|
3266
|
+
* {collection.name}
|
|
3267
|
+
* </div>
|
|
3268
|
+
* ))}
|
|
3269
|
+
* </div>
|
|
3270
|
+
* );
|
|
3271
|
+
* ```
|
|
3272
|
+
*
|
|
3273
|
+
* @example
|
|
3274
|
+
* Filtering by marketplace type:
|
|
3275
|
+
* ```typescript
|
|
3276
|
+
* const { data: marketCollections } = useListCollections({
|
|
3277
|
+
* marketplaceType: 'market'
|
|
3278
|
+
* });
|
|
3279
|
+
* ```
|
|
3280
|
+
*/
|
|
3281
|
+
function useListCollections(params = {}) {
|
|
3282
|
+
const defaultConfig = useConfig();
|
|
3283
|
+
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
3284
|
+
const { config = defaultConfig, marketplaceConfig: paramMarketplaceConfig,...rest } = params;
|
|
3285
|
+
const queryOptions$1 = listCollectionsQueryOptions({
|
|
3286
|
+
config,
|
|
3287
|
+
marketplaceConfig: paramMarketplaceConfig || marketplaceConfig,
|
|
3288
|
+
...rest
|
|
3289
|
+
});
|
|
3290
|
+
return useQuery({ ...queryOptions$1 });
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
//#endregion
|
|
3294
|
+
//#region src/react/queries/listListingsForCollectible.ts
|
|
3295
|
+
/**
|
|
3296
|
+
* Fetches listings for a specific collectible from the Marketplace API
|
|
3297
|
+
*/
|
|
3298
|
+
async function fetchListListingsForCollectible(params) {
|
|
3299
|
+
const { collectionAddress, chainId, collectibleId, config,...additionalApiParams } = params;
|
|
3300
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
3301
|
+
const apiArgs = {
|
|
3302
|
+
contractAddress: collectionAddress,
|
|
3303
|
+
chainId: String(chainId),
|
|
3304
|
+
tokenId: collectibleId,
|
|
3305
|
+
...additionalApiParams
|
|
3306
|
+
};
|
|
3307
|
+
return await marketplaceClient.listCollectibleListings(apiArgs);
|
|
3308
|
+
}
|
|
3309
|
+
function listListingsForCollectibleQueryOptions(params) {
|
|
3310
|
+
const enabled = Boolean(params.collectionAddress && params.chainId && params.collectibleId && params.config && (params.query?.enabled ?? true));
|
|
3311
|
+
return queryOptions({
|
|
3312
|
+
queryKey: [...collectableKeys.listings, params],
|
|
3313
|
+
queryFn: () => fetchListListingsForCollectible({
|
|
3314
|
+
chainId: params.chainId,
|
|
3315
|
+
collectionAddress: params.collectionAddress,
|
|
3316
|
+
collectibleId: params.collectibleId,
|
|
3317
|
+
config: params.config,
|
|
3318
|
+
filter: params.filter,
|
|
3319
|
+
page: params.page
|
|
3320
|
+
}),
|
|
3321
|
+
...params.query,
|
|
3322
|
+
enabled
|
|
3323
|
+
});
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
//#endregion
|
|
3327
|
+
//#region src/react/hooks/useListListingsForCollectible.tsx
|
|
3328
|
+
/**
|
|
3329
|
+
* Hook to fetch listings for a specific collectible
|
|
3330
|
+
*
|
|
3331
|
+
* Fetches active listings (sales) for a specific token from the marketplace
|
|
3332
|
+
* with support for filtering and pagination.
|
|
3333
|
+
*
|
|
3334
|
+
* @param params - Configuration parameters
|
|
3335
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
3336
|
+
* @param params.collectionAddress - The collection contract address
|
|
3337
|
+
* @param params.collectibleId - The specific token ID to fetch listings for
|
|
3338
|
+
* @param params.filter - Optional filtering parameters (marketplace, currencies, etc.)
|
|
3339
|
+
* @param params.page - Optional pagination parameters
|
|
3340
|
+
* @param params.query - Optional React Query configuration
|
|
3341
|
+
*
|
|
3342
|
+
* @returns Query result containing listings data for the collectible
|
|
3343
|
+
*
|
|
3344
|
+
* @example
|
|
3345
|
+
* Basic usage:
|
|
3346
|
+
* ```typescript
|
|
3347
|
+
* const { data, isLoading } = useListListingsForCollectible({
|
|
3348
|
+
* chainId: 137,
|
|
3349
|
+
* collectionAddress: '0x...',
|
|
3350
|
+
* collectibleId: '123'
|
|
3351
|
+
* })
|
|
3352
|
+
* ```
|
|
3353
|
+
*
|
|
3354
|
+
* @example
|
|
3355
|
+
* With pagination:
|
|
3356
|
+
* ```typescript
|
|
3357
|
+
* const { data } = useListListingsForCollectible({
|
|
3358
|
+
* chainId: 1,
|
|
3359
|
+
* collectionAddress: '0x...',
|
|
3360
|
+
* collectibleId: '456',
|
|
3361
|
+
* page: {
|
|
3362
|
+
* page: 2,
|
|
3363
|
+
* pageSize: 20
|
|
3364
|
+
* }
|
|
3365
|
+
* })
|
|
3366
|
+
* ```
|
|
3367
|
+
*
|
|
3368
|
+
* @example
|
|
3369
|
+
* With filtering:
|
|
3370
|
+
* ```typescript
|
|
3371
|
+
* const { data } = useListListingsForCollectible({
|
|
3372
|
+
* chainId: 137,
|
|
3373
|
+
* collectionAddress: '0x...',
|
|
3374
|
+
* collectibleId: '789',
|
|
3375
|
+
* filter: {
|
|
3376
|
+
* marketplace: [MarketplaceKind.sequence_marketplace_v2],
|
|
3377
|
+
* currencies: ['0x...'] // Specific currency addresses
|
|
3378
|
+
* }
|
|
3379
|
+
* })
|
|
3380
|
+
* ```
|
|
3381
|
+
*/
|
|
3382
|
+
function useListListingsForCollectible(params) {
|
|
3383
|
+
const defaultConfig = useConfig();
|
|
3384
|
+
const { config = defaultConfig,...rest } = params;
|
|
3385
|
+
const queryOptions$1 = listListingsForCollectibleQueryOptions({
|
|
3386
|
+
config,
|
|
3387
|
+
...rest
|
|
3388
|
+
});
|
|
3389
|
+
return useQuery({ ...queryOptions$1 });
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3392
|
+
//#endregion
|
|
3393
|
+
//#region src/react/ui/modals/SellModal/store.ts
|
|
3394
|
+
const initialState = {
|
|
3395
|
+
isOpen: false,
|
|
3396
|
+
collectionAddress: "",
|
|
3397
|
+
chainId: 0,
|
|
3398
|
+
tokenId: "",
|
|
3399
|
+
order: void 0,
|
|
3400
|
+
callbacks: void 0,
|
|
3401
|
+
sellIsBeingProcessed: false,
|
|
3402
|
+
open: (args) => {
|
|
3403
|
+
sellModal$.collectionAddress.set(args.collectionAddress);
|
|
3404
|
+
sellModal$.chainId.set(args.chainId);
|
|
3405
|
+
sellModal$.tokenId.set(args.tokenId);
|
|
3406
|
+
sellModal$.order.set(args.order);
|
|
3407
|
+
sellModal$.callbacks.set(args.callbacks);
|
|
3408
|
+
sellModal$.isOpen.set(true);
|
|
3409
|
+
},
|
|
3410
|
+
close: () => {
|
|
3411
|
+
sellModal$.isOpen.set(false);
|
|
3412
|
+
sellModal$.callbacks.set(void 0);
|
|
3413
|
+
sellModal$.sellIsBeingProcessed.set(false);
|
|
3414
|
+
},
|
|
3415
|
+
steps: {
|
|
3416
|
+
approval: {
|
|
3417
|
+
exist: false,
|
|
3418
|
+
isExecuting: false,
|
|
3419
|
+
execute: () => Promise.resolve()
|
|
3420
|
+
},
|
|
3421
|
+
transaction: {
|
|
3422
|
+
exist: false,
|
|
3423
|
+
isExecuting: false,
|
|
3424
|
+
execute: () => Promise.resolve()
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
};
|
|
3428
|
+
const sellModal$ = observable(initialState);
|
|
3429
|
+
|
|
3430
|
+
//#endregion
|
|
3431
|
+
//#region src/react/ui/modals/SellModal/index.tsx
|
|
3432
|
+
const useSellModal = (callbacks) => {
|
|
3433
|
+
return {
|
|
3434
|
+
show: (args) => sellModal$.open({
|
|
3435
|
+
...args,
|
|
3436
|
+
callbacks
|
|
3437
|
+
}),
|
|
3438
|
+
close: () => sellModal$.close()
|
|
3439
|
+
};
|
|
3440
|
+
};
|
|
3441
|
+
|
|
3442
|
+
//#endregion
|
|
3443
|
+
//#region src/react/hooks/useListMarketCardData.tsx
|
|
3444
|
+
function useListMarketCardData({ collectionAddress, chainId, orderbookKind, collectionType, filterOptions, searchText, showListedOnly = false, onCollectibleClick, onCannotPerformAction, prioritizeOwnerActions, assetSrcPrefixUrl }) {
|
|
3445
|
+
const { address: accountAddress } = useAccount();
|
|
3446
|
+
const { show: showSellModal } = useSellModal();
|
|
3447
|
+
const { data: collectiblesList, isLoading: collectiblesListIsLoading, fetchNextPage, hasNextPage, isFetchingNextPage, error: collectiblesListError } = useListCollectibles({
|
|
3448
|
+
collectionAddress,
|
|
3449
|
+
chainId,
|
|
3450
|
+
side: OrderSide.listing,
|
|
3451
|
+
filter: {
|
|
3452
|
+
includeEmpty: !showListedOnly,
|
|
3453
|
+
searchText,
|
|
3454
|
+
properties: filterOptions
|
|
3455
|
+
},
|
|
3456
|
+
query: { enabled: !!collectionAddress && !!chainId }
|
|
3457
|
+
});
|
|
3458
|
+
const { data: collectionBalance, isLoading: balanceLoading } = useCollectionBalanceDetails({
|
|
3459
|
+
chainId,
|
|
3460
|
+
filter: {
|
|
3461
|
+
accountAddresses: accountAddress ? [accountAddress] : [],
|
|
3462
|
+
omitNativeBalances: true,
|
|
3463
|
+
contractWhitelist: [collectionAddress]
|
|
3464
|
+
},
|
|
3465
|
+
query: { enabled: !!accountAddress }
|
|
3466
|
+
});
|
|
3467
|
+
const allCollectibles = useMemo(() => {
|
|
3468
|
+
if (!collectiblesList?.pages) return [];
|
|
3469
|
+
return collectiblesList.pages.flatMap((page) => page.collectibles);
|
|
3470
|
+
}, [collectiblesList?.pages]);
|
|
3471
|
+
const collectibleCards = useMemo(() => {
|
|
3472
|
+
return allCollectibles.map((collectible) => {
|
|
3473
|
+
const balance = collectionBalance?.balances.find((balance$1) => balance$1.tokenID === collectible.metadata.tokenId)?.balance;
|
|
3474
|
+
const cardProps = {
|
|
3475
|
+
collectibleId: collectible.metadata.tokenId,
|
|
3476
|
+
chainId,
|
|
3477
|
+
collectionAddress,
|
|
3478
|
+
collectionType,
|
|
3479
|
+
cardLoading: collectiblesListIsLoading || balanceLoading,
|
|
3480
|
+
marketplaceType: "market",
|
|
3481
|
+
orderbookKind,
|
|
3482
|
+
collectible,
|
|
3483
|
+
onCollectibleClick,
|
|
3484
|
+
balance,
|
|
3485
|
+
balanceIsLoading: balanceLoading,
|
|
3486
|
+
onCannotPerformAction,
|
|
3487
|
+
prioritizeOwnerActions,
|
|
3488
|
+
assetSrcPrefixUrl,
|
|
3489
|
+
onOfferClick: ({ order }) => {
|
|
3490
|
+
if (!accountAddress) return;
|
|
3491
|
+
if (balance) {
|
|
3492
|
+
showSellModal({
|
|
3493
|
+
chainId,
|
|
3494
|
+
collectionAddress,
|
|
3495
|
+
tokenId: collectible.metadata.tokenId,
|
|
3496
|
+
order
|
|
3497
|
+
});
|
|
3498
|
+
return;
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
};
|
|
3502
|
+
return cardProps;
|
|
3503
|
+
});
|
|
3504
|
+
}, [
|
|
3505
|
+
allCollectibles,
|
|
3506
|
+
chainId,
|
|
3507
|
+
collectionAddress,
|
|
3508
|
+
collectionType,
|
|
3509
|
+
collectiblesListIsLoading,
|
|
3510
|
+
balanceLoading,
|
|
3511
|
+
orderbookKind,
|
|
3512
|
+
onCollectibleClick,
|
|
3513
|
+
collectionBalance?.balances,
|
|
3514
|
+
onCannotPerformAction,
|
|
3515
|
+
prioritizeOwnerActions,
|
|
3516
|
+
assetSrcPrefixUrl,
|
|
3517
|
+
accountAddress,
|
|
3518
|
+
showSellModal
|
|
3519
|
+
]);
|
|
3520
|
+
return {
|
|
3521
|
+
collectibleCards,
|
|
3522
|
+
isLoading: collectiblesListIsLoading || balanceLoading,
|
|
3523
|
+
error: collectiblesListError,
|
|
3524
|
+
hasNextPage,
|
|
3525
|
+
isFetchingNextPage,
|
|
3526
|
+
fetchNextPage,
|
|
3527
|
+
allCollectibles
|
|
3528
|
+
};
|
|
3529
|
+
}
|
|
3530
|
+
|
|
3531
|
+
//#endregion
|
|
3532
|
+
//#region src/react/hooks/useListOffersForCollectible.tsx
|
|
3533
|
+
const fetchListOffersForCollectible = async (config, args) => {
|
|
3534
|
+
const arg = {
|
|
3535
|
+
chainId: String(args.chainId),
|
|
3536
|
+
contractAddress: args.collectionAddress,
|
|
3537
|
+
tokenId: args.collectibleId,
|
|
3538
|
+
filter: args.filter,
|
|
3539
|
+
page: args.page
|
|
3540
|
+
};
|
|
3541
|
+
const marketplaceClient = getMarketplaceClient(config);
|
|
3542
|
+
return marketplaceClient.listCollectibleOffers(arg);
|
|
3543
|
+
};
|
|
3544
|
+
const listOffersForCollectibleOptions = (args, config) => {
|
|
3545
|
+
return queryOptions({
|
|
3546
|
+
queryKey: [
|
|
3547
|
+
...collectableKeys.offers,
|
|
3548
|
+
args,
|
|
3549
|
+
config
|
|
3550
|
+
],
|
|
3551
|
+
queryFn: () => fetchListOffersForCollectible(config, args)
|
|
3552
|
+
});
|
|
3553
|
+
};
|
|
3554
|
+
const useListOffersForCollectible = (args) => {
|
|
3555
|
+
const config = useConfig();
|
|
3556
|
+
return useQuery(listOffersForCollectibleOptions(args, config));
|
|
3557
|
+
};
|
|
3558
|
+
|
|
3559
|
+
//#endregion
|
|
3560
|
+
//#region src/react/hooks/useListShopCardData.tsx
|
|
3561
|
+
function useListShopCardData({ tokenIds, chainId, contractAddress, salesContractAddress, contractType, enabled = true }) {
|
|
3562
|
+
const shouldUse721 = contractType === ContractType.ERC721;
|
|
3563
|
+
const shouldUse1155 = contractType === ContractType.ERC1155;
|
|
3564
|
+
const erc721Data = useList721ShopCardData({
|
|
3565
|
+
tokenIds,
|
|
3566
|
+
chainId,
|
|
3567
|
+
contractAddress,
|
|
3568
|
+
salesContractAddress,
|
|
3569
|
+
enabled: enabled && shouldUse721
|
|
3570
|
+
});
|
|
3571
|
+
const erc1155Data = useList1155ShopCardData({
|
|
3572
|
+
tokenIds,
|
|
3573
|
+
chainId,
|
|
3574
|
+
contractAddress,
|
|
3575
|
+
salesContractAddress,
|
|
3576
|
+
enabled: enabled && shouldUse1155
|
|
3577
|
+
});
|
|
3578
|
+
if (shouldUse721) return erc721Data;
|
|
3579
|
+
if (shouldUse1155) return {
|
|
3580
|
+
collectibleCards: erc1155Data.collectibleCards,
|
|
3581
|
+
isLoading: erc1155Data.isLoading,
|
|
3582
|
+
saleDetailsError: erc1155Data.tokenSaleDetailsError,
|
|
3583
|
+
primarySaleItemsError: erc1155Data.tokenMetadataError,
|
|
3584
|
+
saleDetails: void 0,
|
|
3585
|
+
primarySaleItems: void 0,
|
|
3586
|
+
salePrice: erc1155Data.collectibleCards[0]?.salePrice
|
|
3587
|
+
};
|
|
3588
|
+
return {
|
|
3589
|
+
collectibleCards: [],
|
|
3590
|
+
isLoading: !contractType,
|
|
3591
|
+
collectionDetailsError: null,
|
|
3592
|
+
saleDetailsError: null,
|
|
3593
|
+
primarySaleItemsError: null,
|
|
3594
|
+
saleDetails: void 0,
|
|
3595
|
+
primarySaleItems: void 0,
|
|
3596
|
+
salePrice: void 0
|
|
3597
|
+
};
|
|
3598
|
+
}
|
|
3599
|
+
|
|
3600
|
+
//#endregion
|
|
3601
|
+
//#region src/react/hooks/useListTokenMetadata.tsx
|
|
3602
|
+
/**
|
|
3603
|
+
* Hook to fetch metadata for multiple tokens
|
|
3604
|
+
*
|
|
3605
|
+
* Retrieves metadata for a batch of tokens from a specific contract using the metadata API.
|
|
3606
|
+
* This hook is optimized for fetching multiple token metadata in a single request.
|
|
3607
|
+
*
|
|
3608
|
+
* @param params - Configuration parameters
|
|
3609
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
3610
|
+
* @param params.contractAddress - The contract address containing the tokens
|
|
3611
|
+
* @param params.tokenIds - Array of token IDs to fetch metadata for
|
|
3612
|
+
* @param params.config - Optional SDK configuration (defaults from context)
|
|
3613
|
+
* @param params.query - Optional React Query configuration
|
|
3614
|
+
*
|
|
3615
|
+
* @returns Query result containing an array of token metadata
|
|
3616
|
+
*
|
|
3617
|
+
* @example
|
|
3618
|
+
* Basic usage:
|
|
3619
|
+
* ```typescript
|
|
3620
|
+
* const { data: metadata, isLoading } = useListTokenMetadata({
|
|
3621
|
+
* chainId: 137,
|
|
3622
|
+
* contractAddress: '0x...',
|
|
3623
|
+
* tokenIds: ['1', '2', '3']
|
|
3624
|
+
* })
|
|
3625
|
+
* ```
|
|
3626
|
+
*
|
|
3627
|
+
* @example
|
|
3628
|
+
* With query options:
|
|
3629
|
+
* ```typescript
|
|
3630
|
+
* const { data: metadata } = useListTokenMetadata({
|
|
3631
|
+
* chainId: 1,
|
|
3632
|
+
* contractAddress: '0x...',
|
|
3633
|
+
* tokenIds: selectedTokenIds,
|
|
3634
|
+
* query: {
|
|
3635
|
+
* enabled: selectedTokenIds.length > 0,
|
|
3636
|
+
* staleTime: 10 * 60 * 1000 // 10 minutes
|
|
3637
|
+
* }
|
|
3638
|
+
* })
|
|
3639
|
+
* ```
|
|
3640
|
+
*/
|
|
3641
|
+
function useListTokenMetadata(params) {
|
|
3642
|
+
const defaultConfig = useConfig();
|
|
3643
|
+
const { config = defaultConfig,...rest } = params;
|
|
3644
|
+
const queryOptions$1 = listTokenMetadataQueryOptions({
|
|
3645
|
+
config,
|
|
3646
|
+
...rest
|
|
3647
|
+
});
|
|
3648
|
+
return useQuery({ ...queryOptions$1 });
|
|
3649
|
+
}
|
|
3650
|
+
|
|
3651
|
+
//#endregion
|
|
3652
|
+
//#region src/react/hooks/useLowestListing.tsx
|
|
3653
|
+
/**
|
|
3654
|
+
* Hook to fetch the lowest listing for a collectible
|
|
3655
|
+
*
|
|
3656
|
+
* Retrieves the lowest priced listing currently available for a specific token
|
|
3657
|
+
* in a collection from the marketplace.
|
|
3658
|
+
*
|
|
3659
|
+
* @param params - Configuration parameters
|
|
3660
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
3661
|
+
* @param params.collectionAddress - The collection contract address
|
|
3662
|
+
* @param params.tokenId - The token ID within the collection
|
|
3663
|
+
* @param params.query - Optional React Query configuration
|
|
3664
|
+
*
|
|
3665
|
+
* @returns Query result containing the lowest listing data or null if no listings exist
|
|
3666
|
+
*
|
|
3667
|
+
* @example
|
|
3668
|
+
* Basic usage:
|
|
3669
|
+
* ```typescript
|
|
3670
|
+
* const { data, isLoading } = useLowestListing({
|
|
3671
|
+
* chainId: 137,
|
|
3672
|
+
* collectionAddress: '0x...',
|
|
3673
|
+
* tokenId: '1'
|
|
3674
|
+
* })
|
|
3675
|
+
* ```
|
|
3676
|
+
*
|
|
3677
|
+
* @example
|
|
3678
|
+
* With custom query options:
|
|
3679
|
+
* ```typescript
|
|
3680
|
+
* const { data, isLoading } = useLowestListing({
|
|
3681
|
+
* chainId: 1,
|
|
3682
|
+
* collectionAddress: '0x...',
|
|
3683
|
+
* tokenId: '42',
|
|
3684
|
+
* query: {
|
|
3685
|
+
* refetchInterval: 15000,
|
|
3686
|
+
* enabled: hasTokenId
|
|
3687
|
+
* }
|
|
3688
|
+
* })
|
|
3689
|
+
* ```
|
|
3690
|
+
*/
|
|
3691
|
+
function useLowestListing(params) {
|
|
3692
|
+
const defaultConfig = useConfig();
|
|
3693
|
+
const { config = defaultConfig,...rest } = params;
|
|
3694
|
+
const queryOptions$1 = lowestListingQueryOptions({
|
|
3695
|
+
config,
|
|
3696
|
+
...rest
|
|
3697
|
+
});
|
|
3698
|
+
return useQuery({ ...queryOptions$1 });
|
|
3699
|
+
}
|
|
3700
|
+
|
|
3701
|
+
//#endregion
|
|
3702
|
+
//#region src/react/hooks/useMarketCurrencies.tsx
|
|
3703
|
+
/**
|
|
3704
|
+
* Hook to fetch supported currencies for a marketplace
|
|
3705
|
+
*
|
|
3706
|
+
* Retrieves the list of currencies supported by the marketplace for a specific chain.
|
|
3707
|
+
* Can optionally filter to exclude native currency or filter by collection.
|
|
3708
|
+
*
|
|
3709
|
+
* @param params - Configuration parameters
|
|
3710
|
+
* @param params.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
3711
|
+
* @param params.includeNativeCurrency - Whether to include native currency (default: true)
|
|
3712
|
+
* @param params.collectionAddress - Optional collection address to filter currencies
|
|
3713
|
+
* @param params.query - Optional React Query configuration
|
|
3714
|
+
*
|
|
3715
|
+
* @returns Query result containing supported currencies
|
|
3716
|
+
*
|
|
3717
|
+
* @example
|
|
3718
|
+
* Basic usage:
|
|
3719
|
+
* ```typescript
|
|
3720
|
+
* const { data, isLoading } = useMarketCurrencies({
|
|
3721
|
+
* chainId: 137
|
|
3722
|
+
* })
|
|
3723
|
+
* ```
|
|
3724
|
+
*
|
|
3725
|
+
* @example
|
|
3726
|
+
* Exclude native currency:
|
|
3727
|
+
* ```typescript
|
|
3728
|
+
* const { data, isLoading } = useMarketCurrencies({
|
|
3729
|
+
* chainId: 1,
|
|
3730
|
+
* includeNativeCurrency: false
|
|
3731
|
+
* })
|
|
3732
|
+
* ```
|
|
3733
|
+
*/
|
|
3734
|
+
function useMarketCurrencies(params) {
|
|
3735
|
+
const defaultConfig = useConfig();
|
|
3736
|
+
const { config = defaultConfig,...rest } = params;
|
|
3737
|
+
const queryOptions$1 = marketCurrenciesQueryOptions({
|
|
3738
|
+
config,
|
|
3739
|
+
...rest
|
|
3740
|
+
});
|
|
3741
|
+
return useQuery({ ...queryOptions$1 });
|
|
3742
|
+
}
|
|
3743
|
+
|
|
3744
|
+
//#endregion
|
|
3745
|
+
//#region src/react/hooks/useOpenConnectModal.tsx
|
|
3746
|
+
const useOpenConnectModal$1 = () => {
|
|
3747
|
+
const context = useConfig();
|
|
3748
|
+
return { openConnectModal: context.openConnectModal };
|
|
3749
|
+
};
|
|
3750
|
+
|
|
3751
|
+
//#endregion
|
|
3752
|
+
//#region src/react/hooks/useRoyalty.tsx
|
|
3753
|
+
/**
|
|
3754
|
+
* Hook to fetch royalty information for a collectible
|
|
3755
|
+
*
|
|
3756
|
+
* Reads royalty information from the blockchain using the EIP-2981 standard.
|
|
3757
|
+
* This hook queries the contract directly to get royalty percentage and recipient
|
|
3758
|
+
* address for a specific token.
|
|
3759
|
+
*
|
|
3760
|
+
* @param args - Configuration parameters
|
|
3761
|
+
* @param args.chainId - The chain ID (must be number, e.g., 1 for Ethereum, 137 for Polygon)
|
|
3762
|
+
* @param args.collectionAddress - The collection contract address
|
|
3763
|
+
* @param args.collectibleId - The token ID within the collection
|
|
3764
|
+
* @param args.query - Optional React Query configuration
|
|
3765
|
+
*
|
|
3766
|
+
* @returns Query result containing royalty information (percentage and recipient) or null
|
|
3767
|
+
*
|
|
3768
|
+
* @example
|
|
3769
|
+
* Basic usage:
|
|
3770
|
+
* ```typescript
|
|
3771
|
+
* const { data, isLoading } = useRoyalty({
|
|
3772
|
+
* chainId: 137,
|
|
3773
|
+
* collectionAddress: '0x...',
|
|
3774
|
+
* collectibleId: '1'
|
|
3775
|
+
* })
|
|
3776
|
+
*
|
|
3777
|
+
* if (data) {
|
|
3778
|
+
* console.log('Royalty:', data.percentage, 'Recipient:', data.recipient)
|
|
3779
|
+
* }
|
|
3780
|
+
* ```
|
|
3781
|
+
*
|
|
3782
|
+
* @example
|
|
3783
|
+
* With custom query options:
|
|
3784
|
+
* ```typescript
|
|
3785
|
+
* const { data, isLoading } = useRoyalty({
|
|
3786
|
+
* chainId: 1,
|
|
3787
|
+
* collectionAddress: '0x...',
|
|
3788
|
+
* collectibleId: '42',
|
|
3789
|
+
* query: {
|
|
3790
|
+
* refetchInterval: 60000,
|
|
3791
|
+
* enabled: hasTokenId
|
|
3792
|
+
* }
|
|
3793
|
+
* })
|
|
3794
|
+
* ```
|
|
3795
|
+
*/
|
|
3796
|
+
function useRoyalty(args) {
|
|
3797
|
+
const { chainId, collectionAddress, collectibleId, query } = args;
|
|
3798
|
+
const scopeKey = `${collectableKeys.royaltyPercentage.join(".")}-${chainId}-${collectionAddress}-${collectibleId}`;
|
|
3799
|
+
const contractResult = useReadContract({
|
|
3800
|
+
scopeKey,
|
|
3801
|
+
abi: EIP2981_ABI,
|
|
3802
|
+
address: collectionAddress,
|
|
3803
|
+
functionName: "royaltyInfo",
|
|
3804
|
+
args: [BigInt(collectibleId), BigInt(100)],
|
|
3805
|
+
chainId,
|
|
3806
|
+
query
|
|
3807
|
+
});
|
|
3808
|
+
const [recipient, percentage] = contractResult.data ?? [];
|
|
3809
|
+
const formattedData = recipient && percentage ? {
|
|
3810
|
+
percentage,
|
|
3811
|
+
recipient
|
|
3812
|
+
} : null;
|
|
3813
|
+
return {
|
|
3814
|
+
...contractResult,
|
|
3815
|
+
data: formattedData
|
|
3816
|
+
};
|
|
3817
|
+
}
|
|
3818
|
+
|
|
3819
|
+
//#endregion
|
|
3820
|
+
//#region src/react/hooks/useShopCollectibleSaleData.tsx
|
|
3821
|
+
function useShopCollectibleSaleData({ chainId, salesContractAddress, itemsContractAddress, tokenId, collectionType, enabled = true }) {
|
|
3822
|
+
const { data: erc721SaleDetails, isLoading: erc721SaleLoading, error: erc721SaleError } = useReadContract({
|
|
3823
|
+
chainId,
|
|
3824
|
+
address: salesContractAddress,
|
|
3825
|
+
abi: ERC721_SALE_ABI,
|
|
3826
|
+
functionName: "saleDetails",
|
|
3827
|
+
query: { enabled: enabled && collectionType === ContractType.ERC721 }
|
|
3828
|
+
});
|
|
3829
|
+
const { data: erc721TotalSupply, isLoading: erc721SupplyLoading, error: erc721SupplyError } = useReadContract({
|
|
3830
|
+
chainId,
|
|
3831
|
+
address: itemsContractAddress,
|
|
3832
|
+
abi: ERC721_ABI,
|
|
3833
|
+
functionName: "totalSupply",
|
|
3834
|
+
query: { enabled: enabled && collectionType === ContractType.ERC721 }
|
|
3835
|
+
});
|
|
3836
|
+
const { data: erc1155TokenSaleDetails, isLoading: erc1155TokenSaleLoading, error: erc1155TokenSaleError } = useReadContract({
|
|
3837
|
+
chainId,
|
|
3838
|
+
address: salesContractAddress,
|
|
3839
|
+
abi: ERC1155_SALES_CONTRACT_ABI,
|
|
3840
|
+
functionName: "tokenSaleDetails",
|
|
3841
|
+
args: collectionType === ContractType.ERC1155 ? [BigInt(tokenId)] : void 0,
|
|
3842
|
+
query: { enabled: enabled && collectionType === ContractType.ERC1155 }
|
|
3843
|
+
});
|
|
3844
|
+
const { data: erc1155GlobalSaleDetails, isLoading: erc1155GlobalSaleLoading, error: erc1155GlobalSaleError } = useReadContract({
|
|
3845
|
+
chainId,
|
|
3846
|
+
address: salesContractAddress,
|
|
3847
|
+
abi: ERC1155_SALES_CONTRACT_ABI,
|
|
3848
|
+
functionName: "globalSaleDetails",
|
|
3849
|
+
query: { enabled: enabled && collectionType === ContractType.ERC1155 }
|
|
3850
|
+
});
|
|
3851
|
+
const { data: erc1155PaymentToken, isLoading: erc1155PaymentTokenLoading, error: erc1155PaymentTokenError } = useReadContract({
|
|
3852
|
+
chainId,
|
|
3853
|
+
address: salesContractAddress,
|
|
3854
|
+
abi: ERC1155_SALES_CONTRACT_ABI,
|
|
3855
|
+
functionName: "paymentToken",
|
|
3856
|
+
query: { enabled: enabled && collectionType === ContractType.ERC1155 }
|
|
3857
|
+
});
|
|
3858
|
+
const { data: erc1155TotalSupply, isLoading: erc1155SupplyLoading, error: erc1155SupplyError } = useReadContract({
|
|
3859
|
+
chainId,
|
|
3860
|
+
address: itemsContractAddress,
|
|
3861
|
+
abi: SEQUENCE_1155_ITEMS_ABI,
|
|
3862
|
+
functionName: "totalSupply",
|
|
3863
|
+
query: { enabled: enabled && collectionType === ContractType.ERC1155 }
|
|
3864
|
+
});
|
|
3865
|
+
return useMemo(() => {
|
|
3866
|
+
const isLoading = collectionType === ContractType.ERC721 ? erc721SaleLoading || erc721SupplyLoading : erc1155TokenSaleLoading || erc1155GlobalSaleLoading || erc1155PaymentTokenLoading || erc1155SupplyLoading;
|
|
3867
|
+
const error = collectionType === ContractType.ERC721 ? erc721SaleError || erc721SupplyError : erc1155TokenSaleError || erc1155GlobalSaleError || erc1155PaymentTokenError || erc1155SupplyError;
|
|
3868
|
+
if (isLoading) return {
|
|
3869
|
+
salePrice: null,
|
|
3870
|
+
paymentToken: null,
|
|
3871
|
+
supplyCap: "0",
|
|
3872
|
+
totalMinted: "0",
|
|
3873
|
+
quantityRemaining: "0",
|
|
3874
|
+
startTime: null,
|
|
3875
|
+
endTime: null,
|
|
3876
|
+
isActive: false,
|
|
3877
|
+
isLoading: true,
|
|
3878
|
+
error: null,
|
|
3879
|
+
isAvailable: false
|
|
3880
|
+
};
|
|
3881
|
+
if (error) return {
|
|
3882
|
+
salePrice: null,
|
|
3883
|
+
paymentToken: null,
|
|
3884
|
+
supplyCap: "0",
|
|
3885
|
+
totalMinted: "0",
|
|
3886
|
+
quantityRemaining: "0",
|
|
3887
|
+
startTime: null,
|
|
3888
|
+
endTime: null,
|
|
3889
|
+
isActive: false,
|
|
3890
|
+
isLoading: false,
|
|
3891
|
+
error,
|
|
3892
|
+
isAvailable: false
|
|
3893
|
+
};
|
|
3894
|
+
if (collectionType === ContractType.ERC721 && erc721SaleDetails && erc721TotalSupply !== void 0) {
|
|
3895
|
+
const saleDetails = erc721SaleDetails;
|
|
3896
|
+
const supplyCap = saleDetails.supplyCap.toString();
|
|
3897
|
+
const totalMinted = erc721TotalSupply.toString();
|
|
3898
|
+
const quantityRemaining = (saleDetails.supplyCap - erc721TotalSupply).toString();
|
|
3899
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3900
|
+
const startTime = Number(saleDetails.startTime);
|
|
3901
|
+
const endTime = Number(saleDetails.endTime);
|
|
3902
|
+
const isActive = now >= startTime && now <= endTime;
|
|
3903
|
+
return {
|
|
3904
|
+
salePrice: {
|
|
3905
|
+
amount: saleDetails.cost.toString(),
|
|
3906
|
+
currencyAddress: saleDetails.paymentToken
|
|
3907
|
+
},
|
|
3908
|
+
paymentToken: saleDetails.paymentToken,
|
|
3909
|
+
supplyCap,
|
|
3910
|
+
totalMinted,
|
|
3911
|
+
quantityRemaining,
|
|
3912
|
+
startTime,
|
|
3913
|
+
endTime,
|
|
3914
|
+
isActive,
|
|
3915
|
+
isLoading: false,
|
|
3916
|
+
error: null,
|
|
3917
|
+
isAvailable: BigInt(quantityRemaining) > 0 && isActive
|
|
3918
|
+
};
|
|
3919
|
+
}
|
|
3920
|
+
if (collectionType === ContractType.ERC1155 && erc1155PaymentToken && erc1155TotalSupply !== void 0 && (erc1155TokenSaleDetails || erc1155GlobalSaleDetails)) {
|
|
3921
|
+
const tokenSaleDetails = erc1155TokenSaleDetails;
|
|
3922
|
+
const globalSaleDetails = erc1155GlobalSaleDetails;
|
|
3923
|
+
const useGlobal = tokenSaleDetails && tokenSaleDetails.supplyCap === 0n;
|
|
3924
|
+
const finalSaleDetails = useGlobal ? globalSaleDetails : tokenSaleDetails || globalSaleDetails;
|
|
3925
|
+
if (!finalSaleDetails) return {
|
|
3926
|
+
salePrice: null,
|
|
3927
|
+
paymentToken: null,
|
|
3928
|
+
supplyCap: "0",
|
|
3929
|
+
totalMinted: "0",
|
|
3930
|
+
quantityRemaining: "0",
|
|
3931
|
+
startTime: null,
|
|
3932
|
+
endTime: null,
|
|
3933
|
+
isActive: false,
|
|
3934
|
+
isLoading: false,
|
|
3935
|
+
error: null,
|
|
3936
|
+
isAvailable: false
|
|
3937
|
+
};
|
|
3938
|
+
const supplyCap = finalSaleDetails.supplyCap.toString();
|
|
3939
|
+
const totalMintedBigInt = erc1155TotalSupply ? BigInt(erc1155TotalSupply) : 0n;
|
|
3940
|
+
const totalMinted = totalMintedBigInt.toString();
|
|
3941
|
+
const quantityRemaining = (finalSaleDetails.supplyCap - totalMintedBigInt).toString();
|
|
3942
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3943
|
+
const startTime = Number(finalSaleDetails.startTime);
|
|
3944
|
+
const endTime = Number(finalSaleDetails.endTime);
|
|
3945
|
+
const isActive = now >= startTime && now <= endTime;
|
|
3946
|
+
return {
|
|
3947
|
+
salePrice: {
|
|
3948
|
+
amount: finalSaleDetails.cost.toString(),
|
|
3949
|
+
currencyAddress: erc1155PaymentToken
|
|
3950
|
+
},
|
|
3951
|
+
paymentToken: erc1155PaymentToken,
|
|
3952
|
+
supplyCap,
|
|
3953
|
+
totalMinted,
|
|
3954
|
+
quantityRemaining,
|
|
3955
|
+
startTime,
|
|
3956
|
+
endTime,
|
|
3957
|
+
isActive,
|
|
3958
|
+
isLoading: false,
|
|
3959
|
+
error: null,
|
|
3960
|
+
isAvailable: BigInt(quantityRemaining) > 0 && isActive
|
|
3961
|
+
};
|
|
3962
|
+
}
|
|
3963
|
+
return {
|
|
3964
|
+
salePrice: null,
|
|
3965
|
+
paymentToken: null,
|
|
3966
|
+
supplyCap: "0",
|
|
3967
|
+
totalMinted: "0",
|
|
3968
|
+
quantityRemaining: "0",
|
|
3969
|
+
startTime: null,
|
|
3970
|
+
endTime: null,
|
|
3971
|
+
isActive: false,
|
|
3972
|
+
isLoading: false,
|
|
3973
|
+
error: null,
|
|
3974
|
+
isAvailable: false
|
|
3975
|
+
};
|
|
3976
|
+
}, [
|
|
3977
|
+
collectionType,
|
|
3978
|
+
erc721SaleDetails,
|
|
3979
|
+
erc721TotalSupply,
|
|
3980
|
+
erc721SaleLoading,
|
|
3981
|
+
erc721SupplyLoading,
|
|
3982
|
+
erc721SaleError,
|
|
3983
|
+
erc721SupplyError,
|
|
3984
|
+
erc1155TokenSaleDetails,
|
|
3985
|
+
erc1155GlobalSaleDetails,
|
|
3986
|
+
erc1155PaymentToken,
|
|
3987
|
+
erc1155TotalSupply,
|
|
3988
|
+
erc1155TokenSaleLoading,
|
|
3989
|
+
erc1155GlobalSaleLoading,
|
|
3990
|
+
erc1155PaymentTokenLoading,
|
|
3991
|
+
erc1155SupplyLoading,
|
|
3992
|
+
erc1155TokenSaleError,
|
|
3993
|
+
erc1155GlobalSaleError,
|
|
3994
|
+
erc1155PaymentTokenError,
|
|
3995
|
+
erc1155SupplyError
|
|
3996
|
+
]);
|
|
3997
|
+
}
|
|
3998
|
+
|
|
3999
|
+
//#endregion
|
|
4000
|
+
//#region src/react/hooks/useTransferTokens.tsx
|
|
4001
|
+
const prepareTransferConfig = (params, accountAddress) => {
|
|
4002
|
+
if (params.contractType === "ERC721") return {
|
|
4003
|
+
abi: erc721Abi,
|
|
4004
|
+
address: params.collectionAddress,
|
|
4005
|
+
functionName: "safeTransferFrom",
|
|
4006
|
+
args: [
|
|
4007
|
+
accountAddress,
|
|
4008
|
+
params.receiverAddress,
|
|
4009
|
+
BigInt(params.tokenId)
|
|
4010
|
+
]
|
|
4011
|
+
};
|
|
4012
|
+
return {
|
|
4013
|
+
abi: ERC1155_ABI,
|
|
4014
|
+
address: params.collectionAddress,
|
|
4015
|
+
functionName: "safeTransferFrom",
|
|
4016
|
+
args: [
|
|
4017
|
+
accountAddress,
|
|
4018
|
+
params.receiverAddress,
|
|
4019
|
+
BigInt(params.tokenId),
|
|
4020
|
+
params.quantity,
|
|
4021
|
+
"0x"
|
|
4022
|
+
]
|
|
4023
|
+
};
|
|
4024
|
+
};
|
|
4025
|
+
const useTransferTokens = () => {
|
|
4026
|
+
const { address: accountAddress } = useAccount();
|
|
4027
|
+
const { writeContractAsync, data: hash, isPending, isError, isSuccess } = useWriteContract();
|
|
4028
|
+
const transferTokensAsync = async (params) => {
|
|
4029
|
+
if (!accountAddress) throw new NoWalletConnectedError();
|
|
4030
|
+
const config = prepareTransferConfig(params, accountAddress);
|
|
4031
|
+
return await writeContractAsync(config);
|
|
4032
|
+
};
|
|
4033
|
+
return {
|
|
4034
|
+
transferTokensAsync,
|
|
4035
|
+
hash,
|
|
4036
|
+
transferring: isPending,
|
|
4037
|
+
transferFailed: isError,
|
|
4038
|
+
transferSuccess: isSuccess
|
|
4039
|
+
};
|
|
4040
|
+
};
|
|
4041
|
+
|
|
4042
|
+
//#endregion
|
|
4043
|
+
export { AlertMessage, MODAL_CONTENT_PROPS, MODAL_OVERLAY_PROPS, checkoutOptionsSalesContractQueryOptions, collectionBalanceDetailsQueryOptions, collectionDetailsPollingOptions, collectionQueryOptions, comparePricesQueryOptions, convertPriceToUSDQueryOptions, countListingsForCollectibleQueryOptions, countOfCollectablesQueryOptions, countOffersForCollectibleQueryOptions, dateToUnixTime, filtersQueryOptions, generateCancelTransaction, generateListingTransaction, generateOfferTransaction, generateSellTransaction, getTokenRangesQueryOptions, listCollectibleActivitiesQueryOptions, listCollectiblesPaginatedQueryOptions, listCollectionActivitiesQueryOptions, listListingsForCollectibleQueryOptions, listOffersForCollectibleOptions, sellModal$, switchChainModal_default, useAutoSelectFeeOption, useBalanceOfCollectible, useCancelOrder, useCheckoutOptionsSalesContract, useCollectible, useCollection, useCollectionBalanceDetails, useCollectionDetails, useCollectionDetailsPolling, useComparePrices, useConfig, useConvertPriceToUSD, useCountListingsForCollectible, useCountOfCollectables, useCountOfPrimarySaleItems, useCountOffersForCollectible, useCurrency, useERC721SaleMintedTokens, useFilterState, useFilters, useFiltersProgressive, useFloorOrder, useGenerateCancelTransaction, useGenerateListingTransaction, useGenerateOfferTransaction, useGenerateSellTransaction, useGetCountOfPrimarySaleItems, useGetTokenRanges, useHighestOffer, useInventory, useList1155ShopCardData, useList721ShopCardData, useListBalances, useListCollectibleActivities, useListCollectibles, useListCollectiblesPaginated, useListCollectionActivities, useListCollections, useListListingsForCollectible, useListMarketCardData, useListOffersForCollectible, useListPrimarySaleItems, useListShopCardData, useListTokenMetadata, useLowestListing, useMarketCurrencies, useMarketplaceConfig, useOpenConnectModal$1 as useOpenConnectModal, useRoyalty, useSellModal, useShopCollectibleSaleData, useSwitchChainModal, useTokenSupplies, useTransferTokens, useWallet };
|
|
4044
|
+
//# sourceMappingURL=hooks-4pxIbLbM.js.map
|