import { LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js"; import { useGetBalance, useGetTokenAccountBalance, useGetTokenAccounts, useRequestAirdrop, useTransferSol, } from "./account-data-access"; import { View, StyleSheet, ScrollView } from "react-native"; import { Text, useTheme, Button, ActivityIndicator, DataTable, TextInput, } from "react-native-paper"; import { useState, useMemo } from "react"; import { ellipsify } from "../../utils/ellipsify"; import { AppModal } from "../ui/app-modal"; function lamportsToSol(balance: number) { return Math.round((balance / LAMPORTS_PER_SOL) * 100000) / 100000; } export function AccountBalance({ address }: { address: PublicKey }) { const query = useGetBalance({ address }); return ( <> Current Balance {query.data ? lamportsToSol(query.data) : "..."} SOL ); } export function AccountButtonGroup({ address }: { address: PublicKey }) { const requestAirdrop = useRequestAirdrop({ address }); const [showAirdropModal, setShowAirdropModal] = useState(false); const [showReceiveModal, setShowReceiveModal] = useState(false); const [showSendModal, setShowSendModal] = useState(false); return ( <> setShowAirdropModal(false)} show={showAirdropModal} address={address} /> setShowSendModal(false)} show={showSendModal} address={address} /> setShowReceiveModal(false)} show={showReceiveModal} address={address} /> ); } export function AirdropRequestModal({ hide, show, address, }: { hide: () => void; show: boolean; address: PublicKey; }) { const requestAirdrop = useRequestAirdrop({ address }); return ( { requestAirdrop.mutateAsync(1).catch((err) => console.log(err)); }} submitLabel="Request" submitDisabled={requestAirdrop.isPending} > Request an airdrop of 1 SOL to your connected wallet account. ); } export function TransferSolModal({ hide, show, address, }: { hide: () => void; show: boolean; address: PublicKey; }) { const transferSol = useTransferSol({ address }); const [destinationAddress, setDestinationAddress] = useState(""); const [amount, setAmount] = useState(""); return ( { transferSol .mutateAsync({ destination: new PublicKey(destinationAddress), amount: parseFloat(amount), }) .then(() => hide()); }} submitLabel="Send" submitDisabled={!destinationAddress || !amount} > ); } export function ReceiveSolModal({ hide, show, address, }: { hide: () => void; show: boolean; address: PublicKey; }) { return ( You can receive assets by sending them to your public key:{"\n\n"} {address.toBase58()} ); } export function AccountTokens({ address }: { address: PublicKey }) { let query = useGetTokenAccounts({ address }); const [currentPage, setCurrentPage] = useState(0); const itemsPerPage = 3; // Items per page const theme = useTheme(); const items = useMemo(() => { const start = currentPage * itemsPerPage; const end = start + itemsPerPage; return query.data?.slice(start, end) ?? []; }, [query.data, currentPage, itemsPerPage]); // Calculate the total number of pages const numberOfPages = useMemo(() => { return Math.ceil((query.data?.length ?? 0) / itemsPerPage); }, [query.data, itemsPerPage]); return ( <> Token Accounts {query.isLoading && } {query.isError && ( Error: {query.error?.message.toString()} )} {query.isSuccess && ( <> Public Key Mint Balance {query.data.length === 0 && ( No token accounts found. )} {items?.map(({ account, pubkey }) => ( {ellipsify(pubkey.toString())} {ellipsify(account.data.parsed.info.mint)} ))} {(query.data?.length ?? 0) > 3 && ( setCurrentPage(page)} label={`${currentPage + 1} of ${numberOfPages}`} numberOfItemsPerPage={itemsPerPage} selectPageDropdownLabel={"Rows per page"} /> )} )} ); } export function AccountTokenBalance({ address }: { address: PublicKey }) { const query = useGetTokenAccountBalance({ address }); return query.isLoading ? ( ) : query.data ? ( {query.data?.value.uiAmount} ) : ( Error ); } const styles = StyleSheet.create({ accountBalance: { marginTop: 12, }, accountButtonGroup: { paddingVertical: 4, flexDirection: "row", }, error: { color: "red", padding: 8, }, });