Skip to content

Latest commit

ย 

History

History
280 lines (210 loc) ยท 8.05 KB

File metadata and controls

280 lines (210 loc) ยท 8.05 KB

Internal Transfer E2E Testing Guide

ๆฆ‚่ฟฐ / Overview

ๆœฌๆ–‡ๆกฃๆ่ฟฐไบ† Phase 0x0B-a ๅ†…้ƒจ่ฝฌ่ดฆๅŠŸ่ƒฝ็š„ๅฎŒๆˆๅทฅไฝœใ€ๅฎž็Žฐ็ป†่Š‚ๅ’Œ็ซฏๅˆฐ็ซฏๆต‹่ฏ•ๆ–นๆณ•ใ€‚

This document describes the completed work, implementation details, and end-to-end testing methodology for Phase 0x0B-a Internal Transfer feature.


ๆœฌ็ซ ๅฎŒๆˆๅทฅไฝœ / Chapter Deliverables

ๆžถๆž„ๅฎž็Žฐ / Architecture Implementation

ๅฎž็Žฐไบ†่ทจ็ณป็ปŸ่ต„้‡‘ๅˆ’่ฝฌ็š„ 2-Phase Commit FSM:

                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚  TransferAPI    โ”‚  Gateway ๅฑ‚
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚ TransferCoord.  โ”‚  FSM ๅ่ฐƒๅ™จ
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
           โ”‚                  โ”‚                  โ”‚
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚ FundingAdapter  โ”‚ โ”‚ TradingAdapterโ”‚ โ”‚  TransferDb   โ”‚
  โ”‚   (PostgreSQL)  โ”‚ โ”‚  (UBSCore)    โ”‚ โ”‚  (FSM State)  โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

ๆ ธๅฟƒๆจกๅ— / Core Modules

ๆจกๅ— / Module ๆ–‡ไปถ / File ๅŠŸ่ƒฝ / Function
TransferCoordinator src/transfer/coordinator.rs FSM ็Šถๆ€ๆœบ้ฉฑๅŠจ
State machine driver
FundingAdapter src/transfer/adapters/funding.rs PostgreSQL ่ต„้‡‘ๆ“ไฝœ
PostgreSQL balance ops
TradingAdapter src/transfer/adapters/trading.rs UBSCore ้€š้“้€šไฟก
UBSCore channel comm
TransferDb src/transfer/db.rs FSM ็Šถๆ€ๆŒไน…ๅŒ–
FSM state persistence
TransferChannel src/transfer/channel.rs ่ทจ็บฟ็จ‹้€šไฟก
Cross-thread messaging

ๆ–ฐๅขž API / New APIs

Endpoint Method ๆ่ฟฐ / Description
/api/v1/private/transfer POST ๅˆ›ๅปบๅ†…้ƒจ่ฝฌ่ดฆ
/api/v1/private/transfer/{req_id} GET ๆŸฅ่ฏข่ฝฌ่ดฆ็Šถๆ€
/api/v1/private/balances/all GET ๆŸฅ่ฏขๆ‰€ๆœ‰่ดฆๆˆทไฝ™้ข

ๆ•ฐๆฎๅบ“่กจ / Database Tables

่กจ / Table ็”จ้€” / Purpose
fsm_transfers_tb FSM ่ฝฌ่ดฆ็Šถๆ€่ฎฐๅฝ•
transfer_operations_tb ๅน‚็ญ‰ๆ“ไฝœ่ฟฝ่ธช
balances_tb ่ดฆๆˆทไฝ™้ข (Funding/Spot)

ไบคไป˜็‰ฉ / Deliverables

  • โœ… ๅฎŒๆ•ด็š„ FSM ๅฎž็Žฐ (Init โ†’ SourcePending โ†’ SourceDone โ†’ TargetPending โ†’ Committed)
  • โœ… ๅŒๅ‘่ฝฌ่ดฆ้ชŒ่ฏ (Funding โ†” Spot)
  • โœ… ๅฏๅค็”จ E2E ๆต‹่ฏ•่„šๆœฌ
  • โœ… /balances/all ไฝ™้ขๆŸฅ่ฏข API
  • โœ… 232 ไธชๅ•ๅ…ƒๆต‹่ฏ•้€š่ฟ‡

ๆต‹่ฏ•่„šๆœฌ / Test Script

่‡ชๅŠจๅŒ– E2E ๆต‹่ฏ• / Automated E2E Test

# ่ฟ่กŒๅฎŒๆ•ด E2E ๆต‹่ฏ• (่‡ชๅŠจๅฏๅŠจ Gateway)
./scripts/test_transfer_e2e.sh

่„šๆœฌไฝ็ฝฎ: scripts/test_transfer_e2e.sh

ๆต‹่ฏ•ๆต็จ‹ / Test Flow

[1/6] Prerequisites Check
    โœ“ PostgreSQL connected (port 5433)
    โœ“ Release binary ready

[2/6] Setup Test Data
    - Enable CAN_INTERNAL_TRANSFER for USDT
    - Create 1000 USDT in Funding for user 1001
    - Clear previous transfer records

[3/6] Start Gateway
    - Stop existing Gateway (pgrep + kill)
    - Start new Gateway with updated config
    - Wait for health check

[4/6] Run Transfer Tests
    - Funding โ†’ Spot (50 USDT)
    - Spot โ†’ Funding (25 USDT)
    - Verify both COMMITTED

[5/6] Verify Balance Changes
    - Check Funding: 1000 โ†’ 975 (ฮ”-25)
    - Use /balances/all API

[6/6] Cleanup
    - Stop Gateway

API ๆต‹่ฏ• / API Testing

ไฝฟ็”จ Python ๅฎขๆˆท็ซฏ / Using Python Client

