aegis-swap-widget 0.3.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/DESIGN.md +11 -0
  3. package/README.md +189 -25
  4. package/dist/address.d.ts +7 -0
  5. package/dist/aegis-swap-widget.js +13983 -3384
  6. package/dist/color.d.ts +8 -0
  7. package/dist/components/Sparkline.d.ts +32 -0
  8. package/dist/components/icons.d.ts +25 -17
  9. package/dist/config/chains.d.ts +1 -11
  10. package/dist/config/contracts.d.ts +1 -6
  11. package/dist/config/createMarket.d.ts +1 -3
  12. package/dist/config/index.d.ts +7 -7
  13. package/dist/config/markets.d.ts +1 -1
  14. package/dist/config/tokens.d.ts +1 -11
  15. package/dist/config/types.d.ts +2 -81
  16. package/dist/core.d.ts +4 -4
  17. package/dist/core.js +8 -7
  18. package/dist/encoding.d.ts +2 -28
  19. package/dist/format.d.ts +44 -1
  20. package/dist/hooks/useBackendSwapData.d.ts +27 -0
  21. package/dist/hooks/useEngineMarketHistory.d.ts +21 -0
  22. package/dist/hooks/useEngineVaultActivity.d.ts +51 -0
  23. package/dist/hooks/useKeyedFetch.d.ts +29 -0
  24. package/dist/hooks/useLifecycleToast.d.ts +1 -1
  25. package/dist/hooks/useNativeMaxFill.d.ts +28 -0
  26. package/dist/hooks/useStatusChangeEmitter.d.ts +1 -1
  27. package/dist/hooks/useSubmitSwap.d.ts +4 -4
  28. package/dist/hooks/useSwapQuote.d.ts +2 -2
  29. package/dist/hooks/useTokenAllowance.d.ts +1 -1
  30. package/dist/hooks/useTokenBalances.d.ts +19 -2
  31. package/dist/hooks/useTokenIconMetadata.d.ts +1 -1
  32. package/dist/hooks/useTokenPriceHistory.d.ts +18 -0
  33. package/dist/hooks/useValueRefresh.d.ts +1 -1
  34. package/dist/hooks/useWalletConnection.d.ts +3 -2
  35. package/dist/index.d.ts +20 -15
  36. package/dist/logger.d.ts +4 -0
  37. package/dist/markets-D31LUAsv.js +71 -0
  38. package/dist/metadata.d.ts +2 -25
  39. package/dist/palette.d.ts +44 -0
  40. package/dist/permit.d.ts +1 -9
  41. package/dist/polling.d.ts +1 -3
  42. package/dist/quote/aggregatedSwapQuote.d.ts +1 -5
  43. package/dist/quote.d.ts +2 -59
  44. package/dist/services/kyberSwap.d.ts +2 -84
  45. package/dist/styles.css +1 -1
  46. package/dist/styles.css.d.ts +2 -0
  47. package/dist/toast/ToastItem.d.ts +2 -8
  48. package/dist/toast/Toaster.d.ts +5 -3
  49. package/dist/toast/swipe.d.ts +12 -2
  50. package/dist/toast/toast.d.ts +1 -1
  51. package/dist/toast/useSwipeDismiss.d.ts +32 -0
  52. package/dist/transactionProgress.d.ts +2 -55
  53. package/dist/types/aggregatedSwap.d.ts +1 -29
  54. package/dist/wallet.d.ts +2 -34
  55. package/dist/widget/AegisAggregatedSwapWidget.d.ts +1 -1
  56. package/dist/widget/AegisDirectSwapWidget.d.ts +1 -1
  57. package/dist/widget/AegisEngineWidget.d.ts +2 -0
  58. package/dist/widget/AmountField.d.ts +17 -3
  59. package/dist/widget/EngineAmountBox.d.ts +33 -0
  60. package/dist/widget/EngineMetricHistoryChart.d.ts +25 -0
  61. package/dist/widget/ExecutionDetails.d.ts +5 -22
  62. package/dist/widget/NetworkSelector.d.ts +7 -1
  63. package/dist/widget/ProgressRail.d.ts +1 -1
  64. package/dist/widget/SettingsMenu.d.ts +21 -0
  65. package/dist/widget/SwapFormBody.d.ts +55 -0
  66. package/dist/widget/SwapWidgetShell.d.ts +51 -25
  67. package/dist/widget/TokenPriceHistoryStrip.d.ts +37 -0
  68. package/dist/widget/TokenSelector.d.ts +27 -6
  69. package/dist/widget/TransactionReceipt.d.ts +22 -0
  70. package/dist/widget/aggregatedQuote.d.ts +10 -0
  71. package/dist/widget/chainDisplay.d.ts +5 -0
  72. package/dist/widget/engine-controller/displayCache.d.ts +69 -0
  73. package/dist/widget/engine-controller/engineActionExpiry.d.ts +12 -0
  74. package/dist/widget/engine-controller/engineActionState.d.ts +63 -0
  75. package/dist/widget/engine-controller/engineCtaLabel.d.ts +42 -0
  76. package/dist/widget/engine-controller/engineDisplay.d.ts +88 -0
  77. package/dist/widget/engine-controller/engineExecutionGuards.d.ts +14 -0
  78. package/dist/widget/engine-controller/engineLifecycle.d.ts +321 -0
  79. package/dist/widget/engine-controller/engineOptions.d.ts +11 -0
  80. package/dist/widget/engine-controller/engineQuoteFetch.d.ts +74 -0
  81. package/dist/widget/engine-controller/engineSurge.d.ts +28 -0
  82. package/dist/widget/engine-controller/engineTransactionProgress.d.ts +17 -0
  83. package/dist/widget/engine-controller/engineTransactionView.d.ts +36 -0
  84. package/dist/widget/engine-controller/useEngineActionDrafts.d.ts +22 -0
  85. package/dist/widget/engine-controller/useEngineActivity.d.ts +15 -0
  86. package/dist/widget/engine-controller/useEngineBuySwapProps.d.ts +30 -0
  87. package/dist/widget/engine-controller/useEngineChainConfig.d.ts +38 -0
  88. package/dist/widget/engine-controller/useEngineFeeEstimate.d.ts +24 -0
  89. package/dist/widget/engine-controller/useEngineFills.d.ts +28 -0
  90. package/dist/widget/engine-controller/useEngineLifecycleToast.d.ts +9 -0
  91. package/dist/widget/engine-controller/useEnginePositionActions.d.ts +73 -0
  92. package/dist/widget/engine-controller/useEnginePositions.d.ts +26 -0
  93. package/dist/widget/engine-controller/useEngineSubmit.d.ts +106 -0
  94. package/dist/widget/engine-ui/EngineBorrowVaultCard.d.ts +14 -0
  95. package/dist/widget/engine-ui/EngineBuyPanel.d.ts +11 -0
  96. package/dist/widget/engine-ui/EngineDetailsBreakdown.d.ts +12 -0
  97. package/dist/widget/engine-ui/EngineDetailsModal.d.ts +7 -0
  98. package/dist/widget/engine-ui/EngineLendPositionCard.d.ts +11 -0
  99. package/dist/widget/engine-ui/EngineLifecycleCard.d.ts +38 -0
  100. package/dist/widget/engine-ui/EngineLoanDetailsDialog.d.ts +55 -0
  101. package/dist/widget/engine-ui/EngineMarketDialog.d.ts +18 -0
  102. package/dist/widget/engine-ui/EnginePositionManageDialog.d.ts +24 -0
  103. package/dist/widget/engine-ui/EnginePositionsPanel.d.ts +7 -0
  104. package/dist/widget/engine-ui/EngineRiskMeter.d.ts +36 -0
  105. package/dist/widget/engine-ui/EngineSurgePill.d.ts +19 -0
  106. package/dist/widget/engine-ui/EngineTermChips.d.ts +8 -0
  107. package/dist/widget/engine-ui/EngineTransactionReceipt.d.ts +7 -0
  108. package/dist/widget/engine-ui/EngineVaultActivityCard.d.ts +24 -0
  109. package/dist/widget/engine-ui/TokenPairMark.d.ts +6 -0
  110. package/dist/widget/engine-ui/useOverlayClose.d.ts +14 -0
  111. package/dist/widget/engine-ui/useOverlayPresence.d.ts +15 -0
  112. package/dist/widget/engineViewState.d.ts +4 -0
  113. package/dist/widget/focusTrap.d.ts +3 -0
  114. package/dist/widget/simpleBorrowMath.d.ts +17 -0
  115. package/dist/widget/simpleBorrowViewModel.d.ts +130 -0
  116. package/dist/widget/types.d.ts +260 -20
  117. package/dist/widget/useAggregatedSwapController.d.ts +30 -15
  118. package/dist/widget/useEngineController.d.ts +250 -0
  119. package/dist/widget/useEnteredFrame.d.ts +1 -0
  120. package/dist/widget/useExecutionDetailsState.d.ts +23 -0
  121. package/dist/widget/useNetworkLens.d.ts +41 -0
  122. package/dist/widget/useRailAutoReset.d.ts +1 -1
  123. package/dist/widget/useStatusSurface.d.ts +5 -5
  124. package/dist/widget/useSwapConfig.d.ts +48 -0
  125. package/dist/widget/useSwapController.d.ts +42 -24
  126. package/dist/widget/useWidgetStyle.d.ts +9 -4
  127. package/dist/widget/viewState.d.ts +34 -19
  128. package/package.json +19 -10
  129. package/dist/abis.d.ts +0 -132
  130. package/dist/metadata-D56OpXF2.js +0 -379
  131. package/dist/widget/PoolSelector.d.ts +0 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3c4e2ba: Engine widget: add `detailsPlacement` ('up' | 'down', default 'up'). Details now
