Transaction State Machine

Real PassimPay statuses → mapping to Unified Interface

Phase 1
Infrastructure
1.

State Diagram

Happy Path

Address requested
Initiated
Address shown to player
Awaiting payment
Processing
BTC/LTC/DOGE: confirmations=1
Blockchain pending
Processing
confirmations=2 (or immediately for EVM/TRX)
Confirmed
Completed

Alternative Paths

No callback
Timed out
TTL expired (H2H)
Partial waiting
Pending partial
Invoice: partial payment → invoice expired
Expired / error
Failed

Additional Information

Click any state for details

H2H (Host-to-Host)

Callback ONLY on successful deposit.
No callback = no payment.
Player pays any amount.
Use amountReceive for crediting

Invoice (Redirect)

Fixed amount.
Status waiting = partial payment
Status error = expired or partial fail
Supports split payment (USDT + BTC).
2.

What is State Machine and who needs states

State Machine is not a UI component and not a settings table. It is rules in code about which state a transaction can transition to and on which event. Lives on the backend.

Where states come from

States are defined in code as constants -- a set of strings (INITIATED, PROCESSING, COMPLETED, etc.) plus a table of allowed transitions: from which state to which, and on which event (PSP webhook, TTL job, manual operator action). This page is documentation of that logic, so that all three parties (product, developer, PSP) speak the same language.

Who sees states and in what form

PartyWhat they seeSource
Player (frontend)Simplified status: "Waiting for payment", "Credited", "Error"GET /payments/:id/status → UnifiedStatus → frontend maps to human-readable
Back office / opsFull UnifiedStatus + transition history from transaction_eventsDB query or internal dashboard (Phase 4)
DeveloperRaw states in DB + full log in transaction_eventsDirect DB access or logs
PSP (PassimPay)Their own statuses (approved, rejected, etc.)Webhook that PSP sends to us

A webhook from the PSP arrives with a PSP-status (passimpay: approved) → State Machine maps it to UnifiedStatus (COMPLETED) → updates transactions.status → writes an event to transaction_events.

Why the UnifiedStatus layer exists

If PSP #2 is connected tomorrow, it will have its own statuses (paid, declined, hold). The frontend, back office and business logic keep working with the same COMPLETED / FAILED -- nothing changes. The PSP #2 adapter simply maps its statuses to UnifiedStatus.

Practically -- what needs to be done

1
Developer
Phase 1--2

Implement stateMachine.transition(txId, newStatus, payload) that: verifies the transition is allowed → updates transactions.status → writes a record to transaction_events. Called from Orchestrator, Cascade Manager, webhook handler, and TTL job.

2
Back office (Phase 4)
Phase 4

Show the full log from transaction_events -- every transition is visible with timestamp and reason.

3
Frontend
Phase 2

Map UnifiedStatus to player-facing text. PENDING_CONFIRMATION → "Awaiting network confirmation". COMPLETED → "Credited".

DEPO44 | PASSIMPAY ADAPTER | PHASE 0 | DRAFT -- REQUIRES VERIFICATION AGAINST DOCUMENTATION