Skip to content

Explorer node: add asset_swaps and asset_swaps_totals endpoints#2054

Merged
valdok merged 10 commits into
boost-1.90from
issue/2053
Jun 20, 2026
Merged

Explorer node: add asset_swaps and asset_swaps_totals endpoints#2054
valdok merged 10 commits into
boost-1.90from
issue/2053

Conversation

@Maxnflaxl

@Maxnflaxl Maxnflaxl commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

Implements #2053. The explorer node already exposes atomic-swap offers via swap_offers / swap_totals, but had no equivalent for Asset Swaps (DEX). This adds two read-only endpoints:

  • /asset_swaps — live asset-swap (DEX) offers
  • /asset_swaps_totals — per-asset aggregate totals + offer count

The node already receives this data over SBBS broadcast, so no wallet / wallet-API is required.

Both endpoints are documented in the Beam Node Explorer API reference.

How it works

The adapter builds a read-only DexBoard over the broadcast router and wallet DB it already creates for the atomic-swap board. It subscribes to the DEX offers broadcast channel and accumulates offers (foreign offers are kept with isMine=false, not rejected). A no-op IRawCommGateway is passed because the explorer only lists offers — it never accepts or processes trades.

Plumbing mirrors the existing swap_offers / swap_totals path exactly: an entry in the ExplorerNodeDirs macro, OnRequest handlers, and backend methods. The new code is gated by BEAM_ASSET_SWAP_SUPPORT, matching how atomic swaps are gated by BEAM_ATOMIC_SWAP_SUPPORT (required, since the wallet DB's DEX methods are themselves behind that flag).

/asset_swaps

Reported in maker terms (send_* = what the maker offers, receive_* = what the maker wants), using the absolute first/second sides rather than DexOrder's isMine-relative send/receive helpers (which are perspective-dependent and meaningless on a neutral node). Amounts are formatted with PrintableAmount, timestamps returned as raw unix seconds (formatted client-side, as on the block-headers page).

{
  "id": "<order-uuid>",
  "send_asset_id": 0, "send_currency": "BEAM", "send_amount": "4,862.63068319",
  "receive_asset_id": 7, "receive_currency": "USDT", "receive_amount": "500",
  "create_time": 1781784005, "expire_time": 1781785805
}

/asset_swaps_totals

{
  "total_offers_count": 12,
  "assets": [
    { "asset_id": 0, "currency": "BEAM", "amount_offered": "5,000", "amount_wanted": "0" },
    { "asset_id": 7, "currency": "USDT", "amount_offered": "0", "amount_wanted": "2,500" }
  ]
}

Bugfixes

Fixes the explorer needed alongside the feature:

  • PoW block timestamps rendered as 1970-01-01. get_Timestamp_s() and the hdrs Age / block-duration deltas read SystemState::get_Timestamp_ms(), which carries a value only for PBFT/PoS consensus — on a PoW chain it reinterprets the PoW solution as PBFT header data and returns 0, so every block / header / status timestamp (and the Age and d.Time columns) collapsed to the epoch. Regression from 221cc7da2 ("explorer: showing time in ms where applicable (for PoS networks)"). Fixed by choosing the source from the chain's consensus type (Rules::m_Consensus) via a single get_Timestamp_ms_safe() helper used at every affected site: the ms timestamp for Pbft, the seconds field m_TimeStamp for PoW / FakePoW.

  • -Wdeprecated-literal-operator build break. Recent clang flags the whitespace-before-suffix user-defined-literal spelling in the bundled 3rdparty/nlohmann/json.hpp; with the project's unconditional -Werror this breaks the build of any target that includes it (e.g. explorer-node). Added -Wno-deprecated-literal-operator to the AppleClang flag block, next to the existing -Wno-enum-constexpr-conversion handling.

Expose live Asset-Swap (DEX) offers from the explorer node, mirroring the
existing swap_offers / swap_totals atomic-swap endpoints.

The adapter builds a read-only DexBoard over the broadcast router and wallet
DB it already creates. A no-op IRawCommGateway is passed, since the explorer
only lists offers and never accepts/processes trades. Two routes are added:

  /asset_swaps         live offers, reported in maker terms (send = offered,
                       receive = wanted), absolute first/second rather than
                       DexOrder's isMine-relative helpers; expired filtered.
  /asset_swaps_totals  per-asset offered/wanted totals plus offer count.

Amounts are serialized as strings to avoid JSON precision loss. The new code
is gated by BEAM_ASSET_SWAP_SUPPORT, matching how the atomic-swap path is
gated by BEAM_ATOMIC_SWAP_SUPPORT.

Closes #2053
Recent clang versions flag the whitespace-before-suffix spelling of the
user-defined literal operators in 3rdparty/nlohmann/json.hpp
(operator "" _json / _json_pointer). With the project's unconditional
-Werror this breaks the build of any target that includes that header,
e.g. explorer-node. Add -Wno-deprecated-literal-operator to the AppleClang
flag block, next to the existing -Wno-enum-constexpr-conversion handling.
@Maxnflaxl Maxnflaxl linked an issue Jun 18, 2026 that may be closed by this pull request
@Maxnflaxl Maxnflaxl requested a review from valdok June 18, 2026 12:27
Add an "Asset Swaps" menu link, a dispatcher branch for type=asset_swaps,
and DisplayAssetSwaps / DisplayAssetSwapTotals render functions, mirroring
the existing Atomic Swaps frontend. Lists /asset_swaps offers and fetches
/asset_swaps_totals into the totals panel.
get_asset_swaps / get_asset_swaps_totals returned raw groth integers plus an
is_mine flag. Wrap the amounts in wallet::PrintableAmount (as the adjacent
atomic-swap handlers already do) so the API returns decimal strings, and drop
is_mine: the explorer runs a FAKE_SEED wallet, so offers are never "mine".
DisplayAssetSwaps / DisplayAssetSwapTotals dumped the JSON via Obj2Html (nested
bullet lists). Render the offers and per-asset totals as dataTables instead,
formatting amounts with MakeAmountClr and dropping the is_mine column.
The "Total offers: N" line used the aboutText class (light-colored text),
which was invisible on the light totals panel. Remove it; the offer count is
already shown in the "Offers (N)" collapsible header.
Render the currency as "NAME (id)" (e.g. BEAM (0), bUSDT (37)) in both the
offers and totals tables, so the underlying confidential-asset id is visible.
DisplayAtomicSwaps dumped offers via Obj2Html. Use the same dataTable layout
as asset swaps (Sends / For / Created / Expires / Order ID), mapping the
atomic fields: beam_amount/swap_amount by is_beam_side -> Sends/For,
time_created, height_expired, txId.
…mestamps

get_Timestamp_s() and the hdrs Age/duration deltas read SystemState::get_Timestamp_ms(),
which is PBFT/PoS-only: on PoW it reinterprets the PoW solution as PBFT header data and
returns 0, so every PoW block timestamp (and the Age / d.Time columns) rendered as 0
(1970-01-01). Regression from 221cc7d.

Choose the source by the chain consensus type (Rules::m_Consensus) via a single
get_Timestamp_ms_safe() helper - the ms timestamp for Pbft, the seconds field
m_TimeStamp otherwise - and use it at every site the regression touched (block
timestamp, genesis, Age and duration deltas).

Also return asset-swap create_time/expire_time as raw unix seconds so the web UI can
format them like the block-headers page.
…lper

Render asset-swap created/expires via formatTimestamp(..., 'local') - the same helper
the hdrs page uses - now that the node returns raw seconds.
Maxnflaxl added a commit to BeamMW/docs-gitbook that referenced this pull request Jun 18, 2026
…ndpoints

Reflects BeamMW/beam#2054: two read-only DEX endpoints gated by
BEAM_ASSET_SWAP_SUPPORT. Adds them to the endpoint list and documents
request/response shapes (maker-terms send_*/receive_*, PrintableAmount
strings, numeric asset IDs, raw unix create/expire times, 32-hex order id).
@valdok valdok merged commit 0de0ace into boost-1.90 Jun 20, 2026
9 checks passed
@Maxnflaxl Maxnflaxl deleted the issue/2053 branch June 20, 2026 11:39
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.

Explorer node: FR add asset swaps

2 participants