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

# Hỗ trợ giao dịch v1

> Chuẩn bị tích hợp Solana cho giao dịch v1: đặt maxSupportedTransactionVersion thành 1, nâng cấp lên SDK hỗ trợ v1 và đọc phí ưu tiên từ transactionConfig.

Agave 4.2 giới thiệu giao dịch v1 ([SIMD-0385](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md)). Sau khi cổng tính năng được kích hoạt trên mainnet, các ví và chương trình sẽ bắt đầu gửi giao dịch v1, và mọi yêu cầu truy xuất toàn bộ dữ liệu giao dịch đều phải chủ động cho phép nhận các giao dịch này.

Trang này trình bày những thay đổi, các endpoint Helius bị ảnh hưởng và cách cập nhật mã. Để xem danh sách kiểm tra đầy đủ cho Agave 4.2, bao gồm các loại phần thưởng, ngữ nghĩa cập nhật tài khoản và thời gian slot, hãy xem [danh sách kiểm tra di chuyển sang Agave 4.2](https://www.helius.dev/blog/agave-4-2-migration-checklist).

## Những thay đổi trong giao dịch v1

Các giao dịch legacy và v0 không thay đổi. Đối với hầu hết các tích hợp, có hai điểm quan trọng về giao dịch v1:

* **Bạn phải chủ động cho phép nhận giao dịch này.** Các yêu cầu lấy toàn bộ dữ liệu giao dịch cần `maxSupportedTransactionVersion: 1`, đồng thời thư viện máy khách phải có phiên bản có thể giải tuần tự hóa v1.
* **Ngân sách tính toán được chuyển vào header của thông điệp.** Một thông điệp v1 chứa đối tượng `transactionConfig` với `computeUnitLimit`, `heapSize`, `loadedAccountsDataSizeLimit` và `priorityFee`. Giao dịch v1 không có lệnh chương trình ComputeBudget.

Định dạng truyền tải cũng thay đổi (thêm một byte phiên bản mới và các chữ ký nằm ở cuối giao dịch), nhưng điều này chỉ ảnh hưởng đến mã giải mã các byte giao dịch thô. Xem phần [Giải mã các byte giao dịch thô](#giải-mã-các-byte-giao-dịch-thô-bằng-trình-phân-tích-cú-pháp-hỗ-trợ-v1) bên dưới.

Trong các phản hồi JSON, giao dịch v1 trả về `"version": 1` và `message` của giao dịch đó bao gồm `transactionConfig`:

```json theme={"system"}
{
  "version": 1,
  "transaction": {
    "signatures": ["..."],
    "message": {
      "accountKeys": ["..."],
      "instructions": [
        { "programIdIndex": 3, "accounts": [0, 1], "data": "3Bxs4..." }
      ],
      "recentBlockhash": "...",
      "transactionConfig": {
        "computeUnitLimit": 200000,
        "heapSize": null,
        "loadedAccountsDataSizeLimit": 200000,
        "priorityFee": 50000
      }
    }
  }
}
```

`"priorityFee": 50000` có nghĩa là giao dịch này trả tổng cộng 50.000 lamport. Trường `null` có nghĩa là người gửi không đặt giá trị này. Các thông điệp legacy và v0 hoàn toàn không có `transactionConfig`.

## Đặt maxSupportedTransactionVersion thành 1

Mọi yêu cầu trả về toàn bộ dữ liệu giao dịch đều phải khai báo phiên bản giao dịch cao nhất mà yêu cầu đó có thể xử lý. Đặt `maxSupportedTransactionVersion: 1` trên:

* [`getTransaction`](/docs/vi/rpc/guides/gettransaction)
* [`getBlock`](/docs/vi/rpc/guides/getblock)
* [`getTransactionsForAddress`](/docs/vi/rpc/gettransactionsforaddress) với `transactionDetails: "full"`
* [`transactionSubscribe`](/docs/vi/rpc/websocket/transaction-subscribe) với `transactionDetails: "accounts"` hoặc `"full"`
* [`blockSubscribe`](/docs/vi/api-reference/rpc/websocket/blocksubscribe)

Một yêu cầu bỏ qua tham số này hoặc đặt tham số thành `0` sẽ gặp lỗi JSON-RPC `-32015` ngay khi yêu cầu truy cập một giao dịch v1:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32015,
    "message": "Transaction version (1) is not supported by the requesting client. Please use \"maxSupportedTransactionVersion\" in your request."
  },
  "id": 1
}
```

Đối với `getBlock`, chỉ cần một giao dịch v1 ở bất kỳ vị trí nào trong khối cũng sẽ khiến toàn bộ yêu cầu thất bại. Nếu thấy `-32015` trong nhật ký, dự án đã gặp lỗi với các giao dịch có phiên bản.

<CodeGroup>
  ```json getTransaction theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTransaction",
    "params": [
      "2id3YC2jK9G5Wo2phDx4gJVAew8DcY5NAojnVuao8rkxwPYPe8cSwE5GzhEgJA2y8fVjDEo6iR6ykBvDxrTQrtpb",
      {
        "encoding": "jsonParsed",
        "commitment": "confirmed",
        "maxSupportedTransactionVersion": 1
      }
    ]
  }
  ```

  ```json getBlock theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getBlock",
    "params": [
      341197053,
      {
        "encoding": "jsonParsed",
        "transactionDetails": "full",
        "maxSupportedTransactionVersion": 1
      }
    ]
  }
  ```

  ```json getTransactionsForAddress theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTransactionsForAddress",
    "params": [
      "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
      {
        "transactionDetails": "full",
        "encoding": "jsonParsed",
        "limit": 100,
        "maxSupportedTransactionVersion": 1
      }
    ]
  }
  ```

  ```json transactionSubscribe theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "transactionSubscribe",
    "params": [
      { "accountInclude": ["86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"] },
      {
        "commitment": "confirmed",
        "encoding": "jsonParsed",
        "transactionDetails": "full",
        "maxSupportedTransactionVersion": 1
      }
    ]
  }
  ```
</CodeGroup>

## Nâng cấp SDK trước khi tăng giá trị

Việc đặt `maxSupportedTransactionVersion: 1` yêu cầu nút trả về các giao dịch v1. Thư viện máy khách vẫn phải có khả năng giải tuần tự hóa các giao dịch này. Hãy nâng cấp trước, sau đó thay đổi tham số:

| Máy khách                                       | Phiên bản tối thiểu hỗ trợ giao dịch v1              |
| ----------------------------------------------- | ---------------------------------------------------- |
| `@solana/kit`                                   | 8.0                                                  |
| `@solana/web3.js`                               | v3                                                   |
| Rust `solana-sdk` / `solana-transaction-status` | Bản phát hành được xây dựng trên các crate Agave 4.2 |
| `yellowstone-grpc-client`                       | 13.3.0                                               |
| `yellowstone-grpc-proto`                        | 12.6.0                                               |
| `helius-laserstream` (JavaScript)               | 0.8.4                                                |
| `helius-laserstream` (Rust)                     | 0.6.3                                                |
| `helius-laserstream` (Go)                       | 0.2.0                                                |

Các triển khai `VersionedTransaction.deserialize` cũ hơn trong JavaScript chỉ xử lý legacy và v0, đồng thời phát sinh lỗi khi gặp byte `0x81` ở đầu. Các proto Yellowstone cũ hơn có trước các trường thông điệp v1, vì vậy trình tiêu thụ gRPC trên những phiên bản đó sẽ không bao giờ thấy `transactionConfig`. Đối với máy khách gRPC Go, hãy tạo lại mã từ các proto Yellowstone mới nhất và `solana-storage-proto`.

## Đọc phí ưu tiên từ transactionConfig

Mã ước tính phí ưu tiên của giao dịch bằng cách quét các lệnh chương trình ComputeBudget (`ComputeBudget111111111111111111111111111111`, `setComputeUnitPrice`, `setComputeUnitLimit`) sẽ xác định mọi giao dịch v1 là trả phí bằng 0. Trong v1, các giá trị nằm trong `message.transactionConfig` và sử dụng đơn vị khác:

| Định dạng  | Vị trí của phí                  | Đơn vị                                  |
| ---------- | ------------------------------- | --------------------------------------- |
| Legacy, v0 | Lệnh `setComputeUnitPrice`      | Micro-lamport trên mỗi đơn vị tính toán |
| v1         | `transactionConfig.priorityFee` | Tổng số lamport cho giao dịch           |

Không áp dụng phép tính `price × computeUnitLimit ÷ 1e6` của định dạng legacy cho `priorityFee`. Giá trị này đã là tổng số.

```typescript priority-fee.ts theme={"system"}
import bs58 from "bs58";

