Merge pull request #354 from public-awesome/develop

Sync dev > main
This commit is contained in:
Serkan Reis 2024-04-02 23:24:14 +03:00 committed by GitHub
commit 29cd89f6a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 968 additions and 47 deletions

View File

@ -16,8 +16,9 @@ NEXT_PUBLIC_VENDING_FACTORY_ADDRESS="stars18h7ugh8eaug7wr0w4yjw0ls5s937z35pnkg93
NEXT_PUBLIC_FEATURED_VENDING_FACTORY_ADDRESS="stars14pd96yk3t6gq9l6uyrkg0n5dr09n8rt5y9v3at8x4wl4lrkxhlzq4trqmh" NEXT_PUBLIC_FEATURED_VENDING_FACTORY_ADDRESS="stars14pd96yk3t6gq9l6uyrkg0n5dr09n8rt5y9v3at8x4wl4lrkxhlzq4trqmh"
NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS="stars1h65nms9gwg4vdktyqj84tu50gwlm34e0eczl5w2ezllxuzfxy9esa9qlt0" NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS="stars1h65nms9gwg4vdktyqj84tu50gwlm34e0eczl5w2ezllxuzfxy9esa9qlt0"
NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftslp2rwkkkcxy269a35a9pq60ug2q" NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftslp2rwkkkcxy269a35a9pq60ug2q"
NEXT_PUBLIC_VENDING_FACTORY_MERKLE_TREE_ADDRESS="stars167tudcsr9n2y9ljgk4cwxhs0cvkfkk0hh6c3dzngsz7m5s9jmqnsdgr3jy"
NEXT_PUBLIC_FEATURED_VENDING_FACTORY_FLEX_ADDRESS="stars1udlmmnmmnnqamh36hy6d7azn3ycv23yymkmg6558ntalvyt2pz7s8lhgcd" 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_FACTORY_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS= # NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS=
@ -40,6 +41,7 @@ NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS=
# NEXT_PUBLIC_FEATURED_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_UPDATABLE_FACTORY_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_TIA_FACTORY_FLEX_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_FLEX_ADDRESS= # NEXT_PUBLIC_FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS= # NEXT_PUBLIC_VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS=
@ -100,6 +102,7 @@ NEXT_PUBLIC_ROYALTY_REGISTRY_ADDRESS="stars1crgx0f70fzksa57hq87wtl8f04h0qyk5la0h
NEXT_PUBLIC_INFINITY_SWAP_PROTOCOL_ADDRESS="stars136yp6fl9h66m0cwv8weu4w4aawveuz40992ty0atj5ecjd8z0thqv9xpy5" NEXT_PUBLIC_INFINITY_SWAP_PROTOCOL_ADDRESS="stars136yp6fl9h66m0cwv8weu4w4aawveuz40992ty0atj5ecjd8z0thqv9xpy5"
NEXT_PUBLIC_WHITELIST_CODE_ID=3131 NEXT_PUBLIC_WHITELIST_CODE_ID=3131
NEXT_PUBLIC_WHITELIST_FLEX_CODE_ID=3130 NEXT_PUBLIC_WHITELIST_FLEX_CODE_ID=3130
NEXT_PUBLIC_WHITELIST_MERKLE_TREE_CODE_ID=3625
NEXT_PUBLIC_BADGE_HUB_CODE_ID=1336 NEXT_PUBLIC_BADGE_HUB_CODE_ID=1336
NEXT_PUBLIC_BADGE_HUB_ADDRESS="stars1dacun0xn7z73qzdcmq27q3xn6xuprg8e2ugj364784al2v27tklqynhuqa" NEXT_PUBLIC_BADGE_HUB_ADDRESS="stars1dacun0xn7z73qzdcmq27q3xn6xuprg8e2ugj364784al2v27tklqynhuqa"
NEXT_PUBLIC_BADGE_NFT_CODE_ID=1337 NEXT_PUBLIC_BADGE_NFT_CODE_ID=1337
@ -114,6 +117,7 @@ NEXT_PUBLIC_STARGAZE_WEBSITE_URL=https://testnet.publicawesome.dev
NEXT_PUBLIC_BADGES_URL=https://badges.publicawesome.dev NEXT_PUBLIC_BADGES_URL=https://badges.publicawesome.dev
NEXT_PUBLIC_WEBSITE_URL=https:// NEXT_PUBLIC_WEBSITE_URL=https://
NEXT_PUBLIC_SYNC_COLLECTIONS_API_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_NFT_STORAGE_DEFAULT_API_KEY="..."
NEXT_PUBLIC_MEILISEARCH_HOST="https://search.publicawesome.dev" NEXT_PUBLIC_MEILISEARCH_HOST="https://search.publicawesome.dev"

