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

# Hướng dẫn routing instruction

> Tham chiếu cho các hướng dẫn AMM Routing được bật trên mainnet — sáu biến thể bao gồm swap exact-input / exact-output và các tiện ích wSOL.

<Info>
  **Trang này được dịch tự động bằng AI. Phiên bản tiếng Anh là bản chính thức.**

  [Xem bản tiếng Anh →](/products/routing/instructions)
</Info>

<Info>
  Trang này là tham chiếu chính thức về instruction cho chương trình AMM Routing. Để xem các ví dụ code, hãy tham khảo [`products/routing/code-demos`](/vi/products/routing/code-demos). Để xem ý nghĩa lỗi, hãy tham khảo [`reference/error-codes`](/vi/reference/error-codes).
</Info>

## Tóm tắt instruction

| Tag | Discriminator                | Chính xác | Biến thể |
| --- | ---------------------------- | --------- | -------- |
| 0   | `SwapBaseInWithUserAccount`  | Input     | Legacy   |
| 1   | `SwapBaseOutWithUserAccount` | Output    | Legacy   |
| 5   | `CreateSyncNative`           | —         | Tiện ích |
| 6   | `CloseTokenAccount`          | —         | Tiện ích |
| 8   | `SwapBaseIn`                 | Input     | Hiện tại |
| 9   | `SwapBaseOut`                | Output    | Hiện tại |

**Chú giải:**

* **Chính xác:** số tiền nào được xác định cố định bởi người gọi (Input = exact-input `amount_in`; Output = exact-output `amount_out`).
* **Biến thể:** Các instruction Legacy yêu cầu một deque `limit_prices` không rỗng ngay cả khi không có CLMM hop nào trong route. Các instruction hiện tại (8 / 9) coi deque `limit_prices` rỗng là "không kiểm tra", đây là cách được khuyến nghị cho code mới.

Tất cả các biến thể swap định tuyến các token trung gian thông qua **các ATA do người dùng kiểm soát** — người dùng sở hữu ATA input, mọi ATA trung gian và ATA output. Đối với các tích hợp mới, hãy sử dụng **tag 8 (`SwapBaseIn`)** hoặc **tag 9 (`SwapBaseOut`)** trừ khi bạn có lý do cụ thể để gọi một biến thể Legacy.

## Các instruction swap hiện tại (được khuyến nghị)

Đây là các điểm vào mà code mới nên sử dụng. Cấu trúc argument giống với các biến thể Legacy nhưng `limit_prices` có thể rỗng.

### `SwapBaseIn` (tag 8)

Swap đa hop exact-input. Người gọi xác định cố định `amount_in`; router thực thi hop từng hop và xác nhận rằng số lượng cuối cùng đạt hoặc vượt quá `minimum_amount_out`.

**Arguments**

```
amount_in:            u64
minimum_amount_out:   u64
limit_prices:         VecDeque<u128>  // optional; empty deque means no per-hop CLMM price check
```

**Accounts**

```
[
  <user_input_ata> W S,         // signer; balance >= amount_in
  <user_intermediate_ata_1> W,  // one per intermediate hop
  ... <user_intermediate_ata_N> W,
  <user_output_ata> W,
  <token_program>,

  <pool_program_hop_1>,         // identifies which AMM family hop 1 is
  <pool_state_hop_1> W,
  ... <other accounts required by hop 1's program>,

  <pool_program_hop_2>,
  <pool_state_hop_2> W,
  ... <hop 2 accounts>,

  ... [repeat per hop]
]
```

Danh sách tài khoản chính xác cho mỗi hop phụ thuộc vào chương trình AMM cơ bản (AMM v4 / CPMM / CLMM / Stable). Router CPI vào từng cái lần lượt và xác thực ID chương trình khớp với một trong bốn chương trình được hỗ trợ.

**Điều kiện tiên quyết**

* Người gọi ký bằng `user_input_ata`.
* `user_input_ata.amount >= amount_in`.
* Mỗi ATA user trung gian tồn tại và được sở hữu bởi người gọi.
* Nếu bất kỳ hop nào là CLMM và bạn muốn thực thi giới hạn giá, hãy cung cấp một mục `limit_prices` cho mỗi CLMM hop.

**Điều kiện sau**

* Số dư `user_input_ata` giảm đi `amount_in`.
* Số dư `user_output_ata` tăng lên ≥ `minimum_amount_out`.
* Mỗi ATA trung gian được để lại với thay đổi ròng bằng không (route tiêu thụ bất cứ thứ gì nó tạo ra ở hop trước đó).

**Lỗi phổ biến**

* `ExceededSlippage` — output cuối cùng \< `minimum_amount_out`.
* `InvalidInput` — route rỗng, account dị hình, hoặc `pool_program` không được hỗ trợ.
* `SqrtPriceX64` — giá CLMM hop di chuyển ngoài giới hạn `limit_prices` được cung cấp (chỉ khi `limit_prices` không rỗng).

***

### `SwapBaseOut` (tag 9)

Swap đa hop exact-output. Người gọi xác định cố định `amount_out`; router xác nhận rằng input thực tế không vượt quá `maximum_amount_in`.

**Arguments**

```
maximum_amount_in:   u64
amount_out:          u64
limit_prices:        VecDeque<u128>  // optional; empty deque means no per-hop CLMM price check
```

**Accounts** — cấu trúc giống như tag 8.

**Điều kiện tiên quyết**

