import { toUtf8 } from '@cosmjs/encoding' import { FormControl } from 'components/FormControl' import { AddressInput, NumberInput } from 'components/forms/FormInput' import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload' import { useEffect, useId, useMemo } from 'react' import toast from 'react-hot-toast' import { FaMinus, FaPlus } from 'react-icons/fa' import { SG721_NAME_ADDRESS } from 'utils/constants' import { isValidAddress } from 'utils/isValidAddress' import { useWallet } from 'utils/wallet' import { useInputState, useNumberInputState } from './FormInput.hooks' export interface FlexMemberAttributesProps { title: string subtitle?: string isRequired?: boolean attributes: [string, WhitelistFlexMember][] onAdd: () => void onChange: (key: string, attribute: WhitelistFlexMember) => void onRemove: (key: string) => void } export function FlexMemberAttributes(props: FlexMemberAttributesProps) { const { title, subtitle, isRequired, attributes, onAdd, onChange, onRemove } = props return ( {attributes.map(([id], i) => ( ))} ) } export interface MemberAttributeProps { id: string isLast: boolean onAdd: FlexMemberAttributesProps['onAdd'] onChange: FlexMemberAttributesProps['onChange'] onRemove: FlexMemberAttributesProps['onRemove'] defaultAttribute: WhitelistFlexMember } export function FlexMemberAttribute({ id, isLast, onAdd, onChange, onRemove, defaultAttribute }: MemberAttributeProps) { const wallet = useWallet() const Icon = useMemo(() => (isLast ? FaPlus : FaMinus), [isLast]) const htmlId = useId() const addressState = useInputState({ id: `ma-address-${htmlId}`, name: `ma-address-${htmlId}`, title: `Address`, defaultValue: defaultAttribute.address, }) const mintCountState = useNumberInputState({ id: `mint-count-${htmlId}`, name: `mint-count-${htmlId}`, title: `Mint Count`, defaultValue: defaultAttribute.mint_count, }) useEffect(() => { onChange(id, { address: addressState.value, mint_count: mintCountState.value }) }, [addressState.value, mintCountState.value, id]) const resolveAddress = async (name: string) => { if (!wallet.isWalletConnected) throw new Error('Wallet not connected') await ( await wallet.getCosmWasmClient() ) .queryContractRaw( SG721_NAME_ADDRESS, toUtf8( Buffer.from( `0006${Buffer.from('tokens').toString('hex')}${Buffer.from(name).toString('hex')}`, 'hex', ).toString(), ), ) .then((res) => { const tokenUri = JSON.parse(new TextDecoder().decode(res as Uint8Array)).token_uri if (tokenUri && isValidAddress(tokenUri)) onChange(id, { address: tokenUri, mint_count: mintCountState.value }) else { toast.error(`Resolved address is empty or invalid for the name: ${name}.stars`) onChange(id, { address: '', mint_count: mintCountState.value }) } }) .catch((err) => { toast.error(`Error resolving address for the name: ${name}.stars`) console.error(err) onChange(id, { address: '', mint_count: mintCountState.value }) }) } useEffect(() => { if (addressState.value.endsWith('.stars')) { void resolveAddress(addressState.value.split('.')[0]) } else { onChange(id, { address: addressState.value, mint_count: mintCountState.value, }) } }, [addressState.value, id]) return (
) }