View File

@ -78,7 +78,7 @@ export const WhitelistUpload = ({ onChange }: WhitelistUploadProps) => {
const printableData = data?.map((item) => item.replace(regex, '')) const printableData = data?.map((item) => item.replace(regex, ''))
const names = printableData?.filter((address) => address !== '' && address.endsWith('.stars')) const names = printableData?.filter((address) => address !== '' && address.endsWith('.stars'))
const strippedNames = names?.map((name) => name.split('.')[0]) const strippedNames = names?.map((name) => name.split('.')[0])
console.log(names) console.log('names: ', names)
if (strippedNames?.length) { if (strippedNames?.length) {
await toast await toast
.promise(resolveAddresses(strippedNames), { .promise(resolveAddresses(strippedNames), {

View File

@ -43,7 +43,7 @@ export interface WhitelistDetailsDataProps {
type WhitelistState = 'none' | 'existing' | 'new' type WhitelistState = 'none' | 'existing' | 'new'
type WhitelistType = 'standard' | 'flex' type WhitelistType = 'standard' | 'flex' | 'merkletree'
export const WhitelistDetails = ({ export const WhitelistDetails = ({
onChange, onChange,
@ -59,6 +59,7 @@ export const WhitelistDetails = ({
const [endDate, setEndDate] = useState<Date | undefined>(undefined) const [endDate, setEndDate] = useState<Date | undefined>(undefined)
const [whitelistStandardArray, setWhitelistStandardArray] = useState<string[]>([]) const [whitelistStandardArray, setWhitelistStandardArray] = useState<string[]>([])
const [whitelistFlexArray, setWhitelistFlexArray] = useState<WhitelistFlexMember[]>([]) const [whitelistFlexArray, setWhitelistFlexArray] = useState<WhitelistFlexMember[]>([])
const [whitelistMerkleTreeArray, setWhitelistMerkleTreeArray] = useState<string[]>([])
const [adminsMutable, setAdminsMutable] = useState<boolean>(true) const [adminsMutable, setAdminsMutable] = useState<boolean>(true)
const whitelistAddressState = useInputState({ const whitelistAddressState = useInputState({
@ -97,7 +98,8 @@ export const WhitelistDetails = ({
const addressListState = useAddressListState() const addressListState = useAddressListState()
const whitelistFileOnChange = (data: string[]) => { const whitelistFileOnChange = (data: string[]) => {
setWhitelistStandardArray(data) if (whitelistType === 'standard') setWhitelistStandardArray(data)
if (whitelistType === 'merkletree') setWhitelistMerkleTreeArray(data)
} }
const whitelistFlexFileOnChange = (whitelistData: WhitelistFlexMember[]) => { const whitelistFlexFileOnChange = (whitelistData: WhitelistFlexMember[]) => {
@ -130,6 +132,7 @@ export const WhitelistDetails = ({
if (!importedWhitelistDetails) { if (!importedWhitelistDetails) {
setWhitelistStandardArray([]) setWhitelistStandardArray([])
setWhitelistFlexArray([]) setWhitelistFlexArray([])
setWhitelistMerkleTreeArray([])
} }
}, [whitelistType]) }, [whitelistType])
@ -143,7 +146,12 @@ export const WhitelistDetails = ({
.replace(/"/g, '') .replace(/"/g, '')
.replace(/'/g, '') .replace(/'/g, '')
.replace(/ /g, ''), .replace(/ /g, ''),
members: whitelistType === 'standard' ? whitelistStandardArray : whitelistFlexArray, members:
whitelistType === 'standard'
? whitelistStandardArray
: whitelistType === 'merkletree'
? whitelistMerkleTreeArray
: whitelistFlexArray,
unitPrice: unitPriceState.value unitPrice: unitPriceState.value
? (Number(unitPriceState.value) * 1_000_000).toString() ? (Number(unitPriceState.value) * 1_000_000).toString()
: unitPriceState.value === 0 : unitPriceState.value === 0
@ -173,7 +181,9 @@ export const WhitelistDetails = ({
endDate, endDate,
whitelistStandardArray, whitelistStandardArray,
whitelistFlexArray, whitelistFlexArray,
whitelistMerkleTreeArray,
whitelistState, whitelistState,
whitelistType,
addressListState.values, addressListState.values,
adminsMutable, adminsMutable,
]) ])
@ -211,7 +221,12 @@ export const WhitelistDetails = ({
importedWhitelistDetails.members?.forEach((member) => { importedWhitelistDetails.members?.forEach((member) => {
setWhitelistStandardArray((standardArray) => [...standardArray, member as string]) 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([]) setWhitelistFlexArray([])
importedWhitelistDetails.members?.forEach((member) => { importedWhitelistDetails.members?.forEach((member) => {
setWhitelistFlexArray((flexArray) => [ setWhitelistFlexArray((flexArray) => [
@ -303,7 +318,7 @@ export const WhitelistDetails = ({
</Conditional> </Conditional>
<Conditional test={whitelistState === 'new'}> <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"> <div className="form-check form-check-inline">
<input <input
checked={whitelistType === 'standard'} checked={whitelistType === 'standard'}
@ -314,7 +329,7 @@ export const WhitelistDetails = ({
setWhitelistType('standard') setWhitelistType('standard')
}} }}
type="radio" type="radio"
value="nft-storage" value="standard"
/> />
<label <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" 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"
@ -343,12 +358,33 @@ export const WhitelistDetails = ({
Whitelist Flex Whitelist Flex
</label> </label>
</div> </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>
<div className="grid grid-cols-2"> <div className="grid grid-cols-2">
<FormGroup subtitle="Information about your minting settings" title="Whitelist Minting Details"> <FormGroup subtitle="Information about your minting settings" title="Whitelist Minting Details">
<NumberInput isRequired {...unitPriceState} /> <NumberInput isRequired {...unitPriceState} />
<NumberInput isRequired {...memberLimitState} /> <Conditional test={whitelistType !== 'merkletree'}>
<Conditional test={whitelistType === 'standard'}> <NumberInput isRequired {...memberLimitState} />
</Conditional>
<Conditional test={whitelistType === 'standard' || whitelistType === 'merkletree'}>
<NumberInput isRequired {...perAddressLimitState} /> <NumberInput isRequired {...perAddressLimitState} />
</Conditional> </Conditional>
<FormControl <FormControl
@ -466,6 +502,24 @@ export const WhitelistDetails = ({
<JsonPreview content={whitelistFlexArray} initialState={false} title="File Contents" /> <JsonPreview content={whitelistFlexArray} initialState={false} title="File Contents" />
</Conditional> </Conditional>
</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>
</div> </div>
</Conditional> </Conditional>

View File

@ -628,6 +628,7 @@ export const OpenEditionMinterCreator = ({
num_tokens: num_tokens:
mintingDetails?.limitType === ('count_limited' as LimitType) ? mintingDetails.tokenCountLimit : null, mintingDetails?.limitType === ('count_limited' as LimitType) ? mintingDetails.tokenCountLimit : null,
payment_address: mintingDetails?.paymentAddress || null, payment_address: mintingDetails?.paymentAddress || null,
// whitelist: null,
}, },
collection_params: { collection_params: {
code_id: collectionDetails?.updatable code_id: collectionDetails?.updatable

View File

@ -26,6 +26,7 @@ import {
OPEN_EDITION_UPDATABLE_IBC_USK_FACTORY_ADDRESS, OPEN_EDITION_UPDATABLE_IBC_USK_FACTORY_ADDRESS,
VENDING_FACTORY_ADDRESS, VENDING_FACTORY_ADDRESS,
VENDING_FACTORY_FLEX_ADDRESS, VENDING_FACTORY_FLEX_ADDRESS,
VENDING_FACTORY_MERKLE_TREE_ADDRESS,
VENDING_FACTORY_UPDATABLE_ADDRESS, VENDING_FACTORY_UPDATABLE_ADDRESS,
VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS, VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS,
VENDING_IBC_ATOM_FACTORY_ADDRESS, VENDING_IBC_ATOM_FACTORY_ADDRESS,
@ -44,6 +45,7 @@ import {
VENDING_IBC_NBTC_UPDATABLE_FACTORY_FLEX_ADDRESS, VENDING_IBC_NBTC_UPDATABLE_FACTORY_FLEX_ADDRESS,
VENDING_IBC_TIA_FACTORY_ADDRESS, VENDING_IBC_TIA_FACTORY_ADDRESS,
VENDING_IBC_TIA_FACTORY_FLEX_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_ADDRESS,
VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS, VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS,
VENDING_IBC_USDC_FACTORY_ADDRESS, VENDING_IBC_USDC_FACTORY_ADDRESS,
@ -84,6 +86,7 @@ export interface MinterInfo {
supportedToken: TokenInfo supportedToken: TokenInfo
updatable?: boolean updatable?: boolean
flexible?: boolean flexible?: boolean
merkleTree?: boolean
featured?: boolean featured?: boolean
} }
@ -267,6 +270,7 @@ export const vendingStarsMinter: MinterInfo = {
supportedToken: stars, supportedToken: stars,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -276,6 +280,7 @@ export const vendingFeaturedStarsMinter: MinterInfo = {
supportedToken: stars, supportedToken: stars,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: true, featured: true,
} }
@ -285,6 +290,7 @@ export const vendingUpdatableStarsMinter: MinterInfo = {
supportedToken: stars, supportedToken: stars,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -294,6 +300,7 @@ export const vendingIbcAtomMinter: MinterInfo = {
supportedToken: ibcAtom, supportedToken: ibcAtom,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -303,6 +310,7 @@ export const vendingUpdatableIbcAtomMinter: MinterInfo = {
supportedToken: ibcAtom, supportedToken: ibcAtom,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -312,6 +320,7 @@ export const vendingIbcUsdcMinter: MinterInfo = {
supportedToken: ibcUsdc, supportedToken: ibcUsdc,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -321,6 +330,7 @@ export const vendingFeaturedIbcUsdcMinter: MinterInfo = {
supportedToken: ibcUsdc, supportedToken: ibcUsdc,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: true, featured: true,
} }
@ -330,6 +340,7 @@ export const vendingIbcTiaMinter: MinterInfo = {
supportedToken: ibcTia, supportedToken: ibcTia,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -339,6 +350,7 @@ export const vendingFeaturedIbcTiaMinter: MinterInfo = {
supportedToken: ibcTia, supportedToken: ibcTia,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: true, featured: true,
} }
@ -348,6 +360,7 @@ export const vendingIbcNbtcMinter: MinterInfo = {
supportedToken: ibcNbtc, supportedToken: ibcNbtc,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -357,6 +370,7 @@ export const vendingUpdatableIbcUsdcMinter: MinterInfo = {
supportedToken: ibcUsdc, supportedToken: ibcUsdc,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -366,6 +380,7 @@ export const vendingUpdatableIbcTiaMinter: MinterInfo = {
supportedToken: ibcTia, supportedToken: ibcTia,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -375,6 +390,7 @@ export const vendingUpdatableIbcNbtcMinter: MinterInfo = {
supportedToken: ibcNbtc, supportedToken: ibcNbtc,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -384,6 +400,7 @@ export const vendingIbcUskMinter: MinterInfo = {
supportedToken: ibcUsk, supportedToken: ibcUsk,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -393,6 +410,7 @@ export const vendingUpdatableIbcUskMinter: MinterInfo = {
supportedToken: ibcUsk, supportedToken: ibcUsk,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -402,6 +420,7 @@ export const vendingIbcKujiMinter: MinterInfo = {
supportedToken: ibcKuji, supportedToken: ibcKuji,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -411,6 +430,7 @@ export const vendingIbcHuahuaMinter: MinterInfo = {
supportedToken: ibcHuahua, supportedToken: ibcHuahua,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -420,6 +440,7 @@ export const vendingIbcCrbrusMinter: MinterInfo = {
supportedToken: ibcCrbrus, supportedToken: ibcCrbrus,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -429,6 +450,7 @@ export const vendingNativeStardustMinter: MinterInfo = {
supportedToken: nativeStardust, supportedToken: nativeStardust,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -438,6 +460,7 @@ export const vendingUpdatableNativeStardustMinter: MinterInfo = {
supportedToken: nativeStardust, supportedToken: nativeStardust,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -447,6 +470,7 @@ export const vendingNativeBrnchMinter: MinterInfo = {
supportedToken: nativeBrnch, supportedToken: nativeBrnch,
updatable: false, updatable: false,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -456,6 +480,7 @@ export const vendingUpdatableNativeBrnchMinter: MinterInfo = {
supportedToken: nativeBrnch, supportedToken: nativeBrnch,
updatable: true, updatable: true,
flexible: false, flexible: false,
merkleTree: false,
featured: false, featured: false,
} }
@ -490,6 +515,7 @@ export const flexibleVendingStarsMinter: MinterInfo = {
supportedToken: stars, supportedToken: stars,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -499,6 +525,7 @@ export const flexibleFeaturedVendingStarsMinter: MinterInfo = {
supportedToken: stars, supportedToken: stars,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: true, featured: true,
} }
@ -508,6 +535,7 @@ export const flexibleVendingUpdatableStarsMinter: MinterInfo = {
supportedToken: stars, supportedToken: stars,
updatable: true, updatable: true,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -517,6 +545,7 @@ export const flexibleVendingIbcAtomMinter: MinterInfo = {
supportedToken: ibcAtom, supportedToken: ibcAtom,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -526,6 +555,7 @@ export const flexibleVendingUpdatableIbcAtomMinter: MinterInfo = {
supportedToken: ibcAtom, supportedToken: ibcAtom,
updatable: true, updatable: true,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -535,6 +565,7 @@ export const flexibleVendingIbcUsdcMinter: MinterInfo = {
supportedToken: ibcUsdc, supportedToken: ibcUsdc,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -544,6 +575,7 @@ export const flexibleFeaturedVendingIbcUsdcMinter: MinterInfo = {
supportedToken: ibcUsdc, supportedToken: ibcUsdc,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: true, featured: true,
} }
@ -553,6 +585,7 @@ export const flexibleVendingIbcTiaMinter: MinterInfo = {
supportedToken: ibcTia, supportedToken: ibcTia,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -562,6 +595,7 @@ export const flexibleFeaturedVendingIbcTiaMinter: MinterInfo = {
supportedToken: ibcTia, supportedToken: ibcTia,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: true, featured: true,
} }
@ -571,6 +605,7 @@ export const flexibleVendingIbcNbtcMinter: MinterInfo = {
supportedToken: ibcNbtc, supportedToken: ibcNbtc,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -580,6 +615,7 @@ export const flexibleVendingUpdatableIbcUsdcMinter: MinterInfo = {
supportedToken: ibcUsdc, supportedToken: ibcUsdc,
updatable: true, updatable: true,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -589,6 +625,7 @@ export const flexibleVendingUpdatableIbcTiaMinter: MinterInfo = {
supportedToken: ibcTia, supportedToken: ibcTia,
updatable: true, updatable: true,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -598,6 +635,7 @@ export const flexibleVendingUpdatableIbcNbtcMinter: MinterInfo = {
supportedToken: ibcNbtc, supportedToken: ibcNbtc,
updatable: true, updatable: true,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -607,6 +645,7 @@ export const flexibleVendingIbcUskMinter: MinterInfo = {
supportedToken: ibcUsk, supportedToken: ibcUsk,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -616,6 +655,7 @@ export const flexibleVendingUpdatableIbcUskMinter: MinterInfo = {
supportedToken: ibcUsk, supportedToken: ibcUsk,
updatable: true, updatable: true,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -625,6 +665,7 @@ export const flexibleVendingIbcKujiMinter: MinterInfo = {
supportedToken: ibcKuji, supportedToken: ibcKuji,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -634,6 +675,7 @@ export const flexibleVendingIbcHuahuaMinter: MinterInfo = {
supportedToken: ibcHuahua, supportedToken: ibcHuahua,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -643,6 +685,7 @@ export const flexibleVendingIbcCrbrusMinter: MinterInfo = {
supportedToken: ibcCrbrus, supportedToken: ibcCrbrus,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -652,6 +695,7 @@ export const flexibleVendingStrdstMinter: MinterInfo = {
supportedToken: nativeStardust, supportedToken: nativeStardust,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -661,6 +705,7 @@ export const flexibleVendingBrnchMinter: MinterInfo = {
supportedToken: nativeBrnch, supportedToken: nativeBrnch,
updatable: false, updatable: false,
flexible: true, flexible: true,
merkleTree: false,
featured: false, featured: false,
} }
@ -686,3 +731,25 @@ export const flexibleVendingMinterList = [
flexibleVendingStrdstMinter, flexibleVendingStrdstMinter,
flexibleVendingBrnchMinter, 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 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 merkleTreeVendingMinterList = [merkleTreeVendingStarsMinter, merkleTreeVendingIbcTiaMinter]

View File

@ -16,6 +16,7 @@ import type { UseVendingMinterContractProps } from 'contracts/vendingMinter'
import { useVendingMinterContract } from 'contracts/vendingMinter' import { useVendingMinterContract } from 'contracts/vendingMinter'
import type { UseWhiteListContractProps } from 'contracts/whitelist' import type { UseWhiteListContractProps } from 'contracts/whitelist'
import { useWhiteListContract } from 'contracts/whitelist' import { useWhiteListContract } from 'contracts/whitelist'
import { type UseWhiteListMerkleTreeContractProps, useWhiteListMerkleTreeContract } from 'contracts/whitelistMerkleTree'
import type { ReactNode, VFC } from 'react' import type { ReactNode, VFC } from 'react'
import { Fragment, useEffect } from 'react' import { Fragment, useEffect } from 'react'
import { create } from 'zustand' import { create } from 'zustand'
@ -32,6 +33,7 @@ export interface ContractsStore {
baseMinter: UseBaseMinterContractProps | null baseMinter: UseBaseMinterContractProps | null
openEditionMinter: UseOpenEditionMinterContractProps | null openEditionMinter: UseOpenEditionMinterContractProps | null
whitelist: UseWhiteListContractProps | null whitelist: UseWhiteListContractProps | null
whitelistMerkleTree: UseWhiteListMerkleTreeContractProps | null
vendingFactory: UseVendingFactoryContractProps | null vendingFactory: UseVendingFactoryContractProps | null
baseFactory: UseBaseFactoryContractProps | null baseFactory: UseBaseFactoryContractProps | null
openEditionFactory: UseOpenEditionFactoryContractProps | null openEditionFactory: UseOpenEditionFactoryContractProps | null
@ -49,6 +51,7 @@ export const defaultValues: ContractsStore = {
baseMinter: null, baseMinter: null,
openEditionMinter: null, openEditionMinter: null,
whitelist: null, whitelist: null,
whitelistMerkleTree: null,
vendingFactory: null, vendingFactory: null,
baseFactory: null, baseFactory: null,
openEditionFactory: null, openEditionFactory: null,
@ -83,6 +86,7 @@ const ContractsSubscription: VFC = () => {
const baseMinter = useBaseMinterContract() const baseMinter = useBaseMinterContract()
const openEditionMinter = useOpenEditionMinterContract() const openEditionMinter = useOpenEditionMinterContract()
const whitelist = useWhiteListContract() const whitelist = useWhiteListContract()
const whitelistMerkleTree = useWhiteListMerkleTreeContract()
const vendingFactory = useVendingFactoryContract() const vendingFactory = useVendingFactoryContract()
const baseFactory = useBaseFactoryContract() const baseFactory = useBaseFactoryContract()
const openEditionFactory = useOpenEditionFactoryContract() const openEditionFactory = useOpenEditionFactoryContract()
@ -97,6 +101,7 @@ const ContractsSubscription: VFC = () => {
baseMinter, baseMinter,
openEditionMinter, openEditionMinter,
whitelist, whitelist,
whitelistMerkleTree,
vendingFactory, vendingFactory,
baseFactory, baseFactory,
openEditionFactory, openEditionFactory,
@ -104,7 +109,20 @@ const ContractsSubscription: VFC = () => {
splits, splits,
royaltyRegistry, royaltyRegistry,
}) })
}, [sg721, vendingMinter, baseMinter, whitelist, vendingFactory, baseFactory, badgeHub, splits, royaltyRegistry]) }, [
sg721,
vendingMinter,
baseMinter,
whitelist,
whitelistMerkleTree,
vendingFactory,
baseFactory,
badgeHub,
splits,
royaltyRegistry,
openEditionMinter,
openEditionFactory,
])
return null return null
} }

View File

@ -0,0 +1,374 @@
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import type { 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_uri: {},
})
}
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,
})
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 }
}

View File

@ -0,0 +1,2 @@
export * from './contract'
export * from './useContract'

View File

@ -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)
}

View File

@ -0,0 +1,66 @@
import type { WhiteListMerkleTreeInstance } from '../contract'
export type QueryType = typeof QUERY_TYPES[number]
export const QUERY_TYPES = [
'has_started',
'has_ended',
'is_active',
'admin_list',
'has_member',
'config',
'merkle_root',
'merkle_tree_uri',
] as const
export interface QueryListItem {
id: QueryType
name: string
description?: string
}
export const 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: QueryType
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')
}
}
}

View File

@ -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,
}
}

4
env.d.ts vendored
View File

@ -22,12 +22,14 @@ declare namespace NodeJS {
readonly NEXT_PUBLIC_OPEN_EDITION_SG721_UPDATABLE_CODE_ID: string readonly NEXT_PUBLIC_OPEN_EDITION_SG721_UPDATABLE_CODE_ID: string
readonly NEXT_PUBLIC_WHITELIST_CODE_ID: string readonly NEXT_PUBLIC_WHITELIST_CODE_ID: string
readonly NEXT_PUBLIC_WHITELIST_FLEX_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_CODE_ID: string
readonly NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID: string readonly NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID: string
readonly NEXT_PUBLIC_VENDING_FACTORY_ADDRESS: string readonly NEXT_PUBLIC_VENDING_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_FEATURED_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_UPDATABLE_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_FACTORY_FLEX_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_FLEX_ADDRESS: string readonly NEXT_PUBLIC_FEATURED_VENDING_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_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_FACTORY_ADDRESS: string
@ -54,6 +56,7 @@ declare namespace NodeJS {
readonly NEXT_PUBLIC_FEATURED_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_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_TIA_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_FLEX_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_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_NBTC_FACTORY_FLEX_ADDRESS: string readonly NEXT_PUBLIC_VENDING_IBC_NBTC_FACTORY_FLEX_ADDRESS: string
@ -114,6 +117,7 @@ declare namespace NodeJS {
readonly NEXT_PUBLIC_STARGAZE_WEBSITE_URL: string readonly NEXT_PUBLIC_STARGAZE_WEBSITE_URL: string
readonly NEXT_PUBLIC_WEBSITE_URL: string readonly NEXT_PUBLIC_WEBSITE_URL: string
readonly NEXT_PUBLIC_SYNC_COLLECTIONS_API_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_NFT_STORAGE_DEFAULT_API_KEY: string
readonly NEXT_PUBLIC_MEILISEARCH_HOST: string readonly NEXT_PUBLIC_MEILISEARCH_HOST: string

View File

@ -23,8 +23,11 @@
"@cosmos-kit/leap": "^2.4.3", "@cosmos-kit/leap": "^2.4.3",
"@cosmos-kit/leap-metamask-cosmos-snap": "^0.3.3", "@cosmos-kit/leap-metamask-cosmos-snap": "^0.3.3",
"@cosmos-kit/react": "^2.9.3", "@cosmos-kit/react": "^2.9.3",
"crypto-js": "4.1.1",
"@types/crypto-js": "4.2.1",
"@fontsource/jetbrains-mono": "^4", "@fontsource/jetbrains-mono": "^4",
"@fontsource/roboto": "^4", "@fontsource/roboto": "^4",
"merkletreejs": "0.3.11",
"@leapwallet/cosmos-snap-provider": "0.1.24", "@leapwallet/cosmos-snap-provider": "0.1.24",
"@pinata/sdk": "^1.1.26", "@pinata/sdk": "^1.1.26",
"@popperjs/core": "^2", "@popperjs/core": "^2",

View File

@ -34,7 +34,12 @@ import { FormControl } from 'components/FormControl'
import { LoadingModal } from 'components/LoadingModal' import { LoadingModal } from 'components/LoadingModal'
import type { OpenEditionMinterCreatorDataProps } from 'components/openEdition/OpenEditionMinterCreator' import type { OpenEditionMinterCreatorDataProps } from 'components/openEdition/OpenEditionMinterCreator'
import { OpenEditionMinterCreator } from 'components/openEdition/OpenEditionMinterCreator' import { OpenEditionMinterCreator } from 'components/openEdition/OpenEditionMinterCreator'
import { flexibleVendingMinterList, openEditionMinterList, vendingMinterList } from 'config/minter' import {
flexibleVendingMinterList,
merkleTreeVendingMinterList,
openEditionMinterList,
vendingMinterList,
} from 'config/minter'
import type { TokenInfo } from 'config/token' import type { TokenInfo } from 'config/token'
import { useContracts } from 'contexts/contracts' import { useContracts } from 'contexts/contracts'
import { addLogItem } from 'contexts/log' import { addLogItem } from 'contexts/log'
@ -67,6 +72,8 @@ import {
VENDING_FACTORY_UPDATABLE_ADDRESS, VENDING_FACTORY_UPDATABLE_ADDRESS,
WHITELIST_CODE_ID, WHITELIST_CODE_ID,
WHITELIST_FLEX_CODE_ID, WHITELIST_FLEX_CODE_ID,
WHITELIST_MERKLE_TREE_API_URL,
WHITELIST_MERKLE_TREE_CODE_ID,
} from 'utils/constants' } from 'utils/constants'
import { checkTokenUri } from 'utils/isValidTokenUri' import { checkTokenUri } from 'utils/isValidTokenUri'
import { withMetadata } from 'utils/layout' import { withMetadata } from 'utils/layout'
@ -88,6 +95,7 @@ const CollectionCreationPage: NextPage = () => {
baseMinter: baseMinterContract, baseMinter: baseMinterContract,
vendingMinter: vendingMinterContract, vendingMinter: vendingMinterContract,
whitelist: whitelistContract, whitelist: whitelistContract,
whitelistMerkleTree: whitelistMerkleTreeContract,
vendingFactory: vendingFactoryContract, vendingFactory: vendingFactoryContract,
baseFactory: baseFactoryContract, baseFactory: baseFactoryContract,
} = useContracts() } = useContracts()
@ -513,41 +521,84 @@ const CollectionCreationPage: NextPage = () => {
if (!wallet.isWalletConnected) throw new Error('Wallet not connected') if (!wallet.isWalletConnected) throw new Error('Wallet not connected')
if (!whitelistContract) throw new Error('Contract not found') if (!whitelistContract) throw new Error('Contract not found')
const standardMsg = { if (whitelistDetails?.whitelistType === 'standard' || whitelistDetails?.whitelistType === 'flex') {
members: whitelistDetails?.members, const standardMsg = {
start_time: whitelistDetails?.startTime, members: whitelistDetails.members,
end_time: whitelistDetails?.endTime, start_time: whitelistDetails.startTime,
mint_price: coin( end_time: whitelistDetails.endTime,
String(Number(whitelistDetails?.unitPrice)), mint_price: coin(
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars', String(Number(whitelistDetails.unitPrice)),
), mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
per_address_limit: whitelistDetails?.perAddressLimit, ),
member_limit: whitelistDetails?.memberLimit, per_address_limit: whitelistDetails.perAddressLimit,
admins: whitelistDetails?.admins || [wallet.address], member_limit: whitelistDetails.memberLimit,
admins_mutable: whitelistDetails?.adminsMutable, 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 axios
.post(`${WHITELIST_MERKLE_TREE_API_URL}/create_whitelist`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.catch((error) => {
console.log('error', error)
throw new Error('Error fetching root hash from Whitelist Merkle Tree API.')
})
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) => { const instantiateVendingMinter = async (baseUri: string, coverImageUri: string, whitelist?: string) => {
@ -1047,6 +1098,8 @@ const CollectionCreationPage: NextPage = () => {
//check if the address belongs to a whitelist contract (see performChecks()) //check if the address belongs to a whitelist contract (see performChecks())
const config = await contract?.config() const config = await contract?.config()
if (JSON.stringify(config).includes('whale_cap')) whitelistDetails.whitelistType = 'flex' 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' else whitelistDetails.whitelistType = 'standard'
if (Number(config?.start_time) !== Number(mintingDetails?.startTime)) { if (Number(config?.start_time) !== Number(mintingDetails?.startTime)) {
const whitelistStartDate = new Date(Number(config?.start_time) / 1000000) const whitelistStartDate = new Date(Number(config?.start_time) / 1000000)
@ -1084,7 +1137,10 @@ const CollectionCreationPage: NextPage = () => {
(!whitelistDetails.perAddressLimit || whitelistDetails.perAddressLimit === 0) (!whitelistDetails.perAddressLimit || whitelistDetails.perAddressLimit === 0)
) )
throw new Error('Per address limit is required') 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') throw new Error('Member limit is required')
if (Number(whitelistDetails.startTime) >= Number(whitelistDetails.endTime)) if (Number(whitelistDetails.startTime) >= Number(whitelistDetails.endTime))
throw new Error('Whitelist start time cannot be equal to or later than the whitelist end time') throw new Error('Whitelist start time cannot be equal to or later than the whitelist end time')
@ -1277,13 +1333,16 @@ const CollectionCreationPage: NextPage = () => {
const client = await wallet.getCosmWasmClient() const client = await wallet.getCosmWasmClient()
const vendingFactoryForSelectedDenom = vendingMinterList const vendingFactoryForSelectedDenom = vendingMinterList
.concat(flexibleVendingMinterList) .concat(flexibleVendingMinterList)
.concat(merkleTreeVendingMinterList)
.find( .find(
(minter) => (minter) =>
minter.supportedToken === mintingDetails?.selectedMintToken && minter.supportedToken === mintingDetails?.selectedMintToken &&
minter.updatable === collectionDetails?.updatable && minter.updatable === collectionDetails?.updatable &&
minter.flexible === (whitelistDetails?.whitelistType === 'flex') && minter.flexible === (whitelistDetails?.whitelistType === 'flex') &&
minter.merkleTree === (whitelistDetails?.whitelistType === 'merkletree') &&
minter.featured === isFeaturedCollection, minter.featured === isFeaturedCollection,
)?.factoryAddress )?.factoryAddress
console.log('Vending Factory: ', vendingFactoryForSelectedDenom)
if (vendingFactoryForSelectedDenom) { if (vendingFactoryForSelectedDenom) {
setIsMatchingVendingFactoryPresent(true) setIsMatchingVendingFactoryPresent(true)

View File

@ -11,10 +11,12 @@ 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 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_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 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 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 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_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_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_FLEX_ADDRESS = process.env.NEXT_PUBLIC_FEATURED_VENDING_FACTORY_FLEX_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_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_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS
@ -46,6 +48,8 @@ export const FEATURED_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS =
export const VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS = export const VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS =
process.env.NEXT_PUBLIC_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_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_FLEX_ADDRESS = export const FEATURED_VENDING_IBC_TIA_FACTORY_FLEX_ADDRESS =
process.env.NEXT_PUBLIC_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 = export const VENDING_IBC_TIA_UPDATABLE_FACTORY_FLEX_ADDRESS =
@ -117,6 +121,7 @@ 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 BLOCK_EXPLORER_URL = process.env.NEXT_PUBLIC_BLOCK_EXPLORER_URL
export const WEBSITE_URL = process.env.NEXT_PUBLIC_WEBSITE_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 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 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_HOST = process.env.NEXT_PUBLIC_MEILISEARCH_HOST

31
utils/merkleTree.ts Normal file
View File

@ -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())
}
}