From 2340657020653277bfb8cdb573f22a6d525c9ec8 Mon Sep 17 00:00:00 2001 From: jhernandezb Date: Thu, 24 Nov 2022 23:32:44 -0600 Subject: [PATCH 1/3] add migrate option --- components/LinkTabs.data.ts | 5 ++ contracts/minter/contract.ts | 27 +++++- contracts/minter/useContract.ts | 18 +++- pages/contracts/minter/migrate.tsx | 132 +++++++++++++++++++++++++++++ yarn.lock | 6 +- 5 files changed, 183 insertions(+), 5 deletions(-) create mode 100644 pages/contracts/minter/migrate.tsx diff --git a/components/LinkTabs.data.ts b/components/LinkTabs.data.ts index 3a38fe3..cd0afa1 100644 --- a/components/LinkTabs.data.ts +++ b/components/LinkTabs.data.ts @@ -34,6 +34,11 @@ export const minterLinkTabs: LinkTabProps[] = [ description: `Execute Minter contract actions`, href: '/contracts/minter/execute', }, + { + title: 'Migrate', + description: `Migrate Minter contract`, + href: '/contracts/minter/migrate', + }, ] export const whitelistLinkTabs: LinkTabProps[] = [ diff --git a/contracts/minter/contract.ts b/contracts/minter/contract.ts index 3392b62..328023f 100644 --- a/contracts/minter/contract.ts +++ b/contracts/minter/contract.ts @@ -12,6 +12,11 @@ export interface InstantiateResponse { readonly logs: readonly logs.Log[] } +export interface MigrateResponse { + readonly transactionHash: string + readonly logs: readonly logs.Log[] +} + export interface RoyalityInfo { payment_address: string share: string @@ -151,6 +156,13 @@ export interface MinterContract { funds?: Coin[], ) => Promise + migrate: ( + senderAddress: string, + contractAddress: string, + codeId: number, + migrateMsg: Record, + ) => Promise + use: (contractAddress: string) => MinterInstance messages: (contractAddress: string) => MinterMessages @@ -374,6 +386,19 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC } } + 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 instantiate = async ( senderAddress: string, codeId: number, @@ -529,5 +554,5 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC } } - return { use, instantiate, messages } + return { use, instantiate, messages, migrate } } diff --git a/contracts/minter/useContract.ts b/contracts/minter/useContract.ts index afca5c5..1121ea2 100644 --- a/contracts/minter/useContract.ts +++ b/contracts/minter/useContract.ts @@ -3,7 +3,7 @@ import type { logs } from '@cosmjs/stargate' import { useWallet } from 'contexts/wallet' import { useCallback, useEffect, useState } from 'react' -import type { MinterContract, MinterInstance, MinterMessages } from './contract' +import type { MigrateResponse, MinterContract, MinterInstance, MinterMessages } from './contract' import { minter as initContract } from './contract' /*export interface InstantiateResponse { @@ -32,6 +32,7 @@ export interface UseMinterContractProps { admin?: string, funds?: Coin[], ) => Promise + migrate: (contractAddress: string, codeId: number, migrateMsg: Record) => Promise use: (customAddress: string) => MinterInstance | undefined updateContractAddress: (contractAddress: string) => void getContractAddress: () => string | undefined @@ -70,6 +71,20 @@ export function useMinterContract(): UseMinterContractProps { [minter, wallet], ) + const migrate = useCallback( + (contractAddress: string, codeId: number, migrateMsg: Record): Promise => { + return new Promise((resolve, reject) => { + if (!minter) { + reject(new Error('Contract is not initialized.')) + return + } + console.log(wallet.address, contractAddress, codeId) + minter.migrate(wallet.address, contractAddress, codeId, migrateMsg).then(resolve).catch(reject) + }) + }, + [minter, wallet], + ) + const use = useCallback( (customAddress = ''): MinterInstance | undefined => { return minter?.use(address || customAddress) @@ -94,5 +109,6 @@ export function useMinterContract(): UseMinterContractProps { updateContractAddress, getContractAddress, messages, + migrate, } } diff --git a/pages/contracts/minter/migrate.tsx b/pages/contracts/minter/migrate.tsx new file mode 100644 index 0000000..b3631b8 --- /dev/null +++ b/pages/contracts/minter/migrate.tsx @@ -0,0 +1,132 @@ +import { Button } from 'components/Button' +import { ContractPageHeader } from 'components/ContractPageHeader' +import { useExecuteComboboxState } from 'components/contracts/minter/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 { minterLinkTabs } from 'components/LinkTabs.data' +import { TransactionHash } from 'components/TransactionHash' +import { useContracts } from 'contexts/contracts' +import { useWallet } from 'contexts/wallet' +import type { MigrateResponse } from 'contracts/minter' +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 MinterMigratePage: NextPage = () => { + const { minter: 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 Minter', + placeholder: '1', + }) + + const contractState = useInputState({ + id: 'contract-address', + name: 'contract-address', + title: 'Minter Address', + subtitle: 'Address of the Minter 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)) + }, + }, + ) + + 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(MinterMigratePage, { center: false }) diff --git a/yarn.lock b/yarn.lock index 8034166..82ce098 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3557,9 +3557,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001332: - version "1.0.30001332" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz" - integrity sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw== + version "1.0.30001434" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz" + integrity sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA== carbites@^1.0.6: version "1.0.6" From fae92e548364a105d638ba976e5a2c888fc74960 Mon Sep 17 00:00:00 2001 From: jhernandezb Date: Thu, 24 Nov 2022 23:59:17 -0600 Subject: [PATCH 2/3] add update and remove discount price --- contracts/minter/contract.ts | 77 ++++++++++++++++++++++++++++ contracts/minter/messages/execute.ts | 26 ++++++++++ pages/contracts/minter/execute.tsx | 2 +- 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/contracts/minter/contract.ts b/contracts/minter/contract.ts index 328023f..f625028 100644 --- a/contracts/minter/contract.ts +++ b/contracts/minter/contract.ts @@ -43,6 +43,8 @@ export interface MinterInstance { shuffle: (senderAddress: string) => Promise withdraw: (senderAddress: string) => Promise airdrop: (senderAddress: string, recipients: string[]) => Promise + updateDiscountPrice: (senderAddress: string, price: string) => Promise + removeDiscountPrice: (senderAddress: string) => Promise } export interface MinterMessages { @@ -56,6 +58,26 @@ export interface MinterMessages { shuffle: () => ShuffleMessage withdraw: () => WithdrawMessage airdrop: (recipients: string[]) => CustomMessage + updateDiscountPrice: (price: string) => UpdateDiscountPriceMessage + removeDiscountPrice: () => RemoveDiscountPriceMessage +} + +export interface UpdateDiscountPriceMessage { + sender: string + contract: string + msg: { + update_discount_price: Record + } + funds: Coin[] +} + +export interface RemoveDiscountPriceMessage { + sender: string + contract: string + msg: { + remove_discount_price: Record + } + funds: Coin[] } export interface MintMessage { @@ -366,6 +388,35 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC return res.transactionHash } + const updateDiscountPrice = async (senderAddress: string, price: string): Promise => { + const res = await client.execute( + senderAddress, + contractAddress, + { + update_discount_price: { + price, + }, + }, + 'auto', + '', + ) + + return res.transactionHash + } + + const removeDiscountPrice = async (senderAddress: string): Promise => { + const res = await client.execute( + senderAddress, + contractAddress, + { + remove_discount_price: {}, + }, + 'auto', + '', + ) + + return res.transactionHash + } return { contractAddress, getConfig, @@ -383,6 +434,8 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC airdrop, shuffle, withdraw, + updateDiscountPrice, + removeDiscountPrice, } } @@ -539,6 +592,28 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC funds: [], } } + const updateDiscountPrice = (price: string): UpdateDiscountPriceMessage => { + return { + sender: txSigner, + contract: contractAddress, + msg: { + update_discount_price: { + price, + }, + }, + funds: [], + } + } + const removeDiscountPrice = (): RemoveDiscountPriceMessage => { + return { + sender: txSigner, + contract: contractAddress, + msg: { + remove_discount_price: {}, + }, + funds: [], + } + } return { mint, @@ -551,6 +626,8 @@ export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterC airdrop, shuffle, withdraw, + updateDiscountPrice, + removeDiscountPrice, } } diff --git a/contracts/minter/messages/execute.ts b/contracts/minter/messages/execute.ts index 6883f7e..7703af1 100644 --- a/contracts/minter/messages/execute.ts +++ b/contracts/minter/messages/execute.ts @@ -12,6 +12,8 @@ export const EXECUTE_TYPES = [ 'mint_for', 'shuffle', 'withdraw', + 'update_discount_price', + 'remove_discount_price', ] as const export interface ExecuteListItem { @@ -56,6 +58,16 @@ export const EXECUTE_LIST: ExecuteListItem[] = [ name: 'Shuffle', description: `Shuffle the token IDs`, }, + { + id: 'update_discount_price', + name: 'Update Discount Price', + description: `Updates discount price`, + }, + { + id: 'remove_discount_price', + name: 'Remove Discount Price', + description: `Removes discount price`, + }, ] export interface DispatchExecuteProps { @@ -80,6 +92,8 @@ export type DispatchExecuteArgs = { | { type: Select<'mint_for'>; recipient: string; tokenId: number } | { type: Select<'shuffle'> } | { type: Select<'withdraw'> } + | { type: Select<'update_discount_price'>; price: string } + | { type: Select<'remove_discount_price'> } ) export const dispatchExecute = async (args: DispatchExecuteArgs) => { @@ -112,6 +126,12 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => { case 'withdraw': { return messages.withdraw(txSigner) } + case 'update_discount_price': { + return messages.updateDiscountPrice(txSigner, args.price === '' ? '0' : args.price) + } + case 'remove_discount_price': { + return messages.removeDiscountPrice(txSigner) + } default: { throw new Error('unknown execute type') } @@ -147,6 +167,12 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => { case 'withdraw': { return messages(contract)?.withdraw() } + case 'update_discount_price': { + return messages(contract)?.updateDiscountPrice(args.price === '' ? '0' : args.price) + } + case 'remove_discount_price': { + return messages(contract)?.removeDiscountPrice() + } default: { return {} } diff --git a/pages/contracts/minter/execute.tsx b/pages/contracts/minter/execute.tsx index 15747ec..b247229 100644 --- a/pages/contracts/minter/execute.tsx +++ b/pages/contracts/minter/execute.tsx @@ -84,7 +84,7 @@ const MinterExecutePage: NextPage = () => { const showLimitField = type === 'update_per_address_limit' const showTokenIdField = type === 'mint_for' const showRecipientField = isEitherType(type, ['mint_to', 'mint_for']) - const showPriceField = type === 'mint' + const showPriceField = isEitherType(type, ['mint', 'update_discount_price']) const messages = useMemo(() => contract?.use(contractState.value), [contract, wallet.address, contractState.value]) const payload: DispatchExecuteArgs = { From fc6505397894aa379d0e80bb0a082878106e5bb5 Mon Sep 17 00:00:00 2001 From: jhernandezb Date: Fri, 25 Nov 2022 06:07:22 -0600 Subject: [PATCH 3/3] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2838a4e..f28a1ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stargaze-studio", - "version": "0.1.0", + "version": "0.1.1", "workspaces": [ "packages/*" ],