Skip to content

Commit

Permalink
define AnonSet context to share anon set state
Browse files Browse the repository at this point in the history
  • Loading branch information
sripwoud committed May 21, 2023
1 parent aa74615 commit af7b1c4
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 85 deletions.
21 changes: 12 additions & 9 deletions .eslintrc.yaml
@@ -1,4 +1,4 @@
extends: ['@3pwd/eslint-config-with-jest']
extends: [ '@3pwd/eslint-config-with-jest' ]
parserOptions:
project:
[
Expand All @@ -16,10 +16,10 @@ rules:
no-useless-constructor: off

overrides:
- files: ['membership/test/ProofRequest.test.ts']
- files: [ 'membership/test/ProofRequest.test.ts' ]
rules:
'@typescript-eslint/dot-notation': off
- files: ['apis/prove/src/mq/queue.ts']
- files: [ 'apis/prove/src/mq/queue.ts' ]
rules:
'@typescript-eslint/strict-boolean-expressions': off
- files:
Expand All @@ -39,19 +39,22 @@ overrides:
]
rules:
'@typescript-eslint/no-inferrable-types': off
- files: ['apis/prove/generated/*.js']
- files: [ 'apis/prove/generated/*.js' ]
rules:
eqeqeq: off
- files: ['apis/prove/generated/witness_calculator.js']
- files: [ 'apis/prove/generated/witness_calculator.js' ]
env:
browser: true
rules:
prefer-const: off
camelcase: off
- files: ['apis/prove/generated/generate_witness.js']
- files: [ 'apis/prove/generated/generate_witness.js' ]
rules:
'@typescript-eslint/no-var-requires': off
- files: ['apis/prove/src/routes.ts']
- files: [ '*.tsx' ]
rules:
'@typescript-eslint/no-misused-promises': [ error, { checksVoidReturn: { attributes: false } } ]
- files: [ 'apis/prove/src/routes.ts' ]
rules:
'@typescript-eslint/no-misused-promises': off
- files:
Expand All @@ -64,7 +67,7 @@ overrides:
]
rules:
no-console: off
- files: ['apis/query/src/decorators/Logger.ts']
- files: [ 'apis/query/src/decorators/Logger.ts' ]
rules:
'@typescript-eslint/no-explicit-any': 'off'
- files:
Expand All @@ -81,6 +84,6 @@ overrides:
]
rules:
jest/expect-expect: 'off'
- files: ['shared/src/index.ts']
- files: [ 'shared/src/index.ts' ]
rules:
'sort/exports': 'off'
12 changes: 5 additions & 7 deletions ui/src/app/layout.tsx
Expand Up @@ -4,25 +4,23 @@ import 'nes.css/css/nes.min.css'
import 'tailwindcss/tailwind.css'
import { WagmiConfig } from 'wagmi'
import { wagmiConfig } from '#/wagmi'
import useReady from '@/hooks/useReady'
import Web3Modal from '@/modals/Web3Modal'
import { Layout } from '@components'
import { AnonSetProvider } from '@context/anonset'

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
const ready = useReady()

return (
<html lang='en'>
<body className='m-3'>
{ready ? (
<WagmiConfig config={wagmiConfig}>
<WagmiConfig config={wagmiConfig}>
<AnonSetProvider>
<Layout>{children}</Layout>
</WagmiConfig>
) : null}
</AnonSetProvider>
</WagmiConfig>
<Web3Modal />
</body>
</html>
Expand Down
60 changes: 15 additions & 45 deletions ui/src/app/prove/from-file/page.tsx
@@ -1,24 +1,11 @@
'use client'
import Link from 'next/link'
import { useRef, useState } from 'react'
import { readJsonFile } from '#/read-json-file'
import { Help, ScrollableContainer } from '@components'
import { Help } from '@components'
import { AnonSetFileInput } from '@components/AnonSetFileInput'
import { useAnonSet } from '@context/anonset'

export default function Page() {
const inputRef = useRef<HTMLInputElement>(null)
const [anonSet, setAnonSet] = useState<string[]>([])
const onClick = () => {
inputRef.current?.click()
}
const onChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files !== undefined && event.target.files !== null) {
const parsedData = await readJsonFile(event.target.files[0])

setAnonSet(parsedData)
}
}

console.log({ anonSet })
const { anonSet } = useAnonSet()

return (
<div className='center flex flex-col space-y-10'>
Expand All @@ -28,36 +15,19 @@ export default function Page() {
'Upload a json file that contains an array of ethereum addresses as hex strings that represent your anon set.',
]}
/>
<Link
href={{
pathname: '/prove/submit-request',
query: { anonSet },
}}
>
<button className='nes-btn is-success'>{'=>'} Submit Proof</button>
</Link>
{anonSet.length > 0 && (
<Link
href={{
pathname: '/prove/submit-request',
query: { anonSet },
}}
>
<button className='nes-btn is-success'>{'=>'} Submit Proof</button>
</Link>
)}
</div>

{anonSet.length === 0 ? (
<>
<input
type='file'
accept='.json,application/json'
onChange={onChange}
className='hidden'
ref={inputRef}
/>
<button
type='button'
className='nes-btn is-warning w-1/4 self-center'
onClick={onClick}
>
Upload file
</button>
</>
) : (
<ScrollableContainer data={anonSet} />
)}
<AnonSetFileInput />
</div>
)
}
5 changes: 4 additions & 1 deletion ui/src/app/prove/page.tsx
@@ -1,6 +1,9 @@
'use client'
import { Screen } from '@components'
import { useAnonSet } from '@context/anonset'

