Whitelist txt upload component (#9)
* Update ts config * Update network chain id * Create whitelist upload component * Use whitelist component in contract ui * Add whitelist component to collection info component
This commit is contained in:
parent
7a46df8161
commit
ff5a8d2e7d
@ -1,15 +1,16 @@
|
|||||||
import { Button } from 'components/Button'
|
import { Button } from 'components/Button'
|
||||||
import { FormControl } from 'components/FormControl'
|
import { FormControl } from 'components/FormControl'
|
||||||
import { FormGroup } from 'components/FormGroup'
|
import { FormGroup } from 'components/FormGroup'
|
||||||
import { AddressList } from 'components/forms/AddressList'
|
|
||||||
import { useAddressListState } from 'components/forms/AddressList.hooks'
|
|
||||||
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||||
import { InputDateTime } from 'components/InputDateTime'
|
import { InputDateTime } from 'components/InputDateTime'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import useCollapse from 'react-collapsed'
|
import useCollapse from 'react-collapsed'
|
||||||
import { useMutation } from 'react-query'
|
import { useMutation } from 'react-query'
|
||||||
|
|
||||||
|
import { Conditional } from './Conditional'
|
||||||
import { NumberInput, TextInput } from './forms/FormInput'
|
import { NumberInput, TextInput } from './forms/FormInput'
|
||||||
|
import { JsonPreview } from './JsonPreview'
|
||||||
|
import { WhitelistUpload } from './WhitelistUpload'
|
||||||
|
|
||||||
export const CollectionInfo = () => {
|
export const CollectionInfo = () => {
|
||||||
const { getCollapseProps, getToggleProps } = useCollapse()
|
const { getCollapseProps, getToggleProps } = useCollapse()
|
||||||
@ -18,6 +19,10 @@ export const CollectionInfo = () => {
|
|||||||
const toggleProps = getToggleProps()
|
const toggleProps = getToggleProps()
|
||||||
const collapseProps = getCollapseProps()
|
const collapseProps = getCollapseProps()
|
||||||
|
|
||||||
|
const [wlstartDate, setwlStartDate] = useState<Date | undefined>(undefined)
|
||||||
|
const [wlendDate, setwlEndDate] = useState<Date | undefined>(undefined)
|
||||||
|
const [whitelistArray, setWhitelistArray] = useState<string[]>([])
|
||||||
|
|
||||||
const nameState = useInputState({
|
const nameState = useInputState({
|
||||||
id: 'name',
|
id: 'name',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
@ -86,11 +91,6 @@ export const CollectionInfo = () => {
|
|||||||
placeholder: '8',
|
placeholder: '8',
|
||||||
})
|
})
|
||||||
|
|
||||||
const [wlstartDate, setwlStartDate] = useState<Date | undefined>(undefined)
|
|
||||||
const [wlendDate, setwlEndDate] = useState<Date | undefined>(undefined)
|
|
||||||
|
|
||||||
const wladdressListState = useAddressListState()
|
|
||||||
|
|
||||||
const wlunitPriceState = useNumberInputState({
|
const wlunitPriceState = useNumberInputState({
|
||||||
id: 'unit-price',
|
id: 'unit-price',
|
||||||
name: 'unitPrice',
|
name: 'unitPrice',
|
||||||
@ -126,6 +126,10 @@ export const CollectionInfo = () => {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const whitelistFileOnChange = (data: string[]) => {
|
||||||
|
setWhitelistArray(data)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form className="grid grid-cols-2 p-4 space-x-8" onSubmit={mutate}>
|
<form className="grid grid-cols-2 p-4 space-x-8" onSubmit={mutate}>
|
||||||
@ -148,16 +152,11 @@ export const CollectionInfo = () => {
|
|||||||
Advanced
|
Advanced
|
||||||
</button>
|
</button>
|
||||||
<section {...collapseProps}>
|
<section {...collapseProps}>
|
||||||
<FormGroup subtitle="Information about your whitelisted addresses" title="Whitelist Details">
|
<FormGroup subtitle="Your whitelisted addresses" title="Whitelist File">
|
||||||
<AddressList
|
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||||
entries={wladdressListState.entries}
|
<Conditional test={whitelistArray.length > 0}>
|
||||||
isRequired
|
<JsonPreview content={whitelistArray} initialState={false} title="File Contents" />
|
||||||
onAdd={wladdressListState.add}
|
</Conditional>
|
||||||
onChange={wladdressListState.update}
|
|
||||||
onRemove={wladdressListState.remove}
|
|
||||||
subtitle="Enter the members you want in your contract"
|
|
||||||
title="Members"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup subtitle="Information about your minting settings" title="Minting Details">
|
<FormGroup subtitle="Information about your minting settings" title="Minting Details">
|
||||||
|
46
components/WhitelistUpload.tsx
Normal file
46
components/WhitelistUpload.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import clsx from 'clsx'
|
||||||
|
import React from 'react'
|
||||||
|
import { toast } from 'react-hot-toast'
|
||||||
|
|
||||||
|
interface WhitelistUploadProps {
|
||||||
|
onChange: (data: string[]) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WhitelistUpload = ({ onChange }: WhitelistUploadProps) => {
|
||||||
|
const onFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (!event.target.files) return toast.error('Error opening file')
|
||||||
|
if (event.target.files[0].type !== 'text/plain') return toast.error('Invalid file type')
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = (e: ProgressEvent<FileReader>) => {
|
||||||
|
const text = e.target?.result?.toString()
|
||||||
|
let newline = '\n'
|
||||||
|
if (text?.includes('\r')) newline = '\r'
|
||||||
|
if (text?.includes('\r\n')) newline = '\r\n'
|
||||||
|
const data = text?.split(newline)
|
||||||
|
|
||||||
|
return onChange([...new Set(data?.filter((address) => address !== '') || [])])
|
||||||
|
}
|
||||||
|
reader.readAsText(event.target.files[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'flex relative justify-center items-center mt-2 space-y-4 w-full h-32',
|
||||||
|
'rounded border-2 border-white/20 border-dashed',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
accept=".txt"
|
||||||
|
className={clsx(
|
||||||
|
'file:py-2 file:px-4 file:mr-4 file:bg-plumbus-light file:rounded file:border-0 cursor-pointer',
|
||||||
|
'before:absolute before:inset-0 before:hover:bg-white/5 before:transition',
|
||||||
|
)}
|
||||||
|
id="whitelist-file"
|
||||||
|
multiple
|
||||||
|
onChange={onFileChange}
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -19,10 +19,10 @@ export const mainnetConfig: AppConfig = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const testnetConfig: AppConfig = {
|
export const testnetConfig: AppConfig = {
|
||||||
chainId: 'stargaze',
|
chainId: 'elgafar-1',
|
||||||
chainName: 'elgafar-1',
|
chainName: 'elgafar-1',
|
||||||
addressPrefix: 'stars',
|
addressPrefix: 'stars',
|
||||||
rpcUrl: "https://rpc.elgafar-1.stargaze-apis.com/",
|
rpcUrl: 'https://rpc.elgafar-1.stargaze-apis.com/',
|
||||||
feeToken: 'ustars',
|
feeToken: 'ustars',
|
||||||
stakingToken: 'ustars',
|
stakingToken: 'ustars',
|
||||||
coinMap: {
|
coinMap: {
|
||||||
|
@ -5,14 +5,13 @@ import { Conditional } from 'components/Conditional'
|
|||||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||||
import { FormControl } from 'components/FormControl'
|
import { FormControl } from 'components/FormControl'
|
||||||
import { FormGroup } from 'components/FormGroup'
|
import { FormGroup } from 'components/FormGroup'
|
||||||
import { AddressList } from 'components/forms/AddressList'
|
|
||||||
import { useAddressListState } from 'components/forms/AddressList.hooks'
|
|
||||||
import { NumberInput } from 'components/forms/FormInput'
|
import { NumberInput } from 'components/forms/FormInput'
|
||||||
import { useNumberInputState } from 'components/forms/FormInput.hooks'
|
import { useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||||
import { InputDateTime } from 'components/InputDateTime'
|
import { InputDateTime } from 'components/InputDateTime'
|
||||||
import { JsonPreview } from 'components/JsonPreview'
|
import { JsonPreview } from 'components/JsonPreview'
|
||||||
import { LinkTabs } from 'components/LinkTabs'
|
import { LinkTabs } from 'components/LinkTabs'
|
||||||
import { whitelistLinkTabs } from 'components/LinkTabs.data'
|
import { whitelistLinkTabs } from 'components/LinkTabs.data'
|
||||||
|
import { WhitelistUpload } from 'components/WhitelistUpload'
|
||||||
import { useContracts } from 'contexts/contracts'
|
import { useContracts } from 'contexts/contracts'
|
||||||
import { useWallet } from 'contexts/wallet'
|
import { useWallet } from 'contexts/wallet'
|
||||||
import type { InstantiateResponse } from 'contracts/sg721'
|
import type { InstantiateResponse } from 'contracts/sg721'
|
||||||
@ -33,7 +32,7 @@ const Sg721InstantiatePage: NextPage = () => {
|
|||||||
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
|
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
|
||||||
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
|
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
|
||||||
|
|
||||||
const addressListState = useAddressListState()
|
const [whitelistArray, setWhitelistArray] = useState<string[]>([])
|
||||||
|
|
||||||
const unitPriceState = useNumberInputState({
|
const unitPriceState = useNumberInputState({
|
||||||
id: 'unit-price',
|
id: 'unit-price',
|
||||||
@ -74,7 +73,7 @@ const Sg721InstantiatePage: NextPage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const msg = {
|
const msg = {
|
||||||
members: addressListState.values.map((a) => a.address),
|
members: whitelistArray,
|
||||||
start_time: (startDate.getTime() * 1_000_000).toString(),
|
start_time: (startDate.getTime() * 1_000_000).toString(),
|
||||||
end_time: (endDate.getTime() * 1_000_000).toString(),
|
end_time: (endDate.getTime() * 1_000_000).toString(),
|
||||||
unit_price: coin(String(Number(unitPriceState.value) * 1000000), 'ustars'),
|
unit_price: coin(String(Number(unitPriceState.value) * 1000000), 'ustars'),
|
||||||
@ -97,6 +96,10 @@ const Sg721InstantiatePage: NextPage = () => {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const whitelistFileOnChange = (whitelistData: string[]) => {
|
||||||
|
setWhitelistArray(whitelistData)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="py-6 px-12 space-y-4" onSubmit={mutate}>
|
<form className="py-6 px-12 space-y-4" onSubmit={mutate}>
|
||||||
<NextSeo title="Instantiate Whitelist Contract" />
|
<NextSeo title="Instantiate Whitelist Contract" />
|
||||||
@ -116,16 +119,11 @@ const Sg721InstantiatePage: NextPage = () => {
|
|||||||
<br />
|
<br />
|
||||||
</Conditional>
|
</Conditional>
|
||||||
|
|
||||||
<FormGroup subtitle="Information about your whitelisted addresses" title="Whitelist Details">
|
<FormGroup subtitle="Your whitelisted addresses" title="Whitelist File">
|
||||||
<AddressList
|
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||||
entries={addressListState.entries}
|
<Conditional test={whitelistArray.length > 0}>
|
||||||
isRequired
|
<JsonPreview content={whitelistArray} initialState={false} title="File Contents" />
|
||||||
onAdd={addressListState.add}
|
</Conditional>
|
||||||
onChange={addressListState.update}
|
|
||||||
onRemove={addressListState.remove}
|
|
||||||
subtitle="Enter the members you want in your contract"
|
|
||||||
title="Members"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup subtitle="Information about your minting settings" title="Minting Details">
|
<FormGroup subtitle="Information about your minting settings" title="Minting Details">
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"target": "es5"
|
"target": "es5",
|
||||||
|
"downlevelIteration": true
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules"],
|
"exclude": ["node_modules"],
|
||||||
"include": ["env.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
"include": ["env.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||||
|
Loading…
Reference in New Issue
Block a user