Skip to content

v2.2.0

Choose a tag to compare

@jesuspirate jesuspirate released this 06 Jun 00:01
v2.2.0
544ee66

v2.2.0 — Healing proven live, claims that can never get stuck, create where you are

Compatibility: SOFT — no wire-format changes, no lockstep. Every flow works
across v2.0.x / v2.1 / v2.2 in any mix. The new guarantees activate on the
device that updates: backups gain field-healing powers on their own update,
claim retries self-heal on the claimer's update, and pooled envelopes include
backups once the PUBLISHING device is on v2.2. No funds at risk in mixed
versions — older devices simply behave like v2.1.

Healing substitution, proven end-to-end in the field (the ₿121 trade)

  • v2.1.0's blind healing was run live: a backup arbiter healed a disputed
    trade that expired while the assigned arbiter was absent — refund voted,
    resolve published, sats claimed back to the locker's wallet through NWC.
    The live run exposed four stacked gaps, all fixed here:
  • Healing now judges by the CLOCK, not the status flag. An expired trade is
    healable the second its deadline passes — previously the backup's client
    waited for a status flip that only an arriving event could cause, so
    "expiry" did nothing until someone else acted.
  • Pooled-trade envelopes now include the backup arbiters. VOTE / CLAIM /
    RESOLVE / release events on pool-share locks are encrypted to the priority
    order, not just the three participants — backups see live tallies and
    settled outcomes instead of "0 votes on both sides". (Events published by
    pre-2.2 devices remain sealed to participants; those partial backup views
    are cosmetic and age out as devices update.)
  • Healable expired trades now appear in the arbiter NEEDS queue ("expired
    unresolved — open it to heal"), instead of only LOCKED disputes counting.
  • RESOLVE starvation fixed: a trade whose votes already decided the outcome
    could sit unresolved forever because the expired-trade path never tried to
    publish the resolve. Loading an expired trade — and the background sweep —
    now publishes any RESOLVE the chain already justifies.
  • Trade-room framing tells the truth mid-heal: an expired-but-healable trade
    reads "EXPIRED · HEALABLE — an arbiter can still heal it", and once a heal
    vote lands it reads "HEALING — refund confirming" instead of the old
    "CLOSED — no longer active" scare.

Claims can never get stuck (the sm_mq1cmq6p_a2arwi0x ₿17 incident)

  • Field-found on a slow connection: a first claim's redeem landed AFTER the
    60s confirm window gave up. Every retry then re-measured balance growth
    from a baseline that already included the landed sats — growth that can
    never be observed again — looping "still arriving" forever while the sats
    sat invisibly in the wallet (below every recovery surface's dust line).
  • Settlement is now provable two ways: balance GROWTH (as before), or the
    absolute balance COVERING the promised payout. If the wallet can pay the
    invoice right now, the claim pays out — retries converge instead of
    looping. One Claim tap after updating pays out a previously-stuck trade.
  • "Notes already consumed" throws get the same rescue: consumed notes plus a
    covering balance means a previous attempt already credited this wallet, so
    the payout proceeds instead of dead-ending. Consumed plus an empty wallet
    still fails honestly — no false hope.
  • Slow links get a fair window: 90s confirm (up from 60s), failed balance
    reads extend the deadline instead of eating it (a read that errors proves
    nothing about non-arrival), hard-capped at 3× so the loop always ends.
  • Cover-path payouts send the money FIRST and publish COMPLETE only after it
    lands — if the payout leg fails, the trade stays claimable and the modal
    says exactly that ("close this and tap Claim again — retries with a fresh
    invoice") instead of pointing small amounts at a recovery surface that
    ignores anything under the dust line.

Create where you are (the stale-home trap)

  • The Create wizard now stamps the community your header actually shows —
    what you see is what you publish. Previously it silently used the home
    picked at sign-in (the only place that could ever change it), so a stale
    home meant listings went out with the wrong country, wrong default
    currency, and the wrong community arbiter pool while every pixel on screen
    said otherwise.
  • When the community you're publishing in differs from your persisted home,
    the listing line grows a one-tap SET AS HOME → affordance — fix the stale
    home at the exact moment the mismatch is visible, no trip back to the
    sign-in screen. Home keeps deciding where Chama signs you in; nothing else
    about boot routing changed.

Your "Chama ready" buzz is back (Android)

  • The boot haptic regressed because it rode the WebView's navigator.vibrate,
    which Android gates behind a fresh user gesture — so on auto-login (no tap
    at all) it could never fire, and on tap-to-connect the relay handshake
    usually outlived the ~5s activation window. Either way the buzz got eaten.
  • Haptics now route through the native @capacitor/haptics plugin on-device,
    which calls the system vibrator straight through the bridge with no
    activation requirement. The exact patterns are preserved — the connected
    double-buzz, the celebratory claim, every tap — replayed faithfully pulse
    for pulse. Web stays on navigator.vibrate (which already honours patterns).

Numbers

  • 2,187 tests green, including new suites pinning the cover-settlement
    verdicts (rescue, timeout-cover, no-cover honesty, pay-then-complete
    ordering, stash preservation) and the slow-link confirm window.