diff --git a/fern/api-reference/node-api/chain-apis-overview.mdx b/fern/api-reference/node-api/chain-apis-overview.mdx
index 2d768722a..746be0708 100644
--- a/fern/api-reference/node-api/chain-apis-overview.mdx
+++ b/fern/api-reference/node-api/chain-apis-overview.mdx
@@ -1296,7 +1296,7 @@ Dive into each API's detailed documentation by following the links below, organi
## Solana APIs
-đ Get started with our [Solana API Quickstart Guide](/docs/reference/solana-api-quickstart).
+đ Get started with our [Solana API Quickstart Guide](/docs/solana).
| | |
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
diff --git a/fern/api-reference/solana/accounts-db-infra.mdx b/fern/api-reference/solana/accounts-db-infra.mdx
new file mode 100644
index 000000000..6ae12faef
--- /dev/null
+++ b/fern/api-reference/solana/accounts-db-infra.mdx
@@ -0,0 +1,68 @@
+---
+title: Leverage AccountsDB Infrastructure for Solana RPC Requests
+description: Leverage Alchemyâs AccountsDB Infrastructure for Solana RPC Requests!
+subtitle: Leverage Alchemyâs AccountsDB Infrastructure for Solana RPC Requests!
+slug: docs/solana/accounts-db-infra
+---
+
+The most expensive Solana RPC requests involve account scans, such as `getProgramAccounts` and `getLargestTokenAccounts`. These methods are incredibly useful but non-performant methods since they induce a heavy RPC load on Solana validator nodes, often resulting in a 5XX response due to timeout or a response with high latency.
+
+Alchemy has built out core infrastructure that sits atop our Solana validator nodes to support these methods at scale, through what we call the AccountsDB Infrastructure. This infrastructure allows for **faster**, **scalable**, and more **reliable** responses to these methods by paginating the response with a `pageKey`. You could then loop through your that same request with at scan and aggregate the full response from our validator nodes.
+
+You can see `pageKey` is now an optional parameter in each account-scanning method in our Solana [docs](/reference/getprogramaccounts), and you may also include an `order` optional parameter that would sort the accounts in the response by their `pubkey` field.
+
+Here's an example with `getProgramAccounts`:
+
+
+ ```typescript typescript
+ const axios = require("axios");
+
+ async function getProgramAccountsExample() {
+ let gPAExampleRequest = {
+ method: "getProgramAccounts",
+ params: [
+ "ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD",
+ {
+ encoding: "base64",
+ withContext: true,
+ order: "desc",
+ dataSlice: {
+ offset: 0,
+ length: 10,
+ },
+ },
+ ],
+ id: 0,
+ jsonrpc: "2.0",
+ };
+ let programAccounts = [];
+
+ const alchemyRPCUrl =
+ "https://solana-mainnet.g.alchemy.com/v2/";
+ try {
+ let response = await axios.post(alchemyRPCUrl, gPAExampleRequest);
+ let responseData = response.data["result"];
+
+ // continue aggregating if there's a new pageKey present in the latest response
+ while (responseData["pageKey"]) {
+ programAccounts = programAccounts.concat(responseData["value"]);
+
+ // place the pagekey within the optional config object
+ // (you may need to create that config object if you didn't have it originally)
+ gPAExampleRequest["params"][1]["pageKey"] = responseData["pageKey"];
+
+ // make another call to getProgramAccounts with the pageKey
+ response = await axios.post(alchemyRPCUrl, gPAExampleRequest);
+ responseData = response.data["result"];
+ }
+
+ programAccounts = programAccounts.concat(responseData["value"]);
+ console.log(programAccounts);
+ return programAccounts;
+ } catch (err) {
+ console.log(err.message);
+ return [];
+ }
+ }
+ ```
+
diff --git a/fern/api-reference/solana/hello-world-application.mdx b/fern/api-reference/solana/hello-world-application.mdx
new file mode 100644
index 000000000..27b68fe18
--- /dev/null
+++ b/fern/api-reference/solana/hello-world-application.mdx
@@ -0,0 +1,272 @@
+---
+title: Set up Frontend for Solana Application
+description: Step-by-step guide to integrating, calling, and interacting with a Solana on-chain program using Rust and Alchemy's Solana RPC from your own application.
+subtitle: Integrate, call, and interact with your Solana on-chain program using Rust and Alchemy RPC
+slug: docs/hello-world-solana-application
+---
+
+You can check out the project in two ways:
+
+* **GitHub Repository:** [alchemyplatform/solana-hello-world-2025](https://github.com/alchemyplatform/solana-hello-world-2025) â Clone this repo to explore or use the code yourself.
+* **Live Demo:** [Deployed Application](https://solana-hello-world-2025.vercel.app/) â Interact with the app directly in your browser.
+
+## Step 1: Get your Solana program ID
+
+[The previous guide](/docs/hello-world-solana-program) shows you how to deploy a program to Solana devnet. Using that guide, we got the following program id:
+
+```bash
+Eq5z52U3gGZNHVhgR1bgba8deMgtuFkpUNzd8iBsKvwJ
+```
+
+You can use this in the examples below, or replace it with your own.
+
+## Step 2: Create a Next.js app
+
+From your terminal, run:
+
+```bash
+npx create-next-app@latest solana-hello-frontend \
+ --typescript \
+ --eslint \
+ --app \
+ --src-dir \
+ --tailwind \
+ --import-alias "@/*"
+
+cd solana-hello-frontend
+```
+
+This sets up:
+
+* Next.js with the App Router
+* TypeScript
+* Tailwind (optional, but nice for styling)
+
+***
+
+## Step 3: Install Solana web3.js and set environment variables
+
+Install the Solana SDK:
+
+```bash
+npm install @solana/web3.js
+```
+
+Create a file called `.env` in the root of `solana-hello-frontend` folder:
+
+```bash
+touch .env
+```
+
+Add your Alchemy RPC URL and program ID:
+
+```bash
+NEXT_PUBLIC_ALCHEMY_RPC_URL="https://solana-devnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY"
+NEXT_PUBLIC_PROGRAM_ID="Eq5z52U3gGZNHVhgR1bgba8deMgtuFkpUNzd8iBsKvwJ"
+```
+
+> In a real app, replace the example program ID with the one from your own deployment.
+
+## Step 4: Build a minimal client UI that pings your program
+
+Weâll make the homepage (app/page.tsx) a client component that:
+
+* connects a Solana wallet (e.g. Phantom)
+
+* builds a transaction with an instruction calling your program
+
+* sends it via Alchemy RPC
+
+* shows the signature + status
+
+Open `src/app/page.tsx` and replace its contents with:
+
+```typescript
+"use client";
+
+import { useState } from "react";
+import {
+ Connection,
+ PublicKey,
+ Transaction,
+ TransactionInstruction,
+} from "@solana/web3.js";
+
+const RPC_URL = process.env.NEXT_PUBLIC_ALCHEMY_RPC_URL as string;
+const PROGRAM_ID = process.env.NEXT_PUBLIC_PROGRAM_ID as string;
+
+declare global {
+ interface Window {
+ solana?: any; // Phantom or compatible wallet
+ }
+}
+
+export default function Home() {
+ const [walletAddress, setWalletAddress] = useState(null);
+ const [txSignature, setTxSignature] = useState(null);
+ const [status, setStatus] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ const connectWallet = async () => {
+ try {
+ if (!window.solana) {
+ alert("No Solana wallet found. Please install Phantom or a compatible wallet.");
+ return;
+ }
+
+ const resp = await window.solana.connect();
+ setWalletAddress(resp.publicKey.toString());
+ setStatus("Wallet connected.");
+ } catch (err) {
+ console.error(err);
+ setStatus("Failed to connect wallet.");
+ }
+ };
+
+ const pingProgram = async () => {
+ if (!walletAddress) {
+ setStatus("Connect your wallet first.");
+ return;
+ }
+
+ if (!RPC_URL || !PROGRAM_ID) {
+ setStatus("Missing RPC URL or PROGRAM_ID env vars.");
+ return;
+ }
+
+ try {
+ setLoading(true);
+ setStatus("Sending transaction...");
+ setTxSignature(null);
+
+ const connection = new Connection(RPC_URL, "confirmed");
+ const provider = window.solana;
+
+ const programId = new PublicKey(PROGRAM_ID);
+ const userPublicKey = new PublicKey(walletAddress);
+
+ // Build an instruction that calls your Hello World program
+ const instruction = new TransactionInstruction({
+ programId,
+ keys: [
+ {
+ pubkey: userPublicKey,
+ isSigner: true,
+ isWritable: false,
+ },
+ ],
+ // Your Hello World program ignores instruction data, so this can be empty
+ data: Buffer.from([]),
+ });
+
+ const transaction = new Transaction().add(instruction);
+
+ // Set fee payer and recent blockhash
+ transaction.feePayer = userPublicKey;
+ const latestBlockhash = await connection.getLatestBlockhash();
+ transaction.recentBlockhash = latestBlockhash.blockhash;
+
+ // Ask the wallet to sign the transaction
+ const signedTx = await provider.signTransaction(transaction);
+
+ // Send to the network through Alchemy RPC
+ const signature = await connection.sendRawTransaction(signedTx.serialize());
+ setTxSignature(signature);
+ setStatus("Transaction sent. Waiting for confirmation...");
+
+ // Wait for confirmation
+ await connection.confirmTransaction(
+ {
+ signature,
+ blockhash: latestBlockhash.blockhash,
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
+ },
+ "confirmed"
+ );
+
+ setStatus("â Success! Your program was invoked.");
+ } catch (err) {
+ console.error(err);
+ setStatus("â Error sending transaction. Check the browser console for details.");
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+
+ Solana Hello World đ
+
+
+ Connect your wallet and ping your on-chain Hello World program on{" "}
+ devnet using Alchemy RPC.
+
- Your First Solana Program with{" "}
- Alchemy!
-
-
-
- );
- }
- ```
-
-
-Some small changes from last time we touched this file:
-
-* We imported some libraries to help with our wallet button.
-* We added the `mounted` function to make sure our wallet button renders only until after the component has mounted, as described earlier.
-* We added our wallet button to appear at the top right of our app using the `WalletMultiButton` component!
-
-At this your app should look like this:
-
-.gif")
-
-Nice đ„ł! Weâve successfully connected a Phantom wallet to your application! Now, you can write code that sends transactions on behalf of the user (with their approval) to write data to the Solana blockchain. Hereâs a [git commit](https://github.com/alchemyplatform/solana-hello-world/commit/207f77372e6f88a2b882af571f8b53455b6608b1) checkpoint. Letâs keep going!
-
-# 4. Connect the App to Your Solana Program
-
-Now we made it to the cool part - connecting to the Solana program we deployed đ€! Really quickly, airdrop some SOL to your Wallet since weâre going to need it soon.
-
-
- ```shell shell
- solana airdrop 3
- ```
-
-
-## Making a Create Message API
-
-Letâs go over what we want our app to do:
-
-1. When a user successfully connects their wallet, we want to show an input form for a user to write a message.
-2. Then, a user should press a button to write that message to the Solana blockchain.
-3. Once itâs written, we should display on our application the details of the message, including its content, author (the user), and the time it was published.
-
-We can actually do all of this by making calls to our Solana program. In our `app/pages/api` folder letâs rename `hello.ts` to `createMessage.ts` and then remove all the code and replace it with this:
-
-
- ```typescript typescript
- import { Program, AnchorProvider, web3 } from "@project-serum/anchor";
- import { SolanaHelloWorld } from "./types/solana_hello_world";
- import {
- connection,
- commitmentLevel,
- helloWorldprogramId,
- helloWorldprogramInterface,
- } from "./utils/constants";
- import { AnchorWallet } from "@solana/wallet-adapter-react";
-
- export default async function createMessage(
- inputtedMessage: string,
- wallet: AnchorWallet,
- messageAccount: web3.Keypair
- ) {
- const provider = new AnchorProvider(connection, wallet, {
- preflightCommitment: commitmentLevel,
- });
-
- if (!provider) return;
-
- /* create the program interface combining the idl, program Id, and provider */
- const program = new Program(
- helloWorldprogramInterface,
- helloWorldprogramId,
- provider
- ) as Program;
-
- try {
- /* interact with the program via rpc */
- const txn = await program.rpc.createMessage(inputtedMessage, {
- accounts: {
- message: messageAccount.publicKey,
- author: provider.wallet.publicKey,
- systemProgram: web3.SystemProgram.programId,
- },
- signers: [messageAccount],
- });
-
- const message = await program.account.message.fetch(
- messageAccount.publicKey
- );
- console.log("messageAccount Data: ", message);
- return message;
- } catch (err) {
- console.log("Transaction error: ", err);
- return;
- }
- }
- ```
-
-
-Youâll notice the code is actually very similar to what we wrote in our tests in the last tutorial! Letâs walk through it briefly:
-
-* After importing relevant libraries and constants, our function will take in the `inputtedMessage` from the user, the userâs `wallet`, and the `account` that our Program will initialize to save the message in.
-* We create a `provider` object, which if you remember from last tutorial, is our connection to Solana through 1) an RPC provider and 2) a Solana wallet address. Connection + Wallet = Provider! We also specify the same commitment level as before.
-* Lastly, we make a call to our Solana program to create the Message. Like in our tests in the last tutorial, we include the relevant accounts and signatures needed, along with the `inputtedMessage` to make the call. We then fetch and return that message to use in our frontend!
-
-Letâs incorporate this new API endpoint in our frontend code now! The full `app/pages/index.tsx` file should look like this now:
-
-
- ```typescript typescript
- import { useState } from "react";
- import { Keypair } from "@solana/web3.js";
- import { useAnchorWallet } from "@solana/wallet-adapter-react";
- import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
- import useIsMounted from "./api/utils/useIsMounted";
- import createMessage from "./api/createMessage";
- import styles from "../styles/Home.module.css";
-
- export default function Home() {
- const [messageAccount, _] = useState(Keypair.generate());
- const [message, setMessage] = useState("");
- const [messageAuthor, setMessageAuthor] = useState("");
- const [messageTime, setMessageTime] = useState(0);
- const [inputtedMessage, setInputtedMessage] = useState("");
-
- const wallet = useAnchorWallet();
- const mounted = useIsMounted();
-
- return (
-
-
{mounted && }
-
-
-
- Your First Solana Program with{" "}
- Alchemy!
-
Time Published: {new Date(messageTime).toLocaleString()}
-
- )}
-
-
- );
- }
- ```
-
-
-We added a few things - letâs review:
-
-* We imported more relevant libraries and our newly created `createMessage` function
-
-* We included a few state variables that will be used.
-
- * `messageAccount` is the generated public-private keypair that will represent storage on the Solana blockchain for our message. We initialized it with `Keypair.generate()`
- * `message`, `messageAuthor`, `messageTime` will store the three corresponding components of a message - itâs content, author, and timestamp. Weâll use this to render a
- * `inputtedMessage` will track what the user inputs as a message in the newly created inputted field below until they submit it. When a message is written, we will clear this variable out.
-
-* We then added an input field and button to our page so our user can input and submit a message if their wallet is connected.
-
-* Lastly, if there is a message that was submitted and the userâs wallet is still connected, weâll render the messageâs content, author, and date published.
-
-Now your app should look like this:
-
-.gif")
-
-Look how far youâve come đšâđ! Youâve made an app that can connect a userâs wallet and submit to the blockchain a message they write, AND youâre able to show it on your application. So impressive. Weâre 99% there - hereâs a [git commit](https://github.com/alchemyplatform/solana-hello-world/commit/6393279cd5c95697465c7d641da7950e8f160ef4) checkpoint to make sure your code is all there.
-
-## Making an Update Message API
-
-There is one thing left to do. If you try to write a message, and then write another message, youâll get an error saying the message account was already initialized. We need to call the separate `updateMessage` function on our Solana program to edit the data in the messageâs account.
-
-In our `app/pages/api` folder, letâs add a `updateMessage.ts` file and then add this:
-
-
- ```typescript typescript
- import { Program, AnchorProvider, web3 } from "@project-serum/anchor";
- import { SolanaHelloWorld } from "./types/solana_hello_world";
- import {
- connection,
- commitmentLevel,
- helloWorldprogramId,
- helloWorldprogramInterface,
- } from "./utils/constants";
- import { AnchorWallet } from "@solana/wallet-adapter-react";
-
- export default async function updateMessage(
- inputtedMessage: string,
- wallet: AnchorWallet,
- messageAccount: web3.Keypair
- ) {
- const provider = new AnchorProvider(connection, wallet, {
- preflightCommitment: commitmentLevel,
- });
-
- if (!provider) return;
-
- /* create the program interface combining the idl, program Id, and provider */
- const program = new Program(
- helloWorldprogramInterface,
- helloWorldprogramId,
- provider
- ) as Program;
-
- try {
- /* interact with the program via rpc */
- const txn = await program.rpc.updateMessage(inputtedMessage, {
- accounts: {
- message: messageAccount.publicKey,
- author: provider.wallet.publicKey,
- systemProgram: web3.SystemProgram.programId,
- },
- });
-
- const message = await program.account.message.fetch(
- messageAccount.publicKey
- );
- console.log("updated messageAccount Data: ", message);
- return message;
- } catch (err) {
- console.log("Transaction error: ", err);
- return;
- }
- }
- ```
-
-
-This is nearly identical to `createMessage`, the only difference is the function we call on our Solana program now is `updateMessage` which doesnât need the message accountâs signature, just the signer (author), which is implicitly added. Everything else is the same!
-
-Letâs integrate this in our `app/pages/index.tsx` file. The full code should look like this:
-
-
- ```typescript typescript
- import { useState } from "react";
- import { Keypair } from "@solana/web3.js";
- import { useAnchorWallet } from "@solana/wallet-adapter-react";
- import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
- import useIsMounted from "./api/utils/useIsMounted";
- import createMessage from "./api/createMessage";
- import updateMessage from "./api/updateMessage";
- import styles from "../styles/Home.module.css";
-
- export default function Home() {
- const [messageAccount, _] = useState(Keypair.generate());
- const [message, setMessage] = useState("");
- const [messageAuthor, setMessageAuthor] = useState("");
- const [messageTime, setMessageTime] = useState(0);
- const [inputtedMessage, setInputtedMessage] = useState("");
-
- const wallet = useAnchorWallet();
- const mounted = useIsMounted();
-
- return (
-
-
{mounted && }
-
-
-
- Your First Solana Program with{" "}
- Alchemy!
-
Time Published: {new Date(messageTime).toLocaleString()}
-
- )}
-
-
- );
- }
- ```
-
-
-Letâs walk through the minor changes we made:
-
-* Now, if there isnât yet a message published, the button will use the `createMessage` function. If there is a message published, the button will use the `updateMessage` function.
-
-Your app should now look like this:
-
-Congrats! You now have the entire web3 app! Users can now write a message to the Solana blockchain, and later edit that same message! Hereâs a [git commit](https://github.com/alchemyplatform/solana-hello-world/commit/ec70d6623285ecd8a0f68b3d28a8d4a818e79812) checkpoint to make sure your app is fully function.
-
-## \[Optional] Prettifying Your Web3 App
-
-Youâll notice it takes a while to update the UI while the message is being published. To make sure people donât get confused starting at a screen that isnât moving, letâs add a loading spinner. This is totally optional, but itâll make the user experience much better!
-
-In your `app/pages/index.tsx` letâs edit it to look like this:
-
-
- ```typescript typescript
- import { useState } from "react";
- import { Keypair } from "@solana/web3.js";
- import { useAnchorWallet } from "@solana/wallet-adapter-react";
- import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
- import useIsMounted from "./api/utils/useIsMounted";
- import createMessage from "./api/createMessage";
- import updateMessage from "./api/updateMessage";
- import styles from "../styles/Home.module.css";
-
- export default function Home() {
- const [messageAccount, _] = useState(Keypair.generate());
- const [message, setMessage] = useState("");
- const [messageAuthor, setMessageAuthor] = useState("");
- const [messageTime, setMessageTime] = useState(0);
- const [inputtedMessage, setInputtedMessage] = useState("");
- const [loading, setLoading] = useState(false);
-
- const wallet = useAnchorWallet();
- const mounted = useIsMounted();
-
- return (
-
-
{mounted && }
-
-
-
- Your First Solana Program with{" "}
- Alchemy!
-