Completed code for Mango Heroes integration
This commit is contained in:
parent
14147aab26
commit
9f66df9bf1
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { FunctionComponent } from 'react'
|
||||
import Modal from './Modal'
|
||||
import { ElementTitle } from './styles'
|
||||
|
@ -6,9 +6,6 @@ import { Responsive, WidthProvider } from 'react-grid-layout'
|
|||
import _ from 'lodash'
|
||||
import Button from './Button'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
// import mango_hero from '../public/mango_heroes.jpg'
|
||||
// import mango_hero1 from '../public/mango_heroes1.jpeg'
|
||||
// import mango_hero2 from '../public/mango_heroes2.jpeg'
|
||||
import { notify } from '../utils/notifications'
|
||||
import { NFT } from '../utils/metaplex/models'
|
||||
|
||||
|
@ -25,30 +22,36 @@ const ChangeAvatarModal: FunctionComponent<ChangeAvatarModalProps> = ({
|
|||
onClose,
|
||||
currentAvatar,
|
||||
}) => {
|
||||
const nfts = useMangoStore((s) => s.settings.nfts)
|
||||
const nfts = [...useMangoStore((s) => s.settings.nfts)].filter(
|
||||
(nft) => nft.metadataUri
|
||||
)
|
||||
const currentIndex = nfts.indexOf(currentAvatar)
|
||||
if (currentIndex != -1) nfts.splice(currentIndex, 1)
|
||||
|
||||
const testImageUrls = [nfts]
|
||||
const listOfNFTs = [currentAvatar, ...nfts]
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
const set = useMangoStore((state) => state.set)
|
||||
const [layouts] = useState(
|
||||
testImageUrls.map((url, key) => {
|
||||
listOfNFTs.map((nft, key) => {
|
||||
return {
|
||||
i: String(key),
|
||||
x: key % 3,
|
||||
y: Math.floor(key / 3),
|
||||
w: 1,
|
||||
h: 1,
|
||||
url: url,
|
||||
nft: nft,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
// Save selected profile picture
|
||||
const saveSelection = () => {
|
||||
const nft = listOfNFTs[selectedIndex]
|
||||
|
||||
set((state) => {
|
||||
state.settings.avatar = testImageUrls[selectedIndex]
|
||||
state.settings.avatar = nft.mintAddress.toBase58()
|
||||
})
|
||||
localStorage.setItem('profilePic', nft.mintAddress.toBase58())
|
||||
|
||||
notify({
|
||||
title: 'Avatar changed successfully',
|
||||
|
@ -83,7 +86,7 @@ const ChangeAvatarModal: FunctionComponent<ChangeAvatarModalProps> = ({
|
|||
onClick={() => setSelectedIndex(+layout.i)}
|
||||
>
|
||||
<NFTDisplay
|
||||
nft={layout.url}
|
||||
nft={layout.nft}
|
||||
selected={selectedIndex === +layout.i}
|
||||
/>
|
||||
</div>
|
||||
|
@ -105,8 +108,37 @@ const ChangeAvatarModal: FunctionComponent<ChangeAvatarModalProps> = ({
|
|||
}
|
||||
|
||||
const NFTDisplay = ({ nft, selected }) => {
|
||||
const [imageUri, setImageUri] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
if (nft.imageUri) {
|
||||
setImageUri(nft.imageUri)
|
||||
} else {
|
||||
try {
|
||||
fetch(nft.metadataUri).then(async (_) => {
|
||||
try {
|
||||
const data = await _.json()
|
||||
nft.imageUri = data['image']
|
||||
setImageUri(nft.imageUri)
|
||||
console.log('imageUri is: ', nft.imageUri)
|
||||
} catch (ex) {
|
||||
console.error('Error trying to parse JSON: ' + ex)
|
||||
}
|
||||
})
|
||||
} catch (ex) {
|
||||
console.error('Error trying to fetch Arweave metadata: ' + ex)
|
||||
}
|
||||
}
|
||||
}, [imageUri])
|
||||
|
||||
return (
|
||||
<div className="hover:scale-110">
|
||||
<div
|
||||
className={`hover:scale-110 ${
|
||||
nft.imageUri == undefined
|
||||
? 'bg-th-bkg-4 h-full w-full rounded-lg animate-pulse'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
<img
|
||||
className={`border ${
|
||||
selected ? 'border-th-primary' : 'border-th-bkg-4'
|
||||
|
|
|
@ -21,48 +21,61 @@ import { useEffect } from 'react'
|
|||
import SettingsModal from './SettingsModal'
|
||||
import { UserCircleIcon } from '@heroicons/react/solid'
|
||||
import ChangeAvatarModal from './ChangeAvatarModal'
|
||||
import { NFT } from '../utils/metaplex/models'
|
||||
|
||||
const ConnectWalletButton = () => {
|
||||
const wallet = useMangoStore((s) => s.wallet.current)
|
||||
const connected = useMangoStore((s) => s.wallet.connected)
|
||||
const nfts = useMangoStore((s) => s.settings.nfts)
|
||||
const imageUrl = useMangoStore((s) => s.settings.avatar)
|
||||
const profilePicMintAddress = useMangoStore((s) => s.settings.avatar)
|
||||
const set = useMangoStore((s) => s.set)
|
||||
const [showAccountsModal, setShowAccountsModal] = useState(false)
|
||||
const [showSettingsModal, setShowSettingsModal] = useState(false)
|
||||
const [showChangeAvatarModal, setChangeAvatarModal] = useState(false)
|
||||
const [selectedWallet, setSelectedWallet] = useState(DEFAULT_PROVIDER.url)
|
||||
const [profilePicture, setProfilePicture] = useState(new NFT())
|
||||
const [imageUrl, setImageUrl] = useState('')
|
||||
const [savedProviderUrl] = useLocalStorageState(
|
||||
PROVIDER_LOCAL_STORAGE_KEY,
|
||||
DEFAULT_PROVIDER.url
|
||||
)
|
||||
|
||||
// update in useEffect to prevent SRR error from next.js
|
||||
useEffect(() => {
|
||||
setSelectedWallet(savedProviderUrl)
|
||||
}, [savedProviderUrl])
|
||||
|
||||
if (nfts.length != 0 && imageUrl == '') {
|
||||
const nft = nfts[0]
|
||||
useEffect(() => {
|
||||
if (!profilePicMintAddress && nfts.length == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const profilePics = nfts.filter(
|
||||
(nft) => nft.mintAddress.toBase58() == profilePicMintAddress
|
||||
)
|
||||
const nft = profilePics.length == 1 ? profilePics[0] : nfts[0]
|
||||
|
||||
if (nft.imageUri) {
|
||||
setImageUrl(nft.imageUri)
|
||||
} else {
|
||||
try {
|
||||
fetch(nft).then(async (_) => {
|
||||
fetch(nft.metadataUri).then(async (_) => {
|
||||
try {
|
||||
const data = await _.json()
|
||||
|
||||
set((state) => {
|
||||
state.settings.avatar = data['image']
|
||||
})
|
||||
nft.imageUri = data['image']
|
||||
setImageUrl(nft.imageUri)
|
||||
} catch (ex) {
|
||||
console.error('Error trying to parse JSON: ' + ex)
|
||||
}
|
||||
})
|
||||
} catch (ex) {
|
||||
console.error('Error trying to fetch Arweave metadata: ' + ex)
|
||||
console.error('Error trying to fetch metadata: ' + ex)
|
||||
}
|
||||
}
|
||||
|
||||
const handleWalletConect = () => {
|
||||
setProfilePicture(nft)
|
||||
}, [nfts, profilePicMintAddress])
|
||||
|
||||
const handleWalletConnect = () => {
|
||||
wallet.connect()
|
||||
set((state) => {
|
||||
state.selectedMangoAccount.initialLoad = true
|
||||
|
@ -90,7 +103,6 @@ const ConnectWalletButton = () => {
|
|||
}
|
||||
>
|
||||
{imageUrl == '' ? <ProfileIcon className="h-6 w-6" /> : null}
|
||||
{/* <NewProfileIcon className="h-6 w-6" src={mango_hero.src} /> */}
|
||||
</Menu.Button>
|
||||
<Menu.Items className="bg-th-bkg-1 mt-2 p-1 absolute right-0 shadow-lg outline-none rounded-md w-48 z-20">
|
||||
<Menu.Item>
|
||||
|
@ -102,6 +114,7 @@ const ConnectWalletButton = () => {
|
|||
<div className="pl-2 text-left">Accounts</div>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
{imageUrl != '' ? (
|
||||
<Menu.Item>
|
||||
<button
|
||||
className="flex flex-row font-normal items-center rounded-none w-full p-2 hover:bg-th-bkg-2 hover:cursor-pointer focus:outline-none"
|
||||
|
@ -111,6 +124,7 @@ const ConnectWalletButton = () => {
|
|||
<div className="pl-2 text-left">Change Avatar</div>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
) : null}
|
||||
<Menu.Item>
|
||||
<button
|
||||
className="flex flex-row font-normal items-center rounded-none w-full p-2 hover:bg-th-bkg-2 hover:cursor-pointer focus:outline-none"
|
||||
|
@ -149,7 +163,7 @@ const ConnectWalletButton = () => {
|
|||
) : (
|
||||
<div className="bg-th-bkg-1 h-14 flex divide-x divide-th-bkg-3 justify-between">
|
||||
<button
|
||||
onClick={handleWalletConect}
|
||||
onClick={handleWalletConnect}
|
||||
disabled={!wallet}
|
||||
className="rounded-none text-th-primary hover:bg-th-bkg-4 focus:outline-none disabled:text-th-fgd-4 disabled:cursor-wait"
|
||||
>
|
||||
|
@ -184,7 +198,7 @@ const ConnectWalletButton = () => {
|
|||
<ChangeAvatarModal
|
||||
onClose={() => setChangeAvatarModal(false)}
|
||||
isOpen={showChangeAvatarModal}
|
||||
url={imageUrl}
|
||||
currentAvatar={profilePicture}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
|
|
|
@ -107,7 +107,7 @@ export default function useWallet() {
|
|||
actions.reloadOrders()
|
||||
actions.fetchTradeHistory()
|
||||
actions.fetchWalletTokens()
|
||||
actions.fetchProfilePicture()
|
||||
actions.fetchMangoHeroesNFTs()
|
||||
notify({
|
||||
title: 'Wallet connected',
|
||||
description:
|
||||
|
@ -145,7 +145,7 @@ export default function useWallet() {
|
|||
useInterval(() => {
|
||||
if (connected && mangoAccount) {
|
||||
actions.fetchWalletTokens()
|
||||
actions.fetchProfilePicture()
|
||||
actions.fetchMangoHeroesNFTs()
|
||||
actions.fetchTradeHistory()
|
||||
}
|
||||
}, 90 * SECONDS)
|
||||
|
|
|
@ -35,7 +35,11 @@ import { TOKEN_PROGRAM_ID } from '../utils/tokens'
|
|||
import { findProgramAddress } from '../utils/metaplex/utils'
|
||||
import * as borsh from 'borsh'
|
||||
import { Metadata, METADATA_SCHEMA, NFT } from '../utils/metaplex/models'
|
||||
import { METADATA_KEY, METADATA_PREFIX } from '../utils/metaplex/types'
|
||||
import {
|
||||
MANGO_HEROES_MINT_AUTHORITY,
|
||||
METADATA_KEY,
|
||||
METADATA_PREFIX,
|
||||
} from '../utils/metaplex/types'
|
||||
|
||||
export const ENDPOINTS: EndpointInfo[] = [
|
||||
{
|
||||
|
@ -283,7 +287,7 @@ const useMangoStore = create<MangoStore>((set, get) => {
|
|||
})
|
||||
}
|
||||
},
|
||||
async fetchProfilePicture() {
|
||||
async fetchMangoHeroesNFTs() {
|
||||
const wallet = get().wallet.current
|
||||
const connected = get().wallet.connected
|
||||
const connection = get().connection.current
|
||||
|
@ -295,7 +299,7 @@ const useMangoStore = create<MangoStore>((set, get) => {
|
|||
{ programId: TOKEN_PROGRAM_ID }
|
||||
)
|
||||
|
||||
const nfts = []
|
||||
const walletNFTs = []
|
||||
|
||||
tokenAccounts.value.forEach((token) => {
|
||||
const tokenAccount = token.account.data.parsed.info
|
||||
|
@ -306,15 +310,17 @@ const useMangoStore = create<MangoStore>((set, get) => {
|
|||
) {
|
||||
const nft = new NFT()
|
||||
nft.mintAddress = new PublicKey(tokenAccount.mint)
|
||||
nfts.push(nft)
|
||||
walletNFTs.push(nft)
|
||||
}
|
||||
})
|
||||
|
||||
if (nfts.length == 0) return
|
||||
if (walletNFTs.length == 0) return
|
||||
|
||||
const metadataProgramId = new PublicKey(METADATA_KEY)
|
||||
|
||||
for (const nft of nfts) {
|
||||
const mangoHeroesNFTs = []
|
||||
|
||||
for (const nft of walletNFTs) {
|
||||
// The return value is [programDerivedAddress, bytes] but we only care about the address
|
||||
|
||||
const [pda] = await findProgramAddress(
|
||||
|
@ -335,12 +341,17 @@ const useMangoStore = create<MangoStore>((set, get) => {
|
|||
Metadata,
|
||||
accountInfo!.data
|
||||
)
|
||||
|
||||
if (metadata.updateAuthority == MANGO_HEROES_MINT_AUTHORITY) {
|
||||
const uri = metadata.data.uri.replace(/\0/g, '')
|
||||
nft.metadataUri = uri
|
||||
mangoHeroesNFTs.push(nft)
|
||||
}
|
||||
}
|
||||
|
||||
set((state) => {
|
||||
state.settings.nfts = nfts
|
||||
;(state.settings.nfts = mangoHeroesNFTs),
|
||||
(state.settings.avatar = localStorage.getItem('profilePic'))
|
||||
})
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,6 +7,8 @@ export type StringPublicKey = string
|
|||
export const EDITION = 'edition'
|
||||
export const METADATA_PREFIX = 'metadata'
|
||||
export const METADATA_KEY = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
|
||||
export const MANGO_HEROES_MINT_AUTHORITY =
|
||||
'3RVBxNcF1LBAVbxPz1KsueWspASJhqz4ZJGDbxy2mKE3'
|
||||
|
||||
export const MAX_AUCTION_DATA_EXTENDED_SIZE = 8 + 9 + 2 + 200
|
||||
|
||||
|
|
Loading…
Reference in New Issue