@aegis-engine/core 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -2,41 +2,308 @@
2
2
 
3
3
  React-free swap operations for Aegis integrations.
4
4
 
5
- This package exposes the operational pieces that the widget uses internally:
6
- direct pool quotes and execution, KyberSwap quotes and execution, Permit2
7
- authorization helpers, chain/wallet helpers, token and market config, and
8
- transaction progress types.
5
+ `@aegis-engine/core` is the operations layer behind the Aegis swap experience.
6
+ Use it when you want Aegis direct-pool swaps or KyberSwap aggregated routes
7
+ inside your own UI instead of using a prebuilt widget.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm install @aegis-engine/core viem
13
+ ```
14
+
15
+ `viem` is a peer dependency because hosts usually already own their wallet and
16
+ RPC setup.
17
+
18
+ ## What It Supports
19
+
20
+ - Direct Aegis pool quotes and execution against host-supplied Uniswap v4 pool
21
+ configs.
22
+ - KyberSwap aggregated quotes and execution through the Kyber aggregator API.
23
+ - ERC-20 approvals, Permit2 signing, Permit2 on-chain fallback, wallet chain
24
+ switching, transaction submission, replacement tracking, and receipt summaries.
25
+ - Token, market, chain, metadata, polling, and progress helpers for custom UIs.
26
+
27
+ Direct pool swaps support `exactIn` and `exactOut`. KyberSwap routes currently
28
+ support `exactIn` only because Kyber's route/build flow is exact-input.
29
+
30
+ Core does not ship a hardcoded pool list. The widget or host app should own pool
31
+ selection and pass the selected market into the operation functions.
32
+
33
+ ## Wallet Sessions
34
+
35
+ Execution functions take a `WalletSession`:
36
+
37
+ ```ts
38
+ type WalletSession = {
39
+ provider: Eip1193Provider
40
+ account: Address
41
+ }
42
+ ```
43
+
44
+ If your app already uses wagmi, RainbowKit, Privy, Dynamic, or another wallet
45
+ manager, you can build this object yourself and skip `resolveWalletSession`.
46
+
47
+ `resolveWalletSession` is a convenience for simple browser integrations. It:
48
+
49
+ - uses a supplied `provider` and `account` when provided,
50
+ - otherwise calls `getProvider`,
51
+ - otherwise falls back to `window.ethereum`,
52
+ - optionally calls your `connectWallet` callback,
53
+ - requests an account by default when one is missing.
54
+
55
+ Call it from a user action, not during render, because it may open the wallet
56
+ connection prompt.
57
+
58
+ ```ts
59
+ import { resolveWalletSession } from '@aegis-engine/core'
60
+
61
+ const wallet = await resolveWalletSession()
62
+ ```
63
+
64
+ With a host wallet manager:
65
+
66
+ ```ts
67
+ const wallet = await resolveWalletSession({
68
+ account: address,
69
+ getProvider: () => connector.getProvider()
70
+ })
71
+ ```
72
+
73
+ To only read an already connected account without prompting:
74
+
75
+ ```ts
76
+ const wallet = await resolveWalletSession({
77
+ provider,
78
+ requestAccount: false
79
+ })
80
+ ```
81
+
82
+ ## Public Client
83
+
84
+ Create a read-side viem client from an Aegis chain config:
9
85
 
10
86
  ```ts
11
87
  import {
12
88
  AEGIS_SWAP_MAINNET_CHAIN,
13
- AEGIS_SWAP_MARKETS,
14
- AEGIS_SWAP_TOKENS,
15
- createSwapPublicClient,
16
- executeDirectPoolSwap,
17
- resolveWalletSession
89
+ createSwapPublicClient
18
90
  } from '@aegis-engine/core'
19
91
 
20
92
  const publicClient = createSwapPublicClient(
21
93
  AEGIS_SWAP_MAINNET_CHAIN.chain,
22
94
  AEGIS_SWAP_MAINNET_CHAIN.rpcUrls
23
95
  )
