diff --git a/pages/contracts/splits/instantiate.tsx b/pages/contracts/splits/instantiate.tsx new file mode 100644 index 0000000..921974b --- /dev/null +++ b/pages/contracts/splits/instantiate.tsx @@ -0,0 +1,228 @@ +import { toBase64, toUtf8 } from '@cosmjs/encoding' +import { Alert } from 'components/Alert' +import { Button } from 'components/Button' +import { Conditional } from 'components/Conditional' +import { ContractPageHeader } from 'components/ContractPageHeader' +import { AddressInput } from 'components/forms/FormInput' +import { JsonPreview } from 'components/JsonPreview' +import { LinkTabs } from 'components/LinkTabs' +import { splitsLinkTabs } from 'components/LinkTabs.data' +import { useContracts } from 'contexts/contracts' +import { useWallet } from 'contexts/wallet' +import type { InstantiateResponse } from 'contracts/sg721' +import type { NextPage } from 'next' +import { NextSeo } from 'next-seo' +import { type FormEvent, useEffect, useState } from 'react' +import { toast } from 'react-hot-toast' +import { FaAsterisk } from 'react-icons/fa' +import { useMutation } from 'react-query' +import { isValidAddress } from 'utils/isValidAddress' +import { withMetadata } from 'utils/layout' +import { links } from 'utils/links' + +import { useInputState } from '../../../components/forms/FormInput.hooks' +import type { Attribute } from '../../../components/forms/MemberAttributes' +import { MemberAttributes } from '../../../components/forms/MemberAttributes' +import { useMemberAttributesState } from '../../../components/forms/MemberAttributes.hooks' +import { CW4_GROUP_CODE_ID, SPLITS_CODE_ID } from '../../../utils/constants' +import { resolveAddress } from '../../../utils/resolveAddress' + +export type CW4Method = 'new' | 'existing' + +const SplitsInstantiatePage: NextPage = () => { + const wallet = useWallet() + const { splits: contract } = useContracts() + const [members, setMembers] = useState([]) + const [cw4Method, setCw4Method] = useState('new') + + const cw4GroupAddressState = useInputState({ + id: 'cw4-group-address', + name: 'cw4-group-address', + title: 'CW4 Group Address', + subtitle: 'Address of the CW4 Group contract', + placeholder: 'stars1...', + }) + + const splitsAdminState = useInputState({ + id: 'splits-admin', + name: 'splits-admin', + title: 'Splits Contract Admin', + subtitle: 'Address of the Splits Contract administrator', + defaultValue: wallet.address, + }) + + const cw4GroupAdminState = useInputState({ + id: 'cw4-group-admin', + name: 'cw4-group-admin', + title: 'CW4 Group Admin', + subtitle: 'Address of the CW4 Group administrator', + defaultValue: wallet.address, + }) + + const memberListState = useMemberAttributesState() + + useEffect(() => { + memberListState.reset() + memberListState.add({ + address: '', + weight: 0, + }) + }, []) + + const { data, isLoading, mutate } = useMutation( + async (event: FormEvent): Promise => { + event.preventDefault() + if (!contract) { + throw new Error('Smart contract connection failed') + } + const msg = + cw4Method === 'existing' + ? { admin: splitsAdminState.value, group: { cw4_address: cw4GroupAddressState.value } } + : { + admin: splitsAdminState.value ? splitsAdminState.value : undefined, + group: { + cw4_instantiate: { + code_id: CW4_GROUP_CODE_ID, + label: 'cw4-group', + msg: toBase64( + toUtf8( + JSON.stringify({ + admin: cw4GroupAdminState.value ? cw4GroupAdminState.value : undefined, + members: [ + ...new Set( + members + .filter( + (member) => + member.address !== '' && + member.weight > 0 && + isValidAddress(member.address) && + member.address.startsWith('stars'), + ) + .map((member) => ({ addr: member.address, weight: member.weight })), + ), + ], + }), + ), + ), + }, + }, + } + return toast.promise(contract.instantiate(SPLITS_CODE_ID, msg, 'Stargaze Splits Contract', wallet.address), { + loading: 'Instantiating contract...', + error: 'Instantiation failed!', + success: 'Instantiation success!', + }) + }, + { + onError: (error) => { + toast.error(String(error), { style: { maxWidth: 'none' } }) + }, + }, + ) + + const resolveMemberAddresses = () => { + const tempMembers: Attribute[] = [] + memberListState.values.map(async (member) => { + await resolveAddress(member.address.trim(), wallet).then((resolvedAddress) => { + tempMembers.push({ address: resolvedAddress, weight: member.weight }) + }) + }) + setMembers(tempMembers) + console.log('Members:', members) + } + + useEffect(() => { + resolveMemberAddresses() + }, [memberListState.values]) + + return ( +
+ + + + + + + Instantiate success! Here is the transaction result containing the contract address and the transaction + hash. + + +
+
+ +
+
+
+ { + setCw4Method('new') + }} + type="radio" + value="New" + /> + +
+
+ { + setCw4Method('existing') + }} + type="radio" + value="Existing" + /> + +
+
+
+ + + + + +
+ +
+
+ + + + +
+
+ +
+ + ) +} + +export default withMetadata(SplitsInstantiatePage, { center: false })