Skip to content

Commit

Permalink
useERC11SaleContractCheckout
Browse files Browse the repository at this point in the history
  • Loading branch information
SamueleA committed Dec 9, 2024
1 parent 38e39f4 commit 17efde8
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 194 deletions.
81 changes: 0 additions & 81 deletions packages/checkout/src/constants/abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,84 +183,3 @@ export const ERC_1155_SALE_CONTRACT = [
"stateMutability": "view"
}
]

export const ERC_721_SALE_CONTRACT = [
{
"type": "function",
"name": "mint",
"inputs": [
{
"name": "to",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "paymentToken",
"type": "address",
"internalType": "address"
},
{
"name": "maxTotal",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "proof",
"type": "bytes32[]",
"internalType": "bytes32[]"
}
],
"outputs": [],
"stateMutability": "payable"
},
{
"type": "function",
"name": "saleDetails",
"inputs": [],
"outputs": [
{
"name": "",
"type": "tuple",
"internalType": "struct IERC721SaleFunctions.SaleDetails",
"components": [
{
"name": "supplyCap",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "cost",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "paymentToken",
"type": "address",
"internalType": "address"
},
{
"name": "startTime",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "endTime",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "merkleRoot",
"type": "bytes32",
"internalType": "bytes32"
}
]
}
],
"stateMutability": "view"
},
]
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import { CheckoutOptionsSalesContractArgs } from '@0xsequence/marketplace'
import { findSupportedNetwork } from '@0xsequence/network'

import { useSelectPaymentModal } from './useSelectPaymentModal'
import { useERC1155SaleContractPaymentModal } from './useSelectPaymentModal'
import { useCheckoutOptionsSalesContract } from "./useCheckoutOptionsSalesContract"
import { ERC_1155_SALE_CONTRACT, ERC_721_SALE_CONTRACT } from '../constants/abi'
import { ERC_1155_SALE_CONTRACT } from '../constants/abi'

import { Abi, Hex } from 'viem'
import { useReadContract, useReadContracts } from 'wagmi'

