---
title: "Ký Web3"
description: "Ký thông điệp, dữ liệu có cấu trúc (typed data) và giao dịch bằng ví Fystack."
url: https://docs.fystack.io/vi/web3-sign
last_updated: 2026-11-13
---

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

# Ký Web3

Ký thông điệp, dữ liệu có cấu trúc (typed data) và giao dịch trên các mạng lưới EVM và Solana.

**Hãy bật Web3 Signing cho ví trước khi sử dụng các endpoint này hoặc SDK.** Tính năng này bị tắt theo mặc định; các yêu cầu ký sẽ trả về **403 Forbidden** cho đến khi được bật. Xem [Bật ký Web3](https://docs.fystack.io/product/web3-sign.md#enable-web3-signing).

Các yêu cầu ký cần được phê duyệt trước khi thực thi. Xem xét chúng tại **Approval → DApp Transaction** trên dashboard. Xem [Phê duyệt ký Web3](https://docs.fystack.io/product/web3-sign.md#review-pending-requests).

Các yêu cầu trả về một `transaction_id`. Hãy polling endpoint trạng thái cho đến khi việc ký hoàn tất hoặc thất bại.

---

## Yêu cầu chữ ký

**Endpoint:** `POST /web3/:wallet_id/sign`

Ký một thông điệp EVM hoặc Solana. Xem [Khóa API](https://docs.fystack.io/api-keys.md) để biết cách xác thực.

SDK yêu cầu một ví và một RPC provider để ký EVM. SDK tự động polling để lấy chữ ký.

### Tham số

- `wallet_id` (string): ID ví trong đường dẫn URL.
- `method` (string): `eth_sign`, `eth_signTypedData_v4` hoặc `solana_signMessage`.
- `message` (string): Thông điệp cần ký. Dùng chuỗi rỗng đối với typed data.
- `chain_id` (number): Chain ID của EVM. Dùng `0` cho Solana.
- `typed_data` (string): Bắt buộc khi ký typed data. Chuỗi JSON chứa `domain`, `types` và `message`.
- `X-Idempotency-Key` (string, recommended): Dùng lại cùng một khóa khi thử lại request. SDK hiện chưa ánh xạ `options.idempotencyKey` sang header này.

### Phản hồi

- `transaction_id` (string): ID yêu cầu để kiểm tra trạng thái ký.

**Request** `POST /web3/:wallet_id/sign`

```typescript
import { EtherSigner, Environment } from '@fystack/sdk'
import { JsonRpcProvider } from 'ethers'

const provider = new JsonRpcProvider(process.env.RPC_URL!)
const signer = new EtherSigner(
  {
    apiKey: process.env.API_KEY!,
    apiSecret: process.env.API_SECRET!,
  },
  Environment.Production,
  provider,
)

signer.setWallet('YOUR_WALLET_ID')
const signature = await signer.signMessage('Authorize this session')
```

```typescript
import { EtherSigner, Environment } from '@fystack/sdk'
import { JsonRpcProvider } from 'ethers'

const provider = new JsonRpcProvider(process.env.RPC_URL!)
const signer = new EtherSigner(
  {
    apiKey: process.env.API_KEY!,
    apiSecret: process.env.API_SECRET!,
  },
  Environment.Production,
  provider,
)

signer.setWallet('YOUR_WALLET_ID')
const network = await provider.getNetwork()

const signature = await signer.signTypedData(
  {
    name: 'Example App',
    version: '1',
    chainId: network.chainId,
  },
  {
    Session: [
      { name: 'account', type: 'address' },
      { name: 'nonce', type: 'string' },
    ],
  },
  {
    account: await signer.getAddress(),
    nonce: crypto.randomUUID(),
  },
)

console.log('Typed data signature:', signature)
```

```typescript
import { SolanaSigner, Environment } from '@fystack/sdk'

const solanaSigner = new SolanaSigner(
  {
    apiKey: process.env.API_KEY!,
    apiSecret: process.env.API_SECRET!,
  },
  Environment.Production,
)

solanaSigner.setWallet('YOUR_WALLET_ID')

const signature = await solanaSigner.signMessage('Authorize this session')

console.log('Signature:', signature)
```

```json
{
  "method": "eth_sign",
  "message": "Authorize this session",
  "chain_id": 11155111
}
```

```json
{
  "transaction_id": "0de79230-a820-4bd4-b020-883d395faa87"
}
```

---

## Lấy trạng thái ký

**Endpoint:** `GET /web3/:wallet_id/sign/:transaction_id`

Lấy trạng thái và chữ ký của một yêu cầu ký.

- `transaction_id` (string): ID yêu cầu ký.
- `status` (string): `pending_approval`, `pending`, `completed`, `confirmed`, `failed` hoặc `rejected`.
- `signature` (string): Chữ ký, khi đã có. Các signer EVM trong SDK chờ trạng thái `confirmed` kèm chữ ký.
- `approvals` (array): Các bản ghi gồm `user_id` và `status`: `pending`, `approved` hoặc `rejected`.
- `created_at` (string): Thời điểm tạo.
- `updated_at` (string): Thời điểm cập nhật gần nhất.

Nếu polling hết thời gian chờ, hãy kiểm tra yêu cầu hiện có trước khi gửi yêu cầu khác.

**Request** `GET /web3/:wallet_id/sign/:transaction_id`

```typescript
import { APIService, Environment } from '@fystack/sdk'

const api = new APIService(
  { apiKey: process.env.API_KEY!, apiSecret: process.env.API_SECRET! },
  Environment.Production,
)

const status = await api.getSignStatus('YOUR_WALLET_ID', 'TRANSACTION_ID')
console.log(status.signature)
```

```json
{
  "transaction_id": "0de79230-a820-4bd4-b020-883d395faa87",
  "status": "pending_approval",
  "approvals": [],
  "created_at": "2026-10-03T00:00:00Z",
  "updated_at": "2026-10-03T00:00:00Z"
}
```

---

## Ký giao dịch

**Endpoint:** `POST /web3/transaction/:wallet_id/signRaw`

> **Warning: Ký không an toàn.** Không khuyến nghị ký dữ liệu thô. Một yêu cầu độc hại có thể lừa bạn ký một giao dịch đánh cắp tiền. Chỉ ký những payload bạn đã xác minh.

Gửi một giao dịch để ký và xử lý. Trả về một `transaction_id`.

- **EVM**: `from`, `to`, `nonce`, `gasLimit`, `data`, `value`, `chainId`, `maxFeePerGas`, `maxPriorityFeePerGas` và `accessList`.
- **Solana**: `data` (giao dịch đã serialize dạng base64), `from`, `meta.tx_method` (`solana_signTransaction`) và `chainId` (`"1399811149"`).

Hàm `signTransaction` của EVM SDK trả về mã băm giao dịch. `sendTransaction` tự điền các trường giao dịch và trả về một transaction response.

**Request** `POST /web3/transaction/:wallet_id/signRaw`

```typescript
import { EtherSigner, Environment } from '@fystack/sdk'
import { JsonRpcProvider, parseEther } from 'ethers'

const provider = new JsonRpcProvider(process.env.RPC_URL!)
const signer = new EtherSigner(
  {
    apiKey: process.env.API_KEY!,
    apiSecret: process.env.API_SECRET!,
  },
  Environment.Production,
  provider,
)

signer.setWallet('YOUR_WALLET_ID')
const tx = await signer.sendTransaction({
  to: '0x7c2BbE2e02af09F1cf9aFd4A79EC201DC841675a',
  value: parseEther('0.01'),
})

console.log(tx.hash)
```

```typescript
import { SolanaSigner, Environment } from '@fystack/sdk'

const solanaSigner = new SolanaSigner(
  {
    apiKey: process.env.API_KEY!,
    apiSecret: process.env.API_SECRET!,
  },
  Environment.Production,
)

solanaSigner.setWallet('YOUR_WALLET_ID')

// Base64 serialized transaction from @solana/web3.js.
const signature = await solanaSigner.signTransaction(serializedTransaction)
console.log(signature)
```

```json
{
  "transaction_id": "0de79230-a820-4bd4-b020-883d395faa87"
}
```

---

## Lấy trạng thái giao dịch

**Endpoint:** `GET /web3/transaction/:wallet_id/:transaction_id`

Trả về `transaction_id`, `status`, `method`, `approvals`, `created_at` và `updated_at`, kèm `hash` và `failed_reason` khi có.

Các signer giao dịch trong SDK chờ trạng thái `confirmed` hoặc `completed` kèm `hash`, và dừng lại khi gặp `failed` hoặc `rejected`.

**Request** `GET /web3/transaction/:wallet_id/:transaction_id`

```typescript
import { APIService, Environment } from '@fystack/sdk'

const api = new APIService(
  { apiKey: process.env.API_KEY!, apiSecret: process.env.API_SECRET! },
  Environment.Production,
)

const status = await api.getTransactionStatus('YOUR_WALLET_ID', 'TRANSACTION_ID')
console.log(status.hash)
```

```json
{
  "transaction_id": "0de79230-a820-4bd4-b020-883d395faa87",
  "status": "pending",
  "method": "solana_signTransaction",
  "approvals": [],
  "created_at": "2026-10-03T00:00:00Z",
  "updated_at": "2026-10-03T00:00:00Z"
}
```
