Skip to content

event-mapper: decode CAP-67 muxed transfer values and full-range i128 amounts - #17

Merged
AquiGorka merged 1 commit into
mainfrom
fix/sac-transfer-amount-decode
Jul 31, 2026
Merged

event-mapper: decode CAP-67 muxed transfer values and full-range i128 amounts#17
AquiGorka merged 1 commit into
mainfrom
fix/sac-transfer-amount-decode

Conversation

@AquiGorka

@AquiGorka AquiGorka commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Root cause (with decoded on-chain evidence)

The empty volume / asset-breakdown tiles were investigated against live testnet data. Findings:

The plain-i128 path works. The two real channel money-flow events on testnet decode correctly with the current code:

  • deposit 0016589233871425536-0000000000 (ledger 3862482): transfer GDKSTZ...OBEF -> channel CD5MZC...KPF2, value scvI128 XDR AAAACgAAAAAAAAAAAAAAADuiayA= = 1000500000 stroops
  • settlement 0016589324065746944-0000000000 (ledger 3862503): channel -> GBCDUL...QXU7, value scvI128 XDR AAAACgAAAAAAAAAAAAAAAAvrwgA= = 200000000 stroops

Both amounts appear intact in the live WS snapshot's recent payloads. The tiles are empty right now because no deposit/settlement has occurred inside the 24h / 60-min windows since 2026-07-29 13:25 UTC, not because these two events lost their amounts.

Two real decode defects existed regardless:

  1. CAP-67 muxed transfer shape drops the amount. Since protocol 23, SAC transfer events whose destination carries a muxed id put their data in an scvMap {"amount": i128, "to_muxed_id": bytes} instead of a bare i128. Real example on testnet: event 0016589229576450048-0000000000 (ledger 3862481). decodeI128 only accepted scvI128, so any muxed deposit/settlement mapped to amount: null and could never reach volume or asset-breakdown aggregates.
  2. i128 >= 2^64 decoded to an unparseable string. decodeI128 returned "<hi>:<lo>" whenever hi != 0; the store's parseAmount rejects that, silently dropping large amounts (and all negative amounts, since hi = -1 for those).

Fix

  • decodeTransferAmount accepts both on-chain shapes: bare scvI128, and the CAP-67 map (extracts the amount entry).
  • decodeI128 does real signed reassembly (hi * 2^64 + lo) and returns a plain decimal string across the full i128 range.

Tests

Five new vectors, the on-chain ones using the verbatim ScVal XDR captured from testnet RPC:

  • real deposit event -> channel_deposit with amount 1000500000
  • real settlement event -> channel_settlement with amount 200000000
  • real CAP-67 muxed map value -> amount decoded (pre-fix: null)
  • hi=1, lo=1 -> 18446744073709551617 (pre-fix: "1:1")
  • end-to-end replay: real deposit event through mapChainEvent -> recordEvent -> sparkline volume bucket 100.05 and 24h asset breakdown row 1000500000 stroops / 100%

deno task test: 51 passed, 0 failed. check, lint, fmt:check clean.

Live verification (2026-07-31)

Ran local-dev testnet suite 1 through the events-capture harness against the deployed testnet platforms: 5/5 network WS events matched, including channel_deposit amount 100500000 and channel_settlement amount 40000000. Post-run snapshot shows volume sparkline 14.05 XLM, 24h asset breakdown XLM 140500000 stroops (100%), and live latency samples. The plain-i128 path is confirmed live end-to-end; the muxed-map and >=2^64 paths this PR adds are covered by the unit vectors and can get the same live check after deploy.

… amounts.

SAC transfer events since protocol 23 can carry their data as a map with amount and to_muxed_id; those deposits mapped to a null amount and never reached volume or asset-breakdown aggregates. decodeI128 also emitted an unparseable hi:lo string for amounts at or above 2^64.
@AquiGorka
AquiGorka force-pushed the fix/sac-transfer-amount-decode branch from 5930df8 to 36787ec Compare July 31, 2026 12:39
@AquiGorka
AquiGorka merged commit c41f6fe into main Jul 31, 2026
5 checks passed
@AquiGorka
AquiGorka deleted the fix/sac-transfer-amount-decode branch July 31, 2026 13:16
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