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