8
+ open as an overlay sheet rising from the bottom of the widget instead of
9
+ expanding inline; the widget's height no longer changes.
10
+ - 3c4e2ba: Add host-selected history windows and mode-aware Engine metric series to the decorative sparklines, including >18h gap breaks in the shared SVG path.
11
+ - 3c4e2ba: Add complete Engine position management and lifecycle surfaces.
12
+
13
+ - Core now exposes guarded repay, withdraw, close, and lend-withdraw flows,
14
+ live vault state and LTV reads, wallet-scoped position activity, fee
15
+ estimation, authorization checks, and transaction progress helpers.
16
+ - The React widget now shows existing borrow and lend positions above their
17
+ forms, adds live-risk and activity details, provides position management
18
+ sheets, and keeps review, pending, replacement, confirmation, and failure
19
+ states in one transaction lifecycle.
20
+
21
+ - 3c4e2ba: Add REST-backed Aegis Engine markets and indexed positions (open + display; repay/redeem/close/withdraw remain deferred), protocol-correct one-token lend and collateralized borrow, rounded LP-debt carry estimates, session-safe caching, and duplicate-submit protection.
22
+
23
+ Bundle the Engine protocol implementation into public Core output so widget
24
+ consumers do not need private-registry credentials.
25
+
26
+ Also remove the unused `showPoolLink` widget prop (playground shared links that still carry it continue to parse; the key is ignored). Use host CSS or trade-details content if a pool explorer chip is still required.
27
+
28
+ - 3c4e2ba: Highlight fresh, authoritative Engine fee surges in the market hero with the
29
+ observed trading-fee multiplier, while suppressing manual-override,
30
+ contract-inconsistent, and stale fee observations.
31
+ - 2202655: Guard submission re-entry and keep reduced-motion/embed behavior honest.
32
+
33
+ - Double-clicking the swap CTA can no longer launch two parallel swap flows
34
+ with duplicate wallet prompts (both widgets).
35
+ - The "Connect wallet" click only connects; it no longer falls through into
36
+ the swap flow when an amount was already typed.
37
+ - Token/chain selection is inert while a swap is in flight, a pending native
38
+ Max fill is invalidated by typing/selection/submit, and an out-of-range
39
+ `defaultSlippagePercent` falls back to 1% instead of bricking the CTA.
40
+ - Reduced-motion polish: network dropdown and rail fade instead of snapping,
41
+ the chain-select flash cleans up its state, and long token symbols truncate
42
+ instead of crushing the amount input. Network menu state classes became
43
+ data attributes so host CSS can't collide; viem peer floor is `^2.23.1`.
44
+
45
+ - 2202655: Add USD-aware swap fields, balance-loading states, a settings menu, and token-picker polish.
46
+
47
+ - Show amount and wallet USD values when pricing is available, while hiding invalid amount estimates.
48
+ - Keep backend market loading states honest and avoid contradictory no-pool CTAs during discovery.
49
+ - Move slippage and approval controls into the header settings menu and add single-action token-dialog network switching.
50
+
51
+ ### Patch Changes
52
+
53
+ - Updated dependencies [3c4e2ba]
54
+ - Updated dependencies [3c4e2ba]
55
+ - Updated dependencies [2202655]
56
+ - Updated dependencies [2202655]
57
+ - @aegis-engine/core@0.3.0
58
+
59
+ ## 0.4.0
60
+
61
+ ### Minor Changes
62
+
63
+ - 51a71c0: Update the React widget to consume the backend-aligned Core contract, refresh network and token controls, improve accessibility and receipt/status presentation, and harden package exports/declaration health.
64
+
65
+ ### Patch Changes
66
+
67
+ - Updated dependencies [28c52c3]
68
+ - @aegis-engine/core@0.2.0
69
+
3
70
  ## 0.3.5
4
71
 
5
72
  ### Patch Changes
package/DESIGN.md CHANGED
@@ -18,15 +18,26 @@ text), and no neutral is pure black or white. Derived accent tints
18
18
  `color-mix(in srgb, …)`, so a host can override `--aegis-swap-accent` with **any**
19
19
  CSS color (hex, `rgb()`, `oklch()`, …) and the whole accent system recomputes.
20
20
 
21
+ The `baseColor` prop regenerates this entire neutral ramp at runtime from one
22
+ surface color (`deriveBasePalette`, also exported): every step adopts the base
23
+ hue with capped chroma, lightness follows the same hand-tuned envelope
24
+ relative to the new bg, and the text steps are re-solved until primary text
25
+ holds APCA Lc ≥ 90 / WCAG ≥ 7:1 on the panels and muted/subtle hold ≥ 4.5:1 on
26
+ every surface — so the guarantees above survive arbitrary host input. Values
27
+ are emitted as inline `oklch()` variables for the resolved theme; explicit
28
+ `--aegis-swap-*` overrides in `style` win over derived ones.
29
+
21
30
  | Token | Role |
22
31
  | --- | --- |
23
32
  | `--aegis-swap-accent` | CTA, selected pool, focus ring, links. Host's primary knob. |
24
33
  | `--aegis-swap-accent-text` | Text on the accent CTA. Auto-derived from `accentColor`; override with `accentTextColor`. |
34
+ | `--aegis-swap-accent-ink` | Accent used *as text on a panel* (quick-fill chips, selected pills, status links, market rate). Resolves to `--aegis-swap-accent-readable` — emitted from `accentColor` only when the raw accent falls under 4.5:1 on the panels — and falls back to the accent itself. |
25
35
  | `--aegis-swap-success` | Terminal success fill (rail, toast). |
26
36
  | `--aegis-swap-danger` | Error fill and inline error text. |
27
37
  | `--aegis-swap-bg` / `--aegis-swap-panel` / `--aegis-swap-panel-raised` / `--aegis-swap-panel-soft` | Surface ramp, darkest → most raised. |
28
38
  | `--aegis-swap-text` / `--aegis-swap-muted` / `--aegis-swap-subtle` | Text ramp, primary → tertiary. |
29
39
  | `--aegis-swap-border` / `--aegis-swap-border-strong` | Hairline and emphasized borders. |
40
+ | `--aegis-swap-bg-hi` / `--aegis-swap-bg-mid` / `--aegis-swap-bg-lo` | Card-gradient stops ("lit from the top" spread of the bg family). |
30
41
  | `--aegis-swap-font-family` | Font family; the widget does **not** inherit the host font by default. |
31
42
 
32
43
  `theme="light"` swaps the surface/text/border/danger ramp; `accent`/`success`
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
- # Aegis Swap Widget
1
+ # Amplifi Swap and Aegis Engine Widget
2
2
 
3
- Embeddable React swap widget for Aegis direct pools. Import the component, import the CSS, and configure pools, wallet handoff, and host styling through props.
3
+ Embed Amplifi Swap or Aegis Engine directly in a React application. Import the
4
+ component and CSS, then configure networks, REST data, wallet handoff, and host
5
+ styling through props.
4
6
 
5
7
  The host app normally only renders `<AegisSwapWidget />`. Quoting, token approval, Permit2 signing, and swap submission are handled inside the widget.
6
8
 
@@ -21,7 +23,9 @@ npm install aegis-swap-widget
21
23
 
22
24
  Peer dependencies (provided by the host app): `react >=18 <20`, `react-dom >=18 <20`,
23
25
  and `viem ^2`. The package is ESM-only. Its only runtime dependencies are
24
- `@aegis-engine/core` (the swap engine) and `lucide-react` (icons).
26
+ `@aegis-engine/core` and its protocol dependencies.
27
+ The published packages are self-contained: host applications do not need a
28
+ GitHub Packages token for the Engine SDK.
25
29
 
26
30
  ## Basic Usage
27
31
 
@@ -34,7 +38,144 @@ export function Swap() {
34
38
  }
