Skip to content

Commit

Permalink
refactor and clean up fungible asset template (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmaayan authored Jun 24, 2024
1 parent e5744d3 commit e2ff94c
Show file tree
Hide file tree
Showing 21 changed files with 254 additions and 186 deletions.
8 changes: 4 additions & 4 deletions templates/fungible-asset-template/frontend/App.tsx
Original file line number Diff line number Diff line change
@@ -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 (
Expand Down
18 changes: 5 additions & 13 deletions templates/fungible-asset-template/frontend/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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 (
Expand All @@ -31,14 +27,10 @@ export function Header() {
<div className="flex gap-2 items-center flex-wrap">
{IS_DEV && (
<>
<Link
className={buttonVariants({ variant: "link" })}
to={"/my-assets"}>
<Link className={buttonVariants({ variant: "link" })} to={"/my-assets"}>
My Assets
</Link>
<Link
className={buttonVariants({ variant: "link" })}
to={"/create-asset"}>
<Link className={buttonVariants({ variant: "link" })} to={"/create-asset"}>
Create Asset
</Link>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -19,15 +20,11 @@ export const LaunchpadHeader: FC<LaunchpadHeaderProps> = ({ title }) => {
Mint Page
</Link>
{location.pathname === "/my-assets" ? (
<Link
className={buttonVariants({ variant: "link" })}
to={"/create-asset"}>
<Link className={buttonVariants({ variant: "link" })} to={"/create-asset"}>
Create Asset
</Link>
) : (
<Link
className={buttonVariants({ variant: "link" })}
to={"/my-assets"}>
<Link className={buttonVariants({ variant: "link" })} to={"/my-assets"}>
My Assets
</Link>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<div
className={cn(
"top-0 left-0 fixed w-full h-full bg-gray-500 bg-opacity-30 flex justify-center items-center flex-col transition-all",
on ? "opacity-100 z-10" : "opacity-0 z-0 pointer-events-none"
on ? "opacity-100 z-10" : "opacity-0 z-0 pointer-events-none",
)}
>
<p className="display">Uploading Files...</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -60,22 +51,15 @@ export function WalletSelector() {
return connected ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button>
{account?.ansName || truncateAddress(account?.address) || "Unknown"}
</Button>
<Button>{account?.ansName || truncateAddress(account?.address) || "Unknown"}</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onSelect={copyAddress} className="gap-2">
<Copy className="h-4 w-4" /> Copy address
</DropdownMenuItem>
{wallet && isAptosConnectWallet(wallet) && (
<DropdownMenuItem asChild>
<a
href={APTOS_CONNECT_ACCOUNT_URL}
target="_blank"
rel="noopener noreferrer"
className="flex gap-2"
>
<a href={APTOS_CONNECT_ACCOUNT_URL} target="_blank" rel="noopener noreferrer" className="flex gap-2">
<User className="h-4 w-4" /> Account
</a>
</DropdownMenuItem>
Expand Down Expand Up @@ -133,11 +117,7 @@ function ConnectWalletDialog({ close }: ConnectWalletDialogProps) {
</DialogHeader>
<div className="flex flex-col gap-3 pt-3">
{aptosConnectWallets.map((wallet) => (
<AptosConnectWalletRow
key={wallet.name}
wallet={wallet}
onConnect={close}
/>
<AptosConnectWalletRow key={wallet.name} wallet={wallet} onConnect={close} />
))}
</div>
<div className="flex items-center gap-3 pt-4 text-muted-foreground">
Expand Down Expand Up @@ -166,11 +146,7 @@ function ConnectWalletDialog({ close }: ConnectWalletDialogProps) {
</CollapsibleTrigger>
<CollapsibleContent className="flex flex-col gap-3">
{moreWallets.map((wallet) => (
<WalletRow
key={wallet.name}
wallet={wallet}
onConnect={close}
/>
<WalletRow key={wallet.name} wallet={wallet} onConnect={close} />
))}
</CollapsibleContent>
</Collapsible>
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
],
},
};
};
Original file line number Diff line number Diff line change
@@ -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)],
},
};
};
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -49,7 +52,10 @@ async function getMintLimit(asset_id: string): Promise<number> {
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({
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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];
Expand All @@ -51,7 +47,7 @@ const getObjects = async (registry: [{ inner: string }]) => {
});

return object.owner_address;
})
}),
);
return objects;
};
Expand All @@ -67,7 +63,7 @@ const getMetadata = async (objects: Array<string>) => {
},
});
return metadata[0];
})
}),
);
return metadatas;
};
11 changes: 6 additions & 5 deletions templates/fungible-asset-template/frontend/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -21,5 +22,5 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
</TooltipProvider>
</QueryClientProvider>
</WalletProvider>
</React.StrictMode>
</React.StrictMode>,
);
Loading

0 comments on commit e2ff94c

Please sign in to comment.