96
+ ```
97
+
98
+ For production integrations, prefer passing your own viem `PublicClient` backed
99
+ by your RPC provider. `createSwapPublicClient` is a convenience fallback for
100
+ simple integrations and demos.
101
+
102
+ ## Direct Pool Market Config
103
+
104
+ The direct pool operations take an `AegisSwapMarket`. Hosts can build one from
105
+ their own pool config:
106
+
107
+ ```ts
108
+ import { createAegisSwapPoolMarket } from '@aegis-engine/core'
109
+
110
+ const market = createAegisSwapPoolMarket({
111
+ id: 'HOST_POOL_ID',
112
+ token: targetToken,
113
+ counterToken,
114
+ poolKey: {
115
+ currency0,
116
+ currency1,
117
+ fee,
118
+ tickSpacing,
119
+ hooks
120
+ },
121
+ poolId
122
+ })
123
+ ```
124
+
125
+ The pool key must use Uniswap v4 canonical currency ordering. If `poolId` is
126
+ provided, core verifies it matches the key.
127
+
128
+ ## Direct Pool Quote
129
+
130
+ ```ts
131
+ import {
132
+ AEGIS_SWAP_MAINNET_CHAIN,
133
+ fetchDirectPoolSwapQuote
134
+ } from '@aegis-engine/core'
135
+
136
+ const quote = await fetchDirectPoolSwapQuote({
137
+ publicClient,
138
+ account,
139
+ activeChain: AEGIS_SWAP_MAINNET_CHAIN,
140
+ market,
141
+ inputToken,
142
+ outputToken,
143
+ mode: 'exactIn',
144
+ amount: 1_000_000n,
145
+ slippageBps: 100
146
+ })
147
+ ```
148
+
149
+ Amounts are raw token base units. `slippageBps: 100` means 1%.
150
+ The Aegis 0.5% output fee is applied by the high-level quote and execution
151
+ helpers.
152
+
153
+ ## Direct Pool Execution
154
+
155
+ ```ts
156
+ import {
157
+ AEGIS_SWAP_MAINNET_CHAIN,
158
+ executeDirectPoolSwap,
159
+ resolveWalletSession
160
+ } from '@aegis-engine/core'
161
+
24
162
  const wallet = await resolveWalletSession()
25
163
 
26
164
  const result = await executeDirectPoolSwap({
27
165
  wallet,
28
166
  publicClient,
29
167
  activeChain: AEGIS_SWAP_MAINNET_CHAIN,
30
- market: AEGIS_SWAP_MARKETS.WATER_USDC,
31
- inputToken: AEGIS_SWAP_TOKENS.USDC,
32
- outputToken: AEGIS_SWAP_TOKENS.WATER,
168
+ market,
169
+ inputToken,
170
+ outputToken,
33
171
  mode: 'exactIn',
34
172
  amount: 1_000_000n,
35
- slippageBps: 100
173
+ slippageBps: 100,
174
+ displayedQuote: quote,
175
+ approvalMode: 'exact',
176
+ onStatus: (status) => setStatus(status),
177
+ onTxHash: (hash) => setTxHash(hash),
178
+ onSubmitted: (hash, swap) => trackSwapSubmitted(hash, swap)
179
+ })
180
+ ```
181
+
182
+ Passing `displayedQuote` is recommended. Core requotes immediately before
183
+ submission and refuses to submit if the fresh quote no longer satisfies the
184
+ protection the user saw.
185
+
186
+ ## KyberSwap Quote
187
+
188
+ ```ts
189
+ import {
190
+ AGGREGATED_SWAP_DEFAULT_TOKENS,
191
+ fetchAggregatedSwapQuote
192
+ } from '@aegis-engine/core'
193
+
194
+ const quote = await fetchAggregatedSwapQuote(
195
+ AGGREGATED_SWAP_DEFAULT_TOKENS.USDC,
196
+ AGGREGATED_SWAP_DEFAULT_TOKENS.USDT,
197
+ 1_000_000n,
198
+ 100,
199
+ 'exactIn'
200
+ )
201
+ ```
202
+
203
+ For a display-only quote, omit the account. For executable calldata, pass the
204
+ user account:
205
+
206
+ ```ts
207
+ const executableQuote = await fetchAggregatedSwapQuote(
208
+ inputToken,
209
+ outputToken,
210
+ amount,
211
+ slippageBps,
212
+ 'exactIn',
213
+ wallet.account
214
+ )
215
+ ```
216
+
217
+ ## KyberSwap Execution
218
+
219
+ ```ts
220
+ import {
221
+ AEGIS_SWAP_MAINNET_CHAIN,
222
+ AGGREGATED_SWAP_DEFAULT_TOKENS,
223
+ executeKyberSwap,
224
+ resolveWalletSession
225
+ } from '@aegis-engine/core'
226
+
227
+ const wallet = await resolveWalletSession()
228
+
229
+ const result = await executeKyberSwap({
230
+ wallet,
231
+ publicClient,
232
+ activeChain: AEGIS_SWAP_MAINNET_CHAIN,
233
+ inputToken: AGGREGATED_SWAP_DEFAULT_TOKENS.USDC,
234
+ outputToken: AGGREGATED_SWAP_DEFAULT_TOKENS.USDT,
235
+ amount: 1_000_000n,
236
+ slippageBps: 100,
237
+ displayedQuote: quote,
238
+ approvalMode: 'exact',
239
+ onStatus: (status) => setStatus(status),
240
+ onTxHash: (hash) => setTxHash(hash)
36
241
  })
