Skip to main content

Code & Invoice Transfers

Besides the instant Internal Transfer, TrexWallet supports code-based transfers: the sender (or recipient) creates a transfer code, hands it to the counterparty out of band, and the counterparty redeems it. There are four variants, formed by two orthogonal choices:

  • Who initiates — the payer (funds-hold transfer) or the recipient (invoice).
  • Confirmation — single-step, or a Safe variant that adds an explicit confirmation step (escrow-style).
typeTxNameInitiatorFunds locked at creationExtra confirmation
11InternalTxpayeryes (creator)no
12InternalTxConfirmpayeryes (creator)yes — sender confirms after recipient joins
13InvoiceTxrecipientnono
14InvoiceTxConfirmrecipientnoyes — payer confirms

typeTx values match the public transaction-type enum 1:1. The transfer code identifies the same transaction ID rather than creating a separate operation.

Endpoints

All three live under /trex/v1/ and use the authenticated session identity:

EndpointPurpose
POST /trex/v1/create_tx_codeCreate a code/invoice, returns the encoded code.
POST /trex/v1/apply_codeRedeem a code by code or id (transact timetick).
POST /trex/v1/cancel_codeCancel a pending code by code or id.

apply_code and cancel_code accept either code (the bearer string) or id (the timetick) — passing both is rejected. Side/ownership checks are enforced per state, so id-based access carries the same security as code-based access.

1. Create the code

POST /trex/v1/create_tx_code
Content-Type: application/json
Cookie: sid=...

{
"amount": 100.0,
"currency": "USDT",
"typeTx": 12,
"timeLimit": false,
"partnerInfo": "Order #4821",
"tag": "deal with @bob"
}

The response (TxCodesOut) carries the encoded code, the timetick, and the current stateCode:

{
"timetick": 738291648372910,
"code": "B73UQPJN5Y6UP",
"currency": "USDT",
"amount": 100.0,
"typeTx": 12,
"stateCode": 1,
"state": "FundsHolded",
"isOwner": true,
"dateTxUTC": "2026-06-10T08:00:00Z"
}

What the server does at creation:

  • Validates amount > 0, partnerInfo/tag ≤ 100 chars, currency exists.
  • Rejects if the wallet has WalletBlock, InnerTransferBlock, or Deleted flags.
  • Resolves the InnerTransfer-class tariff for the chosen typeTx.
  • Funds-hold types (11, 12): checks free_balance ≥ amount, then locks the creator's funds — free_balance -= amount, lock_out_balance += amount (action SFromFree | DFromOut). State becomes Created / FundsHolded.
  • Invoice types (13, 14): no balance check and no money moves — the invoice is just a payment request. State becomes Created / InvoiceCreated.

Set timeLimit: true to embed the creation timestamp in the code (enables time restrictions; makes the code string longer).

2. Redeem the code (apply_code)

POST /trex/v1/apply_code?code=B73UQPJN5Y6UP&amount=100.0&client_nonce=1739123

Behaviour depends on typeTx:

InternalTx (11) — funds-hold, single step

The redeemer is bound as the recipient (wallet_to) and the held funds settle immediately:

Created (FundsHolded)
└── recipient applies → Finished
creator.lock_out -= amount
recipient.free += amount - fee

Rejected with SameAccounts (10008) if the creator tries to redeem their own code.

InternalTxConfirm (12) — funds-hold + sender confirmation (escrow)

Two-stage. The recipient joins first; then the sender confirms to release the funds:

Created (FundsHolded)
└── recipient applies → Created|Confirmed (NeedConfirm) [recipient is now bound]
├── sender applies again → Finished [funds released to recipient]
└── cancel — see below

InvoiceTx (13) — invoice, single step

The redeemer is bound as the payer (wallet_from). The amount query parameter must equal the invoice amount, otherwise InvalidAmount (returned before any money moves):

Created (InvoiceCreated)
└── payer applies (amount must match) → Finished
payer.free -= amount
recipient.free += amount - fee

Rejected with SameAccounts if the invoice creator tries to pay their own invoice.

InvoiceTxConfirm (14) — invoice + payer confirmation

Two-stage on the payer side. First call binds the payer and locks funds; the response is NeedCodeConfirm. The second call (same payer, amount matching) finalizes:

Created (InvoiceCreated)
└── payer applies → Confirmed (NeedConfirm) → response: NeedCodeConfirm
└── payer applies again (amount must match) → Finished

Response (ApplyCodeOut)

FieldMeaning
confirmationStatusCodeConfirmed when settled; NeedCodeConfirm when a further confirmation step is required.
txIdThe transact timetick (string).
resultSuccess / status text; for room-join codes holds the room timetick.

Pass client_nonce for idempotency (see Error Handling); a repeated nonce is rejected with NonceExists (10130).

3. Cancel the code (cancel_code)

Who is allowed to cancel depends on the state — this is what makes the Confirm variants safe.

Funds-hold (InternalTx / InternalTxConfirm):

StateWho may cancelEffect
Created (not yet redeemed)creator (sender) onlyCanceled — held funds returned to sender's free_balance
Created|Confirmed (recipient joined)recipient onlyCanceled — funds returned to sender

Invoice (InvoiceTx / InvoiceTxConfirm):

StateWho may cancelEffect
Created (no payer yet)creator (recipient) onlyCanceled
Created|Confirmed (payer joined)payersteps back to Predicted (payer detaches)
Created|Confirmed (payer joined)creator (recipient)Canceled

Escrow protection (safe deal)

The InternalTxConfirm flow is the escrow primitive. The key invariant:

Once the recipient (seller) has joined, the sender (buyer) can no longer cancel — only the seller can.

This blocks the fraud scenario where a buyer receives goods and then cancels the payment, keeping both the money and the goods. The buyer's funds stay locked in lock_out_balance until either the buyer confirms (funds go to the seller) or the seller voluntarily cancels (funds return to the buyer).

StateCan finalizeCan cancel
Created (before seller joins)buyer (creator)
Created|Confirmed (seller joined)buyerseller

Code states (CodeStateEnum)

stateCode in TxCodesOut / TxCodeInfoOut converts the transaction state into a client-friendly value:

stateCodeNameMeaning
0UnknownUnrecognized state
1FundsHoldedFunds locked, code waiting to be redeemed
2InvoiceCreatedInvoice issued, awaiting a payer
3NeedConfirmCounterparty joined, confirmation required
4NeedCancelCancellation in progress
7FinishedSettled
8CancelledCancelled