Skip to content

fix(swap): post-swap on-chain reconcile for EVM token outputs + tracker hardening#377

Merged
BitHighlander merged 3 commits into
developfrom
feature/post-swap-reconcile
Jul 23, 2026
Merged

fix(swap): post-swap on-chain reconcile for EVM token outputs + tracker hardening#377
BitHighlander merged 3 commits into
developfrom
feature/post-swap-reconcile

Conversation

@BitHighlander

Copy link
Copy Markdown
Collaborator

Why

After a swap delivered 85.643286 USDT, all three post-swap refreshes (immediate/+30s/+90s) re-queried the same indexed source (Zapper via Pioneer), got back the stale pre-swap dust balance marked fresh, and persisted it. Separately, the swap tracker accepted a malformed provider response (received 0.604399 with an all-zeros outbound tx hash) as final.

What

Post-swap targeted refresh reconciles the destination contract on-chain

  • keepkey-swap-completed event (SwapTracker/ActivityTracker) now carries toCaip.
  • Dashboard passes an ERC-20 destination caip through refreshBalancesgetBalances RPC (swapDestCaips, new optional param in rpc-schema).
  • The bun backend converts it to an extraContracts entry on the Pioneer GetPortfolioBalances body — networkId/contract parsed from the caip, decimals/symbol/name from pioneer-discovery assetData with cached-token-row fallback; entries with unresolvable decimals are skipped (never guessed). Deduped against existing custom-token extraContracts. Rides all three refreshes.
  • Pairs with pioneer PR coinmastersguild/pioneer#176, where an explicitly requested contract's direct balanceOf now upserts over stale indexer rows.

Swap-tracker hardening (src/bun/swap-tracker.ts)

  • All-zeros/empty outbound tx hashes are treated as not-yet-known (dropped with a warn), not final.
  • A received amount arriving alongside a placeholder outbound hash is rejected; the existing > 0 guard keeps rejecting non-positive amounts. A later poll with real data fills in the correct values.

Verified

  • bun scripts/bundle-backend.ts OK (7.60 MB), bunx vite build OK (4.03s) — the compile steps make build runs.
  • Baseline-diffed tsc output for the six touched files: zero new errors (repo has ~1576 pre-existing).
  • Not verified live: a real EVM-token swap end-to-end.

🤖 Generated with Claude Code

BitHighlander and others added 2 commits July 21, 2026 02:12
Recorded as an unresolved REST-layer issue on the strength of a single
observation. It was a stuck emulator. /hive/sign-operations is in
SIGNING_ROUTES and does get server.timeout(req, 0), so a pending confirm
holds the socket open as designed. Rewritten so the next agent restarts the
emulator instead of going hunting in rest-api.ts.
…t malformed tracker rows

Two fixes for the stale-USDT-after-swap incident (85.6 USDT delivered, dashboard
kept a dust balance and the tracker stored received=0.604399 with a zeroed
outbound hash):

1. Post-swap targeted refresh now forces a direct on-chain balanceOf for the
   swap's destination token. The swap-completed event carries the output CAIP;
   when it is an EVM token (/erc20:) the Dashboard forwards it through
   getBalances (swapDestCaips) and the bun backend appends an extraContracts
   entry ({networkId, contractAddress, symbol, decimals}) to the Pioneer
   POST /portfolio body — bypassing the indexed (Zapper) source, which lags a
   few blocks after a swap and can return a stale pre-swap balance marked
   fresh. Decimals/symbol come from pioneer-discovery assetData, falling back
   to a previously cached token row; unknown tokens are skipped with a warning.

2. swap-tracker hardening: an all-zero (or empty) outbound tx hash in a
   provider status response is treated as not-yet-known instead of being
   stored, and the received amount from such a malformed row is rejected
   (amounts <= 0 were already rejected) — a later poll carries the real values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@BitHighlander
BitHighlander merged commit 222d2b2 into develop Jul 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant