import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react' import { init, mute, onClick, unmute } from '../../lib/render' import { Claim } from '@blockworks-foundation/mango-mints-redemption' import { Token } from 'types/jupiter' import BigNumber from 'bignumber.js' import { IconButton } from '@components/shared/Button' import { XMarkIcon } from '@heroicons/react/20/solid' import { PublicKey } from '@solana/web3.js' import { CUSTOM_TOKEN_ICONS } from 'utils/constants' import { Sft, SftWithToken, Nft, NftWithToken } from '@metaplex-foundation/js' import { Lalezar } from 'next/font/google' import mangoStore from '@store/mangoStore' const lalezar = Lalezar({ weight: '400', subsets: ['latin'], display: 'swap', }) export type Prize = { //symbol item: string //amount info: string rarity: 'Rare' | 'Legendary' | 'Common' //eg [32, 32] token, nft [400,400] itemResolution: number[] itemUrl: string particleId: 'particles-coins' | 'particles-fireworks' stencilUrl: | '/models/tex_procedural/tex_card_front_gold_circle_albedo.png' | '/models/tex_procedural/tex_card_front_silver_square_albedo.png' frontMaterialId: | 'loader_mat_card_gold_front_circle' | 'loader_mat_card_silver_front_square' backMaterialId: 'loader_mat_card_gold_back' | 'loader_mat_card_silver_back' } export const getFallbackImg = ( mint: PublicKey, jupiterLogoUrl: string | undefined, ) => { const group = mangoStore.getState().group const bank = group?.getFirstBankByMint(mint) const tokenSymbol = bank?.name.toLowerCase() const hasCustomIcon = tokenSymbol ? CUSTOM_TOKEN_ICONS[tokenSymbol] : false if (hasCustomIcon) { return `/icons/${tokenSymbol}.svg` } else { return jupiterLogoUrl || '/icons/mngo.svg' } } export const getClaimsAsPrizes = ( claims: Claim[], tokensInfo: Token[], nftsRewardsInfo: (Sft | SftWithToken | Nft | NftWithToken)[], ) => claims.map((x) => { const tokenInfo = x.mintProperties.type === 'token' ? tokensInfo.find((t) => t.address === x.mint.toBase58()) : null const nftInfo = x.mintProperties.type === 'nft' ? nftsRewardsInfo.find( (ni) => ni.address.toBase58() === x.mint.toBase58(), ) : null const resultion = x.mintProperties.type === 'token' ? [32, 32] : [400, 400] const materials: { [key: string]: Omit< Prize, 'item' | 'info' | 'rarity' | 'itemResolution' | 'itemUrl' > } = { Common: { particleId: 'particles-coins', frontMaterialId: 'loader_mat_card_silver_front_square', backMaterialId: 'loader_mat_card_silver_back', stencilUrl: '/models/tex_procedural/tex_card_front_silver_square_albedo.png', }, Legendary: { particleId: 'particles-fireworks', frontMaterialId: 'loader_mat_card_gold_front_circle', backMaterialId: 'loader_mat_card_gold_back', stencilUrl: '/models/tex_procedural/tex_card_front_gold_circle_albedo.png', }, Rare: { particleId: 'particles-fireworks', frontMaterialId: 'loader_mat_card_gold_front_circle', backMaterialId: 'loader_mat_card_gold_back', stencilUrl: '/models/tex_procedural/tex_card_front_gold_circle_albedo.png', }, } return { item: x.mintProperties.name, info: x.mintProperties.type === 'token' && tokenInfo ? new BigNumber(x.quantity.toString()) .shiftedBy(-tokenInfo.decimals) .toString() : x.quantity.toString(), rarity: x.mintProperties.rarity, itemResolution: resultion, //fallback of img from files if mint matches mango bank itemUrl: x.mintProperties.type === 'token' ? getFallbackImg(x.mint, tokenInfo?.logoURI) : nftInfo?.json?.image || '/icons/mngo.svg', ...materials[x.mintProperties.rarity as 'Rare' | 'Legendary' | 'Common'], } }) export default function RewardsComponent({ setShowRender, claims, tokensInfo, nftsRewardsInfo, start, }: { setShowRender: Dispatch> claims: Claim[] tokensInfo: Token[] nftsRewardsInfo: (Sft | SftWithToken | Nft | NftWithToken)[] start: boolean }) { const renderLoaded = useRef(false) // eslint-disable-next-line @typescript-eslint/no-explicit-any const [collectedPrizes, setCollectedPrize] = useState([] as any[]) const [prizes, setPrizes] = useState([]) const [currentPrize, setCurrentPrize] = useState() function iOS() { return ( [ 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod', ].includes(navigator.platform) || // iPad on iOS 13 detection (navigator.userAgent.includes('Mac') && 'ontouchend' in document) ) } useEffect(() => { if (!renderLoaded.current && prizes.length && start) { try { // eslint-disable-next-line @typescript-eslint/no-explicit-any const v1 = document.getElementById('particles-fireworks') as any v1.onloadedmetadata = () => (v1.currentTime = v1.duration) // eslint-disable-next-line @typescript-eslint/no-explicit-any const v2 = document.getElementById('particles-coins') as any v2.onloadedmetadata = () => (v2.currentTime = v2.duration) // eslint-disable-next-line @typescript-eslint/no-explicit-any init(document, window, prizes, (prize: any) => { console.log('callback:showPrize', prize) setCurrentPrize(prize) collectedPrizes.push(prize) setCollectedPrize(collectedPrizes) setTimeout(() => { console.log('callback:hidePrize') setCurrentPrize(undefined) }, 5000) }) renderLoaded.current = true } catch (e) { //if webgl is turned off or someone uses old computer console.log(e) setShowRender(false) } } }, [prizes, start]) useEffect(() => { if (tokensInfo.length) { const claimsAsPrizes = getClaimsAsPrizes( claims, tokensInfo, nftsRewardsInfo, ) setPrizes(claimsAsPrizes) } }, [claims, getFallbackImg, tokensInfo]) return (
{start && (
{ setShowRender(false) mute() document.getElementById('render-output')?.remove() }} >
)}
{collectedPrizes.map((p, i) => { return ( // eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text ) })}
{!!currentPrize && ( <>

{currentPrize['item']}

{currentPrize['rarity']}

{currentPrize['info']}

)}
{ unmute() if (!iOS()) { onClick() } }} >
) }