Skip to content

Commit

Permalink
Merge pull request #82 from NiftyLeague/features/FE-525_imx-marketpla…
Browse files Browse the repository at this point in the history
…ce-contract-integration

Integrate new marketplace contract with web app
  • Loading branch information
NiftyAndy authored Sep 24, 2024
2 parents dc72bbf + 15632f7 commit 385722d
Show file tree
Hide file tree
Showing 41 changed files with 425 additions and 846 deletions.
1 change: 0 additions & 1 deletion apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"dependencies": {
"@cowprotocol/cow-sdk": "^5.4.1",
"@hookform/resolvers": "^3.9.0",
"@imtbl/imx-sdk": "~3.8.2",
"@mui/x-data-grid": "^7.18.0",
"@nl/imx-passport": "workspace:^",
"@nl/theme": "workspace:^",
Expand Down
4 changes: 2 additions & 2 deletions apps/app/src/app/(private-routes)/dashboard/degens/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from '@/components/extended/DegensFilter/utils';
import RenameDegenDialogContent from '@/app/(private-routes)/dashboard/degens/_dialogs/RenameDegenDialogContent';
import SectionTitle from '@/components/sections/SectionTitle';
import { DEGEN_BASE_API_URL, DEGEN_OPENSEA_URL, PROFILE_FAV_DEGENS_API } from '@/constants/url';
import { DEGEN_BASE_API_URL, DEGEN_COLLECTION_URL, PROFILE_FAV_DEGENS_API } from '@/constants/url';
import { HYDRAS } from '@/constants/hydras';
import { useProfileFavDegens } from '@/hooks/useGamerProfile';
import useFetch from '@/hooks/useFetch';
Expand Down Expand Up @@ -321,7 +321,7 @@ const DashboardDegensPage = (): JSX.Element => {
) : dataForCurrentPage.length ? (
dataForCurrentPage.map(renderDegen)
) : !characters?.length ? (
<Link href={DEGEN_OPENSEA_URL} target="_blank" rel="noreferrer">
<Link href={DEGEN_COLLECTION_URL} target="_blank" rel="noreferrer">
<EmptyState
message="No DEGENs found. Please check your address or go purchase a degen if you have not done so already!"
buttonText="Buy a DEGEN"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import merge from 'lodash/merge';

import { useGamerProfile, useProfileAvatarFee } from '@/hooks/useGamerProfile';
import useFetch from '@/hooks/useFetch';
import useComicsBalance from '@/hooks/useComicsBalance';
import useIMXContext from '@/hooks/useIMXContext';

import SectionSlider from '@/components/sections/SectionSlider';
import ImageProfile from './_ImageProfile';
Expand Down Expand Up @@ -37,7 +37,7 @@ const GamerProfile = (): JSX.Element => {
const { profile, error, loadingProfile } = useGamerProfile();
const { address } = useAccount();
const { avatarsAndFee } = useProfileAvatarFee();
const { comicsBalance, loading: loadingComics } = useComicsBalance();
const { comicsBalance, comicsLoading } = useIMXContext();
const { data } = useFetch<Degen[]>(`${DEGEN_BASE_API_URL}/cache/rentals/rentables.json`);

const { loadingDegens, characters, characterCount: degenCount } = useBalances();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import sum from 'lodash/sum';
import { ImageList, ImageListItem, ImageListItemBar, Skeleton, TextField, InputAdornment } from '@mui/material';
import BurnIcon from '@mui/icons-material/Whatshot';

import useComicsBalance from '@/hooks/useComicsBalance';
import type { Comic } from '@/types/comic';
import useIMXContext from '@/hooks/useIMXContext';
import type { Comic } from '@/types/marketplace';

const PREFIX = 'comics-grid';

Expand Down Expand Up @@ -82,7 +82,7 @@ export default function ComicsGrid({
setSelectedComics: React.Dispatch<React.SetStateAction<Comic[]>>;
refreshKey: number;
}) {
const { comicsBalance, loading: loadingComics } = useComicsBalance(refreshKey);
const { comicsBalance, comicsLoading } = useIMXContext();
const keyCount = useMemo(() => (burnCount.some(v => v === 0) ? 0 : Math.min(...burnCount)), [burnCount]);
const itemCount = useMemo(() => sum(burnCount) - keyCount * 6, [burnCount, keyCount]);

Expand Down Expand Up @@ -111,7 +111,7 @@ export default function ComicsGrid({
handleUpdateBurnCount(comic, newSelectedComics);
};

return loadingComics ? (
return comicsLoading ? (
<Skeleton variant="rectangular" animation="wave" width={315} height={265} sx={{ ...gridStyles }} />
) : (
<Root>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useContext } from 'react';
import { styled } from '@nl/theme';
import Image from 'next/image';
import { ImageList, ImageListItem, ImageListItemBar, Skeleton } from '@mui/material';

import IMXContext from '@/contexts/IMXContext';
import useIMXContext from '@/hooks/useIMXContext';

const PREFIX = 'items-grid';

Expand Down Expand Up @@ -50,9 +49,9 @@ const gridStyles = {
};

export default function ItemsGrid({ itemCounts }: { itemCounts: number[] }) {
const imx = useContext(IMXContext);
const { itemsLoading } = useIMXContext();

return imx.loading ? (
return itemsLoading ? (
<Skeleton variant="rectangular" animation="wave" width={315} height={403} sx={{ ...containerStyles }} />
) : (
<Root style={containerStyles}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
'use client';

import { memo, useContext, useState } from 'react';
import { memo, useState } from 'react';
import useInterval from '@/hooks/useInterval';
import IMXContext, { Context } from '@/contexts/IMXContext';
import useIMXContext from '@/hooks/useIMXContext';
import MachineFrame from './machine-frame';
import type { Comic } from '@/types/comic';
import type { Comic } from '@/types/marketplace';

const ComicsBurnerMachine: React.FC<
React.PropsWithChildren<
React.PropsWithChildren<{
address?: `0x${string}`;
burnDisabled: boolean;
imx: Context;
selectedComics: Comic[];
}>
>
> = memo(({ burnDisabled, imx, selectedComics }) => {
> = memo(({ address, burnDisabled, selectedComics }) => {
const [count, setCount] = useState<number>(0);

useInterval(() => {
Expand All @@ -25,7 +25,7 @@ const ComicsBurnerMachine: React.FC<
<>
<MachineFrame frames={['/img/comics/burner/machine/machine_main_3.webp']} />
<MachineFrame frames={['/img/comics/burner/machine/fx_combined_02.gif']} />
{!imx.registeredUser ? (
{!address ? (
<MachineFrame
frames={[
'/img/comics/burner/machine/button_connectwallet_01.webp',
Expand All @@ -48,13 +48,11 @@ const ComicsBurnerMachine: React.FC<
/>
) : (
<>
{!imx.registeredUser ? (
<MachineFrame frames={['/img/comics/burner/machine/connectwalletabove_button_01.webp']} />
) : null}
{!address ? <MachineFrame frames={['/img/comics/burner/machine/connectwalletabove_button_01.webp']} /> : null}
{selectedComics.length < 1 ? (
<MachineFrame frames={['/img/comics/burner/machine/selectcomics_button_02.webp']} />
) : null}
{imx.registeredUser && selectedComics.length > 1 ? (
{address && selectedComics.length > 1 ? (
<MachineFrame frames={['/img/comics/burner/machine/button_burn_gray_01.webp']} />
) : null}
</>
Expand All @@ -74,8 +72,8 @@ const ComicsBurnerMachineWithContext = ({
burnDisabled: boolean;
selectedComics: Comic[];
}) => {
const imx = useContext(IMXContext);
return <ComicsBurnerMachine imx={imx} burnDisabled={burnDisabled} selectedComics={selectedComics} />;
const { address } = useIMXContext();
return <ComicsBurnerMachine address={address} burnDisabled={burnDisabled} selectedComics={selectedComics} />;
};

export default ComicsBurnerMachineWithContext;
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { memo, useContext } from 'react';
import IMXContext, { Context } from '@/contexts/IMXContext';
import { memo } from 'react';
import SatoshiFrame from './satoshi-frame';
import SatoshiBurnAnim from './satoshi-burn-animations';

const SatoshiAnimations: React.FC<
React.PropsWithChildren<React.PropsWithChildren<{ burning: boolean; imx: Context }>>
> = memo(({ burning, imx }) => {
return <>{burning ? <SatoshiBurnAnim /> : <SatoshiFrame frames={['/img/comics/burner/idleanim.gif']} />}</>;
});
const SatoshiAnimations: React.FC<React.PropsWithChildren<React.PropsWithChildren<{ burning: boolean }>>> = memo(
({ burning }) => {
return <>{burning ? <SatoshiBurnAnim /> : <SatoshiFrame frames={['/img/comics/burner/idleanim.gif']} />}</>;
},
);

const SatoshiAnimationsWithContext = ({ burning = false }) => {
const imx = useContext(IMXContext);
return <SatoshiAnimations burning={burning} imx={imx} />;
return <SatoshiAnimations burning={burning} />;
};

SatoshiAnimations.displayName = 'SatoshiAnimations';
Expand Down
30 changes: 16 additions & 14 deletions apps/app/src/app/(private-routes)/dashboard/items/burner/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
'use client';

import { useCallback, useContext, useEffect, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import { Button } from '@mui/material';

import { type AddressLike } from 'ethers6';
import IMXContext from '@/contexts/IMXContext';
import useIMXContext from '@/hooks/useIMXContext';
import useNetworkContext from '@/hooks/useNetworkContext';
import { COMICS_BURNER_CONTRACT, COMICS_CONTRACT } from '@/constants/contracts';
import { COMICS_BURNER_CONTRACT, MARKETPLACE_CONTRACT } from '@/constants/contracts';
import { DEBUG } from '@/constants/index';
import type { Comic } from '@/types/comic';
import type { Comic } from '@/types/marketplace';

import Machine from './_components/machine';
import MachineButton from './_components/machine-button';
Expand All @@ -18,9 +18,11 @@ import ComicsGrid from './_components/comics-grid';
import SatoshiAnimations from './_components/satoshi-animations';
import ItemsGrid from './_components/items-grid';

// TODO: Config Signer for MARKETPLACE_CONTRACT or add to writeContracts

const ComicsBurner = () => {
const router = useRouter();
const imx = useContext(IMXContext);
const { itemsBalance } = useIMXContext();
const { address, tx, writeContracts } = useNetworkContext();
const [isApprovedForAll, setIsApprovedForAll] = useState(false);
const [helpDialogOpen, setHelpDialogOpen] = useState(false);
Expand All @@ -29,23 +31,23 @@ const ComicsBurner = () => {
const [burnCount, setBurnCount] = useState([0, 0, 0, 0, 0, 0]);
const [burning, setBurning] = useState(false);
const [refreshKey, setRefreshKey] = useState(0);
const burnDisabled = !imx.registeredUser || burning || selectedComics.length < 1 || burnCount.every(c => !c);
const burnDisabled = burning || selectedComics.length < 1 || burnCount.every(c => !c);

useEffect(() => {
if (imx.itemsBalance) {
setItemsCounts(imx.itemsBalance.map(it => it.balance || 0));
if (itemsBalance.length) {
setItemsCounts(itemsBalance.map(it => it.balance || 0));
}
}, [imx.itemsBalance]);
}, [itemsBalance]);

useEffect(() => {
const getAllowance = async () => {
const burnContract = writeContracts[COMICS_BURNER_CONTRACT];
const burnContractAddress = await burnContract.getAddress();
const comicsContract = writeContracts[COMICS_CONTRACT];
const comicsContract = writeContracts[MARKETPLACE_CONTRACT];
const approved = (await comicsContract.isApprovedForAll(address as AddressLike, burnContractAddress)) as boolean;
setIsApprovedForAll(approved);
};
if (writeContracts && writeContracts[COMICS_BURNER_CONTRACT] && writeContracts[COMICS_CONTRACT]) {
if (writeContracts && writeContracts[COMICS_BURNER_CONTRACT] && writeContracts[MARKETPLACE_CONTRACT]) {
// eslint-disable-next-line no-void
void getAllowance();
}
Expand All @@ -55,7 +57,7 @@ const ComicsBurner = () => {
const burnContract = writeContracts[COMICS_BURNER_CONTRACT];
if (!isApprovedForAll) {
const burnContractAddress = await burnContract.getAddress();
const comicsContract = writeContracts[COMICS_CONTRACT];
const comicsContract = writeContracts[MARKETPLACE_CONTRACT];
await tx(comicsContract.setApprovalForAll(burnContractAddress, true));
}
}, [isApprovedForAll, tx, writeContracts]);
Expand Down Expand Up @@ -93,15 +95,15 @@ const ComicsBurner = () => {
← Back to Comics &amp; Items
</Button>
<Machine burnDisabled={burnDisabled} selectedComics={selectedComics} />
<MachineButton
{/* <MachineButton
disabled={imx.registeredUser}
height={25}
name="Connect Wallet"
onClick={imx.linkSetup}
width={135}
top={45}
left={-200}
/>
/> */}
<HelpDialog open={helpDialogOpen} setOpen={setHelpDialogOpen} />
<MachineButton
height={20}
Expand Down
71 changes: 35 additions & 36 deletions apps/app/src/app/(private-routes)/dashboard/items/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useContext, useMemo, useState } from 'react';
import { useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { v4 as uuidv4 } from 'uuid';
Expand All @@ -11,11 +11,9 @@ import ComicCard from '@/components/cards/ComicCard';
import ViewComicDialog from '@/components/dialog/ViewComicDialog';
import SectionSlider from '@/components/sections/SectionSlider';

import IMXContext from '@/contexts/IMXContext';
import useNetworkContext from '@/hooks/useNetworkContext';
import type { Comic, Item } from '@/types/comic';
import useComicsBalance from '@/hooks/useComicsBalance';
import { COMICS_OPENSEA_URL, ITEM_PURCHASE_URL } from '@/constants/url';
import useIMXContext from '@/hooks/useIMXContext';
import type { Comic, Item } from '@/types/marketplace';
import { COMICS_PURCHASE_URL, ITEM_PURCHASE_URL } from '@/constants/url';
import ComicDetail from '@/components/cards/ComicDetail';
import ComicPlaceholder from '@/components/cards/Skeleton/ComicPlaceholder';
import BuyCard from '@/components/cards/BuyCard';
Expand All @@ -28,10 +26,8 @@ const DashboardComicsPage = (): JSX.Element => {
const [selectedComic, setSelectedComic] = useState<Comic | null>(null);
const [selectedItem, setSelectedItem] = useState<Item | null>(null);
const [selectedSubIndex, setSelectedSubIndex] = useState<number>(-1);
const { comicsBalance, loading: loadingComics } = useComicsBalance();
const { comicsBalance, comicsLoading, itemsBalance, itemsLoading } = useIMXContext();
const router = useRouter();
const imx = useContext(IMXContext);
const { selectedNetworkId } = useNetworkContext();
const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down('md'));

Expand Down Expand Up @@ -72,14 +68,12 @@ const DashboardComicsPage = (): JSX.Element => {
const handleLaunchBurner = () => router.push('items/burner');

const renderComics = useMemo(() => {
if (comicsBalance.length === 0 && loadingComics) {
if (loadingComics) {
return [...Array(6)].map(() => (
<Grid2 key={uuidv4()}>
<ComicPlaceholder />
</Grid2>
));
}
if (comicsBalance.length === 0 && comicsLoading) {
return [...Array(6)].map(() => (
<Grid2 key={uuidv4()}>
<ComicPlaceholder />
</Grid2>
));
} else if (comicsBalance.length > 0) {
return comicsBalance.map(comic => (
<Grid2 key={comic.id}>
Expand All @@ -92,22 +86,31 @@ const DashboardComicsPage = (): JSX.Element => {
));
}
return null;
}, [comicsBalance, loadingComics, selectedComic]);
}, [comicsBalance, comicsLoading, selectedComic]);

const renderItems = useMemo(() => {
return imx.itemsBalance
.filter(item => !selectedItem?.balance || selectedItem?.balance <= 1 || item.id !== selectedItem?.id)
.map(item => (
<Grid2 key={item.id}>
<WearableItemCard
data={item}
onViewItem={() => handleViewItem(item)}
isSelected={item.id === selectedItem?.id}
/>
if (itemsBalance.length === 0 && itemsLoading) {
return [...Array(6)].map(() => (
<Grid2 key={uuidv4()}>
<ComicPlaceholder />
</Grid2>
));
} else if (itemsBalance.length > 0) {
return itemsBalance
.filter(item => !selectedItem?.balance || selectedItem?.balance <= 1 || item.id !== selectedItem?.id)
.map(item => (
<Grid2 key={item.id}>
<WearableItemCard
data={item}
onViewItem={() => handleViewItem(item)}
isSelected={item.id === selectedItem?.id}
/>
</Grid2>
));
}
return null;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedItem, imx.itemsBalance]);
}, [itemsBalance, itemsLoading, selectedItem]);

const renderSubItems = useMemo(() => {
if (!selectedItem?.balance || selectedItem?.balance <= 1) return null;
Expand Down Expand Up @@ -158,7 +161,7 @@ const DashboardComicsPage = (): JSX.Element => {
{renderComics}
{comicsBalance.length > 0 && (
<Grid2>
<Link href={COMICS_OPENSEA_URL} target="_blank" rel="noreferrer">
<Link href={COMICS_PURCHASE_URL} target="_blank" rel="noreferrer">
<BuyCard
onBuy={() => {}}
isNew={!comicsBalance.some(comic => comic.balance && comic.balance > 0)}
Expand Down Expand Up @@ -207,14 +210,10 @@ const DashboardComicsPage = (): JSX.Element => {
)}
<Grid2 container flexWrap="wrap" gap={2} justifyContent={{ xs: 'space-between', sm: 'inherit' }}>
{renderItems}
{imx.itemsBalance.length > 0 && (
{itemsBalance.length > 0 && (
<Grid2>
<Link
href={ITEM_PURCHASE_URL[selectedNetworkId as keyof typeof ITEM_PURCHASE_URL]}
target="_blank"
rel="noreferrer"
>
<BuyCard onBuy={() => {}} isNew={!imx.itemsBalance.some(it => it.balance && it.balance > 0)} />
<Link href={ITEM_PURCHASE_URL} target="_blank" rel="noreferrer">
<BuyCard onBuy={() => {}} isNew={!itemsBalance.some(it => it.balance && it.balance > 0)} />
</Link>
</Grid2>
)}
Expand Down
Loading

0 comments on commit 385722d

Please sign in to comment.