Skip to content

Commit

Permalink
add token mint functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
exitatmosphere committed Feb 21, 2025
1 parent c2d0268 commit 5021b24
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/components/AppBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ export const AppBar: FC = (props) => {
Upload metadata
</a>
</Link>
<Link href="/utils">
<a className="btn btn-ghost rounded-btn btn-sm">Token utils</a>
</Link>
<Link href="/misc">
<a className="btn btn-ghost rounded-btn btn-sm">Miscellaneous</a>
</Link>
Expand Down
5 changes: 5 additions & 0 deletions src/components/ContentContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export const ContentContainer: FC = (props) => {
<a>Upload metadata</a>
</Link>
</li>
<li>
<Link href="/utils">
<a>Token utils</a>
</Link>
</li>
<li>
<Link href="/misc">
<a>Miscellaneous</a>
Expand Down
153 changes: 153 additions & 0 deletions src/components/Mint.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { PublicKey, Transaction, TransactionSignature } from "@solana/web3.js";
import { ChangeEvent, FC, useCallback, useState } from "react";
import { notify } from "../utils/notifications";
import { INPUT_FLOAT_REGEX } from "../constants";
import {
createAssociatedTokenAccountInstruction,
createMintToInstruction,
getAssociatedTokenAddress,
getMint,
} from "@solana/spl-token";

export const Mint: FC = () => {
const { connection } = useConnection();
const { publicKey, sendTransaction } = useWallet();

const [tokenMintAddress, setTokenMintAddress] = useState("");
const [receiverAddress, setReceiverAddress] = useState("");
const [amount, setAmount] = useState("0.0");

const tokenInputValidation = async (e: ChangeEvent<HTMLInputElement>) => {
const res = new RegExp(INPUT_FLOAT_REGEX).exec(e.target.value);
res && setAmount(e.target.value);
};

const onClick = useCallback(async () => {
if (!publicKey) {
notify({ type: "error", message: `Wallet not connected!` });
console.log("error", `Send Transaction: Wallet not connected!`);
return;
}

let signature: TransactionSignature = "";
const transaction = new Transaction();

try {
const tokenMintPubkey = new PublicKey(tokenMintAddress);
const receiverPubkey = new PublicKey(receiverAddress);

const mintAccountInfo = await getMint(connection, tokenMintPubkey);
const decimals = mintAccountInfo.decimals;

const tokenReceiverAccount = await getAssociatedTokenAddress(
tokenMintPubkey,
receiverPubkey,
true,
);

if (
!(await connection.getAccountInfo(tokenReceiverAccount))?.data.length
) {
transaction.add(
createAssociatedTokenAccountInstruction(
publicKey,
tokenReceiverAccount,
receiverPubkey,
tokenMintPubkey,
),
);
}

transaction.add(
createMintToInstruction(
tokenMintPubkey,
tokenReceiverAccount,
publicKey,
10 ** decimals * Number(amount),
),
);

signature = await sendTransaction(transaction, connection);

notify({
type: "success",
message: "Transaction successful!",
txid: signature,
});
} catch (error: any) {
notify({
type: "error",
message: `Transaction failed!`,
description: error?.message,
txid: signature,
});
console.log("error", `Transaction failed! ${error?.message}`, signature);
return;
}
}, [
publicKey,
tokenMintAddress,
receiverAddress,
amount,
sendTransaction,
connection,
]);

return (
<div>
<div>
<div className="p-2">
<div className="text-xl font-normal">Mint tokens</div>
</div>
<div className="mt-4 sm:grid sm:grid-cols-2 sm:gap-4">
<div className="m-auto p-2 text-xl font-normal">
Token mint address
</div>
<div className="m-auto p-2">
<input
className="rounded border px-4 py-2 text-xl font-normal text-gray-700 focus:border-blue-600 focus:outline-none"
onChange={(e) => setTokenMintAddress(e.target.value)}
/>
</div>
</div>
<div className="mt-4 sm:grid sm:grid-cols-2 sm:gap-4">
<div className="m-auto p-2 text-xl font-normal">
Receiver wallet address
</div>
<div className="m-auto p-2">
<input
className="rounded border px-4 py-2 text-xl font-normal text-gray-700 focus:border-blue-600 focus:outline-none"
onChange={(e) => setReceiverAddress(e.target.value)}
/>
</div>
</div>
<div className="mt-4 sm:grid sm:grid-cols-2 sm:gap-4">
<div className="m-auto p-2 text-xl font-normal">Amount</div>
<div className="m-auto p-2">
<input
className="rounded border px-4 py-2 text-xl font-normal text-gray-700 focus:border-blue-600 focus:outline-none"
value={amount}
maxLength={20}
onChange={(e) => tokenInputValidation(e)}
/>
</div>
</div>
<div className="mt-4">
<button
className="... group btn m-2 w-60 animate-pulse bg-gradient-to-r from-[#9945FF] to-[#14F195] hover:from-pink-500 hover:to-yellow-500 disabled:animate-none "
onClick={onClick}
disabled={!publicKey}
>
<div className="hidden group-disabled:block ">
Wallet not connected
</div>
<span className="block group-disabled:hidden">
Send Transaction
</span>
</button>
</div>
</div>
</div>
);
};
9 changes: 4 additions & 5 deletions src/components/SendTransaction.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import {
Keypair,
LAMPORTS_PER_SOL,
PublicKey,
SystemProgram,
Transaction,
TransactionSignature,
} from "@solana/web3.js";
import { FC, useCallback, useState } from "react";
import { ChangeEvent, FC, useCallback, useState } from "react";
import { notify } from "../utils/notifications";
import { INPUT_FLOAT_REGEX } from "../constants";

export const SendTransaction: FC = () => {
const { connection } = useConnection();
const { publicKey, sendTransaction } = useWallet();

const [amount, setAmount] = useState("0.0");

const solInputValidation = async (e) => {
const monstrosity = /((^\.(\d+)?$)|(^\d+(\.\d*)?$)|(^$))/;
const res = new RegExp(monstrosity).exec(e.target.value);
const solInputValidation = async (e: ChangeEvent<HTMLInputElement>) => {
const res = new RegExp(INPUT_FLOAT_REGEX).exec(e.target.value);
res && setAmount(e.target.value);
};

Expand Down
1 change: 1 addition & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const INPUT_FLOAT_REGEX = /((^\.(\d+)?$)|(^\d+(\.\d*)?$)|(^$))/;
2 changes: 1 addition & 1 deletion src/pages/misc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const Misc: NextPage = (props) => {
<div>
<Head>
<title>Solana Token Creator - Miscellaneous</title>
<meta name="description" content="Additional Functionality" />
<meta name="description" content="Additional functionality" />
</Head>
<MiscView />
</div>
Expand Down
17 changes: 17 additions & 0 deletions src/pages/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { NextPage } from "next";
import Head from "next/head";
import { UtilsView } from "../views";

const Utils: NextPage = (props) => {
return (
<div>
<Head>
<title>Solana Token Creator - Token Utils</title>
<meta name="description" content="Token functionality" />
</Head>
<UtilsView />
</div>
);
};

export default Utils;
1 change: 1 addition & 0 deletions src/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { HomeView } from "./home";
export { MiscView } from "./misc";
export { UploadView } from "./upload";
export { CreateView } from "./create";
export { UtilsView } from "./utils";
18 changes: 18 additions & 0 deletions src/views/utils/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Mint } from "components/Mint";
import { FC } from "react";

export const UtilsView: FC = ({}) => {
return (
<div className="mx-auto p-4 md:hero">
<div className="flex flex-col md:hero-content">
<h1 className="bg-gradient-to-tr from-[#9945FF] to-[#14F195] bg-clip-text text-center text-5xl font-bold text-transparent">
Token utils
</h1>
{/* CONTENT GOES HERE */}
<div className="text-center">
<Mint />
</div>
</div>
</div>
);
};

0 comments on commit 5021b24

Please sign in to comment.