Step 8- Power Up Wallet Display + Ignite Gasless Minting
At this stage, your editor might be throwing errors, that's because we’re referencing two components we haven’t summoned into existence yet: WalletDisplay
and GaslessMinter
. No worries, let’s bring these Magmar modules to life.
WalletDisplay: Visualize Your Digital Assets
Create a new file in your /common
folder named:
WalletDisplay.tsx
Paste the following Magmar-powered logic inside:
import { useAuth } from "@common/AuthProvider";
import Loader from "@common/utils/Loader";
import { useEffect, useState } from "react";
interface Nft {
contract: object;
tokenId: string;
tokenType: string;
title: string;
description: string;
media: object;
}
interface Data {
ownedNfts: Nft[];
length: number;
}
export default function WalletDisplay() {
const { user } = useAuth();
const [ownedNftsArray, setOwnedNftsArray] = useState<Data | null>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
fetchUserNfts();
}, []);
function truncateDescription(description: string, wordCount: number) {
const words = description.split(" ");
if (words.length > wordCount) {
return `${words.slice(0, wordCount).join(" ")} ...`;
}
return description;
}
async function fetchUserNfts() {
setIsLoading(true);
try {
const response = await fetch("/api/get-user-nfts/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ address: user?.scwAddress }),
});
const messageResponse = await response.json();
setOwnedNftsArray(messageResponse.data.ownedNfts);
setIsLoading(false);
} catch (error) {
console.error("Error fetching NFTs:", error);
}
}
return (
<div>
{isLoading ? (
<div className="flex items-center justify-center mt-[-350px]">
<Loader />
</div>
) : ownedNftsArray && ownedNftsArray.length >= 1 ? (
<div className="flex flex-col items-center">
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 mx-12 mb-6">
{ownedNftsArray.map((nft, index) => (
<div
key={index}
className="rounded-lg shadow-xl max-w-[250px] max-h-[600px] overflow-hidden"
>
<figure>
<img
src={
nft.tokenUri.gateway
? nft.tokenUri.gateway
: nft.tokenUri.raw
}
alt="user nft image"
className="w-full max-h-[300px]"
/>
</figure>
<div className="p-4">
<h2 className="text-xl font-semibold mb-2">{nft.title}</h2>
<p>{truncateDescription(nft.description, 25)}</p>
</div>
</div>
))}
</div>
</div>
) : (
<div className="flex flex-col items-center justify-center mx-8 mt-32 text-black">
<p>Your Magmar Wallet is ready to ignite, but it holds no NFTs yet. 🔥</p>
<div className="mt-4">
Use the <b> Mint an NFT </b> tab to spark your first one!
</div>
</div>
)}
</div>
);
}
This component fires a fetch call on mount to check which NFTs the user's Smart Contract Wallet (SCW) owns. If there’s any fire in the vault, you’ll see the blaze of your assets. If not, the minting forge awaits.
GaslessMinter: Mint with No Friction
Time to integrate Magmar’s gasless minting magic.
Install the celebratory react-confetti
package first:
npm install react-confetti
Then, create the component:
GaslessMinter.tsx
Paste the following:
import { useAuth } from "@common/AuthProvider";
import { useState } from "react";
import Confetti from "react-confetti";
export default function GaslessMinter() {
const { user } = useAuth();
const [isLoading, setIsLoading] = useState(false);
const [hasMinted, setHasMinted] = useState(false);
async function handleMint() {
setIsLoading(true);
const data = {
userId: user?.userId,
userScwAddress: user?.scwAddress,
nameOfFunction: "mint",
};
await fetch("/api/mint-nft-user-op/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
setTimeout(() => {}, 10000); // Simulate minting delay
setIsLoading(false);
setHasMinted(true);
}
return (
<div className="flex items-center justify-center mt-12">
{hasMinted && <Confetti />}
<div className="card lg:card-side shadow-xl w-[70%] mb-16">
<figure>
<img
src="https://github-production-user-asset-6210df.s3.amazonaws.com/83442423/267730896-dd9791c9-00b9-47ff-816d-0d626177909c.png"
alt="sample nft"
/>
</figure>
<div className="card-body text-black">
<h2 className="card-title text-2xl">🔥 Magmar Test NFT</h2>
<p className="text-sm">
You’re minting a test NFT on Sepolia. No gas. No friction. Just fire.
This NFT lands directly into your Smart Contract Wallet.
</p>
<div className="flex items-center justify-end">
<div
className={`alert w-[75%] mr-4 ${
hasMinted ? "visible" : "hidden"
}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="stroke-current shrink-0 h-6 w-6"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<div className="flex justify-end text-right">
<span className="text-white">🔥 NFT minted successfully!</span>
</div>
</div>
<button className="btn btn-primary text-white" onClick={handleMint}>
<span
className={`${
isLoading ? "loading loading-spinner" : "hidden"
}`}
></span>
{isLoading ? "Minting..." : hasMinted ? "Mint Again" : "Mint"}
</button>
</div>
</div>
</div>
</div>
);
}
This component handles your minting flow and throws confetti when a user successfully mints their NFT — all on Sepolia and completely gasless.
Last updated