diff --git a/.changeset/quiet-streets-lie.md b/.changeset/quiet-streets-lie.md new file mode 100644 index 00000000000..c94ea294b13 --- /dev/null +++ b/.changeset/quiet-streets-lie.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/api": patch +--- + +added solana token balances endpoint diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx index bfcf5590f83..73ec2777eb9 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx @@ -40,6 +40,13 @@ import { PaginationNext, PaginationPrevious, } from "@/components/ui/pagination"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; import { Skeleton } from "@/components/ui/skeleton"; import { Switch } from "@/components/ui/switch"; import { @@ -57,6 +64,7 @@ import { useV5DashboardChain } from "@/hooks/chains/v5-adapter"; import { WalletProductIcon } from "@/icons/WalletProductIcon"; import { useDashboardRouter } from "@/lib/DashboardRouter"; import { cn } from "@/lib/utils"; +import { fetchSolanaBalance } from "../lib/getSolanaBalance"; import { updateDefaultProjectWallet } from "../lib/vault.client"; import { CreateServerWallet } from "../server-wallets/components/create-server-wallet.client"; import type { Wallet as EVMWallet } from "../server-wallets/wallet-table/types"; @@ -79,6 +87,7 @@ interface ServerWalletsTableProps { teamSlug: string; client: ThirdwebClient; solanaPermissionError?: boolean; + authToken: string; } export function ServerWalletsTable(props: ServerWalletsTableProps) { @@ -95,10 +104,14 @@ export function ServerWalletsTable(props: ServerWalletsTableProps) { solanaTotalPages, client, solanaPermissionError, + authToken, } = props; const [activeChain, setActiveChain] = useState("evm"); const [selectedChainId, setSelectedChainId] = useState(1); + const [selectedSolanaChain, setSelectedSolanaChain] = useState< + "solana:mainnet" | "solana:devnet" + >("solana:mainnet"); const [showSmartAccount, setShowSmartAccount] = useState(false); const queryClient = useQueryClient(); @@ -145,11 +158,33 @@ export function ServerWalletsTable(props: ServerWalletsTableProps) { )} {activeChain === "solana" && ( - + <> + + + )} @@ -278,6 +313,8 @@ export function ServerWalletsTable(props: ServerWalletsTableProps) { project={project} teamSlug={teamSlug} client={client} + authToken={authToken} + chainId={selectedSolanaChain} /> ))} @@ -507,11 +544,15 @@ function SolanaWalletRow({ project, teamSlug, client, + authToken, + chainId, }: { wallet: SolanaWallet; project: Project; teamSlug: string; client: ThirdwebClient; + authToken: string; + chainId: "solana:mainnet" | "solana:devnet"; }) { const engineService = project.services.find( (s) => s.name === "engineCloud", @@ -547,7 +588,12 @@ function SolanaWalletRow({ - + @@ -739,16 +785,27 @@ function WalletBalance({ ); } -function SolanaWalletBalance({ publicKey }: { publicKey: string }) { +function SolanaWalletBalance({ + publicKey, + authToken, + clientId, + chainId, +}: { + publicKey: string; + authToken: string; + clientId: string; + chainId: "solana:mainnet" | "solana:devnet"; +}) { const balance = useQuery({ queryFn: async () => { - // TODO: Implement actual Solana balance fetching - return { - displayValue: "0", - symbol: "SOL", - }; + return await fetchSolanaBalance({ + publicKey, + authToken, + clientId, + chainId, + }); }, - queryKey: ["solanaWalletBalance", publicKey], + queryKey: ["solanaWalletBalance", publicKey, chainId], }); if (balance.isFetching) { diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/getSolanaBalance.ts b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/getSolanaBalance.ts new file mode 100644 index 00000000000..bd3c0cc6248 --- /dev/null +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/getSolanaBalance.ts @@ -0,0 +1,60 @@ +import { configure, getSolanaWalletBalance } from "@thirdweb-dev/api"; +import { THIRDWEB_API_HOST } from "@/constants/urls"; + +// Configure the API client to use the correct base URL +configure({ + override: { + baseUrl: THIRDWEB_API_HOST, + }, +}); + +export async function fetchSolanaBalance({ + publicKey, + authToken, + clientId, + chainId = "solana:mainnet", +}: { + publicKey: string; + authToken: string; + clientId: string; + chainId?: "solana:mainnet" | "solana:devnet"; +}): Promise<{ + displayValue: string; + symbol: string; + value: string; + decimals: number; +} | null> { + try { + const response = await getSolanaWalletBalance({ + path: { + address: publicKey, + }, + query: { + chainId, + }, + headers: { + Authorization: `Bearer ${authToken}`, + "Content-Type": "application/json", + "x-client-id": clientId, + }, + }); + + if (response.error || !response.data) { + console.error( + "Error fetching Solana balance:", + response.error || "No data returned", + ); + return null; + } + + return { + displayValue: response.data.result.displayValue, + symbol: "SOL", + value: response.data.result.value, + decimals: response.data.result.decimals, + }; + } catch (error) { + console.error("Error fetching Solana balance:", error); + return null; + } +} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx index 38f7ba4e18f..e9a37e0525b 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx @@ -215,6 +215,7 @@ export default async function TransactionsAnalyticsPage(props: { solanaWallets={solanaAccounts.data.items} teamSlug={params.team_slug} solanaPermissionError={isSolanaPermissionError} + authToken={authToken} /> )} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx index d22037da74a..01ef9b6118c 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx @@ -70,8 +70,8 @@ export function CreateSolanaWallet(props: {