> ## 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.

# Triển khai chương trình Solana đầu tiên của bạn

> Đưa một chương trình Solana từ mã nguồn đến giao dịch devnet thực tế, trong đó việc cấp vốn, triển khai và gọi chương trình đều được định tuyến qua Helius RPC của bạn.

export const DevnetFaucet = () => {
  const [apiKey, setApiKey] = useState('');
  const [address, setAddress] = useState('');
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState(null);
  const [error, setError] = useState(null);
  const handleAirdrop = async e => {
    e.preventDefault();
    setLoading(true);
    setError(null);
    setResult(null);
    try {
      const res = await fetch(`https://devnet.helius-rpc.com/?api-key=${apiKey}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          jsonrpc: '2.0',
          id: 'faucet',
          method: 'requestAirdrop',
          params: [address, 1000000000]
        })
      });
      const json = await res.json();
      if (json.error) throw new Error(json.error.message || 'Airdrop thất bại');
      setResult(json.result);
    } catch (err) {
      setError(err.message || 'Airdrop thất bại. Vòi devnet bị giới hạn tốc độ, hãy thử lại sau giây lát.');
    } finally {
      setLoading(false);
    }
  };
  const btnClass = loading ? 'px-4 py-2 font-medium rounded-full bg-gray-300 dark:bg-gray-700 cursor-not-allowed' : 'px-4 py-2 font-medium rounded-full bg-primary hover:bg-primary/80 text-white';
  return <div className="p-4 border dark:border-zinc-950/80 rounded-xl bg-white dark:bg-zinc-950/80 shadow-sm">
      <form onSubmit={handleAirdrop} className="space-y-4">
        <div>
          <label className="block text-sm text-zinc-950/70 dark:text-white/70 mb-1">Khóa API của bạn</label>
          <input type="text" value={apiKey} onChange={e => setApiKey(e.target.value)} placeholder="Nhập khóa API của bạn" className="w-full p-2 border rounded dark:bg-zinc-900 dark:border-zinc-700" required />
        </div>
        <div>
          <label className="block text-sm text-zinc-950/70 dark:text-white/70 mb-1">Địa chỉ ví Devnet</label>
          <input type="text" value={address} onChange={e => setAddress(e.target.value)} placeholder="Địa chỉ devnet của bạn" className="w-full p-2 border rounded dark:bg-zinc-900 dark:border-zinc-700" required />
        </div>
        <button type="submit" disabled={loading} className={btnClass}>
          {loading ? 'Đang yêu cầu...' : 'Yêu cầu 1 SOL Devnet'}
        </button>
      </form>
      <p className="mt-3 text-xs text-zinc-500 dark:text-zinc-400">
        Khóa API chỉ được sử dụng trong trình duyệt của bạn để gọi trực tiếp đến Helius. Khóa này không bao giờ được gửi đến bất kỳ nơi nào khác.
      </p>
      {error ? <div className="mt-4 p-3 bg-red-100 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded text-red-700 dark:text-red-300">
          <strong>Lỗi:</strong> {error}
        </div> : null}
      {result ? <div className="mt-4 p-3 bg-green-100 dark:bg-green-900/30 border border-green-200 dark:border-green-800 rounded text-green-700 dark:text-green-300 text-sm break-all">
          <strong>Đã gửi airdrop!</strong> Chữ ký: {result}
        </div> : null}
    </div>;
};

Trong hướng dẫn này, bạn sẽ triển khai một chương trình thực tế lên devnet và gọi chương trình đó, với toàn bộ quy trình chạy trên hạ tầng Helius. Bạn sẽ cấp vốn cho ví bằng [`requestAirdrop`](/docs/vi/api-reference/rpc/http/requestairdrop), triển khai một chương trình mẫu dựng sẵn, sau đó gọi chương trình bằng [`sendTransaction`](/docs/vi/api-reference/rpc/http/sendtransaction) và xác nhận kết quả bằng [`getSignatureStatuses`](/docs/vi/api-reference/rpc/http/getsignaturestatuses). Việc sử dụng chương trình dựng sẵn giúp bạn tập trung vào vòng lặp triển khai và gọi thay vì viết mã Rust.

<Info>
  **Điều kiện tiên quyết:** [Solana CLI](https://solana.com/docs/intro/installation) và [Rust](https://www.rust-lang.org/tools/install) (để dựng chương trình), Node.js 18+ (để gọi chương trình) và một [khóa API Helius](https://dashboard.helius.dev/api-keys). Devnet hoạt động với mọi gói Helius.
</Info>

***

<Steps>
  <Step title="Point the Solana CLI at your Helius devnet RPC">
    Sử dụng endpoint Helius của bạn cho mọi lệnh CLI và tạo ví nếu chưa có:

    ```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` in khóa công khai của ví; bạn sẽ cấp vốn cho ví ở bước tiếp theo.
  </Step>

  <Step title="Get devnet SOL">
    Việc triển khai cần một ít SOL. SOL trên devnet hoàn toàn miễn phí và chỉ dùng để thử nghiệm, vì vậy hãy cấp vốn cho địa chỉ của bạn bằng faucet bên dưới hoặc qua CLI:

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

    <DevnetFaucet />

    <Note>
      Các faucet devnet bị giới hạn tốc độ, vì vậy airdrop có thể không thành công. Nếu điều đó xảy ra, hãy đợi một lúc rồi thử lại hoặc sử dụng [faucet devnet trên web](https://faucet.solana.com/) chính thức của Solana làm phương án dự phòng. Chỉ cần khoảng 1 SOL để triển khai chương trình mẫu.
    </Note>
  </Step>

  <Step title="Clone and build the sample program">
    Lấy chương trình "Hello, Solana!" từ kho lưu trữ [program-examples](https://github.com/solana-developers/program-examples) chính thức của Solana. Chương trình chỉ ghi một lời chào vào nhật ký khi được gọi. Đây gần như là chương trình nhỏ nhất vẫn có thể chứng minh toàn bộ vòng lặp hoạt động.

    ```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` là một workspace Cargo, vì vậy `cargo build-sbf` biên dịch chương trình thành `target/deploy/hello_solana_program.so` tại thư mục gốc của kho lưu trữ (không phải bên trong thư mục chương trình). Hãy ở lại trong thư mục `program-examples` cho bước tiếp theo.
  </Step>

  <Step title="Deploy to devnet through Helius">
    ```bash theme={"system"}
    solana program deploy target/deploy/hello_solana_program.so
    ```

    CLI gửi giao dịch triển khai qua Helius RPC của bạn và in ra **ID chương trình**. Hãy sao chép ID này vì bạn sẽ gọi chương trình ở bước tiếp theo.

    ```
    Program Id: 4Nd1mYQ...your program id...
    ```
  </Step>

  <Step title="Invoke the program with sendTransaction">
    Trong một thư mục mới, hãy thiết lập một ứng dụng khách TypeScript nhỏ để tạo, gửi và xác nhận giao dịch.

    ```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);
    ```

    Thay thế `YOUR_API_KEY` và `YOUR_PROGRAM_ID`, sau đó chạy chương trình:

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

    Bạn sẽ nhận được một chữ ký và liên kết Explorer. Mở liên kết rồi mở rộng **Nhật ký lệnh chương trình** để xem lời chào `Hello, Solana!` của chương trình.
  </Step>
</Steps>

## Điều gì đang diễn ra

### Mọi thứ đều được định tuyến qua Helius RPC của bạn

`solana config set --url` hướng mọi lệnh CLI (airdrop, triển khai và kiểm tra số dư) đến endpoint devnet Helius của bạn. Ứng dụng khách TypeScript sử dụng cùng endpoint, vì vậy toàn bộ quy trình chạy trên hạ tầng Helius.

### Vòng lặp gọi chương trình: gửi rồi xác nhận

`sendRawTransaction` gọi phương thức RPC [`sendTransaction`](/docs/vi/api-reference/rpc/http/sendtransaction) ở tầng bên dưới và trả về chữ ký ngay lập tức, trước khi mạng xử lý giao dịch. Vì vậy, bạn cần liên tục truy vấn [`getSignatureStatuses`](/docs/vi/api-reference/rpc/http/getsignaturestatuses) cho đến khi `confirmationStatus` đạt đến `confirmed`, đồng thời kiểm tra `err` để phát hiện lỗi. Mẫu gửi rồi xác nhận này là nền tảng của mọi giao dịch Solana mà bạn sẽ gửi.

## Các bước tiếp theo

<CardGroup cols={2}>
  <Card title="How to Get Devnet SOL" icon="faucet-drip" href="/docs/vi/rpc/devnet-sol">
    Tất cả cách cấp vốn cho ví devnet cùng các mẹo về giới hạn tốc độ.
  </Card>

  <Card title="sendTransaction" icon="paper-plane" href="/docs/vi/api-reference/rpc/http/sendtransaction">
    Tất cả tham số, bao gồm skipPreflight, preflightCommitment và số lần thử lại.
  </Card>

  <Card title="Land transactions reliably" icon="rocket" href="/docs/vi/api-reference/sender/sendtransaction">
    Khi chuyển sang mainnet, hãy sử dụng Sender để đưa giao dịch vào chuỗi với độ trễ cực thấp.
  </Card>

  <Card title="Build a portfolio tracker" icon="wallet" href="/docs/vi/quickstart/portfolio-tracker">
    Hướng dẫn khác: truy xuất token, NFT và SOL của bất kỳ ví nào, kèm nguồn cấp hoạt động trực tiếp.
  </Card>
</CardGroup>
