Skip to content

feat: auto-select best pool fee tier for trades#37

Merged
Maxnflaxl merged 27 commits into
masterfrom
pool-selection
Apr 6, 2026
Merged

feat: auto-select best pool fee tier for trades#37
Maxnflaxl merged 27 commits into
masterfrom
pool-selection

Conversation

@Maxnflaxl
Copy link
Copy Markdown
Member

@Maxnflaxl Maxnflaxl commented Apr 3, 2026

When a user enters a trade amount, all pools matching the token pair are queried sequentially (bPredictOnly=1) and the one returning the highest buy amount is selected automatically. Adds a fee tier picker showing a "Best" badge on the winning pool with manual override and an "Auto" reset button.

dapp

  • New onFindBestPool saga action queries each fee tier and dispatches setCurrentPool with the winner (takeLatest cancels stale searches).
  • activePool memo replaced with matchedPools + manualKind/bestKind state so auto and manual selections are tracked independently.
  • Amount inputs format with thousands separators in real time; Input.tsx validates amounts using a comma-stripped copy so typing isn’t blocked; selection is restored after format so the caret doesn’t jump to the end; useValidation strips commas in the isMax check.
  • formatPredictAmount preserves full decimal precision (no rounding).
  • Clearing the active input now also clears the predicted output.
  • Fee tier picker is consistent across embedded and non-embedded layouts; helpers moved to module level.
  • Fix: saga filter cast and duplicate clean: true in webpack config.
  • Raise max amount cap to MAX_SAFE_INTEGER to allow full trading in bigger pools (noticed this limitation in the TICO pool).
  • FROM and TO fields on the TRADE page show a "0" as a placeholder at start, which gets automatically removed when the input field is in focus and returns when the field is out of focus but still without input.
  • Fix: correct fee token labels and full decimal precision in trade summary
  • Add Liquidity and Remove Liquidity pages now use the same number formatting and placeholder logic
  • remove blue outline from fee tier list on the CREATE POOL page
  • inline reserve errors replaces asset amount > MAX bottom right alert
  • popup search modal with two types, asset and explore
  • Asset Info Page
  • extend favorites to assets with filter in asset selector
  • Replace old utils.js with @vsnation's BeamDappConnector
  • Added support for AMML 0/7/1 and AMML BEAM/BEAMX 1%, updated labels to AMML (SN(id)/SN(id) - fee%), and removed ambiguous fee-index matches.
  • Fake Asset warning
  • clicking on an asset in the POOL INFO widget on the TRADE page opens that asset in the ASSET INFO page

ui

Scroll / layout

  • App: Scrollbars view uses overflow-x hidden + overscroll-behavior none; hide
    tracks when not needed; optional body/html overscroll-behavior in global styles.
  • Global: html/body/#root overflow-x hidden, width chains; remove body min-width
    that forced horizontal overflow; #root block + height 100% for Scrollbars.
  • Global: body.web / body.mobile + html:has(...) use --color-dark-blue and
    min-height 100vh so the shell fills the viewport behind TopNav (not only the
    Window content column).
  • Container: width 100% + max-width 914px; optional wide (980px) for embedded
    trade; TradePool embedded uses wide.
  • Window, SwapPoolsHome, EmbeddedLayout, AssetsSection, InlineSelect: min-width,
    overflow-x, and grid column width (620px trade column) to avoid clip/scroll;
    InlineSelect min-width 200px and flex-shrink 0 so control/menu stay readable.
  • poolFlowLayout Line: max-width 412px instead of fixed width.

Asset selector (react-select custom-filter)

  • Menu portaled to document.body with position fixed so dropdown is not clipped
    by overflow ancestors.
  • SCSS: menu/menu-portal z-index, control min-width, option/menu overflow,
    tighter menu-list padding; styles consolidated from inline TS where possible.
  • ReactSelect: layout via Linaria (grid row + ellipsis); removed unused inline
    StylesConfig blob; portal props kept in component.

Metadata

  • getOptions / asset labels use SN from parsed metadata (short ticker), then UN,
    then N; shared assetShortLabel helper in appUtils.

image image image image

Github CI build used the dev build before, now uses the correct prod build.

When a user enters a trade amount, all pools matching the token pair
are queried sequentially (bPredictOnly=1) and the one returning the
highest buy amount is selected automatically. Adds a fee tier picker
showing a "Best" badge on the winning pool with manual override and
an "Auto" reset button.

- New onFindBestPool saga action queries each fee tier and dispatches
  setCurrentPool with the winner (takeLatest cancels stale searches)
- activePool memo replaced with matchedPools + manualKind/bestKind
  state so auto and manual selections are tracked independently
- Amount inputs format with thousands separators in real time;
  Input.tsx strips commas before REG_AMOUNT validation so typing
  is never blocked; useValidation strips commas in the isMax check
- formatPredictAmount preserves full decimal precision (no rounding)
- Clearing the active input now also clears the predicted output
- Fee tier picker is consistent across embedded and non-embedded
  layouts; helpers moved to module level
