Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions web/app/(general)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,23 @@ import { FADE_DOWN_ANIMATION_VARIANTS } from '@/config/design'
import { DEPLOY_URL, siteConfig } from '@/config/site'
import { turboIntegrations } from '@/data/turbo-integrations'
import erc20TokenSymbolToAddress from '@/lib/erc20TokenSymbolToAddress'
import { HypercertCreateForm } from '@/components/hypercert/hypercert-create'

export default function Home() {
const props = {
children: {
type: 'slot',
defaultValue: {
type: 'text',
value: 'Placeholder',
},
},
}

return (
<>
<div>
Hello World!!!
</div>
<HypercertCreateForm />
<>Hello World</>
</>
)
}
}
45 changes: 45 additions & 0 deletions web/components/hypercert/claim-all-fractions-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Button } from '@mui/material'
import { useRouter } from 'next/router'

import { useAccountLowerCase } from '../../hooks/hypercert/account'
import { useGetAllEligibility, useMintFractionAllowlistBatch } from '../../hooks/hypercert/mintFractionAllowlistBatch'

const LOCALSTORAGE_KEY = 'claimAllFractionsTime'
const DELAY = 5 * 60 * 1000 // 5 minutes
export const claimedRecently = () => {
// Check if we need to wait (been less than DELAY since last claim)
const lastClaimStr = localStorage.getItem(LOCALSTORAGE_KEY)
const needToWait = lastClaimStr ? Date.now() < parseInt(lastClaimStr) + DELAY : false
return needToWait
}

export const ClaimAllFractionsButton = ({
className,
text = 'Claim all fractions',
disabled,
}: {
className?: string
text: string
disabled?: boolean
}) => {
const { address } = useAccountLowerCase()

const router = useRouter()
const { data: claimIds } = useGetAllEligibility(address ?? '')
const { write } = useMintFractionAllowlistBatch({
onComplete: () => {
console.log('Minted all of them')
// Store the current time
window.localStorage.setItem(LOCALSTORAGE_KEY, `${Date.now()}`)
router.reload()
},
})

return (
<Button disabled={!claimIds?.length || disabled} className={className} onClick={() => write()} variant="outlined" size="small">
{text}
</Button>
)
}

export default ClaimAllFractionsButton
70 changes: 70 additions & 0 deletions web/components/hypercert/contract-interaction-dialog-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { PropsWithChildren, useContext, useState } from 'react'

import { Box, Dialog, DialogContent, DialogContentText, DialogTitle, Step, StepLabel, Stepper } from '@mui/material'

type StepDescriptions = Record<string, string>

interface IContractInteractionModalProvider {
showModal: (args: { stepDescriptions: StepDescriptions }) => void
setStep: (step: string) => void
hideModal: () => void
}

const ContractInteractionDialogContext = React.createContext<IContractInteractionModalProvider>({
showModal: () => {}, // eslint-disable-line
setStep: () => {}, // eslint-disable-line
hideModal: () => {}, // eslint-disable-line
})

export const ContractInteractionDialogProvider: React.FC<PropsWithChildren> = ({ children }) => {
const [showContractModal, setShowContractModal] = useState(false)
const [stepDescriptions, setStepDescriptions] = useState<StepDescriptions>({})
const [step, setStep] = useState<string>()

const onShowModal = (args: { stepDescriptions: StepDescriptions }) => {
setStepDescriptions(args.stepDescriptions)
setShowContractModal(true)
}

const onCloseModal = () => {
setStep(undefined)
setStepDescriptions({})
setShowContractModal(false)
}

return (
<ContractInteractionDialogContext.Provider
value={{
setStep,
showModal: onShowModal,
hideModal: onCloseModal,
}}>
{children}
<Dialog
open={showContractModal}
onClose={() => {
console.log('Manual closing of dialog disabled')
}}
disableEscapeKeyDown={true}
fullWidth={true}>
<DialogTitle>Contract interaction</DialogTitle>

<DialogContent>
<DialogContentText>Please keep this tab open until completion</DialogContentText>
</DialogContent>

<Box sx={{ px: 3, pb: 3 }}>
<Stepper orientation="vertical" activeStep={step ? Object.keys(stepDescriptions).indexOf(step) : 0}>
{Object.keys(stepDescriptions).map((key) => (
<Step key={key} classes={{}}>
<StepLabel>{stepDescriptions[key]}</StepLabel>
</Step>
))}
</Stepper>
</Box>
</Dialog>
</ContractInteractionDialogContext.Provider>
)
}

