aegis-swap-widget 0.1.2 → 0.3.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.
- package/CHANGELOG.md +200 -0
- package/DESIGN.md +77 -0
- package/LICENSE +21 -0
- package/README.md +346 -24
- package/dist/abis.d.ts +18 -1
- package/dist/address.d.ts +5 -0
- package/dist/aegis-swap-widget.js +2716 -1470
- package/dist/color.d.ts +2 -0
- package/dist/components/icons.d.ts +30 -0
- package/dist/config.d.ts +3 -2
- package/dist/core.d.ts +15 -0
- package/dist/core.js +66 -0
- package/dist/encoding.d.ts +5 -1
- package/dist/errors.d.ts +3 -0
- package/dist/format.d.ts +3 -3
- package/dist/hooks/useChangeEmitter.d.ts +25 -0
- package/dist/hooks/useLifecycleToast.d.ts +16 -0
- package/dist/hooks/usePoolChangeEmitter.d.ts +1 -0
- package/dist/hooks/useResolvedTheme.d.ts +4 -0
- package/dist/hooks/useStableValue.d.ts +2 -0
- package/dist/hooks/useStatusChangeEmitter.d.ts +2 -0
- package/dist/hooks/useSubmitSwap.d.ts +75 -0
- package/dist/hooks/useSwapQuote.d.ts +30 -0
- package/dist/hooks/useTokenAllowance.d.ts +27 -0
- package/dist/hooks/useTokenBalances.d.ts +15 -0
- package/dist/hooks/useTokenIconMetadata.d.ts +7 -0
- package/dist/hooks/useValueRefresh.d.ts +1 -0
- package/dist/hooks/useWalletConnection.d.ts +18 -0
- package/dist/index.d.ts +12 -46
- package/dist/metadata.d.ts +8 -1
- package/dist/permit.d.ts +31 -1
- package/dist/polling-BI4pZg8Z.js +1252 -0
- package/dist/polling.d.ts +3 -0
- package/dist/quote.d.ts +30 -2
- package/dist/styles.css +1 -1
- package/dist/swap/authorizePermit.d.ts +30 -0
- package/dist/swap/executeSwapTransaction.d.ts +37 -0
- package/dist/swap/types.d.ts +7 -0
- package/dist/toast/ToastItem.d.ts +33 -0
- package/dist/toast/Toaster.d.ts +31 -0
- package/dist/toast/layout.d.ts +21 -0
- package/dist/toast/state.d.ts +69 -0
- package/dist/toast/swipe.d.ts +23 -0
- package/dist/toast/timer.d.ts +16 -0
- package/dist/toast/toast.d.ts +28 -0
- package/dist/toast/useDocumentVisible.d.ts +6 -0
- package/dist/toast/useToastTimer.d.ts +13 -0
- package/dist/transactionProgress.d.ts +42 -0
- package/dist/wallet.d.ts +19 -8
- package/dist/widget/AegisDirectSwapWidget.d.ts +20 -0
- package/dist/widget/AmountField.d.ts +20 -0
- package/dist/widget/ExecutionDetails.d.ts +27 -0
- package/dist/widget/NetworkSelector.d.ts +6 -0
- package/dist/widget/PoolSelector.d.ts +13 -0
- package/dist/widget/ProgressRail.d.ts +23 -0
- package/dist/widget/types.d.ts +129 -0
- package/dist/widget/useSwapController.d.ts +89 -0
- package/dist/widget/viewState.d.ts +55 -0
- package/package.json +45 -8
- package/dist/abis.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/encoding.d.ts.map +0 -1
- package/dist/format.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/metadata.d.ts.map +0 -1
- package/dist/permit.d.ts.map +0 -1
- package/dist/quote.d.ts.map +0 -1
- package/dist/wallet.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# Aegis Swap Widget
|
|
2
2
|
|
|
3
|
-
Embeddable React swap widget for Aegis direct pools.
|
|
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
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
fee
|
|
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
|
|
|
@@ -18,6 +19,9 @@ fee on other chains yet.
|
|
|
18
19
|
npm install aegis-swap-widget
|
|
19
20
|
```
|
|
20
21
|
|
|
22
|
+
Peer dependencies (provided by the host app): `react >=18 <20`, `react-dom >=18 <20`,
|
|
23
|
+
and `viem ^2`. The package is ESM-only and ships no runtime dependencies of its own.
|
|
24
|
+
|
|
21
25
|
## Basic Usage
|
|
22
26
|
|
|
23
27
|
```tsx
|
|
@@ -25,12 +29,7 @@ import { AegisSwapWidget } from 'aegis-swap-widget'
|
|
|
25
29
|
import 'aegis-swap-widget/styles.css'
|
|
26
30
|
|
|
27
31
|
export function Swap() {
|
|
28
|
-
return
|
|
29
|
-
<AegisSwapWidget
|
|
30
|
-
theme="dark"
|
|
31
|
-
accentColor="#31d48a"
|
|
32
|
-
/>
|
|
33
|
-
)
|
|
32
|
+
return <AegisSwapWidget />
|
|
34
33
|
}
|
|
35
34
|
```
|
|
36
35
|
|
|
@@ -43,6 +42,32 @@ Token icons are hydrated from the same metadata table used by the Aegis website:
|
|
|
43
42
|
`GlobalToken.iconURL` from the Aegis metadata GraphQL API. The default endpoint is
|
|
44
43
|
`https://aegis.markets/graphql/meta`.
|
|
45
44
|
|
|
45
|
+
## Headless Core
|
|
46
|
+
|
|
47
|
+
Use the root import for the React widget and CSS. Use the `/core` entry when a
|
|
48
|
+
host, backend-backed client, or future query layer needs the swap primitives
|
|
49
|
+
without importing the widget UI:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import {
|
|
53
|
+
AEGIS_SWAP_MARKETS,
|
|
54
|
+
createSwapPublicClient,
|
|
55
|
+
fetchDirectSwapQuote,
|
|
56
|
+
} from 'aegis-swap-widget/core'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The core entry exports chain and pool config helpers, quote fetching, calldata
|
|
60
|
+
encoding, Permit2 helpers, wallet/provider utilities, metadata fetchers, and the
|
|
61
|
+
pure transaction-progress helpers. It does not import the React widget or the
|
|
62
|
+
package stylesheet.
|
|
63
|
+
|
|
64
|
+
To render token icons with the widget's exact resolution order (config
|
|
65
|
+
`iconUrl` → metadata endpoint → ICHI guess), use `resolveTokenIconUrl`:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { resolveTokenIconUrl, fetchGlobalTokenMetadata } from 'aegis-swap-widget/core'
|
|
69
|
+
```
|
|
70
|
+
|
|
46
71
|
## Appearance
|
|
47
72
|
|
|
48
73
|
Hosts can choose the widget surface and brand accent at instantiation time:
|
|
@@ -55,7 +80,13 @@ Hosts can choose the widget surface and brand accent at instantiation time:
|
|
|
55
80
|
/>
|
|
56
81
|
```
|
|
57
82
|
|
|
58
|
-
`theme` supports `dark`
|
|
83
|
+
`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).
|
|
84
|
+
|
|
85
|
+
The default accent is neutral green. Pass `accentColor`, `accentTextColor`, `title`, `subtitle`, `className`, or `style` when the widget should blend into another product UI.
|
|
86
|
+
|
|
87
|
+
The default palette is authored in OKLCH (tinted neutrals, a calmer accent). The
|
|
88
|
+
full set of host-overridable CSS variables — color, motion, rail, and toast
|
|
89
|
+
tokens — is documented in [DESIGN.md](./DESIGN.md).
|
|
59
90
|
|
|
60
91
|
## Configure Pools
|
|
61
92
|
|
|
@@ -86,24 +117,27 @@ export function Swap() {
|
|
|
86
117
|
}
|
|
87
118
|
```
|
|
88
119
|
|
|
89
|
-
Use `defaultPoolId` to choose which pool opens first. Use `
|
|
120
|
+
Use `defaultPoolId` to choose which pool opens first. Use `poolIds` when a host wants a different pool order or subset:
|
|
90
121
|
|
|
91
122
|
```tsx
|
|
92
123
|
<AegisSwapWidget
|
|
93
124
|
pools={pools}
|
|
94
125
|
defaultPoolId="GRASS_USDC"
|
|
95
|
-
|
|
126
|
+
poolIds={['GRASS_USDC', 'WATER_USDC']}
|
|
96
127
|
/>
|
|
97
128
|
```
|
|
98
129
|
|
|
99
130
|
## Fees
|
|
100
131
|
|
|
101
|
-
The widget applies
|
|
132
|
+
The widget applies an internal output-token fee per chain. Each bundled chain config
|
|
133
|
+
carries its own fee. Today only Ethereum mainnet is bundled:
|
|
102
134
|
|
|
103
135
|
- Fee: `50` bps
|
|
104
136
|
- Recipient: `0x8ea2C7de60ef1Cd4dcE64ea2DDDe2f99F0127eFC`
|
|
105
137
|
|
|
106
|
-
This fee is internal to the widget and is not configured by host sites
|
|
138
|
+
This fee is internal to the widget and is not configured by host sites — host `chains`
|
|
139
|
+
overrides cannot set or change it. Chains added later carry a fee only when their
|
|
140
|
+
bundled config provides one.
|
|
107
141
|
|
|
108
142
|
For custom assets, provide full pool and token metadata:
|
|
109
143
|
|
|
@@ -255,24 +289,291 @@ host connect modal creates the provider during the button click:
|
|
|
255
289
|
If none of these props are supplied, the widget still checks `window.ethereum`
|
|
256
290
|
automatically when it renders and again when the user clicks connect/swap.
|
|
257
291
|
|
|
292
|
+
## UI Integration
|
|
293
|
+
|
|
294
|
+
Use `className` for host CSS selectors and `style` for one-off layout overrides or CSS variables:
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
<AegisSwapWidget
|
|
298
|
+
className="partner-swap"
|
|
299
|
+
style={{ maxWidth: 520 }}
|
|
300
|
+
title="Swap"
|
|
301
|
+
subtitle="Aegis direct pools"
|
|
302
|
+
ariaLabel="Partner swap"
|
|
303
|
+
/>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`accentColor`, `accentTextColor`, `title`, and `subtitle` are the intended props for making the widget fit a host surface without forking the component.
|
|
307
|
+
|
|
308
|
+
## Transaction Status
|
|
309
|
+
|
|
310
|
+
The widget paints swap progress on a rail along its own top edge — an accent
|
|
311
|
+
sweep while pending/mining, solid green on success, solid red on errors
|
|
312
|
+
(including wallet rejections), then a short hold and fade. The rail is the
|
|
313
|
+
default of two built-in status surfaces; `statusSurface` switches to toast
|
|
314
|
+
notifications, shows `'both'`, or `'none'` (see Toasts below). Hosts can tune
|
|
315
|
+
the rail through the widget's `style` prop:
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
<AegisSwapWidget
|
|
319
|
+
style={{
|
|
320
|
+
'--aegis-rail-height': '4px',
|
|
321
|
+
'--aegis-rail-hold': '1800ms',
|
|
322
|
+
'--aegis-rail-fade': '260ms'
|
|
323
|
+
}}
|
|
324
|
+
/>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Use CSS time strings (`ms` or `s`) for `--aegis-rail-hold` and
|
|
328
|
+
`--aegis-rail-fade`; the widget reads the computed tokens at runtime so the
|
|
329
|
+
success auto-reset stays in sync with the host-tuned animation. Hosts can
|
|
330
|
+
mirror that state outside the widget three ways:
|
|
331
|
+
|
|
332
|
+
`onStatusChange` fires a snapshot on every lifecycle transition. `walletPrompts`
|
|
333
|
+
is the SDK-owned provider-prompt plan: ERC20 approval, Permit2 authorization,
|
|
334
|
+
and swap submission are counted from the current allowance/authorization reads.
|
|
335
|
+
Use that for step copy or external rails instead of guessing from status names:
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
<AegisSwapWidget
|
|
339
|
+
onStatusChange={({ status, progress, walletPrompts, txHash, error }) => {
|
|
340
|
+
// status: 'idle' | 'approving' | 'signing' | 'submitting' | 'success'
|
|
341
|
+
// progress: 'pending' | 'mining' | 'success' | 'error' | null (rail hidden)
|
|
342
|
+
// walletPrompts: { total, completed, active } // active is 1-based or null
|
|
343
|
+
// error: user-facing message, e.g. "Request rejected."
|
|
344
|
+
}}
|
|
345
|
+
/>
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
The rail separates step completion from activity: `completePct` fills the calm
|
|
349
|
+
completed portion (for example 33.3% after one of three wallet prompts), while
|
|
350
|
+
the pending/mining shimmer is always a full-width top-border sweep.
|
|
351
|
+
|
|
352
|
+
Errors never appear in `status` (the submit machine resets to `'idle'`); read
|
|
353
|
+
them from `progress === 'error'` plus `error`. For classifying the raw `Error`
|
|
354
|
+
from `onError`, `isUserRejectedError` is exported.
|
|
355
|
+
|
|
356
|
+
Success clears itself after confirming (by default a 3s hold plus the 420ms
|
|
357
|
+
rail fade-out), the widget resets and emits a final
|
|
358
|
+
`{ status: 'idle', progress: null }` snapshot. Errors persist until the
|
|
359
|
+
user interacts with the widget again — the in-widget rail fades out visually,
|
|
360
|
+
but the last snapshot and `data-progress-state` keep reporting `'error'`,
|
|
361
|
+
matching the widget's own inline error message.
|
|
362
|
+
|
|
363
|
+
`AegisSwapProgressRail` renders the animated rail standalone — mount it inside
|
|
364
|
+
any `position: relative` container and feed it the snapshot's `progress`:
|
|
365
|
+
|
|
366
|
+
```tsx
|
|
367
|
+
import { useState } from 'react'
|
|
368
|
+
import {
|
|
369
|
+
AegisSwapProgressRail,
|
|
370
|
+
AegisSwapWidget,
|
|
371
|
+
type AegisSwapStatusSnapshot
|
|
372
|
+
} from 'aegis-swap-widget'
|
|
373
|
+
import 'aegis-swap-widget/styles.css'
|
|
374
|
+
|
|
375
|
+
export function CheckoutHeader() {
|
|
376
|
+
const [status, setStatus] = useState<AegisSwapStatusSnapshot | null>(null)
|
|
377
|
+
|
|
378
|
+
return (
|
|
379
|
+
<>
|
|
380
|
+
<AegisSwapWidget onStatusChange={setStatus} />
|
|
381
|
+
|
|
382
|
+
<header style={{ position: 'relative' }}>
|
|
383
|
+
<AegisSwapProgressRail
|
|
384
|
+
state={status?.progress ?? null}
|
|
385
|
+
label={status?.label ?? undefined}
|
|
386
|
+
completePct={status?.completePct ?? undefined}
|
|
387
|
+
activeWidthPct={status?.activeWidthPct ?? undefined}
|
|
388
|
+
/>
|
|
389
|
+
My checkout
|
|
390
|
+
</header>
|
|
391
|
+
</>
|
|
392
|
+
)
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Driven from `progress` alone, the standalone rail uses simplified geometry — a
|
|
397
|
+
full-width sweep while in flight, solid fill when terminal. Feed the snapshot's
|
|
398
|
+
`completePct` and `activeWidthPct` to mirror the in-widget prompt-aware fill.
|
|
399
|
+
Theme it by setting `--aegis-swap-accent` (plus
|
|
400
|
+
`--aegis-swap-danger` and `--aegis-swap-success` for the terminal fills) on an
|
|
401
|
+
ancestor. `--aegis-rail-height`, `--aegis-rail-hold`, and
|
|
402
|
+
`--aegis-rail-fade` apply to the standalone rail as CSS too; only the in-widget
|
|
403
|
+
auto-reset timer reads those motion tokens. The built-in color fallbacks are
|
|
404
|
+
the dark-theme values, so light hosts should set them.
|
|
405
|
+
|
|
406
|
+
For CSS-only hooks, the widget root mirrors the rail as
|
|
407
|
+
`data-progress-state="pending | mining | success | error"`, so a host
|
|
408
|
+
stylesheet can react without JavaScript. The attribute stays on for every
|
|
409
|
+
`statusSurface`, including `'toast'` and `'none'`.
|
|
410
|
+
|
|
411
|
+
## Toasts
|
|
412
|
+
|
|
413
|
+
`statusSurface="toast"` replaces the rail with toast notifications; `'both'`
|
|
414
|
+
shows rail and toasts, `'none'` neither. With `'toast'` or `'both'` the widget
|
|
415
|
+
provides its own toast viewport — no extra setup:
|
|
416
|
+
|
|
417
|
+
```tsx
|
|
418
|
+
<AegisSwapWidget statusSurface="toast" toastPosition="bottom-right" />
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
One toast per swap attempt morphs through the lifecycle: a loading card
|
|
422
|
+
follows the same wallet-prompt copy as the rail, then settles into success
|
|
423
|
+
(received amount plus a View transaction link) or error in place. Wallet
|
|
424
|
+
rejections auto-dismiss after 4s and other errors after 8s — the widget's
|
|
425
|
+
inline error message and `data-progress-state` persist regardless. A retry
|
|
426
|
+
withdraws the previous attempt's toast and starts a fresh one.
|
|
427
|
+
|
|
428
|
+
Mounting `<AegisSwapToaster />` anywhere in the app takes over rendering from
|
|
429
|
+
every widget-provided toaster — exactly one toast viewport exists per page —
|
|
430
|
+
which is how hosts control placement and toast options:
|
|
431
|
+
|
|
432
|
+
```tsx
|
|
433
|
+
import { AegisSwapToaster, AegisSwapWidget } from 'aegis-swap-widget'
|
|
434
|
+
import 'aegis-swap-widget/styles.css'
|
|
435
|
+
|
|
436
|
+
<AegisSwapWidget statusSurface="toast" />
|
|
437
|
+
<AegisSwapToaster position="top-right" theme="light" accentColor="#006adc" closeButton />
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
`AegisSwapToaster` props: `position` (`top`/`bottom` × `left`/`center`/`right`,
|
|
441
|
+
default `'bottom-right'`), `theme`/`accentColor`/`accentTextColor` (the toaster
|
|
442
|
+
portals to `document.body`, so widget-root accent variables do not reach it —
|
|
443
|
+
pass these props or set `--aegis-swap-accent` and friends on `:root`),
|
|
444
|
+
`duration` (auto-dismiss for info/success, default 5000ms), `visibleToasts`
|
|
445
|
+
(default 3), `closeButton` (default `false` — swipe and auto-dismiss always
|
|
446
|
+
work), `expand` (always-expanded list instead of the hover-expanded stack),
|
|
447
|
+
`offset` (viewport inset, default 24px / 16px on small screens), `className`,
|
|
448
|
+
and `style` (e.g. `'--aegis-swap-toast-z'`, `'--aegis-swap-toast-width'`).
|
|
449
|
+
|
|
450
|
+
The toast system is the widget's own implementation, not a dependency: toasts
|
|
451
|
+
stack with depth, hovering (or focusing) the stack expands it into a list,
|
|
452
|
+
swiping toward the nearest viewport edge dismisses (momentum-based — a quick
|
|
453
|
+
flick is enough), auto-dismiss timers pause while hovered, while swiping, and
|
|
454
|
+
in hidden tabs, and `prefers-reduced-motion` reduces all motion to fades.
|
|
455
|
+
|
|
456
|
+
`aegisToast` is exported so host apps can fire their own toasts through the
|
|
457
|
+
same viewport — a plain function, no hooks or context:
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
import { aegisToast } from 'aegis-swap-widget'
|
|
461
|
+
|
|
462
|
+
aegisToast('Copied') // info
|
|
463
|
+
aegisToast.success('Saved', { description: 'Order #1204' })
|
|
464
|
+
aegisToast.error('Could not save', { duration: 8000 })
|
|
465
|
+
|
|
466
|
+
const id = aegisToast.loading('Uploading…') // sticky until updated
|
|
467
|
+
aegisToast.success('Uploaded', { id }) // reusing an id morphs in place
|
|
468
|
+
|
|
469
|
+
aegisToast.promise(save(), {
|
|
470
|
+
loading: 'Saving…',
|
|
471
|
+
success: (result) => `Saved ${result.name}`,
|
|
472
|
+
error: (reason) => (reason instanceof Error ? reason.message : 'Save failed')
|
|
473
|
+
})
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Every creator returns the toast id. Actions render as a new-tab link
|
|
477
|
+
(`{ label, href }`) or a button (`{ label, onClick }`); acting on a toast
|
|
478
|
+
dismisses it. `duration: Infinity` keeps a toast until dismissed;
|
|
479
|
+
`dismissible: false` hides the close affordance and blocks swiping. One caveat
|
|
480
|
+
shared with every module-store toast library: two bundled copies of the
|
|
481
|
+
package keep two independent toast stores (and two viewports).
|
|
482
|
+
|
|
483
|
+
## Motion
|
|
484
|
+
|
|
485
|
+
Switching pools or the approval mode glides a single active pill between the
|
|
486
|
+
options (iOS-segmented-control style), and the Sell/Buy token pills cross-fade
|
|
487
|
+
when a switch retargets them. It is all CSS — no animation library — and every
|
|
488
|
+
animation respects `prefers-reduced-motion` automatically.
|
|
489
|
+
|
|
490
|
+
Hosts tune or disable the switch motion through CSS tokens on the `style` prop:
|
|
491
|
+
|
|
492
|
+
```tsx
|
|
493
|
+
<AegisSwapWidget
|
|
494
|
+
style={{
|
|
495
|
+
'--aegis-switch-dur': '180ms', // pill glide + token swap; '0ms' disables
|
|
496
|
+
'--aegis-spring': 'cubic-bezier(0.2, 0, 0, 1)' // switch easing
|
|
497
|
+
}}
|
|
498
|
+
/>
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
## Migrating to 0.3.0
|
|
502
|
+
|
|
503
|
+
0.3.0 removes the props that were deprecated in 0.2.x. The replacements are
|
|
504
|
+
drop-in:
|
|
505
|
+
|
|
506
|
+
| Removed | Use instead |
|
|
507
|
+
| --- | --- |
|
|
508
|
+
| `targets={[...]}` | `poolIds={[...]}` (same `string[]`) |
|
|
509
|
+
| `markets={map}` | `pools={Object.values(map)}` |
|
|
510
|
+
| `defaultDirection="intoTarget"` | `defaultDirection="buy"` |
|
|
511
|
+
| `defaultDirection="outOfTarget"` | `defaultDirection="sell"` |
|
|
512
|
+
| `showApprovalModeControl` | `showApprovalMode` |
|
|
513
|
+
|
|
514
|
+
No other props changed. See the [CHANGELOG](./CHANGELOG.md) for the full entry.
|
|
515
|
+
|
|
258
516
|
## Props
|
|
259
517
|
|
|
260
518
|
- `provider`: optional EIP-1193 provider. Defaults to auto-detected `window.ethereum`.
|
|
261
519
|
- `account`: optional connected account from the host wallet UI.
|
|
262
520
|
- `getProvider`: optional provider resolver for wallet libraries with async providers.
|
|
263
521
|
- `onConnectWallet`: optional callback for opening the host wallet modal. It may return `{ provider, account }`.
|
|
522
|
+
- `onSubmitted`: `(hash, swap?)` fired when the swap transaction is sent. `swap` carries mode, token symbols, amounts, and fee for analytics.
|
|
523
|
+
- `onSuccess`: `({ hash, explorerUrl, swap? })` fired when the receipt confirms.
|
|
524
|
+
- `onError`: `(error)` fired on approval/swap failures (after the widget shows its own message).
|
|
525
|
+
- `onQuote`: `(quote)` fired on every quote refresh.
|
|
526
|
+
- `onStatusChange`: `(snapshot)` fired on every lifecycle transition with what the top progress rail shows (see Transaction Status).
|
|
527
|
+
- `onPoolChange`: `(poolId)` fired when the active pool changes — user selection or a `poolIds` update that forces a fallback. Silent on mount.
|
|
264
528
|
- `chainId`: active chain id. Defaults to Ethereum mainnet.
|
|
265
529
|
- `chains`: optional chain config overrides or additional chain configs, including per-chain `v4Contracts`.
|
|
266
|
-
- `
|
|
530
|
+
- `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.
|
|
531
|
+
- `pools`: direct pool configs to render and swap against. This is the canonical config path.
|
|
267
532
|
- `defaultPoolId`: initial pool id when `pools` is provided.
|
|
268
|
-
- `
|
|
269
|
-
- `defaultDirection`: `
|
|
270
|
-
- `
|
|
271
|
-
- `rpcUrls`:
|
|
533
|
+
- `poolIds`: optional pool id order/subset. Use this when the host wants to hide pools or control ordering.
|
|
534
|
+
- `defaultDirection`: `buy` (counter token into the pool token) or `sell` (pool token into the counter token). Defaults to `buy`.
|
|
535
|
+
- `defaultSlippagePercent`: number (canonical) or numeric string, in percent. Defaults to `1`.
|
|
536
|
+
- `rpcUrls`: RPC fallback list for the active chain, or a `{ [chainId]: string[] }` map for multichain hosts.
|
|
272
537
|
- `metadataEndpoint`: optional metadata GraphQL endpoint for `GlobalToken.iconURL` token icons. Set to `null` to disable.
|
|
273
|
-
- `
|
|
274
|
-
- `
|
|
538
|
+
- `className`: optional class for host layout and styling hooks.
|
|
539
|
+
- `style`: optional root style object, useful for host layout constraints or CSS variables.
|
|
540
|
+
- `title`: optional widget heading. Empty by default (compact topbar, no header row).
|
|
541
|
+
- `subtitle`: optional header eyebrow. Defaults to empty. Pass a string to show it.
|
|
542
|
+
- `ariaLabel`: optional accessible label for the widget region.
|
|
543
|
+
- `theme`: `dark`, `light`, or `auto` (follows `prefers-color-scheme`). Defaults to `dark`.
|
|
544
|
+
- `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
545
|
- `accentTextColor`: optional CTA text color for contrast with the chosen accent.
|
|
546
|
+
- `showPoolLink`: whether to render the direct-pool link when the active chain provides `poolExplorerUrl`.
|
|
547
|
+
- `defaultApprovalMode`: `exact` approves only the current quote spend by default; `max` opts into the old unlimited ERC-20 to Permit2 approval behavior.
|
|
548
|
+
- `showApprovalMode`: whether the details drawer exposes the Exact/Max approval toggle. Defaults to `true`.
|
|
549
|
+
- `showExecutionDetails`: whether to render the collapsible settings drawer for slippage, approval mode, and route. Defaults to `true`.
|
|
550
|
+
- `defaultExecutionDetailsOpen`: whether that settings drawer starts expanded. Defaults to `false`.
|
|
551
|
+
- `statusSurface`: where transaction status is surfaced — `'rail'` (default), `'toast'`, `'both'`, or `'none'`. The root `data-progress-state` attribute stays on regardless (see Toasts).
|
|
552
|
+
- `toastPosition`: viewport corner for the widget-provided toaster. Defaults to `'bottom-right'`; ignored once a host mounts `<AegisSwapToaster />`.
|
|
553
|
+
|
|
554
|
+
The widget intentionally does not inherit the host font; set the
|
|
555
|
+
`--aegis-swap-font-family` CSS variable (via `style` or a stylesheet) to match
|
|
556
|
+
the host typography.
|
|
557
|
+
|
|
558
|
+
### With wagmi
|
|
559
|
+
|
|
560
|
+
The widget consumes the host's wallet instead of bundling its own connect UI.
|
|
561
|
+
From a wagmi app, derive the EIP-1193 provider from the active connector:
|
|
562
|
+
|
|
563
|
+
```tsx
|
|
564
|
+
import { useAccount } from 'wagmi'
|
|
565
|
+
|
|
566
|
+
function Swap() {
|
|
567
|
+
const { address, connector } = useAccount()
|
|
568
|
+
return (
|
|
569
|
+
<AegisSwapWidget
|
|
570
|
+
account={address}
|
|
571
|
+
getProvider={async () => (await connector?.getProvider()) ?? null}
|
|
572
|
+
onConnectWallet={openConnectModal}
|
|
573
|
+
/>
|
|
574
|
+
)
|
|
575
|
+
}
|
|
576
|
+
```
|
|
276
577
|
|
|
277
578
|
## Default Markets
|
|
278
579
|
|
|
@@ -287,9 +588,30 @@ These use the Aegis mainnet router `0x00581261a1200956ea05d1810fF28ffd66D8E254`
|
|
|
287
588
|
and the Ethereum entry in `UNISWAP_V4_CONTRACTS_BY_CHAIN` for Permit2 and the
|
|
288
589
|
public Uniswap v4 Quoter.
|
|
289
590
|
|
|
591
|
+
## License
|
|
592
|
+
|
|
593
|
+
MIT.
|
|
594
|
+
|
|
290
595
|
## Local Demo
|
|
291
596
|
|
|
292
597
|
```bash
|
|
293
|
-
npm
|
|
598
|
+
npm ci
|
|
294
599
|
npm run dev
|
|
295
600
|
```
|
|
601
|
+
|
|
602
|
+
## Releasing
|
|
603
|
+
|
|
604
|
+
Maintainer release flow (publishes to npm). `dist/` is not committed — the `prepack`
|
|
605
|
+
hook rebuilds it on every `npm pack`/`npm publish`, and `prepublishOnly` runs the
|
|
606
|
+
typecheck + test gate.
|
|
607
|
+
|
|
608
|
+
```bash
|
|
609
|
+
git switch main && git pull
|
|
610
|
+
npm ci
|
|
611
|
+
npm run typecheck && npm run test && npm run build
|
|
612
|
+
# Move CHANGELOG [Unreleased] entries under the new version heading.
|
|
613
|
+
npm version minor # e.g. 0.2.1 -> 0.3.0 for a breaking 0.x release; commits and tags vX.Y.Z
|
|
614
|
+
git push origin main --follow-tags
|
|
615
|
+
npm publish --access public # prepublishOnly gate + prepack build run automatically
|
|
616
|
+
npm view aegis-swap-widget version
|
|
617
|
+
```
|
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;
|