My website works fine locally but when deployed to Vercel, I get a client-side exception error. After checking other parts of the website, I've found the culprit to be in my UMI function code. I'm getting an error of:
TypeError: Cannot read properties of undefined (reading 'length')
That I think might be coming from:
(candyMachine.itemsRedeemed === 500 as BigIntInput)
Not sure if that has to do with how the candymachine is fetched or if I'm using the BigIntInput wrong and need a different way to read if items redeemed is less than 500?
Here is my full code for the page. Like I mentioned earlier it will work fine on the local level. It's just not working in production.
import {
some,
generateSigner,
transactionBuilder,
publicKey,
BigIntInput
} from "@metaplex-foundation/umi";
import {
CandyMachine,
fetchCandyMachine,
mintV2
} from "@metaplex-foundation/mpl-candy-machine";
import { TokenStandard } from "@metaplex-foundation/mpl-token-metadata";
import { setComputeUnitLimit } from "@metaplex-foundation/mpl-toolbox";
import { CircularProgress, Container, } from "@mui/material";
import Button from "@mui/material/Button";
import Grid from "@mui/material/Grid";
import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography";
import { useWallet } from "@solana/wallet-adapter-react";
import { useEffect, useState } from "react";
import styles from '../../styles/mint.module.css';
import { useSnackbar } from "notistack";
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
import { mplCandyMachine } from "@metaplex-foundation/mpl-candy-machine";
import { walletAdapterIdentity } from '@metaplex-foundation/umi-signer-wallet-adapters';
import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
const CarMint = () => {
const wallet = useWallet();
const [pageLoading, setPageLoading] = useState<boolean>(true);
const [candyMachine, setCandyMachine] = useState<CandyMachine | undefined>();
const [isUserMinting, setIsUserMinting] = useState(false);
const owner = publicKey(process.env.NEXT_PUBLIC_OWNER_WALLET as unknown as string);
const { enqueueSnackbar } = useSnackbar();
const umi = createUmi(process.env.NEXT_PUBLIC_SOLANA_RPC_HOST as unknown as string)
.use(walletAdapterIdentity(wallet))
.use(mplCandyMachine());
const getCandyMachine = async () => {
setPageLoading(true);
try {
const cmPubkey = publicKey(process.env.NEXT_PUBLIC_CANDY_MACHINE_CAR_ID as unknown as string);
const candyMachine = await fetchCandyMachine(umi, cmPubkey);
if (!candyMachine) throw new Error("No Candymachine at address");
setCandyMachine(candyMachine);
} catch (error) {
console.log("Fetching CM Error", error);
enqueueSnackbar(
"Fetching CM Error: Check console logs for more details",
{
variant: "error",
anchorOrigin: { vertical: "top", horizontal: "right" },
}
);
}
setPageLoading(false);
};
useEffect(() => {
getCandyMachine();
}, []);
const getPayMintButtonContent = () => {
if (!candyMachine) {
return "Loading...";
}
if (isUserMinting) {
return "Minting in progress..";
} else if (candyMachine.itemsRedeemed === 500 as BigIntInput) {
return "Sold out";
} else {
return <img
style={{
maxHeight: "75px",
}}
src="/images/freeby.png"
alt="freeby"
/>;
}
};
const payMintButtonClicked = async () => {
setIsUserMinting(true);
try {
if (candyMachine?.publicKey) {
const nftMint = generateSigner(umi);
const freeMint = await transactionBuilder()
.add(setComputeUnitLimit(umi, { units: 800_000 }))
.add(
mintV2(umi, {
candyMachine: candyMachine.publicKey,
nftMint,
collectionMint: candyMachine.collectionMint,
collectionUpdateAuthority: owner,
group: some("fren"),
mintArgs: {
mintLimit: some({ id: 1 }),
solPayment: some({ destination: owner }),
},
tokenStandard: TokenStandard.ProgrammableNonFungible,
})
)
.sendAndConfirm(umi);
console.log( "Mint Success!!!", freeMint )
enqueueSnackbar(
"Mint Success!!!",
{
variant: "success",
anchorOrigin: { vertical: "top", horizontal: "right" },
}
);
getCandyMachine();
}
} catch (error) {
console.error("Mint Error", error);
enqueueSnackbar("Mint Error: Only one per customer, Pal!!!", {
variant: "error",
anchorOrigin: { vertical: "top", horizontal: "right" },
});
}
setIsUserMinting(false);
};
return (
<Container style={{ marginTop: 20 }}>
<Container maxWidth="xs" style={{ position: 'relative' }}>
<Paper
style={{ padding: 24, background: '#3a434a', borderColor: '#ffd839', border: '3px solid #ffd839', borderRadius: 6 }}
>
{!wallet.connected ? (
<div className={styles.connectButton}>
<WalletMultiButton className="w-80 text-center mx-3">
<img className="mt-10" src="/images/freeby.png"></img>
</WalletMultiButton>
</div>
) : (
<>
<Grid
container
direction="row"
justifyContent="center"
wrap="nowrap"
>
{pageLoading ? (
<CircularProgress />
) : (
<Grid item xs={3}>
<Typography variant="h6" color="#ffd839" style={{
textAlign: "center", fontFamily: "Press Start 2P"
}}>
Redeemed
</Typography>
<Typography
variant="h6"
color="white"
style={{
fontWeight: "bold",
textAlign: "center",
}}
>
{`${candyMachine ? candyMachine.itemsRedeemed : "Loading.."}`}
</Typography>
</Grid>
)}
<Grid item xs={4}>
<Typography
variant="h6"
color="#ffd839"
style={{ fontFamily: "Press Start 2p" }}
>
.
</Typography>
<Typography
variant="h6"
color="white"
style={{ fontFamily: "Press Start 2P" }}
>
/500
</Typography>
</Grid>
<Grid item xs={4}>
<Typography
variant="h6"
color="#ffd839"
style={{ fontFamily: "Press Start 2p" }}
>
Price USDC
</Typography>
<Typography
variant="h6"
color="white"
style={{ fontFamily: "Press Start 2P" }}
>
Free Fiddy
</Typography>
</Grid>
</Grid>
<Grid
container
direction="row"
justifyContent="center"
wrap="nowrap"
>
<div className={styles.mintButton}>
<Button onClick={async () => await payMintButtonClicked()} disabled={isUserMinting || candyMachine?.itemsRedeemed === 500 as BigIntInput}>
<Typography variant="body2" color="textSecondary" style={{
fontSize: "16px",
fontWeight: "bold",
color: "white",
textAlign: "center",
}}>
{ getPayMintButtonContent() }
</Typography>
</Button>
</div>
</Grid>
</>
)}
</Paper>
</Container>
</Container>
);
};
export default CarMint;