@aori/mega-swap-widget 0.1.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/LICENSE +21 -0
- package/README.md +404 -0
- package/dist/AssetSelectionMenu-Y3EB32BT.cjs +13 -0
- package/dist/AssetSelectionMenu-Y3EB32BT.cjs.map +1 -0
- package/dist/AssetSelectionMenu-ZRG42UCZ.js +13 -0
- package/dist/AssetSelectionMenu-ZRG42UCZ.js.map +1 -0
- package/dist/ChainSelectionMenu-FBAPPFKI.cjs +11 -0
- package/dist/ChainSelectionMenu-FBAPPFKI.cjs.map +1 -0
- package/dist/ChainSelectionMenu-QO3H4TNR.js +11 -0
- package/dist/ChainSelectionMenu-QO3H4TNR.js.map +1 -0
- package/dist/SwapFormHorizontal-JDJUDFNX.js +573 -0
- package/dist/SwapFormHorizontal-JDJUDFNX.js.map +1 -0
- package/dist/SwapFormHorizontal-WG3Z3CFT.cjs +573 -0
- package/dist/SwapFormHorizontal-WG3Z3CFT.cjs.map +1 -0
- package/dist/SwapFormSplit-7CHTPLEQ.js +441 -0
- package/dist/SwapFormSplit-7CHTPLEQ.js.map +1 -0
- package/dist/SwapFormSplit-VDDIRQUQ.cjs +441 -0
- package/dist/SwapFormSplit-VDDIRQUQ.cjs.map +1 -0
- package/dist/WalletPlaceholderPanel-7YDQ4FT6.js +57 -0
- package/dist/WalletPlaceholderPanel-7YDQ4FT6.js.map +1 -0
- package/dist/WalletPlaceholderPanel-FZ6XIAMF.cjs +57 -0
- package/dist/WalletPlaceholderPanel-FZ6XIAMF.cjs.map +1 -0
- package/dist/WidgetWalletPanel-D7I5TAU3.js +789 -0
- package/dist/WidgetWalletPanel-D7I5TAU3.js.map +1 -0
- package/dist/WidgetWalletPanel-T7H6FGVN.cjs +789 -0
- package/dist/WidgetWalletPanel-T7H6FGVN.cjs.map +1 -0
- package/dist/chunk-3E6RNP2D.cjs +389 -0
- package/dist/chunk-3E6RNP2D.cjs.map +1 -0
- package/dist/chunk-5TH6MFQD.cjs +122 -0
- package/dist/chunk-5TH6MFQD.cjs.map +1 -0
- package/dist/chunk-5XSCUUOW.js +101 -0
- package/dist/chunk-5XSCUUOW.js.map +1 -0
- package/dist/chunk-6Q7MSCKS.js +2199 -0
- package/dist/chunk-6Q7MSCKS.js.map +1 -0
- package/dist/chunk-6XB5R4GF.cjs +368 -0
- package/dist/chunk-6XB5R4GF.cjs.map +1 -0
- package/dist/chunk-6YLNOZ7P.js +389 -0
- package/dist/chunk-6YLNOZ7P.js.map +1 -0
- package/dist/chunk-7AWG6OWF.js +27 -0
- package/dist/chunk-7AWG6OWF.js.map +1 -0
- package/dist/chunk-ARMW5POL.js +3082 -0
- package/dist/chunk-ARMW5POL.js.map +1 -0
- package/dist/chunk-B3ILUJ7G.cjs +101 -0
- package/dist/chunk-B3ILUJ7G.cjs.map +1 -0
- package/dist/chunk-GGM3MDFM.js +32 -0
- package/dist/chunk-GGM3MDFM.js.map +1 -0
- package/dist/chunk-GZUTUD5O.cjs +2199 -0
- package/dist/chunk-GZUTUD5O.cjs.map +1 -0
- package/dist/chunk-HXOGJSAI.cjs +3082 -0
- package/dist/chunk-HXOGJSAI.cjs.map +1 -0
- package/dist/chunk-LTA7IG3J.js +122 -0
- package/dist/chunk-LTA7IG3J.js.map +1 -0
- package/dist/chunk-NBJPKJBC.cjs +32 -0
- package/dist/chunk-NBJPKJBC.cjs.map +1 -0
- package/dist/chunk-PGYOJ5RB.cjs +27 -0
- package/dist/chunk-PGYOJ5RB.cjs.map +1 -0
- package/dist/chunk-QHW27RMH.js +199 -0
- package/dist/chunk-QHW27RMH.js.map +1 -0
- package/dist/chunk-TMC4SUEV.js +368 -0
- package/dist/chunk-TMC4SUEV.js.map +1 -0
- package/dist/chunk-XQINW7QP.cjs +199 -0
- package/dist/chunk-XQINW7QP.cjs.map +1 -0
- package/dist/index.cjs +1780 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1424 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +555 -0
- package/dist/index.d.ts +555 -0
- package/dist/index.js +1780 -0
- package/dist/index.js.map +1 -0
- package/package.json +82 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aori
|
|
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
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
# @aori/mega-swap-widget
|
|
2
|
+
|
|
3
|
+
Embeddable cross-chain swap widget powered by [Aori](https://aori.io).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @aori/mega-swap-widget
|
|
9
|
+
# or
|
|
10
|
+
yarn add @aori/mega-swap-widget
|
|
11
|
+
# or
|
|
12
|
+
bun add @aori/mega-swap-widget
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Peer Dependencies
|
|
16
|
+
|
|
17
|
+
| Package | Version | Required |
|
|
18
|
+
| ------------------------------- | -------- | -------- |
|
|
19
|
+
| `wagmi` | ^2 | Yes |
|
|
20
|
+
| `@wagmi/core` | ^2 | Yes |
|
|
21
|
+
| `viem` | ^2 | Yes |
|
|
22
|
+
| `@tanstack/react-query` | ≥5 | Yes |
|
|
23
|
+
| `zustand` | ^4 / ^5 | Yes |
|
|
24
|
+
| `abitype` | ≥1 | Optional |
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### 1. Configure the widget
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import type { AoriSwapWidgetConfig } from '@aori/mega-swap-widget';
|
|
32
|
+
|
|
33
|
+
const config: AoriSwapWidgetConfig = {
|
|
34
|
+
vtApiBaseUrl: '/api/vt',
|
|
35
|
+
walletConnectProjectId: 'YOUR_WALLETCONNECT_PROJECT_ID',
|
|
36
|
+
rpcOverrides: {
|
|
37
|
+
1: '/api/rpc/1',
|
|
38
|
+
10: '/api/rpc/10',
|
|
39
|
+
8453: '/api/rpc/8453',
|
|
40
|
+
42161: '/api/rpc/42161',
|
|
41
|
+
// ...
|
|
42
|
+
},
|
|
43
|
+
theme: {
|
|
44
|
+
mode: 'dark',
|
|
45
|
+
dark: { /* color overrides */ },
|
|
46
|
+
light: { /* color overrides */ },
|
|
47
|
+
},
|
|
48
|
+
// All token/chain fields are optional — omit to allow all supported tokens and chains.
|
|
49
|
+
tokens: {
|
|
50
|
+
defaultBase: { chainId: 1, address: '0x...' },
|
|
51
|
+
defaultQuote: { chainId: 4326, address: '0x...' },
|
|
52
|
+
supportedInputTokens: [
|
|
53
|
+
{ chainId: 1, address: '0x...' },
|
|
54
|
+
// ...
|
|
55
|
+
],
|
|
56
|
+
supportedOutputTokens: [
|
|
57
|
+
{ chainId: 4326, address: '0x...' },
|
|
58
|
+
// ...
|
|
59
|
+
],
|
|
60
|
+
supportedInputChains: [1, 10, 8453, 42161],
|
|
61
|
+
supportedOutputChains: [4326],
|
|
62
|
+
enabledChains: [1, 10, 56, 143, 4326, 8453, 42161],
|
|
63
|
+
lockBase: false,
|
|
64
|
+
lockQuote: false,
|
|
65
|
+
disableInverting: true,
|
|
66
|
+
},
|
|
67
|
+
appearance: {
|
|
68
|
+
widgetType: 'default',
|
|
69
|
+
tokenDisplay: 'default',
|
|
70
|
+
fillContainer: false,
|
|
71
|
+
hideBorder: true,
|
|
72
|
+
walletButtonEnabled: false,
|
|
73
|
+
},
|
|
74
|
+
settings: {
|
|
75
|
+
defaultSlippage: 0.01,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Render
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { SwapWidget } from '@aori/mega-swap-widget';
|
|
84
|
+
import { ConnectButton, useConnectModal, useAccountModal } from '@rainbow-me/rainbowkit';
|
|
85
|
+
|
|
86
|
+
export default function App() {
|
|
87
|
+
const { openConnectModal } = useConnectModal();
|
|
88
|
+
const { openAccountModal } = useAccountModal();
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div>
|
|
92
|
+
<ConnectButton />
|
|
93
|
+
<SwapWidget
|
|
94
|
+
config={config}
|
|
95
|
+
customWalletUI="provider"
|
|
96
|
+
onRequestConnect={() => openConnectModal?.()}
|
|
97
|
+
onRequestAccount={() => openAccountModal?.()}
|
|
98
|
+
/>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Wallet Connection
|
|
105
|
+
|
|
106
|
+
The widget expects your app to provide the wallet context (wagmi, RainbowKit, AppKit, etc.). A typical integration uses `customWalletUI="provider"` with `onRequestConnect` and `onRequestAccount` to wire the widget's connect/account buttons into your existing wallet modals — this is the recommended approach for most integrators.
|
|
107
|
+
|
|
108
|
+
### Provider (recommended)
|
|
109
|
+
|
|
110
|
+
Wrap the widget inside your existing wallet provider. Pass `onRequestConnect` and `onRequestAccount` so the widget's built-in buttons open your modals. The widget inherits the wagmi context automatically.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { useConnectModal, useAccountModal } from '@rainbow-me/rainbowkit';
|
|
114
|
+
|
|
115
|
+
function SwapPage() {
|
|
116
|
+
const { openConnectModal } = useConnectModal();
|
|
117
|
+
const { openAccountModal } = useAccountModal();
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<SwapWidget
|
|
121
|
+
config={config}
|
|
122
|
+
customWalletUI="provider"
|
|
123
|
+
onRequestConnect={() => openConnectModal?.()}
|
|
124
|
+
onRequestAccount={() => openAccountModal?.()}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
This works the same way with AppKit or any other wagmi-compatible wallet kit — just swap the modal hooks.
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
## Chain & RPC Configuration
|
|
135
|
+
|
|
136
|
+
Your wagmi config **must include all Aori-supported chains** or approvals, wrapping/unwrapping, and chain switching will fail silently.
|
|
137
|
+
|
|
138
|
+
Import `wagmiChains` and `buildTransports` from the widget package — these provide every supported chain with built-in RPC fallback (multiple public RPCs per chain, tried in order on error or rate-limit).
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { wagmiChains, buildTransports } from '@aori/mega-swap-widget';
|
|
142
|
+
import { getDefaultConfig } from '@rainbow-me/rainbowkit';
|
|
143
|
+
import { aoriConfig } from './aori.config';
|
|
144
|
+
|
|
145
|
+
const wagmiConfig = getDefaultConfig({
|
|
146
|
+
appName: 'My App',
|
|
147
|
+
projectId: 'YOUR_WALLETCONNECT_PROJECT_ID',
|
|
148
|
+
chains: wagmiChains,
|
|
149
|
+
transports: buildTransports(aoriConfig.rpcOverrides),
|
|
150
|
+
ssr: false,
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
There are two separate RPC paths in the widget:
|
|
155
|
+
|
|
156
|
+
| Path | Source | Used for |
|
|
157
|
+
| --- | --- | --- |
|
|
158
|
+
| **Widget internal** | `rpcOverrides` in `AoriSwapWidgetConfig` | Balance fetching, quote pricing |
|
|
159
|
+
| **Wagmi** | `buildTransports()` in your wagmi config | Signing, sending txs, chain switching |
|
|
160
|
+
|
|
161
|
+
`rpcOverrides` in your `aori.config` only affects the widget's internal viem clients. Wagmi transports are configured separately via `buildTransports()` — any URLs passed there are **client-side JavaScript** and will be visible in the browser. Never pass private RPC URLs directly to `buildTransports`.
|
|
162
|
+
|
|
163
|
+
To keep private RPCs server-side for both paths, use the same relative proxy paths (e.g. `/api/rpc/1`) in your `rpcOverrides` and pass them to `buildTransports` as shown above. The browser hits your API route, which forwards to the real RPC with credentials from environment variables. See [Server-Side Proxying](#server-side-proxying) for how to set up the proxy routes.
|
|
164
|
+
|
|
165
|
+
## Server-Side Proxying
|
|
166
|
+
|
|
167
|
+
In production you almost certainly want to keep your API key **and** private RPC URLs off the client. The widget supports this via two config fields: `vtApiBaseUrl` and `rpcOverrides`. Both accept relative paths that hit your own backend routes, which then forward requests upstream with the real credentials attached.
|
|
168
|
+
|
|
169
|
+
### API Key Proxy (`vtApiBaseUrl`)
|
|
170
|
+
|
|
171
|
+
Instead of passing `apiKey` in the client config, point `vtApiBaseUrl` at your own API route. The widget will send all transfer/quote requests there instead of directly to the Aori API.
|
|
172
|
+
|
|
173
|
+
**Widget config:**
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
const config: AoriSwapWidgetConfig = {
|
|
177
|
+
vtApiBaseUrl: '/api/vt',
|
|
178
|
+
// no apiKey needed — the server injects it
|
|
179
|
+
// ...
|
|
180
|
+
};
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Next.js API route** (`pages/api/vt/[...path].ts`):
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
187
|
+
|
|
188
|
+
const VT_UPSTREAM = 'https://transfer.layerzero-api.com/v1';
|
|
189
|
+
|
|
190
|
+
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
191
|
+
const { path } = req.query;
|
|
192
|
+
const segments = Array.isArray(path) ? path.join('/') : path ?? '';
|
|
193
|
+
const queryString = new URL(req.url!, `http://${req.headers.host}`).search;
|
|
194
|
+
const upstreamUrl = `${VT_UPSTREAM}/${segments}${queryString}`;
|
|
195
|
+
|
|
196
|
+
const apiKey = process.env.VT_API_KEY;
|
|
197
|
+
if (!apiKey) {
|
|
198
|
+
return res.status(500).json({ error: 'VT_API_KEY not configured' });
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const headers: Record<string, string> = {
|
|
202
|
+
'Content-Type': 'application/json',
|
|
203
|
+
'x-api-key': apiKey,
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const upstream = await fetch(upstreamUrl, {
|
|
207
|
+
method: req.method,
|
|
208
|
+
headers,
|
|
209
|
+
body: req.method !== 'GET' && req.method !== 'HEAD' ? JSON.stringify(req.body) : undefined,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const contentType = upstream.headers.get('content-type') ?? 'application/json';
|
|
213
|
+
res.setHeader('Content-Type', contentType);
|
|
214
|
+
res.status(upstream.status);
|
|
215
|
+
|
|
216
|
+
const body = await upstream.text();
|
|
217
|
+
res.send(body);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Then set `VT_API_KEY` in your `.env` (or hosting provider's environment variables):
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
VT_API_KEY=your_aori_api_key
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Private RPC Proxy (`rpcOverrides`)
|
|
228
|
+
|
|
229
|
+
The same pattern works for RPC endpoints. Point each chain's override at a local route that forwards JSON-RPC requests to your private RPC, keeping the URL and any auth tokens server-side.
|
|
230
|
+
|
|
231
|
+
**Widget config:**
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
const config: AoriSwapWidgetConfig = {
|
|
235
|
+
vtApiBaseUrl: '/api/vt',
|
|
236
|
+
rpcOverrides: {
|
|
237
|
+
1: '/api/rpc/1',
|
|
238
|
+
10: '/api/rpc/10',
|
|
239
|
+
56: '/api/rpc/56',
|
|
240
|
+
8453: '/api/rpc/8453',
|
|
241
|
+
42161: '/api/rpc/42161',
|
|
242
|
+
143: '/api/rpc/143',
|
|
243
|
+
4326: '/api/rpc/4326',
|
|
244
|
+
},
|
|
245
|
+
// ...
|
|
246
|
+
};
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Next.js API route** (`pages/api/rpc/[chainId].ts`):
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
253
|
+
|
|
254
|
+
const RPC_URLS: Record<string, string | undefined> = {
|
|
255
|
+
'1': process.env.ETHEREUM_RPC_URL,
|
|
256
|
+
'10': process.env.OPTIMISM_RPC_URL,
|
|
257
|
+
'56': process.env.BSC_RPC_URL,
|
|
258
|
+
'8453': process.env.BASE_RPC_URL,
|
|
259
|
+
'42161': process.env.ARBITRUM_RPC_URL,
|
|
260
|
+
'143': process.env.MONAD_RPC_URL,
|
|
261
|
+
'4326': process.env.MEGAETH_RPC_URL,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
function jsonRpcError(res: NextApiResponse, id: unknown, code: number, message: string) {
|
|
265
|
+
return res.status(200).json({ jsonrpc: '2.0', id: id ?? null, error: { code, message } });
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
269
|
+
if (req.method !== 'POST') {
|
|
270
|
+
return res.status(405).json({ error: 'Method not allowed' });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const chainId = req.query.chainId as string;
|
|
274
|
+
const rpcUrl = RPC_URLS[chainId];
|
|
275
|
+
|
|
276
|
+
if (!rpcUrl) {
|
|
277
|
+
return jsonRpcError(res, null, -32603, `RPC not configured for chain ${chainId}`);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
const response = await fetch(rpcUrl, {
|
|
282
|
+
method: 'POST',
|
|
283
|
+
headers: { 'Content-Type': 'application/json' },
|
|
284
|
+
body: JSON.stringify(req.body),
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
288
|
+
return res.status(200).json(await response.json());
|
|
289
|
+
} catch (error) {
|
|
290
|
+
return jsonRpcError(res, null, -32603, error instanceof Error ? error.message : 'RPC request failed');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**.env:**
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
ETHEREUM_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
|
|
299
|
+
OPTIMISM_RPC_URL=https://opt-mainnet.g.alchemy.com/v2/YOUR_KEY
|
|
300
|
+
BSC_RPC_URL=https://bsc-mainnet.g.alchemy.com/v2/YOUR_KEY
|
|
301
|
+
BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/YOUR_KEY
|
|
302
|
+
ARBITRUM_RPC_URL=https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY
|
|
303
|
+
MONAD_RPC_URL=https://your-monad-rpc.example.com
|
|
304
|
+
MEGAETH_RPC_URL=https://your-megaeth-rpc.example.com
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
> **Not using Next.js?** The same approach works with any backend — Express, Fastify, Cloudflare Workers, etc. The proxy just needs to forward the request body upstream and return the response. The widget doesn't care what's behind the route as long as it speaks the same protocol (REST for VT, JSON-RPC for RPCs).
|
|
308
|
+
|
|
309
|
+
## Props
|
|
310
|
+
|
|
311
|
+
| Prop | Type | Default | Description |
|
|
312
|
+
| -------------------- | ---------------------------------------- | -------------- | ------------------------------------------------ |
|
|
313
|
+
| `config` | `AoriSwapWidgetConfig` | — | Widget configuration (required) |
|
|
314
|
+
| `customWalletUI` | `'none' \| 'provider'` | `'provider'` | `'provider'` wires into your wallet modals via callbacks; `'none'` hides all wallet UI |
|
|
315
|
+
| `onRequestConnect` | `() => void` | — | Open the host app's connect modal |
|
|
316
|
+
| `onRequestAccount` | `() => void` | — | Open the host app's account modal |
|
|
317
|
+
| `onSwapComplete` | `(orderHash: string) => void` | — | Callback after a successful swap |
|
|
318
|
+
| `onBaseTokenChange` | `(token: Asset) => void` | — | Callback when the base token changes |
|
|
319
|
+
| `onQuoteTokenChange` | `(token: Asset) => void` | — | Callback when the quote token changes |
|
|
320
|
+
| `className` | `string` | — | Additional CSS class on the root element |
|
|
321
|
+
|
|
322
|
+
## Configuration
|
|
323
|
+
|
|
324
|
+
See [`AoriSwapWidgetConfig`](./src/config/types.ts) for the full type. Only non-default values need to be specified.
|
|
325
|
+
|
|
326
|
+
| Section | Type | Description |
|
|
327
|
+
| --- | --- | --- |
|
|
328
|
+
| `theme` | `{ mode, light?, dark? }` | Active color mode and optional light/dark theme overrides. Each theme controls colors, border radius, fonts, and shadows. |
|
|
329
|
+
| `tokens` | `{ defaultBase?, defaultQuote?, lockBase?, lockQuote?, enabledChains?, disableInverting?, supportedInputTokens?, supportedOutputTokens? }` | Default token pair, enabled chains, lock/invert settings, and per-side token whitelists. All fields are optional — when omitted, all supported tokens and chains are available. |
|
|
330
|
+
| `appearance` | `{ widgetType?, tokenDisplay?, assetMenuVariant?, swapButtonVariant?, ... }` | Layout variant (`default`, `compact`, `horizontal`, `split`), token display style, asset menu variant, quote loader, and other UI options. |
|
|
331
|
+
| `settings` | `{ defaultSlippage? }` | Default slippage tolerance. |
|
|
332
|
+
| `integrator` | `{ id?, feeRecipient?, feeAmount? }` | Integrator ID, fee recipient address, and fee amount for revenue attribution. |
|
|
333
|
+
| `vtApiBaseUrl` | `string` | Base URL for the Aori transfer API. Use a relative path (e.g. `'/api/vt'`) to proxy through your server and keep the API key off the client. |
|
|
334
|
+
| `rpcOverrides` | `Record<number, string \| string[]>` | Override RPCs for the widget's internal viem clients. Accepts direct URLs or relative paths to your own proxy routes. |
|
|
335
|
+
|
|
336
|
+
## Display Patterns
|
|
337
|
+
|
|
338
|
+
The widget is a standard React component — place it anywhere in your layout.
|
|
339
|
+
|
|
340
|
+
### Inline (default)
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
<SwapWidget config={config} />
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Modal / Dialog
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
const [open, setOpen] = useState(false);
|
|
350
|
+
|
|
351
|
+
return (
|
|
352
|
+
<>
|
|
353
|
+
<button onClick={() => setOpen(true)}>Swap</button>
|
|
354
|
+
{open && (
|
|
355
|
+
<div
|
|
356
|
+
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
|
|
357
|
+
onClick={() => setOpen(false)}
|
|
358
|
+
>
|
|
359
|
+
<div onClick={(e) => e.stopPropagation()}>
|
|
360
|
+
<SwapWidget config={config} />
|
|
361
|
+
</div>
|
|
362
|
+
</div>
|
|
363
|
+
)}
|
|
364
|
+
</>
|
|
365
|
+
);
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Drawer / Slide-in
|
|
369
|
+
|
|
370
|
+
```tsx
|
|
371
|
+
const [open, setOpen] = useState(false);
|
|
372
|
+
|
|
373
|
+
return (
|
|
374
|
+
<>
|
|
375
|
+
<button onClick={() => setOpen(true)}>Swap</button>
|
|
376
|
+
<div
|
|
377
|
+
className={`fixed top-0 right-0 z-50 h-full w-[420px] bg-background shadow-xl
|
|
378
|
+
transition-transform duration-300
|
|
379
|
+
${open ? 'translate-x-0' : 'translate-x-full'}`}
|
|
380
|
+
>
|
|
381
|
+
<button onClick={() => setOpen(false)}>Close</button>
|
|
382
|
+
<SwapWidget config={config} />
|
|
383
|
+
</div>
|
|
384
|
+
{open && (
|
|
385
|
+
<div
|
|
386
|
+
className="fixed inset-0 z-40 bg-black/30"
|
|
387
|
+
onClick={() => setOpen(false)}
|
|
388
|
+
/>
|
|
389
|
+
)}
|
|
390
|
+
</>
|
|
391
|
+
);
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
These are minimal examples. In production, use your app's existing modal/drawer components (Radix, shadcn, Headless UI, etc.) for accessibility and consistent behavior.
|
|
395
|
+
|
|
396
|
+
## Resources
|
|
397
|
+
|
|
398
|
+
- [Full Documentation](https://docs.aori.io)
|
|
399
|
+
- [Widget API Reference](https://docs.aori.io/swap-widget)
|
|
400
|
+
- [GitHub](https://github.com/aori-io)
|
|
401
|
+
|
|
402
|
+
## License
|
|
403
|
+
|
|
404
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunk3E6RNP2Dcjs = require('./chunk-3E6RNP2D.cjs');
|
|
6
|
+
require('./chunk-6XB5R4GF.cjs');
|
|
7
|
+
require('./chunk-GZUTUD5O.cjs');
|
|
8
|
+
require('./chunk-PGYOJ5RB.cjs');
|
|
9
|
+
require('./chunk-NBJPKJBC.cjs');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
exports.default = _chunk3E6RNP2Dcjs.AssetSelectionMenu_default;
|
|
13
|
+
//# sourceMappingURL=AssetSelectionMenu-Y3EB32BT.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/flooreyes/mega-swap-widget/dist/AssetSelectionMenu-Y3EB32BT.cjs"],"names":[],"mappings":"AAAA,qFAAY;AACZ,YAAY;AACZ;AACE;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACF,+DAAC","file":"/Users/flooreyes/mega-swap-widget/dist/AssetSelectionMenu-Y3EB32BT.cjs"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import {
|
|
4
|
+
AssetSelectionMenu_default
|
|
5
|
+
} from "./chunk-6YLNOZ7P.js";
|
|
6
|
+
import "./chunk-TMC4SUEV.js";
|
|
7
|
+
import "./chunk-6Q7MSCKS.js";
|
|
8
|
+
import "./chunk-7AWG6OWF.js";
|
|
9
|
+
import "./chunk-GGM3MDFM.js";
|
|
10
|
+
export {
|
|
11
|
+
AssetSelectionMenu_default as default
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=AssetSelectionMenu-ZRG42UCZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunkB3ILUJ7Gcjs = require('./chunk-B3ILUJ7G.cjs');
|
|
6
|
+
require('./chunk-GZUTUD5O.cjs');
|
|
7
|
+
require('./chunk-NBJPKJBC.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exports.default = _chunkB3ILUJ7Gcjs.ChainSelectionMenu_default;
|
|
11
|
+
//# sourceMappingURL=ChainSelectionMenu-FBAPPFKI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/flooreyes/mega-swap-widget/dist/ChainSelectionMenu-FBAPPFKI.cjs"],"names":[],"mappings":"AAAA,qFAAY;AACZ,YAAY;AACZ;AACE;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACF,+DAAC","file":"/Users/flooreyes/mega-swap-widget/dist/ChainSelectionMenu-FBAPPFKI.cjs"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import {
|
|
4
|
+
ChainSelectionMenu_default
|
|
5
|
+
} from "./chunk-5XSCUUOW.js";
|
|
6
|
+
import "./chunk-6Q7MSCKS.js";
|
|
7
|
+
import "./chunk-GGM3MDFM.js";
|
|
8
|
+
export {
|
|
9
|
+
ChainSelectionMenu_default as default
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=ChainSelectionMenu-QO3H4TNR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|