From e2ff94c76b18d8e4c145f739fbed822d68629dbb Mon Sep 17 00:00:00 2001 From: Maayan Date: Mon, 24 Jun 2024 15:00:21 -0700 Subject: [PATCH] refactor and clean up fungible asset template (#124) --- .../fungible-asset-template/frontend/App.tsx | 8 +- .../frontend/components/Header.tsx | 18 +--- .../frontend/components/LaunchpadHeader.tsx | 15 ++- .../frontend/components/UploadSpinner.tsx | 8 +- .../frontend/components/WalletProvider.tsx | 4 +- .../frontend/components/WalletSelector.tsx | 44 ++------- .../frontend/entry-functions/create_asset.ts | 46 +++++++++ .../frontend/entry-functions/mint_asset.ts | 20 ++++ .../useGetAssetData.ts} | 16 +++- .../frontend/hooks/useGetAssetMetadata.tsx | 16 ++-- .../fungible-asset-template/frontend/main.tsx | 11 ++- .../frontend/pages/CreateFungibleAsset.tsx | 96 ++++++++++--------- .../Mint/components/ConnectWalletAlert.tsx | 11 ++- .../pages/Mint/components/HeroSection.tsx | 39 +++++--- .../pages/Mint/components/OurStorySection.tsx | 5 +- .../pages/Mint/components/Socials.tsx | 14 ++- .../pages/Mint/components/StatsSection.tsx | 4 +- .../frontend/pages/Mint/index.tsx | 4 +- .../frontend/pages/MyFungibleAssets.tsx | 32 +++---- .../frontend/utils/Irys.ts | 12 +-- .../frontend/view-functions/accountBalance.ts | 17 ++++ 21 files changed, 254 insertions(+), 186 deletions(-) create mode 100644 templates/fungible-asset-template/frontend/entry-functions/create_asset.ts create mode 100644 templates/fungible-asset-template/frontend/entry-functions/mint_asset.ts rename templates/fungible-asset-template/frontend/{pages/Mint/hooks/useMintData.ts => hooks/useGetAssetData.ts} (95%) create mode 100644 templates/fungible-asset-template/frontend/view-functions/accountBalance.ts diff --git a/templates/fungible-asset-template/frontend/App.tsx b/templates/fungible-asset-template/frontend/App.tsx index e1d52a53..3db71b78 100644 --- a/templates/fungible-asset-template/frontend/App.tsx +++ b/templates/fungible-asset-template/frontend/App.tsx @@ -1,8 +1,8 @@ import { RouterProvider, createBrowserRouter, Outlet } from "react-router-dom"; - -import { Mint } from "./pages/Mint"; -import { CreateFungibleAsset } from "./pages/CreateFungibleAsset"; -import { MyFungibleAssets } from "./pages/MyFungibleAssets"; +// Internal pages +import { Mint } from "@/pages/Mint"; +import { CreateFungibleAsset } from "@/pages/CreateFungibleAsset"; +import { MyFungibleAssets } from "@/pages/MyFungibleAssets"; function Layout() { return ( diff --git a/templates/fungible-asset-template/frontend/components/Header.tsx b/templates/fungible-asset-template/frontend/components/Header.tsx index dcc0494e..aacaef67 100644 --- a/templates/fungible-asset-template/frontend/components/Header.tsx +++ b/templates/fungible-asset-template/frontend/components/Header.tsx @@ -1,5 +1,5 @@ import { IS_DEV } from "@/constants"; -import { useMintData } from "@/pages/Mint/hooks/useMintData"; +import { useGetAssetData } from "@/hooks/useGetAssetData"; import { useMemo } from "react"; import { Link } from "react-router-dom"; import { useLocation } from "react-router-dom"; @@ -8,18 +8,14 @@ import { buttonVariants } from "./ui/button"; import { config } from "@/config"; export function Header() { - const { data } = useMintData(); + const { data } = useGetAssetData(); const location = useLocation(); const isRoot = location.pathname === "/"; const title = useMemo(() => { if (!isRoot) return "Fungible Asset Launchpad"; - return ( - data?.asset.symbol.toUpperCase() ?? - config.defaultAsset?.name ?? - "Fungible Asset Launchpad" - ); + return data?.asset.symbol.toUpperCase() ?? config.defaultAsset?.name ?? "Fungible Asset Launchpad"; }, [isRoot, data?.asset]); return ( @@ -31,14 +27,10 @@ export function Header() {
{IS_DEV && ( <> - + My Assets - + Create Asset diff --git a/templates/fungible-asset-template/frontend/components/LaunchpadHeader.tsx b/templates/fungible-asset-template/frontend/components/LaunchpadHeader.tsx index f50acaa7..8760b13c 100644 --- a/templates/fungible-asset-template/frontend/components/LaunchpadHeader.tsx +++ b/templates/fungible-asset-template/frontend/components/LaunchpadHeader.tsx @@ -1,8 +1,9 @@ +import { FC } from "react"; import { Link } from "react-router-dom"; import { useLocation } from "react-router-dom"; -import { WalletSelector } from "./WalletSelector"; -import { buttonVariants } from "./ui/button"; -import { FC } from "react"; +// Internal components +import { WalletSelector } from "@/components/WalletSelector"; +import { buttonVariants } from "@/components/ui/button"; interface LaunchpadHeaderProps { title: string; @@ -19,15 +20,11 @@ export const LaunchpadHeader: FC = ({ title }) => { Mint Page {location.pathname === "/my-assets" ? ( - + Create Asset ) : ( - + My Assets )} diff --git a/templates/fungible-asset-template/frontend/components/UploadSpinner.tsx b/templates/fungible-asset-template/frontend/components/UploadSpinner.tsx index 1d58bfd2..260a6520 100644 --- a/templates/fungible-asset-template/frontend/components/UploadSpinner.tsx +++ b/templates/fungible-asset-template/frontend/components/UploadSpinner.tsx @@ -1,13 +1,15 @@ -import { cn } from "@/lib/utils"; -import { Spinner } from "./ui/spinner"; import { FC } from "react"; +// Internal utils +import { cn } from "@/lib/utils"; +// Internal components +import { Spinner } from "@/components/ui/spinner"; export const UploadSpinner: FC<{ on: boolean }> = ({ on }) => { return (

Uploading Files...

diff --git a/templates/fungible-asset-template/frontend/components/WalletProvider.tsx b/templates/fungible-asset-template/frontend/components/WalletProvider.tsx index 132d9e09..9a5b66aa 100644 --- a/templates/fungible-asset-template/frontend/components/WalletProvider.tsx +++ b/templates/fungible-asset-template/frontend/components/WalletProvider.tsx @@ -1,6 +1,8 @@ import { PropsWithChildren } from "react"; -import { useToast } from "./ui/use-toast"; import { AptosWalletAdapterProvider } from "@aptos-labs/wallet-adapter-react"; +// Internal components +import { useToast } from "@/components/ui/use-toast"; +// Internal constants import { NETWORK } from "@/constants"; export function WalletProvider({ children }: PropsWithChildren) { diff --git a/templates/fungible-asset-template/frontend/components/WalletSelector.tsx b/templates/fungible-asset-template/frontend/components/WalletSelector.tsx index 62da8491..67d3279e 100644 --- a/templates/fungible-asset-template/frontend/components/WalletSelector.tsx +++ b/templates/fungible-asset-template/frontend/components/WalletSelector.tsx @@ -12,26 +12,17 @@ import { import { ChevronDown, Copy, LogOut, User } from "lucide-react"; import { useCallback, useState } from "react"; import { useLocation } from "react-router-dom"; -import { Button } from "./ui/button"; -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "./ui/collapsible"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "./ui/dialog"; +// Internal components +import { Button } from "@/components/ui/button"; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "./ui/dropdown-menu"; -import { useToast } from "./ui/use-toast"; +} from "@/components/ui/dropdown-menu"; +import { useToast } from "@/components/ui/use-toast"; export function WalletSelector() { const { account, connected, disconnect, wallet } = useWallet(); @@ -60,9 +51,7 @@ export function WalletSelector() { return connected ? ( - + @@ -70,12 +59,7 @@ export function WalletSelector() { {wallet && isAptosConnectWallet(wallet) && ( - + Account @@ -133,11 +117,7 @@ function ConnectWalletDialog({ close }: ConnectWalletDialogProps) {
{aptosConnectWallets.map((wallet) => ( - + ))}
@@ -166,11 +146,7 @@ function ConnectWalletDialog({ close }: ConnectWalletDialogProps) { {moreWallets.map((wallet) => ( - + ))} diff --git a/templates/fungible-asset-template/frontend/entry-functions/create_asset.ts b/templates/fungible-asset-template/frontend/entry-functions/create_asset.ts new file mode 100644 index 00000000..009e81bc --- /dev/null +++ b/templates/fungible-asset-template/frontend/entry-functions/create_asset.ts @@ -0,0 +1,46 @@ +import { InputTransactionData } from "@aptos-labs/wallet-adapter-react"; +// Internal utils +import { + APT_DECIMALS, + convertAmountFromHumanReadableToOnChain, + convertAmountFromOnChainToHumanReadable, +} from "@/utils/helpers"; + +export type CreateAssetArguments = { + maxSupply: number; // The total amount of the asset in full unit that can be minted. + name: string; // The name of the asset + symbol: string; // The symbol of the asset + decimal: number; // How many 0's constitute one full unit of the asset. For example, APT has 8. + iconURL: string; // The asset icon URL + projectURL: string; // Your project URL (i.e https://mydomain.com) + mintFeePerFA?: number; // The fee cost for the minter to pay to mint one full unit of an asset, denominated in APT. For example, if a user mints 10 assets in a single transaction, they are charged 10x the mint fee. + mintForMyself?: number; // How many assets in full unit to mint right away and send to the signer address. + maxMintPerAccount?: number; // The maximum amount in full unit that any single individual address can mint +}; + +export const createAsset = (args: CreateAssetArguments): InputTransactionData => { + const { maxSupply, name, symbol, decimal, iconURL, projectURL, mintFeePerFA, mintForMyself, maxMintPerAccount } = + args; + return { + data: { + function: `${import.meta.env.VITE_MODULE_ADDRESS}::launchpad::create_fa`, + typeArguments: [], + functionArguments: [ + convertAmountFromHumanReadableToOnChain(maxSupply, decimal), + name, + symbol, + decimal, + iconURL, + projectURL, + mintFeePerFA + ? convertAmountFromOnChainToHumanReadable( + convertAmountFromHumanReadableToOnChain(mintFeePerFA, APT_DECIMALS), + decimal, + ) + : 0, + mintForMyself ? convertAmountFromHumanReadableToOnChain(mintForMyself, decimal) : 0, + maxMintPerAccount ? convertAmountFromHumanReadableToOnChain(maxMintPerAccount, decimal) : 0, + ], + }, + }; +}; diff --git a/templates/fungible-asset-template/frontend/entry-functions/mint_asset.ts b/templates/fungible-asset-template/frontend/entry-functions/mint_asset.ts new file mode 100644 index 00000000..2773c328 --- /dev/null +++ b/templates/fungible-asset-template/frontend/entry-functions/mint_asset.ts @@ -0,0 +1,20 @@ +import { InputTransactionData } from "@aptos-labs/wallet-adapter-react"; +// Internal utils +import { convertAmountFromHumanReadableToOnChain } from "@/utils/helpers"; + +export type MintAssetArguments = { + assetType: string; + amount: number; + decimals: number; +}; + +export const mintAsset = (args: MintAssetArguments): InputTransactionData => { + const { assetType, amount, decimals } = args; + return { + data: { + function: `${import.meta.env.VITE_MODULE_ADDRESS}::launchpad::mint_fa`, + typeArguments: [], + functionArguments: [assetType, convertAmountFromHumanReadableToOnChain(amount, decimals)], + }, + }; +}; diff --git a/templates/fungible-asset-template/frontend/pages/Mint/hooks/useMintData.ts b/templates/fungible-asset-template/frontend/hooks/useGetAssetData.ts similarity index 95% rename from templates/fungible-asset-template/frontend/pages/Mint/hooks/useMintData.ts rename to templates/fungible-asset-template/frontend/hooks/useGetAssetData.ts index d6de4ed9..0b0495ad 100644 --- a/templates/fungible-asset-template/frontend/pages/Mint/hooks/useMintData.ts +++ b/templates/fungible-asset-template/frontend/hooks/useGetAssetData.ts @@ -1,10 +1,13 @@ -import { config } from "@/config"; -import { aptosClient } from "@/utils/aptosClient"; -import { useQuery } from "@tanstack/react-query"; import { useWallet } from "@aptos-labs/wallet-adapter-react"; import { AccountAddress } from "@aptos-labs/ts-sdk"; -import { MODULE_ADDRESS } from "@/constants"; +import { useQuery } from "@tanstack/react-query"; +// Internal config +import { config } from "@/config"; +// Internal utils +import { aptosClient } from "@/utils/aptosClient"; import { convertAmountFromOnChainToHumanReadable } from "@/utils/helpers"; +// Internal constants +import { MODULE_ADDRESS } from "@/constants"; export interface FungibleAsset { maximum_v2: number; @@ -49,7 +52,10 @@ async function getMintLimit(asset_id: string): Promise { return Number(mintLimitRes[0].vec[0]); } -export function useMintData(asset_id: string = config.asset_id) { +/** + * A react hook to get fungible asset data. + */ +export function useGetAssetData(asset_id: string = config.asset_id) { const { account } = useWallet(); return useQuery({ diff --git a/templates/fungible-asset-template/frontend/hooks/useGetAssetMetadata.tsx b/templates/fungible-asset-template/frontend/hooks/useGetAssetMetadata.tsx index 93550a15..45383f79 100644 --- a/templates/fungible-asset-template/frontend/hooks/useGetAssetMetadata.tsx +++ b/templates/fungible-asset-template/frontend/hooks/useGetAssetMetadata.tsx @@ -1,9 +1,7 @@ -import { aptosClient } from "@/utils/aptosClient"; -import { - AccountAddress, - GetFungibleAssetMetadataResponse, -} from "@aptos-labs/ts-sdk"; +import { AccountAddress, GetFungibleAssetMetadataResponse } from "@aptos-labs/ts-sdk"; import { useState, useEffect } from "react"; +// Internal utils +import { aptosClient } from "@/utils/aptosClient"; /** * A react hook to get fungible asset metadatas. @@ -34,9 +32,7 @@ export function useGetAssetMetadata() { const getRegistry = async () => { const registry = await aptosClient().view<[[{ inner: string }]]>({ payload: { - function: `${AccountAddress.from( - import.meta.env.VITE_MODULE_ADDRESS - )}::launchpad::get_registry`, + function: `${AccountAddress.from(import.meta.env.VITE_MODULE_ADDRESS)}::launchpad::get_registry`, }, }); return registry[0]; @@ -51,7 +47,7 @@ const getObjects = async (registry: [{ inner: string }]) => { }); return object.owner_address; - }) + }), ); return objects; }; @@ -67,7 +63,7 @@ const getMetadata = async (objects: Array) => { }, }); return metadata[0]; - }) + }), ); return metadatas; }; diff --git a/templates/fungible-asset-template/frontend/main.tsx b/templates/fungible-asset-template/frontend/main.tsx index 702a22f2..7fa87ab2 100644 --- a/templates/fungible-asset-template/frontend/main.tsx +++ b/templates/fungible-asset-template/frontend/main.tsx @@ -4,10 +4,11 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import React from "react"; import ReactDOM from "react-dom/client"; -import App from "./App.tsx"; -import { Toaster } from "./components/ui/toaster.tsx"; -import { TooltipProvider } from "./components/ui/tooltip.tsx"; -import { WalletProvider } from "./components/WalletProvider.tsx"; +import App from "@/App.tsx"; +// Internal components +import { Toaster } from "@/components/ui/toaster.tsx"; +import { TooltipProvider } from "@/components/ui/tooltip.tsx"; +import { WalletProvider } from "@/components/WalletProvider.tsx"; const queryClient = new QueryClient(); @@ -21,5 +22,5 @@ ReactDOM.createRoot(document.getElementById("root")!).render( - + , ); diff --git a/templates/fungible-asset-template/frontend/pages/CreateFungibleAsset.tsx b/templates/fungible-asset-template/frontend/pages/CreateFungibleAsset.tsx index 17576128..a4638cac 100644 --- a/templates/fungible-asset-template/frontend/pages/CreateFungibleAsset.tsx +++ b/templates/fungible-asset-template/frontend/pages/CreateFungibleAsset.tsx @@ -1,82 +1,90 @@ +import { useWallet } from "@aptos-labs/wallet-adapter-react"; +import { Link, useNavigate } from "react-router-dom"; +import { useRef, useState } from "react"; +// Internal components import { Button, buttonVariants } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; - -import { checkIfFund, uploadFile } from "@/utils/Irys"; -import { useWallet } from "@aptos-labs/wallet-adapter-react"; -import { Link, useNavigate } from "react-router-dom"; -import { useRef, useState } from "react"; -import { aptosClient } from "@/utils/aptosClient"; -import { - APT_DECIMALS, - convertAmountFromHumanReadableToOnChain, - convertAmountFromOnChainToHumanReadable, -} from "@/utils/helpers"; -import { LaunchpadHeader } from "@/components/LaunchpadHeader"; -import { CREATOR_ADDRESS } from "@/constants"; import { WarningAlert } from "@/components/ui/warning-alert"; import { UploadSpinner } from "@/components/UploadSpinner"; import { LabeledInput } from "@/components/ui/labeled-input"; import { ConfirmButton } from "@/components/ui/confirm-button"; +import { LaunchpadHeader } from "@/components/LaunchpadHeader"; +// Internal utils +import { checkIfFund, uploadFile } from "@/utils/Irys"; +import { aptosClient } from "@/utils/aptosClient"; +// Internal constants +import { CREATOR_ADDRESS } from "@/constants"; +// Entry functions +import { createAsset } from "@/entry-functions/create_asset"; export function CreateFungibleAsset() { + // Wallet Adapter provider const aptosWallet = useWallet(); const { account, signAndSubmitTransaction } = useWallet(); + + // If we are on Production mode, redierct to the public mint page const navigate = useNavigate(); - const [name, setName] = useState(); - const [symbol, setSymbol] = useState(); + if (import.meta.env.PROD) navigate("/", { replace: true }); + + // Collection data entered by the user on UI + const [name, setName] = useState(""); + const [symbol, setSymbol] = useState(""); const [maxSupply, setMaxSupply] = useState(); const [maxMintPerAccount, setMaxMintPerAccount] = useState(); const [decimal, setDecimal] = useState(); const [image, setImage] = useState(null); - const [projectURL, setProjectURL] = useState(); - const [mintFeePerFA, setMintFeePerFA] = useState(); - const [mintForMyself, setMintForMyself] = useState(); + const [projectURL, setProjectURL] = useState(""); + const [mintFeePerFA, setMintFeePerFA] = useState(); + const [mintForMyself, setMintForMyself] = useState(); + + // Internal state const [isUploading, setIsUploading] = useState(false); + + // Local Ref const inputRef = useRef(null); const disableCreateAssetButton = !name || !symbol || !maxSupply || !decimal || !projectURL || !maxMintPerAccount || !account || isUploading; - const createAsset = async () => { + // On create asset button clicked + const onCreateAsset = async () => { try { if (!account) throw new Error("Connect wallet first"); if (!image) throw new Error("Select image first"); + // Set internal isUploading state setIsUploading(true); + // Check an Irys node has funded const funded = await checkIfFund(aptosWallet, image.size); if (!funded) throw new Error("Current account balance is not enough to fund a decentralized asset node"); + // Upload asset file to Irys const iconURL = await uploadFile(aptosWallet, image); - const response = await signAndSubmitTransaction({ - data: { - function: `${import.meta.env.VITE_MODULE_ADDRESS}::launchpad::create_fa`, - typeArguments: [], - functionArguments: [ - convertAmountFromHumanReadableToOnChain(Number(maxSupply), Number(decimal)), - name, - symbol, - decimal, - iconURL, - projectURL, - mintFeePerFA - ? convertAmountFromOnChainToHumanReadable( - convertAmountFromHumanReadableToOnChain(Number(mintFeePerFA), APT_DECIMALS), - Number(decimal), - ) - : 0, - mintForMyself ? convertAmountFromHumanReadableToOnChain(Number(mintForMyself), Number(decimal)) : 0, - maxMintPerAccount ? convertAmountFromHumanReadableToOnChain(maxMintPerAccount, Number(decimal)) : 0, - ], - }, - }); + // Submit a create_fa entry function transaction + const response = await signAndSubmitTransaction( + createAsset({ + maxSupply: Number(maxSupply), + name, + symbol, + decimal: Number(decimal), + iconURL, + projectURL, + mintFeePerFA, + mintForMyself, + maxMintPerAccount, + }), + ); + // Wait for the transaction to be commited to chain const committedTransactionResponse = await aptosClient().waitForTransaction({ transactionHash: response.hash, }); + + // Once the transaction has been successfully commited to chain, navigate to the `my-assets` page if (committedTransactionResponse.success) { navigate(`/my-assets`, { replace: true }); } @@ -220,7 +228,7 @@ export function CreateFungibleAsset() { id="mint-fee" label="Mint fee per fungible asset in APT" tooltip="The fee cost for the minter to pay to mint one full unit of an asset, denominated in APT. For example, if a user mints 10 assets in a single transaction, they are charged 10x the mint fee." - onChange={(e) => setMintFeePerFA(e.target.value)} + onChange={(e) => setMintFeePerFA(Number(e.target.value))} disabled={isUploading || !account} type="number" /> @@ -229,7 +237,7 @@ export function CreateFungibleAsset() { id="for-myself" label="Mint for myself" tooltip="How many assets in full unit to mint right away and send to your address." - onChange={(e) => setMintForMyself(e.target.value)} + onChange={(e) => setMintForMyself(Number(e.target.value))} disabled={isUploading || !account} type="number" /> @@ -237,7 +245,7 @@ export function CreateFungibleAsset() { diff --git a/templates/fungible-asset-template/frontend/pages/Mint/components/ConnectWalletAlert.tsx b/templates/fungible-asset-template/frontend/pages/Mint/components/ConnectWalletAlert.tsx index 9b1b187f..58f7d78a 100644 --- a/templates/fungible-asset-template/frontend/pages/Mint/components/ConnectWalletAlert.tsx +++ b/templates/fungible-asset-template/frontend/pages/Mint/components/ConnectWalletAlert.tsx @@ -1,7 +1,9 @@ -import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { config } from "@/config"; import { AlertOctagon } from "lucide-react"; import { FC } from "react"; +// Internal components +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; +// Internal config +import { config } from "@/config"; export const ConnectWalletAlert: FC = () => { if (config.asset_id) return null; @@ -15,9 +17,8 @@ export const ConnectWalletAlert: FC = () => { This page is placeholder content, to render your fungible asset:
  1. - Make sure you have created a fungible asset, click the "My Assets" - button and verify a collection is created, if not, click "Create - Asset". + Make sure you have created a fungible asset, click the "My Assets" button and verify a collection is + created, if not, click "Create Asset".
  2. Fill in the{" "} diff --git a/templates/fungible-asset-template/frontend/pages/Mint/components/HeroSection.tsx b/templates/fungible-asset-template/frontend/pages/Mint/components/HeroSection.tsx index f5a38576..9de3e798 100644 --- a/templates/fungible-asset-template/frontend/pages/Mint/components/HeroSection.tsx +++ b/templates/fungible-asset-template/frontend/pages/Mint/components/HeroSection.tsx @@ -1,25 +1,33 @@ import { FC, FormEvent, useState } from "react"; +import { useQueryClient } from "@tanstack/react-query"; +import { useWallet } from "@aptos-labs/wallet-adapter-react"; +// Internal utils import { truncateAddress } from "@/utils/truncateAddress"; +// Internal components import { Image } from "@/components/ui/image"; import { Card, CardContent } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Button, buttonVariants } from "@/components/ui/button"; -import { useMintData } from "../hooks/useMintData"; -import Copy from "@/assets/icons/copy.svg"; -import ExternalLink from "@/assets/icons/external-link.svg"; -import { Socials } from "./Socials"; -import { MODULE_ADDRESS, NETWORK } from "@/constants"; -import { useWallet } from "@aptos-labs/wallet-adapter-react"; +import { Socials } from "@/pages/Mint/components/Socials"; +// Internal hooks +import { useGetAssetData } from "../../../hooks/useGetAssetData"; +// Internal utils import { aptosClient } from "@/utils/aptosClient"; -import { useQueryClient } from "@tanstack/react-query"; +// Internal constants +import { NETWORK } from "@/constants"; +// Internal assets import Placeholder1 from "@/assets/placeholders/asset.png"; +import ExternalLink from "@/assets/icons/external-link.svg"; +import Copy from "@/assets/icons/copy.svg"; +// Internal config import { config } from "@/config"; -import { convertAmountFromHumanReadableToOnChain } from "@/utils/helpers"; +// Internal enrty functions +import { mintAsset } from "@/entry-functions/mint_asset"; interface HeroSectionProps {} export const HeroSection: React.FC = () => { - const { data } = useMintData(); + const { data } = useGetAssetData(); const queryClient = useQueryClient(); const { account, signAndSubmitTransaction } = useWallet(); const [assetCount, setAssetCount] = useState("1"); @@ -48,12 +56,13 @@ export const HeroSection: React.FC = () => { return setError("Invalid amount"); } - const response = await signAndSubmitTransaction({ - data: { - function: `${MODULE_ADDRESS}::launchpad::mint_fa`, - functionArguments: [asset.asset_type, convertAmountFromHumanReadableToOnChain(amount, asset.decimals)], - }, - }); + const response = await signAndSubmitTransaction( + mintAsset({ + assetType: asset.asset_type, + amount, + decimals: asset.decimals, + }), + ); await aptosClient().waitForTransaction({ transactionHash: response.hash }); queryClient.invalidateQueries(); setAssetCount("1"); diff --git a/templates/fungible-asset-template/frontend/pages/Mint/components/OurStorySection.tsx b/templates/fungible-asset-template/frontend/pages/Mint/components/OurStorySection.tsx index 34d71bfe..bba7d40f 100644 --- a/templates/fungible-asset-template/frontend/pages/Mint/components/OurStorySection.tsx +++ b/templates/fungible-asset-template/frontend/pages/Mint/components/OurStorySection.tsx @@ -1,4 +1,6 @@ +// Internal components import { buttonVariants } from "@/components/ui/button"; +// Internal config import { config } from "@/config"; interface OurStorySectionProps {} @@ -19,7 +21,8 @@ export const OurStorySection: React.FC = () => { className={buttonVariants({ variant: "outline", className: "mt-4", - })}> + })} + > Join Our Discord )} diff --git a/templates/fungible-asset-template/frontend/pages/Mint/components/Socials.tsx b/templates/fungible-asset-template/frontend/pages/Mint/components/Socials.tsx index cac0a9c9..3afbb072 100644 --- a/templates/fungible-asset-template/frontend/pages/Mint/components/Socials.tsx +++ b/templates/fungible-asset-template/frontend/pages/Mint/components/Socials.tsx @@ -1,7 +1,10 @@ +import { FC } from "react"; +// Internal components import { buttonVariants } from "@/components/ui/button"; import { Image } from "@/components/ui/image"; +// Internal config import { config } from "@/config"; -import { FC } from "react"; +// Internal assets import Twitter from "@/assets/icons/twitter.svg"; import Link from "@/assets/icons/link.svg"; import Discord from "@/assets/icons/discord.svg"; @@ -16,7 +19,8 @@ export const Socials: FC = () => { + className={buttonVariants({ variant: "icon", size: "icon" })} + >
  3. @@ -26,7 +30,8 @@ export const Socials: FC = () => { + className={buttonVariants({ variant: "icon", size: "icon" })} + > @@ -36,7 +41,8 @@ export const Socials: FC = () => { + className={buttonVariants({ variant: "icon", size: "icon" })} + > diff --git a/templates/fungible-asset-template/frontend/pages/Mint/components/StatsSection.tsx b/templates/fungible-asset-template/frontend/pages/Mint/components/StatsSection.tsx index b832fbff..9f32102f 100644 --- a/templates/fungible-asset-template/frontend/pages/Mint/components/StatsSection.tsx +++ b/templates/fungible-asset-template/frontend/pages/Mint/components/StatsSection.tsx @@ -1,11 +1,11 @@ import { Card } from "@/components/ui/card"; import { clampNumber } from "@/utils/clampNumber"; -import { useMintData } from "../hooks/useMintData"; +import { useGetAssetData } from "../../../hooks/useGetAssetData"; interface StatsSectionProps {} export const StatsSection: React.FC = () => { - const { data } = useMintData(); + const { data } = useGetAssetData(); if (!data) return null; const { maxSupply, currentSupply, uniqueHolders } = data; diff --git a/templates/fungible-asset-template/frontend/pages/Mint/index.tsx b/templates/fungible-asset-template/frontend/pages/Mint/index.tsx index f6d21a8d..041abde4 100644 --- a/templates/fungible-asset-template/frontend/pages/Mint/index.tsx +++ b/templates/fungible-asset-template/frontend/pages/Mint/index.tsx @@ -1,7 +1,7 @@ import { HeroSection } from "./components/HeroSection"; import { StatsSection } from "./components/StatsSection"; import { OurStorySection } from "./components/OurStorySection"; -import { useMintData } from "./hooks/useMintData"; +import { useGetAssetData } from "../../hooks/useGetAssetData"; import { Socials } from "./components/Socials"; import { ConnectWalletAlert } from "./components/ConnectWalletAlert"; import { Header } from "@/components/Header"; @@ -10,7 +10,7 @@ import { useEffect } from "react"; import { useQueryClient } from "@tanstack/react-query"; export function Mint() { - const { data, isLoading } = useMintData(); + const { data, isLoading } = useGetAssetData(); const queryClient = useQueryClient(); const { account } = useWallet(); diff --git a/templates/fungible-asset-template/frontend/pages/MyFungibleAssets.tsx b/templates/fungible-asset-template/frontend/pages/MyFungibleAssets.tsx index 147a4c45..f033e611 100644 --- a/templates/fungible-asset-template/frontend/pages/MyFungibleAssets.tsx +++ b/templates/fungible-asset-template/frontend/pages/MyFungibleAssets.tsx @@ -1,28 +1,22 @@ +import { Link, useNavigate } from "react-router-dom"; +// Internal components import { LaunchpadHeader } from "@/components/LaunchpadHeader"; -import { - Table, - TableBody, - TableCaption, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; +import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; +// Internal hooks import { useGetAssetMetadata } from "@/hooks/useGetAssetMetadata"; -import { Link } from "react-router-dom"; export function MyFungibleAssets() { const fas = useGetAssetMetadata(); + // If we are on Production mode, redierct to the public mint page + const navigate = useNavigate(); + if (import.meta.env.PROD) navigate("/", { replace: true }); + return ( <> - {!fas.length && ( - - A list of the fungible assets created under the current contract. - - )} + {!fas.length && A list of the fungible assets created under the current contract.} Symbol @@ -40,10 +34,7 @@ export function MyFungibleAssets() {
    - + {fa.symbol}
    @@ -54,7 +45,8 @@ export function MyFungibleAssets() { fa.asset_type }?network=${import.meta.env.VITE_APP_NETWORK}`} target="_blank" - style={{ textDecoration: "underline" }}> + style={{ textDecoration: "underline" }} + > {fa.asset_type} diff --git a/templates/fungible-asset-template/frontend/utils/Irys.ts b/templates/fungible-asset-template/frontend/utils/Irys.ts index bba379e3..689ed404 100644 --- a/templates/fungible-asset-template/frontend/utils/Irys.ts +++ b/templates/fungible-asset-template/frontend/utils/Irys.ts @@ -1,6 +1,6 @@ import { WebIrys } from "@irys/sdk"; import { WalletContextState } from "@aptos-labs/wallet-adapter-react"; -import { aptosClient } from "./aptosClient"; +import { accountAPTBalance } from "@/view-functions/accountBalance"; // eslint-disable-next-line @typescript-eslint/no-explicit-any const getWebIrys = async (aptosWallet: any) => { @@ -34,16 +34,10 @@ export const checkIfFund = async (aptosWallet: WalletContextState, fileSize: num // 4. if balance is not enough, check the payer balance const currentAccountAddress = await aptosWallet.account!.address; - const currentAccountBalance = await aptosClient().view<[number]>({ - payload: { - function: "0x1::coin::balance", - typeArguments: ["0x1::aptos_coin::AptosCoin"], - functionArguments: [currentAccountAddress], - }, - }); + const currentAccountBalance = await accountAPTBalance({ accountAddress: currentAccountAddress }); // 5. if payer balance > the amount based on the estimation, fund the irys node irys.fund, then upload - if (currentAccountBalance[0] > costToUpload.toNumber()) { + if (currentAccountBalance > costToUpload.toNumber()) { try { await fundNode(aptosWallet, costToUpload.toNumber()); return true; diff --git a/templates/fungible-asset-template/frontend/view-functions/accountBalance.ts b/templates/fungible-asset-template/frontend/view-functions/accountBalance.ts new file mode 100644 index 00000000..ff25b9e4 --- /dev/null +++ b/templates/fungible-asset-template/frontend/view-functions/accountBalance.ts @@ -0,0 +1,17 @@ +import { aptosClient } from "@/utils/aptosClient"; + +export type AccountAPTBalanceArguments = { + accountAddress: string; +}; + +export const accountAPTBalance = async (args: AccountAPTBalanceArguments): Promise => { + const { accountAddress } = args; + const balance = await aptosClient().view<[number]>({ + payload: { + function: "0x1::coin::balance", + typeArguments: ["0x1::aptos_coin::AptosCoin"], + functionArguments: [accountAddress], + }, + }); + return balance[0]; +};