export default function ProvePage() {
const { resetAnonSet: onClick } = useAnonSet()
return (
<Screen
question='Where is your anonset?'
Expand All @@ -11,7 +14,7 @@ export default function ProvePage() {
]}
buttons={[
{ href: '/prove/from-on-chain', text: 'On chain' },
{ href: '/prove/from-file', text: 'On a file' },
{ href: '/prove/from-file', onClick, text: 'On a file' },
]}
/>
)
Expand Down
4 changes: 2 additions & 2 deletions ui/src/app/prove/submit-request/page.tsx
@@ -1,5 +1,5 @@
import { SubmitProofRequest } from '@components'

export default function Page({ searchParams: { anonSet } }) {
return <SubmitProofRequest anonSet={anonSet} />
export default function Page() {
return <SubmitProofRequest />
}
42 changes: 42 additions & 0 deletions ui/src/components/AnonSetFileInput.tsx
@@ -0,0 +1,42 @@
import { useRef } from 'react'
import { readJsonFile } from '#/read-json-file'
import { ScrollableContainer } from '@components/ScrollableContainer'
import { useAnonSet } from '@context/anonset'

export function AnonSetFileInput() {
const { anonSet, setAnonSet } = useAnonSet()
const inputRef = useRef<HTMLInputElement>(null)

const onClick = () => {
inputRef.current?.click()
}

const onChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files !== undefined && event.target.files !== null) {
const parsedData = await readJsonFile(event.target.files[0])

setAnonSet(parsedData)
}
}

return anonSet.length === 0 ? (
<>
<input
type='file'
accept='.json,application/json'
onChange={onChange}
className='hidden'
ref={inputRef}
/>
<button
type='button'
className='nes-btn is-warning w-1/4 self-center'
onClick={onClick}
>
Upload file
</button>
</>
) : (
<ScrollableContainer data={anonSet} />
)
}
15 changes: 0 additions & 15 deletions ui/src/components/JsonFileInput.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion ui/src/components/Screen.tsx
Expand Up @@ -8,7 +8,7 @@ export function Screen({
}: {
question: string
help: string[]
buttons: Array<{ href: string; text: string }>
buttons: Array<{ href: string; text: string; onClick?: () => void }>
}) {
return (
<div className='flex flex-col justify-center'>
Expand Down
13 changes: 8 additions & 5 deletions ui/src/components/SubmitProofRequest.tsx
@@ -1,12 +1,16 @@
'use client'
import { useState } from 'react'
import { useRef, useState } from 'react'
import { Help, ScrollableContainer, Star } from '@components'
import { useAnonSet } from '@context/anonset'

export function SubmitProofRequest({ anonSet }) {
export function SubmitProofRequest() {
const dialogRef = useRef<HTMLDialogElement>(null)
const { anonSet } = useAnonSet()
const [message, setMessage] = useState('')
const [signedMessage, setSignedMessage] = useState('')
const canSign = message !== '' && signedMessage === ''
const canSubmit = signedMessage !== '' && anonSet?.length > 0

return (
<div className='flex flex-col space-y-10'>
<div className='self-end'>
Expand All @@ -20,12 +24,11 @@ export function SubmitProofRequest({ anonSet }) {
{anonSet?.length > 0 ? (
<a
onClick={() => {
// @ts-expect-error anonset el exists
document.getElementById('anonset').showModal()
dialogRef.current?.showModal()
}}
>
<Star full={anonSet?.length > 0} text='Anonset' />
<dialog className='nes-dialog' id='anonset'>
<dialog className='nes-dialog' id='anonset' ref={dialogRef}>
<form method='dialog'>
<ScrollableContainer data={anonSet} />
<menu className='dialog-menu flex flex-row justify-center'>
Expand Down
31 changes: 31 additions & 0 deletions ui/src/context/anonset.tsx
@@ -0,0 +1,31 @@
import { createContext, FC, ReactNode, useContext, useState } from 'react'

interface AnonSetContextType {
anonSet: string[]
setAnonSet: (anonSet: string[]) => void
resetAnonSet: () => void
}

const AnonSetContext = createContext<AnonSetContextType | null>(null)

export const useAnonSet = () => {
const context = useContext(AnonSetContext)

if (context === null)
throw new Error('useAnonSet must be used within a AnonSetProvider')

return context
}

export const AnonSetProvider: FC<{ children: ReactNode }> = ({ children }) => {
const [anonSet, setAnonSet] = useState<string[]>([])
const resetAnonSet = () => {
setAnonSet([])
}

return (
<AnonSetContext.Provider value={{ anonSet, resetAnonSet, setAnonSet }}>
{children}
</AnonSetContext.Provider>
)
}
1 change: 1 addition & 0 deletions ui/tsconfig.json
Expand Up @@ -20,6 +20,7 @@
"@/*": ["src/*"],
"@components": ["src/components"],
"@components/*": ["src/components/*"],
"@context/*": ["src/context/*"],
"@images/*": ["public/images/*"],
"#/*": ["src/lib/*"]
},
Expand Down

0 comments on commit af7b1c4

Please sign in to comment.