Skip to content

Commit

Permalink
Merge pull request #1367 from Itheum/stg
Browse files Browse the repository at this point in the history
1.15.0 STG -> MAIN
  • Loading branch information
damienen authored May 10, 2024
2 parents fd58357 + df959b3 commit 3d61d57
Show file tree
Hide file tree
Showing 40 changed files with 1,113 additions and 250 deletions.
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
{
"name": "data-dex",
"version": "1.14.6",
"version": "1.15.1",
"description": "The Itheum Data DEX enables you to trade your data using web3 tech",
"dependencies": {
"@chakra-ui/icons": "2.1.1",
"@chakra-ui/react": "2.8.2",
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.0",
"@emotion/styled": "11.11.5",
"@hookform/resolvers": "3.3.4",
"@itheum/sdk-mx-data-nft": "3.4.0",
"@itheum/sdk-mx-enterprise": "0.2.0",
"@multiversx/sdk-core": "12.19.0",
"@multiversx/sdk-dapp": "2.28.8",
"@multiversx/sdk-native-auth-client": "1.0.7",
"@multiversx/sdk-network-providers": "2.3.0",
"@itheum/sdk-mx-enterprise": "0.3.0",
"@multiversx/sdk-core": "13.0.1",
"@multiversx/sdk-dapp": "2.31.3",
"@multiversx/sdk-native-auth-client": "1.0.8",
"@multiversx/sdk-network-providers": "2.4.3",
"@peerme/sdk": "0.2.1",
"@sentry/react": "7.103.0",
"@tanstack/match-sorter-utils": "8.11.8",
"@tanstack/react-table": "8.13.2",
"axios": "1.6.7",
"@sentry/react": "7.110.1",
"@tanstack/match-sorter-utils": "8.15.1",
"@tanstack/react-table": "8.16.0",
"axios": "1.6.8",
"bignumber.js": "9.1.2",
"dotenv": "16.4.5",
"framer-motion": "11.0.6",
"framer-motion": "11.1.3",
"mime": "4.0.1",
"moment": "2.30.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "7.50.1",
"react-icons": "5.0.1",
"react-router-dom": "6.22.2",
"react-hook-form": "7.51.3",
"react-icons": "5.1.0",
"react-router-dom": "6.22.3",
"web-vitals": "3.5.2",
"yup": "1.3.3",
"zustand": "4.5.1"
"yup": "1.4.0",
"zustand": "4.5.2"
},
"scripts": {
"start": "vite dev",
Expand Down
4 changes: 2 additions & 2 deletions src/components/Faucet/Faucet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Address } from "@multiversx/sdk-core/out";
import { useGetNetworkConfig } from "@multiversx/sdk-dapp/hooks";
import { useGetAccountInfo } from "@multiversx/sdk-dapp/hooks/account";
import { useGetPendingTransactions } from "@multiversx/sdk-dapp/hooks/transactions";
import { CHAIN_TOKEN_SYMBOL } from "libs/config";
import { CHAIN_TOKEN_SYMBOL, IS_DEVNET } from "libs/config";
import { FaucetContract } from "libs/MultiversX/faucet";

const Faucet = ({ tileBoxW, tileBoxH }: any) => {
Expand All @@ -18,7 +18,7 @@ const Faucet = ({ tileBoxW, tileBoxH }: any) => {
useEffect(() => {
// hasPendingTransactions will fire with false during init and then move from true to false each time a TX is done...
// ... so if it's 'false' we need check and prevent faucet from being used too often
if (chainID === "D" && mxAddress && mxFaucetContract && !hasPendingTransactions) {
if (IS_DEVNET && mxAddress && mxFaucetContract && !hasPendingTransactions) {
mxFaucetContract.getFaucetTime(new Address(mxAddress)).then((lastUsedTime) => {
const timeNow = new Date().getTime();

Expand Down
56 changes: 35 additions & 21 deletions src/components/ImageSlider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import { ArrowBackIcon, ArrowForwardIcon } from "@chakra-ui/icons";
import { Box, Container, Flex, IconButton, Image, Text } from "@chakra-ui/react";
import { Box, Container, Flex, IconButton, Image, AspectRatio, Text } from "@chakra-ui/react";
import { motion } from "framer-motion";
import { DEFAULT_NFT_IMAGE } from "libs/mxConstants";
import Card3DAnimation from "./Card3DAnimation";
Expand Down Expand Up @@ -70,16 +70,24 @@ const ImageSlider: React.FC<ImageSliderProps> = (props) => {
backfaceVisibility: "hidden",
position: "absolute",
}}>
<Image
w={imageWidth}
h={imageHeight}
borderRadius={"32px"}
src={imageUrls[imageIndex]}
onLoad={onLoad}
onError={({ currentTarget }) => {
currentTarget.src = DEFAULT_NFT_IMAGE;
}}
/>
{imageUrls[nextImageIndex].includes("mp4") ? (
<Box width={imageWidth} height={imageHeight} as="div" borderRadius={"32px"} overflow={"hidden"}>
<Box as="div" width={"420px"} height={"420px"} ml={"-92px"}>
<video width={"420px"} height={"420px"} src={imageUrls[nextImageIndex]} autoPlay loop muted></video>
</Box>{" "}
</Box>
) : (
<Image
w={imageWidth}
h={imageHeight}
borderRadius={"32px"}
src={imageUrls[imageIndex]}
onLoad={onLoad}
onError={({ currentTarget }) => {
currentTarget.src = DEFAULT_NFT_IMAGE;
}}
/>
)}
</motion.div>
{makeFlip && (
<motion.div
Expand All @@ -98,16 +106,22 @@ const ImageSlider: React.FC<ImageSliderProps> = (props) => {
onAnimationComplete={() => {
setImageIndex(nextImageIndex);
}}>
<Image
w={imageWidth}
h={imageHeight}
borderRadius={"32px"}
src={imageUrls[nextImageIndex]}
onLoad={onLoad}
onError={({ currentTarget }) => {
currentTarget.src = DEFAULT_NFT_IMAGE;
}}
/>
{imageUrls[nextImageIndex].includes("mp4") ? (
<AspectRatio w={imageWidth} h={imageHeight} borderRadius={"32px"} onLoad={onLoad}>
<iframe title="Data Nft Video" src={imageUrls[nextImageIndex]} />
</AspectRatio>
) : (
<Image
w={imageWidth}
h={imageHeight}
borderRadius={"32px"}
src={imageUrls[nextImageIndex]}
onLoad={onLoad}
onError={({ currentTarget }) => {
currentTarget.src = DEFAULT_NFT_IMAGE;
}}
/>
)}
</motion.div>
)}
</div>
Expand Down
10 changes: 7 additions & 3 deletions src/components/ListDataNFTModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export type ListModalProps = {
marketContract: DataNftMarketContract;
amount: number;
setAmount: (amount: number) => void;
maxPerAddress: number;
};

export default function ListDataNFTModal({ isOpen, onClose, sellerFee, nftData, offer, marketContract, amount, setAmount }: ListModalProps) {
export default function ListDataNFTModal({ isOpen, onClose, sellerFee, nftData, offer, marketContract, amount, setAmount, maxPerAddress }: ListModalProps) {
const { chainID } = useGetNetworkConfig();
const { address } = useGetAccountInfo();
const { hasPendingTransactions } = useGetPendingTransactions();
Expand Down Expand Up @@ -105,7 +106,8 @@ export default function ListDataNFTModal({ isOpen, onClose, sellerFee, nftData,
(Number(offer.wantedTokenAmount) + (Number(offer.wantedTokenAmount) * (marketRequirements.buyerTaxPercentage ?? 200)) / 10000) * Number(10 ** 18)
).toString(),
quantity = amount * 1,
owner = address
owner = address,
maxQuantityPerAddress = maxPerAddress
) {
const indexResponse = await axios.get(
`https://${getApi(chainID)}/accounts/${contractsForChain(chainID).market}/transactions?hashes=${txHash}&status=success&withScResults=true&withLogs=true`
Expand Down Expand Up @@ -148,6 +150,7 @@ export default function ListDataNFTModal({ isOpen, onClose, sellerFee, nftData,
wantedTokenAmount,
quantity,
owner,
maxQuantityPerAddress,
};

const response = await fetch(`${backendUrl}/addOffer`, {
Expand Down Expand Up @@ -198,7 +201,7 @@ export default function ListDataNFTModal({ isOpen, onClose, sellerFee, nftData,
}
}

const { sessionId } = await marketContract.addToMarket(nftData.collection, nftData.nonce, amount, offer.wantedTokenAmount ?? 0, address);
const { sessionId } = await marketContract.addToMarket(nftData.collection, nftData.nonce, amount, offer.wantedTokenAmount ?? 0, address, maxPerAddress);
if (isWebWallet) {
const price = Number(offer.wantedTokenAmount) + (Number(offer.wantedTokenAmount) * (marketRequirements.buyerTaxPercentage ?? 200)) / 10000;
sessionStorage.setItem(
Expand All @@ -215,6 +218,7 @@ export default function ListDataNFTModal({ isOpen, onClose, sellerFee, nftData,
wantedTokenAmount: Number(price * Number(10 ** 18)).toString(),
quantity: amount * 1,
owner: address,
maxQuantityPerAddress: maxPerAddress,
})
);
}
Expand Down
18 changes: 11 additions & 7 deletions src/components/MarketplaceLowerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { useGetPendingTransactions } from "@multiversx/sdk-dapp/hooks/transactio
import ProcureDataNFTModal from "components/ProcureDataNFTModal";
import ExploreAppButton from "components/UtilComps/ExploreAppButton";
import { ExtendedOffer } from "libs/types";
import { isValidNumericCharacter } from "libs/utils";
import { computeMaxBuyForOfferForAddress, isValidNumericCharacter } from "libs/utils";
import { useMarketStore } from "store";
import { LivelinessScore } from "./Liveliness/LivelinessScore";
import PreviewDataButton from "./PreviewDataButton";
Expand All @@ -38,8 +38,11 @@ const MarketplaceLowerCard: FC<MarketplaceLowerCardProps> = ({ extendedOffer: of
const [amountError, setAmountError] = useState<string>("");
const { isOpen: isProcureModalOpen, onOpen: onProcureModalOpen, onClose: onProcureModalClose } = useDisclosure();
const isMyNft = offer.owner === address;
const maxBuyLimit = import.meta.env.VITE_MAX_BUY_LIMIT_PER_SFT ? Number(import.meta.env.VITE_MAX_BUY_LIMIT_PER_SFT) : 0;
const maxBuyNumber = maxBuyLimit > 0 ? Math.min(maxBuyLimit, offer.quantity) : offer.quantity;
const maxBuyPerTransaction = import.meta.env.VITE_MAX_BUY_LIMIT_PER_SFT ? Number(import.meta.env.VITE_MAX_BUY_LIMIT_PER_SFT) : 0;
const maxBuyPerAddress = offer ? offer.maxQuantityPerAddress : 0;
const boughtByAddressAlreadyForThisOffer =
useMarketStore((state) => state.addressBoughtOffers).find((boughtOffer) => boughtOffer.offerId === offer.index)?.quantity ?? 0;
const maxBuyForOfferForAddress = computeMaxBuyForOfferForAddress(offer, maxBuyPerTransaction, maxBuyPerAddress, boughtByAddressAlreadyForThisOffer);

return (
<>
Expand All @@ -63,7 +66,7 @@ const MarketplaceLowerCard: FC<MarketplaceLowerCardProps> = ({ extendedOffer: of
maxW="24"
step={1}
min={1}
max={maxBuyNumber}
max={maxBuyForOfferForAddress}
isValidCharacter={isValidNumericCharacter}
value={amount}
defaultValue={1}
Expand All @@ -74,10 +77,11 @@ const MarketplaceLowerCard: FC<MarketplaceLowerCardProps> = ({ extendedOffer: of
error = "Cannot be zero or negative";
} else if (value > offer.quantity) {
error = "Cannot exceed listed amount";
} else if (maxBuyLimit > 0 && value > maxBuyLimit) {
error = "Cannot exceed max buy limit";
} else if (maxBuyPerTransaction > 0 && value > maxBuyPerTransaction) {
error = "Cannot exceed max buy limit per tx";
} else if (maxBuyPerAddress > 0 && value > maxBuyPerAddress) {
error = "Cannot exceed max buy limit per address";
}

setAmountError(error);
setAmount(value);
}}>
Expand Down
65 changes: 11 additions & 54 deletions src/components/MyListedDataLowerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import { useGetNetworkConfig } from "@multiversx/sdk-dapp/hooks";
import { useGetAccountInfo, useGetLoginInfo } from "@multiversx/sdk-dapp/hooks/account";
import { useGetPendingTransactions, useGetSignedTransactions, useTrackTransactionStatus } from "@multiversx/sdk-dapp/hooks/transactions";
import BigNumber from "bignumber.js";
import { PREVIEW_DATA_ON_DEVNET_SESSION_KEY, contractsForChain } from "libs/config";
import { useLocalStorage } from "libs/hooks";
import { contractsForChain } from "libs/config";
import { updateOfferSupplyOnBackend, updatePriceOnBackend } from "libs/MultiversX";
import { DataNftMarketContract } from "libs/MultiversX/dataNftMarket";
import {
convertToLocalString,
Expand Down Expand Up @@ -90,11 +90,14 @@ const MyListedDataLowerCard: FC<MyListedDataLowerCardProps> = ({ offer, nftMetad
const { type } = JSON.parse(sessionInfo);
if (type == "delist-tx") {
const { index, amount } = JSON.parse(sessionInfo);
updateOfferOnBackend(index, amount);
updateOfferSupplyOnBackend(chainID, tokenLogin?.nativeAuthToken ?? "", index, amount);
sessionStorage.removeItem("web-wallet-tx");
} else if (type == "update-price-tx") {
const { index, price } = JSON.parse(sessionInfo);
updatePriceOnBackend(index, price);

const newPrice = price + (price * (marketRequirements.buyerTaxPercentage ?? 200)) / 10000;
const formattedPrice = convertEsdtToWei(newPrice, tokenDecimals(offer.wantedTokenIdentifier)).toFixed();
updatePriceOnBackend(chainID, tokenLogin?.nativeAuthToken ?? "", index, formattedPrice);
sessionStorage.removeItem("web-wallet-tx");
}
}
Expand All @@ -121,64 +124,18 @@ const MyListedDataLowerCard: FC<MyListedDataLowerCardProps> = ({ offer, nftMetad

useEffect(() => {
if (updatePriceTxStatus && !isWebWallet) {
updatePriceOnBackend();
const price = newListingPrice + (newListingPrice * (marketRequirements.buyerTaxPercentage ?? 200)) / 10000;
const formattedPrice = convertEsdtToWei(price, tokenDecimals(offer.wantedTokenIdentifier)).toFixed();
updatePriceOnBackend(chainID, tokenLogin?.nativeAuthToken ?? "", offer.index, formattedPrice);
}
}, [updatePriceTxStatus]);

async function updatePriceOnBackend(index = offer.index, newPrice = newListingPrice) {
try {
const headers = {
Authorization: `Bearer ${tokenLogin?.nativeAuthToken}`,
"Content-Type": "application/json",
};

const price = newPrice + (newPrice * (marketRequirements.buyerTaxPercentage ?? 200)) / 10000;

const requestBody = { price: convertEsdtToWei(price, tokenDecimals(offer.wantedTokenIdentifier)).toFixed() };
const response = await fetch(`${backendUrl}/updateOffer/${index}`, {
method: "POST",
headers: headers,
body: JSON.stringify(requestBody),
});

if (response.ok) {
console.log("Response:", response.ok);
}
} catch (error) {
console.log("Error:", error);
}
}

async function updateOfferOnBackend(index = offer.index, supply = delistAmount) {
try {
const headers = {
Authorization: `Bearer ${tokenLogin?.nativeAuthToken}`,
"Content-Type": "application/json",
};

const requestBody = { supply: supply };
const response = await fetch(`${backendApi(chainID)}/updateOffer/${index}`, {
method: "POST",
headers: headers,
body: JSON.stringify(requestBody),
});

if (response.ok) {
console.log("Response:", response.ok);
}
} catch (error) {
console.log("Error:", error);
}
}

useEffect(() => {
if (delistTxStatus && !isWebWallet) {
updateOfferOnBackend();
updateOfferSupplyOnBackend(chainID, tokenLogin?.nativeAuthToken ?? "", offer.index, delistAmount);
}
}, [delistTxStatus]);

const [previewDataOnDevnetSession] = useLocalStorage(PREVIEW_DATA_ON_DEVNET_SESSION_KEY, null);

const fee =
marketRequirements && offer
? convertWeiToEsdt(
Expand Down
4 changes: 2 additions & 2 deletions src/components/MyListedDataNFT.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const MyListedDataNFT: FC<MyListedDataNFTProps> = (props) => {

const marketRequirements = useMarketStore((state) => state.marketRequirements);
const userData = useMintStore((state) => state.userData);

const nftParsedCreationTime = moment(nftMetadata[index].creationTime);
return (
<Skeleton isLoaded={nftMetadataLoading}>
<Flex wrap="wrap" gap="5" key={index}>
Expand Down Expand Up @@ -161,7 +161,7 @@ const MyListedDataNFT: FC<MyListedDataNFTProps> = (props) => {
</Flex>

<Box display="flex" justifyContent="flex-start" mt="2">
<Text fontSize="xs">{`Creation time: ${moment(nftMetadata[index].creationTime).format(uxConfig.dateStr)}`}</Text>
{nftParsedCreationTime.isValid() && <Text fontSize="xs">{`Creation time: ${nftParsedCreationTime.format(uxConfig.dateStr)}`}</Text>}
</Box>

<Box color="gray.600" fontSize="sm">
Expand Down
Loading

0 comments on commit 3d61d57

Please sign in to comment.