import sys
sys.path.append('scripts/lib')
from api_auth import get_test_client

USER_ID = 1001
client = get_test_client(user_id=USER_ID)
headers = {'X-User-ID': str(USER_ID)}

# 1. ๆŸฅ่ฏขไฝ™้ข / Query balances
resp = client.get('/api/v1/private/balances/all', headers=headers)
print(resp.json())

# 2. ๅ‘่ตท่ฝฌ่ดฆ / Create transfer
resp = client.post('/api/v1/private/transfer',
    json_body={
        'from': 'funding',
        'to': 'spot',
        'asset': 'USDT',
        'amount': '50'
    },
    headers=headers)
print(resp.json())

# 3. ๆŸฅ่ฏข่ฝฌ่ดฆ็Šถๆ€ / Query transfer status
req_id = resp.json()['data']['req_id']
resp = client.get(f'/api/v1/private/transfer/{req_id}', headers=headers)
print(resp.json())

ไฝฟ็”จ curl / Using curl

# ๆŸฅ่ฏขไฝ™้ข (้œ€่ฆๆญฃ็กฎ็ญพๅ)
curl http://localhost:8080/api/v1/private/balances/all \
  -H "X-API-Key: AK_0000000000001001" \
  -H "X-Signature: ..." \
  -H "X-User-ID: 1001"

ๆ•ฐๆฎๅบ“้ชŒ่ฏ / Database Verification

ๆฃ€ๆŸฅไฝ™้ข / Check Balances

PGPASSWORD=trading123 psql -h localhost -p 5433 -U trading -d exchange_info_db -c "
SELECT 
    CASE account_type WHEN 1 THEN 'Spot' WHEN 2 THEN 'Funding' END as account,
    (available / 1000000)::text || ' USDT' as balance
FROM balances_tb 
WHERE user_id = 1001 AND asset_id = 2
ORDER BY account_type;
"

ๆฃ€ๆŸฅ FSM ็Šถๆ€ / Check FSM State

PGPASSWORD=trading123 psql -h localhost -p 5433 -U trading -d exchange_info_db -c "
SELECT req_id, amount, state, created_at 
FROM fsm_transfers_tb 
WHERE user_id = 1001
ORDER BY created_at DESC LIMIT 5;
"

State ๅ€ผๅซไน‰ / State Values:

  • 0: INIT
  • 10: SOURCE_PENDING
  • 20: SOURCE_DONE
  • 30: TARGET_PENDING
  • 40: COMMITTED โœ…
  • -10: FAILED
  • -20: COMPENSATING
  • -30: ROLLED_BACK

ๅทฒไฟฎๅค็š„ Bug / Fixed Bugs

1. FSM ๆœชๆ‰ง่กŒ / FSM Not Executing

้—ฎ้ข˜: create_transfer_fsm ๅช่ฐƒ็”จ coordinator.create()๏ผŒๆฒกๆœ‰่ฐƒ็”จ coordinator.execute()

ไฟฎๅค: ๆทปๅŠ  execute() ่ฐƒ็”จ

// src/transfer/api.rs
let req_id = coordinator.create(core_req).await?;
let state = coordinator.execute(req_id).await?; // โ† Added

2. ้‡‘้ข่งฃๆžไธบ 0 / Amount Parsed as 0

้—ฎ้ข˜: Decimal.to_string().parse::<u64>() ๅฏน "50000000.00000000" ่ฟ”ๅ›žๅคฑ่ดฅ

ไฟฎๅค: ไฝฟ็”จ trunc().to_i64()

// src/transfer/db.rs
let amount_u64 = amount.trunc().to_i64().unwrap_or(0) as u64;

3. ็ฑปๅž‹ไธๅŒน้… / Type Mismatch

  • status ๅˆ—: INT4 (i32), ไธๆ˜ฏ INT2
  • decimals ๅˆ—: INT2 (i16), ไธๆ˜ฏ i32

ๆต‹่ฏ•็ป“ๆžœ็คบไพ‹ / Sample Test Output

==============================================
Internal Transfer E2E Test (Phase 0x0B-a)
==============================================

[1/6] Checking prerequisites...
  โœ“ PostgreSQL connected
  โœ“ Release binary ready
[2/6] Setting up test data...
  โœ“ Test data initialized (1000 USDT in Funding only for user 1001)
[3/6] Starting Gateway...
  โœ“ Gateway ready
[4/6] Running transfer tests with balance verification...
  [BEFORE] Getting initial balances...
    USDT:funding: 1000.00

  [TRANSFER 1] Funding โ†’ Spot (50 USDT)...
    โœ“ COMMITTED
  [TRANSFER 2] Spot โ†’ Funding (25 USDT)...
    โœ“ COMMITTED

  [AFTER] Getting final Funding balance...
    USDT:funding: 975.00

  [VERIFY] Checking Funding balance changes...
    โœ“ Funding: 1000.00 โ†’ 975.00 (ฮ”-25.00)

  Results: 3 passed, 0 failed
[5/6] Final database state...
 Funding | 975.0000000000000000 USDT

[6/6] Cleanup...

==============================================
โœ… All E2E Transfer Tests PASSED
==============================================

็›ธๅ…ณๆ–‡ไปถ / Related Files

ๆ–‡ไปถ / File ๆ่ฟฐ / Description
scripts/test_transfer_e2e.sh E2E ๆต‹่ฏ•่„šๆœฌ
scripts/lib/api_auth.py API ่ฎค่ฏๅบ“
src/transfer/api.rs ่ฝฌ่ดฆ API ๅค„็†
src/transfer/coordinator.rs FSM ๅ่ฐƒๅ™จ
src/transfer/adapters/funding.rs Funding ้€‚้…ๅ™จ
src/transfer/adapters/trading.rs Trading ้€‚้…ๅ™จ