From 2e080488e382096b01b0fa092acb2369711d55d5 Mon Sep 17 00:00:00 2001 From: Serkan Reis Date: Sun, 19 Mar 2023 21:40:54 +0300 Subject: [PATCH] Init splits contract dashboard > Migrate --- contracts/splits/contract.ts | 28 +++++- contracts/splits/useContract.ts | 19 ++++- pages/contracts/splits/migrate.tsx | 133 +++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 pages/contracts/splits/migrate.tsx diff --git a/contracts/splits/contract.ts b/contracts/splits/contract.ts index ccd1900..06593d0 100644 --- a/contracts/splits/contract.ts +++ b/contracts/splits/contract.ts @@ -1,11 +1,17 @@ import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate' import type { Coin } from '@cosmjs/proto-signing' +import type { logs } from '@cosmjs/stargate' export interface InstantiateResponse { readonly contractAddress: string readonly transactionHash: string } +export interface MigrateResponse { + readonly transactionHash: string + readonly logs: readonly logs.Log[] +} + export interface SplitsInstance { readonly contractAddress: string //Query @@ -50,6 +56,13 @@ export interface SplitsContract { use: (contractAddress: string) => SplitsInstance + migrate: ( + senderAddress: string, + contractAddress: string, + codeId: number, + migrateMsg: Record, + ) => Promise + messages: (contractAddress: string) => SplitsMessages } @@ -132,6 +145,19 @@ export const Splits = (client: SigningCosmWasmClient, txSigner: string): SplitsC } } + const migrate = async ( + senderAddress: string, + contractAddress: string, + codeId: number, + migrateMsg: Record, + ): Promise => { + const result = await client.migrate(senderAddress, contractAddress, codeId, migrateMsg, 'auto') + return { + transactionHash: result.transactionHash, + logs: result.logs, + } + } + const messages = (contractAddress: string) => { const updateAdmin = (admin: string) => { return { @@ -161,5 +187,5 @@ export const Splits = (client: SigningCosmWasmClient, txSigner: string): SplitsC } } - return { use, instantiate, messages } + return { use, instantiate, migrate, messages } } diff --git a/contracts/splits/useContract.ts b/contracts/splits/useContract.ts index 70ae0f9..69a1c63 100644 --- a/contracts/splits/useContract.ts +++ b/contracts/splits/useContract.ts @@ -3,7 +3,7 @@ import { useWallet } from 'contexts/wallet' import { useCallback, useEffect, useState } from 'react' -import type { InstantiateResponse, SplitsContract, SplitsInstance, SplitsMessages } from './contract' +import type { InstantiateResponse, MigrateResponse, SplitsContract, SplitsInstance, SplitsMessages } from './contract' import { Splits as initContract } from './contract' export interface UseSplitsContractProps { @@ -14,6 +14,8 @@ export interface UseSplitsContractProps { admin?: string, ) => Promise + migrate: (contractAddress: string, codeId: number, migrateMsg: Record) => Promise + use: (customAddress?: string) => SplitsInstance | undefined updateContractAddress: (contractAddress: string) => void @@ -53,6 +55,20 @@ export function useSplitsContract(): UseSplitsContractProps { [splits], ) + const migrate = useCallback( + (contractAddress: string, codeId: number, migrateMsg: Record): Promise => { + return new Promise((resolve, reject) => { + if (!splits) { + reject(new Error('Contract is not initialized.')) + return + } + console.log(wallet.address, contractAddress, codeId) + splits.migrate(wallet.address, contractAddress, codeId, migrateMsg).then(resolve).catch(reject) + }) + }, + [splits, wallet], + ) + const use = useCallback( (customAddress = ''): SplitsInstance | undefined => { return splits?.use(address || customAddress) @@ -69,6 +85,7 @@ export function useSplitsContract(): UseSplitsContractProps { return { instantiate, + migrate, use, updateContractAddress, messages, diff --git a/pages/contracts/splits/migrate.tsx b/pages/contracts/splits/migrate.tsx new file mode 100644 index 0000000..75d1314 --- /dev/null +++ b/pages/contracts/splits/migrate.tsx @@ -0,0 +1,133 @@ +import { Button } from 'components/Button' +import { ContractPageHeader } from 'components/ContractPageHeader' +import { useExecuteComboboxState } from 'components/contracts/splits/ExecuteCombobox.hooks' +import { FormControl } from 'components/FormControl' +import { AddressInput, NumberInput } from 'components/forms/FormInput' +import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks' +import { JsonPreview } from 'components/JsonPreview' +import { LinkTabs } from 'components/LinkTabs' +import { splitsLinkTabs } from 'components/LinkTabs.data' +import { TransactionHash } from 'components/TransactionHash' +import { useContracts } from 'contexts/contracts' +import { useWallet } from 'contexts/wallet' +import type { MigrateResponse } from 'contracts/splits' +import type { NextPage } from 'next' +import { useRouter } from 'next/router' +import { NextSeo } from 'next-seo' +import type { FormEvent } from 'react' +import { useEffect, useState } from 'react' +import { toast } from 'react-hot-toast' +import { FaArrowRight } from 'react-icons/fa' +import { useMutation } from 'react-query' +import { withMetadata } from 'utils/layout' +import { links } from 'utils/links' + +const SplitsMigratePage: NextPage = () => { + const { splits: contract } = useContracts() + const wallet = useWallet() + + const [lastTx, setLastTx] = useState('') + + const comboboxState = useExecuteComboboxState() + const type = comboboxState.value?.id + const codeIdState = useNumberInputState({ + id: 'code-id', + name: 'code-id', + title: 'Code ID', + subtitle: 'Code ID of the New Splits contract', + placeholder: '1', + }) + + const contractState = useInputState({ + id: 'contract-address', + name: 'contract-address', + title: 'Splits Address', + subtitle: 'Address of the Splits contract', + }) + const contractAddress = contractState.value + + const { data, isLoading, mutate } = useMutation( + async (event: FormEvent): Promise => { + event.preventDefault() + if (!contract) { + throw new Error('Smart contract connection failed') + } + if (!wallet.initialized) { + throw new Error('Please connect your wallet.') + } + + const migrateMsg = {} + + return toast.promise(contract.migrate(contractAddress, codeIdState.value, migrateMsg), { + error: `Migration failed!`, + loading: 'Executing message...', + success: (tx) => { + if (tx) { + setLastTx(tx.transactionHash) + } + return `Transaction success!` + }, + }) + }, + { + onError: (error) => { + toast.error(String(error), { style: { maxWidth: 'none' } }) + }, + }, + ) + + const router = useRouter() + + useEffect(() => { + if (contractAddress.length > 0) { + void router.replace({ query: { contractAddress } }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [contractAddress]) + useEffect(() => { + const initial = new URL(document.URL).searchParams.get('contractAddress') + if (initial && initial.length > 0) contractState.onChange(initial) + }, []) + + return ( +
+ + + + +
+
+ + +
+
+
+ + + + +
+ + + +
+
+
+ ) +} + +export default withMetadata(SplitsMigratePage, { center: false })