Merge pull request #128 from public-awesome/wl-related-changes
WL related changes
This commit is contained in:
commit
2e0d8e8ed9
@ -1,4 +1,4 @@
|
||||
APP_VERSION=0.4.9
|
||||
APP_VERSION=0.5.0
|
||||
|
||||
NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS
|
||||
NEXT_PUBLIC_SG721_CODE_ID=1702
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { FormControl } from 'components/FormControl'
|
||||
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 { InputDateTime } from 'components/InputDateTime'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { isValidAddress } from 'utils/isValidAddress'
|
||||
|
||||
import { Conditional } from '../../Conditional'
|
||||
import { AddressInput, NumberInput } from '../../forms/FormInput'
|
||||
@ -22,6 +25,8 @@ export interface WhitelistDetailsDataProps {
|
||||
endTime?: string
|
||||
perAddressLimit?: number
|
||||
memberLimit?: number
|
||||
admins?: string[]
|
||||
adminsMutable?: boolean
|
||||
}
|
||||
|
||||
type WhitelistState = 'none' | 'existing' | 'new'
|
||||
@ -31,6 +36,7 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
|
||||
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
|
||||
const [whitelistArray, setWhitelistArray] = useState<string[]>([])
|
||||
const [adminsMutable, setAdminsMutable] = useState<boolean>(true)
|
||||
|
||||
const whitelistAddressState = useInputState({
|
||||
id: 'whitelist-address',
|
||||
@ -67,6 +73,8 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
setWhitelistArray(data)
|
||||
}
|
||||
|
||||
const addressListState = useAddressListState()
|
||||
|
||||
useEffect(() => {
|
||||
const data: WhitelistDetailsDataProps = {
|
||||
whitelistType: whitelistState,
|
||||
@ -82,6 +90,14 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
endTime: endDate ? (endDate.getTime() * 1_000_000).toString() : '',
|
||||
perAddressLimit: perAddressLimitState.value,
|
||||
memberLimit: memberLimitState.value,
|
||||
admins: [
|
||||
...new Set(
|
||||
addressListState.values
|
||||
.map((a) => a.address.trim())
|
||||
.filter((address) => address !== '' && isValidAddress(address.trim()) && address.startsWith('stars')),
|
||||
),
|
||||
],
|
||||
adminsMutable,
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@ -94,6 +110,8 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
endDate,
|
||||
whitelistArray,
|
||||
whitelistState,
|
||||
addressListState.values,
|
||||
adminsMutable,
|
||||
])
|
||||
|
||||
return (
|
||||
@ -186,6 +204,28 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
<div>
|
||||
<div className="mt-2 ml-3 w-[65%] form-control">
|
||||
<label className="justify-start cursor-pointer label">
|
||||
<span className="mr-4 font-bold">Mutable Administrator Addresses</span>
|
||||
<input
|
||||
checked={adminsMutable}
|
||||
className={`toggle ${adminsMutable ? `bg-stargaze` : `bg-gray-600`}`}
|
||||
onClick={() => setAdminsMutable(!adminsMutable)}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="my-4 ml-4">
|
||||
<AddressList
|
||||
entries={addressListState.entries}
|
||||
isRequired
|
||||
onAdd={addressListState.add}
|
||||
onChange={addressListState.update}
|
||||
onRemove={addressListState.remove}
|
||||
subtitle="The list of administrator addresses"
|
||||
title="Administrator Addresses"
|
||||
/>
|
||||
</div>
|
||||
<FormGroup subtitle="TXT file that contains the whitelisted addresses" title="Whitelist File">
|
||||
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||
</FormGroup>
|
||||
|
@ -27,5 +27,9 @@ export function useAddressListState() {
|
||||
})
|
||||
}
|
||||
|
||||
return { entries, values, add, update, remove }
|
||||
function reset() {
|
||||
setRecord({})
|
||||
}
|
||||
|
||||
return { entries, values, add, update, remove, reset }
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ export interface WhiteListInstance {
|
||||
isActive: () => Promise<boolean>
|
||||
members: (startAfter?: string, limit?: number) => Promise<string[]>
|
||||
hasMember: (member: string) => Promise<boolean>
|
||||
adminList: () => Promise<string[]>
|
||||
config: () => Promise<ConfigResponse>
|
||||
|
||||
//Execute
|
||||
@ -33,6 +34,8 @@ export interface WhiteListInstance {
|
||||
removeMembers: (memberList: string[]) => Promise<string>
|
||||
updatePerAddressLimit: (limit: number) => Promise<string>
|
||||
increaseMemberLimit: (limit: number) => Promise<string>
|
||||
updateAdmins: (admins: string[]) => Promise<string>
|
||||
freeze: () => Promise<string>
|
||||
}
|
||||
|
||||
export interface WhitelistMessages {
|
||||
@ -42,6 +45,8 @@ export interface WhitelistMessages {
|
||||
removeMembers: (memberList: string[]) => RemoveMembersMessage
|
||||
updatePerAddressLimit: (limit: number) => UpdatePerAddressLimitMessage
|
||||
increaseMemberLimit: (limit: number) => IncreaseMemberLimitMessage
|
||||
updateAdmins: (admins: string[]) => UpdateAdminsMessage
|
||||
freeze: () => FreezeMessage
|
||||
}
|
||||
|
||||
export interface UpdateStartTimeMessage {
|
||||
@ -62,6 +67,22 @@ export interface UpdateEndTimeMessage {
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface UpdateAdminsMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_admins: { admins: string[] }
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface FreezeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: { freeze: Record<string, never> }
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface AddMembersMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
@ -139,6 +160,12 @@ export const WhiteList = (client: SigningCosmWasmClient, txSigner: string): Whit
|
||||
})
|
||||
}
|
||||
|
||||
const adminList = async (): Promise<string[]> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
admin_list: {},
|
||||
})
|
||||
}
|
||||
|
||||
const config = async (): Promise<ConfigResponse> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
config: {},
|
||||
@ -170,6 +197,32 @@ export const WhiteList = (client: SigningCosmWasmClient, txSigner: string): Whit
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const updateAdmins = async (admins: string[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
update_admins: {
|
||||
admins,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const freeze = async (): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
freeze: {},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const removeMembers = async (memberList: string[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
txSigner,
|
||||
@ -199,6 +252,8 @@ export const WhiteList = (client: SigningCosmWasmClient, txSigner: string): Whit
|
||||
contractAddress,
|
||||
updateStartTime,
|
||||
updateEndTime,
|
||||
updateAdmins,
|
||||
freeze,
|
||||
addMembers,
|
||||
removeMembers,
|
||||
updatePerAddressLimit,
|
||||
@ -208,6 +263,7 @@ export const WhiteList = (client: SigningCosmWasmClient, txSigner: string): Whit
|
||||
isActive,
|
||||
members,
|
||||
hasMember,
|
||||
adminList,
|
||||
config,
|
||||
}
|
||||
}
|
||||
@ -263,6 +319,28 @@ export const WhiteList = (client: SigningCosmWasmClient, txSigner: string): Whit
|
||||
}
|
||||
}
|
||||
|
||||
const updateAdmins = (admins: string[]) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_admins: { admins },
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const freeze = () => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
freeze: {},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const removeMembers = (memberList: string[]) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
@ -299,10 +377,12 @@ export const WhiteList = (client: SigningCosmWasmClient, txSigner: string): Whit
|
||||
return {
|
||||
updateStartTime,
|
||||
updateEndTime,
|
||||
updateAdmins,
|
||||
addMembers,
|
||||
removeMembers,
|
||||
updatePerAddressLimit,
|
||||
increaseMemberLimit,
|
||||
freeze,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,12 @@ export type ExecuteType = typeof EXECUTE_TYPES[number]
|
||||
export const EXECUTE_TYPES = [
|
||||
'update_start_time',
|
||||
'update_end_time',
|
||||
'update_admins',
|
||||
'add_members',
|
||||
'remove_members',
|
||||
'update_per_address_limit',
|
||||
'increase_member_limit',
|
||||
'freeze',
|
||||
] as const
|
||||
|
||||
export interface ExecuteListItem {
|
||||
@ -29,6 +31,11 @@ export const EXECUTE_LIST: ExecuteListItem[] = [
|
||||
name: 'Update End Time',
|
||||
description: `Update the end time of the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'update_admins',
|
||||
name: 'Update Admins',
|
||||
description: `Update the list of administrators for the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'add_members',
|
||||
name: 'Add Members',
|
||||
@ -49,6 +56,11 @@ export const EXECUTE_LIST: ExecuteListItem[] = [
|
||||
name: 'Increase Member Limit',
|
||||
description: `Increase the member limit of the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'freeze',
|
||||
name: 'Freeze',
|
||||
description: `Freeze the current state of the contract admin list`,
|
||||
},
|
||||
]
|
||||
|
||||
export interface DispatchExecuteProps {
|
||||
@ -70,6 +82,8 @@ export type DispatchExecuteArgs = {
|
||||
| { type: Select<'remove_members'>; members: string[] }
|
||||
| { type: Select<'update_per_address_limit'>; limit: number }
|
||||
| { type: Select<'increase_member_limit'>; limit: number }
|
||||
| { type: Select<'update_admins'>; admins: string[] }
|
||||
| { type: Select<'freeze'> }
|
||||
)
|
||||
|
||||
export const dispatchExecute = async (args: DispatchExecuteArgs) => {
|
||||
@ -84,6 +98,9 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
|
||||
case 'update_end_time': {
|
||||
return messages.updateEndTime(args.timestamp)
|
||||
}
|
||||
case 'update_admins': {
|
||||
return messages.updateAdmins(args.admins)
|
||||
}
|
||||
case 'add_members': {
|
||||
return messages.addMembers(args.members)
|
||||
}
|
||||
@ -96,6 +113,9 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
|
||||
case 'increase_member_limit': {
|
||||
return messages.increaseMemberLimit(args.limit)
|
||||
}
|
||||
case 'freeze': {
|
||||
return messages.freeze()
|
||||
}
|
||||
default: {
|
||||
throw new Error('unknown execute type')
|
||||
}
|
||||
@ -113,6 +133,9 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
|
||||
case 'update_end_time': {
|
||||
return messages(contract)?.updateEndTime(args.timestamp)
|
||||
}
|
||||
case 'update_admins': {
|
||||
return messages(contract)?.updateAdmins(args.admins)
|
||||
}
|
||||
case 'add_members': {
|
||||
return messages(contract)?.addMembers(args.members)
|
||||
}
|
||||
@ -125,6 +148,9 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
|
||||
case 'increase_member_limit': {
|
||||
return messages(contract)?.increaseMemberLimit(args.limit)
|
||||
}
|
||||
case 'freeze': {
|
||||
return messages(contract)?.freeze()
|
||||
}
|
||||
default: {
|
||||
return {}
|
||||
}
|
||||
|
@ -2,8 +2,15 @@ import type { WhiteListInstance } from '../contract'
|
||||
|
||||
export type QueryType = typeof QUERY_TYPES[number]
|
||||
|
||||
export const QUERY_TYPES = ['has_started', 'has_ended', 'is_active', 'members', 'has_member', 'config'] as const
|
||||
|
||||
export const QUERY_TYPES = [
|
||||
'has_started',
|
||||
'has_ended',
|
||||
'is_active',
|
||||
'members',
|
||||
'admin_list',
|
||||
'has_member',
|
||||
'config',
|
||||
] as const
|
||||
export interface QueryListItem {
|
||||
id: QueryType
|
||||
name: string
|
||||
@ -15,6 +22,7 @@ export const QUERY_LIST: QueryListItem[] = [
|
||||
{ id: 'has_ended', name: 'Has Ended', description: 'Check if the whitelist minting has ended' },
|
||||
{ id: 'is_active', name: 'Is Active', description: 'Check if the whitelist minting is active' },
|
||||
{ id: 'members', name: 'Members', description: 'View the whitelist members' },
|
||||
{ id: 'admin_list', name: 'Admin List', description: 'View the whitelist admin list' },
|
||||
{ id: 'has_member', name: 'Has Member', description: 'Check if a member is in the whitelist' },
|
||||
{ id: 'config', name: 'Config', description: 'View the whitelist configuration' },
|
||||
]
|
||||
@ -36,6 +44,8 @@ export const dispatchQuery = (props: DispatchQueryProps) => {
|
||||
return messages?.isActive()
|
||||
case 'members':
|
||||
return messages?.members()
|
||||
case 'admin_list':
|
||||
return messages?.adminList()
|
||||
case 'has_member':
|
||||
return messages?.hasMember(address)
|
||||
case 'config':
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "stargaze-studio",
|
||||
"version": "0.4.9",
|
||||
"version": "0.5.0",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
|
@ -378,6 +378,8 @@ const CollectionCreationPage: NextPage = () => {
|
||||
mint_price: coin(String(Number(whitelistDetails?.unitPrice)), 'ustars'),
|
||||
per_address_limit: whitelistDetails?.perAddressLimit,
|
||||
member_limit: whitelistDetails?.memberLimit,
|
||||
admins: whitelistDetails?.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails?.adminsMutable,
|
||||
}
|
||||
|
||||
const data = await whitelistContract.instantiate(
|
||||
@ -813,8 +815,8 @@ const CollectionCreationPage: NextPage = () => {
|
||||
throw new Error('Per address limit is required')
|
||||
if (!whitelistDetails.memberLimit || whitelistDetails.memberLimit === 0)
|
||||
throw new Error('Member limit is required')
|
||||
if (Number(whitelistDetails.startTime) > Number(whitelistDetails.endTime))
|
||||
throw new Error('Whitelist start time cannot be later than whitelist end time')
|
||||
if (Number(whitelistDetails.startTime) >= Number(whitelistDetails.endTime))
|
||||
throw new Error('Whitelist start time cannot be equal to or later than the whitelist end time')
|
||||
if (Number(whitelistDetails.startTime) !== Number(mintingDetails?.startTime))
|
||||
throw new Error('Whitelist start time must be the same as the minting start time')
|
||||
if (whitelistDetails.perAddressLimit && mintingDetails?.numTokens) {
|
||||
|
@ -64,6 +64,7 @@ const WhitelistExecutePage: NextPage = () => {
|
||||
const showLimitState = isEitherType(type, ['update_per_address_limit', 'increase_member_limit'])
|
||||
const showTimestamp = isEitherType(type, ['update_start_time', 'update_end_time'])
|
||||
const showMemberList = isEitherType(type, ['add_members', 'remove_members'])
|
||||
const showAdminList = isEitherType(type, ['update_admins'])
|
||||
|
||||
const messages = useMemo(() => contract?.use(contractState.value), [contract, contractState.value])
|
||||
const payload: DispatchExecuteArgs = {
|
||||
@ -80,6 +81,13 @@ const WhitelistExecutePage: NextPage = () => {
|
||||
.concat(memberList),
|
||||
),
|
||||
],
|
||||
admins: [
|
||||
...new Set(
|
||||
addressListState.values
|
||||
.map((a) => a.address.trim())
|
||||
.filter((address) => address !== '' && isValidAddress(address.trim()) && address.startsWith('stars')),
|
||||
),
|
||||
] || [wallet.address],
|
||||
}
|
||||
const { isLoading, mutate } = useMutation(
|
||||
async (event: FormEvent) => {
|
||||
@ -146,20 +154,22 @@ const WhitelistExecutePage: NextPage = () => {
|
||||
<InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />
|
||||
</FormControl>
|
||||
</Conditional>
|
||||
<Conditional test={showMemberList}>
|
||||
<Conditional test={showMemberList || showAdminList}>
|
||||
<AddressList
|
||||
entries={addressListState.entries}
|
||||
isRequired
|
||||
onAdd={addressListState.add}
|
||||
onChange={addressListState.update}
|
||||
onRemove={addressListState.remove}
|
||||
subtitle="Enter the member addresses"
|
||||
subtitle={type === 'update_admins' ? 'Enter the admin addresses' : 'Enter the member addresses'}
|
||||
title="Addresses"
|
||||
/>
|
||||
<Alert className="mt-8" type="info">
|
||||
You may optionally choose a text file of additional member addresses.
|
||||
</Alert>
|
||||
<WhitelistUpload onChange={setMemberList} />
|
||||
<Conditional test={showMemberList}>
|
||||
<Alert className="mt-8" type="info">
|
||||
You may optionally choose a text file of additional member addresses.
|
||||
</Alert>
|
||||
<WhitelistUpload onChange={setMemberList} />
|
||||
</Conditional>
|
||||
</Conditional>
|
||||
</div>
|
||||
<div className="space-y-8">
|
||||
|
@ -5,6 +5,8 @@ import { Conditional } from 'components/Conditional'
|
||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||
import { FormControl } from 'components/FormControl'
|
||||
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 { useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||
import { InputDateTime } from 'components/InputDateTime'
|
||||
@ -22,6 +24,7 @@ import { toast } from 'react-hot-toast'
|
||||
import { FaAsterisk } from 'react-icons/fa'
|
||||
import { useMutation } from 'react-query'
|
||||
import { WHITELIST_CODE_ID } from 'utils/constants'
|
||||
import { isValidAddress } from 'utils/isValidAddress'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { links } from 'utils/links'
|
||||
|
||||
@ -31,6 +34,7 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
|
||||
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
|
||||
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
|
||||
const [adminsMutable, setAdminsMutable] = useState<boolean>(true)
|
||||
|
||||
const [whitelistArray, setWhitelistArray] = useState<string[]>([])
|
||||
|
||||
@ -58,6 +62,8 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
placeholder: '5',
|
||||
})
|
||||
|
||||
const addressListState = useAddressListState()
|
||||
|
||||
const { data, isLoading, mutate } = useMutation(
|
||||
async (event: FormEvent): Promise<InstantiateResponse | null> => {
|
||||
event.preventDefault()
|
||||
@ -79,6 +85,14 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
mint_price: coin(String(Number(unitPriceState.value) * 1000000), 'ustars'),
|
||||
per_address_limit: perAddressLimitState.value,
|
||||
member_limit: memberLimitState.value,
|
||||
admins: [
|
||||
...new Set(
|
||||
addressListState.values
|
||||
.map((a) => a.address.trim())
|
||||
.filter((address) => address !== '' && isValidAddress(address.trim()) && address.startsWith('stars')),
|
||||
),
|
||||
] || [wallet.address],
|
||||
admins_mutable: adminsMutable,
|
||||
}
|
||||
return toast.promise(
|
||||
contract.instantiate(WHITELIST_CODE_ID, msg, 'Stargaze Whitelist Contract', wallet.address),
|
||||
@ -119,6 +133,29 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
<br />
|
||||
</Conditional>
|
||||
|
||||
<div className="mt-2 ml-3 w-full form-control">
|
||||
<label className="justify-start cursor-pointer label">
|
||||
<span className="mr-4 font-bold">Mutable Administrator Addresses</span>
|
||||
<input
|
||||
checked={adminsMutable}
|
||||
className={`toggle ${adminsMutable ? `bg-stargaze` : `bg-gray-600`}`}
|
||||
onClick={() => setAdminsMutable(!adminsMutable)}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="my-4 ml-4 w-1/2">
|
||||
<AddressList
|
||||
entries={addressListState.entries}
|
||||
isRequired
|
||||
onAdd={addressListState.add}
|
||||
onChange={addressListState.update}
|
||||
onRemove={addressListState.remove}
|
||||
subtitle="The list of administrator addresses"
|
||||
title="Administrator Addresses"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<FormGroup subtitle="Your whitelisted addresses" title="Whitelist File">
|
||||
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||
<Conditional test={whitelistArray.length > 0}>
|
||||
|
@ -108,7 +108,7 @@ const WhitelistQueryPage: NextPage = () => {
|
||||
onChange={(e) => setType(e.target.value as QueryType)}
|
||||
>
|
||||
{QUERY_LIST.map(({ id, name }) => (
|
||||
<option key={`query-${id}`} value={id}>
|
||||
<option key={`query-${id}`} className="mt-2 text-lg bg-[#1A1A1A]" value={id}>
|
||||
{name}
|
||||
</option>
|
||||
))}
|
||||
|
Loading…
Reference in New Issue
Block a user