35
39
  ```
36
40
 
37
- Without a `pools` prop, the widget uses the bundled Aegis WATER, WOOD, GRASS, and STONE pool configs. For production integrations, pass the pools the host app wants to expose.
41
+ ## Engine usage
42
+
43
+ ```tsx
44
+ import { AegisEngineWidget } from 'aegis-swap-widget'
45
+ import 'aegis-swap-widget/styles.css'
46
+
47
+ export function Engine({ account, provider }) {
48
+ return (
49
+ <AegisEngineWidget
50
+ account={account}
51
+ provider={provider}
52
+ defaultSurface="buy"
53
+ showTokenPriceHistory
54
+ showEngineMarketHistory
55
+ surfaces={['buy', 'borrow', 'lend', 'positions']}
56
+ />
57
+ )
58
+ }
59
+ ```
60
+
61
+ The Engine discovery surface defaults to Amplifi's public production REST API.
62
+ The production source implements
63
+ `GET /v1/engine/markets?chainId=`,
64
+ `GET /v1/engine/positions/v2?chainId=&account=`, and
65
+ `GET /v1/engine/positions/activity?chainId=&account=`, and
66
+ `GET /v1/engine/markets/{marketId}/history?window=30d`. Position reads prefer
67
+ v2 so borrow vaults and indexed lender shares are returned together, then fall
68
+ back to the frozen v1 positions route only when v2 returns `404`. The UI labels
69
+ that fallback as borrow-vault-only coverage. For REST sources, the Borrow tail
70
+ also recovers the selected vault's latest indexed transaction from the activity
71
+ ledger; missing activity stays display-only and never blocks quoting. When a
72
+ host supplies a custom REST `engineDataSource`, an omitted `backendBaseUrl`
73
+ inherits the same base URL for
74
+ the nested Buy surface and token-price history. That origin must also expose
75
+ `/v1/config`, `/v1/markets`, `/v1/tokens`, and the token-history route.
76
+
77
+ `showTokenPriceHistory` is a separate, display-only opt-in. It reads the active
78
+ token's price window (`tokenPriceHistoryWindow`, default `30d`) from
79
+ `GET /v1/tokens/{chainId}/{address}/price-history` through `backendBaseUrl` and
80
+ renders only when at least two usable points and a current market/token USD
81
+ price are available. Missing, warming, or malformed history fails soft. The
82
+ latest history bucket is never treated as the executable current price.
83
+ The active token is the direct-pool target, aggregated-swap output, Engine lend
84
+ deposit, or Engine borrow output for the current surface.
85
+
86
+ `showEngineMarketHistory` is another display-only opt-in and defaults to
87
+ `false`. In Lend or Borrow, the Details view renders the selected market's
88
+ 12-hour observations from the Engine history endpoint. The series follows
89
+ `defaultEngineMarketHistoryMetric` (default `'rate'`): lend APY / borrow APR,
90
+ shared utilization, or mode-aware liquidity (`suppliedUsd` vs
91
+ `availableToBorrowUsd`). The fetch window is
92
+ `defaultEngineMarketHistoryWindow` (default `'30d'`). The widget exposes
93
+ loading, `warming_up`, `no_data`, incomplete, and unavailable states without
94
+ blocking quotes or transactions. Current market details also preserve the
95
+ backend's rate, fee, surge, and freshness fields; `surgeActive` is authoritative
96
+ and is not inferred from `inCapEvent`.
97
+
98
+ `detailsPlacement` controls where the Lend/Borrow breakdown opens. `'up'`
99
+ (default) keeps the Details summary row in place and raises the breakdown as a
100
+ full-width sheet inside the widget's own bounds — the row stays live and
101
+ pressing it again (or Escape, or tapping the scrim) brings the sheet back down,
102
+ and the widget's height never changes. `'down'` expands the breakdown inline
103
+ below the CTA, growing the widget.
104
+
105
+ A lend or borrow renders one transaction lifecycle card in the form's outcome
106
+ slot: Review (feasible quote) → Pending (in flight) → Confirmed (mined). The
107
+ same before → after metric rows persist across all three states — projected
108
+ values are labeled, the network fee starts as a pre-submit estimate (approvals
109
+ excluded) and flips to the mined fee, and the explorer action is promoted into
110
+ the card header on confirm. `defaultTransactionDetailsOpen` (default `true`)
111
+ sets whether the card's metric breakdown starts expanded; the Details row keeps
112
+ its single trigger for the quote breakdown sheet.
113
+
114
+ Product semantics are deliberately conservative:
115
+
116
+ - A borrow requires an upfront collateral deposit.
117
+ - Carry uses the exact rounded LP-shaped debt from the live SDK quote, not only
118
+ the token value received.
119
+ - Repayment requires both pool tokens; remaining collateral is withdrawn
120
+ separately.
121
+ - A one-token lend becomes a two-sided full-range LP with price and
122
+ impermanent-loss exposure.
123
+ - The widget does not claim borrowing is cheaper than buying without a
124
+ partner-provided returnability/consumption model and duration.
125
+ - Positions are indexed snapshots (open + display). Last-locked LTV is not
126
+ presented as current health. Repay, redeem, close, and withdraw flows are
127
+ deferred and not exposed in the widget.
128
+ - Lender balances are indexed Engine share units, not token amounts; the widget
129
+ does not invent a token/USD value without a current share price.
130
+
131
+ The Engine widget loads market discovery from the production REST API unless a
132
+ host supplies `engineDataSource`. Static or offline Engine integrations use
133
+ `engineDataSource={{ kind: 'static', markets: [...] }}`. Setting
134
+ `backendBaseUrl={null}` disables token-price history and backend reads for the
135
+ nested Buy surface; it does not change Engine market discovery.
136
+
137
+ The backend-enabled network list comes from `GET /v1/config` (`chains[]`). By
138
+ default the widget exposes every backend chain it can configure. Projects that
139
+ only support a subset should pass `enabledChainIds`; the first entry becomes
140
+ the uncontrolled initial network and the widget only fetches markets for
141
+ enabled chains:
142
+
143
+ ```tsx
144
+ <AegisSwapWidget enabledChainIds={[130]} />
145
+ <AegisSwapWidget enabledChainIds={[1, 8453]} />
146
+ ```
147
+
148
+ Use `pinnedChainIds` when the project supports several chains but wants common
149
+ choices surfaced first in the network selector and token selector. This only changes
150
+ display order; it never enables chains outside `enabledChainIds` or backend
151
+ config:
152
+
153
+ ```tsx
154
+ <AegisSwapWidget enabledChainIds={[1, 130, 8453]} pinnedChainIds={[8453, 1]} />
155
+ ```
156
+
157
+ By default the compact network selector uses the host accent color. Set
158
+ `networkSelectorColorMode="chain"` to use the built-in DFF chain palette
159
+ (Ethereum grey, Unichain pink, Base blue) for selector chrome:
160
+
161
+ ```tsx
162
+ <AegisSwapWidget networkSelectorColorMode="chain" />
163
+ ```
164
+
165
+ The selector renders as a compact chain-icon strip by default. Hosts that prefer
166
+ a single menu trigger can opt into the dropdown presentation without changing
167
+ the enabled network catalog:
168
+
169
+ ```tsx
170
+ <AegisSwapWidget networkSelectorVariant="dropdown" />
171
+ ```
172
+
173
+ The selector sits on the left by default. Use `networkSelectorPosition="right"`
174
+ when the host chrome needs the selector on the trailing edge:
175
+
176
+ ```tsx
177
+ <AegisSwapWidget networkSelectorPosition="right" />
178
+ ```
38
179
 
39
180
  By default the component uses `window.ethereum` when available, so injected wallets
40
181
  like MetaMask and Rabby work without any wallet props.
@@ -56,10 +197,11 @@ belong in the playground app (`apps/playground` in this monorepo). They are not
56
197
  exposed as production widget props, so an embedded widget cannot accidentally
57
198
  run in a fake mode.
58
199
 
59
- Hosts should customize through `pools`, `chains`, `rpcUrls`,
60
- `metadataEndpoint`, wallet/provider callbacks, status surfaces, `accentColor`,
61
- `accentTextColor`, `className`, `style`, `title`, and `subtitle`. The widget is
62
- meant to blend into a host app without forking its internals.
200
+ Hosts should customize through `backendBaseUrl`, `pools`, `chains`, `rpcUrls`,
201
+ `metadataEndpoint`, `showTokenPriceHistory`, `showEngineMarketHistory`,
202
+ wallet/provider callbacks, status surfaces, `accentColor`, `accentTextColor`,
203
+ `className`, `style`, `title`, and `subtitle`. The widget is meant to blend into
204
+ a host app without forking its internals.
63
205
 
64
206
  Treat contract addresses as trusted integration config. Pool and chain config
65
207
  can provide `router`, `permit2`, `quoter`, `poolKey`, and `poolId`; the widget
@@ -79,15 +221,19 @@ Hosts can choose the widget surface and brand accent at instantiation time:
79
221
 
80
222
  ```tsx
81
223
  <AegisSwapWidget
82
- theme="light"
83
- accentColor="#006adc"
84
- accentTextColor="#ffffff"
224
+ theme="dark"
225
+ accentColor="#7c5cff"
226
+ baseColor="#16121f"
85
227
  />
86
228
  ```
87
229
 
88
230
  `theme` supports `dark`, `light`, or `auto` (which follows the host's `prefers-color-scheme`). `accentColor` accepts any CSS color value and is used for the CTA, selected pools, focus states, links, and swap controls. The widget auto-derives a readable CTA text color from `accentColor` — for hex, `rgb()`, and `hsl()` values everywhere, and for any CSS color (named, `oklch()`, …) in the browser. `accentTextColor` overrides that and is the deterministic choice when you want an exact CTA text color (or are rendering a named/`oklch()` accent during SSR).
89
231
 
90
- The default accent is neutral green. Pass `accentColor`, `accentTextColor`, `title`, `subtitle`, `className`, or `style` when the widget should blend into another product UI.
232
+ `accentColor` is applied verbatim, so wide-gamut values (`color(display-p3 …)`, high-chroma `oklch()`) render in P3 where the display supports it — only the auto-derived text/ink variants are computed in sRGB, which is safe because they solve contrast, not vibrancy.
233
+
234
+ `baseColor` re-themes the whole neutral family — background, panels, borders, text, and the card gradient — from one surface color. The ramp is derived in OKLCH against the widget's hand-tuned lightness envelope: every step adopts the base hue, chroma is capped so a saturated input yields a tinted surface rather than a neon one, lightness is clamped into the active theme's band, and the text steps are solved until they pass their contrast targets (primary text ≥ APCA Lc 90 / WCAG 7:1 on the panels; secondary text ≥ 4.5:1 everywhere) — arbitrary input cannot produce unreadable text. The same color-format rules as `accentColor` apply (named/`oklch()` inputs resolve in the browser only). Individual `--aegis-swap-*` variables passed through `style` still override any derived value, and `deriveBasePalette(baseColor, 'dark' | 'light')` is exported for hosts that want the computed variables themselves (e.g. to inline them during SSR).
235
+
236
+ The default accent is neutral green on a green-tinted dark surface. Pass `accentColor`, `baseColor`, `accentTextColor`, `title`, `subtitle`, `className`, or `style` when the widget should blend into another product UI.
91
237
 
92
238
  The default palette is authored in OKLCH (tinted neutrals, a calmer accent). The
93
239
  full set of host-overridable CSS variables — color, motion, rail, and toast
@@ -95,9 +241,12 @@ tokens — is documented in [DESIGN.md](./DESIGN.md).
95
241
 
96
242
  ## Configure Pools
97
243
 
98
- Out of the box, `<AegisSwapWidget />` exposes the bundled WATER, WOOD, GRASS,
99
- and STONE mainnet pools. Use `poolIds` when a host wants a different built-in
100
- pool order or subset:
244
+ Out of the box, `<AegisSwapWidget />` exposes the enabled markets returned by
245
+ the Aegis backend for the active chain. Use `enabledChainIds` when a project
246
+ should expose only some backend-enabled networks, and use `poolIds` when a host
247
+ wants a different backend-market order or subset. Pass `backendBaseUrl={null}`
248
+ when those ids should resolve against the bundled static WATER, WOOD, GRASS,
249
+ and STONE mainnet pools:
101
250
 
102
251
  ```tsx
