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

feat: list 1155s (#6193)

* undisable 1155s and add nftStandard to CollectionRow

* working OS 1155 listing

* amend OS listing to handle 0 creator fee

* handle no royalties set

* disable already listed protection for 1155s

* can list to LR

* stuck on x2

* working x2y2

* remove comment

* add listing issue finding to helper fn

---------
Co-authored-by: default avatarCharles Bachmeier <charlie@genie.xyz>
parent c7f67437
import { Plural, t, Trans } from '@lingui/macro' import { Plural, t, Trans } from '@lingui/macro'
import { BaseButton } from 'components/Button' import { BaseButton } from 'components/Button'
import ms from 'ms.macro'
import { BelowFloorWarningModal } from 'nft/components/profile/list/Modal/BelowFloorWarningModal' import { BelowFloorWarningModal } from 'nft/components/profile/list/Modal/BelowFloorWarningModal'
import { useIsMobile, useSellAsset } from 'nft/hooks' import { useIsMobile, useSellAsset } from 'nft/hooks'
import { Listing, WalletAsset } from 'nft/types'
import { useMemo, useState } from 'react' import { useMemo, useState } from 'react'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { BREAKPOINTS } from 'theme' import { BREAKPOINTS } from 'theme'
import { shallow } from 'zustand/shallow' import { shallow } from 'zustand/shallow'
const BELOW_FLOOR_PRICE_THRESHOLD = 0.8 import { findListingIssues } from './utils'
const StyledListingButton = styled(BaseButton)<{ showResolveIssues: boolean; missingPrices: boolean }>` const StyledListingButton = styled(BaseButton)<{ showResolveIssues: boolean; missingPrices: boolean }>`
background: ${({ showResolveIssues, theme }) => (showResolveIssues ? theme.accentFailure : theme.accentAction)}; background: ${({ showResolveIssues, theme }) => (showResolveIssues ? theme.accentFailure : theme.accentAction)};
...@@ -47,35 +45,13 @@ export const ListingButton = ({ onClick }: { onClick: () => void }) => { ...@@ -47,35 +45,13 @@ export const ListingButton = ({ onClick }: { onClick: () => void }) => {
// Find issues with item listing data // Find issues with item listing data
const [listingsMissingPrice, listingsBelowFloor] = useMemo(() => { const [listingsMissingPrice, listingsBelowFloor] = useMemo(() => {
const missingExpiration = sellAssets.some((asset) => { const {
return ( missingExpiration,
asset.expirationTime != null && overMaxExpiration,
(isNaN(asset.expirationTime) || asset.expirationTime * 1000 - Date.now() < ms`60 seconds`) listingsMissingPrice,
) listingsBelowFloor,
}) listingsAboveSellOrderFloor,
const overMaxExpiration = sellAssets.some((asset) => { } = findListingIssues(sellAssets)
return asset.expirationTime != null && asset.expirationTime * 1000 - Date.now() > ms`180 days`
})
const listingsMissingPrice: [WalletAsset, Listing][] = []
const listingsBelowFloor: [WalletAsset, Listing][] = []
const listingsAboveSellOrderFloor: [WalletAsset, Listing][] = []
const invalidPrices: [WalletAsset, Listing][] = []
for (const asset of sellAssets) {
if (asset.newListings) {
for (const listing of asset.newListings) {
if (!listing.price) listingsMissingPrice.push([asset, listing])
else if (isNaN(listing.price) || listing.price < 0) invalidPrices.push([asset, listing])
else if (
listing.price < (asset?.floorPrice ?? 0) * BELOW_FLOOR_PRICE_THRESHOLD &&
!listing.overrideFloorPrice
)
listingsBelowFloor.push([asset, listing])
else if (asset.floor_sell_order_price && listing.price >= asset.floor_sell_order_price)
listingsAboveSellOrderFloor.push([asset, listing])
}
}
}
// set number of issues // set number of issues
const foundIssues = const foundIssues =
......
...@@ -4,7 +4,12 @@ import Column from 'components/Column' ...@@ -4,7 +4,12 @@ import Column from 'components/Column'
import Row from 'components/Row' import Row from 'components/Row'
import { MouseoverTooltip } from 'components/Tooltip' import { MouseoverTooltip } from 'components/Tooltip'
import { RowsCollpsedIcon, RowsExpandedIcon } from 'nft/components/icons' import { RowsCollpsedIcon, RowsExpandedIcon } from 'nft/components/icons'
import { getRoyalty, useHandleGlobalPriceToggle, useSyncPriceWithGlobalMethod } from 'nft/components/profile/list/utils' import {
getMarketplaceFee,
getRoyalty,
useHandleGlobalPriceToggle,
useSyncPriceWithGlobalMethod,
} from 'nft/components/profile/list/utils'
import { useSellAsset } from 'nft/hooks' import { useSellAsset } from 'nft/hooks'
import { ListingMarket, WalletAsset } from 'nft/types' import { ListingMarket, WalletAsset } from 'nft/types'
import { formatEth, formatUsdPrice } from 'nft/utils/currency' import { formatEth, formatUsdPrice } from 'nft/utils/currency'
...@@ -150,11 +155,11 @@ export const MarketplaceRow = ({ ...@@ -150,11 +155,11 @@ export const MarketplaceRow = ({
const fees = useMemo(() => { const fees = useMemo(() => {
if (selectedMarkets.length === 1) { if (selectedMarkets.length === 1) {
return getRoyalty(selectedMarkets[0], asset) + selectedMarkets[0].fee return getRoyalty(selectedMarkets[0], asset) + getMarketplaceFee(selectedMarkets[0], asset)
} else { } else {
let max = 0 let max = 0
for (const selectedMarket of selectedMarkets) { for (const selectedMarket of selectedMarkets) {
const fee = selectedMarket.fee + getRoyalty(selectedMarket, asset) const fee = getRoyalty(selectedMarket, asset) + getMarketplaceFee(selectedMarket, asset)
max = Math.max(fee, max) max = Math.max(fee, max)
} }
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import Column from 'components/Column' import Column from 'components/Column'
import Row from 'components/Row' import Row from 'components/Row'
import { getRoyalty } from 'nft/components/profile/list/utils' import { getMarketplaceFee, getRoyalty } from 'nft/components/profile/list/utils'
import { ListingMarket, WalletAsset } from 'nft/types' import { ListingMarket, WalletAsset } from 'nft/types'
import { formatEth } from 'nft/utils' import { formatEth } from 'nft/utils'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
...@@ -63,7 +63,7 @@ export const RoyaltyTooltip = ({ ...@@ -63,7 +63,7 @@ export const RoyaltyTooltip = ({
<Trans>fee</Trans> <Trans>fee</Trans>
</ThemedText.Caption> </ThemedText.Caption>
</Row> </Row>
<FeePercent>{market.fee}%</FeePercent> <FeePercent>{getMarketplaceFee(market, asset)}%</FeePercent>
</FeeWrap> </FeeWrap>
))} ))}
<FeeWrap> <FeeWrap>
......
import type { JsonRpcSigner, Web3Provider } from '@ethersproject/providers' import type { JsonRpcSigner, Web3Provider } from '@ethersproject/providers'
import { addressesByNetwork, SupportedChainId } from '@looksrare/sdk' import { addressesByNetwork, SupportedChainId } from '@looksrare/sdk'
import { NftStandard } from 'graphql/data/__generated__/types-and-hooks'
import ms from 'ms.macro'
import { SetPriceMethod, WarningType } from 'nft/components/profile/list/shared' import { SetPriceMethod, WarningType } from 'nft/components/profile/list/shared'
import { useNFTList, useSellAsset } from 'nft/hooks' import { useNFTList, useSellAsset } from 'nft/hooks'
import { LOOKSRARE_MARKETPLACE_CONTRACT, X2Y2_TRANSFER_CONTRACT } from 'nft/queries' import {
LOOKSRARE_MARKETPLACE_CONTRACT_721,
LOOKSRARE_MARKETPLACE_CONTRACT_1155,
X2Y2_TRANSFER_CONTRACT_721,
X2Y2_TRANSFER_CONTRACT_1155,
} from 'nft/queries'
import { OPENSEA_CROSS_CHAIN_CONDUIT } from 'nft/queries/openSea' import { OPENSEA_CROSS_CHAIN_CONDUIT } from 'nft/queries/openSea'
import { CollectionRow, ListingMarket, ListingRow, ListingStatus, WalletAsset } from 'nft/types' import { CollectionRow, Listing, ListingMarket, ListingRow, ListingStatus, WalletAsset } from 'nft/types'
import { approveCollection, LOOKS_RARE_CREATOR_BASIS_POINTS, signListing } from 'nft/utils/listNfts' import { approveCollection, LOOKS_RARE_CREATOR_BASIS_POINTS, signListing } from 'nft/utils/listNfts'
import { Dispatch, useEffect } from 'react' import { Dispatch, useEffect } from 'react'
import { shallow } from 'zustand/shallow' import { shallow } from 'zustand/shallow'
...@@ -20,19 +27,27 @@ export async function approveCollectionRow( ...@@ -20,19 +27,27 @@ export async function approveCollectionRow(
) { ) {
const callback = () => approveCollectionRow(collectionRow, signer, setCollectionStatusAndCallback) const callback = () => approveCollectionRow(collectionRow, signer, setCollectionStatusAndCallback)
setCollectionStatusAndCallback(collectionRow, ListingStatus.SIGNING, callback) setCollectionStatusAndCallback(collectionRow, ListingStatus.SIGNING, callback)
const { marketplace, collectionAddress } = collectionRow const { marketplace, collectionAddress, nftStandard } = collectionRow
const addresses = addressesByNetwork[SupportedChainId.MAINNET] const addresses = addressesByNetwork[SupportedChainId.MAINNET]
const spender = const spender =
marketplace.name === 'OpenSea' marketplace.name === 'OpenSea'
? OPENSEA_CROSS_CHAIN_CONDUIT ? OPENSEA_CROSS_CHAIN_CONDUIT
: marketplace.name === 'Rarible' : marketplace.name === 'LooksRare'
? LOOKSRARE_MARKETPLACE_CONTRACT ? collectionRow.nftStandard === NftStandard.Erc721
? LOOKSRARE_MARKETPLACE_CONTRACT_721
: LOOKSRARE_MARKETPLACE_CONTRACT_1155
: marketplace.name === 'X2Y2' : marketplace.name === 'X2Y2'
? X2Y2_TRANSFER_CONTRACT ? collectionRow.nftStandard === NftStandard.Erc721
? X2Y2_TRANSFER_CONTRACT_721
: X2Y2_TRANSFER_CONTRACT_1155
: addresses.TRANSFER_MANAGER_ERC721 : addresses.TRANSFER_MANAGER_ERC721
!!collectionAddress && !!collectionAddress &&
(await approveCollection(spender, collectionAddress, signer, (newStatus: ListingStatus) => (await approveCollection(
setCollectionStatusAndCallback(collectionRow, newStatus, callback) spender,
collectionAddress,
signer,
(newStatus: ListingStatus) => setCollectionStatusAndCallback(collectionRow, newStatus, callback),
nftStandard
)) ))
} }
...@@ -100,6 +115,7 @@ const getListings = (sellAssets: WalletAsset[]): [CollectionRow[], ListingRow[]] ...@@ -100,6 +115,7 @@ const getListings = (sellAssets: WalletAsset[]): [CollectionRow[], ListingRow[]]
collectionAddress: asset.asset_contract.address, collectionAddress: asset.asset_contract.address,
isVerified: asset.collectionIsVerified, isVerified: asset.collectionIsVerified,
marketplace, marketplace,
nftStandard: asset.asset_contract.tokenType,
} }
newCollectionsToApprove.push(newCollectionRow) newCollectionsToApprove.push(newCollectionRow)
} }
...@@ -183,14 +199,75 @@ export function useUpdateInputAndWarnings( ...@@ -183,14 +199,75 @@ export function useUpdateInputAndWarnings(
const price = listPrice ?? 0 const price = listPrice ?? 0
inputRef.current.value = `${price}` inputRef.current.value = `${price}`
if (price < (asset?.floorPrice ?? 0) && price > 0) setWarningType(WarningType.BELOW_FLOOR) if (price < (asset?.floorPrice ?? 0) && price > 0) setWarningType(WarningType.BELOW_FLOOR)
else if (asset.floor_sell_order_price && price >= asset.floor_sell_order_price) else if (
asset.floor_sell_order_price &&
price >= asset.floor_sell_order_price &&
asset.asset_contract.tokenType !== NftStandard.Erc1155
)
setWarningType(WarningType.ALREADY_LISTED) setWarningType(WarningType.ALREADY_LISTED)
}, [asset?.floorPrice, asset.floor_sell_order_price, inputRef, listPrice, setWarningType]) }, [
asset.asset_contract.tokenType,
asset?.floorPrice,
asset.floor_sell_order_price,
inputRef,
listPrice,
setWarningType,
])
} }
export const getRoyalty = (listingMarket: ListingMarket, asset: WalletAsset) => { export const getRoyalty = (listingMarket: ListingMarket, asset: WalletAsset) => {
// LooksRare is a unique case where royalties for creators are a flat 0.5% or 50 basis points // LooksRare is a unique case where royalties for creators are a flat 0.5% or 50 basis points if royalty is set
const baseFee = listingMarket.name === 'LooksRare' ? LOOKS_RARE_CREATOR_BASIS_POINTS : asset.basisPoints ?? 0 const baseFee =
listingMarket.name === 'LooksRare'
? asset.basisPoints
? LOOKS_RARE_CREATOR_BASIS_POINTS
: 0
: asset.basisPoints ?? 0
return baseFee * 0.01 return baseFee * 0.01
} }
// OpenSea has a 0.5% fee for all assets that do not have a royalty set
export const getMarketplaceFee = (listingMarket: ListingMarket, asset: WalletAsset) => {
return listingMarket.name === 'OpenSea' && !asset.basisPoints ? 0.5 : listingMarket.fee
}
const BELOW_FLOOR_PRICE_THRESHOLD = 0.8
export const findListingIssues = (sellAssets: WalletAsset[]) => {
const missingExpiration = sellAssets.some((asset) => {
return (
asset.expirationTime != null &&
(isNaN(asset.expirationTime) || asset.expirationTime * 1000 - Date.now() < ms`60 seconds`)
)
})
const overMaxExpiration = sellAssets.some((asset) => {
return asset.expirationTime != null && asset.expirationTime * 1000 - Date.now() > ms`180 days`
})
const listingsMissingPrice: [WalletAsset, Listing][] = []
const listingsBelowFloor: [WalletAsset, Listing][] = []
const listingsAboveSellOrderFloor: [WalletAsset, Listing][] = []
for (const asset of sellAssets) {
if (asset.newListings) {
for (const listing of asset.newListings) {
if (!listing.price) listingsMissingPrice.push([asset, listing])
else if (listing.price < (asset?.floorPrice ?? 0) * BELOW_FLOOR_PRICE_THRESHOLD && !listing.overrideFloorPrice)
listingsBelowFloor.push([asset, listing])
else if (
asset.floor_sell_order_price &&
listing.price >= asset.floor_sell_order_price &&
asset.asset_contract.tokenType !== NftStandard.Erc1155
)
listingsAboveSellOrderFloor.push([asset, listing])
}
}
}
return {
missingExpiration,
overMaxExpiration,
listingsMissingPrice,
listingsBelowFloor,
listingsAboveSellOrderFloor,
}
}
...@@ -2,7 +2,6 @@ import { Trans } from '@lingui/macro' ...@@ -2,7 +2,6 @@ import { Trans } from '@lingui/macro'
import { useTrace } from '@uniswap/analytics' import { useTrace } from '@uniswap/analytics'
import { sendAnalyticsEvent } from '@uniswap/analytics' import { sendAnalyticsEvent } from '@uniswap/analytics'
import { NFTEventName } from '@uniswap/analytics-events' import { NFTEventName } from '@uniswap/analytics-events'
import { NftStandard } from 'graphql/data/__generated__/types-and-hooks'
import { NftCard, NftCardDisplayProps } from 'nft/components/card' import { NftCard, NftCardDisplayProps } from 'nft/components/card'
import { VerifiedIcon } from 'nft/components/icons' import { VerifiedIcon } from 'nft/components/icons'
import { useBag, useIsMobile, useSellAsset } from 'nft/hooks' import { useBag, useIsMobile, useSellAsset } from 'nft/hooks'
...@@ -59,7 +58,7 @@ export const ViewMyNftsAsset = ({ ...@@ -59,7 +58,7 @@ export const ViewMyNftsAsset = ({
toggleCart() toggleCart()
} }
const isDisabled = asset.asset_contract.tokenType === NftStandard.Erc1155 || asset.susFlag const isDisabled = asset.susFlag
const display: NftCardDisplayProps = useMemo(() => { const display: NftCardDisplayProps = useMemo(() => {
return { return {
......
export const LOOKSRARE_MARKETPLACE_CONTRACT = '0x59728544B08AB483533076417FbBB2fD0B17CE3a' export const LOOKSRARE_MARKETPLACE_CONTRACT_721 = '0x59728544B08AB483533076417FbBB2fD0B17CE3a'
export const LOOKSRARE_MARKETPLACE_CONTRACT_1155 = '0xfed24ec7e22f573c2e08aef55aa6797ca2b3a051'
export const OPENSEA_FEE_ADDRESS = '0x0000a26b00c1F0DF003000390027140000fAa719'
export const OPENSEA_DEFAULT_CROSS_CHAIN_CONDUIT_KEY = export const OPENSEA_DEFAULT_CROSS_CHAIN_CONDUIT_KEY =
'0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000' '0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000'
export const OPENSEA_CROSS_CHAIN_CONDUIT = '0x1e0049783f008a0085193e00003d00cd54003c71' export const OPENSEA_CROSS_CHAIN_CONDUIT = '0x1e0049783f008a0085193e00003d00cd54003c71'
......
import { OrderPayload } from '../../utils/x2y2' import { OrderPayload } from '../../utils/x2y2'
export const X2Y2_TRANSFER_CONTRACT = '0xf849de01b080adc3a814fabe1e2087475cf2e354' export const X2Y2_TRANSFER_CONTRACT_721 = '0xf849de01b080adc3a814fabe1e2087475cf2e354'
export const X2Y2_TRANSFER_CONTRACT_1155 = '0x024ac22acdb367a3ae52a3d94ac6649fdc1f0779'
export const newX2Y2Order = async (payload: OrderPayload): Promise<boolean> => { export const newX2Y2Order = async (payload: OrderPayload): Promise<boolean> => {
const body = JSON.stringify(payload) const body = JSON.stringify(payload)
......
...@@ -105,6 +105,7 @@ export interface CollectionRow extends AssetRow { ...@@ -105,6 +105,7 @@ export interface CollectionRow extends AssetRow {
collectionAddress?: string collectionAddress?: string
isVerified?: boolean isVerified?: boolean
marketplace: ListingMarket marketplace: ListingMarket
nftStandard?: NftStandard
} }
// Creating this as an enum and not boolean as we will likely have a success screen state to show // Creating this as an enum and not boolean as we will likely have a success screen state to show
......
...@@ -8,17 +8,20 @@ import { Seaport } from '@opensea/seaport-js' ...@@ -8,17 +8,20 @@ import { Seaport } from '@opensea/seaport-js'
import { ItemType } from '@opensea/seaport-js/lib/constants' import { ItemType } from '@opensea/seaport-js/lib/constants'
import { ConsiderationInputItem } from '@opensea/seaport-js/lib/types' import { ConsiderationInputItem } from '@opensea/seaport-js/lib/types'
import { ZERO_ADDRESS } from 'constants/misc' import { ZERO_ADDRESS } from 'constants/misc'
import { NftStandard } from 'graphql/data/__generated__/types-and-hooks'
import { import {
OPENSEA_DEFAULT_CROSS_CHAIN_CONDUIT_KEY, OPENSEA_DEFAULT_CROSS_CHAIN_CONDUIT_KEY,
OPENSEA_FEE_ADDRESS,
OPENSEA_KEY_TO_CONDUIT, OPENSEA_KEY_TO_CONDUIT,
OPENSEA_SEAPORT_V1_4_CONTRACT, OPENSEA_SEAPORT_V1_4_CONTRACT,
} from 'nft/queries/openSea' } from 'nft/queries/openSea'
import ERC721 from '../../abis/erc721.json' import ERC721 from '../../abis/erc721.json'
import ERC1155 from '../../abis/erc1155.json'
import { import {
createLooksRareOrder, createLooksRareOrder,
getOrderId, getOrderId,
LOOKSRARE_MARKETPLACE_CONTRACT, LOOKSRARE_MARKETPLACE_CONTRACT_721,
newX2Y2Order, newX2Y2Order,
PostOpenSeaSellOrder, PostOpenSeaSellOrder,
} from '../queries' } from '../queries'
...@@ -60,15 +63,18 @@ const getConsiderationItems = ( ...@@ -60,15 +63,18 @@ const getConsiderationItems = (
): { ): {
sellerFee: ConsiderationInputItem sellerFee: ConsiderationInputItem
creatorFee?: ConsiderationInputItem creatorFee?: ConsiderationInputItem
openSeaFee?: ConsiderationInputItem
} => { } => {
const creatorFeeBasisPoints = asset?.basisPoints ?? 0 const creatorFeeBasisPoints = asset?.basisPoints ?? 0
const sellerBasisPoints = INVERSE_BASIS_POINTS - creatorFeeBasisPoints const openSeaBasisPoints = !asset?.basisPoints ? 50 : 0
const sellerBasisPoints = INVERSE_BASIS_POINTS - creatorFeeBasisPoints - openSeaBasisPoints
const creatorFee = price const creatorFee = price
.mul(BigNumber.from(creatorFeeBasisPoints)) .mul(BigNumber.from(creatorFeeBasisPoints))
.div(BigNumber.from(INVERSE_BASIS_POINTS)) .div(BigNumber.from(INVERSE_BASIS_POINTS))
.toString() .toString()
const sellerFee = price.mul(BigNumber.from(sellerBasisPoints)).div(BigNumber.from(INVERSE_BASIS_POINTS)).toString() const sellerFee = price.mul(BigNumber.from(sellerBasisPoints)).div(BigNumber.from(INVERSE_BASIS_POINTS)).toString()
const openSeaFee = price.mul(BigNumber.from(openSeaBasisPoints)).div(BigNumber.from(INVERSE_BASIS_POINTS)).toString()
return { return {
sellerFee: createConsiderationItem(sellerFee, signerAddress), sellerFee: createConsiderationItem(sellerFee, signerAddress),
...@@ -76,6 +82,7 @@ const getConsiderationItems = ( ...@@ -76,6 +82,7 @@ const getConsiderationItems = (
creatorFeeBasisPoints > 0 creatorFeeBasisPoints > 0
? createConsiderationItem(creatorFee, asset?.asset_contract?.payout_address ?? '') ? createConsiderationItem(creatorFee, asset?.asset_contract?.payout_address ?? '')
: undefined, : undefined,
openSeaFee: openSeaBasisPoints ? createConsiderationItem(openSeaFee, OPENSEA_FEE_ADDRESS) : undefined,
} }
} }
...@@ -83,22 +90,21 @@ export async function approveCollection( ...@@ -83,22 +90,21 @@ export async function approveCollection(
operator: string, operator: string,
collectionAddress: string, collectionAddress: string,
signer: Signer, signer: Signer,
setStatus: (newStatus: ListingStatus) => void setStatus: (newStatus: ListingStatus) => void,
nftStandard: NftStandard = NftStandard.Erc721
): Promise<void> { ): Promise<void> {
// This will work for both 721s & 1155s because they both have the const contract = new Contract(collectionAddress, nftStandard === NftStandard.Erc721 ? ERC721 : ERC1155, signer)
// setApprovalForAll() method
const ERC721Contract = new Contract(collectionAddress, ERC721, signer)
const signerAddress = await signer.getAddress() const signerAddress = await signer.getAddress()
try { try {
const approved = await ERC721Contract.isApprovedForAll(signerAddress, operator) const approved = await contract.isApprovedForAll(signerAddress, operator)
if (approved) { if (approved) {
setStatus(ListingStatus.APPROVED) setStatus(ListingStatus.APPROVED)
return return
} }
setStatus(ListingStatus.SIGNING) setStatus(ListingStatus.SIGNING)
const approvalTransaction = await ERC721Contract.setApprovalForAll(operator, true) const approvalTransaction = await contract.setApprovalForAll(operator, true)
setStatus(ListingStatus.PENDING) setStatus(ListingStatus.PENDING)
const tx = await approvalTransaction.wait() const tx = await approvalTransaction.wait()
...@@ -133,8 +139,8 @@ export async function signListing( ...@@ -133,8 +139,8 @@ export async function signListing(
case 'OpenSea': case 'OpenSea':
try { try {
const listingInWei = parseEther(`${listingPrice}`) const listingInWei = parseEther(`${listingPrice}`)
const { sellerFee, creatorFee } = getConsiderationItems(asset, listingInWei, signerAddress) const { sellerFee, creatorFee, openSeaFee } = getConsiderationItems(asset, listingInWei, signerAddress)
const considerationItems = [sellerFee, creatorFee].filter( const considerationItems = [sellerFee, creatorFee, openSeaFee].filter(
(item): item is ConsiderationInputItem => item !== undefined (item): item is ConsiderationInputItem => item !== undefined
) )
...@@ -142,9 +148,10 @@ export async function signListing( ...@@ -142,9 +148,10 @@ export async function signListing(
{ {
offer: [ offer: [
{ {
itemType: ItemType.ERC721, itemType: asset.asset_contract.tokenType === NftStandard.Erc721 ? ItemType.ERC721 : ItemType.ERC1155,
token: asset.asset_contract.address, token: asset.asset_contract.address,
identifier: asset.tokenId, identifier: asset.tokenId,
amount: '1',
}, },
], ],
consideration: considerationItems, consideration: considerationItems,
...@@ -206,7 +213,7 @@ export async function signListing( ...@@ -206,7 +213,7 @@ export async function signListing(
signer, signer,
SupportedChainId.MAINNET, SupportedChainId.MAINNET,
makerOrder, makerOrder,
LOOKSRARE_MARKETPLACE_CONTRACT LOOKSRARE_MARKETPLACE_CONTRACT_721
) )
setStatus(ListingStatus.PENDING) setStatus(ListingStatus.PENDING)
const payload = { const payload = {
...@@ -241,10 +248,11 @@ export async function signListing( ...@@ -241,10 +248,11 @@ export async function signListing(
{ {
token: asset.asset_contract.address, token: asset.asset_contract.address,
tokenId: BigNumber.from(asset.tokenId), tokenId: BigNumber.from(asset.tokenId),
amount: 1,
}, },
], ],
} }
const order = createSellOrder(signerAddress, asset.expirationTime, [orderItem]) const order = createSellOrder(signerAddress, asset.expirationTime, [orderItem], asset.asset_contract.tokenType)
try { try {
const prevOrderId = await getOrderId(asset.asset_contract.address, asset.tokenId) const prevOrderId = await getOrderId(asset.asset_contract.address, asset.tokenId)
await signOrderData(provider, order) await signOrderData(provider, order)
......
...@@ -5,8 +5,9 @@ import { AddressZero } from '@ethersproject/constants' ...@@ -5,8 +5,9 @@ import { AddressZero } from '@ethersproject/constants'
import { keccak256 } from '@ethersproject/keccak256' import { keccak256 } from '@ethersproject/keccak256'
import type { Web3Provider } from '@ethersproject/providers' import type { Web3Provider } from '@ethersproject/providers'
import { randomBytes } from '@ethersproject/random' import { randomBytes } from '@ethersproject/random'
import { NftStandard } from 'graphql/data/__generated__/types-and-hooks'
const dataParamType = `tuple(address token, uint256 tokenId)[]` const dataParamType = `tuple(address token, uint256 tokenId, uint256 amount)[]`
const orderItemParamType = `tuple(uint256 price, bytes data)` const orderItemParamType = `tuple(uint256 price, bytes data)`
const orderParamTypes = [ const orderParamTypes = [
`uint256`, `uint256`,
...@@ -27,6 +28,7 @@ export type OfferItem = { ...@@ -27,6 +28,7 @@ export type OfferItem = {
tokens: { tokens: {
token: string token: string
tokenId: BigNumberish tokenId: BigNumberish
amount: number
}[] }[]
} }
...@@ -67,7 +69,7 @@ const randomSalt = () => { ...@@ -67,7 +69,7 @@ const randomSalt = () => {
return hexZeroPad(randomHex, 64) return hexZeroPad(randomHex, 64)
} }
const encodeItemData = (data: { token: string; tokenId: BigNumberish }[]) => { const encodeItemData = (data: { token: string; tokenId: BigNumberish; amount: number }[]) => {
return defaultAbiCoder.encode([dataParamType], [data]) return defaultAbiCoder.encode([dataParamType], [data])
} }
...@@ -105,11 +107,16 @@ export const encodeOrder = (order: Order): string => { ...@@ -105,11 +107,16 @@ export const encodeOrder = (order: Order): string => {
return defaultAbiCoder.encode([orderParamType], [order]) return defaultAbiCoder.encode([orderParamType], [order])
} }
export const createSellOrder = (user: string, deadline: number, items: OfferItem[]): Order => { export const createSellOrder = (
user: string,
deadline: number,
items: OfferItem[],
nftStandard: NftStandard = NftStandard.Erc721
): Order => {
const salt = randomSalt() const salt = randomSalt()
const network = 1 // mainnet const network = 1 // mainnet
const intent = 1 // INTENT_SELL const intent = 1 // INTENT_SELL
const delegateType = 1 // DELEGATION_TYPE_ERC721 const delegateType = nftStandard === NftStandard.Erc721 ? 1 : 2
const currency = AddressZero // ETH const currency = AddressZero // ETH
return { return {
salt, salt,
......
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