Skip to content

Invoice progress versus lifecycle, exact configured approval tracker identity, partial evidence, payment activity, mixed assets, indexer lag, and safe retry reconciliation.

A payment collection needs more than one boolean. Track each obligation's progress, its time window, the current payer's eligibility, and available evidence independently. Collection summaries are derived from those facts.

Progress and Lifecycle

FactInterpretation
No received units/payments, with complete evidenceUnpaid
Some finite units/payments receivedPartially paid until the obligation's configured target is met
Finite target reachedPaid, even after the payment window closes
Before opening timeScheduled; not yet payable
Inside the inclusive payment windowOpen lifecycle; payable additionally requires remaining capacity and payer eligibility
Past cutoff with an outstanding amountExpired with an outstanding amount; prior payments remain recorded
Past an informational due dateOverdue if outstanding; it may still be payable
A reusable link has prior paymentsUsage history; the link does not become finally paid
Tracker or payout evidence is unavailableUnknown; do not substitute unpaid or zero

For multi-obligation invoices, one obligation can be paid while another is scheduled or expired. Show the underlying obligations when a collection-level label would obscure that distinction. A partial receipt count is an amount of units, not a count of contributing people.

Tracker Identity

Use the tracker identity configured by the approval: collection ID, approval level, approver where applicable, approval ID, amount/count tracker ID, tracker type, and relevant address. Include reset semantics where the standard configures resets. Reusing an unrelated tracker or omitting one identity field can report the wrong progress.

Fixed payment caps use payment counts; partial targets use cumulative receipt amounts. Distinct-payer obligations additionally use per-initiator counts. A public link's overall count measures uses without imposing a finite completion target.

The indexer reads configured trackers and builds the projection from authoritative documents. Incomplete reads must fail/retry or remain explicitly unknown. A missing API response is not evidence that an existing obligation has never been paid.

Amounts and Participants

For a fixed obligation, each successful payment contributes the specified payout amounts. For a partial obligation, multiply each payout by received receipt units. Sum exact integer base units only within the same denomination.

Keep requested face amount, collected amount, and remaining amount separate. Legacy rows can have a known face amount with unknown payment history. Showing the face amount as collected would mislead managers.

Participants include named eligible payers and payout recipients. Public payer status is an explicit property, not an empty roster. An index row can help discover the collection but cannot enumerate every person who may use a public link. Actual contributors belong in payment activity.

Activity and Confirmation

Use successful chain execution and its payment events to identify receipts. Keep obligation references, transaction identity, initiator, receipt units, and denomination-specific payouts together. Failed transactions must not increase paid progress.

An SDK action builds a message. A browser callback may report a submitted transaction. Neither alone proves the payment executed successfully. Confirm the hash on the selected chain, then allow the indexer to catch up before expecting the dashboard projection to change.

If an event or rebuild fails, durable retry must preserve the last valid projection and eventually converge to chain evidence. A delayed worker must not overwrite a newer projection or acknowledge a replacement queue generation. These are indexer requirements, not extra payment permissions.

Retry Decisions

SituationNext step
User rejects the wallet request before submissionPreserve the proposal; ask again only when the user requests it
Wallet reports a hashCheck execution result on the same network
Browser closes or CLI times outTreat as uncertain; inspect wallet and chain before retrying
Chain rejects due to exhausted capacityRefresh the obligation; explain that another payment consumed the slot
Chain succeeds but dashboard is staleWait for/requery the indexer; do not pay again
Receipt evidence is incompleteReport unknown; retain transaction identity for reconciliation

A finite invoice may reject duplicate payment after its cap is consumed. A reusable link deliberately allows repeats. Neither should be treated as a general idempotency key for arbitrary client retries.

Reconciliation Record

Keep a durable application record for each attempted action. This is an application-owned example, not a BitBadges API response or an on-chain standard field:

json
{
  "network": "mainnet",
  "collectionId": "46",
  "obligationId": "payment-1",
  "requestedUnits": "1",
  "transactionHash": null,
  "outcome": "unknown",
  "retrySafe": false
}

Replace the illustrative collection ID and persist the actual expected signer and payout terms before handing off to a wallet. Fill in the hash when available and reconcile against execution and obligation trackers. Keep an unknown attempt in this state until evidence resolves it; do not infer failure from a missing callback or replace a missing tracker with a zero balance. The CLI's own result envelope and fields are documented in browser deployment.

Edit this page on GitHub