103
252
  import { AegisSwapWidget } from 'aegis-swap-widget'
@@ -106,6 +255,7 @@ import 'aegis-swap-widget/styles.css'
106
255
  export function Swap() {
107
256
  return (
108
257
  <AegisSwapWidget
258
+ backendBaseUrl={null}
109
259
  defaultPoolId="WATER_USDC"
110
260
  poolIds={['WATER_USDC', 'WOOD_USDC', 'GRASS_USDC', 'STONE_USDC']}
111
261
  theme="dark"
@@ -323,7 +473,9 @@ The widget fetches token icons by address using the metadata IDs from the Aegis
323
473
  />
324
474
  ```
325
475
 
326
- Use `metadataEndpoint={null}` to disable backend icon hydration. Tokens can also provide `iconUrl` directly.
476
+ Use `metadataEndpoint={null}` to disable backend icon hydration. It does not
477
+ disable token-price history, which uses `backendBaseUrl`. Tokens can also
478
+ provide `iconUrl` directly.
327
479
 
328
480
  ## With Existing Wallet UI
329
481
 
@@ -381,7 +533,7 @@ Use `className` for host CSS selectors and `style` for one-off layout overrides
381
533
  />
382
534
  ```
383
535
 
384
- `accentColor`, `accentTextColor`, `title`, and `subtitle` are the intended props for making the widget fit a host surface without forking the component.
536
+ `accentColor`, `baseColor`, `accentTextColor`, `title`, and `subtitle` are the intended props for making the widget fit a host surface without forking the component.
385
537
 
386
538
  ## Transaction Status
387
539
 
@@ -516,9 +668,10 @@ import 'aegis-swap-widget/styles.css'
516
668
  ```
517
669
 
518
670
  `AegisSwapToaster` props: `position` (`top`/`bottom` × `left`/`center`/`right`,
519
- default `'bottom-right'`), `theme`/`accentColor`/`accentTextColor` (the toaster
520
- portals to `document.body`, so widget-root accent variables do not reach it —
521
- pass these props or set `--aegis-swap-accent` and friends on `:root`),
671
+ default `'bottom-right'`), `theme`/`accentColor`/`accentTextColor`/`baseColor`
672
+ (the toaster portals to `document.body`, so widget-root accent and ramp
673
+ variables do not reach it — pass these props or set `--aegis-swap-accent` and
674
+ friends on `:root`),
522
675
  `duration` (auto-dismiss for info/success, default 5000ms), `visibleToasts`
523
676
  (default 3), `closeButton` (default `false` — swipe and auto-dismiss always
524
677
  work), `expand` (always-expanded list instead of the hover-expanded stack),
@@ -605,23 +758,34 @@ No other props changed. See the [CHANGELOG](./CHANGELOG.md) for the full entry.
605
758
  - `onPoolChange`: `(poolId)` fired when the active pool changes — user selection or a `poolIds` update that forces a fallback. Silent on mount.
606
759
  - `chainId`: active chain id. Defaults to Ethereum mainnet.
607
760
  - `chains`: optional chain config overrides or additional chain configs, including per-chain `v4Contracts`.
608
- - `networkOptions`: optional display-only entries for the network menu (`{ id, name, icon?, selected?, disabled?, status? }`). The active entry is resolved by explicit `selected: true`, else by `id` matching the active chain id, else by `name`; a list without the active chain gets it prepended so the trigger never misreports the chain in use. Non-selected options render disabled by default with optional `status` text (e.g. "Coming soon"); `icon` is `'ethereum' | 'base'`. Clicking the enabled option only closes the menu (disabled options ignore clicks) — switching is not wired yet.
761
+ - `enabledChainIds`: backend-discovered chain ids this host project exposes. Omit to use every backend chain the widget can configure.
762
+ - `pinnedChainIds`: preferred chain ids to surface first in backend-derived network selectors and token selector filters. This only changes display order.
763
+ - `networkOptions`: optional entries for the network selector (`{ id, name, icon?, selected?, disabled?, status? }`). The active entry is resolved by id/name, and a list without the active chain gets it prepended so the selector never misreports the chain in use. Non-selected options are enabled only when chain switching is wired through backend discovery or `onChainChange`; `icon` is `'ethereum' | 'base' | 'unichain'`.
764
+ - `networkSelectorVariant`: `'icons'` (default) renders the compact chain-icon strip; `'dropdown'` renders a menu button/listbox for hosts that prefer a single trigger.
765
+ - `networkSelectorPosition`: `'left'` (default) places the selector on the leading side of the widget chrome; `'right'` places it on the trailing side.
766
+ - `networkSelectorColorMode`: `'accent'` (default) keeps host-brand selector chrome; `'chain'` uses the built-in DFF chain palette for supported chains.
609
767
  - `pools`: direct pool configs to render and swap against. This is the canonical config path.
610
768
  - `defaultPoolId`: initial pool id when `pools` is provided.
611
769
  - `poolIds`: optional pool id order/subset. Use this when the host wants to hide pools or control ordering.
612
770
  - `defaultDirection`: `buy` (counter token into the pool token) or `sell` (pool token into the counter token). Defaults to `buy`.
613
771
  - `defaultSlippagePercent`: number (canonical) or numeric string, in percent. Defaults to `1`.
614
772
  - `rpcUrls`: RPC fallback list for the active chain, or a `{ [chainId]: string[] }` map for multichain hosts.
615
- - `metadataEndpoint`: optional metadata GraphQL endpoint for `GlobalToken.iconURL` token icons. Set to `null` to disable.
773
+ - `backendBaseUrl`: REST origin for Swap discovery and token-price history, and for the Engine widget's nested Buy surface. Defaults to the Aegis production backend. Engine market and position discovery is controlled separately by `engineDataSource`.
774
+ - `backendRequestTimeoutMs`: timeout for backend REST reads. Defaults to 30000 ms.
775
+ - `metadataEndpoint`: optional metadata GraphQL endpoint for `GlobalToken.iconURL` token icons only. Set to `null` to disable icon hydration.
776
+ - `showTokenPriceHistory`: display a compact, fail-soft USD history for the active token through `backendBaseUrl`. Defaults to `false`.
777
+ - `tokenPriceHistoryWindow`: `'7d' | '30d' | '90d' | '180d'` fetch/display window when token history is on. Defaults to `'30d'`. There is no in-widget window selector.
616
778
  - `className`: optional class for host layout and styling hooks.
617
779
  - `style`: optional root style object, useful for host layout constraints or CSS variables.
618
- - `title`: optional widget heading. Empty by default (compact topbar, no header row).
780
+ - `title`: optional widget heading. Swap and Engine default to empty for compact embedded chrome.
781
+ - `showNetworkSelector`: Engine header-network visibility: `'never'` (default), `'auto'`, or `'always'`. Cross-chain markets and tokens remain available in the full selectors when the header rail is hidden.
782
+ - `showBuySettings`: show the Engine Buy surface's slippage-settings control. Defaults to `false`.
619
783
  - `subtitle`: optional header eyebrow. Defaults to empty. Pass a string to show it.
620
- - `ariaLabel`: optional accessible label for the widget region.
784
+ - `ariaLabel`: optional accessible label for the widget region. Defaults to `Swap` for Swap and `Lend, borrow, and buy` for Engine.
621
785
  - `theme`: `dark`, `light`, or `auto` (follows `prefers-color-scheme`). Defaults to `dark`.
622
786
  - `accentColor`: CSS accent color for the CTA, selected pools, focus states, links, and swap controls. When set without `accentTextColor`, the widget derives a readable CTA text color automatically (see Appearance for supported color formats).
623
787
  - `accentTextColor`: optional CTA text color for contrast with the chosen accent.
624
- - `showPoolLink`: whether to render the direct-pool link when the active chain provides `poolExplorerUrl`.
788
+ - `baseColor`: CSS base surface color; derives the full neutral ramp (background, panels, borders, text, card gradient) in OKLCH for the active theme with contrast enforced (see Appearance).
625
789
  - `defaultApprovalMode`: `exact` approves only the current quote spend by default; `max` opts into the old unlimited ERC-20 to Permit2 approval behavior.
626
790
  - `showApprovalMode`: whether the details drawer exposes the Exact/Max approval toggle. Defaults to `true`.
627
791
  - `showExecutionDetails`: whether to render the collapsible drawer for trade details and, after a confirmed swap, the session-local Latest tx receipt. Defaults to `true`.
package/dist/address.d.ts CHANGED
@@ -2,4 +2,11 @@ import type { Address, Hex } from 'viem';
2
2
  export declare function addressKey(address: Address | null | undefined): string;
3
3
  export declare function sameAddress(a: Address, b: Address): boolean;
4
4
  export declare function sameOptionalAddress(a: Address | null, b: Address | null): boolean;
5
+ export type TokenIdentity = {
6
+ chainId: number;
7
+ address: Address;
8
+ };
9
+ export declare function tokenIdentityKey(token: TokenIdentity): string;
10
+ export declare function sameTokenIdentity(a: TokenIdentity | null, b: TokenIdentity | null): boolean;
5
11
  export declare function samePoolId(a: Hex, b: Hex): boolean;
12
+ export declare function truncateHex(value: string): string;