A withdrawal is a state machine, not a button

The interface should expose enough of this state to set expectations. “Pending” is acceptable for a short period; a permanent pending state without a reason or support route is not. The operator needs more detail than the user, including asset, destination, request identifier, attempts and final reference.

StateWhat it meansWhat must not happen
AvailableBalance can be requested under current rulesNo transfer has been promised yet
RequestedChecks passed and one queue item existsA repeated tap must not create another request
Review or queuedRequest awaits an operator or workerBalance cannot be spent twice
BroadcastA transfer was submittedDo not retry until chain status is known
PaidThe transfer is finalized and traceableDo not refund the debit
Failed and refundedNo payment completed and balance was restored onceDo not run a second refund

Name the asset before choosing automatic payout

Native TON, a Jetton, a project point and a manually distributed campaign token are different assets. They use different transfer formats, fee assumptions and operational controls. A generic amount field is dangerous when one worker could interpret every pending request as a native transfer.

Store the asset and payout mode on each request. Let the automatic worker select only supported automatic assets. Route manual project-token requests to an owner inbox where the operator can attach a transaction reference or deny and refund with a reason. Do not silently substitute one asset for another.

Reserve the balance atomically

When a valid request is created, reserve or debit the amount in the same transaction that inserts the queue record. If those actions are separate, two rapid requests can both see the old balance and spend it. Use a unique request key derived from the user action or generated server-side, then reject a repeated confirmation.

The ledger should preserve the reason for the debit. A failed request restores that exact debit through one refund event. Operators should not edit the total balance manually to “fix” a payout, because that destroys the audit trail and can hide a duplicate transfer.

  • Atomic request and debit
  • Unique request key
  • Explicit asset
  • Explicit payout mode
  • Original ledger reference
  • One refund reference
  • Immutable final state

Validate destinations without pretending to own them

Validate that the destination is a syntactically acceptable address for the selected asset and network before queueing. Normalize formats where the official tooling supports it. Do not claim that format validation proves the user controls the wallet or that a custodial destination will accept every memo or token.

For a high-value or first withdrawal, a confirmation screen can show the normalized destination, asset, amount, estimated fee behavior and warning that blockchain transfers may be irreversible. Never ask users to reveal a seed phrase or private key.

  • Network and asset named
  • Address normalized
  • Memo or comment rule stated
  • Minimum and fee treatment visible
  • Irreversibility warning
  • No private-key collection

Fund the queue, not just the marketing balance

Compare the project wallet reserve with available user liability and already pending requests. A campaign may look funded while most value remains in unqualified points; the risk changes when those points become withdrawable. Alert before the automatic reserve falls below pending obligations.

Keep operational funds separate from estimates of future advertising or acquisition revenue. If the reserve is insufficient, stop creating new funded rewards or enter a disclosed maintenance state. Do not let the queue repeatedly fail and charge users through lost balances or hidden conditions.

Working formulaCoverage ratio = liquid payout reserve ÷ (available withdrawable balances + pending requests)

Design automatic and manual paths deliberately

ModeUse whenRequired owner control
Automatic native payoutThe platform supports the asset and project wallet is fundedLimits, reserve alerts, pause switch and key security
Automatic Jetton payoutA dedicated Jetton-aware implementation is testedCorrect master and wallet validation, decimals and fee reserve
Manual project-token payoutThe owner distributes an external asset outside the native workerReview inbox, proof reference, deny and refund actions
Campaign allocation onlyNo transfer is currently promisedDo not label points as withdrawable

Prepare for the five incidents that will happen

  1. Insufficient wallet funds

    Pause automatic dispatch, preserve requests and alert the owner.

  2. Ambiguous network response

    Check chain state before retrying.

  3. Wrong or unsupported asset

    Block before queueing and never substitute automatically.

  4. Compromised signing path

    Disable payouts, rotate credentials and retain the ledger for reconciliation.

  5. Duplicate callback or worker retry

    Idempotency returns the original request instead of paying again.

Run reconciliation as an operating habit

At a regular interval, compare opening reserve, deposits, confirmed outgoing transfers, fees and closing reserve. Separately reconcile user ledger debits with paid requests and refunds. A small unexplained difference is an incident, not rounding to ignore.

Monitor queue age, success rate, failures by reason, refunds, repeated destinations and coverage ratio. Publish expected processing behavior for users, and notify them through the bot when a material outage changes it. Reliable withdrawals are a product feature and a trust system.

Common questions

Can a Telegram Mini App send withdrawals automatically?

Yes, when the backend supports the exact asset, the project wallet is funded and signing, limits and queue controls are configured. The Mini App interface itself should not hold private keys.

Are native TON and Jetton withdrawals the same?

No. Jettons have their own master and wallet contracts, decimals and transfer flow. Never send a project-token amount through a native-asset worker.

What should happen when a withdrawal fails?

If no transfer completed, restore the reserved or debited user balance exactly once and mark the request with a final failure reason.

Should users pay a deposit to unlock withdrawal?

Only if it is a genuine, lawful and clearly disclosed product rule. Adding an unexpected deposit demand after rewards are earned is deceptive and should not be used as a payout control.

Sources and further reading

Technical and product claims were checked against these primary sources.