From a8c25485544cd1633f4ded748b732d5ba991a375 Mon Sep 17 00:00:00 2001
From: Serkan Reis
Date: Fri, 9 Dec 2022 11:27:50 +0300
Subject: [PATCH] Implement Base Minter Contract dashboard
---
.env.example | 4 +-
components/LinkTabs.data.ts | 41 ++-
components/Sidebar.tsx | 7 +-
components/collections/actions/Action.tsx | 8 +-
components/collections/actions/actions.ts | 74 ++---
components/collections/queries/Queries.tsx | 2 +-
components/collections/queries/query.ts | 16 +-
.../ExecuteCombobox.hooks.ts | 2 +-
.../ExecuteCombobox.tsx | 4 +-
.../vendingMinter/ExecuteCombobox.hooks.ts | 7 +
.../vendingMinter/ExecuteCombobox.tsx | 92 +++++++
contexts/contracts.tsx | 26 +-
contracts/baseFactory/contract.ts | 93 +++++++
contracts/{minter => baseFactory}/index.ts | 0
contracts/baseFactory/messages/execute.ts | 28 ++
contracts/baseFactory/useContract.ts | 57 ++++
contracts/baseMinter/contract.ts | 243 ++++++++++++++++
contracts/baseMinter/index.ts | 2 +
contracts/baseMinter/messages/execute.ts | 82 ++++++
contracts/baseMinter/messages/query.ts | 37 +++
contracts/baseMinter/useContract.ts | 102 +++++++
contracts/sg721/contract.ts | 2 +-
contracts/vendingFactory/contract.ts | 26 +-
contracts/vendingFactory/messages/execute.ts | 4 +-
.../{minter => vendingMinter}/contract.ts | 14 +-
contracts/vendingMinter/index.ts | 2 +
.../messages/execute.ts | 10 +-
.../messages/query.ts | 4 +-
.../{minter => vendingMinter}/useContract.ts | 42 +--
env.d.ts | 2 +
pages/collections/actions.tsx | 12 +-
pages/collections/create.tsx | 22 +-
pages/collections/queries.tsx | 14 +-
pages/contracts/baseMinter/execute.tsx | 145 ++++++++++
.../{minter => baseMinter}/index.tsx | 0
pages/contracts/baseMinter/instantiate.tsx | 259 ++++++++++++++++++
.../{minter => baseMinter}/migrate.tsx | 26 +-
pages/contracts/baseMinter/query.tsx | 116 ++++++++
.../{minter => vendingMinter}/execute.tsx | 28 +-
pages/contracts/vendingMinter/index.tsx | 1 +
.../{minter => vendingMinter}/instantiate.tsx | 22 +-
pages/contracts/vendingMinter/migrate.tsx | 132 +++++++++
.../{minter => vendingMinter}/query.tsx | 24 +-
utils/constants.ts | 2 +
44 files changed, 1641 insertions(+), 195 deletions(-)
rename components/contracts/{minter => baseMinter}/ExecuteCombobox.hooks.ts (74%)
rename components/contracts/{minter => baseMinter}/ExecuteCombobox.tsx (95%)
create mode 100644 components/contracts/vendingMinter/ExecuteCombobox.hooks.ts
create mode 100644 components/contracts/vendingMinter/ExecuteCombobox.tsx
create mode 100644 contracts/baseFactory/contract.ts
rename contracts/{minter => baseFactory}/index.ts (100%)
create mode 100644 contracts/baseFactory/messages/execute.ts
create mode 100644 contracts/baseFactory/useContract.ts
create mode 100644 contracts/baseMinter/contract.ts
create mode 100644 contracts/baseMinter/index.ts
create mode 100644 contracts/baseMinter/messages/execute.ts
create mode 100644 contracts/baseMinter/messages/query.ts
create mode 100644 contracts/baseMinter/useContract.ts
rename contracts/{minter => vendingMinter}/contract.ts (97%)
create mode 100644 contracts/vendingMinter/index.ts
rename contracts/{minter => vendingMinter}/messages/execute.ts (95%)
rename contracts/{minter => vendingMinter}/messages/query.ts (93%)
rename contracts/{minter => vendingMinter}/useContract.ts (65%)
create mode 100644 pages/contracts/baseMinter/execute.tsx
rename pages/contracts/{minter => baseMinter}/index.tsx (100%)
create mode 100644 pages/contracts/baseMinter/instantiate.tsx
rename pages/contracts/{minter => baseMinter}/migrate.tsx (83%)
create mode 100644 pages/contracts/baseMinter/query.tsx
rename pages/contracts/{minter => vendingMinter}/execute.tsx (87%)
create mode 100644 pages/contracts/vendingMinter/index.tsx
rename pages/contracts/{minter => vendingMinter}/instantiate.tsx (93%)
create mode 100644 pages/contracts/vendingMinter/migrate.tsx
rename pages/contracts/{minter => vendingMinter}/query.tsx (82%)
diff --git a/.env.example b/.env.example
index 5ee02b1..377c3be 100644
--- a/.env.example
+++ b/.env.example
@@ -1,9 +1,11 @@
-APP_VERSION=0.1.0
+APP_VERSION=0.2.0
NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS
NEXT_PUBLIC_SG721_CODE_ID=274
NEXT_PUBLIC_VENDING_MINTER_CODE_ID=275
NEXT_PUBLIC_VENDING_FACTORY_ADDRESS="stars1j4qn9krchp5xs8nued4j4vcr4j654wxkhf7acy76734xe5fsz08sku28s2"
+NEXT_PUBLIC_BASE_FACTORY_ADDRESS=""
+NEXT_PUBLIC_BASE_MINTER_CODE_ID=275
NEXT_PUBLIC_WHITELIST_CODE_ID=277
NEXT_PUBLIC_API_URL=https://
diff --git a/components/LinkTabs.data.ts b/components/LinkTabs.data.ts
index c9c7b39..81ba9bb 100644
--- a/components/LinkTabs.data.ts
+++ b/components/LinkTabs.data.ts
@@ -18,26 +18,49 @@ export const sg721LinkTabs: LinkTabProps[] = [
},
]
-export const minterLinkTabs: LinkTabProps[] = [
+export const vendingMinterLinkTabs: LinkTabProps[] = [
{
title: 'Instantiate',
- description: `Initialize a new Minter contract`,
- href: '/contracts/minter/instantiate',
+ description: `Initialize a new Vending Minter contract`,
+ href: '/contracts/vendingMinter/instantiate',
},
{
title: 'Query',
- description: `Dispatch queries with your Minter contract`,
- href: '/contracts/minter/query',
+ description: `Dispatch queries with your Vending Minter contract`,
+ href: '/contracts/vendingMinter/query',
},
{
title: 'Execute',
- description: `Execute Minter contract actions`,
- href: '/contracts/minter/execute',
+ description: `Execute Vending Minter contract actions`,
+ href: '/contracts/vendingMinter/execute',
},
{
title: 'Migrate',
- description: `Migrate Minter contract`,
- href: '/contracts/minter/migrate',
+ description: `Migrate Vending Minter contract`,
+ href: '/contracts/vendingMinter/migrate',
+ },
+]
+
+export const baseMinterLinkTabs: LinkTabProps[] = [
+ {
+ title: 'Instantiate',
+ description: `Initialize a new Base Minter contract`,
+ href: '/contracts/baseMinter/instantiate',
+ },
+ {
+ title: 'Query',
+ description: `Dispatch queries with your Base Minter contract`,
+ href: '/contracts/baseMinter/query',
+ },
+ {
+ title: 'Execute',
+ description: `Execute Base Minter contract actions`,
+ href: '/contracts/baseMinter/execute',
+ },
+ {
+ title: 'Migrate',
+ description: `Migrate Base Minter contract`,
+ href: '/contracts/baseMinter/migrate',
},
]
diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx
index 345d265..399dcae 100644
--- a/components/Sidebar.tsx
+++ b/components/Sidebar.tsx
@@ -14,7 +14,8 @@ const routes = [
{ text: 'My Collections', href: `/collections/myCollections/`, isChild: true },
{ text: 'Collection Actions', href: `/collections/actions/`, isChild: true },
{ text: 'Contract Dashboards', href: `/contracts/`, isChild: false },
- { text: 'Minter Contract', href: `/contracts/minter/`, isChild: true },
+ { text: 'Base Minter Contract', href: `/contracts/baseMinter/`, isChild: true },
+ { text: 'Vending Minter Contract', href: `/contracts/vendingMinter/`, isChild: true },
{ text: 'SG721 Contract', href: `/contracts/sg721/`, isChild: true },
{ text: 'Whitelist Contract', href: `/contracts/whitelist/`, isChild: true },
]
@@ -37,9 +38,9 @@ export const Sidebar = () => {
{
const wallet = useWallet()
const [lastTx, setLastTx] = useState('')
@@ -169,7 +169,7 @@ export const CollectionActions = ({
tokenId: tokenIdState.value,
tokenIds: tokenIdListState.value,
batchNumber: batchNumberState.value,
- minterMessages,
+ vendingMinterMessages,
sg721Messages,
recipient: recipientState.value,
recipients: airdropArray,
diff --git a/components/collections/actions/actions.ts b/components/collections/actions/actions.ts
index 86700f4..b664724 100644
--- a/components/collections/actions/actions.ts
+++ b/components/collections/actions/actions.ts
@@ -1,7 +1,7 @@
-import type { MinterInstance } from 'contracts/minter'
-import { useMinterContract } from 'contracts/minter'
import type { CollectionInfo, SG721Instance } from 'contracts/sg721'
import { useSG721Contract } from 'contracts/sg721'
+import type { VendingMinterInstance } from 'contracts/vendingMinter'
+import { useVendingMinterContract } from 'contracts/vendingMinter'
export type ActionType = typeof ACTION_TYPES[number]
@@ -150,11 +150,11 @@ export interface DispatchExecuteProps {
type Select = T
-/** @see {@link MinterInstance} */
+/** @see {@link VendingMinterInstance} */
export type DispatchExecuteArgs = {
minterContract: string
sg721Contract: string
- minterMessages?: MinterInstance
+ vendingMinterMessages?: VendingMinterInstance
sg721Messages?: SG721Instance
txSigner: string
} & (
@@ -183,40 +183,40 @@ export type DispatchExecuteArgs = {
)
export const dispatchExecute = async (args: DispatchExecuteArgs) => {
- const { minterMessages, sg721Messages, txSigner } = args
- if (!minterMessages || !sg721Messages) {
+ const { vendingMinterMessages, sg721Messages, txSigner } = args
+ if (!vendingMinterMessages || !sg721Messages) {
throw new Error('Cannot execute actions')
}
switch (args.type) {
case 'mint': {
- return minterMessages.mint(txSigner)
+ return vendingMinterMessages.mint(txSigner)
}
case 'purge': {
- return minterMessages.purge(txSigner)
+ return vendingMinterMessages.purge(txSigner)
}
case 'update_mint_price': {
- return minterMessages.updateMintPrice(txSigner, args.price)
+ return vendingMinterMessages.updateMintPrice(txSigner, args.price)
}
case 'mint_to': {
- return minterMessages.mintTo(txSigner, args.recipient)
+ return vendingMinterMessages.mintTo(txSigner, args.recipient)
}
case 'mint_for': {
- return minterMessages.mintFor(txSigner, args.recipient, args.tokenId)
+ return vendingMinterMessages.mintFor(txSigner, args.recipient, args.tokenId)
}
case 'batch_mint': {
- return minterMessages.batchMint(txSigner, args.recipient, args.batchNumber)
+ return vendingMinterMessages.batchMint(txSigner, args.recipient, args.batchNumber)
}
case 'set_whitelist': {
- return minterMessages.setWhitelist(txSigner, args.whitelist)
+ return vendingMinterMessages.setWhitelist(txSigner, args.whitelist)
}
case 'update_start_time': {
- return minterMessages.updateStartTime(txSigner, args.startTime)
+ return vendingMinterMessages.updateStartTime(txSigner, args.startTime)
}
case 'update_start_trading_time': {
- return minterMessages.updateStartTradingTime(txSigner, args.startTime)
+ return vendingMinterMessages.updateStartTradingTime(txSigner, args.startTime)
}
case 'update_per_address_limit': {
- return minterMessages.updatePerAddressLimit(txSigner, args.limit)
+ return vendingMinterMessages.updatePerAddressLimit(txSigner, args.limit)
}
case 'update_collection_info': {
return sg721Messages.updateCollectionInfo(args.collectionInfo as CollectionInfo)
@@ -225,10 +225,10 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
return sg721Messages.freezeCollectionInfo()
}
case 'shuffle': {
- return minterMessages.shuffle(txSigner)
+ return vendingMinterMessages.shuffle(txSigner)
}
case 'withdraw': {
- return minterMessages.withdraw(txSigner)
+ return vendingMinterMessages.withdraw(txSigner)
}
case 'transfer': {
return sg721Messages.transferNft(args.recipient, args.tokenId.toString())
@@ -243,13 +243,13 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
return sg721Messages.batchBurn(args.tokenIds)
}
case 'batch_mint_for': {
- return minterMessages.batchMintFor(txSigner, args.recipient, args.tokenIds)
+ return vendingMinterMessages.batchMintFor(txSigner, args.recipient, args.tokenIds)
}
case 'airdrop': {
- return minterMessages.airdrop(txSigner, args.recipients)
+ return vendingMinterMessages.airdrop(txSigner, args.recipients)
}
case 'burn_remaining': {
- return minterMessages.burnRemaining(txSigner)
+ return vendingMinterMessages.burnRemaining(txSigner)
}
default: {
throw new Error('Unknown action')
@@ -259,40 +259,40 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
export const previewExecutePayload = (args: DispatchExecuteArgs) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
- const { messages: minterMessages } = useMinterContract()
+ const { messages: vendingMinterMessages } = useVendingMinterContract()
// eslint-disable-next-line react-hooks/rules-of-hooks
const { messages: sg721Messages } = useSG721Contract()
const { minterContract, sg721Contract } = args
switch (args.type) {
case 'mint': {
- return minterMessages(minterContract)?.mint()
+ return vendingMinterMessages(minterContract)?.mint()
}
case 'purge': {
- return minterMessages(minterContract)?.purge()
+ return vendingMinterMessages(minterContract)?.purge()
}
case 'update_mint_price': {
- return minterMessages(minterContract)?.updateMintPrice(args.price)
+ return vendingMinterMessages(minterContract)?.updateMintPrice(args.price)
}
case 'mint_to': {
- return minterMessages(minterContract)?.mintTo(args.recipient)
+ return vendingMinterMessages(minterContract)?.mintTo(args.recipient)
}
case 'mint_for': {
- return minterMessages(minterContract)?.mintFor(args.recipient, args.tokenId)
+ return vendingMinterMessages(minterContract)?.mintFor(args.recipient, args.tokenId)
}
case 'batch_mint': {
- return minterMessages(minterContract)?.batchMint(args.recipient, args.batchNumber)
+ return vendingMinterMessages(minterContract)?.batchMint(args.recipient, args.batchNumber)
}
case 'set_whitelist': {
- return minterMessages(minterContract)?.setWhitelist(args.whitelist)
+ return vendingMinterMessages(minterContract)?.setWhitelist(args.whitelist)
}
case 'update_start_time': {
- return minterMessages(minterContract)?.updateStartTime(args.startTime)
+ return vendingMinterMessages(minterContract)?.updateStartTime(args.startTime)
}
case 'update_start_trading_time': {
- return minterMessages(minterContract)?.updateStartTradingTime(args.startTime as string)
+ return vendingMinterMessages(minterContract)?.updateStartTradingTime(args.startTime as string)
}
case 'update_per_address_limit': {
- return minterMessages(minterContract)?.updatePerAddressLimit(args.limit)
+ return vendingMinterMessages(minterContract)?.updatePerAddressLimit(args.limit)
}
case 'update_collection_info': {
return sg721Messages(sg721Contract)?.updateCollectionInfo(args.collectionInfo as CollectionInfo)
@@ -301,10 +301,10 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
return sg721Messages(sg721Contract)?.freezeCollectionInfo()
}
case 'shuffle': {
- return minterMessages(minterContract)?.shuffle()
+ return vendingMinterMessages(minterContract)?.shuffle()
}
case 'withdraw': {
- return minterMessages(minterContract)?.withdraw()
+ return vendingMinterMessages(minterContract)?.withdraw()
}
case 'transfer': {
return sg721Messages(sg721Contract)?.transferNft(args.recipient, args.tokenId.toString())
@@ -319,13 +319,13 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
return sg721Messages(sg721Contract)?.batchBurn(args.tokenIds)
}
case 'batch_mint_for': {
- return minterMessages(minterContract)?.batchMintFor(args.recipient, args.tokenIds)
+ return vendingMinterMessages(minterContract)?.batchMintFor(args.recipient, args.tokenIds)
}
case 'airdrop': {
- return minterMessages(minterContract)?.airdrop(args.recipients)
+ return vendingMinterMessages(minterContract)?.airdrop(args.recipients)
}
case 'burn_remaining': {
- return minterMessages(minterContract)?.burnRemaining()
+ return vendingMinterMessages(minterContract)?.burnRemaining()
}
default: {
return {}
diff --git a/components/collections/queries/Queries.tsx b/components/collections/queries/Queries.tsx
index e9138e3..b9ca571 100644
--- a/components/collections/queries/Queries.tsx
+++ b/components/collections/queries/Queries.tsx
@@ -5,8 +5,8 @@ import { FormControl } from 'components/FormControl'
import { AddressInput, TextInput } from 'components/forms/FormInput'
import { useInputState } from 'components/forms/FormInput.hooks'
import { JsonPreview } from 'components/JsonPreview'
-import type { MinterInstance } from 'contracts/minter'
import type { SG721Instance } from 'contracts/sg721'
+import type { MinterInstance } from 'contracts/vendingMinter'
import { toast } from 'react-hot-toast'
import { useQuery } from 'react-query'
diff --git a/components/collections/queries/query.ts b/components/collections/queries/query.ts
index e9454db..ad1482b 100644
--- a/components/collections/queries/query.ts
+++ b/components/collections/queries/query.ts
@@ -1,5 +1,5 @@
-import type { MinterInstance } from 'contracts/minter'
import type { SG721Instance } from 'contracts/sg721'
+import type { VendingMinterInstance } from 'contracts/vendingMinter'
export type QueryType = typeof QUERY_TYPES[number]
@@ -59,7 +59,7 @@ export interface DispatchExecuteProps {
type Select = T
export type DispatchQueryArgs = {
- minterMessages?: MinterInstance
+ vendingMinterMessages?: VendingMinterInstance
sg721Messages?: SG721Instance
} & (
| { type: undefined }
@@ -72,8 +72,8 @@ export type DispatchQueryArgs = {
)
export const dispatchQuery = async (args: DispatchQueryArgs) => {
- const { minterMessages, sg721Messages } = args
- if (!minterMessages || !sg721Messages) {
+ const { vendingMinterMessages, sg721Messages } = args
+ if (!vendingMinterMessages || !sg721Messages) {
throw new Error('Cannot execute actions')
}
switch (args.type) {
@@ -81,16 +81,16 @@ export const dispatchQuery = async (args: DispatchQueryArgs) => {
return sg721Messages.collectionInfo()
}
case 'mint_price': {
- return minterMessages.getMintPrice()
+ return vendingMinterMessages.getMintPrice()
}
case 'num_tokens': {
- return minterMessages.getMintableNumTokens()
+ return vendingMinterMessages.getMintableNumTokens()
}
case 'tokens_minted_to_user': {
- return minterMessages.getMintCount(args.address)
+ return vendingMinterMessages.getMintCount(args.address)
}
// case 'token_owners': {
- // return minterMessages.updateStartTime(txSigner, args.startTime)
+ // return vendingMinterMessages.updateStartTime(txSigner, args.startTime)
// }
case 'token_info': {
if (!args.tokenId) return
diff --git a/components/contracts/minter/ExecuteCombobox.hooks.ts b/components/contracts/baseMinter/ExecuteCombobox.hooks.ts
similarity index 74%
rename from components/contracts/minter/ExecuteCombobox.hooks.ts
rename to components/contracts/baseMinter/ExecuteCombobox.hooks.ts
index 19830ab..2c9ee59 100644
--- a/components/contracts/minter/ExecuteCombobox.hooks.ts
+++ b/components/contracts/baseMinter/ExecuteCombobox.hooks.ts
@@ -1,4 +1,4 @@
-import type { ExecuteListItem } from 'contracts/minter/messages/execute'
+import type { ExecuteListItem } from 'contracts/baseMinter/messages/execute'
import { useState } from 'react'
export const useExecuteComboboxState = () => {
diff --git a/components/contracts/minter/ExecuteCombobox.tsx b/components/contracts/baseMinter/ExecuteCombobox.tsx
similarity index 95%
rename from components/contracts/minter/ExecuteCombobox.tsx
rename to components/contracts/baseMinter/ExecuteCombobox.tsx
index e327c6d..7f32de0 100644
--- a/components/contracts/minter/ExecuteCombobox.tsx
+++ b/components/contracts/baseMinter/ExecuteCombobox.tsx
@@ -1,8 +1,8 @@
import { Combobox, Transition } from '@headlessui/react'
import clsx from 'clsx'
import { FormControl } from 'components/FormControl'
-import type { ExecuteListItem } from 'contracts/minter/messages/execute'
-import { EXECUTE_LIST } from 'contracts/minter/messages/execute'
+import type { ExecuteListItem } from 'contracts/baseMinter/messages/execute'
+import { EXECUTE_LIST } from 'contracts/baseMinter/messages/execute'
import { matchSorter } from 'match-sorter'
import { Fragment, useState } from 'react'
import { FaChevronDown, FaInfoCircle } from 'react-icons/fa'
diff --git a/components/contracts/vendingMinter/ExecuteCombobox.hooks.ts b/components/contracts/vendingMinter/ExecuteCombobox.hooks.ts
new file mode 100644
index 0000000..09ef184
--- /dev/null
+++ b/components/contracts/vendingMinter/ExecuteCombobox.hooks.ts
@@ -0,0 +1,7 @@
+import type { ExecuteListItem } from 'contracts/vendingMinter/messages/execute'
+import { useState } from 'react'
+
+export const useExecuteComboboxState = () => {
+ const [value, setValue] = useState(null)
+ return { value, onChange: (item: ExecuteListItem) => setValue(item) }
+}
diff --git a/components/contracts/vendingMinter/ExecuteCombobox.tsx b/components/contracts/vendingMinter/ExecuteCombobox.tsx
new file mode 100644
index 0000000..0f01538
--- /dev/null
+++ b/components/contracts/vendingMinter/ExecuteCombobox.tsx
@@ -0,0 +1,92 @@
+import { Combobox, Transition } from '@headlessui/react'
+import clsx from 'clsx'
+import { FormControl } from 'components/FormControl'
+import type { ExecuteListItem } from 'contracts/vendingMinter/messages/execute'
+import { EXECUTE_LIST } from 'contracts/vendingMinter/messages/execute'
+import { matchSorter } from 'match-sorter'
+import { Fragment, useState } from 'react'
+import { FaChevronDown, FaInfoCircle } from 'react-icons/fa'
+
+export interface ExecuteComboboxProps {
+ value: ExecuteListItem | null
+ onChange: (item: ExecuteListItem) => void
+}
+
+export const ExecuteCombobox = ({ value, onChange }: ExecuteComboboxProps) => {
+ const [search, setSearch] = useState('')
+
+ const filtered =
+ search === '' ? EXECUTE_LIST : matchSorter(EXECUTE_LIST, search, { keys: ['id', 'name', 'description'] })
+
+ return (
+
+
+ val?.name ?? ''}
+ id="message-type"
+ onChange={(event) => setSearch(event.target.value)}
+ placeholder="Select message type"
+ />
+
+
+ {({ open }) => }
+
+
+ setSearch('')} as={Fragment}>
+
+ {filtered.length < 1 && (
+
+ Message type not found.
+
+ )}
+ {filtered.map((entry) => (
+
+ clsx('flex relative flex-col py-2 px-4 space-y-1 cursor-pointer', { 'bg-plumbus-70': active })
+ }
+ value={entry}
+ >
+ {entry.name}
+ {entry.description}
+
+ ))}
+
+
+
+
+ {value && (
+
+
+
+
+
{value.description}
+
+ )}
+
+ )
+}
diff --git a/contexts/contracts.tsx b/contexts/contracts.tsx
index 5094c4a..b0fbd06 100644
--- a/contexts/contracts.tsx
+++ b/contexts/contracts.tsx
@@ -1,9 +1,13 @@
-import type { UseMinterContractProps } from 'contracts/minter'
-import { useMinterContract } from 'contracts/minter'
+import type { UseBaseFactoryContractProps } from 'contracts/baseFactory'
+import { useBaseFactoryContract } from 'contracts/baseFactory'
+import type { UseBaseMinterContractProps } from 'contracts/baseMinter'
+import { useBaseMinterContract } from 'contracts/baseMinter'
import type { UseSG721ContractProps } from 'contracts/sg721'
import { useSG721Contract } from 'contracts/sg721'
import type { UseVendingFactoryContractProps } from 'contracts/vendingFactory'
import { useVendingFactoryContract } from 'contracts/vendingFactory'
+import type { UseVendingMinterContractProps } from 'contracts/vendingMinter'
+import { useVendingMinterContract } from 'contracts/vendingMinter'
import type { UseWhiteListContractProps } from 'contracts/whitelist'
import { useWhiteListContract } from 'contracts/whitelist'
import type { ReactNode, VFC } from 'react'
@@ -16,9 +20,11 @@ import create from 'zustand'
*/
export interface ContractsStore extends State {
sg721: UseSG721ContractProps | null
- minter: UseMinterContractProps | null
+ vendingMinter: UseVendingMinterContractProps | null
+ baseMinter: UseBaseMinterContractProps | null
whitelist: UseWhiteListContractProps | null
vendingFactory: UseVendingFactoryContractProps | null
+ baseFactory: UseBaseFactoryContractProps | null
}
/**
@@ -26,9 +32,11 @@ export interface ContractsStore extends State {
*/
export const defaultValues: ContractsStore = {
sg721: null,
- minter: null,
+ vendingMinter: null,
+ baseMinter: null,
whitelist: null,
vendingFactory: null,
+ baseFactory: null,
}
/**
@@ -53,18 +61,22 @@ export const ContractsProvider = ({ children }: { children: ReactNode }) => {
const ContractsSubscription: VFC = () => {
const sg721 = useSG721Contract()
- const minter = useMinterContract()
+ const vendingMinter = useVendingMinterContract()
+ const baseMinter = useBaseMinterContract()
const whitelist = useWhiteListContract()
const vendingFactory = useVendingFactoryContract()
+ const baseFactory = useBaseFactoryContract()
useEffect(() => {
useContracts.setState({
sg721,
- minter,
+ vendingMinter,
+ baseMinter,
whitelist,
vendingFactory,
+ baseFactory,
})
- }, [sg721, minter, whitelist, vendingFactory])
+ }, [sg721, vendingMinter, baseMinter, whitelist, vendingFactory, baseFactory])
return null
}
diff --git a/contracts/baseFactory/contract.ts b/contracts/baseFactory/contract.ts
new file mode 100644
index 0000000..20fd166
--- /dev/null
+++ b/contracts/baseFactory/contract.ts
@@ -0,0 +1,93 @@
+import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
+import type { Coin } from '@cosmjs/proto-signing'
+import { coin } from '@cosmjs/proto-signing'
+import type { logs } from '@cosmjs/stargate'
+import { BASE_FACTORY_ADDRESS } from 'utils/constants'
+
+export interface CreateBaseMinterResponse {
+ readonly baseMinterAddress: string
+ readonly sg721Address: string
+ readonly transactionHash: string
+ readonly logs: readonly logs.Log[]
+}
+
+export interface BaseFactoryInstance {
+ readonly contractAddress: string
+
+ //Query
+ getParams: () => Promise
+ //Execute
+ createBaseMinter: (
+ senderAddress: string,
+ msg: Record,
+ funds: Coin[],
+ ) => Promise
+}
+
+export interface BaseFactoryMessages {
+ createBaseMinter: (msg: Record) => CreateBaseMinterMessage
+}
+
+export interface CreateBaseMinterMessage {
+ sender: string
+ contract: string
+ msg: Record
+ funds: Coin[]
+}
+
+export interface BaseFactoryContract {
+ use: (contractAddress: string) => BaseFactoryInstance
+
+ messages: (contractAddress: string) => BaseFactoryMessages
+}
+
+export const baseFactory = (client: SigningCosmWasmClient, txSigner: string): BaseFactoryContract => {
+ const use = (contractAddress: string): BaseFactoryInstance => {
+ //Query
+ const getParams = async (): Promise => {
+ const res = await client.queryContractSmart(contractAddress, {
+ params: {},
+ })
+ return res
+ }
+
+ //Execute
+ const createBaseMinter = async (
+ senderAddress: string,
+ msg: Record,
+ funds: Coin[],
+ ): Promise => {
+ const result = await client.execute(senderAddress, BASE_FACTORY_ADDRESS, msg, 'auto', '', funds)
+
+ return {
+ baseMinterAddress: result.logs[0].events[5].attributes[0].value,
+ sg721Address: result.logs[0].events[5].attributes[2].value,
+ transactionHash: result.transactionHash,
+ logs: result.logs,
+ }
+ }
+
+ return {
+ contractAddress,
+ getParams,
+ createBaseMinter,
+ }
+ }
+
+ const messages = (contractAddress: string) => {
+ const createBaseMinter = (msg: Record): CreateBaseMinterMessage => {
+ return {
+ sender: txSigner,
+ contract: contractAddress,
+ msg,
+ funds: [coin('1000000000', 'ustars')],
+ }
+ }
+
+ return {
+ createBaseMinter,
+ }
+ }
+
+ return { use, messages }
+}
diff --git a/contracts/minter/index.ts b/contracts/baseFactory/index.ts
similarity index 100%
rename from contracts/minter/index.ts
rename to contracts/baseFactory/index.ts
diff --git a/contracts/baseFactory/messages/execute.ts b/contracts/baseFactory/messages/execute.ts
new file mode 100644
index 0000000..374aba9
--- /dev/null
+++ b/contracts/baseFactory/messages/execute.ts
@@ -0,0 +1,28 @@
+import type { Coin } from '@cosmjs/proto-signing'
+
+import type { BaseFactoryInstance } from '../index'
+import { useBaseFactoryContract } from '../index'
+
+/** @see {@link VendingFactoryInstance} */
+export interface DispatchExecuteArgs {
+ contract: string
+ messages?: BaseFactoryInstance
+ txSigner: string
+ msg: Record
+ funds: Coin[]
+}
+
+export const dispatchExecute = async (args: DispatchExecuteArgs) => {
+ const { messages, txSigner } = args
+ if (!messages) {
+ throw new Error('cannot dispatch execute, messages is not defined')
+ }
+ return messages.createBaseMinter(txSigner, args.msg, args.funds)
+}
+
+export const previewExecutePayload = (args: DispatchExecuteArgs) => {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ const { messages } = useBaseFactoryContract()
+ const { contract } = args
+ return messages(contract)?.createBaseMinter(args.msg)
+}
diff --git a/contracts/baseFactory/useContract.ts b/contracts/baseFactory/useContract.ts
new file mode 100644
index 0000000..d03ff09
--- /dev/null
+++ b/contracts/baseFactory/useContract.ts
@@ -0,0 +1,57 @@
+import { useWallet } from 'contexts/wallet'
+import { useCallback, useEffect, useState } from 'react'
+
+import type { BaseFactoryContract, BaseFactoryInstance, BaseFactoryMessages } from './contract'
+import { baseFactory as initContract } from './contract'
+
+export interface UseBaseFactoryContractProps {
+ use: (customAddress: string) => BaseFactoryInstance | undefined
+ updateContractAddress: (contractAddress: string) => void
+ getContractAddress: () => string | undefined
+ messages: (contractAddress: string) => BaseFactoryMessages | undefined
+}
+
+export function useBaseFactoryContract(): UseBaseFactoryContractProps {
+ const wallet = useWallet()
+
+ const [address, setAddress] = useState('')
+ const [baseFactory, setBaseFactory] = useState()
+
+ useEffect(() => {
+ setAddress(localStorage.getItem('contract_address') || '')
+ }, [])
+
+ useEffect(() => {
+ const BaseFactoryBaseContract = initContract(wallet.getClient(), wallet.address)
+ setBaseFactory(BaseFactoryBaseContract)
+ }, [wallet])
+
+ const updateContractAddress = (contractAddress: string) => {
+ setAddress(contractAddress)
+ }
+
+ const use = useCallback(
+ (customAddress = ''): BaseFactoryInstance | undefined => {
+ return baseFactory?.use(address || customAddress)
+ },
+ [baseFactory, address],
+ )
+
+ const getContractAddress = (): string | undefined => {
+ return address
+ }
+
+ const messages = useCallback(
+ (customAddress = ''): BaseFactoryMessages | undefined => {
+ return baseFactory?.messages(address || customAddress)
+ },
+ [baseFactory, address],
+ )
+
+ return {
+ use,
+ updateContractAddress,
+ getContractAddress,
+ messages,
+ }
+}
diff --git a/contracts/baseMinter/contract.ts b/contracts/baseMinter/contract.ts
new file mode 100644
index 0000000..7ebfcd4
--- /dev/null
+++ b/contracts/baseMinter/contract.ts
@@ -0,0 +1,243 @@
+import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
+import type { Coin } from '@cosmjs/proto-signing'
+import { coin } from '@cosmjs/proto-signing'
+import type { logs } from '@cosmjs/stargate'
+import type { Timestamp } from '@stargazezone/types/contracts/minter/shared-types'
+import toast from 'react-hot-toast'
+import { BASE_FACTORY_ADDRESS } from 'utils/constants'
+
+export interface InstantiateResponse {
+ readonly contractAddress: string
+ readonly transactionHash: string
+ readonly logs: readonly logs.Log[]
+}
+
+export interface MigrateResponse {
+ readonly transactionHash: string
+ readonly logs: readonly logs.Log[]
+}
+
+export interface RoyaltyInfo {
+ payment_address: string
+ share: string
+}
+
+export interface BaseMinterInstance {
+ readonly contractAddress: string
+
+ //Query
+ getConfig: () => Promise
+ getStatus: () => Promise
+
+ //Execute
+ mint: (senderAddress: string, tokenUri: string) => Promise
+ updateStartTradingTime: (senderAddress: string, time?: Timestamp) => Promise
+}
+
+export interface BaseMinterMessages {
+ mint: (tokenUri: string) => MintMessage
+ updateStartTradingTime: (time: Timestamp) => UpdateStartTradingTimeMessage
+}
+
+export interface MintMessage {
+ sender: string
+ contract: string
+ msg: {
+ mint: {
+ token_uri: string
+ }
+ }
+ funds: Coin[]
+}
+
+export interface UpdateStartTradingTimeMessage {
+ sender: string
+ contract: string
+ msg: {
+ update_start_trading_time: string
+ }
+ funds: Coin[]
+}
+
+export interface CustomMessage {
+ sender: string
+ contract: string
+ msg: Record[]
+ funds: Coin[]
+}
+
+export interface MintPriceMessage {
+ public_price: {
+ denom: string
+ amount: string
+ }
+ airdrop_price: {
+ denom: string
+ amount: string
+ }
+ whitelist_price?: {
+ denom: string
+ amount: string
+ }
+ current_price: {
+ denom: string
+ amount: string
+ }
+}
+
+export interface BaseMinterContract {
+ instantiate: (
+ senderAddress: string,
+ codeId: number,
+ initMsg: Record,
+ label: string,
+ admin?: string,
+ funds?: Coin[],
+ ) => Promise
+
+ migrate: (
+ senderAddress: string,
+ contractAddress: string,
+ codeId: number,
+ migrateMsg: Record,
+ ) => Promise
+
+ use: (contractAddress: string) => BaseMinterInstance
+
+ messages: (contractAddress: string) => BaseMinterMessages
+}
+
+export const baseMinter = (client: SigningCosmWasmClient, txSigner: string): BaseMinterContract => {
+ const use = (contractAddress: string): BaseMinterInstance => {
+ //Query
+ const getFactoryParameters = async (): Promise => {
+ const res = await client.queryContractSmart(BASE_FACTORY_ADDRESS, { params: {} })
+ return res
+ console.log(res)
+ }
+
+ const getConfig = async (): Promise => {
+ const res = await client.queryContractSmart(contractAddress, {
+ config: {},
+ })
+ return res
+ }
+
+ const getStatus = async (): Promise => {
+ const res = await client.queryContractSmart(contractAddress, {
+ status: {},
+ })
+ return res
+ }
+
+ //Execute
+ const mint = async (senderAddress: string, tokenUri: string): Promise => {
+ //const factoryParameters = await baseFactory?.use(BASE_FACTORY_ADDRESS)?.getParams()
+
+ const factoryParameters = await toast.promise(getFactoryParameters(), {
+ loading: 'Querying Factory Parameters...',
+ error: 'Querying Factory Parameters failed!',
+ success: 'Query successful! Minting...',
+ })
+ console.log(factoryParameters.params.mint_fee_bps)
+
+ const price = (await getConfig()).config.mint_price.amount
+ console.log(price)
+ console.log((Number(price) * Number(factoryParameters.params.mint_fee_bps)) / 100)
+ const res = await client.execute(
+ senderAddress,
+ contractAddress,
+ {
+ mint: { token_uri: tokenUri },
+ },
+ 'auto',
+ '',
+ [coin((Number(price) * Number(factoryParameters.params.mint_fee_bps)) / 100 / 100, 'ustars')],
+ )
+
+ return res.transactionHash
+ }
+
+ const updateStartTradingTime = async (senderAddress: string, time?: Timestamp): Promise => {
+ const res = await client.execute(
+ senderAddress,
+ contractAddress,
+ {
+ update_start_trading_time: time || null,
+ },
+ 'auto',
+ '',
+ )
+
+ return res.transactionHash
+ }
+
+ return {
+ contractAddress,
+ getConfig,
+ getStatus,
+ mint,
+ updateStartTradingTime,
+ }
+ }
+
+ 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,
+ initMsg: Record,
+ label: string,
+ ): Promise => {
+ const result = await client.instantiate(senderAddress, codeId, initMsg, label, 'auto', {
+ funds: [coin('1000000000', 'ustars')],
+ })
+ return {
+ contractAddress: result.contractAddress,
+ transactionHash: result.transactionHash,
+ logs: result.logs,
+ }
+ }
+
+ const messages = (contractAddress: string) => {
+ const mint = (tokenUri: string): MintMessage => {
+ return {
+ sender: txSigner,
+ contract: contractAddress,
+ msg: {
+ mint: { token_uri: tokenUri },
+ },
+ funds: [],
+ }
+ }
+
+ const updateStartTradingTime = (startTime: string): UpdateStartTradingTimeMessage => {
+ return {
+ sender: txSigner,
+ contract: contractAddress,
+ msg: {
+ update_start_trading_time: startTime,
+ },
+ funds: [],
+ }
+ }
+
+ return {
+ mint,
+ updateStartTradingTime,
+ }
+ }
+
+ return { use, instantiate, migrate, messages }
+}
diff --git a/contracts/baseMinter/index.ts b/contracts/baseMinter/index.ts
new file mode 100644
index 0000000..6dc6461
--- /dev/null
+++ b/contracts/baseMinter/index.ts
@@ -0,0 +1,2 @@
+export * from './contract'
+export * from './useContract'
diff --git a/contracts/baseMinter/messages/execute.ts b/contracts/baseMinter/messages/execute.ts
new file mode 100644
index 0000000..65fd2f0
--- /dev/null
+++ b/contracts/baseMinter/messages/execute.ts
@@ -0,0 +1,82 @@
+import type { BaseMinterInstance } from '../index'
+import { useBaseMinterContract } from '../index'
+
+export type ExecuteType = typeof EXECUTE_TYPES[number]
+
+export const EXECUTE_TYPES = ['mint', 'update_start_trading_time'] as const
+
+export interface ExecuteListItem {
+ id: ExecuteType
+ name: string
+ description?: string
+}
+
+export const EXECUTE_LIST: ExecuteListItem[] = [
+ {
+ id: 'mint',
+ name: 'Mint',
+ description: `Mint new tokens for a given address`,
+ },
+ {
+ id: 'update_start_trading_time',
+ name: 'Update Start Trading Time',
+ description: `Update start trading time for minting`,
+ },
+]
+
+export interface DispatchExecuteProps {
+ type: ExecuteType
+ [k: string]: unknown
+}
+
+type Select = T
+
+/** @see {@link BaseMinterInstance} */
+export type DispatchExecuteArgs = {
+ contract: string
+ messages?: BaseMinterInstance
+ txSigner: string
+} & (
+ | { type: undefined }
+ | { type: Select<'mint'>; tokenUri: string }
+ | { type: Select<'update_start_trading_time'>; startTime?: string }
+)
+
+export const dispatchExecute = async (args: DispatchExecuteArgs) => {
+ const { messages, txSigner } = args
+ if (!messages) {
+ throw new Error('cannot dispatch execute, messages is not defined')
+ }
+ switch (args.type) {
+ case 'mint': {
+ return messages.mint(txSigner, args.tokenUri)
+ }
+ case 'update_start_trading_time': {
+ return messages.updateStartTradingTime(txSigner, args.startTime)
+ }
+ default: {
+ throw new Error('unknown execute type')
+ }
+ }
+}
+
+export const previewExecutePayload = (args: DispatchExecuteArgs) => {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ const { messages } = useBaseMinterContract()
+ const { contract } = args
+ switch (args.type) {
+ case 'mint': {
+ return messages(contract)?.mint(args.tokenUri)
+ }
+ case 'update_start_trading_time': {
+ return messages(contract)?.updateStartTradingTime(args.startTime as string)
+ }
+ default: {
+ return {}
+ }
+ }
+}
+
+export const isEitherType = (type: unknown, arr: T[]): type is T => {
+ return arr.some((val) => type === val)
+}
diff --git a/contracts/baseMinter/messages/query.ts b/contracts/baseMinter/messages/query.ts
new file mode 100644
index 0000000..6f92b26
--- /dev/null
+++ b/contracts/baseMinter/messages/query.ts
@@ -0,0 +1,37 @@
+import type { BaseMinterInstance } from '../contract'
+
+export type QueryType = typeof QUERY_TYPES[number]
+
+export const QUERY_TYPES = ['config', 'status'] as const
+
+export interface QueryListItem {
+ id: QueryType
+ name: string
+ description?: string
+}
+
+export const QUERY_LIST: QueryListItem[] = [
+ { id: 'config', name: 'Config', description: 'Query current contract config' },
+ { id: 'status', name: 'Status', description: 'Query current contract status' },
+]
+
+export interface DispatchQueryProps {
+ address: string
+ messages: BaseMinterInstance | undefined
+ type: QueryType
+}
+
+export const dispatchQuery = (props: DispatchQueryProps) => {
+ const { address, messages, type } = props
+ switch (type) {
+ case 'config': {
+ return messages?.getConfig()
+ }
+ case 'status': {
+ return messages?.getStatus()
+ }
+ default: {
+ throw new Error('unknown query type')
+ }
+ }
+}
diff --git a/contracts/baseMinter/useContract.ts b/contracts/baseMinter/useContract.ts
new file mode 100644
index 0000000..35d54fe
--- /dev/null
+++ b/contracts/baseMinter/useContract.ts
@@ -0,0 +1,102 @@
+import type { Coin } from '@cosmjs/proto-signing'
+import type { logs } from '@cosmjs/stargate'
+import { useWallet } from 'contexts/wallet'
+import { useCallback, useEffect, useState } from 'react'
+
+import type { BaseMinterContract, BaseMinterInstance, BaseMinterMessages, MigrateResponse } from './contract'
+import { baseMinter as initContract } from './contract'
+
+interface InstantiateResponse {
+ readonly contractAddress: string
+ readonly transactionHash: string
+ readonly logs: readonly logs.Log[]
+}
+
+export interface UseBaseMinterContractProps {
+ instantiate: (
+ codeId: number,
+ initMsg: Record,
+ label: string,
+ admin?: string,
+ funds?: Coin[],
+ ) => Promise
+ migrate: (contractAddress: string, codeId: number, migrateMsg: Record) => Promise
+ use: (customAddress: string) => BaseMinterInstance | undefined
+ updateContractAddress: (contractAddress: string) => void
+ getContractAddress: () => string | undefined
+ messages: (contractAddress: string) => BaseMinterMessages | undefined
+}
+
+export function useBaseMinterContract(): UseBaseMinterContractProps {
+ const wallet = useWallet()
+
+ const [address, setAddress] = useState('')
+ const [baseMinter, setBaseMinter] = useState()
+
+ useEffect(() => {
+ setAddress(localStorage.getItem('contract_address') || '')
+ }, [])
+
+ useEffect(() => {
+ const BaseMinterBaseContract = initContract(wallet.getClient(), wallet.address)
+ setBaseMinter(BaseMinterBaseContract)
+ }, [wallet])
+
+ const updateContractAddress = (contractAddress: string) => {
+ setAddress(contractAddress)
+ }
+
+ const instantiate = useCallback(
+ (codeId: number, initMsg: Record, label: string, admin?: string): Promise => {
+ return new Promise((resolve, reject) => {
+ if (!baseMinter) {
+ reject(new Error('Contract is not initialized.'))
+ return
+ }
+ baseMinter.instantiate(wallet.address, codeId, initMsg, label, admin).then(resolve).catch(reject)
+ })
+ },
+ [baseMinter, wallet],
+ )
+
+ const migrate = useCallback(
+ (contractAddress: string, codeId: number, migrateMsg: Record): Promise => {
+ return new Promise((resolve, reject) => {
+ if (!baseMinter) {
+ reject(new Error('Contract is not initialized.'))
+ return
+ }
+ console.log(wallet.address, contractAddress, codeId)
+ baseMinter.migrate(wallet.address, contractAddress, codeId, migrateMsg).then(resolve).catch(reject)
+ })
+ },
+ [baseMinter, wallet],
+ )
+
+ const use = useCallback(
+ (customAddress = ''): BaseMinterInstance | undefined => {
+ return baseMinter?.use(address || customAddress)
+ },
+ [baseMinter, address],
+ )
+
+ const getContractAddress = (): string | undefined => {
+ return address
+ }
+
+ const messages = useCallback(
+ (customAddress = ''): BaseMinterMessages | undefined => {
+ return baseMinter?.messages(address || customAddress)
+ },
+ [baseMinter, address],
+ )
+
+ return {
+ instantiate,
+ use,
+ updateContractAddress,
+ getContractAddress,
+ messages,
+ migrate,
+ }
+}
diff --git a/contracts/sg721/contract.ts b/contracts/sg721/contract.ts
index 7183816..dbefd57 100644
--- a/contracts/sg721/contract.ts
+++ b/contracts/sg721/contract.ts
@@ -4,7 +4,7 @@ import type { Coin, logs } from '@cosmjs/stargate'
import { coin } from '@cosmjs/stargate'
import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx'
-import type { RoyaltyInfo } from '../minter/contract'
+import type { RoyaltyInfo } from '../vendingMinter/contract'
export interface InstantiateResponse {
readonly contractAddress: string
diff --git a/contracts/vendingFactory/contract.ts b/contracts/vendingFactory/contract.ts
index a172157..6082804 100644
--- a/contracts/vendingFactory/contract.ts
+++ b/contracts/vendingFactory/contract.ts
@@ -4,8 +4,8 @@ import { coin } from '@cosmjs/proto-signing'
import type { logs } from '@cosmjs/stargate'
import { VENDING_FACTORY_ADDRESS } from 'utils/constants'
-export interface CreateMinterResponse {
- readonly minterAddress: string
+export interface CreateVendingMinterResponse {
+ readonly vendingMinterAddress: string
readonly sg721Address: string
readonly transactionHash: string
readonly logs: readonly logs.Log[]
@@ -17,14 +17,18 @@ export interface VendingFactoryInstance {
//Query
//Execute
- createMinter: (senderAddress: string, msg: Record, funds: Coin[]) => Promise
+ createVendingMinter: (
+ senderAddress: string,
+ msg: Record,
+ funds: Coin[],
+ ) => Promise
}
export interface VendingFactoryMessages {
- createMinter: (msg: Record) => CreateMinterMessage
+ createVendingMinter: (msg: Record) => CreateVendingMinterMessage
}
-export interface CreateMinterMessage {
+export interface CreateVendingMinterMessage {
sender: string
contract: string
msg: Record
@@ -42,15 +46,15 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string):
//Query
//Execute
- const createMinter = async (
+ const createVendingMinter = async (
senderAddress: string,
msg: Record,
funds: Coin[],
- ): Promise => {
+ ): Promise => {
const result = await client.execute(senderAddress, VENDING_FACTORY_ADDRESS, msg, 'auto', '', funds)
return {
- minterAddress: result.logs[0].events[5].attributes[0].value,
+ vendingMinterAddress: result.logs[0].events[5].attributes[0].value,
sg721Address: result.logs[0].events[5].attributes[2].value,
transactionHash: result.transactionHash,
logs: result.logs,
@@ -59,12 +63,12 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string):
return {
contractAddress,
- createMinter,
+ createVendingMinter,
}
}
const messages = (contractAddress: string) => {
- const createMinter = (msg: Record): CreateMinterMessage => {
+ const createVendingMinter = (msg: Record): CreateVendingMinterMessage => {
return {
sender: txSigner,
contract: contractAddress,
@@ -74,7 +78,7 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string):
}
return {
- createMinter,
+ createVendingMinter,
}
}
diff --git a/contracts/vendingFactory/messages/execute.ts b/contracts/vendingFactory/messages/execute.ts
index fedf1f2..7939a7f 100644
--- a/contracts/vendingFactory/messages/execute.ts
+++ b/contracts/vendingFactory/messages/execute.ts
@@ -17,12 +17,12 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
if (!messages) {
throw new Error('cannot dispatch execute, messages is not defined')
}
- return messages.createMinter(txSigner, args.msg, args.funds)
+ return messages.createVendingMinter(txSigner, args.msg, args.funds)
}
export const previewExecutePayload = (args: DispatchExecuteArgs) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const { messages } = useVendingFactoryContract()
const { contract } = args
- return messages(contract)?.createMinter(args.msg)
+ return messages(contract)?.createVendingMinter(args.msg)
}
diff --git a/contracts/minter/contract.ts b/contracts/vendingMinter/contract.ts
similarity index 97%
rename from contracts/minter/contract.ts
rename to contracts/vendingMinter/contract.ts
index ca9b9e5..e462cfb 100644
--- a/contracts/minter/contract.ts
+++ b/contracts/vendingMinter/contract.ts
@@ -22,7 +22,7 @@ export interface RoyaltyInfo {
share: string
}
-export interface MinterInstance {
+export interface VendingMinterInstance {
readonly contractAddress: string
//Query
@@ -50,7 +50,7 @@ export interface MinterInstance {
burnRemaining: (senderAddress: string) => Promise
}
-export interface MinterMessages {
+export interface VendingMinterMessages {
mint: () => MintMessage
purge: () => PurgeMessage
updateMintPrice: (price: string) => UpdateMintPriceMessage
@@ -219,7 +219,7 @@ export interface MintPriceMessage {
}
}
-export interface MinterContract {
+export interface VendingMinterContract {
instantiate: (
senderAddress: string,
codeId: number,
@@ -236,13 +236,13 @@ export interface MinterContract {
migrateMsg: Record,
) => Promise
- use: (contractAddress: string) => MinterInstance
+ use: (contractAddress: string) => VendingMinterInstance
- messages: (contractAddress: string) => MinterMessages
+ messages: (contractAddress: string) => VendingMinterMessages
}
-export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterContract => {
- const use = (contractAddress: string): MinterInstance => {
+export const vendingMinter = (client: SigningCosmWasmClient, txSigner: string): VendingMinterContract => {
+ const use = (contractAddress: string): VendingMinterInstance => {
//Query
const getConfig = async (): Promise => {
const res = await client.queryContractSmart(contractAddress, {
diff --git a/contracts/vendingMinter/index.ts b/contracts/vendingMinter/index.ts
new file mode 100644
index 0000000..6dc6461
--- /dev/null
+++ b/contracts/vendingMinter/index.ts
@@ -0,0 +1,2 @@
+export * from './contract'
+export * from './useContract'
diff --git a/contracts/minter/messages/execute.ts b/contracts/vendingMinter/messages/execute.ts
similarity index 95%
rename from contracts/minter/messages/execute.ts
rename to contracts/vendingMinter/messages/execute.ts
index f2f072f..058ae73 100644
--- a/contracts/minter/messages/execute.ts
+++ b/contracts/vendingMinter/messages/execute.ts
@@ -1,5 +1,5 @@
-import type { MinterInstance } from '../index'
-import { useMinterContract } from '../index'
+import type { VendingMinterInstance } from '../index'
+import { useVendingMinterContract } from '../index'
export type ExecuteType = typeof EXECUTE_TYPES[number]
@@ -89,10 +89,10 @@ export interface DispatchExecuteProps {
type Select = T
-/** @see {@link MinterInstance} */
+/** @see {@link VendingMinterInstance} */
export type DispatchExecuteArgs = {
contract: string
- messages?: MinterInstance
+ messages?: VendingMinterInstance
txSigner: string
} & (
| { type: undefined }
@@ -160,7 +160,7 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
export const previewExecutePayload = (args: DispatchExecuteArgs) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
- const { messages } = useMinterContract()
+ const { messages } = useVendingMinterContract()
const { contract } = args
switch (args.type) {
case 'mint': {
diff --git a/contracts/minter/messages/query.ts b/contracts/vendingMinter/messages/query.ts
similarity index 93%
rename from contracts/minter/messages/query.ts
rename to contracts/vendingMinter/messages/query.ts
index 496ca5e..f5673ed 100644
--- a/contracts/minter/messages/query.ts
+++ b/contracts/vendingMinter/messages/query.ts
@@ -1,4 +1,4 @@
-import type { MinterInstance } from '../contract'
+import type { VendingMinterInstance } from '../contract'
export type QueryType = typeof QUERY_TYPES[number]
@@ -24,7 +24,7 @@ export const QUERY_LIST: QueryListItem[] = [
export interface DispatchQueryProps {
address: string
- messages: MinterInstance | undefined
+ messages: VendingMinterInstance | undefined
type: QueryType
}
diff --git a/contracts/minter/useContract.ts b/contracts/vendingMinter/useContract.ts
similarity index 65%
rename from contracts/minter/useContract.ts
rename to contracts/vendingMinter/useContract.ts
index 1121ea2..d118f04 100644
--- a/contracts/minter/useContract.ts
+++ b/contracts/vendingMinter/useContract.ts
@@ -3,8 +3,8 @@ import type { logs } from '@cosmjs/stargate'
import { useWallet } from 'contexts/wallet'
import { useCallback, useEffect, useState } from 'react'
-import type { MigrateResponse, MinterContract, MinterInstance, MinterMessages } from './contract'
-import { minter as initContract } from './contract'
+import type { MigrateResponse, VendingMinterContract, VendingMinterInstance, VendingMinterMessages } from './contract'
+import { vendingMinter as initContract } from './contract'
/*export interface InstantiateResponse {
/** The address of the newly instantiated contract *-/
@@ -24,7 +24,7 @@ interface InstantiateResponse {
readonly logs: readonly logs.Log[]
}
-export interface UseMinterContractProps {
+export interface UseVendingMinterContractProps {
instantiate: (
codeId: number,
initMsg: Record,
@@ -33,25 +33,25 @@ export interface UseMinterContractProps {
funds?: Coin[],
) => Promise
migrate: (contractAddress: string, codeId: number, migrateMsg: Record) => Promise
- use: (customAddress: string) => MinterInstance | undefined
+ use: (customAddress: string) => VendingMinterInstance | undefined
updateContractAddress: (contractAddress: string) => void
getContractAddress: () => string | undefined
- messages: (contractAddress: string) => MinterMessages | undefined
+ messages: (contractAddress: string) => VendingMinterMessages | undefined
}
-export function useMinterContract(): UseMinterContractProps {
+export function useVendingMinterContract(): UseVendingMinterContractProps {
const wallet = useWallet()
const [address, setAddress] = useState('')
- const [minter, setMinter] = useState()
+ const [vendingMinter, setVendingMinter] = useState()
useEffect(() => {
setAddress(localStorage.getItem('contract_address') || '')
}, [])
useEffect(() => {
- const MinterBaseContract = initContract(wallet.getClient(), wallet.address)
- setMinter(MinterBaseContract)
+ const VendingMinterBaseContract = initContract(wallet.getClient(), wallet.address)
+ setVendingMinter(VendingMinterBaseContract)
}, [wallet])
const updateContractAddress = (contractAddress: string) => {
@@ -61,35 +61,35 @@ export function useMinterContract(): UseMinterContractProps {
const instantiate = useCallback(
(codeId: number, initMsg: Record, label: string, admin?: string): Promise => {
return new Promise((resolve, reject) => {
- if (!minter) {
+ if (!vendingMinter) {
reject(new Error('Contract is not initialized.'))
return
}
- minter.instantiate(wallet.address, codeId, initMsg, label, admin).then(resolve).catch(reject)
+ vendingMinter.instantiate(wallet.address, codeId, initMsg, label, admin).then(resolve).catch(reject)
})
},
- [minter, wallet],
+ [vendingMinter, wallet],
)
const migrate = useCallback(
(contractAddress: string, codeId: number, migrateMsg: Record): Promise => {
return new Promise((resolve, reject) => {
- if (!minter) {
+ if (!vendingMinter) {
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)
+ vendingMinter.migrate(wallet.address, contractAddress, codeId, migrateMsg).then(resolve).catch(reject)
})
},
- [minter, wallet],
+ [vendingMinter, wallet],
)
const use = useCallback(
- (customAddress = ''): MinterInstance | undefined => {
- return minter?.use(address || customAddress)
+ (customAddress = ''): VendingMinterInstance | undefined => {
+ return vendingMinter?.use(address || customAddress)
},
- [minter, address],
+ [vendingMinter, address],
)
const getContractAddress = (): string | undefined => {
@@ -97,10 +97,10 @@ export function useMinterContract(): UseMinterContractProps {
}
const messages = useCallback(
- (customAddress = ''): MinterMessages | undefined => {
- return minter?.messages(address || customAddress)
+ (customAddress = ''): VendingMinterMessages | undefined => {
+ return vendingMinter?.messages(address || customAddress)
},
- [minter, address],
+ [vendingMinter, address],
)
return {
diff --git a/env.d.ts b/env.d.ts
index 51d0974..bc8526b 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -18,6 +18,8 @@ declare namespace NodeJS {
readonly NEXT_PUBLIC_WHITELIST_CODE_ID: string
readonly NEXT_PUBLIC_VENDING_MINTER_CODE_ID: string
readonly NEXT_PUBLIC_VENDING_FACTORY_ADDRESS: string
+ readonly NEXT_PUBLIC_BASE_FACTORY_ADDRESS: string
+ readonly NEXT_PUBLIC_BASE_MINTER_CODE_ID: string
readonly NEXT_PUBLIC_PINATA_ENDPOINT_URL: string
readonly NEXT_PUBLIC_API_URL: string
diff --git a/pages/collections/actions.tsx b/pages/collections/actions.tsx
index 8757da5..d6ce4b5 100644
--- a/pages/collections/actions.tsx
+++ b/pages/collections/actions.tsx
@@ -13,7 +13,7 @@ import { withMetadata } from 'utils/layout'
import { links } from 'utils/links'
const CollectionActionsPage: NextPage = () => {
- const { minter: minterContract, sg721: sg721Contract } = useContracts()
+ const { vendingMinter: vendingMinterContract, sg721: sg721Contract } = useContracts()
const wallet = useWallet()
const [action, setAction] = useState(false)
@@ -32,9 +32,9 @@ const CollectionActionsPage: NextPage = () => {
subtitle: 'Address of the Minter contract',
})
- const minterMessages = useMemo(
- () => minterContract?.use(minterContractState.value),
- [minterContract, minterContractState.value],
+ const vendingMinterMessages = useMemo(
+ () => vendingMinterContract?.use(minterContractState.value),
+ [vendingMinterContract, minterContractState.value],
)
const sg721Messages = useMemo(
() => sg721Contract?.use(sg721ContractState.value),
@@ -126,14 +126,14 @@ const CollectionActionsPage: NextPage = () => {
{(action && (
)) || (
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index f09b4c2..730e99f 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -49,7 +49,7 @@ import { getAssetType } from '../../utils/getAssetType'
const CollectionCreationPage: NextPage = () => {
const wallet = useWallet()
const {
- minter: minterContract,
+ vendingMinter: vendingMinterContract,
whitelist: whitelistContract,
vendingFactory: vendingFactoryContract,
} = useContracts()
@@ -69,7 +69,7 @@ const CollectionCreationPage: NextPage = () => {
const [uploading, setUploading] = useState(false)
const [creatingCollection, setCreatingCollection] = useState(false)
const [readyToCreate, setReadyToCreate] = useState(false)
- const [minterContractAddress, setMinterContractAddress] = useState(null)
+ const [vendingMinterContractAddress, setVendingMinterContractAddress] = useState(null)
const [sg721ContractAddress, setSg721ContractAddress] = useState(null)
const [whitelistContractAddress, setWhitelistContractAddress] = useState(null)
const [baseTokenUri, setBaseTokenUri] = useState(null)
@@ -102,7 +102,7 @@ const CollectionCreationPage: NextPage = () => {
setCreatingCollection(true)
setBaseTokenUri(null)
setCoverImageUrl(null)
- setMinterContractAddress(null)
+ setVendingMinterContractAddress(null)
setSg721ContractAddress(null)
setWhitelistContractAddress(null)
setTransactionHash(null)
@@ -176,7 +176,7 @@ const CollectionCreationPage: NextPage = () => {
const instantiate = async (baseUri: string, coverImageUri: string, whitelist?: string) => {
if (!wallet.initialized) throw new Error('Wallet not connected')
- if (!minterContract) throw new Error('Contract not found')
+ if (!vendingMinterContract) throw new Error('Contract not found')
let royaltyInfo = null
if (royaltyDetails?.royaltyType === 'new') {
@@ -229,7 +229,7 @@ const CollectionCreationPage: NextPage = () => {
}
const data = await dispatchExecute(payload)
setTransactionHash(data.transactionHash)
- setMinterContractAddress(data.minterAddress)
+ setVendingMinterContractAddress(data.vendingMinterAddress)
setSg721ContractAddress(data.sg721Address)
}
@@ -399,8 +399,8 @@ const CollectionCreationPage: NextPage = () => {
}
}
useEffect(() => {
- if (minterContractAddress !== null) scrollRef.current?.scrollIntoView({ behavior: 'smooth' })
- }, [minterContractAddress])
+ if (vendingMinterContractAddress !== null) scrollRef.current?.scrollIntoView({ behavior: 'smooth' })
+ }, [vendingMinterContractAddress])
useEffect(() => {
setBaseTokenUri(uploadDetails?.baseTokenURI as string)
@@ -427,7 +427,7 @@ const CollectionCreationPage: NextPage = () => {
-
+
Base Token URI:{' '}
@@ -456,9 +456,9 @@ const CollectionCreationPage: NextPage = () => {
- {minterContractAddress}
+ {vendingMinterContractAddress}
SG721 Contract Address:{' '}
@@ -504,7 +504,7 @@ const CollectionCreationPage: NextPage = () => {
View on Launchpad
diff --git a/pages/collections/queries.tsx b/pages/collections/queries.tsx
index ea9f5b0..40a2ebb 100644
--- a/pages/collections/queries.tsx
+++ b/pages/collections/queries.tsx
@@ -16,7 +16,7 @@ import { withMetadata } from 'utils/layout'
import { links } from 'utils/links'
const CollectionQueriesPage: NextPage = () => {
- const { minter: minterContract, sg721: sg721Contract } = useContracts()
+ const { vendingMinter: vendingMinterContract, sg721: sg721Contract } = useContracts()
const comboboxState = useQueryComboboxState()
const type = comboboxState.value?.id
@@ -57,19 +57,19 @@ const CollectionQueriesPage: NextPage = () => {
const showTokenIdField = type === 'token_info'
const showAddressField = type === 'tokens_minted_to_user'
- const minterMessages = useMemo(
- () => minterContract?.use(minterContractAddress),
- [minterContract, minterContractAddress],
+ const vendingMinterMessages = useMemo(
+ () => vendingMinterContract?.use(minterContractAddress),
+ [vendingMinterContract, minterContractAddress],
)
const sg721Messages = useMemo(() => sg721Contract?.use(sg721ContractAddress), [sg721Contract, sg721ContractAddress])
const { data: response } = useQuery(
- [sg721Messages, minterMessages, type, tokenId, address] as const,
+ [sg721Messages, vendingMinterMessages, type, tokenId, address] as const,
async ({ queryKey }) => {
- const [_sg721Messages, _minterMessages, _type, _tokenId, _address] = queryKey
+ const [_sg721Messages, _vendingMinterMessages, _type, _tokenId, _address] = queryKey
const result = await dispatchQuery({
tokenId: _tokenId,
- minterMessages: _minterMessages,
+ minterMessages: _vendingMinterMessages,
sg721Messages: _sg721Messages,
address: _address,
type: _type,
diff --git a/pages/contracts/baseMinter/execute.tsx b/pages/contracts/baseMinter/execute.tsx
new file mode 100644
index 0000000..5288e02
--- /dev/null
+++ b/pages/contracts/baseMinter/execute.tsx
@@ -0,0 +1,145 @@
+import { Button } from 'components/Button'
+import { Conditional } from 'components/Conditional'
+import { ContractPageHeader } from 'components/ContractPageHeader'
+import { ExecuteCombobox } from 'components/contracts/baseMinter/ExecuteCombobox'
+import { useExecuteComboboxState } from 'components/contracts/baseMinter/ExecuteCombobox.hooks'
+import { FormControl } from 'components/FormControl'
+import { AddressInput, TextInput } from 'components/forms/FormInput'
+import { useInputState } from 'components/forms/FormInput.hooks'
+import { InputDateTime } from 'components/InputDateTime'
+import { JsonPreview } from 'components/JsonPreview'
+import { LinkTabs } from 'components/LinkTabs'
+import { baseMinterLinkTabs } from 'components/LinkTabs.data'
+import { TransactionHash } from 'components/TransactionHash'
+import { useContracts } from 'contexts/contracts'
+import { useWallet } from 'contexts/wallet'
+import type { DispatchExecuteArgs } from 'contracts/baseMinter/messages/execute'
+import { dispatchExecute, previewExecutePayload } from 'contracts/baseMinter/messages/execute'
+import type { NextPage } from 'next'
+import { useRouter } from 'next/router'
+import { NextSeo } from 'next-seo'
+import type { FormEvent } from 'react'
+import { useEffect, useMemo, 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 BaseMinterExecutePage: NextPage = () => {
+ const { baseMinter: contract } = useContracts()
+ const wallet = useWallet()
+ const [lastTx, setLastTx] = useState('')
+
+ const [timestamp, setTimestamp] = useState
(undefined)
+
+ const comboboxState = useExecuteComboboxState()
+ const type = comboboxState.value?.id
+
+ const contractState = useInputState({
+ id: 'contract-address',
+ name: 'contract-address',
+ title: 'Base Minter Address',
+ subtitle: 'Address of the Base Minter contract',
+ })
+
+ const tokenUriState = useInputState({
+ id: 'token-uri',
+ name: 'token-uri',
+ title: 'Token URI',
+ placeholder: 'ipfs://',
+ })
+ const contractAddress = contractState.value
+
+ const showDateField = type === 'update_start_trading_time'
+ const showTokenUriField = type === 'mint'
+
+ const messages = useMemo(() => contract?.use(contractState.value), [contract, wallet.address, contractState.value])
+ const payload: DispatchExecuteArgs = {
+ startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '',
+ tokenUri: tokenUriState.value,
+ contract: contractState.value,
+ messages,
+ txSigner: wallet.address,
+ type,
+ }
+ const { isLoading, mutate } = useMutation(
+ async (event: FormEvent) => {
+ event.preventDefault()
+ if (!type) {
+ throw new Error('Please select message type!')
+ }
+ if (!wallet.initialized) {
+ throw new Error('Please connect your wallet.')
+ }
+ const txHash = await toast.promise(dispatchExecute(payload), {
+ error: `${type.charAt(0).toUpperCase() + type.slice(1)} execute failed!`,
+ loading: 'Executing message...',
+ success: (tx) => `Transaction ${tx} success!`,
+ })
+ if (txHash) {
+ setLastTx(txHash)
+ }
+ },
+ {
+ 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(BaseMinterExecutePage, { center: false })
diff --git a/pages/contracts/minter/index.tsx b/pages/contracts/baseMinter/index.tsx
similarity index 100%
rename from pages/contracts/minter/index.tsx
rename to pages/contracts/baseMinter/index.tsx
diff --git a/pages/contracts/baseMinter/instantiate.tsx b/pages/contracts/baseMinter/instantiate.tsx
new file mode 100644
index 0000000..8f54656
--- /dev/null
+++ b/pages/contracts/baseMinter/instantiate.tsx
@@ -0,0 +1,259 @@
+import { coin } from '@cosmjs/proto-signing'
+import { Alert } from 'components/Alert'
+import { Button } from 'components/Button'
+import { Conditional } from 'components/Conditional'
+import { ContractPageHeader } from 'components/ContractPageHeader'
+import { FormControl } from 'components/FormControl'
+import { FormGroup } from 'components/FormGroup'
+import { NumberInput, TextInput } from 'components/forms/FormInput'
+import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
+import { FormTextArea } from 'components/forms/FormTextArea'
+import { InputDateTime } from 'components/InputDateTime'
+import { JsonPreview } from 'components/JsonPreview'
+import { LinkTabs } from 'components/LinkTabs'
+import { baseMinterLinkTabs } from 'components/LinkTabs.data'
+import { useContracts } from 'contexts/contracts'
+import { useWallet } from 'contexts/wallet'
+import type { NextPage } from 'next'
+import { NextSeo } from 'next-seo'
+import type { FormEvent } from 'react'
+import { useState } from 'react'
+import { toast } from 'react-hot-toast'
+import { FaAsterisk } from 'react-icons/fa'
+import { useMutation } from 'react-query'
+import { BASE_FACTORY_ADDRESS } from 'utils/constants'
+import { withMetadata } from 'utils/layout'
+import { links } from 'utils/links'
+
+import type { CreateBaseMinterResponse } from '../../../contracts/baseFactory/contract'
+import { SG721_CODE_ID } from '../../../utils/constants'
+
+const BaseMinterInstantiatePage: NextPage = () => {
+ const wallet = useWallet()
+ const contract = useContracts().baseFactory
+
+ const [timestamp, setTimestamp] = useState()
+ const [explicit, setExplicit] = useState(false)
+
+ const nameState = useInputState({
+ id: 'name',
+ name: 'name',
+ title: 'Name',
+ placeholder: 'My Awesome SG721 Contract',
+ subtitle: 'Name of the sg721 contract',
+ })
+
+ const symbolState = useInputState({
+ id: 'symbol',
+ name: 'symbol',
+ title: 'Symbol',
+ placeholder: 'AWSM',
+ subtitle: 'Symbol of the sg721 contract',
+ })
+
+ const codeIdState = useNumberInputState({
+ id: 'code-id',
+ name: 'code-id',
+ title: 'Code ID',
+ subtitle: 'Code ID for the sg721 contract',
+ placeholder: '1',
+ defaultValue: SG721_CODE_ID,
+ })
+
+ const creatorState = useInputState({
+ id: 'creator-address',
+ name: 'creatorAddress',
+ title: 'Creator Address',
+ placeholder: 'stars1234567890abcdefghijklmnopqrstuvwxyz...',
+ subtitle: 'Address of the collection creator',
+ defaultValue: wallet.address,
+ })
+
+ const descriptionState = useInputState({
+ id: 'description',
+ name: 'description',
+ title: 'Description',
+ subtitle: 'Description of the collection',
+ })
+
+ const imageState = useInputState({
+ id: 'image',
+ name: 'image',
+ title: 'Image',
+ subtitle: 'Image of the collection',
+ placeholder: 'ipfs://bafybe....',
+ })
+
+ const externalLinkState = useInputState({
+ id: 'external-link',
+ name: 'externalLink',
+ title: 'External Link (optional)',
+ subtitle: 'External link to the collection',
+ })
+
+ const royaltyPaymentAddressState = useInputState({
+ id: 'royalty-payment-address',
+ name: 'royaltyPaymentAddress',
+ title: 'Payment Address',
+ subtitle: 'Address to receive royalties',
+ placeholder: 'stars1234567890abcdefghijklmnopqrstuvwxyz...',
+ })
+
+ const royaltyShareState = useInputState({
+ id: 'royalty-share',
+ name: 'royaltyShare',
+ title: 'Share Percentage',
+ subtitle: 'Percentage of royalties to be paid',
+ placeholder: '8%',
+ })
+
+ const { data, isLoading, mutate } = useMutation(
+ async (event: FormEvent): Promise => {
+ event.preventDefault()
+ if (!contract) {
+ throw new Error('Smart contract connection failed')
+ }
+
+ let royaltyInfo = null
+ if (royaltyPaymentAddressState.value && royaltyShareState.value) {
+ royaltyInfo = {
+ payment_address: royaltyPaymentAddressState.value,
+ share: (Number(royaltyShareState.value) / 100).toString(),
+ }
+ }
+
+ const msg = {
+ create_minter: {
+ collection_params: {
+ code_id: codeIdState.value,
+ name: nameState.value,
+ symbol: symbolState.value,
+ info: {
+ creator: creatorState.value,
+ description: descriptionState.value,
+ image: imageState.value,
+ external_link: externalLinkState.value || null,
+ explicit_content: explicit,
+ start_trading_time: timestamp ? (timestamp.getTime() * 1_000_000).toString() : null,
+ royalty_info: royaltyInfo,
+ },
+ },
+ },
+ }
+
+ return toast.promise(
+ contract
+ .use(BASE_FACTORY_ADDRESS)
+ ?.createBaseMinter(wallet.address, msg, [coin('1000000000', 'ustars')]) as Promise,
+ {
+ loading: 'Instantiating contract...',
+ error: 'Instantiation failed!',
+ success: 'Instantiation success!',
+ },
+ )
+ },
+ {
+ onError: (error) => {
+ toast.error(String(error), { style: { maxWidth: 'none' } })
+ },
+ },
+ )
+
+ const txHash = data?.transactionHash
+
+ return (
+
+ )
+}
+
+export default withMetadata(BaseMinterInstantiatePage, { center: false })
diff --git a/pages/contracts/minter/migrate.tsx b/pages/contracts/baseMinter/migrate.tsx
similarity index 83%
rename from pages/contracts/minter/migrate.tsx
rename to pages/contracts/baseMinter/migrate.tsx
index 3389bf7..60e8b25 100644
--- a/pages/contracts/minter/migrate.tsx
+++ b/pages/contracts/baseMinter/migrate.tsx
@@ -1,16 +1,16 @@
import { Button } from 'components/Button'
import { ContractPageHeader } from 'components/ContractPageHeader'
-import { useExecuteComboboxState } from 'components/contracts/minter/ExecuteCombobox.hooks'
+import { useExecuteComboboxState } from 'components/contracts/baseMinter/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 { baseMinterLinkTabs } 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 { MigrateResponse } from 'contracts/baseMinter'
import type { NextPage } from 'next'
import { useRouter } from 'next/router'
import { NextSeo } from 'next-seo'
@@ -22,8 +22,8 @@ import { useMutation } from 'react-query'
import { withMetadata } from 'utils/layout'
import { links } from 'utils/links'
-const MinterMigratePage: NextPage = () => {
- const { minter: contract } = useContracts()
+const BaseMinterMigratePage: NextPage = () => {
+ const { baseMinter: contract } = useContracts()
const wallet = useWallet()
const [lastTx, setLastTx] = useState('')
@@ -34,15 +34,15 @@ const MinterMigratePage: NextPage = () => {
id: 'code-id',
name: 'code-id',
title: 'Code ID',
- subtitle: 'Code ID of the New Minter',
+ subtitle: 'Code ID of the New Base Minter',
placeholder: '1',
})
const contractState = useInputState({
id: 'contract-address',
name: 'contract-address',
- title: 'Minter Address',
- subtitle: 'Address of the Minter contract',
+ title: 'Base Minter Address',
+ subtitle: 'Address of the Base Minter contract',
})
const contractAddress = contractState.value
@@ -90,13 +90,13 @@ const MinterMigratePage: NextPage = () => {
return (