export const useContractModal = () => useContext(ContractInteractionDialogContext)
108 changes: 108 additions & 0 deletions web/components/hypercert/dapp-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import '@rainbow-me/rainbowkit/styles.css'

import React, { ReactNode } from 'react'

import { PlasmicCanvasContext } from '@plasmicapp/loader-nextjs'
import { DataProvider } from '@plasmicapp/loader-nextjs'
import { RainbowKitProvider, getDefaultWallets } from '@rainbow-me/rainbowkit'
import { QueryClient } from '@tanstack/query-core'
import { QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { Chain, WagmiConfig, configureChains, createClient, useNetwork } from 'wagmi'
import { goerli, hardhat, mainnet, optimism, sepolia } from 'wagmi/chains'
import { publicProvider } from 'wagmi/providers/public'

import { claimedRecently } from './claim-all-fractions-button'
import { ContractInteractionDialogProvider } from './contract-interaction-dialog-context'
import { useAccountLowerCase } from '../../hooks/hypercert/account'
import { DEFAULT_CHAIN_ID } from '../../lib/hypercert/config'

const DAPP_CONTEXT_NAME = 'DappContext'

const queryClient = new QueryClient({})
const ALL_CHAINS = [mainnet, goerli, sepolia, optimism, hardhat]
const { provider, webSocketProvider, chains } = configureChains(ALL_CHAINS, [publicProvider()])

const { connectors } = getDefaultWallets({
appName: 'Hypercerts',
chains,
})

const wagmiClient = createClient({
autoConnect: true,
provider,
webSocketProvider,
connectors,
})

export interface DappContextData {
myAddress?: string
defaultChainId?: string
chain?: Chain
chains?: Chain[]
waitToClaim?: boolean
}

export const DEFAULT_TEST_DATA: DappContextData = {
myAddress: '0x22E4b9b003Cc7B7149CF2135dfCe2BaddC7a534f'.toLowerCase(),
defaultChainId: '5',
chain: goerli,
chains: ALL_CHAINS,
waitToClaim: false,
}

export interface DappContextProps {
className?: string // Plasmic CSS class
children?: ReactNode // Shown by default or if wallet is connected
notConnected?: ReactNode // Shown if wallet is not connected and `showIfNotConnected` is true
showIfNotConnected?: boolean // Show `notConnected` if wallet is not connected
testData?: DappContextData // Test data for
useTestData?: boolean //
}

export function DappContext(props: DappContextProps) {
const { className, children, notConnected, showIfNotConnected, testData, useTestData } = props
const [waitToClaim, setWaitToClaim] = React.useState(false)

const inEditor = React.useContext(PlasmicCanvasContext)
const { address } = useAccountLowerCase()
const { chain, chains } = useNetwork()
const data: DappContextData =
useTestData && testData && inEditor
? testData
: {
myAddress: address,
chain,
chains,
defaultChainId: DEFAULT_CHAIN_ID,
waitToClaim,
}

React.useEffect(() => {
// Reaches into window.localStorage, so doing it within a useEffect
setWaitToClaim(claimedRecently())
})

if (showIfNotConnected && !data.myAddress && notConnected) {
return <div className={className}> {notConnected} </div>
}

return (
<div className={className}>
<QueryClientProvider client={queryClient}>
<WagmiConfig client={wagmiClient}>
<RainbowKitProvider chains={chains}>
<DataProvider name={DAPP_CONTEXT_NAME} data={data}>
<ContractInteractionDialogProvider>
{children}
<ReactQueryDevtools initialIsOpen={false} />
</ContractInteractionDialogProvider>
</DataProvider>
</RainbowKitProvider>
</WagmiConfig>
</QueryClientProvider>
</div>
)
}

export default DappContext
Loading