- @solana/kit
- @solana/web3.js
- Anchor
import { useParaSolanaSigner, useParaSolanaSignAndSend } from '@getpara/react-sdk';
import {
createSolanaRpc,
pipe,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
address
} from '@solana/kit';
import {
getCreateAssociatedTokenAccountInstruction,
findAssociatedTokenPda,
getCloseAccountInstruction
} from '@solana-program/token';
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
function ManageTokenAccounts() {
const { solanaSigner, isLoading } = useParaSolanaSigner({ rpc });
const { signAndSendAsync, isPending } = useParaSolanaSignAndSend(solanaSigner);
const createTokenAccount = async (mint: string, owner?: string) => {
if (!solanaSigner) return;
const mintAddress = address(mint);
const ownerAddress = owner ? address(owner) : solanaSigner.address;
const [ata] = await findAssociatedTokenPda({
mint: mintAddress,
owner: ownerAddress,
});
const accountInfo = await rpc.getAccountInfo(ata).send();
if (accountInfo.value) {
console.log("Token account already exists:", ata);
return ata;
}
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const transaction = pipe(
createTransactionMessage({ version: 0 }),
tx => setTransactionMessageFeePayer(solanaSigner.address, tx),
tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
tx => appendTransactionMessageInstruction(
getCreateAssociatedTokenAccountInstruction({
ata,
mint: mintAddress,
owner: ownerAddress,
payer: solanaSigner,
}),
tx
)
);
try {
const result = await signAndSendAsync({ transactions: [transaction] });
console.log("Created token account:", ata);
console.log("Transaction signature:", result);
return ata;
} catch (error) {
console.error("Failed to create token account:", error);
throw error;
}
};
const closeTokenAccount = async (tokenAccount: string) => {
if (!solanaSigner) return;
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const transaction = pipe(
createTransactionMessage({ version: 0 }),
tx => setTransactionMessageFeePayer(solanaSigner.address, tx),
tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
tx => appendTransactionMessageInstruction(
getCloseAccountInstruction({
account: address(tokenAccount),
destination: solanaSigner.address,
authority: solanaSigner,
}),
tx
)
);
try {
const result = await signAndSendAsync({ transactions: [transaction] });
console.log("Closed token account:", tokenAccount);
console.log("Transaction signature:", result);
return result;
} catch (error) {
console.error("Failed to close token account:", error);
throw error;
}
};
return (
<div>
<button onClick={() => createTokenAccount("USDC_MINT_ADDRESS")}>
Create USDC Account
</button>
<button onClick={() => closeTokenAccount("TOKEN_ACCOUNT_ADDRESS")}>
Close Token Account
</button>
</div>
);
}
import { useParaSolana } from './hooks/useParaSolana';
import { Transaction, PublicKey } from '@solana/web3.js';
import {
createAssociatedTokenAccountInstruction,
getAssociatedTokenAddress,
createCloseAccountInstruction,
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
} from '@solana/spl-token';
function ManageTokenAccounts() {
const { connection, signer } = useParaSolana();
const createTokenAccount = async (mint: string, owner?: string) => {
const mintPubkey = new PublicKey(mint);
const ownerPubkey = owner ? new PublicKey(owner) : signer.sender;
const ata = await getAssociatedTokenAddress(mintPubkey, ownerPubkey);
const accountInfo = await connection.getAccountInfo(ata);
if (accountInfo) {
console.log("Token account already exists:", ata.toString());
return ata;
}
const transaction = new Transaction().add(
createAssociatedTokenAccountInstruction(
signer.sender,
ata,
ownerPubkey,
mintPubkey,
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
)
);
try {
const signature = await signer.sendTransaction(transaction);
console.log("Created token account:", ata.toString());
console.log("Transaction signature:", signature);
return ata;
} catch (error) {
console.error("Failed to create token account:", error);
throw error;
}
};
const closeTokenAccount = async (tokenAccount: string) => {
const tokenAccountPubkey = new PublicKey(tokenAccount);
const transaction = new Transaction().add(
createCloseAccountInstruction(
tokenAccountPubkey,
signer.sender,
signer.sender,
[],
TOKEN_PROGRAM_ID
)
);
try {
const signature = await signer.sendTransaction(transaction);
console.log("Closed token account:", tokenAccount);
console.log("Transaction signature:", signature);
return signature;
} catch (error) {
console.error("Failed to close token account:", error);
throw error;
}
};
return (
<div>
<button onClick={() => createTokenAccount("USDC_MINT_ADDRESS")}>
Create USDC Account
</button>
<button onClick={() => closeTokenAccount("TOKEN_ACCOUNT_ADDRESS")}>
Close Token Account
</button>
</div>
);
}
Token account management uses
@solana-program/token with Codama-generated helpers:import { useParaSolanaSigner } from "@getpara/react-sdk";
import { createSolanaRpc } from "@solana/kit";
import { pipe, createTransactionMessage, setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstruction,
signAndSendTransactionMessageWithSigners } from "@solana/kit";
import { getCreateAssociatedTokenInstruction, findAssociatedTokenPda } from "@solana-program/token";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
function CreateTokenAccount() {
const { solanaSigner, isLoading } = useParaSolanaSigner({ rpc });
const createAccount = async (mintAddress: string) => {
if (!solanaSigner) return;
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const [ata] = await findAssociatedTokenPda({
mint: mintAddress as any,
owner: solanaSigner.address as any,
});
const instruction = getCreateAssociatedTokenInstruction({
payer: solanaSigner,
owner: solanaSigner.address as any,
mint: mintAddress as any,
ata,
});
const tx = pipe(
createTransactionMessage({ version: 0 }),
tx => setTransactionMessageFeePayerSigner(solanaSigner, tx),
tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
tx => appendTransactionMessageInstruction(instruction, tx),
);
const signature = await signAndSendTransactionMessageWithSigners(tx);
console.log("Token account created:", signature);
};
if (isLoading) return <p>Loading...</p>;
return <button onClick={() => createAccount("mint-address...")}>Create Token Account</button>;
}