Compare commits
104
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e319a4306c | ||
|
|
5e963cf615 | ||
|
|
41d71a6765 | ||
|
|
22d58dbe45 | ||
|
|
471ff43fcf | ||
|
|
027c4c6821 | ||
|
|
f0b94422b1 | ||
|
|
bb8b3e1791 | ||
|
|
42707adc0b | ||
|
|
35bed9d6aa | ||
|
|
93f98bcec6 | ||
|
|
83835dfba2 | ||
|
|
d85e19b770 | ||
|
|
1abb2f82df | ||
|
|
b44e4512a5 | ||
|
|
a226d8b341 | ||
|
|
8a02a7f80d | ||
|
|
122c61055f | ||
|
|
81880aecdd | ||
|
|
b38562d9fd | ||
|
|
0eb94e4ee8 | ||
|
|
3a150a50f3 | ||
|
|
03c008d0fa | ||
|
|
6487646f2c | ||
|
|
b1094f5231 | ||
|
|
97bb60b3ff | ||
|
|
9654ec845e | ||
|
|
41e8a3961a | ||
|
|
43fd0d7848 | ||
|
|
cc16f7ceb1 | ||
|
|
cc58de90a4 | ||
|
|
27f8510335 | ||
|
|
0fc60f6c05 | ||
|
|
c59531f87e | ||
|
|
6ddd780338 | ||
|
|
57e36b6dbd | ||
|
|
1a866db888 | ||
|
|
7e97f5d393 | ||
|
|
e26068085d | ||
|
|
1ccc55a3b2 | ||
|
|
99f7b25f10 | ||
|
|
3308cfdcf2 | ||
|
|
5e9fdc1cf1 | ||
|
|
39847d1ab9 | ||
|
|
29cd89f6a5 | ||
|
|
6466945e28 | ||
|
|
db9ffb0899 | ||
|
|
a295dd5d4a | ||
|
|
85ac7a4f71 | ||
|
|
ee46fa64d3 | ||
|
|
f5f14fb330 | ||
|
|
fd65316d1f | ||
|
|
004b102540 | ||
|
|
9095c5c06c | ||
|
|
55e46cc830 | ||
|
|
d07ad7db04 | ||
|
|
8f0a0e84aa | ||
|
|
4e6db44105 | ||
|
|
7b0f1f6176 | ||
|
|
fe8bfd14bc | ||
|
|
1c7c0a682d | ||
|
|
b58549b1a2 | ||
|
|
6cdd2a24ac | ||
|
|
437ac5b6f5 | ||
|
|
afef36375b | ||
|
|
0231692eb1 | ||
|
|
e0d6aaee4d | ||
|
|
c4027859c0 | ||
|
|
c12fd51525 | ||
|
|
f1aeeb2167 | ||
|
|
103921d946 | ||
|
|
b4fcc63de6 | ||
|
|
b3dea5e757 | ||
|
|
e43ec78acc | ||
|
|
4c312d0ad8 | ||
|
|
89836ad84e | ||
|
|
51f38f12d7 | ||
|
|
609745ce11 | ||
|
|
3b9778270b | ||
|
|
c66b21792c | ||
|
|
35a9c0eba8 | ||
|
|
07152745e0 | ||
|
|
7a455b60bc | ||
|
|
67694d4c5d | ||
|
|
4ec704f588 | ||
|
|
3f44e342e8 | ||
|
|
245fd2253b | ||
|
|
ed1844fdf0 | ||
|
|
6316a68408 | ||
|
|
a949a1e103 | ||
|
|
39385ee82e | ||
|
|
440ee78122 | ||
|
|
1f31cdbe29 | ||
|
|
b66e6d0920 | ||
|
|
ab4d4fa31d | ||
|
|
92ce752b15 | ||
|
|
01936d8f5e | ||
|
|
02df116e09 | ||
|
|
ab724afb9c | ||
|
|
3c3b60ebe8 | ||
|
|
de5de84873 | ||
|
|
7951669ed2 | ||
|
|
20944cf5de | ||
|
|
0f1c4a027b |
+26
-5
@@ -16,8 +16,10 @@ NEXT_PUBLIC_VENDING_FACTORY_ADDRESS="stars18h7ugh8eaug7wr0w4yjw0ls5s937z35pnkg93
|
||||
NEXT_PUBLIC_FEATURED_VENDING_FACTORY_ADDRESS="stars14pd96yk3t6gq9l6uyrkg0n5dr09n8rt5y9v3at8x4wl4lrkxhlzq4trqmh"
|
||||
NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS="stars1h65nms9gwg4vdktyqj84tu50gwlm34e0eczl5w2ezllxuzfxy9esa9qlt0"
|
||||
NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftslp2rwkkkcxy269a35a9pq60ug2q"
|
||||
NEXT_PUBLIC_VENDING_FACTORY_MERKLE_TREE_ADDRESS="stars167tudcsr9n2y9ljgk4cwxhs0cvkfkk0hh6c3dzngsz7m5s9jmqnsdgr3jy"
|
||||
NEXT_PUBLIC_FEATURED_VENDING_FACTORY_MERKLE_TREE_ADDRESS="stars167tudcsr9n2y9ljgk4cwxhs0cvkfkk0hh6c3dzngsz7m5s9jmqnsdgr3jy"
|
||||
NEXT_PUBLIC_FEATURED_VENDING_FACTORY_FLEX_ADDRESS="stars1udlmmnmmnnqamh36hy6d7azn3ycv23yymkmg6558ntalvyt2pz7s8lhgcd"
|
||||
NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS=
|
||||
|
||||
# NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS=
|
||||
@@ -25,8 +27,10 @@ NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS=
|
||||
|
||||
# NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_FEATURED_VENDING_IBC_USDC_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_FEATURED_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS=
|
||||
|
||||
# NEXT_PUBLIC_VENDING_IBC_USK_FACTORY_ADDRESS=
|
||||
@@ -34,6 +38,15 @@ NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_USK_FACTORY_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_USK_UPDATABLE_FACTORY_FLEX_ADDRESS=
|
||||
|
||||
# NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS=
|
||||
# NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS=
|
||||
# NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS=
|
||||
# NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS=
|
||||
|
||||
NEXT_PUBLIC_VENDING_NATIVE_STARDUST_FACTORY_ADDRESS="stars1mxwf2hjcjvqnlw0v3j7m0u34975qesp325wzrgz0ht7vr8ys2zmsenjutf"
|
||||
NEXT_PUBLIC_VENDING_NATIVE_STARDUST_UPDATABLE_FACTORY_ADDRESS="stars18gjczf88jd4z3a3megwj9g5c9famu654csxfnnq59mkqeszuzy4ssdgr46"
|
||||
NEXT_PUBLIC_VENDING_NATIVE_STRDST_FLEX_FACTORY_ADDRESS="stars1eluqmr6x78ehl4plrln6khxc0qrspfhc7rt3whmr59escpve0r4swcacjh"
|
||||
@@ -46,6 +59,7 @@ NEXT_PUBLIC_BASE_FACTORY_ADDRESS="stars1a45hcxty3spnmm2f0papl8v4dk5ew29s4syhn4ef
|
||||
NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym"
|
||||
|
||||
NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
|
||||
NEXT_PUBLIC_OPEN_EDITION_FACTORY_FLEX_ADDRESS="stars1nc59ddaa8xcx9mu8jladza82dznhxrta3njal3xylkqlsfqa7g4s9s5q02"
|
||||
NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS="stars1fk5dkzcylam8mcpqrn8y9spauvc3d4navtaqurcc49dc3p9f8d3qdkvymx"
|
||||
|
||||
NEXT_PUBLIC_VENDING_IBC_KUJI_FACTORY_ADDRESS="stars1yyje87e0h9mqg34kp3x75yesa78ve4glc3dstdrn6nscw3zjfanqkj95f0"
|
||||
@@ -59,8 +73,12 @@ NEXT_PUBLIC_VENDING_IBC_CRBRUS_FACTORY_FLEX_ADDRESS="stars1halhp674yxwgn3p4gpkl8
|
||||
|
||||
# NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS="stars152a40mmd3k2kk90add606vrqxcvzdp29qrjx4pjv33cjl6svksfscrrtuk"
|
||||
# NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_FLEX_ADDRESS="stars10sz9mup3a548l34k83q5w59nrklrnvv2gdsdkr2xref4zl5j3d4q0efamx"
|
||||
# NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS=
|
||||
# NEXT_PUBLIC_OPEN_EDITION_IBC_TIA_FACTORY_ADDRESS="stars1vza7k890fkejxz3mqwau0u2m89k9y76w94vvxe4d42ya9862ryfq0damns"
|
||||
# NEXT_PUBLIC_OPEN_EDITION_IBC_TIA_FACTORY_FLEX_ADDRESS="stars1jgn0ntt5tut93yn756rrqa60794qdsrn6dwhl8vhfx0yxgpr44qsfzhmrt"
|
||||
# NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_TIA_FACTORY_ADDRESS=
|
||||
NEXT_PUBLIC_OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS="stars1vzffawsjhvspstu5lvtzz2x5n7zh07hnw09c9dfxcj78un05rcms5n3q3e"
|
||||
NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS="stars1tc09vlgdg8rqyapcxwm9qdq8naj4gym9px4ntue9cs0kse5rvess0nee3a"
|
||||
|
||||
@@ -87,13 +105,14 @@ NEXT_PUBLIC_VENDING_IBC_NBTC_UPDATABLE_FACTORY_ADDRESS="stars1k6ee8qgwvumguqnqqr
|
||||
NEXT_PUBLIC_SG721_NAME_ADDRESS="stars1fx74nkqkw2748av8j7ew7r3xt9cgjqduwn8m0ur5lhe49uhlsasszc5fhr"
|
||||
NEXT_PUBLIC_ROYALTY_REGISTRY_ADDRESS="stars1crgx0f70fzksa57hq87wtl8f04h0qyk5la0hk0fu8dyhl67ju80qaxzr5z"
|
||||
NEXT_PUBLIC_INFINITY_SWAP_PROTOCOL_ADDRESS="stars136yp6fl9h66m0cwv8weu4w4aawveuz40992ty0atj5ecjd8z0thqv9xpy5"
|
||||
NEXT_PUBLIC_WHITELIST_CODE_ID=3131
|
||||
NEXT_PUBLIC_WHITELIST_FLEX_CODE_ID=3130
|
||||
NEXT_PUBLIC_WHITELIST_CODE_ID=4008
|
||||
NEXT_PUBLIC_WHITELIST_FLEX_CODE_ID=4009
|
||||
NEXT_PUBLIC_WHITELIST_MERKLE_TREE_CODE_ID=3911
|
||||
NEXT_PUBLIC_BADGE_HUB_CODE_ID=1336
|
||||
NEXT_PUBLIC_BADGE_HUB_ADDRESS="stars1dacun0xn7z73qzdcmq27q3xn6xuprg8e2ugj364784al2v27tklqynhuqa"
|
||||
NEXT_PUBLIC_BADGE_NFT_CODE_ID=1337
|
||||
NEXT_PUBLIC_BADGE_NFT_ADDRESS="stars1vlw4y54dyzt3zg7phj8yey9fg4zj49czknssngwmgrnwymyktztstalg7t"
|
||||
NEXT_PUBLIC_SPLITS_CODE_ID=1905
|
||||
NEXT_PUBLIC_SPLITS_CODE_ID=4010
|
||||
NEXT_PUBLIC_CW4_GROUP_CODE_ID=1904
|
||||
|
||||
NEXT_PUBLIC_API_URL=https://nft-api.elgafar-1.stargaze-apis.com
|
||||
@@ -103,6 +122,8 @@ NEXT_PUBLIC_STARGAZE_WEBSITE_URL=https://testnet.publicawesome.dev
|
||||
NEXT_PUBLIC_BADGES_URL=https://badges.publicawesome.dev
|
||||
NEXT_PUBLIC_WEBSITE_URL=https://
|
||||
NEXT_PUBLIC_SYNC_COLLECTIONS_API_URL="https://..."
|
||||
NEXT_PUBLIC_WHITELIST_MERKLE_TREE_API_URL="https://..."
|
||||
NEXT_PUBLIC_NFT_STORAGE_DEFAULT_API_KEY="..."
|
||||
|
||||
NEXT_PUBLIC_MEILISEARCH_HOST="https://search.publicawesome.dev"
|
||||
NEXT_PUBLIC_MEILISEARCH_API_KEY= "..."
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
|
||||
// Styles required for @cosmos-kit/react modal
|
||||
import '@interchain-ui/react/styles'
|
||||
|
||||
@@ -7,6 +9,7 @@ import { wallets as leapExtensionWallets } from '@cosmos-kit/leap-extension'
|
||||
import { ChainProvider } from '@cosmos-kit/react'
|
||||
import { assets, chains } from 'chain-registry'
|
||||
import { getConfig } from 'config'
|
||||
import { fangAssetList, fangTestnet } from 'config/fangTestnet'
|
||||
import type { ReactNode } from 'react'
|
||||
import { NETWORK } from 'utils/constants'
|
||||
|
||||
@@ -14,8 +17,8 @@ export const WalletProvider = ({ children }: { children: ReactNode }) => {
|
||||
const { gasPrice, feeToken } = getConfig(NETWORK)
|
||||
return (
|
||||
<ChainProvider
|
||||
assetLists={assets}
|
||||
chains={chains}
|
||||
assetLists={[...assets, fangAssetList]}
|
||||
chains={[...chains, fangTestnet]}
|
||||
endpointOptions={{
|
||||
endpoints: {
|
||||
stargaze: {
|
||||
@@ -26,6 +29,10 @@ export const WalletProvider = ({ children }: { children: ReactNode }) => {
|
||||
rpc: ['https://rpc.elgafar-1.stargaze-apis.com/'],
|
||||
rest: ['https://rest.elgafar-1.stargaze-apis.com/'],
|
||||
},
|
||||
stargazefangtestnet: {
|
||||
rpc: ['https://rpc.fang-1.stargaze-apis.com/'],
|
||||
rest: ['https://rest.fang-1.stargaze-apis.com/'],
|
||||
},
|
||||
},
|
||||
isLazy: true,
|
||||
}}
|
||||
@@ -37,7 +44,7 @@ export const WalletProvider = ({ children }: { children: ReactNode }) => {
|
||||
gasPrice: GasPrice.fromString(`${gasPrice}${feeToken}`),
|
||||
}),
|
||||
signingStargate: () => ({
|
||||
gasPrice: GasPrice.fromString(`${gasPrice}${feeToken}`),
|
||||
gasPrice: GasPrice.fromString(`${0.01}${feeToken}`),
|
||||
}),
|
||||
}}
|
||||
wallets={[...keplrExtensionWallets, ...leapExtensionWallets]}
|
||||
|
||||
@@ -78,7 +78,7 @@ export const WhitelistUpload = ({ onChange }: WhitelistUploadProps) => {
|
||||
const printableData = data?.map((item) => item.replace(regex, ''))
|
||||
const names = printableData?.filter((address) => address !== '' && address.endsWith('.stars'))
|
||||
const strippedNames = names?.map((name) => name.split('.')[0])
|
||||
console.log(names)
|
||||
console.log('names: ', names)
|
||||
if (strippedNames?.length) {
|
||||
await toast
|
||||
.promise(resolveAddresses(strippedNames), {
|
||||
|
||||
@@ -13,6 +13,7 @@ import type { ChangeEvent } from 'react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import type { UploadServiceType } from 'services/upload'
|
||||
import { NFT_STORAGE_DEFAULT_API_KEY } from 'utils/constants'
|
||||
import { getAssetType } from 'utils/getAssetType'
|
||||
|
||||
export type UploadMethod = 'new' | 'existing'
|
||||
@@ -37,6 +38,7 @@ export const ImageUploadDetails = ({ onChange, mintRule }: ImageUploadDetailsPro
|
||||
const [assetFile, setAssetFile] = useState<File>()
|
||||
const [uploadMethod, setUploadMethod] = useState<UploadMethod>('new')
|
||||
const [uploadService, setUploadService] = useState<UploadServiceType>('nft-storage')
|
||||
const [useDefaultApiKey, setUseDefaultApiKey] = useState(false)
|
||||
|
||||
const assetFileRef = useRef<HTMLInputElement | null>(null)
|
||||
|
||||
@@ -130,6 +132,14 @@ export const ImageUploadDetails = ({ onChange, mintRule }: ImageUploadDetailsPro
|
||||
imageUrlState.onChange('')
|
||||
}, [uploadMethod, mintRule])
|
||||
|
||||
useEffect(() => {
|
||||
if (useDefaultApiKey) {
|
||||
nftStorageApiKeyState.onChange(NFT_STORAGE_DEFAULT_API_KEY || '')
|
||||
} else {
|
||||
nftStorageApiKeyState.onChange('')
|
||||
}
|
||||
}, [useDefaultApiKey])
|
||||
|
||||
const videoPreview = useMemo(
|
||||
() => (
|
||||
<video
|
||||
@@ -269,7 +279,22 @@ export const ImageUploadDetails = ({ onChange, mintRule }: ImageUploadDetailsPro
|
||||
|
||||
<div className="flex w-full">
|
||||
<Conditional test={uploadService === 'nft-storage'}>
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" />
|
||||
<div className="flex-col w-full">
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" disabled={useDefaultApiKey} />
|
||||
<div className="flex-row mt-2 w-full form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="mr-2 font-bold">Use Default API Key</span>
|
||||
<input
|
||||
checked={useDefaultApiKey}
|
||||
className={`${useDefaultApiKey ? `bg-stargaze` : `bg-gray-600`} checkbox`}
|
||||
onClick={() => {
|
||||
setUseDefaultApiKey(!useDefaultApiKey)
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</Conditional>
|
||||
<Conditional test={uploadService === 'pinata'}>
|
||||
<TextInput {...pinataApiKeyState} className="w-full" />
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { toUtf8 } from '@cosmjs/encoding'
|
||||
import clsx from 'clsx'
|
||||
import { AirdropUpload } from 'components/AirdropUpload'
|
||||
import { Alert } from 'components/Alert'
|
||||
import { Button } from 'components/Button'
|
||||
import type { DispatchExecuteArgs } from 'components/collections/actions/actions'
|
||||
import { dispatchExecute, isEitherType, previewExecutePayload } from 'components/collections/actions/actions'
|
||||
@@ -115,6 +116,13 @@ export const CollectionActions = ({
|
||||
subtitle: 'Address of the recipient',
|
||||
})
|
||||
|
||||
const creatorState = useInputState({
|
||||
id: 'creator-address',
|
||||
name: 'creator',
|
||||
title: 'Creator Address',
|
||||
subtitle: 'Address of the creator',
|
||||
})
|
||||
|
||||
const tokenURIState = useInputState({
|
||||
id: 'token-uri',
|
||||
name: 'tokenURI',
|
||||
@@ -217,6 +225,7 @@ export const CollectionActions = ({
|
||||
])
|
||||
const showPriceField = isEitherType(type, ['update_mint_price', 'update_discount_price'])
|
||||
const showDescriptionField = type === 'update_collection_info'
|
||||
const showCreatorField = type === 'update_collection_info'
|
||||
const showImageField = type === 'update_collection_info'
|
||||
const showExternalLinkField = type === 'update_collection_info'
|
||||
const showRoyaltyRelatedFields =
|
||||
@@ -289,6 +298,16 @@ export const CollectionActions = ({
|
||||
void resolveRoyaltyPaymentAddress()
|
||||
}, [royaltyPaymentAddressState.value])
|
||||
|
||||
const resolveCreatorAddress = async () => {
|
||||
await resolveAddress(creatorState.value.trim(), wallet).then((resolvedAddress) => {
|
||||
creatorState.onChange(resolvedAddress)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
void resolveCreatorAddress()
|
||||
}, [creatorState.value])
|
||||
|
||||
useEffect(() => {
|
||||
setCollectionInfo({
|
||||
description: descriptionState.value.replaceAll('\\n', '\n') || undefined,
|
||||
@@ -302,6 +321,7 @@ export const CollectionActions = ({
|
||||
share: (Number(royaltyShareState.value) / 100).toString(),
|
||||
}
|
||||
: undefined,
|
||||
creator: creatorState.value || undefined,
|
||||
})
|
||||
}, [
|
||||
descriptionState.value,
|
||||
@@ -310,6 +330,7 @@ export const CollectionActions = ({
|
||||
externalLinkState.value,
|
||||
royaltyPaymentAddressState.value,
|
||||
royaltyShareState.value,
|
||||
creatorState.value,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -438,6 +459,27 @@ export const CollectionActions = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'update_collection_info' && creatorState.value) {
|
||||
const resolvedCreatorAddress = await resolveAddress(creatorState.value.trim(), wallet)
|
||||
const contractInfoResponse = await (await wallet.getCosmWasmClient())
|
||||
.queryContractRaw(
|
||||
resolvedCreatorAddress,
|
||||
toUtf8(Buffer.from(Buffer.from('contract_info').toString('hex'), 'hex').toString()),
|
||||
)
|
||||
.catch((e) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
if (e.message.includes('bech32')) throw new Error('Invalid creator address.')
|
||||
console.log(e.message)
|
||||
})
|
||||
if (contractInfoResponse !== undefined) {
|
||||
const contractInfo = JSON.parse(new TextDecoder().decode(contractInfoResponse as Uint8Array))
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
if (contractInfo && !contractInfo.contract.includes('dao'))
|
||||
throw new Error('The provided creator address does not belong to a compatible contract.')
|
||||
else console.log(contractInfo)
|
||||
}
|
||||
}
|
||||
|
||||
const txHash = await toast.promise(dispatchExecute(payload), {
|
||||
error: `${type.charAt(0).toUpperCase() + type.slice(1)} execute failed!`,
|
||||
loading: 'Executing message...',
|
||||
@@ -494,6 +536,7 @@ export const CollectionActions = ({
|
||||
{showBaseUriField && <TextInput className="mt-2" {...baseURIState} />}
|
||||
{showNumberOfTokensField && <NumberInput className="mt-2" {...batchNumberState} />}
|
||||
{showPriceField && <NumberInput className="mt-2" {...priceState} />}
|
||||
{showCreatorField && <AddressInput className="mt-2" {...creatorState} />}
|
||||
{showDescriptionField && <TextInput className="my-2" {...descriptionState} />}
|
||||
{showImageField && <TextInput className="mb-2" {...imageState} />}
|
||||
{showExternalLinkField && <TextInput className="mb-2" {...externalLinkState} />}
|
||||
@@ -664,6 +707,17 @@ export const CollectionActions = ({
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Conditional>
|
||||
<Conditional test={type === 'update_collection_info'}>
|
||||
<Alert className="mt-2 text-sm" type="info">
|
||||
Please note that you are only required to fill in the fields you want to update.
|
||||
</Alert>
|
||||
</Conditional>
|
||||
<Conditional test={type === 'update_discount_price'}>
|
||||
<Alert className="mt-2 text-sm" type="warning">
|
||||
Please note that discount price can only be updated every 24 hours and be removed 12 hours after its last
|
||||
update.
|
||||
</Alert>
|
||||
</Conditional>
|
||||
</div>
|
||||
<div className="-mt-6">
|
||||
<div className="relative mb-2">
|
||||
|
||||
@@ -20,6 +20,7 @@ import type { ChangeEvent } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import type { UploadServiceType } from 'services/upload'
|
||||
import { NFT_STORAGE_DEFAULT_API_KEY } from 'utils/constants'
|
||||
import type { AssetType } from 'utils/getAssetType'
|
||||
import { getAssetType } from 'utils/getAssetType'
|
||||
import { uid } from 'utils/random'
|
||||
@@ -66,6 +67,7 @@ export const UploadDetails = ({
|
||||
const [uploadService, setUploadService] = useState<UploadServiceType>('nft-storage')
|
||||
const [metadataFileArrayIndex, setMetadataFileArrayIndex] = useState(0)
|
||||
const [refreshMetadata, setRefreshMetadata] = useState(false)
|
||||
const [useDefaultApiKey, setUseDefaultApiKey] = useState(false)
|
||||
|
||||
const [baseMinterMetadataFile, setBaseMinterMetadataFile] = useState<File | undefined>()
|
||||
|
||||
@@ -461,6 +463,14 @@ export const UploadDetails = ({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [importedUploadDetails])
|
||||
|
||||
useEffect(() => {
|
||||
if (useDefaultApiKey) {
|
||||
nftStorageApiKeyState.onChange(NFT_STORAGE_DEFAULT_API_KEY || '')
|
||||
} else {
|
||||
nftStorageApiKeyState.onChange('')
|
||||
}
|
||||
}, [useDefaultApiKey])
|
||||
|
||||
return (
|
||||
<div className="justify-items-start mb-3 rounded border-2 border-white/20 flex-column">
|
||||
<div className="flex justify-center">
|
||||
@@ -616,7 +626,22 @@ export const UploadDetails = ({
|
||||
|
||||
<div className="flex w-full">
|
||||
<Conditional test={uploadService === 'nft-storage'}>
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" />
|
||||
<div className="flex-col w-full">
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" disabled={useDefaultApiKey} />
|
||||
<div className="flex-row mt-2 w-full form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="mr-2 font-bold">Use Default API Key</span>
|
||||
<input
|
||||
checked={useDefaultApiKey}
|
||||
className={`${useDefaultApiKey ? `bg-stargaze` : `bg-gray-600`} checkbox`}
|
||||
onClick={() => {
|
||||
setUseDefaultApiKey(!useDefaultApiKey)
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</Conditional>
|
||||
<Conditional test={uploadService === 'pinata'}>
|
||||
<TextInput {...pinataApiKeyState} className="w-full" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import { Button } from 'components/Button'
|
||||
import { FormControl } from 'components/FormControl'
|
||||
import { FormGroup } from 'components/FormGroup'
|
||||
import { AddressList } from 'components/forms/AddressList'
|
||||
@@ -42,7 +43,7 @@ export interface WhitelistDetailsDataProps {
|
||||
|
||||
type WhitelistState = 'none' | 'existing' | 'new'
|
||||
|
||||
type WhitelistType = 'standard' | 'flex'
|
||||
export type WhitelistType = 'standard' | 'flex' | 'merkletree'
|
||||
|
||||
export const WhitelistDetails = ({
|
||||
onChange,
|
||||
@@ -58,6 +59,7 @@ export const WhitelistDetails = ({
|
||||
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
|
||||
const [whitelistStandardArray, setWhitelistStandardArray] = useState<string[]>([])
|
||||
const [whitelistFlexArray, setWhitelistFlexArray] = useState<WhitelistFlexMember[]>([])
|
||||
const [whitelistMerkleTreeArray, setWhitelistMerkleTreeArray] = useState<string[]>([])
|
||||
const [adminsMutable, setAdminsMutable] = useState<boolean>(true)
|
||||
|
||||
const whitelistAddressState = useInputState({
|
||||
@@ -96,17 +98,41 @@ export const WhitelistDetails = ({
|
||||
const addressListState = useAddressListState()
|
||||
|
||||
const whitelistFileOnChange = (data: string[]) => {
|
||||
setWhitelistStandardArray(data)
|
||||
if (whitelistType === 'standard') setWhitelistStandardArray(data)
|
||||
if (whitelistType === 'merkletree') setWhitelistMerkleTreeArray(data)
|
||||
}
|
||||
|
||||
const whitelistFlexFileOnChange = (whitelistData: WhitelistFlexMember[]) => {
|
||||
setWhitelistFlexArray(whitelistData)
|
||||
}
|
||||
|
||||
const downloadSampleWhitelistFlexFile = () => {
|
||||
const csvData =
|
||||
'address,mint_count\nstars153w5xhuqu3et29lgqk4dsynj6gjn96lr33wx4e,3\nstars1xkes5r2k8u3m3ayfpverlkcrq3k4jhdk8ws0uz,1\nstars1s8qx0zvz8yd6e4x0mqmqf7fr9vvfn622wtp3g3,2'
|
||||
const blob = new Blob([csvData], { type: 'text/csv' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', url)
|
||||
a.setAttribute('download', 'sample_whitelist_flex.csv')
|
||||
a.click()
|
||||
}
|
||||
|
||||
const downloadSampleWhitelistFile = () => {
|
||||
const txtData =
|
||||
'stars153w5xhuqu3et29lgqk4dsynj6gjn96lr33wx4e\nstars1xkes5r2k8u3m3ayfpverlkcrq3k4jhdk8ws0uz\nstars1s8qx0zvz8yd6e4x0mqmqf7fr9vvfn622wtp3g3'
|
||||
const blob = new Blob([txtData], { type: 'text/txt' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', url)
|
||||
a.setAttribute('download', 'sample_whitelist.txt')
|
||||
a.click()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!importedWhitelistDetails) {
|
||||
setWhitelistStandardArray([])
|
||||
setWhitelistFlexArray([])
|
||||
setWhitelistMerkleTreeArray([])
|
||||
}
|
||||
}, [whitelistType])
|
||||
|
||||
@@ -120,7 +146,12 @@ export const WhitelistDetails = ({
|
||||
.replace(/"/g, '')
|
||||
.replace(/'/g, '')
|
||||
.replace(/ /g, ''),
|
||||
members: whitelistType === 'standard' ? whitelistStandardArray : whitelistFlexArray,
|
||||
members:
|
||||
whitelistType === 'standard'
|
||||
? whitelistStandardArray
|
||||
: whitelistType === 'merkletree'
|
||||
? whitelistMerkleTreeArray
|
||||
: whitelistFlexArray,
|
||||
unitPrice: unitPriceState.value
|
||||
? (Number(unitPriceState.value) * 1_000_000).toString()
|
||||
: unitPriceState.value === 0
|
||||
@@ -150,7 +181,9 @@ export const WhitelistDetails = ({
|
||||
endDate,
|
||||
whitelistStandardArray,
|
||||
whitelistFlexArray,
|
||||
whitelistMerkleTreeArray,
|
||||
whitelistState,
|
||||
whitelistType,
|
||||
addressListState.values,
|
||||
adminsMutable,
|
||||
])
|
||||
@@ -188,7 +221,12 @@ export const WhitelistDetails = ({
|
||||
importedWhitelistDetails.members?.forEach((member) => {
|
||||
setWhitelistStandardArray((standardArray) => [...standardArray, member as string])
|
||||
})
|
||||
} else {
|
||||
} else if (importedWhitelistDetails.whitelistType === 'merkletree') {
|
||||
setWhitelistMerkleTreeArray([])
|
||||
// importedWhitelistDetails.members?.forEach((member) => {
|
||||
// setWhitelistMerkleTreeArray((merkleTreeArray) => [...merkleTreeArray, member as string])
|
||||
// })
|
||||
} else if (importedWhitelistDetails.whitelistType === 'flex') {
|
||||
setWhitelistFlexArray([])
|
||||
importedWhitelistDetails.members?.forEach((member) => {
|
||||
setWhitelistFlexArray((flexArray) => [
|
||||
@@ -280,7 +318,7 @@ export const WhitelistDetails = ({
|
||||
</Conditional>
|
||||
|
||||
<Conditional test={whitelistState === 'new'}>
|
||||
<div className="flex justify-between mb-5 ml-6 max-w-[300px] text-lg font-bold">
|
||||
<div className="flex justify-between mb-5 ml-6 max-w-[500px] text-lg font-bold">
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistType === 'standard'}
|
||||
@@ -291,7 +329,7 @@ export const WhitelistDetails = ({
|
||||
setWhitelistType('standard')
|
||||
}}
|
||||
type="radio"
|
||||
value="nft-storage"
|
||||
value="standard"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
@@ -320,12 +358,33 @@ export const WhitelistDetails = ({
|
||||
Whitelist Flex
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistType === 'merkletree'}
|
||||
className="peer sr-only"
|
||||
id="inlineRadio9"
|
||||
name="inlineRadioOptions9"
|
||||
onClick={() => {
|
||||
setWhitelistType('merkletree')
|
||||
}}
|
||||
type="radio"
|
||||
value="merkletree"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="inlineRadio9"
|
||||
>
|
||||
Whitelist Merkle Tree
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2">
|
||||
<FormGroup subtitle="Information about your minting settings" title="Whitelist Minting Details">
|
||||
<NumberInput isRequired {...unitPriceState} />
|
||||
<NumberInput isRequired {...memberLimitState} />
|
||||
<Conditional test={whitelistType === 'standard'}>
|
||||
<Conditional test={whitelistType !== 'merkletree'}>
|
||||
<NumberInput isRequired {...memberLimitState} />
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'standard' || whitelistType === 'merkletree'}>
|
||||
<NumberInput isRequired {...perAddressLimitState} />
|
||||
</Conditional>
|
||||
<FormControl
|
||||
@@ -408,7 +467,17 @@ export const WhitelistDetails = ({
|
||||
/>
|
||||
</div>
|
||||
<Conditional test={whitelistType === 'standard'}>
|
||||
<FormGroup subtitle="TXT file that contains the whitelisted addresses" title="Whitelist File">
|
||||
<FormGroup
|
||||
subtitle={
|
||||
<div>
|
||||
<span>TXT file that contains the whitelisted addresses</span>
|
||||
<Button className="mt-2 text-sm text-white" onClick={downloadSampleWhitelistFile}>
|
||||
Download Sample File
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title="Whitelist File"
|
||||
>
|
||||
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||
</FormGroup>
|
||||
<Conditional test={whitelistStandardArray.length > 0}>
|
||||
@@ -417,7 +486,14 @@ export const WhitelistDetails = ({
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'flex'}>
|
||||
<FormGroup
|
||||
subtitle="CSV file that contains the whitelisted addresses and their corresponding mint counts"
|
||||
subtitle={
|
||||
<div>
|
||||
<span>CSV file that contains the whitelisted addresses and corresponding mint counts</span>
|
||||
<Button className="mt-2 text-sm text-white" onClick={downloadSampleWhitelistFlexFile}>
|
||||
Download Sample File
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title="Whitelist File"
|
||||
>
|
||||
<WhitelistFlexUpload onChange={whitelistFlexFileOnChange} />
|
||||
@@ -426,6 +502,24 @@ export const WhitelistDetails = ({
|
||||
<JsonPreview content={whitelistFlexArray} initialState={false} title="File Contents" />
|
||||
</Conditional>
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'merkletree'}>
|
||||
<FormGroup
|
||||
subtitle={
|
||||
<div>
|
||||
<span>TXT file that contains the whitelisted addresses</span>
|
||||
<Button className="mt-2 text-sm text-white" onClick={downloadSampleWhitelistFile}>
|
||||
Download Sample File
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title="Whitelist File"
|
||||
>
|
||||
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||
</FormGroup>
|
||||
<Conditional test={whitelistStandardArray.length > 0}>
|
||||
<JsonPreview content={whitelistStandardArray} initialState title="File Contents" />
|
||||
</Conditional>
|
||||
</Conditional>
|
||||
</div>
|
||||
</div>
|
||||
</Conditional>
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import { Combobox, Transition } from '@headlessui/react'
|
||||
import clsx from 'clsx'
|
||||
import { FormControl } from 'components/FormControl'
|
||||
import type { ExecuteListItem } from 'contracts/whitelist/messages/execute'
|
||||
import { EXECUTE_LIST } from 'contracts/whitelist/messages/execute'
|
||||
import { EXECUTE_LIST as WL_MERKLE_TREE_EXECUTE_LIST } from 'contracts/whitelistMerkleTree/messages/execute'
|
||||
import { matchSorter } from 'match-sorter'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { FaChevronDown, FaInfoCircle } from 'react-icons/fa'
|
||||
@@ -10,13 +13,20 @@ import { FaChevronDown, FaInfoCircle } from 'react-icons/fa'
|
||||
export interface ExecuteComboboxProps {
|
||||
value: ExecuteListItem | null
|
||||
onChange: (item: ExecuteListItem) => void
|
||||
whitelistType?: 'standard' | 'flex' | 'merkletree'
|
||||
}
|
||||
|
||||
export const ExecuteCombobox = ({ value, onChange }: ExecuteComboboxProps) => {
|
||||
export const ExecuteCombobox = ({ value, onChange, whitelistType }: ExecuteComboboxProps) => {
|
||||
const [search, setSearch] = useState('')
|
||||
|
||||
const filtered =
|
||||
search === '' ? EXECUTE_LIST : matchSorter(EXECUTE_LIST, search, { keys: ['id', 'name', 'description'] })
|
||||
whitelistType !== 'merkletree'
|
||||
? search === ''
|
||||
? EXECUTE_LIST
|
||||
: matchSorter(EXECUTE_LIST, search, { keys: ['id', 'name', 'description'] })
|
||||
: search === ''
|
||||
? WL_MERKLE_TREE_EXECUTE_LIST
|
||||
: matchSorter(WL_MERKLE_TREE_EXECUTE_LIST, search, { keys: ['id', 'name', 'description'] })
|
||||
|
||||
return (
|
||||
<Combobox
|
||||
|
||||
@@ -14,6 +14,7 @@ import type { ChangeEvent } from 'react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import type { UploadServiceType } from 'services/upload'
|
||||
import { NFT_STORAGE_DEFAULT_API_KEY } from 'utils/constants'
|
||||
import type { AssetType } from 'utils/getAssetType'
|
||||
import { getAssetType } from 'utils/getAssetType'
|
||||
|
||||
@@ -43,6 +44,7 @@ export const ImageUploadDetails = ({ onChange, importedImageUploadDetails }: Ima
|
||||
const [isThumbnailCompatible, setIsThumbnailCompatible] = useState<boolean>(false)
|
||||
const [uploadMethod, setUploadMethod] = useState<UploadMethod>('new')
|
||||
const [uploadService, setUploadService] = useState<UploadServiceType>('nft-storage')
|
||||
const [useDefaultApiKey, setUseDefaultApiKey] = useState(false)
|
||||
|
||||
const assetFileRef = useRef<HTMLInputElement | null>(null)
|
||||
const thumbnailFileRef = useRef<HTMLInputElement | null>(null)
|
||||
@@ -192,6 +194,14 @@ export const ImageUploadDetails = ({ onChange, importedImageUploadDetails }: Ima
|
||||
}
|
||||
}, [importedImageUploadDetails])
|
||||
|
||||
useEffect(() => {
|
||||
if (useDefaultApiKey) {
|
||||
nftStorageApiKeyState.onChange(NFT_STORAGE_DEFAULT_API_KEY || '')
|
||||
} else {
|
||||
nftStorageApiKeyState.onChange('')
|
||||
}
|
||||
}, [useDefaultApiKey])
|
||||
|
||||
const previewUrl = imageUrlState.value.toLowerCase().trim().startsWith('ipfs://')
|
||||
? `https://ipfs-gw.stargaze-apis.com/ipfs/${imageUrlState.value.substring(7)}`
|
||||
: imageUrlState.value
|
||||
@@ -343,7 +353,22 @@ export const ImageUploadDetails = ({ onChange, importedImageUploadDetails }: Ima
|
||||
|
||||
<div className="flex w-full">
|
||||
<Conditional test={uploadService === 'nft-storage'}>
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" />
|
||||
<div className="flex-col w-full">
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" disabled={useDefaultApiKey} />
|
||||
<div className="flex-row mt-2 w-full form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="mr-2 font-bold">Use Default API Key</span>
|
||||
<input
|
||||
checked={useDefaultApiKey}
|
||||
className={`${useDefaultApiKey ? `bg-stargaze` : `bg-gray-600`} checkbox`}
|
||||
onClick={() => {
|
||||
setUseDefaultApiKey(!useDefaultApiKey)
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</Conditional>
|
||||
<Conditional test={uploadService === 'pinata'}>
|
||||
<TextInput {...pinataApiKeyState} className="w-full" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import { Conditional } from 'components/Conditional'
|
||||
import { FormControl } from 'components/FormControl'
|
||||
import { FormGroup } from 'components/FormGroup'
|
||||
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||
@@ -16,21 +17,27 @@ import { useWallet } from 'utils/wallet'
|
||||
import { NumberInput, TextInput } from '../forms/FormInput'
|
||||
import type { UploadMethod } from './OffChainMetadataUploadDetails'
|
||||
|
||||
export type LimitType = 'count_limited' | 'time_limited' | 'time_and_count_limited'
|
||||
|
||||
interface MintingDetailsProps {
|
||||
onChange: (data: MintingDetailsDataProps) => void
|
||||
uploadMethod: UploadMethod
|
||||
minimumMintPrice: number
|
||||
mintTokenFromFactory?: TokenInfo | undefined
|
||||
importedMintingDetails?: MintingDetailsDataProps
|
||||
isPresale: boolean
|
||||
whitelistStartDate?: string
|
||||
}
|
||||
|
||||
export interface MintingDetailsDataProps {
|
||||
unitPrice: string
|
||||
perAddressLimit: number
|
||||
startTime: string
|
||||
endTime: string
|
||||
endTime?: string
|
||||
tokenCountLimit?: number
|
||||
paymentAddress?: string
|
||||
selectedMintToken?: TokenInfo
|
||||
limitType: LimitType
|
||||
}
|
||||
|
||||
export const MintingDetails = ({
|
||||
@@ -39,6 +46,8 @@ export const MintingDetails = ({
|
||||
minimumMintPrice,
|
||||
mintTokenFromFactory,
|
||||
importedMintingDetails,
|
||||
isPresale,
|
||||
whitelistStartDate,
|
||||
}: MintingDetailsProps) => {
|
||||
const wallet = useWallet()
|
||||
|
||||
@@ -46,6 +55,7 @@ export const MintingDetails = ({
|
||||
const [endTimestamp, setEndTimestamp] = useState<Date | undefined>()
|
||||
const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
|
||||
const [mintingDetailsImported, setMintingDetailsImported] = useState(false)
|
||||
const [limitType, setLimitType] = useState<LimitType>('time_limited')
|
||||
const { timezone } = useGlobalSettings()
|
||||
|
||||
const unitPriceState = useNumberInputState({
|
||||
@@ -66,6 +76,14 @@ export const MintingDetails = ({
|
||||
placeholder: '1',
|
||||
})
|
||||
|
||||
const tokenCountLimitState = useNumberInputState({
|
||||
id: 'tokencountlimit',
|
||||
name: 'tokencountlimit',
|
||||
title: 'Maximum Token Count',
|
||||
subtitle: 'Total number of mintable tokens',
|
||||
placeholder: '100',
|
||||
})
|
||||
|
||||
const paymentAddressState = useInputState({
|
||||
id: 'payment-address',
|
||||
name: 'paymentAddress',
|
||||
@@ -95,9 +113,19 @@ export const MintingDetails = ({
|
||||
: '',
|
||||
perAddressLimit: perAddressLimitState.value,
|
||||
startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '',
|
||||
endTime: endTimestamp ? (endTimestamp.getTime() * 1_000_000).toString() : '',
|
||||
endTime:
|
||||
limitType === 'time_limited' || limitType === 'time_and_count_limited'
|
||||
? endTimestamp
|
||||
? (endTimestamp.getTime() * 1_000_000).toString()
|
||||
: ''
|
||||
: undefined,
|
||||
paymentAddress: paymentAddressState.value.trim(),
|
||||
selectedMintToken,
|
||||
limitType,
|
||||
tokenCountLimit:
|
||||
limitType === 'count_limited' || limitType === 'time_and_count_limited'
|
||||
? tokenCountLimitState.value
|
||||
: undefined,
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -108,6 +136,8 @@ export const MintingDetails = ({
|
||||
endTimestamp,
|
||||
paymentAddressState.value,
|
||||
selectedMintToken,
|
||||
tokenCountLimitState.value,
|
||||
limitType,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -115,6 +145,8 @@ export const MintingDetails = ({
|
||||
console.log('Selected Token ID: ', importedMintingDetails.selectedMintToken?.id)
|
||||
unitPriceState.onChange(Number(importedMintingDetails.unitPrice) / 1000000)
|
||||
perAddressLimitState.onChange(importedMintingDetails.perAddressLimit)
|
||||
setLimitType(importedMintingDetails.limitType)
|
||||
tokenCountLimitState.onChange(importedMintingDetails.tokenCountLimit ? importedMintingDetails.tokenCountLimit : 0)
|
||||
setTimestamp(new Date(Number(importedMintingDetails.startTime) / 1_000_000))
|
||||
setEndTimestamp(new Date(Number(importedMintingDetails.endTime) / 1_000_000))
|
||||
paymentAddressState.onChange(importedMintingDetails.paymentAddress ? importedMintingDetails.paymentAddress : '')
|
||||
@@ -124,6 +156,12 @@ export const MintingDetails = ({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [importedMintingDetails])
|
||||
|
||||
useEffect(() => {
|
||||
if (isPresale) {
|
||||
setTimestamp(whitelistStartDate ? new Date(Number(whitelistStartDate) / 1_000_000) : undefined)
|
||||
}
|
||||
}, [whitelistStartDate, isPresale])
|
||||
|
||||
return (
|
||||
<div className="border-l-[1px] border-gray-500 border-opacity-20">
|
||||
<FormGroup subtitle="Information about your minting settings" title="Minting Details">
|
||||
@@ -152,6 +190,7 @@ export const MintingDetails = ({
|
||||
title="Start Time"
|
||||
>
|
||||
<InputDateTime
|
||||
disabled={isPresale}
|
||||
minDate={
|
||||
timezone === 'Local' ? new Date() : new Date(Date.now() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
}
|
||||
@@ -171,32 +210,69 @@ export const MintingDetails = ({
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl
|
||||
htmlId="endTimestamp"
|
||||
isRequired
|
||||
subtitle={`Minting end time ${timezone === 'Local' ? '(local)' : '(UTC)'}`}
|
||||
title="End Time"
|
||||
>
|
||||
<InputDateTime
|
||||
minDate={
|
||||
timezone === 'Local' ? new Date() : new Date(Date.now() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
}
|
||||
onChange={(date) =>
|
||||
date
|
||||
? setEndTimestamp(
|
||||
timezone === 'Local' ? date : new Date(date.getTime() - new Date().getTimezoneOffset() * 60 * 1000),
|
||||
)
|
||||
: setEndTimestamp(undefined)
|
||||
}
|
||||
value={
|
||||
timezone === 'Local'
|
||||
? endTimestamp
|
||||
: endTimestamp
|
||||
? new Date(endTimestamp.getTime() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<div className="flex-row mt-2 w-full form-control">
|
||||
<h1 className="mt-2 font-bold text-md">Limit Type: </h1>
|
||||
<label className="justify-start ml-6 cursor-pointer label">
|
||||
<span className="mr-2">Time</span>
|
||||
<input
|
||||
checked={limitType === 'time_limited' || limitType === 'time_and_count_limited'}
|
||||
className={`${limitType === 'time_limited' ? `bg-stargaze` : `bg-gray-600`} checkbox`}
|
||||
onClick={() => {
|
||||
if (limitType === 'time_and_count_limited') setLimitType('count_limited' as LimitType)
|
||||
else if (limitType === 'count_limited') setLimitType('time_and_count_limited' as LimitType)
|
||||
else setLimitType('count_limited' as LimitType)
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
<label className="justify-start ml-4 cursor-pointer label">
|
||||
<span className="mr-2">Token Count</span>
|
||||
<input
|
||||
checked={limitType === 'count_limited' || limitType === 'time_and_count_limited'}
|
||||
className={`${limitType === 'count_limited' ? `bg-stargaze` : `bg-gray-600`} checkbox`}
|
||||
onClick={() => {
|
||||
if (limitType === 'time_and_count_limited') setLimitType('time_limited' as LimitType)
|
||||
else if (limitType === 'time_limited') setLimitType('time_and_count_limited' as LimitType)
|
||||
else setLimitType('time_limited' as LimitType)
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<Conditional test={limitType === 'time_limited' || limitType === 'time_and_count_limited'}>
|
||||
<FormControl
|
||||
htmlId="endTimestamp"
|
||||
isRequired
|
||||
subtitle={`Minting end time ${timezone === 'Local' ? '(local)' : '(UTC)'}`}
|
||||
title="End Time"
|
||||
>
|
||||
<InputDateTime
|
||||
minDate={
|
||||
timezone === 'Local' ? new Date() : new Date(Date.now() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
}
|
||||
onChange={(date) =>
|
||||
date
|
||||
? setEndTimestamp(
|
||||
timezone === 'Local'
|
||||
? date
|
||||
: new Date(date.getTime() - new Date().getTimezoneOffset() * 60 * 1000),
|
||||
)
|
||||
: setEndTimestamp(undefined)
|
||||
}
|
||||
value={
|
||||
timezone === 'Local'
|
||||
? endTimestamp
|
||||
: endTimestamp
|
||||
? new Date(endTimestamp.getTime() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
</Conditional>
|
||||
<Conditional test={limitType === 'count_limited' || limitType === 'time_and_count_limited'}>
|
||||
<NumberInput {...tokenCountLimitState} isRequired />
|
||||
</Conditional>
|
||||
</FormGroup>
|
||||
<TextInput className="pr-4 pl-4 mt-3" {...paymentAddressState} />
|
||||
</div>
|
||||
|
||||
@@ -18,6 +18,7 @@ import type { ChangeEvent } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import type { UploadServiceType } from 'services/upload'
|
||||
import { NFT_STORAGE_DEFAULT_API_KEY } from 'utils/constants'
|
||||
import type { AssetType } from 'utils/getAssetType'
|
||||
import { getAssetType } from 'utils/getAssetType'
|
||||
import { uid } from 'utils/random'
|
||||
@@ -64,6 +65,7 @@ export const OffChainMetadataUploadDetails = ({
|
||||
const [refreshMetadata, setRefreshMetadata] = useState(false)
|
||||
const [exportedMetadata, setExportedMetadata] = useState(undefined)
|
||||
const [openEditionMinterMetadataFile, setOpenEditionMinterMetadataFile] = useState<File | undefined>()
|
||||
const [useDefaultApiKey, setUseDefaultApiKey] = useState(false)
|
||||
|
||||
const thumbnailCompatibleAssetTypes: AssetType[] = ['video', 'audio', 'html', 'document']
|
||||
|
||||
@@ -297,6 +299,14 @@ export const OffChainMetadataUploadDetails = ({
|
||||
}
|
||||
}, [importedOffChainMetadataUploadDetails])
|
||||
|
||||
useEffect(() => {
|
||||
if (useDefaultApiKey) {
|
||||
nftStorageApiKeyState.onChange(NFT_STORAGE_DEFAULT_API_KEY || '')
|
||||
} else {
|
||||
nftStorageApiKeyState.onChange('')
|
||||
}
|
||||
}, [useDefaultApiKey])
|
||||
|
||||
return (
|
||||
<div className="justify-items-start mb-3 rounded border-2 border-white/20 flex-column">
|
||||
<div className="flex justify-center">
|
||||
@@ -415,7 +425,22 @@ export const OffChainMetadataUploadDetails = ({
|
||||
|
||||
<div className="flex w-full">
|
||||
<Conditional test={uploadService === 'nft-storage'}>
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" />
|
||||
<div className="flex-col w-full">
|
||||
<TextInput {...nftStorageApiKeyState} className="w-full" disabled={useDefaultApiKey} />
|
||||
<div className="flex-row mt-2 w-full form-control">
|
||||
<label className="cursor-pointer label">
|
||||
<span className="mr-2 font-bold">Use Default API Key</span>
|
||||
<input
|
||||
checked={useDefaultApiKey}
|
||||
className={`${useDefaultApiKey ? `bg-stargaze` : `bg-gray-600`} checkbox`}
|
||||
onClick={() => {
|
||||
setUseDefaultApiKey(!useDefaultApiKey)
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</Conditional>
|
||||
<Conditional test={uploadService === 'pinata'}>
|
||||
<TextInput {...pinataApiKeyState} className="w-full" />
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { toUtf8 } from '@cosmjs/encoding'
|
||||
import { coin } from '@cosmjs/proto-signing'
|
||||
import axios from 'axios'
|
||||
import clsx from 'clsx'
|
||||
import { Button } from 'components/Button'
|
||||
import type { MinterType } from 'components/collections/actions/Combobox'
|
||||
import { Conditional } from 'components/Conditional'
|
||||
import { ConfirmationModal } from 'components/ConfirmationModal'
|
||||
import { LoadingModal } from 'components/LoadingModal'
|
||||
import { openEditionMinterList } from 'config/minter'
|
||||
import { type TokenInfo } from 'config/token'
|
||||
import { useContracts } from 'contexts/contracts'
|
||||
import { addLogItem } from 'contexts/log'
|
||||
@@ -22,12 +22,15 @@ import React, { useEffect, useMemo, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import { upload } from 'services/upload'
|
||||
import {
|
||||
OPEN_EDITION_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS,
|
||||
SG721_OPEN_EDITION_CODE_ID,
|
||||
SG721_OPEN_EDITION_UPDATABLE_CODE_ID,
|
||||
STRDST_SG721_CODE_ID,
|
||||
WHITELIST_CODE_ID,
|
||||
WHITELIST_FLEX_CODE_ID,
|
||||
WHITELIST_MERKLE_TREE_API_URL,
|
||||
WHITELIST_MERKLE_TREE_CODE_ID,
|
||||
} from 'utils/constants'
|
||||
import { useDebounce } from 'utils/debounce'
|
||||
import type { AssetType } from 'utils/getAssetType'
|
||||
import { isValidAddress } from 'utils/isValidAddress'
|
||||
import { checkTokenUri } from 'utils/isValidTokenUri'
|
||||
@@ -37,7 +40,7 @@ import { useWallet } from 'utils/wallet'
|
||||
import { type CollectionDetailsDataProps, CollectionDetails } from './CollectionDetails'
|
||||
import type { ImageUploadDetailsDataProps } from './ImageUploadDetails'
|
||||
import { ImageUploadDetails } from './ImageUploadDetails'
|
||||
import type { MintingDetailsDataProps } from './MintingDetails'
|
||||
import type { LimitType, MintingDetailsDataProps } from './MintingDetails'
|
||||
import { MintingDetails } from './MintingDetails'
|
||||
import type { UploadMethod } from './OffChainMetadataUploadDetails'
|
||||
import {
|
||||
@@ -47,12 +50,14 @@ import {
|
||||
import type { OnChainMetadataInputDetailsDataProps } from './OnChainMetadataInputDetails'
|
||||
import { OnChainMetadataInputDetails } from './OnChainMetadataInputDetails'
|
||||
import { type RoyaltyDetailsDataProps, RoyaltyDetails } from './RoyaltyDetails'
|
||||
import { type WhitelistDetailsDataProps, WhitelistDetails } from './WhitelistDetails'
|
||||
|
||||
export type MetadataStorageMethod = 'off-chain' | 'on-chain'
|
||||
|
||||
export interface OpenEditionMinterDetailsDataProps {
|
||||
imageUploadDetails?: ImageUploadDetailsDataProps
|
||||
collectionDetails?: CollectionDetailsDataProps
|
||||
whitelistDetails?: WhitelistDetailsDataProps
|
||||
royaltyDetails?: RoyaltyDetailsDataProps
|
||||
onChainMetadataInputDetails?: OnChainMetadataInputDetailsDataProps
|
||||
offChainMetadataUploadDetails?: OffChainMetadataUploadDetailsDataProps
|
||||
@@ -62,24 +67,26 @@ export interface OpenEditionMinterDetailsDataProps {
|
||||
coverImageUrl?: string | null
|
||||
tokenUri?: string | null
|
||||
tokenImageUri?: string | null
|
||||
isRefreshed?: boolean
|
||||
}
|
||||
|
||||
interface OpenEditionMinterCreatorProps {
|
||||
onChange: (data: OpenEditionMinterCreatorDataProps) => void
|
||||
onDetailsChange: (data: OpenEditionMinterDetailsDataProps) => void
|
||||
openEditionMinterUpdatableCreationFee?: string
|
||||
openEditionMinterCreationFee?: string
|
||||
minimumMintPrice?: string
|
||||
minimumUpdatableMintPrice?: string
|
||||
minterType?: MinterType
|
||||
mintTokenFromFactory?: TokenInfo | undefined
|
||||
importedOpenEditionMinterDetails?: OpenEditionMinterDetailsDataProps
|
||||
isMatchingFactoryPresent?: boolean
|
||||
openEditionFactoryAddress?: string
|
||||
}
|
||||
|
||||
export interface OpenEditionMinterCreatorDataProps {
|
||||
metadataStorageMethod: MetadataStorageMethod
|
||||
openEditionMinterContractAddress: string | null
|
||||
sg721ContractAddress: string | null
|
||||
whitelistContractAddress: string | null
|
||||
transactionHash: string | null
|
||||
}
|
||||
|
||||
@@ -87,21 +94,27 @@ export const OpenEditionMinterCreator = ({
|
||||
onChange,
|
||||
onDetailsChange,
|
||||
openEditionMinterCreationFee,
|
||||
openEditionMinterUpdatableCreationFee,
|
||||
minimumMintPrice,
|
||||
minimumUpdatableMintPrice,
|
||||
minterType,
|
||||
mintTokenFromFactory,
|
||||
importedOpenEditionMinterDetails,
|
||||
isMatchingFactoryPresent,
|
||||
openEditionFactoryAddress,
|
||||
}: OpenEditionMinterCreatorProps) => {
|
||||
const wallet = useWallet()
|
||||
const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } =
|
||||
useContracts()
|
||||
const {
|
||||
openEditionMinter: openEditionMinterContract,
|
||||
openEditionFactory: openEditionFactoryContract,
|
||||
whitelist: whitelistContract,
|
||||
whitelistMerkleTree: whitelistMerkleTreeContract,
|
||||
} = useContracts()
|
||||
|
||||
const [metadataStorageMethod, setMetadataStorageMethod] = useState<MetadataStorageMethod>('off-chain')
|
||||
const [imageUploadDetails, setImageUploadDetails] = useState<ImageUploadDetailsDataProps | null>(null)
|
||||
const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null)
|
||||
const [whitelistDetails, setWhitelistDetails] = useState<WhitelistDetailsDataProps | null>(null)
|
||||
const [royaltyDetails, setRoyaltyDetails] = useState<RoyaltyDetailsDataProps | null>(null)
|
||||
const [isRefreshed, setIsRefreshed] = useState(false)
|
||||
const [onChainMetadataInputDetails, setOnChainMetadataInputDetails] =
|
||||
useState<OnChainMetadataInputDetailsDataProps | null>(null)
|
||||
const [offChainMetadataUploadDetails, setOffChainMetadataUploadDetails] =
|
||||
@@ -116,29 +129,19 @@ export const OpenEditionMinterCreator = ({
|
||||
const [coverImageUrl, setCoverImageUrl] = useState<string | null>(null)
|
||||
const [openEditionMinterContractAddress, setOpenEditionMinterContractAddress] = useState<string | null>(null)
|
||||
const [sg721ContractAddress, setSg721ContractAddress] = useState<string | null>(null)
|
||||
const [whitelistContractAddress, setWhitelistContractAddress] = useState<string | null>(null)
|
||||
const [transactionHash, setTransactionHash] = useState<string | null>(null)
|
||||
const [thumbnailImageUri, setThumbnailImageUri] = useState<string | undefined>(undefined)
|
||||
|
||||
const thumbnailCompatibleAssetTypes: AssetType[] = ['video', 'audio', 'html']
|
||||
|
||||
const factoryAddressForSelectedDenom =
|
||||
openEditionMinterList.find((minter) => minter.supportedToken === mintTokenFromFactory && minter.updatable === false)
|
||||
?.factoryAddress || OPEN_EDITION_FACTORY_ADDRESS
|
||||
const updatableFactoryAddressForSelectedDenom =
|
||||
openEditionMinterList.find((minter) => minter.supportedToken === mintTokenFromFactory && minter.updatable === true)
|
||||
?.factoryAddress || OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS
|
||||
|
||||
const openEditionFactoryMessages = useMemo(
|
||||
() =>
|
||||
openEditionFactoryContract?.use(
|
||||
collectionDetails?.updatable ? updatableFactoryAddressForSelectedDenom : factoryAddressForSelectedDenom,
|
||||
),
|
||||
() => openEditionFactoryContract?.use(openEditionFactoryAddress as string),
|
||||
[
|
||||
openEditionFactoryContract,
|
||||
wallet.address,
|
||||
collectionDetails?.updatable,
|
||||
factoryAddressForSelectedDenom,
|
||||
updatableFactoryAddressForSelectedDenom,
|
||||
openEditionFactoryAddress,
|
||||
wallet.isWalletConnected,
|
||||
],
|
||||
)
|
||||
@@ -152,13 +155,26 @@ export const OpenEditionMinterCreator = ({
|
||||
.then(() => {
|
||||
void checkRoyaltyDetails()
|
||||
.then(() => {
|
||||
void checkwalletBalance()
|
||||
checkWhitelistDetails()
|
||||
.then(() => {
|
||||
setReadyToCreate(true)
|
||||
void checkwalletBalance()
|
||||
.then(() => {
|
||||
setReadyToCreate(true)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
toast.error(`Error in Wallet Balance: ${error.message}`, { style: { maxWidth: 'none' } })
|
||||
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
|
||||
setReadyToCreate(false)
|
||||
})
|
||||
})
|
||||
.catch((error: any) => {
|
||||
toast.error(`Error in Wallet Balance: ${error.message}`, { style: { maxWidth: 'none' } })
|
||||
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
|
||||
.catch((error) => {
|
||||
if (String(error.message).includes('Insufficient wallet balance')) {
|
||||
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
|
||||
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
|
||||
} else {
|
||||
toast.error(`Error in Whitelist Configuration: ${error.message}`, { style: { maxWidth: 'none' } })
|
||||
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
|
||||
}
|
||||
setReadyToCreate(false)
|
||||
})
|
||||
})
|
||||
@@ -299,9 +315,9 @@ export const OpenEditionMinterCreator = ({
|
||||
if (!mintingDetails) throw new Error('Please fill out the minting details')
|
||||
if (mintingDetails.unitPrice === '') throw new Error('Mint price is required')
|
||||
if (collectionDetails?.updatable) {
|
||||
if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice))
|
||||
if (Number(mintingDetails.unitPrice) < Number(minimumMintPrice))
|
||||
throw new Error(
|
||||
`Invalid mint price: The minimum mint price is ${Number(minimumUpdatableMintPrice) / 1000000} ${
|
||||
`Invalid mint price: The minimum mint price is ${Number(minimumMintPrice) / 1000000} ${
|
||||
mintTokenFromFactory?.displayName
|
||||
}`,
|
||||
)
|
||||
@@ -314,11 +330,27 @@ export const OpenEditionMinterCreator = ({
|
||||
if (!mintingDetails.perAddressLimit || mintingDetails.perAddressLimit < 1 || mintingDetails.perAddressLimit > 50)
|
||||
throw new Error('Invalid limit for tokens per address')
|
||||
if (mintingDetails.startTime === '') throw new Error('Start time is required')
|
||||
if (mintingDetails.endTime === '') throw new Error('End time is required')
|
||||
if (mintingDetails.limitType === 'time_limited' && mintingDetails.endTime === '')
|
||||
throw new Error('End time is required')
|
||||
if (mintingDetails.limitType === 'count_limited' && mintingDetails.tokenCountLimit === undefined)
|
||||
throw new Error('Token count limit is required')
|
||||
if (
|
||||
mintingDetails.limitType === 'count_limited' &&
|
||||
mintingDetails.perAddressLimit > (mintingDetails.tokenCountLimit as number)
|
||||
)
|
||||
throw new Error('Per address limit cannot exceed maximum token count limit')
|
||||
if (mintingDetails.limitType === 'count_limited' && (mintingDetails.tokenCountLimit as number) > 10000)
|
||||
throw new Error('Maximum token count cannot exceed 10000')
|
||||
if (Number(mintingDetails.startTime) < new Date().getTime() * 1000000) throw new Error('Invalid start time')
|
||||
if (Number(mintingDetails.endTime) < Number(mintingDetails.startTime))
|
||||
if (
|
||||
mintingDetails.limitType === 'time_limited' &&
|
||||
Number(mintingDetails.endTime) < Number(mintingDetails.startTime)
|
||||
)
|
||||
throw new Error('End time cannot be earlier than start time')
|
||||
if (Number(mintingDetails.endTime) === Number(mintingDetails.startTime))
|
||||
if (
|
||||
mintingDetails.limitType === 'time_limited' &&
|
||||
Number(mintingDetails.endTime) === Number(mintingDetails.startTime)
|
||||
)
|
||||
throw new Error('End time cannot be equal to the start time')
|
||||
|
||||
if (
|
||||
@@ -326,6 +358,92 @@ export const OpenEditionMinterCreator = ({
|
||||
(!isValidAddress(mintingDetails.paymentAddress) || !mintingDetails.paymentAddress.startsWith('stars1'))
|
||||
)
|
||||
throw new Error('Invalid payment address')
|
||||
|
||||
if (!isMatchingFactoryPresent)
|
||||
throw new Error(
|
||||
`No matching open edition factory contract found for the selected parameters (Mint Price Denom: ${mintingDetails.selectedMintToken?.displayName}, Whitelist Type: ${whitelistDetails?.whitelistType})`,
|
||||
)
|
||||
}
|
||||
|
||||
const checkWhitelistDetails = async () => {
|
||||
if (!whitelistDetails) throw new Error('Please fill out the whitelist details')
|
||||
if (whitelistDetails.whitelistState === 'existing') {
|
||||
if (whitelistDetails.contractAddress === '') throw new Error('Whitelist contract address is required')
|
||||
else {
|
||||
const contract = whitelistContract?.use(whitelistDetails.contractAddress)
|
||||
//check if the address belongs to a whitelist contract (see performChecks())
|
||||
const config = await contract?.config()
|
||||
if (JSON.stringify(config).includes('whale_cap')) whitelistDetails.whitelistType = 'flex'
|
||||
else if (!JSON.stringify(config).includes('member_limit') || config?.member_limit === 0) {
|
||||
// whitelistDetails.whitelistType = 'merkletree'
|
||||
throw new Error(
|
||||
'Whitelist Merkle Tree is not supported yet. Please use a standard or flexible whitelist contract.',
|
||||
)
|
||||
} else whitelistDetails.whitelistType = 'standard'
|
||||
if (Number(config?.start_time) !== Number(mintingDetails?.startTime)) {
|
||||
const whitelistStartDate = new Date(Number(config?.start_time) / 1000000)
|
||||
throw Error(`Whitelist start time (${whitelistStartDate.toLocaleString()}) does not match minting start time`)
|
||||
}
|
||||
|
||||
if (mintingDetails?.tokenCountLimit && config?.per_address_limit) {
|
||||
if (mintingDetails.tokenCountLimit >= 100 && Number(config.per_address_limit) > 50) {
|
||||
throw Error(
|
||||
`Invalid limit for tokens per address (${config.per_address_limit} tokens). Tokens per address limit cannot exceed 50 regardless of the total number of tokens.`,
|
||||
)
|
||||
} else if (
|
||||
mintingDetails.tokenCountLimit >= 100 &&
|
||||
Number(config.per_address_limit) > Math.ceil((mintingDetails.tokenCountLimit / 100) * 3)
|
||||
) {
|
||||
throw Error(
|
||||
`Invalid limit for tokens per address (${config.per_address_limit} tokens). Tokens per address limit cannot exceed 3% of the total number of tokens in the collection.`,
|
||||
)
|
||||
} else if (mintingDetails.tokenCountLimit < 100 && Number(config.per_address_limit) > 3) {
|
||||
throw Error(
|
||||
`Invalid limit for tokens per address (${config.per_address_limit} tokens). Tokens per address limit cannot exceed 3 for collections with a token count limit smaller than 100 tokens.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (whitelistDetails.whitelistState === 'new') {
|
||||
if (whitelistDetails.members?.length === 0) throw new Error('Whitelist member list cannot be empty')
|
||||
if (whitelistDetails.unitPrice === undefined) throw new Error('Whitelist unit price is required')
|
||||
if (Number(whitelistDetails.unitPrice) < 0)
|
||||
throw new Error('Invalid unit price: The unit price cannot be negative')
|
||||
if (whitelistDetails.startTime === '') throw new Error('Start time is required')
|
||||
if (whitelistDetails.endTime === '') throw new Error('End time is required')
|
||||
if (
|
||||
whitelistDetails.whitelistType === 'standard' &&
|
||||
(!whitelistDetails.perAddressLimit || whitelistDetails.perAddressLimit === 0)
|
||||
)
|
||||
throw new Error('Per address limit is required')
|
||||
if (
|
||||
whitelistDetails.whitelistType !== 'merkletree' &&
|
||||
(!whitelistDetails.memberLimit || whitelistDetails.memberLimit === 0)
|
||||
)
|
||||
throw new Error('Member limit is required')
|
||||
if (Number(whitelistDetails.startTime) >= Number(whitelistDetails.endTime))
|
||||
throw new Error('Whitelist start time cannot be equal to or later than the whitelist end time')
|
||||
if (Number(whitelistDetails.startTime) !== Number(mintingDetails?.startTime))
|
||||
throw new Error('Whitelist start time must be the same as the minting start time')
|
||||
if (whitelistDetails.perAddressLimit && mintingDetails?.tokenCountLimit) {
|
||||
if (mintingDetails.tokenCountLimit >= 100 && whitelistDetails.perAddressLimit > 50) {
|
||||
throw Error(
|
||||
`Invalid limit for tokens per address. Tokens per address limit cannot exceed 50 regardless of the total number of tokens.`,
|
||||
)
|
||||
} else if (
|
||||
mintingDetails.tokenCountLimit >= 100 &&
|
||||
whitelistDetails.perAddressLimit > Math.ceil((mintingDetails.tokenCountLimit / 100) * 3)
|
||||
) {
|
||||
throw Error(
|
||||
`Invalid limit for tokens per address. Tokens per address limit cannot exceed 3% of the total number of tokens in the collection.`,
|
||||
)
|
||||
} else if (mintingDetails.tokenCountLimit < 100 && whitelistDetails.perAddressLimit > 3) {
|
||||
throw Error(
|
||||
`Invalid limit for tokens per address. Tokens per address limit cannot exceed 3 for collections with a token count limit smaller than 100 tokens.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const checkRoyaltyDetails = async () => {
|
||||
@@ -362,9 +480,13 @@ export const OpenEditionMinterCreator = ({
|
||||
|
||||
const checkwalletBalance = async () => {
|
||||
if (!wallet.isWalletConnected) throw new Error('Wallet not connected.')
|
||||
const amountNeeded = collectionDetails?.updatable
|
||||
? Number(openEditionMinterUpdatableCreationFee)
|
||||
: Number(openEditionMinterCreationFee)
|
||||
let amountNeeded = 0
|
||||
if (whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) {
|
||||
amountNeeded =
|
||||
Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000 + Number(openEditionMinterCreationFee)
|
||||
} else {
|
||||
amountNeeded = openEditionMinterCreationFee ? Number(openEditionMinterCreationFee) : 0
|
||||
}
|
||||
await (await wallet.getCosmWasmClient()).getBalance(wallet.address || '', 'ustars').then((balance) => {
|
||||
if (amountNeeded >= Number(balance.amount))
|
||||
throw new Error(
|
||||
@@ -383,6 +505,7 @@ export const OpenEditionMinterCreator = ({
|
||||
setTokenImageUri(null)
|
||||
setOpenEditionMinterContractAddress(null)
|
||||
setSg721ContractAddress(null)
|
||||
setWhitelistContractAddress(null)
|
||||
setTransactionHash(null)
|
||||
if (metadataStorageMethod === 'off-chain') {
|
||||
if (offChainMetadataUploadDetails?.uploadMethod === 'new') {
|
||||
@@ -407,13 +530,27 @@ export const OpenEditionMinterCreator = ({
|
||||
setTokenUri(metadataUriWithBase)
|
||||
setCoverImageUrl(coverImageUriWithBase)
|
||||
setUploading(false)
|
||||
await instantiateOpenEditionMinter(metadataUriWithBase, coverImageUriWithBase)
|
||||
|
||||
let whitelist: string | undefined
|
||||
if (whitelistDetails?.whitelistState === 'existing') whitelist = whitelistDetails.contractAddress
|
||||
else if (whitelistDetails?.whitelistState === 'new') whitelist = await instantiateWhitelist()
|
||||
setWhitelistContractAddress(whitelist as string)
|
||||
|
||||
await instantiateOpenEditionMinter(metadataUriWithBase, coverImageUriWithBase, undefined, whitelist)
|
||||
} else {
|
||||
setTokenUri(offChainMetadataUploadDetails?.tokenURI as string)
|
||||
setCoverImageUrl(offChainMetadataUploadDetails?.imageUrl as string)
|
||||
|
||||
let whitelist: string | undefined
|
||||
if (whitelistDetails?.whitelistState === 'existing') whitelist = whitelistDetails.contractAddress
|
||||
else if (whitelistDetails?.whitelistState === 'new') whitelist = await instantiateWhitelist()
|
||||
setWhitelistContractAddress(whitelist as string)
|
||||
|
||||
await instantiateOpenEditionMinter(
|
||||
offChainMetadataUploadDetails?.tokenURI as string,
|
||||
offChainMetadataUploadDetails?.imageUrl as string,
|
||||
undefined,
|
||||
whitelist,
|
||||
)
|
||||
}
|
||||
} else if (metadataStorageMethod === 'on-chain') {
|
||||
@@ -455,15 +592,27 @@ export const OpenEditionMinterCreator = ({
|
||||
? `ipfs://${thumbnailUri}/${(imageUploadDetails.thumbnailFile as File).name}`
|
||||
: undefined
|
||||
setThumbnailImageUri(thumbnailUriWithBase)
|
||||
|
||||
setUploading(false)
|
||||
await instantiateOpenEditionMinter(imageUriWithBase, coverImageUriWithBase, thumbnailUriWithBase)
|
||||
|
||||
let whitelist: string | undefined
|
||||
if (whitelistDetails?.whitelistState === 'existing') whitelist = whitelistDetails.contractAddress
|
||||
else if (whitelistDetails?.whitelistState === 'new') whitelist = await instantiateWhitelist()
|
||||
setWhitelistContractAddress(whitelist as string)
|
||||
|
||||
await instantiateOpenEditionMinter(imageUriWithBase, coverImageUriWithBase, thumbnailUriWithBase, whitelist)
|
||||
} else if (imageUploadDetails?.uploadMethod === 'existing') {
|
||||
setTokenImageUri(imageUploadDetails.imageUrl as string)
|
||||
setCoverImageUrl(imageUploadDetails.coverImageUrl as string)
|
||||
|
||||
let whitelist: string | undefined
|
||||
if (whitelistDetails?.whitelistState === 'existing') whitelist = whitelistDetails.contractAddress
|
||||
else if (whitelistDetails?.whitelistState === 'new') whitelist = await instantiateWhitelist()
|
||||
setWhitelistContractAddress(whitelist as string)
|
||||
|
||||
await instantiateOpenEditionMinter(
|
||||
imageUploadDetails.imageUrl as string,
|
||||
imageUploadDetails.coverImageUrl as string,
|
||||
whitelist,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -562,7 +711,104 @@ export const OpenEditionMinterCreator = ({
|
||||
})
|
||||
}
|
||||
|
||||
const instantiateOpenEditionMinter = async (uri: string, coverImageUri: string, thumbnailUri?: string) => {
|
||||
const instantiateWhitelist = async () => {
|
||||
if (!wallet.isWalletConnected) throw new Error('Wallet not connected')
|
||||
if (!whitelistContract) throw new Error('Contract not found')
|
||||
|
||||
if (whitelistDetails?.whitelistType === 'standard' || whitelistDetails?.whitelistType === 'flex') {
|
||||
const standardMsg = {
|
||||
members: whitelistDetails.members,
|
||||
start_time: whitelistDetails.startTime,
|
||||
end_time: whitelistDetails.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails.unitPrice)),
|
||||
mintTokenFromFactory ? mintTokenFromFactory.denom : 'ustars',
|
||||
),
|
||||
per_address_limit: whitelistDetails.perAddressLimit,
|
||||
member_limit: whitelistDetails.memberLimit,
|
||||
admins: whitelistDetails.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails.adminsMutable,
|
||||
}
|
||||
|
||||
const flexMsg = {
|
||||
members: whitelistDetails.members,
|
||||
start_time: whitelistDetails.startTime,
|
||||
end_time: whitelistDetails.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails.unitPrice)),
|
||||
mintTokenFromFactory ? mintTokenFromFactory.denom : 'ustars',
|
||||
),
|
||||
member_limit: whitelistDetails.memberLimit,
|
||||
admins: whitelistDetails.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails.adminsMutable,
|
||||
}
|
||||
|
||||
const data = await whitelistContract.instantiate(
|
||||
whitelistDetails.whitelistType === 'standard' ? WHITELIST_CODE_ID : WHITELIST_FLEX_CODE_ID,
|
||||
whitelistDetails.whitelistType === 'standard' ? standardMsg : flexMsg,
|
||||
'Stargaze Whitelist Contract',
|
||||
wallet.address,
|
||||
)
|
||||
|
||||
return data.contractAddress
|
||||
} else if (whitelistDetails?.whitelistType === 'merkletree') {
|
||||
const members = whitelistDetails.members as string[]
|
||||
const membersCsv = members.join('\n')
|
||||
const membersBlob = new Blob([membersCsv], { type: 'text/csv' })
|
||||
const membersFile = new File([membersBlob], 'members.csv', { type: 'text/csv' })
|
||||
const formData = new FormData()
|
||||
formData.append('whitelist', membersFile)
|
||||
const response = await toast
|
||||
.promise(
|
||||
axios.post(`${WHITELIST_MERKLE_TREE_API_URL}/create_whitelist`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Fetching merkle root hash...',
|
||||
success: 'Merkle root fetched successfully.',
|
||||
error: 'Error fetching root hash from Whitelist Merkle Tree API.',
|
||||
},
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log('error', error)
|
||||
throw new Error('Whitelist instantiation failed.')
|
||||
})
|
||||
|
||||
const rootHash = response.data.root_hash
|
||||
console.log('rootHash', rootHash)
|
||||
|
||||
const merkleTreeMsg = {
|
||||
merkle_root: rootHash,
|
||||
merkle_tree_uri: null,
|
||||
start_time: whitelistDetails.startTime,
|
||||
end_time: whitelistDetails.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails.unitPrice)),
|
||||
mintTokenFromFactory ? mintTokenFromFactory.denom : 'ustars',
|
||||
),
|
||||
per_address_limit: whitelistDetails.perAddressLimit,
|
||||
admins: whitelistDetails.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails.adminsMutable,
|
||||
}
|
||||
|
||||
const data = await whitelistMerkleTreeContract?.instantiate(
|
||||
WHITELIST_MERKLE_TREE_CODE_ID,
|
||||
merkleTreeMsg,
|
||||
'Stargaze Whitelist Merkle Tree Contract',
|
||||
wallet.address,
|
||||
)
|
||||
return data?.contractAddress
|
||||
}
|
||||
}
|
||||
|
||||
const instantiateOpenEditionMinter = async (
|
||||
uri: string,
|
||||
coverImageUri: string,
|
||||
thumbnailUri?: string,
|
||||
whitelist?: string,
|
||||
) => {
|
||||
if (!wallet.isWalletConnected) throw new Error('Wallet not connected')
|
||||
if (!openEditionFactoryContract) throw new Error('Contract not found')
|
||||
if (!openEditionMinterContract) throw new Error('Contract not found')
|
||||
@@ -603,19 +849,30 @@ export const OpenEditionMinterCreator = ({
|
||||
: null,
|
||||
},
|
||||
start_time: mintingDetails?.startTime,
|
||||
end_time: mintingDetails?.endTime,
|
||||
end_time:
|
||||
mintingDetails?.limitType === ('time_limited' as LimitType) ||
|
||||
mintingDetails?.limitType === ('time_and_count_limited' as LimitType)
|
||||
? mintingDetails.endTime
|
||||
: null,
|
||||
mint_price: {
|
||||
amount: Number(mintingDetails?.unitPrice).toString(),
|
||||
denom: (mintTokenFromFactory?.denom as string) || 'ustars',
|
||||
},
|
||||
per_address_limit: mintingDetails?.perAddressLimit,
|
||||
num_tokens:
|
||||
mintingDetails?.limitType === ('count_limited' as LimitType) ||
|
||||
mintingDetails?.limitType === ('time_and_count_limited' as LimitType)
|
||||
? mintingDetails.tokenCountLimit
|
||||
: null,
|
||||
payment_address: mintingDetails?.paymentAddress || null,
|
||||
whitelist,
|
||||
},
|
||||
collection_params: {
|
||||
code_id: collectionDetails?.updatable
|
||||
? SG721_OPEN_EDITION_UPDATABLE_CODE_ID
|
||||
: mintingDetails?.selectedMintToken?.displayName === 'USK' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'USDC' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'TIA' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'STRDST' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'KUJI' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'HUAHUA' ||
|
||||
@@ -638,18 +895,11 @@ export const OpenEditionMinterCreator = ({
|
||||
}
|
||||
|
||||
const payload: OpenEditionFactoryDispatchExecuteArgs = {
|
||||
contract: collectionDetails?.updatable ? updatableFactoryAddressForSelectedDenom : factoryAddressForSelectedDenom,
|
||||
contract: openEditionFactoryAddress as string,
|
||||
messages: openEditionFactoryMessages,
|
||||
txSigner: wallet.address || '',
|
||||
msg,
|
||||
funds: [
|
||||
coin(
|
||||
collectionDetails?.updatable
|
||||
? (openEditionMinterUpdatableCreationFee as string)
|
||||
: (openEditionMinterCreationFee as string),
|
||||
'ustars',
|
||||
),
|
||||
],
|
||||
funds: [coin(openEditionMinterCreationFee as string, 'ustars')],
|
||||
updatable: collectionDetails?.updatable,
|
||||
}
|
||||
await openEditionFactoryDispatchExecute(payload)
|
||||
@@ -680,16 +930,24 @@ export const OpenEditionMinterCreator = ({
|
||||
metadataStorageMethod,
|
||||
openEditionMinterContractAddress,
|
||||
sg721ContractAddress,
|
||||
whitelistContractAddress,
|
||||
transactionHash,
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [metadataStorageMethod, openEditionMinterContractAddress, sg721ContractAddress, transactionHash])
|
||||
}, [
|
||||
metadataStorageMethod,
|
||||
openEditionMinterContractAddress,
|
||||
sg721ContractAddress,
|
||||
whitelistContractAddress,
|
||||
transactionHash,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
const data: OpenEditionMinterDetailsDataProps = {
|
||||
imageUploadDetails: imageUploadDetails ? imageUploadDetails : undefined,
|
||||
collectionDetails: collectionDetails ? collectionDetails : undefined,
|
||||
whitelistDetails: whitelistDetails ? whitelistDetails : undefined,
|
||||
royaltyDetails: royaltyDetails ? royaltyDetails : undefined,
|
||||
onChainMetadataInputDetails: onChainMetadataInputDetails ? onChainMetadataInputDetails : undefined,
|
||||
offChainMetadataUploadDetails: offChainMetadataUploadDetails ? offChainMetadataUploadDetails : undefined,
|
||||
@@ -699,12 +957,14 @@ export const OpenEditionMinterCreator = ({
|
||||
coverImageUrl,
|
||||
tokenUri,
|
||||
tokenImageUri,
|
||||
isRefreshed,
|
||||
}
|
||||
onDetailsChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
imageUploadDetails,
|
||||
collectionDetails,
|
||||
whitelistDetails,
|
||||
royaltyDetails,
|
||||
onChainMetadataInputDetails,
|
||||
offChainMetadataUploadDetails,
|
||||
@@ -714,6 +974,7 @@ export const OpenEditionMinterCreator = ({
|
||||
coverImageUrl,
|
||||
tokenUri,
|
||||
tokenImageUri,
|
||||
isRefreshed,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -722,6 +983,40 @@ export const OpenEditionMinterCreator = ({
|
||||
}
|
||||
}, [importedOpenEditionMinterDetails])
|
||||
|
||||
const fetchWhitelistConfig = async (contractAddress: string | undefined) => {
|
||||
if (contractAddress === '' || !whitelistDetails) return
|
||||
const contract = whitelistContract?.use(contractAddress)
|
||||
|
||||
await contract
|
||||
?.config()
|
||||
.then((config) => {
|
||||
if (!config) {
|
||||
whitelistDetails.whitelistType = 'standard'
|
||||
return
|
||||
}
|
||||
|
||||
if (JSON.stringify(config).includes('whale_cap')) whitelistDetails.whitelistType = 'flex'
|
||||
else if (!JSON.stringify(config).includes('member_limit') || config.member_limit === 0) {
|
||||
// whitelistDetails.whitelistType = 'merkletree'
|
||||
toast.error(
|
||||
'Whitelist Merkle Tree is not supported yet for open edition collections. Please use a standard or flexible whitelist contract.',
|
||||
)
|
||||
} else whitelistDetails.whitelistType = 'standard'
|
||||
setIsRefreshed(!isRefreshed)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('error', error)
|
||||
})
|
||||
}
|
||||
|
||||
const debouncedWhitelistContractAddress = useDebounce(whitelistDetails?.contractAddress, 300)
|
||||
|
||||
useEffect(() => {
|
||||
if (whitelistDetails?.whitelistState === 'existing' && debouncedWhitelistContractAddress !== '') {
|
||||
void fetchWhitelistConfig(debouncedWhitelistContractAddress)
|
||||
}
|
||||
}, [whitelistDetails?.whitelistState, debouncedWhitelistContractAddress])
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* TODO: Cancel once we're able to index on-chain metadata */}
|
||||
@@ -810,16 +1105,23 @@ export const OpenEditionMinterCreator = ({
|
||||
/>
|
||||
<MintingDetails
|
||||
importedMintingDetails={importedOpenEditionMinterDetails?.mintingDetails}
|
||||
minimumMintPrice={
|
||||
collectionDetails?.updatable
|
||||
? Number(minimumUpdatableMintPrice) / 1000000
|
||||
: Number(minimumMintPrice) / 1000000
|
||||
}
|
||||
isPresale={whitelistDetails?.whitelistState === 'new'}
|
||||
minimumMintPrice={Number(minimumMintPrice) / 1000000}
|
||||
mintTokenFromFactory={mintTokenFromFactory}
|
||||
onChange={setMintingDetails}
|
||||
uploadMethod={offChainMetadataUploadDetails?.uploadMethod as UploadMethod}
|
||||
whitelistStartDate={whitelistDetails?.startTime}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="my-6 mx-10">
|
||||
<WhitelistDetails
|
||||
importedWhitelistDetails={importedOpenEditionMinterDetails?.whitelistDetails}
|
||||
mintingTokenFromFactory={mintTokenFromFactory}
|
||||
onChange={setWhitelistDetails}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="my-6">
|
||||
<RoyaltyDetails
|
||||
importedRoyaltyDetails={importedOpenEditionMinterDetails?.royaltyDetails}
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import { Button } from 'components/Button'
|
||||
import { FormControl } from 'components/FormControl'
|
||||
import { FormGroup } from 'components/FormGroup'
|
||||
import { AddressList } from 'components/forms/AddressList'
|
||||
import { useAddressListState } from 'components/forms/AddressList.hooks'
|
||||
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||
import { InputDateTime } from 'components/InputDateTime'
|
||||
import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload'
|
||||
import { WhitelistFlexUpload } from 'components/WhitelistFlexUpload'
|
||||
import type { TokenInfo } from 'config/token'
|
||||
import { useGlobalSettings } from 'contexts/globalSettings'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { isValidAddress } from 'utils/isValidAddress'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
import { Conditional } from '../Conditional'
|
||||
import { AddressInput, NumberInput } from '../forms/FormInput'
|
||||
import { JsonPreview } from '../JsonPreview'
|
||||
import { WhitelistUpload } from '../WhitelistUpload'
|
||||
|
||||
interface WhitelistDetailsProps {
|
||||
onChange: (data: WhitelistDetailsDataProps) => void
|
||||
mintingTokenFromFactory?: TokenInfo
|
||||
importedWhitelistDetails?: WhitelistDetailsDataProps
|
||||
}
|
||||
|
||||
export interface WhitelistDetailsDataProps {
|
||||
whitelistState: WhitelistState
|
||||
whitelistType: WhitelistType
|
||||
contractAddress?: string
|
||||
members?: string[] | WhitelistFlexMember[]
|
||||
unitPrice?: string
|
||||
startTime?: string
|
||||
endTime?: string
|
||||
perAddressLimit?: number
|
||||
memberLimit?: number
|
||||
admins?: string[]
|
||||
adminsMutable?: boolean
|
||||
}
|
||||
|
||||
type WhitelistState = 'none' | 'existing' | 'new'
|
||||
|
||||
export type WhitelistType = 'standard' | 'flex' | 'merkletree'
|
||||
|
||||
export const WhitelistDetails = ({
|
||||
onChange,
|
||||
mintingTokenFromFactory,
|
||||
importedWhitelistDetails,
|
||||
}: WhitelistDetailsProps) => {
|
||||
const wallet = useWallet()
|
||||
const { timezone } = useGlobalSettings()
|
||||
|
||||
const [whitelistState, setWhitelistState] = useState<WhitelistState>('none')
|
||||
const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
|
||||
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
|
||||
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
|
||||
const [whitelistStandardArray, setWhitelistStandardArray] = useState<string[]>([])
|
||||
const [whitelistFlexArray, setWhitelistFlexArray] = useState<WhitelistFlexMember[]>([])
|
||||
const [whitelistMerkleTreeArray, setWhitelistMerkleTreeArray] = useState<string[]>([])
|
||||
const [adminsMutable, setAdminsMutable] = useState<boolean>(true)
|
||||
|
||||
const whitelistAddressState = useInputState({
|
||||
id: 'whitelist-address',
|
||||
name: 'whitelistAddress',
|
||||
title: 'Whitelist Address',
|
||||
defaultValue: '',
|
||||
})
|
||||
|
||||
const unitPriceState = useNumberInputState({
|
||||
id: 'unit-price',
|
||||
name: 'unitPrice',
|
||||
title: 'Unit Price',
|
||||
subtitle: `Token price for whitelisted addresses \n (min. 0 ${
|
||||
mintingTokenFromFactory ? mintingTokenFromFactory.displayName : 'STARS'
|
||||
})`,
|
||||
placeholder: '25',
|
||||
})
|
||||
|
||||
const memberLimitState = useNumberInputState({
|
||||
id: 'member-limit',
|
||||
name: 'memberLimit',
|
||||
title: 'Member Limit',
|
||||
subtitle: 'Maximum number of whitelisted addresses',
|
||||
placeholder: '1000',
|
||||
})
|
||||
|
||||
const perAddressLimitState = useNumberInputState({
|
||||
id: 'per-address-limit',
|
||||
name: 'perAddressLimit',
|
||||
title: 'Per Address Limit',
|
||||
subtitle: 'Maximum number of tokens per whitelisted address',
|
||||
placeholder: '5',
|
||||
})
|
||||
|
||||
const addressListState = useAddressListState()
|
||||
|
||||
const whitelistFileOnChange = (data: string[]) => {
|
||||
if (whitelistType === 'standard') setWhitelistStandardArray(data)
|
||||
if (whitelistType === 'merkletree') setWhitelistMerkleTreeArray(data)
|
||||
}
|
||||
|
||||
const whitelistFlexFileOnChange = (whitelistData: WhitelistFlexMember[]) => {
|
||||
setWhitelistFlexArray(whitelistData)
|
||||
}
|
||||
|
||||
const downloadSampleWhitelistFlexFile = () => {
|
||||
const csvData =
|
||||
'address,mint_count\nstars153w5xhuqu3et29lgqk4dsynj6gjn96lr33wx4e,3\nstars1xkes5r2k8u3m3ayfpverlkcrq3k4jhdk8ws0uz,1\nstars1s8qx0zvz8yd6e4x0mqmqf7fr9vvfn622wtp3g3,2'
|
||||
const blob = new Blob([csvData], { type: 'text/csv' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', url)
|
||||
a.setAttribute('download', 'sample_whitelist_flex.csv')
|
||||
a.click()
|
||||
}
|
||||
|
||||
const downloadSampleWhitelistFile = () => {
|
||||
const txtData =
|
||||
'stars153w5xhuqu3et29lgqk4dsynj6gjn96lr33wx4e\nstars1xkes5r2k8u3m3ayfpverlkcrq3k4jhdk8ws0uz\nstars1s8qx0zvz8yd6e4x0mqmqf7fr9vvfn622wtp3g3'
|
||||
const blob = new Blob([txtData], { type: 'text/txt' })
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', url)
|
||||
a.setAttribute('download', 'sample_whitelist.txt')
|
||||
a.click()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!importedWhitelistDetails) {
|
||||
setWhitelistStandardArray([])
|
||||
setWhitelistFlexArray([])
|
||||
setWhitelistMerkleTreeArray([])
|
||||
}
|
||||
}, [whitelistType])
|
||||
|
||||
useEffect(() => {
|
||||
const data: WhitelistDetailsDataProps = {
|
||||
whitelistState,
|
||||
whitelistType,
|
||||
contractAddress: whitelistAddressState.value
|
||||
.toLowerCase()
|
||||
.replace(/,/g, '')
|
||||
.replace(/"/g, '')
|
||||
.replace(/'/g, '')
|
||||
.replace(/ /g, ''),
|
||||
members:
|
||||
whitelistType === 'standard'
|
||||
? whitelistStandardArray
|
||||
: whitelistType === 'merkletree'
|
||||
? whitelistMerkleTreeArray
|
||||
: whitelistFlexArray,
|
||||
unitPrice: unitPriceState.value
|
||||
? (Number(unitPriceState.value) * 1_000_000).toString()
|
||||
: unitPriceState.value === 0
|
||||
? '0'
|
||||
: undefined,
|
||||
startTime: startDate ? (startDate.getTime() * 1_000_000).toString() : '',
|
||||
endTime: endDate ? (endDate.getTime() * 1_000_000).toString() : '',
|
||||
perAddressLimit: perAddressLimitState.value,
|
||||
memberLimit: memberLimitState.value,
|
||||
admins: [
|
||||
...new Set(
|
||||
addressListState.values
|
||||
.map((a) => a.address.trim())
|
||||
.filter((address) => address !== '' && isValidAddress(address.trim()) && address.startsWith('stars')),
|
||||
),
|
||||
],
|
||||
adminsMutable,
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
whitelistAddressState.value,
|
||||
unitPriceState.value,
|
||||
memberLimitState.value,
|
||||
perAddressLimitState.value,
|
||||
startDate,
|
||||
endDate,
|
||||
whitelistStandardArray,
|
||||
whitelistFlexArray,
|
||||
whitelistMerkleTreeArray,
|
||||
whitelistState,
|
||||
whitelistType,
|
||||
addressListState.values,
|
||||
adminsMutable,
|
||||
])
|
||||
|
||||
// make the necessary changes with respect to imported whitelist details
|
||||
useEffect(() => {
|
||||
if (importedWhitelistDetails) {
|
||||
setWhitelistState(importedWhitelistDetails.whitelistState)
|
||||
setWhitelistType(importedWhitelistDetails.whitelistType)
|
||||
whitelistAddressState.onChange(
|
||||
importedWhitelistDetails.contractAddress ? importedWhitelistDetails.contractAddress : '',
|
||||
)
|
||||
unitPriceState.onChange(
|
||||
importedWhitelistDetails.unitPrice ? Number(importedWhitelistDetails.unitPrice) / 1000000 : 0,
|
||||
)
|
||||
memberLimitState.onChange(importedWhitelistDetails.memberLimit ? importedWhitelistDetails.memberLimit : 0)
|
||||
perAddressLimitState.onChange(
|
||||
importedWhitelistDetails.perAddressLimit ? importedWhitelistDetails.perAddressLimit : 0,
|
||||
)
|
||||
setStartDate(
|
||||
importedWhitelistDetails.startTime
|
||||
? new Date(Number(importedWhitelistDetails.startTime) / 1_000_000)
|
||||
: undefined,
|
||||
)
|
||||
setEndDate(
|
||||
importedWhitelistDetails.endTime ? new Date(Number(importedWhitelistDetails.endTime) / 1_000_000) : undefined,
|
||||
)
|
||||
setAdminsMutable(importedWhitelistDetails.adminsMutable ? importedWhitelistDetails.adminsMutable : true)
|
||||
importedWhitelistDetails.admins?.forEach((admin) => {
|
||||
addressListState.reset()
|
||||
addressListState.add({ address: admin })
|
||||
})
|
||||
if (importedWhitelistDetails.whitelistType === 'standard') {
|
||||
setWhitelistStandardArray([])
|
||||
importedWhitelistDetails.members?.forEach((member) => {
|
||||
setWhitelistStandardArray((standardArray) => [...standardArray, member as string])
|
||||
})
|
||||
} else if (importedWhitelistDetails.whitelistType === 'merkletree') {
|
||||
setWhitelistMerkleTreeArray([])
|
||||
// importedWhitelistDetails.members?.forEach((member) => {
|
||||
// setWhitelistMerkleTreeArray((merkleTreeArray) => [...merkleTreeArray, member as string])
|
||||
// })
|
||||
} else if (importedWhitelistDetails.whitelistType === 'flex') {
|
||||
setWhitelistFlexArray([])
|
||||
importedWhitelistDetails.members?.forEach((member) => {
|
||||
setWhitelistFlexArray((flexArray) => [
|
||||
...flexArray,
|
||||
{
|
||||
address: (member as WhitelistFlexMember).address,
|
||||
mint_count: (member as WhitelistFlexMember).mint_count,
|
||||
},
|
||||
])
|
||||
})
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [importedWhitelistDetails])
|
||||
|
||||
useEffect(() => {
|
||||
if (whitelistState === 'new' && wallet.address) {
|
||||
addressListState.reset()
|
||||
addressListState.add({ address: wallet.address })
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [whitelistState, wallet.address])
|
||||
|
||||
return (
|
||||
<div className="py-3 px-8 rounded border-2 border-white/20">
|
||||
<div className="flex justify-center">
|
||||
<div className="ml-4 font-bold form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistState === 'none'}
|
||||
className="peer sr-only"
|
||||
id="whitelistRadio1"
|
||||
name="whitelistRadioOptions1"
|
||||
onClick={() => {
|
||||
setWhitelistState('none')
|
||||
setWhitelistType('standard')
|
||||
}}
|
||||
type="radio"
|
||||
value="None"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="whitelistRadio1"
|
||||
>
|
||||
No whitelist
|
||||
</label>
|
||||
</div>
|
||||
<div className="ml-4 font-bold form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistState === 'existing'}
|
||||
className="peer sr-only"
|
||||
id="whitelistRadio2"
|
||||
name="whitelistRadioOptions2"
|
||||
onClick={() => {
|
||||
setWhitelistState('existing')
|
||||
}}
|
||||
type="radio"
|
||||
value="Existing"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="whitelistRadio2"
|
||||
>
|
||||
Existing whitelist
|
||||
</label>
|
||||
</div>
|
||||
<div className="ml-4 font-bold form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistState === 'new'}
|
||||
className="peer sr-only"
|
||||
id="whitelistRadio3"
|
||||
name="whitelistRadioOptions3"
|
||||
onClick={() => {
|
||||
setWhitelistState('new')
|
||||
}}
|
||||
type="radio"
|
||||
value="New"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="whitelistRadio3"
|
||||
>
|
||||
New whitelist
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Conditional test={whitelistState === 'existing'}>
|
||||
<AddressInput {...whitelistAddressState} className="pb-5" isRequired />
|
||||
</Conditional>
|
||||
|
||||
<Conditional test={whitelistState === 'new'}>
|
||||
<div className="flex justify-between mb-5 ml-6 max-w-[300px] text-lg font-bold">
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistType === 'standard'}
|
||||
className="peer sr-only"
|
||||
id="inlineRadio7"
|
||||
name="inlineRadioOptions7"
|
||||
onClick={() => {
|
||||
setWhitelistType('standard')
|
||||
}}
|
||||
type="radio"
|
||||
value="standard"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="inlineRadio7"
|
||||
>
|
||||
Standard Whitelist
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistType === 'flex'}
|
||||
className="peer sr-only"
|
||||
id="inlineRadio8"
|
||||
name="inlineRadioOptions8"
|
||||
onClick={() => {
|
||||
setWhitelistType('flex')
|
||||
}}
|
||||
type="radio"
|
||||
value="flex"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="inlineRadio8"
|
||||
>
|
||||
Whitelist Flex
|
||||
</label>
|
||||
</div>
|
||||
{/* <div className="form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistType === 'merkletree'}
|
||||
className="peer sr-only"
|
||||
id="inlineRadio9"
|
||||
name="inlineRadioOptions9"
|
||||
onClick={() => {
|
||||
setWhitelistType('merkletree')
|
||||
}}
|
||||
type="radio"
|
||||
value="merkletree"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="inlineRadio9"
|
||||
>
|
||||
Whitelist Merkle Tree
|
||||
</label>
|
||||
</div> */}
|
||||
</div>
|
||||
<div className="grid grid-cols-2">
|
||||
<FormGroup subtitle="Information about your minting settings" title="Whitelist Minting Details">
|
||||
<NumberInput isRequired {...unitPriceState} />
|
||||
<Conditional test={whitelistType !== 'merkletree'}>
|
||||
<NumberInput isRequired {...memberLimitState} />
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'standard' || whitelistType === 'merkletree'}>
|
||||
<NumberInput isRequired {...perAddressLimitState} />
|
||||
</Conditional>
|
||||
<FormControl
|
||||
htmlId="start-date"
|
||||
isRequired
|
||||
subtitle="Start time for minting tokens to whitelisted addresses"
|
||||
title={`Whitelist Start Time ${timezone === 'Local' ? '(local)' : '(UTC)'}`}
|
||||
>
|
||||
<InputDateTime
|
||||
minDate={
|
||||
timezone === 'Local' ? new Date() : new Date(Date.now() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
}
|
||||
onChange={(date) =>
|
||||
date
|
||||
? setStartDate(
|
||||
timezone === 'Local'
|
||||
? date
|
||||
: new Date(date.getTime() - new Date().getTimezoneOffset() * 60 * 1000),
|
||||
)
|
||||
: setStartDate(undefined)
|
||||
}
|
||||
value={
|
||||
timezone === 'Local'
|
||||
? startDate
|
||||
: startDate
|
||||
? new Date(startDate.getTime() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl
|
||||
htmlId="end-date"
|
||||
isRequired
|
||||
subtitle="Whitelist End Time dictates when public sales will start"
|
||||
title={`Whitelist End Time ${timezone === 'Local' ? '(local)' : '(UTC)'}`}
|
||||
>
|
||||
<InputDateTime
|
||||
minDate={
|
||||
timezone === 'Local' ? new Date() : new Date(Date.now() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
}
|
||||
onChange={(date) =>
|
||||
date
|
||||
? setEndDate(
|
||||
timezone === 'Local'
|
||||
? date
|
||||
: new Date(date.getTime() - new Date().getTimezoneOffset() * 60 * 1000),
|
||||
)
|
||||
: setEndDate(undefined)
|
||||
}
|
||||
value={
|
||||
timezone === 'Local'
|
||||
? endDate
|
||||
: endDate
|
||||
? new Date(endDate.getTime() + new Date().getTimezoneOffset() * 60 * 1000)
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormGroup>
|
||||
<div>
|
||||
<div className="mt-2 ml-3 w-[65%] form-control">
|
||||
<label className="justify-start cursor-pointer label">
|
||||
<span className="mr-4 font-bold">Mutable Administrator Addresses</span>
|
||||
<input
|
||||
checked={adminsMutable}
|
||||
className={`toggle ${adminsMutable ? `bg-stargaze` : `bg-gray-600`}`}
|
||||
onClick={() => setAdminsMutable(!adminsMutable)}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="my-4 ml-4">
|
||||
<AddressList
|
||||
entries={addressListState.entries}
|
||||
onAdd={addressListState.add}
|
||||
onChange={addressListState.update}
|
||||
onRemove={addressListState.remove}
|
||||
subtitle="The list of administrator addresses"
|
||||
title="Administrator Addresses"
|
||||
/>
|
||||
</div>
|
||||
<Conditional test={whitelistType === 'standard'}>
|
||||
<FormGroup
|
||||
subtitle={
|
||||
<div>
|
||||
<span>TXT file that contains the whitelisted addresses</span>
|
||||
<Button className="mt-2 text-sm text-white" onClick={downloadSampleWhitelistFile}>
|
||||
Download Sample File
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title="Whitelist File"
|
||||
>
|
||||
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||
</FormGroup>
|
||||
<Conditional test={whitelistStandardArray.length > 0}>
|
||||
<JsonPreview content={whitelistStandardArray} initialState title="File Contents" />
|
||||
</Conditional>
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'flex'}>
|
||||
<FormGroup
|
||||
subtitle={
|
||||
<div>
|
||||
<span>CSV file that contains the whitelisted addresses and corresponding mint counts</span>
|
||||
<Button className="mt-2 text-sm text-white" onClick={downloadSampleWhitelistFlexFile}>
|
||||
Download Sample File
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title="Whitelist File"
|
||||
>
|
||||
<WhitelistFlexUpload onChange={whitelistFlexFileOnChange} />
|
||||
</FormGroup>
|
||||
<Conditional test={whitelistFlexArray.length > 0}>
|
||||
<JsonPreview content={whitelistFlexArray} initialState={false} title="File Contents" />
|
||||
</Conditional>
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'merkletree'}>
|
||||
<FormGroup
|
||||
subtitle={
|
||||
<div>
|
||||
<span>TXT file that contains the whitelisted addresses</span>
|
||||
<Button className="mt-2 text-sm text-white" onClick={downloadSampleWhitelistFile}>
|
||||
Download Sample File
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title="Whitelist File"
|
||||
>
|
||||
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||
</FormGroup>
|
||||
<Conditional test={whitelistStandardArray.length > 0}>
|
||||
<JsonPreview content={whitelistStandardArray} initialState title="File Contents" />
|
||||
</Conditional>
|
||||
</Conditional>
|
||||
</div>
|
||||
</div>
|
||||
</Conditional>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import type { AssetList, Chain } from '@chain-registry/types'
|
||||
|
||||
export const fangTestnet: Chain = {
|
||||
$schema: '../../chain.schema.json',
|
||||
chain_name: 'stargazefangtestnet',
|
||||
status: 'live',
|
||||
network_type: 'testnet',
|
||||
website: 'https://stargaze.zone/',
|
||||
pretty_name: 'Fang Testnet',
|
||||
chain_id: 'fang-1',
|
||||
bech32_prefix: 'stars',
|
||||
daemon_name: 'starsd',
|
||||
node_home: '$HOME/.starsd',
|
||||
slip44: 118,
|
||||
fees: {
|
||||
fee_tokens: [
|
||||
{
|
||||
denom: 'ustars',
|
||||
low_gas_price: 0.3,
|
||||
average_gas_price: 0.4,
|
||||
high_gas_price: 0.5,
|
||||
},
|
||||
],
|
||||
},
|
||||
codebase: {
|
||||
git_repo: 'https://github.com/public-awesome/stargaze',
|
||||
recommended_version: 'v7.0.0',
|
||||
compatible_versions: ['v7.0.0'],
|
||||
cosmos_sdk_version: '0.45',
|
||||
consensus: {
|
||||
type: 'tendermint',
|
||||
version: '0.34',
|
||||
},
|
||||
cosmwasm_version: '0.28',
|
||||
cosmwasm_enabled: true,
|
||||
genesis: {
|
||||
genesis_url: 'https://github.com/public-awesome/testnets/blob/main/elgafar-1/genesis/genesis.tar.gz?raw=true',
|
||||
},
|
||||
versions: [
|
||||
{
|
||||
name: 'v7.0.0',
|
||||
recommended_version: 'v7.0.0',
|
||||
compatible_versions: ['v7.0.0'],
|
||||
cosmos_sdk_version: '0.45',
|
||||
consensus: {
|
||||
type: 'tendermint',
|
||||
version: '0.34',
|
||||
},
|
||||
cosmwasm_version: '0.28',
|
||||
cosmwasm_enabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
peers: {
|
||||
seeds: [],
|
||||
persistent_peers: [
|
||||
{
|
||||
id: 'e31886cba90a06e165b0df18cc5c8ae015ecd23e',
|
||||
address: '209.159.152.82:26656',
|
||||
provider: 'stargaze',
|
||||
},
|
||||
{
|
||||
id: 'de00d2d65594b672469ecd65826a94ec1be80b9f',
|
||||
address: '208.73.205.226:26656',
|
||||
provider: 'stargaze',
|
||||
},
|
||||
{
|
||||
id: '496ac0ba20188f70f41e0a814dfd4d9a617338f8',
|
||||
address: 'stargaze-testnet-seed.ibs.team:16652',
|
||||
provider: 'Inter Blockchain Services',
|
||||
},
|
||||
],
|
||||
},
|
||||
apis: {
|
||||
rpc: [
|
||||
{
|
||||
address: 'https://rpc.fang-1.stargaze-apis.com',
|
||||
provider: 'Stargaze Foundation',
|
||||
},
|
||||
],
|
||||
rest: [
|
||||
{
|
||||
address: 'https://rest.fang-1.stargaze-apis.com',
|
||||
provider: 'Stargaze Foundation',
|
||||
},
|
||||
],
|
||||
grpc: [
|
||||
{
|
||||
address: 'http://grpc-1.fang-1.stargaze-apis.com:26660',
|
||||
provider: 'Stargaze Foundation',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const fangAssetList: AssetList = {
|
||||
$schema: '../../assetlist.schema.json',
|
||||
chain_name: 'stargazefangtestnet',
|
||||
assets: [
|
||||
{
|
||||
description: 'The native token of Stargaze',
|
||||
denom_units: [
|
||||
{
|
||||
denom: 'ustars',
|
||||
exponent: 0,
|
||||
},
|
||||
{
|
||||
denom: 'stars',
|
||||
exponent: 6,
|
||||
},
|
||||
],
|
||||
base: 'ustars',
|
||||
name: 'Stargaze',
|
||||
display: 'stars',
|
||||
symbol: 'STARS',
|
||||
logo_URIs: {
|
||||
png: 'https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/stars.png',
|
||||
},
|
||||
coingecko_id: 'stargaze',
|
||||
images: [
|
||||
{
|
||||
png: 'https://raw.githubusercontent.com/cosmos/chain-registry/master/stargaze/images/stars.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
+295
-30
@@ -1,14 +1,24 @@
|
||||
import {
|
||||
FEATURED_IBC_TIA_FACTORY_ADDRESS,
|
||||
FEATURED_IBC_USDC_FACTORY_ADDRESS,
|
||||
FEATURED_VENDING_FACTORY_ADDRESS,
|
||||
FEATURED_VENDING_FACTORY_FLEX_ADDRESS,
|
||||
FEATURED_VENDING_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS,
|
||||
FEATURED_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
FEATURED_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS,
|
||||
OPEN_EDITION_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_FACTORY_FLEX_ADDRESS,
|
||||
OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_ATOM_FACTORY_FLEX_ADDRESS,
|
||||
OPEN_EDITION_IBC_CRBRUS_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_HUAHUA_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_KUJI_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_NBTC_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_TIA_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_TIA_FACTORY_FLEX_ADDRESS,
|
||||
OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_IBC_USDC_FACTORY_FLEX_ADDRESS,
|
||||
OPEN_EDITION_IBC_USK_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_NATIVE_BRNCH_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_NATIVE_STRDST_FACTORY_ADDRESS,
|
||||
@@ -16,10 +26,12 @@ import {
|
||||
OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_UPDATABLE_IBC_NBTC_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_UPDATABLE_IBC_TIA_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_UPDATABLE_IBC_USK_FACTORY_ADDRESS,
|
||||
VENDING_FACTORY_ADDRESS,
|
||||
VENDING_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
VENDING_FACTORY_UPDATABLE_ADDRESS,
|
||||
VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS,
|
||||
VENDING_IBC_ATOM_FACTORY_ADDRESS,
|
||||
@@ -28,14 +40,17 @@ import {
|
||||
VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_CRBRUS_FACTORY_ADDRESS,
|
||||
VENDING_IBC_CRBRUS_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_HUAHUA_FACTORY_ADDRESS,
|
||||
VENDING_IBC_HUAHUA_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_KUJI_FACTORY_ADDRESS,
|
||||
VENDING_IBC_KUJI_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_NBTC_FACTORY_ADDRESS,
|
||||
VENDING_IBC_NBTC_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_NBTC_UPDATABLE_FACTORY_ADDRESS,
|
||||
VENDING_IBC_NBTC_UPDATABLE_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_TIA_FACTORY_ADDRESS,
|
||||
VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
VENDING_IBC_TIA_UPDATABLE_FACTORY_ADDRESS,
|
||||
VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_USDC_FACTORY_ADDRESS,
|
||||
VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS,
|
||||
VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS,
|
||||
@@ -57,9 +72,10 @@ import {
|
||||
ibcAtom,
|
||||
ibcCrbrus,
|
||||
ibcFrnz,
|
||||
ibcHuahua,
|
||||
// ibcHuahua,
|
||||
ibcKuji,
|
||||
ibcNbtc,
|
||||
ibcTia,
|
||||
ibcUsdc,
|
||||
ibcUsk,
|
||||
nativeBrnch,
|
||||
@@ -73,6 +89,7 @@ export interface MinterInfo {
|
||||
supportedToken: TokenInfo
|
||||
updatable?: boolean
|
||||
flexible?: boolean
|
||||
merkleTree?: boolean
|
||||
featured?: boolean
|
||||
}
|
||||
|
||||
@@ -82,6 +99,7 @@ export const openEditionStarsMinter: MinterInfo = {
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionUpdatableStarsMinter: MinterInfo = {
|
||||
@@ -90,6 +108,7 @@ export const openEditionUpdatableStarsMinter: MinterInfo = {
|
||||
supportedToken: stars,
|
||||
updatable: true,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcAtomMinter: MinterInfo = {
|
||||
@@ -98,6 +117,7 @@ export const openEditionIbcAtomMinter: MinterInfo = {
|
||||
supportedToken: ibcAtom,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionUpdatableIbcAtomMinter: MinterInfo = {
|
||||
@@ -106,6 +126,7 @@ export const openEditionUpdatableIbcAtomMinter: MinterInfo = {
|
||||
supportedToken: ibcAtom,
|
||||
updatable: true,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcUsdcMinter: MinterInfo = {
|
||||
@@ -114,6 +135,16 @@ export const openEditionIbcUsdcMinter: MinterInfo = {
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcTiaMinter: MinterInfo = {
|
||||
id: 'open-edition-ibc-tia-minter',
|
||||
factoryAddress: OPEN_EDITION_IBC_TIA_FACTORY_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcNbtcMinter: MinterInfo = {
|
||||
@@ -122,6 +153,7 @@ export const openEditionIbcNbtcMinter: MinterInfo = {
|
||||
supportedToken: ibcNbtc,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionUpdatableIbcUsdcMinter: MinterInfo = {
|
||||
@@ -130,6 +162,16 @@ export const openEditionUpdatableIbcUsdcMinter: MinterInfo = {
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: true,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionUpdatableIbcTiaMinter: MinterInfo = {
|
||||
id: 'open-edition-updatable-ibc-tia-minter',
|
||||
factoryAddress: OPEN_EDITION_UPDATABLE_IBC_TIA_FACTORY_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: true,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionUpdatableIbcNbtcMinter: MinterInfo = {
|
||||
@@ -138,6 +180,7 @@ export const openEditionUpdatableIbcNbtcMinter: MinterInfo = {
|
||||
supportedToken: ibcNbtc,
|
||||
updatable: true,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcFrnzMinter: MinterInfo = {
|
||||
@@ -146,6 +189,7 @@ export const openEditionIbcFrnzMinter: MinterInfo = {
|
||||
supportedToken: ibcFrnz,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionUpdatableIbcFrnzMinter: MinterInfo = {
|
||||
@@ -154,6 +198,7 @@ export const openEditionUpdatableIbcFrnzMinter: MinterInfo = {
|
||||
supportedToken: ibcFrnz,
|
||||
updatable: true,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcUskMinter: MinterInfo = {
|
||||
@@ -162,6 +207,7 @@ export const openEditionIbcUskMinter: MinterInfo = {
|
||||
supportedToken: ibcUsk,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionUpdatableIbcUskMinter: MinterInfo = {
|
||||
@@ -170,6 +216,7 @@ export const openEditionUpdatableIbcUskMinter: MinterInfo = {
|
||||
supportedToken: ibcUsk,
|
||||
updatable: true,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcKujiMinter: MinterInfo = {
|
||||
@@ -178,15 +225,16 @@ export const openEditionIbcKujiMinter: MinterInfo = {
|
||||
supportedToken: ibcKuji,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionIbcHuahuaMinter: MinterInfo = {
|
||||
id: 'open-edition-ibc-huahua-minter',
|
||||
factoryAddress: OPEN_EDITION_IBC_HUAHUA_FACTORY_ADDRESS,
|
||||
supportedToken: ibcHuahua,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
}
|
||||
// export const openEditionIbcHuahuaMinter: MinterInfo = {
|
||||
// id: 'open-edition-ibc-huahua-minter',
|
||||
// factoryAddress: OPEN_EDITION_IBC_HUAHUA_FACTORY_ADDRESS,
|
||||
// supportedToken: ibcHuahua,
|
||||
// updatable: false,
|
||||
// featured: false,
|
||||
// }
|
||||
|
||||
export const openEditionIbcCrbrusMinter: MinterInfo = {
|
||||
id: 'open-edition-ibc-crbrus-minter',
|
||||
@@ -194,6 +242,7 @@ export const openEditionIbcCrbrusMinter: MinterInfo = {
|
||||
supportedToken: ibcCrbrus,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionNativeStrdstMinter: MinterInfo = {
|
||||
@@ -202,6 +251,7 @@ export const openEditionNativeStrdstMinter: MinterInfo = {
|
||||
supportedToken: nativeStardust,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionNativeBrnchMinter: MinterInfo = {
|
||||
@@ -210,6 +260,7 @@ export const openEditionNativeBrnchMinter: MinterInfo = {
|
||||
supportedToken: nativeBrnch,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: false,
|
||||
}
|
||||
|
||||
export const openEditionMinterList = [
|
||||
@@ -221,23 +272,69 @@ export const openEditionMinterList = [
|
||||
openEditionUpdatableIbcFrnzMinter,
|
||||
openEditionIbcUsdcMinter,
|
||||
openEditionUpdatableIbcUsdcMinter,
|
||||
openEditionIbcTiaMinter,
|
||||
openEditionUpdatableIbcTiaMinter,
|
||||
openEditionIbcNbtcMinter,
|
||||
openEditionUpdatableIbcNbtcMinter,
|
||||
openEditionIbcUskMinter,
|
||||
openEditionUpdatableIbcUskMinter,
|
||||
openEditionIbcKujiMinter,
|
||||
openEditionIbcHuahuaMinter,
|
||||
// openEditionIbcHuahuaMinter,
|
||||
openEditionIbcCrbrusMinter,
|
||||
openEditionNativeStrdstMinter,
|
||||
openEditionNativeBrnchMinter,
|
||||
]
|
||||
|
||||
export const flexibleOpenEditionStarsMinter: MinterInfo = {
|
||||
id: 'flexible-open-edition-stars-minter',
|
||||
factoryAddress: OPEN_EDITION_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: true,
|
||||
}
|
||||
|
||||
export const flexibleOpenEditionIbcAtomMinter: MinterInfo = {
|
||||
id: 'flexible-open-edition-ibc-atom-minter',
|
||||
factoryAddress: OPEN_EDITION_IBC_ATOM_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcAtom,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: true,
|
||||
}
|
||||
|
||||
export const flexibleOpenEditionIbcUsdcMinter: MinterInfo = {
|
||||
id: 'flexible-open-edition-ibc-usdc-minter',
|
||||
factoryAddress: OPEN_EDITION_IBC_USDC_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: true,
|
||||
}
|
||||
|
||||
export const flexibleOpenEditionIbcTiaMinter: MinterInfo = {
|
||||
id: 'flexible-open-edition-ibc-tia-minter',
|
||||
factoryAddress: OPEN_EDITION_IBC_TIA_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
featured: false,
|
||||
flexible: true,
|
||||
}
|
||||
|
||||
export const flexibleOpenEditionMinterList = [
|
||||
flexibleOpenEditionStarsMinter,
|
||||
flexibleOpenEditionIbcAtomMinter,
|
||||
flexibleOpenEditionIbcUsdcMinter,
|
||||
flexibleOpenEditionIbcTiaMinter,
|
||||
]
|
||||
|
||||
export const vendingStarsMinter: MinterInfo = {
|
||||
id: 'vending-stars-minter',
|
||||
factoryAddress: VENDING_FACTORY_ADDRESS,
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -247,6 +344,7 @@ export const vendingFeaturedStarsMinter: MinterInfo = {
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
@@ -256,6 +354,7 @@ export const vendingUpdatableStarsMinter: MinterInfo = {
|
||||
supportedToken: stars,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -265,6 +364,7 @@ export const vendingIbcAtomMinter: MinterInfo = {
|
||||
supportedToken: ibcAtom,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -274,6 +374,7 @@ export const vendingUpdatableIbcAtomMinter: MinterInfo = {
|
||||
supportedToken: ibcAtom,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -283,15 +384,47 @@ export const vendingIbcUsdcMinter: MinterInfo = {
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const vendingFeaturedIbcUsdcMinter: MinterInfo = {
|
||||
id: 'vending-featured-ibc-usdc-minter',
|
||||
factoryAddress: FEATURED_IBC_USDC_FACTORY_ADDRESS,
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
export const vendingIbcTiaMinter: MinterInfo = {
|
||||
id: 'vending-ibc-tia-minter',
|
||||
factoryAddress: VENDING_IBC_TIA_FACTORY_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const vendingFeaturedIbcTiaMinter: MinterInfo = {
|
||||
id: 'vending-featured-ibc-tia-minter',
|
||||
factoryAddress: FEATURED_IBC_TIA_FACTORY_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
export const vendingIbcNbtcMinter: MinterInfo = {
|
||||
id: 'vending-ibc-nbtc-minter',
|
||||
factoryAddress: VENDING_IBC_NBTC_FACTORY_ADDRESS,
|
||||
supportedToken: ibcNbtc,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -301,6 +434,17 @@ export const vendingUpdatableIbcUsdcMinter: MinterInfo = {
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const vendingUpdatableIbcTiaMinter: MinterInfo = {
|
||||
id: 'vending-updatable-ibc-tia-minter',
|
||||
factoryAddress: VENDING_IBC_TIA_UPDATABLE_FACTORY_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -310,6 +454,7 @@ export const vendingUpdatableIbcNbtcMinter: MinterInfo = {
|
||||
supportedToken: ibcNbtc,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -319,6 +464,7 @@ export const vendingIbcUskMinter: MinterInfo = {
|
||||
supportedToken: ibcUsk,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -328,6 +474,7 @@ export const vendingUpdatableIbcUskMinter: MinterInfo = {
|
||||
supportedToken: ibcUsk,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -337,17 +484,19 @@ export const vendingIbcKujiMinter: MinterInfo = {
|
||||
supportedToken: ibcKuji,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const vendingIbcHuahuaMinter: MinterInfo = {
|
||||
id: 'vending-ibc-huahua-minter',
|
||||
factoryAddress: VENDING_IBC_HUAHUA_FACTORY_ADDRESS,
|
||||
supportedToken: ibcHuahua,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
featured: false,
|
||||
}
|
||||
// export const vendingIbcHuahuaMinter: MinterInfo = {
|
||||
// id: 'vending-ibc-huahua-minter',
|
||||
// factoryAddress: VENDING_IBC_HUAHUA_FACTORY_ADDRESS,
|
||||
// supportedToken: ibcHuahua,
|
||||
// updatable: false,
|
||||
// flexible: false,
|
||||
// merkleTree: false,
|
||||
// featured: false,
|
||||
// }
|
||||
|
||||
export const vendingIbcCrbrusMinter: MinterInfo = {
|
||||
id: 'vending-ibc-crbrus-minter',
|
||||
@@ -355,6 +504,7 @@ export const vendingIbcCrbrusMinter: MinterInfo = {
|
||||
supportedToken: ibcCrbrus,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -364,6 +514,7 @@ export const vendingNativeStardustMinter: MinterInfo = {
|
||||
supportedToken: nativeStardust,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -373,6 +524,7 @@ export const vendingUpdatableNativeStardustMinter: MinterInfo = {
|
||||
supportedToken: nativeStardust,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -382,6 +534,7 @@ export const vendingNativeBrnchMinter: MinterInfo = {
|
||||
supportedToken: nativeBrnch,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -391,6 +544,7 @@ export const vendingUpdatableNativeBrnchMinter: MinterInfo = {
|
||||
supportedToken: nativeBrnch,
|
||||
updatable: true,
|
||||
flexible: false,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -401,13 +555,17 @@ export const vendingMinterList = [
|
||||
vendingIbcAtomMinter,
|
||||
vendingUpdatableIbcAtomMinter,
|
||||
vendingIbcUsdcMinter,
|
||||
vendingFeaturedIbcUsdcMinter,
|
||||
vendingUpdatableIbcUsdcMinter,
|
||||
vendingIbcTiaMinter,
|
||||
vendingFeaturedIbcTiaMinter,
|
||||
vendingUpdatableIbcTiaMinter,
|
||||
vendingIbcNbtcMinter,
|
||||
vendingUpdatableIbcNbtcMinter,
|
||||
vendingIbcUskMinter,
|
||||
vendingUpdatableIbcUskMinter,
|
||||
vendingIbcKujiMinter,
|
||||
vendingIbcHuahuaMinter,
|
||||
// vendingIbcHuahuaMinter,
|
||||
vendingIbcCrbrusMinter,
|
||||
vendingNativeStardustMinter,
|
||||
vendingUpdatableNativeStardustMinter,
|
||||
@@ -421,6 +579,7 @@ export const flexibleVendingStarsMinter: MinterInfo = {
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -430,6 +589,7 @@ export const flexibleFeaturedVendingStarsMinter: MinterInfo = {
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
@@ -439,6 +599,7 @@ export const flexibleVendingUpdatableStarsMinter: MinterInfo = {
|
||||
supportedToken: stars,
|
||||
updatable: true,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -448,6 +609,7 @@ export const flexibleVendingIbcAtomMinter: MinterInfo = {
|
||||
supportedToken: ibcAtom,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -457,6 +619,7 @@ export const flexibleVendingUpdatableIbcAtomMinter: MinterInfo = {
|
||||
supportedToken: ibcAtom,
|
||||
updatable: true,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -466,15 +629,47 @@ export const flexibleVendingIbcUsdcMinter: MinterInfo = {
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const flexibleFeaturedVendingIbcUsdcMinter: MinterInfo = {
|
||||
id: 'flexible-featured-vending-ibc-usdc-minter',
|
||||
factoryAddress: FEATURED_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
export const flexibleVendingIbcTiaMinter: MinterInfo = {
|
||||
id: 'flexible-vending-ibc-tia-minter',
|
||||
factoryAddress: VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const flexibleFeaturedVendingIbcTiaMinter: MinterInfo = {
|
||||
id: 'flexible-featured-vending-ibc-tia-minter',
|
||||
factoryAddress: FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
export const flexibleVendingIbcNbtcMinter: MinterInfo = {
|
||||
id: 'flexible-vending-ibc-nbtc-minter',
|
||||
factoryAddress: VENDING_IBC_NBTC_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcNbtc,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -484,6 +679,17 @@ export const flexibleVendingUpdatableIbcUsdcMinter: MinterInfo = {
|
||||
supportedToken: ibcUsdc,
|
||||
updatable: true,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const flexibleVendingUpdatableIbcTiaMinter: MinterInfo = {
|
||||
id: 'flexible-vending-updatable-ibc-tia-minter',
|
||||
factoryAddress: VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: true,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -493,6 +699,7 @@ export const flexibleVendingUpdatableIbcNbtcMinter: MinterInfo = {
|
||||
supportedToken: ibcNbtc,
|
||||
updatable: true,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -502,6 +709,7 @@ export const flexibleVendingIbcUskMinter: MinterInfo = {
|
||||
supportedToken: ibcUsk,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -511,6 +719,7 @@ export const flexibleVendingUpdatableIbcUskMinter: MinterInfo = {
|
||||
supportedToken: ibcUsk,
|
||||
updatable: true,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -520,17 +729,19 @@ export const flexibleVendingIbcKujiMinter: MinterInfo = {
|
||||
supportedToken: ibcKuji,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const flexibleVendingIbcHuahuaMinter: MinterInfo = {
|
||||
id: 'flexible-vending-ibc-huahua-minter',
|
||||
factoryAddress: VENDING_IBC_HUAHUA_FACTORY_FLEX_ADDRESS,
|
||||
supportedToken: ibcHuahua,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
featured: false,
|
||||
}
|
||||
// export const flexibleVendingIbcHuahuaMinter: MinterInfo = {
|
||||
// id: 'flexible-vending-ibc-huahua-minter',
|
||||
// factoryAddress: VENDING_IBC_HUAHUA_FACTORY_FLEX_ADDRESS,
|
||||
// supportedToken: ibcHuahua,
|
||||
// updatable: false,
|
||||
// flexible: true,
|
||||
// merkleTree: false,
|
||||
// featured: false,
|
||||
// }
|
||||
|
||||
export const flexibleVendingIbcCrbrusMinter: MinterInfo = {
|
||||
id: 'flexible-vending-ibc-crbrus-minter',
|
||||
@@ -538,6 +749,7 @@ export const flexibleVendingIbcCrbrusMinter: MinterInfo = {
|
||||
supportedToken: ibcCrbrus,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -547,6 +759,7 @@ export const flexibleVendingStrdstMinter: MinterInfo = {
|
||||
supportedToken: nativeStardust,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -556,6 +769,7 @@ export const flexibleVendingBrnchMinter: MinterInfo = {
|
||||
supportedToken: nativeBrnch,
|
||||
updatable: false,
|
||||
flexible: true,
|
||||
merkleTree: false,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
@@ -566,14 +780,65 @@ export const flexibleVendingMinterList = [
|
||||
flexibleVendingIbcAtomMinter,
|
||||
flexibleVendingUpdatableIbcAtomMinter,
|
||||
flexibleVendingIbcUsdcMinter,
|
||||
flexibleFeaturedVendingIbcUsdcMinter,
|
||||
flexibleVendingUpdatableIbcUsdcMinter,
|
||||
flexibleVendingIbcTiaMinter,
|
||||
flexibleFeaturedVendingIbcTiaMinter,
|
||||
flexibleVendingUpdatableIbcTiaMinter,
|
||||
flexibleVendingIbcNbtcMinter,
|
||||
flexibleVendingUpdatableIbcNbtcMinter,
|
||||
flexibleVendingIbcUskMinter,
|
||||
flexibleVendingUpdatableIbcUskMinter,
|
||||
flexibleVendingIbcKujiMinter,
|
||||
flexibleVendingIbcHuahuaMinter,
|
||||
// flexibleVendingIbcHuahuaMinter,
|
||||
flexibleVendingIbcCrbrusMinter,
|
||||
flexibleVendingStrdstMinter,
|
||||
flexibleVendingBrnchMinter,
|
||||
]
|
||||
|
||||
export const merkleTreeVendingStarsMinter: MinterInfo = {
|
||||
id: 'merkletree-vending-stars-minter',
|
||||
factoryAddress: VENDING_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: true,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const merkleTreeVendingFeaturedStarsMinter: MinterInfo = {
|
||||
id: 'merkletree-vending-featured-stars-minter',
|
||||
factoryAddress: FEATURED_VENDING_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
supportedToken: stars,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: true,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
export const merkleTreeVendingIbcTiaMinter: MinterInfo = {
|
||||
id: 'merkletree-vending-ibc-tia-minter',
|
||||
factoryAddress: VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: true,
|
||||
featured: false,
|
||||
}
|
||||
|
||||
export const merkleTreeVendingFeaturedIbcTiaMinter: MinterInfo = {
|
||||
id: 'merkletree-vending-featured-ibc-tia-minter',
|
||||
factoryAddress: FEATURED_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS,
|
||||
supportedToken: ibcTia,
|
||||
updatable: false,
|
||||
flexible: false,
|
||||
merkleTree: true,
|
||||
featured: true,
|
||||
}
|
||||
|
||||
export const merkleTreeVendingMinterList = [
|
||||
merkleTreeVendingStarsMinter,
|
||||
merkleTreeVendingIbcTiaMinter,
|
||||
merkleTreeVendingFeaturedStarsMinter,
|
||||
merkleTreeVendingFeaturedIbcTiaMinter,
|
||||
]
|
||||
|
||||
@@ -19,6 +19,25 @@ export const mainnetConfig: AppConfig = {
|
||||
},
|
||||
}
|
||||
|
||||
export const fangTestnetConfig: AppConfig = {
|
||||
chainId: 'fang-1',
|
||||
chainName: 'fang-1',
|
||||
addressPrefix: 'stars',
|
||||
rpcUrl: 'https://rpc.fang-1.stargaze-apis.com/',
|
||||
httpUrl: 'https://rest.fang-1.stargaze-apis.com/',
|
||||
feeToken: 'ustars',
|
||||
stakingToken: 'ustars',
|
||||
coinMap: {
|
||||
ustars: { denom: 'STARS', fractionalDigits: 6 },
|
||||
},
|
||||
gasPrice: 0.025,
|
||||
fees: {
|
||||
upload: 1500000,
|
||||
init: 500000,
|
||||
exec: 200000,
|
||||
},
|
||||
}
|
||||
|
||||
export const testnetConfig: AppConfig = {
|
||||
chainId: 'elgafar-1',
|
||||
chainName: 'elgafar-1',
|
||||
@@ -40,5 +59,6 @@ export const testnetConfig: AppConfig = {
|
||||
|
||||
export const getConfig = (network: string): AppConfig => {
|
||||
if (network === 'mainnet') return mainnetConfig
|
||||
else if (network === 'fang-testnet') return fangTestnetConfig
|
||||
return testnetConfig
|
||||
}
|
||||
|
||||
+21
-10
@@ -69,15 +69,15 @@ export const ibcNbtc: TokenInfo = {
|
||||
decimalPlaces: 6,
|
||||
}
|
||||
|
||||
export const ibcHuahua: TokenInfo = {
|
||||
id: 'ibc-huahua',
|
||||
denom:
|
||||
NETWORK === 'mainnet'
|
||||
? 'ibc/CAD8A9F306CAAC55731C66930D6BEE539856DD12E59061C965E44D82AA26A0E7'
|
||||
: 'factory/stars153w5xhuqu3et29lgqk4dsynj6gjn96lr33wx4e/uhuahua',
|
||||
displayName: 'HUAHUA',
|
||||
decimalPlaces: 6,
|
||||
}
|
||||
// export const ibcHuahua: TokenInfo = {
|
||||
// id: 'ibc-huahua',
|
||||
// denom:
|
||||
// NETWORK === 'mainnet'
|
||||
// ? 'ibc/CAD8A9F306CAAC55731C66930D6BEE539856DD12E59061C965E44D82AA26A0E7'
|
||||
// : 'factory/stars153w5xhuqu3et29lgqk4dsynj6gjn96lr33wx4e/uhuahua',
|
||||
// displayName: 'HUAHUA',
|
||||
// decimalPlaces: 6,
|
||||
// }
|
||||
|
||||
export const ibcCrbrus: TokenInfo = {
|
||||
id: 'ibc-crbrus',
|
||||
@@ -89,6 +89,16 @@ export const ibcCrbrus: TokenInfo = {
|
||||
decimalPlaces: 6,
|
||||
}
|
||||
|
||||
export const ibcTia: TokenInfo = {
|
||||
id: 'ibc-tia',
|
||||
denom:
|
||||
NETWORK === 'mainnet'
|
||||
? 'ibc/14D1406D84227FDF4B055EA5CB2298095BBCA3F3BC3EF583AE6DF36F0FB179C8'
|
||||
: 'factory/stars153w5xhuqu3et29lgqk4dsynj6gjn96lr33wx4e/utia',
|
||||
displayName: 'TIA',
|
||||
decimalPlaces: 6,
|
||||
}
|
||||
|
||||
export const nativeStardust: TokenInfo = {
|
||||
id: 'native-strdst',
|
||||
denom:
|
||||
@@ -117,8 +127,9 @@ export const tokensList = [
|
||||
ibcFrnz,
|
||||
ibcNbtc,
|
||||
ibcKuji,
|
||||
ibcHuahua,
|
||||
// ibcHuahua,
|
||||
ibcCrbrus,
|
||||
ibcTia,
|
||||
nativeStardust,
|
||||
nativeBrnch,
|
||||
]
|
||||
|
||||
+19
-1
@@ -16,6 +16,7 @@ import type { UseVendingMinterContractProps } from 'contracts/vendingMinter'
|
||||
import { useVendingMinterContract } from 'contracts/vendingMinter'
|
||||
import type { UseWhiteListContractProps } from 'contracts/whitelist'
|
||||
import { useWhiteListContract } from 'contracts/whitelist'
|
||||
import { type UseWhiteListMerkleTreeContractProps, useWhiteListMerkleTreeContract } from 'contracts/whitelistMerkleTree'
|
||||
import type { ReactNode, VFC } from 'react'
|
||||
import { Fragment, useEffect } from 'react'
|
||||
import { create } from 'zustand'
|
||||
@@ -32,6 +33,7 @@ export interface ContractsStore {
|
||||
baseMinter: UseBaseMinterContractProps | null
|
||||
openEditionMinter: UseOpenEditionMinterContractProps | null
|
||||
whitelist: UseWhiteListContractProps | null
|
||||
whitelistMerkleTree: UseWhiteListMerkleTreeContractProps | null
|
||||
vendingFactory: UseVendingFactoryContractProps | null
|
||||
baseFactory: UseBaseFactoryContractProps | null
|
||||
openEditionFactory: UseOpenEditionFactoryContractProps | null
|
||||
@@ -49,6 +51,7 @@ export const defaultValues: ContractsStore = {
|
||||
baseMinter: null,
|
||||
openEditionMinter: null,
|
||||
whitelist: null,
|
||||
whitelistMerkleTree: null,
|
||||
vendingFactory: null,
|
||||
baseFactory: null,
|
||||
openEditionFactory: null,
|
||||
@@ -83,6 +86,7 @@ const ContractsSubscription: VFC = () => {
|
||||
const baseMinter = useBaseMinterContract()
|
||||
const openEditionMinter = useOpenEditionMinterContract()
|
||||
const whitelist = useWhiteListContract()
|
||||
const whitelistMerkleTree = useWhiteListMerkleTreeContract()
|
||||
const vendingFactory = useVendingFactoryContract()
|
||||
const baseFactory = useBaseFactoryContract()
|
||||
const openEditionFactory = useOpenEditionFactoryContract()
|
||||
@@ -97,6 +101,7 @@ const ContractsSubscription: VFC = () => {
|
||||
baseMinter,
|
||||
openEditionMinter,
|
||||
whitelist,
|
||||
whitelistMerkleTree,
|
||||
vendingFactory,
|
||||
baseFactory,
|
||||
openEditionFactory,
|
||||
@@ -104,7 +109,20 @@ const ContractsSubscription: VFC = () => {
|
||||
splits,
|
||||
royaltyRegistry,
|
||||
})
|
||||
}, [sg721, vendingMinter, baseMinter, whitelist, vendingFactory, baseFactory, badgeHub, splits, royaltyRegistry])
|
||||
}, [
|
||||
sg721,
|
||||
vendingMinter,
|
||||
baseMinter,
|
||||
whitelist,
|
||||
whitelistMerkleTree,
|
||||
vendingFactory,
|
||||
baseFactory,
|
||||
badgeHub,
|
||||
splits,
|
||||
royaltyRegistry,
|
||||
openEditionMinter,
|
||||
openEditionFactory,
|
||||
])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ export const baseFactory = (client: SigningCosmWasmClient, txSigner: string): Ba
|
||||
)
|
||||
|
||||
return {
|
||||
baseMinterAddress: result.logs[0].events[5].attributes[0].value,
|
||||
sg721Address: result.logs[0].events[5].attributes[2].value,
|
||||
baseMinterAddress: result.logs[0].events[16].attributes[0].value,
|
||||
sg721Address: result.logs[0].events[18].attributes[0].value,
|
||||
transactionHash: result.transactionHash,
|
||||
logs: result.logs,
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ export const openEditionFactory = (client: SigningCosmWasmClient, txSigner: stri
|
||||
const result = await client.execute(senderAddress, contractAddress, msg, 'auto', '', funds)
|
||||
|
||||
return {
|
||||
openEditionMinterAddress: result.logs[0].events[5].attributes[0].value,
|
||||
sg721Address: result.logs[0].events[5].attributes[2].value,
|
||||
openEditionMinterAddress: result.logs[0].events[16].attributes[0].value,
|
||||
sg721Address: result.logs[0].events[18].attributes[0].value,
|
||||
transactionHash: result.transactionHash,
|
||||
logs: result.logs,
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface CollectionInfo {
|
||||
external_link?: string
|
||||
explicit_content?: boolean
|
||||
royalty_info?: RoyaltyInfo | undefined
|
||||
creator?: string
|
||||
}
|
||||
|
||||
export interface SG721Instance {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
|
||||
import type { StdFee } from '@cosmjs/amino'
|
||||
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import type { Coin } from '@cosmjs/proto-signing'
|
||||
import { type Coin, coins } from '@cosmjs/proto-signing'
|
||||
import type { logs } from '@cosmjs/stargate'
|
||||
|
||||
export interface CreateVendingMinterResponse {
|
||||
@@ -52,6 +53,11 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string):
|
||||
const use = (contractAddress: string): VendingFactoryInstance => {
|
||||
//Query
|
||||
|
||||
const defaultFee: StdFee = {
|
||||
amount: coins('100000', 'ustars'),
|
||||
gas: '100000',
|
||||
}
|
||||
|
||||
//Execute
|
||||
const createVendingMinter = async (
|
||||
senderAddress: string,
|
||||
@@ -63,8 +69,8 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string):
|
||||
const result = await client.execute(senderAddress, contractAddress, msg, 'auto', '', funds)
|
||||
|
||||
return {
|
||||
vendingMinterAddress: result.logs[0].events[5].attributes[0].value,
|
||||
sg721Address: result.logs[0].events[5].attributes[2].value,
|
||||
vendingMinterAddress: result.logs[0].events[16].attributes[0].value,
|
||||
sg721Address: result.logs[0].events[18].attributes[0].value,
|
||||
transactionHash: result.transactionHash,
|
||||
logs: result.logs,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { type Coin, coin } from '@cosmjs/proto-signing'
|
||||
import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload'
|
||||
|
||||
export interface InstantiateResponse {
|
||||
readonly contractAddress: string
|
||||
readonly transactionHash: string
|
||||
}
|
||||
|
||||
export interface ConfigResponse {
|
||||
readonly per_address_limit: number
|
||||
readonly start_time: string
|
||||
readonly end_time: string
|
||||
readonly mint_price: Coin
|
||||
readonly is_active: boolean
|
||||
}
|
||||
export interface WhiteListMerkleTreeInstance {
|
||||
readonly contractAddress: string
|
||||
//Query
|
||||
hasStarted: () => Promise<boolean>
|
||||
hasEnded: () => Promise<boolean>
|
||||
isActive: () => Promise<boolean>
|
||||
hasMember: (member: string, proof_hashes: string[]) => Promise<boolean>
|
||||
adminList: () => Promise<string[]>
|
||||
config: () => Promise<ConfigResponse>
|
||||
canExecute: (sender: string, msg: string) => Promise<boolean>
|
||||
merkleRoot: () => Promise<string>
|
||||
merkleTreeUri: () => Promise<string>
|
||||
|
||||
//Execute
|
||||
updateStartTime: (startTime: string) => Promise<string>
|
||||
updateEndTime: (endTime: string) => Promise<string>
|
||||
addMembers: (memberList: string[] | WhitelistFlexMember[]) => Promise<string>
|
||||
removeMembers: (memberList: string[]) => Promise<string>
|
||||
// updatePerAddressLimit: (limit: number) => Promise<string>
|
||||
updateAdmins: (admins: string[]) => Promise<string>
|
||||
freeze: () => Promise<string>
|
||||
}
|
||||
|
||||
export interface WhiteListMerkleTreeMessages {
|
||||
updateStartTime: (startTime: string) => UpdateStartTimeMessage
|
||||
updateEndTime: (endTime: string) => UpdateEndTimeMessage
|
||||
addMembers: (memberList: string[] | WhitelistFlexMember[]) => AddMembersMessage
|
||||
removeMembers: (memberList: string[]) => RemoveMembersMessage
|
||||
// updatePerAddressLimit: (limit: number) => UpdatePerAddressLimitMessage
|
||||
updateAdmins: (admins: string[]) => UpdateAdminsMessage
|
||||
freeze: () => FreezeMessage
|
||||
}
|
||||
|
||||
export interface UpdateStartTimeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_start_time: string
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface UpdateEndTimeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_end_time: string
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface UpdateAdminsMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_admins: { admins: string[] }
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface FreezeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: { freeze: Record<string, never> }
|
||||
funds: Coin[]
|
||||
}
|
||||
export interface AddMembersMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
add_members: { to_add: string[] | WhitelistFlexMember[] }
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface RemoveMembersMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
remove_members: { to_remove: string[] }
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
// export interface UpdatePerAddressLimitMessage {
|
||||
// sender: string
|
||||
|
||||
// contract: string
|
||||
// msg: {
|
||||
// update_per_address_limit: number
|
||||
// }
|
||||
// funds: Coin[]
|
||||
// }
|
||||
|
||||
export interface WhiteListMerkleTreeContract {
|
||||
instantiate: (
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
) => Promise<InstantiateResponse>
|
||||
|
||||
use: (contractAddress: string) => WhiteListMerkleTreeInstance
|
||||
|
||||
messages: (contractAddress: string) => WhiteListMerkleTreeMessages
|
||||
}
|
||||
|
||||
export const WhiteListMerkleTree = (client: SigningCosmWasmClient, txSigner: string): WhiteListMerkleTreeContract => {
|
||||
const use = (contractAddress: string): WhiteListMerkleTreeInstance => {
|
||||
///QUERY START
|
||||
const hasStarted = async (): Promise<boolean> => {
|
||||
return client.queryContractSmart(contractAddress, { has_started: {} })
|
||||
}
|
||||
|
||||
const hasEnded = async (): Promise<boolean> => {
|
||||
return client.queryContractSmart(contractAddress, { has_ended: {} })
|
||||
}
|
||||
|
||||
const isActive = async (): Promise<boolean> => {
|
||||
return client.queryContractSmart(contractAddress, { is_active: {} })
|
||||
}
|
||||
|
||||
const hasMember = async (member: string, proofHashes: string[]): Promise<boolean> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
has_member: { member, proof_hashes: proofHashes },
|
||||
})
|
||||
}
|
||||
|
||||
const adminList = async (): Promise<string[]> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
admin_list: {},
|
||||
})
|
||||
}
|
||||
|
||||
const config = async (): Promise<ConfigResponse> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
config: {},
|
||||
})
|
||||
}
|
||||
|
||||
const merkleRoot = async (): Promise<string> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
merkle_root: {},
|
||||
})
|
||||
}
|
||||
|
||||
const merkleTreeUri = async (): Promise<string> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
merkle_tree_u_r_i: {},
|
||||
})
|
||||
}
|
||||
|
||||
const canExecute = async (sender: string, msg: string): Promise<boolean> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
can_execute: { sender, msg },
|
||||
})
|
||||
}
|
||||
/// QUERY END
|
||||
/// EXECUTE START
|
||||
const updateStartTime = async (startTime: string): Promise<string> => {
|
||||
const res = await client.execute(txSigner, contractAddress, { update_start_time: startTime }, 'auto')
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const updateEndTime = async (endTime: string): Promise<string> => {
|
||||
const res = await client.execute(txSigner, contractAddress, { update_end_time: endTime }, 'auto')
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const addMembers = async (memberList: string[] | WhitelistFlexMember[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
add_members: {
|
||||
to_add: memberList,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const updateAdmins = async (admins: string[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
update_admins: {
|
||||
admins,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const freeze = async (): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
freeze: {},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const removeMembers = async (memberList: string[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
remove_members: {
|
||||
to_remove: memberList,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
// const updatePerAddressLimit = async (limit: number): Promise<string> => {
|
||||
// const res = await client.execute(txSigner, contractAddress, { update_per_address_limit: limit }, 'auto')
|
||||
// return res.transactionHash
|
||||
// }
|
||||
|
||||
/// EXECUTE END
|
||||
|
||||
return {
|
||||
contractAddress,
|
||||
updateStartTime,
|
||||
updateEndTime,
|
||||
updateAdmins,
|
||||
freeze,
|
||||
addMembers,
|
||||
removeMembers,
|
||||
// updatePerAddressLimit,
|
||||
hasStarted,
|
||||
hasEnded,
|
||||
isActive,
|
||||
hasMember,
|
||||
adminList,
|
||||
config,
|
||||
merkleRoot,
|
||||
merkleTreeUri,
|
||||
canExecute,
|
||||
}
|
||||
}
|
||||
|
||||
const instantiate = async (
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
): Promise<InstantiateResponse> => {
|
||||
const result = await client.instantiate(txSigner, codeId, initMsg, label, 'auto', {
|
||||
admin,
|
||||
funds: [coin(1000000000, 'ustars')],
|
||||
})
|
||||
|
||||
return {
|
||||
contractAddress: result.contractAddress,
|
||||
transactionHash: result.transactionHash,
|
||||
}
|
||||
}
|
||||
|
||||
const messages = (contractAddress: string) => {
|
||||
const updateStartTime = (startTime: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_start_time: startTime,
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const updateEndTime = (endTime: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_end_time: endTime,
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const addMembers = (memberList: string[] | WhitelistFlexMember[]) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
add_members: { to_add: memberList },
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const updateAdmins = (admins: string[]) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_admins: { admins },
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const freeze = () => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
freeze: {},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const removeMembers = (memberList: string[]) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
remove_members: { to_remove: memberList },
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
// const updatePerAddressLimit = (limit: number) => {
|
||||
// return {
|
||||
// sender: txSigner,
|
||||
// contract: contractAddress,
|
||||
// msg: {
|
||||
// update_per_address_limit: limit,
|
||||
// },
|
||||
// funds: [],
|
||||
// }
|
||||
// }
|
||||
|
||||
return {
|
||||
updateStartTime,
|
||||
updateEndTime,
|
||||
updateAdmins,
|
||||
addMembers,
|
||||
removeMembers,
|
||||
// updatePerAddressLimit,
|
||||
freeze,
|
||||
}
|
||||
}
|
||||
|
||||
return { use, instantiate, messages }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './contract'
|
||||
export * from './useContract'
|
||||
@@ -0,0 +1,144 @@
|
||||
import type { WhitelistFlexMember } from '../../../components/WhitelistFlexUpload'
|
||||
import type { WhiteListMerkleTreeInstance } from '../index'
|
||||
import { useWhiteListMerkleTreeContract } from '../index'
|
||||
|
||||
export type ExecuteType = typeof EXECUTE_TYPES[number]
|
||||
|
||||
export const EXECUTE_TYPES = [
|
||||
'update_start_time',
|
||||
'update_end_time',
|
||||
'update_admins',
|
||||
'add_members',
|
||||
'remove_members',
|
||||
// 'update_per_address_limit',
|
||||
'freeze',
|
||||
] as const
|
||||
|
||||
export interface ExecuteListItem {
|
||||
id: ExecuteType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const EXECUTE_LIST: ExecuteListItem[] = [
|
||||
{
|
||||
id: 'update_start_time',
|
||||
name: 'Update Start Time',
|
||||
description: `Update the start time of the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'update_end_time',
|
||||
name: 'Update End Time',
|
||||
description: `Update the end time of the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'update_admins',
|
||||
name: 'Update Admins',
|
||||
description: `Update the list of administrators for the whitelist`,
|
||||
},
|
||||
// {
|
||||
// id: 'add_members',
|
||||
// name: 'Add Members',
|
||||
// description: `Add members to the whitelist`,
|
||||
// },
|
||||
// {
|
||||
// id: 'remove_members',
|
||||
// name: 'Remove Members',
|
||||
// description: `Remove members from the whitelist`,
|
||||
// },
|
||||
// {
|
||||
// id: 'update_per_address_limit',
|
||||
// name: 'Update Per Address Limit',
|
||||
// description: `Update tokens per address limit`,
|
||||
// },
|
||||
{
|
||||
id: 'freeze',
|
||||
name: 'Freeze',
|
||||
description: `Freeze the current state of the contract admin list`,
|
||||
},
|
||||
]
|
||||
|
||||
export interface DispatchExecuteProps {
|
||||
type: ExecuteType
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
/** @see {@link WhiteListMerkleTreeInstance} */
|
||||
export interface DispatchExecuteArgs {
|
||||
contract: string
|
||||
messages?: WhiteListMerkleTreeInstance
|
||||
type: string | undefined
|
||||
timestamp: string
|
||||
members: string[] | WhitelistFlexMember[]
|
||||
limit: number
|
||||
admins: string[]
|
||||
}
|
||||
|
||||
export const dispatchExecute = async (args: DispatchExecuteArgs) => {
|
||||
const { messages } = args
|
||||
if (!messages) {
|
||||
throw new Error('cannot dispatch execute, messages is not defined')
|
||||
}
|
||||
switch (args.type) {
|
||||
case 'update_start_time': {
|
||||
return messages.updateStartTime(args.timestamp)
|
||||
}
|
||||
case 'update_end_time': {
|
||||
return messages.updateEndTime(args.timestamp)
|
||||
}
|
||||
case 'update_admins': {
|
||||
return messages.updateAdmins(args.admins)
|
||||
}
|
||||
case 'add_members': {
|
||||
return messages.addMembers(args.members)
|
||||
}
|
||||
case 'remove_members': {
|
||||
return messages.removeMembers(args.members as string[])
|
||||
}
|
||||
// case 'update_per_address_limit': {
|
||||
// return messages.updatePerAddressLimit(args.limit)
|
||||
// }
|
||||
case 'freeze': {
|
||||
return messages.freeze()
|
||||
}
|
||||
default: {
|
||||
throw new Error('unknown execute type')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const previewExecutePayload = (args: DispatchExecuteArgs) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const { messages } = useWhiteListMerkleTreeContract()
|
||||
const { contract } = args
|
||||
switch (args.type) {
|
||||
case 'update_start_time': {
|
||||
return messages(contract)?.updateStartTime(args.timestamp)
|
||||
}
|
||||
case 'update_end_time': {
|
||||
return messages(contract)?.updateEndTime(args.timestamp)
|
||||
}
|
||||
case 'update_admins': {
|
||||
return messages(contract)?.updateAdmins(args.admins)
|
||||
}
|
||||
case 'add_members': {
|
||||
return messages(contract)?.addMembers(args.members)
|
||||
}
|
||||
case 'remove_members': {
|
||||
return messages(contract)?.removeMembers(args.members as string[])
|
||||
}
|
||||
// case 'update_per_address_limit': {
|
||||
// return messages(contract)?.updatePerAddressLimit(args.limit)
|
||||
// }
|
||||
case 'freeze': {
|
||||
return messages(contract)?.freeze()
|
||||
}
|
||||
default: {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const isEitherType = <T extends ExecuteType>(type: unknown, arr: T[]): type is T => {
|
||||
return arr.some((val) => type === val)
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import type { WhiteListMerkleTreeInstance } from '../contract'
|
||||
|
||||
export type WhitelistMerkleTreeQueryType = typeof WHITELIST_MERKLE_TREE_QUERY_TYPES[number]
|
||||
|
||||
export const WHITELIST_MERKLE_TREE_QUERY_TYPES = [
|
||||
'has_started',
|
||||
'has_ended',
|
||||
'is_active',
|
||||
'admin_list',
|
||||
'has_member',
|
||||
'config',
|
||||
'merkle_root',
|
||||
'merkle_tree_uri',
|
||||
] as const
|
||||
|
||||
export interface QueryListItem {
|
||||
id: WhitelistMerkleTreeQueryType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const WHITELIST_MERKLE_TREE_QUERY_LIST: QueryListItem[] = [
|
||||
{ id: 'has_started', name: 'Has Started', description: 'Check if the whitelist minting has started' },
|
||||
{ id: 'has_ended', name: 'Has Ended', description: 'Check if the whitelist minting has ended' },
|
||||
{ id: 'is_active', name: 'Is Active', description: 'Check if the whitelist minting is active' },
|
||||
{ id: 'admin_list', name: 'Admin List', description: 'View the whitelist admin list' },
|
||||
{ id: 'has_member', name: 'Has Member', description: 'Check if a member is in the whitelist' },
|
||||
{ id: 'config', name: 'Config', description: 'View the whitelist configuration' },
|
||||
{ id: 'merkle_root', name: 'Merkle Root', description: 'View the whitelist merkle root' },
|
||||
{ id: 'merkle_tree_uri', name: 'Merkle Tree URI', description: 'View the whitelist merkle tree URI' },
|
||||
]
|
||||
|
||||
export interface DispatchQueryProps {
|
||||
messages: WhiteListMerkleTreeInstance | undefined
|
||||
type: WhitelistMerkleTreeQueryType
|
||||
address: string
|
||||
startAfter?: string
|
||||
limit?: number
|
||||
proofHashes?: string[]
|
||||
}
|
||||
|
||||
export const dispatchQuery = (props: DispatchQueryProps) => {
|
||||
const { messages, type, address, proofHashes } = props
|
||||
switch (type) {
|
||||
case 'has_started':
|
||||
return messages?.hasStarted()
|
||||
case 'has_ended':
|
||||
return messages?.hasEnded()
|
||||
case 'is_active':
|
||||
return messages?.isActive()
|
||||
case 'admin_list':
|
||||
return messages?.adminList()
|
||||
case 'has_member':
|
||||
return messages?.hasMember(address, proofHashes || [])
|
||||
case 'config':
|
||||
return messages?.config()
|
||||
case 'merkle_root':
|
||||
return messages?.merkleRoot()
|
||||
case 'merkle_tree_uri':
|
||||
return messages?.merkleTreeUri()
|
||||
|
||||
default: {
|
||||
throw new Error('unknown query type')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
import type {
|
||||
InstantiateResponse,
|
||||
WhiteListMerkleTreeContract,
|
||||
WhiteListMerkleTreeInstance,
|
||||
WhiteListMerkleTreeMessages,
|
||||
} from './contract'
|
||||
import { WhiteListMerkleTree as initContract } from './contract'
|
||||
|
||||
export interface UseWhiteListMerkleTreeContractProps {
|
||||
instantiate: (
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
) => Promise<InstantiateResponse>
|
||||
|
||||
use: (customAddress?: string) => WhiteListMerkleTreeInstance | undefined
|
||||
|
||||
updateContractAddress: (contractAddress: string) => void
|
||||
|
||||
messages: (contractAddress: string) => WhiteListMerkleTreeMessages | undefined
|
||||
}
|
||||
|
||||
export function useWhiteListMerkleTreeContract(): UseWhiteListMerkleTreeContractProps {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [address, setAddress] = useState<string>('')
|
||||
const [whiteListMerkleTree, setWhiteListMerkleTree] = useState<WhiteListMerkleTreeContract>()
|
||||
|
||||
useEffect(() => {
|
||||
setAddress(localStorage.getItem('contract_address') || '')
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!wallet.isWalletConnected) {
|
||||
return
|
||||
}
|
||||
|
||||
const load = async () => {
|
||||
const client = await wallet.getSigningCosmWasmClient()
|
||||
const contract = initContract(client, wallet.address || '')
|
||||
setWhiteListMerkleTree(contract)
|
||||
}
|
||||
|
||||
load().catch(console.error)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [wallet.isWalletConnected, wallet.address])
|
||||
|
||||
const updateContractAddress = (contractAddress: string) => {
|
||||
setAddress(contractAddress)
|
||||
}
|
||||
|
||||
const instantiate = useCallback(
|
||||
(codeId: number, initMsg: Record<string, unknown>, label: string, admin?: string): Promise<InstantiateResponse> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!whiteListMerkleTree) {
|
||||
reject(new Error('Contract is not initialized.'))
|
||||
return
|
||||
}
|
||||
whiteListMerkleTree.instantiate(codeId, initMsg, label, admin).then(resolve).catch(reject)
|
||||
})
|
||||
},
|
||||
[whiteListMerkleTree],
|
||||
)
|
||||
|
||||
const use = useCallback(
|
||||
(customAddress = ''): WhiteListMerkleTreeInstance | undefined => {
|
||||
return whiteListMerkleTree?.use(address || customAddress)
|
||||
},
|
||||
[whiteListMerkleTree, address],
|
||||
)
|
||||
|
||||
const messages = useCallback(
|
||||
(customAddress = ''): WhiteListMerkleTreeMessages | undefined => {
|
||||
return whiteListMerkleTree?.messages(address || customAddress)
|
||||
},
|
||||
[whiteListMerkleTree, address],
|
||||
)
|
||||
|
||||
return {
|
||||
instantiate,
|
||||
use,
|
||||
updateContractAddress,
|
||||
messages,
|
||||
}
|
||||
}
|
||||
@@ -22,18 +22,25 @@ declare namespace NodeJS {
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_SG721_UPDATABLE_CODE_ID: string
|
||||
readonly NEXT_PUBLIC_WHITELIST_CODE_ID: string
|
||||
readonly NEXT_PUBLIC_WHITELIST_FLEX_CODE_ID: string
|
||||
readonly NEXT_PUBLIC_WHITELIST_MERKLE_TREE_CODE_ID: string
|
||||
readonly NEXT_PUBLIC_VENDING_MINTER_CODE_ID: string
|
||||
readonly NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID: string
|
||||
readonly NEXT_PUBLIC_VENDING_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_FACTORY_MERKLE_TREE_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_FACTORY_MERKLE_TREE_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_IBC_USDC_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_NBTC_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_NBTC_UPDATABLE_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_USK_FACTORY_ADDRESS: string
|
||||
@@ -47,7 +54,13 @@ declare namespace NodeJS {
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_NBTC_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_NBTC_UPDATABLE_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_IBC_USK_FACTORY_FLEX_ADDRESS: string
|
||||
@@ -65,11 +78,17 @@ declare namespace NodeJS {
|
||||
readonly NEXT_PUBLIC_VENDING_NATIVE_BRNCH_UPDATABLE_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_VENDING_NATIVE_BRNCH_FLEX_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_TIA_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_TIA_FACTORY_FLEX_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_TIA_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_NBTC_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_NBTC_FACTORY_ADDRESS: string
|
||||
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS: string
|
||||
@@ -104,6 +123,8 @@ declare namespace NodeJS {
|
||||
readonly NEXT_PUBLIC_STARGAZE_WEBSITE_URL: string
|
||||
readonly NEXT_PUBLIC_WEBSITE_URL: string
|
||||
readonly NEXT_PUBLIC_SYNC_COLLECTIONS_API_URL: string
|
||||
readonly NEXT_PUBLIC_WHITELIST_MERKLE_TREE_API_URL: string
|
||||
readonly NEXT_PUBLIC_NFT_STORAGE_DEFAULT_API_KEY: string
|
||||
|
||||
readonly NEXT_PUBLIC_MEILISEARCH_HOST: string
|
||||
readonly NEXT_PUBLIC_MEILISEARCH_API_KEY: string
|
||||
|
||||
@@ -23,8 +23,11 @@
|
||||
"@cosmos-kit/leap": "^2.4.3",
|
||||
"@cosmos-kit/leap-metamask-cosmos-snap": "^0.3.3",
|
||||
"@cosmos-kit/react": "^2.9.3",
|
||||
"crypto-js": "4.1.1",
|
||||
"@types/crypto-js": "4.2.1",
|
||||
"@fontsource/jetbrains-mono": "^4",
|
||||
"@fontsource/roboto": "^4",
|
||||
"merkletreejs": "0.3.11",
|
||||
"@leapwallet/cosmos-snap-provider": "0.1.24",
|
||||
"@pinata/sdk": "^1.1.26",
|
||||
"@popperjs/core": "^2",
|
||||
|
||||
+179
-100
@@ -34,7 +34,13 @@ import { FormControl } from 'components/FormControl'
|
||||
import { LoadingModal } from 'components/LoadingModal'
|
||||
import type { OpenEditionMinterCreatorDataProps } from 'components/openEdition/OpenEditionMinterCreator'
|
||||
import { OpenEditionMinterCreator } from 'components/openEdition/OpenEditionMinterCreator'
|
||||
import { flexibleVendingMinterList, openEditionMinterList, vendingMinterList } from 'config/minter'
|
||||
import {
|
||||
flexibleOpenEditionMinterList,
|
||||
flexibleVendingMinterList,
|
||||
merkleTreeVendingMinterList,
|
||||
openEditionMinterList,
|
||||
vendingMinterList,
|
||||
} from 'config/minter'
|
||||
import type { TokenInfo } from 'config/token'
|
||||
import { useContracts } from 'contexts/contracts'
|
||||
import { addLogItem } from 'contexts/log'
|
||||
@@ -56,7 +62,6 @@ import {
|
||||
BLOCK_EXPLORER_URL,
|
||||
NETWORK,
|
||||
OPEN_EDITION_FACTORY_ADDRESS,
|
||||
OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS,
|
||||
SG721_CODE_ID,
|
||||
SG721_UPDATABLE_CODE_ID,
|
||||
STARGAZE_URL,
|
||||
@@ -67,6 +72,8 @@ import {
|
||||
VENDING_FACTORY_UPDATABLE_ADDRESS,
|
||||
WHITELIST_CODE_ID,
|
||||
WHITELIST_FLEX_CODE_ID,
|
||||
WHITELIST_MERKLE_TREE_API_URL,
|
||||
WHITELIST_MERKLE_TREE_CODE_ID,
|
||||
} from 'utils/constants'
|
||||
import { checkTokenUri } from 'utils/isValidTokenUri'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
@@ -88,6 +95,7 @@ const CollectionCreationPage: NextPage = () => {
|
||||
baseMinter: baseMinterContract,
|
||||
vendingMinter: vendingMinterContract,
|
||||
whitelist: whitelistContract,
|
||||
whitelistMerkleTree: whitelistMerkleTreeContract,
|
||||
vendingFactory: vendingFactoryContract,
|
||||
baseFactory: baseFactoryContract,
|
||||
} = useContracts()
|
||||
@@ -122,20 +130,19 @@ const CollectionCreationPage: NextPage = () => {
|
||||
const [baseMinterCreationFee, setBaseMinterCreationFee] = useState<string | null>(null)
|
||||
const [vendingMinterUpdatableCreationFee, setVendingMinterUpdatableCreationFee] = useState<string | null>(null)
|
||||
const [openEditionMinterCreationFee, setOpenEditionMinterCreationFee] = useState<string | null>(null)
|
||||
const [openEditionMinterUpdatableCreationFee, setOpenEditionMinterUpdatableCreationFee] = useState<string | null>(
|
||||
null,
|
||||
)
|
||||
const [vendingMinterFlexCreationFee, setVendingMinterFlexCreationFee] = useState<string | null>(null)
|
||||
const [baseMinterUpdatableCreationFee, setBaseMinterUpdatableCreationFee] = useState<string | null>(null)
|
||||
const [minimumMintPrice, setMinimumMintPrice] = useState<string | null>('0')
|
||||
const [minimumUpdatableMintPrice, setMinimumUpdatableMintPrice] = useState<string | null>('0')
|
||||
const [minimumOpenEditionMintPrice, setMinimumOpenEditionMintPrice] = useState<string | null>('0')
|
||||
const [minimumOpenEditionUpdatableMintPrice, setMinimumOpenEditionUpdatableMintPrice] = useState<string | null>('0')
|
||||
const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState<string | null>('0')
|
||||
|
||||
const [mintTokenFromOpenEditionFactory, setMintTokenFromOpenEditionFactory] = useState<TokenInfo | undefined>(stars)
|
||||
const [mintTokenFromVendingFactory, setMintTokenFromVendingFactory] = useState<TokenInfo | undefined>(stars)
|
||||
const [vendingFactoryAddress, setVendingFactoryAddress] = useState<string | null>(VENDING_FACTORY_ADDRESS)
|
||||
const [openEditionFactoryAddress, setOpenEditionFactoryAddress] = useState<string | undefined>(
|
||||
OPEN_EDITION_FACTORY_ADDRESS,
|
||||
)
|
||||
|
||||
const vendingFactoryMessages = useMemo(
|
||||
() => vendingFactoryContract?.use(vendingFactoryAddress as string),
|
||||
@@ -162,6 +169,7 @@ const CollectionCreationPage: NextPage = () => {
|
||||
const [coverImageUrl, setCoverImageUrl] = useState<string | null>(null)
|
||||
const [transactionHash, setTransactionHash] = useState<string | null>(null)
|
||||
const [isMatchingVendingFactoryPresent, setIsMatchingVendingFactoryPresent] = useState<boolean>(true)
|
||||
const [isMatchingOpenEditionFactoryPresent, setIsMatchingOpenEditionFactoryPresent] = useState<boolean>(true)
|
||||
|
||||
const performVendingMinterChecks = () => {
|
||||
try {
|
||||
@@ -513,41 +521,92 @@ const CollectionCreationPage: NextPage = () => {
|
||||
if (!wallet.isWalletConnected) throw new Error('Wallet not connected')
|
||||
if (!whitelistContract) throw new Error('Contract not found')
|
||||
|
||||
const standardMsg = {
|
||||
members: whitelistDetails?.members,
|
||||
start_time: whitelistDetails?.startTime,
|
||||
end_time: whitelistDetails?.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails?.unitPrice)),
|
||||
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
|
||||
),
|
||||
per_address_limit: whitelistDetails?.perAddressLimit,
|
||||
member_limit: whitelistDetails?.memberLimit,
|
||||
admins: whitelistDetails?.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails?.adminsMutable,
|
||||
if (whitelistDetails?.whitelistType === 'standard' || whitelistDetails?.whitelistType === 'flex') {
|
||||
const standardMsg = {
|
||||
members: whitelistDetails.members,
|
||||
start_time: whitelistDetails.startTime,
|
||||
end_time: whitelistDetails.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails.unitPrice)),
|
||||
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
|
||||
),
|
||||
per_address_limit: whitelistDetails.perAddressLimit,
|
||||
member_limit: whitelistDetails.memberLimit,
|
||||
admins: whitelistDetails.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails.adminsMutable,
|
||||
}
|
||||
|
||||
const flexMsg = {
|
||||
members: whitelistDetails.members,
|
||||
start_time: whitelistDetails.startTime,
|
||||
end_time: whitelistDetails.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails.unitPrice)),
|
||||
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
|
||||
),
|
||||
member_limit: whitelistDetails.memberLimit,
|
||||
admins: whitelistDetails.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails.adminsMutable,
|
||||
}
|
||||
|
||||
const data = await whitelistContract.instantiate(
|
||||
whitelistDetails.whitelistType === 'standard' ? WHITELIST_CODE_ID : WHITELIST_FLEX_CODE_ID,
|
||||
whitelistDetails.whitelistType === 'standard' ? standardMsg : flexMsg,
|
||||
'Stargaze Whitelist Contract',
|
||||
wallet.address,
|
||||
)
|
||||
|
||||
return data.contractAddress
|
||||
} else if (whitelistDetails?.whitelistType === 'merkletree') {
|
||||
const members = whitelistDetails.members as string[]
|
||||
const membersCsv = members.join('\n')
|
||||
const membersBlob = new Blob([membersCsv], { type: 'text/csv' })
|
||||
const membersFile = new File([membersBlob], 'members.csv', { type: 'text/csv' })
|
||||
const formData = new FormData()
|
||||
formData.append('whitelist', membersFile)
|
||||
const response = await toast
|
||||
.promise(
|
||||
axios.post(`${WHITELIST_MERKLE_TREE_API_URL}/create_whitelist`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Fetching merkle root hash...',
|
||||
success: 'Merkle root fetched successfully.',
|
||||
error: 'Error fetching root hash from Whitelist Merkle Tree API.',
|
||||
},
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log('error', error)
|
||||
throw new Error('Whitelist instantiation failed.')
|
||||
})
|
||||
|
||||
const rootHash = response.data.root_hash
|
||||
console.log('rootHash', rootHash)
|
||||
|
||||
const merkleTreeMsg = {
|
||||
merkle_root: rootHash,
|
||||
merkle_tree_uri: null,
|
||||
start_time: whitelistDetails.startTime,
|
||||
end_time: whitelistDetails.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails.unitPrice)),
|
||||
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
|
||||
),
|
||||
per_address_limit: whitelistDetails.perAddressLimit,
|
||||
admins: whitelistDetails.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails.adminsMutable,
|
||||
}
|
||||
|
||||
const data = await whitelistMerkleTreeContract?.instantiate(
|
||||
WHITELIST_MERKLE_TREE_CODE_ID,
|
||||
merkleTreeMsg,
|
||||
'Stargaze Whitelist Merkle Tree Contract',
|
||||
wallet.address,
|
||||
)
|
||||
return data?.contractAddress
|
||||
}
|
||||
|
||||
const flexMsg = {
|
||||
members: whitelistDetails?.members,
|
||||
start_time: whitelistDetails?.startTime,
|
||||
end_time: whitelistDetails?.endTime,
|
||||
mint_price: coin(
|
||||
String(Number(whitelistDetails?.unitPrice)),
|
||||
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
|
||||
),
|
||||
member_limit: whitelistDetails?.memberLimit,
|
||||
admins: whitelistDetails?.admins || [wallet.address],
|
||||
admins_mutable: whitelistDetails?.adminsMutable,
|
||||
}
|
||||
|
||||
const data = await whitelistContract.instantiate(
|
||||
whitelistDetails?.whitelistType === 'standard' ? WHITELIST_CODE_ID : WHITELIST_FLEX_CODE_ID,
|
||||
whitelistDetails?.whitelistType === 'standard' ? standardMsg : flexMsg,
|
||||
'Stargaze Whitelist Contract',
|
||||
wallet.address,
|
||||
)
|
||||
|
||||
return data.contractAddress
|
||||
}
|
||||
|
||||
const instantiateVendingMinter = async (baseUri: string, coverImageUri: string, whitelist?: string) => {
|
||||
@@ -582,6 +641,7 @@ const CollectionCreationPage: NextPage = () => {
|
||||
: mintingDetails?.selectedMintToken?.displayName === 'STRDST' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'USK' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'USDC' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'TIA' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'nBTC' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'KUJI' ||
|
||||
mintingDetails?.selectedMintToken?.displayName === 'HUAHUA' ||
|
||||
@@ -1046,6 +1106,8 @@ const CollectionCreationPage: NextPage = () => {
|
||||
//check if the address belongs to a whitelist contract (see performChecks())
|
||||
const config = await contract?.config()
|
||||
if (JSON.stringify(config).includes('whale_cap')) whitelistDetails.whitelistType = 'flex'
|
||||
else if (!JSON.stringify(config).includes('member_limit') || config?.member_limit === 0)
|
||||
whitelistDetails.whitelistType = 'merkletree'
|
||||
else whitelistDetails.whitelistType = 'standard'
|
||||
if (Number(config?.start_time) !== Number(mintingDetails?.startTime)) {
|
||||
const whitelistStartDate = new Date(Number(config?.start_time) / 1000000)
|
||||
@@ -1083,7 +1145,10 @@ const CollectionCreationPage: NextPage = () => {
|
||||
(!whitelistDetails.perAddressLimit || whitelistDetails.perAddressLimit === 0)
|
||||
)
|
||||
throw new Error('Per address limit is required')
|
||||
if (!whitelistDetails.memberLimit || whitelistDetails.memberLimit === 0)
|
||||
if (
|
||||
whitelistDetails.whitelistType !== 'merkletree' &&
|
||||
(!whitelistDetails.memberLimit || whitelistDetails.memberLimit === 0)
|
||||
)
|
||||
throw new Error('Member limit is required')
|
||||
if (Number(whitelistDetails.startTime) >= Number(whitelistDetails.endTime))
|
||||
throw new Error('Whitelist start time cannot be equal to or later than the whitelist end time')
|
||||
@@ -1208,32 +1273,27 @@ const CollectionCreationPage: NextPage = () => {
|
||||
setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee?.amount)
|
||||
setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)
|
||||
}
|
||||
if (OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS) {
|
||||
const openEditionUpdatableFactoryParameters = await client
|
||||
.queryContractSmart(OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS, { params: {} })
|
||||
.catch((error) => {
|
||||
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
|
||||
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
|
||||
})
|
||||
setOpenEditionMinterUpdatableCreationFee(openEditionUpdatableFactoryParameters?.params?.creation_fee?.amount)
|
||||
setMinimumOpenEditionUpdatableMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount)
|
||||
}
|
||||
setInitialParametersFetched(true)
|
||||
}
|
||||
|
||||
const fetchOpenEditionFactoryParameters = useCallback(async () => {
|
||||
const client = await wallet.getCosmWasmClient()
|
||||
const factoryForSelectedDenom = openEditionMinterList.find(
|
||||
(minter) =>
|
||||
minter.supportedToken === openEditionMinterDetails?.mintingDetails?.selectedMintToken &&
|
||||
minter.updatable === false,
|
||||
)
|
||||
const updatableFactoryForSelectedDenom = openEditionMinterList.find(
|
||||
(minter) =>
|
||||
minter.supportedToken === openEditionMinterDetails?.mintingDetails?.selectedMintToken &&
|
||||
minter.updatable === true,
|
||||
)
|
||||
const factoryForSelectedDenom = openEditionMinterList
|
||||
.concat(flexibleOpenEditionMinterList)
|
||||
.find(
|
||||
(minter) =>
|
||||
minter.supportedToken === openEditionMinterDetails?.mintingDetails?.selectedMintToken &&
|
||||
minter.updatable === openEditionMinterDetails.collectionDetails?.updatable &&
|
||||
minter.flexible ===
|
||||
(openEditionMinterDetails.whitelistDetails?.whitelistState !== 'none' &&
|
||||
openEditionMinterDetails.whitelistDetails?.whitelistType === 'flex'),
|
||||
)
|
||||
|
||||
console.log('OE Factory: ', factoryForSelectedDenom?.factoryAddress)
|
||||
if (factoryForSelectedDenom?.factoryAddress) {
|
||||
setIsMatchingOpenEditionFactoryPresent(true)
|
||||
setOpenEditionFactoryAddress(factoryForSelectedDenom.factoryAddress)
|
||||
|
||||
const openEditionFactoryParameters = await client
|
||||
.queryContractSmart(factoryForSelectedDenom.factoryAddress, { params: {} })
|
||||
.catch((error) => {
|
||||
@@ -1241,48 +1301,40 @@ const CollectionCreationPage: NextPage = () => {
|
||||
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
|
||||
})
|
||||
setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee?.amount)
|
||||
if (!openEditionMinterDetails?.collectionDetails?.updatable) {
|
||||
setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)
|
||||
setMintTokenFromOpenEditionFactory(
|
||||
tokensList.find((token) => token.denom === openEditionFactoryParameters?.params?.min_mint_price?.denom),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (updatableFactoryForSelectedDenom?.factoryAddress) {
|
||||
const openEditionUpdatableFactoryParameters = await client
|
||||
.queryContractSmart(updatableFactoryForSelectedDenom.factoryAddress, { params: {} })
|
||||
.catch((error) => {
|
||||
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
|
||||
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
|
||||
})
|
||||
setOpenEditionMinterUpdatableCreationFee(openEditionUpdatableFactoryParameters?.params?.creation_fee?.amount)
|
||||
if (openEditionMinterDetails?.collectionDetails?.updatable) {
|
||||
setMinimumOpenEditionUpdatableMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount)
|
||||
setMintTokenFromOpenEditionFactory(
|
||||
tokensList.find(
|
||||
(token) => token.denom === openEditionUpdatableFactoryParameters?.params?.min_mint_price?.denom,
|
||||
),
|
||||
)
|
||||
}
|
||||
setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)
|
||||
setMintTokenFromOpenEditionFactory(
|
||||
tokensList.find((token) => token.denom === openEditionFactoryParameters?.params?.min_mint_price?.denom),
|
||||
)
|
||||
} else if (
|
||||
openEditionMinterDetails?.mintingDetails?.selectedMintToken &&
|
||||
openEditionMinterDetails.whitelistDetails?.whitelistState
|
||||
) {
|
||||
setIsMatchingOpenEditionFactoryPresent(false)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
openEditionMinterDetails?.mintingDetails?.selectedMintToken,
|
||||
openEditionMinterDetails?.collectionDetails?.updatable,
|
||||
openEditionMinterDetails?.whitelistDetails?.whitelistType,
|
||||
openEditionMinterDetails?.whitelistDetails?.whitelistState,
|
||||
wallet.isWalletConnected,
|
||||
openEditionMinterDetails?.isRefreshed,
|
||||
])
|
||||
|
||||
const fetchVendingFactoryParameters = useCallback(async () => {
|
||||
const client = await wallet.getCosmWasmClient()
|
||||
const vendingFactoryForSelectedDenom = vendingMinterList
|
||||
.concat(flexibleVendingMinterList)
|
||||
.concat(merkleTreeVendingMinterList)
|
||||
.find(
|
||||
(minter) =>
|
||||
minter.supportedToken === mintingDetails?.selectedMintToken &&
|
||||
minter.updatable === collectionDetails?.updatable &&
|
||||
minter.flexible === (whitelistDetails?.whitelistType === 'flex') &&
|
||||
minter.merkleTree === (whitelistDetails?.whitelistType === 'merkletree') &&
|
||||
minter.featured === isFeaturedCollection,
|
||||
)?.factoryAddress
|
||||
console.log('Vending Factory: ', vendingFactoryForSelectedDenom)
|
||||
|
||||
if (vendingFactoryForSelectedDenom) {
|
||||
setIsMatchingVendingFactoryPresent(true)
|
||||
@@ -1321,20 +1373,34 @@ const CollectionCreationPage: NextPage = () => {
|
||||
|
||||
const checkwalletBalance = async () => {
|
||||
await (await wallet.getCosmWasmClient()).getBalance(wallet.address || '', 'ustars').then((balance) => {
|
||||
if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) {
|
||||
const amountNeeded =
|
||||
Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000 +
|
||||
(whitelistDetails.whitelistType === 'flex'
|
||||
? Number(vendingMinterFlexCreationFee)
|
||||
: collectionDetails?.updatable
|
||||
? Number(vendingMinterUpdatableCreationFee)
|
||||
: Number(vendingMinterCreationFee))
|
||||
if (amountNeeded >= Number(balance.amount))
|
||||
throw new Error(
|
||||
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
|
||||
amountNeeded / 1000000
|
||||
).toString()} STARS`,
|
||||
)
|
||||
if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new') {
|
||||
if (whitelistDetails.whitelistType !== 'merkletree' && whitelistDetails.memberLimit) {
|
||||
const amountNeeded =
|
||||
Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000 +
|
||||
(whitelistDetails.whitelistType === 'flex'
|
||||
? Number(vendingMinterFlexCreationFee)
|
||||
: collectionDetails?.updatable
|
||||
? Number(vendingMinterUpdatableCreationFee)
|
||||
: Number(vendingMinterCreationFee))
|
||||
if (amountNeeded >= Number(balance.amount))
|
||||
throw new Error(
|
||||
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
|
||||
amountNeeded / 1000000
|
||||
).toString()} STARS`,
|
||||
)
|
||||
} else if (whitelistDetails.whitelistType === 'merkletree') {
|
||||
const amountNeeded =
|
||||
1000000000 +
|
||||
(collectionDetails?.updatable
|
||||
? Number(vendingMinterUpdatableCreationFee)
|
||||
: Number(vendingMinterCreationFee))
|
||||
if (amountNeeded >= Number(balance.amount))
|
||||
throw new Error(
|
||||
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(
|
||||
amountNeeded / 1000000
|
||||
).toString()} STARS`,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
const amountNeeded =
|
||||
minterType === 'vending'
|
||||
@@ -1540,6 +1606,19 @@ const CollectionCreationPage: NextPage = () => {
|
||||
>
|
||||
{openEditionMinterCreatorData?.sg721ContractAddress as string}
|
||||
</Anchor>
|
||||
<Conditional test={openEditionMinterCreatorData?.whitelistContractAddress !== null}>
|
||||
<br />
|
||||
Whitelist Contract Address:{' '}
|
||||
<Anchor
|
||||
className="text-stargaze hover:underline"
|
||||
external
|
||||
href={`/contracts/whitelist/query/?contractAddress=${
|
||||
openEditionMinterCreatorData?.whitelistContractAddress as string
|
||||
}`}
|
||||
>
|
||||
{openEditionMinterCreatorData?.whitelistContractAddress as string}
|
||||
</Anchor>
|
||||
</Conditional>
|
||||
<br />
|
||||
Transaction Hash: {' '}
|
||||
<Conditional test={NETWORK === 'testnet'}>
|
||||
@@ -1848,14 +1927,14 @@ const CollectionCreationPage: NextPage = () => {
|
||||
<Conditional test={minterType === 'openEdition'}>
|
||||
<OpenEditionMinterCreator
|
||||
importedOpenEditionMinterDetails={importedDetails?.openEditionMinterDetails}
|
||||
isMatchingFactoryPresent={isMatchingOpenEditionFactoryPresent}
|
||||
minimumMintPrice={minimumOpenEditionMintPrice as string}
|
||||
minimumUpdatableMintPrice={minimumOpenEditionUpdatableMintPrice as string}
|
||||
mintTokenFromFactory={mintTokenFromOpenEditionFactory}
|
||||
minterType={minterType}
|
||||
onChange={setOpenEditionMinterCreatorData}
|
||||
onDetailsChange={setOpenEditionMinterDetails}
|
||||
openEditionFactoryAddress={openEditionFactoryAddress}
|
||||
openEditionMinterCreationFee={openEditionMinterCreationFee as string}
|
||||
openEditionMinterUpdatableCreationFee={openEditionMinterUpdatableCreationFee as string}
|
||||
/>
|
||||
</Conditional>
|
||||
<div className="mx-10">
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
|
||||
import { Alert } from 'components/Alert'
|
||||
import { Button } from 'components/Button'
|
||||
import { Conditional } from 'components/Conditional'
|
||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||
import { AddressInput } from 'components/forms/FormInput'
|
||||
import { useInputState } from 'components/forms/FormInput.hooks'
|
||||
import type { NextPage } from 'next'
|
||||
import { useRouter } from 'next/router'
|
||||
import { NextSeo } from 'next-seo'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import { NETWORK } from 'utils/constants'
|
||||
import { useDebounce } from 'utils/debounce'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { links } from 'utils/links'
|
||||
import { resolveAddress } from 'utils/resolveAddress'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
const RemoveOfferPage: NextPage = () => {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [txHash, setTxHash] = useState<string | undefined>(undefined)
|
||||
|
||||
const collectionAddressState = useInputState({
|
||||
id: 'collection-address',
|
||||
name: 'collectionAddress',
|
||||
title: 'Collection Contract Address',
|
||||
defaultValue: '',
|
||||
placeholder: 'stars1...',
|
||||
})
|
||||
const collectionAddress = useDebounce(collectionAddressState.value, 300)
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
if (collectionAddress.length > 0) {
|
||||
void router.replace({ query: { contractAddress: collectionAddress } })
|
||||
}
|
||||
if (collectionAddress.length === 0) {
|
||||
void router.replace({ query: {} })
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [collectionAddress])
|
||||
|
||||
useEffect(() => {
|
||||
const initial = new URL(document.URL).searchParams.get('contractAddress')
|
||||
if (initial && initial.length > 0) collectionAddressState.onChange(initial)
|
||||
}, [])
|
||||
|
||||
const resolveCollectionAddress = async () => {
|
||||
await resolveAddress(collectionAddressState.value.trim(), wallet).then((resolvedAddress) => {
|
||||
if (resolvedAddress) {
|
||||
collectionAddressState.onChange(resolvedAddress)
|
||||
}
|
||||
})
|
||||
}
|
||||
useEffect(() => {
|
||||
void resolveCollectionAddress()
|
||||
}, [collectionAddressState.value])
|
||||
|
||||
const handleRemoveOffer = async () => {
|
||||
if (!wallet.isWalletConnected) return toast.error('Please connect your wallet.')
|
||||
if (!collectionAddressState.value) return toast.error('Please enter a collection address.')
|
||||
|
||||
const client = await wallet.getSigningCosmWasmClient()
|
||||
setTxHash(undefined)
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const result = await client.execute(
|
||||
wallet.address as string,
|
||||
NETWORK === 'mainnet'
|
||||
? 'stars1fvhcnyddukcqfnt7nlwv3thm5we22lyxyxylr9h77cvgkcn43xfsvgv0pl'
|
||||
: 'stars18cszlvm6pze0x9sz32qnjq4vtd45xehqs8dq7cwy8yhq35wfnn3qgzs5gu',
|
||||
{
|
||||
remove_collection_bid: {
|
||||
collection: collectionAddressState.value,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
toast.success('Offer successfully removed.')
|
||||
setTxHash(result.transactionHash)
|
||||
} catch (error: any) {
|
||||
toast.error(error.message, { style: { maxWidth: 'none' } })
|
||||
setTxHash(undefined)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="py-6 px-12 space-y-4">
|
||||
<NextSeo title="Remove Collection offer" />
|
||||
<ContractPageHeader link={links.Documentation} title="Remove Collection Offer" />
|
||||
<div className="space-y-8">
|
||||
<AddressInput {...collectionAddressState} />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row content-center">
|
||||
<Button
|
||||
isDisabled={collectionAddressState.value === ''}
|
||||
isLoading={isLoading}
|
||||
onClick={() => {
|
||||
void handleRemoveOffer()
|
||||
}}
|
||||
>
|
||||
Remove Collection Offer
|
||||
</Button>
|
||||
</div>
|
||||
<Conditional test={txHash !== undefined}>
|
||||
<Alert type="info">
|
||||
<b>Transaction Hash:</b> {txHash}
|
||||
</Alert>
|
||||
</Conditional>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export default withMetadata(RemoveOfferPage, { center: false })
|
||||
@@ -23,13 +23,12 @@ import { useEffect, 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 { BASE_FACTORY_ADDRESS, BASE_FACTORY_SG721_CODE_ID } from 'utils/constants'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { links } from 'utils/links'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
import type { CreateBaseMinterResponse } from '../../../contracts/baseFactory/contract'
|
||||
import { SG721_CODE_ID } from '../../../utils/constants'
|
||||
import { resolveAddress } from '../../../utils/resolveAddress'
|
||||
|
||||
const BaseMinterInstantiatePage: NextPage = () => {
|
||||
@@ -62,7 +61,7 @@ const BaseMinterInstantiatePage: NextPage = () => {
|
||||
title: 'Code ID',
|
||||
subtitle: 'Code ID for the sg721 contract',
|
||||
placeholder: '1',
|
||||
defaultValue: SG721_CODE_ID,
|
||||
defaultValue: BASE_FACTORY_SG721_CODE_ID,
|
||||
})
|
||||
|
||||
const creatorState = useInputState({
|
||||
|
||||
@@ -48,7 +48,7 @@ const WhitelistExecutePage: NextPage = () => {
|
||||
const [lastTx, setLastTx] = useState('')
|
||||
const [memberList, setMemberList] = useState<string[]>([])
|
||||
const [flexMemberList, setFlexMemberList] = useState<WhitelistFlexMember[]>([])
|
||||
const [whitelistType, setWhitelistType] = useState<'standard' | 'flex'>('standard')
|
||||
const [whitelistType, setWhitelistType] = useState<'standard' | 'flex' | 'merkletree'>('standard')
|
||||
|
||||
const comboboxState = useExecuteComboboxState()
|
||||
const type = comboboxState.value?.id
|
||||
@@ -211,6 +211,8 @@ const WhitelistExecutePage: NextPage = () => {
|
||||
.then((contractType) => {
|
||||
if (contractType?.includes('flex')) {
|
||||
setWhitelistType('flex')
|
||||
} else if (contractType?.includes('merkle')) {
|
||||
setWhitelistType('merkletree')
|
||||
} else {
|
||||
setWhitelistType('standard')
|
||||
}
|
||||
@@ -236,7 +238,7 @@ const WhitelistExecutePage: NextPage = () => {
|
||||
<form className="grid grid-cols-2 p-4 space-x-8" onSubmit={mutate}>
|
||||
<div className="space-y-8">
|
||||
<AddressInput {...contractState} />
|
||||
<ExecuteCombobox {...comboboxState} />
|
||||
<ExecuteCombobox whitelistType={whitelistType} {...comboboxState} />
|
||||
<Conditional test={showLimitState}>
|
||||
<NumberInput {...limitState} />
|
||||
</Conditional>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import { coin } from '@cosmjs/proto-signing'
|
||||
import axios from 'axios'
|
||||
import { Alert } from 'components/Alert'
|
||||
import { Button } from 'components/Button'
|
||||
import { Conditional } from 'components/Conditional'
|
||||
@@ -34,17 +35,22 @@ import { withMetadata } from 'utils/layout'
|
||||
import { links } from 'utils/links'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
import { WHITELIST_CODE_ID, WHITELIST_FLEX_CODE_ID } from '../../../utils/constants'
|
||||
import {
|
||||
WHITELIST_CODE_ID,
|
||||
WHITELIST_FLEX_CODE_ID,
|
||||
WHITELIST_MERKLE_TREE_API_URL,
|
||||
WHITELIST_MERKLE_TREE_CODE_ID,
|
||||
} from '../../../utils/constants'
|
||||
|
||||
const WhitelistInstantiatePage: NextPage = () => {
|
||||
const wallet = useWallet()
|
||||
const { whitelist: contract } = useContracts()
|
||||
const { whitelist: contract, whitelistMerkleTree: whitelistMerkleTreeContract } = useContracts()
|
||||
const { timezone } = useGlobalSettings()
|
||||
|
||||
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
|
||||
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
|
||||
const [adminsMutable, setAdminsMutable] = useState<boolean>(true)
|
||||
const [whitelistType, setWhitelistType] = useState<'standard' | 'flex'>('standard')
|
||||
const [whitelistType, setWhitelistType] = useState<'standard' | 'flex' | 'merkletree'>('standard')
|
||||
|
||||
const [whitelistStandardArray, setWhitelistStandardArray] = useState<string[]>([])
|
||||
const [whitelistFlexArray, setWhitelistFlexArray] = useState<WhitelistFlexMember[]>([])
|
||||
@@ -85,12 +91,16 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
const addressListState = useAddressListState()
|
||||
|
||||
const { data, isLoading, mutate } = useMutation(
|
||||
async (event: FormEvent): Promise<InstantiateResponse | null> => {
|
||||
async (event: FormEvent): Promise<InstantiateResponse | undefined | null> => {
|
||||
event.preventDefault()
|
||||
if (!contract) {
|
||||
throw new Error('Smart contract connection failed')
|
||||
}
|
||||
|
||||
if (!whitelistMerkleTreeContract && whitelistType === 'merkletree') {
|
||||
throw new Error('Smart contract connection failed')
|
||||
}
|
||||
|
||||
if (!startDate) {
|
||||
throw new Error('Start date is required')
|
||||
}
|
||||
@@ -132,19 +142,79 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
admins_mutable: adminsMutable,
|
||||
}
|
||||
|
||||
return toast.promise(
|
||||
contract.instantiate(
|
||||
whitelistType === 'standard' ? WHITELIST_CODE_ID : WHITELIST_FLEX_CODE_ID,
|
||||
whitelistType === 'standard' ? standardMsg : flexMsg,
|
||||
whitelistType === 'standard' ? 'Stargaze Whitelist Contract' : 'Stargaze Whitelist Flex Contract',
|
||||
wallet.address,
|
||||
),
|
||||
{
|
||||
loading: 'Instantiating contract...',
|
||||
error: 'Instantiation failed!',
|
||||
success: 'Instantiation success!',
|
||||
},
|
||||
)
|
||||
if (whitelistType !== 'merkletree') {
|
||||
return toast.promise(
|
||||
contract.instantiate(
|
||||
whitelistType === 'standard' ? WHITELIST_CODE_ID : WHITELIST_FLEX_CODE_ID,
|
||||
whitelistType === 'standard' ? standardMsg : flexMsg,
|
||||
whitelistType === 'standard' ? 'Stargaze Whitelist Contract' : 'Stargaze Whitelist Flex Contract',
|
||||
wallet.address,
|
||||
),
|
||||
{
|
||||
loading: 'Instantiating contract...',
|
||||
error: 'Instantiation failed!',
|
||||
success: 'Instantiation success!',
|
||||
},
|
||||
)
|
||||
} else if (whitelistType === 'merkletree') {
|
||||
const members = whitelistStandardArray
|
||||
const membersCsv = members.join('\n')
|
||||
const membersBlob = new Blob([membersCsv], { type: 'text/csv' })
|
||||
const membersFile = new File([membersBlob], 'members.csv', { type: 'text/csv' })
|
||||
const formData = new FormData()
|
||||
formData.append('whitelist', membersFile)
|
||||
const response = await toast
|
||||
.promise(
|
||||
axios.post(`${WHITELIST_MERKLE_TREE_API_URL}/create_whitelist`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
}),
|
||||
{
|
||||
loading: 'Fetching merkle root hash...',
|
||||
success: 'Merkle root fetched successfully.',
|
||||
error: 'Error fetching root hash from Whitelist Merkle Tree API.',
|
||||
},
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log('error', error)
|
||||
throw new Error('Whitelist instantiation failed.')
|
||||
})
|
||||
|
||||
const rootHash = response.data.root_hash
|
||||
console.log('rootHash', rootHash)
|
||||
|
||||
const merkleTreeMsg = {
|
||||
merkle_root: rootHash,
|
||||
merkle_tree_uri: null,
|
||||
start_time: (startDate.getTime() * 1_000_000).toString(),
|
||||
end_time: (endDate.getTime() * 1_000_000).toString(),
|
||||
mint_price: coin(String(Number(unitPriceState.value) * 1000000), selectedMintToken?.denom || 'ustars'),
|
||||
per_address_limit: perAddressLimitState.value,
|
||||
admins: [
|
||||
...new Set(
|
||||
addressListState.values
|
||||
.map((a) => a.address.trim())
|
||||
.filter((address) => address !== '' && isValidAddress(address.trim()) && address.startsWith('stars')),
|
||||
),
|
||||
] || [wallet.address],
|
||||
admins_mutable: adminsMutable,
|
||||
}
|
||||
|
||||
return toast.promise(
|
||||
whitelistMerkleTreeContract?.instantiate(
|
||||
WHITELIST_MERKLE_TREE_CODE_ID,
|
||||
merkleTreeMsg,
|
||||
'Stargaze Whitelist Merkle Tree Contract',
|
||||
wallet.address,
|
||||
) as Promise<InstantiateResponse>,
|
||||
{
|
||||
loading: 'Instantiating contract...',
|
||||
error: 'Instantiation failed!',
|
||||
success: 'Instantiation success!',
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
onError: (error) => {
|
||||
@@ -176,7 +246,7 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
/>
|
||||
<LinkTabs activeIndex={0} data={whitelistLinkTabs} />
|
||||
|
||||
<div className="flex justify-between mb-5 ml-6 max-w-[300px] text-lg font-bold">
|
||||
<div className="flex justify-between mb-5 ml-6 max-w-[520px] text-lg font-bold">
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistType === 'standard'}
|
||||
@@ -216,6 +286,26 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
Whitelist Flex
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="form-check form-check-inline">
|
||||
<input
|
||||
checked={whitelistType === 'merkletree'}
|
||||
className="peer sr-only"
|
||||
id="inlineRadio3"
|
||||
name="inlineRadioOptions3"
|
||||
onClick={() => {
|
||||
setWhitelistType('merkletree')
|
||||
}}
|
||||
type="radio"
|
||||
value="merkletree"
|
||||
/>
|
||||
<label
|
||||
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
|
||||
htmlFor="inlineRadio3"
|
||||
>
|
||||
Whitelist Merkle Tree
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Conditional test={Boolean(data)}>
|
||||
@@ -251,7 +341,7 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
</div>
|
||||
|
||||
<FormGroup subtitle="Your whitelisted addresses" title="Whitelist File">
|
||||
<Conditional test={whitelistType === 'standard'}>
|
||||
<Conditional test={whitelistType === 'standard' || whitelistType === 'merkletree'}>
|
||||
<WhitelistUpload onChange={whitelistFileOnChange} />
|
||||
<Conditional test={whitelistStandardArray.length > 0}>
|
||||
<JsonPreview content={whitelistStandardArray} initialState={false} title="File Contents" />
|
||||
@@ -283,8 +373,10 @@ const WhitelistInstantiatePage: NextPage = () => {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<NumberInput isRequired {...memberLimitState} />
|
||||
<Conditional test={whitelistType === 'standard'}>
|
||||
<Conditional test={whitelistType !== 'merkletree'}>
|
||||
<NumberInput isRequired {...memberLimitState} />
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'standard' || whitelistType === 'merkletree'}>
|
||||
<NumberInput isRequired {...perAddressLimitState} />
|
||||
</Conditional>
|
||||
<Conditional test={whitelistType === 'flex'}>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
|
||||
/* eslint-disable no-await-in-loop */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
@@ -8,6 +10,7 @@
|
||||
import { toUtf8 } from '@cosmjs/encoding'
|
||||
import clsx from 'clsx'
|
||||
import { Button } from 'components/Button'
|
||||
import type { WhitelistType } from 'components/collections/creation/WhitelistDetails'
|
||||
import { Conditional } from 'components/Conditional'
|
||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||
import { FormControl } from 'components/FormControl'
|
||||
@@ -19,12 +22,18 @@ import { whitelistLinkTabs } from 'components/LinkTabs.data'
|
||||
import { useContracts } from 'contexts/contracts'
|
||||
import type { QueryType } from 'contracts/whitelist/messages/query'
|
||||
import { dispatchQuery, QUERY_LIST } from 'contracts/whitelist/messages/query'
|
||||
import type { WhitelistMerkleTreeQueryType } from 'contracts/whitelistMerkleTree/messages/query'
|
||||
import {
|
||||
dispatchQuery as disptachWhitelistMerkleTreeQuery,
|
||||
WHITELIST_MERKLE_TREE_QUERY_LIST,
|
||||
} from 'contracts/whitelistMerkleTree/messages/query'
|
||||
import type { NextPage } from 'next'
|
||||
import { useRouter } from 'next/router'
|
||||
import { NextSeo } from 'next-seo'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import { useQuery } from 'react-query'
|
||||
import { WHITELIST_MERKLE_TREE_API_URL } from 'utils/constants'
|
||||
import { useDebounce } from 'utils/debounce'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { links } from 'utils/links'
|
||||
@@ -33,8 +42,11 @@ import { useWallet } from 'utils/wallet'
|
||||
|
||||
const WhitelistQueryPage: NextPage = () => {
|
||||
const { whitelist: contract } = useContracts()
|
||||
const { whitelistMerkleTree: contractWhitelistMerkleTree } = useContracts()
|
||||
const wallet = useWallet()
|
||||
const [exporting, setExporting] = useState(false)
|
||||
const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
|
||||
const [proofHashes, setProofHashes] = useState<string[]>([])
|
||||
|
||||
const contractState = useInputState({
|
||||
id: 'contract-address',
|
||||
@@ -44,6 +56,46 @@ const WhitelistQueryPage: NextPage = () => {
|
||||
})
|
||||
const contractAddress = contractState.value
|
||||
|
||||
const debouncedWhitelistContractState = useDebounce(contractAddress, 300)
|
||||
|
||||
useEffect(() => {
|
||||
async function getWhitelistContractType() {
|
||||
if (debouncedWhitelistContractState.length > 0) {
|
||||
const client = await wallet.getCosmWasmClient()
|
||||
const data = await toast.promise(
|
||||
client.queryContractRaw(
|
||||
debouncedWhitelistContractState,
|
||||
toUtf8(Buffer.from(Buffer.from('contract_info').toString('hex'), 'hex').toString()),
|
||||
),
|
||||
{
|
||||
loading: 'Retrieving whitelist type...',
|
||||
error: 'Whitelist type retrieval failed.',
|
||||
success: 'Whitelist type retrieved.',
|
||||
},
|
||||
)
|
||||
const whitelistContract: string = JSON.parse(new TextDecoder().decode(data as Uint8Array)).contract
|
||||
console.log(contract)
|
||||
return whitelistContract
|
||||
}
|
||||
}
|
||||
void getWhitelistContractType()
|
||||
.then((whitelistContract) => {
|
||||
if (whitelistContract?.includes('merkletree')) {
|
||||
setWhitelistType('merkletree')
|
||||
} else if (whitelistContract?.includes('flex')) {
|
||||
setWhitelistType('flex')
|
||||
} else {
|
||||
setWhitelistType('standard')
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
setWhitelistType('standard')
|
||||
console.log('Unable to retrieve contract type. Defaulting to "standard".')
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [debouncedWhitelistContractState, wallet.isWalletConnected])
|
||||
|
||||
const addressState = useInputState({
|
||||
id: 'address',
|
||||
name: 'address',
|
||||
@@ -52,6 +104,47 @@ const WhitelistQueryPage: NextPage = () => {
|
||||
})
|
||||
const address = addressState.value
|
||||
|
||||
const debouncedAddress = useDebounce(address, 300)
|
||||
|
||||
const fetchProofHashes = async (whitelistContractAddress: string, memberAddress: string): Promise<string[]> => {
|
||||
if (whitelistContractAddress.length === 0 || memberAddress.length === 0)
|
||||
throw new Error('Contract or member address is empty.')
|
||||
const resolvedAddress = await resolveAddress(memberAddress, wallet)
|
||||
const merkleRootResponse = await (
|
||||
await wallet.getCosmWasmClient()
|
||||
).queryContractSmart(contractAddress, { merkle_root: {} })
|
||||
const proofs = await toast.promise(
|
||||
fetch(`${WHITELIST_MERKLE_TREE_API_URL}/whitelist/${merkleRootResponse.merkle_root}/${resolvedAddress}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => data.proofs)
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
setProofHashes([])
|
||||
}),
|
||||
{
|
||||
loading: 'Fetching proof hashes...',
|
||||
error: 'Error fetching proof hashes from Whitelist Merkle Tree API.',
|
||||
success: 'Proof hashes fetched.',
|
||||
},
|
||||
)
|
||||
return proofs as string[] | []
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
whitelistType === 'merkletree' &&
|
||||
whitelistMerkleTreeQueryType === 'has_member' &&
|
||||
debouncedAddress.length > 0
|
||||
) {
|
||||
void fetchProofHashes(contractAddress, debouncedAddress)
|
||||
.then((proofs) => setProofHashes(proofs))
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
setProofHashes([])
|
||||
})
|
||||
}
|
||||
}, [debouncedAddress])
|
||||
|
||||
const limit = useNumberInputState({
|
||||
id: 'limit',
|
||||
name: 'limit',
|
||||
@@ -80,22 +173,59 @@ const WhitelistQueryPage: NextPage = () => {
|
||||
}, [debouncedLimit])
|
||||
|
||||
const [type, setType] = useState<QueryType>('config')
|
||||
const [whitelistMerkleTreeQueryType, setWhitelistMerkleTreeQueryType] =
|
||||
useState<WhitelistMerkleTreeQueryType>('config')
|
||||
|
||||
const addressVisible = type === 'has_member'
|
||||
const addressVisible = type === 'has_member' || whitelistMerkleTreeQueryType === 'has_member'
|
||||
|
||||
const { data: response } = useQuery(
|
||||
[contractAddress, type, contract, wallet.address, address, startAfter.value, limit.value] as const,
|
||||
[
|
||||
contractAddress,
|
||||
type,
|
||||
whitelistMerkleTreeQueryType,
|
||||
contract,
|
||||
contractWhitelistMerkleTree,
|
||||
wallet.address,
|
||||
address,
|
||||
startAfter.value,
|
||||
limit.value,
|
||||
proofHashes,
|
||||
whitelistType,
|
||||
] as const,
|
||||
async ({ queryKey }) => {
|
||||
const [_contractAddress, _type, _contract, _wallet, _address, _startAfter, _limit] = queryKey
|
||||
const [
|
||||
_contractAddress,
|
||||
_type,
|
||||
_whitelistMerkleTreeQueryType,
|
||||
_contract,
|
||||
_contractWhitelistMerkleTree,
|
||||
_wallet,
|
||||
_address,
|
||||
_startAfter,
|
||||
_limit,
|
||||
_proofHashes,
|
||||
_whitelistType,
|
||||
] = queryKey
|
||||
const messages = contract?.use(contractAddress)
|
||||
const whitelistMerkleTreeMessages = contractWhitelistMerkleTree?.use(contractAddress)
|
||||
|
||||
const res = await resolveAddress(_address, wallet).then(async (resolvedAddress) => {
|
||||
const result = await dispatchQuery({
|
||||
messages,
|
||||
type,
|
||||
address: resolvedAddress,
|
||||
startAfter: _startAfter || undefined,
|
||||
limit: _limit,
|
||||
})
|
||||
const result =
|
||||
whitelistType === 'merkletree'
|
||||
? await disptachWhitelistMerkleTreeQuery({
|
||||
messages: whitelistMerkleTreeMessages,
|
||||
address: resolvedAddress,
|
||||
type: whitelistMerkleTreeQueryType,
|
||||
limit: _limit,
|
||||
proofHashes: _proofHashes,
|
||||
})
|
||||
: await dispatchQuery({
|
||||
messages,
|
||||
type,
|
||||
address: resolvedAddress,
|
||||
startAfter: _startAfter || undefined,
|
||||
limit: _limit,
|
||||
})
|
||||
return result
|
||||
})
|
||||
return res
|
||||
@@ -105,7 +235,7 @@ const WhitelistQueryPage: NextPage = () => {
|
||||
onError: (error: any) => {
|
||||
toast.error(error.message, { style: { maxWidth: 'none' } })
|
||||
},
|
||||
enabled: Boolean(contractAddress && contract),
|
||||
enabled: Boolean(contractAddress && (contract || contractWhitelistMerkleTree)),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -230,9 +360,13 @@ const WhitelistQueryPage: NextPage = () => {
|
||||
defaultValue="config"
|
||||
id="contract-query-type"
|
||||
name="query-type"
|
||||
onChange={(e) => setType(e.target.value as QueryType)}
|
||||
onChange={(e) =>
|
||||
whitelistType === 'merkletree'
|
||||
? setWhitelistMerkleTreeQueryType(e.target.value as WhitelistMerkleTreeQueryType)
|
||||
: setType(e.target.value as QueryType)
|
||||
}
|
||||
>
|
||||
{QUERY_LIST.map(({ id, name }) => (
|
||||
{(whitelistType === 'merkletree' ? WHITELIST_MERKLE_TREE_QUERY_LIST : QUERY_LIST).map(({ id, name }) => (
|
||||
<option key={`query-${id}`} className="mt-2 text-lg bg-[#1A1A1A]" value={id}>
|
||||
{name}
|
||||
</option>
|
||||
@@ -255,7 +389,16 @@ const WhitelistQueryPage: NextPage = () => {
|
||||
</Button>
|
||||
</Conditional>
|
||||
</div>
|
||||
<JsonPreview content={contractAddress ? { type, response } : null} title="Query Response" />
|
||||
<JsonPreview
|
||||
content={
|
||||
contractAddress
|
||||
? whitelistType === 'merkletree'
|
||||
? { type: whitelistMerkleTreeQueryType, response }
|
||||
: { type, response }
|
||||
: null
|
||||
}
|
||||
title="Query Response"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
@@ -30,6 +30,7 @@ const Holders: NextPage = () => {
|
||||
|
||||
const [includeStaked, setIncludeStaked] = useState<boolean>(true)
|
||||
const [includeListed, setIncludeListed] = useState<boolean>(true)
|
||||
const [includeInPool, setIncludeInPool] = useState<boolean>(true)
|
||||
const [exportIndividualTokens, setExportIndividualTokens] = useState<boolean>(false)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
@@ -83,6 +84,17 @@ const Holders: NextPage = () => {
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
<label className="justify-start cursor-pointer label w-2/5">
|
||||
<span className="mr-2 font-bold">Include tokens in Infinity Pools</span>
|
||||
<input
|
||||
checked={includeInPool}
|
||||
className={`${includeInPool ? `bg-stargaze` : `bg-gray-600`} checkbox`}
|
||||
onClick={() => {
|
||||
setIncludeInPool(!includeInPool)
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
<label className="justify-start cursor-pointer label w-2/5">
|
||||
<span className="mr-2 font-bold">Export by Token ID</span>
|
||||
<input
|
||||
@@ -122,6 +134,8 @@ const Holders: NextPage = () => {
|
||||
?.map((row: any) => {
|
||||
if (!includeListed && row.is_listed) return ''
|
||||
if (!includeStaked && row.is_staked) return ''
|
||||
if (!includeInPool && row.is_in_pool) return ''
|
||||
if (row.owner_addr === null) return ''
|
||||
return `${row.owner_addr},${row.token_id}\n`
|
||||
})
|
||||
.join('')}`
|
||||
@@ -133,6 +147,8 @@ const Holders: NextPage = () => {
|
||||
data.forEach((row: any) => {
|
||||
if (!includeListed && row.is_listed) return
|
||||
if (!includeStaked && row.is_staked) return
|
||||
if (!includeInPool && row.is_in_pool) return
|
||||
if (row.owner_addr === null) return
|
||||
const existingRow = aggregatedData.find((r) => r.address === row.owner_addr)
|
||||
if (existingRow) {
|
||||
existingRow.amount += 1
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable tailwindcss/classnames-order */
|
||||
/* eslint-disable react/button-has-type */
|
||||
|
||||
import type { EncodeObject } from '@cosmjs/proto-signing'
|
||||
import { Registry } from '@cosmjs/proto-signing'
|
||||
import { GasPrice, SigningStargateClient } from '@cosmjs/stargate'
|
||||
import { Button } from 'components/Button'
|
||||
import { Conditional } from 'components/Conditional'
|
||||
import { ContractPageHeader } from 'components/ContractPageHeader'
|
||||
import { DenomUnits } from 'components/forms/DenomUnits'
|
||||
@@ -17,6 +18,7 @@ import { NextSeo } from 'next-seo'
|
||||
import { Field, Type } from 'protobufjs'
|
||||
import { useEffect, useState } from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import { NETWORK } from 'utils/constants'
|
||||
import { withMetadata } from 'utils/layout'
|
||||
import { useWallet } from 'utils/wallet'
|
||||
|
||||
@@ -52,16 +54,13 @@ const MsgMint = new Type('MsgMint')
|
||||
.add(new Field('sender', 1, 'string', 'required'))
|
||||
.add(new Field('amount', 2, 'Coin', 'required'))
|
||||
.add(new Field('mintToAddress', 3, 'string', 'required'))
|
||||
|
||||
const CoinType = new Type('Coin').add(new Field('denom', 1, 'string')).add(new Field('amount', 2, 'string'))
|
||||
MsgMint.add(CoinType)
|
||||
.add(new Type('Coin').add(new Field('denom', 1, 'string')).add(new Field('amount', 2, 'string')))
|
||||
|
||||
const MsgSend = new Type('MsgSend')
|
||||
.add(new Field('fromAddress', 1, 'string'))
|
||||
.add(new Field('toAddress', 2, 'string'))
|
||||
.add(new Field('amount', 3, 'Coin', 'repeated'))
|
||||
|
||||
MsgSend.add(CoinType)
|
||||
.add(new Type('Coin').add(new Field('denom', 1, 'string')).add(new Field('amount', 2, 'string')))
|
||||
|
||||
const MsgChangeAdmin = new Type('MsgChangeAdmin')
|
||||
.add(new Field('sender', 1, 'string', 'required'))
|
||||
@@ -88,6 +87,7 @@ const Tokenfactory: NextPage = () => {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [messageType, setMessageType] = useState<MessageType>('MsgCreateDenom')
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const denomState = useInputState({
|
||||
id: 'denom',
|
||||
@@ -118,8 +118,8 @@ const Tokenfactory: NextPage = () => {
|
||||
id: 'mintToAddress',
|
||||
name: 'mintToAddress',
|
||||
title: 'Mint To Address',
|
||||
//placeholder: `${wallet.isWalletConnected && wallet.address ? wallet.address : 'stars1...'}`,
|
||||
placeholder: 'The tokens can only be minted to the creator address currently.',
|
||||
placeholder: 'stars1...',
|
||||
defaultValue: wallet.address ?? '',
|
||||
subtitle: 'The address to mint tokens to',
|
||||
})
|
||||
|
||||
@@ -209,10 +209,14 @@ const Tokenfactory: NextPage = () => {
|
||||
const handleSendMessage = async () => {
|
||||
try {
|
||||
if (!wallet.isWalletConnected) return toast.error('Please connect your wallet.')
|
||||
|
||||
setLoading(true)
|
||||
const offlineSigner = wallet.getOfflineSignerDirect()
|
||||
const stargateClient = await SigningStargateClient.connectWithSigner(
|
||||
'https://rpc.elgafar-1.stargaze-apis.com/',
|
||||
NETWORK === 'fang-testnet'
|
||||
? 'https://rpc.fang-1.stargaze-apis.com/'
|
||||
: NETWORK === 'testnet'
|
||||
? 'https://rpc.fang-1.stargaze-apis.com/'
|
||||
: 'https://rpc.stargaze-apis.com/',
|
||||
offlineSigner,
|
||||
{
|
||||
gasPrice: GasPrice.fromString('0.025ustars'),
|
||||
@@ -302,9 +306,10 @@ const Tokenfactory: NextPage = () => {
|
||||
'auto',
|
||||
)
|
||||
console.log('response: ', response)
|
||||
|
||||
setLoading(false)
|
||||
toast.success(`${messageType} success.`, { style: { maxWidth: 'none' } })
|
||||
} catch (error: any) {
|
||||
setLoading(false)
|
||||
toast.error(error.message, { style: { maxWidth: 'none' } })
|
||||
console.error('Error: ', error)
|
||||
}
|
||||
@@ -349,7 +354,7 @@ const Tokenfactory: NextPage = () => {
|
||||
<Conditional test={messageType === 'MsgMint'}>
|
||||
<TextInput className="w-3/5" {...denomState} />
|
||||
<NumberInput className="w-1/4" {...amountState} />
|
||||
<AddressInput className="w-3/5" disabled {...mintToAddressState} />
|
||||
<AddressInput className="w-3/5" {...mintToAddressState} />
|
||||
</Conditional>
|
||||
<Conditional test={messageType === 'MsgSend'}>
|
||||
<TextInput className="w-3/5" {...denomState} />
|
||||
@@ -375,15 +380,16 @@ const Tokenfactory: NextPage = () => {
|
||||
<TextInput className="w-1/2" {...denomState} />
|
||||
<AddressInput className="w-1/2" {...newAdminAddressState} />
|
||||
</Conditional>
|
||||
<button
|
||||
<Button
|
||||
className="px-4 py-2 font-bold text-white bg-stargaze rounded-md"
|
||||
isLoading={loading}
|
||||
onClick={() => {
|
||||
void handleSendMessage()
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
{getButtonName()}
|
||||
</button>
|
||||
</Button>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,18 +11,27 @@ export const WHITELIST_CODE_ID = parseInt(process.env.NEXT_PUBLIC_WHITELIST_CODE
|
||||
export const WHITELIST_FLEX_CODE_ID = parseInt(process.env.NEXT_PUBLIC_WHITELIST_FLEX_CODE_ID, 10)
|
||||
export const VENDING_MINTER_CODE_ID = parseInt(process.env.NEXT_PUBLIC_VENDING_MINTER_CODE_ID, 10)
|
||||
export const VENDING_MINTER_FLEX_CODE_ID = parseInt(process.env.NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID, 10)
|
||||
export const WHITELIST_MERKLE_TREE_CODE_ID = parseInt(process.env.NEXT_PUBLIC_WHITELIST_MERKLE_TREE_CODE_ID, 10)
|
||||
export const VENDING_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_ADDRESS
|
||||
export const FEATURED_VENDING_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_FEATURED_VENDING_FACTORY_ADDRESS
|
||||
export const VENDING_FACTORY_UPDATABLE_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS
|
||||
export const VENDING_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_FACTORY_MERKLE_TREE_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_MERKLE_TREE_ADDRESS
|
||||
export const FEATURED_VENDING_FACTORY_MERKLE_TREE_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_FEATURED_VENDING_FACTORY_MERKLE_TREE_ADDRESS
|
||||
export const FEATURED_VENDING_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_FEATURED_VENDING_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS
|
||||
export const VENDING_IBC_ATOM_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS
|
||||
export const VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS
|
||||
export const VENDING_IBC_USDC_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS
|
||||
export const FEATURED_IBC_USDC_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_FEATURED_VENDING_IBC_USDC_FACTORY_ADDRESS
|
||||
export const VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS
|
||||
export const VENDING_IBC_TIA_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_ADDRESS
|
||||
export const FEATURED_IBC_TIA_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_ADDRESS
|
||||
export const VENDING_IBC_TIA_UPDATABLE_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_ADDRESS
|
||||
export const VENDING_IBC_NBTC_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_NBTC_FACTORY_ADDRESS
|
||||
export const VENDING_IBC_NBTC_UPDATABLE_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_NBTC_UPDATABLE_FACTORY_ADDRESS
|
||||
@@ -36,8 +45,19 @@ export const VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VEN
|
||||
export const VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS
|
||||
export const FEATURED_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_FEATURED_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS
|
||||
export const FEATURED_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_MERKLE_TREE_ADDRESS
|
||||
export const FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_IBC_NBTC_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_NBTC_FACTORY_FLEX_ADDRESS
|
||||
export const VENDING_IBC_NBTC_UPDATABLE_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_VENDING_IBC_NBTC_UPDATABLE_FACTORY_FLEX_ADDRESS
|
||||
@@ -60,13 +80,23 @@ export const VENDING_NATIVE_BRNCH_FLEX_FACTORY_ADDRESS =
|
||||
export const BASE_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_BASE_FACTORY_ADDRESS
|
||||
export const BASE_FACTORY_UPDATABLE_ADDRESS = process.env.NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS
|
||||
export const OPEN_EDITION_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_FACTORY_FLEX_ADDRESS
|
||||
export const OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_IBC_ATOM_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_FLEX_ADDRESS
|
||||
export const OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_IBC_USDC_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_FLEX_ADDRESS
|
||||
export const OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_IBC_TIA_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_TIA_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_IBC_TIA_FACTORY_FLEX_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_TIA_FACTORY_FLEX_ADDRESS
|
||||
export const OPEN_EDITION_UPDATABLE_IBC_TIA_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_TIA_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_IBC_NBTC_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_NBTC_FACTORY_ADDRESS
|
||||
export const OPEN_EDITION_UPDATABLE_IBC_NBTC_FACTORY_ADDRESS =
|
||||
process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_NBTC_FACTORY_ADDRESS
|
||||
@@ -102,6 +132,8 @@ export const STARGAZE_URL = process.env.NEXT_PUBLIC_STARGAZE_WEBSITE_URL
|
||||
export const BLOCK_EXPLORER_URL = process.env.NEXT_PUBLIC_BLOCK_EXPLORER_URL
|
||||
export const WEBSITE_URL = process.env.NEXT_PUBLIC_WEBSITE_URL
|
||||
export const SYNC_COLLECTIONS_API_URL = process.env.NEXT_PUBLIC_SYNC_COLLECTIONS_API_URL
|
||||
export const WHITELIST_MERKLE_TREE_API_URL = process.env.NEXT_PUBLIC_WHITELIST_MERKLE_TREE_API_URL
|
||||
export const NFT_STORAGE_DEFAULT_API_KEY = process.env.NEXT_PUBLIC_NFT_STORAGE_DEFAULT_API_KEY
|
||||
|
||||
export const MEILISEARCH_HOST = process.env.NEXT_PUBLIC_MEILISEARCH_HOST
|
||||
export const MEILISEARCH_API_KEY = process.env.NEXT_PUBLIC_MEILISEARCH_API_KEY
|
||||
|
||||
@@ -4,14 +4,14 @@ import { toast } from 'react-hot-toast'
|
||||
import { isValidAddress } from './isValidAddress'
|
||||
|
||||
export const isValidFlexListFile = (file: WhitelistFlexMember[]) => {
|
||||
let sumOfAmounts = 0
|
||||
file.forEach((allocation) => {
|
||||
sumOfAmounts += Number(allocation.mint_count)
|
||||
})
|
||||
if (sumOfAmounts > 10000) {
|
||||
toast.error(`Total mint count should be less than 10000 tokens (current count: ${sumOfAmounts}))`)
|
||||
return false
|
||||
}
|
||||
// let sumOfAmounts = 0
|
||||
// file.forEach((allocation) => {
|
||||
// sumOfAmounts += Number(allocation.mint_count)
|
||||
// })
|
||||
// if (sumOfAmounts > 10000) {
|
||||
// toast.error(`Total mint count should be less than 10000 tokens (current count: ${sumOfAmounts}))`)
|
||||
// return false
|
||||
// }
|
||||
|
||||
const checks = file.map((account) => {
|
||||
// Check if address is valid bech32 address
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import sha256 from 'crypto-js/sha256'
|
||||
import { MerkleTree } from 'merkletreejs'
|
||||
|
||||
export class WhitelistMerkleTree {
|
||||
tree: MerkleTree
|
||||
constructor(members: string[]) {
|
||||
this.tree = new MerkleTree(
|
||||
members.map((member) => sha256(member)),
|
||||
sha256,
|
||||
{
|
||||
// sort: true,
|
||||
// hashLeaves: false,
|
||||
// sortLeaves: true,
|
||||
sortPairs: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
getMerkleRoot() {
|
||||
return this.tree.getRoot().toString('hex')
|
||||
}
|
||||
|
||||
getMerkleProof(member: string) {
|
||||
console.log('this.tree.getProof(sha256(member).toString()): ', this.tree.getProof(sha256(member).toString()))
|
||||
return this.tree.getProof(sha256(member).toString()).map((item) => item.data.toString('hex'))
|
||||
}
|
||||
|
||||
verify(proof: string[], member: string) {
|
||||
return this.tree.verify(proof, sha256(member).toString(), this.tree.getRoot())
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
import { useChain as useCosmosKitChain } from '@cosmos-kit/react'
|
||||
import { chains } from 'chain-registry'
|
||||
import { getConfig } from 'config'
|
||||
import { fangTestnet } from 'config/fangTestnet'
|
||||
|
||||
import { NETWORK } from './constants'
|
||||
|
||||
@@ -9,7 +10,7 @@ import { NETWORK } from './constants'
|
||||
*/
|
||||
export const useWallet = () => {
|
||||
const { chainId } = getConfig(NETWORK)
|
||||
const chain = chains.find((c) => c.chain_id === chainId)
|
||||
const chain = chains.concat([fangTestnet]).find((c) => c.chain_id === chainId)
|
||||
if (!chain) {
|
||||
throw new Error('Chain not found')
|
||||
}
|
||||
|
||||
@@ -2295,6 +2295,20 @@
|
||||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@ethereumjs/rlp@^4.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41"
|
||||
integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==
|
||||
|
||||
"@ethereumjs/util@^8.1.0":
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4"
|
||||
integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==
|
||||
dependencies:
|
||||
"@ethereumjs/rlp" "^4.0.1"
|
||||
ethereum-cryptography "^2.0.0"
|
||||
micro-ftch "^0.3.1"
|
||||
|
||||
"@ethersproject/address@^5.6.0":
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37"
|
||||
@@ -2803,11 +2817,28 @@
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.5.tgz#02f377e4d41eaaacf265e34bab9bacd8efc4a351"
|
||||
integrity sha512-/SoXW1Ntpmpw3AXAzfDRaQidnd8kbZ2oSni8u5z0yw6t4RwJvmdZy1eOaAADRThWKV+2oU90++LSnXJIwBRWYQ==
|
||||
|
||||
"@noble/curves@1.3.0", "@noble/curves@~1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e"
|
||||
integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==
|
||||
dependencies:
|
||||
"@noble/hashes" "1.3.3"
|
||||
|
||||
"@noble/hashes@1.3.3", "@noble/hashes@~1.3.2":
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
|
||||
integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
|
||||
|
||||
"@noble/hashes@^1", "@noble/hashes@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.0.0.tgz"
|
||||
integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==
|
||||
|
||||
"@noble/hashes@^1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426"
|
||||
integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
|
||||
@@ -2908,6 +2939,28 @@
|
||||
resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.1.tgz"
|
||||
integrity sha512-BUyKJGdDWqvWC5GEhyOiUrGNi9iJUr4CU0O2WxJL6QJhHeeA/NVBalH+FeK0r/x/W0rPymXt5s78TDS7d6lCwg==
|
||||
|
||||
"@scure/base@~1.1.4":
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.6.tgz#8ce5d304b436e4c84f896e0550c83e4d88cb917d"
|
||||
integrity sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==
|
||||
|
||||
"@scure/bip32@1.3.3":
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8"
|
||||
integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==
|
||||
dependencies:
|
||||
"@noble/curves" "~1.3.0"
|
||||
"@noble/hashes" "~1.3.2"
|
||||
"@scure/base" "~1.1.4"
|
||||
|
||||
"@scure/bip39@1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527"
|
||||
integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==
|
||||
dependencies:
|
||||
"@noble/hashes" "~1.3.2"
|
||||
"@scure/base" "~1.1.4"
|
||||
|
||||
"@stablelib/aead@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@stablelib/aead/-/aead-1.0.1.tgz#c4b1106df9c23d1b867eb9b276d8f42d5fc4c0c3"
|
||||
@@ -3184,6 +3237,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@typeform/embed/-/embed-2.11.0.tgz#97ab13d8c010a87bd2586b95b4d44c27859ba671"
|
||||
integrity sha512-MEckCfqsqj4z00w5b3D4nK1ix4Elm15L4xsgAkFX7NuCLETa9TZD/vqARlBb63yqR5tPD4LW1mw/ftBBoeIQgA==
|
||||
|
||||
"@types/crypto-js@4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.2.1.tgz#480edd76991a63050cb88db1a8840758c55a7135"
|
||||
integrity sha512-FSPGd9+OcSok3RsM0UZ/9fcvMOXJ1ENE/ZbLfOPlBWj7BgXtEAM8VYfTtT760GiLbQIMoVozwVuisjvsVwqYWw==
|
||||
|
||||
"@types/glob@*":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz"
|
||||
@@ -4230,7 +4288,7 @@ big-integer@^1.6.16, big-integer@^1.6.48:
|
||||
resolved "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz"
|
||||
integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==
|
||||
|
||||
bignumber.js@^9.1.1, bignumber.js@^9.1.2:
|
||||
bignumber.js@^9.0.1, bignumber.js@^9.1.1, bignumber.js@^9.1.2:
|
||||
version "9.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c"
|
||||
integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==
|
||||
@@ -4300,6 +4358,11 @@ blockstore-core@^1.0.2:
|
||||
it-take "^1.0.1"
|
||||
multiformats "^9.4.7"
|
||||
|
||||
bn.js@4.11.6:
|
||||
version "4.11.6"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
|
||||
integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==
|
||||
|
||||
bn.js@^4.11.8, bn.js@^4.11.9:
|
||||
version "4.12.0"
|
||||
resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz"
|
||||
@@ -4391,6 +4454,11 @@ bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2:
|
||||
create-hash "^1.1.0"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
buffer-reverse@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-reverse/-/buffer-reverse-1.0.1.tgz#49283c8efa6f901bc01fa3304d06027971ae2f60"
|
||||
integrity sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==
|
||||
|
||||
buffer@^5.5.0, buffer@^5.6.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||
@@ -4770,11 +4838,16 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypto-js@^4.0.0:
|
||||
crypto-js@4.1.1, crypto-js@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz"
|
||||
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
|
||||
|
||||
crypto-js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
|
||||
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
|
||||
|
||||
css-select@^4.1.3:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz"
|
||||
@@ -5542,6 +5615,31 @@ eth-rpc-errors@^4.0.2:
|
||||
dependencies:
|
||||
fast-safe-stringify "^2.0.6"
|
||||
|
||||
ethereum-bloom-filters@^1.0.6:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.1.0.tgz#b3fc1eb789509ee30db0bf99a2988ccacb8d0397"
|
||||
integrity sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw==
|
||||
dependencies:
|
||||
"@noble/hashes" "^1.4.0"
|
||||
|
||||
ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a"
|
||||
integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==
|
||||
dependencies:
|
||||
"@noble/curves" "1.3.0"
|
||||
"@noble/hashes" "1.3.3"
|
||||
"@scure/bip32" "1.3.3"
|
||||
"@scure/bip39" "1.2.2"
|
||||
|
||||
ethjs-unit@0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699"
|
||||
integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==
|
||||
dependencies:
|
||||
bn.js "4.11.6"
|
||||
number-to-bn "1.7.0"
|
||||
|
||||
event-emitter@^0.3.5:
|
||||
version "0.3.5"
|
||||
resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz"
|
||||
@@ -6358,6 +6456,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-hex-prefixed@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
|
||||
integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==
|
||||
|
||||
is-ip@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz"
|
||||
@@ -6967,6 +7070,22 @@ merge2@^1.3.0, merge2@^1.4.1:
|
||||
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
merkletreejs@0.3.11:
|
||||
version "0.3.11"
|
||||
resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.3.11.tgz#e0de05c3ca1fd368de05a12cb8efb954ef6fc04f"
|
||||
integrity sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==
|
||||
dependencies:
|
||||
bignumber.js "^9.0.1"
|
||||
buffer-reverse "^1.0.1"
|
||||
crypto-js "^4.2.0"
|
||||
treeify "^1.1.0"
|
||||
web3-utils "^1.3.4"
|
||||
|
||||
micro-ftch@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f"
|
||||
integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==
|
||||
|
||||
micromatch@^4.0.4:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz"
|
||||
@@ -7333,6 +7452,14 @@ nth-check@^2.0.1:
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
|
||||
number-to-bn@1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0"
|
||||
integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==
|
||||
dependencies:
|
||||
bn.js "4.11.6"
|
||||
strip-hex-prefix "1.0.0"
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
|
||||
@@ -7823,7 +7950,7 @@ rainbow-sprinkles@^0.17.0:
|
||||
resolved "https://registry.yarnpkg.com/rainbow-sprinkles/-/rainbow-sprinkles-0.17.0.tgz#6ee06c6decc767b89bf01fc5fe87ecf859fd4c2f"
|
||||
integrity sha512-ok3NrylQ0szvJtuBYaB/w09L9zOvvqcSQrvycT2A5XJxQNvwvkeADvTqQWGOQ3b6MkO8UmYccBPt8g8vVvxM9A==
|
||||
|
||||
randombytes@^2.0.1:
|
||||
randombytes@^2.0.1, randombytes@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz"
|
||||
integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
|
||||
@@ -8584,6 +8711,13 @@ strip-final-newline@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz"
|
||||
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
|
||||
|
||||
strip-hex-prefix@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f"
|
||||
integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==
|
||||
dependencies:
|
||||
is-hex-prefixed "1.0.0"
|
||||
|
||||
strip-indent@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz"
|
||||
@@ -8775,6 +8909,11 @@ toggle-selection@^1.0.6:
|
||||
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
|
||||
integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==
|
||||
|
||||
treeify@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8"
|
||||
integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==
|
||||
|
||||
trim-newlines@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz"
|
||||
@@ -8936,6 +9075,11 @@ use-sync-external-store@1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||
|
||||
utf8@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1"
|
||||
integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
@@ -9012,6 +9156,20 @@ web-streams-polyfill@^3.1.1:
|
||||
resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz"
|
||||
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
|
||||
|
||||
web3-utils@^1.3.4:
|
||||
version "1.10.4"
|
||||
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.4.tgz#0daee7d6841641655d8b3726baf33b08eda1cbec"
|
||||
integrity sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==
|
||||
dependencies:
|
||||
"@ethereumjs/util" "^8.1.0"
|
||||
bn.js "^5.2.1"
|
||||
ethereum-bloom-filters "^1.0.6"
|
||||
ethereum-cryptography "^2.1.2"
|
||||
ethjs-unit "0.1.6"
|
||||
number-to-bn "1.7.0"
|
||||
randombytes "^2.1.0"
|
||||
utf8 "3.0.0"
|
||||
|
||||
"webextension-polyfill@>=0.10.0 <1.0", webextension-polyfill@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz#ccb28101c910ba8cf955f7e6a263e662d744dbb8"
|
||||
|
||||
Reference in New Issue
Block a user