GVI Phase 3 — Activation Playbook
Admin Login · Bank Account · VietQR/VNPAY · eKYC C06 VNPT | DB: v5 · goldvninvest.online
📊 Trạng Thái Hiện Tại (2026-07-20)
| Thành phần | Trạng thái | Giá trị |
| Admin account | ✅ Hoạt động | admin@goldvninvest.online · roleId=52 |
| superadmin@example.com | ✅ Hoạt động | roleId=53 · emailVerified=1 |
| role_permission | ✅ 1413 perms | Super Admin + Admin + User đầy đủ |
| binary_market | ✅ 7 cặp | BTC/ETH/BNB/SOL/XRP/DOGE/GIV |
| binary_duration | ✅ 6 durations | 1,3,5,15,30,60 phút |
| investment_plan | ✅ 11 plans | starter_vnd, growth_vnd, vip... |
| staking_pools | ❌ 0 records | Bảng có — dữ liệu trống |
| kyc_level | ❌ 0 records | kyc_verification_service: 3 (SumSub/DeepSeek/Gemini) |
| internal_wallet | ❌ Bảng chưa tạo | Migration script chưa chạy --apply |
| payment_provider_config | ❌ Bảng chưa tạo | Migration script chưa chạy --apply |
| BANK_ACCOUNT_NUMBER (.env) | ❌ Trống | Cần điền số TK thật |
| VIETQR_WEBHOOK_SECRET (.env) | ❌ Trống | Cần điền secret thật |
| eKYC VNPT C06 | ⚠️ Chưa cấu hình | kyc_verification_service chỉ có SumSub/AI — chưa có VNPT |
🔐 Bước 3.1 — Test Admin Login
⚠️ Mật khẩu mặc định: Tài khoản superadmin@example.com đang dùng mật khẩu mặc định 12345678. Đổi ngay sau khi đăng nhập thành công.
Thông tin đăng nhập
| Account | Email | Password | Role |
| Super Admin (chính) | admin@goldvninvest.online | xem DB hoặc .env | roleId=52 |
| Super Admin (mặc định) | superadmin@example.com | 12345678 | roleId=53 |
Checklist kiểm tra sau login
- Truy cập
https://goldvninvest.online/en/login → đăng nhập thành công → redirect /en/user/dashboard
- Truy cập
https://goldvninvest.online/en/admin → Admin panel load (không 500)
- Admin > CRM > Users → Danh sách user hiển thị được (role_permission OK)
- Admin > Finance > Deposit Gateways → Có gateway hoạt động
- Admin > System > Settings → Các key cấu hình load được (149 keys)
- Đổi mật khẩu superadmin@example.com ngay
- Bật 2FA cho tài khoản admin chính (Admin > Profile > Security)
Fix nhanh nếu Admin Panel vẫn lỗi
pm2 logs backend --lines 50 # Xem lỗi mới nhất
pm2 restart backend # Restart backend, reload cache
node scripts/redis-seed-cache.js --force # Warm Redis cache
🗄️ Bước 3.2 — Tạo Bảng internal_wallet & payment_provider_config
❌ Bắt buộc chạy trước: Hai bảng này chưa tồn tại trong DB v5. Phải tạo trước khi điền bank account hoặc cấu hình VietQR.
1
Chạy migration tạo bảng
# Từ thư mục gốc (/var/app/public_html)
cd /var/app/public_html
# DRY-RUN trước — xem thay đổi mà không ghi DB
node backend/scripts/create-internal-wallet-table.mjs
# Kết quả mong đợi DRY-RUN:
# [CREATE] Bảng 'internal_wallet'.
# [ADD] INDEX 'internalWalletProviderIdx' ...
# DRY-RUN — 5 thay đổi cần áp dụng. Chạy lại với --apply.
# APPLY thực tế
node backend/scripts/create-internal-wallet-table.mjs --apply
2
Tạo bảng payment_provider_config thủ công nếu chưa có
mysql -u goldvninvest v5 -e "
CREATE TABLE IF NOT EXISTS \`payment_provider_config\` (
\`id\` CHAR(36) NOT NULL,
\`name\` VARCHAR(100) NOT NULL UNIQUE,
\`provider\` ENUM('STRIPE','PAYPAL','COINBASE','NOWPAYMENTS',
'MANUAL','VIETQR','VNPAY','MOMO','ZALOPAY')
NOT NULL,
\`environment\` ENUM('SANDBOX','PRODUCTION') NOT NULL DEFAULT 'SANDBOX',
\`credentials\` JSON NULL,
\`supportedCurrencies\` JSON NULL,
\`webhookSecret\` VARCHAR(500) NULL,
\`callbackUrl\` VARCHAR(1000) NULL,
\`status\` ENUM('ACTIVE','INACTIVE','ERROR') NOT NULL DEFAULT 'INACTIVE',
\`priority\` INT NOT NULL DEFAULT 10,
\`createdAt\` DATETIME NOT NULL,
\`updatedAt\` DATETIME NOT NULL,
PRIMARY KEY (\`id\`),
INDEX \`paymentProviderConfigStatusIdx\` (\`status\`),
INDEX \`paymentProviderConfigProviderIdx\` (\`provider\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
"
3
Xác nhận tạo thành công
mysql -u goldvninvest v5 -e "SHOW TABLES LIKE 'internal_wallet'; SHOW TABLES LIKE 'payment_provider_config';"
# Expected: 2 tables listed
pm2 restart backend # Backend cần restart để nhận model mới
🏦 Bước 3.3 — Điền Bank Account (internal_wallet)
Thay STK_THUC_TE, TEN_CHU_TK, MA_NGAN_HANG bằng thông tin thật của công ty trước khi chạy SQL.
Tên chủ tài khoản phải đúng như in trên tài khoản ngân hàng để VietQR xác minh auto-credit.
Mã ngân hàng Napas (bankCode) — tham khảo nhanh
| Ngân hàng | bankCode (BIN Napas) | Số TK bắt đầu bằng |
| Vietcombank (VCB) | 970436 | 0071… |
| Techcombank (TCB) | 970407 | 1903… |
| MB Bank | 970422 | 0909… / 0777… |
| BIDV | 970418 | 21… |
| Vietinbank (CTG) | 970415 | 1001… / 1002… |
| ACB | 970416 | 05… / 06… |
| Sacombank | 970403 | 03… |
SQL — Insert tài khoản ngân hàng nhận tiền (thay STK thật)
-- Ưu tiên 1: Tài khoản nhận chính (VD: VCB)
INSERT INTO internal_wallet
(id, name, provider, currency, balance,
bankAccountNumber, bankName, bankCode, accountHolderName,
isDepositWallet, isWithdrawWallet,
minDeposit, maxDeposit, status,
accountDetails, createdAt, updatedAt)
VALUES (
UUID(),
'VCB Nhận Nạp Chính',
'VIETQR',
'VND',
0,
'STK_THUC_TE_VCB', -- ← thay bằng số TK thật (VD: 0071000123456)
'Vietcombank',
'970436', -- BIN Napas của VCB
'CONG TY TNHH GVI', -- ← tên chủ TK đúng như ngân hàng
1, -- isDepositWallet
0, -- isWithdrawWallet
50000, -- minDeposit: 50,000 VND
500000000, -- maxDeposit: 500 triệu VND
1,
JSON_OBJECT(
'qrTemplate', 'https://img.vietqr.io/image/970436-STK_THUC_TE_VCB-compact2.png',
'napasCode', '970436',
'transferNote', 'GVN{userId}'
),
NOW(), NOW()
);
-- Ưu tiên 2: Tài khoản dự phòng (VD: Techcombank)
INSERT INTO internal_wallet
(id, name, provider, currency, balance,
bankAccountNumber, bankName, bankCode, accountHolderName,
isDepositWallet, isWithdrawWallet,
minDeposit, maxDeposit, status,
accountDetails, createdAt, updatedAt)
VALUES (
UUID(),
'TCB Dự Phòng',
'VIETQR',
'VND',
0,
'STK_THUC_TE_TCB', -- ← thay bằng số TK thật
'Techcombank',
'970407',
'CONG TY TNHH GVI',
1, 0,
50000, 500000000,
1,
JSON_OBJECT('napasCode', '970407'),
NOW(), NOW()
);
-- Xác nhận
SELECT name, bankName, bankAccountNumber, bankCode,
accountHolderName, isDepositWallet, status
FROM internal_wallet;
Cập nhật .env sau khi điền TK
# --------------- Bank Account (VietQR IPN auto-credit) ---------------
BANK_ACCOUNT_NUMBER=0071000123456 # Số TK ngân hàng nhận tiền
BANK_ACCOUNT_NAME=CONG TY TNHH GVI # Tên chủ TK (không dấu, in hoa)
BANK_CODE=VCB # Alias ngân hàng (VCB/MB/TCB/ACB...)
VNL_MEMO_PREFIX=GVN # Prefix memo — đã có, không đổi
💳 Bước 3.4 — Cấu Hình VietQR & VNPAY
A. VietQR (Casso / MB Open Banking)
Cách lấy webhook secret: Đăng nhập
casso.vn → Tích hợp → Webhook → Tạo mới → copy
secretKey. Hoặc dùng
api.vietqr.io.
Insert VietQR vào payment_provider_config
INSERT INTO payment_provider_config
(id, name, provider, environment, credentials,
supportedCurrencies, webhookSecret, callbackUrl,
status, priority, createdAt, updatedAt)
VALUES (
UUID(),
'VietQR Production',
'VIETQR',
'PRODUCTION',
JSON_OBJECT(
'bankCode', '970436', -- BIN Napas ngân hàng nhận
'accountNo', 'STK_THUC_TE', -- ← thay bằng số TK thật
'accountName', 'CONG TY TNHH GVI',
'memoPrefix', 'GVN',
'cassoToken', 'CASSO_API_TOKEN_DAY', -- ← token từ casso.vn
'ipnSecretKey', 'WEBHOOK_SECRET_DAY' -- ← secret từ casso.vn
),
JSON_ARRAY('VND', 'VNL'),
'WEBHOOK_SECRET_DAY', -- phải giống ipnSecretKey
'https://goldvninvest.online/api/webhook/vietqr',
'ACTIVE',
1,
NOW(), NOW()
);
-- Thêm webhook secret vào .env
-- VIETQR_WEBHOOK_SECRET=WEBHOOK_SECRET_DAY
Update .env — VietQR secrets
VIETQR_WEBHOOK_SECRET=your_casso_webhook_secret # từ casso.vn → Webhook → secretKey
Luồng hoạt động VietQR tự động
| Bước | Hành động | Endpoint |
| 1 | User gọi tạo memo | POST /api/finance/deposit/fiat/create-memo |
| 2 | User chuyển khoản với memo GVN{id} | — (ngân hàng) — |
| 3 | Casso/Bank gửi IPN | POST /api/webhook/vietqr |
| 4 | vnfAutoDepositService xử lý | Cộng VNL vào ví FIAT |
| 5 | WebSocket thông báo | User nhận thông báo < 30s |
B. VNPAY (Sandbox → Production)
INSERT INTO payment_provider_config
(id, name, provider, environment, credentials,
supportedCurrencies, webhookSecret, callbackUrl,
status, priority, createdAt, updatedAt)
VALUES (
UUID(),
'VNPay Sandbox',
'VNPAY',
'SANDBOX',
JSON_OBJECT(
'tmnCode', 'YOUR_TMN_CODE', -- ← từ VNPay developer portal
'hashSecret', 'YOUR_HASH_SECRET', -- ← từ VNPay developer portal
'payUrl', 'https://sandbox.vnpayment.vn/paymentv2/vpcpay.html',
'returnUrl', 'https://goldvninvest.online/finance/deposit/vnpay/return',
'ipnUrl', 'https://goldvninvest.online/api/webhook/vnpay'
),
JSON_ARRAY('VND'),
NULL,
'https://goldvninvest.online/api/webhook/vnpay',
'INACTIVE', -- Để INACTIVE cho đến khi test sandbox xong
2,
NOW(), NOW()
);
-- Khi test sandbox thành công → đổi sang PRODUCTION + ACTIVE:
UPDATE payment_provider_config
SET environment = 'PRODUCTION', status = 'ACTIVE',
credentials = JSON_SET(credentials,
'$.payUrl', 'https://pay.vnpay.vn/vpcpay.html',
'$.tmnCode', 'PROD_TMN_CODE',
'$.hashSecret', 'PROD_HASH_SECRET'
)
WHERE provider = 'VNPAY';
VNPAY_HASH_SECRET=your_vnpay_hash_secret
C. Xác nhận cấu hình thanh toán
-- Kiểm tra payment providers
SELECT name, provider, environment, status, priority
FROM payment_provider_config
ORDER BY priority;
-- Kiểm tra internal wallet
SELECT name, bankName, bankAccountNumber, bankCode,
isDepositWallet, status
FROM internal_wallet
WHERE isDepositWallet = 1;
-- Smoke test IPN endpoint (thay memo và amount thật)
curl -X POST https://goldvninvest.online/api/webhook/vietqr \
-H "Content-Type: application/json" \
-d '{"id":"TEST-001","amount":100000,"description":"GVN","bankCode":"VCB"}'
# Expected: {"success":true,"processed":{...}}
🪪 Bước 3.5 — eKYC C06 qua VNPT (ekyc.vnpt.vn)
C06 là gì? Cơ sở dữ liệu căn cước công dân Bộ Công An (CCCD). VNPT eKYC tích hợp tra cứu C06 giúp xác minh danh tính người dùng theo đúng quy định pháp lý Việt Nam. Endpoint: https://api.idg.vnpt.vn/
Bước 3.5.1 — Đăng ký & lấy token VNPT eKYC
1
Truy cập https://ekyc.vnpt.vn → Đăng nhập tài khoản doanh nghiệp (hoặc đăng ký mới)
2
Vào menu
Token Management → Tạo token mới → Copy 3 giá trị:
| Tham số | Mô tả | Dùng ở đâu |
TOKEN_KEY | API Key | Header token-key |
TOKEN_ID | Token ID | Header token-id |
AUTHORIZATION | Bearer token (bỏ chữ "Bearer") | Header Authorization: Bearer ... |
3
Gửi email yêu cầu whitelist domain production:
goldvninvest.online
Liên hệ:
https://ekyc.vnpt.vn/vi/contact
(Môi trường dev: chỉ cần localhost:4200 — không cần whitelist)
Bước 3.5.2 — Seed kyc_verification_service VNPT
Bảng kyc_verification_service hiện có 3 records (SumSub, DeepSeek, Gemini). Cần thêm VNPT-C06.
-- Thêm VNPT eKYC service (VNPT C06 — Căn cước công dân)
INSERT INTO kyc_verification_service
(id, name, description, type, integrationDetails, createdAt, updatedAt)
VALUES (
'vnpt-ekyc-1',
'VNPT eKYC — C06 Bộ Công An',
'Xác minh danh tính công dân Việt Nam qua cơ sở dữ liệu C06 Bộ Công An. Hỗ trợ CCCD gắn chip, ePassport, nhận diện khuôn mặt liveness.',
'VNPT_EKYC',
JSON_OBJECT(
'features', JSON_ARRAY(
'CCCD_CHIP',
'C06_LOOKUP',
'FACE_MATCHING',
'LIVENESS_CHECK',
'EPASSPORT'
),
'apiBase', 'https://api.idg.vnpt.vn',
'cdnBase', 'https://ekyc-web.vnpt.vn',
'sdkGuide', 'https://ekyc.vnpt.vn/vi/docs/web-sdk',
'tokenKey', 'THAY_BANG_TOKEN_KEY_THUC_TE',
'tokenId', 'THAY_BANG_TOKEN_ID_THUC_TE',
'authorization', 'THAY_BANG_ACCESS_TOKEN_THUC_TE'
),
NOW(), NOW()
);
-- Xác nhận
SELECT id, name, type FROM kyc_verification_service;
Bước 3.5.3 — Seed kyc_level cho VNPT
-- Level 1: Xác minh CCCD cơ bản (Rút dưới 50 triệu/ngày)
INSERT INTO kyc_level
(id, name, description, level, fields, features, status, serviceId, createdAt, updatedAt)
VALUES (
UUID(),
'KYC Level 1 — Xác minh CCCD',
'Xác minh Căn cước công dân qua VNPT eKYC. Cho phép nạp/rút tối đa 50 triệu VND/ngày.',
1,
JSON_ARRAY(
JSON_OBJECT('name', 'frontImage', 'title', 'Ảnh mặt trước CCCD', 'type', 'image', 'required', JSON_VALUE('true','$')),
JSON_OBJECT('name', 'backImage', 'title', 'Ảnh mặt sau CCCD', 'type', 'image', 'required', JSON_VALUE('true','$')),
JSON_OBJECT('name', 'selfieImage', 'title', 'Ảnh selfie nhận diện', 'type', 'image', 'required', JSON_VALUE('true','$'))
),
JSON_ARRAY('DEPOSIT', 'WITHDRAW', 'TRADE'),
'ACTIVE',
'vnpt-ekyc-1',
NOW(), NOW()
);
-- Level 2: Xác minh nâng cao (tra cứu C06 + liveness — Rút trên 50 triệu)
INSERT INTO kyc_level
(id, name, description, level, fields, features, status, serviceId, createdAt, updatedAt)
VALUES (
UUID(),
'KYC Level 2 — C06 + Liveness',
'Xác minh nâng cao: tra cứu C06 Bộ Công An + nhận diện khuôn mặt liveness. Không giới hạn giao dịch.',
2,
JSON_ARRAY(
JSON_OBJECT('name', 'frontImage', 'title', 'Ảnh mặt trước CCCD gắn chip', 'type', 'image'),
JSON_OBJECT('name', 'backImage', 'title', 'Ảnh mặt sau CCCD gắn chip', 'type', 'image'),
JSON_OBJECT('name', 'livenessVideo', 'title', 'Video liveness check', 'type', 'video'),
JSON_OBJECT('name', 'cccdNumber', 'title', 'Số CCCD/CMND', 'type', 'text')
),
JSON_ARRAY('DEPOSIT', 'WITHDRAW_UNLIMITED', 'TRADE', 'P2P', 'FUTURES'),
'ACTIVE',
'vnpt-ekyc-1',
NOW(), NOW()
);
-- Xác nhận
SELECT id, name, level, status, serviceId FROM kyc_level;
Bước 3.5.4 — Cập nhật .env với VNPT credentials
# --------------- VNPT eKYC (C06 Bộ Công An) ---------------
VNPT_EKYC_TOKEN_KEY=your_token_key_from_ekyc.vnpt.vn
VNPT_EKYC_TOKEN_ID=your_token_id_from_ekyc.vnpt.vn
VNPT_EKYC_AUTHORIZATION=your_access_token_no_bearer_prefix
VNPT_EKYC_API_BASE=https://api.idg.vnpt.vn
VNPT_EKYC_CDN=https://ekyc-web.vnpt.vn
Bước 3.5.5 — Thêm handler VNPT vào check-connection.get.js
File backend/dist/src/api/admin/crm/kyc/service/[id]/check-connection.get.js hiện chỉ handle sumsub, gemini, deepseek. Cần thêm branch cho vnpt-ekyc.
// Thêm vào hàm default export, sau block `else if (id.startsWith("deepseek"))`:
else if (id.startsWith("vnpt")) {
result = await checkVnptEkycConnection();
}
// Thêm hàm checkVnptEkycConnection() vào cuối file:
async function checkVnptEkycConnection() {
const tokenKey = process.env.VNPT_EKYC_TOKEN_KEY;
const tokenId = process.env.VNPT_EKYC_TOKEN_ID;
const auth = process.env.VNPT_EKYC_AUTHORIZATION;
if (!tokenKey || !tokenId || !auth) {
return { connected: false,
message: "Missing VNPT_EKYC_TOKEN_KEY / TOKEN_ID / AUTHORIZATION in .env" };
}
try {
const resp = await fetch(
`https://api.idg.vnpt.vn/ai/v1/server-info`,
{ method: "GET", headers: {
"token-key": tokenKey,
"token-id": tokenId,
"Authorization": `Bearer ${auth}`,
"Content-Type": "application/json"
}
}
);
if (resp.ok) return { connected: true, message: "VNPT eKYC API reachable" };
return { connected: false, message: `VNPT eKYC: HTTP ${resp.status}` };
} catch(e) {
return { connected: false, message: `VNPT eKYC error: ${e.message}` };
}
}
Bước 3.5.6 — Seed staking_pools (còn thiếu)
INSERT INTO staking_pools
(id, name, token, symbol, description, walletType,
apr, lockPeriod, minStake, maxStake, availableToStake,
earlyWithdrawalFee, adminFeePercentage, status, isPromoted,
\`order\`, earningFrequency, autoCompound, externalPoolUrl,
profitSource, fundAllocation, risks, rewards, createdAt, updatedAt)
VALUES
(UUID(), 'USDT Flexible Savings', 'Tether USD', 'USDT',
'Gửi USDT linh hoạt, nhận lãi hàng ngày, rút bất kỳ lúc nào.', 'SPOT',
0.08, 0, 10, NULL, 1000000, 0, 2,
'ACTIVE', 1, 1, 'DAILY', 0, NULL,
'Market Making nội bộ', '70% thanh khoản, 30% dự trữ',
'Rủi ro thị trường thấp', 'APR 8%, rút bất kỳ lúc nào',
NOW(), NOW()),
(UUID(), 'USDT 30-Day Lock', 'Tether USD', 'USDT',
'Khoá USDT 30 ngày, nhận APR 12%.', 'SPOT',
0.12, 30, 50, 100000, 500000, 5, 2,
'ACTIVE', 1, 2, 'MONTHLY', 1, NULL,
'Lending + arbitrage', '60% lending, 40% hedge',
'Không rút trước 30 ngày (phạt 5%)', 'APR 12%, tự động tái tục',
NOW(), NOW()),
(UUID(), 'GIV Loyalty Pool', 'GIV Token', 'GIV',
'Pool đặc biệt cho GIV holder. APR 20%, nhận lãi hàng tuần.', 'ECO',
0.20, 30, 1000, NULL, 0, 5, 1,
'COMING_SOON', 1, 3, 'WEEKLY', 1, NULL,
'Phí platform chia sẻ cho GIV holder', '100% phí giao dịch',
'GIV là token nội bộ', 'APR 20%, nhận GIV hàng tuần',
NOW(), NOW());
-- Xác nhận
SELECT name, symbol, apr, lockPeriod, status FROM staking_pools;
✅ Checklist Cuối — Phase 3 Complete
| # | Hạng mục | Lệnh xác nhận | Expected |
| 1 | internal_wallet bảng tồn tại | SHOW TABLES LIKE 'internal_wallet' | 1 row |
| 2 | payment_provider_config tồn tại | SHOW TABLES LIKE 'payment_provider_config' | 1 row |
| 3 | Bank account đã điền | SELECT COUNT(*) FROM internal_wallet WHERE isDepositWallet=1 | ≥ 1 |
| 4 | VietQR provider ACTIVE | SELECT status FROM payment_provider_config WHERE provider='VIETQR' | ACTIVE |
| 5 | kyc_level seeded | SELECT COUNT(*) FROM kyc_level | ≥ 2 |
| 6 | VNPT eKYC service thêm | SELECT id FROM kyc_verification_service WHERE id='vnpt-ekyc-1' | 1 row |
| 7 | staking_pools có data | SELECT COUNT(*) FROM staking_pools WHERE status='ACTIVE' | ≥ 2 |
| 8 | Admin login OK | curl https://goldvninvest.online/api/settings | jq '.total' | 149 |
| 9 | VietQR IPN test | curl POST /api/webhook/vietqr | {"success":true} |
| 10 | VNPT eKYC test connection | Admin → KYC Services → Test Connection | Connected ✅ |
| 11 | BANK_ACCOUNT_NUMBER .env | grep BANK_ACCOUNT_NUMBER .env | Không còn trống |
| 12 | VIETQR_WEBHOOK_SECRET .env | grep VIETQR_WEBHOOK_SECRET .env | Không còn trống |
Lệnh reload sau tất cả thay đổi
# 1. Restart backend để model nhận bảng mới + .env mới
pm2 restart backend --update-env
# 2. Warm Redis cache với data mới
node scripts/redis-seed-cache.js --force
# 3. Kiểm tra logs không có lỗi mới
pm2 logs backend --lines 100 | grep -E "ERROR|WARN|CRIT"
# 4. Smoke test
curl https://goldvninvest.online/api/health
curl https://goldvninvest.online/api/settings | jq '.total' # Expected: 149
curl https://goldvninvest.online/api/binary/market | jq '.total' # Expected: 7
✅ Sau Phase 3: Hệ thống sẵn sàng nhận nạp VNL qua VietQR tự động, xác minh KYC qua VNPT C06, Admin panel đầy đủ quyền. Bước tiếp theo: smoke test end-to-end (nạp tiền thật → nhận VNL → staking → rút).