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

# Разверните свою первую программу Solana

> Пройдите весь путь программы Solana от исходного кода до транзакции в devnet: пополните баланс, разверните и вызовите программу через Helius RPC.

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 || 'Не удалось запросить токены');
      setResult(json.result);
    } catch (err) {
      setError(err.message || 'Не удалось запросить токены. Для крана Devnet действует ограничение частоты запросов. Повторите попытку через некоторое время.');
    } 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">Ваш ключ API</label>
          <input type="text" value={apiKey} onChange={e => setApiKey(e.target.value)} placeholder="Введите ключ API" 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">Адрес кошелька Devnet</label>
          <input type="text" value={address} onChange={e => setAddress(e.target.value)} placeholder="Ваш адрес в Devnet" 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 ? 'Отправка запроса...' : 'Запросить 1 SOL в Devnet'}
        </button>
      </form>
      <p className="mt-3 text-xs text-zinc-500 dark:text-zinc-400">
        Ваш ключ API используется только в браузере для прямого обращения к Helius. Он больше никуда не отправляется.
      </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>Ошибка:</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>Токены отправлены!</strong> Подпись: {result}
        </div> : null}
    </div>;
};

В этом руководстве вы развернете настоящую программу в devnet и вызовете ее, причем весь процесс будет выполняться в инфраструктуре Helius. Вы пополните кошелек с помощью [`requestAirdrop`](/docs/ru/api-reference/rpc/http/requestairdrop), развернете готовую тестовую программу, затем вызовете ее через [`sendTransaction`](/docs/ru/api-reference/rpc/http/sendtransaction) и подтвердите результат с помощью [`getSignatureStatuses`](/docs/ru/api-reference/rpc/http/getsignaturestatuses). Готовая программа позволяет сосредоточиться на цикле развертывания и вызова, а не на написании кода на Rust.

<Info>
  **Предварительные требования:** [Solana CLI](https://solana.com/docs/intro/installation) и [Rust](https://www.rust-lang.org/tools/install) (для сборки программы), Node.js 18+ (для ее вызова), а также [ключ API Helius](https://dashboard.helius.dev/api-keys). Devnet доступна на любом тарифном плане Helius.
</Info>

***

<Steps>
  <Step title="Point the Solana CLI at your Helius devnet RPC">
    Используйте конечную точку Helius для каждой команды CLI и создайте кошелек, если у вас его еще нет:

    ```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` выводит публичный ключ вашего кошелька, баланс которого вы пополните на следующем шаге.
  </Step>

  <Step title="Get devnet SOL">
    Для развертывания требуется немного SOL. Токены SOL в devnet бесплатны и предназначены только для тестирования, поэтому пополните свой адрес через кран ниже или с помощью CLI:

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

    <DevnetFaucet />

    <Note>
      Для кранов devnet действуют ограничения частоты запросов, поэтому раздача токенов может завершиться ошибкой. В таком случае немного подождите и повторите попытку либо воспользуйтесь официальным [веб-краном Solana для devnet](https://faucet.solana.com/) в качестве запасного варианта. Для развертывания тестовой программы требуется всего около 1 SOL.
    </Note>
  </Step>

  <Step title="Clone and build the sample program">
    Скачайте программу «Hello, Solana!» из официального репозитория Solana [program-examples](https://github.com/solana-developers/program-examples). При вызове она просто записывает приветствие в журнал. Это практически самая маленькая программа, которая позволяет убедиться, что весь цикл работает.

    ```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` — это рабочая область Cargo, поэтому `cargo build-sbf` компилирует программу в `target/deploy/hello_solana_program.so` в корне репозитория, а не в папке программы. Для следующего шага оставайтесь в каталоге `program-examples`.
  </Step>

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

    CLI отправляет транзакцию развертывания через Helius RPC и выводит **Program Id**. Скопируйте его, поскольку далее вы вызовете эту программу.

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

  <Step title="Invoke the program with sendTransaction">
    В новой папке настройте небольшой клиент TypeScript, который создает, отправляет и подтверждает транзакцию.

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

    Замените `YOUR_API_KEY` и `YOUR_PROGRAM_ID`, а затем запустите клиент:

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

    Вы получите подпись и ссылку на Explorer. Откройте ссылку и разверните раздел **Program Instruction Logs**, чтобы увидеть приветствие программы `Hello, Solana!`.
  </Step>
</Steps>

## Что происходит

### Все запросы проходят через Helius RPC

`solana config set --url` направляет каждую команду CLI — раздачу токенов, развертывание и проверку баланса — в вашу конечную точку Helius для devnet. Клиент TypeScript использует ту же конечную точку, поэтому весь процесс выполняется в инфраструктуре Helius.

### Цикл вызова: отправка, затем подтверждение

`sendRawTransaction` вызывает метод RPC [`sendTransaction`](/docs/ru/api-reference/rpc/http/sendtransaction) и немедленно возвращает подпись, еще до того, как сеть обработает транзакцию. Поэтому нужно опрашивать [`getSignatureStatuses`](/docs/ru/api-reference/rpc/http/getsignaturestatuses), пока `confirmationStatus` не достигнет состояния `confirmed`, и проверять `err` для обнаружения ошибок. Этот шаблон «отправить, затем подтвердить» лежит в основе каждой отправляемой вами транзакции Solana.

## Следующие шаги

<CardGroup cols={2}>
  <Card title="How to Get Devnet SOL" icon="faucet-drip" href="/docs/ru/rpc/devnet-sol">
    Все способы пополнения кошелька в devnet и рекомендации по ограничениям частоты запросов.
  </Card>

  <Card title="sendTransaction" icon="paper-plane" href="/docs/ru/api-reference/rpc/http/sendtransaction">
    Все параметры, включая skipPreflight, preflightCommitment и повторные попытки.
  </Card>

  <Card title="Land transactions reliably" icon="rocket" href="/docs/ru/api-reference/sender/sendtransaction">
    При переходе в mainnet используйте Sender для включения транзакций в блок с минимальной задержкой.
  </Card>

  <Card title="Build a portfolio tracker" icon="wallet" href="/docs/ru/quickstart/portfolio-tracker">
    Альтернативный вариант: получите токены, NFT и SOL любого кошелька с лентой активности в реальном времени.
  </Card>
</CardGroup>


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