Reputation: 83
I'm trying to transfer USDC on Solana using @solana/spl-token
in a React app with @solana/wallet-adapter-react
, but I'm getting this error:
Uncaught TypeError: Cannot read properties of undefined (reading 'from')
at @solana_spl-token.js?v=0c2b08b7:5387:43
🔹 What I'm Doing:
getAssociatedTokenAddress
.getAccount
.createTransferInstruction
to transfer USDC.TOKEN_PROGRAM_ID
is imported.🔍 Troubleshooting I've Tried:
getAssociatedTokenAddress
values.BigInt(Math.round(amount * 1e6))
).TOKEN_PROGRAM_ID
is correctly imported.❓ Where Could This Error Be Coming From?
getAssociatedTokenAddress
return undefined
under certain conditions?createTransferInstruction
that might cause this?Here's my full React/TypeScript code for reference:
import { useState, useEffect } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import {
Connection,
PublicKey,
Transaction,
} from "@solana/web3.js";
import {
getAssociatedTokenAddress,
createAssociatedTokenAccountInstruction,
createTransferInstruction,
getAccount,
TOKEN_PROGRAM_ID, // Ensure TOKEN_PROGRAM_ID is imported
} from "@solana/spl-token";
import axios from "axios";
const USDC_MINT_ADDRESS = new PublicKey("11111111111111111111111111111111111111111111");
const USDC = () => {
const { publicKey, sendTransaction } = useWallet();
const [recipient, setRecipient] = useState("");
const [amount, setAmount] = useState<string>(""); // Keep it as a string for input handling
const connection = new Connection("https://api.devnet.solana.com");
useEffect(() => {
fetchRecipientAddress();
}, []);
const fetchRecipientAddress = async () => {
try {
console.log("Fetching recipient wallet address...");
const response = await axios.get("http://192.168.29.183:5000/wallet");
setRecipient(response.data.wallet_address);
console.log("✅ Recipient Wallet Address:", response.data.wallet_address);
} catch (error) {
console.error("❌ Error fetching recipient address:", error);
}
};
const transferUSDC = async (recipientWallet: string, amount: number): Promise<void> => {
try {
console.log("🔹 USDC Transfer Initiated...");
if (!publicKey) {
console.error("🚨 Wallet not connected. Aborting transaction.");
alert("⚠️ Wallet not connected!");
return;
}
console.log("✅ Wallet Connected:", publicKey.toBase58());
const senderPublicKey = publicKey;
const recipientPublicKey = new PublicKey(recipientWallet);
console.log("✅ Recipient Public Key:", recipientPublicKey.toBase58());
// ✅ Log ATA Before Fetching
console.log("🔍 Fetching Associated Token Addresses...");
const senderTokenAccount = await getAssociatedTokenAddress(
USDC_MINT_ADDRESS, senderPublicKey, false, TOKEN_PROGRAM_ID
);
const recipientTokenAccount = await getAssociatedTokenAddress(
USDC_MINT_ADDRESS, recipientPublicKey, false, TOKEN_PROGRAM_ID
);
if (!senderTokenAccount || !recipientTokenAccount) {
console.error("❌ Error fetching token accounts!");
alert("⚠️ Error retrieving token accounts.");
return;
}
console.log("✅ Sender USDC Token Account:", senderTokenAccount.toBase58());
console.log("✅ Recipient USDC Token Account:", recipientTokenAccount.toBase58());
// ✅ Ensure sender has a USDC token account
try {
console.log("🔍 Checking sender's USDC token account...");
await getAccount(connection, senderTokenAccount);
console.log("✅ Sender USDC token account exists.");
} catch (error) {
console.error("❌ Sender does not have a USDC token account!");
alert("⚠️ Your wallet doesn't have a USDC account. Please receive some USDC first.");
return;
}
// ✅ Check if recipient's ATA exists
console.log("🔍 Checking recipient's USDC token account...");
const recipientATAInfo = await connection.getAccountInfo(recipientTokenAccount);
const transaction = new Transaction();
if (!recipientATAInfo) {
console.log("⚠️ Recipient does not have a USDC ATA. Creating one...");
transaction.add(
createAssociatedTokenAccountInstruction(
senderPublicKey,
recipientTokenAccount,
recipientPublicKey,
USDC_MINT_ADDRESS,
TOKEN_PROGRAM_ID
)
);
console.log("✅ Recipient USDC ATA Created.");
} else {
console.log("✅ Recipient already has a USDC ATA.");
}
// ✅ Convert amount to smallest unit & use BigInt
const amountInSmallestUnit = BigInt(Math.round(amount * 1e6));
// ✅ Add transfer instruction
console.log(`🔹 Adding transfer instruction: ${amount} USDC`);
transaction.add(
createTransferInstruction(
senderTokenAccount,
recipientTokenAccount,
senderPublicKey,
amountInSmallestUnit,
[],
TOKEN_PROGRAM_ID
)
);
console.log("✅ Transaction built, sending transaction...");
// ✅ Send transaction
const signature = await sendTransaction(transaction, connection);
console.log("✅ USDC Transfer Successful! Signature:", signature);
alert(`✅ Transfer successful! Transaction: ${signature}`);
} catch (error) {
console.error("❌ USDC Transfer Failed:", error);
alert("❌ Transfer failed. Check console for details.");
}
};
const handleTransfer = async () => {
if (!publicKey) {
alert("⚠️ Connect your wallet first!");
return;
}
if (!recipient) {
alert("⚠️ Recipient address not fetched!");
return;
}
// ✅ Convert amount to number
const numericAmount = parseFloat(amount);
if (isNaN(numericAmount) || numericAmount <= 0) {
alert("⚠️ Please enter a valid amount.");
return;
}
console.log("🔹 Initiating transfer process...");
try {
await transferUSDC(recipient, numericAmount); // Pass number, not string
} catch (error) {
console.error(error);
}
};
return (
<div>
<h2>USDC Transfer</h2>
<p><strong>Recipient Wallet:</strong> {recipient || "Fetching..."}</p>
<input
type="number"
placeholder="Amount (USDC)"
value={amount}
onChange={(e) => setAmount(e.target.value)} // Keep as string
/>
<button onClick={handleTransfer}>Send USDC</button>
</div>
);
};
export default USDC;
Upvotes: 1
Views: 30