Andamio Logo
Protocol/Protocol V2/Transaction State Machine

Transaction State Machine

How Andamio tracks every Cardano transaction from build to database synchronization

Transaction State Machine

How Andamio tracks every transaction from build to database synchronization — the lifecycle, states, monitoring, and integration patterns.

Looking for individual transaction specs? The V2 Transactions section has detailed technical reference for each transaction type — inputs, outputs, costs, and datums.

Every Andamio blockchain transaction follows a consistent 6-step lifecycle, managed automatically by the API Gateway.

Lifecycle

StepWhoWhat Happens
BUILDAPI GatewayBuilds an unsigned transaction (CBOR)
SIGNUser's walletUser signs the transaction in their browser wallet
SUBMITUser's walletSigned transaction is submitted to the Cardano network
REGISTERFrontendCalls the registration endpoint with the transaction hash and type
CONFIRMGateway (automatic)Polls the blockchain until the transaction appears on-chain
UPDATEGateway (automatic)Syncs the confirmed on-chain data to the Andamio database

State Transitions

Once a transaction is registered, it enters the state machine and transitions automatically:

StateMeaning
pendingSubmitted to Cardano, awaiting on-chain confirmation
confirmedFound on-chain, database update in progress (or not needed)
updatedDatabase synchronized — terminal success
failedDatabase sync retries exhausted — terminal failure
expiredNot confirmed on-chain within the timeout window — terminal

All database updates are idempotent — if a sync is interrupted and retried, it produces the same result.

Transaction Types

Andamio supports 17 transaction types across three categories:

Global

TransactionType KeyRoleDB Sync
Mint Access Tokenaccess_token_mintUserNo

Course

TransactionType KeyRoleDB Sync
Create Coursecourse_createOwnerYes
Enroll in Coursecourse_enrollStudentNo
Manage Teachersteachers_updateOwnerYes
Manage Modulesmodules_manageTeacherYes
Submit Assignmentassignment_submitStudentYes
Assess Assignmentsassessment_assessTeacherYes
Claim Course Credentialcredential_claimStudentNo

Project

TransactionType KeyRoleDB Sync
Create Projectproject_createOwnerYes
Manage Managersmanagers_manageOwnerYes
Manage Blacklistblacklist_updateOwnerNo
Manage Taskstasks_manageManagerYes
Commit to Taskproject_joinContributorYes
Submit Task Worktask_submitContributorYes
Assess Taskstask_assessManagerYes
Claim Project Credentialproject_credential_claimContributorYes
Fund Treasurytreasury_fundUserNo

"No" DB Sync means the blockchain is the sole source of truth for that data. "Yes" DB Sync means the Gateway automatically synchronizes on-chain state to the database after confirmation.

TX Type Mapping

Some build endpoints share the same state machine type. This is intentional — the on-chain action is identical, so Andamioscan indexes them the same way.

Course Assignments

Build EndpointTX TypeNotes
/tx/course/student/assignment/commitassignment_submitFirst commitment to a module
/tx/course/student/assignment/updateassignment_submitUpdate evidence on existing commitment

Both use assignment_submit because the on-chain action is the same: spending and recreating the enrollment UTxO with updated assignment info. The state machine's upsert behavior handles both cases correctly.

Project Tasks

Build EndpointTX TypeNotes
/tx/project/contributor/task/commit (first time)project_joinMints contributor token
/tx/project/contributor/task/commit (repeat)project_joinNo mint for existing contributors

The state machine tries the "join" classifier first, then falls back to "task submit" for already-enrolled contributors. From the API consumer's perspective, use project_join for all task commits.

See also: API Integration Guide for the complete endpoint-to-type mapping table.

Integration Flow

The full flow for building, signing, and tracking a transaction:

1. POST /api/v2/tx/{build-endpoint}         → unsigned_tx (+ course_id/project_id for creates)
2. wallet.signTx(unsigned_tx)                → signed_tx
3. wallet.submitTx(signed_tx)                → tx_hash
4. POST /api/v2/tx/register                  → { state: "pending" }
5. GET  /api/v2/tx/stream/{tx_hash}   (SSE)  → real-time state change events
   OR
   GET  /api/v2/tx/status/{tx_hash}  (poll)  → check state periodically

All build endpoints require authentication via Authorization: Bearer <jwt> or X-API-Key: <key>.

Registration

After submitting a transaction to the Cardano network, register it with the state machine:

POST /api/v2/tx/register

{
  "tx_hash": "64-char hex hash from wallet.submitTx()",
  "tx_type": "course_create",
  "instance_id": "optional course_id or project_id",
  "metadata": {}
}

Most transaction types require no metadata. Only three types need it:

TypeRequired Metadata
course_createowner_alias (auto-captured, no action needed)
project_jointask_hash (required — 64 hex chars)
project_credential_claimtask_hash (required — 64 hex chars)

Registering the same tx_hash twice returns 409 Conflict.

Commitment Lifecycle

Several transaction types involve commitments — records that link a participant to a piece of work (an assignment or a task). These commitments follow a draft-to-chain lifecycle that gives developers two integration paths.

Two Paths to On-Chain

Draft-first is recommended because it gives users immediate feedback — they can see their pending commitment in the UI before the blockchain transaction confirms. But if a client goes straight to chain (skipping the draft step), the state machine handles it automatically by creating the DB record on confirmation.

Assignment Commitments (Courses)

When a student submits an assignment (assignment_submit):

  1. Optional: Create a draft commitment via the API — the student's intent is saved immediately
  2. Required: Build and submit the on-chain transaction, then register it
  3. Automatic: On confirmation, the state machine either updates the existing draft or creates a new record, setting the status to ON_CHAIN

Status progression: DRAFTON_CHAINACCEPTED or REFUSED (after teacher assessment)

Task Commitments (Projects)

When a contributor commits to a task (project_join):

  1. Optional: Create a draft commitment via the API
  2. Required: Build and submit the on-chain transaction, then register with task_hash in metadata
  3. Automatic: On confirmation, the state machine confirms the commitment and links the contributor to the task

Status progression: DRAFTCOMMITTEDSUBMITTEDACCEPTED or REFUSEDREWARDED

Note: A contributor's first commit to a project also "joins" the project by minting a contributor token. Subsequent commits by the same contributor do not mint again. The state machine handles both cases transparently.

Task Drafts

Managers can also create tasks as drafts in the database before publishing them on-chain via tasks_manage. When the on-chain transaction confirms, the state machine automatically matches new on-chain tasks to existing drafts by content hash and updates their status to ON_CHAIN.

Monitoring

EndpointPurpose
GET /api/v2/tx/status/:tx_hashCurrent state of a single transaction
GET /api/v2/tx/pendingAll tracked transactions for the authenticated user
GET /api/v2/tx/typesList all valid transaction types
GET /api/v2/tx/stream/:tx_hashSSE stream — real-time state change events

SSE Stream Events

EventWhenPayload
stateImmediately on connectCurrent state
state_changeEach transition{ tx_hash, old_state, new_state, timestamp }
completeTerminal state reached{ tx_hash, final_state } — stream auto-closes

Self-Healing

If a transaction is confirmed on-chain but the database update was missed (for example, due to a service restart), the Gateway automatically detects and repairs the inconsistency when related data is next accessed. This is transparent to API consumers — no manual intervention is needed.

Important Notes

  • Course and project creation return IDs: The build response includes a course_id or project_id. Save these — they're the on-chain policy IDs used for all subsequent operations.
  • Single teacher/manager at creation: Courses start with one teacher and projects start with one manager (the creator). Use the manage endpoints to add more after creation.
  • Not yet implemented: Task Leave and Task Update sub-actions have build endpoints but are not yet tracked by the state machine. The on-chain effects still work.