interface UseSaleContractCheckoutArgs extends CheckoutOptionsSalesContractArgs {
interface UseERC1155SaleContractCheckoutArgs extends CheckoutOptionsSalesContractArgs {
chain: number | string,
tokenType: 'ERC1155' | 'ERC721'
}

interface UseSaleContractCheckoutReturn {
data?: undefined,
interface UseERC1155SaleContractCheckoutReturn {
openCheckoutModal: () => void,
isLoading: boolean,
isError: boolean
}

export const useSaleContractCheckout = ({
export const useERC1155SaleContractCheckout = ({
chain,
tokenType,
contractAddress,
wallet,
collectionAddress,
items,
}: UseSaleContractCheckoutArgs): UseSaleContractCheckoutReturn => {
}: UseERC1155SaleContractCheckoutArgs): UseERC1155SaleContractCheckoutReturn => {
const { openERC1155SaleContractPaymentModal } = useERC1155SaleContractPaymentModal()
const { data: checkoutOptions, isLoading: isLoadingCheckoutOptions, isError: isErrorCheckoutOtions } = useCheckoutOptionsSalesContract(chain, {
contractAddress,
wallet,
Expand All @@ -36,24 +35,41 @@ export const useSaleContractCheckout = ({
const network = findSupportedNetwork(chain)
const chainId = network?.chainId || 137

const { data: saleConfigData, isLoading: isLoadingSaleConfig, isError: isErrorSaleConfig } = useSaleContractConfig({ chainId, tokenType, contractAddress, tokenIds: items.map(i => i.tokenId) })
const { data: saleConfigData, isLoading: isLoadingSaleConfig, isError: isErrorSaleConfig } = useSaleContractConfig({ chainId, contractAddress, tokenIds: items.map(i => i.tokenId) })

// Get sale contract currency data...
// Get token sale data
// Pass wrapper to open select modal
const isLoading = isLoadingCheckoutOptions || isLoadingSaleConfig
const error = isErrorCheckoutOtions || isErrorSaleConfig


const openCheckoutModal = () => {
if (isLoading || error) return
if (isLoading || error) {
console.error('Error loading checkout options or sale config', { isLoading, error })
return
}

// return openCheckoutModal({
// })
return () => {
openERC1155SaleContractPaymentModal({
collectibles: items.map(item => ({
tokenId: item.tokenId,
quantity: item.quantity
})),
chain: chainId,
price: items.reduce((acc, item) => {
const price = BigInt(saleConfigData?.saleConfigs.find(sale => sale.tokenId === item.tokenId)?.price || 0)
return acc + BigInt(item.quantity) * price
}, BigInt(0)).toString(),
currencyAddress: saleConfigData?.currencyAddress || '',
recipientAddress: wallet,
collectionAddress,
targetContractAddress: contractAddress,
})
}
}

return ({
data: undefined,
openCheckoutModal,
isLoading,
isError: error
})
Expand All @@ -62,7 +78,6 @@ export const useSaleContractCheckout = ({
interface UseSaleContractConfigArgs {
chainId: number
contractAddress: string
tokenType: 'ERC1155'| 'ERC721',
tokenIds: string[]
}

Expand All @@ -82,15 +97,12 @@ interface UseSaleContractConfigReturn {
isError: boolean
}

export const useSaleContractConfig = ({ chainId, tokenType, contractAddress, tokenIds, }: UseSaleContractConfigArgs): UseSaleContractConfigReturn => {
export const useSaleContractConfig = ({ chainId, contractAddress, tokenIds, }: UseSaleContractConfigArgs): UseSaleContractConfigReturn => {
const { data: paymentTokenERC1155, isLoading: isLoadingPaymentTokenERC1155, isError: isErrorPaymentTokenERC1155 } = useReadContract({
chainId,
abi: ERC_1155_SALE_CONTRACT,
address: contractAddress as Hex,
functionName: 'paymentToken',
query: {
enabled: tokenType === 'ERC1155'
}
})

// [cost, supplyCap, startTime, endTime, merkleRoot]
Expand All @@ -101,9 +113,6 @@ export const useSaleContractConfig = ({ chainId, tokenType, contractAddress, tok
abi: ERC_1155_SALE_CONTRACT,
address: contractAddress as Hex,
functionName: 'globalSaleDetails',
query: {
enabled: tokenType === 'ERC1155'
}
})

const baseTokenSaleContract = {
Expand All @@ -120,74 +129,46 @@ export const useSaleContractConfig = ({ chainId, tokenType, contractAddress, tok

const { data: tokenSaleDetailsERC1155, isLoading: isLoadingTokenSaleDetailsERC1155, isError: isErrorTokenSaleDetailsERC1155 } = useReadContracts({
contracts: tokenSaleContracts,
query: {
enabled: tokenType === 'ERC1155'
}
})

// [supplyCap, cost, paymentToken, startTime, endTime, merkleRoot]
type SaleDetailsERC721 = [bigint, bigint, string, bigint, string, string]

const { data: saleDetailsERC721, isLoading: isLoadingSaleDetailsERC721, isError: isErrorSaleDetailsERC721 } = useReadContract({
chainId,
abi: ERC_721_SALE_CONTRACT,
address: contractAddress as Hex,
functionName: 'saleDetails',
query: {
enabled: tokenType === 'ERC721'
}
})

const isLoadingERC1155 = isLoadingPaymentTokenERC1155 || isLoadingGlobalSaleDetailsERC1155 || isLoadingTokenSaleDetailsERC1155
const isLoadingERC721 = isLoadingSaleDetailsERC721
const isErrorERC1155 = isErrorPaymentTokenERC1155 || isErrorGlobalSaleDetailsERC1155 || isErrorTokenSaleDetailsERC1155
const isErrorERC721 = isErrorSaleDetailsERC721

if (isLoadingERC1155 || isLoadingERC721 || isErrorERC1155 || isErrorERC721) {
if (isLoadingERC1155 || isErrorERC1155) {
return ({
data: undefined,
isLoading: tokenType === 'ERC1155' ? isLoadingERC1155 : isLoadingERC721,
isError: tokenType === 'ERC1155' ? isErrorERC1155 : isErrorERC721
isLoading: isLoadingERC1155,
isError: isErrorERC1155
})
}

const getSaleConfigs = (): SaleConfig[] => {
let saleInfos: SaleConfig[] = []

if (isLoadingERC1155 || isLoadingERC721 || isErrorERC1155 || isErrorERC721) return saleInfos
if (isLoadingERC1155 || isErrorERC1155 ) return saleInfos

if (tokenType === 'ERC1155') {
// In the sale contract, the global sale has priority over the token sale
// So we need to check if the global sale is set, and if it is, use that
// Otherwise, we use the token sale
const [costERC721, _, startTime, endTime] = globalSaleDetailsERC1155 as SaleDetailsERC1155
const isGlobalSaleValid = endTime === BigInt(0) || (startTime <= BigInt(Math.floor(Date.now() / 1000)) || endTime >= BigInt(Math.floor(Date.now() / 1000)))
saleInfos = tokenIds.map((tokenId, index) => {
const tokenPrice = (tokenSaleDetailsERC1155?.[index].result as SaleDetailsERC1155)[0] || BigInt(0)
return ({
tokenId,
price: (isGlobalSaleValid ? costERC721 : tokenPrice).toString()
})
})
} else {
saleInfos = tokenIds.map((tokenId, index) => {
const tokenPrice = (saleDetailsERC721 as SaleDetailsERC721)[1] || BigInt(0)
return ({
tokenId,
price: tokenPrice.toString()
})
// In the sale contract, the global sale has priority over the token sale
// So we need to check if the global sale is set, and if it is, use that
// Otherwise, we use the token sale
const [costERC1155, _, startTime, endTime] = globalSaleDetailsERC1155 as SaleDetailsERC1155
const isGlobalSaleValid = endTime === BigInt(0) || (startTime <= BigInt(Math.floor(Date.now() / 1000)) || endTime >= BigInt(Math.floor(Date.now() / 1000)))
saleInfos = tokenIds.map((tokenId, index) => {
const tokenPrice = (tokenSaleDetailsERC1155?.[index].result as SaleDetailsERC1155)[0] || BigInt(0)
return ({
tokenId,
price: (isGlobalSaleValid ? costERC1155 : tokenPrice).toString()
})
}
})

return saleInfos
}

return ({
data: {
currencyAddress: tokenType === 'ERC1155' ? (paymentTokenERC1155 as string) : (saleDetailsERC721 as SaleDetailsERC721)[2],
currencyAddress: paymentTokenERC1155 as string,
saleConfigs: getSaleConfigs()
},
isLoading: tokenType === 'ERC1155' ? isLoadingERC1155 : isLoadingERC721,
isError: tokenType === 'ERC1155' ? isErrorERC1155 : isErrorERC721
isLoading: isLoadingERC1155,
isError: isErrorERC1155
})
}
45 changes: 1 addition & 44 deletions packages/checkout/src/hooks/useSelectPaymentModal.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ethers } from 'ethers'
import { encodeFunctionData, toHex } from 'viem'

import { ERC_1155_SALE_CONTRACT, ERC_721_SALE_CONTRACT } from '../constants/abi'
import { ERC_1155_SALE_CONTRACT } from '../constants/abi'
import { SelectPaymentSettings } from '../contexts'
import { useSelectPaymentContext } from '../contexts/SelectPaymentModal'

Expand Down Expand Up @@ -55,46 +55,3 @@ export const useERC1155SaleContractPaymentModal = () => {
selectPaymentSettings
}
}

export const getERC721SaleContractConfig = ({
chain,
price,
currencyAddress = ethers.ZeroAddress,
recipientAddress,
collectibles,
collectionAddress,
isDev = false,
...restProps
}: SaleContractSettings): SelectPaymentSettings => {
const purchaseTransactionData = encodeFunctionData({
abi: ERC_721_SALE_CONTRACT,
functionName: 'mint',
// [to, amount, paymentToken, maxTotal, proof]
// args: [recipientAddress, collectibles.map(c => BigInt(c.quantity)), toHex(0), currencyAddress, price, [toHex(0, { size: 32 })]]
})

return {
chain,
price,
currencyAddress,
recipientAddress,
collectibles,
collectionAddress,
isDev,
txData: purchaseTransactionData,
...restProps
}
}

export const useERC721SaleContractPaymentModal = () => {
const { openSelectPaymentModal, closeSelectPaymentModal, selectPaymentSettings } = useSelectPaymentModal()
const openERC721SaleContractPaymentModal = (saleContractSettings: SaleContractSettings) => {
openSelectPaymentModal(getERC721SaleContractConfig(saleContractSettings))
}

return {
openERC721SaleContractPaymentModal,
closeERC721SaleContractPaymentModal: closeSelectPaymentModal,
selectPaymentSettings
}
}

0 comments on commit 17efde8

Please sign in to comment.