Skip to content

Send current exchange-rate requests without a device timestamp - #6155

Merged
peachbits merged 1 commit into
developfrom
matthew/rates-current-clock-skew
Aug 15, 2026
Merged

Send current exchange-rate requests without a device timestamp#6155
peachbits merged 1 commit into
developfrom
matthew/rates-current-clock-skew

Conversation

@peachbits

@peachbits peachbits commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

none

Requirements

No visual changes to the GUI — this touches the exchange-rate request logic only — so the device-testing checklist below does not apply.

  • Tested on iOS device
  • Tested on Android device
  • Tested on small-screen device (iPod Touch)
  • Tested on large-screen device (tablet)

Description

Symptom: wallets render correct crypto balances but $0.00 fiat — the same signature as the Cardano report in the ticket.

Verbose exchange-rate logging from an affected device (4.50.2, Android) shows every current rate returning no rate while historical rates resolve:

rates query 0 result: 13 resolved, 16 no-rate:
  base_USD@2026-08-13T13:04:43.935Z, bitcoin_USD@…, monero_USD@…,
  cardano_USD@…, USD_USD@2026-08-13T13:04:43.935Z

The 16 no-rate pairs are exactly the current-timestamp ones; the cache then stores current: 0, so fiat = amount × 0 = $0.00.

Root cause: convertToRatesParams stamped "current" pairs with the device clock (new Date()). The rates server returns no rate for a timestamp more than ~2 minutes in the future, and this device's clock runs ~2 minutes fast (its log uploads show the device UTC ahead of the server date header), so every current request landed right on the server's future cutoff.

Replaying the device's verbatim request against rates3/rates4.edge.app/v3/rates confirmed it: past / now / +1m resolve; +2m and beyond return null. With isoDate omitted, the server uses its own clock and returns the latest rate.

Fix: omit isoDate for current pairs so the server timestamps them; historical pairs keep their explicit date. Immune to device clock skew, with no behavior change when the clock is correct. Adds a convertToRatesParams regression test (current → no isoDate; historical → date preserved).

Verified: tsc, eslint, and the ExchangeRateActions jest suite (6/6) pass.


Note

Medium Risk
Changes how all current rate queries are built for the rates server; incorrect behavior would affect fiat display app-wide, but the change is narrow and covered by a targeted test.

Overview
Fixes wallets showing correct crypto balances but $0.00 fiat when the device clock is slightly fast. Current rate pairs used to get isoDate from new Date() in convertToRatesParams; the rates server rejects timestamps too far in the future and returns no rate, so the cache stored current: 0.

convertToRatesParams now leaves isoDate undefined for pairs with no historical date (crypto and fiat), so the server timestamps with its own clock. Pairs with an explicit isoDate still send that date for historical lookups.

Also exports convertToRatesParams for tests and adds a regression test that current pairs omit isoDate on the wire while historical pairs keep it. CHANGELOG updated.

Reviewed by Cursor Bugbot for commit 1c64ca1. Bugbot is set up for automated code reviews on this repo. Configure here.


The rates loop stamped "current" pairs with the device clock (new Date()).
On a device whose clock runs fast that isoDate is a future date, and the
rates server returns no rate for future dates. Every current rate came back
null, so the cache stored current: 0 and fiat balances rendered as $0.00
even though crypto balances were correct.

Confirmed against rates3/rates4.edge.app: past / now / +1m resolve, while
+2m and beyond return null. The reporting device was ~2 min ahead of server
time (its log uploads show the device UTC ahead of the server date header),
so its current requests landed right on the server's future cutoff.

Omit isoDate for current pairs so the server timestamps them with its own
clock; historical pairs keep their explicit date. Verified the server
returns the latest rate when isoDate is absent.
@peachbits
peachbits force-pushed the matthew/rates-current-clock-skew branch from 4f1705a to 1c64ca1 Compare August 15, 2026 03:03
@peachbits
peachbits enabled auto-merge August 15, 2026 03:09
@peachbits
peachbits merged commit 924bfe5 into develop Aug 15, 2026
7 checks passed
@peachbits
peachbits deleted the matthew/rates-current-clock-skew branch August 15, 2026 03:23
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.

2 participants