const COMPUTE_BUDGET = "ComputeBudget111111111111111111111111111111";

/** Total priority fee in lamports for a `json`-encoded transaction. */
function priorityFeeLamports(tx: any): number {
  const message = tx.transaction.message;

  // v1: the header carries the total directly.
  if (message.transactionConfig) {
    return message.transactionConfig.priorityFee ?? 0;
  }

  // Legacy and v0: derive it from ComputeBudget instructions.
  let microLamportsPerCu = 0n;
  let computeUnitLimit: bigint | null = null;
  let otherInstructions = 0;

  for (const ix of message.instructions) {
    if (message.accountKeys[ix.programIdIndex] !== COMPUTE_BUDGET) {
      otherInstructions++;
      continue;
    }
    const data = bs58.decode(ix.data);
    const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
    if (data[0] === 2) computeUnitLimit = BigInt(view.getUint32(1, true));
    if (data[0] === 3) microLamportsPerCu = view.getBigUint64(1, true);
  }

  // Without an explicit limit, the runtime grants 200,000 CU per non-ComputeBudget instruction, capped at 1,400,000.
  const limit = computeUnitLimit ?? BigInt(Math.min(otherInstructions * 200_000, 1_400_000));
  return Number((microLamportsPerCu * limit) / 1_000_000n);
}
```

Hãy phân nhánh theo `transactionConfig` (hoặc `version === 1`) thay vì dựa trên sự hiện diện của các lệnh ComputeBudget, vì một giao dịch legacy không có phí ưu tiên cũng không có các lệnh này.

## Giải mã các byte giao dịch thô bằng trình phân tích cú pháp hỗ trợ v1

Phần này chỉ áp dụng nếu bạn sử dụng các byte giao dịch thô, chẳng hạn từ [preconfSubscribe](/docs/vi/pre-confirmations/preconf-subscribe), [preprocessedSubscribe](/docs/vi/preprocessed-transactions/preprocessed-subscribe) hoặc phản hồi RPC được mã hóa bằng `base64`. Nếu làm việc với các phản hồi `json` hoặc `jsonParsed`, hãy bỏ qua phần này.

Giao dịch v1 thay đổi bố cục truyền tải theo hai cách:

* **Byte phiên bản.** Giao dịch v1 bắt đầu bằng `0x81` (129 ở hệ thập phân). Giao dịch v0 bắt đầu bằng `0x80`.
* **Chữ ký được chuyển xuống cuối.** Legacy và v0 đặt chữ ký trước, sau đó là thông điệp. Giao dịch v1 đặt thông điệp trước và chữ ký ở cuối, vì vậy các trình giải mã kiểu `bincode` vốn yêu cầu mảng chữ ký ở đầu sẽ thất bại với các byte v1.

<Frame caption="Byte layout of a transaction v1 with three addresses and one instruction. The signature sits at the end, after the message.">
  <img src="https://mintcdn.com/helius/VV8h76d8Pisjh8RU/images/solana-transaction-v1-byte-layout.png?fit=max&auto=format&n=VV8h76d8Pisjh8RU&q=85&s=75b76003a7c6a506f6ff24dfc47cb677" alt="Byte-by-byte layout of a Solana transaction v1: version byte, header, config mask, lifetime specifier, address and instruction counts, three 32-byte addresses, compute unit config, instruction header, indices, discriminators, lamports, and a 64-byte signature at the end" width="1280" height="720" data-path="images/solana-transaction-v1-byte-layout.png" />
</Frame>

Để xem hướng dẫn chi tiết từng trường trong định dạng truyền tải v1, hãy xem [Giao dịch v1 trong bài viết về các phiên bản giao dịch Solana](https://www.helius.dev/blog/solana-transaction-versions#transaction-v1).

Sử dụng trình giải mã hiểu bố cục v1:

* **Rust:** [`agave-transaction-view`](https://docs.rs/agave-transaction-view) phân tích trực tiếp legacy, v0 và v1. [`wincode`](https://docs.rs/wincode), bộ tuần tự hóa tương thích với bincode được các SDK Solana hiện tại sử dụng, cũng giải mã v1 thành `VersionedTransaction`.
* **JavaScript / TypeScript:** `@solana/kit` 8.0+ hoặc `@solana/web3.js` v3.

Các trình giải mã tùy chỉnh cần kiểm tra byte đầu tiên: `0x81` biểu thị v1 và các chữ ký nằm sau thông điệp thay vì nằm trước.

## Danh sách kiểm tra

1. Dùng Grep để tìm `getBlock`, `getTransaction`, `getTransactionsForAddress`, `transactionSubscribe` và `blockSubscribe`, bao gồm cả phần thân JSON-RPC thô và các trình bao SDK như `connection.getParsedTransaction`.
2. Nâng cấp lên SDK hỗ trợ v1.
3. Đặt `maxSupportedTransactionVersion: 1` trên mọi lệnh gọi tìm thấy ở bước 1.
4. Thay việc quét lệnh ComputeBudget bằng phép kiểm tra `transactionConfig` và coi `priorityFee` là tổng số lamport.
5. Thay các trình giải mã thô kiểu `bincode` bằng `agave-transaction-view` hoặc SDK đã nâng cấp.
6. Nâng các phần phụ thuộc phát trực tuyến lên các phiên bản trong bảng trên.
7. Dùng Grep để tìm `-32015` trong nhật ký sau khi thay đổi nhằm xác nhận không còn lỗi nào.

Để tìm hiểu chuyên sâu về thông số kỹ thuật của các phiên bản giao dịch Solana, định dạng truyền tải và ví dụ, hãy đọc bài viết [Quản lý phiên bản giao dịch Solana: Legacy, v0 và v1](https://www.helius.dev/blog/solana-transaction-versions).

## Nội dung liên quan

<CardGroup cols={2}>
  <Card title="getTransaction guide" icon="magnifying-glass" href="/docs/vi/rpc/guides/gettransaction">
    Các tham số, cấu trúc phản hồi và ví dụ để truy xuất một giao dịch duy nhất.
  </Card>

  <Card title="getBlock guide" icon="cube" href="/docs/vi/rpc/guides/getblock">
    Truy xuất toàn bộ một khối, bao gồm mọi giao dịch trong khối đó.
  </Card>

  <Card title="getTransactionsForAddress" icon="list" href="/docs/vi/rpc/gettransactionsforaddress">
    Lịch sử giao dịch được lọc và phân trang cho bất kỳ địa chỉ nào chỉ trong một lệnh gọi.
  </Card>

  <Card title="Agave 4.2 migration checklist" icon="clipboard-check" href="https://www.helius.dev/blog/agave-4-2-migration-checklist">
    Mọi thay đổi không tương thích ngược trong Agave 4.2, kèm theo các bước khắc phục.
  </Card>
</CardGroup>
