Implement initial mint_by_key logic for Badge Actions
This commit is contained in:
parent
bdd39d2dc2
commit
e1adca8ddf
@ -21,10 +21,11 @@ import { toast } from 'react-hot-toast'
|
||||
import { FaArrowRight } from 'react-icons/fa'
|
||||
import { useMutation } from 'react-query'
|
||||
import * as secp256k1 from 'secp256k1'
|
||||
import { sha256 } from 'utils/hash'
|
||||
import type { AirdropAllocation } from 'utils/isValidAccountsFile'
|
||||
import { resolveAddress } from 'utils/resolveAddress'
|
||||
|
||||
import { TextInput } from '../../forms/FormInput'
|
||||
import { AddressInput, TextInput } from '../../forms/FormInput'
|
||||
import type { MintRule } from '../creation/ImageUploadDetails'
|
||||
|
||||
interface BadgeActionsProps {
|
||||
@ -49,6 +50,7 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
const [editFee, setEditFee] = useState<number | undefined>(undefined)
|
||||
const [triggerDispatch, setTriggerDispatch] = useState<boolean>(false)
|
||||
const [keyPairs, setKeyPairs] = useState<string[]>([])
|
||||
const [signature, setSignature] = useState<string>('')
|
||||
|
||||
const actionComboboxState = useActionsComboboxState()
|
||||
const type = actionComboboxState.value?.id
|
||||
@ -139,6 +141,7 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
name: 'owner',
|
||||
title: 'Owner',
|
||||
subtitle: 'The owner of the badge',
|
||||
defaultValue: wallet.address,
|
||||
})
|
||||
|
||||
const pubkeyState = useInputState({
|
||||
@ -148,11 +151,11 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
subtitle: 'The public key for the badge',
|
||||
})
|
||||
|
||||
const signatureState = useInputState({
|
||||
id: 'signature',
|
||||
name: 'signature',
|
||||
title: 'Signature',
|
||||
subtitle: 'The signature for the badge',
|
||||
const privateKeyState = useInputState({
|
||||
id: 'privateKey',
|
||||
name: 'privateKey',
|
||||
title: 'Private Key',
|
||||
subtitle: 'The private key to claim the badge with',
|
||||
})
|
||||
|
||||
const nftState = useInputState({
|
||||
@ -170,6 +173,8 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
})
|
||||
|
||||
const showMetadataField = isEitherType(type, ['edit_badge'])
|
||||
const showOwnerField = isEitherType(type, ['mint_by_key', 'mint_by_keys'])
|
||||
const showPrivateKeyField = isEitherType(type, ['mint_by_key', 'mint_by_keys'])
|
||||
|
||||
const payload: DispatchExecuteArgs = {
|
||||
badge: {
|
||||
@ -223,7 +228,7 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
editFee,
|
||||
owner: resolvedOwnerAddress,
|
||||
pubkey: pubkeyState.value,
|
||||
signature: signatureState.value,
|
||||
signature,
|
||||
keys: [],
|
||||
limit: limitState.value,
|
||||
owners: [],
|
||||
@ -339,6 +344,11 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
})
|
||||
}, [triggerDispatch])
|
||||
|
||||
useEffect(() => {
|
||||
if (privateKeyState.value.length === 64 && resolvedOwnerAddress)
|
||||
handleGenerateSignature(badgeId, resolvedOwnerAddress, privateKeyState.value)
|
||||
}, [privateKeyState.value, resolvedOwnerAddress])
|
||||
|
||||
useEffect(() => {
|
||||
const addresses: string[] = []
|
||||
airdropAllocationArray.forEach((allocation) => {
|
||||
@ -356,6 +366,9 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
|
||||
const { isLoading, mutate } = useMutation(
|
||||
async (event: FormEvent) => {
|
||||
if (!wallet.client) {
|
||||
throw new Error('Please connect your wallet.')
|
||||
}
|
||||
event.preventDefault()
|
||||
if (!type) {
|
||||
throw new Error('Please select an action.')
|
||||
@ -364,6 +377,10 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
throw new Error('Please enter the Badge Hub contract addresses.')
|
||||
}
|
||||
|
||||
if (type === 'mint_by_key' && privateKeyState.value.length !== 64) {
|
||||
throw new Error('Please enter a valid private key.')
|
||||
}
|
||||
|
||||
if (wallet.client && type === 'edit_badge') {
|
||||
const feeRateRaw = await wallet.client.queryContractRaw(
|
||||
badgeHubContractAddress,
|
||||
@ -442,6 +459,22 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
setAirdropAllocationArray(data)
|
||||
}
|
||||
|
||||
const handleGenerateSignature = (id: number, owner: string, privateKey: string) => {
|
||||
try {
|
||||
const message = `claim badge ${id} for user ${owner}`
|
||||
|
||||
const privKey = Buffer.from(privateKey, 'hex')
|
||||
// const pubKey = Buffer.from(secp256k1.publicKeyCreate(privKey, true))
|
||||
const msgBytes = Buffer.from(message, 'utf8')
|
||||
const msgHashBytes = sha256(msgBytes)
|
||||
const signedMessage = secp256k1.ecdsaSign(msgHashBytes, privKey)
|
||||
setSignature(Buffer.from(signedMessage.signature).toString('hex'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
toast.error('Error generating signature.')
|
||||
}
|
||||
}
|
||||
|
||||
const handleGenerateKeys = (amount: number) => {
|
||||
for (let i = 0; i < amount; i++) {
|
||||
let privKey: Buffer
|
||||
@ -482,6 +515,15 @@ export const BadgeActions = ({ badgeHubContractAddress, badgeId, badgeHubMessage
|
||||
<TextInput className="mt-2" {...youtubeUrlState} />
|
||||
</div>
|
||||
)}
|
||||
{showOwnerField && (
|
||||
<AddressInput
|
||||
className="mt-2"
|
||||
{...ownerState}
|
||||
subtitle="The address that the badge will be minted to"
|
||||
title="Owner"
|
||||
/>
|
||||
)}
|
||||
{showPrivateKeyField && <TextInput className="mt-2" {...privateKeyState} />}
|
||||
|
||||
{/* {showAirdropFileField && (
|
||||
<FormGroup
|
||||
|
@ -21,6 +21,7 @@
|
||||
"@fontsource/jetbrains-mono": "^4",
|
||||
"@fontsource/roboto": "^4",
|
||||
"@headlessui/react": "^1",
|
||||
"jscrypto": "^1.0.3",
|
||||
"@keplr-wallet/cosmos": "^0.9.16",
|
||||
"@pinata/sdk": "^1.1.26",
|
||||
"@popperjs/core": "^2",
|
||||
|
8
utils/hash.ts
Normal file
8
utils/hash.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
|
||||
import { Word32Array } from 'jscrypto'
|
||||
import { SHA256 } from 'jscrypto/SHA256'
|
||||
|
||||
export function sha256(data: Buffer): Buffer {
|
||||
return Buffer.from(SHA256.hash(new Word32Array(data)).toUint8Array())
|
||||
}
|
@ -5627,6 +5627,11 @@ js-yaml@^4.1.0:
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
jscrypto@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/jscrypto/-/jscrypto-1.0.3.tgz#598febca2a939d6f679c54f56e1fe364cef30cc9"
|
||||
integrity sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ==
|
||||
|
||||
jsesc@^2.5.1:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user