* Người gọi ký bằng `user_input_ata`; số dư `>= maximum_amount_in` (trường hợp xấu nhất).
* Mỗi ATA trung gian và ATA output tồn tại.

**Điều kiện sau**

* `user_input_ata` giảm đi số lượng thực tế cần thiết (≤ `maximum_amount_in`).
* `user_output_ata` tăng lên chính xác `amount_out`.

**Lỗi phổ biến**

* `ExceededSlippage` — input cần thiết vượt quá `maximum_amount_in`.
* `InvalidInput`, `SqrtPriceX64` — giống như tag 8.

***

## Các instruction swap Legacy

Những biến thể cũ hơn này vẫn có thể được gọi trên chương trình live và được tài liệu hóa ở đây để hoàn chỉnh. Ưu tiên tag 8 / tag 9 cho code mới; cả hai biến thể Legacy dưới đây yêu cầu một deque `limit_prices` không rỗng ngay cả khi không có CLMM hop nào liên quan, điều này làm cho chúng khó sử dụng.

### `SwapBaseInWithUserAccount` (tag 0)

Swap đa hop exact-input, giống hệt như tag 8 nhưng có yêu cầu `limit_prices` nghiêm ngặt hơn.

**Arguments**

```
amount_in:           u64
minimum_amount_out:  u64
limit_prices:        VecDeque<u128>  // required, non-empty
```

**Accounts** — cấu trúc giống như `SwapBaseIn` (tag 8). Tất cả các slot trung gian phải là ATA do người gọi sở hữu.

**Điều kiện tiên quyết**

* Người gọi ký bằng `user_input_ata`.
* `user_input_ata.amount >= amount_in`.
* Tất cả các ATA user trung gian tồn tại và được sở hữu bởi người gọi.
* `limit_prices` không rỗng (một mục cho mỗi CLMM hop; điền các giá trị placeholder nếu không có CLMM hop nào liên quan).

**Điều kiện sau**

* Số dư `user_input_ata` giảm đi `amount_in`.
* Số dư `user_output_ata` tăng lên ≥ `minimum_amount_out`.

**Lỗi phổ biến**

* `ExceededSlippage`.
* `InvalidInput` — deque `limit_prices` rỗng bị từ chối ở biến thể Legacy này.
* `SqrtPriceX64`.

***

### `SwapBaseOutWithUserAccount` (tag 1)

Swap exact-output, đối tác Legacy của `SwapBaseOut` (tag 9).

**Arguments**

```
maximum_amount_in:   u64
amount_out:          u64
limit_prices:        VecDeque<u128>  // required, non-empty
```

**Accounts** — cấu trúc giống như tag 0 / tag 9.

**Điều kiện tiên quyết**

* Người gọi ký bằng `user_input_ata`.
* `user_input_ata.amount >= maximum_amount_in`.
* Tất cả các ATA user trung gian tồn tại và được sở hữu bởi người gọi.
* `limit_prices` không rỗng.

**Điều kiện sau**

* `user_input_ata` giảm đi số lượng thực tế cần thiết (≤ `maximum_amount_in`).
* `user_output_ata` tăng lên chính xác `amount_out`.

**Lỗi phổ biến**

* `ExceededSlippage`.
* `InvalidInput`.
* `SqrtPriceX64`.

***

## Các instruction tiện ích

### `CreateSyncNative` (tag 5)

Tạo (nếu bị thiếu) và đồng bộ hóa wSOL ATA trong một bước. Tiện lợi khi gói SOL inline cùng một swap.

**Arguments**

```
amount: u64    // SOL to wrap (lamports)
```

**Accounts**

```
[
  <user_wsol_ata> W,            // ATA for wSOL; created if missing
  <user_native_account> W S,    // signer; SOL is debited from here
  <wsol_mint>,
  <system_program>,
  <token_program>,
  <associated_token_program>,
]
```

**Tác dụng**

* Tạo `user_wsol_ata` nếu nó chưa tồn tại.
* Chuyển `amount` lamports từ số dư SOL gốc của người ký đến ATA.
* Gọi `SyncNative` trên ATA để số dư token của nó phản ánh lamports mới.

**Lỗi phổ biến**

* `InvalidOwner` — chủ sở hữu của `user_wsol_ata` không phải là người ký.

***

### `CloseTokenAccount` (tag 6)

Đóng một tài khoản token và trả tiền cho ví đích của nó. Được ghép nối với `CreateSyncNative`: sau khi swap có leg wSOL, gọi `CloseTokenAccount` để phục hồi tiền cho ATA wSOL.

**Arguments** — không có.

**Accounts**

```
[
  <token_account_to_close> W,
  <destination_for_rent> W,
  <owner> S,
  <token_program>,
]
```

**Tác dụng**

* Đóng `token_account_to_close`.
* Chuyển số dư lamport miễn phí tiền thuê (\~0.00203928 SOL trên mainnet cho một tài khoản SPL Token vanilla) đến `destination_for_rent`.
* Tài khoản token phải có số dư token bằng không.

**Lỗi phổ biến**

* `InvalidOwner` — người gọi không phải là chủ sở hữu ATA.
* Số dư tài khoản token khác không.

***

## Tiếp theo bạn nên tham khảo

* [`products/routing/code-demos`](/vi/products/routing/code-demos) — xây dựng từng instruction này bằng TypeScript.
* [`products/routing/accounts`](/vi/products/routing/accounts) — các khoá dispatch theo AMM và bố cục tài khoản theo hop.
* [`reference/error-codes`](/vi/reference/error-codes) — danh sách đầy đủ `RouteError`.
