Commit d3c4ca6e authored by Charles Bachmeier's avatar Charles Bachmeier Committed by GitHub

feat: add Sell listing page (#4664)

* add listing modal

* add new files

* Add listing page

* remove useeffect

* re-add useeffect and includes array

* position relative

* add listing datatype

* use pluralize

* readable const

* clsx

* parseFloat 0 default

* don't use any

* cant use months for ms

* remove unused input style

* border sprinkles

* clsx

* duration enum

* remove unused index

* pluralize

* clsx

* pluralize

* type refactoring

* move format to utils

* remove uneeded check

* border sprinkles

* change input based on ref

* remove console.log

* correct warning check

* better clsx
Co-authored-by: default avatarCharles Bachmeier <charlie@genie.xyz>
parent 28538214
import { forwardRef } from 'react' import { isNumber } from 'nft/utils/numbers'
import { FormEvent } from 'react' import { FormEvent, forwardRef } from 'react'
import { Atoms } from '../../css/atoms'
import { isNumber } from '../../utils/numbers'
import { Box, BoxProps } from '../Box' import { Box, BoxProps } from '../Box'
export const defaultInputStyle: Atoms = {
borderColor: { default: 'medGray', focus: 'darkGray' },
borderWidth: '1px',
borderStyle: 'solid',
borderRadius: '8',
padding: '12',
fontSize: '14',
color: { placeholder: 'darkGray', default: 'blackBlue' },
backgroundColor: 'transparent',
}
export const Input = forwardRef<HTMLInputElement, BoxProps>((props, ref) => ( export const Input = forwardRef<HTMLInputElement, BoxProps>((props, ref) => (
<Box <Box
ref={ref} ref={ref}
......
import { style } from '@vanilla-extract/css'
import { sprinkles, themeVars } from 'nft/css/sprinkles.css'
export const buttonSelected = style([
sprinkles({
borderWidth: '1px',
borderStyle: 'solid',
borderColor: 'genieBlue',
}),
])
export const nftDivider = style([
sprinkles({
height: '0',
width: 'full',
borderRadius: '20',
borderWidth: '0.5px',
borderStyle: 'solid',
borderColor: 'medGray',
}),
])
export const priceChevron = style([
sprinkles({
height: '20',
width: '20',
transition: '250',
}),
{
marginBottom: '-6px',
},
])
export const durationChevron = style([
sprinkles({
height: '16',
width: '16',
transition: '250',
}),
{
marginBottom: '-4px',
},
])
export const chevronDown = style({
transform: 'rotate(180deg)',
})
export const dropdown = style({
boxShadow: `0px 4px 16px ${themeVars.colors.blackBlue20}`,
marginLeft: '-12px',
})
export const removeAsset = style({
top: '31px',
left: '15px',
})
export const removeMarketplace = style({
top: '11px',
right: '14px',
})
This diff is collapsed.
...@@ -71,11 +71,10 @@ export const ListingButton = ({ onClick, buttonText, showWarningOverride = false ...@@ -71,11 +71,10 @@ export const ListingButton = ({ onClick, buttonText, showWarningOverride = false
if (asset.newListings) { if (asset.newListings) {
for (const listing of asset.newListings) { for (const listing of asset.newListings) {
if (!listing.price) listingsMissingPrice.push([asset, listing]) if (!listing.price) listingsMissingPrice.push([asset, listing])
else if (isNaN(parseFloat(listing.price)) || parseFloat(listing.price) < 0) else if (isNaN(listing.price) || listing.price < 0) invalidPrices.push([asset, listing])
invalidPrices.push([asset, listing]) else if (listing.price < asset.floorPrice && !listing.overrideFloorPrice)
else if (parseFloat(listing.price) < asset.floorPrice && !listing.overrideFloorPrice)
listingsBelowFloor.push([asset, listing]) listingsBelowFloor.push([asset, listing])
else if (asset.floor_sell_order_price && parseFloat(listing.price) > asset.floor_sell_order_price) else if (asset.floor_sell_order_price && listing.price > asset.floor_sell_order_price)
listingsAboveSellOrderFloor.push([asset, listing]) listingsAboveSellOrderFloor.push([asset, listing])
} }
} }
......
...@@ -49,9 +49,7 @@ export const ListingSection = ({ ...@@ -49,9 +49,7 @@ export const ListingSection = ({
function getListingRowPrice(row: AssetRow): number | undefined { function getListingRowPrice(row: AssetRow): number | undefined {
const listingRow = row as ListingRow const listingRow = row as ListingRow
const newListings = listingRow.asset.newListings const newListings = listingRow.asset.newListings
return parseFloat( return newListings?.find((listing) => listing.marketplace.name === listingRow.marketplace.name)?.price ?? 0
newListings?.find((listing) => listing.marketplace.name === listingRow.marketplace.name)?.price ?? '0'
)
} }
const allApproved = !notAllApproved && rows.length > 0 && !isSuccessScreen const allApproved = !notAllApproved && rows.length > 0 && !isSuccessScreen
......
...@@ -129,13 +129,11 @@ export async function signListingRow( ...@@ -129,13 +129,11 @@ export async function signListingRow(
export const getTotalEthValue = (sellAssets: WalletAsset[]) => { export const getTotalEthValue = (sellAssets: WalletAsset[]) => {
const total = sellAssets.reduce((total, asset: WalletAsset) => { const total = sellAssets.reduce((total, asset: WalletAsset) => {
if (asset.newListings?.length) { if (asset.newListings?.length) {
const maxListing = asset.newListings.reduce((a, b) => const maxListing = asset.newListings.reduce((a, b) => ((a.price ?? 0) > (b.price ?? 0) ? a : b))
parseFloat(a.price ?? '0') > parseFloat(b.price ?? '0') ? a : b
)
return ( return (
total + total +
parseFloat(maxListing.price ?? '0') - (maxListing.price ?? 0) -
parseFloat(maxListing.price ?? '0') * (maxListing.marketplace.fee / 100 + asset.creatorPercentage) (maxListing.price ?? 0) * (maxListing.marketplace.fee / 100 + asset.creatorPercentage)
) )
} }
return total return total
......
...@@ -10,7 +10,7 @@ interface SellAssetState { ...@@ -10,7 +10,7 @@ interface SellAssetState {
removeSellAsset: (asset: WalletAsset) => void removeSellAsset: (asset: WalletAsset) => void
reset: () => void reset: () => void
setGlobalExpiration: (expirationTime: number) => void setGlobalExpiration: (expirationTime: number) => void
setAssetListPrice: (asset: WalletAsset, price: string, marketplace?: ListingMarket) => void setAssetListPrice: (asset: WalletAsset, price?: number, marketplace?: ListingMarket) => void
setGlobalMarketplaces: (marketplaces: ListingMarket[]) => void setGlobalMarketplaces: (marketplaces: ListingMarket[]) => void
removeAssetMarketplace: (asset: WalletAsset, marketplace: ListingMarket) => void removeAssetMarketplace: (asset: WalletAsset, marketplace: ListingMarket) => void
addMarketplaceWarning: (asset: WalletAsset, warning: ListingWarning) => void addMarketplaceWarning: (asset: WalletAsset, warning: ListingWarning) => void
......
...@@ -29,7 +29,7 @@ export interface SellOrder { ...@@ -29,7 +29,7 @@ export interface SellOrder {
} }
export interface Listing { export interface Listing {
price?: string price?: number
marketplace: ListingMarket marketplace: ListingMarket
overrideFloorPrice?: boolean overrideFloorPrice?: boolean
} }
...@@ -65,7 +65,7 @@ export interface WalletAsset { ...@@ -65,7 +65,7 @@ export interface WalletAsset {
floor_sell_order_price: number floor_sell_order_price: number
// Used for creating new listings // Used for creating new listings
expirationTime?: number expirationTime?: number
marketAgnosticPrice?: string marketAgnosticPrice?: number
newListings?: Listing[] newListings?: Listing[]
marketplaces?: ListingMarket[] marketplaces?: ListingMarket[]
listingWarnings?: ListingWarning[] listingWarnings?: ListingWarning[]
......
...@@ -10,6 +10,16 @@ export const formatUsdPrice = (price: number) => { ...@@ -10,6 +10,16 @@ export const formatUsdPrice = (price: number) => {
} }
} }
export const formatEth = (price: number) => {
if (price > 1000000) {
return `${Math.round(price / 1000000)}M`
} else if (price > 1000) {
return `${Math.round(price / 1000)}K`
} else {
return `${Math.round(price * 100 + Number.EPSILON) / 100}`
}
}
export const formatUSDPriceWithCommas = (price: number) => { export const formatUSDPriceWithCommas = (price: number) => {
return `$${Math.round(price) return `$${Math.round(price)
.toString() .toString()
......
...@@ -15,12 +15,9 @@ import { ...@@ -15,12 +15,9 @@ import {
} from 'nft/queries/openSea' } from 'nft/queries/openSea'
import ERC721 from '../../abis/erc721.json' import ERC721 from '../../abis/erc721.json'
import { PostOpenSeaSellOrder } from '../queries' import { createLooksRareOrder, newX2Y2Order, PostOpenSeaSellOrder } from '../queries'
import { createLooksRareOrder } from '../queries'
import { newX2Y2Order } from '../queries'
import { INVERSE_BASIS_POINTS, OPENSEA_DEFAULT_FEE, OPENSEA_FEE_ADDRESS } from '../queries/openSea' import { INVERSE_BASIS_POINTS, OPENSEA_DEFAULT_FEE, OPENSEA_FEE_ADDRESS } from '../queries/openSea'
import { ListingMarket, WalletAsset } from '../types' import { ListingMarket, ListingStatus, WalletAsset } from '../types'
import { ListingStatus } from '../types'
import { createSellOrder, encodeOrder, OfferItem, OrderPayload, signOrderData } from './x2y2' import { createSellOrder, encodeOrder, OfferItem, OrderPayload, signOrderData } from './x2y2'
export const ListingMarkets: ListingMarket[] = [ export const ListingMarkets: ListingMarket[] = [
...@@ -128,7 +125,7 @@ export async function signListing( ...@@ -128,7 +125,7 @@ export async function signListing(
switch (marketplace.name) { switch (marketplace.name) {
case 'OpenSea': case 'OpenSea':
try { try {
const listingInWei = parseEther(listingPrice) const listingInWei = parseEther(`${listingPrice}`)
const { sellerFee, openseaFee, creatorFee } = getConsiderationItems(asset, listingInWei, signerAddress) const { sellerFee, openseaFee, creatorFee } = getConsiderationItems(asset, listingInWei, signerAddress)
const considerationItems = [sellerFee, openseaFee, creatorFee].filter( const considerationItems = [sellerFee, openseaFee, creatorFee].filter(
(item): item is ConsiderationInputItem => item !== undefined (item): item is ConsiderationInputItem => item !== undefined
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment