> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Your First Solana Program

> Take a Solana program from source to a live devnet transaction, with funding, deployment, and calls all routed through your Helius RPC.

In this guide you'll deploy a real program to devnet and invoke it, with the entire flow running on Helius infrastructure. You'll fund a wallet with [`requestAirdrop`](https://www.helius.dev/docs/api-reference/rpc/http/requestairdrop), deploy a prebuilt sample program, then call it with [`sendTransaction`](https://www.helius.dev/docs/api-reference/rpc/http/sendtransaction) and confirm the result with [`getSignatureStatuses`](https://www.helius.dev/docs/api-reference/rpc/http/getsignaturestatuses). Using a ready-made program keeps the focus on the deploy-and-invoke loop instead of writing Rust.

> [!NOTE]
>
> **Prerequisites:** the [Solana CLI](https://solana.com/docs/intro/installation) and [Rust](https://www.rust-lang.org/tools/install) (to build the program), Node.js 18+ (to invoke it), and a [Helius API key](https://dashboard.helius.dev/api-keys). Devnet works on every Helius plan.

***

**1. Point the Solana CLI at your Helius devnet RPC**

Use your Helius endpoint for every CLI command, and create a wallet if you don't have one:

```bash theme={"system"}
solana config set --url https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY
solana-keygen new --no-bip39-passphrase   # skip if you already have a keypair
solana address
```

`solana address` prints your wallet's public key, which you'll fund next.

**2. Get devnet SOL**

Deploying costs a bit of SOL. Devnet SOL is free and only good for testing, so fund your address with the faucet below or from the CLI:

```bash theme={"system"}
solana airdrop 1
solana balance
```

<form>
  Your API Key

  Devnet Wallet Address
</form>

Your API key is used only in your browser to call Helius directly. It is never sent anywhere else.

> [!NOTE]
>
> Devnet faucets are rate-limited, so an airdrop can fail. If it does, wait a moment and retry, or use Solana's official [devnet web faucet](https://faucet.solana.com/) as a fallback. Deploying the sample program needs only \~1 SOL.

**3. Clone and build the sample program**

Grab the "Hello, Solana!" program from Solana's official [program-examples](https://github.com/solana-developers/program-examples) repo. It just logs a greeting when invoked, which is about the smallest program that still proves the full loop works.

```bash theme={"system"}
git clone https://github.com/solana-developers/program-examples.git
cd program-examples
cargo build-sbf --manifest-path basics/hello-solana/native/program/Cargo.toml
```

`program-examples` is a Cargo workspace, so `cargo build-sbf` compiles the program to `target/deploy/hello_solana_program.so` at the repo root (not inside the program folder). Stay in the `program-examples` directory for the next step.

**4. Deploy to devnet through Helius**

```bash theme={"system"}
solana program deploy target/deploy/hello_solana_program.so
```

The CLI submits the deploy transaction through your Helius RPC and prints the **Program Id**. Copy it, since you'll invoke this program next.

```
Program Id: 4Nd1mYQ...your program id...
```

**5. Invoke the program with sendTransaction**

In a fresh folder, set up a small TypeScript client that builds a transaction, sends it, and confirms it.

```bash theme={"system"}
mkdir invoke-client && cd invoke-client
npm init -y
npm install @solana/web3.js
```

```typescript invoke.ts [expandable] theme={"system"}
import {
  Connection,
  Keypair,
  PublicKey,
  Transaction,
  TransactionInstruction,
} from "@solana/web3.js";
import { readFileSync } from "fs";
import { homedir } from "os";

const RPC = "https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY";
const PROGRAM_ID = new PublicKey("YOUR_PROGRAM_ID"); // from the deploy step

async function main() {
  const connection = new Connection(RPC, "confirmed");

  // Load the same keypair the CLI created and funded.
  const secret = JSON.parse(
    readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")
  );
  const payer = Keypair.fromSecretKey(Uint8Array.from(secret));

  // The hello-solana program takes no accounts and no data. It just logs.
  const instruction = new TransactionInstruction({
    keys: [],
    programId: PROGRAM_ID,
    data: Buffer.alloc(0),
  });

  const tx = new Transaction().add(instruction);
  const { blockhash } = await connection.getLatestBlockhash();
  tx.recentBlockhash = blockhash;
  tx.feePayer = payer.publicKey;
  tx.sign(payer);

  // sendTransaction submits the signed transaction to the cluster via Helius.
  const signature = await connection.sendRawTransaction(tx.serialize());
  console.log("Sent:", signature);

  // Poll getSignatureStatuses until the transaction is confirmed.
  for (let i = 0; i < 30; i++) {
    const { value } = await connection.getSignatureStatuses([signature]);
    const status = value[0];
    if (status?.confirmationStatus === "confirmed" || status?.confirmationStatus === "finalized") {
      if (status.err) throw new Error(`Failed: ${JSON.stringify(status.err)}`);
      console.log("Confirmed! View it on Solana Explorer:");
      console.log(`https://explorer.solana.com/tx/${signature}?cluster=devnet`);
      return;
    }
    await new Promise((r) => setTimeout(r, 1000));
  }
  throw new Error("Timed out waiting for confirmation");
}

main().catch(console.error);
```

Replace `YOUR_API_KEY` and `YOUR_PROGRAM_ID`, then run it:

```bash theme={"system"}
npx tsx invoke.ts
```

You'll get a signature and an Explorer link. Open the link and expand **Program Instruction Logs** to see the program's `Hello, Solana!` greeting.

## What's happening

### Everything routes through your Helius RPC

`solana config set --url` points every CLI command (airdrop, deploy, and the balance checks) at your Helius devnet endpoint. The TypeScript client uses the same endpoint, so the whole flow runs on Helius infrastructure.

### The invoke loop: send, then confirm

`sendRawTransaction` calls the [`sendTransaction`](https://www.helius.dev/docs/api-reference/rpc/http/sendtransaction) RPC method under the hood and returns a signature immediately, before the network has processed the transaction. That's why you poll [`getSignatureStatuses`](https://www.helius.dev/docs/api-reference/rpc/http/getsignaturestatuses) until `confirmationStatus` reaches `confirmed`, checking `err` to catch failures. This send-then-confirm pattern is the foundation of every Solana transaction you'll submit.

## Next steps

> [card] [How to Get Devnet SOL](https://www.helius.dev/docs/rpc/devnet-sol.md)
>
> Every way to fund a devnet wallet, plus rate-limit tips.

> [card] [sendTransaction](https://www.helius.dev/docs/api-reference/rpc/http/sendtransaction.md)
>
> All parameters, including skipPreflight, preflightCommitment, and retries.

> [card] [Land transactions reliably](https://www.helius.dev/docs/api-reference/sender/sendtransaction.md)
>
> When you go to mainnet, use Sender for ultra-low-latency landing.

> [card] [Build a portfolio tracker](https://www.helius.dev/docs/quickstart/portfolio-tracker.md)
>
> Other track: pull any wallet's tokens, NFTs, and SOL, with a live activity feed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.