Enable Mint Rule: By Keys & By Minter for badge creation using the dashboard
This commit is contained in:
parent
4bf6e6ee5f
commit
3c2478cd38
@ -1,11 +1,14 @@
|
|||||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||||
|
/* eslint-disable no-nested-ternary */
|
||||||
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
|
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
import { toUtf8 } from '@cosmjs/encoding'
|
import { toUtf8 } from '@cosmjs/encoding'
|
||||||
|
import clsx from 'clsx'
|
||||||
import { Alert } from 'components/Alert'
|
import { Alert } from 'components/Alert'
|
||||||
|
import type { MintRule } from 'components/badges/creation/ImageUploadDetails'
|
||||||
import { Button } from 'components/Button'
|
import { Button } from 'components/Button'
|
||||||
import { Conditional } from 'components/Conditional'
|
import { Conditional } from 'components/Conditional'
|
||||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||||
@ -66,6 +69,7 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
const [createdBadgeId, setCreatedBadgeId] = useState<string | null>(null)
|
const [createdBadgeId, setCreatedBadgeId] = useState<string | null>(null)
|
||||||
const [createdBadgeKey, setCreatedBadgeKey] = useState<string | undefined>(undefined)
|
const [createdBadgeKey, setCreatedBadgeKey] = useState<string | undefined>(undefined)
|
||||||
const [resolvedOwnerAddress, setResolvedOwnerAddress] = useState<string>('')
|
const [resolvedOwnerAddress, setResolvedOwnerAddress] = useState<string>('')
|
||||||
|
const [resolvedMinterAddress, setResolvedMinterAddress] = useState<string>('')
|
||||||
const [signature, setSignature] = useState<string>('')
|
const [signature, setSignature] = useState<string>('')
|
||||||
const [ownerList, setOwnerList] = useState<string[]>([])
|
const [ownerList, setOwnerList] = useState<string[]>([])
|
||||||
const [editFee, setEditFee] = useState<number | undefined>(undefined)
|
const [editFee, setEditFee] = useState<number | undefined>(undefined)
|
||||||
@ -73,6 +77,7 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
const qrRef = useRef<HTMLDivElement>(null)
|
const qrRef = useRef<HTMLDivElement>(null)
|
||||||
const [numberOfKeys, setNumberOfKeys] = useState(0)
|
const [numberOfKeys, setNumberOfKeys] = useState(0)
|
||||||
const [keyPairs, setKeyPairs] = useState<{ publicKey: string; privateKey: string }[]>([])
|
const [keyPairs, setKeyPairs] = useState<{ publicKey: string; privateKey: string }[]>([])
|
||||||
|
const [mintRule, setMintRule] = useState<MintRule>('by_key')
|
||||||
|
|
||||||
const comboboxState = useExecuteComboboxState()
|
const comboboxState = useExecuteComboboxState()
|
||||||
const type = comboboxState.value?.id
|
const type = comboboxState.value?.id
|
||||||
@ -216,6 +221,14 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
subtitle: 'Number of keys/owners to execute the action for (0 for all)',
|
subtitle: 'Number of keys/owners to execute the action for (0 for all)',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const designatedMinterState = useInputState({
|
||||||
|
id: 'designatedMinter',
|
||||||
|
name: 'designatedMinter',
|
||||||
|
title: 'Minter Address',
|
||||||
|
subtitle: 'The address of the designated minter for this badge',
|
||||||
|
defaultValue: wallet.address,
|
||||||
|
})
|
||||||
|
|
||||||
const showBadgeField = type === 'create_badge'
|
const showBadgeField = type === 'create_badge'
|
||||||
const showMetadataField = isEitherType(type, ['create_badge', 'edit_badge'])
|
const showMetadataField = isEitherType(type, ['create_badge', 'edit_badge'])
|
||||||
const showIdField = isEitherType(type, [
|
const showIdField = isEitherType(type, [
|
||||||
@ -258,9 +271,16 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
youtube_url: youtubeUrlState.value || undefined,
|
youtube_url: youtubeUrlState.value || undefined,
|
||||||
},
|
},
|
||||||
transferrable,
|
transferrable,
|
||||||
rule: {
|
rule:
|
||||||
by_key: keyState.value,
|
mintRule === 'by_key'
|
||||||
},
|
? {
|
||||||
|
by_key: keyState.value,
|
||||||
|
}
|
||||||
|
: mintRule === 'by_minter'
|
||||||
|
? {
|
||||||
|
by_minter: resolvedMinterAddress,
|
||||||
|
}
|
||||||
|
: 'by_keys',
|
||||||
expiry: timestamp ? timestamp.getTime() * 1000000 : undefined,
|
expiry: timestamp ? timestamp.getTime() * 1000000 : undefined,
|
||||||
max_supply: maxSupplyState.value || undefined,
|
max_supply: maxSupplyState.value || undefined,
|
||||||
},
|
},
|
||||||
@ -284,7 +304,7 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
youtube_url: youtubeUrlState.value || undefined,
|
youtube_url: youtubeUrlState.value || undefined,
|
||||||
},
|
},
|
||||||
id: badgeIdState.value,
|
id: badgeIdState.value,
|
||||||
owner: ownerState.value,
|
owner: resolvedOwnerAddress,
|
||||||
pubkey: pubkeyState.value,
|
pubkey: pubkeyState.value,
|
||||||
signature,
|
signature,
|
||||||
keys: keyPairs.map((keyPair) => keyPair.publicKey),
|
keys: keyPairs.map((keyPair) => keyPair.publicKey),
|
||||||
@ -368,6 +388,7 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
if (txHash) {
|
if (txHash) {
|
||||||
setLastTx(txHash.split(':')[0])
|
setLastTx(txHash.split(':')[0])
|
||||||
setCreatedBadgeId(txHash.split(':')[1])
|
setCreatedBadgeId(txHash.split(':')[1])
|
||||||
|
badgeIdState.onChange(!isNaN(Number(txHash.split(':')[1])) ? Number(txHash.split(':')[1]) : 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -493,6 +514,15 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
void resolveOwnerAddress()
|
void resolveOwnerAddress()
|
||||||
}, [ownerState.value])
|
}, [ownerState.value])
|
||||||
|
|
||||||
|
const resolveMinterAddress = async () => {
|
||||||
|
await resolveAddress(designatedMinterState.value.trim(), wallet).then((resolvedAddress) => {
|
||||||
|
setResolvedMinterAddress(resolvedAddress)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
void resolveMinterAddress()
|
||||||
|
}, [designatedMinterState.value])
|
||||||
|
|
||||||
const resolveManagerAddress = async () => {
|
const resolveManagerAddress = async () => {
|
||||||
await resolveAddress(managerState.value.trim(), wallet).then((resolvedAddress) => {
|
await resolveAddress(managerState.value.trim(), wallet).then((resolvedAddress) => {
|
||||||
setBadge({
|
setBadge({
|
||||||
@ -517,9 +547,16 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
youtube_url: youtubeUrlState.value || undefined,
|
youtube_url: youtubeUrlState.value || undefined,
|
||||||
},
|
},
|
||||||
transferrable,
|
transferrable,
|
||||||
rule: {
|
rule:
|
||||||
by_key: keyState.value,
|
mintRule === 'by_key'
|
||||||
},
|
? {
|
||||||
|
by_key: keyState.value,
|
||||||
|
}
|
||||||
|
: mintRule === 'by_minter'
|
||||||
|
? {
|
||||||
|
by_minter: resolvedMinterAddress,
|
||||||
|
}
|
||||||
|
: 'by_keys',
|
||||||
expiry: timestamp ? timestamp.getTime() * 1000000 : undefined,
|
expiry: timestamp ? timestamp.getTime() * 1000000 : undefined,
|
||||||
max_supply: maxSupplyState.value || undefined,
|
max_supply: maxSupplyState.value || undefined,
|
||||||
})
|
})
|
||||||
@ -553,9 +590,16 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
youtube_url: youtubeUrlState.value || undefined,
|
youtube_url: youtubeUrlState.value || undefined,
|
||||||
},
|
},
|
||||||
transferrable,
|
transferrable,
|
||||||
rule: {
|
rule:
|
||||||
by_key: keyState.value,
|
mintRule === 'by_key'
|
||||||
},
|
? {
|
||||||
|
by_key: keyState.value,
|
||||||
|
}
|
||||||
|
: mintRule === 'by_minter'
|
||||||
|
? {
|
||||||
|
by_minter: resolvedMinterAddress,
|
||||||
|
}
|
||||||
|
: 'by_keys',
|
||||||
expiry: timestamp ? timestamp.getTime() * 1000000 : undefined,
|
expiry: timestamp ? timestamp.getTime() * 1000000 : undefined,
|
||||||
max_supply: maxSupplyState.value || undefined,
|
max_supply: maxSupplyState.value || undefined,
|
||||||
})
|
})
|
||||||
@ -586,7 +630,7 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
/>
|
/>
|
||||||
<LinkTabs activeIndex={2} data={badgeHubLinkTabs} />
|
<LinkTabs activeIndex={2} data={badgeHubLinkTabs} />
|
||||||
|
|
||||||
{showBadgeField && createdBadgeId && createdBadgeKey && (
|
{showBadgeField && createdBadgeId && createdBadgeKey && mintRule === 'by_key' && (
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<div className="ml-4">
|
<div className="ml-4">
|
||||||
<div className="w-[384px] h-[384px]" ref={qrRef}>
|
<div className="w-[384px] h-[384px]" ref={qrRef}>
|
||||||
@ -643,14 +687,116 @@ const BadgeHubExecutePage: NextPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showBadgeField && createdBadgeId && mintRule === 'by_keys' && (
|
||||||
|
<Alert className="mt-5" type="info">
|
||||||
|
<div className="ml-4 text-lg">
|
||||||
|
Badge ID:{` ${createdBadgeId as string}`}
|
||||||
|
<br />
|
||||||
|
<div className="text-base">
|
||||||
|
<div className="flex-row pt-4 mt-4 border-t-2">
|
||||||
|
<span>
|
||||||
|
You may select Message Type {'>'} Add Keys to add whitelisted keys authorized to mint a badge.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showBadgeField && createdBadgeId && mintRule === 'by_minter' && (
|
||||||
|
<Alert className="mt-5" type="info">
|
||||||
|
<div className="ml-4 text-lg">
|
||||||
|
Badge successfully created with ID:{` ${createdBadgeId as string}`}
|
||||||
|
<br />
|
||||||
|
Designated Minter Address: {` ${resolvedMinterAddress}`}
|
||||||
|
<br />
|
||||||
|
<div className="text-base">
|
||||||
|
<div className="flex-row pt-4 mt-4 border-t-2">
|
||||||
|
<span>
|
||||||
|
You may select Message Type {'>'} Mint by Minter to mint badges using the designated minter wallet.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
<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}>
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<AddressInput {...contractState} />
|
<AddressInput {...contractState} />
|
||||||
<ExecuteCombobox {...comboboxState} />
|
<ExecuteCombobox {...comboboxState} />
|
||||||
|
<Conditional test={type === 'create_badge'}>
|
||||||
|
<div className={clsx('flex flex-col space-y-2')}>
|
||||||
|
<div>
|
||||||
|
<div className="flex">
|
||||||
|
<span className="mt-1 text-base font-bold first-letter:capitalize">Mint Rule: </span>
|
||||||
|
<div className="ml-2 font-bold form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
checked={mintRule === 'by_key'}
|
||||||
|
className="peer sr-only"
|
||||||
|
id="ruleRadio1"
|
||||||
|
name="ruletRadio1"
|
||||||
|
onClick={() => {
|
||||||
|
setMintRule('by_key')
|
||||||
|
setCreatedBadgeId(null)
|
||||||
|
}}
|
||||||
|
type="radio"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="inline-block py-1 px-2 text-base text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||||
|
htmlFor="ruleRadio1"
|
||||||
|
>
|
||||||
|
By Key
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="ml-2 font-bold form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
checked={mintRule === 'by_keys'}
|
||||||
|
className="peer sr-only"
|
||||||
|
id="ruleRadio2"
|
||||||
|
name="ruletRadio2"
|
||||||
|
onClick={() => {
|
||||||
|
setMintRule('by_keys')
|
||||||
|
setCreatedBadgeId(null)
|
||||||
|
}}
|
||||||
|
type="radio"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="inline-block py-1 px-2 text-base text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||||
|
htmlFor="ruleRadio2"
|
||||||
|
>
|
||||||
|
By Keys
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="ml-2 font-bold form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
checked={mintRule === 'by_minter'}
|
||||||
|
className="peer sr-only"
|
||||||
|
id="ruleRadio3"
|
||||||
|
name="ruletRadio3"
|
||||||
|
onClick={() => {
|
||||||
|
setMintRule('by_minter')
|
||||||
|
setCreatedBadgeId(null)
|
||||||
|
}}
|
||||||
|
type="radio"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="inline-block py-1 px-2 text-base text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||||
|
htmlFor="ruleRadio3"
|
||||||
|
>
|
||||||
|
By Minter
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Conditional>
|
||||||
{showIdField && <NumberInput {...badgeIdState} />}
|
{showIdField && <NumberInput {...badgeIdState} />}
|
||||||
{showBadgeField && <AddressInput {...managerState} />}
|
{showBadgeField && <AddressInput {...managerState} />}
|
||||||
{showBadgeField && <TextInput {...keyState} />}
|
{showBadgeField && mintRule === 'by_key' && <TextInput {...keyState} />}
|
||||||
{showBadgeField && <Button onClick={handleGenerateKey}>Generate Key</Button>}
|
{showBadgeField && mintRule === 'by_key' && <Button onClick={handleGenerateKey}>Generate Key</Button>}
|
||||||
|
{showBadgeField && mintRule === 'by_minter' && <TextInput {...designatedMinterState} />}
|
||||||
{showMetadataField && (
|
{showMetadataField && (
|
||||||
<div className="p-4 rounded-md border-2 border-gray-800">
|
<div className="p-4 rounded-md border-2 border-gray-800">
|
||||||
<span className="text-gray-400">Metadata</span>
|
<span className="text-gray-400">Metadata</span>
|
||||||
|
Loading…
Reference in New Issue
Block a user