37
242
  ```
38
243
 
39
- For Kyber routes, call `executeKyberSwap` with an input token, output token,
40
- amount, and slippage. Both execution actions accept callbacks for status,
41
- transaction hash, and submitted swap details so a host UI can render its own
42
- progress surfaces.
244
+ Kyber execution will:
245
+
246
+ - switch the wallet to the active chain when needed,
247
+ - approve the Kyber router for ERC-20 input tokens,
248
+ - skip approval for native ETH-style input tokens,
249
+ - rebuild the route with executable calldata for the connected account,
250
+ - reject submission if the route moved below the displayed minimum,
251
+ - send the transaction and wait for a receipt.
252
+
253
+ ## Approval Modes
254
+
255
+ `approvalMode` controls ERC-20 approval sizing.
256
+
257
+ - `exact`: approve only the current quote spend.
258
+ - `max`: approve the maximum spender allowance to reduce future approval prompts.
259
+
260
+ Direct pool swaps also use Permit2. Core first attempts an off-chain Permit2
261
+ signature and falls back to an on-chain Permit2 approval if the wallet cannot
262
+ produce a compatible typed-data signature.
263
+
264
+ ## Result Shape
265
+
266
+ Execution returns:
267
+
268
+ ```ts
269
+ {
270
+ hash: Hex
271
+ explorerUrl: string
272
+ quote: DirectSwapQuote | AggregatedSwapQuote
273
+ receiptSummary: {
274
+ transactionHash: Hex
275
+ blockNumber: bigint
276
+ gasUsed: bigint
277
+ effectiveGasPrice: bigint
278
+ feeWei: bigint
279
+ }
280
+ swap: {
281
+ mode: 'exactIn' | 'exactOut'
282
+ inputSymbol: string
283
+ outputSymbol: string
284
+ amountIn: bigint
285
+ amountOut: bigint
286
+ feeAmount: bigint
287
+ feeBps: number
288
+ }
289
+ }
290
+ ```
291
+
292
+ ## Errors To Handle
293
+
294
+ - `DirectPoolSwapPriceMovedError`: direct pool submit-time quote moved beyond
295
+ the displayed tolerance. The error includes the fresh `quote`.
296
+ - `KyberSwapPriceMovedError`: Kyber executable route moved below the displayed
297
+ minimum. The error includes the fresh `quote`.
298
+ - User rejection errors normalize through `errorMessage(error, fallback)`.
299
+ - Kyber temporary failures can be mapped with
300
+ `aggregatedSwapErrorMessage(error, fallback)`.
301
+
302
+ ## Publishing
303
+
304
+ This package is configured with `prepack`, so `npm publish` builds `dist` before
305
+ creating the tarball.
306
+
307
+ ```sh
308
+ npm publish --access public
309
+ ```
@@ -1,5 +1,5 @@
1
1
  import { type Hex, type PublicClient } from 'viem';
2
- import type { AegisSwapChainConfig, AegisSwapFeeConfig, AegisSwapMarket, AegisSwapToken } from '../config';
2
+ import type { AegisSwapChainConfig, AegisSwapMarket, AegisSwapToken } from '../config';
3
3
  import { type DirectSwapQuote, type SwapQuoteMode } from '../quote';
4
4
  import type { AegisSwapApprovalMode, WalletSession } from '../swap/types';
5
5
  import type { AegisSwapActionCallbacks, AegisSwapActionResult } from './types';
@@ -11,6 +11,18 @@ export type DirectPoolSwapApprovalResult = {
11
11
  approvalHash: Hex | null;
12
12
  allowance: bigint;
13
13
  };
14
+ export declare function fetchDirectPoolSwapQuote(args: {
15
+ publicClient: PublicClient;
16
+ account: WalletSession['account'];
17
+ activeChain: AegisSwapChainConfig;
18
+ market: AegisSwapMarket;
19
+ inputToken: AegisSwapToken;
20
+ outputToken: AegisSwapToken;
21
+ mode: SwapQuoteMode;
22
+ amount: bigint;
23
+ slippageBps: number;
24
+ signal?: AbortSignal;
25
+ }): Promise<DirectSwapQuote>;
14
26
  export declare function approveDirectPoolSwapInput(args: {
15
27
  wallet: WalletSession;
16
28
  publicClient: PublicClient;
@@ -31,7 +43,6 @@ export declare function executeDirectPoolSwap(args: {
31
43
  mode: SwapQuoteMode;
32
44
  amount: bigint;
33
45
  slippageBps: number;
34
- fee?: AegisSwapFeeConfig | null;
35
46
  displayedQuote?: DirectSwapQuote | null;
36
47
  approvalMode?: AegisSwapApprovalMode;
37
48
  signal?: AbortSignal;