- Fix: saga filter cast and duplicate clean:true in webpack config
@Maxnflaxl Maxnflaxl marked this pull request as ready for review April 3, 2026 19:13
Maxnflaxl and others added 24 commits April 3, 2026 21:16
…hell bg

Scroll / layout
- App: Scrollbars view uses overflow-x hidden + overscroll-behavior none; hide
  tracks when not needed; optional body/html overscroll-behavior in global styles.
- Global: html/body/#root overflow-x hidden, width chains; remove body min-width
  that forced horizontal overflow; #root block + height 100% for Scrollbars.
- Global: body.web / body.mobile + html:has(...) use --color-dark-blue and
  min-height 100vh so the shell fills the viewport behind TopNav (not only the
  Window content column).
- Container: width 100% + max-width 914px; optional wide (980px) for embedded
  trade; TradePool embedded uses wide.
- Window, SwapPoolsHome, EmbeddedLayout, AssetsSection, InlineSelect: min-width,
  overflow-x, and grid column width (620px trade column) to avoid clip/scroll;
  InlineSelect min-width 200px and flex-shrink 0 so control/menu stay readable.
- poolFlowLayout Line: max-width 412px instead of fixed width.

Asset selector (react-select custom-filter)
- Menu portaled to document.body with position fixed so dropdown is not clipped
  by overflow ancestors.
- SCSS: menu/menu-portal z-index, control min-width, option/menu overflow,
  tighter menu-list padding; styles consolidated from inline TS where possible.
- ReactSelect: layout via Linaria (grid row + ellipsis); removed unused inline
  StylesConfig blob; portal props kept in component.

Metadata
- getOptions / asset labels use SN from parsed metadata (short ticker), then UN,
  then N; shared assetShortLabel helper in appUtils.
- Default both amount fields to 0; paired field resets to 0 when quote clears
- Focus clears placeholder 0; blur restores 0 if the user entered nothing
- Share amount focus/blur handlers; dedupe fee-tier UI and token select handlers
- Drop redundant embedded checks in the full-page trade branch
…ade summary

- DAO Fee, LP Fee, and Total Fee rows now show the FROM token (currentToken) instead of the TO token, matching contract output where fee_dao and fee_pool are denominated in the payment asset
- "You buy" row in the full view now correctly shows the TO token (secondToken)
- "Total Pay" row in the full view now correctly shows the FROM token
- formatNumber now uses maximumFractionDigits: 8 so small fee values
  (e.g. 0.00300123) are no longer truncated to 3 decimal places
Extract poolAmountInput (parseAmount, grouping, caret-safe onChange,
createAmountFieldHandlers, formatPredictedFieldDisplay) and wire TradePool,
AddLiquidity, and WithdrawPool to use it for consistent placeholders and
number formatting. Keep add/withdraw as single slim container files; move
predicted display helpers into the shared module to avoid duplicated logic.
- When several pools match, detect if the from/to amount exceeds every pool’s relevant reserve; show ErrorHint and AssetsSection error ring and red numbers instead of a toast, and skip trade requests while isMax on that side.
- findBestPool: only setCurrentPool when bestBuy > 0.
- poolFlowLayout: add HintRow and ErrorHint styled components.
- Replace ReactSelect token pickers with AssetSearchModal / AssetSelectorButton
in trade, create pool, and explore (searchable selection, exclude paired asset).

- Add AssetInfo at /asset/:id with metadata and pools list; extract PoolTable
for explore + asset detail; small explore header/layout and sort underline fix.

- Update IAsset for emission fields; simplify add-liquidity amount flow (drop swap
toggle, clear predict when the other side is empty).
…ctor

- add favoriteAssets (number[]) to Redux state, persisted to localStorage
- toggle favorite assets via saga (onToggleFavoriteAsset)
- add star button to each asset row in AssetSearchModal
- add ALL / Favorite filter dropdown in the asset selector tab bar
- when Favorite filter is active, asset list and pool pair search results only show items where both assets are in favorites
replaces old utils

Co-Authored-By: vsnation <44433026+vsnation@users.noreply.github.com>
Handle wallet cancel without forcing connector lock state, keep prediction calls returning shader results, and fix auto-mode tier probing/validation so Trade Summary and fee-tier switching stay responsive.
support AMML query formats, keep AMML-prefixed `/` searches out of POOL mode, and enforce exact fee-tier matching.
- Add fake-real asset ID mapping (imposterAssets) and surface it across trade
(select + execute), explore pool open, asset info, and asset/pool search with
badges and confirm/modal flows (desktop uses window.confirm, component used in web doesnt work in the desktop wallet for some reason).

- Pool list and explore: apply tab filter before search; enable fav/created tabs
even when empty; show contextual empty copy instead of disabling tabs or an
infinite loader.

- Asset search: onSelect may return false to keep the modal open during imposter
handling; AssetSelectorButton supports warning state and controlled open/close.
clicking on one of the assets in the POOL INFO section of the TRADE page opens the asset in the ASSET INFO page
@Maxnflaxl Maxnflaxl merged commit 5905229 into master Apr 6, 2026
1 check passed
@Maxnflaxl Maxnflaxl deleted the pool-selection branch April 6, 2026 23:18
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