Transaction flow (Deposits & Withdrawals)

This doc explains how transaction status fields are used in HollaEx.

Concepts and balances

HollaEx effectively treats funds in a few “buckets”:

  • Available balance: spendable/tradable/withdrawable (depending on your rules).

  • Locked amount: reserved so the user can’t double-spend while a withdrawal is pending.

  • Final balance deduction: when the withdrawal is confirmed/settled.

Withdrawals typically move funds like:

Available → Locked → Deducted (final)


Deposits: what fields do

Deposit status

  • status: falsedoes nothing (no balance change).

  • status: trueadds balance (credits user funds).

Other deposit fields

Other fields may exist on the deposit record, but do not trigger special behavior by default. They are still useful as:

  • metadata for audits,

  • integration-specific routing,

  • custom flow extensions in a plugin.


Withdrawals: lifecycle and field meanings

A withdrawal record contains flags like:

Core behavior at creation time

When a withdrawal is created:

  • It deducts from available immediately

  • and locks the amount (reserves it).

So the user can’t use the same funds again while the withdrawal is pending.


What each withdrawal field means

status (finalization switch)

  • status: false → withdrawal is not finalized.

  • status: true → withdrawal is finalized and the system deducts the balance (i.e., completes the accounting outcome).

In other words:

  • Creation locks funds.

  • status=true completes the “final deduction” step.

rejected and dismissed (unlock paths when not finalized)

If status: false and either:

  • rejected: true, or

  • dismissed: true

then the system should unlock the locked funds (release them back to available), because the withdrawal won’t be finalized.

“Updating rejected or dismissed to true when status is false will unlock the locked balance.”

dismissed is generally used when admin dismissed the transaction and rejected is used when the system rejects the transaction.

processing and waiting (worker/cron safety flags)

  • They do not change balances

  • They exist to prevent race conditions (e.g., cron job double-picking the same withdrawal)

  • They can be used however you want as “in-progress” markers.

Typical intention:

  • processing: true → a worker has claimed it and is actively handling it now.

  • waiting: true → it’s queued/backing off/awaiting external confirmation (or simply “don’t pick me again yet”).

onhold (manual pause / admin gate)

  • Does not directly change balances by itself.

  • Used to prevent automated processing until an admin clears it.

  • Practically: if onhold: true, the cron/plugin should skip it.


Withdrawal state transitions

1) New withdrawal (eligible for processing)

  • Funds: Available decreases, Locked increases

  • Flags commonly look like:

    • status=false

    • processing=false

    • waiting=false

    • onhold=false

    • rejected=false

    • dismissed=false

2) Claimed by cron/plugin

  • Funds: unchanged

  • Flags:

    • set processing=true (or waiting=true depending on your approach)

3) Success path (completed)

  • Set status=true

  • Funds: final deduction happens (the withdrawal is accounted as completed)

4) Failure path (not completed, funds returned)

  • Keep status=false

  • Set rejected=true or dismissed=true

  • Funds: locked amount is unlocked back to available


Retry behavior: “Resend withdrawal”

When you click Resend withdrawal:

  • it sets all values to false,

  • so the withdrawal returns to the “fresh / eligible” state,

  • and it will re-enter the plugin cron processing flow.

So it effectively:

  • clears processing, waiting, onhold, rejected, dismissed, and keeps status=false,

  • making it pickable again by the worker.

This is a “reset and retry” mechanism.


Admin console: validation + retry logic

Even without code-level specifics, the admin console typically implements guardrails like:

Validation (what should be checked before processing)

Common checks before a worker/admin action finalizes:

  • Withdrawal still exists and is consistent (amount, asset, destination).

  • Sufficient locked amount exists (i.e., it was reserved).

  • Not already finalized (status !== true).

  • Not blocked by flags (e.g., onhold === true, or processing === true depending on the action).

Retry logic (what “resend” achieves)

  • Clears flags that prevent picking (processing/waiting/onhold)

  • Leaves it in a clean status=false state for cron/plugin to attempt again

Preventing double processing (race condition control)

The reason processing/waiting exist is to ensure:

  • two cron runs don’t send the same withdrawal twice,

  • an admin action doesn’t collide with a worker action.


Practical “rules of thumb”

  • Deposits: only status=true credits balance. status=false does nothing.

  • Withdrawals:

    • Creation: locks funds (reduces available, increases locked).

    • status=true: finalizes and deducts balance.

    • status=false + (rejected=true or dismissed=true): unlocks funds.

    • processing/waiting: no balance effects, just worker flags.

    • onhold: pause flag (usually skip in cron).

  • Resend withdrawal: sets everything to false → makes it eligible for cron/plugin again.

Last updated