aegis-swap-widget 0.1.2 → 0.2.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 (46) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/LICENSE +21 -0
  3. package/README.md +101 -24
  4. package/dist/abis.d.ts +18 -1
  5. package/dist/address.d.ts +5 -0
  6. package/dist/aegis-swap-widget.js +2423 -1014
  7. package/dist/color.d.ts +2 -0
  8. package/dist/components/icons.d.ts +23 -0
  9. package/dist/config.d.ts +3 -2
  10. package/dist/encoding.d.ts +5 -1
  11. package/dist/errors.d.ts +2 -0
  12. package/dist/format.d.ts +3 -3
  13. package/dist/hooks/useResolvedTheme.d.ts +3 -0
  14. package/dist/hooks/useScrollAnchor.d.ts +12 -0
  15. package/dist/hooks/useStableValue.d.ts +2 -0
  16. package/dist/hooks/useSubmitSwap.d.ts +66 -0
  17. package/dist/hooks/useSwapQuote.d.ts +30 -0
  18. package/dist/hooks/useTokenAllowance.d.ts +24 -0
  19. package/dist/hooks/useTokenBalances.d.ts +15 -0
  20. package/dist/hooks/useTokenIconMetadata.d.ts +7 -0
  21. package/dist/hooks/useWalletConnection.d.ts +18 -0
  22. package/dist/index.d.ts +6 -42
  23. package/dist/metadata.d.ts +0 -1
  24. package/dist/permit.d.ts +24 -1
  25. package/dist/polling.d.ts +2 -0
  26. package/dist/quote.d.ts +30 -2
  27. package/dist/styles.css +1 -1
  28. package/dist/transactionProgress.d.ts +18 -0
  29. package/dist/wallet.d.ts +19 -8
  30. package/dist/widget/AegisDirectSwapWidget.d.ts +4 -0
  31. package/dist/widget/AmountField.d.ts +17 -0
  32. package/dist/widget/ExecutionDetails.d.ts +29 -0
  33. package/dist/widget/NetworkSelector.d.ts +3 -0
  34. package/dist/widget/PoolSelector.d.ts +13 -0
  35. package/dist/widget/types.d.ts +66 -0
  36. package/dist/widget/viewState.d.ts +54 -0
  37. package/package.json +40 -8
  38. package/dist/abis.d.ts.map +0 -1
  39. package/dist/config.d.ts.map +0 -1
  40. package/dist/encoding.d.ts.map +0 -1
  41. package/dist/format.d.ts.map +0 -1
  42. package/dist/index.d.ts.map +0 -1
  43. package/dist/metadata.d.ts.map +0 -1
  44. package/dist/permit.d.ts.map +0 -1
  45. package/dist/quote.d.ts.map +0 -1
  46. package/dist/wallet.d.ts.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,82 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2026-06-05
11
+
12
+ ### Added
13
+ - Premium embeddable swap surface with collapsible trade details, route chip, token icons,
14
+ Ethereum light/dark assets, and host-controlled execution details.
15
+ - Exact-vs-max approval mode support, defaulting to exact approvals with Permit2 fallback.
16
+ - Wallet, quote, allowance, balance, token icon, and submit hooks split out of the widget
17
+ entrypoint for a smaller public surface and easier testing.
18
+ - Address, color, error, transaction progress, and widget view-state helpers with tests
19
+ organized under `tests/`.
20
+
21
+ ### Changed
22
+ - The public widget entrypoint now delegates to focused widget modules instead of carrying
23
+ the entire implementation in `src/index.tsx`.
24
+ - Quote and router encoding paths are hardened around calldata construction, stale quote
25
+ handling, and direct-pool route metadata.
26
+ - Pool, wallet, metadata, and config inputs are normalized more defensively for host apps.
27
+ - The default approval mode is `exact`; hosts can still opt into `max`.
28
+
29
+ ### Deprecated
30
+ - `targets` remains available as a backwards-compatible alias for `poolIds` and will be
31
+ removed in `0.3.0`.
32
+
33
+ ## [0.1.3] - 2026-06-05
34
+
35
+ ### Added
36
+ - Per-chain internal fee: `fee` field on `AegisSwapChainConfig`, so the output-token
37
+ fee applies to any bundled chain that sets one (mainnet keeps its 50 bps fee).
38
+ - Package metadata (`license`, `repository`, `homepage`, `bugs`, `keywords`) and a
39
+ `LICENSE` file (MIT).
40
+ - Test suite (Vitest) covering the quote/encoding money-path, formatting, and config
41
+ factories, plus a GitHub Actions CI workflow (typecheck + test + build).
42
+ - `prepack` build hook and a `prepublishOnly` typecheck + test gate so published
43
+ tarballs always contain a fresh build.
44
+
45
+ ### Changed
46
+ - `resolveWidgetFee` now reads the per-chain `fee` from the resolved chain config
47
+ instead of hardcoding Ethereum mainnet. Default mainnet behavior is unchanged.
48
+ - Swap submission re-quotes immediately before building calldata so the on-chain
49
+ `amountOutMinimum`/`amountInMaximum` reflect the current price, not a stale quote.
50
+ - After switching the wallet network, submission waits for the switch to settle and
51
+ continues the swap automatically instead of forcing a second click.
52
+ - `viem` moved from `dependencies` to `peerDependencies` (it was already externalized
53
+ from the bundle).
54
+
55
+ ### Removed
56
+ - `dist/` build artifacts are no longer committed to git (rebuilt on pack/publish).
57
+
58
+ ## [0.1.2] - 2026-06-04
59
+
60
+ > Note: the published 0.1.2 tarball was cut before commit `31f01fa`
61
+ > ("Round displayed token amounts"); that change first reaches consumers in the
62
+ > next published version.
63
+
64
+ ### Added
65
+ - Adjustable internal widget swap fee, fixed to Ethereum mainnet (50 bps).
66
+ - Exact-output swaps and a 5-second quote refresh.
67
+ - Per-chain Uniswap v4 contract config (`UNISWAP_V4_CONTRACTS_BY_CHAIN`).
68
+
69
+ ### Changed
70
+ - Display token amounts are rounded (local only; not in the published 0.1.2 tarball).
71
+
72
+ ## [0.1.0] - 2026-06-04
73
+
74
+ ### Added
75
+ - Initial embeddable direct-pool Aegis swap widget for WATER, WOOD, GRASS, and STONE.
76
+ - Generic pool widget API; ERC-20 → Permit2 approval and Permit2 batch signing.
77
+
78
+ [Unreleased]: https://github.com/amplifi-liquidity/aegis-widget/compare/v0.2.0...HEAD
79
+ [0.2.0]: https://github.com/amplifi-liquidity/aegis-widget/compare/v0.1.3...v0.2.0
80
+ [0.1.3]: https://github.com/amplifi-liquidity/aegis-widget/compare/v0.1.2...v0.1.3
81
+ [0.1.2]: https://github.com/amplifi-liquidity/aegis-widget/compare/v0.1.0...v0.1.2
82
+ [0.1.0]: https://github.com/amplifi-liquidity/aegis-widget/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aegis Swap Widget contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,16 +1,17 @@
1
1
  # Aegis Swap Widget
2
2
 
3
- Embeddable React swap widget for Aegis direct pools. It does not import the private Aegis Engine SDK and does not use Uniswap widget packages.
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.
4
4
 
5
- The widget quotes the configured Uniswap v4 pool, handles ERC20 approval to Permit2, signs a Permit2 batch for the Aegis router, and submits the direct pool swap.
5
+ The host app normally only renders `<AegisSwapWidget />`. Quoting, token approval, Permit2 signing, and swap submission are handled inside the widget.
6
6
 
7
7
  Typing in the Sell field creates an exact-input swap. Typing in the Buy field
8
8
  creates an exact-output swap. Active quotes refresh every five seconds while the
9
9
  amount is valid.
10
10
 
11
- On Ethereum mainnet, widget swaps apply a fixed 50 bps output-token fee to
12
- `0x8ea2C7de60ef1Cd4dcE64ea2DDDe2f99F0127eFC`. The widget does not apply this
13
- fee on other chains yet.
11
+ Widget swaps apply an internal output-token fee per configured chain. The bundled
12
+ Ethereum mainnet config carries a fixed 50 bps fee to
13
+ `0x8ea2C7de60ef1Cd4dcE64ea2DDDe2f99F0127eFC`. A chain carries a fee only when its
14
+ bundled config sets one; today only Ethereum mainnet is bundled.
14
15
 
15
16
  ## Install
16
17
 
@@ -25,12 +26,7 @@ import { AegisSwapWidget } from 'aegis-swap-widget'
25
26
  import 'aegis-swap-widget/styles.css'
26
27
 
27
28
  export function Swap() {
28
- return (
29
- <AegisSwapWidget
30
- theme="dark"
31
- accentColor="#31d48a"
32
- />
33
- )
29
+ return <AegisSwapWidget />
34
30
  }
35
31
  ```
36
32
 
@@ -55,7 +51,9 @@ Hosts can choose the widget surface and brand accent at instantiation time:
55
51
  />
56
52
  ```
57
53
 
58
- `theme` supports `dark` and `light`. `accentColor` accepts any CSS color value and is used for the CTA, selected pools, focus states, links, and swap controls. `accentTextColor` is optional and only needed when the accent color needs a different CTA text color for contrast.
54
+ `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).
55
+
56
+ The default accent is neutral green. Pass `accentColor`, `accentTextColor`, `title`, `subtitle`, `className`, or `style` when the widget should blend into another product UI.
59
57
 
60
58
  ## Configure Pools
61
59
 
@@ -86,24 +84,27 @@ export function Swap() {
86
84
  }
87
85
  ```
88
86
 
89
- Use `defaultPoolId` to choose which pool opens first. Use `targets` when a host wants a different pool order or subset:
87
+ Use `defaultPoolId` to choose which pool opens first. Use `poolIds` when a host wants a different pool order or subset:
90
88
 
91
89
  ```tsx
92
90
  <AegisSwapWidget
93
91
  pools={pools}
94
92
  defaultPoolId="GRASS_USDC"
95
- targets={['GRASS_USDC', 'WATER_USDC']}
93
+ poolIds={['GRASS_USDC', 'WATER_USDC']}
96
94
  />
97
95
  ```
98
96
 
99
97
  ## Fees
100
98
 
101
- The widget applies a fixed output-token fee only on Ethereum mainnet:
99
+ The widget applies an internal output-token fee per chain. Each bundled chain config
100
+ carries its own fee. Today only Ethereum mainnet is bundled:
102
101
 
103
102
  - Fee: `50` bps
104
103
  - Recipient: `0x8ea2C7de60ef1Cd4dcE64ea2DDDe2f99F0127eFC`
105
104
 
106
- This fee is internal to the widget and is not configured by host sites.
105
+ This fee is internal to the widget and is not configured by host sites — host `chains`
106
+ overrides cannot set or change it. Chains added later carry a fee only when their
107
+ bundled config provides one.
107
108
 
108
109
  For custom assets, provide full pool and token metadata:
109
110
 
@@ -255,24 +256,79 @@ host connect modal creates the provider during the button click:
255
256
  If none of these props are supplied, the widget still checks `window.ethereum`
256
257
  automatically when it renders and again when the user clicks connect/swap.
257
258
 
259
+ ## UI Integration
260
+
261
+ Use `className` for host CSS selectors and `style` for one-off layout overrides or CSS variables:
262
+
263
+ ```tsx
264
+ <AegisSwapWidget
265
+ className="partner-swap"
266
+ style={{ maxWidth: 520 }}
267
+ title="Swap"
268
+ subtitle="Aegis direct pools"
269
+ ariaLabel="Partner swap"
270
+ />
271
+ ```
272
+
273
+ `accentColor`, `accentTextColor`, `title`, and `subtitle` are the intended props for making the widget fit a host surface without forking the component.
274
+
258
275
  ## Props
259
276
 
260
277
  - `provider`: optional EIP-1193 provider. Defaults to auto-detected `window.ethereum`.
261
278
  - `account`: optional connected account from the host wallet UI.
262
279
  - `getProvider`: optional provider resolver for wallet libraries with async providers.
263
280
  - `onConnectWallet`: optional callback for opening the host wallet modal. It may return `{ provider, account }`.
281
+ - `onSubmitted`: `(hash, swap?)` fired when the swap transaction is sent. `swap` carries mode, token symbols, amounts, and fee for analytics.
282
+ - `onSuccess`: `({ hash, explorerUrl, swap? })` fired when the receipt confirms.
283
+ - `onError`: `(error)` fired on approval/swap failures (after the widget shows its own message).
284
+ - `onQuote`: `(quote)` fired on every quote refresh.
264
285
  - `chainId`: active chain id. Defaults to Ethereum mainnet.
265
286
  - `chains`: optional chain config overrides or additional chain configs, including per-chain `v4Contracts`.
266
- - `pools`: direct pool configs to render and swap against.
287
+ - `pools`: direct pool configs to render and swap against. This is the canonical config path.
267
288
  - `defaultPoolId`: initial pool id when `pools` is provided.
268
- - `targets`: optional pool id order/subset.
269
- - `defaultDirection`: `intoTarget` for USDC to target, or `outOfTarget` for target to USDC.
270
- - `markets`: advanced override for normalized pool/router/quoter config.
271
- - `rpcUrls`: optional RPC fallback list for the active chain.
289
+ - `poolIds`: optional pool id order/subset. Use this when the host wants to hide pools or control ordering.
290
+ - `defaultDirection`: `buy` (counter token into the pool token) or `sell`. The legacy `intoTarget`/`outOfTarget` values still work but are deprecated.
291
+ - `markets`: **deprecated** advanced override; pass `pools` (or `Object.values(markets)`) instead.
292
+ - `defaultSlippagePercent`: number (canonical) or numeric string, in percent. Defaults to `1`.
293
+ - `rpcUrls`: RPC fallback list for the active chain, or a `{ [chainId]: string[] }` map for multichain hosts.
272
294
  - `metadataEndpoint`: optional metadata GraphQL endpoint for `GlobalToken.iconURL` token icons. Set to `null` to disable.
273
- - `theme`: `dark` or `light`. Defaults to `dark`.
274
- - `accentColor`: CSS accent color for the CTA, selected pools, focus states, links, and swap controls.
295
+ - `className`: optional class for host layout and styling hooks.
296
+ - `style`: optional root style object, useful for host layout constraints or CSS variables.
297
+ - `title`: optional widget heading. Empty by default (compact topbar, no header row).
298
+ - `subtitle`: optional header eyebrow. Defaults to empty. Pass a string to show it.
299
+ - `ariaLabel`: optional accessible label for the widget region.
300
+ - `theme`: `dark`, `light`, or `auto` (follows `prefers-color-scheme`). Defaults to `dark`.
301
+ - `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).
275
302
  - `accentTextColor`: optional CTA text color for contrast with the chosen accent.
303
+ - `showPoolLink`: whether to render the direct-pool link when the active chain provides `poolExplorerUrl`.
304
+ - `defaultApprovalMode`: `exact` approves only the current quote spend by default; `max` opts into the old unlimited ERC-20 to Permit2 approval behavior.
305
+ - `showApprovalModeControl`: whether the details drawer exposes the Exact/Max approval toggle. Defaults to `true`.
306
+ - `showExecutionDetails`: whether to render the collapsible settings drawer for slippage, approval mode, and route. Defaults to `true`.
307
+ - `defaultExecutionDetailsOpen`: whether that settings drawer starts expanded. Defaults to `false`.
308
+
309
+ The widget intentionally does not inherit the host font; set the
310
+ `--aegis-swap-font-family` CSS variable (via `style` or a stylesheet) to match
311
+ the host typography.
312
+
313
+ ### With wagmi
314
+
315
+ The widget consumes the host's wallet instead of bundling its own connect UI.
316
+ From a wagmi app, derive the EIP-1193 provider from the active connector:
317
+
318
+ ```tsx
319
+ import { useAccount } from 'wagmi'
320
+
321
+ function Swap() {
322
+ const { address, connector } = useAccount()
323
+ return (
324
+ <AegisSwapWidget
325
+ account={address}
326
+ getProvider={async () => (await connector?.getProvider()) ?? null}
327
+ onConnectWallet={openConnectModal}
328
+ />
329
+ )
330
+ }
331
+ ```
276
332
 
277
333
  ## Default Markets
278
334
 
@@ -287,9 +343,30 @@ These use the Aegis mainnet router `0x00581261a1200956ea05d1810fF28ffd66D8E254`
287
343
  and the Ethereum entry in `UNISWAP_V4_CONTRACTS_BY_CHAIN` for Permit2 and the
288
344
  public Uniswap v4 Quoter.
289
345
 
346
+ ## License
347
+
348
+ MIT.
349
+
290
350
  ## Local Demo
291
351
 
292
352
  ```bash
293
- npm install
353
+ npm ci
294
354
  npm run dev
295
355
  ```
356
+
357
+ ## Releasing
358
+
359
+ Maintainer release flow (publishes to npm). `dist/` is not committed — the `prepack`
360
+ hook rebuilds it on every `npm pack`/`npm publish`, and `prepublishOnly` runs the
361
+ typecheck + test gate.
362
+
363
+ ```bash
364
+ git switch main && git pull
365
+ npm ci
366
+ npm run typecheck && npm run test && npm run build
367
+ # Move CHANGELOG [Unreleased] entries under the new version heading.
368
+ npm version patch # e.g. 0.1.2 -> 0.1.3; commits and tags vX.Y.Z
369
+ git push origin main --follow-tags
370
+ npm publish --access public # prepublishOnly gate + prepack build run automatically
371
+ npm view aegis-swap-widget version
372
+ ```
package/dist/abis.d.ts CHANGED
@@ -72,6 +72,24 @@ export declare const AEGIS_ROUTER_ABI: readonly [{
72
72
  readonly outputs: readonly [];
73
73
  }];
74
74
  export declare const PERMIT2_ABI: readonly [{
75
+ readonly type: "function";
76
+ readonly name: "approve";
77
+ readonly stateMutability: "nonpayable";
78
+ readonly inputs: readonly [{
79
+ readonly name: "token";
80
+ readonly type: "address";
81
+ }, {
82
+ readonly name: "spender";
83
+ readonly type: "address";
84
+ }, {
85
+ readonly name: "amount";
86
+ readonly type: "uint160";
87
+ }, {
88
+ readonly name: "expiration";
89
+ readonly type: "uint48";
90
+ }];
91
+ readonly outputs: readonly [];
92
+ }, {
75
93
  readonly type: "function";
76
94
  readonly name: "allowance";
77
95
  readonly stateMutability: "view";
@@ -185,4 +203,3 @@ export declare const UNISWAP_V4_QUOTER_ABI: readonly [{
185
203
  readonly type: "uint256";
186
204
  }];
187
205
  }];
188
- //# sourceMappingURL=abis.d.ts.map
@@ -0,0 +1,5 @@
1
+ import type { Address, Hex } from 'viem';
2
+ export declare function addressKey(address: Address | null | undefined): string;
3
+ export declare function sameAddress(a: Address, b: Address): boolean;
4
+ export declare function sameOptionalAddress(a: Address | null, b: Address | null): boolean;
5
+ export declare function samePoolId(a: Hex, b: Hex): boolean;