From c8c3a4c87b33df58818729a39e0a488a3f426c72 Mon Sep 17 00:00:00 2001 From: samuelea Date: Tue, 10 Dec 2024 17:52:23 -0500 Subject: [PATCH] fix checkout options --- examples/react/src/components/Connected.tsx | 75 +++++++++++-------- examples/react/src/config.ts | 17 +++++ .../hooks/useCheckoutOptionsSalesContract.ts | 7 +- .../hooks/useERC1155SaleContractCheckout.ts | 34 ++++++--- .../src/hooks/useMarketplaceClient.ts | 9 +-- packages/checkout/src/index.ts | 1 + 6 files changed, 94 insertions(+), 49 deletions(-) diff --git a/examples/react/src/components/Connected.tsx b/examples/react/src/components/Connected.tsx index 89903ae3..78f8fcaa 100644 --- a/examples/react/src/components/Connected.tsx +++ b/examples/react/src/components/Connected.tsx @@ -7,7 +7,13 @@ import { validateEthProof, getModalPositionCss } from '@0xsequence/kit' -import { useCheckoutModal, useAddFundsModal, useERC1155SaleContractPaymentModal, useSwapModal } from '@0xsequence/kit-checkout' +import { + useCheckoutModal, + useAddFundsModal, + useERC1155SaleContractPaymentModal, + useSwapModal, + useERC1155SaleContractCheckout +} from '@0xsequence/kit-checkout' import type { SwapModalSettings } from '@0xsequence/kit-checkout' import { CardButton, Header } from '@0xsequence/kit-example-shared-components' import { useOpenWalletModal } from '@0xsequence/kit-wallet' @@ -26,7 +32,7 @@ import { useWriteContract } from 'wagmi' -import { sponsoredContractAddresses } from '../config' +import { sponsoredContractAddresses, getErc1155SaleContractConfig } from '../config' import { messageToSign } from '../constants' import { abi } from '../constants/nft-abi' import { delay, getCheckoutSettings, getOrderbookCalldata } from '../utils' @@ -42,6 +48,9 @@ export const Connected = () => { const { triggerCheckout } = useCheckoutModal() const { triggerAddFunds } = useAddFundsModal() const { openERC1155SaleContractPaymentModal } = useERC1155SaleContractPaymentModal() + const { openCheckoutModal, isLoading: isLoadingCheckoutModal } = useERC1155SaleContractCheckout( + getErc1155SaleContractConfig(address || '') + ) const { data: walletClient } = useWalletClient() const storage = useStorage() @@ -331,36 +340,37 @@ export const Connected = () => { // const price = '200000000000000' // // ERC-20 contract - const currencyAddress = '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359' - const salesContractAddress = '0xe65b75eb7c58ffc0bf0e671d64d0e1c6cd0d3e5b' - const collectionAddress = '0xdeb398f41ccd290ee5114df7e498cf04fac916cb' - const price = '20000' - - const chainId = 137 - - openERC1155SaleContractPaymentModal({ - collectibles: [ - { - tokenId: '1', - quantity: '1' - } - ], - chain: chainId, - price, - targetContractAddress: salesContractAddress, - recipientAddress: address, - currencyAddress, - collectionAddress, - creditCardProviders: ['sardine'], - isDev: true, - copyrightText: 'ⓒ2024 Sequence', - onSuccess: (txnHash: string) => { - console.log('success!', txnHash) - }, - onError: (error: Error) => { - console.error(error) - } - }) + // const currencyAddress = '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359' + // const salesContractAddress = '0xe65b75eb7c58ffc0bf0e671d64d0e1c6cd0d3e5b' + // const collectionAddress = '0xdeb398f41ccd290ee5114df7e498cf04fac916cb' + // const price = '20000' + + // const chainId = 137 + + // openERC1155SaleContractPaymentModal({ + // collectibles: [ + // { + // tokenId: '1', + // quantity: '1' + // } + // ], + // chain: chainId, + // price, + // targetContractAddress: salesContractAddress, + // recipientAddress: address, + // currencyAddress, + // collectionAddress, + // creditCardProviders: ['sardine'], + // isDev: true, + // copyrightText: 'ⓒ2024 Sequence', + // onSuccess: (txnHash: string) => { + // console.log('success!', txnHash) + // }, + // onError: (error: Error) => { + // console.error(error) + // } + // }) + openCheckoutModal() } const onCheckoutInfoConfirm = () => { @@ -543,6 +553,7 @@ export const Connected = () => { title="Checkout with Sequence Pay" description="Purchase an NFT through various purchase methods" onClick={onClickSelectPayment} + isPending={isLoadingCheckoutModal} /> diff --git a/examples/react/src/config.ts b/examples/react/src/config.ts index 5ce77c06..9349f0c2 100644 --- a/examples/react/src/config.ts +++ b/examples/react/src/config.ts @@ -100,3 +100,20 @@ export const config = projectId: walletConnectProjectId } }) + +export const getErc1155SaleContractConfig = (walletAddress: string) => ({ + chain: 137, + // ERC20 token sale + contractAddress: '0xe65b75eb7c58ffc0bf0e671d64d0e1c6cd0d3e5b', + collectionAddress: '0xdeb398f41ccd290ee5114df7e498cf04fac916cb', + // Native token sale + // contractAddress: '0xf0056139095224f4eec53c578ab4de1e227b9597', + // collectionAddress: '0x92473261f2c26f2264429c451f70b0192f858795', + wallet: walletAddress, + items: [{ + tokenId: '1', + quantity: '1' + }], + onSuccess: () => { console.log('success') }, + isDev: isDebugMode +}) diff --git a/packages/checkout/src/hooks/useCheckoutOptionsSalesContract.ts b/packages/checkout/src/hooks/useCheckoutOptionsSalesContract.ts index 2b83199f..f6e4bae1 100644 --- a/packages/checkout/src/hooks/useCheckoutOptionsSalesContract.ts +++ b/packages/checkout/src/hooks/useCheckoutOptionsSalesContract.ts @@ -3,11 +3,12 @@ import { CheckoutOptionsSalesContractArgs } from '@0xsequence/marketplace' import { useMarketplaceClient } from './useMarketplaceClient' export interface UseGenerateBuyTransactionOptions { - disabled?: boolean + disabled?: boolean, + isDev?: boolean } export const useCheckoutOptionsSalesContract = (chain: number | string, args: CheckoutOptionsSalesContractArgs, options?: UseGenerateBuyTransactionOptions) => { - const marketplaceClient = useMarketplaceClient({ chain }) + const marketplaceClient = useMarketplaceClient({ chain, isDev: options?.isDev }) return useQuery({ queryKey: ['useCheckoutOptionsSalesContract', args], @@ -18,6 +19,6 @@ export const useCheckoutOptionsSalesContract = (chain: number | string, args: Ch }, retry: false, staleTime: 360 * 1000, - enabled: !options?.disabled, + enabled: !options?.disabled && !!args.wallet, }) } diff --git a/packages/checkout/src/hooks/useERC1155SaleContractCheckout.ts b/packages/checkout/src/hooks/useERC1155SaleContractCheckout.ts index 75546970..b0d365bc 100644 --- a/packages/checkout/src/hooks/useERC1155SaleContractCheckout.ts +++ b/packages/checkout/src/hooks/useERC1155SaleContractCheckout.ts @@ -1,13 +1,17 @@ import { CheckoutOptionsSalesContractArgs } from '@0xsequence/marketplace' import { findSupportedNetwork } from '@0xsequence/network' +import { TransactionSwapProvider, TransactionNFTCheckoutProvider } from '@0xsequence/marketplace' import { useERC1155SaleContractPaymentModal } from './useSelectPaymentModal' import { useCheckoutOptionsSalesContract } from "./useCheckoutOptionsSalesContract" import { ERC_1155_SALE_CONTRACT } from '../constants/abi' +import { SelectPaymentSettings } from '../contexts/SelectPaymentModal' -import { Abi, Hex } from 'viem' +import { Abi, Hex, padBytes } from 'viem' import { useReadContract, useReadContracts } from 'wagmi' +type BasePaymentModalSettings = Pick + interface UseERC1155SaleContractCheckoutArgs extends CheckoutOptionsSalesContractArgs { chain: number | string, } @@ -24,13 +28,16 @@ export const useERC1155SaleContractCheckout = ({ wallet, collectionAddress, items, -}: UseERC1155SaleContractCheckoutArgs): UseERC1155SaleContractCheckoutReturn => { + ...restArgs +}: UseERC1155SaleContractCheckoutArgs & BasePaymentModalSettings): UseERC1155SaleContractCheckoutReturn => { const { openERC1155SaleContractPaymentModal } = useERC1155SaleContractPaymentModal() - const { data: checkoutOptions, isLoading: isLoadingCheckoutOptions, isError: isErrorCheckoutOtions } = useCheckoutOptionsSalesContract(chain, { + const { data: checkoutOptions, isLoading: isLoadingCheckoutOptions, isError: isErrorCheckoutOptions } = useCheckoutOptionsSalesContract(chain, { contractAddress, wallet, collectionAddress, items + }, { + isDev: restArgs.isDev }) const network = findSupportedNetwork(chain) const chainId = network?.chainId || 137 @@ -41,7 +48,7 @@ export const useERC1155SaleContractCheckout = ({ // Get token sale data // Pass wrapper to open select modal const isLoading = isLoadingCheckoutOptions || isLoadingSaleConfig - const error = isErrorCheckoutOtions || isErrorSaleConfig + const error = isErrorCheckoutOptions || isErrorSaleConfig const openCheckoutModal = () => { if (isLoading || error) { @@ -64,6 +71,10 @@ export const useERC1155SaleContractCheckout = ({ recipientAddress: wallet, collectionAddress, targetContractAddress: contractAddress, + enableMainCurrencyPayment: true, + enableSwapPayments: checkoutOptions?.options.swap.includes(TransactionSwapProvider.zerox) || false, + creditCardProviders: checkoutOptions?.options.nftCheckout || [], + ...restArgs }) } } @@ -105,8 +116,13 @@ export const useSaleContractConfig = ({ chainId, contractAddress, tokenIds, }: U functionName: 'paymentToken', }) - // [cost, supplyCap, startTime, endTime, merkleRoot] - type SaleDetailsERC1155 = [bigint, bigint, bigint, bigint, string] + interface SaleDetailsERC1155 { + cost: bigint, + startTime: bigint, + endTime: bigint, + supplyCap: bigint, + merkleRoot: string + } const { data: globalSaleDetailsERC1155, isLoading: isLoadingGlobalSaleDetailsERC1155, isError: isErrorGlobalSaleDetailsERC1155 } = useReadContract({ chainId, @@ -150,13 +166,13 @@ export const useSaleContractConfig = ({ chainId, contractAddress, tokenIds, }: U // 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 { cost: globalCost, 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) + const tokenPrice = (tokenSaleDetailsERC1155?.[index].result as SaleDetailsERC1155)['cost'] || BigInt(0) return ({ tokenId, - price: (isGlobalSaleValid ? costERC1155 : tokenPrice).toString() + price: (isGlobalSaleValid ? globalCost : tokenPrice).toString() }) }) diff --git a/packages/checkout/src/hooks/useMarketplaceClient.ts b/packages/checkout/src/hooks/useMarketplaceClient.ts index 2ccbd799..981c7693 100644 --- a/packages/checkout/src/hooks/useMarketplaceClient.ts +++ b/packages/checkout/src/hooks/useMarketplaceClient.ts @@ -5,17 +5,16 @@ import { useMemo } from 'react' export interface UseMarketplaceClientArgs { - chain: ChainNameOrId + chain: ChainNameOrId, + isDev?: boolean } export const useMarketplaceClient = ({ - chain + chain, + isDev = false }: UseMarketplaceClientArgs) => { const projectAccessKey = useProjectAccessKey() - // TODO: move to env variable - const isDev = false - const marketplaceClient = useMemo(() => { const env = isDev ? 'development' : 'production' const clientUrl = marketplaceApiURL(chain, env) diff --git a/packages/checkout/src/index.ts b/packages/checkout/src/index.ts index 8c27b62a..f32d294c 100644 --- a/packages/checkout/src/index.ts +++ b/packages/checkout/src/index.ts @@ -8,6 +8,7 @@ export { useSelectPaymentModal, useERC1155SaleContractPaymentModal } from './hoo export { useTransferFundsModal } from './hooks/useTransferFundsModal' export { useCheckoutWhitelistStatus } from './hooks/useCheckoutWhitelistStatus' export { useSwapModal } from './hooks/useSwapModal' +export { useERC1155SaleContractCheckout } from './hooks/useERC1155SaleContractCheckout' export { type CheckoutSettings } from './contexts/CheckoutModal' export { type AddFundsSettings } from './contexts/AddFundsModal'