Murphy Logo Murphy

Send Token Form

A Solana token transfer component with shadcn UI styling

Send Token Form

Send Tokens

Installation

Install dependencies

Start by installing required Solana dependencies

pnpm add @solana/web3.js @solana/spl-token @solana/wallet-adapter-react

Add Wallet Provider

Make sure you have added the Wallet Provider to your application. If not, follow the steps in the Connect Wallet Button guide first.

Add Send Token Form

pnpm dlx shadcn@canary add https://www.murphyai.dev/r/send-token-form.json

Basic Usage

import { SendTokenForm } from "@/components/ui/murphy/send-token-form";
export default function MyPage() {
  return (
    <div>
      <h1 className="text-xl font-bold mb-2">Transfer Solana Tokens</h1>
      <SendTokenForm className="max-w-md" />
    </div>
  );
}

Custom Token List

You can provide your own token list:

import {
  SendTokenForm,
  TokenInfo,
} from "@/components/ui/murphy/send-token-form";
 
export default function MyPage() {
  const customTokens: TokenInfo[] = [
    {
      id: "sol",
      symbol: "SOL",
      name: "Solana",
      balance: 5.25,
      decimals: 9,
      mintAddress: "So11111111111111111111111111111111111111112",
      icon: "/crypto-logos/solana-logo.svg",
    },
    {
      id: "usdc",
      symbol: "USDC",
      name: "USD Coin",
      balance: 100.5,
      decimals: 6,
      mintAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      icon: "/crypto-logos/usdc-logo.svg",
    },
  ];
 
  return (
    <div>
      <h1 className="text-xl font-bold mb-2">Transfer Tokens</h1>
      <SendTokenForm tokens={customTokens} className="max-w-md" />
    </div>
  );
}

Custom Transaction Handling

You can provide your own send token function:

import { SendTokenForm } from "@/components/ui/murphy/send-token-form";
import { toast } from "sonner";
import type { FormValues } from "@/components/ui/murphy/send-token-form";
 
export default function MyPage() {
  const handleSendToken = async (values: FormValues) => {
    // Your custom transaction logic
    console.log(
      "Sending",
      values.amount,
      "of token",
      values.token,
      "to",
      values.destination
    );
 
    // Example of custom validation
    if (values.amount > 10) {
      throw new Error("Amount cannot exceed 10 tokens");
    }
 
    // Wait for transaction
    await new Promise((resolve) => setTimeout(resolve, 1000));
 
    // Show success notification
    toast.success("Transaction completed");
  };
 
  return (
    <div>
      <h1 className="text-xl font-bold mb-2">Custom Transfer</h1>
      <SendTokenForm onSendToken={handleSendToken} className="max-w-md" />
    </div>
  );
}

Props

PropTypeDefault
tokens?
TokenInfo[]
undefined
onSendToken?
(values: FormValues) => Promise<void>
undefined
isLoading?
boolean
false
showTokenBalance?
boolean
true
validateDestination?
(address: string) => Promise<boolean>
undefined
className?
string
undefined

Types

The component uses the following types:

// Form values type
type FormValues = {
  destination: string;
  amount: number | undefined;
  token: string;
};
 
// Token information type
export type TokenInfo = {
  id: string;
  symbol: string;
  name: string;
  balance: number;
  decimals: number;
  mintAddress?: string;
  icon?: string;
};

On this page