utils#formatNumber JavaScript Examples
The following examples show how to use
utils#formatNumber.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.jsx From Artion-Client with GNU General Public License v3.0 | 6 votes |
OwnersModal = ({ visible, onClose, holders }) => {
return (
<Modal visible={visible} title="Owned by" onClose={onClose}>
{holders.map((holder, idx) => (
<Holder key={idx} holder={holder}>
<div className={styles.holderInfo}>
<div className={styles.avatarWrapper}>
{holder.imageHash ? (
<img
src={`https://cloudflare-ipfs.com/ipfs/${holder.imageHash}`}
width={40}
height={40}
/>
) : (
<Identicon
account={holder.address}
size={40}
className={styles.avatar}
/>
)}
</div>
<div className={styles.info}>
<div className={styles.alias}>{holder.alias || 'Unnamed'}</div>
<div className={styles.address}>
{shortenAddress(holder.address)}
</div>
</div>
</div>
<div className={styles.holdCount}>
{`${formatNumber(holder.supply)} item${
holder.supply !== 1 ? 's' : ''
}`}
</div>
</Holder>
))}
</Modal>
);
}
Example #2
Source File: index.jsx From Artion-Client with GNU General Public License v3.0 | 4 votes |
AuctionModal = ({
visible,
onClose,
onStartAuction,
auction,
auctionStarted,
confirming,
approveContract,
contractApproving,
contractApproved,
}) => {
const { tokens } = useTokens();
const { getSalesContract } = useSalesContract();
const [now, setNow] = useState(new Date());
const [reservePrice, setReservePrice] = useState('');
const [startTime, setStartTime] = useState(
new Date(new Date().getTime() + 2 * 60 * 1000)
);
const [endTime, setEndTime] = useState(
new Date(new Date().getTime() + 24 * 60 * 60 * 1000)
);
const [focused, setFocused] = useState(false);
const [minBidReserve, setMinBidReserve] = useState(false);
const [options, setOptions] = useState([]);
const [selected, setSelected] = useState([]);
const [tokenPrice, setTokenPrice] = useState();
const [tokenPriceInterval, setTokenPriceInterval] = useState();
const [inputError, setInputError] = useState(null);
useEffect(() => {
setInterval(() => setNow(new Date()), 1000);
}, []);
useEffect(() => {
if (tokens?.length) {
setOptions(tokens);
}
}, [tokens]);
useEffect(() => {
setReservePrice(auction?.reservePrice || '');
setStartTime(
auction?.startTime
? new Date(auction.startTime * 1000)
: new Date(new Date().getTime() + 2 * 60 * 1000)
);
setEndTime(
auction?.endTime
? new Date(auction.endTime * 1000)
: new Date(new Date().getTime() + 24 * 60 * 60 * 1000)
);
}, [visible, auction]);
useEffect(() => {
if (visible && tokens?.length) {
setSelected([auction ? auction.token : tokens[0]]);
}
}, [visible, auction]);
const CustomCheckbox = withStyles({
root: {
'&$checked': {
color: '#1969FF',
},
},
checked: {},
})(props => <Checkbox color="default" {...props} />);
const getTokenPrice = () => {
if (tokenPriceInterval) clearInterval(tokenPriceInterval);
const func = async () => {
const tk = selected[0].address || ethers.constants.AddressZero;
try {
const salesContract = await getSalesContract();
const price = await salesContract.getPrice(tk);
setTokenPrice(parseFloat(ethers.utils.formatUnits(price, 18)));
} catch {
setTokenPrice(null);
}
};
func();
setTokenPriceInterval(setInterval(func, 60 * 1000));
};
useEffect(() => {
if (selected.length === 0) return;
getTokenPrice();
}, [selected]);
const validateInput = (() => {
if (reservePrice.length === 0 || parseFloat(reservePrice) == 0)
return false;
if (!auctionStarted && startTime.getTime() < now.getTime()) return false;
return (
endTime.getTime() >= now.getTime() + 1000 * 60 * 5 &&
endTime.getTime() >= startTime.getTime() + 1000 * 60 * 5
);
})();
return (
<Modal
visible={visible}
title={auction ? 'Update Auction' : 'Start Auction'}
onClose={onClose}
submitDisabled={
contractApproving ||
confirming ||
(contractApproved && !validateInput) ||
inputError
}
submitLabel={
contractApproved ? (
confirming ? (
<ClipLoader color="#FFF" size={16} />
) : auction ? (
'Update Auction'
) : (
'Start Auction'
)
) : contractApproving ? (
'Approving Item'
) : (
'Approve Item'
)
}
onSubmit={() =>
contractApproved
? !confirming && validateInput
? onStartAuction(
selected[0],
reservePrice,
startTime,
endTime,
minBidReserve
)
: null
: approveContract()
}
>
<div className={styles.formGroup}>
<div className={styles.formLabel}>
Reserve Price
<BootstrapTooltip
title="Reserve price is your desired one you want to get from this auction."
placement="top"
>
<HelpOutlineIcon />
</BootstrapTooltip>
</div>
<div className={cx(styles.formInputCont, focused && styles.focused)}>
<Select
options={options}
disabled={auction || confirming}
values={selected}
onChange={tk => {
setSelected(tk);
}}
className={styles.select}
placeholder=""
itemRenderer={({ item, itemIndex, methods }) => (
<div
key={itemIndex}
className={styles.token}
onClick={() => {
methods.clearAll();
methods.addItem(item);
}}
>
<img src={item?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{item.symbol}</div>
</div>
)}
contentRenderer={({ props: { values } }) =>
values.length > 0 ? (
<div className={styles.selectedToken}>
<img src={values[0]?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{values[0].symbol}</div>
</div>
) : (
<div className={styles.selectedToken} />
)
}
/>
<PriceInput
className={styles.formInput}
placeholder="0.00"
value={'' + reservePrice}
decimals={selected[0]?.decimals || 0}
onChange={setReservePrice}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
disabled={contractApproving || confirming}
onInputError={err => setInputError(err)}
/>
<div className={styles.usdPrice}>
{!isNaN(tokenPrice) && tokenPrice !== null ? (
`$${formatNumber(
((parseFloat(reservePrice) || 0) * tokenPrice).toFixed(2)
)}`
) : (
<Skeleton width={100} height={24} />
)}
</div>
</div>
<InputError text={inputError} />
</div>
<div className={styles.formGroupDates}>
<div className={styles.formGroup}>
<div className={styles.formLabel}>Start Time</div>
<div className={styles.formInputCont}>
<Datetime
value={startTime}
className={'calendarAboveInput'}
onChange={val => setStartTime(val.toDate())}
inputProps={{
className: styles.formInput,
onKeyDown: e => e.preventDefault(),
disabled: auctionStarted || contractApproving || confirming,
}}
closeOnSelect
isValidDate={cur =>
cur.valueOf() > now.getTime() - 1000 * 60 * 60 * 24
}
/>
</div>
</div>
<div className={styles.formGroup}>
<div className={styles.formLabel}>Auction Expiration</div>
<div className={styles.formInputCont}>
<Datetime
value={endTime}
className={'calendarAboveInput'}
onChange={val => setEndTime(val.toDate())}
inputProps={{
className: styles.formInput,
onKeyDown: e => e.preventDefault(),
disabled: contractApproving || confirming,
}}
closeOnSelect
isValidDate={cur =>
cur.valueOf() > startTime.getTime() - 1000 * 60 * 60 * 23
}
/>
</div>
</div>
</div>
<FormControlLabel
className={cx(styles.formControl, styles.selected)}
classes={{ label: styles.groupTitle }}
control={
<CustomCheckbox
checked={minBidReserve}
onChange={() => setMinBidReserve(prevState => !prevState)}
/>
}
label="Minimum bid should be equal or greater than reserve price"
/>
</Modal>
);
}
Example #3
Source File: index.jsx From Artion-Client with GNU General Public License v3.0 | 4 votes |
BidModal = ({
visible,
onClose,
onPlaceBid,
minBidAmount,
confirming,
token,
firstBid,
}) => {
const { tokens } = useTokens();
const { getSalesContract } = useSalesContract();
const [currentBid, setCurrentBid] = useState(0);
const [price, setPrice] = useState('');
const [focused, setFocused] = useState(false);
const [options, setOptions] = useState([]);
const [tokenPrice, setTokenPrice] = useState();
const [tokenPriceInterval, setTokenPriceInterval] = useState();
const [inputError, setInputError] = useState(null);
useEffect(() => {
setPrice(minBidAmount);
setCurrentBid(parseFloat(minBidAmount));
}, [visible]);
useEffect(() => {
if (tokens?.length) {
setOptions(tokens);
}
}, [tokens]);
const getTokenPrice = () => {
if (tokenPriceInterval) clearInterval(tokenPriceInterval);
const func = async () => {
const tk = token.address || ethers.constants.AddressZero;
try {
const salesContract = await getSalesContract();
const price = await salesContract.getPrice(tk);
setTokenPrice(parseFloat(ethers.utils.formatUnits(price, 18)));
} catch {
setTokenPrice(null);
}
};
func();
setTokenPriceInterval(setInterval(func, 60 * 1000));
};
useEffect(() => {
if (token) {
getTokenPrice();
}
}, [token]);
const validateInput = () => {
return (
price.length > 0 &&
parseFloat(price) > 0 &&
(firstBid
? parseFloat(price) >= currentBid
: parseFloat(price) > currentBid)
);
};
return (
<Modal
visible={visible}
title="Place Bid"
onClose={onClose}
submitDisabled={confirming || !validateInput() || inputError}
submitLabel={confirming ? <ClipLoader color="#FFF" size={16} /> : 'Place'}
onSubmit={() =>
!confirming && validateInput() ? onPlaceBid(price) : null
}
>
<div className={styles.formGroup}>
<div className={styles.formLabel}>Price</div>
<div className={cx(styles.formInputCont, focused && styles.focused)}>
<Select
options={options}
disabled
values={token ? [token] : []}
className={styles.select}
placeholder=""
itemRenderer={({ item, itemIndex, methods }) => (
<div
key={itemIndex}
className={styles.token}
onClick={() => {
methods.clearAll();
methods.addItem(item);
}}
>
<img src={item?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{item.symbol}</div>
</div>
)}
contentRenderer={({ props: { values } }) =>
values.length > 0 ? (
<div className={styles.selectedToken}>
<img src={values[0]?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{values[0].symbol}</div>
</div>
) : (
<div className={styles.selectedToken} />
)
}
/>
<PriceInput
className={styles.formInput}
placeholder="0.00"
decimals={token?.decimals || 0}
value={'' + price}
onChange={setPrice}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
disabled={confirming}
onInputError={err => setInputError(err)}
/>
<div className={styles.usdPrice}>
{!isNaN(tokenPrice) && tokenPrice !== null ? (
`$${formatNumber(
((parseFloat(price) || 0) * tokenPrice).toFixed(2)
)}`
) : (
<Skeleton width={100} height={24} />
)}
</div>
</div>
<InputError text={inputError} />
</div>
</Modal>
);
}
Example #4
Source File: index.js From Artion-Client with GNU General Public License v3.0 | 4 votes |
BaseCard = ({ item, loading, style, create, onCreate, onLike }) => {
const { storageUrl, likeItem, likeBundle } = useApi();
const { getAuction } = useAuctionContract();
const { getTokenByAddress } = useTokens();
const [now, setNow] = useState(new Date());
const [fetching, setFetching] = useState(false);
const [isLiking, setIsLiking] = useState(false);
const [info, setInfo] = useState(null);
const [index, setIndex] = useState(0);
const [isLike, setIsLike] = useState(false);
const [liked, setLiked] = useState(0);
const [auction, setAuction] = useState(null);
const { collections } = useSelector(state => state.Collections);
const { authToken } = useSelector(state => state.ConnectWallet);
const collection = collections.find(
col => col.address === item?.contractAddress
);
const getTokenURI = async tokenURI => {
setFetching(true);
try {
tokenURI = getRandomIPFS(tokenURI);
const { data } = await axios.get(tokenURI);
if (data[Object.keys(data)[0]].image) {
data.image = getRandomIPFS(data[Object.keys(data)[0]].image);
data.name = data[Object.keys(data)[0]].name;
}
if (data.properties && data.properties.image) {
data.image = getRandomIPFS(data.properties.image.description);
}
setInfo(data);
} catch {
setInfo(null);
}
setFetching(false);
};
const getCurrentAuction = async () => {
try {
const _auction = await getAuction(item.contractAddress, item.tokenID);
if (_auction.endTime !== 0) {
const token = getTokenByAddress(_auction.payToken);
_auction.reservePrice = parseFloat(
ethers.utils.formatUnits(_auction.reservePrice, token.decimals)
);
_auction.token = token;
setAuction(_auction);
}
} catch (e) {
console.log(e);
}
};
useEffect(() => {
async function fetchMyAPI() {
if (item && !item.name) {
await getTokenURI(item.tokenURI);
}
if (item) {
if (item.imageURL) {
// eslint-disable-next-line require-atomic-updates
item.imageURL = getRandomIPFS(item.imageURL);
}
setLiked(item.liked);
if (item.items) {
setAuction(null);
} else {
getCurrentAuction();
}
}
}
fetchMyAPI();
}, [item]);
useEffect(() => {
if (item?.isLiked !== undefined) {
setIsLike(item.isLiked);
}
}, [item?.isLiked]);
useEffect(() => {
setInterval(() => {
setNow(new Date());
}, 1000);
}, []);
const auctionStarted = now.getTime() / 1000 >= auction?.startTime;
const auctionEnded = auction?.endTime <= now.getTime() / 1000;
const auctionActive = auctionStarted && !auctionEnded;
const toggleFavorite = async e => {
e.preventDefault();
if (isLiking) return;
setIsLiking(true);
try {
if (item.items) {
const { data } = await likeBundle(item._id, authToken);
setLiked(data);
} else {
const { data } = await likeItem(
item.contractAddress,
item.tokenID,
authToken
);
setLiked(data);
}
} catch (err) {
console.log(err);
}
setIsLike(!isLike);
setIsLiking(false);
onLike && onLike();
};
const formatDiff = diff => {
if (diff >= ONE_MONTH) {
const m = Math.ceil(diff / ONE_MONTH);
return `${m} Month${m > 1 ? 's' : ''}`;
}
if (diff >= ONE_DAY) {
const d = Math.ceil(diff / ONE_DAY);
return `${d} Day${d > 1 ? 's' : ''}`;
}
if (diff >= ONE_HOUR) {
const h = Math.ceil(diff / ONE_HOUR);
return `${h} Hour${h > 1 ? 's' : ''}`;
}
if (diff >= ONE_MIN) {
const h = Math.ceil(diff / ONE_MIN);
return `${h} Min${h > 1 ? 's' : ''}`;
}
return `${diff} Second${diff > 1 ? 's' : ''}`;
};
const formatDuration = endTime => {
const diff = endTime - Math.floor(now.getTime() / 1000);
return formatDiff(diff);
};
const renderSlides = () => {
return item.items.map((v, idx) => (
<div className={styles.imageBox} key={idx}>
{(v.imageURL || v.thumbnailPath?.length > 10) &&
(v.imageURL?.includes('youtube') ? (
<ReactPlayer
className={styles.media}
url={v.imageURL}
controls={true}
width="100%"
height="100%"
/>
) : (
<Suspense
fallback={
<Loader
type="Oval"
color="#007BFF"
height={32}
width={32}
className={styles.loader}
/>
}
>
<SuspenseImg
src={
v.thumbnailPath?.length > 10
? `${storageUrl}/image/${v.thumbnailPath}`
: v.imageURL
}
className={styles.media}
alt={v.name}
/>
</Suspense>
))}
</div>
));
};
const renderDots = () => {
return item.items.map((v, idx) => (
<div className={cx(styles.dot)} key={idx} />
));
};
const renderContent = () => {
return (
<>
<div className={cx(styles.cardHeader, isLike && styles.liking)}>
{!item ? (
<Skeleton width={80} height={20} />
) : (
<>
{isLike ? (
<FavoriteIcon
className={styles.favIcon}
onClick={toggleFavorite}
/>
) : (
<FavoriteBorderIcon
className={styles.favIcon}
onClick={toggleFavorite}
/>
)}
<span className={styles.favLabel}>{liked || 0}</span>
</>
)}
</div>
<div className={styles.mediaBox}>
<div className={styles.mediaPanel}>
{loading || fetching ? (
<Skeleton
width="100%"
height="100%"
className={styles.mediaLoading}
/>
) : item.items ? (
<>
<Carousel
className={styles.carousel}
plugins={['fastSwipe']}
value={index}
onChange={_index =>
setIndex(Math.min(Math.max(_index, 0), 2))
}
slides={renderSlides()}
numberOfInfiniteClones={1}
/>
<Dots
className={styles.dots}
value={index}
onChange={setIndex}
number={Math.min(item.items.length, 18)}
thumbnails={renderDots()}
/>
</>
) : (
<div className={styles.imageBox}>
{(item?.imageURL ||
info?.image ||
item?.thumbnailPath?.length > 10 ||
item?.thumbnailPath === 'embed') &&
(item?.thumbnailPath === 'embed' ? (
<iframe src={item?.imageURL} className={styles.media} />
) : (item?.imageURL || info?.image)?.includes('youtube') ? (
<ReactPlayer
className={styles.media}
url={item?.imageURL || info?.image}
controls={true}
width="100%"
height="100%"
/>
) : (
<Suspense
fallback={
<Loader
type="Oval"
color="#007BFF"
height={32}
width={32}
className={styles.loader}
/>
}
>
<SuspenseImg
src={
item.thumbnailPath?.length > 10
? `${storageUrl}/image/${item.thumbnailPath}`
: item?.imageURL || info?.image
}
className={styles.media}
alt={item.name}
/>
</Suspense>
))}
</div>
)}
</div>
</div>
<div className={styles.content}>
<div className={styles.topLine}>
<div className={styles.itemName}>
{loading || fetching ? (
<Skeleton width={100} height={20} />
) : (
<div className={styles.label}>
{collection?.collectionName || collection?.name}
{collection?.isVerified && (
<BootstrapTooltip
title="Verified Collection"
placement="top"
>
<CheckCircleIcon className={styles.checkIcon} />
</BootstrapTooltip>
)}
</div>
)}
{loading || fetching ? (
<Skeleton width={100} height={20} />
) : (
<div className={styles.name}>{item?.name || info?.name}</div>
)}
</div>
{auction?.reservePrice || item?.price ? (
<div className={styles.alignRight}>
{!loading && (
<div className={styles.label}>
{auctionActive ? 'Auction' : 'Price'}
</div>
)}
{loading || fetching ? (
<Skeleton width={80} height={20} />
) : (
<div className={cx(styles.label, styles.price)}>
<img
src={
auctionActive
? auction?.token?.icon
: getTokenByAddress(item?.paymentToken)?.icon ||
wFTMLogo
}
/>
{formatNumber(
auctionActive
? auction.reservePrice
: item.price.toFixed(2)
)}
</div>
)}
</div>
) : (
''
)}
</div>
<div className={styles.alignBottom}>
<div>
{auctionActive && (
<>
{!loading && <div className={styles.label2}>Time left</div>}
<div className={styles.name2}>
{formatDuration(auction.endTime)}
</div>
</>
)}
</div>
{item?.lastSalePrice > 0 && (
<div className={styles.alignRight}>
{!loading && <div className={styles.label2}>Last Price</div>}
{loading || fetching ? (
<Skeleton width={80} height={20} />
) : (
<div className={cx(styles.label2, styles.price2)}>
<img
src={
getTokenByAddress(item?.lastSalePricePaymentToken)?.icon
}
/>
{formatNumber(item.lastSalePrice)}
</div>
)}
</div>
)}
{/* {loading || fetching ? (
<Skeleton width={80} height={20} />
) : (
<div className={styles.label}>
{item.items
? `${item.items.length} item${
item.items.length !== 1 ? 's' : ''
}`
: `${formatNumber(
item?.holderSupply || item?.supply || 1
)} of ${formatNumber(item?.supply || 1)}`}
</div>
)} */}
</div>
</div>
</>
);
};
return (
<div style={style} className={styles.root} onClick={onCreate}>
<div className={styles.card}>
{create ? (
<div className={styles.createBtn}>
<div className={styles.createIcon}>
<img src={iconPlus} />
</div>
<div className={styles.createLabel}>Create Bundle</div>
</div>
) : item ? (
<Link
to={
item.items
? `/bundle/${item._id}`
: `/explore/${item.contractAddress}/${item.tokenID}`
}
className={styles.link}
>
{renderContent()}
</Link>
) : (
renderContent()
)}
</div>
{item?.tokenType === 1155 && (
<>
<div className={styles.card} />
<div className={styles.card} />
</>
)}
</div>
);
}
Example #5
Source File: index.jsx From Artion-Client with GNU General Public License v3.0 | 4 votes |
OfferModal = ({
visible,
onClose,
onMakeOffer,
confirming,
totalSupply,
}) => {
const { tokens } = useTokens();
const { getSalesContract } = useSalesContract();
const [price, setPrice] = useState('');
const [quantity, setQuantity] = useState('1');
const [endTime, setEndTime] = useState(
new Date(new Date().getTime() + 24 * 60 * 60 * 1000)
);
const [options, setOptions] = useState([]);
const [selected, setSelected] = useState([]);
const [tokenPrice, setTokenPrice] = useState();
const [tokenPriceInterval, setTokenPriceInterval] = useState();
const [inputError, setInputError] = useState(null);
useEffect(() => {
if (tokens?.length > 1) {
setOptions(tokens);
}
}, [tokens]);
useEffect(() => {
if (visible) {
setPrice('');
setQuantity('1');
setEndTime(new Date(new Date().getTime() + 24 * 60 * 60 * 1000));
if (tokens?.length > 1) {
setSelected([tokens[0]]);
}
}
}, [visible]);
const getTokenPrice = () => {
if (tokenPriceInterval) clearInterval(tokenPriceInterval);
const func = async () => {
const tk = selected[0].address || ethers.constants.AddressZero;
try {
const salesContract = await getSalesContract();
const price = await salesContract.getPrice(tk);
setTokenPrice(parseFloat(ethers.utils.formatUnits(price, 18)));
} catch {
setTokenPrice(null);
}
};
func();
setTokenPriceInterval(setInterval(func, 60 * 1000));
};
useEffect(() => {
if (selected.length === 0) return;
getTokenPrice();
}, [selected]);
const handleQuantityChange = e => {
const val = e.target.value;
if (!val) {
setQuantity('');
return;
}
if (isNaN(val)) return;
const _quantity = parseInt(val);
setQuantity(Math.min(_quantity, totalSupply));
};
const handleMakeOffer = () => {
let quant = 1;
if (totalSupply > 1) {
quant = parseInt(quantity);
}
onMakeOffer(selected[0], price, quant, endTime);
};
const validateInput = () => {
if (price.length === 0 || parseFloat(price) == 0) return false;
if (totalSupply > 1 && quantity.length === 0) return false;
if (endTime.getTime() < new Date().getTime()) return false;
return true;
};
return (
<Modal
visible={visible}
title="Place your offer"
onClose={onClose}
submitDisabled={confirming || !validateInput() || inputError}
submitLabel={
confirming ? <ClipLoader color="#FFF" size={16} /> : 'Place Offer'
}
onSubmit={() =>
!confirming && validateInput() ? handleMakeOffer() : null
}
>
<div className={styles.formGroup}>
<div className={styles.formLabel}>Price</div>
<div className={styles.formInputCont}>
<Select
options={options}
disabled={confirming}
values={selected}
onChange={tk => {
setSelected(tk);
}}
className={styles.select}
placeholder=""
itemRenderer={({ item, itemIndex, methods }) => (
<div
key={itemIndex}
className={styles.token}
onClick={() => {
methods.clearAll();
methods.addItem(item);
}}
>
<img src={item?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{item.symbol}</div>
</div>
)}
contentRenderer={({ props: { values } }) =>
values.length > 0 ? (
<div className={styles.selectedToken}>
<img src={values[0]?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{values[0].symbol}</div>
</div>
) : (
<div className={styles.selectedToken} />
)
}
/>
<PriceInput
className={styles.formInput}
placeholder="0.00"
decimals={selected[0]?.decimals || 0}
value={'' + price}
onChange={setPrice}
disabled={confirming}
onInputError={err => setInputError(err)}
/>
<div className={styles.usdPrice}>
{!isNaN(tokenPrice) && tokenPrice !== null ? (
`$${formatNumber(
((parseFloat(price) || 0) * tokenPrice).toFixed(2)
)}`
) : (
<Skeleton width={100} height={24} />
)}
</div>
</div>
<InputError text={inputError} />
</div>
{totalSupply !== null && (
<div className={styles.formGroup}>
<div className={styles.formLabel}>Quantity</div>
<div className={styles.formInputCont}>
<input
className={styles.formInput}
placeholder={totalSupply}
value={quantity}
onChange={handleQuantityChange}
disabled={confirming || totalSupply === 1}
/>
</div>
</div>
)}
<div className={styles.formGroup}>
<div className={styles.formLabel}>Offer Expiration</div>
<div className={styles.formInputCont}>
<Datetime
value={endTime}
onChange={val => setEndTime(val.toDate())}
inputProps={{
className: styles.formInput,
onKeyDown: e => e.preventDefault(),
disabled: confirming,
}}
closeOnSelect
isValidDate={cur =>
cur.valueOf() > new Date().getTime() - 1000 * 60 * 60 * 24
}
/>
</div>
</div>
</Modal>
);
}
Example #6
Source File: index.jsx From Artion-Client with GNU General Public License v3.0 | 4 votes |
SellModal = ({
visible,
onClose,
onSell,
startPrice,
confirming,
approveContract,
contractApproving,
contractApproved,
totalSupply,
}) => {
const { tokens } = useTokens();
const { getSalesContract } = useSalesContract();
const [price, setPrice] = useState('');
const [quantity, setQuantity] = useState('1');
const [focused, setFocused] = useState(false);
const [options, setOptions] = useState([]);
const [selected, setSelected] = useState([]);
const [tokenPrice, setTokenPrice] = useState();
const [tokenPriceInterval, setTokenPriceInterval] = useState();
const [inputError, setInputError] = useState(null);
useEffect(() => {
setPrice(startPrice > 0 ? startPrice.toString() : '');
setQuantity('1');
if (visible && tokens?.length) {
setSelected([tokens[0]]);
}
}, [visible]);
useEffect(() => {
if (tokens?.length) {
setOptions(tokens);
}
}, [tokens]);
const getTokenPrice = () => {
if (tokenPriceInterval) clearInterval(tokenPriceInterval);
const func = async () => {
const tk = selected[0].address || ethers.constants.AddressZero;
try {
const salesContract = await getSalesContract();
const price = await salesContract.getPrice(tk);
setTokenPrice(parseFloat(ethers.utils.formatUnits(price, 18)));
} catch {
setTokenPrice(null);
}
};
func();
setTokenPriceInterval(setInterval(func, 60 * 1000));
};
useEffect(() => {
if (selected.length === 0) return;
getTokenPrice();
}, [selected]);
const handleQuantityChange = e => {
const val = e.target.value;
if (!val) {
setQuantity('');
return;
}
if (isNaN(val)) return;
const _quantity = parseInt(val);
setQuantity(Math.min(_quantity, totalSupply));
};
const handleSellItem = () => {
let quant = 1;
if (totalSupply > 1) {
quant = parseInt(quantity);
}
onSell(selected[0], price, quant);
};
const validateInput = () => {
if (price.length === 0 || parseFloat(price) == 0) return false;
if (totalSupply > 1 && quantity.length === 0) return false;
if (selected.length === 0) return false;
return true;
};
return (
<Modal
visible={visible}
title={startPrice > 0 ? 'Update Your Listing' : 'Sell Your Item'}
onClose={onClose}
submitDisabled={
contractApproving ||
confirming ||
(contractApproved && !validateInput()) ||
inputError
}
submitLabel={
contractApproved ? (
confirming ? (
<ClipLoader color="#FFF" size={16} />
) : startPrice > 0 ? (
'Update Price'
) : (
'List Item'
)
) : contractApproving ? (
'Approving Item'
) : (
'Approve Item'
)
}
onSubmit={() =>
contractApproved
? !confirming && validateInput()
? handleSellItem()
: null
: approveContract()
}
>
<div className={styles.formGroup}>
<div className={styles.formLabel}>Price</div>
<div className={cx(styles.formInputCont, focused && styles.focused)}>
<Select
options={options}
disabled={confirming}
values={selected}
onChange={tk => {
setSelected(tk);
}}
className={styles.select}
placeholder=""
itemRenderer={({ item, itemIndex, methods }) => (
<div
key={itemIndex}
className={styles.token}
onClick={() => {
methods.clearAll();
methods.addItem(item);
}}
>
<img src={item?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{item.symbol}</div>
</div>
)}
contentRenderer={({ props: { values } }) =>
values.length > 0 ? (
<div className={styles.selectedToken}>
<img src={values[0]?.icon} className={styles.tokenIcon} />
<div className={styles.tokenSymbol}>{values[0].symbol}</div>
</div>
) : (
<div className={styles.selectedToken} />
)
}
/>
<PriceInput
className={styles.formInput}
placeholder="0.00"
decimals={selected[0]?.decimals || 0}
value={'' + price}
onChange={setPrice}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
disabled={contractApproving || confirming}
onInputError={setInputError}
/>
<div className={styles.usdPrice}>
{!isNaN(tokenPrice) && tokenPrice !== null ? (
`$${formatNumber(
((parseFloat(price) || 0) * tokenPrice).toFixed(2)
)}`
) : (
<Skeleton width={100} height={24} />
)}
</div>
</div>
<InputError text={inputError} />
</div>
{totalSupply !== null && (
<div className={styles.formGroup}>
<div className={styles.formLabel}>Quantity</div>
<div className={styles.formInputCont}>
<input
className={styles.formInput}
placeholder={totalSupply}
value={quantity}
onChange={handleQuantityChange}
disabled={contractApproving || confirming || totalSupply === 1}
/>
</div>
</div>
)}
</Modal>
);
}
Example #7
Source File: index.jsx From Artion-Client with GNU General Public License v3.0 | 4 votes |
WFTMModal = ({ visible, onClose }) => {
const { account, chainId } = useWeb3React();
const { explorerUrl } = useApi();
const { getWFTMBalance, wrapFTM, unwrapFTM } = useWFTMContract();
const [loading, setLoading] = useState(false);
const [balance, setBalance] = useState(0);
const [wrappedBalance, setWrappedBalance] = useState(0);
const [confirming, setConfirming] = useState(false);
const [wrap, setWrap] = useState(true);
const [amount, setAmount] = useState('');
const [inputError, setInputError] = useState(null);
const { price } = useSelector(state => state.Price);
const getBalances = async (overrideLoading = false) => {
if (!overrideLoading) {
setLoading(true);
}
await window.ethereum.enable();
const provider = new ethers.providers.Web3Provider(window.ethereum);
let [ftmBal, wftmBal] = await Promise.all([
await provider.getBalance(account),
await getWFTMBalance(account),
]);
setBalance(parseFloat(ftmBal.toString()) / 10 ** 18);
setWrappedBalance(parseFloat(wftmBal.toString()) / 10 ** 18);
if (!overrideLoading) {
setLoading(false);
}
return [
parseFloat(ftmBal.toString()) / 10 ** 18,
parseFloat(wftmBal.toString()) / 10 ** 18,
];
};
const pollBalanceChange = async (initialFtmBal, initialWftmBal) => {
setLoading(true);
let timeout;
let updated = false;
await new Promise(
resolve =>
(timeout = setTimeout(
() =>
getBalances(true).then(([ftmBal, wftmBal]) => {
if (ftmBal !== initialFtmBal || wftmBal !== initialWftmBal) {
updated = true;
}
resolve();
}),
200
))
);
if (!updated) {
await pollBalanceChange(initialFtmBal, initialWftmBal);
}
clearTimeout(timeout);
return setLoading(false);
};
useEffect(() => {
if (visible) {
setLoading(false);
setConfirming(false);
setWrap(true);
setAmount('');
getBalances();
}
}, [visible, chainId]);
const parseBalance = bal => {
return bal.toFixed(4);
};
const isMax = () => {
if (wrap) {
return amount === (balance - 0.01).toString();
}
return amount === wrappedBalance.toString();
};
const onMax = () => {
if (wrap) {
setAmount((balance - 0.01).toString());
} else {
setAmount(wrappedBalance.toString());
}
};
const handleWrapFTM = async () => {
if (confirming || loading) return;
setConfirming(true);
try {
const price = ethers.utils.parseEther(amount);
if (wrap) {
const tx = await wrapFTM(price, account);
await tx.wait();
await pollBalanceChange(balance, wrappedBalance);
const toastId = showToast(
'success',
'Wrapped FTM successfully!',
'',
() => {
toast.dismiss(toastId);
window.open(`${explorerUrl}/tx/${tx.hash}`, '_blank');
}
);
} else {
const tx = await unwrapFTM(price);
await tx.wait();
await pollBalanceChange(balance, wrappedBalance);
const toastId = showToast(
'success',
'Unwrap W-FTM successfully!',
'',
() => {
toast.dismiss(toastId);
window.open(`${explorerUrl}/tx/${tx.hash}`, '_blank');
}
);
}
setAmount('');
} catch (err) {
showToast('error', formatError(err));
console.log(err);
} finally {
setConfirming(false);
}
getBalances();
};
return (
<Modal
visible={visible}
title="FTM / WFTM Station"
onClose={onClose}
submitDisabled={
confirming ||
loading ||
inputError ||
amount.length === 0 ||
parseFloat(amount) === 0 ||
parseFloat(amount) > (wrap ? balance - 0.01 : wrappedBalance)
}
submitLabel={
confirming || loading ? (
<ClipLoader color="#FFF" size={16} />
) : wrap ? (
'Wrap'
) : (
'Unwrap'
)
}
onSubmit={() =>
amount.length &&
parseFloat(amount) > 0 &&
parseFloat(amount) <= (wrap ? balance - 0.01 : wrappedBalance) &&
handleWrapFTM()
}
>
<div className={cx(styles.swapContainer, !wrap && styles.reverse)}>
<div className={styles.swapBox}>
<div className={styles.symbol}>FTM</div>
<div className={styles.swapBoxInner}>
<div className={styles.balance}>
Balance:{' '}
{loading ? (
<Skeleton width={60} height={20} />
) : (
parseBalance(balance)
)}
{wrap && !isMax() && !loading && balance > 0 && (
<div className={styles.max} onClick={onMax}>
(Max)
</div>
)}
</div>
<div className={styles.rightBox}>
<PriceInput
className={styles.input}
placeholder="0.0"
decimals={18}
value={'' + amount}
onChange={setAmount}
onInputError={setInputError}
/>
<div className={styles.usdVal}>
${formatNumber(((parseFloat(amount) || 0) * price).toFixed(2))}
</div>
</div>
</div>
</div>
<div className={styles.swapbtn} onClick={() => setWrap(!wrap)}>
<SwapVertIcon className={styles.icon} />
</div>
<div className={styles.swapBox}>
<div className={styles.symbol}>WFTM</div>
<div className={styles.swapBoxInner}>
<div className={styles.balance}>
Balance:{' '}
{loading ? (
<Skeleton width={60} height={20} />
) : (
parseBalance(wrappedBalance)
)}
{!wrap && !isMax() && !loading && balance > 0 && (
<div className={styles.max} onClick={onMax}>
(Max)
</div>
)}
</div>
<div className={styles.rightBox}>
<PriceInput
className={styles.input}
placeholder="0.0"
decimals={18}
value={'' + amount}
onChange={setAmount}
onInputError={setInputError}
/>
<div className={styles.usdVal}>
${formatNumber(((parseFloat(amount) || 0) * price).toFixed(2))}
</div>
</div>
</div>
</div>
</div>
<InputError text={inputError} />
</Modal>
);
}
Example #8
Source File: index.js From Artion-Client with GNU General Public License v3.0 | 4 votes |
ExploreFilterHeader = ({ loading, category }) => {
const dispatch = useDispatch();
const { collections: collectionItems } = useSelector(
state => state.Collections
);
const { count } = useSelector(state => state.Tokens);
const { groupType, sortBy, collections } = useSelector(state => state.Filter);
const selectedCollections = () => {
const res = new Array(collections.length).fill(null);
collectionItems.map(item => {
const index = collections.findIndex(_item => _item === item.address);
if (index > -1) {
res[index] = item;
}
});
return res.filter(item => !!item);
};
const handleGroupTypeChange = e => {
const newGroupType = e.target.value;
dispatch(FilterActions.updateGroupTypeFilter(newGroupType));
};
const handleSortByChange = e => {
const newSortBy = e.target.value;
dispatch(FilterActions.updateSortByFilter(newSortBy));
};
const handleDeselectCollection = addr => {
let newCollections = [];
newCollections = collections.filter(item => item !== addr);
dispatch(FilterActions.updateCollectionsFilter(newCollections));
};
return (
<div className="filterHeaderRoot">
<div className="filterHeaderLeft">
<label className="filterResultLabel">
{loading ? (
<Skeleton width={100} height={24} />
) : (
`${formatNumber(count)} Result${count !== 1 ? 's' : ''}
${
category === null ? '' : `- Category: ${formatCategory(category)}`
}`
)}
</label>
{selectedCollections().map((item, idx) => (
<div key={idx} className="filterCollectionItem">
<img
className="filterCollectionItemLogo"
src={
item.isVerified
? `${getRandomIPFS('', true)}${item.logoImageHash}`
: nftActiveIcon
}
/>
<span className="filterCollectionItemName">
{item.name || item.collectionName}
</span>
<CloseIcon
className="filterCollectionRemoveItem"
onClick={() => handleDeselectCollection(item.address)}
/>
</div>
))}
</div>
<div className="filterSelectGroup">
<FormControl className="filterHeaderFormControl">
<Select
value={groupType}
onChange={handleGroupTypeChange}
className="selectBox"
classes={{
select: 'selectInner',
selectMenu: 'selectMenu',
icon: 'selectIcon',
}}
MenuProps={{
classes: {
paper: 'menuPropsPaper',
list: 'menuItemList',
},
}}
IconComponent={ExpandMoreIcon}
>
{GroupFilters.map((filter, idx) => {
return (
<MenuItem
value={filter.value}
key={idx}
className="menuItem"
classes={{ selected: 'menuItemSelected ' }}
>
{filter.label}
</MenuItem>
);
})}
</Select>
</FormControl>
<FormControl className="filterHeaderFormControl">
<Select
value={sortBy}
onChange={handleSortByChange}
className="selectBox"
classes={{
select: 'selectInner',
selectMenu: 'selectMenu',
icon: 'selectIcon',
}}
MenuProps={{
classes: {
paper: 'menuPropsPaper',
list: 'menuItemList',
},
}}
IconComponent={ExpandMoreIcon}
>
{SortByOptions.map((option, idx) => {
return (
<MenuItem
value={option.id}
key={idx}
className="menuItem"
classes={{ selected: 'menuItemSelected ' }}
>
{option.label}
</MenuItem>
);
})}
</Select>
</FormControl>
</div>
</div>
);
}